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.
This commit is contained in:
miketsai 2026-06-14 13:38:38 +08:00
parent 953b7a348a
commit 0d924d139c

View File

@ -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;