feat(upload): update OOB upload URL format and make CAN speeds INI-configurable

- Change upload URL path: golf.cgi -> golf-golface.cgi
- Add upload_dev INI key (1=dev, appends &dev=1 to URL)
- Change query params: ?filename= -> ?did={device_id}&vid={event_id}
- Add event_recorder_init params: device_id, dev_mode, speed_normal/alert/stop
- Make CAN speed limits configurable via [can] speed_normal/alert/stop in INI
  (replaces hardcoded SPEED_LIMIT_* macros with runtime static vars)
- Fix build_targz: use tar -C + mkdir -p for BusyBox compat;
  use open()+lseek() instead of stat() (struct stat ABI mismatch on target)
- Extend TEST_UPLOAD snapshot poll timeout: 5s -> 15s; same lseek fix
- Add BLE SET command: persist_ini_int() for runtime INI parameter update
- Fix app_header_init: elapsed_us long -> long long (overflow guard)
- Remove verbose debug printf from mcp2515 reset/send paths
- can_bus: wrap CTL log printf in #if 1 for easy toggle
This commit is contained in:
miketsai 2026-07-11 18:01:21 +08:00
parent 83e2256192
commit 2081c7b1f5
7 changed files with 299 additions and 82 deletions

View File

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

View File

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

View File

@ -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) {

View File

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

View File

@ -22,6 +22,7 @@
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/time.h>
@ -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 /* <20><><EFBFBD>`<60><>p */
#define SPEED_LIMIT_ALERT 35 /* <20><>a/ĵ<><C4B5> (<28><><EFBFBD><EFBFBD><EFBFBD>a level <20>Τ@) */
#define SPEED_LIMIT_STOP 10 /* <20>I<EFBFBD><49>/<2F><><EFBFBD> */
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);
/* 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, (long)_st.st_size);
printf("[EVT] created %s (%ld bytes)\n", out_path, _sz);
}
}
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) {
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, (long)_st.st_size, _i + 1);
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 1255
* speed_alert 1255
* speed_stop 1255
* 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);
}

View File

@ -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 --- */

View File

@ -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; i<N_TXBUFFERS; i++) {
//printf("i : %d\n",i);
const struct TXBn_REGS *txbuf = &TXB[txBuffers[i]];
uint8_t ctrlval = mcp2515_read_register_once(mcp2515_device, txbuf->CTRL);
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;i<data_length;i++)
{
printf("0x%x ",data[i]);
}
printf("\n");
const struct TXBn_REGS *txbuf = &TXB[txbn];
uint8_t data1[13];
@ -1097,7 +1080,7 @@ int mcp2515_sendMessageT(mcp2515_dev *mcp2515_device, const TXBn txbn, uint32_t
uint8_t ctrl = mcp2515_read_register_once(mcp2515_device,txbuf->CTRL);
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);