Files

190 lines
11 KiB
Markdown

# Abnahme sACN/E1.31
Datum: 2026-09-20, nachts
Lampe: Klyqa E27 RGB CW/WW, `192.168.2.204`, MAC `28:6d:cd:5c:7f:5b`, Board `e27_rgb` (6 Slots)
Firmware vorher: `0.3.8-36-gca9bb` — nachher: `0.3.8-61-g9b80a`
Sender: `tools/sacn_send.py`, ausgefuehrt vom Pi `ninlight-station` (192.168.2.96), also aus
demselben Netz wie die Lampen.
## Ergebnis
Bestanden, mit einer benannten Einschraenkung: **Multicast erreicht die Lampe nicht**,
Unicast funktioniert vollstaendig. Siehe den eigenen Abschnitt unten.
## Einzelne Schritte
| # | Pruefpunkt | Wie geprueft | Ergebnis |
|---|---|---|---|
| 0 | OTA aus Home Assistant | `update.install` auf der Update-Entitaet, Abbild aus dem Firmware-Ordner der Produktiv-HA | bestanden; Lampe nach dem Neustart mit Uptime 12 s zurueck, WLAN unveraendert |
| 0a | Versionsvergleich der Integration | HA meldete `0.3.8-36-gca9bb` -> `0.3.8-61-g9b80a` als Update | bestanden; HAs eingebauter Vergleich haette diese Git-Versionen falsch sortiert, der eigene greift |
| 0b | Vorgaben nach dem Update | `GET system/settings` | bestanden: `enabled true`, Universe 1, Startslot 1, `release`, `slots 6` |
| 1 | Uebernahme, Farbe | Gruen per Unicast, 60 s | bestanden (Sichtpruefung Michael: "leuchtet gruen") |
| 2 | Dimmer-Rampe | 0..255 und zurueck, 25 fps | bestanden nach Wechsel des Senders auf den Pi, siehe "Ruckeln" unten |
| 3 | Timeout, Modus `release` | 30 s Blau, dann Strom beenden | bestanden: nach 2,5 s zurueck auf den HA-Zustand (rot, 21 %), Sicht + `device/state` |
| 4 | Timeout, Modus `hold` | Nullen senden, dann Strom beenden | bestanden: Lampe blieb dunkel, obwohl HA "an, rot" hielt |
| 5 | HA holt die Kontrolle zurueck | `light.turn_on` waehrend die Lampe im `hold` dunkel festhing | bestanden: sofort gelb/80 %, `sacn.active` aus |
| 6 | Abbruch-Bit | Zweimal gemessen, mit und ohne `--terminate` | bestanden: **0,1 s** mit Abbruch-Bit gegen **2,5 s** ueber den Timeout |
| 7 | Universe im Betrieb wechseln | auf 12 umgestellt, dann auf 1 und auf 12 gesendet | bestanden: altes Universe wirkungslos, neues uebernimmt, kein Neustart |
Nicht auf Hardware geprueft: ein Board **ohne RGB** (3 Slots, Dimmer/CW/WW). Dafuer haette
eine zweite Lampe geflasht werden muessen. Abgedeckt ist der Fall durch die Host-Tests
(`test_dmx.c`, `test_board_without_rgb_uses_three_slots`) und die board-abhaengige
Slotgrenze in `test_api.c`.
## Befund: Multicast erreicht die Lampe nicht - Ursache liegt im WLAN
Unicast an die Lampen-IP funktioniert durchgaengig. Multicast auf `239.255.0.1` kommt nicht
an, auch nicht von einem Sender im selben Netz.
**Geklaert am 2026-09-20 mit einer Diagnose-Firmware** (`0.3.8-63-gfd61f`, Commit fd61f15):
`system/info` meldet seitdem `sacn.multicast`, also das Ergebnis von `IP_ADD_MEMBERSHIP`.
Die Lampe liefert **`multicast: true`** - der Beitritt zur Gruppe gelingt. Die Pakete kommen
trotzdem nicht an. Damit liegt es nicht an der Firmware, sondern am Netz: das WLAN reicht
die Gruppe `239.255.0.1` nicht an die Lampe weiter.
Dass mDNS funktioniert, widerspricht dem nicht: `224.0.0.251` liegt im link-lokalen Bereich
`224.0.0.0/24`, den Switches und Access Points per Norm von der IGMP-Filterung ausnehmen und
immer fluten. `239.255.0.1` unterliegt dagegen der Filterung.
**Netzseite in derselben Nacht durchprobiert - ohne Erfolg:**
| Zustand im UniFi | Multicast kommt an? |
|---|---|
| Snooping aus, Multicast-zu-Unicast aus, kein Blocker (Ausgangslage) | nein |
| Multicast-zu-Unicast an | nein |
| zusaetzlich IGMP-Snooping an, Querier "Aus (Drittanbieter)" | nein |
| zusaetzlich Querier "Primaer/Failover" | nein |
| dasselbe, danach frischer Beitritt der Lampe erzwungen | nein (`multicast: true` gemeldet) |
Unicast funktionierte in jeder dieser Varianten sofort. Der Multicast- und Broadcast-Blocker
war durchgehend aus, Geraete- und L3-Isolierung ebenfalls.
**Damit zeigt der Verdacht auf die Lampe.** Wichtig fuer den naechsten Versuch: Das Feld
`sacn.multicast` ist NICHT so aussagekraeftig, wie es aussieht. Es meldet nur, dass
`IP_ADD_MEMBERSHIP` erfolgreich zurueckkam. Die SDK-Funktion, die den Hardware-Filter des
W600 programmiert (`ethernetif_igmp_mac_filter` in
`sdk/Src/Network/lwip2.0.3/netif/ethernetif.c`), steigt jedoch ganz oben mit
```c
if (netif != tls_get_netif())
return ERR_OK;
```
aus - sie meldet also Erfolg, OHNE den Filter gesetzt zu haben, wenn die Schnittstelle nicht
die vom SDK als aktuell gefuehrte ist. Dann nimmt der Chip die Frames nie an.
### Was in derselben Nacht noch geprueft und AUSGESCHLOSSEN wurde
- **Der Ausstieg in `ethernetif_igmp_mac_filter` greift nicht.** `tls_get_netif()`
(`sdk/Src/Network/lwip2.0.3/netif/wm_ethernet.c:473`) liefert `nif`, und das ist das
STA-Interface - genau das, auf dem der Beitritt laeuft. `netif != tls_get_netif()` ist
also falsch, der Hardware-Schluessel wird gesetzt. Meine erste Theorie war damit falsch.
- **Die Lampe empfaengt Multicast.** Sie beantwortet eine mDNS-Anfrage, die ausschliesslich
als Multicast an 224.0.0.251 ging.
- **Die Lampe sendet Multicast.** Nach einem Neustart sah der Pi ihre mDNS-Ankuendigung auf
224.0.0.251 - Multicast von WLAN-Geraet zu WLAN-Geraet ist also sichtbar und die Messung
taugt.
- **Im IGMP-Mitschnitt schweigt die Lampe.** Querier-Abfragen (vom Gateway) und Meldungen
anderer Geraete sind zu sehen, von der Lampe kommt weder eine Beitrittsmeldung noch eine
Antwort auf die Abfrage. ABER: Bei aktivem Snooping leiten Switches Meldungen nur Richtung
Router weiter - das Schweigen ist damit ein Indiz, kein Beweis.
- **`tls_filter_mcast_mac(gruppen_mac, 1)` nach dem Beitritt aendert nichts.** Die zweite,
im SDK-Header dokumentierte Filterebene wird aus dem Quelltext nie aufgerufen; sie
ausdruecklich zu oeffnen wurde gebaut, aufgespielt und getestet - Multicast kam weiterhin
nicht an. Der Versuch wurde danach zurueckgenommen, die Lampe laeuft wieder auf `main`.
- **Stromsparen/DTIM scheidet aus**: Waere das die Ursache, kaeme auch mDNS nicht an.
### Naechste Schritte, wenn es weitergeht
1. Serielle Konsole an eine Lampe haengen: sieht man beim Beitritt einen Sendeversuch der
IGMP-Meldung? Das ist die einzige Messung, die das verbleibende Indiz zum Beweis macht.
2. Mitschnitt im Monitor-Modus (Laptop auf demselben Kanal) - zeigt, was wirklich ueber die
Luft geht, unabhaengig davon, was der AP weiterreicht.
3. IGMP-Snooping einmal ganz aus und dabei mitschneiden: dann fluten Switches auch
IGMP-Meldungen, und das Schweigen der Lampe waere eindeutig zu belegen oder zu widerlegen.
4. `sacn.multicast` ehrlicher benennen: es meldet den Rueckgabewert von
`IP_ADD_MEMBERSHIP`, nicht die tatsaechliche Empfangsbereitschaft.
Zwei Fehlversuche auf dem Weg dorthin, damit sie niemand wiederholt:
- Der erste Multicast-Test lief vom Mac (192.168.1.131) gegen eine Lampe in 192.168.2.x.
Multicast wird zwischen den Netzen nicht geroutet - der Test konnte gar nicht gelingen.
- Der zweite liess den Pi in die Gruppe eintreten und an sie senden. Ein Access Point
schickt einem Sender seine eigenen Multicast-Frames nicht zurueck; das Ergebnis war
aussagelos, nicht negativ.
## Befund: Ruckeln bei der Dimmer-Rampe
Die erste Rampe kam sichtbar ruckelig an ("ruckelt sehr"). Gesendet wurde vom Mac, der in
einem anderen Netz haengt als die Lampen; jedes Paket lief ueber den Router. Dieselbe Rampe
vom Pi aus, im selben Netz wie die Lampe, lief deutlich glatter ("viel besser").
Fuer den Einsatz heisst das: Die sACN-Quelle gehoert in dasselbe Netz wie die Lampen.
## Nicht geprueft, weil dafuer eine alte Firmware noetig waere
Der Migrationspfad aus dem kritischen Befund des Schlussreviews (ein vor sACN geschriebener
208-Byte-Datensatz darf `sacn_enabled` nicht ueberschreiben) wurde auf dieser Lampe nicht
durchlaufen: Sie trug keinen gespeicherten Einstellungssatz, alle Werte standen auf Vorgabe.
Abgedeckt ist der Fall durch den Host-Test in `test_settings.c`, der vor dem Fix fehlschlug
und danach besteht. Wer ihn auf Hardware sehen will, nimmt eine Lampe, deren
Einschaltverhalten vom Vorgabewert abweicht — die traegt einen echten alten Datensatz.
## Nachtrag 2026-09-20, 03:40 - Belegung "rgb"
Umgesetzt und an derselben E27 RGB geprueft (Firmware `0.3.8-70-gfbdf0`):
| Pruefpunkt | Ergebnis |
|---|---|
| `PUT {"type":"sacn","layout":"rgb"}` | bestanden; `GET` meldet `layout: rgb`, `slots: 3` |
| Paket mit NUR drei Slots | bestanden: wird angenommen (mit Dimmer-Belegung waere es verworfen worden) |
| Reines Rot (255,0,0) | bestanden (Sichtpruefung Michael: "leuchtet rot") - genau der Fall, der mit der Dimmer-Belegung Dunkelheit ergeben haette |
Die Lampe bleibt im `rgb`-Layout stehen, damit sie fuer LedFx vorbereitet ist. Die anderen
Lampen tragen noch die alte Firmware und damit nur die Dimmer-Belegung.
Nicht auf Hardware geprueft: das `rgb`-Layout auf einem Board OHNE Farbkanaele (groesster
der drei Werte auf beide Weisskanaele). Abgedeckt durch `test_dmx.c`.
## Nachtrag 2026-09-21 - Multicast GEFUNDEN und behoben
Die Ursache lag die ganze Zeit bei uns, nicht im Netz: Die Lampe trat der **falschen Gruppe**
bei. Aus Universe 1 wurde `239.255.239.255` statt `239.255.0.1`.
Schuld ist ein nicht geklammertes Makro im SDK
(`sdk/Include/Net/wm_sockets2.0.3.h`):
```c
#define htonl(n) (((n & 0xff) << 24) | ((n & 0xff00) << 8) | ...)
```
Stand die Adressrechnung direkt im Aufruf, traf die Maske nach der Textersetzung nur den
letzten Term, weil `&` staerker bindet als `|`. Fuer Universe 1 ergibt das exakt `0xefffefff` -
genau der Wert, der am EVK auf der seriellen Konsole stand.
Damit erklaert sich alles, was vorher widerspruechlich aussah: Der Beitritt gelang (deshalb
`multicast: true`), die Lampe meldete ihn auch brav per IGMP - nur eben fuer eine Gruppe, auf
die niemand sendete. Unicast war davon nicht betroffen, mDNS auch nicht (das joint das SDK
selbst mit einer festen Adresse).
**Gefunden am EVK ueber die serielle Konsole**, nachdem vier Netz-Konfigurationen und fuenf
andere Theorien nichts ergeben hatten. LwIPs `igmp.c` liegt als Quelltext im Baum und laesst
sich instrumentieren - das war der Hebel, der zwei Naechte lang fehlte.
### Abnahme des Fixes
| Pruefpunkt | Ergebnis |
|---|---|
| EVK, Gruppe laut Konsole | `join efff0001`, MAC-Filter `01:00:5e:7f:00:01`, Report `type=0x16` |
| EVK, Multicast-Uebernahme | bestanden |
| EVK, Universe-Wechsel ueber Multicast | bestanden: Sender auf 1 wirkungslos, Sender auf 12 uebernimmt |
| E27 RGB (Produktivlampe), Multicast im `rgb`-Layout | bestanden |
| Farbzuordnung: `255,0,255` | lila (Sichtpruefung) - R und B an, G aus |
| Farbzuordnung: `0,255,0` | gruen (Sichtpruefung) - nur der mittlere Kanal |
### Fuer die Netzseite
Die vier UniFi-Umstellungen vom Vortag (Multicast-zu-Unicast, IGMP-Snooping, Querier) waren
fuer dieses Problem nicht noetig. Der Querier auf "Primaer/Failover" gehoert trotzdem so -
Snooping ohne Querier ist unabhaengig davon eine schlechte Kombination.