2023年3月13日月曜日

openemoteを動かしてmqttでデータを送信してグラフで見る


背景

出来合いのログ取りサーバーをRaspberry Piで動かして家のデータ収集サーバーを構築したいのでweb検索したところ、openremoteというオープンソースの情報収集サーバープログラムを見つけました。

これが最善の選択かは分かりませんが、起動して情報送信してグラフを見るのはできました。
備忘録を兼ねて取り組んだ内容を共有します。

便利なログ取りサーバープログラムやサービスがあればコメントなどで共有していただけると嬉しいです。
なおthingspeakは知っています。


後日thingsboardというプログラムを試しました。

ログ取りサーバーthingsboardをRaspberry Piで動かしてデータを表示

thingsboardはhttpで動かせてcurlでログを送信できるので、LAN内で動かすならこちらの方が都合が良いと思います。

使ったもの

  • Raspberry Pi 4B + Raspberry Pi OS 64bit
    検証はしていませんが32bitのOSだとopenremoteが動かない可能性が高いので64bit版を使ってください。
  • docker + docker compose
    Raspberry Piにインストールしてください。
    Install Docker Engine
    Install Docker Engine on Debian
  • Raspberry Piと連携するPC
    Raspberry Piだけで動作確認しても良いですが、外部からの情報送信を受け付けていることの確認と、普段使っているノートPCで試行錯誤するほうが楽だったので、ノートPCで情報送信やデータの閲覧を行いました。
    今回はubuntu22.04をインストールしたノートPCを利用しました。
  • python3
    連携するPCにインストールしてください。
    ログ情報の送信に利用します。
  • openssl
    連携するPCにインストールしてください。
    ubuntuなら標準でインストールされていると思います。
    証明書の取得に利用します。

openremoteをダウンロードして起動

この節で紹介するコマンドはopenremoteを動かすPC(Raspberry Piなど)上で実行してください。

ダウンロード(git clone)にgitが必要なのでインストールします。
sudo apt install git

この記事では~/gitprojects/openremoteにopenremoteを配置します。
mkdir -p ~/giprojects
cd ~/gitprojects
git clone https://github.com/openremote/openremote.git

Quick startを参考にしつつ起動します。
openremoteは標準でhttpsで通信する使用になっており、外部からアクセスする場合は自身に割り当てられるホスト名を引数で渡しながら起動する必要があります。
Raspberry Piの場合、ローカルのアドレスは下記のコマンドで確認できます。
ip a show | grep 192

今回利用するRaspberry Piは192.168.1.171で動いていると分かりました。


OR_HOSTNAMEとしてローカルアドレスを割り当てつつopenremoteを起動します。
下記のコマンドの192.168.1.171をご利用の装置のアドレスに書き換えて実行してください。
cd ~/gitprojects/openremote
OR_HOSTNAME=192.168.1.171 docker compose -p openremote up -d

初回実行時は関連するコンテナをダウンロードするため時間がかかります。
自分の環境だと10分ほどかかりました。

端末が実行可能状態に戻ったら起動できた可能性が高いです。


docker composeのlogコマンドに-fオプションを付けると最新のログが表示されます。
cd ~/gitprojects/openremote
docker compose logs -f

openremoteにブラウザからアクセス: ローカルアドレスなので警告を無視してアクセス

ノートPCからRaspberry Piで起動しているopenremoteを開きます。
ノートPCとRaspberry PIは同一ローカルネットワーク(LAN、WiFi)に接続してください。

先程openremoteを実行したRaspberry Piのアドレスは192.168.1.171だったので、それをブラウザで開きます。

openremoteはドメインを割り当てるとlet's encryptで認証登録して認証されたhttpsのページを表示するらしいのですが、ローカルアドレスは登録のしようがないため保護されていない通信として警告画面が表示されます。
(自己著名証明書、通称オレオレ証明書を利用しています。)

chromeの場合は「詳細設定」を押し、「アクセスする(安全ではありません)」をクリックすると保護されていないページを表示できます。




認証されていないのを承知でアクセスすると開けます。


openremoteの初期の管理者のアクセス情報はこちらです。
username: admin
password: secret

上記の情報を入力するとログインできます。



mqttでデータ受信用のuserとassetを作成

mqttとは非力な装置や不安定なネットワークでも扱えるように作られた軽量のプロトコルです。wikipedia:mqtt
openremoteでmqttを使うには送信権限を持つuserと送信先のassetが必要なので、それらを作成します。

なお、MQTTを利用する理由はhttpのpostなどでの情報送信方法を自分が把握できず、httpでの送信方法を効いているフォーラムでのMQTTの利用を進められていたのと、MQTT送信に関する事例(pdf)wikiが見つかったためです。

service userを作成

openremote右上のハンバーガーボタンを押すとメニュが出てくるのでusersを選びます。


service usersの右側にある「+ ADD USER」を押します。


今回はexample-service-userという名前でattributesへの書き込み権限を付与したユーザーを作成します。


パスワードはユーザー作成後に生成されるので、一覧から作成したユーザーを選んで確認します。


生成されたパスワードを確認します。
これはデータ送信時に利用します。


