From 0d924d139c0f27bbc233031b5491668188c9e241 Mon Sep 17 00:00:00 2001 From: miketsai Date: Sun, 14 Jun 2026 13:38:38 +0800 Subject: [PATCH] refactor(test): split CAN and buzzer into independent test groups test_can_event() no longer controls buzzer; new TEST_BUZZER_ALL thread tests all buzzer patterns independently. TEST_ALL now runs three sequential groups: BLE, CAN-only, Buzzer-only. --- src/host_stream/event_recorder.c | 106 +++++++++++++++++++------------ 1 file changed, 66 insertions(+), 40 deletions(-) diff --git a/src/host_stream/event_recorder.c b/src/host_stream/event_recorder.c index 958e060..e8339f2 100644 --- a/src/host_stream/event_recorder.c +++ b/src/host_stream/event_recorder.c @@ -191,7 +191,7 @@ volatile int g_test_mode = 0; static time_t s_test_mode_entered = 0; static volatile int s_test_all_running = 0; -#define TEST_MODE_TIMEOUT_SEC 60 +#define TEST_MODE_TIMEOUT_SEC 300 /* 5 minutes — enough for a full test sequence */ #define TEST_OBS_DEFAULT_SEC 10 /* *URL / network helpers (Channel B only)**/ @@ -434,7 +434,11 @@ static void fire_json_async(const char *event_id, const char *type, int level) static void str_toupper(char *s) { - for (; *s; s++) *s = (char)toupper((unsigned char)*s); + /* Avoid locale-dependent toupper() — use direct ASCII range check instead. + * On uClibc without locale initialisation, toupper() may produce garbage. */ + for (; *s; s++) { + if (*s >= 'a' && *s <= 'z') *s = (char)(*s - 32); + } } static void test_reply(const char *msg) @@ -512,20 +516,13 @@ static void test_ble_alert(int ll, const char *lt, int rl, const char *rt) test_reply(ack); } -static void test_can_event(const char *event, int level, - uint8_t speed, buzzer_pattern_t pat) +static void test_can_event(const char *event, int level, uint8_t speed) { can_ctrl_cmd_t ctrl = { .speed = speed, .led_gpio = 0, .led_enable = 0, .keepalive_interval_ms = 0 }; can_bus_send_control_cmd(&ctrl); - buzzer_set_pattern(pat); - char ack[96]; - snprintf(ack, sizeof(ack), - "TEST_ACK CAN %s %d speed=%u buzzer=%s", - event, level, (unsigned)speed, - pat == BUZZER_PATTERN_COLLISION ? "collision" : - pat == BUZZER_PATTERN_ALERT ? "alert" : - pat == BUZZER_PATTERN_GRASS ? "grass" : "off"); + char ack[64]; + snprintf(ack, sizeof(ack), "TEST_ACK CAN %s %d speed=%u", event, level, (unsigned)speed); test_reply(ack); } @@ -551,27 +548,42 @@ static void *test_can_all_thread(void *arg) { int obs = arg ? (int)(intptr_t)arg : TEST_OBS_DEFAULT_SEC; test_reply("TEST_CAN_ALL_START"); - test_can_event("VIOLATION", 1, SPEED_LIMIT_ALERT, BUZZER_PATTERN_GRASS); sleep(obs); - test_can_event("VIOLATION", 0, SPEED_LIMIT_NORMAL, BUZZER_PATTERN_OFF); sleep(3); - test_can_event("COLLISION", 1, SPEED_LIMIT_STOP, BUZZER_PATTERN_COLLISION); sleep(obs); - test_can_event("COLLISION", 0, SPEED_LIMIT_NORMAL, BUZZER_PATTERN_OFF); sleep(3); - test_can_event("ALERT", 1, SPEED_LIMIT_ALERT, BUZZER_PATTERN_ALERT); sleep(obs); - test_can_event("ALERT", 0, SPEED_LIMIT_NORMAL, BUZZER_PATTERN_OFF); sleep(3); - test_reply("TEST_CAN_BUZZER_ONLY_START"); - buzzer_set_pattern(BUZZER_PATTERN_GRASS); sleep(4); - buzzer_set_pattern(BUZZER_PATTERN_ALERT); sleep(4); - buzzer_set_pattern(BUZZER_PATTERN_COLLISION); sleep(4); - buzzer_set_pattern(BUZZER_PATTERN_OFF); + test_can_event("VIOLATION", 1, SPEED_LIMIT_ALERT); sleep(obs); + test_can_event("VIOLATION", 0, SPEED_LIMIT_NORMAL); sleep(3); + test_can_event("COLLISION", 1, SPEED_LIMIT_STOP); sleep(obs); + test_can_event("COLLISION", 0, SPEED_LIMIT_NORMAL); sleep(3); + test_can_event("ALERT", 1, SPEED_LIMIT_ALERT); sleep(obs); + test_can_event("ALERT", 0, SPEED_LIMIT_NORMAL); sleep(3); test_reply("TEST_CAN_ALL_DONE"); test_mode_exit_internal("CAN_ALL complete"); s_test_all_running = 0; return NULL; } +static void *test_buzzer_all_thread(void *arg) +{ + (void)arg; + test_reply("TEST_BUZZER_ALL_START"); + buzzer_set_pattern(BUZZER_PATTERN_GRASS); + test_reply("TEST_ACK BUZZER GRASS"); sleep(4); + buzzer_set_pattern(BUZZER_PATTERN_ALERT); + test_reply("TEST_ACK BUZZER ALERT"); sleep(4); + buzzer_set_pattern(BUZZER_PATTERN_COLLISION); + test_reply("TEST_ACK BUZZER COLLISION"); sleep(4); + buzzer_set_pattern(BUZZER_PATTERN_OFF); + test_reply("TEST_ACK BUZZER OFF"); + test_reply("TEST_BUZZER_ALL_DONE"); + test_mode_exit_internal("BUZZER_ALL complete"); + s_test_all_running = 0; + return NULL; +} + static void *test_all_thread(void *arg) { int obs = arg ? (int)(intptr_t)arg : TEST_OBS_DEFAULT_SEC; test_reply("TEST_ALL_START"); + + /* Group 1: BLE */ test_reply("TEST_ALL_BLE_GROUP_START"); test_ble_violation(1); sleep(3); test_ble_violation(0); sleep(2); @@ -583,18 +595,26 @@ static void *test_all_thread(void *arg) test_ble_alert(0, NULL, 0, NULL); sleep(2); test_reply("TEST_ALL_BLE_GROUP_DONE"); sleep(3); + + /* Group 2: CAN only */ test_reply("TEST_ALL_CAN_GROUP_START"); - test_can_event("VIOLATION", 1, SPEED_LIMIT_ALERT, BUZZER_PATTERN_GRASS); sleep(obs); - test_can_event("VIOLATION", 0, SPEED_LIMIT_NORMAL, BUZZER_PATTERN_OFF); sleep(3); - test_can_event("COLLISION", 1, SPEED_LIMIT_STOP, BUZZER_PATTERN_COLLISION); sleep(obs); - test_can_event("COLLISION", 0, SPEED_LIMIT_NORMAL, BUZZER_PATTERN_OFF); sleep(3); - test_can_event("ALERT", 1, SPEED_LIMIT_ALERT, BUZZER_PATTERN_ALERT); sleep(obs); - test_can_event("ALERT", 0, SPEED_LIMIT_NORMAL, BUZZER_PATTERN_OFF); sleep(3); + test_can_event("VIOLATION", 1, SPEED_LIMIT_ALERT); sleep(obs); + test_can_event("VIOLATION", 0, SPEED_LIMIT_NORMAL); sleep(3); + test_can_event("COLLISION", 1, SPEED_LIMIT_STOP); sleep(obs); + test_can_event("COLLISION", 0, SPEED_LIMIT_NORMAL); sleep(3); + test_can_event("ALERT", 1, SPEED_LIMIT_ALERT); sleep(obs); + test_can_event("ALERT", 0, SPEED_LIMIT_NORMAL); sleep(3); + test_reply("TEST_ALL_CAN_GROUP_DONE"); + sleep(3); + + /* Group 3: Buzzer only */ + test_reply("TEST_ALL_BUZZER_GROUP_START"); buzzer_set_pattern(BUZZER_PATTERN_GRASS); sleep(4); buzzer_set_pattern(BUZZER_PATTERN_ALERT); sleep(4); buzzer_set_pattern(BUZZER_PATTERN_COLLISION); sleep(4); buzzer_set_pattern(BUZZER_PATTERN_OFF); - test_reply("TEST_ALL_CAN_GROUP_DONE"); + test_reply("TEST_ALL_BUZZER_GROUP_DONE"); + test_reply("TEST_ALL_DONE"); test_mode_exit_internal("ALL complete"); s_test_all_running = 0; @@ -608,6 +628,7 @@ static void handle_test_cmd(const char *raw) cmd[sizeof(cmd) - 1] = '\0'; str_toupper(cmd); printf("[TEST CMD] %s\n", cmd); + fflush(stdout); /* ensure this line is visible in fw.log even if next call hangs */ if (g_test_mode) s_test_mode_entered = time(NULL); @@ -650,32 +671,37 @@ static void handle_test_cmd(const char *raw) pthread_t tid; pthread_create(&tid, NULL, test_can_all_thread, (void*)(intptr_t)obs); pthread_detach(tid); } else if (strncmp(cmd, "TEST_CAN VIOLATION", 18) == 0) { int lv = atoi(cmd + 18); - test_can_event("VIOLATION", lv, - lv ? SPEED_LIMIT_ALERT : SPEED_LIMIT_NORMAL, - lv ? BUZZER_PATTERN_GRASS : BUZZER_PATTERN_OFF); + test_can_event("VIOLATION", lv, lv ? SPEED_LIMIT_ALERT : SPEED_LIMIT_NORMAL); } else if (strncmp(cmd, "TEST_CAN COLLISION", 18) == 0) { int lv = atoi(cmd + 18); - test_can_event("COLLISION", lv, - lv ? SPEED_LIMIT_STOP : SPEED_LIMIT_NORMAL, - lv ? BUZZER_PATTERN_COLLISION : BUZZER_PATTERN_OFF); + test_can_event("COLLISION", lv, lv ? SPEED_LIMIT_STOP : SPEED_LIMIT_NORMAL); } else if (strncmp(cmd, "TEST_CAN ALERT", 14) == 0) { int ll = 0, rl = 0; sscanf(cmd + 14, " %d %d", &ll, &rl); int active = ll || rl; - test_can_event("ALERT", active, - active ? SPEED_LIMIT_ALERT : SPEED_LIMIT_NORMAL, - active ? BUZZER_PATTERN_ALERT : BUZZER_PATTERN_OFF); + test_can_event("ALERT", active, active ? SPEED_LIMIT_ALERT : SPEED_LIMIT_NORMAL); + } else if (strncmp(cmd, "TEST_BUZZER_ALL", 15) == 0) { + if (s_test_all_running) { test_reply("TEST_ERR ALL_ALREADY_RUNNING"); return; } + s_test_all_running = 1; + pthread_t tid; pthread_create(&tid, NULL, test_buzzer_all_thread, NULL); pthread_detach(tid); } else if (strncmp(cmd, "TEST_BUZZER", 11) == 0) { char pat[16] = "OFF"; sscanf(cmd + 11, " %15s", pat); + printf("[TEST BUZZER] pat=%s\n", pat); buzzer_pattern_t p = BUZZER_PATTERN_OFF; if (strcmp(pat, "COLLISION") == 0) p = BUZZER_PATTERN_COLLISION; else if (strcmp(pat, "ALERT") == 0) p = BUZZER_PATTERN_ALERT; else if (strcmp(pat, "GRASS") == 0) p = BUZZER_PATTERN_GRASS; + printf("[TEST BUZZER] calling buzzer_set_pattern(%d)\n", (int)p); buzzer_set_pattern(p); + printf("[TEST BUZZER] buzzer_set_pattern returned — building ack\n"); char ack[48]; snprintf(ack, sizeof(ack), "TEST_ACK BUZZER %s OK", pat); - test_reply(ack); + printf("[TEST BUZZER] calling bt_uart_send_json\n"); + bt_uart_send_json(ack); + printf("[TEST BUZZER] bt_uart_send_json returned — printing reply\n"); + printf("[TEST] reply: %s\n", ack); + printf("[TEST BUZZER] done\n"); } else if (strncmp(cmd, "TEST_ALL", 8) == 0) { if (s_test_all_running) { test_reply("TEST_ERR ALL_ALREADY_RUNNING"); return; } int obs = TEST_OBS_DEFAULT_SEC;