【コード作成】オフラインのHiveOSを外出先から再起動

スポンサーリンク
マイニング
スポンサーリンク

概ね環境が整ってきたのでコード作成に入ります。

スポンサーリンク

前回内容・まとめページ

429 Too Many Requests
https://stshjblg.com/%e3%80%90%e3%81%be%e3%81%a8%e3%82%81%e3%80%91%e3%82%aa%e3%83%95%e3%83%a9%e3%82%a4%e3%83%b3%e3%81%aehiveos%e3%82%92%e5%a4%96%e5%87%ba%e5%85%88%e3%81%8b%e3%82%89%e5%86%8d%e8%b5%b7%e5%8b%95/1703/

1.通信の流れ確認

今一度流れの確認です。ラズパイは『beebotte』からメッセージを受け取り、そのメッセージ内容によってマザーボードの電源をどうするか判断し、『SW回路』に電気を流します。

つまり『どんなメッセージを受け取ったら』『何をするか』ということをコード化します。使用する言語はPythonです。
※筆者はPython素人ですので、何か不備があるかもしれませんがご容赦下さい。

2.beebotteの登録

コード作成の前にbeebotteのアカウント登録を行います。コード作成後の検証に使いますのでこのタイミングで登録します。登録は以下のリンクを参考にしてもらえれば良いかと思います。

beebotteの使い方メモ.md
GitHub Gist: instantly share code, notes, and snippets.

3.コードの作成

コードは2つに分けて作成します。
①サブコード:マザーボード(リグ)の電源操作(GPIO)に関するコード
②メインコード:メッセージ待機と受け取った時のリアクションに関するコード

①サブコード:マザーボード(リグ)の電源操作(GPIO)

GPIOに関するコードは基本部は以下リンクを参照しております。ピンの配置も掲載されていますので参考にしてみてください。

PythonでRaspberry PiのGPIO、LED、スイッチ制御 – Indoor Corgi

from pickletools import read_string1
import RPi.GPIO as GPIO # RPi.GPIOモジュールを使用
import time

gpio_GATE1 = 22                     #RIG1の電源SWに接続するピンNo.15
gpio_GATE2 = 23                     #RIG2の電源SWに接続するピンNo.16


def GPIO_INITILIZE(RIG_NO):         #GPIO初期設定の関数
    if RIG_NO == 1:                 #因数が1の場合、
        gpio = gpio_GATE1           #gpioにはRIG1のピンを代入
    elif RIG_NO == 2:               #因数が2の場合、
        gpio = gpio_GATE2           #gpioにはRIG2のピンを代入

    # GPIO番号指定の準備
    GPIO.setmode(GPIO.BCM)          #指定したGPIO番号をGPIOとして使うことを意味する。
    # 出力に設定
    GPIO.setup(gpio, GPIO.OUT)      #gpioピンを出力として使う宣言

    #初期値設定
    GPIO.output(gpio,0)             #gpioピンの出力をLOW(0V)とする
    time.sleep(1)                   #1秒待機
    print('RIG',end='')             #RIG"因数" ready のコメント出力
    print(RIG_NO,end='')
    print(' ready')


def SW_ON(RIG_NO):                      #SWをONする関数
    if RIG_NO == 1:                     
        gpio = gpio_GATE1
    elif RIG_NO == 2:
        gpio = gpio_GATE2   
    print('RIG',end='') 
    print(RIG_NO,end='')
    GPIO.output(gpio,1)                 #GPIO X のトランジスタON=フォトカプラON
    time.sleep(1)                       #1秒待機 電源ON
    GPIO.output(gpio,0)                 #GPIO X のトランジスタOFF=フォトカプラOFF
    print('POWER_ON')                   #POWER ON のコメント出力
    time.sleep(5)                       #5秒待機


def SW_OFF(RIG_NO):                     #SWをOFFする動作関数
    if RIG_NO == 1: 
        gpio = gpio_GATE1
    elif RIG_NO == 2:
        gpio = gpio_GATE2   
    print('RIG',end='') 
    print(RIG_NO,end='')
    GPIO.output(gpio,1)                 #GPIO X のトランジスタON=フォトカプラON
    time.sleep(5)                       #5秒待機 電源ON
    GPIO.output(gpio,0)                 #GPIO X のトランジスタOFF=フォトカプラOFF
    print('POWER_OFF')                  #POWER ON のコメント出力
    time.sleep(30)                      #30秒待機


def CLEANUP(RIG_NO):                    #GPIOを解放する関数
    if RIG_NO == 1: 
        gpio = gpio_GATE1
    elif RIG_NO == 2:
        gpio = gpio_GATE2
    GPIO.cleanup(gpio)                  #GPIOを解放
    print('GPIO_cleannup_done')         #GPIO_cleannup_doneを出力
    time.sleep(10)                      #10秒待機


