babycam/scripts/network_state.py

126 lines
3.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Babycam Network State Machine
Verwaltet die drei Betriebsmodi:
A Heimnetz (wlan0 verbunden, AP aus)
B Kein WLAN (AP auf wlan1 automatisch)
C Setup-Modus (AP läuft, User konfiguriert WLAN)
Override-Datei: /tmp/babycam-ap-override
"on" → AP immer an (manuell)
"off" → AP immer aus (manuell)
fehlt → Automatik
"""
import subprocess
import time
import logging
import sys
import os
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
handlers=[logging.StreamHandler(sys.stdout)],
)
log = logging.getLogger(__name__)
AP_INTERFACE = "wlan1"
CLIENT_INTERFACE = "wlan0"
AP_IP = "192.168.50.1"
CHECK_INTERVAL = 30 # Sekunden
OVERRIDE_FILE = "/var/lib/babycam/ap-override"
def run(cmd, check=False):
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if check and result.returncode != 0:
log.error(f"Fehler bei: {cmd}\n{result.stderr}")
return result
def get_override():
"""Liest die manuelle Override-Einstellung. Gibt 'on', 'off' oder None zurück."""
try:
with open(OVERRIDE_FILE) as f:
val = f.read().strip().lower()
if val in ("on", "off"):
return val
except FileNotFoundError:
pass
return None
def is_wlan0_connected():
result = run(f"nmcli -t -f GENERAL.STATE device show {CLIENT_INTERFACE}")
return "100 (connected)" in result.stdout
def is_ap_running():
result = run("systemctl is-active hostapd")
return result.stdout.strip() == "active"
def start_ap():
log.info("Starte Access Point (BabyCam)...")
run("ip addr add 192.168.50.1/24 dev wlan1 2>/dev/null || true")
run("ip link set wlan1 up")
run("systemctl start hostapd", check=True)
run("systemctl start dnsmasq", check=True)
log.info("Access Point gestartet.")
def stop_ap():
log.info("Stoppe Access Point...")
run("systemctl stop hostapd")
run("systemctl stop dnsmasq")
run("ip addr flush dev wlan1 2>/dev/null || true")
log.info("Access Point gestoppt.")
def main():
log.info("Babycam Network State Machine gestartet.")
current_mode = None
while True:
override = get_override()
connected = is_wlan0_connected()
ap_running = is_ap_running()
if override == "on":
# Manuell: AP immer an
if current_mode != "MANUAL_ON":
log.info("Modus: Manuell Access Point erzwungen AN.")
if not ap_running:
start_ap()
current_mode = "MANUAL_ON"
elif override == "off":
# Manuell: AP immer aus
if current_mode != "MANUAL_OFF":
log.info("Modus: Manuell Access Point erzwungen AUS.")
if ap_running:
stop_ap()
current_mode = "MANUAL_OFF"
else:
# Automatik
if connected:
if current_mode != "A":
log.info("Modus A: Heimnetz aktiv AP aus.")
if ap_running:
stop_ap()
current_mode = "A"
else:
if current_mode != "B":
log.info("Modus B: Kein WLAN starte Access Point.")
if not ap_running:
start_ap()
current_mode = "B"
time.sleep(CHECK_INTERVAL)
if __name__ == "__main__":
main()