6 Commits

Author SHA1 Message Date
T cca78896a9 use correct timezone 2026-06-17 13:20:48 +02:00
지지 ᚠד (Jiji Freya Daniel) Maslowski 23e126a08b do not open upstairs on bell ring on a Wednesday
Signed-off-by: 지지 ᚠד (Jiji Freya Daniel) Maslowski <info@orangecms.org>
2026-06-13 12:40:42 +02:00
Daniel Maslowski 3dd171484f Document how key update script runs the commands 2025-07-23 21:20:17 +02:00
T ba2946706b Fix update-keydb 2025-02-13 16:44:08 +01:00
T 80573055d9 Resend last known state on reconnect 2025-01-27 23:50:22 +01:00
T 1941698a52 Bug Fix 2025-01-14 19:04:13 +01:00
7 changed files with 45 additions and 18 deletions
+12 -2
View File
@@ -43,8 +43,18 @@ Das IdentityFile ist der Deploy-SSH-Key, der im [Repo](https://git.chaospott.de/
### Schlüsselupdate ### Schlüsselupdate
`foodoor-update-keydb` Das Script [`foodoor-update-keydb`](debian/usr/sbin/foodoor-update-keydb)
Aktualisiert die Schlüssel auf der Tür und baut die *Authorized_Keys* für die User *open* und *close*. Keys die nicht dem OpenSSH-Format mit 4096 bit entsprechen, werden ignoriert. Wenn das Script von Hand aufgerufen wird, werden die betroffenen Keys angezeigt. Über einen Cronjob werden die Keys alle **5 Min aktualisiert**. aktualisiert regelmäßig die Schlüssel auf der Tür und baut die `authorized_keys`
für die Benutzer `open` und `close`. Keys, die nicht dem OpenSSH-Format mit 4096
Bit entsprechen, werden ignoriert.
Wenn das Script von Hand aufgerufen wird, werden die betroffenen Keys angezeigt.
Über einen Cronjob werden die Keys **alle 5 Minuten aktualisiert**.
Das Script beinhaltet auch den Aufruf von `/usr/sbin/foodoor`, das dem Keyfile
für den jeweiligen Schlüssel hinzugefügt wird. Bei Login mit dem Benutzer
`open`/`close`/`door` wird das entsprechende Argument dadurch mitgegeben, um die
Tür zu öffnen oder zu schließen bzw. den Status abzufragen.
### Schlüsselformate ### Schlüsselformate
+1 -1
View File
@@ -1,3 +1,3 @@
#!/bin/bash #!/bin/bash
VERSION=3.3.0 VERSION=$(grep -oP '(?<=Version: ).*$' debian/DEBIAN/control)
dpkg-deb --root-owner-group -b debian "foodoord_${VERSION}_all.deb" dpkg-deb --root-owner-group -b debian "foodoord_${VERSION}_all.deb"
+2 -2
View File
@@ -1,6 +1,6 @@
Package: foodoord Package: foodoord
Version: 3.3.0 Version: 3.4.0
Maintainer: Bandie <bandie@chaospott.de>, Tobi <tobi@chaospott.de> Maintainer: Tobi <tobi@chaospott.de>
Architecture: all Architecture: all
Description: Control the doors of the club, ja! Description: Control the doors of the club, ja!
Depends: dash, git, python3, pip, tmux Depends: dash, git, python3, pip, tmux
+3 -2
View File
@@ -26,8 +26,9 @@ while [ "$prompt" != "oben" ] && [ "$prompt" != "unten" ]; do
done done
echo "##################" echo "##################"
echo "Installing dependencies via pip: pifacecommon pifacedigitalio" PIP_DEP=(pifacecommon pifacedigitalio paho-mqtt)
pip install pifacecommon pifacedigitalio paho-mqtt echo "Installing dependencies via pip: ${PIP_DEP[*]}"
pip install "${PIP_DEP[@]}"
echo "Enabling and starting systemd-Services" echo "Enabling and starting systemd-Services"
systemctl daemon-reload systemctl daemon-reload
+2 -2
View File
@@ -1,4 +1,4 @@
#!/bin/bash #!/usr/bin/env bash
set -e set -e
export PATH="/usr/bin:/bin:/usr/sbin:/sbin" export PATH="/usr/bin:/bin:/usr/sbin:/sbin"
@@ -8,7 +8,7 @@ temp_outfile=$dest.tmp
if [ ! -e "$dest/.git/config" ]; then if [ ! -e "$dest/.git/config" ]; then
#echo "Repo does not exist, trying to clone..." #echo "Repo does not exist, trying to clone..."
git -C "$dest" clone --quiet --single-branch --depth=1 ssh://git.chaospott.de/Keyverwaltung/foodoor-keys.git "$dest" git clone --quiet --single-branch --depth=1 ssh://git.chaospott.de/Keyverwaltung/foodoor-keys.git "$dest"
else else
#echo "Repo exists, updating..." #echo "Repo exists, updating..."
git -C "$dest" fetch --quiet && git -C "$dest" merge --quiet origin/master master git -C "$dest" fetch --quiet && git -C "$dest" merge --quiet origin/master master
+21 -9
View File
@@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# vim: ts=2 sw=2 et # vim: ts=2 sw=2 et
import datetime
import grp import grp
import json import json
import os import os
@@ -12,6 +13,7 @@ import threading
import time import time
from configparser import ConfigParser from configparser import ConfigParser
from dataclasses import dataclass from dataclasses import dataclass
from zoneinfo import ZoneInfo
import paho.mqtt.client as mqtt import paho.mqtt.client as mqtt
import pifacedigitalio import pifacedigitalio
@@ -24,6 +26,7 @@ class FoodoorMQTT:
self.client.on_connect = self.on_connect self.client.on_connect = self.on_connect
self.client.on_message = self.on_message self.client.on_message = self.on_message
self._last_state = None
self._connect_lock = threading.Condition() self._connect_lock = threading.Condition()
def connect(self): def connect(self):
@@ -39,6 +42,8 @@ class FoodoorMQTT:
self.client.loop_stop() self.client.loop_stop()
def on_connect(self, client, userdata, flags, rc): def on_connect(self, client, userdata, flags, rc):
if self._last_state is not None:
self.send_state(self._last_state)
with self._connect_lock: with self._connect_lock:
self._connect_lock.notify() self._connect_lock.notify()
@@ -46,6 +51,7 @@ class FoodoorMQTT:
print(f"MQTT-Server Message: {msg.topic} {msg.payload}") print(f"MQTT-Server Message: {msg.topic} {msg.payload}")
def send_state(self, locked: bool): def send_state(self, locked: bool):
self._last_state = locked
self.client.publish(f"foobar/{self.area}/foodoor/status", { self.client.publish(f"foobar/{self.area}/foodoor/status", {
False: "open", False: "open",
True: "closed", True: "closed",
@@ -108,6 +114,7 @@ class Foodoord:
self.status_open = False self.status_open = False
self.mqtt = FoodoorMQTT("oben") self.mqtt = FoodoorMQTT("oben")
self.pifacedigital = pifacedigitalio.PiFaceDigital()
self.listener = pifacedigitalio.InputEventListener() self.listener = pifacedigitalio.InputEventListener()
self.listener.register(self.DOOR_BELL, pifacedigitalio.IODIR_RISING_EDGE, self.doorbell, settle_time=10) self.listener.register(self.DOOR_BELL, pifacedigitalio.IODIR_RISING_EDGE, self.doorbell, settle_time=10)
self.listener.register(self.CLOSE_BUTTON, pifacedigitalio.IODIR_RISING_EDGE, self.close_button, settle_time=5) self.listener.register(self.CLOSE_BUTTON, pifacedigitalio.IODIR_RISING_EDGE, self.close_button, settle_time=5)
@@ -137,15 +144,21 @@ class Foodoord:
def set_led(self, color): def set_led(self, color):
for led, gpio in self.LEDS.items(): for led, gpio in self.LEDS.items():
if color & led: if color & led:
pifacedigital.leds[gpio].turn_on() self.pifacedigital.leds[gpio].turn_on()
else: else:
pifacedigital.leds[gpio].turn_off() self.pifacedigital.leds[gpio].turn_off()
def doorbell(self, event): def doorbell(self, event):
# ignore doorbell button on Wednesdays
now = datetime.datetime.now(ZoneInfo("Europe/Berlin"))
if ((now.isoweekday() == 3 and now.time() >= datetime.time(10))
or (now.isoweekday() == 4 and now.time() < datetime.time(2))):
return
if self.status_open: if self.status_open:
pifacedigital.relays[self.RELAYS_UNLOCK].toggle() self.pifacedigital.relays[self.RELAYS_UNLOCK].toggle()
time.sleep(2) time.sleep(2)
pifacedigital.relays[self.RELAYS_UNLOCK].toggle() self.pifacedigital.relays[self.RELAYS_UNLOCK].toggle()
def close_button(self, _event): def close_button(self, _event):
self.status_open = False self.status_open = False
@@ -156,7 +169,6 @@ class Foodoord:
self.mqtt.connect() self.mqtt.connect()
self.listener.activate() self.listener.activate()
pifacedigital = pifacedigitalio.PiFaceDigital()
signal.signal(signal.SIGTERM, self.signal_handler) signal.signal(signal.SIGTERM, self.signal_handler)
# Start settings # Start settings
@@ -176,18 +188,18 @@ class Foodoord:
pipe_cmd = ssh_input.readline().strip() pipe_cmd = ssh_input.readline().strip()
if pipe_cmd == "close" and self.status_open: if pipe_cmd == "close" and self.status_open:
pifacedigital.relays[self.RELAYS_LOCK].toggle() self.pifacedigital.relays[self.RELAYS_LOCK].toggle()
time.sleep(1) time.sleep(1)
pifacedigital.relays[self.RELAYS_LOCK].toggle() self.pifacedigital.relays[self.RELAYS_LOCK].toggle()
self.status_open = False self.status_open = False
self.update_api(True) self.update_api(True)
self.set_led(self.RED) self.set_led(self.RED)
elif pipe_cmd == "open": elif pipe_cmd == "open":
pifacedigital.relays[self.RELAYS_UNLOCK].toggle() self.pifacedigital.relays[self.RELAYS_UNLOCK].toggle()
time.sleep(2) time.sleep(2)
pifacedigital.relays[self.RELAYS_UNLOCK].toggle() self.pifacedigital.relays[self.RELAYS_UNLOCK].toggle()
if not self.status_open: if not self.status_open:
self.update_api(False) self.update_api(False)
+4
View File
@@ -22,6 +22,7 @@ class FoodoorMQTT:
self.client.on_connect = self.on_connect self.client.on_connect = self.on_connect
self.client.on_message = self.on_message self.client.on_message = self.on_message
self._last_state = None
self._connect_lock = threading.Condition() self._connect_lock = threading.Condition()
def connect(self): def connect(self):
@@ -37,6 +38,8 @@ class FoodoorMQTT:
self.client.loop_stop() self.client.loop_stop()
def on_connect(self, client, userdata, flags, rc): def on_connect(self, client, userdata, flags, rc):
if self._last_state is not None:
self.send_state(self._last_state)
with self._connect_lock: with self._connect_lock:
self._connect_lock.notify() self._connect_lock.notify()
@@ -44,6 +47,7 @@ class FoodoorMQTT:
print(f"MQTT-Server Message: {msg.topic} {msg.payload}") print(f"MQTT-Server Message: {msg.topic} {msg.payload}")
def send_state(self, locked: bool): def send_state(self, locked: bool):
self._last_state = locked
self.client.publish(f"foobar/{self.area}/foodoor/status", { self.client.publish(f"foobar/{self.area}/foodoor/status", {
False: "open", False: "open",
True: "closed", True: "closed",