got mqtt and wifi connection working reliably
This commit is contained in:
93
PROJEKT.md
93
PROJEKT.md
@@ -60,11 +60,15 @@ sensor-pico/ ← Git Repo Root
|
||||
│ ├── bme280/ ← Git Submodule (lafftale1999/bme280_driver)
|
||||
│ └── dhcp_server/ ← DHCP Server (von pico-examples, kein Submodule)
|
||||
├── src/
|
||||
│ ├── main.cpp ← Hauptprogramm
|
||||
│ ├── webserver.c ← lwIP httpd Initialisierung + CGI-Handler
|
||||
│ ├── main.cpp ← Hauptprogramm (WiFi + MQTT Verbindungslogik)
|
||||
│ ├── webserver.c ← lwIP POST-Handler + Formular-Parsing
|
||||
│ ├── webserver.h ← Exports: saved_ssid, saved_mqtt_* etc.
|
||||
│ └── fsdata.c ← Generiert von makefsdata, nicht im Git!
|
||||
├── fs/
|
||||
│ └── index.html ← Weboberfläche, wird beim Build eingebaut
|
||||
│ ├── index.html ← Navigations-Hub (Links zu den Unterseiten)
|
||||
│ ├── wlan_config.html ← WLAN SSID + Passwort Formular (POST /config)
|
||||
│ ├── mqtt_config.html ← MQTT + Frequenz Formular (POST /mqtt-config)
|
||||
│ └── live_stats.html ← (geplant) Live-Sensordaten
|
||||
├── build/ ← Von cmake generiert, nicht im Git
|
||||
├── CMakeLists.txt
|
||||
├── lwipopts.h ← lwIP Konfiguration
|
||||
@@ -125,7 +129,7 @@ pico_sdk_init()
|
||||
add_subdirectory(lib/bme280 bme280_build)
|
||||
add_subdirectory(lib/dhcp_server dhcp_server_build)
|
||||
|
||||
# makefsdata: fs/index.html → src/fsdata.c
|
||||
# makefsdata: fs/ → src/fsdata.c (wird von fs.c via #include eingebunden)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/src/fsdata.c
|
||||
COMMAND perl ${PICO_SDK_PATH}/lib/lwip/src/apps/http/makefsdata/makefsdata
|
||||
@@ -133,12 +137,15 @@ add_custom_command(
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/prepend_include.cmake
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/fs/index.html
|
||||
${CMAKE_SOURCE_DIR}/fs/wlan_config.html
|
||||
${CMAKE_SOURCE_DIR}/fs/mqtt_config.html
|
||||
)
|
||||
|
||||
# fsdata.c wird NICHT in add_executable gelistet – fs.c inkludiert sie via
|
||||
# #include HTTPD_FSDATA_FILE (definiert in lwipopts.h als "src/fsdata.c")
|
||||
add_executable(sensor-pico
|
||||
src/main.cpp
|
||||
src/webserver.c
|
||||
src/fsdata.c
|
||||
)
|
||||
|
||||
pico_enable_stdio_usb(sensor-pico 1)
|
||||
@@ -153,6 +160,7 @@ target_link_libraries(sensor-pico
|
||||
pico_cyw43_arch_lwip_threadsafe_background
|
||||
pico_lwip
|
||||
pico_lwip_http
|
||||
pico_lwip_mqtt
|
||||
bme280
|
||||
dhcp_server
|
||||
)
|
||||
@@ -260,16 +268,36 @@ Der Pico hat zwei Betriebsmodi:
|
||||
- ✅ Access Point (`SensorAP`, WPA2) öffnet sich
|
||||
- ✅ DHCP-Server läuft – Clients bekommen IP
|
||||
- ✅ Pico erreichbar unter `192.168.4.1`
|
||||
- ✅ lwIP httpd läuft – Index-Seite wird ausgeliefert
|
||||
- ✅ lwIP httpd läuft – Seiten werden ausgeliefert
|
||||
- ✅ `makefsdata` automatisch im Build-Prozess eingebunden
|
||||
- ✅ `fs/index.html` wird beim Build als Byte-Array in Firmware eingebaut
|
||||
- ✅ Alle HTML-Seiten aus `fs/` werden als Byte-Array in Firmware eingebaut
|
||||
- ✅ WLAN-Konfiguration über Captive Portal (POST Handler)
|
||||
- ✅ Pico verbindet sich mit bestehendem WLAN (Station Mode)
|
||||
- ✅ MQTT-Konfiguration über Webformular (Adresse, Port, User, Passwort, Frequenzen)
|
||||
- ✅ MQTT-Verbindung zum Broker steht
|
||||
- ✅ BME280 Sensor liest Messwerte aus und gibt JSON per printf aus
|
||||
- ⬜ Sensordaten per MQTT publishen
|
||||
- ⬜ Live-Daten Seite (`live_stats.html`)
|
||||
|
||||
### Programm-Ablauf (main.cpp)
|
||||
```
|
||||
1. cyw43_arch_init() + httpd_init()
|
||||
2. WiFi-Schleife:
|
||||
└─ ap_init() → warte auf SSID+Passwort → verbinde mit WLAN
|
||||
└─ bei Erfolg: weiter; bei Fehler: neu versuchen
|
||||
3. MQTT-Config-Schleife:
|
||||
└─ warte bis saved_mqtt_address gesetzt ist (Formular abgeschickt)
|
||||
└─ connect_to_mqtt() → bei Fehler: Config zurücksetzen + neu warten
|
||||
4. Sensor-Loop (TODO):
|
||||
└─ BME280 auslesen → per MQTT publishen
|
||||
```
|
||||
|
||||
### Geplante Anforderungen
|
||||
1. Beim Erststart: Access Point für Erstkonfiguration
|
||||
2. Weboberfläche zum Einstellen von:
|
||||
- WLAN SSID + Passwort
|
||||
- MQTT Broker (Adresse, Port, User, Passwort)
|
||||
- Sendefrequenz
|
||||
1. ✅ Beim Erststart: Access Point für Erstkonfiguration
|
||||
2. ✅ Weboberfläche zum Einstellen von:
|
||||
- ✅ WLAN SSID + Passwort
|
||||
- ✅ MQTT Broker (Adresse, Port, User, Passwort)
|
||||
- ✅ Messfrequenz + Pushfrequenz
|
||||
3. Im Produktionsbetrieb: Live-Daten + Einstellungen änderbar
|
||||
|
||||
### makefsdata – wie es funktioniert
|
||||
@@ -286,6 +314,9 @@ Es liest alle Dateien aus dem `fs/`-Ordner und erzeugt daraus eine `fsdata.c` mi
|
||||
|
||||
### lwipopts.h
|
||||
```c
|
||||
// fsdata.c wird von lwIP's fs.c via #include eingebunden – Pfad relativ zum Include-Root
|
||||
#define HTTPD_FSDATA_FILE "src/fsdata.c"
|
||||
|
||||
#define NO_SYS 1
|
||||
#define LWIP_SOCKET 0
|
||||
#define LWIP_NETCONN 0
|
||||
@@ -310,18 +341,22 @@ Es liest alle Dateien aus dem `fs/`-Ordner und erzeugt daraus eine `fsdata.c` mi
|
||||
#define LWIP_HTTPD 1
|
||||
#define LWIP_HTTPD_CGI 1
|
||||
#define LWIP_HTTPD_SSI 1
|
||||
#define LWIP_HTTPD_SUPPORT_POST 1 // POST-Body Callbacks aktivieren
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Nächste Schritte
|
||||
|
||||
- [x] `makefsdata` automatisch in cmake einbinden damit `fs/index.html` beim Build in die Firmware eingebaut wird
|
||||
- [ ] Konfigurationsformular in `index.html` (WLAN + MQTT + Sendefrequenz)
|
||||
- [ ] CGI-Handler in `webserver.c` für POST-Request vom Formular
|
||||
- [ ] Einstellungen im Flash speichern
|
||||
- [ ] WLAN Station Mode (Verbindung mit bestehendem Netz)
|
||||
- [ ] MQTT einbinden
|
||||
- [x] `makefsdata` automatisch in cmake einbinden
|
||||
- [x] WLAN Konfigurationsformular + POST-Handler
|
||||
- [x] WLAN Station Mode
|
||||
- [x] MQTT Konfigurationsformular + POST-Handler
|
||||
- [x] MQTT Verbindung zum Broker
|
||||
- [x] BME280 Sensor auslesen
|
||||
- [ ] BME280 Sensordaten per MQTT publishen
|
||||
- [ ] Live-Daten Seite (`live_stats.html`)
|
||||
- [ ] Einstellungen im Flash speichern (Neustart ohne Neukonfiguration)
|
||||
|
||||
---
|
||||
|
||||
@@ -352,6 +387,22 @@ Es liest alle Dateien aus dem `fs/`-Ordner und erzeugt daraus eine `fsdata.c` mi
|
||||
- **${CMAKE_COMMAND} -E** – plattformunabhängige CMake-Dateibefehle (rename, copy, remove) ohne Shell-Abhängigkeit
|
||||
- **${CMAKE_COMMAND} -P** – führt ein CMake-Script direkt aus, ohne Shell-Umweg und ohne Quoting-Probleme
|
||||
- **GET vs POST** – GET-Parameter landen in der URL (sichtbar, in Logs), POST-Daten im Body – für Passwörter immer POST
|
||||
- **Buffer** – Array als temporärer Zwischenspeicher; in C immer manuell null-terminieren (`buf[len] = '\0'`)
|
||||
- **pbuf** – lwIPs internes Paket-Buffer-Format; Inhalt mit `pbuf_copy_partial()` extrahieren, danach `pbuf_free()` aufrufen
|
||||
- **strstr** – sucht Substring in String, gibt Zeiger auf Fundstelle zurück oder NULL
|
||||
- **strchr** – sucht einzelnes Zeichen in String, gibt Zeiger darauf zurück
|
||||
- **Zeigerarithmetik** – zwei Zeiger auf denselben String subtrahieren gibt die Länge zwischen ihnen
|
||||
- **strlen** – Länge eines C-Strings ohne Null-Terminator
|
||||
- **atoi** – wandelt C-String (`"30"`) in Integer (`30`) um; aus `<stdlib.h>`
|
||||
- **memset** – setzt alle Bytes eines Arrays auf einen Wert; `memset(arr, 0, sizeof(arr))` zum Nullen
|
||||
- **static (lokale Variable)** – lebt für die gesamte Programmlaufzeit, wird nicht bei jedem Aufruf neu initialisiert
|
||||
- **Asynchrone Callbacks** – Funktion wird nicht direkt aufgerufen sondern von lwIP registriert und später automatisch aufgerufen (z.B. bei MQTT-Verbindung)
|
||||
- **void *arg** – generischer Kontext-Zeiger in C-Callbacks; übergib `&deine_variable`, caste in Callback zurück mit `static_cast<typ*>(arg)`
|
||||
- **static_cast<>** – C++ Cast-Operator; typsicherer als C-Style-Cast `(typ)`
|
||||
- **Ternary Operator** – `bedingung ? wert_true : wert_false`; Kurzform für einfache if/else-Zuweisungen
|
||||
- **mqtt_client_t** – lwIP MQTT Client-Objekt; erstellt mit `mqtt_client_new()`
|
||||
- **mqtt_connect_client_info_t** – Struct mit Client-ID, Username, Passwort für MQTT-Verbindung
|
||||
- **MQTT Verbindungsflow** – `mqtt_client_connect()` kehrt sofort zurück; Ergebnis kommt asynchron im Callback
|
||||
|
||||
### CMake-Konzepte
|
||||
|
||||
@@ -375,3 +426,9 @@ Es liest alle Dateien aus dem `fs/`-Ordner und erzeugt daraus eine `fsdata.c` mi
|
||||
- `makefsdata` generiert `fsdata.c` ohne `#include "lwip/apps/fs.h"` → Compiler kennt `struct fsdata_file` nicht → `prepend_include.cmake` als Workaround
|
||||
- Shell-Quoting in CMake `COMMAND` ist fehleranfällig bei komplexen Perl-Ausdrücken → CMake-Scripts (`-P`) verwenden statt Shell-Befehle
|
||||
- `add_custom_command OUTPUT` mit relativem Pfad legt die Datei im Build-Verzeichnis ab, nicht im Source-Verzeichnis → immer absoluten Pfad mit `${CMAKE_CURRENT_SOURCE_DIR}` angeben
|
||||
- `pico_lwip_http` ist ein INTERFACE-Target – `target_include_directories` mit `PRIVATE` schlägt fehl; stattdessen `HTTPD_FSDATA_FILE` in `lwipopts.h` überschreiben
|
||||
- lwIP `fs.c` inkludiert `fsdata.c` direkt via `#include HTTPD_FSDATA_FILE` – ohne Override wird die Default-Seite aus dem pico-sdk verwendet statt der eigenen
|
||||
- `strcmp` gibt `0` zurück wenn Strings gleich sind, nicht `true` – `== true` prüft auf Verschiedenheit
|
||||
- lwIP CGI-Handler parst nur GET-Parameter aus der URL, nicht POST-Body → für POST-Formulare `LWIP_HTTPD_SUPPORT_POST` + die drei Callbacks (`httpd_post_begin`, `httpd_post_receive_data`, `httpd_post_finished`) verwenden
|
||||
- `dhcp_server_t` in `ap_init()` muss `static` sein – sonst wird der Stack-Speicher nach Funktionsrückkehr freigegeben, der DHCP-Server läuft aber weiter und greift auf ungültigen Speicher zu
|
||||
- `strncpy` fügt **kein** Null-Byte hinzu wenn exakte Länge übergeben wird → immer `dest[len] = '\0'` danach setzen
|
||||
|
||||
Reference in New Issue
Block a user