#!/usr/bin/env python3 # vim: ts=2 sw=2 et import grp import json import os import stat import subprocess import threading import time from configparser import ConfigParser from dataclasses import dataclass import RPi.GPIO as gpio import paho.mqtt.client as mqtt class FoodoorMQTT: def __init__(self, area): self.area = area self.client = mqtt.Client() self.client.on_connect = self.on_connect self.client.on_message = self.on_message self._connect_lock = threading.Condition() def connect(self): try: self.client.connect("mqtt.chaospott.de") self.client.loop_start() with self._connect_lock: self._connect_lock.wait() except Exception as e: print(f"Verbindungsfehler zu MQTT-Server: {e}") def disconnect(self): self.client.loop_stop() def on_connect(self, client, userdata, flags, rc): with self._connect_lock: self._connect_lock.notify() def on_message(self, client, userdata, msg): print(f"MQTT-Server Message: {msg.topic} {msg.payload}") def send_state(self, locked: bool): self.client.publish(f"foobar/{self.area}/foodoor/status", { False: "open", True: "closed", }[locked], qos=0, retain=True) # Definitions for output PIN_OPEN = 24 PIN_CLOSE = 27 # Read config parser = ConfigParser() parser.read('/etc/foodoord.conf') @dataclass class API: location: str api_url: str consumer_key: str consumer_secret: str def update_state(self, locked): subprocess.check_call([ "/usr/bin/curl", "-XPOST", "--header", "Content-Type: application/json", "--data", json.dumps({"consumer_key": self.consumer_key, "consumer_secret": self.consumer_secret, self.location: locked}), self.api_url ]) MQTT = FoodoorMQTT("unten") APIv1 = API("cellar", parser.get('doorstatus', 'status_url'), parser.get('doorstatus', 'key'), parser.get('doorstatus', 'secret'), ) APIv2 = API("cellar", parser.get('doorstatusv2', 'status_url'), parser.get('doorstatusv2', 'key'), parser.get('doorstatusv2', 'secret'), ) def write_state(state): try: with open("/tmp/door_state", "w") as f: f.write(state) except: pass def update_api(locked): try: MQTT.send_state(locked) except: pass try: APIv1.update_state(locked) except: pass try: APIv2.update_state(locked) except: pass def main(): # Start settings gpio.setmode(gpio.BCM) gpio.setup(PIN_OPEN, gpio.OUT) gpio.setup(PIN_CLOSE, gpio.OUT) # Setting up FiFo to get sshd-output try: os.mkfifo("/var/run/foodoord.pipe") os.chown("/var/run/foodoord.pipe", -1, grp.getgrnam('foodoor')[2]) os.chmod("/var/run/foodoord.pipe", stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP) except OSError: pass MQTT.connect() ssh_input = open("/var/run/foodoord.pipe", "r") while True: # Read sshd output from pipe pipe_cmd = ssh_input.readline().strip() if pipe_cmd == "close": gpio.output(PIN_CLOSE, 1) time.sleep(1) gpio.output(PIN_CLOSE, 0) write_state("closed") update_api(True) elif pipe_cmd == "open": # Locking gpio.output(PIN_OPEN, 1) time.sleep(1) gpio.output(PIN_OPEN, 0) write_state("open") # Save State update_api(False) # Status Update time.sleep(0.2) if __name__ == "__main__": main()