Commit Graph
44 Commits
Author SHA1 Message Date
Michael Sauer 6754cdfb66 fix: RSSI mit Vorzeichen melden 2026-09-12 00:32:37 +02:00
Michael Sauer aae7a7462d docs: Checkliste Netzwerk ergänzt
M9: Hardware-Checkliste um Einträge für C1 (verschachteltes JSON, 400,
Lampe läuft weiter), C2 (Onboarding, 60 s warten, Reboot + Router-Neustart
-> AP darf nicht wiederkommen) und einen Hinweis auf den Build ohne
NINLIGHT_WIFI_SSID für Onboarding-Tests ergänzt. `bri 30`-Eintrag nennt
jetzt explizit den REST-Weg (`{"brightness":30}`) neben der Konsole.

README: klargestellt, dass der Onboarding-Aufruf ohne Authorization-Header
nur im unkonfigurierten AP funktioniert - im Fallback-AP (Zugangsdaten
bereits vorhanden) ist der Token-Header wie bei jedem anderen Endpunkt
erforderlich.
2026-09-11 23:52:18 +02:00
Michael Sauer 2e90b8fd06 fix: kleinere Netzwerk-Härtungen
M2: WLAN-Passwort muss leer (offenes Netz) oder 8..64 Zeichen lang sein
(400 "invalid password" bei 1..7 Zeichen). CMake prüft NINLIGHT_WIFI_PASSWORD
ebenso (0 oder 8..63 Zeichen) und der Zeichen-Blacklist-Check bekommt `;`
dazu.

M4: Ein Authorization-Wert, der länger als NL_TOKEN_LEN-1 (64) ist, wird
von nl_http_parse() nicht mehr stillschweigend abgeschnitten, sondern setzt
`auth_too_long` in nl_http_request_t; nl_api_handle() behandelt eine solche
Anfrage als unauthentifiziert (außer bei offenem Zugriff), damit ein
abgeschnittener Wert nie zufällig auf ein kürzeres Token passt.

M5: get_int() prüfte die (long)-Cast-Gleichheit vor dem Bereichscheck -
bei sehr großen oder NaN-Werten ist der Cast von double nach long
undefiniertes Verhalten. Bereichs- und NaN-Check laufen jetzt vor dem Cast.

T1: sdk/Platform/Drivers/internalflash/wm_internal_fls.c: tls_fls_init()
ignorierte den Rückgabewert von tls_os_sem_create(&s_fls2_lock, 1) - jetzt
eine TLS_DBGPRT_ERR-Meldung, falls das fehlschlägt (dokumentiert in
sdk/PATCHES.md).

Tests: test_api.c (Passwortlängen, auth_too_long, 1e300-Brightness),
test_http.c (auth_too_long wird gesetzt). Für M5 zeigt der Host-Test kein
sichtbares RED, weil der (double)->(long)-Cast auf dieser Plattform/diesem
Compiler keinen Crash auslöst (implementation-defined statt UB-Crash) - der
Fix wird trotzdem angewendet, da er auf dem Zielcompiler (arm-none-eabi 4.9)
nicht garantiert sicher ist.
2026-09-11 23:52:03 +02:00
Michael Sauer d098623121 fix: SDK-SoftAP-Parameter löschen
C2: tls_wifi_softap_create() setzt das SOFTAP-Bit (IEEE80211_MODE_AP = 4)
in TLS_PARAM_ID_WPROTOCOL und schreibt es in den Flash; tls_wifi_softap_destroy()
löscht es nie wieder. Solange das Bit gesetzt bleibt, erstellt
sys_net_status_changed() (sdk/Platform/Sys/tls_sys.c:519-525) bei jedem
NETIF_IP_NET_UP über tls_auto_reconnect_softap() erneut den Onboarding-AP
mit den SDK-eigenen (öffentlichen Default-)Parametern - unabhängig vom
Auto-Connect-Flag. Nach jedem Onboarding/Fallback käme der AP
`ninlight-<mac4>` mit dem öffentlichen Default-Passwort bei jedem
Reconnect/Reboot zurück, offen fürs LAN (SDK-NAPT).

