【目的】

 複数のラズパイ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おわり