Commit Graph
7 Commits
Author SHA1 Message Date
Michael Sauer 993b7c1575 fix(settings): neue Felder erst ab dem alten sizeof - sonst war sACN nach dem Update aus
Ein Datensatz aus der Firmware vor diesem Zweig ist 208 Byte lang und traegt hinter
wake_on_change (206) noch ein Fuellbyte. sacn_enabled lag auf genau diesem Byte (207),
und read_rec() kopiert hdr.length Bytes ueber die Vorgaben - jede Lampe im Feld waere
nach der OTA mit sacn_enabled == 0 hochgekommen und haette keinen Socket gebunden,
genau das Gegenteil dessen, was Spezifikation und README versprechen.

_legacy_pad schiebt das erste neue Feld auf 208; _padding schrumpft auf 1 Byte, damit
sizeof ein Vielfaches von 4 bleibt (216). nl_settings_legacy_check pinnt den Offset zur
Uebersetzungszeit fest, denn die bisherige Pruefung sah nur die Teilbarkeit durch 4 und
liess diesen Fall durch. Der Test kuerzte auf offsetof(sacn_enabled) - eine Laenge, die
es auf keiner Lampe je gab - und ging deshalb durch; er kuerzt jetzt auf die Literalzahl
208 und stellt das Fuellbyte nach.
2026-09-20 01:16:42 +02:00
Michael Sauer 33d085cbed feat(sacn): Slotzahl je Board und vier Settings-Felder 2026-09-19 23:56:00 +02:00
Michael SauerandClaude Opus 5 00d5a4c532 feat: Default-Transition, Weckschalter und farbfreier Ausschaltfade
Zwei neue Einstellungen, beide wie fade_in/fade_out ueber
POST /api/v1/device/state les- und schreibbar und sofort wirksam:

- transition_default (Voreinstellung 300 ms) fuellt die Transition fuer
  Farb-, Weiss- und Helligkeitswechsel bei eingeschalteter Lampe, wenn der
  Aufruf kein eigenes "transition" mitbringt. Beim Ein- und Ausschalten
  behalten fade_in/fade_out weiterhin Vorrang.
- wake_on_change (Voreinstellung aus) schaltet die Lampe bei einer Farb-,
  Weiss- oder Helligkeitsaenderung ein, wenn sie aus war. Ein
  ausdrueckliches "on": false im selben Aufruf gewinnt immer.

Beide Felder haengen am Ende von nl_settings_t, damit bestehende Lampen
ueber die Laengentoleranz von read_rec() ihre echten Voreinstellungen
bekommen statt Nullen. nl_ctrl_set_fades() heisst jetzt
nl_ctrl_set_options().

Dazu ein Treiberfehler, der erst an der migrierten GU10 RGB auffiel: der
WY-Zweig von nl_sm2135eh_set() schrieb nur Header und WY-Daten, nie die
RGB-Datenregister. Der Chip behielt also die zuletzt gesetzte Farbe, und
bei einem direkten Wechsel Farbe -> Weiss (ohne Zwischenschritt ueber
dunkel) schaelte sie sich beim Ausblenden wieder frei. Der Header sendet
jetzt die - in Weiss immer nullwertigen - RGB-Daten mit.

Die Bruno-Collection zeigt Transition jetzt zusammen mit einem Farb- und
einem Weisswechsel im selben Aufruf und hat einen Request fuer die
beiden neuen Einstellungen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 02:56:56 +02:00
Michael Sauer a400cc1649 fix: CRC im Settings-Record dort schreiben, wo der Leser sie erwartet
nl_settings_save() rechnete die CRC über [0, offsetof(rec_t, crc)) und legte sie
dort ab, read_rec() liest sie bei sizeof(rec_hdr_t) + hdr.length. Beide Offsets
stimmen nur überein, solange sizeof(nl_settings_t) ein Vielfaches von 4 ist
(aktuell 204). Ein zusätzliches uint16_t - in Plan 4 (Migration) sehr
wahrscheinlich - macht 206, und jeder gespeicherte Record fiele beim nächsten
Boot still durch die CRC: WLAN, Token und Name wären auf allen Lampen weg.

Geschrieben wird jetzt explizit bei NL_SETTINGS_CRC_OFF(length), also exakt an
der Leseposition; dazu eine Übersetzungszeit-Zusicherung, dass die Nutzdaten
direkt hinter dem Header beginnen (die CRC läuft auf beiden Seiten über einen
zusammenhängenden Block).

Test: test_crc_offset_matches_reader prüft die Symmetrie unabhängig von der
Strukturgröße. Gegenprobe mit einem zusätzlichen uint16_t im Struct: mit der
alten Schreibposition fallen vier Settings-Tests, mit der neuen keiner.
2026-09-12 03:14:31 +02:00
Michael Sauer c96e0442c0 fix: fehlende Felder in gekürzten Settings-Records auf echte Defaults setzen
read_rec() füllte den Puffer bisher mit memset(0) statt mit
nl_settings_defaults() vor, bevor die tatsächlich vorhandenen hdr.length
Bytes darübergeschrieben werden. Ein gekürzter Record, dessen Länge vor
fade_in_ms/fade_out_ms endet, aber token noch enthält, lief damit mit
fade_in_ms=0/fade_out_ms=0 statt der spezifizierten 500 ms - genau der Fall,
für den die Längentoleranz gedacht war. Die davor eingebaute "leerer Record"
Sonderbehandlung in nl_settings_load() (fade_in_ms==0 && fade_out_ms==0 &&
token[0]=='\0' -> volle Defaults) ist dadurch überflüssig geworden und
entfernt.

test_load_accepts_shorter_record kürzt jetzt bis vor fade_in_ms und prüft
explizit auf die echten Defaults (500/500/0) statt nur auf Felder vor dem
gekürzten Bereich. test_load_rejects_longer_record verzichtet auf die tote
CRC-Neuberechnung, da read_rec() zu lange Records schon anhand der Länge
verwirft, bevor Payload oder CRC gelesen werden.
2026-09-12 01:11:18 +02:00
Michael Sauer 6e9fb09455 test: Settings-Format längentolerant machen, ota_pending ergänzen
read_rec() akzeptiert jetzt Records mit hdr.length <= sizeof(nl_settings_t):
CRC wird nur über die tatsächlich geschriebenen Bytes geprüft, fehlende Felder
bleiben auf 0 (Default). Ein zu langer (unbekannter) Record wird weiter
abgelehnt. Ein durch massive Kürzung "leer" gelesener Record (fade_in_ms,
fade_out_ms und token allesamt 0) fällt komplett auf die Defaults zurück.
Neues Feld ota_pending (nach fade_out_ms) für den kommenden OTA-Ablauf.
2026-09-12 00:55:20 +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