MQTTでIoT通信(3)受け取ったのデータのファイル保存 プログラムをサービスとして起動する
2026/1/3変更
当初ファイルをSDの寿命に考慮してtmpfsで作った/tmpに保存していたが、これがそれからの地獄のはじまりだった。munin-nodeが基本nobody権限で動作するのがこれの/tmpにあるファイルが見えない。tmpfs上に作ったファイルへのアクセスを禁じられている。まあ、セキュリティー的観点から正しい判断だろう。
とはいえSD上で頻繁に書き換えたくないのでメモリ上で保存したい。でGeminiに聞いたら/dev/shm使えば良いじゃんって返ってきた。/dev/shm ? ってなったので調べてみると
いろいろなところで、以下のような内容を書かれている。「POSITシステムでのアプリケーション間の効率的なデータの受け渡しに使われる。」バッチリじゃん。ただ、使い方に関しては、世間全般として賛否両論なところがあるようだ。
とりあえず、
sudo mkdir -p /dev/shm/mqtt
sudo chmod 777 /dev/shm/mqtt
でディレクトリを作ってここでデータのやりとりをすることにする。
-------------------
2026/1/3 さらに追記
x86用のRaspberry OSをインストールした仮想マシン上で当初プログラムしていたら、仮想マシン上のOSがDebian GNU/Linux 11 (bullseye)で実際のラズパイで動いているのでRaspbian GNU/Linux 13 (trixie)でバージョンそろってなかった。仮想マシン作った時期そんなに前では無いのがが古いバージョンだった。気付かんかった。結果logger.pyが動かず。サービスとしては動いているように見えるのに。。。。。。。
結果。仮想マシン python3-paho-mqtt 1.5.1-1
実ラズパイ python3-paho-mqtt 2.1.0-1
でpython3-paho-mqttが1系から2系になった時に結構かわっているらしいので修正。
#クライアントのインスタンスを作成
client = mqtt.Client()
のところがダメで、
-----------------------------
MQTTでIoT通信(4)受け取ったのデータのファイル保存に挑戦。
sudo apt install python3-paho-mqtt
で Pythonの paho-mqtt ライブラリをインストール
logger.pyとして
import paho.mqtt.client as mqtt
import os
# --- 設定 ---
BROKER = "localhost"
TOPIC = "sensor/#" # 受信したいトピック
USER = "testuser" # ユーザー名
PASSWORD = "testtest" # パスワード
LOG_FILE_pre = "/dev/shm/mqtt/mqtt-data-" # 保存ファイル名の接頭部分# メッセージ受信時の処理
def on_message(client, userdata, msg):
# 届いた内容を文字列に変換
payload = msg.payload.decode("utf-8")
#トピックスのデータの処理 sensor/マシン名
myTOPIC = msg.topic.split('/') #myTOPIC[0]がsensorで[1]がマシン名
#ペイロードのデータの処理
mydata = payload.split(':') # mydata[0] = tmp mydata[1]が温度になるはず
LOG_FILE = LOG_FILE_pre +myTOPIC[1] + '-' + mydata[0] + ".txt" #logファイルの指定 /tmp/に接頭語 マシン[>
# ファイルに上書き保存(自動で閉じる仕組み) データの値だけ格納、温度だと24.45みたいな
with open(LOG_FILE, "w", encoding="utf-8") as f:
f.write( mydata[1] + "\n")
print(f"Saved: {msg.topic} -> {payload}")
# --- メイン処理 ---
#クライアントのインスタンスを作成
client = mqtt.Client(callback_api_version=mqtt.CallbackAPIVersion.VERSION2)
#「イベント」と「実行する関数」を紐付ける
client.on_message = on_message
client.connect(BROKER, 1883)
client.subscribe(TOPIC)
#受信待ちの無限ループに入る
print(f"Running... Saving to...")
client.loop_forever()
を作る。
作ったファイルを /usr/local/bin/ にコピーする
mqtt-logger.service を作る
[Unit]#概要Description=MQTT Data Logger Service# ネットワークが繋がり、Mosquittoが起動した後にこのスクリプトを動かすという指定After=network.target mosquitto.service[Service]# あなたのユーザー名(通常は pi ですが、確認したディレクトリの所有者に合わせてください)User=[ユーザー名] #piとか# スラッシュから始まる「絶対パス」で指定してくださいWorkingDirectory=/home/pi/mqtt_projectExecStart=/usr/bin/python3 /usr/local/bin/logger.pyRestart=always[Install]# 複数のユーザーが使える状態(通常の起動状態)になったら有効にするWantedBy=multi-user.target
このとき大文字小文字に注意 WantedBy を wantedBy にしていて30分くらいエラー探しをしていた。
/etc/systemd/system/ に移動する。以下のコマンドで登録して、自動起動にして再起動する
sudo systemctl daemon-reload
sudo systemctl enable mqtt-logger.service
sudo systemctl start mqtt-logger.service
テストコマンドは
mosquitto_pub -h [ip] -p 1883 -t sensor/m1 -u testuser -P testtest -m "tmp:32.12"
コメント
コメントを投稿