Files
vd_960/vd960DBN/tests/test_report_cadence.c
T
wangfq a457b81916 feat(iot_mqtt): loop_data 上报调度升级三档 — car_state 沿立即上报
原双速率下进/出车沿最坏等 300ms 门控。改为三档:
- 立即档: 任一通道 car_state 翻转沿 → 直通间隔门控立即发布
- 快速档: |variation|>阈值 → 300ms (不变)
- 空闲档: 配置 interval, 默认 60s (不变)

要点:
- car_edge 优先级最高; 快照仍在门控后刷新, 同沿只触发一次立即档
- 防洪泛天然有界: Loop 事件帧最快 150ms/帧 且 car_state 为防抖后状态
- 协议 §5.2 补上报节奏说明; tests/test_report_cadence.c 8 组全过
2026-07-15 16:56:21 +08:00

79 lines
3.3 KiB
C

/* 隔离单测: 传感数据三档上报调度 (与 iot_mqtt_publish_sensor Step2/3 同构)
* 立即档: car_state 沿 → 直通门控
* 快速档: |variation|>10 → 300ms
* 空闲档: interval (测试用 60s)
*/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define THRESH 10
#define FAST_MS 300
#define IDLE_MS 60000 /* interval=60s */
#define NCOIL 4
typedef struct { int32_t variation; uint8_t car_state; } Coil;
static uint8_t last_car[NCOIL];
static uint32_t last_pub;
/* 返回 1=本轮发布 */
static int publish_step(uint32_t now, Coil *coils, int n) {
uint8_t fast_mode = 0, car_edge = 0; int i;
for (i = 0; i < n; i++) {
if (last_car[i] != coils[i].car_state) { car_edge = 1; break; }
int32_t v = coils[i].variation, av = (v>=0)?v:-v;
if (av > THRESH) fast_mode = 1;
}
uint32_t itv = (fast_mode || car_edge) ? FAST_MS : IDLE_MS;
if (!car_edge && last_pub != 0 && (now - last_pub) < itv) return 0;
last_pub = now;
for (i = 0; i < n; i++) last_car[i] = coils[i].car_state; /* 门控后刷新快照 */
return 1;
}
static int fails = 0;
#define CHECK(c,m) do{ if(!(c)){ printf("FAIL: %s\n", m); fails++; } }while(0)
int main(void) {
Coil coils[NCOIL]; memset(coils, 0, sizeof(coils));
memset(last_car, 0, sizeof(last_car)); last_pub = 0;
/* T1: 首发 (last_pub=0 直发) */
CHECK(publish_step(1000, coils, NCOIL) == 1, "T1 首发");
/* T2: 空闲档 — 平稳时 60s 内不发, 到点才发 */
CHECK(publish_step(1500, coils, NCOIL) == 0, "T2 空闲0.5s不发");
CHECK(publish_step(31000, coils, NCOIL) == 0, "T2 空闲30s不发");
CHECK(publish_step(61000, coils, NCOIL) == 1, "T2 空闲60s到点发");
/* T3: 立即档 — 进车沿, 距上次发布仅 50ms 也立即发 (旧版要等300ms) */
coils[1].car_state = 1; /* ch2 进车 */
CHECK(publish_step(61050, coils, NCOIL) == 1, "T3 进车沿距上次50ms仍立即发");
/* T4: 同一个沿不重复触发 — 快照已同步, 下一轮回到常规档 */
coils[1].variation = 53; /* 有车, variation高 → 快速档 */
CHECK(publish_step(61100, coils, NCOIL) == 0, "T4 沿已消费, 50ms后不再直通");
CHECK(publish_step(61350, coils, NCOIL) == 1, "T4 快速档300ms到点发");
/* T5: 快速档仍受 300ms 门控 (variation大但无沿) */
CHECK(publish_step(61500, coils, NCOIL) == 0, "T5 快速档150ms不发");
CHECK(publish_step(61650, coils, NCOIL) == 1, "T5 快速档300ms发");
/* T6: 出车沿同样立即 — 距上次仅 20ms */
coils[1].car_state = 0; coils[1].variation = 0;
CHECK(publish_step(61670, coils, NCOIL) == 1, "T6 出车沿20ms立即发");
/* T7: 出车后平稳 → 回落空闲档 */
CHECK(publish_step(61970, coils, NCOIL) == 0, "T7 平稳300ms不发(已是空闲档)");
CHECK(publish_step(121670, coils, NCOIL) == 1, "T7 空闲60s到点发");
/* T8: 多通道同帧翻转 → 一次立即发布覆盖全部 (单包含4通道) */
coils[0].car_state = 1; coils[2].car_state = 1;
CHECK(publish_step(121700, coils, NCOIL) == 1, "T8 双通道沿立即发");
CHECK(publish_step(121750, coils, NCOIL) == 0, "T8 快照已同步不重发");
printf(fails ? "\n== %d FAIL ==\n" : "\n== ALL PASS ==\n", fails);
return fails;
}