From ef7ced3cadde168ca3416cbb1f5facd6a3fc2026 Mon Sep 17 00:00:00 2001 From: czq <860517298@qq.com> Date: Fri, 13 Jun 2025 14:47:53 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9A=82=E5=AD=98=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=93=8D=E5=BA=94=E5=92=8C=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/inc/bsp_ml307r.h | 17 ++- bsp/src/bsp_ml307r.c | 286 ++++++++++++++++++++----------------------- bsp/src/bsp_valve.c | 21 +++- 3 files changed, 168 insertions(+), 156 deletions(-) diff --git a/bsp/inc/bsp_ml307r.h b/bsp/inc/bsp_ml307r.h index 97f3899..05add73 100644 --- a/bsp/inc/bsp_ml307r.h +++ b/bsp/inc/bsp_ml307r.h @@ -18,10 +18,12 @@ // MQTT服务器配置 // #define MQTT_HOST "120.25.151.173" // MQTT服务器地址 #define MQTT_HOST "8.135.10.183" // MQTT服务器地址 +// #define MQTT_HOST "8.130.110.62" // MQTT服务器地址 // #define MQTT_PORT 1883 // MQTT服务器端口 -#define MQTT_PORT 20609 // MQTT服务器端口 -#define MQTT_USER "guest" // MQTT用户名 -#define MQTT_PASS "guest" // MQTT密码 +#define MQTT_PORT 26866 // MQTT服务器端口 +// #define MQTT_PORT 7193 // MQTT服务器端口 +#define MQTT_USER "zbf_mqtt" // MQTT用户名 +#define MQTT_PASS "zbf123456" // MQTT密码 #define CLIENT_ID "ZBF" // 客户端ID前缀 // MQTT主题定义 @@ -127,6 +129,13 @@ typedef enum { IOT_STATE_PROCESS // 处理 } IoT_State_t; +// 定义JSON缓冲区大小 +#define JSON_BUFFER_SIZE 512 +// 定义4G上报数据结构体 +typedef struct { + char json_buffer[JSON_BUFFER_SIZE]; // JSON字符串缓冲区 + uint16_t length; // JSON字符串长度 +} Ts4GJsonData; extern IotFlagStruct IotFlag_t; extern struct tm Network_Time_t; @@ -145,6 +154,8 @@ static void BSP_Read_Module(void); static void BSP_simcom_init(void); static void BSP_Get_Module_Info(void); static void BSP_Module_Connect_CtWing(void); +static void BSP_SendMessage(void); +uint8_t BSP_4G_Generate_Response(Ts4GJsonData *p4GData, uint32_t timestamp, TeFrameCmd responseCmd); // 状态上报请求结构体 typedef struct { diff --git a/bsp/src/bsp_ml307r.c b/bsp/src/bsp_ml307r.c index 743384b..c7cf033 100644 --- a/bsp/src/bsp_ml307r.c +++ b/bsp/src/bsp_ml307r.c @@ -83,6 +83,10 @@ static const at_adapter_t at_adapter = .urc_bufsize = 512 }; +// 全局JSON数据结构体 +Ts4GJsonData g4GJsonData; +char *json_data; + static IoT_State_t state = IOT_STATE_POWER_ON; /* * 时间间隔,单位:ms,默认:10s @@ -167,7 +171,7 @@ void StopTask_CallBack(MultiTimer* timer, void* userData) * @param json_str JSON字符串 * @return 0: 成功, -1: 失败 */ -static int parse_server_json_data(const char* json_str) +static int _parse_server_json_data(const char* json_str) { lwjson_t lwjson; lwjson_token_t tokens[64]; @@ -185,7 +189,6 @@ static int parse_server_json_data(const char* json_str) lwjson_free(&lwjson); return -1; } - logDebug("JSON parse success\r\n"); // 解析设备序列号 @@ -200,133 +203,118 @@ static int parse_server_json_data(const char* json_str) } // 解析时间戳 - token = lwjson_find(&lwjson, "t"); + uint32_t timestamp = 0; + token = lwjson_find(&lwjson, "time"); if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { uint32_t timestamp = (uint32_t)token->u.num_int; logDebug("Timestamp: %u\r\n", timestamp); } // 解析类型 - token = lwjson_find(&lwjson, "type"); + TeFrameCmd msg_cmd = kCmdCfg; + token = lwjson_find(&lwjson, "cmd"); if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { - int msg_type = (int)token->u.num_int; - logDebug("Message type: %d\r\n", msg_type); + msg_cmd = (int)token->u.num_int; + logDebug("Message cmd: %d\r\n", msg_cmd); } - // 解析data对象中的各个字段 - - // 开关状态 - token = lwjson_find(&lwjson, "data.switch_status"); - if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { - int switch_status = (int)token->u.num_int; - logDebug("Switch status: %d\r\n", switch_status); + // 根据不同的命令类型解析特定数据 + switch (msg_cmd) { + case kCmdCfg: + logDebug("Data response %d\r\n", msg_cmd); + break; + case kCmdCloseVavle: + token = lwjson_find(&lwjson, "data.switch_status"); + if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { + int switch_status = (int)token->u.num_int; + logDebug("Switch status: %d\r\n", switch_status); + if (switch_status == 0) { + logDebug("Command: Close valve\r\n"); + // BSP_VALVE_Close(); // 取消注释以执行实际操作 + IotFlag_t.Valve_Close_flag = 1; + } + } + break; + case kCmdOpenVavle: + token = lwjson_find(&lwjson, "data.switch_status"); + if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { + int switch_status = (int)token->u.num_int; + logDebug("Switch status: %d\r\n", switch_status); + if (switch_status == 1) { + logDebug("Command: Open valve\r\n"); + // BSP_VALVE_Open(); // 取消注释以执行实际操作 + IotFlag_t.Valve_Open_flag = 1; + } + } + break; + case KValveCmdTimeSet: + token = lwjson_find(&lwjson, "data.timer_minutes"); + if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { + uint32_t timer_minutes = (uint32_t)token->u.num_int; + logDebug("Delay close time: %d minutes\r\n", timer_minutes); + } + break; + case kValveCmdOverPressure: + token = lwjson_find(&lwjson, "data.over_press"); + if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { + uint16_t over_press = (uint16_t)token->u.num_int; + logDebug("Over pressure threshold: %d Pa\r\n", over_press); + // 更新阀门超压阈值 + ValveInfo.over_press = over_press; + } + break; + case kValveCmdUnderPressure: + token = lwjson_find(&lwjson, "data.low_press"); + if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { + uint16_t low_press = (uint16_t)token->u.num_int; + logDebug("Low pressure threshold: %d Pa\r\n", low_press); + // 更新阀门欠压阈值 + ValveInfo.low_press = low_press; + } + break; + case kValveCmdDelayClose: + token = lwjson_find(&lwjson, "data.delay_close_time"); + if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { + uint32_t delay_close_time = (uint32_t)token->u.num_int; + logDebug("Delay close time: %d minutes\r\n", delay_close_time); + // 更新阀门延时次数 + ValveInfo.delay_close_count = delay_close_time/5; + logDebug("delay_close_count: %d \r\n", ValveInfo.delay_close_count); + } + break; + case kValveCmdOverTemperature: + token = lwjson_find(&lwjson, "data.over_temp"); + if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { + uint8_t over_temp = (uint8_t)token->u.num_int; + logDebug("Over temperature threshold: %d°C\r\n", over_temp); + // 更新阀门超温阈值 + ValveInfo.over_temp = over_temp; + } + break; + default: + // 处理其他命令类型 + logDebug("Unhandled command type: %d\r\n", msg_cmd); + break; + } + if (msg_cmd != kCmdCfg) { + // 生成响应并发送 + Ts4GJsonData responseData; + BSP_4G_Generate_Response(&responseData, timestamp, msg_cmd); - // 根据开关状态执行相应操作 - if (switch_status == 1) { - logDebug("Command: Open valve\r\n"); - // BSP_VALVE_Open(); // 取消注释以执行实际操作 - IotFlag_t.Valve_Open_flag = 1; - } else if (switch_status == 0) { - logDebug("Command: Close valve\r\n"); - // BSP_VALVE_Close(); // 取消注释以执行实际操作 - IotFlag_t.Valve_Close_flag = 1; + // 分配内存并复制JSON字符串 + char* response_json = (char *)tmos_msg_allocate(responseData.length + 1); + if (response_json != NULL) { + strcpy(response_json, responseData.json_buffer); + logDebug("Response JSON: %s\r\n", response_json); + + // 保存到全局变量以便发送 + json_data = response_json; + BSP_SendMessage(); + } else { + logDebug("Response JSON Memory failure!\n"); } } - - // 温度 - token = lwjson_find(&lwjson, "data.temp"); - if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { - int temperature = (int)token->u.num_int; - logDebug("Temperature: %d°C\r\n", temperature); - } - - // 进口压力 - token = lwjson_find(&lwjson, "data.in_pressure"); - if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { - int in_pressure = (int)token->u.num_int; - logDebug("In pressure: %d Pa\r\n", in_pressure); - } - - // 出口压力 - token = lwjson_find(&lwjson, "data.out_pressure"); - if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { - int out_pressure = (int)token->u.num_int; - logDebug("Out pressure: %d Pa\r\n", out_pressure); - } - - // 大气压力 - token = lwjson_find(&lwjson, "data.atm_pressure"); - if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { - int atm_pressure = (int)token->u.num_int; - logDebug("Atm pressure: %d Pa\r\n", atm_pressure); - } - - // 电池电量 - token = lwjson_find(&lwjson, "data.bat"); - if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { - int battery = (int)token->u.num_int; - logDebug("Battery: %d%mv\r\n", battery); - } - - // 湿度 - token = lwjson_find(&lwjson, "data.humi"); - if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { - int humidity = (int)token->u.num_int; - logDebug("Humidity: %d%%\r\n", humidity); - } - - // RSSI - token = lwjson_find(&lwjson, "data.rssi"); - if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { - int rssi = (int)token->u.num_int; - logDebug("RSSI: %d\r\n", rssi); - } - - // 信号强度 - token = lwjson_find(&lwjson, "data.signal"); - if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { - int signal = (int)token->u.num_int; - logDebug("Signal: %d\r\n", signal); - } - - // 超压阈值 - token = lwjson_find(&lwjson, "data.over_press"); - if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { - uint16_t over_press = (uint16_t)token->u.num_int; - logDebug("Over pressure threshold: %d Pa\r\n", over_press); - // 更新阀门超压阈值 - ValveInfo.over_press = over_press; - } - - // 欠压阈值 - token = lwjson_find(&lwjson, "data.low_press"); - if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { - uint16_t low_press = (uint16_t)token->u.num_int; - logDebug("Low pressure threshold: %d Pa\r\n", low_press); - // 更新阀门欠压阈值 - ValveInfo.low_press = low_press; - } - - // 延时关阀时间 - token = lwjson_find(&lwjson, "data.delay_close_time"); - if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { - uint32_t delay_close_time = (uint32_t)token->u.num_int; - logDebug("Delay close time: %d minutes\r\n", delay_close_time); - // 更新阀门延时次数 - ValveInfo.delay_close_count = delay_close_time/5; - logDebug("delay_close_count: %d \r\n", ValveInfo.delay_close_count); - } - - // 超温阈值 - token = lwjson_find(&lwjson, "data.over_temp"); - if (token != NULL && token->type == LWJSON_TYPE_NUM_INT) { - uint8_t over_temp = (uint8_t)token->u.num_int; - logDebug("Over temperature threshold: %d°C\r\n", over_temp); - // 更新阀门超温阈值 - ValveInfo.over_temp = over_temp; - } - - // 释放资源 + lwjson_free(&lwjson); return 0; } @@ -347,22 +335,25 @@ static int URC_MQTT_Publish_Cb(at_urc_info_t *info) char topic[64] = {0}; char payload[512] = {0}; + int connect_id; + int mid; + int total_len; + int payload_len; - if (sscanf(info->urcbuf, "+MQTTURC: \"publish\",%*d,%*d,\"%[^\"]\",", topic) >= 1) { - logDebug("topic: %s\r\n", topic); - - // 查找JSON数据的起始位置(查找第一个'{'字符) - char *json_start = strchr(info->urcbuf, '{'); - if (json_start) { - logDebug("payload: %s\r\n", json_start); - - // 解析JSON负载 - if (parse_server_json_data(json_start) == 0) { - logDebug("Server JSON data parsed successfully\r\n"); - } else { - logDebug("Failed to parse server JSON data\r\n"); - } - + if (6 == sscanf(info->urcbuf, "+MQTTURC: \"publish\",%d,%d,\"%[^\"]\",%d,%d,%s" + ,&connect_id, &mid, topic, &total_len, &payload_len, payload)) + { + logDebug("connect_id:%d, mid:%d", connect_id, mid); + logDebug("topic: %s", topic); + logDebug("total_len: %d", total_len); + logDebug("payload_len: %d", payload_len); + logDebug("payload: %s", payload); + if (_parse_server_json_data(payload) == 0) + { + logDebug("Server JSON data parsed successfully\r\n"); + } else + { + logDebug("Failed to parse server JSON data\r\n"); } } @@ -914,14 +905,6 @@ void BSP_Module_Send_Data(uint8_t* data, uint8_t len) at_send_data(ml307r_obj, &attr, data, len); } -// 定义JSON缓冲区大小 -#define JSON_BUFFER_SIZE 512 - -// 定义4G上报数据结构体 -typedef struct { - char json_buffer[JSON_BUFFER_SIZE]; // JSON字符串缓冲区 - uint16_t length; // JSON字符串长度 -} Ts4GJsonData; /** * @brief 生成4G模组上报的JSON数据 @@ -948,6 +931,7 @@ uint8_t BSP_4G_Generate_JsonData(Ts4GJsonData *p4GData, TeFrameCmd cmd) ValveData.bat = BSP_ReadVbat(); ValveData.humi = 50; ValveData.rssi = gValveData.rssi; + ValveData.Lock = gValveData.Lock; ValveData.delay_close_time = ValveInfo.delay_close_count * 5; // 解析信号强度,这里简单处理为0-5的整数值 @@ -977,7 +961,7 @@ uint8_t BSP_4G_Generate_JsonData(Ts4GJsonData *p4GData, TeFrameCmd cmd) "{" "\"sn\":\"%s\"," "\"time\":%u," - "\"type\":%d," + "\"cmd\":%d," "\"data\":{" "\"switch_status\":%d," "\"temp\":%d," @@ -988,6 +972,7 @@ uint8_t BSP_4G_Generate_JsonData(Ts4GJsonData *p4GData, TeFrameCmd cmd) "\"bat\":%d," "\"humi\":%d," "\"rssi\":%d," + "\"Lock\":%d," "\"signal\":%d," "\"over_press\":%d," "\"low_press\":%d," @@ -1007,6 +992,7 @@ uint8_t BSP_4G_Generate_JsonData(Ts4GJsonData *p4GData, TeFrameCmd cmd) ValveData.bat, ValveData.humi, ValveData.rssi, + ValveData.Lock, signal_strength, ValveInfo.over_press, ValveInfo.low_press, @@ -1027,19 +1013,21 @@ uint8_t BSP_4G_Generate_JsonData(Ts4GJsonData *p4GData, TeFrameCmd cmd) * @param result 响应结果,0成功,非0失败 * @return uint8_t 0表示成功 */ -uint8_t BSP_4G_Generate_Response(Ts4GJsonData *p4GData, TeFrameCmd responseCmd, uint8_t result) +uint8_t BSP_4G_Generate_Response(Ts4GJsonData *p4GData, uint32_t timestamp, TeFrameCmd responseCmd) { p4GData->length = snprintf(p4GData->json_buffer, JSON_BUFFER_SIZE, "{" - "\"cmd\":%d," + "\"sn\":\"%s\"," + "\"time\":%u," + "\"type\":%d," "\"data\":{" - "\"response_cmd\":%d," - "\"result\":%d" + "\"switch_status\":%d" "}" "}", - kCmdData, // 使用数据命令作为响应命令 + device_sn, + timestamp, responseCmd, - result + gValveData.switch_status ); logDebug("4G响应JSON数据:\r\n%s", p4GData->json_buffer); @@ -1047,9 +1035,7 @@ uint8_t BSP_4G_Generate_Response(Ts4GJsonData *p4GData, TeFrameCmd responseCmd, return 0; } -// 全局JSON数据结构体 -Ts4GJsonData g4GJsonData; -char *json_data; + static int SendMessage(at_env_t *e) { diff --git a/bsp/src/bsp_valve.c b/bsp/src/bsp_valve.c index f307b93..ea9c2cf 100644 --- a/bsp/src/bsp_valve.c +++ b/bsp/src/bsp_valve.c @@ -174,6 +174,12 @@ void BSP_VALVE_Generate_Data(TsRawFrameData *pRawData, TeFrameCmd cmd) // 鐢熸垚 ValveData.humi = 50; ValveData.rssi = gValveData.rssi; + ValveData.Lock = gValveData.Lock; + ValveData.over_pressure = ValveInfo.over_press; + ValveData.under_pressure = ValveInfo.low_press; + ValveData.over_temp = ValveInfo.over_temp; + ValveData.delay_close_time = ValveInfo.delay_close_count * 5; + // 鎵撳嵃ValveData鐨勬墍鏈夊瓧娈 logDebug("ValveData info:\r\n" "switch_status: %d\r\n" @@ -184,7 +190,12 @@ void BSP_VALVE_Generate_Data(TsRawFrameData *pRawData, TeFrameCmd cmd) // 鐢熸垚 "type: %d\r\n" "bat: %d\r\n" "humi: %d\r\n" - "rssi: %d", + "rssi: %d\r\n" + "Lock: %d\r\n" + "over_pressure: %d\r\n" + "under_pressure: %d\r\n" + "over_temp: %d\r\n" + "delay_close_time: %d", ValveData.switch_status, ValveData.temp, ValveData.in_pressure, @@ -193,7 +204,12 @@ void BSP_VALVE_Generate_Data(TsRawFrameData *pRawData, TeFrameCmd cmd) // 鐢熸垚 ValveData.type, ValveData.bat, ValveData.humi, - ValveData.rssi); + ValveData.rssi, + ValveData.Lock, + ValveData.over_pressure, + ValveData.under_pressure, + ValveData.over_temp, + ValveData.delay_close_time); GenerateRawFrame(pRawData, cmd, (uint8_t *)&ValveData, sizeof(ValveData)); } @@ -241,7 +257,6 @@ static void VAVLE_Task_ProcessTmosMsg(uint8_t *p_rev_msg) // 澶勭悊TMOS娑堟伅鍑 } else if(OpenStatus == 2) { - logWarning("?????????????????????????"); BSP_VALVE_Generate_Data(&RelyData, valve_safety.lock_reason); tmos_set_event(Peripheral_TaskID, SBP_REPLY_CMD_EVT); }