いつかやろうと思っていたんだけどできなかったものの消化です。
はじめに
WioNodeを使用していると単純にcurl
コマンドなどを使ってセンサーの状態の取得ができるのですが、センサーによっては常時通信を行いながら、
そのイベントのトリガーをJSON形式で受信するというタイプのものもあります。
例えば、ButtonやGestureなどがそれにあたります。
WioアプリのAPIページにも使い方の記載されているので大きく問題はないのですが、WebSocketのサンプルはJavaScriptのみなので、JSがそんなに得意ではない自分には できればPythonから使えないかなと考えてしまいます。
今回のエントリーでは、そのPythonで書いてみようというものです。 PythonのWebSocketのライブラリは調べてみると2つほどあったので、今回はその両方でチャレンジしました。
前処理
WioNodeの設定に関しては、過去のエントリーなどを参照いただければと思います。
今回は、ButtonのGroveモジュールをWioNodeに接続してテストを行います。
Buttonの設定を行ってFirmwareの書き換えをし、画面右上のハンバーガーメニューからViewAPIのページを表示します。APIページの一覧の中にJavaScriptで書かれたWebSocket経由でのイベントの取得サンプルがあります。 ソース内の*はアクセスキーになりますので伏せてあります。
<script> var ws = new WebSocket('wss://us.wio.seeed.io/v1/node/event'); ws.onopen = function() { ws.send("*****************************"); }; ws.onmessage = function (evt) { alert(evt.data); }; </script>
これと同じ処理を行うコードをPythonで書いていくことになります。
PythonのWebSocketのライブラリモジュールを調べてみると
WebSocketのライブラリモジュールをググってみると2つほどヒットします。
- websocket-client
- websockets
個人的には、websocket-client
をオススメしますが、非同期的なwebsockets
も今っぽい感じで悪くないかなという印象です。
ただ、websocket-client
がオススメなのはJSなどとの類似性があるのでソースの可読性が高い点が理由かなと思います。(移植がらく)
websocket-clientを使用してコードを書いてみる
インストールはpipでOKです。Python 2.7とPython 3.4以上に対応しています。
【Windows10の場合】
$ pip install websocket-client
【RaspberryPiの場合】
$ pip3 install websocket-client
インストール時には依存性がある別のパッケージがインストールされます。詳細は以下のページを御覧ください。
このページにあるサンプルを改良していきます。*はキーの部分なので伏せてあります。
import websocket try: import thread except ImportError: import _thread as thread import time def on_message(ws, message): print(message) def on_error(ws, error): print(error) def on_close(ws): print("### closed ###") def on_open(ws): ws.send('*******************') if __name__ == "__main__": websocket.enableTrace(True) ws = websocket.WebSocketApp('wss://us.wio.seeed.io/v1/node/event', on_message = on_message, on_error = on_error, on_close = on_close) ws.on_open = on_open ws.run_forever()
変更点としては - WebSocketのURL - WebSocketの接続後に接続キーを送信する(Openイベントが発生したタイミング)
あたりかなと思います。
実行すると以下のように動作します。WioNodeにつけたButtonを押すとJSONデータが受信されます。 JSONデータにはイベント名(今回は"button_pressed")と接続されたpin番号が受信されます。
>> WioNode WEB Socket server connected. < {"msg": {"button_pressed": "3"}} < {"msg": {"button_pressed": "3"}} < {"msg": {"button_pressed": "3"}}
Windows10のAnaconda環境でも、RaspberryPiでもうまく動いているようです。
JavaScriptと同じようにonほげのような感じでイベントハンドラの登録ができるような感じです。かなり分かりやすい印象です。
websocketsを使用してコードを書いてみる
インストールはpipでOKです。Python 3.4以上に対応していますが、それ以下でも書き方次第で動くかも?
【Windows10の場合】
$ pip install websockets
【RaspberryPiの場合】
$ pip3 install websockets
詳細は以下のページを御覧ください。
このページのサンプルに改良していきます。*はキーの部分なので伏せてあります。
#!/usr/bin/env python import asyncio import websockets async def loop(): async with websockets.connect('wss://us.wio.seeed.io/v1/node/event') as websocket: await websocket.send('*******************') print(">> WioNode WEB Socket server connected.") while True: receiveData = await websocket.recv() print("{}".format(receiveData)) asyncio.get_event_loop().run_until_complete(loop())
python3で使用可能となったasync/await
とasyncio
を使用しています。
asyncio
の持つイベントループにWebSocketの接続をいれてデータの送受信をする形になります。
非同期処理なんですが、同期的っぽくかけます。
他のライブラリなどとは記載の仕方が違う点は特殊ですが、分かりやすいといえば分かりやすいかもって感じです。
ただ、Pythonのバージョンが限定されるので、用途が限られるかなという印象はあります。
こちらもWindows10のAnaconda環境でもRaspberryPiでも動作していましたが、RaspberryPiではCtrl+CのInterruptでエラーメッセージが大量に表示されるので微妙なのかも。 RaspberryPiのPython3のバージョンは3.5.3でした。
おわりに
ようやくやれてなかったことをまとめられました。JavaScriptもう少しかけるように慣れればいいんでしょうけど個人的にはPythonも捨てがたいです。