Verifiziert in sdk/Platform/Sys/tls_sys.c, sdk/Include/Platform/wm_params.h
und sdk/Platform/Common/Params/wm_param.c:
- TLS_PARAM_ID_WPROTOCOL (10) ist ein u8, TLS_PARAM_IEEE80211_SOFTAP == 4 ==
  IEEE80211_MODE_AP (sdk/Include/WiFi/wm_wifi.h).
- tls_param_get()/tls_param_set(id, argv, to_flash) - genau die Signaturen
  aus dem Finding.
- tls_param_to_default() (tls_param_load_factory_default() + param_to_flash())
  arbeitet ausschließlich auf `struct tls_sys_param` (Wi-Fi/Netzwerk-Konfig);
  es liest/schreibt nirgends die MAC-Adresse oder RF-Kalibrierdaten - die
  liegen in einer komplett getrennten, efuse-gestützten FT_PARAM_ST-Struktur
  in sdk/Platform/Drivers/efuse/wm_efuse.c. tls_param_to_default() ist damit
  für den Werksreset sicher.

Fix (nl_wifi_w600.c):
1. clear_softap_param(): liest TLS_PARAM_ID_WPROTOCOL, löscht bei gesetztem
   IEEE80211_MODE_AP-Bit und persistiert das (to_flash=TRUE). Aufgerufen in
   nl_wifi_start() (vor allem anderen) und nach jedem tls_wifi_softap_destroy().
2. nl_wifi_start(): zerstört einen bereits vom SDK selbst erzeugten SoftAP
   (tls_wifi_softap_get_state() != WM_WIFI_DISCONNECTED), bevor unsere eigene
   State Machine startet.
3. Backstop im Netzwerk-Task: NETIF_WIFI_SOFTAP_SUCCESS, während die State
   Machine sagt, der AP solle unten sein (s_sm.ap_up == false) -> AP wieder
   zerstören und Param erneut löschen (geloggt).
4. Werksreset (nl_app_factory_reset, src/app_main.c): setzt zusätzlich
   tls_param_to_default() (siehe Verifikation oben) und dokumentiert das
   inline.

Nebenbei im selben Treiber erledigt, weil sie denselben Codepfad betreffen:
- M2: connect_station() loggt den Rückgabewert von tls_wifi_connect(), wenn
  er nicht WM_SUCCESS ist.
- M3: start_ap() merkt sich einen fehlgeschlagenen tls_wifi_softap_create()
  (`s_ap_create_pending`) und wiederholt ihn alle 5 s, solange die State
  Machine den AP oben haben will.

Nicht host-testbar (bindet SDK-Header ein); über den Firmware-Build
verifiziert (baut sauber für evk, keine neuen Warnungen).
2026-09-11 23:51:38 +02:00
Michael Sauer 5f45b9e996 fix: Gesamt-Timeout für HTTP-Anfragen
I2: SO_RCVTIMEO=5s war ein Timeout pro recv(), nicht für die gesamte
Anfrage. Ein Client, der 1 Byte alle 4,9 s schickt, konnte den einzigen
HTTP-Server-Task damit stundenlang belegen (Spec §7.2 will 5 s pro Header).

serve() rechnet jetzt eine absolute Deadline (nl_app_now_ms() + 5000 ms)
und setzt SO_RCVTIMEO vor jedem recv() auf die verbleibende Zeit (mindestens
1 ms); ist die Deadline überschritten, wird die Verbindung sofort verworfen.

Nicht host-testbar (nl_http_server.c bindet SDK-Sockets ein); über den
Firmware-Build verifiziert.
2026-09-11 23:51:11 +02:00
Michael Sauer 3250b89986 fix: Onboarding-Test trennt die Verbindung
I1: fail_test() kehrte ohne gespeicherte Zugangsdaten stillschweigend nach
AP_ONBOARDING zurück, ohne den Stationsversuch zu trennen; ein danach doch
noch eintreffendes CONNECTED wurde in AP_ONBOARDING ignoriert, aber der
Treiber rief nl_mdns_on_ip_up() unabhängig vom Zustand auf - die Lampe
landete offen im LAN, ohne dass Zugangsdaten gespeichert wurden.