def REBOOT(RIG_NO):                     #再起動の動作関数
    GPIO_INITILIZE(RIG_NO)              #指定リグ用のGPIO設定
    SW_OFF(RIG_NO)                      #SWOFF動作=電源OFF
    SW_ON(RIG_NO)                       #SWON動作=電源ON
    CLEANUP(RIG_NO)                     #GPIOを解放

def POWER_ON(RIG_NO):                   #電源ONの関数
    GPIO_INITILIZE(RIG_NO)              #指定リグ用のGPIO設定
    SW_ON(RIG_NO)                       #SWON動作=電源ON
    CLEANUP(RIG_NO)                     #GPIOを解放

def POWER_OFF(RIG_NO):                  #電源OFFの関数
    GPIO_INITILIZE(RIG_NO)              #指定リグ用のGPIO設定
    SW_OFF(RIG_NO)                      #SWOFF動作=電源OFF
    CLEANUP(RIG_NO)                     #GPIOを解放

このコードでは、最終的に『電源ON(def POWER_ON)』『電源OFF(def POWER_OFF)』『再起動(def REBOOT)』の三種類の動作を実施するために複数の関数を定義してます。メインコードからこれらの3つの関数を呼び出す形にします。

細かい内容はコメントアウトしているのでそちらを参照して頂ければと思います。

②メインコード:メッセージ待機と受け取った時のリアクション

メインのコードは以下のリンクを参考にしました。というかほぼ同じです。リンク先【beebotteを試す。】項のSubscriberプログラムを参考にしてます。

Raspberry Pi(MQTT連携)
#!/usr/bin/python3
# -*- coding: utf-8 -*- 
#smartremocon.py
 
from pickletools import read_string1
import paho.mqtt.client as mqtt         # MQTTのライブラリをインポート
import subprocess
import json
from time import sleep
import GPIO_SW                          #GPIOサブコードの参照
 
HOST = 'mqtt.beebotte.com'
PORT = 8883
CA_CERTS = 'mqtt.beebotte.com.pem'
TOKEN = 'token_xxxxxxxxxx'        #Beebotteで作成したチャンネルのトークンを代入
TOPIC = 'channel名/resource名'    #Beebotteで作成した"channel名/resource名"を代入。今回はraspberry_pi/RIG
 
def on_connect(client, userdata, flags, respons_code):  # ブローカーに接続できたときの処理
    print('status {0}'.format(respons_code))
 
def on_disconnect(client, userdata, flags, respons_code):# ブローカーが切断したときの処理
    print("Unexpected disconnection.")
    client.loop_stop()
 
def on_message(client, userdata, msg):  # メッセージが届いたときの処理
    print(msg.payload.decode("utf-8"))
    try:
        data = json.loads(msg.payload.decode("utf-8"))["data"]
        for dat in data:
            print(dat)
    except :
        print("jsonフォーマットエラー")

    if dat == 'RIG1_POWER_ON':          #"RIG1_POWER_ON"というメッセージが届いた場合
        GPIO_SW.POWER_ON(1)             #サブコードの『電源ON 因数1』を呼び出す
    elif dat == 'RIG1_POWER_OFF':       #"RIG1_POWER_OFF"というメッセージが届いた場合
        GPIO_SW.POWER_OFF(1)            #サブコードの『電源OFF 因数1』を呼び出す
    elif dat == 'RIG1_REBOOT':          #"RIG1_REBOOT"というメッセージが届いた場合
        GPIO_SW.REBOOT(1)               #サブコードの『再起動 因数1』を呼び出す
    elif dat == 'RIG2_POWER_ON':        #"RIG2_POWER_ON"というメッセージが届いた場合
        GPIO_SW.POWER_ON(2)             #サブコードの『電源ON 因数2』を呼び出す
    elif dat == 'RIG2_POWER_OFF':       #"RIG2_POWER_OFF"というメッセージが届いた場合
        GPIO_SW.POWER_OFF(2)            #サブコードの『電源OFF 因数2』を呼び出す
    elif dat == 'RIG2_REBOOT':          #"RIG2_REBOOT"というメッセージが届いた場合
        GPIO_SW.REBOOT(2)               #サブコードの『再起動 因数2』を呼び出す


if __name__ == '__main__':
    client = mqtt.Client()              # クラスのインスタンスの作成
    client.on_connect = on_connect      # 接続時のコールバック関数を登録
    client.on_disconnect = on_disconnect   # 切断時のコールバックを登録
    client.on_message = on_message          # メッセージ到着時のコールバック
    client.username_pw_set('token:%s' % TOKEN)
    client.tls_set("/etc/ssl/certs/ca-certificates.crt")
    client.connect(HOST, PORT)   # 接続
    client.subscribe(TOPIC)
    client.loop_forever() # 永久ループして待ち続ける

上記がメインのコードになります。わかる範囲で以下より解説します。

