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_project
ExecStart=/usr/bin/python3 /usr/local/bin/logger.py
Restart=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"

 

コメント

このブログの人気の投稿

ImDisk Toolkitが開発終了していた。AIM Toolkitに乗り換え

Windows 10 デフォルトゲートウェイに0.0.0.0が追加される

iOS VLC でSMB共有できなかった点について