Warning
đ§ Work in Progress â ESP-Kerberos befindet sich noch mitten in der Entwicklungsphase und wird aktuell umgesetzt. Hier kann sich tĂ€glich etwas Ă€ndern!
Batteriebetriebener Ăffnungsmelder auf ESP32-C6-Basis fĂŒr Paketboxen mit integrierter Briefbox.
Wacht ĂŒber bis zu 4 unabhĂ€ngige EingĂ€nge gleichzeitig â typisch Brief-Einwurf, Paket-Einwurf, Brief-Entnahme und Paket-Entnahme â funktioniert aber mit jedem potentialfreien Schalter fĂŒr jede Art "etwas wurde geöffnet/ausgelöst"-Erkennung â siehe Sensor/Schalter. Die gesamte Konfiguration (WLAN, EingĂ€nge, Meldekanal inkl. MQTT) lĂ€uft ĂŒber ein WebUI im Access-Point-Modus â kein Neu-Kompilieren pro GerĂ€t nötig, siehe Setup.
Kernidee: der ESP32 verbringt praktisch seine gesamte Lebenszeit im Deep Sleep (Verbrauch im niedrigen ”A-Bereich) und wacht ausschlieĂlich durch den externen Schalter auf. Nach dem Wecken verbindet er sich per WLAN, schickt eine Push-Nachricht und legt sich sofort wieder schlafen â die aktive Wachzeit pro Auslösung liegt im Sekundenbereich.
Kein PlatformIO, kein Terminal, kein Compiler nötig: Firmware direkt aus dem Browser flashen, per ESP Web Tools.
đ docbigs-lab.github.io/ESP-Kerberos â ein Klick auf âInstall" reicht.
- Voraussetzung: Chrome oder Edge (Web Serial API), ESP32-C6 per USB angeschlossen.
- Danach direkt weiter mit Konfiguration ĂŒber WebUI.
- Quelle des Installers:
docs/index.html+docs/manifest.json, Firmware-Datei wird vonmerge_bin.pybei jedempio runautomatisch nachdocs/ESP-Kerberos-merged.bingebaut.
Deep Sleep ââ(Schalter löst aus)âââ¶ Wake âââ¶ WLAN verbinden âââ¶ Benachrichtigung senden
âČ â
â âŒ
âââââââââââââââââ Cooldown-Sleep (nur Timer-Wakeup) âââââââââââââââ
- Deep Sleep als Grundzustand, Aufwachen ĂŒber EXT1-Wakeup an einem GPIO.
- Entprellung: nach dem Wachwerden kurzer Delay + erneute Pin-PrĂŒfung, um Kontaktprellen nicht als Auslösung zu werten.
- WLAN-Verbindung (optional mit statischer IP statt DHCP, spart Verbindungszeit).
- Push-Benachrichtigung per HTTPS an den konfigurierten Meldekanal (Telegram, Pushover, ntfy.sh oder MQTT â siehe MQTT / Home Assistant) â kein SMTP/E-Mail-Versand, das wĂ€re auf dem Chip deutlich langsamer.
- Cooldown-Sleep: nach dem Versand schlĂ€ft der Chip fĂŒr einige Sekunden mit ausschlieĂlich Timer-Wakeup (Schalter-Wakeup ist in dieser Zeit deaktiviert), damit Nachschwingen/Prellen keine weiteren Nachrichten auslöst. Erst danach wird der Schalter wieder scharf geschaltet.
- Bleibt ein Eingang lange ausgelöst (z. B. Klappe bleibt offen): Nach jedem Cooldown-Ablauf prĂŒft der Chip kurz und ohne WLAN/Nachricht, ob der Kontakt noch aktiv ist. Ist das der Fall, schlĂ€ft er einfach direkt fĂŒr einen weiteren Cooldown-Zyklus weiter â ganz ohne erneuten Versand. Erst wenn der Kontakt wieder in Ruhe ist, wird der Trigger erneut scharf geschaltet; eine neue Auslösung löst dann wieder genau eine Nachricht aus. Pro Auslöse-Flanke gibt es also immer nur eine Nachricht, unabhĂ€ngig davon, wie lange der Kontakt offen bleibt.
Die gesamte Konfiguration (WLAN, EingĂ€nge, Meldekanal) erfolgt zur Laufzeit ĂŒber ein WebUI â keine Zugangsdaten-Datei, kein Neu-Kompilieren pro GerĂ€t:
-
Erststart: Ist noch keine Konfiguration im Flash gespeichert, öffnet das GerÀt automatisch ein eigenes WLAN namens
ESP-Kerberos-Setup-XXXX(XXXX= letzte zwei MAC-Adress-Bytes, zur Unterscheidung mehrerer GerÀte). -
AP-Passwort: Das Setup-WLAN ist WPA2-geschĂŒtzt. Solange kein eigenes Passwort gesetzt wurde, gilt der aus der MAC-Adresse abgeleitete Default
kerberos-XXXX(dieselben vier Hex-Zeichen wie im WLAN-Namen) â pro GerĂ€t unterschiedlich, kein fĂŒr alle GerĂ€te identisches Passwort. Im Formular unter "Zugriffsschutz (Setup-AP)" durch ein eigenes Passwort (mind. 8 Zeichen) ersetzbar; leeres Feld lĂ€sst das aktuelle/Standard-Passwort unverĂ€ndert. SchĂŒtzt sowohl die Konfigurationsseite (inkl. WLAN-/Meldekanal-Zugangsdaten) als auch das Firmware-Update vor jedem, der nur in Funkreichweite ist. -
Mit diesem WLAN verbinden â auf den meisten Smartphones öffnet sich automatisch ein Anmelde-Popup mit der Konfigseite (Captive Portal). Ăffnet sich nichts von selbst,
http://192.168.4.1manuell im Browser aufrufen. -
Formular ausfĂŒllen: Das SSID-Feld schlĂ€gt gefundene WLANs vor (nach SignalstĂ€rke sortiert, stĂ€rkstes zuerst â der Button "Netzwerke neu suchen" stöĂt einen erneuten Scan an, ohne bereits eingetragene Werte in anderen Feldern zu verwerfen), man kann aber auch jede beliebige SSID frei eintippen (z. B. bei versteckten Netzwerken). Bei aktivierter "Statische IP verwenden"-Checkbox zusĂ€tzlich IP-Adresse, Gateway, Subnetzmaske und DNS-Server eintragen (sonst bleibt es bei DHCP, Standardfall). Dazu gemeinsame Cooldown-Dauer und optionales Heartbeat-Intervall (siehe Heartbeat), sowie bis zu 4 unabhĂ€ngige EingĂ€nge (siehe Mehrere EingĂ€nge) â standardmĂ€Ăig sind alle 4 aktiv, vorbelegt mit den Paketbox-Rollen Brief-Einwurf/Paket-Einwurf/Brief-Entnahme/Paket-Entnahme, per Checkbox einzeln ab-/zuwĂ€hlbar â, jeder mit eigenem GPIO-Pin, eigener Auslöse-PolaritĂ€t und eigenem Nachrichtentext, gewĂŒnschter Meldekanal (gilt fĂŒr alle EingĂ€nge gemeinsam, inkl. MQTT â siehe MQTT / Home Assistant) mit dessen Zugangsdaten. Speichern â GerĂ€t startet neu und verbindet sich mit dem konfigurierten WLAN.
-
Rekonfiguration: Kurz nach einem echten Power-On/Reset (Batterie/USB neu anschlieĂen oder EN-Taste drĂŒcken â nicht nach einem normalen Deep-Sleep-Aufwachen durch einen Trigger) öffnet sich ein 5-Sekunden-Fenster: Wird in dieser Zeit die BOOT-Taste des Boards gedrĂŒckt, öffnet das GerĂ€t das Setup-WLAN erneut, unabhĂ€ngig davon, ob schon eine Konfiguration existiert. Ohne Tastendruck lĂ€uft der Normalbetrieb einfach weiter. Bei einer bereits konfigurierten Rekonfiguration kehrt das Portal ohne Eingabe nach 10 Minuten InaktivitĂ€t automatisch in den Normalbetrieb mit der bisherigen Konfiguration zurĂŒck. Ablauf zum Rekonfigurieren: Reset-Taste drĂŒcken, loslassen, dann innerhalb von 5 Sekunden die BOOT-Taste drĂŒcken (nicht gleichzeitig mit dem Reset â der ROM-Bootloader prĂŒft deren Pegel nur exakt im Reset-Moment fĂŒr den Flash-Download-Modus, danach ist GPIO9 ein normaler Eingang).
Die Konfiguration wird im NVS-Flash (Preferences) gespeichert und ĂŒbersteht Neustarts sowie
Firmware-Updates ĂŒber die OTA-Funktion (solange der Flash nicht komplett
gelöscht wird).
- AP-Passwort vergessen? Es gibt bewusst keinen eigenen Software-Reset dafĂŒr â stattdessen ĂŒber USB oder den Web-Flasher neu flashen. Das schreibt Bootloader, Partitionstabelle und Firmware auf einen Schlag neu; die LĂŒcke im gemergten Image ĂŒberschreibt dabei auch die NVS-Partition mit gelöschtem Flash-Inhalt. Das GerĂ€t startet danach komplett zurĂŒckgesetzt â WLAN, EingĂ€nge, Meldekanal und AP-Passwort sind weg, nicht nur Letzteres, und mĂŒssen ĂŒber das Setup-Portal neu eingerichtet werden.
Firmware-Updates lassen sich, ohne das GerĂ€t per USB anzuschlieĂen, direkt ĂŒber das (durch das AP-Passwort geschĂŒtzte) Setup-Portal einspielen:
- Ins Setup-WLAN verbinden (Rekonfiguration öffnet das Portal auch bei bereits konfigurierten GerÀten).
- Auf der Konfigseite oben auf "Firmware-Update" klicken.
ESP-Kerberos-ota.binausdocs/im Projekt-Repository auswĂ€hlen und hochladen â die Datei entsteht automatisch bei jedempio run(viamerge_bin.py), kein manuelles Suchen im PlatformIO-Build-Ordner nötig.- Nach erfolgreichem Upload startet das GerĂ€t automatisch mit der neuen Firmware neu.
Wichtig â die richtige Datei: Hochgeladen wird ESP-Kerberos-ota.bin (reine App-Partition),
nicht ESP-Kerberos-merged.bin aus demselben Ordner (die enthÀlt zusÀtzlich Bootloader und
Partitionstabelle fĂŒr den USB-Erstflash und ist fĂŒr OTA ungeeignet). Ein versehentlicher Upload
der falschen Datei fĂŒhrt zu einem nicht startenden GerĂ€t â Wiederherstellung dann nur per USB
oder Web-Flasher (siehe AP-Passwort vergessen
oben, Reflash setzt dabei die gesamte Konfiguration zurĂŒck).
Bewusst kein automatischer Versions-Check und kein Bezug einer Firmware-Datei von extern â der Upload passiert rein lokal im Setup-AP, ausgelöst durch den Nutzer selbst. Das hĂ€lt den sonst auf minimale Wachzeit optimierten Normalbetrieb (Deep Sleep/Trigger-Wake) vollstĂ€ndig unberĂŒhrt: OTA ist nur im ohnehin seltenen Rekonfigurations-Fenster verfĂŒgbar, nie im Hintergrund wĂ€hrend des Batteriebetriebs.
Elektrisch ist jeder potentialfreie Schalter (dry contact) gleich verkabelt: eine Ader an
den Trigger-Pin, die andere an GND. Der interne Pull-up hÀlt den Pin im Ruhezustand HIGH;
schlieĂt der Schalter, geht der Pin auf LOW. Diese Verkabelung ist unabhĂ€ngig vom
Schaltertyp immer identisch:
GPIOx (Trigger-Pin) âââŹââ Schalter ââ GND
â
(interner Pull-up, per Software aktiviert)
Funktioniert z. B. mit:
- Reedkontakt (Magnetkontakt) â klassisch fĂŒr Klappen/TĂŒren/Fenster
- Mikroschalter / Endschalter â z. B. an einer Klappe, die beim Ăffnen einen Hebel drĂŒckt
- Taster â fĂŒr "manueller Alarmknopf"-AnwendungsfĂ€lle
- Kipp-/Neigungsschalter â z. B. Kippt-Erkennung
- Jeder andere einfache mechanische Schalter mit zwei potentialfreien AnschlĂŒssen
Welche Pin-PolaritĂ€t als "Auslösung" gilt, hĂ€ngt nur davon ab, ob der jeweilige Schalter beim auslösenden Ereignis öffnet oder schlieĂt â das wird im WebUI pro Eingang eingestellt, die Verkabelung selbst Ă€ndert sich dabei nicht.
Wichtige EinschrĂ€nkung (ESP32-C6): Nur die GPIOs 0â7 sind RTC/LP-fĂ€hig und damit grundsĂ€tzlich als Deep-Sleep-Wakeup-Quelle nutzbar. Jeder andere Pin kann den Chip nicht aus dem Deep Sleep wecken. Welche dieser acht Pins auf dem jeweiligen Board tatsĂ€chlich herausgefĂŒhrt sind, hĂ€ngt vom konkreten Modul ab (Pinout/Silkscreen prĂŒfen). Auf dem Referenzboard (FireBeetle 2 ESP32-C6) ist GPIO0 zusĂ€tzlich fest mit dem eingebauten Akku-Spannungsteiler verdrahtet (siehe BatterieĂŒberwachung) und daher als Trigger-Pin ungeeignet â die WebUI-Auswahl fĂŒr Trigger-EingĂ€nge ist deshalb auf GPIO1â7 begrenzt.
Die werkseitig vorbelegten Pins (GPIO1, 2, 3, 4) passen zum Referenzboard (FireBeetle 2 ESP32-C6, siehe Hardware) â dort ist GPIO0 fest mit dem eingebauten Akku-Spannungsteiler verdrahtet (siehe BatterieĂŒberwachung) und daher als Trigger-Pin ungeeignet. Auf anderen Boards kann die sinnvolle Vorbelegung abweichen â die Zuordnung ist pro Eingang im Setup-Portal unter "GPIO-Pin" frei Ă€nderbar, ein Neuflashen ist dafĂŒr nicht nötig.
ESP-Kerberos ĂŒberwacht bis zu 4 unabhĂ€ngige EingĂ€nge gleichzeitig â namensgebender Regelfall ist eine Paketbox mit integrierter Briefbox (Brief-Einwurf, Paket-Einwurf, Brief-Entnahme, Paket-Entnahme), es funktioniert aber genauso fĂŒr jede andere Kombination (z. B. Briefkasten + GartentĂŒr + Garagentor). Jeder Eingang ist im WebUI einzeln:
- aktivierbar/deaktivierbar (nicht benötigte EingÀnge einfach abwÀhlen),
- einem eigenen GPIO-Pin (0â7) zugeordnet,
- mit eigener Auslöse-PolaritĂ€t (öffnet/schlieĂt) konfigurierbar â jeder Eingang kann anders verdrahtet sein, das ist unabhĂ€ngig von den anderen,
- mit eigenem Nachrichtentext versehen, damit die Push-Nachricht (bzw. bei MQTT: der Home-Assistant-Entity-Name) erkennen lÀsst, welcher Kontakt ausgelöst hat.
Der Meldekanal (Telegram/Pushover/ntfy/MQTT) und die Cooldown-Dauer gelten gerĂ€teweit fĂŒr alle EingĂ€nge gemeinsam. Löst mehr als ein Eingang gleichzeitig aus, wird fĂŒr jeden aktiven Eingang eine eigene Nachricht ĂŒber dieselbe WLAN-Verbindung verschickt. Wird kein einziger Eingang aktiviert, bleibt Eingang 1 als Sicherheitsnetz automatisch aktiv â sonst hĂ€tte das GerĂ€t keine Aufwach-Quelle mehr und wĂŒrde nie wieder von selbst aus dem Deep Sleep zurĂŒckkehren.
Genau ein Kanal ist pro GerÀt aktiv, umschaltbar im WebUI:
- Telegram â Bot ĂŒber @BotFather anlegen, Token kopieren; eigene Chat-ID z. B. ĂŒber @userinfobot ermitteln.
- Pushover â App-Token und User-Key aus dem eigenen Pushover-Konto.
- ntfy.sh â kein Konto nötig, einfach einen (möglichst schwer zu erratenden) Topic-Namen wĂ€hlen; Server-URL ist im WebUI ĂŒberschreibbar fĂŒr selbstgehostete ntfy-Instanzen.
- MQTT â Anbindung an beliebige Smart-Home-Systeme, inkl. automatischer Home-Assistant- Discovery. Siehe MQTT / Home Assistant.
Optionaler periodischer Wake unabhĂ€ngig von echten Auslösungen (WebUI-Feld âHeartbeat-Intervall (Minuten)", 0 = deaktiviert, Default 60 min) â lĂ€uft als zusĂ€tzliche Deep-Sleep-Wakeup-Quelle parallel zum EXT1-Trigger, ohne dass der Chip dafĂŒr dauerhaft wach bleibt oder pollt.
- Bei MQTT-Kanal: hĂ€lt Home-Assistant-Discovery- und State-Topics aktuell, falls der Broker zwischenzeitlich Retained Messages verloren hat (z. B. Neustart ohne Persistence) â sonst mĂŒsste man dafĂŒr auf den nĂ€chsten echten Power-On/Reset warten. Details siehe MQTT / Home Assistant weiter unten.
- Bei Push-KanĂ€len (Telegram/Pushover/ntfy): per Checkbox âTĂ€gliches Lebenszeichen per Push" zuschaltbar, sendet dann unabhĂ€ngig vom (ggf. kĂŒrzeren) technischen Heartbeat-Intervall höchstens 1x/Tag eine âESP-Kerberos ist online"-Nachricht (inkl. Akkustand, falls BatterieĂŒberwachung aktiv) â bewusst selten, um bei einer Briefkasten-App nicht zu nerven. Push-KanĂ€le kennen anders als Home Assistant kein ânicht verfĂŒgbar", das ist hier der einzige Weg, ĂŒberhaupt mitzubekommen, dass das GerĂ€t noch antwortet.
- Stromkosten: ein zusĂ€tzlicher Wake-Zyklus kostet laut Hardware â5,1 ”Ah. Beim Default von 60 Minuten macht das rechnerisch â122 ”Ah/Tag zusĂ€tzlich â bei einem 3000-mAh-Akku vernachlĂ€ssigbar (die Selbstentladung der Zelle dominiert ohnehin, siehe Hardware-Abschnitt).
Anders als die drei Push-KanĂ€le (die pro Auslösung eine einmalige Nachricht schicken) bildet der MQTT-Kanal den aktuellen Zustand jedes Eingangs ab â genau wie ein handelsĂŒblicher TĂŒr-/Fenstersensor:
- Pro Eingang wird ein retained
ON/OFF-Status auf<Basis-Topic>/input<N>/stateveröffentlicht (N= 0â3). Ăffnet ein Kontakt âON, schlieĂt er wieder âOFF. Das Basis-Topic ist im WebUI frei wĂ€hlbar, leer gelassen wird automatischkerberos/<GerĂ€te-ID>verwendet (<GerĂ€te-ID>= letzte zwei MAC-Adress-Bytes). - Bei jeder Auslösung wird kurz vor dem
ONimmer zuerst einOFFgepusht. Das erzwingt einen echten Zustandswechsel in Home Assistant, selbst wenn der dort zuletzt bekannte (retained) Zustand schonONwar â z. B. weil ein frĂŒheresOFFwegen eines WLAN-/Broker-Ausfalls nie ankam. Ohne diesen Puls wĂŒrde ein erneutesONmit identischem Payload keinenstate_changed-Event auslösen, wodurch Automationen mittrigger: state, to: "on"die Auslösung verpassen wĂŒrden. - Home-Assistant-Autodiscovery (per Checkbox im WebUI an-/abschaltbar) legt fĂŒr jeden
aktivierten Eingang automatisch einen
binary_sensor(device_classdoor) an, gruppiert unter einem gemeinsamen GerĂ€t âESP-Kerberos <GerĂ€te-ID>â â keine manuelle Konfiguration in Home Assistant nötig. Deaktivierte EingĂ€nge bzw. abgeschaltete Discovery entfernen die zugehörige Entity automatisch wieder aus Home Assistant. - Kein Dauerbetrieb, reiner Publish-Kanal: Das GerĂ€t verbindet sich nur kurz zum Broker, wenn
es ohnehin wach ist (Auslösung, RĂŒckkehr in Ruhezustand, einmalig nach jedem Power-On/Reset fĂŒr
die Discovery-Configs, oder beim optionalen Heartbeat) â passend zum Kernprinzip
minimaler Wachzeit. Es gibt bewusst kein eingehendes Command-Topic/Subscribe (kein "2-Weg"
im engeren Sinn) und keine klassische MQTT-Availability/Last-Will-Verfolgung, da ein GerÀt,
das die meiste Zeit im Deep Sleep verbringt, damit fĂ€lschlich dauerhaft als "nicht verfĂŒgbar"
erschiene. Als optionale Alternative dazu: Ist der Heartbeat aktiv, tragen alle Discovery-Configs
ein
expire_after(2x Heartbeat-Intervall) â Home Assistant markiert die Entities dann von sich aus als "nicht verfĂŒgbar", wenn tatsĂ€chlich zu lange nichts mehr ankam. - Heartbeat-Sensor als "letzter Kontakt": Eine zusĂ€tzliche
sensor-Entity zĂ€hlt Wake-Zyklen (Trigger und Heartbeat) auf<Basis-Topic>/heartbeat/state. Der ESP32 kennt dabei keine Uhrzeit (keine NTP-Synchronisation) â Home Assistant trackt fĂŒr jede Entity ohnehin automatisch einenlast_updated-Zeitstempel, der genau diese Rolle ĂŒbernimmt, direkt in der HA-UI bzw. per Template nutzbar. - Publishes werden bewusst entzerrt, nicht als Burst gefeuert: Nach jedem einzelnen
publish()folgt eine kurze Pause (mqttClient.loop()+ ~20 ms), zusĂ€tzlich ~200 ms Einschwingzeit direkt nach dem WLAN-Connect, bevor ĂŒberhaupt losgesendet wird. Ohne das gingen bei einem Direktstart aus dem Deep Sleep (kein vorher verbundener USB-Host, z. B. reiner Akku-/Netzteilbetrieb) vereinzelt einzelne der bis zu 14 Nachrichten (7 Discovery + 4 State + 2 Batterie + 1 Heartbeat) auf Funkebene verloren â via MQTT QoS 0 (PubSubClient-Standard) gibt es dafĂŒr weder BestĂ€tigung noch Retry, sodass die Firmware den Verlust nie bemerkte (Log zeigte durchgehend "erfolgreich", am Broker kam aber nichts an). Betraf reproduzierbar den ersten Verbindungsversuch nach einem Kaltstart ohne angeschlossenen USB-Host; ein zweiter Versuch kurz danach funktionierte meist schon. Statische IP statt DHCP behob es NICHT (schlieĂt DHCP-/ARP-Timing als Ursache aus) â die Entzerrung schon (3/3 TestlĂ€ufe auf Akku bzw. Fremdnetzteil erfolgreich, 2026-07-19). - Verbindung erfolgt unverschlĂŒsselt (TCP, Standardport 1883) â gedacht fĂŒr einen Broker im eigenen lokalen Netz (z. B. das Mosquitto-Add-on von Home Assistant). Nutzername/Passwort sind optional.
Optionale Akku-Spannungsmessung, per Default deaktiviert, im WebUI unter "Batterie" aktivierbar:
- Messzeitpunkt: bei einer echten Trigger-Auslösung (EXT1-Wakeup), nicht bei jedem Cooldown-/Poll-Wake. Es gibt bewusst keine eigene periodische Wakeup-Quelle nur fĂŒr die Akkumessung â der optionale Heartbeat ist ein allgemeiner, fĂŒr andere Zwecke gedachter Mechanismus, den die Batteriemeldung lediglich mitnutzt, sobald ohnehin gerade gewacht/verbunden wird: bei MQTT-Kanal bei jedem Heartbeat-Wake, bei Push-KanĂ€len nur innerhalb des tĂ€glichen Lebenszeichens (falls beides aktiviert ist). In der Praxis bedeutet das: der Akkustand wird bei jeder Auslösung mitgemeldet, ganz ohne zusĂ€tzliche WLAN-Verbindung, die nicht ohnehin schon aufgebaut wĂŒrde.
- Messung: ADC-Spannungsteiler, Default-Werte (Pin GPIO0, Faktor Ă2) passen zum eingebauten Teiler des Referenzboards (FireBeetle 2 ESP32-C6, siehe DFRobot-Wiki) und sind bei abweichender Hardware im WebUI anpassbar. Die Umrechnung in Prozent erfolgt ĂŒber eine lineare NĂ€herung (3,3 V = 0 %, 4,2 V = 100 %) â kein Fuel-Gauge-IC, keine Kalibrierung gegen Zellalterung, ausreichend fĂŒr eine grobe Warnschwelle, nicht fĂŒr eine prĂ€zise Restlaufzeitanzeige.
- Meldung je nach Meldekanal (siehe MeldekanÀle):
- MQTT: kontinuierlicher Zustand als zwei retained Sensor-Entities (
.../battery/statein Prozent,.../battery_voltage/statein Volt), inkl. Home-Assistant-Autodiscovery (device_classbattery/voltage) nach demselben Muster wie die EingĂ€nge. - Push-KanĂ€le (Telegram/Pushover/ntfy): einmalige Warnmeldung beim Unterschreiten der im WebUI konfigurierten Warnschwelle (Default 15 %) â kein Dauer-Spam bei jeder weiteren Auslösung. Die Warnung wird erst wieder gelöscht (und kann erneut auslösen), sobald der Ladezustand die Schwelle um mehr als 10 Prozentpunkte ĂŒbersteigt (Hysterese gegen Flattern knapp um die Schwelle).
- MQTT: kontinuierlicher Zustand als zwei retained Sensor-Entities (
-
Microcontroller: DFRobot FireBeetle 2 ESP32-C6 (DFR1075) â ESP32-C6-Modul (RISC-V, WLAN 6 + BLE 5.0), Referenz-/Empfehlungsboard fĂŒr dieses Projekt. Der Code selbst bleibt board-agnostisch, solange GPIO0â7 (Trigger) zugĂ€nglich sind; auf dem FireBeetle 2 ist GPIO0 allerdings fest fĂŒr die eingebaute Akku-Spannungsmessung reserviert (siehe BatterieĂŒberwachung) und steht daher nicht als Trigger-Pin zur VerfĂŒgung. Die BOOT-Taste (GPIO9) wird von der Firmware fĂŒr die Rekonfiguration genutzt (5-Sekunden-Fenster nach Power-On/Reset) â zusĂ€tzlich zu ihrer ĂŒblichen Rolle beim Flashen ĂŒber esptool.
-
Stromversorgung: Getesteter/empfohlener Akku: Meshnology-Akku (gleiche Baureihe, hier in der 3000-mAh-Variante statt der ursprĂŒnglich dokumentierten 5000-mAh-Zelle), 3,7 V nominal, PH-2.0-Steckverbinder (passend zum Akku-Anschluss des FireBeetle 2, mechanisch gesteckt statt gedrahtet), mit eingebauter Schutzplatine gegen Tiefentladung/Kurzschluss. Max. Ladestrom laut Datenblatt der 3000-mAh-Variante vor Inbetriebnahme gegenprĂŒfen â bei der 5000-mAh-Variante lag er bei 2,5 A und damit weit ĂŒber den â540 mA, mit denen der eingebaute Lade-IC des Boards (CN3165, USB-C) tatsĂ€chlich lĂ€dt (unkritisch, nur entsprechend lange Ladezeit); kleinere Zellen können einen geringeren zulĂ€ssigen Ladestrom haben. Ăberlade-/ Ăberentladeschwellen (4,2 V / 3,0 V) und Ladetemperaturbereich (0â45 °C) decken sich mit den Werten, auf denen die BatterieĂŒberwachung dieses Projekts aufbaut, siehe BatterieĂŒberwachung. Bewusst kein 18650: runde Zellen sind ohne eigene Schutzplatine ĂŒblich und mĂŒssten separat abgesichert werden.
â ïž Sicherheitshinweise:- Akku nicht im eingebauten/verschlossenen Zustand laden. Stattdessen den Akku aus der Paketbox entnehmen und ĂŒber sein eigenes, mitgeliefertes USB-Ladekabel auĂerhalb laden (der Lade-IC des Boards bleibt dabei ungenutzt) â sowohl wegen des Thermal-Runaway-Risikos einer Lithium-Zelle in einem geschlossenen GehĂ€use als auch weil ein USB-Kabel durch eine Paketbox ohnehin unpraktikabel ist.
- Laden bei KĂ€lte ist nicht vorgesehen und wird von der Firmware nicht abgesichert (kein Temperatur-Gate) â nur bei Zimmertemperatur laden (0â45 °C laut Akku-Datenblatt). Siehe auch Bekannte offene Punkte.
-
Gemessener Ruhestrom & Akkulaufzeit (2026-07-16, PPK2-Messung): Deep-Sleep-Durchschnitt 37,88 ”A, stabil ĂŒber mehrere Minuten gemessen (kurze periodische Spikes bis ~490 ”A alle ~23 ms sind normales Regler-/RTC-Refresh-Verhalten des Power-Managements, kein Firmware-Effekt â im Deep Sleep lĂ€uft kein Anwendungscode). Ein einzelner Meldezyklus (EXT1-Wake â WLAN verbinden â Nachricht senden â zurĂŒck in Sleep) kostet zusĂ€tzlich â 5,1 ”Ah. Diese Messung stammt von vor der MQTT-Publish-Entzerrung (s. u.) â bei aktivem MQTT-Kanal kommen dadurch nochmal grob 0,3â0,7 s zusĂ€tzliche Wachzeit pro Zyklus dazu, bislang nicht neu gemessen. Beispielrechnung mit dem oben empfohlenen 3,7 V/3000-mAh-Akku:
- Ruhestrom: 37,88 ”A Ă 24 h â 0,91 mAh/Tag
- Selbst bei 20 Auslösungen/Tag: zusĂ€tzlich nur â 0,10 mAh/Tag
- Gesamt â 1,01 mAh/Tag â 3000 mAh Ă· 1,01 mAh/Tag â ~8 Jahre rechnerische Standby-Zeit
In der Praxis begrenzt nicht der Stromverbrauch der Elektronik die Akkulaufzeit, sondern die Selbstentladung der Li-Ion-Zelle (typ. 2â5 %/Monat).
-
GehĂ€use: Elektronik möglichst auĂerhalb metallischer GehĂ€use (Faraday-KĂ€fig-Effekt) montieren, nur die dĂŒnne Schalter-Verkabelung nach innen fĂŒhren.
- Bauen und flashen (Konfiguration erfolgt anschlieĂend ĂŒber das WebUI):
Alternativ ohne Kommandozeile: siehe Web-Flasher oben.
pio run --target upload - GerÀt startet, öffnet mangels Konfiguration automatisch das Setup-WLAN
ESP-Kerberos-Setup-XXXXâ siehe Konfiguration ĂŒber WebUI. - Formular ausfĂŒllen und speichern. GerĂ€t startet neu und lĂ€uft im Normalbetrieb.
ESP-Kerberos/
âââ platformio.ini
âââ merge_bin.py # Post-Build-Hook: erzeugt docs/ESP-Kerberos-merged.bin
âââ README.md
âââ LICENSE
âââ docs/ # GitHub-Pages-Root: Web-Flasher
â âââ index.html # ESP Web Tools UI
â âââ manifest.json # Firmware-Manifest fĂŒr den Flasher
â âââ ESP-Kerberos-merged.bin # von merge_bin.py generiert â USB-Erstflash, nicht fĂŒr OTA
â âââ ESP-Kerberos-ota.bin # von merge_bin.py generiert â Upload im Setup-Portal (/update)
âââ src/
âââ main.cpp # Boot-Orchestrierung, Sleep/Wake, Entprellung
âââ kerberos_config.h # Config-Struct + Enums (header-only)
âââ config_store.h/.cpp # NVS laden/speichern (Preferences)
âââ portal.h/.cpp # AP + Captive Portal + Webformular + OTA-Firmware-Upload
âââ notify.h/.cpp # Telegram/Pushover/ntfy-Versand
âââ mqtt.h/.cpp # MQTT-Zustands-Publish + Home-Assistant-Discovery
âââ battery.h/.cpp # Akku-ADC-Messung + Prozent-NĂ€herung
âââ debug_log.h # Serial-Debug-Logging, per Build-Flag abschaltbar
StandardmĂ€Ăig aktiv (KERBEROS_DEBUG=1), 115200 Baud (pio device monitor). Loggt
Boot-/Wake-Ursache, WLAN-Verbindungsstatus, Portal-/Scan-Ereignisse und HTTP-Antwortcodes der
MeldekanĂ€le â bewusst ohne Passwörter/Tokens im Log. FĂŒr den spĂ€teren Batteriebetrieb
abschaltbar (spart die minimale Restlaufzeit, die Serial.begin()/Prints kosten):
build_flags = -DKERBEROS_DEBUG=0- Ruhestrom durch interne Pull-ups bei geschlossenem Ruhekontakt: Der interne Pull-up fĂŒr
den EXT1-Wakeup hÀlt zusÀtzlich die RTC_PERIPH-DomÀne wÀhrend des Deep Sleep aktiv, was den
Ruhestrom leicht erhöht. Relevanter ist der Fall
triggerOnOpen = true(Default aller 4 EingĂ€nge): Der Ruhezustand ist dabei "Kontakt geschlossen", der interne Pull-up (laut ESP32-C6-Datenblatt nĂ€herungsweise 45 kΩ) liegt dann dauerhaft ĂŒber den geschlossenen Schalter an GND â rechnerisch rund 70 ”A pro so beschaltetem Eingang (3,3 V Ă· 45 kΩ), bei allen 4 EingĂ€ngen im ungĂŒnstigsten Fall in Summe rund 280 ”A zusĂ€tzlich, auch im Deep Sleep. Das ist eine SchĂ€tzung nach Datenblattwert, keine gemessene Zahl â eine PPK2-Verifikation der tatsĂ€chlichen internen Pull-up-StromstĂ€rke des C6 im Deep Sleep steht noch aus. Zwei Möglichkeiten zur EntschĂ€rfung, falls relevant:- Kontakte/Schalter so montieren bzw. wĂ€hlen, dass der Ruhezustand "offen" ist
(
triggerOnOpen = false) â dann flieĂt im Ruhezustand kein Pull-up-Strom ĂŒber den Schalter, nur kurzzeitig wĂ€hrend der Auslösung selbst. - Statt des internen Pull-ups einen externen ~1-MΩ-Pull-up je Eingang verwenden (reduziert
den Ruhestrom um etwa den Faktor 20 gegenĂŒber den internen ~45 kΩ) â dafĂŒr aktuell keine
Firmware-UnterstĂŒtzung, da die interne
rtc_gpio_pullup_en()-Konfiguration fest verdrahtet ist.
- Kontakte/Schalter so montieren bzw. wÀhlen, dass der Ruhezustand "offen" ist
(
- Akku-Sicherheit bei AuĂenmontage (z. B. Briefkasten): Li-Ion-Zellen dĂŒrfen laut den meisten Zellenherstellern nicht unter 0 °C geladen werden (Lithium-Plating-Risiko). Ob der TEMP-Pin des CN3165 an einen NTC im Akkupack angeschlossen ist oder nur fest verdrahtet (d. h. die TemperaturĂŒberwachung faktisch deaktiviert), lĂ€sst sich aus dem Schaltplan allein nicht zuverlĂ€ssig klĂ€ren und muss an der realen Hardware nachgemessen bzw. im DFRobot-Wiki verifiziert werden. Bis dahin gilt uneingeschrĂ€nkt: Akku nur kontrolliert bei Zimmertemperatur laden (siehe Hardware), nicht bei Wintermontage im Freien.
- Software-Reset fĂŒr vergessenes AP-Passwort (erwogen, zurĂŒckgestellt): Aktuell nur per
USB/Web-Flasher behebbar (AP-Passwort vergessen),
was einen Computer/Browser voraussetzt. Eine BOOT-Taste-Geste (z. B. ~10s halten â
Preferences::clear()+ Neustart) wĂ€re bequemer fĂŒr ein bereits fest montiertes GerĂ€t, wurde aber zurĂŒckgestellt â dupliziert technisch nur den bereits vorhandenen Reflash-Reset und wĂŒrde die BOOT-Taste-Zeitfenster-Logik (main.cpp, aktuell reine Ja/Nein-Erkennung statt Haltedauer-Messung) nicht unerheblich verkomplizieren.
