From bc3eff1a41fcd2e57a1a0e964844063e83538fc7 Mon Sep 17 00:00:00 2001 From: Michael Sauer Date: Fri, 2 Oct 2026 19:32:47 +0200 Subject: [PATCH] fix(mdns): im eigenen AP bis zum Erfolg wiederholen, netif-Zeiger raus I5: s_ap_mdns_done wurde VOR nl_mdns_on_ip_up() gesetzt und merkte damit den Versuch, nicht den Erfolg. Die Arbeit laeuft asynchron im tcpip-Thread; liefert pick_netif() dort NULL, weil das AP-Netif noch keine Adresse hat, protokolliert announce() nur "no usable netif yet" - und niemand versucht es je wieder, solange der AP steht. mDNS ist laut Spec Pflichtteil, die Lampe waere im eigenen AP dauerhaft nicht auffindbar. Neu meldet nl_mdns_service_up() den tatsaechlichen Zustand aus s_service_added, und der Netz-Task stoesst alle 5 s erneut an, solange die Lampe standalone ist, der AP steht und der Dienst noch nicht gemeldet ist. s_announce_pending deckt das Fenster zwischen dem Anstossen und dem Lauf von announce() ab: ohne das haette die Abfrage beim Wechsel Station -> eigener AP noch den Dienst des alten Netifs als Erfolg gewertet. Dazu der netif-Zeiger (%p) aus der mdns-Protokollzeile: waehrend der Fehlersuche war er wertvoll, in einer Release-Firmware ist er Rauschen. Namenskuerzel, Nummer und IPv4 unterscheiden Station und eigenen AP bereits eindeutig, eine Speicheradresse in einem Protokoll, das Nutzer weiterreichen, hilft niemandem - und die Abnahmeliste zitiert die Zeile ohnehin ohne ihn. --- src/net/nl_mdns.c | 24 ++++++++++++++++++++---- src/net/nl_mdns.h | 6 ++++++ src/net/nl_wifi_w600.c | 24 +++++++++++++++++++----- 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/net/nl_mdns.c b/src/net/nl_mdns.c index 758b8cc..5ee8f09 100644 --- a/src/net/nl_mdns.c +++ b/src/net/nl_mdns.c @@ -19,7 +19,11 @@ static bool s_inited; static struct netif *s_nif; /* Netif, an dem Antwortdienst und Dienst haengen */ static bool s_netif_added; -static bool s_service_added; +/* Vom Netz-Task gelesen, im tcpip-Thread geschrieben: volatile, und s_announce_pending deckt + * das Fenster zwischen dem Anstossen und dem Lauf von announce() ab. Ohne das meldete + * nl_mdns_service_up() beim Wechsel Station -> eigener AP noch den Dienst des alten Netifs. */ +static volatile bool s_service_added; +static volatile bool s_announce_pending; static char s_name[NL_NAME_LEN]; static char s_mac[18]; @@ -80,6 +84,7 @@ static void announce(void *arg) (void)arg; if (!nif) { printf("mdns: no usable netif yet\r\n"); + s_announce_pending = false; return; } @@ -109,13 +114,18 @@ static void announce(void *arg) } if (attempted) { - /* Welches Netif benutzt wurde, steht in der Zeile selbst: Zeiger, Namenskuerzel, IPv4. */ + /* Welches Netif benutzt wurde, steht in der Zeile selbst: Namenskuerzel, Nummer, IPv4. + * Der rohe netif-Zeiger stand hier frueher mit (%p) dabei; waehrend der Fehlersuche war + * er nuetzlich, in einer Release-Firmware ist er Rauschen - Kuerzel und Adresse + * unterscheiden Station und eigenen AP bereits eindeutig, und eine Speicheradresse in + * einem Protokoll, das Nutzer weiterreichen, hat keinen Nutzen. */ const ip4_addr_t *ip = netif_ip4_addr(nif); - printf("mdns: %s.local _ninlight._tcp %s on %c%c%u %u.%u.%u.%u (%p)\r\n", nl_wifi_hostname(), + printf("mdns: %s.local _ninlight._tcp %s on %c%c%u %u.%u.%u.%u\r\n", nl_wifi_hostname(), s_service_added ? "up" : "failed", nif->name[0], nif->name[1], (unsigned)nif->num, - ip4_addr1(ip), ip4_addr2(ip), ip4_addr3(ip), ip4_addr4(ip), (void *)nif); + ip4_addr1(ip), ip4_addr2(ip), ip4_addr3(ip), ip4_addr4(ip)); } else mdns_resp_netif_settings_changed(nif); /* re-announce: new IP or TXT */ + s_announce_pending = false; } void nl_mdns_on_ip_up(void) @@ -123,9 +133,15 @@ void nl_mdns_on_ip_up(void) uint8_t mac[6]; nl_wifi_mac(mac); nl_names_mac_str(mac, s_mac); + s_announce_pending = true; tcpip_callback(announce, NULL); } +bool nl_mdns_service_up(void) +{ + return !s_announce_pending && s_service_added; +} + void nl_mdns_set_name(const char *name) { u32 sr = tls_os_set_critical(); diff --git a/src/net/nl_mdns.h b/src/net/nl_mdns.h index 7380eac..08b22f2 100644 --- a/src/net/nl_mdns.h +++ b/src/net/nl_mdns.h @@ -1,8 +1,14 @@ #ifndef NL_MDNS_H #define NL_MDNS_H +#include + /* Called by the network task once the station got an IP (again). */ void nl_mdns_on_ip_up(void); +/* True, sobald der Dienst wirklich angemeldet ist - und erst, nachdem die zuletzt + * angestossene Bekanntmachung im tcpip-Thread auch gelaufen ist. Der Netz-Task stoesst + * im eigenen AP so lange erneut an, bis das hier wahr ist (I5). */ +bool nl_mdns_service_up(void); /* Device name for the TXT record; re-announces when mDNS is running. */ void nl_mdns_set_name(const char *name); diff --git a/src/net/nl_wifi_w600.c b/src/net/nl_wifi_w600.c index 08018f7..ec14583 100644 --- a/src/net/nl_wifi_w600.c +++ b/src/net/nl_wifi_w600.c @@ -45,7 +45,12 @@ static bool s_ap_live; * betritt die Lampe Standalone auf einem schon laufenden, unveraenderten AP, entsteht kein * SOFTAP_SUCCESS mehr. Beides nur im Netz-Task angefasst. */ static bool s_ap_event_seen; /* zum aktuell stehenden AP kam SOFTAP_SUCCESS an */ -static bool s_ap_mdns_done; /* fuer den aktuell stehenden AP wurde nl_mdns_on_ip_up() gerufen */ +static bool s_ap_mdns_done; /* fuer den aktuell stehenden AP steht der mDNS-Dienst wirklich */ +/* I5: s_ap_mdns_done haengt am ERFOLG, nicht am Versuch. nl_mdns_on_ip_up() reicht die Arbeit + * nur an den tcpip-Thread weiter; findet announce() dort noch kein Netif mit Adresse, gibt es + * auf. Bis der Dienst steht, wird alle NL_AP_MDNS_RETRY_MS erneut angestossen. */ +#define NL_AP_MDNS_RETRY_MS 5000u +static uint32_t s_ap_mdns_retry_at; /* Drei Versuche, dann der Rueckfall auf Daten, die schon einmal getragen haben: einer koennte * ein Zufall sein (das Funkteil raeumt gerade den alten AP ab), aber drei hintereinander * heissen, dass das Funkteil genau diese Daten nicht annimmt. Und 3 x 5 s hoechstens @@ -430,11 +435,20 @@ static void net_task(void *arg) /* Zustandsgebunden: auch ein Wechsel auf einen unveraendert stehenden AP loest es aus. * Mehrfaches Rufen waere harmlos, s_ap_mdns_done spart es trotzdem. Faellt der Zustand * weg, gilt die Bekanntmachung beim naechsten Eintritt neu. */ - if (!standalone_now) + if (!standalone_now) { s_ap_mdns_done = false; - else if (s_ap_live && s_ap_event_seen && !s_ap_mdns_done) { - s_ap_mdns_done = true; - nl_mdns_on_ip_up(); + s_ap_mdns_retry_at = now; /* beim Eintritt sofort anstossen */ + } else if (s_ap_live && s_ap_event_seen && !s_ap_mdns_done) { + /* I5: Erst der Erfolg beendet die Sache. Wer den blossen Versuch als erledigt + * verbucht, laesst die Lampe fuer die ganze Standzeit des AP unauffindbar, + * sobald announce() einmal "no usable netif yet" gemeldet hat. Deshalb immer + * erst anstossen und dann den gemeldeten Zustand abfragen - nl_mdns_service_up() + * ist erst wahr, wenn die Bekanntmachung im tcpip-Thread auch gelaufen ist. */ + if (due_now(now, s_ap_mdns_retry_at)) { + s_ap_mdns_retry_at = now + NL_AP_MDNS_RETRY_MS; + nl_mdns_on_ip_up(); + } else + s_ap_mdns_done = nl_mdns_service_up(); } /* M3: retry a softap create that failed, as long as the SM still wants the AP up. */