Realm rolesを選ばないと管理者権限になるのか(不具合?)、書き込み権限があればassetに書き込み可能になります。

データ保存用のassetを作成: 要store data points

assetsタブを選び、右のメニューの+を押します。


mqttを選んでaddを押します。


生成したassetを選び、modifyを押します。


asset編集画面をスクロールして最も下にあるadd attributeを押します。


temperatureという名前のattributeを下記のように作ります。
type: custom attribute
name: temperature
value type: number


attribute一覧にtemperatureが追加されるので、左の>を押してメニューを開き、add configuration itemsを押します。


store data pontsを有効にしてaddを押します。
これがなかなか重要な設定でして、過去の値を保持してグラフなどを表示するためにstore data pointsの有効化が必要なのです。


attributeを設定できたらassetのsaveを押します。
saveを押さないとattributeの追加や設定変更が破棄されるので注意です。


最後にurlからasset idを確認します。
mqttの情報送信に必要なのにも関わらず画面上で表示されないため(どうして…)、urlの最後の/以後の文字列をコピーして使います。


これで書き込み先のassetとattributeを準備できました。

pythonでmqttのpublish(書き込み)

pythonでpahoというライブラリを利用してmqttのpublishを行いopenremoteに値を送信します。

pipでpahoをインストールします
# ノートPCのターミナル
pip install paho

自己著名証明書を利用するにはopensslなどで事前に証明書を取得しておく必要があるため、下記のコマンドでファイル local-server.crt に書き出します。
この記事ではopenremoteと連携するプログラムを~/gitprojects/openremote-practiceに配置します。
ホスト名である192.168.1.171を利用する環境に合わせて書き換えて実行してください。
# ノートPCのターミナル
mkdir -p ~/gitprojects/openremote-practice
cd ~/gitprojects/openremote-practice
rm local-server.crt
openssl s_client -connect 192.168.1.171:8883 -showcerts < /dev/null 2>/dev/null | openssl x509 -outform pem > local-server.crt

プログラムを作成します。
secret,assertId,hostは利用している環境に合わせて書き換えてください。
~/gitprojects/openermote-practice/send-on-mqtt.py
import paho.mqtt.client as mqttClient
import time
# import certifi

connected = False
clientId = 'MQTTpub'
username = 'master:example-service-user'
secret = 'IPPMCJaqcxxxxxxxxxxxxHEKx'
assertId = '212dqa0cUzTEZjpVI9m3u1'
attribute = 'temperature'
attributeValue = 18
host = '192.168.1.171'
# port = 1883 # without tls or ssl
port = 8883


def on_message(clinet, userdata, message):
print("received message =", str(message.payload.decode("utf-8")))


def on_connect(client, userdata, flags, rc):
if rc == 0:
print("connected")
global connected
connected = True
else:
print('connection failed')


def on_publish(client, userdata, result):
print("publish")
pass


clientMQTT = mqttClient.Client(clientId)
clientMQTT.username_pw_set(username, password=secret)
# clientMQTT.tls_set(certifi.where())
clientMQTT.tls_set("local-server.crt")
clientMQTT.tls_insecure_set(True)
clientMQTT.on_connect = on_connect
clientMQTT.on_publish = on_publish
clientMQTT.on_message = on_message
clientMQTT.connect(host, port)
clientMQTT.loop_start()

while connected != True:
print("not connected")
time.sleep(1)

clientMQTT.publish(
f"master/{clientId}/writeattributevalue/{attribute}/{assertId}", attributeValue)

clientMQTT.disconnect()
clientMQTT.loop_stop()

実行します。
# ノートPCのターミナル
cd ~/gitprojects/openremote-practice
python send-on-mqtt.py

成功するとこのようなログが表示されます。
失敗する場合はエラー内容を読みつつ接続情報を確認してください。
not connected
connected
publish

値として18を送っているので、openremoteのasset管理画面を見ると、送信に成功していればそれに合わせて値が変わります。


なお、接続情報が間違っているとエラーが出て繋がりませんが、書き込み先のassetは間違っていても送信側のログには何もエラーは表示されずに終わります。
そのような場合はopenremoteを動かしている装置(今回はraspberry pi)でログを確認してください。
# raspberry piのターミナル
cd ~/gitprojects/openremote
docker compose logs -f
成功時はこのようなログが出ます。
openremote-proxy-1       | 12/Mar/2023:15:07:55 +0000 mqtt~ CLIENT=192.168.1.159:54331 BACKEND=172.31.0.5:47244 -- 4/1/1/1/0 0/0

