diff --git a/include/host_stream/event_recorder.h b/include/host_stream/event_recorder.h index 686a17b..f26b547 100644 --- a/include/host_stream/event_recorder.h +++ b/include/host_stream/event_recorder.h @@ -29,7 +29,10 @@ void event_recorder_init(const char *upload_url, int upload_delay_ms, int enable, const char *device_id, - int dev_mode); + int dev_mode, + int speed_normal, + int speed_alert, + int speed_stop); /* Drive the state machine — call from app_header_recv_inference. */ void event_recorder_update(const stdc_analysis_t *ana); diff --git a/ini/host_stream.ini b/ini/host_stream.ini index 2bafb03..e46adc6 100644 --- a/ini/host_stream.ini +++ b/ini/host_stream.ini @@ -24,7 +24,7 @@ SegOverlayEnable = 0 # 0: outline only, 1: also paint per-class colour ov OnlyPerson = 1 # only draw person bounding box when DrawBoxEnable #(so far for yolo only, JobId = 11) DrawOnResize = 0; # If InferenceStream is 0. This setting needs to be enabled. The box will be drawn on all resize streams. -verbose_log = 0 # 0: quiet (warnings only, ~30B/s), 1: per-frame class ratios every 20 frames (~1KB/s). Toggle from web UI. +verbose_log = 1 # 0: quiet (warnings only, ~30B/s), 1: per-frame class ratios every 20 frames (~1KB/s). Toggle from web UI. NnmSource = 0 # 0: run host_stream independently, 1: run with streamer ssm_name = "vsrc_ssm_ifp_0" # If NnmSource is 1. This setting needs to be set. The name is automaticlly create by streamer. @@ -112,3 +112,6 @@ enable = 1 # 1: enable CAN bus output; 0: disabled spidev = /dev/spidev1.0 # SPI device path for MCP2515 speed_kbps = 250 # CAN bus speed: 125 / 250 / 500 / 1000 kbps can_id = 0x100 # 11-bit standard frame ID for outbound event frames +speed_normal = 240 # CAN speed command: normal driving +speed_alert = 35 # CAN speed command: slow/alert (person or obstacle detected) +speed_stop = 10 # CAN speed command: stop/emergency diff --git a/src/host_stream/app_header_init.c b/src/host_stream/app_header_init.c index 46fb8a4..657a95c 100644 --- a/src/host_stream/app_header_init.c +++ b/src/host_stream/app_header_init.c @@ -525,9 +525,9 @@ int app_header_recv_inference(uint32_t buf_addr, bool *bl_run_next_inference) static struct timeval s_last_log = {0, 0}; struct timeval now; gettimeofday(&now, NULL); - long elapsed_us = (now.tv_sec - s_last_log.tv_sec) * 1000000L - + (now.tv_usec - s_last_log.tv_usec); - if (elapsed_us >= 1000000L) { + long long elapsed_us = (long long)(now.tv_sec - s_last_log.tv_sec) * 1000000LL + + (long long)(now.tv_usec - s_last_log.tv_usec); + if (elapsed_us >= 1000000LL) { s_last_log = now; log_trim_if_needed(); /* keep /tmp/fw.log under LOG_MAX_BYTES */ if (g_verbose_log) { diff --git a/src/host_stream/can_bus.c b/src/host_stream/can_bus.c index dffcdb2..a0e32e8 100644 --- a/src/host_stream/can_bus.c +++ b/src/host_stream/can_bus.c @@ -671,12 +671,13 @@ void can_bus_send_control_cmd(const can_ctrl_cmd_t *ctrl) frame[6] = (ctrl->led_enable & 1); frame[7] = (ctrl->led_r & 1) | ((ctrl->led_l & 1) << 7); rc = send_one_frame_with_retry(s_ctl_can_id, frame, 8); +#if 1 if (rc == ERROR_OK) { - printf("[CAN-CTL] tx id=0x%03X dlc=8 data=[0x%02X 0x%02X 00 00 00 00 0x%02X 0x%02X]\n", - s_ctl_can_id, frame[0], frame[1], frame[6], frame[7]); + printf("[CAN-CTL] tx id=0x%03X dlc=8 data=[0x%02X 0x%02X 00 00 00 00 0x%02X 0x%02X]\n",s_ctl_can_id, frame[0], frame[1], frame[6], frame[7]); } else { printf("[CAN-CTL] tx failed (speed=%u rc=%d)\n", ctrl->speed, rc); } +#endif } void can_bus_close(void) diff --git a/src/host_stream/event_recorder.c b/src/host_stream/event_recorder.c index a085f91..07bff47 100644 --- a/src/host_stream/event_recorder.c +++ b/src/host_stream/event_recorder.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,10 @@ /* ── External (from kdp2_host_stream.c) ──────────────────────────────────── */ extern VMF_VSRC_HANDLE_T *g_ptVsrcHandle; +/* ── External globals settable via BLE SET command ───────────────────────── */ +extern unsigned int g_dwSegOverlayEnable; /* defined in kp_firmware.c */ +extern unsigned int g_verbose_log; /* defined in kp_firmware.c */ + /* ── Speed control via MsgBroker ─────────────────────────────────────────── */ /* Must be defined before any caller (grass state machine, single-shot). */ static int msg_send(const char *fifo, @@ -112,15 +117,16 @@ static int s_up_port = 80; static char s_up_path[128] = "/api/golf-golface.cgi"; static char s_device_id[64] = ""; static int s_upload_dev = 0; +static char s_ini_path[256] = "./ini/host_stream.ini"; /* for SET → sed persistence */ static char s_sd_path[256] = "/tmp/sdcard/events"; static long long s_sd_max_bytes = (long long)7 * 1024 * 1024 * 1024; static int s_upload_delay_ms = 60000; static int s_enabled = 0; -#define SPEED_LIMIT_NORMAL 240//255 /* ���`��p */ -#define SPEED_LIMIT_ALERT 35 /* ��a/ĵ�� (�����a level �Τ@) */ -#define SPEED_LIMIT_STOP 10 /* �I��/��� */ +static uint8_t s_speed_normal = 240; /* normal driving — configurable via [can] speed_normal */ +static uint8_t s_speed_alert = 35; /* slow/alert — configurable via [can] speed_alert */ +static uint8_t s_speed_stop = 10; /* stop/emergency — configurable via [can] speed_stop */ /* Speed levels sent via MsgBroker → CAN bus process. * To tune: adjust the numbers here only — no logic changes needed. @@ -361,23 +367,36 @@ static void build_targz(const char *work_dir, const char *event_id, strftime(ts, sizeof(ts), "%Y%m%d_%H%M%S", t); snprintf(out_path, out_n, "%s/event_%s_%s.tar.gz", s_sd_path, event_id, ts); - mkdir(s_sd_path, 0755); char cmd[768]; + /* BusyBox v1.27.2 tar does NOT support -z flag (no gzip built-in). + * Use explicit pipe to /bin/gzip instead. + * mkdir -p creates the sd_path in case it does not yet exist. */ snprintf(cmd, sizeof(cmd), - "(cd '%s' && tar cf - . 2>>/tmp/fw.log) | gzip -c > '%s'", - work_dir, out_path); + "mkdir -p '%s' && tar cf - -C '%s' . 2>>/tmp/fw.log | /bin/gzip -c > '%s'", + s_sd_path, work_dir, out_path); + printf("[EVT] build_targz: work_dir=%s sd=%s\n", work_dir, s_sd_path); + printf("[EVT] build_targz: cmd=%s\n", cmd); + fflush(stdout); int sys_rc = system(cmd); sync(); - struct stat _st; - if (stat(out_path, &_st) != 0) { - printf("[EVT] tar/gzip failed (shell rc=%d) — file not created\n", sys_rc); - out_path[0] = '\0'; - return; + /* stat() st_size is unreliable on this target (struct stat ABI mismatch). + * Use open()+lseek(SEEK_END) to obtain the true file size. */ + { + int _fd = open(out_path, O_RDONLY); + long _sz = (_fd >= 0) ? (long)lseek(_fd, 0, SEEK_END) : -1L; + if (_fd >= 0) close(_fd); + if (_sz <= 0) { + printf("[EVT] tar/gzip: empty/missing output (shell rc=%d lseek=%ld) — treating as failed\n", + sys_rc, _sz); + fflush(stdout); + out_path[0] = '\0'; + return; + } + printf("[EVT] created %s (%ld bytes)\n", out_path, _sz); } - printf("[EVT] created %s (%ld bytes)\n", out_path, (long)_st.st_size); } typedef struct { char path[320]; time_t mtime; } FileEntry; @@ -470,7 +489,7 @@ static void test_mode_exit_internal(const char *reason) { g_test_mode = 0; s_test_mode_entered = 0; - can_ctrl_cmd_t ctrl = { .speed = SPEED_LIMIT_NORMAL, + can_ctrl_cmd_t ctrl = { .speed = s_speed_normal, .led_enable = 0, .led_r = 0, .led_l = 0, .keepalive_interval_ms = 0 }; can_bus_send_control_cmd(&ctrl); @@ -567,12 +586,12 @@ 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); 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_can_event("VIOLATION", 1, s_speed_alert); sleep(obs); + test_can_event("VIOLATION", 0, s_speed_normal); sleep(3); + test_can_event("COLLISION", 1, s_speed_stop); sleep(obs); + test_can_event("COLLISION", 0, s_speed_normal); sleep(3); + test_can_event("ALERT", 1, s_speed_alert); sleep(obs); + test_can_event("ALERT", 0, s_speed_normal); sleep(3); test_reply("TEST_CAN_ALL_DONE"); test_mode_exit_internal("CAN_ALL complete"); s_test_all_running = 0; @@ -627,22 +646,36 @@ static void *test_upload_thread(void *arg) /* Request one JPEG snapshot from the VMF thread */ request_snap(snap_name, work_dir, event_id, evt_type, 1, 0); - /* Poll up to 5 s (50 × 100 ms) — stop as soon as file arrives */ + /* Poll up to 15 s (150 × 100 ms) — stop as soon as file arrives. + * Inference submit happens every ~30 frames at ~7 fps (~4.3 s), + * plus JPEGEnc init time; 15 s gives ample margin. */ char snap_path[320]; snprintf(snap_path, sizeof(snap_path), "%s/%s", work_dir, snap_name); - struct stat _st; + /* stat() st_size is unreliable (struct stat ABI mismatch): use lseek instead. */ int has_snap = 0; - for (int _i = 0; _i < 50; _i++) { + for (int _i = 0; _i < 150; _i++) { usleep(100000); /* 100 ms */ - if (stat(snap_path, &_st) == 0 && _st.st_size > 0) { - has_snap = 1; - printf("[TEST] upload: snapshot %s OK (%ld bytes, waited %d00ms)\n", - snap_path, (long)_st.st_size, _i + 1); - break; + int _pfd = open(snap_path, O_RDONLY); + if (_pfd >= 0) { + long _psz = (long)lseek(_pfd, 0, SEEK_END); + close(_pfd); + if (_psz > 0) { + has_snap = 1; + printf("[TEST] upload: snapshot %s OK (%ld bytes, waited %d00ms)\n", + snap_path, _psz, _i + 1); + fflush(stdout); + break; + } } } - if (!has_snap) - printf("[TEST] upload: snapshot %s missing after 5s\n", snap_path); + if (!has_snap) { + int _pfd2 = open(snap_path, O_RDONLY); + long _psz2 = (_pfd2 >= 0) ? (long)lseek(_pfd2, 0, SEEK_END) : -1L; + if (_pfd2 >= 0) close(_pfd2); + printf("[TEST] upload: snapshot %s missing after 15s (lseek=%ld)\n", + snap_path, _psz2); + fflush(stdout); + } /* Write event.json */ char imgs[4][64]; @@ -698,12 +731,12 @@ static void *test_all_thread(void *arg) /* Group 2: CAN only */ test_reply("TEST_ALL_CAN_GROUP_START"); - 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_can_event("VIOLATION", 1, s_speed_alert); sleep(obs); + test_can_event("VIOLATION", 0, s_speed_normal); sleep(3); + test_can_event("COLLISION", 1, s_speed_stop); sleep(obs); + test_can_event("COLLISION", 0, s_speed_normal); sleep(3); + test_can_event("ALERT", 1, s_speed_alert); sleep(obs); + test_can_event("ALERT", 0, s_speed_normal); sleep(3); test_reply("TEST_ALL_CAN_GROUP_DONE"); sleep(3); @@ -721,6 +754,165 @@ static void *test_all_thread(void *arg) return NULL; } +/* ── BLE SET command: runtime INI parameter update ───────────────────────── */ +/* Persist an integer value to the INI file using line-by-line temp-file I/O. + * Avoids system()/fork() (SIGCHLD hang) and large stack buffers. */ +static void persist_ini_int(const char *ini_key, int val) +{ + printf("[SET] persist_ini_int: key=%s val=%d path=%s\n", ini_key, val, s_ini_path); + fflush(stdout); + + /* Write new content to a temp file alongside the INI */ + char tmp_path[300]; + snprintf(tmp_path, sizeof(tmp_path), "%s.tmp", s_ini_path); + + FILE *fin = fopen(s_ini_path, "r"); + if (!fin) { + printf("[SET] WARNING: cannot open %s\n", s_ini_path); + fflush(stdout); + return; + } + FILE *fout = fopen(tmp_path, "w"); + if (!fout) { + fclose(fin); + printf("[SET] WARNING: cannot create %s\n", tmp_path); + fflush(stdout); + return; + } + + int key_len = (int)strlen(ini_key); + char line[512]; + int found = 0; + + while (fgets(line, sizeof(line), fin)) { + if (!found && strncmp(line, ini_key, (size_t)key_len) == 0) { + const char *p = line + key_len; + while (*p == ' ' || *p == '\t') p++; + if (*p == '=') { + fprintf(fout, "%s = %d\n", ini_key, val); + found = 1; + continue; /* skip original line */ + } + } + fputs(line, fout); + } + fclose(fin); + fclose(fout); + + if (!found) { + printf("[SET] WARNING: key=%s not found in %s\n", ini_key, s_ini_path); + fflush(stdout); + return; + } + + if (rename(tmp_path, s_ini_path) != 0) { + printf("[SET] WARNING: rename failed for %s\n", tmp_path); + fflush(stdout); + return; + } + + printf("[SET] persisted: %s = %d\n", ini_key, val); + fflush(stdout); +} + +/* Handle "SET key=value" command — works outside test mode. + * cmd must already be uppercased (as provided by handle_test_cmd). + * Supported keys (case-insensitive from sender): + * SegOverlayEnable — 0/1 + * speed_normal — 1–255 + * speed_alert — 1–255 + * speed_stop — 1–255 + * verbose_log — 0/1 + */ +static void handle_set_cmd(const char *cmd) +{ + /* cmd is already uppercased; format: "SET KEY=VALUE" */ + const char *p = cmd + 4; /* skip "SET " */ + while (*p == ' ') p++; + + char key[64] = "", valstr[32] = ""; + printf("[SET] parsing: [%s]\n", p); + fflush(stdout); + /* Manual parse: "KEY VALUE" (space-separated) */ + const char *sp = strchr(p, ' '); + if (!sp || sp == p) { + bt_uart_send_json("SET_NACK BAD_FORMAT"); + printf("[SET] bad format (no space): [%s]\n", cmd); + fflush(stdout); + return; + } + size_t klen = (size_t)(sp - p); + if (klen >= sizeof(key)) klen = sizeof(key) - 1; + memcpy(key, p, klen); + key[klen] = '\0'; + while (*sp == ' ') sp++; /* skip extra spaces */ + strncpy(valstr, sp, sizeof(valstr) - 1); + valstr[sizeof(valstr) - 1] = '\0'; + /* trim trailing whitespace/CR/LF from valstr */ + { + char *end = valstr + strlen(valstr); + while (end > valstr && (*(end-1) == '\r' || *(end-1) == '\n' || *(end-1) == ' ')) + *(--end) = '\0'; + } + printf("[SET] key=[%s] val=[%s]\n", key, valstr); + fflush(stdout); + if (key[0] == '\0' || valstr[0] == '\0') { + bt_uart_send_json("SET_NACK BAD_FORMAT"); + fflush(stdout); + return; + } + + int val = atoi(valstr); + printf("[SET] dispatch key=[%s] val=%d\n", key, val); + fflush(stdout); + char ack[96]; + + if (strcmp(key, "SEGOVERLAYENABLE") == 0) { + int v = val ? 1 : 0; + printf("[SET] writing g_dwSegOverlayEnable=%d\n", v); + fflush(stdout); + g_dwSegOverlayEnable = (unsigned int)v; + printf("[SET] g_dwSegOverlayEnable OK\n"); + fflush(stdout); + persist_ini_int("SegOverlayEnable", v); + snprintf(ack, sizeof(ack), "SET_ACK SegOverlayEnable=%d", v); + + } else if (strcmp(key, "SPEED_NORMAL") == 0) { + if (val < 1 || val > 255) { bt_uart_send_json("SET_NACK SPEED_NORMAL OUT_OF_RANGE"); return; } + s_speed_normal = (uint8_t)val; + persist_ini_int("speed_normal", val); + snprintf(ack, sizeof(ack), "SET_ACK speed_normal=%d", val); + + } else if (strcmp(key, "SPEED_ALERT") == 0) { + if (val < 1 || val > 255) { bt_uart_send_json("SET_NACK SPEED_ALERT OUT_OF_RANGE"); return; } + s_speed_alert = (uint8_t)val; + persist_ini_int("speed_alert", val); + snprintf(ack, sizeof(ack), "SET_ACK speed_alert=%d", val); + + } else if (strcmp(key, "SPEED_STOP") == 0) { + if (val < 1 || val > 255) { bt_uart_send_json("SET_NACK SPEED_STOP OUT_OF_RANGE"); return; } + s_speed_stop = (uint8_t)val; + persist_ini_int("speed_stop", val); + snprintf(ack, sizeof(ack), "SET_ACK speed_stop=%d", val); + + } else if (strcmp(key, "VERBOSE_LOG") == 0) { + int v = val ? 1 : 0; + g_verbose_log = (unsigned int)v; + persist_ini_int("verbose_log", v); + snprintf(ack, sizeof(ack), "SET_ACK verbose_log=%d", v); + + } else { + snprintf(ack, sizeof(ack), "SET_NACK UNKNOWN_KEY %.48s", key); + bt_uart_send_json(ack); + printf("[SET] %s\n", ack); + return; + } + + bt_uart_send_json(ack); + printf("[SET] %s\n", ack); + fflush(stdout); +} + static void handle_test_cmd(const char *raw) { char cmd[128]; @@ -744,6 +936,11 @@ static void handle_test_cmd(const char *raw) test_mode_exit_internal("user request"); return; } + /* SET works regardless of test mode — runtime parameter update */ + if (strncmp(cmd, "SET ", 4) == 0) { + handle_set_cmd(cmd); + return; + } if (!g_test_mode) { test_reply("TEST_ERR NOT_IN_TEST_MODE"); return; } if (strncmp(cmd, "TEST_BLE_ALL", 12) == 0) { @@ -771,13 +968,13 @@ 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); + test_can_event("VIOLATION", lv, lv ? s_speed_alert : s_speed_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); + test_can_event("COLLISION", lv, lv ? s_speed_stop : s_speed_normal); } else if (strncmp(cmd, "TEST_CAN ALERT", 14) == 0) { int lv = atoi(cmd + 14); - test_can_event("ALERT", lv, lv ? SPEED_LIMIT_ALERT : SPEED_LIMIT_NORMAL); + test_can_event("ALERT", lv, lv ? s_speed_alert : s_speed_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; @@ -830,7 +1027,7 @@ void fire_collision_warning(int level, const char *type) "\"content\":{\"level\":%d,\"type\":%s}}", level, type_str); { - uint8_t speed = level ? SPEED_LIMIT_STOP : SPEED_LIMIT_NORMAL; + uint8_t speed = level ? s_speed_stop : s_speed_normal; can_ctrl_cmd_t ctrl = { .speed = speed, .led_enable = 0, .led_r = 0, .led_l = 0, .keepalive_interval_ms = 0 }; can_bus_send_control_cmd(&ctrl); @@ -862,7 +1059,7 @@ static void fire_alert(int left_level, const char *left_type, "\"right\":{\"level\":%d,\"type\":%s}}}", left_level, l_str, right_level, r_str); { - uint8_t speed = (left_level || right_level) ? SPEED_LIMIT_ALERT : SPEED_LIMIT_NORMAL; + uint8_t speed = (left_level || right_level) ? s_speed_alert : s_speed_normal; can_ctrl_cmd_t ctrl = { .speed = speed, .led_enable = 0, .led_r = 0, .led_l = 0, .keepalive_interval_ms = 0 }; can_bus_send_control_cmd(&ctrl); @@ -995,9 +1192,17 @@ static void save_jpeg(const char *path, const uint8_t *buf, int size) printf("[EVT] save_jpeg: cannot open %s\n", path); return; } - fwrite(buf, 1, (size_t)size, f); - fclose(f); - printf("[EVT] saved %s (%d bytes)\n", path, size); + size_t written = fwrite(buf, 1, (size_t)size, f); + int ferr = ferror(f); + int fcrc = fclose(f); + if (fcrc != 0 || ferr) { + printf("[EVT] save_jpeg: write error %s (written=%zu ferr=%d fcrc=%d errno=%d)\n", + path, written, ferr, fcrc, errno); + fflush(stdout); + return; + } + printf("[EVT] saved %s (requested=%d written=%zu)\n", path, size, written); + fflush(stdout); } /* ═══════════════════════════════════════════════════════════════════════════ @@ -1046,7 +1251,10 @@ void event_recorder_init(const char *upload_url, int upload_delay_ms, int enable, const char *device_id, - int dev_mode) + int dev_mode, + int speed_normal, + int speed_alert, + int speed_stop) { s_enabled = enable; s_upload_delay_ms = (upload_delay_ms >= 0) ? upload_delay_ms : 60000; @@ -1060,11 +1268,16 @@ void event_recorder_init(const char *upload_url, if (device_id && *device_id) snprintf(s_device_id, sizeof(s_device_id), "%s", device_id); s_upload_dev = dev_mode; - printf("[EVT] init: enable=%d ch_a=bt_uart ch_b=%s:%d%s did=%s dev=%d sd=%s max=%dMB delay=%dms\n", + if (speed_normal > 0) s_speed_normal = (uint8_t)speed_normal; + if (speed_alert > 0) s_speed_alert = (uint8_t)speed_alert; + if (speed_stop > 0) s_speed_stop = (uint8_t)speed_stop; + + printf("[EVT] init: enable=%d ch_a=bt_uart ch_b=%s:%d%s did=%s dev=%d sd=%s max=%dMB delay=%dms spd=%d/%d/%d\n", s_enabled, s_up_host, s_up_port, s_up_path, s_device_id, s_upload_dev, - s_sd_path, sd_max_mb, s_upload_delay_ms); + s_sd_path, sd_max_mb, s_upload_delay_ms, + s_speed_normal, s_speed_alert, s_speed_stop); bt_uart_set_extra_cmd_cb(handle_test_cmd); } @@ -1103,7 +1316,7 @@ void event_recorder_update(const stdc_analysis_t *ana) g_grass.state = GRASS_L1; pthread_mutex_unlock(&g_grass_mtx); grass_enter_level(1); - speed_val = SPEED_LIMIT_STOP; + speed_val = s_speed_stop; msg_send("/tmp/canbus/c0/command.fifo", "host_stream", "setSpeed",&speed_val, sizeof(speed_val), 0); buzzer_set_pattern(BUZZER_PATTERN_GRASS); return; @@ -1118,13 +1331,13 @@ void event_recorder_update(const stdc_analysis_t *ana) g_grass.state = GRASS_L2; pthread_mutex_unlock(&g_grass_mtx); grass_enter_level(2); - speed_val = SPEED_LIMIT_STOP; + speed_val = s_speed_stop; msg_send("/tmp/canbus/c0/command.fifo", "host_stream", "setSpeed",&speed_val, sizeof(speed_val), 0); buzzer_set_pattern(BUZZER_PATTERN_GRASS); return; } } else { - speed_val = SPEED_LIMIT_NORMAL; + speed_val = s_speed_normal; msg_send("/tmp/canbus/c0/command.fifo", "host_stream", "setSpeed",&speed_val, sizeof(speed_val), 0); if (!g_last_collision_warning && !g_last_left_alert && !g_last_right_alert) buzzer_set_pattern(BUZZER_PATTERN_OFF); @@ -1150,12 +1363,12 @@ void event_recorder_update(const stdc_analysis_t *ana) g_grass.state = GRASS_L3; pthread_mutex_unlock(&g_grass_mtx); grass_enter_level(3); - speed_val = SPEED_LIMIT_STOP; + speed_val = s_speed_stop; msg_send("/tmp/canbus/c0/command.fifo", "host_stream", "setSpeed",&speed_val, sizeof(speed_val), 0); return; } } else { - speed_val = SPEED_LIMIT_NORMAL; + speed_val = s_speed_normal; msg_send("/tmp/canbus/c0/command.fifo", "host_stream", "setSpeed",&speed_val, sizeof(speed_val), 0); if (!g_last_collision_warning && !g_last_left_alert && !g_last_right_alert) buzzer_set_pattern(BUZZER_PATTERN_OFF); @@ -1176,11 +1389,11 @@ void event_recorder_update(const stdc_analysis_t *ana) case GRASS_L3: if (on_grass) { gettimeofday(&g_grass.t_last_active, NULL); - speed_val = SPEED_LIMIT_STOP; + speed_val = s_speed_stop; msg_send("/tmp/canbus/c0/command.fifo", "host_stream", "setSpeed",&speed_val, sizeof(speed_val), 0); buzzer_set_pattern(BUZZER_PATTERN_GRASS); } else { - speed_val = SPEED_LIMIT_NORMAL; + speed_val = s_speed_normal; msg_send("/tmp/canbus/c0/command.fifo", "host_stream", "setSpeed",&speed_val, sizeof(speed_val), 0); if (!g_last_collision_warning && !g_last_left_alert && !g_last_right_alert) buzzer_set_pattern(BUZZER_PATTERN_OFF); @@ -1202,7 +1415,7 @@ void event_recorder_update(const stdc_analysis_t *ana) /* Upload thread will reset to IDLE when done. * Keep sending SPEED_LEVEL_5 every frame until upload finishes * (keepalive in can_bus.c also maintains this every 200ms). */ - speed_val = SPEED_LIMIT_NORMAL; + speed_val = s_speed_normal; msg_send("/tmp/canbus/c0/command.fifo", "host_stream", "setSpeed",&speed_val, sizeof(speed_val), 0); if (!g_last_collision_warning && !g_last_left_alert && !g_last_right_alert) buzzer_set_pattern(BUZZER_PATTERN_OFF); @@ -1327,7 +1540,17 @@ void event_recorder_provide_frame(void) if (snap_ok) { char out_path[384]; snprintf(out_path, sizeof(out_path), "%s/%s", req.work_dir, req.filename); + printf("[EVT] snap: saving %s (%d bytes)\n", out_path, jpeg_size); + fflush(stdout); save_jpeg(out_path, jpeg, jpeg_size); + /* Immediate verify — use lseek (stat st_size unreliable: ABI mismatch) */ + { + int _vfd = open(out_path, O_RDONLY); + long _vsz = (_vfd >= 0) ? (long)lseek(_vfd, 0, SEEK_END) : -1L; + if (_vfd >= 0) close(_vfd); + printf("[EVT] snap: verify %s lseek=%ld\n", out_path, _vsz); + fflush(stdout); + } } else { printf("[EVT] snap: ProcessOneFrame failed (%d) — upload will proceed without image\n", jpeg_size); } diff --git a/src/host_stream/kp_firmware.c b/src/host_stream/kp_firmware.c index ef72389..a01045c 100644 --- a/src/host_stream/kp_firmware.c +++ b/src/host_stream/kp_firmware.c @@ -318,7 +318,11 @@ int loadConfig(HOST_STREAM_INIT_OPT_T* pHostStreamInit) printf("[BT] WARNING: sed INI update returned %d (%s)\n", rc, HOST_STREAM_CONFIG_PATH); } - event_recorder_init(ev_up, ev_sd, ev_max_mb, ev_delay, ev_enable, device_id, ev_dev); + int ev_spd_normal = iniparser_getint(ini, "can:speed_normal", 240); + int ev_spd_alert = iniparser_getint(ini, "can:speed_alert", 35); + int ev_spd_stop = iniparser_getint(ini, "can:speed_stop", 10); + event_recorder_init(ev_up, ev_sd, ev_max_mb, ev_delay, ev_enable, device_id, ev_dev, + ev_spd_normal, ev_spd_alert, ev_spd_stop); } /* --- [can] section: MCP2515 CAN bus via J15 SPI connector --- */ diff --git a/src/host_stream/mcp2515.c b/src/host_stream/mcp2515.c index ae30f9d..bb07e38 100644 --- a/src/host_stream/mcp2515.c +++ b/src/host_stream/mcp2515.c @@ -595,28 +595,22 @@ int mcp2515_reset(mcp2515_dev *mcp2515_device) // Set to configuration mode uint8_t zeros[14]; memset(zeros, 0, sizeof(zeros)); - printf("mcp2515 clean MCP_TXBXCTRL\n"); mcp2515_write_register(mcp2515_device,MCP_TXB0CTRL, zeros, 14); mcp2515_write_register(mcp2515_device,MCP_TXB1CTRL, zeros, 14); mcp2515_write_register(mcp2515_device,MCP_TXB2CTRL, zeros, 14); - printf("mcp2515 clean MCP_RXBXCTRL\n"); mcp2515_write_register_once(mcp2515_device,MCP_RXB0CTRL, 0); mcp2515_write_register_once(mcp2515_device,MCP_RXB1CTRL, 0); - printf("mcp2515 clean MCP_CANINTE\n"); mcp2515_write_register_once(mcp2515_device, MCP_CANINTE, CANINTF_RX0IF | CANINTF_RX1IF | CANINTF_ERRIF | CANINTF_MERRF); - printf("mcp2515 clean MCP_RXB0CTRL\n"); mcp2515_modify_bit(mcp2515_device, MCP_RXB0CTRL, RXBnCTRL_RXM_MASK | RXB0CTRL_BUKT | RXB0CTRL_FILHIT_MASK, RXBnCTRL_RXM_STDEXT | RXB0CTRL_BUKT | RXB0CTRL_FILHIT); - printf("mcp2515 clean MCP_RXB1CTRL\n"); mcp2515_modify_bit(mcp2515_device,MCP_RXB1CTRL, RXBnCTRL_RXM_MASK | RXB1CTRL_FILHIT_MASK, RXBnCTRL_RXM_STDEXT | RXB1CTRL_FILHIT); // clear filters and masks // do not filter any standard frames for RXF0 used by RXB0 // do not filter any extended frames for RXF1 used by RXB1 - printf("mcp2515 clean RXF\n"); RXF filters[] = {RXF0, RXF1, RXF2, RXF3, RXF4, RXF5}; int i=0; for (i=0; i<6; i++) { @@ -1027,22 +1021,18 @@ void mcp2515_modify_bit(mcp2515_dev *mcp2515_device, uint8_t register_address, u } int mcp2515_sendMessage(mcp2515_dev *mcp2515_device, uint32_t can_id, uint8_t* data, uint8_t data_length) { -//printf("%s: func:%s,line:%d \n", __FILE__, __func__,__LINE__); if (data_length > 8) { return ERROR_FAILTX; } TXBn txBuffers[N_TXBUFFERS] = {TXB0, TXB1, TXB2}; int i=0; for (i=0; iCTRL); if ( (ctrlval & TXB_TXREQ) == 0 ) { - printf("Send Message: %x\n",txbuf->CTRL); return mcp2515_sendMessageT(mcp2515_device,txBuffers[i], can_id, data, data_length); } } - //printf("%s: func:%s,line:%d \n", __FILE__, __func__,__LINE__); return ERROR_ALLTXBUSY; } @@ -1051,13 +1041,6 @@ int mcp2515_sendMessageT(mcp2515_dev *mcp2515_device, const TXBn txbn, uint32_t if (data_length > 8) { return ERROR_FAILTX; } - printf("%x %x ",can_id,data_length); - int i=0; - for(i=0;iCTRL); if ((ctrl & (TXB_ABTF | TXB_MLOA)) != 0) { - printf("ERROR\n"); + //printf("ERROR\n"); return ERROR_FAILTX; } @@ -1107,10 +1090,10 @@ int mcp2515_sendMessageT(mcp2515_dev *mcp2515_device, const TXBn txbn, uint32_t if ((ctrl & TXB_TXREQ) == 0) { if (saw_txerr) { - printf("ERROR\n"); + //printf("ERROR\n"); return ERROR_FAILTX; } - printf("OK\n"); + //printf("OK\n"); return ERROR_OK; } usleep(1000);