import paho.mqtt.client as mqtt         # MQTTのライブラリをインポート

このライブラリはインストールをしなければ使えません。私はpip install paho-mqttではインストールできなかったので、pip3 install paho-mqtt python-etcdでインストールしました。以下リンクを参照しました。

Import Error: paho.mqtt.client not found
I am creating a docker containing python and php. I am writing a python script to connect to a MQTT broker residing in another docker.In my dockerfile I ensure ...
import GPIO_SW                          #GPIOサブコードの参照

これは先ほど作成した①サブコードを参照することを意味します。サブコード内のグローバル変数と関数が使用可能になります。

サブコードを参照するにはメインコードと同じディレクトリ内にファイルを入れておく必要があるので注意して下さい。

TOKEN = 'token_xxxxxxxxxx'        #Beebotteで作成したチャンネルのトークンを代入
TOPIC = 'channel名/resource名'    #Beebotteで作成した"channel名/resource名"を代入
beebotte チャンネル詳細

beebotteで作成したチャンネルを参照して代入してください。上の画像だと、
TOKEN:赤塗りつぶし部の文字列
channnel名:raspberry_pi
resources名:RIG

になります。

def on_message(client, userdata, msg):  # メッセージが届いたときの処理
    print(msg.payload.decode("utf-8"))
    try:
        data = json.loads(msg.payload.decode("utf-8"))["data"]
        for dat in data:
            print(dat)                  #メッセージをコメント出力
    except :
        print("jsonフォーマットエラー")

    if dat == 'RIG1_POWER_ON':          #"RIG1_POWER_ON"というメッセージが届いた場合
        GPIO_SW.POWER_ON(1)             #サブコードの『電源ON 因数1』を呼び出す
    elif dat == 'RIG1_POWER_OFF':       #"RIG1_POWER_OFF"というメッセージが届いた場合
        GPIO_SW.POWER_OFF(1)            #サブコードの『電源OFF 因数1』を呼び出す
    elif dat == 'RIG1_REBOOT':          #"RIG1_REBOOT"というメッセージが届いた場合
        GPIO_SW.REBOOT(1)               #サブコードの『再起動 因数1』を呼び出す
    elif dat == 'RIG2_POWER_ON':        #"RIG2_POWER_ON"というメッセージが届いた場合
        GPIO_SW.POWER_ON(2)             #サブコードの『電源ON 因数2』を呼び出す
    elif dat == 'RIG2_POWER_OFF':       #"RIG2_POWER_OFF"というメッセージが届いた場合
        GPIO_SW.POWER_OFF(2)            #サブコードの『電源OFF 因数2』を呼び出す
    elif dat == 'RIG2_REBOOT':          #"RIG2_REBOOT"というメッセージが届いた場合
        GPIO_SW.REBOOT(2)               #サブコードの『再起動 因数2』を呼び出す

def on_message(client, userdata, msg) :メッセージが届いた時に呼び出される関数
この関数内に、メッセージ条件でリグの電源をどうするか、どのサブコードを呼び出すか記載します。

他に良い方法があるかもしれませんが、if文で条件分けしてサブコード呼び出す形としてます。

4.コードの検証

コードの検証方法ですが、【beebotteのコンソール機能】【ラズパイのIDE】で試します。

ラズパイIDEでコードを走らせる

メインコード(ここではSUBSCRIBE_MAIN.py)をIDEで起動します。
その際、今回作成したサブコード(ここでは、GPIO_SW.py)も同じフォルダに入れておきます。

IDEで『RUN』を押し、シェルにstatus 0のコメントが出てくれば準備完了です。

beebotteでコンソール活用の準備

beebotteのコンソール画面で、『secret key』とPublish項の『Channel』『Resource』『Data』を打ち込みます。『secret key』はアカウントセッティングで確認できます。今回は以下の通り。

Channel:raspberry_pi
Resource:RIG
Data:[“RIG1_POWER_ON”]

このコンソール画面で[Publish data]ボタンを押す。
⇒ラズパイのシェルでRIG1_POWER_ONのコメントが出てくる
GPIO_SW.POWER_ONが呼び出され、POWER_ONGPIO_cleannup_doneコメントが表示される

以上が確認できれば検証OKです。

検証結果

結果は以下の通り。beebotteでLogにtrueと出て、その後、ラズパイshellにコマンドが出てきます。

各コマンドのDataもPublishしてみて、ラズパイのコードが動けば検証完了です。

また、できれば実際にGPIOピンに配線して電気回路のデバッグをすることをお勧めします。
具体的には、使用するGPIOピンにジャンパー線を接続し、テスターでデータ送信時に電圧がかかるか計測するといった感じです。

以上。コード編でした。次はiphoneから動かしてみます。

つづき<端末操作編>

429 Too Many Requests

コメント

タイトルとURLをコピーしました