📌
MQTTでM5StickC Plus2からPythonへデータを送信
やりたいこと
M5StickC Plus2からIMUの値を取得して、MQTTでPythonにデータを送信する検証を実施しました。
ハマった点
ファイアウォールにより接続が遮断されていました。うまく接続できない場合は、ネットワーク設定を確認してみてください。
手順
1.mosquittoのインストール
ブローカーとして使いたいPCにソフトをインストールする。
手順は以下を参考に実施しました。
2.Pythonプログラム(Subscriber)の作成
import json
from datetime import datetime
import paho.mqtt.client as mqtt
# MQTT設定
MQTT_BROKER = "localhost"
MQTT_PORT = 1883
MQTT_TOPIC = "m5stick/data"
# ブローカーに接続できたときの処理
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("MQTTブローカーに接続しました。")
# 指定したトピックを購読(Subscribe)
client.subscribe(MQTT_TOPIC)
else:
print(f"接続に失敗しました。リターンコード: {rc}")
# メッセージを受信したときの処理
def on_message(client, userdata, msg):
try:
# 受信したメッセージはbytes型なので、UTF-8でデコード
payload_str = msg.payload.decode("utf-8")
# JSON文字列をPythonの辞書型に変換
data = json.loads(payload_str)
print("----------------------------------------")
print(datetime.now())
print(f"トピック '{msg.topic}' からメッセージを受信しました:")
print(f" デバイスID: {data.get('deviceId', 'N/A')}")
print(f" 加速度(X): {data.get('accel_x', 0):.2f}")
print(f" 加速度(Y): {data.get('accel_y', 0):.2f}")
print(f" 加速度(Z): {data.get('accel_z', 0):.2f}")
print(f" ボタンA: {'押された' if data.get('btnA_pressed') else '---'}")
except json.JSONDecodeError:
print(f"JSONのデコードに失敗しました: {msg.payload.decode('utf-8')}")
except Exception as e:
print(f"エラーが発生しました: {e}")
def main():
# MQTTクライアントの作成
client = mqtt.Client()
# コールバック関数の設定
client.on_connect = on_connect
client.on_message = on_message
print(f"{MQTT_BROKER} に接続します...")
try:
# ブローカーに接続
client.connect(MQTT_BROKER, MQTT_PORT, 60)
# 無限ループでメッセージを待機
# (バックグラウンドで通信を処理し続ける)
client.loop_forever()
except KeyboardInterrupt:
print("\nプログラムを終了します。")
client.disconnect()
except Exception as e:
print(f"接続エラー: {e}")
if __name__ == "__main__":
main()
3.M5StickC Plus2のプログラム(Publisher)の作成
#include <M5Unified.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
// WiFi設定
const char* ssid = "xxxxx";
const char* password = "xxxxx";
// MQTT設定
const char* mqtt_server = "ブローカーのIPアドレス"; // 公開MQTTブローカー
const int mqtt_port = 1883;
const char* mqtt_topic = "m5stick/data"; // データを送信するトピック名
const char* mqtt_client_id = "m5stickc-plus2-client-01"; // 他のクライアントと重複しないように設定
// グローバル変数
WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsgTime = 0;
const long msgInterval = 1000; // メッセージ送信間隔 (ミリ秒)
// WiFi接続処理
void setup_wifi() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
M5.Lcd.print("IP address: ");
M5.Lcd.println(WiFi.localIP());
}
// MQTT再接続処理
void reconnect() {
while (!client.connected()) {
if (client.connect(mqtt_client_id)) {
M5.Lcd.println("MQTT connected");
} else {
M5.Lcd.print("failed, rc=");
M5.Lcd.print(client.state());
M5.Lcd.println(" try again in 5 seconds");
delay(5000);
}
}
}
void setup() {
// M5Stackの初期化
auto cfg = M5.config();
M5.begin(cfg);
Serial.begin(115200);
M5.Lcd.setRotation(1); // 画面の向きを設定
M5.Lcd.setTextSize(2);
M5.Lcd.fillScreen(BLACK);
// IMUの初期化
M5.Imu.begin();
// WiFi接続
setup_wifi();
// MQTTクライアントの設定
client.setServer(mqtt_server, mqtt_port);
delay(1500);
}
void loop() {
// M5デバイスの状態を更新
M5.update();
// MQTT接続が切れていたら再接続
if (!client.connected()){
reconnect();
}
client.loop(); // MQTTクライアントの状態を維持
// 前回の送信から指定時間が経過したかチェック
unsigned long now = millis();
if (now - lastMsgTime > msgInterval) {
lastMsgTime = now;
// IMUから加速度データを取得
float ax, ay, az;
M5.Imu.getAccel(&ax, &ay, &az);
// JSONデータを作成
StaticJsonDocument<200> doc;
doc["deviceId"] = mqtt_client_id;
doc["accel_x"] = ax;
doc["accel_y"] = ay;
doc["accel_z"] = az;
doc["btnA_pressed"] = M5.BtnA.wasPressed(); // ボタンAが押されたか
// JSONを文字列に変換
char buffer[200];
size_t n = serializeJson(doc, buffer);
// MQTTトピックにデータをPublish
client.publish(mqtt_topic, buffer, n);
// LCDに送信データを表示
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setCursor(0, 0);
M5.Lcd.println("MQTT Publisher");
M5.Lcd.printf("Topic: %s\n", mqtt_topic);
M5.Lcd.println("----------------");
M5.Lcd.printf("ax: %.2f\n", ax);
M5.Lcd.printf("ay: %.2f\n", ay);
M5.Lcd.printf("az: %.2f\n", az);
M5.Lcd.println("Data sent!");
Serial.print("Publish message: ");
Serial.println(buffer);
}
delay(10);
}
Discussion