失敗時はこのようなログが出ます。
openremote-proxy-1       | 12/Mar/2023:15:05:24 +0000 mqtt~ CLIENT=192.168.1.159:55767 BACKEND=172.31.0.5:43630 -- 4/1/1/1/0 0/0
openremote-manager-1 | 2023-03-12 16:05:26.141 ERROR [Thread-2 (ActiveMQ-serve..463)] ache.activemq.artemis.core.protocol.mqtt : AMQ834002: Error processing control packet: MqttPublishMessage[fixedHeader=MqttFixedHeader[messageType=PUBLISH, isDup=false, qosLevel=AT_MOST_ONCE, isRetain=false, remainingLength=74], variableHeader=MqttPublishVariableHeader[topicName=master/MQTTpub/writeattributevalue/temperature/212dqa0cUzTEZjpVI9m3u1e, packetId=-1], payload=PooledSlicedByteBuf(ridx: 0, widx: 2, cap: 2/2, unwrapped: PooledUnsafeDirectByteBuf(ridx: 78, widx: 78, cap: 2048))]
openremote-manager-1 | ActiveMQSecurityException[errorType=SECURITY_EXCEPTION message=AMQ229032: User: master:example-service-user does not have permission='SEND' on address master.MQTTpub.writeattributevalue.temperature.212dqa0cUzTEZjpVI9m3u1e]
openremote-manager-1 | at org.apache.activemq.artemis.core.security.impl.SecurityStoreImpl.check(SecurityStoreImpl.java:289)
openremote-manager-1 | at org.apache.activemq.artemis.core.server.impl.ServerSessionImpl.securityCheck(ServerSessionImpl.java:502)
openremote-manager-1 | at org.apache.activemq.artemis.core.server.impl.ServerSessionImpl.doSend(ServerSessionImpl.java:2212)
openremote-manager-1 | at org.apache.activemq.artemis.core.server.impl.ServerSessionImpl.send(ServerSessionImpl.java:1840)
openremote-manager-1 | at org.apache.activemq.artemis.core.server.impl.ServerSessionImpl.send(ServerSessionImpl.java:1781)
openremote-manager-1 | at org.apache.activemq.artemis.core.protocol.mqtt.MQTTPublishManager.sendToQueue(MQTTPublishManager.java:217)
openremote-manager-1 | at org.apache.activemq.artemis.core.protocol.mqtt.MQTTProtocolHandler.handlePublish(MQTTProtocolHandler.java:317)
openremote-manager-1 | at org.apache.activemq.artemis.core.protocol.mqtt.MQTTProtocolHandler.act(MQTTProtocolHandler.java:160)
openremote-manager-1 | at org.apache.activemq.artemis.utils.actors.Actor.doTask(Actor.java:33)
openremote-manager-1 | at org.apache.activemq.artemis.utils.actors.ProcessorBase.executePendingTasks(ProcessorBase.java:67)
openremote-manager-1 | at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
openremote-manager-1 | at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
openremote-manager-1 | at org.apache.activemq.artemis.utils.ActiveMQThreadFactory$1.run(ActiveMQThreadFactory.java:118)
失敗時は書き込み先のassetが無くても権限設定が間違っていても「does not have permission='SEND'」のエラーが出て何が原因か判別できないので、userとassetの権限、assetのidを注意深く確認してください。

グラフで値を確認

assetのhistoryで確認

送信先のattributeがあるassetを開き、ページ下部のhistoryで履歴を見たいattributeを選びます。
sotre data pointsを有効にしているattributeをここで選べます。



過去の値をグラフで見れました。
期間やグラフの終了点を選べるので、見たい時間の情報を確認できます。


insightページの表示で確認

insightページを作って値の確認が可能です。
insightsページで+を押します。


widgetを配置可能な画面が開くものの初期表示だと不具合のためかwidgetを動かせないので、settingsを選び set mobile presetを押します。


mobile presetを行うと配置画面の枠が更新されてwidgetを配置可能になります。
widgetタブからline chartをドラッグドロップして置いてみます。


配置されたline chartを押すとメニューが右に表示されるので、+ attributeを選びます。


assetを選び、表示したいattributeを有効にし、addを押します。


表示されました。
表示間隔を調整できるので必要に応じて変えてください。
良ければsaveを押します。


mqttで送信された情報を表示するinsightページができました。


気になること

  • tls(https)無しで動かしたい
  • userに権限を付与してないと管理者権限でアクセスできるなど、開発途中の印象
  • 送信側でpublishで送信失敗したことを知りたい(subscribeすれば良い?)
  • insightページは即時更新されない
  • attributeのhisotry表示画面のグラフの方がinsightページのグラフより見やすく感じる

対策方法をご存知でしたらコメントなどで情報共有していただけると嬉しいです。

おわり

気になることはいくつかありますが、openremoteをrapsberry piで動かし、ノートPCのpythonプログラムからmqttで情報を送信し、送信された情報をopenremoteのグラフで確認できました。

送信に必要な設定と流れを把握できました。

参考

openremoteのgithuページです。
openremote

openremoteにmqttで情報送信する全体像の把握に役立ったpdfです。
Plant Pal MQTT Publish Subscribe (pdf)

openremote公式のmqttの使い方説明ページです。
Tutorial: Connect your MQTT Client

自己著名証明書でmqtt通信するのに参考にしたページです。
Trust Self Signed Certificates #783 - issues - paho.mqtt.c
How to use ssl/tls in paho mqtt using python? I got certificate verify failed
サーバに設定されている証明書を確認する方法
Using openssl to get the certificate from a server

変更履歴

2023.04.02
thingsboardの紹介記事のリンクを背景に追加しました。

0 件のコメント :