feat(vd960DBN): MQTT/TCP report_config 支持完整7参数配置
- 新增 ReportConfig 结构体 (sensor_type/enable/once/env_eval/interval/ack_required/timeout) - net_srv.c: MQTT report_config handler — 查询/设置均返回完整配置JSON - tcp_json_srv.c: TCP JSON handle_report_config 同步升级,兼容旧 active_report - iot_mqtt_srv.c: g_report_active → g_report_cfg.enable - g_report_active 全局变量替换为 g_report_cfg 结构体
This commit is contained in:
@@ -58,6 +58,19 @@ typedef struct {
|
|||||||
uint32_t deadline; // ms deadline for timeout
|
uint32_t deadline; // ms deadline for timeout
|
||||||
} TcpJsonPending;
|
} TcpJsonPending;
|
||||||
|
|
||||||
|
/*===========================================================================
|
||||||
|
* Report Config
|
||||||
|
*===========================================================================*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t enable; // 0=off, 1=on
|
||||||
|
uint8_t sensor_type; // Sensor type, default 12
|
||||||
|
uint8_t once; // 0=periodic, 1=single report
|
||||||
|
uint8_t env_eval; // 0=skip, 1=environment evaluation
|
||||||
|
uint16_t interval; // Report interval in seconds
|
||||||
|
uint8_t ack_required; // 0=fire-and-forget, 1=ACK required
|
||||||
|
uint16_t timeout; // Timeout in ms
|
||||||
|
} ReportConfig;
|
||||||
|
|
||||||
/*===========================================================================
|
/*===========================================================================
|
||||||
* Externs
|
* Externs
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
@@ -70,7 +83,7 @@ extern uint32_t g_json_last_comm_ts; // Last communication timestamp (ms)
|
|||||||
extern uint32_t g_json_last_connect_ts; // Last client connect timestamp (ms)
|
extern uint32_t g_json_last_connect_ts; // Last client connect timestamp (ms)
|
||||||
extern uint8_t g_json_restart_count; // Auto-restart counter
|
extern uint8_t g_json_restart_count; // Auto-restart counter
|
||||||
extern uint32_t g_json_restart_cooldown; // Cooldown deadline (ms)
|
extern uint32_t g_json_restart_cooldown; // Cooldown deadline (ms)
|
||||||
extern uint8_t g_report_active; // 0=inactive 1=active report
|
extern ReportConfig g_report_cfg; // Active report configuration
|
||||||
|
|
||||||
/*===========================================================================
|
/*===========================================================================
|
||||||
* API
|
* API
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
||||||
|
|
||||||
extern uint8_t g_report_active; // from tcp_json_srv.c, 0=inactive 1=active
|
extern ReportConfig g_report_cfg; // from tcp_json_srv.c
|
||||||
extern uint8_t SocketId_TCP; // from net_srv.c, MQTT socket created by WCHNET_CreateTcpMqttSocket
|
extern uint8_t SocketId_TCP; // from net_srv.c, MQTT socket created by WCHNET_CreateTcpMqttSocket
|
||||||
uint8_t g_iot_socket = 0xFF; // MQTT TCP socket ID
|
uint8_t g_iot_socket = 0xFF; // MQTT TCP socket ID
|
||||||
IotMqttState g_iot_state = IOT_STATE_DISCONNECTED;
|
IotMqttState g_iot_state = IOT_STATE_DISCONNECTED;
|
||||||
@@ -372,7 +372,7 @@ static void iot_process_recv(void) {
|
|||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
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_active) return;
|
if (!g_report_cfg.enable) return;
|
||||||
|
|
||||||
/* 复用 g_pkg_uart_2 中的传感器帧 */
|
/* 复用 g_pkg_uart_2 中的传感器帧 */
|
||||||
if (g_pkg_uart_2.flag == 0) return;
|
if (g_pkg_uart_2.flag == 0) return;
|
||||||
|
|||||||
@@ -1252,6 +1252,73 @@ void manage_mqtt_recv_message(char * msg, int length)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- report_config ---
|
||||||
|
if(strcmp(cmd_str, "report_config") == 0) {
|
||||||
|
char *data_buf = (char *)malloc(512);
|
||||||
|
if(data_buf) {
|
||||||
|
memset(data_buf, 0, 512);
|
||||||
|
simple_parse_json(msg, "\"data\"", data_buf);
|
||||||
|
|
||||||
|
if(strlen(data_buf) > 0) {
|
||||||
|
// sensor_type (int)
|
||||||
|
memset(tmp, 0, sizeof(tmp));
|
||||||
|
simple_parse_json(data_buf, "\"sensor_type\"", tmp);
|
||||||
|
if(strlen(tmp) > 0) g_report_cfg.sensor_type = (uint8_t)strtoul(tmp, NULL, 10);
|
||||||
|
|
||||||
|
// enable (bool)
|
||||||
|
memset(tmp, 0, sizeof(tmp));
|
||||||
|
simple_parse_json(data_buf, "\"enable\"", tmp);
|
||||||
|
if(strlen(tmp) > 0) g_report_cfg.enable = (uint8_t)(strstr(tmp, "true") ? 1 : 0);
|
||||||
|
|
||||||
|
// once (bool)
|
||||||
|
memset(tmp, 0, sizeof(tmp));
|
||||||
|
simple_parse_json(data_buf, "\"once\"", tmp);
|
||||||
|
if(strlen(tmp) > 0) g_report_cfg.once = (uint8_t)(strstr(tmp, "true") ? 1 : 0);
|
||||||
|
|
||||||
|
// env_eval (bool)
|
||||||
|
memset(tmp, 0, sizeof(tmp));
|
||||||
|
simple_parse_json(data_buf, "\"env_eval\"", tmp);
|
||||||
|
if(strlen(tmp) > 0) g_report_cfg.env_eval = (uint8_t)(strstr(tmp, "true") ? 1 : 0);
|
||||||
|
|
||||||
|
// interval (int)
|
||||||
|
memset(tmp, 0, sizeof(tmp));
|
||||||
|
simple_parse_json(data_buf, "\"interval\"", tmp);
|
||||||
|
if(strlen(tmp) > 0) g_report_cfg.interval = (uint16_t)strtoul(tmp, NULL, 10);
|
||||||
|
|
||||||
|
// ack_required (bool)
|
||||||
|
memset(tmp, 0, sizeof(tmp));
|
||||||
|
simple_parse_json(data_buf, "\"ack_required\"", tmp);
|
||||||
|
if(strlen(tmp) > 0) g_report_cfg.ack_required = (uint8_t)(strstr(tmp, "true") ? 1 : 0);
|
||||||
|
|
||||||
|
// timeout (int)
|
||||||
|
memset(tmp, 0, sizeof(tmp));
|
||||||
|
simple_parse_json(data_buf, "\"timeout\"", tmp);
|
||||||
|
if(strlen(tmp) > 0) g_report_cfg.timeout = (uint16_t)strtoul(tmp, NULL, 10);
|
||||||
|
}
|
||||||
|
free(data_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
char resp[400];
|
||||||
|
snprintf(resp, sizeof(resp),
|
||||||
|
"{\"msg_id\":%lu,\"cmd\":\"report_config\","
|
||||||
|
"\"ts\":%lu,\"code\":0,\"msg\":\"success\","
|
||||||
|
"\"data\":{"
|
||||||
|
"\"sensor_type\":%d,\"enable\":%s,\"once\":%s,\"env_eval\":%s,"
|
||||||
|
"\"interval\":%u,\"ack_required\":%s,\"timeout\":%u}}",
|
||||||
|
msg_id, mstick() / 1000,
|
||||||
|
g_report_cfg.sensor_type,
|
||||||
|
g_report_cfg.enable ? "true" : "false",
|
||||||
|
g_report_cfg.once ? "true" : "false",
|
||||||
|
g_report_cfg.env_eval ? "true" : "false",
|
||||||
|
g_report_cfg.interval,
|
||||||
|
g_report_cfg.ack_required ? "true" : "false",
|
||||||
|
g_report_cfg.timeout);
|
||||||
|
mqtt_publish(resp_topic, resp, 1);
|
||||||
|
PRINT("IOT: report_config enable=%d interval=%u sensor=%d\n",
|
||||||
|
g_report_cfg.enable, g_report_cfg.interval, g_report_cfg.sensor_type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// --- 未支持的命令 ---
|
// --- 未支持的命令 ---
|
||||||
{
|
{
|
||||||
char resp[256];
|
char resp[256];
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ uint32_t g_json_auth_timer = 0;
|
|||||||
uint8_t g_json_pwd_retry = 0;
|
uint8_t g_json_pwd_retry = 0;
|
||||||
uint32_t g_json_lockout_timer = 0;
|
uint32_t g_json_lockout_timer = 0;
|
||||||
TcpJsonPending g_json_pending = {0, 0, 0, "", 0};
|
TcpJsonPending g_json_pending = {0, 0, 0, "", 0};
|
||||||
uint8_t g_report_active = 0; // 0=不主动上报, 1=主动上报传感器数据
|
ReportConfig g_report_cfg = {0}; // 上电默认关闭上报
|
||||||
uint32_t g_json_last_comm_ts = 0; // 最后通信时间戳
|
uint32_t g_json_last_comm_ts = 0; // 最后通信时间戳
|
||||||
uint32_t g_json_last_connect_ts = 0; // 最后连接时间戳
|
uint32_t g_json_last_connect_ts = 0; // 最后连接时间戳
|
||||||
uint8_t g_json_restart_count = 0; // 自动重启计数
|
uint8_t g_json_restart_count = 0; // 自动重启计数
|
||||||
@@ -555,29 +555,85 @@ static void handle_loop_param_query(uint8_t socket, uint32_t msg_id, const char
|
|||||||
PRINT("JSON: loop_param_query sent\n");
|
PRINT("JSON: loop_param_query sent\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 4.15 report_config — 配置主动上报开关 */
|
/* 4.15 report_config — 配置主动上报参数 */
|
||||||
static void handle_report_config(uint8_t socket, uint32_t msg_id, const char *json) {
|
static void handle_report_config(uint8_t socket, uint32_t msg_id, const char *json) {
|
||||||
char *data = json_get_data_str(json);
|
char *data = json_get_data_str(json);
|
||||||
if (!data) {
|
if (data) {
|
||||||
json_send_error(socket, msg_id, "report_config", JSON_CODE_PARAM_ERR, "missing data");
|
reset_tmp();
|
||||||
return;
|
|
||||||
|
// sensor_type (int)
|
||||||
|
simple_parse_json(data, "\"sensor_type\"", g_tmp_value);
|
||||||
|
if (strlen(g_tmp_value) > 0) {
|
||||||
|
g_report_cfg.sensor_type = (uint8_t)strtoul(g_tmp_value, NULL, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse active_report flag
|
// enable (bool)
|
||||||
reset_tmp();
|
memset(g_tmp_value, 0, sizeof(g_tmp_value));
|
||||||
|
simple_parse_json(data, "\"enable\"", g_tmp_value);
|
||||||
|
if (strlen(g_tmp_value) > 0) {
|
||||||
|
g_report_cfg.enable = (uint8_t)(strstr(g_tmp_value, "true") ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// once (bool)
|
||||||
|
memset(g_tmp_value, 0, sizeof(g_tmp_value));
|
||||||
|
simple_parse_json(data, "\"once\"", g_tmp_value);
|
||||||
|
if (strlen(g_tmp_value) > 0) {
|
||||||
|
g_report_cfg.once = (uint8_t)(strstr(g_tmp_value, "true") ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// env_eval (bool)
|
||||||
|
memset(g_tmp_value, 0, sizeof(g_tmp_value));
|
||||||
|
simple_parse_json(data, "\"env_eval\"", g_tmp_value);
|
||||||
|
if (strlen(g_tmp_value) > 0) {
|
||||||
|
g_report_cfg.env_eval = (uint8_t)(strstr(g_tmp_value, "true") ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// interval (int)
|
||||||
|
memset(g_tmp_value, 0, sizeof(g_tmp_value));
|
||||||
|
simple_parse_json(data, "\"interval\"", g_tmp_value);
|
||||||
|
if (strlen(g_tmp_value) > 0) {
|
||||||
|
g_report_cfg.interval = (uint16_t)strtoul(g_tmp_value, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ack_required (bool)
|
||||||
|
memset(g_tmp_value, 0, sizeof(g_tmp_value));
|
||||||
|
simple_parse_json(data, "\"ack_required\"", g_tmp_value);
|
||||||
|
if (strlen(g_tmp_value) > 0) {
|
||||||
|
g_report_cfg.ack_required = (uint8_t)(strstr(g_tmp_value, "true") ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// timeout (int)
|
||||||
|
memset(g_tmp_value, 0, sizeof(g_tmp_value));
|
||||||
|
simple_parse_json(data, "\"timeout\"", g_tmp_value);
|
||||||
|
if (strlen(g_tmp_value) > 0) {
|
||||||
|
g_report_cfg.timeout = (uint16_t)strtoul(g_tmp_value, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 兼容旧协议 active_report
|
||||||
|
memset(g_tmp_value, 0, sizeof(g_tmp_value));
|
||||||
simple_parse_json(data, "\"active_report\"", g_tmp_value);
|
simple_parse_json(data, "\"active_report\"", g_tmp_value);
|
||||||
if (strlen(g_tmp_value) > 0) {
|
if (strlen(g_tmp_value) > 0) {
|
||||||
if (strstr(g_tmp_value, "true")) {
|
g_report_cfg.enable = (uint8_t)(strstr(g_tmp_value, "true") ? 1 : 0);
|
||||||
g_report_active = 1;
|
|
||||||
} else {
|
|
||||||
g_report_active = 0;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
free(data);
|
|
||||||
|
|
||||||
json_send_ok(socket, msg_id, "report_config",
|
free(data);
|
||||||
g_report_active ? "{\"active_report\":true}" : "{\"active_report\":false}");
|
}
|
||||||
PRINT("JSON: report_config active_report=%d\n", g_report_active);
|
|
||||||
|
char data_json[256];
|
||||||
|
snprintf(data_json, sizeof(data_json),
|
||||||
|
"{\"sensor_type\":%d,\"enable\":%s,\"once\":%s,\"env_eval\":%s,"
|
||||||
|
"\"interval\":%u,\"ack_required\":%s,\"timeout\":%u}",
|
||||||
|
g_report_cfg.sensor_type,
|
||||||
|
g_report_cfg.enable ? "true" : "false",
|
||||||
|
g_report_cfg.once ? "true" : "false",
|
||||||
|
g_report_cfg.env_eval ? "true" : "false",
|
||||||
|
g_report_cfg.interval,
|
||||||
|
g_report_cfg.ack_required ? "true" : "false",
|
||||||
|
g_report_cfg.timeout);
|
||||||
|
|
||||||
|
json_send_ok(socket, msg_id, "report_config", data_json);
|
||||||
|
PRINT("JSON: report_config enable=%d interval=%u sensor=%d\\n",
|
||||||
|
g_report_cfg.enable, g_report_cfg.interval, g_report_cfg.sensor_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 4.16 loop_version_query — 获取地感MCU版本号 (CMD 0x4A) */
|
/* 4.16 loop_version_query — 获取地感MCU版本号 (CMD 0x4A) */
|
||||||
@@ -758,12 +814,12 @@ static int format_loop_param_json(char *buf, uint16_t buf_size, const LUP_ParamG
|
|||||||
static void json_sensor_callback(const uint8_t *pkg, uint16_t len)
|
static void json_sensor_callback(const uint8_t *pkg, uint16_t len)
|
||||||
{
|
{
|
||||||
PRINT("JSON: sensor_cb enter socket=%d auth=%d report=%d\n",
|
PRINT("JSON: sensor_cb enter socket=%d auth=%d report=%d\n",
|
||||||
g_json_socket_listen, g_json_auth_state, g_report_active);
|
g_json_socket_listen, g_json_auth_state, g_report_cfg.enable);
|
||||||
|
|
||||||
// Check: socket active, authed, report enabled
|
// Check: socket active, authed, report enabled
|
||||||
if (g_json_socket_listen == 0xFF) { PRINT("JSON: sensor_cb skip: no socket\n"); return; }
|
if (g_json_socket_listen == 0xFF) { PRINT("JSON: sensor_cb skip: no socket\n"); return; }
|
||||||
if (g_json_auth_state != JSON_STATE_AUTHED) { PRINT("JSON: sensor_cb skip: not authed\n"); return; }
|
if (g_json_auth_state != JSON_STATE_AUTHED) { PRINT("JSON: sensor_cb skip: not authed\n"); return; }
|
||||||
if (!g_report_active) { PRINT("JSON: sensor_cb skip: report disabled\n"); return; }
|
if (!g_report_cfg.enable) { PRINT("JSON: sensor_cb skip: report disabled\\n"); return; }
|
||||||
|
|
||||||
LUP_SensorReport sr;
|
LUP_SensorReport sr;
|
||||||
memset(&sr, 0, sizeof(sr));
|
memset(&sr, 0, sizeof(sr));
|
||||||
@@ -1247,7 +1303,7 @@ void tcp_json_push_sensor(void) {
|
|||||||
// Check: socket active, authed, report enabled
|
// Check: socket active, authed, report enabled
|
||||||
if (g_json_socket_listen == 0xFF) return;
|
if (g_json_socket_listen == 0xFF) return;
|
||||||
if (g_json_auth_state != JSON_STATE_AUTHED) return;
|
if (g_json_auth_state != JSON_STATE_AUTHED) return;
|
||||||
if (!g_report_active) return; // 主动上报未开启
|
if (!g_report_cfg.enable) return; // 主动上报未开启
|
||||||
|
|
||||||
// Only proceed if g_pkg_uart_2 has data and it's a 0xC0 sensor report
|
// Only proceed if g_pkg_uart_2 has data and it's a 0xC0 sensor report
|
||||||
if (g_pkg_uart_2.flag == 0) return;
|
if (g_pkg_uart_2.flag == 0) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user