概要
- M5GO(M5Stack) から MQTT でデータ送信
- MQTT Broker は Mosquitto を使用
- Mosquitto は Raspberry Pi 上に Docker で動かす
環境
- M5GO (Firmware 0.15)
- Raspberry Pi 3 Model B (Raspbian Stretch)
Mosquitto 立ち上げ
以下から Dockerfile、docker-entrypoint.sh を取得
https://github.com/eclipse/mosquitto/tree/master/docker/1.4.14
Dockerfileを修正し、動作確認のために mosquitto-clients もインストール
Dockerfile
FROM arm32v6/alpine
LABEL Description="Eclipse Mosquitto MQTT Broker"
RUN apk --no-cache add mosquitto mosquitto-clients && \
mkdir -p /mosquitto/config /mosquitto/data /mosquitto/log && \
cp /etc/mosquitto/mosquitto.conf /mosquitto/config && \
chown -R mosquitto:mosquitto /mosquitto
COPY docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["/usr/sbin/mosquitto", "-c", "/mosquitto/config/mosquitto.conf"]
Dockerイメージの作成および起動
docker build -t rpi-mosquitto .
docker run -d --name mosquitto -p 1883:1883 rpi-mosquitto
MicroPython MQTT Client
M5GO MicroPython の MQTT Client については以下を参照
https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/wiki/mqtt
M5GOから送信する以下の投稿のプログラムを修正し Ambient ではなく MQTT Broker へ送るようにする。
M5GO(M5Stack)でDHT12とBMP280の気温値を比較
M5GO Cloudから下に貼ったMicroPythonプログラムを実行
動作確認
動作確認のために mosquitto_sub を起動。M5GOから送信した気温、湿度、気圧の値が表示されるのを確認。
$ docker exec -it mosquitto mosquitto_sub -t "M5GO/Env"
2018-07-15 16:02:29,28.7,62.1,28.16,1000.77140625
2018-07-15 16:02:30,28.7,62.1,28.16,1000.70984375
2018-07-15 16:02:31,28.7,62.1,28.15,1000.8093359375
2018-07-15 16:02:32,28.7,62.1,28.16,1000.8172265625
: : :
プログラム
from m5stack import lcd
import machine
import time
import units
import gc
import network
def conncb(task):
print('MQTT Server [{}] Connected'.format(task))
def disconncb(task):
print('MQTT Server [{}] Disconnected'.format(task))
# 日本時間に同期
rtc = machine.RTC()
rtc.ntp_sync('ntp.nict.jp', tz='JST-9')
# M5GOのfirmwareがv0.11ではntp_syncでtzを指定するとエラーになるので以下で対応
# rtc.ntp_sync('ntp.nict.jp')
# sys.tz('JST-9')
# 同期が完了するまで100ms程度かかる
for i in range(100):
if rtc.synced():
print('synced.')
break
print(i, end=' ')
time.sleep_ms(10)
lcd.font(lcd.FONT_DejaVu18)
lcd.clear()
lcd.print('DHT12', 10, 50)
lcd.print('humidity:', 30, 80)
lcd.print('temperature:', 30, 110)
lcd.print('BMP280', 10, 140)
lcd.print('temperature:', 30, 170)
lcd.print('pressure:', 30, 200)
env = units.ENV(units.PORTA)
mqtt = network.mqtt('raspi', 'mqtt://MQTTサーバー',
autoreconnect=True,
connected_cb=conncb, disconnected_cb=disconncb)
mqtt.start()
while True:
#次の秒までの差分(ミリ秒)を求めてスリープ
time.sleep_ms(1000 - int(time.time() % 1 * 1000))
localtime = time.localtime()
localtime_str = time.strftime('%Y-%m-%d %H:%M:%S', localtime)
try:
# DHT12 から気温と湿度を取得
env.dht12.measure()
d_h = env.dht12.humidity()
d_t = env.dht12.temperature()
# BMP280 から気温と気圧を取得
b_t, b_p = env.bmp280.values
lcd.print(localtime_str, 10, 10)
# 表示桁数が減った時に(気圧が1000から999になった時)
# 後ろを消すのに空白2個入れる
lcd.print('{:.2f}% '.format(d_h), 180, 80) # DHT12の湿度
lcd.print('{:.2f}C '.format(d_t), 180, 110) # DHT12の気温
lcd.print('{:.2f}C '.format(b_t), 180, 170) # BMP280の気温
lcd.print('{:.2f}hPa '.format(b_p), 180, 200) # BMP280の気圧
if mqtt.status()[0] == 2: # (2, 'Connected')
mqtt.publish('M5GO/Env', '{},{},{},{},{}'.format(
localtime_str, d_t, d_h, b_t, b_p))
else:
print(localtime_str, ' MQTT Status: ', mqtt.status())
except Exception as e:
# 時々I2C bus error が起きる。
# データを取得できなかった時は時刻を赤字で表示
lcd.print(localtime_str, 10, 10, lcd.RED)
print(localtime_str, ' Script Name: ', __name__)
print('Exception: ', e)
gc.collect()