proto(V1.05): variation 由 2B无符号 扩展为 3B有符号
背景: variation 是遥测量, 用于离线跟踪分析车检器算法。原 2B 无符号 存在两个缺陷: (1)CAPVD域量级~131072, 大车全覆盖时偏差可超65535而回绕, 污染数据; (2)绝对值丢失方向, 分不清'车进入'与'反向漂移'。 改动 (三端联动, 同版本发布): - 协议 DLD960Loop_串口通信协议.md: 变化量 2B->3B有符号补码, 定义 variation=Origin-CAPVD (正=车/裕量, 负=反向漂移); 每单元11->12B, Len 47->51; 补符号扩展说明; 示例报文重算(XOR=FE SUM=38); 修订记录V1.05 - vd960Loop main.c: 组包 uint32->int32, Origin-CAPVD, 3B LE, +-2^23饱和防回绕 - vd960DBN loop_uart_proto.h: variation uint16->int32 - vd960DBN loop_uart_proto.c: 步长11->12, data_len/11->/12, misc偏移右移1B, variation 3B解码+bit23符号扩展 - vd960DBN iot_mqtt_srv.c: fast_mode 阈值判断改 abs(variation)>=10, 正负变化都加速 验证: 本地 gcc 隔离单测 编解码往返/符号扩展/饱和/方向语义/fast_mode 全通过; 大车 diff=100000 旧版回绕34464 新版正确保留。字节账: 帧56B < Loop缓冲64B < DBN缓冲512B < MSS576, 均不溢出。整体固件编译需在 Keil/MounRiver 侧完成。
This commit is contained in:
@@ -97,8 +97,9 @@ typedef struct {
|
||||
uint8_t loop_state : 1; // 0=正常, 1=断开
|
||||
uint8_t car_state : 1; // 0=无车, 1=有车
|
||||
uint8_t misc_type : 2; // 0=时间量, 1=断开次数, 2=车流量, 3=继电器输出次数
|
||||
uint32_t freq; // 频率 (3 bytes, little-endian)
|
||||
uint16_t variation; // 变化量 (2 bytes, little-endian)
|
||||
uint32_t freq; // 频率 (3 bytes, little-endian, 无符号)
|
||||
int32_t variation; // 变化量 (3 bytes, little-endian, 有符号补码) — V1.05
|
||||
// = Origin - CAPVD; 正=当前值低于基线(车/裕量), 负=反向漂移
|
||||
union {
|
||||
uint32_t passtime_ms; // 通过时间/车间距, 50ms单位 (misc_type=0)
|
||||
uint32_t cut_amount; // 线圈断开次数 (misc_type=1)
|
||||
|
||||
@@ -412,7 +412,10 @@ void iot_mqtt_publish_sensor(void) {
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < _cached_sr.coil_count; i++) {
|
||||
if (_cached_sr.coils[i].variation >= IOT_MQTT_VARIATION_THRESHOLD) {
|
||||
// variation 为有符号(V1.05): 正=车/裕量, 负=反向漂移, 两向显著变化都加速
|
||||
int32_t v = _cached_sr.coils[i].variation;
|
||||
int32_t av = (v >= 0) ? v : -v;
|
||||
if (av >= IOT_MQTT_VARIATION_THRESHOLD) {
|
||||
fast_mode = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -376,12 +376,12 @@ int lup_parse_set_param_resp(const uint8_t *pkg, uint16_t len, uint8_t *success)
|
||||
/*
|
||||
* Parse 0xC0/0x0C — 多路线圈传感信息
|
||||
*
|
||||
* 每路线圈数据单元 = 11 bytes:
|
||||
* 每路线圈数据单元 = 12 bytes (V1.05):
|
||||
* [0] 配置1: freq_level(2) | Direction(1) | freq_type(1) | sens(4)
|
||||
* [1] 评估条件: condition(4) | loop_state(1) | car_state(1) | misc_type(2)
|
||||
* [2-4] 频率 (3 bytes, LE)
|
||||
* [5-6] 变化量 (2 bytes, LE)
|
||||
* [7-10] 杂项 (4 bytes)
|
||||
* [2-4] 频率 (3 bytes, LE, 无符号)
|
||||
* [5-7] 变化量 (3 bytes, LE, 有符号补码, = Origin - CAPVD)
|
||||
* [8-11] 杂项 (4 bytes)
|
||||
*/
|
||||
int lup_parse_sensor_report(const uint8_t *pkg, uint16_t len, LUP_SensorReport *report)
|
||||
{
|
||||
@@ -397,17 +397,17 @@ int lup_parse_sensor_report(const uint8_t *pkg, uint16_t len, LUP_SensorReport *
|
||||
report->sub_amount = (sub_pkg >> 4) & 0x0F;
|
||||
report->sub_sequence = sub_pkg & 0x0F;
|
||||
|
||||
// 计算线圈数: Value = sensType(1) + SubPkgFlag(1) + coil_count * 11
|
||||
// 计算线圈数: Value = sensType(1) + SubPkgFlag(1) + coil_count * 12
|
||||
uint16_t val_len = pkg[2]; // LEN field
|
||||
uint16_t data_offset = 6; // 跳过 7F + Addr + LEN + CMD + SensType + SubPkgFlag
|
||||
uint16_t data_len = val_len - 2; // 减去 SensType + SubPkgFlag
|
||||
|
||||
uint8_t coil_count = data_len / 11;
|
||||
uint8_t coil_count = data_len / 12;
|
||||
if (coil_count > LUP_COIL_COUNT) coil_count = LUP_COIL_COUNT;
|
||||
report->coil_count = coil_count;
|
||||
|
||||
for (i = 0; i < coil_count; i++) {
|
||||
const uint8_t *c = pkg + data_offset + i * 11;
|
||||
const uint8_t *c = pkg + data_offset + i * 12;
|
||||
|
||||
LUP_CoilSensor *cs = &report->coils[i];
|
||||
cs->freq_level = (c[0] >> 6) & 0x03;
|
||||
@@ -421,9 +421,15 @@ int lup_parse_sensor_report(const uint8_t *pkg, uint16_t len, LUP_SensorReport *
|
||||
cs->misc_type = c[1] & 0x03;
|
||||
|
||||
cs->freq = c[2] | ((uint32_t)c[3] << 8) | ((uint32_t)c[4] << 16);
|
||||
cs->variation = c[5] | ((uint16_t)c[6] << 8);
|
||||
cs->misc.passtime_ms = c[7] | ((uint32_t)c[8] << 8)
|
||||
| ((uint32_t)c[9] << 16) | ((uint32_t)c[10] << 24);
|
||||
|
||||
// 变化量 3B 有符号 (LE) — 读入后须符号扩展 bit23
|
||||
{
|
||||
int32_t v = c[5] | ((int32_t)c[6] << 8) | ((int32_t)c[7] << 16);
|
||||
if (v & 0x800000) v |= (int32_t)0xFF000000;
|
||||
cs->variation = v;
|
||||
}
|
||||
cs->misc.passtime_ms = c[8] | ((uint32_t)c[9] << 8)
|
||||
| ((uint32_t)c[10] << 16) | ((uint32_t)c[11] << 24);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user