nl_wifi_actions_t bekommt ein neues Feld `disconnect`:
- fail_test() ohne Zugangsdaten setzt es (Timeout/Fehler beendet den
  Stationsversuch).
- Ein CONNECTED-Event in AP_ONBOARDING gilt als Ausreißer eines bereits
  gescheiterten Versuchs und wird ebenfalls getrennt (Zustand bleibt
  unverändert).
- M1: nl_wifi_sm_onboard() trennt jetzt immer vor dem Testverbindungsaufbau,
  damit veraltete Events eines vorherigen Versuchs nicht mehr zählen; der
  Treiber (nl_wifi_request_onboard) meldet zusätzlich "wifi busy" (503),
  solange bereits ein Onboarding-Test läuft.

Der Treiber (src/net/nl_wifi_w600.c) führt `disconnect` vor `connect` aus
und ruft nl_mdns_on_ip_up() nur noch, wenn der Zustand nach der Verarbeitung
tatsächlich STA_CONNECTED ist.

Tests (test_wifi_sm.c): Timeout/Fehler ohne Zugangsdaten -> disconnect;
CONNECTED während AP_ONBOARDING -> disconnect, Zustand unverändert;
erneutes Onboarding während laufendem Test -> disconnect vor dem neuen
connect.
2026-09-11 23:51:03 +02:00
Michael Sauer 89c764514a fix: cJSON-Verschachtelung begrenzen
C1: Ein POST an /api/v1/device/state mit tief verschachteltem JSON (z.B.
20 Ebenen "[[[[...") lässt cJSONs rekursiven Parser den 6-KB-Stack des
HTTP-Tasks überlaufen - CJSON_NESTING_LIMIT war mit 1000 viel zu hoch und
FreeRTOS' Stack-Overflow-Checking ist aus. Begrenzt auf 8 Ebenen, sowohl
für die Firmware (third_party/cJSON/cJSON.c) als auch für die
Host-Tests (nl_cjson), damit beide dasselbe Verhalten zeigen.

