Vogelalbum 1.0.0
Eine Kamera am Vogelhaus, ein Rechner der erkennt wer da war — und eine Sammlung, die sich von allein fuellt. Zwei neuronale Netze: eines findet den Vogel im Bild, eines bestimmt die Art. 148 heimische Arten, auf Deutschland eingeschraenkt und neu normiert — ohne diese Einschraenkung wird aus einer Kohlmeise eine nordamerikanische Schwesterart. Daraus entsteht ein Sammelalbum: nummerierte Seiten, gefundene Arten in Farbe, fehlende als Schatten, dazu Erstfang, Punkte, Stufen und 15 Abzeichen. Laeuft vollstaendig auf eigener Hardware. Kein Cloud-Dienst, kein Konto, keine Telemetrie; die Bilder verlassen das eigene Netz nicht. Zwei getrennt deploybare Teile: die Sammlung als Django-Anwendung, die Erkennung als eigener Dienst. Der Erkennungs-Dienst fragt selbst an und braucht deshalb weder eine erreichbare Adresse noch einen offenen Port — er laeuft hinter einem gewoehnlichen Router. Dabei: Firmware fuer Raspberry Pi und ESP32-S3, Anbindung an Home Assistant ueber MQTT, Oberflaeche auf Deutsch und Englisch, Einstellungen je Kamera aus dem Browser, und ein Weg fuer Fotos von unterwegs. AGPL-3.0.
This commit is contained in:
commit
c11fe9ab04
189 files changed
+29806
No files matched your search
@@ -0,0 +1,116 @@
|
||||
// WLAN: Zugangsdaten im NVS, Verbindung als Station, Einrichtung als
|
||||
// Zugangspunkt. Wer die Daten hat, verbindet sich; wer keine hat, macht
|
||||
// sein eigenes Netz auf.
|
||||
//
|
||||
// Uebernommen aus Hey Fred (firmware/main/netz.c) am 23.09.2026. Dort ist
|
||||
// es erprobt; hier geaendert wurden der NVS-Bereich und der Name des
|
||||
// Einrichtungsnetzes.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#define NETZ_SSID_MAX 32
|
||||
#define NETZ_PASS_MAX 64
|
||||
|
||||
// Name des Zugangspunkts zur Einrichtung. ⚠ Anders als bei Fred NICHT
|
||||
// fest: Die letzten beiden Bytes der MAC haengen hinten dran, also etwa
|
||||
// "Vogelkamera-A4F2". Zwei Kameras im selben Garten -- Futterhaus und
|
||||
// Traenke -- wuerden sich sonst denselben Namen teilen, und man wuesste
|
||||
// beim Einrichten nicht, welche man gerade vor sich hat.
|
||||
#define NETZ_SETUP_PRAEFIX "Vogelkamera"
|
||||
|
||||
// Der tatsaechliche Name, erst zur Laufzeit bekannt.
|
||||
const char *netz_setup_ssid(void);
|
||||
|
||||
// Das Geheimnis fuer Updates ueber WLAN.
|
||||
//
|
||||
// ⚠ Bewusst NICHT einkompiliert (so macht es Hey Fred in secrets.h). Fuer
|
||||
// ein Geraet, das als Bausatz weitergegeben wird, waere das derselbe
|
||||
// Fehler wie eingebackene WLAN-Daten: Jeder muesste die Firmware selbst
|
||||
// uebersetzen, und alle Geraete haetten dasselbe Geheimnis.
|
||||
//
|
||||
// Stattdessen: Beim ersten Start wuerfelt sich jedes Geraet sein eigenes
|
||||
// und legt es im NVS ab. Zu sehen bekommt man es im Einrichtungsnetz --
|
||||
// wer dort steht, steht ohnehin vor dem Geraet.
|
||||
const char *netz_ota_token(void);
|
||||
|
||||
typedef struct {
|
||||
char ssid[NETZ_SSID_MAX + 1];
|
||||
int8_t rssi;
|
||||
bool verschluesselt;
|
||||
} netz_fund_t;
|
||||
|
||||
// Einmal beim Start aufrufen, vor allem anderen.
|
||||
void netz_init(void);
|
||||
|
||||
// Liegen Zugangsdaten im NVS?
|
||||
bool netz_zugang_vorhanden(void);
|
||||
|
||||
// Der gespeicherte Netzname, oder "" wenn keiner da ist. Fuer die Anzeige
|
||||
// auf der Einrichtungsseite: Erst damit sieht man, ob das Speichern
|
||||
// ueberhaupt ankommt -- ohne Kabel, ohne Raten.
|
||||
const char *netz_gespeicherte_ssid(void);
|
||||
|
||||
// Gibt false zurueck, wenn das Schreiben scheitert -- der Grund steht dann
|
||||
// in *fehler. ⚠ Frueher brach das Geraet bei einem Fehler einfach ab
|
||||
// (ESP_ERROR_CHECK): Es startete mitten im Absenden neu, der Browser blieb
|
||||
// haengen, nichts war gespeichert, und niemand erfuhr warum.
|
||||
bool netz_zugang_speichern(const char *ssid, const char *passwort,
|
||||
esp_err_t *fehler);
|
||||
void netz_zugang_loeschen(void);
|
||||
|
||||
// Verbindet mit den gespeicherten Daten. Blockiert bis zum Erfolg oder bis
|
||||
// die Versuche aufgebraucht sind. Gibt false zurück, wenn es nicht klappt —
|
||||
// dann gehört Fred in den Einrichtungsmodus.
|
||||
bool netz_verbinden(void);
|
||||
|
||||
// Öffnet den Zugangspunkt für die Einrichtung. Danach ist Fred unter
|
||||
// 192.168.4.1 erreichbar.
|
||||
void netz_setup_ap_start(void);
|
||||
|
||||
// Sucht Netze in der Umgebung. Schreibt bis `max` Funde nach `ziel` und gibt
|
||||
// die Anzahl zurück. Doppelte SSIDs werden übersprungen, der stärkste
|
||||
// Fund gewinnt.
|
||||
int netz_suchen(netz_fund_t *ziel, int max);
|
||||
|
||||
// Sucht EINMAL und merkt sich das Ergebnis.
|
||||
//
|
||||
// ⚠ Der Grund ist unangenehm und kostet sonst Stunden: Eine WLAN-Suche
|
||||
// wechselt den Funkkanal. Laeuft gleichzeitig der eigene Zugangspunkt,
|
||||
// fliegen die verbundenen Geraete dabei raus. Sucht man also, waehrend
|
||||
// jemand das Formular betrachtet, verliert genau dieser Jemand die
|
||||
// Verbindung -- und sein Absenden kommt nie an. Am 23.09.2026 genau so
|
||||
// passiert, an Handy wie an Mac.
|
||||
//
|
||||
// Deshalb: einmal suchen, bevor der erste Besucher da ist, und danach
|
||||
// nur noch die Liste ausliefern.
|
||||
int netz_funde_holen(netz_fund_t *ziel, int max);
|
||||
void netz_funde_auffrischen(void);
|
||||
|
||||
// IP als Zeichenkette, leer wenn nicht verbunden.
|
||||
const char *netz_ip(void);
|
||||
|
||||
// Wie oft die Verbindung seit dem Start abgerissen ist, und warum zuletzt.
|
||||
// Der Grund ist der Code des WLAN-Treibers: 15 und 204 stehen für ein
|
||||
// falsches Passwort, 201 für „Netz nicht gefunden", 2 bis 4 zeigen auf
|
||||
// Verschlüsselung und Management-Frames.
|
||||
int netz_trennungen(void);
|
||||
int netz_letzter_grund(void);
|
||||
|
||||
// Läuft die Verbindung gerade?
|
||||
bool netz_verbunden(void);
|
||||
|
||||
// Holt die Uhrzeit per SNTP und stellt sie auf deutsche Zeit. Blockiert
|
||||
// nicht — das Ergebnis trudelt im Hintergrund ein.
|
||||
void zeit_holen(void);
|
||||
|
||||
// Steht die Uhr schon auf einer plausiblen Zeit?
|
||||
bool zeit_steht(void);
|
||||
|
||||
// Empfangsstaerke zum Zugangspunkt in dBm (negativ; naeher an null ist
|
||||
// besser). 0 heisst: nicht ermittelbar.
|
||||
int netz_feldstaerke(void);
|
||||
Reference in new issue
Block a user