feat: Licht nach einem OTA wie bei power_on_behaviour=last wiederherstellen

Spec 8.2 verlangt, dass ein durch ein Update ausgelöster Neustart nicht wie ein
Stromausfall wirkt: Das Flag ota_pending wurde bisher nur geschrieben und beim
nächsten Boot wieder gelöscht, nl_boot_state() wendet aber weiterhin das normale
power_on_behaviour an. Eine eingeschaltete Lampe mit pob=off kam nach einem Update
aus zurück, mit pob=on umgekehrt.

nl_boot_state() bekommt dafür ein Argument after_ota; ist ein gespeicherter
Zustand vorhanden, wird er unverändert übernommen. Ohne gespeicherten Zustand
gelten weiterhin die normalen Regeln.

Hosttests: vier neue Fälle in test_boot_state.c (pob=off/on über ein OTA,
Sanitisierung bleibt aktiv, kein gespeicherter Zustand).
This commit is contained in:
Michael Sauer
2026-09-12 03:13:36 +02:00
parent b601ddeb9b
commit 1822014e48
4 changed files with 71 additions and 14 deletions
+48 -5
View File
@@ -23,14 +23,14 @@ static void test_default_state(void)
static void test_last_restores_everything(void)
{
nl_light_state_t last = red_off();
nl_light_state_t s = nl_boot_state(NL_POB_LAST, &last, nl_board_find("evk"));
nl_light_state_t s = nl_boot_state(NL_POB_LAST, &last, nl_board_find("evk"), false);
TEST_ASSERT_TRUE(nl_light_state_equal(&last, &s));
}
static void test_last_without_saved_state_uses_default(void)
{
const nl_board_t *b = nl_board_find("evk");
nl_light_state_t s = nl_boot_state(NL_POB_LAST, NULL, b);
nl_light_state_t s = nl_boot_state(NL_POB_LAST, NULL, b, false);
nl_light_state_t d = nl_boot_default_state(b);
TEST_ASSERT_TRUE(nl_light_state_equal(&d, &s));
}
@@ -38,7 +38,7 @@ static void test_last_without_saved_state_uses_default(void)
static void test_on_forces_on_with_last_values(void)
{
nl_light_state_t last = red_off();
nl_light_state_t s = nl_boot_state(NL_POB_ON, &last, nl_board_find("evk"));
nl_light_state_t s = nl_boot_state(NL_POB_ON, &last, nl_board_find("evk"), false);
TEST_ASSERT_TRUE(s.on);
TEST_ASSERT_EQUAL_UINT8(40, s.brightness);
TEST_ASSERT_EQUAL(NL_MODE_COLOR, s.mode);
@@ -48,7 +48,7 @@ static void test_off_forces_off(void)
{
nl_light_state_t last = red_off();
last.on = true;
nl_light_state_t s = nl_boot_state(NL_POB_OFF, &last, nl_board_find("evk"));
nl_light_state_t s = nl_boot_state(NL_POB_OFF, &last, nl_board_find("evk"), false);
TEST_ASSERT_FALSE(s.on);
TEST_ASSERT_EQUAL_UINT8(40, s.brightness);
}
@@ -56,12 +56,51 @@ static void test_off_forces_off(void)
static void test_sanitizes_stored_values(void)
{
nl_light_state_t last = {true, 0, NL_MODE_COLOR, 1, 2, 3, 9000};
nl_light_state_t s = nl_boot_state(NL_POB_LAST, &last, nl_board_find("e27_cw"));
nl_light_state_t s = nl_boot_state(NL_POB_LAST, &last, nl_board_find("e27_cw"), false);
TEST_ASSERT_EQUAL_UINT8(100, s.brightness); /* invalid 0 -> 100 */
TEST_ASSERT_EQUAL(NL_MODE_WHITE, s.mode); /* no RGB on this board */
TEST_ASSERT_EQUAL_UINT16(5000, s.ct); /* clamped */
}
/* Spec 8.2: a reboot caused by an OTA is not a power cut - the light comes back effectively as
* power_on_behaviour = last, whatever pob says. */
static void test_after_ota_ignores_pob_off(void)
{
nl_light_state_t last = red_off();
nl_light_state_t s;
last.on = true;
s = nl_boot_state(NL_POB_OFF, &last, nl_board_find("evk"), true);
TEST_ASSERT_TRUE(s.on);
TEST_ASSERT_TRUE(nl_light_state_equal(&last, &s));
}
static void test_after_ota_ignores_pob_on(void)
{
nl_light_state_t last = red_off(); /* stored state: off */
nl_light_state_t s = nl_boot_state(NL_POB_ON, &last, nl_board_find("evk"), true);
TEST_ASSERT_FALSE(s.on);
TEST_ASSERT_TRUE(nl_light_state_equal(&last, &s));
}
static void test_after_ota_still_sanitizes(void)
{
nl_light_state_t last = {true, 200, NL_MODE_COLOR, 1, 2, 3, 9000};
nl_light_state_t s = nl_boot_state(NL_POB_OFF, &last, nl_board_find("e27_cw"), true);
TEST_ASSERT_TRUE(s.on);
TEST_ASSERT_EQUAL_UINT8(100, s.brightness);
TEST_ASSERT_EQUAL(NL_MODE_WHITE, s.mode);
TEST_ASSERT_EQUAL_UINT16(5000, s.ct);
}
/* Nothing stored (first boot after a migration): there is no "last" to restore, so the normal
* power_on_behaviour rules apply even with the flag set. */
static void test_after_ota_without_saved_state_uses_pob(void)
{
const nl_board_t *b = nl_board_find("evk");
nl_light_state_t s = nl_boot_state(NL_POB_OFF, NULL, b, true);
TEST_ASSERT_FALSE(s.on);
}
int main(void)
{
UNITY_BEGIN();
@@ -71,5 +110,9 @@ int main(void)
RUN_TEST(test_on_forces_on_with_last_values);
RUN_TEST(test_off_forces_off);
RUN_TEST(test_sanitizes_stored_values);
RUN_TEST(test_after_ota_ignores_pob_off);
RUN_TEST(test_after_ota_ignores_pob_on);
RUN_TEST(test_after_ota_still_sanitizes);
RUN_TEST(test_after_ota_without_saved_state_uses_pob);
return UNITY_END();
}