Test: test_post_validation deckt jetzt einen Body mit 20 verschachtelten
Arrays ab (400 "invalid json").
2026-09-11 23:50:45 +02:00
Michael Sauer de49647f9d docs: Bruno-Collection, REST-Doku und Netzwerk-Checkliste 2026-09-11 23:14:15 +02:00
Michael Sauer f11ac8d9cc fix: mDNS-Init nur einmal, Teilfehler wiederholbar 2026-09-11 23:10:51 +02:00
Michael Sauer 27a6d6caf2 feat: mDNS-Responder für _ninlight._tcp 2026-09-11 23:06:04 +02:00
Michael Sauer c068156e6c fix: Send-Timeout für den HTTP-Server 2026-09-11 23:03:01 +02:00
Michael Sauer 15f709594b feat: HTTP-Server auf Port 3333 mit App-API-Kontext 2026-09-11 22:59:34 +02:00
Michael Sauer 4c2f9e5374 feat: WLAN-Treiber mit Onboarding-AP, Build-Credentials und Befehl net 2026-09-11 22:50:43 +02:00
Michael Sauer 2f7cadaeee fix: Verbindungs-Timeout im WLAN-Zustandsautomaten 2026-09-11 22:42:49 +02:00
Michael Sauer 2bdeaed98d feat: WLAN-Zustandsautomat mit Onboarding, Backoff und AP-Fallback 2026-09-11 22:35:30 +02:00
Michael Sauer dc23d3d887 feat: REST-API mit Routing, Auth und Handlern 2026-09-11 22:24:24 +02:00
Michael Sauer 4a23df1b8d feat: cJSON, Gerätenamen und HTTP-Parser 2026-09-11 22:18:14 +02:00
Michael Sauer 0648b3a252 fix: Flash-Lock im SDK, Store-Lock, Flush vor Reboot 2026-09-11 22:10:28 +02:00
Michael Sauer dce9ad2946 docs: Watchdog-Test am EVK bestanden 2026-09-11 21:33:50 +02:00
Michael Sauer e19ee98ee8 docs: Hardware-Checkliste und README aktualisieren
hardware-checklist.md: Watchdog-Zeile beschreibt jetzt den wdtest-Testablauf (Neustart nach ca. 20-40s), bleibt unabgehakt; neuer Punkt unter "Später (Lampen)" zum SM2135EH-Standby-Bit. README.md: tools/flash.sh full als auf Hardware noch ungetestet markiert.
2026-09-11 20:53:50 +02:00
Michael Sauer d03b571bb8 docs: irreführende Kommentare zu Flash-Locking und G95-Pinbelegung korrigieren
nl_flash_w600.c: der Header-Kommentar behauptete, tls_spifls_*/tls_fls_* kämen ganz ohne Locking aus - tatsächlich ist nur das Pin-Switching für die >1MB-Region (ioclose/cs/ck-Switching in wm_internal_fls.c) unsynchronisiert, unser Mutex serialisiert ausschließlich ninlights eigene Tasks, nicht SDK-interne Flash-Nutzer wie den Parameter-Store oder fwup (für Plan 2 vorgemerkt). Auch der Kommentar auf nl_flash_region_base() war ungenau. nl_board.c: G95-Kommentar eindeutiger formuliert (aktuelle Tabelle CW=PB13/WW=PB15, alte Lampen ggf. PB16=WW/PB15=CW).
2026-09-11 20:53:43 +02:00
Michael Sauer 9ce5135489 fix: Rückgabewert von tls_os_mutex_create in UserMain prüfen
Schlägt die Mutex-Erstellung für s_lock fehl, wird jetzt "FATAL: cannot create app lock" ausgegeben und UserMain kehrt zurück, statt mit einem NULL-Mutex weiterzumachen und den App-Task zu starten.
2026-09-11 20:53:34 +02:00
Michael Sauer 4f270ad79b fix: Watchdog wirksam machen, Factory-Reset im App-Task, Resetzähler-Retry
- vApplicationIdleHook() füttert den Watchdog nicht mehr (sdk/Platform/Sys/wm_main.c,
  dokumentiert als Patch 4 in sdk/PATCHES.md). Bisher fütterte der Idle-Task den
  Watchdog bei jedem Leerlauf, auch wenn ein Task deadlockt (z.B. nl_app_lock() hält
  und nie freigibt) - der Watchdog konnte so nie greifen.
- Neues Konsolenkommando `wdtest` (Parser in nl_console_cmd.c/.h, Ausführung in
  nl_console.c, Host-Test in test_console_cmd.c): hält nl_app_lock() für immer, damit
  light_task und app_task blockieren und nur der Watchdog-Reset den Chip retten kann.
- nl_app_request_factory_reset() (nl_app.h) setzt nur ein volatile Flag; app_task
  prüft es in der Hauptschleife und ruft nl_app_factory_reset() selbst auf, da nur der
  App-Task die Flash-Stores besitzt. Das Konsolenkommando `factory` ruft jetzt diese
  Funktion statt nl_app_factory_reset() direkt aufzurufen, um die Race mit
  nl_state_log_append()/nl_resetcnt_clear() im App-Task zu vermeiden. Der Bootpfad
  (Bootzähler >= 5) ruft weiterhin direkt nl_app_factory_reset() auf.
- nl_resetcnt_clear() wird nur noch als erledigt markiert, wenn es 0 zurückgibt, damit
  ein fehlgeschlagener Clear in der nächsten Schleifeniteration erneut versucht wird.
