foodoord/debian/usr/sbin/foodoord_unten
2025-01-10 01:10:31 +01:00

158 lines
3.6 KiB
Python
Executable File

#!/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()