feat(sacn): Ergebnis des Multicast-Beitritts sichtbar machen
Bei der Abnahme kam Multicast nicht an, waehrend Unicast lief. Der Rueckgabewert von IP_ADD_MEMBERSHIP wurde bis jetzt verworfen - absichtlich, weil ein gescheiterter Beitritt den Unicast-Empfang nicht verhindern soll. Die Folge war aber, dass sich die entscheidende Frage nicht beantworten liess: tritt die Lampe nicht bei, oder reicht das WLAN die Gruppe nicht weiter? system/info traegt deshalb jetzt "sacn.multicast", und der Beitritt schreibt beim Socket-Aufbau eine Zeile auf die Konsole. Am Verhalten aendert sich nichts: ein Fehlschlag bleibt folgenlos fuer Unicast.
This commit is contained in:
@@ -271,6 +271,10 @@ static void handle_info(const nl_api_ctx_t *ctx, nl_api_response_t *resp)
|
||||
ctx->get_settings(&s);
|
||||
cJSON_AddBoolToObject(sa, "active", in.sacn_active);
|
||||
cJSON_AddNumberToObject(sa, "universe", s.sacn_universe);
|
||||
/* Sagt, ob der Beitritt zur Multicast-Gruppe gelungen ist. Ohne dieses Feld war bei
|
||||
* der Abnahme nicht zu unterscheiden, ob die Lampe nicht beitritt oder das WLAN die
|
||||
* Gruppe nicht weiterreicht - Unicast laeuft in beiden Faellen. */
|
||||
cJSON_AddBoolToObject(sa, "multicast", in.sacn_joined);
|
||||
}
|
||||
reply_json(resp, 200, o);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ typedef struct {
|
||||
uint32_t free_heap;
|
||||
const char *last_ota_error; /* NULL until OTA exists */
|
||||
bool sacn_active; /* true, solange die Lampe ferngesteuert wird */
|
||||
bool sacn_joined; /* Multicast-Gruppe des Universe beigetreten */
|
||||
} nl_sys_info_t;
|
||||
|
||||
/* Everything the API needs from the application; implemented by src/sys/nl_app_api.c. */
|
||||
|
||||
+14
-2
@@ -30,6 +30,8 @@ volatile uint32_t nl_sacn_beat;
|
||||
* wuerde die Lampe im 20-s-Takt endlos zuruecksetzen - ein Zusatzdienst darf sie nicht
|
||||
* unbrauchbar machen. */
|
||||
static volatile bool s_running = true;
|
||||
/* Ergebnis des letzten Multicast-Beitritts; ueber system/info sichtbar. */
|
||||
static volatile bool s_joined;
|
||||
|
||||
void nl_sacn_apply_settings(const nl_settings_t *s)
|
||||
{
|
||||
@@ -79,12 +81,20 @@ static int open_socket(uint16_t universe, char ip_seen[16])
|
||||
ip_seen[15] = '\0';
|
||||
|
||||
/* 239.255.<hi>.<lo> gemaess E1.31 Anhang A. Ein fehlgeschlagener Beitritt ist kein
|
||||
* Abbruchgrund: Unicast an die Lampen-IP kommt auf demselben Socket weiterhin an. */
|
||||
* Abbruchgrund: Unicast an die Lampen-IP kommt auf demselben Socket weiterhin an.
|
||||
*
|
||||
* Das Ergebnis wird aber festgehalten und ueber system/info sichtbar gemacht. Bei der
|
||||
* Abnahme am 2026-09-20 kam Multicast nicht an, waehrend Unicast lief - und weil der
|
||||
* Rueckgabewert damals verworfen wurde, liess sich nicht unterscheiden, ob die Lampe
|
||||
* nicht beitritt oder das WLAN die Gruppe nicht weiterreicht. Genau diese Frage
|
||||
* beantwortet das Feld. */
|
||||
memset(&mreq, 0, sizeof mreq);
|
||||
mreq.imr_multiaddr.s_addr =
|
||||
htonl(0xefff0000u | ((uint32_t)(universe >> 8) << 8) | (universe & 0xffu));
|
||||
mreq.imr_interface.s_addr = ip_seen[0] ? inet_addr(ip_seen) : htonl(INADDR_ANY);
|
||||
setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof mreq);
|
||||
s_joined = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof mreq) == 0;
|
||||
printf("sacn: universe %u, multicast join %s\r\n", (unsigned)universe,
|
||||
s_joined ? "ok" : "FEHLGESCHLAGEN");
|
||||
return fd;
|
||||
}
|
||||
|
||||
@@ -171,3 +181,5 @@ bool nl_sacn_running(void)
|
||||
{
|
||||
return s_running;
|
||||
}
|
||||
|
||||
bool nl_sacn_joined(void) { return s_joined; }
|
||||
|
||||
@@ -18,5 +18,8 @@ void nl_sacn_start(void);
|
||||
/* false, wenn der Empfangs-Task nicht angelegt werden konnte. Dann bewegt sich
|
||||
* nl_sacn_beat nie und der Wachhund darf ihn nicht mehr verlangen. */
|
||||
bool nl_sacn_running(void);
|
||||
/* true, wenn der Beitritt zur Multicast-Gruppe des eingestellten Universe gelungen ist.
|
||||
* Unicast an die Lampen-IP funktioniert unabhaengig davon. */
|
||||
bool nl_sacn_joined(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -95,6 +95,8 @@ static void get_info(nl_sys_info_t *out)
|
||||
* zu sperren. */
|
||||
out->sacn_active = nl_dmx_active();
|
||||
nl_app_unlock();
|
||||
/* Ausserhalb der Sperre: nl_sacn haelt den Wert selbst, nl_dmx ist nicht beteiligt. */
|
||||
out->sacn_joined = nl_sacn_joined();
|
||||
nl_wifi_status(&w);
|
||||
out->wifi_mode = w.mode;
|
||||
memcpy(out->ssid, w.ssid, sizeof out->ssid);
|
||||
|
||||
@@ -461,11 +461,13 @@ static void test_put_sacn_start_slot_limit_follows_the_board(void)
|
||||
static void test_info_exposes_sacn_state(void)
|
||||
{
|
||||
fake_info.sacn_active = true;
|
||||
fake_info.sacn_joined = true;
|
||||
fake_settings.sacn_universe = 5;
|
||||
call(NL_HTTP_GET, "/api/v1/system/info", NULL, NULL);
|
||||
TEST_ASSERT_EQUAL_INT(200, resp.status);
|
||||
TEST_ASSERT_TRUE(cJSON_IsTrue(sacn_field("active")));
|
||||
TEST_ASSERT_EQUAL_INT(5, (int)cJSON_GetNumberValue(sacn_field("universe")));
|
||||
TEST_ASSERT_TRUE(cJSON_IsTrue(sacn_field("multicast")));
|
||||
}
|
||||
|
||||
/* --- system/command --- */
|
||||
|
||||
Reference in New Issue
Block a user