【目的】
複数のラズパイPICOからデータを送り、サーバにてデータを受信、保存する。
まず最初にラズパイPICOからデータ送信、PCサーバで受信に関する情報収集
■HTTPプロトコルによる方法
出典1:ESP32からMicropythonでHTTPリクエスト(POST)でデータを送信し,
PHP(サーバ)で受け取る
https://qiita.com/sirius1000/items/5a4d18a76ddf67a6839c
ライブラリは標準ですむのですが、WEBサーバだと運用の手間が多くて
手を出しにくい(出したくなく)感。
■FTPによる方法
出典2:micropythonではFTPLibが標準では使えない。
Pythonでのライブラリは使えず、
「SpotlightKid氏のmicropython-ftplibを使用」だそうです。
ライブラリ依存になるし、ftpサーバ自体なんとなく手を出しにくい感。
■MQTTによる方法
・・・これが一番目的に合いそうです。
出典3:MQTTブローカーのセットアップ
https://qiita.com/hsgucci/items/be9665bafe6e449377c9
出典4:Raspberry Pi で mosquitto を使う
https://qiita.com/ekzemplaro/items/ab90dd630c3ad8e819ab
出典5:pythonでMQTT送受信
https://qiita.com/hsgucci/items/6461d8555ea1245ef6c2
出典6:PythonでMQTT(Paho) - 2023
https://qiita.com/emqx_japan/items/d33acb84f525853f2a51
出典7:【MQTT】MQTTの導入 mosquittoのインストール/動作確認まで
https://qiita.com/koichi_baseball/items/8fa9e0bdbe6d0aebe57d
出典8:MQTTブローカーMosquittoを設置する
https://diysmartmatter.com/archives/352
出典9:WindowsのMQTTブローカーの設定
https://qiita.com/yomori/items/74a9af05a8ccdda12e2f
2409151800追記
■Step1:MQTTサーバ稼働
テスト環境1と結果1
MQTTサーバー:Windows11
送信クライアント:Windows11(サーバー自身)
受信クライアント:Windows11(サーバー自身)
動作環境:VSCode+JupyterNotebook+Python3.11
Pubコード実行結果:正常に送信した。
Subコード実行結果:正常に受信した。
テスト環境2と結果2
Pubクライアント:macOS
その他:同上
conf:Listener 1883 0.0.0.0
ファイヤウォール:ポート1883新規設定
Pubコード実行結果:「Timeout」
→おそらくサーバに到達していない。
サーバ設定、ファイヤウォールのどこかが可怪しいと推察
テスト環境3と結果3
Windowsのファイヤウォール:全部オフ
その他:同上
Pubコード実行結果:正常に送信した。
Subコード実行結果:正常に受信した。
以上から、Windows11におけるファイヤウォールの設定が正しくできていないが、
MQTTサーバ自体のリモート接続は正常にできていることが判明した。
多少ゴタゴタしましたが、これは簡単です。IoT用に設計されているようで、
今回の目的にぴったしとわかりました。
■Step2:ラズパイPico設定
いよいよラズパイPICOを用い、MicropythonにてMQTT接続の設定をします。
環境:Thonny4.1.14
PC:Windows11 python3.10.11
MicroPython v1.23.0 on 2024-06-02; Raspberry Pi Pico W with RP2040
(MicroPythonのバージョンはThonnyを立ち上げるとシェルに表示される)
PICOに触るのが久しぶりですので、
まずはPCとPICO-Wの接続確認を兼ねてPICO-W上でLチカしてみます。
・・・
動きませんやん!!!
まじか??? LED壊れてるとか?(いやサラッピンなんやけど)
・・・
ひょっとして?と思い、PICOとPICO-Wの違いについて調べますと・・・
出典10:MicroPython で 内蔵LEDのLチカさせてみました(Paspberry Pi Pico W編)
PICO-Wに搭載のLEDはGPIO25ではないそうです。特別な記述になるとのこと。
出典元さま、お陰様ですぐに対処できました。感謝です!
ということでPC&PICO-W接続確認とThonny使用法を再学習できましたので、
本題のPICO-WによるMQTTにチャレンジです。
出典11:【Wi-Fi】RaspberryPi Pico W MicroPythonでMQTTを使う方【Mosquitto】
https://tech-and-investment.com/raspberrypi-picow-6-mqtt/
さて、Pico上のMicropythonではMQTT接続に
umqtt.simple
という外部ライブラリを使うということですが、Pythonと違って
pipやaptに相当する方法が見当たりません。
これまではGPIOやI2Cなど使ってきましたが、そのためのライブラリは
多々の例がネットなどに載っていてそこにダウンロード先がありました。
で、MQTTとMicroPythonについてはネット情報はさほど多くなく・・・
ありました!
↓インストールの仕方は以下出典ご参照。(まだ操作確認前です)
出典12:Raspberry Pi Pico W: Getting Started with MQTT (MicroPython)
↑これの中ほどに「Installing MQTT MicroPython Modules」があります。
英文ですがスクリーンショットもあって、わりと楽に読めます。
MQTTClientでClientIDが必要かどうかについて・・・
出典13:How to use client id in Mosquitto MQTT?
まだちゃんと読めてませんが・・・たぶんトピックを入れればIDはいらないのではないかと。。。Windows上でのMQTT接続ではIDに言及がありませんでしたから。
一方で、こういうのもあります。
出典14:MQTT利用時のクライアントID重複に注意
クライアントIDはルールを決めてユニークに定めよ、とのこと。
クライアントIDをどこかにリスト化して設定するのか???
あるいはユニーク確保してどこにも記述設定せずにClientIDを使う???
Pubは複数/Subが1つならばどうすればよいのか?よくわかりません。
もう少し調べないと・・・
↓ここにもう少し詳しい実例記述がありました。(これも英文)
出典15:
ここまで読み解いてみた感じからは、、、
・ClientIDがあると、セッションが途中で切れても復活できる。
・ClientIDはMQTTサーバ側で設定するものではなく、
クライアント側が自分で定めるものである。
・ClientIDなしの場合、MQTTサーバがClientIDをランダムな値で自動設定する。
以上から、ネット接続に特段の不調がない、あるいは多少データを喪失しても
問題にならない場合は、わざわざClientIDを設定しなくてもよさそう、と
思われます。
ということでやってみます。
・・・
いけちゃいました!ClientIDも適当に入れておきました。
以下、PICO-Wのほうのコード。
ほぼほぼ出典11からのコピペですが、使わない部分は削除、編集しました。
#コードーーーーーーーーーーーーーーーー
#ライブラリインポート
import time
import network
from umqtt.simple import MQTTClient
import machine
import sys
# Wifi接続先の設定
#PICO-WのWifiは2.4GHzのみ。5GHz帯がないので注意!
ssid = '2.4GHzのWifiのSSID'
password = '2.4GHzのWifiのパスワード'
# Wifi接続
def connect():
# Wifi接続インスタンス生成
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
# Wifi接続開始、接続確認待ち
wlan.connect(ssid, password)
while wlan.isconnected() == False:
print('Waiting for connection...')
time.sleep(1)
# IPアドレスリターン
ip = wlan.ifconfig()[0]
print(f'Connected on {ip}')
return ip
# 受信メッセージ表示
def printMessage(topic, message):
# bytes型である受信データをUTF-8に変換して標準出力に表示
print("topic:" + topic.decode("utf-8") )
print("message:" + message.decode("utf-8") )
# 以下、主ルーチンーーー
# ブローカーのIPとトピック名定義
mqttBroker = '192.168.10.128'
myId = 'kabayon'
topic= b"test_mqtt" #byte型にする
# MQTTオブジェクト(変数)定義
client = MQTTClient(myId, mqttBroker, keepalive=3600)
# 受信関数設定
client.set_callback(printMessage)
# Wi-Fi接続実施
connect()
try:
# MQTTブローカー接続実行
client.connect()
# 読み出しトピック登録(必ずブローカー接続のあとに登録)
client.subscribe(topic)
except:
# ブローカー接続失敗時、プログラム終了(sysで落とす)
print("Could not connect to mqtt server.")
sys.exit()
#ブローカー接続が成立した表示
print("mqqtt connect done ")
# テストデータ連続送信
i_count = 0
while True:
i_count = i_count +1
# 送信メッセージ生成
msg = "send amount is "+str(i_count)
# 送信実行
client.publish(topic, msg)
# ブローカーからの返信メッセージ確認
client.check_msg()
time.sleep(3)
#PICO-Wのコードおわりーーーーーーーーーーーーーーーー
最初にWifiを5GHzで設定しており、当然ながらWifi接続できず。
あ!と気づいて修正したらあっさりとすべてがOKに!
手順追ってきっちり積み上げたら、意外と早くなんとかなるもんですね。
■複数PICO-Wの運用への第一歩:
想定状況
1:複数の設備に設置されたPICO-Wがそれぞれの設備の動作状態を取得し、
それぞれから異なるトピックで送信(Pub)、
2:1台のPC上のMQTTサーバですべて受信、
3:MQTTサーバの動作するPC上で各トピックを受信(Sub)
4:受信したデータをそのままDBMS(SQLiteあるいはPostgreSQL)へ保存
1フロアに設備10台(PICO-Wも10台)かつ1MQTTサーバと想定すると、
1レコード30msec(30Hz程度)ぐらいに収めないと安心できないかも。
まず最初にPICO-Wが1台だけの場合の動作速度を見ておきます。
上述のPubコードの最後の行、time.sleepは3秒になっていますが、
こんなトロい状況は今回の目的では発生しないので、
とりあえず0.01秒にしてみましたところ・・・
余裕でOKでした。つまり100Hz。
データ保存のルーチンが入ってくるとこうはいかないはずです。
PostgreSQLでは無理かもしれません。
↓情報
出典16:SQLiteデータベースの速度比較:詳細解説
https://runebook.dev/ja/docs/sqlite/speed
SQLiteは動作が早く、Pythonの標準でSQLite3が入っていて扱いが楽ですので、
やはり最初はコレでやってみます。
最終的には排他制御のきっちりしたPostgreSQLに置き換えたいと思いますが、
速度が追いつかない場合はSQLiteで一旦受けて、複数フロアのサーバから
PostgreSQLへデータを集結する方法もあるかと。。。
以上、とりあえずPico-W1台でのMQTTは接続できたので、
つぎは複数PICO-Wの接続ですが、これは別記事で・・・
以上、その1おわり