feat(iot_mqtt): 传感器MQTT主动上报改为双速率间隔上报
- 新增传感器数据缓存(_cached_sr), 0xC0帧到达时更新缓存, 不上报 - 根据各通道 variation 决定上报间隔: 空闲态(diff < 10): 使用 g_report_cfg.interval 秒 变化态(diff >= 10): 固定 300ms 快速上报 - interval=0 时自动退化为最小 1s 空闲间隔 - 断线时清缓存+复位计时, 重连后等新帧首发 - 消除对 g_pkg_uart_2.flag 的硬依赖, 从缓存自主定时上报 新增常量: IOT_MQTT_FAST_INTERVAL_MS 300 IOT_MQTT_VARIATION_THRESHOLD 10 IOT_MQTT_IDLE_INTERVAL_MIN_MS 1000
This commit is contained in:
@@ -42,6 +42,17 @@ static uint32_t _iot_reconnect_deadline = 0;
|
|||||||
static uint32_t _iot_reconnect_backoff = 0;
|
static uint32_t _iot_reconnect_backoff = 0;
|
||||||
static uint32_t _iot_connect_start = 0; // TCP connect 开始时刻
|
static uint32_t _iot_connect_start = 0; // TCP connect 开始时刻
|
||||||
|
|
||||||
|
/*===========================================================================
|
||||||
|
* 传感器数据缓存 & 上报间隔控制
|
||||||
|
*===========================================================================*/
|
||||||
|
#define IOT_MQTT_FAST_INTERVAL_MS 300 // 变化态快速上报间隔 (ms)
|
||||||
|
#define IOT_MQTT_VARIATION_THRESHOLD 10 // diff 阈值: >= 此值进入快速上报
|
||||||
|
#define IOT_MQTT_IDLE_INTERVAL_MIN_MS 1000 // 空闲间隔最小 1s (防 interval=0 死锁)
|
||||||
|
|
||||||
|
static LUP_SensorReport _cached_sr; // 最新传感器数据缓存
|
||||||
|
static uint8_t _cached_sr_valid; // 缓存有效标志
|
||||||
|
static uint32_t _last_publish_ms; // 上次上报时刻 (ms)
|
||||||
|
|
||||||
/*===========================================================================
|
/*===========================================================================
|
||||||
* Buffers
|
* Buffers
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
@@ -363,29 +374,71 @@ static void iot_process_recv(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================
|
/*===========================================================================
|
||||||
* 传感器数据上报
|
* 传感器数据上报 (双速率: 空闲态按 interval 上报, 变化态 300ms 快速上报)
|
||||||
|
*
|
||||||
|
* Step 1 — 消费 Loop MCU 新帧 → 更新缓存
|
||||||
|
* Step 2 — 对所有通道检测 variation, 决定上报间隔
|
||||||
|
* Step 3 — 间隔门控: 时间到了才从缓存发布
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
void iot_mqtt_publish_sensor(void) {
|
void iot_mqtt_publish_sensor(void) {
|
||||||
if (g_iot_state != IOT_STATE_READY) return;
|
if (g_iot_state != IOT_STATE_READY) return;
|
||||||
if (!g_report_cfg.enable) return;
|
if (!g_report_cfg.enable) return;
|
||||||
|
|
||||||
/* Reuse g_pkg_uart_2 sensor frame from Loop MCU */
|
/*--- Step 1: 消费 0xC0 帧 → 更新缓存 ---*/
|
||||||
if (g_pkg_uart_2.flag == 0) return;
|
if (g_pkg_uart_2.flag != 0
|
||||||
if (g_pkg_uart_2.pkg[0] != 0x7F) return;
|
&& g_pkg_uart_2.pkg[0] == 0x7F
|
||||||
if (g_pkg_uart_2.pkg[3] != 0xC0) return;
|
&& g_pkg_uart_2.pkg[3] == 0xC0) {
|
||||||
|
|
||||||
LUP_SensorReport sr;
|
LUP_SensorReport sr;
|
||||||
memset(&sr, 0, sizeof(sr));
|
memset(&sr, 0, sizeof(sr));
|
||||||
int ret = lup_parse_sensor_report(g_pkg_uart_2.pkg, g_pkg_uart_2.offset, &sr);
|
int ret = lup_parse_sensor_report(g_pkg_uart_2.pkg, g_pkg_uart_2.offset, &sr);
|
||||||
if (ret != 0) {
|
InitPkgUart(&g_pkg_uart_2); // 读完即清, 不持有
|
||||||
PRINT("IOT: sensor parse failed (%d)\n", ret);
|
|
||||||
InitPkgUart(&g_pkg_uart_2);
|
if (ret == 0) {
|
||||||
return;
|
memcpy(&_cached_sr, &sr, sizeof(sr));
|
||||||
|
_cached_sr_valid = 1;
|
||||||
|
} else {
|
||||||
|
PRINT("IOT: sensor parse failed (%d)\n", ret);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 全通道一次性上报,字段按 DLD960_IoT_MQTT协议.md §5.2 V1.02:
|
/* 尚无缓存数据 → 不发 */
|
||||||
ch, level, iscar, loop_ok, freq, diff, sens, cndtn, misc.{type,value}
|
if (!_cached_sr_valid) return;
|
||||||
注意: mqttBuf 需 ≥ 1024 才能容纳 4 通道全字段封包 (~800 字节) */
|
|
||||||
|
/*--- Step 2: 判断是否进入变化态 (任一通道 diff >= 10) ---*/
|
||||||
|
uint32_t interval_ms;
|
||||||
|
uint8_t fast_mode = 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
for (i = 0; i < _cached_sr.coil_count; i++) {
|
||||||
|
if (_cached_sr.coils[i].variation >= IOT_MQTT_VARIATION_THRESHOLD) {
|
||||||
|
fast_mode = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fast_mode) {
|
||||||
|
interval_ms = IOT_MQTT_FAST_INTERVAL_MS; // 300ms
|
||||||
|
} else {
|
||||||
|
/* 空闲态: 使用配置的 interval (秒→毫秒), 最小 1s */
|
||||||
|
uint32_t cfg_ms = (uint32_t)g_report_cfg.interval * 1000;
|
||||||
|
interval_ms = (cfg_ms >= IOT_MQTT_IDLE_INTERVAL_MIN_MS)
|
||||||
|
? cfg_ms : IOT_MQTT_IDLE_INTERVAL_MIN_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--- Step 3: 间隔门控 ---*/
|
||||||
|
{
|
||||||
|
uint32_t now = mstick();
|
||||||
|
if (_last_publish_ms != 0
|
||||||
|
&& (now - _last_publish_ms) < interval_ms) {
|
||||||
|
return; // 未到间隔
|
||||||
|
}
|
||||||
|
_last_publish_ms = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--- Step 4: 构建 JSON → 发布 (字段与 V1.02 协议一致) ---*/
|
||||||
static char data_json[1024];
|
static char data_json[1024];
|
||||||
static char payload[1400];
|
static char payload[1400];
|
||||||
char *p = data_json;
|
char *p = data_json;
|
||||||
@@ -395,16 +448,16 @@ void iot_mqtt_publish_sensor(void) {
|
|||||||
uint8_t i;
|
uint8_t i;
|
||||||
|
|
||||||
written = snprintf(p, remaining, "{\"channels\":[");
|
written = snprintf(p, remaining, "{\"channels\":[");
|
||||||
if (written < 0 || written >= remaining) goto done;
|
if (written < 0 || written >= remaining) return;
|
||||||
p += written; remaining -= written;
|
p += written; remaining -= written;
|
||||||
|
|
||||||
for (i = 0; i < sr.coil_count; i++) {
|
for (i = 0; i < _cached_sr.coil_count; i++) {
|
||||||
const LUP_CoilSensor *cs = &sr.coils[i];
|
const LUP_CoilSensor *cs = &_cached_sr.coils[i];
|
||||||
const char *misc_type_str = "time";
|
const char *misc_type_str = "time";
|
||||||
uint32_t misc_val = 0;
|
uint32_t misc_val = 0;
|
||||||
|
|
||||||
if (cs->misc_type == 0) { misc_type_str = "time"; misc_val = cs->misc.passtime_ms; }
|
if (cs->misc_type == 0) { misc_type_str = "time"; misc_val = cs->misc.passtime_ms; }
|
||||||
else if (cs->misc_type == 1) { misc_type_str = "cut_count"; misc_val = cs->misc.cut_amount; }
|
else if (cs->misc_type == 1) { misc_type_str = "cut_count"; misc_val = cs->misc.cut_amount; }
|
||||||
else if (cs->misc_type == 2) { misc_type_str = "flow_count"; misc_val = cs->misc.flow_amount; }
|
else if (cs->misc_type == 2) { misc_type_str = "flow_count"; misc_val = cs->misc.flow_amount; }
|
||||||
else if (cs->misc_type == 3) { misc_type_str = "relay_count"; misc_val = cs->misc.relay_count; }
|
else if (cs->misc_type == 3) { misc_type_str = "relay_count"; misc_val = cs->misc.relay_count; }
|
||||||
|
|
||||||
@@ -421,7 +474,7 @@ void iot_mqtt_publish_sensor(void) {
|
|||||||
cs->freq, cs->variation,
|
cs->freq, cs->variation,
|
||||||
cs->sensitivity, cs->condition,
|
cs->sensitivity, cs->condition,
|
||||||
misc_type_str, misc_val);
|
misc_type_str, misc_val);
|
||||||
if (written < 0 || written >= remaining) goto done;
|
if (written < 0 || written >= remaining) return;
|
||||||
p += written; remaining -= written;
|
p += written; remaining -= written;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,9 +490,6 @@ void iot_mqtt_publish_sensor(void) {
|
|||||||
snprintf(topic, sizeof(topic), "dld960/%s/dev", g_iot_dev_serial);
|
snprintf(topic, sizeof(topic), "dld960/%s/dev", g_iot_dev_serial);
|
||||||
mqtt_publish(topic, payload, 0);
|
mqtt_publish(topic, payload, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
|
||||||
InitPkgUart(&g_pkg_uart_2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================
|
/*===========================================================================
|
||||||
@@ -519,6 +569,8 @@ void iot_mqtt_handle_sock_int(uint8_t socketid, uint8_t intstat) {
|
|||||||
g_iot_state = IOT_STATE_DISCONNECTED;
|
g_iot_state = IOT_STATE_DISCONNECTED;
|
||||||
g_iot_socket = 0xFF;
|
g_iot_socket = 0xFF;
|
||||||
_iot_recv_len = 0;
|
_iot_recv_len = 0;
|
||||||
|
_cached_sr_valid = 0; // 清缓存: 重连后等新帧
|
||||||
|
_last_publish_ms = 0; // 复位: 重连后立即首发
|
||||||
_iot_reconnect_backoff = IOT_MQTT_RECONNECT_MIN_MS;
|
_iot_reconnect_backoff = IOT_MQTT_RECONNECT_MIN_MS;
|
||||||
_iot_reconnect_deadline = mstick() + _iot_reconnect_backoff;
|
_iot_reconnect_deadline = mstick() + _iot_reconnect_backoff;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user