diff --git a/Doc/温湿度风扇_固件需求规格书.md b/Doc/温湿度风扇_固件需求规格书.md index 5714e15..60a94dd 100644 --- a/Doc/温湿度风扇_固件需求规格书.md +++ b/Doc/温湿度风扇_固件需求规格书.md @@ -532,6 +532,8 @@ usr_rtc_get_time() 失败 → 全部定时不执行(等同 time_en=0) - 对时成功:按本地日历把数组左移 N 天(跨了几天就移几天),新今天从 0 或当天已累加值继续。 - 掉电再上电:先把 VM 里 31 格灌进 `gDevData.run_record`;未对时继续往 slot[0] 加。 +**上报:** 今天累计秒数相对上次 0x07 上报满 **60 秒** 才进差分(`JB_RUNREC_DIFF_SEC`);跨天旋转立刻带 DP15。APP 0x05 读、10 分钟全量仍带完整 124B。其它 DP 上报时不刷新运行记录基准。 + **落盘:** 每累计运行满 600 秒写一次 VM。跨天立刻写。拔电没有软关机钩子,**接受最多丢不满 10 分钟的秒数**。 `BOARD_RUNREC_ENABLE=0`:不累加、DP15 报全 0。 @@ -561,7 +563,7 @@ usr_rtc_get_time() 失败 → 全部定时不执行(等同 time_en=0) | 6 linkage_config | 20 字节 memcpy + 存 VM + 第 10.5 节立刻重判 | | 7 time_en | 见第 11 章 | | 8~14 time_config | 8 字节 + 存 VM | -| 15 run_record | RO,由 `app_runrec` 填 124B,禁止 APP 写 | +| 15 run_record | RO,由 `app_runrec` 填 124B,禁止 APP 写。差分满 1 分钟或跨天才 0x07 | | 16 heartbeat | 本版忽略(写了也不停温湿度上报) | | 17 fault_en | 原样存,P0 不做位级过滤 | | 18 fault_code | 0 无 / 1 传感器故障 / 2 预留 | diff --git a/apps/usr_app/app_runrec.c b/apps/usr_app/app_runrec.c index a2b3270..f77f9b9 100644 --- a/apps/usr_app/app_runrec.c +++ b/apps/usr_app/app_runrec.c @@ -12,9 +12,9 @@ * - app_runrec_tick(20ms 中断):只把在转的毫秒折成 pending 秒, * **不碰 s_rr.rec[]、不打日志、不写 flash**(跨天旋转在任务侧)。 * - app_runrec_rotate_if_needed(500ms 任务):收下 pending 加到 - * slot[0]、每拍灌 DP21、跨天旋转、满 10 分钟 / 跨天才写 VM。 - * DP21 每 500ms 更新到 gDevData,供读请求和 10min 全量上报; - * 差分变化上报不带 DP21(避免每秒推 124B)。 + * slot[0]、每拍灌 DP15、跨天旋转、满 10 分钟 / 跨天才写 VM。 + * DP15 每 500ms 更新到 gDevData:0x05 读立刻拿到当前秒; + * 差分满 1 分钟才 0x07;10min 全量仍带。 * 拔电没有软关机钩子,接受最多丢不满 10 分钟的秒数(13.1 已拍板)。 ******************************************************************************/ @@ -197,7 +197,7 @@ void app_runrec_rotate_if_needed(void) } } - /* 每拍灌 DP21:读请求 / 10min 全量能拿到当前秒数;差分上报不带本 DP */ + /* 每拍灌 DP15:0x05 读立刻拿到当前秒;差分满 1 分钟才 0x07;10min 全量仍带 */ app_runrec_pack(gDevData.run_record); if (need_vm) { app_nvm_save_runrec(); /* 满 10 分钟或跨天 / 首次对时才写 flash */ diff --git a/apps/usr_app/app_runrec.h b/apps/usr_app/app_runrec.h index 6115156..0e301d8 100644 --- a/apps/usr_app/app_runrec.h +++ b/apps/usr_app/app_runrec.h @@ -13,8 +13,8 @@ * N 天;掉电上电先把 VM 的 31 格灌回 RAM。 * 落盘:每累计运行满 BOARD_RUN_RECORD_SAVE_SEC(600s) 写一次 VM; * 跨天旋转**立刻写**。拔电无软关机钩子,接受丢不满 10 分钟的秒数。 - * DP21:任务上下文每 500ms 灌进 gDevData(读请求 / 10min 全量用); - * 差分变化上报不带本 DP,避免每秒推 124B。 + * DP15:任务上下文每 500ms 灌进 gDevData(0x05 读立刻拿到当前秒; + * 差分满 1 分钟才 0x07;10min 全量仍带)。 * * ⚠ 上下文分工(规格书第 0/13 章,2026-08-31 事故定论): * - app_runrec_tick() = 20ms **中断上下文**:只折 pending 秒, diff --git a/apps/usr_jb_proto/Protocol/jb_protocol.c b/apps/usr_jb_proto/Protocol/jb_protocol.c index ae7d0eb..2c572f6 100644 --- a/apps/usr_jb_proto/Protocol/jb_protocol.c +++ b/apps/usr_jb_proto/Protocol/jb_protocol.c @@ -582,7 +582,15 @@ static void jbUnpackDps(const uint8_t *bitmap, const uint8_t *values, /* ════════════════════════════════════════════════════════════════ * jbBuildDiffMask — 比较上次与当前值,为变化的可上报 DP 置 mask 位 * 返回: 1 = 有 DP 发生变化, 0 = 全部未变化 + * DP15 运行记录:今天累计秒数相对上次上报满 JB_RUNREC_DIFF_SEC 才进差分; + * 其它日期格变化(跨天旋转)立刻进差分。0x05 读 / 10min 全量仍带完整 124B。 * ════════════════════════════════════════════════════════════════ */ +static uint32_t jbRunrecTodaySec(const uint8_t *rec) +{ + return ((uint32_t)rec[0] << 24) | ((uint32_t)rec[1] << 16) + | ((uint32_t)rec[2] << 8) | (uint32_t)rec[3]; +} + static uint8_t jbBuildDiffMask(const jb_data_point_t *last, const jb_data_point_t *cur, uint8_t *mask) @@ -680,8 +688,21 @@ static uint8_t jbBuildDiffMask(const jb_data_point_t *last, mask[DP_ID_TIME_CONFIG7 / 8] |= (1 << (DP_ID_TIME_CONFIG7 % 8)); hasChange = 1; } - /* DP15 运行记录:每秒都在变,不参与差分上报(避免 2s 防抖推 124B)。 - * 读请求与 REPORT_PERIOD 全量仍带当前 gDevData.run_record。 */ + /* DP15 运行记录:今天秒数差分满 1 分钟,或后 30 天格变了(跨天) */ + { + uint32_t last_today = jbRunrecTodaySec(last->run_record); + uint32_t cur_today = jbRunrecTodaySec(cur->run_record); + uint32_t delta = (cur_today > last_today) + ? (cur_today - last_today) + : (last_today - cur_today); + + if ((delta >= JB_RUNREC_DIFF_SEC) + || memcmp(&last->run_record[4], &cur->run_record[4], 120)) + { + mask[DP_ID_RUN_RECORD / 8] |= (1 << (DP_ID_RUN_RECORD % 8)); + hasChange = 1; + } + } /* DP17 设备故障使能 */ if (last->fault_en != cur->fault_en) { @@ -864,7 +885,19 @@ static void jbReportPolicy(jb_data_point_t *data) (now - jbProtocol.lastChangeTime > REPORT_DEBOUNCE)) { jbSendReport(data, diffMask); - memcpy(&jbProtocol.lastData, data, sizeof(jb_data_point_t)); + /* 未带 DP15 时保留上次记录基准,避免档位/模式等上报把 1 分钟差分冲掉 */ + if (!(diffMask[DP_ID_RUN_RECORD / 8] & (1u << (DP_ID_RUN_RECORD % 8)))) + { + uint8_t keep[124]; + + memcpy(keep, jbProtocol.lastData.run_record, 124); + memcpy(&jbProtocol.lastData, data, sizeof(jb_data_point_t)); + memcpy(jbProtocol.lastData.run_record, keep, 124); + } + else + { + memcpy(&jbProtocol.lastData, data, sizeof(jb_data_point_t)); + } jbProtocol.lastChangeTime = now; jbProtocol.lastReportTime = now; return; diff --git a/apps/usr_jb_proto/Protocol/jb_protocol.h b/apps/usr_jb_proto/Protocol/jb_protocol.h index c959eb5..b79959b 100644 --- a/apps/usr_jb_proto/Protocol/jb_protocol.h +++ b/apps/usr_jb_proto/Protocol/jb_protocol.h @@ -36,6 +36,7 @@ #define SEND_MAX_NUM 3 /* 最大重传次数 */ #define REPORT_DEBOUNCE 2000 /* 变化上报防抖时间(ms) */ #define REPORT_PERIOD 600000 /* 定时全量上报周期(ms) */ +#define JB_RUNREC_DIFF_SEC 60 /* DP15 差分:今天秒数相对上次上报满 1 分钟才带 */ /* Device identity: 取自 Excel 设备信息表的 ProdtCode / productCode。 * JB_CATEGORY_CODE: 必须 4 字符 ASCII,供 BLE 广播 prodcode 使用