#include #include #include /* mock SnapRec (与 snapshot.h 一致, 64B) */ typedef struct { uint8_t magic; uint8_t len; uint8_t flags; uint8_t rsvd; uint32_t seq; uint32_t ts_ms; uint16_t boot_seq; uint16_t rsvd2; uint8_t coils[48]; } SnapRec; #define SNAP_COILS_MAX 4 #define SNAP_COIL_BYTES 12 int snap_rec_to_json(const SnapRec *r, char *buf, int buf_len) { int coil_count = (r->len > (SNAP_COILS_MAX * SNAP_COIL_BYTES)) ? SNAP_COILS_MAX : (r->len / SNAP_COIL_BYTES); if (coil_count < 0) coil_count = 0; int pos = snprintf(buf, buf_len, "{\"seq\":%lu,\"boot_seq\":%u,\"ts_ms\":%lu,\"coil_count\":%u,\"channels\":[", (unsigned long)r->seq, (unsigned)r->boot_seq, (unsigned long)r->ts_ms, (unsigned)coil_count); int c; for (c = 0; c < coil_count; c++) { const uint8_t *p = &r->coils[c * SNAP_COIL_BYTES]; uint8_t cfg = p[0]; uint8_t cond = p[1]; uint32_t freq = (uint32_t)p[2] | ((uint32_t)p[3] << 8) | ((uint32_t)p[4] << 16); int32_t variation = (int32_t)((uint32_t)p[5] | ((uint32_t)p[6] << 8) | ((uint32_t)p[7] << 16)); uint32_t misc = (uint32_t)p[8] | ((uint32_t)p[9] << 8) | ((uint32_t)p[10] << 16) | ((uint32_t)p[11] << 24); uint8_t freq_level = (cfg >> 6) & 0x03; uint8_t direction = (cfg >> 5) & 0x01; uint8_t freq_type = (cfg >> 4) & 0x01; uint8_t sensitivity = cfg & 0x0F; uint8_t condition = (cond >> 4) & 0x0F; uint8_t loop_state = (cond >> 3) & 0x01; /* 0=normal 1=cut */ uint8_t car_state = (cond >> 2) & 0x01; /* 0=nocar 1=car */ uint8_t misc_type = cond & 0x03; const char *fl = "high"; const char *mt = "time"; if (variation & 0x800000) variation |= (int32_t)0xFF000000; /* 3B sign extend */ if (freq_level == 1) fl = "mid_high"; else if (freq_level == 2) fl = "mid_low"; else if (freq_level == 3) fl = "low"; if (misc_type == 1) mt = "cut_count"; else if (misc_type == 2) mt = "flow_count"; else if (misc_type == 3) mt = "relay_count"; if (c > 0) pos += snprintf(buf + pos, buf_len - pos, ","); pos += snprintf(buf + pos, buf_len - pos, "{\"ch\":%u,\"freq_level\":\"%s\",\"direction\":%u,\"freq_type\":%u," "\"sensitivity\":%u,\"condition\":%u,\"loop_ok\":%s,\"has_car\":%s," "\"misc_type\":\"%s\",\"freq\":%lu,\"variation\":%ld,\"misc\":%lu}", (unsigned)(c + 1), fl, (unsigned)direction, (unsigned)freq_type, (unsigned)sensitivity, (unsigned)condition, loop_state ? "false" : "true", car_state ? "true" : "false", mt, (unsigned long)freq, (long)variation, (unsigned long)misc); } pos += snprintf(buf + pos, buf_len - pos, "]}"); return pos; } #define CHECK(cond) do { if (!(cond)) { printf("FAIL %s:%d: %s\n", __FILE__, __LINE__, #cond); fails++; } else { passes++; } } while (0) static int passes = 0, fails = 0; int main(void) { char buf[2048]; SnapRec r; /* 用例1: 单线圈, 高频(00)/触发/实时频率/灵敏度2, 正常无车, 时间量 freq=0x010F2A=69418, variation=+7, misc=0 */ memset(&r, 0, sizeof(r)); r.magic = 0xA6; r.len = 12; r.seq = 12345; r.ts_ms = 456789; r.boot_seq = 2; r.coils[0] = 0x12; /* freq_level=00 direction=0 freq_type=1 sens=0010 */ r.coils[1] = 0x00; /* condition=0 loop_state=0 car_state=0 misc_type=00 */ r.coils[2] = 0x2A; r.coils[3] = 0x0F; r.coils[4] = 0x01; /* 69418 */ r.coils[5] = 0x07; r.coils[6] = 0x00; r.coils[7] = 0x00; /* +7 */ r.coils[8] = 0x00; r.coils[9] = 0x00; r.coils[10] = 0x00; r.coils[11] = 0x00; snap_rec_to_json(&r, buf, sizeof(buf)); printf("case1: %s\n", buf); CHECK(strstr(buf, "\"seq\":12345") != NULL); CHECK(strstr(buf, "\"boot_seq\":2") != NULL); CHECK(strstr(buf, "\"ts_ms\":456789") != NULL); CHECK(strstr(buf, "\"coil_count\":1") != NULL); CHECK(strstr(buf, "\"ch\":1") != NULL); CHECK(strstr(buf, "\"freq_level\":\"high\"") != NULL); CHECK(strstr(buf, "\"direction\":0") != NULL); CHECK(strstr(buf, "\"freq_type\":1") != NULL); CHECK(strstr(buf, "\"sensitivity\":2") != NULL); CHECK(strstr(buf, "\"condition\":0") != NULL); CHECK(strstr(buf, "\"loop_ok\":true") != NULL); CHECK(strstr(buf, "\"has_car\":false") != NULL); CHECK(strstr(buf, "\"misc_type\":\"time\"") != NULL); CHECK(strstr(buf, "\"freq\":69418") != NULL); CHECK(strstr(buf, "\"variation\":7") != NULL); CHECK(strstr(buf, "\"misc\":0") != NULL); /* 用例2: 4线圈全量 + 负 variation + 低频 + relay_count + 有车/断开 ch1: 低频(11)/方向判别(1)/初始频率(0)/灵敏度0, condition=0xF, loop_state=1(断开), car_state=1(有车), misc_type=11(relay) freq=0x00C383=50051, variation=-10 (F6 FF FF), misc=128 */ memset(&r, 0, sizeof(r)); r.magic = 0xA6; r.len = 48; r.seq = 999; r.ts_ms = 1234; r.boot_seq = 3; r.coils[0] = 0xE8; /* 11 1 0 0000 */ r.coils[1] = 0xFF; /* 1111 1 1 11 */ r.coils[2] = 0x83; r.coils[3] = 0xC3; r.coils[4] = 0x00; /* 50051 */ r.coils[5] = 0xF6; r.coils[6] = 0xFF; r.coils[7] = 0xFF; /* -10 */ r.coils[8] = 0x80; r.coils[9] = 0x00; r.coils[10] = 0x00; r.coils[11] = 0x00; /* 128 */ /* ch2: 中高(01), 正常无车, cut_count */ r.coils[12] = 0x50; /* 01 0 1 0000 */ r.coils[13] = 0x01; /* 0000 0 0 01 */ r.coils[14] = 0x00; r.coils[15] = 0x02; r.coils[16] = 0x00; /* 512 */ r.coils[17] = 0x01; r.coils[18] = 0x00; r.coils[19] = 0x00; /* +1 */ /* ch3: 中低(10), flow_count */ r.coils[24] = 0xA0; /* 10 1 0 0000 */ r.coils[25] = 0x02; /* 0000 0 0 10 */ r.coils[26] = 0x00; r.coils[27] = 0x01; r.coils[28] = 0x00; /* 256 */ /* ch4: 高频, 空 */ snap_rec_to_json(&r, buf, sizeof(buf)); printf("case2: %s\n", buf); CHECK(strstr(buf, "\"coil_count\":4") != NULL); CHECK(strstr(buf, "\"freq_level\":\"low\"") != NULL); CHECK(strstr(buf, "\"direction\":1") != NULL); CHECK(strstr(buf, "\"freq_type\":0") != NULL); CHECK(strstr(buf, "\"sensitivity\":0") != NULL); CHECK(strstr(buf, "\"condition\":15") != NULL); CHECK(strstr(buf, "\"loop_ok\":false") != NULL); CHECK(strstr(buf, "\"has_car\":true") != NULL); CHECK(strstr(buf, "\"misc_type\":\"relay_count\"") != NULL); CHECK(strstr(buf, "\"freq\":50051") != NULL); CHECK(strstr(buf, "\"variation\":-10") != NULL); CHECK(strstr(buf, "\"misc\":128") != NULL); CHECK(strstr(buf, "\"freq_level\":\"mid_high\"") != NULL); CHECK(strstr(buf, "\"misc_type\":\"cut_count\"") != NULL); CHECK(strstr(buf, "\"freq_level\":\"mid_low\"") != NULL); CHECK(strstr(buf, "\"misc_type\":\"flow_count\"") != NULL); /* 用例3: len=0 边界 (空记录) */ memset(&r, 0, sizeof(r)); r.magic = 0xA6; r.len = 0; snap_rec_to_json(&r, buf, sizeof(buf)); printf("case3: %s\n", buf); CHECK(strstr(buf, "\"coil_count\":0") != NULL); CHECK(strstr(buf, "\"channels\":[]") != NULL); printf("\nPASS=%d FAIL=%d\n", passes, fails); return fails ? 1 : 0; }