From c15d238e797bb3e4902eb4389cceadd8e9818916 Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Fri, 13 Jul 2018 22:40:39 +0200 Subject: [PATCH 1/3] Add MqTT handler --- daemon/CMakeLists.txt | 1 + daemon/matrix-mqtt.service | 11 +++++ daemon/mqtt/CMakeLists.txt | 4 ++ daemon/mqtt/matrix-mqtt | 90 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+) create mode 100644 daemon/matrix-mqtt.service create mode 100644 daemon/mqtt/CMakeLists.txt create mode 100644 daemon/mqtt/matrix-mqtt diff --git a/daemon/CMakeLists.txt b/daemon/CMakeLists.txt index 11685f5..3daaa76 100644 --- a/daemon/CMakeLists.txt +++ b/daemon/CMakeLists.txt @@ -50,3 +50,4 @@ target_link_libraries(matrixd wiringPi ${CMAKE_THREAD_LIBS_INIT}) install(TARGETS matrixd DESTINATION sbin/) add_subdirectory(webserver) +add_subdirectory(mqtt) diff --git a/daemon/matrix-mqtt.service b/daemon/matrix-mqtt.service new file mode 100644 index 0000000..54f7842 --- /dev/null +++ b/daemon/matrix-mqtt.service @@ -0,0 +1,11 @@ +[Unit] +Description=Matrix Daemon +After=network.target + +[Service] +Type=simple +ExecStart=/usr/local/sbin/matrix-mqtt +Nice=10 + +[Install] +WantedBy=multi-user.target diff --git a/daemon/mqtt/CMakeLists.txt b/daemon/mqtt/CMakeLists.txt new file mode 100644 index 0000000..ef2e985 --- /dev/null +++ b/daemon/mqtt/CMakeLists.txt @@ -0,0 +1,4 @@ +install(FILES matrix-mqtt + DESTINATION sbin/ + PERMISSIONS WORLD_EXECUTE WORLD_READ OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE) + diff --git a/daemon/mqtt/matrix-mqtt b/daemon/mqtt/matrix-mqtt new file mode 100644 index 0000000..ee108dc --- /dev/null +++ b/daemon/mqtt/matrix-mqtt @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 + +import codecs +import paho.mqtt.client as mqtt +from os import kill, system +import signal +import subprocess + +MQTT_HOSTNAME = '172.23.4.6' +MQTT_USERNAME = '' +MQTT_PASSWORD = '' +TOPIC_BASE = 'Kitchen/Matrix/' +TOPIC_ANIM = TOPIC_BASE + 'Animation' +TOPIC_LWT = TOPIC_BASE + 'lwt' +TOPIC_REBOOT = TOPIC_BASE + 'reboot' +TOPIC_SHUTDOWN = TOPIC_BASE + 'shutdown' + +# no root no fun. +ANIMATION_DICT = { + 1: 'matrix-clock', + 2: 'matrix-analogclock', + 3: 'matrix-chess', + 4: 'matrix-fullblink', + 5: 'matrix-cairoexample', + 6: 'matrix-circle', + 7: 'matrix-fire', + 8: 'matrix-zwickl', + 9: 'matrix-rain' +} + +cur_anim_pid = -1 + +def on_message_animation(client, userdata, message): + global cur_anim_pid + + no = int(message.payload.decode("utf-8")) + + if no >= 100: + if no == 102: + if cur_anim_pid != -1: + kill(cur_anim_pid, signal.SIGKILL) + cur_anim_pid = -1 + else: + print('Go home kiddy!') + + print('Aye, aye!') + + if not no in ANIMATION_DICT: + print('Go home kiddy!') + + if cur_anim_pid != -1: + kill(cur_anim_pid, signal.SIGKILL) + + proc = subprocess.Popen([ANIMATION_DICT.get(no), '-s', 'localhost']) + cur_anim_pid = proc.pid + print('Aye, aye, captain!') + +def on_message_reboot(client, userdata, message): + if not message.retain: + system("reboot") + +def on_message_shutdown(client, userdata, message): + if not message.retain: + system("poweroff") + +def on_connect(client, userdata, flags, rc): + print("Connection returned result: " + mqtt.connack_string(rc)) + client.subscribe(TOPIC_ANIM) + client.subscribe(TOPIC_REBOOT) + client.subscribe(TOPIC_SHUTDOWN) + client.publish(TOPIC_LWT, 'online', 0, True) + +mqttc = mqtt.Client() +mqttc.on_connect = on_connect +mqttc.message_callback_add(TOPIC_ANIM, on_message_animation) +mqttc.message_callback_add(TOPIC_REBOOT, on_message_reboot) +mqttc.message_callback_add(TOPIC_SHUTDOWN, on_message_shutdown) +mqttc.will_set(TOPIC_LWT, 'offline', 0, True) + +if MQTT_USERNAME != "": + mqttc.username_pw_set(MQTT_USERNAME, MQTT_PASSWORD) + +mqttc.connect_async(MQTT_HOSTNAME) + +try: + mqttc.loop_forever() +except KeyboardInterrupt: + pass + +mqttc.loop_stop() From e4c4aa095ef3e4ab799dcafe9b6a193f01fc779b Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Sat, 14 Jul 2018 01:06:43 +0200 Subject: [PATCH 2/3] Remove trailing newline --- daemon/mqtt/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/daemon/mqtt/CMakeLists.txt b/daemon/mqtt/CMakeLists.txt index ef2e985..e36711c 100644 --- a/daemon/mqtt/CMakeLists.txt +++ b/daemon/mqtt/CMakeLists.txt @@ -1,4 +1,3 @@ install(FILES matrix-mqtt DESTINATION sbin/ PERMISSIONS WORLD_EXECUTE WORLD_READ OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE) - From 528f0e7af8f22467729211b2581c3022ac570cdb Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Sat, 14 Jul 2018 01:34:40 +0200 Subject: [PATCH 3/3] Added license, don't require root anymore, better error handling --- daemon/mqtt/matrix-mqtt | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/daemon/mqtt/matrix-mqtt b/daemon/mqtt/matrix-mqtt index ee108dc..9faf94e 100644 --- a/daemon/mqtt/matrix-mqtt +++ b/daemon/mqtt/matrix-mqtt @@ -1,6 +1,23 @@ #!/usr/bin/env python3 -import codecs +""" +matrix-mqtt -- Daemon to control the LED Matrix via MqTT + +Copyright (c) Binary Kitchen e.V., 2018 + +Author: + Thomas Basler + Ralf Ramsauer + +This work is licensed under the terms of the GNU GPL, version 2. See +the LICENSE file in the top-level directory. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. +""" + import paho.mqtt.client as mqtt from os import kill, system import signal @@ -15,7 +32,6 @@ TOPIC_LWT = TOPIC_BASE + 'lwt' TOPIC_REBOOT = TOPIC_BASE + 'reboot' TOPIC_SHUTDOWN = TOPIC_BASE + 'shutdown' -# no root no fun. ANIMATION_DICT = { 1: 'matrix-clock', 2: 'matrix-analogclock', @@ -57,11 +73,11 @@ def on_message_animation(client, userdata, message): def on_message_reboot(client, userdata, message): if not message.retain: - system("reboot") + system("systemctl reboot") def on_message_shutdown(client, userdata, message): if not message.retain: - system("poweroff") + system("systemctl poweroff") def on_connect(client, userdata, flags, rc): print("Connection returned result: " + mqtt.connack_string(rc)) @@ -82,9 +98,14 @@ if MQTT_USERNAME != "": mqttc.connect_async(MQTT_HOSTNAME) -try: - mqttc.loop_forever() -except KeyboardInterrupt: - pass +# For some reasons the loop_forever method throws an exception +# Let's just continue reconnecting +while True: + try: + mqttc.loop_forever() + except KeyboardInterrupt: + break + except: + pass mqttc.loop_stop()