2026-09-11 20:53:25 +02:00
Michael Sauer 488dac9167 fix: LED-Init an den Anfang von app_task verschieben (Boot-Reihenfolge Spec §3.4)
nl_led_init(board) läuft jetzt direkt nach nl_flash_init(), noch vor dem Reset-Counter/Settings/State-Log-Scan, damit die LEDs von Anfang an dunkel bleiben statt erst nach dem Flash-Scan initialisiert zu werden.
2026-09-11 17:05:08 +02:00
Michael Sauer 64acc6b1d9 fix: Flash-Skript an EVK-Befund angepasst, Checkliste abgehakt
- Flash-Skript flasht jetzt das App-Image (ninlight_<dev>_gz.img) mit 460800 baud
- -rs none statt -rs rts, Reset-Taste manuell nötig
- Optionales Argument 'full' für Vollbild-Flash (blank chips nur)
- Checkliste Light und Persistenz als bestanden markiert, Testdatum notiert
2026-09-11 16:45:15 +02:00
Michael Sauer b986bb10b9 build: Build aller Geräte und README 2026-09-11 16:30:47 +02:00
Michael Sauer 7502f4f022 fix: Flash-Mutex beim Boot statt im kritischen Abschnitt anlegen 2026-09-11 16:14:15 +02:00
Michael Sauer 21dcdcb13b fix: Flash-Zugriffe der ninlight-Tasks per Mutex serialisieren 2026-09-11 16:10:09 +02:00
Michael Sauer 55b162b0a0 feat: Persistenz, Einschaltverhalten, Werksreset und Watchdog 2026-09-11 16:01:41 +02:00
Michael Sauer 757620f222 feat: LED-Treiber, Licht-Task und UART-Testkonsole 2026-09-11 13:51:31 +02:00
Michael Sauer 1074a8f034 feat: Parser für die UART-Testkonsole 2026-09-11 13:43:08 +02:00
Michael Sauer 663825c165 feat: Power-Cycle-Zähler für den Werksreset 2026-09-11 13:39:01 +02:00
Michael Sauer 35b59a64ed fix: Zustands-Log bei fehlgeschlagenem Löschen neu einlesen 2026-09-11 13:35:56 +02:00
Michael Sauer b1b4ec214b feat: Ring-Log für den Lichtzustand 2026-09-11 13:30:26 +02:00
Michael Sauer 91721ac47d feat: Flash-HAL-Interface und Settings-Store mit A/B-Slots
Implementiert:
- Flash HAL (nl_flash_read/write/erase_sector) Interfaces
- Flash Layout mit A/B-Settings Slots und weiteren Regions
- Test-Fake für Flash mit Fehlerinjection (Stromausfall-Simulation)
- Settings-Store mit CRC32 Recovery und Slot-Alternierung
- Vollständige Test-Suite mit Corruption/Power-Loss-Tests
2026-09-11 13:24:52 +02:00
Michael Sauer e0bde7bee3 feat: Licht-Steuerung mit Fade-Regeln und Einschaltverhalten 2026-09-11 13:20:49 +02:00
Michael Sauer 472d2398ac fix: Engine-Grenzen für Segmente und Blink-Anzahl 2026-09-11 13:17:21 +02:00
Michael Sauer 73a7f31cb6 feat: Licht-Engine mit Transitionen, Moduswechsel und Effekten 2026-09-11 13:11:23 +02:00
Michael Sauer 42eeb0e0eb feat: Farbrechnung mit CIE-Helligkeit und CW/WW-Mischung 2026-09-11 13:06:19 +02:00
Michael Sauer 6e6cfeaf3a feat: Board-Tabelle für alle acht Gerätetypen 2026-09-11 13:00:02 +02:00
Michael Sauer 1b0501179d build: W600-SDK importiert, Firmware-Build und Hello am EVK
Docker-Build mit gcc-arm-none-eabi 4.9-2014q4 (statt Homebrew-Cask) verwendet,
Dockerfile/tools/docker.sh dafür aus Task 13 vorgezogen. cmake/sdk.cmake schont
gcc 4.9 (kennt -fcommon/-Wno-error=... nicht). Zwei zusätzliche SDK-Stubs
(EarlyInit, pre_gpio_config) in src/sys/sdk_stubs.c ergänzt, siehe sdk/PATCHES.md.
2026-09-11 12:52:26 +02:00
Michael Sauer 4e7ff78fc6 test: Host-Testumgebung mit Unity, SHA256 und CRC 2026-09-11 12:23:04 +02:00
Michael Sauer 23df6b9d29 build: .superpowers/ ignorieren 2026-09-11 12:19:33 +02:00
Michael Sauer 3854c3a0bd Initiales Repo mit .gitignore 2026-09-11 11:17:52 +02:00