🔲
ESP32 - MicroPythonで家電を制御しよう-その4(イベント管理)
ESP32を使って、IFTTTサービスにリクエストを送り、家電を制御します。その仕組みとコードの部分について説明します。
全体像は、その1(コンセプト、スイッチ)を参照してください。
本記事は、イベント管理スレッドについての説明です。
関連記事
イベント管理スレッド
概要
イベント管理スレッドは、名前の通りイベントの交通整理/ロジック管理するためのスレッドです。
本スレッドは、直接ハードウェアの制御は行いません。
現状、アクターからの入力はスイッチのみですが、ロータリーエンコーダなどに変更された場合、
本スレッドがないと他のスレッドのインターフェースに大きく影響を与えてしまいます。
開発環境の構築
開発環境の構築は、下記の記事を参考にしてください。
コード(イベント管理スレッド)
プログラム全体となるため、全ファイルが必要となります。
下記のレポジトリにまとめています。
presenter.py
import _thread
import time
from util import *
class PreProc():
def __init__(self, lock=None, snd_ques=None, rcv_ques=None):
self._lock = lock
self._snd_ques = snd_ques
self._rcv_ques = rcv_ques
return
def _command_sw(self, msg):
print("pre_command_sw:run")
d = conv_msg2dict(msg)
print(d)
send_que(self._lock, self._snd_ques["httpc"], ("dst:httpc,src:pre,cmd:sw,type:"+d["type"]+",how:"+d["how"]))
return
def _command_dsp(self, msg):
print("pre_command_dsp:run")
msg = msg.replace("dst:pre,src:httpc,", "dst:dsp,src:pre,")
send_que(self._lock, self._snd_ques["dsp"], msg)
print("pre_command_dsp:over")
return
def _command_led(self, msg):
print("pre_command_led:run")
msg = msg.replace("dst:pre,src:httpc,", "dst:led,src:pre,")
send_que(self._lock, self._snd_ques["led"], msg)
print("pre_command_led:over")
return
def _proc_pre(self):
while True:
# recvive_que
for key, rcv_q in self._rcv_ques.items():
msg = recv_que(self._lock, rcv_q)
if msg is None:
# print("IndexError")
continue
print("proc_presenter:msg - ", msg)
command = conv_msg2dict(msg)['cmd']
if "sw" == command:
self._command_sw(msg)
elif "dsp" == command:
self._command_dsp(msg)
elif "led" == command:
self._command_led(msg)
else:
print("proc_presenter:error - ", msg)
time.sleep_ms(10)
return
def run(self):
_thread.start_new_thread(self._proc_pre, ())
def main():
lock = _thread.allocate_lock()
from sw import SwProc
que_sw2pre = []
sw_proc = SwProc(lock, snd_que=que_sw2pre)
sw_proc.run()
from led import LedProc
que_pre2led = []
led_proc = LedProc(lock, rcv_que=que_pre2led)
led_proc.run()
from httpc import HttpcProc
que_httpc2pre = []
que_pre2httpc = []
httpc_proc = HttpcProc(lock, snd_que=que_httpc2pre, rcv_que=que_pre2httpc)
httpc_proc.run()
from dsp import DspProc
que_pre2dsp = []
dsp_proc = DspProc(lock, rcv_que=que_pre2dsp)
dsp_proc.run()
que_snds = {
"led" : que_pre2led,
"httpc" : que_pre2httpc,
"dsp" : que_pre2dsp,
}
que_rcvs = {
"sw" : que_sw2pre,
"httpc" : que_httpc2pre,
}
pre_proc = PreProc(lock, que_snds, que_rcvs)
pre_proc.run()
time.sleep(10_000)
return
if __name__ == "__main__":
main()
実行方法と結果
croPython v1.16 on 2021-06-23; ESP32 module with ESP32
Type "help()" for more information.
>>> import presenter
>>> presenter.main()
led:init
LedCtl - init
dsp:__init__ - run
OledCtl - init
Warning: I2C(-1, ...) is deprecated, use SoftI2C(...) instead
dsp:_proc_dsp - run
_proc_poll - run
_proc_poll - run
connecting to network...
.
network config: ('192.168.XX.x', '255.255.255.0', '192.168.XX.1', '192.168.XX.1')
proc_presenter:msg - dst:pre,src:httpc,cmd:dsp,type:clear
pre_command_dsp:run
pre_command_dsp:over
dsp:stop_timer - run
proc_dsp:msg - dst:dsp,src:pre,cmd:dsp,type:clearproc_presenter:msg -
dsp:act_dsp - run
dst:pre,src:httpc,cmd:led,type:off_alldsp:act_dsp - over
pre_command_led:run
pre_command_led:over
proc_led:msg - dst:led,src:pre,cmd:led,type:off_all
act_led_led:run
{'cmd': 'led', 'type': 'off_all', 'dst': 'led', 'src': 'pre'}
led:_act_cmd - over
proc_presenter:msg - dst:pre,src:httpc,cmd:led,type:blink,name:green
pre_command_led:run
pre_command_led:over
proc_led:msg - dst:led,src:pre,cmd:led,type:blink,name:green
act_led_led:run
{'name': 'green', 'src': 'pre', 'dst': 'led', 'cmd': 'led', 'type': 'blink'}
led:_act_cmd - over
dst:pre,src:sw,cmd:sw,type:no1,how:pressed
proc_presenter:msg - dst:pre,src:sw,cmd:sw,type:no1,how:released
dst:pre,src:sw,cmd:sw,type:no1,how:pressed
pre_command_sw:run
{'src': 'sw', 'dst': 'pre', 'cmd': 'sw', 'how': 'pressed', 'type': 'no1'}
proc_httpc:msg - dst:httpc,src:pre,cmd:sw,type:no1,how:pressed
act_httpc:run
{'src': 'pre', 'dst': 'httpc', 'cmd': 'sw', 'how': 'pressed', 'type': 'no1'}
None
proc_presenter:msg - dst:pre,src:sw,cmd:sw,type:no1,how:released
pre_command_sw:run
{'src': 'sw', 'dst': 'pre', 'cmd': 'sw', 'how': 'released', 'type': 'no1'}
proc_httpc:msg - dst:httpc,src:pre,cmd:sw,type:no1,how:released
act_httpc:run
{'src': 'pre', 'dst': 'httpc', 'cmd': 'sw', 'how': 'released', 'type': 'no1'}
sw1
proc_presenter:msg - dst:pre,src:httpc,cmd:dsp,type:ifttt,how:sw1,sts:sending...,tmr:3000
pre_command_dsp:run
pre_command_dsp:over
dsp:stop_timer - run
proc_dsp:msg - dst:dsp,src:pre,cmd:dsp,type:ifttt,how:sw1,sts:sending...,tmr:3000
dsp:act_dsp - run
dsp:dsp_ifttt - run
dsp:start_timer - run 3000
dsp:act_dsp - over
proc_presenter:msg - dst:pre,src:httpc,cmd:led,type:blink,name:blue
pre_command_led:run
pre_command_led:over
proc_led:msg - dst:led,src:pre,cmd:led,type:blink,name:blue
act_led_led:run
{'name': 'blue', 'src': 'pre', 'dst': 'led', 'cmd': 'led', 'type': 'blink'}
led:_act_cmd - over
proc_presenter:msg - dst:pre,src:httpc,cmd:dsp,type:ifttt,how:sw1,sts:sended.,tmr:3000
pre_command_dsp:run
pre_command_dsp:over
dsp:stop_timer - run
proc_dsp:msg - dst:dsp,src:pre,cmd:dsp,type:ifttt,how:sw1,sts:sended.,tmr:3000
dsp:act_dsp - run
dsp:dsp_ifttt - run
dsp:start_timer - run 3000
dsp:act_dsp - over
dsp:_set_event_clear - run
ポイント
キューの管理
- イベント管理スレッドには、すべてのキューを渡します。
- que_snds : イベント管理スレッドから送信するキューを辞書で渡す
- que_rcvs : イベント管理スレッドで受信するキューを辞書で渡す
- que_rcvsを定期的に監視し、必要なイベントをque_sndsを経由して通知する
基本的なシーケンス
以下が基本動作となります。
さいごに
その1-4までで、約2年ほど前につくった電子工作を紹介しました。
説明のために、以下の機能を割愛しました。
- サーバモード
- アクセスポイント情報、トークン情報の登録画面
- 設定ファイル
- テキストファイルとして設定情報を保持
- ロータリーエンコーダ
- ロータリーエンコーダも搭載している
- 電池駆動
- 電池で動くようになっている
フル機能のソースコードは、下記のレポジトリに配置してあります。
テレビのオンオフ、エアコンの制御、扇風機の制御と活躍しています。
Discussion