feat: sACN-Belegung rgb als Vorgabe
Pixelorientierte Werkzeuge wie LedFx schreiben drei Kanaele je Pixel; mit dem Dimmer voran landet deren erstes Pixel auf Dimmer, R, G. rgb ist damit die Belegung, die out of the box das Richtige tut - der Dimmer bleibt fuer DMX-Pulte eine Umschaltung entfernt.
This commit is contained in:
@@ -75,14 +75,14 @@ Verfügbare Befehle in der Konsole: `help`.
|
||||
|
||||
Die Lampe empfängt sACN (E1.31) auf UDP-Port 5568 — per Multicast auf
|
||||
`239.255.<universe_hi>.<universe_lo>` und per Unicast direkt an ihre IP. Nach einem
|
||||
Update ist der Empfang aktiv: Universe 1, Startslot 1.
|
||||
Update ist der Empfang aktiv: Universe 1, Startslot 1, Belegung `rgb`.
|
||||
|
||||
Es gibt zwei Slot-Belegungen, umschaltbar über `layout`:
|
||||
|
||||
| `layout` | Slots ab `start_slot` | wofür |
|
||||
|---|---|---|
|
||||
| `dimmer` (Vorgabe) | Dimmer, R, G, B, CW, WW — ohne RGB: Dimmer, CW, WW | DMX-Pulte, die einen Master-Dimmer erwarten |
|
||||
| `rgb` | R, G, B (3 Slots auf jedem Board) | pixelorientierte Werkzeuge wie LedFx, die je Pixel drei Kanäle schreiben |
|
||||
| `dimmer` | Dimmer, R, G, B, CW, WW — ohne RGB: Dimmer, CW, WW | DMX-Pulte, die einen Master-Dimmer erwarten |
|
||||
| `rgb` (Vorgabe) | R, G, B (3 Slots auf jedem Board) | pixelorientierte Werkzeuge wie LedFx, die je Pixel drei Kanäle schreiben |
|
||||
|
||||
Im `rgb`-Layout ist jede Lampe genau ein Pixel: Lampe 1 auf Offset 0, Lampe 2 auf Offset 3,
|
||||
und so weiter. Ein Board ohne Farbkanäle nimmt den größten der drei Werte auf beide
|
||||
|
||||
@@ -77,7 +77,7 @@ void nl_settings_defaults(nl_settings_t *s)
|
||||
s->sacn_universe = 1;
|
||||
s->sacn_start_slot = 1;
|
||||
s->sacn_hold = 0;
|
||||
s->sacn_layout = 0;
|
||||
s->sacn_layout = 1;
|
||||
}
|
||||
|
||||
void nl_settings_init(uint32_t addr_a, uint32_t addr_b)
|
||||
|
||||
@@ -36,7 +36,7 @@ typedef struct {
|
||||
uint16_t sacn_start_slot; /* 1..512 (Vorgabe 1) */
|
||||
uint8_t sacn_hold; /* 0 = nach dem Timeout zurueck zum HA-Zustand, 1 = halten */
|
||||
uint8_t _padding[1]; /* haelt sizeof auf einem Vielfachen von 4 */
|
||||
uint8_t sacn_layout; /* Offset 216 - 0 = Dimmer voran, 1 = nur R,G,B (nl_dmx_layout_t).
|
||||
uint8_t sacn_layout; /* Offset 216 - 0 = Dimmer voran, 1 = nur R,G,B (Vorgabe 1).
|
||||
* Dieselbe Regel wie oben: neue Felder beginnen bei oder hinter
|
||||
* dem vorherigen sizeof (216), sonst ueberschreibt das Fuellbyte
|
||||
* eines aelteren Satzes sie. */
|
||||
|
||||
+12
-8
@@ -361,7 +361,8 @@ static void test_settings_exposes_sacn_block(void)
|
||||
TEST_ASSERT_EQUAL_INT(1, (int)cJSON_GetNumberValue(sacn_field("universe")));
|
||||
TEST_ASSERT_EQUAL_INT(1, (int)cJSON_GetNumberValue(sacn_field("start_slot")));
|
||||
TEST_ASSERT_EQUAL_STRING("release", cJSON_GetStringValue(sacn_field("on_timeout")));
|
||||
TEST_ASSERT_EQUAL_INT(6, (int)cJSON_GetNumberValue(sacn_field("slots")));
|
||||
TEST_ASSERT_EQUAL_STRING("rgb", cJSON_GetStringValue(sacn_field("layout")));
|
||||
TEST_ASSERT_EQUAL_INT(3, (int)cJSON_GetNumberValue(sacn_field("slots")));
|
||||
}
|
||||
|
||||
static void test_settings_sacn_block_reflects_stored_values(void)
|
||||
@@ -442,6 +443,7 @@ static void test_put_sacn_rejects_fractional_numbers(void)
|
||||
/* Ein Board mit RGB braucht 6 Slots: ab 508 passt der Satz nicht mehr ins Universe. */
|
||||
static void test_put_sacn_start_slot_must_leave_room_for_all_slots(void)
|
||||
{
|
||||
fake_settings.sacn_layout = 0; /* die Vorgabe ist rgb mit 3 Slots - hier geht es um 6 */
|
||||
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"sacn\",\"start_slot\":507}");
|
||||
TEST_ASSERT_EQUAL_INT(200, resp.status);
|
||||
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"sacn\",\"start_slot\":508}");
|
||||
@@ -451,7 +453,9 @@ static void test_put_sacn_start_slot_must_leave_room_for_all_slots(void)
|
||||
|
||||
static void test_put_sacn_start_slot_limit_follows_the_board(void)
|
||||
{
|
||||
fake_api_reset("g95_cw"); /* drei Slots: 510 passt noch */
|
||||
fake_api_reset("g95_cw");
|
||||
fake_settings.sacn_layout = 0; /* im dimmer-Layout haengt die Slotzahl am Board */
|
||||
/* Ein Board ohne Farbe hat auch mit Dimmer nur drei Slots: 510 passt noch. */
|
||||
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"sacn\",\"start_slot\":510}");
|
||||
TEST_ASSERT_EQUAL_INT(200, resp.status);
|
||||
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"sacn\",\"start_slot\":511}");
|
||||
@@ -512,15 +516,15 @@ static void test_commands(void)
|
||||
|
||||
static void test_settings_reports_the_layout_and_matching_slots(void)
|
||||
{
|
||||
call(NL_HTTP_GET, "/api/v1/system/settings", TOKEN, NULL);
|
||||
/* Vorgabe: rgb - und darin belegt auch ein Board mit Farbe nur drei Slots. */
|
||||
TEST_ASSERT_EQUAL_STRING("rgb", cJSON_GetStringValue(sacn_field("layout")));
|
||||
TEST_ASSERT_EQUAL_INT(3, (int)cJSON_GetNumberValue(sacn_field("slots")));
|
||||
|
||||
fake_settings.sacn_layout = 0;
|
||||
call(NL_HTTP_GET, "/api/v1/system/settings", TOKEN, NULL);
|
||||
TEST_ASSERT_EQUAL_STRING("dimmer", cJSON_GetStringValue(sacn_field("layout")));
|
||||
TEST_ASSERT_EQUAL_INT(6, (int)cJSON_GetNumberValue(sacn_field("slots")));
|
||||
|
||||
fake_settings.sacn_layout = 1;
|
||||
call(NL_HTTP_GET, "/api/v1/system/settings", TOKEN, NULL);
|
||||
TEST_ASSERT_EQUAL_STRING("rgb", cJSON_GetStringValue(sacn_field("layout")));
|
||||
/* Im rgb-Layout belegt auch ein Board mit Farbe nur drei Slots. */
|
||||
TEST_ASSERT_EQUAL_INT(3, (int)cJSON_GetNumberValue(sacn_field("slots")));
|
||||
}
|
||||
|
||||
static void test_put_sacn_layout(void)
|
||||
|
||||
@@ -238,20 +238,20 @@ static void test_record_without_sacn_gets_defaults(void)
|
||||
|
||||
/* Die Satzlaenge muss durch 4 teilbar bleiben, sonst laufen Schreiber und Leser beim CRC
|
||||
* auseinander (siehe NL_SETTINGS_CRC_OFF in nl_settings.c). */
|
||||
static void test_sacn_layout_defaults_to_dimmer(void)
|
||||
static void test_sacn_layout_defaults_to_rgb(void)
|
||||
{
|
||||
nl_settings_t s;
|
||||
TEST_ASSERT_FALSE(nl_settings_load(&s));
|
||||
TEST_ASSERT_EQUAL_UINT8(0, s.sacn_layout);
|
||||
TEST_ASSERT_EQUAL_UINT8(1, s.sacn_layout);
|
||||
}
|
||||
|
||||
static void test_sacn_layout_roundtrip(void)
|
||||
{
|
||||
nl_settings_t in = sample("layout"), out;
|
||||
in.sacn_layout = 1;
|
||||
in.sacn_layout = 0; /* weg von der Vorgabe, sonst prueft der Test nur diese */
|
||||
TEST_ASSERT_EQUAL_INT(0, nl_settings_save(&in));
|
||||
TEST_ASSERT_TRUE(nl_settings_load(&out));
|
||||
TEST_ASSERT_EQUAL_UINT8(1, out.sacn_layout);
|
||||
TEST_ASSERT_EQUAL_UINT8(0, out.sacn_layout);
|
||||
}
|
||||
|
||||
/* Derselbe Fallstrick wie bei sacn_enabled, eine Feldgeneration weiter: ein Satz, der von
|
||||
@@ -261,7 +261,7 @@ static void test_record_without_layout_gets_the_default(void)
|
||||
{
|
||||
nl_settings_t in = sample("vor-layout"), out;
|
||||
uint32_t crc;
|
||||
in.sacn_layout = 1;
|
||||
in.sacn_layout = 0; /* der abgeschnittene Satz darf diese 0 nicht zurueckliefern */
|
||||
nl_settings_save(&in);
|
||||
{
|
||||
uint16_t shorter = 216u; /* sizeof(nl_settings_t) vor dem Layout-Feld */
|
||||
@@ -272,7 +272,7 @@ static void test_record_without_layout_gets_the_default(void)
|
||||
TEST_ASSERT_TRUE(nl_settings_load(&out));
|
||||
TEST_ASSERT_EQUAL_STRING("vor-layout", out.name);
|
||||
TEST_ASSERT_EQUAL_UINT8(1, out.sacn_enabled);
|
||||
TEST_ASSERT_EQUAL_UINT8(0, out.sacn_layout);
|
||||
TEST_ASSERT_EQUAL_UINT8(1, out.sacn_layout);
|
||||
}
|
||||
|
||||
static void test_record_size_stays_aligned(void)
|
||||
@@ -297,7 +297,7 @@ int main(void)
|
||||
RUN_TEST(test_sacn_defaults);
|
||||
RUN_TEST(test_sacn_roundtrip);
|
||||
RUN_TEST(test_record_without_sacn_gets_defaults);
|
||||
RUN_TEST(test_sacn_layout_defaults_to_dimmer);
|
||||
RUN_TEST(test_sacn_layout_defaults_to_rgb);
|
||||
RUN_TEST(test_sacn_layout_roundtrip);
|
||||
RUN_TEST(test_record_without_layout_gets_the_default);
|
||||
RUN_TEST(test_record_size_stays_aligned);
|
||||
|
||||
Reference in New Issue
Block a user