暂存 使用MQTT进行数据收发
This commit is contained in:
parent
7d7f2f1dab
commit
8d3080daef
|
@ -15,7 +15,20 @@
|
||||||
#define ML307_UART_TX_PIN GPIO_Pin_13 //PB13
|
#define ML307_UART_TX_PIN GPIO_Pin_13 //PB13
|
||||||
#define ML307_UART_RX_PIN GPIO_Pin_12 //PB12
|
#define ML307_UART_RX_PIN GPIO_Pin_12 //PB12
|
||||||
|
|
||||||
|
// MQTT服务器配置
|
||||||
|
// #define MQTT_HOST "120.25.151.173" // MQTT服务器地址
|
||||||
|
#define MQTT_HOST "8.135.10.183" // MQTT服务器地址
|
||||||
|
// #define MQTT_PORT 1883 // MQTT服务器端口
|
||||||
|
#define MQTT_PORT 25237 // MQTT服务器端口
|
||||||
|
#define MQTT_USER "guest" // MQTT用户名
|
||||||
|
#define MQTT_PASS "guest" // MQTT密码
|
||||||
|
#define CLIENT_ID "MKL-ZW001" // 客户端ID前缀
|
||||||
|
|
||||||
|
// MQTT主题定义
|
||||||
|
// #define MQTT_TOPIC_REV "/mkl/zw001/order/" // 订阅主题前缀,后面会拼接设备SN
|
||||||
|
#define MQTT_TOPIC_REV "test"
|
||||||
|
// #define MQTT_TOPIC_UP "/mkl/zw001/push/data" // 发布主题
|
||||||
|
#define MQTT_TOPIC_UP "test" // 发布主题
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct __attribute__((packed))
|
||||||
{
|
{
|
||||||
|
|
|
@ -178,6 +178,29 @@ static int URC_Module_Ready_Cb(at_urc_info_t *info)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MQTT消息接收回调函数
|
||||||
|
static int URC_MQTT_Publish_Cb(at_urc_info_t *info)
|
||||||
|
{
|
||||||
|
logDebug("MQTT rece: %s\r\n", info->urcbuf);
|
||||||
|
|
||||||
|
char topic[64] = {0};
|
||||||
|
char payload[512] = {0};
|
||||||
|
|
||||||
|
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负载
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief urc订阅表
|
* @brief urc订阅表
|
||||||
|
@ -185,6 +208,7 @@ static int URC_Module_Ready_Cb(at_urc_info_t *info)
|
||||||
static const urc_item_t urc_table[] =
|
static const urc_item_t urc_table[] =
|
||||||
{
|
{
|
||||||
{.prefix = "+CPIN: READY", .endmark = '\n', .handler = URC_Module_Ready_Cb},//模块准备就绪
|
{.prefix = "+CPIN: READY", .endmark = '\n', .handler = URC_Module_Ready_Cb},//模块准备就绪
|
||||||
|
{.prefix = "publish", .endmark = '\n', .handler = URC_MQTT_Publish_Cb},//MQTT消息接收
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -199,6 +223,23 @@ void Module_String2Hex(char *hex_arry, char *str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加全局变量用于存储设备SN
|
||||||
|
char device_sn[16] = {0};
|
||||||
|
|
||||||
|
// 获取设备SN(基于IMEI)
|
||||||
|
static void BSP_Get_Device_SN(void)
|
||||||
|
{
|
||||||
|
// 使用IMEI的后12位作为设备SN
|
||||||
|
if (strlen(Module_Info_t.imei) >= 12) {
|
||||||
|
strncpy(device_sn, Module_Info_t.imei + (strlen(Module_Info_t.imei) - 12), 12);
|
||||||
|
device_sn[12] = '\0';
|
||||||
|
logDebug("Device SN: %s\r\n", device_sn);
|
||||||
|
} else {
|
||||||
|
strcpy(device_sn, "000000000000");
|
||||||
|
logDebug("Using default SN: %s\r\n", device_sn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void Module_Get_Imei_Cb(at_response_t *r)
|
static void Module_Get_Imei_Cb(at_response_t *r)
|
||||||
{
|
{
|
||||||
char imei[16] = {0};
|
char imei[16] = {0};
|
||||||
|
@ -391,6 +432,59 @@ static void Module_Timer(void)
|
||||||
at_send_singlline(ml307r_obj, &attr, "AT+CCLK?");
|
at_send_singlline(ml307r_obj, &attr, "AT+CCLK?");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加时间戳转换函数
|
||||||
|
static const uint16_t month_days[] = {0, 31, 28, 31, 30, 31, 30,
|
||||||
|
31, 31, 30, 31, 30, 31}; // 每月的天数
|
||||||
|
|
||||||
|
// 判断是否为闰年
|
||||||
|
static int is_leap_year(int year)
|
||||||
|
{
|
||||||
|
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t utc_to_timestamp(const struct tm *timeinfo)
|
||||||
|
{
|
||||||
|
int year = timeinfo->tm_year;
|
||||||
|
int month = timeinfo->tm_mon; // 假设月份从 1 开始
|
||||||
|
int day = timeinfo->tm_mday;
|
||||||
|
int hour = timeinfo->tm_hour;
|
||||||
|
int min = timeinfo->tm_min;
|
||||||
|
int sec = timeinfo->tm_sec;
|
||||||
|
|
||||||
|
int total_days = 0;
|
||||||
|
|
||||||
|
// 累加整年的天数
|
||||||
|
for (int y = 1970; y < year; y++)
|
||||||
|
{
|
||||||
|
total_days += 365;
|
||||||
|
if (is_leap_year(y))
|
||||||
|
{
|
||||||
|
total_days += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 累加当年的各个月份天数
|
||||||
|
for (int m = 1; m < month; m++)
|
||||||
|
{
|
||||||
|
total_days += month_days[m];
|
||||||
|
// 如果是闰年且月份超过2月,则多加一天
|
||||||
|
if (m == 2 && is_leap_year(year))
|
||||||
|
{
|
||||||
|
total_days += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加上当月天数
|
||||||
|
total_days += day - 1;
|
||||||
|
|
||||||
|
// 计算总秒数
|
||||||
|
uint32_t timestamp = ((uint32_t)total_days * 24 * 60 * 60) +
|
||||||
|
((uint32_t)hour * 60 * 60) +
|
||||||
|
((uint32_t)min * 60) +
|
||||||
|
sec;
|
||||||
|
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
Ts_Network_Service_Info_t Service_Info_t = {0};
|
Ts_Network_Service_Info_t Service_Info_t = {0};
|
||||||
|
|
||||||
|
@ -513,10 +607,96 @@ static void BSP_Get_Module_Info(void)
|
||||||
Module_Get_Iccid();
|
Module_Get_Iccid();
|
||||||
Module_Timer();
|
Module_Timer();
|
||||||
Module_NetWork_Info(); // 获取网络连接信息
|
Module_NetWork_Info(); // 获取网络连接信息
|
||||||
|
// BSP_Get_Device_SN(); // 获取设备SN
|
||||||
// at_send_singlline(ml307r_obj, NULL, "AT+MIPMODE=0,1"); // 进入透传模式
|
// at_send_singlline(ml307r_obj, NULL, "AT+MIPMODE=0,1"); // 进入透传模式
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int MQTT_CfgConnSub(at_env_t *e)
|
||||||
|
{
|
||||||
|
char data[128] = {0};
|
||||||
|
|
||||||
|
switch (e->state)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
logDebug("MQTT config start!\r\n");
|
||||||
|
e->println(e, "AT+MQTTCFG=\"pingresp\",0,1");
|
||||||
|
e->reset_timer(e);
|
||||||
|
e->state++;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (e->contains(e, "OK"))
|
||||||
|
{
|
||||||
|
tmos_memset(data, 0, sizeof(data));
|
||||||
|
// 使用设备SN作为客户端ID的一部分
|
||||||
|
sprintf(data, "AT+MQTTCONN=0,\"%s\",%d,\"%s-%s\",\"%s\",\"%s\"",
|
||||||
|
MQTT_HOST, MQTT_PORT, CLIENT_ID, device_sn, MQTT_USER, MQTT_PASS);
|
||||||
|
e->println(e, data);
|
||||||
|
e->reset_timer(e);
|
||||||
|
e->state++;
|
||||||
|
}
|
||||||
|
if (e->is_timeout(e, 5000))
|
||||||
|
{
|
||||||
|
e->state--;
|
||||||
|
if (++e->i > 3)
|
||||||
|
{
|
||||||
|
logDebug("MQTT config error!\r\n");
|
||||||
|
e->finish(e, AT_RESP_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (e->contains(e, "\"conn\",0,0"))
|
||||||
|
{
|
||||||
|
logDebug("MQTTCONN OK\r\n");
|
||||||
|
tmos_memset(data, 0, sizeof(data));
|
||||||
|
// 订阅主题
|
||||||
|
sprintf(data, "AT+MQTTSUB=0,\"%s%s\",0", MQTT_TOPIC_REV, device_sn);
|
||||||
|
logDebug("MQTTSUB: %s\r\n", data);
|
||||||
|
e->println(e, data);
|
||||||
|
e->reset_timer(e);
|
||||||
|
e->state++;
|
||||||
|
}
|
||||||
|
if (e->is_timeout(e, 5000))
|
||||||
|
{
|
||||||
|
e->state--;
|
||||||
|
if (++e->i > 3)
|
||||||
|
{
|
||||||
|
logDebug("MQTT connect error!\r\n");
|
||||||
|
e->finish(e, AT_RESP_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (e->contains(e, "suback"))
|
||||||
|
{
|
||||||
|
logDebug("MQTTSUB OK\r\n");
|
||||||
|
IotFlag_t.Connect_success_flag = 1;
|
||||||
|
e->finish(e, AT_RESP_OK);
|
||||||
|
}
|
||||||
|
if (e->is_timeout(e, 5000))
|
||||||
|
{
|
||||||
|
e->state--;
|
||||||
|
if (++e->i > 3)
|
||||||
|
{
|
||||||
|
logDebug("MQTT subscribe error!\r\n");
|
||||||
|
IotFlag_t.Connect_error_flag = 1;
|
||||||
|
e->finish(e, AT_RESP_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void BSP_MQTT_CfgConnSub(void)
|
||||||
|
{
|
||||||
|
at_do_work(ml307r_obj, NULL, MQTT_CfgConnSub);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief 创建设备
|
* @brief 创建设备
|
||||||
* @return
|
* @return
|
||||||
|
@ -557,7 +737,8 @@ static int BSP_Module_Connect_CtWing_Handle(at_env_t *e)
|
||||||
//连接服务器
|
//连接服务器
|
||||||
static void BSP_Module_Connect_CtWing(void)
|
static void BSP_Module_Connect_CtWing(void)
|
||||||
{
|
{
|
||||||
at_do_work(ml307r_obj, NULL, BSP_Module_Connect_CtWing_Handle);//创建设备
|
BSP_MQTT_CfgConnSub();
|
||||||
|
// at_do_work(ml307r_obj, NULL, BSP_Module_Connect_CtWing_Handle);//创建设备
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -577,13 +758,13 @@ typedef struct {
|
||||||
uint16_t length; // JSON字符串长度
|
uint16_t length; // JSON字符串长度
|
||||||
} Ts4GJsonData;
|
} Ts4GJsonData;
|
||||||
|
|
||||||
/**
|
/**********************************
|
||||||
* @brief 生成4G模组上报的JSON数据
|
* @brief 生成4G模组上报的JSON数据
|
||||||
*
|
*
|
||||||
* @param p4GData JSON数据结构体指针
|
* @param p4GData JSON数据结构体指针
|
||||||
* @param cmd 命令类型,与蓝牙命令类型保持一致
|
* @param cmd 命令类型,与蓝牙命令类型保持一致
|
||||||
* @return uint8_t 0表示成功
|
* @return uint8_t 0表示成功
|
||||||
*/
|
|
||||||
uint8_t BSP_4G_Generate_JsonData(Ts4GJsonData *p4GData, TeFrameCmd cmd)
|
uint8_t BSP_4G_Generate_JsonData(Ts4GJsonData *p4GData, TeFrameCmd cmd)
|
||||||
{
|
{
|
||||||
// 首先清零JSON缓冲区
|
// 首先清零JSON缓冲区
|
||||||
|
@ -647,7 +828,94 @@ uint8_t BSP_4G_Generate_JsonData(Ts4GJsonData *p4GData, TeFrameCmd cmd)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
********************/
|
||||||
|
/**
|
||||||
|
* @brief 生成4G模组上报的JSON数据
|
||||||
|
*
|
||||||
|
* @param p4GData JSON数据结构体指针
|
||||||
|
* @param cmd 命令类型,与蓝牙命令类型保持一致
|
||||||
|
* @return uint8_t 0表示成功
|
||||||
|
*/
|
||||||
|
uint8_t BSP_4G_Generate_JsonData(Ts4GJsonData *p4GData, TeFrameCmd cmd)
|
||||||
|
{
|
||||||
|
// 首先清零JSON缓冲区
|
||||||
|
memset(p4GData->json_buffer, 0, JSON_BUFFER_SIZE);
|
||||||
|
|
||||||
|
// 获取阀门数据
|
||||||
|
TsValveData ValveData;
|
||||||
|
|
||||||
|
// 填充阀门数据,与蓝牙上报相同
|
||||||
|
ValveData.switch_status = gValveData.switch_status;
|
||||||
|
ValveData.temp = ValveRawData.atom_temp;
|
||||||
|
ValveData.in_pressure = ValveRawData.in_press_raw;
|
||||||
|
ValveData.out_pressure = ValveRawData.out_press_raw;
|
||||||
|
ValveData.atm_pressure = ValveRawData.atom_press;
|
||||||
|
ValveData.type = kZbf;
|
||||||
|
ValveData.bat = BSP_ReadVbat();
|
||||||
|
ValveData.humi = 50;
|
||||||
|
ValveData.rssi = gValveData.rssi;
|
||||||
|
|
||||||
|
// 解析信号强度,这里简单处理为0-5的整数值
|
||||||
|
int signal_strength = 0;
|
||||||
|
long rssi = strtol(Service_Info_t.rssi, NULL, 16);
|
||||||
|
if (rssi > -90) signal_strength = 5;
|
||||||
|
else if (rssi > -100) signal_strength = 4;
|
||||||
|
else if (rssi > -110) signal_strength = 3;
|
||||||
|
else if (rssi > -120) signal_strength = 2;
|
||||||
|
else if (rssi > -130) signal_strength = 1;
|
||||||
|
|
||||||
|
// 获取当前时间戳
|
||||||
|
uint32_t timestamp = 0;
|
||||||
|
if (Network_Time_t.tm_year > 0) {
|
||||||
|
struct tm timeinfo;
|
||||||
|
timeinfo.tm_year = Network_Time_t.tm_year;
|
||||||
|
timeinfo.tm_mon = Network_Time_t.tm_mon;
|
||||||
|
timeinfo.tm_mday = Network_Time_t.tm_mday;
|
||||||
|
timeinfo.tm_hour = Network_Time_t.tm_hour;
|
||||||
|
timeinfo.tm_min = Network_Time_t.tm_min;
|
||||||
|
timeinfo.tm_sec = Network_Time_t.tm_sec;
|
||||||
|
timestamp = utc_to_timestamp(&timeinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成MQTT格式的JSON字符串
|
||||||
|
p4GData->length = snprintf(p4GData->json_buffer, JSON_BUFFER_SIZE,
|
||||||
|
"{"
|
||||||
|
"\"sn\":\"%s\","
|
||||||
|
"\"t\":%u,"
|
||||||
|
"\"type\":%d,"
|
||||||
|
"\"data\":{"
|
||||||
|
"\"switch_status\":%d,"
|
||||||
|
"\"temp\":%d,"
|
||||||
|
"\"in_pressure\":%d,"
|
||||||
|
"\"out_pressure\":%d,"
|
||||||
|
"\"atm_pressure\":%d,"
|
||||||
|
"\"type\":%d,"
|
||||||
|
"\"bat\":%d,"
|
||||||
|
"\"humi\":%d,"
|
||||||
|
"\"rssi\":%d,"
|
||||||
|
"\"signal\":%d"
|
||||||
|
"}"
|
||||||
|
"}",
|
||||||
|
device_sn,
|
||||||
|
timestamp,
|
||||||
|
cmd,
|
||||||
|
ValveData.switch_status,
|
||||||
|
ValveData.temp,
|
||||||
|
ValveData.in_pressure,
|
||||||
|
ValveData.out_pressure,
|
||||||
|
ValveData.atm_pressure,
|
||||||
|
ValveData.type,
|
||||||
|
ValveData.bat,
|
||||||
|
ValveData.humi,
|
||||||
|
ValveData.rssi,
|
||||||
|
signal_strength
|
||||||
|
);
|
||||||
|
|
||||||
|
// 打印JSON数据信息
|
||||||
|
logDebug("MQTT JSON数据 (cmd=%d):\r\n%s", cmd, p4GData->json_buffer);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @brief 生成4G模组响应JSON数据
|
* @brief 生成4G模组响应JSON数据
|
||||||
*
|
*
|
||||||
|
@ -680,6 +948,7 @@ uint8_t BSP_4G_Generate_Response(Ts4GJsonData *p4GData, TeFrameCmd responseCmd,
|
||||||
Ts4GJsonData g4GJsonData;
|
Ts4GJsonData g4GJsonData;
|
||||||
char *json_data;
|
char *json_data;
|
||||||
|
|
||||||
|
/*******************************************
|
||||||
static int SendMessage(at_env_t *e)
|
static int SendMessage(at_env_t *e)
|
||||||
{
|
{
|
||||||
switch (e->state)
|
switch (e->state)
|
||||||
|
@ -717,6 +986,45 @@ static int SendMessage(at_env_t *e)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
**************************************************/
|
||||||
|
static int SendMessage(at_env_t *e)
|
||||||
|
{
|
||||||
|
switch (e->state)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
logDebug("MQTT SendMessage start!\r\n");
|
||||||
|
// 使用MQTT发布命令发送JSON数据
|
||||||
|
e->println(e, "AT+MQTTPUB=0,\"%s\",0,0,0,0,\"%s\"", MQTT_TOPIC_UP, json_data);
|
||||||
|
e->reset_timer(e);
|
||||||
|
e->state++;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (e->contains(e, "OK"))
|
||||||
|
{
|
||||||
|
logDebug("MQTT SendMessage end!\r\n");
|
||||||
|
IotFlag_t.send_complete_flag = 1;
|
||||||
|
// 发送完成后释放json_data内存
|
||||||
|
tmos_msg_deallocate((uint8_t *)json_data);
|
||||||
|
json_data = NULL;
|
||||||
|
e->finish(e, AT_RESP_OK);
|
||||||
|
}
|
||||||
|
if (e->is_timeout(e, 5000))
|
||||||
|
{
|
||||||
|
e->state--;
|
||||||
|
if (++e->i > 3)
|
||||||
|
{
|
||||||
|
logDebug("MQTT SendMessage error!\r\n");
|
||||||
|
IotFlag_t.send_complete_flag = 1;
|
||||||
|
// 发送失败也需要释放json_data内存
|
||||||
|
tmos_msg_deallocate((uint8_t *)json_data);
|
||||||
|
json_data = NULL;
|
||||||
|
e->finish(e, AT_RESP_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void BSP_SendMessage(void)
|
static void BSP_SendMessage(void)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue