Files
BLV_C1F_Module/BasicCode/Drive/MQTT/mqtt.c
caocong 95916b9995 fix:修改UDP通讯中,取电变化上报机制
1、问题点:当RCU网络状态异常的情况下,网络还处于协商状态下,还未进入正常通讯环节时,取电变化不会进行判断。这会导致取电变化上报与实际产生取电状态时间点对不上。
2、将BLV_C1F_Module代码上传至Gitea,之前代码修改记录请查看 .\BasicCode\Readme.txt
2026-01-23 09:23:12 +08:00

1136 lines
36 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/********************************** (C) COPYRIGHT ******************************
* File Name : MQTT_Sub.c
* Author : WCH
* Version : V1.0
* Date : 2018/12/01
* Description : 基于TCP/IP的MQTT协议通讯例程实现以MQTT方式通过百度、阿里云物联网服务器实现设备互通使用前需设置帐号和密码
* (1)、CH579 Examples by KEIL;
* (2)、串口0输出监控信息,115200bps,打开或者关闭调试信息打印输出在IDE宏定义中设置;
* (3)、本程序用于演示基于TCP/IP的MQTT协议通讯
此程序演示SUB的过程
* log 202204211400 打印MQTT发起连接数据 发起订阅数据 连接回复 订阅回复
* 202204231151 MQTT发送的数据存储到日志
*******************************************************************************/
/******************************************************************************/
/* 头文件包含*/
#include <stdio.h>
#include <string.h>
#include "net.h"
#include "aLiYun.h"
#include "mqtt.h"
#include "SPI_SRAM.h"
#include "DBG.h"
#include "PC_DeviceTest_Fun.h"
#include "flash.h"
#include "rtc.h"
#include "includes.h"
#define KEEPLIVE_ENABLE 1 /* 开启KEEPLIVE功能 */
/* 本演示程序的相关宏 */
#define RECE_BUF_LEN 536 /* 接收缓冲区的大小 */
/* CH57xNET库TCP的MSS长度为536字节即一个TCP包里的数据部分最长为536字节 */
/* TCP协议栈采用滑动窗口进行流控窗口最大值为socket的接收缓冲区长度。在设定 */
/* RX_QUEUE_ENTRIES时要考虑MSS和窗口之间的关系例如窗口值为4*MSS则远端一次会发送 */
/* 4个TCP包如果RX_QUEUE_ENTRIES小于4则必然会导致数据包丢失从而导致通讯效率降低 */
/* 建议RX_QUEUE_ENTRIES要大于( 窗口/MSS ),如果多个socket同时进行大批量发送数据则 */
/* 建议RX_QUEUE_ENTRIES要大于(( 窗口/MSS )*socket个数) 在多个socket同时进行大批数据收发时 */
/* 为了节约RAM请将接收缓冲区的长度设置为MSS */
#if MQTT_EN
#define MQTT_NORMALDATA_UP_FLAG 0x01
#endif
UINT16 aport=1000; /* CH579源端口 */
#if MQTT_EN
/*本地函数申明开始*/
uint8_t MQTT_NoramlData_Up(void);
uint8_t MQTT_WxLock_Ctrl(uint8_t *buf);
void MQTT_Dev_Ctrl(uint8_t *buf);
void TimeSetUseStamp(uint32_t TimeStamp);
/*本地函数申明结束*/
MQTT_INFO mqtt_info = {
.init_flag = 0, /*开启初始化标记*/
.con_flag = 0, /* 已连接MQTT服务器标志位 */
.pub_flag = 1, /* 已发布会话消息标志位 */
.sub_flag = 0, /* 已订阅会话标志位 */
.tout_flag = 0, /* 超时标志位 */
.domain_dns = 0, //mqtt域名解析标志
.reconnect = 3, //失败重连次数
.keepAliveInterval = 60, //保持在线时间
.packetid = 0, /* 包ID */
.username = /*USER_NAME*/NULL, /* 设备名,每个设备唯一,可用”/“做分级 */
.password = /*PASSWORD*/NULL, /* 服务器登陆密码 */
.sub_topic = /*SUB_TOPIC*/NULL, /* 订阅的会话名, */
.pub_topic = /*PUB_TOPIC*/NULL, /* 发布的会话*/
.mqtt_socket = 0, //存放mqtt 套接字
.MyBuf = {0},
.Sram_write_addr = SRAM_MQTT_RECEIVE_START, //
.Sram_read_addr = SRAM_MQTT_RECEIVE_START, //
};
#endif
#if MQTT_EN
/*******************************************************************************
* Function Name : Transport_Open
* Description : 创建TCP连接
* Input : UINT8* dis_ip目的ip,
UINT32 sour_port源端口
* Output : None
* Return : 创建的套接字索引
*******************************************************************************/
UINT8 Transport_Open(MQTT_INFO* Mqtt_info, UINT8* des_ip, UINT32 sour_port)
{
UINT8 i,s;
SOCK_INF TmpSocketInf; /* 创建临时socket变量 */
if(Mqtt_info == NULL) return 0xFF;
memset((void *)&TmpSocketInf,0,sizeof(SOCK_INF)); /* 库内部会将此变量复制,所以最好将临时变量先全部清零 */
memcpy((void *)TmpSocketInf.IPAddr, des_ip, 4); /* 设置目的IP地址 */
TmpSocketInf.DesPort = 1883; /* 设置目的端口 */
TmpSocketInf.SourPort = /*aport++*/sour_port; /* 设置源端口 */
TmpSocketInf.ProtoType = PROTO_TYPE_TCP; /* 设置socekt类型 */
TmpSocketInf.RecvStartPoint = (UINT32)/*SocketRecvBuf*/&Mqtt_info->MyBuf[0]; /* 设置接收缓冲区的接收缓冲区 */
TmpSocketInf.RecvBufLen = RECE_BUF_LEN ; /* 设置接收缓冲区的接收长度 */
i = CH57xNET_SocketCreat(&s, &TmpSocketInf); /* 创建socket将返回的socket索引保存在SocketId中 */
mStopIfError(i); /* 检查错误 */
i = CH57xNET_SocketConnect(s); /* TCP连接 */
mStopIfError(i); /* 检查错误 */
return s;
}
/*******************************************************************************
* Function Name : Transport_Close
* Description : 关闭TCP连接
* Input : UINT8 S要关闭的TCP套接字
* Output : None
* Return : 错误码
*******************************************************************************/
UINT8 Transport_Close(UINT8 S)
{
UINT8 i;
i=CH57xNET_SocketClose(S, TCP_CLOSE_NORMAL);
mStopIfError(i);
return i;
}
/*******************************************************************************
* Function Name : Transport_SendPacket
* Description : 以太网发送数据
* Input : UINT8 S套接字
UINT8 *buf 发送数据的首字节地址
UINT32 len 发送数据的长度
* Output : None
* Return : None
*******************************************************************************/
void Transport_SendPacket(UINT8 S, UINT8 *buf, UINT32 len)
{
UINT32 totallen;
UINT8 *p=buf;
UINT8 ReNum=0; //剩余数据重发次数 2022-07-07
totallen=len;
while(1)
{
len = totallen;
CH57xNET_SocketSend(S, p, &len); /* 将MyBuf中的数据发送 */
totallen -= len; /* 将总长度减去以及发送完毕的长度 */
p += len; /* 将缓冲区指针偏移*/
if(totallen)
{
Dbg_Print(DBG_BIT_NET_STATUS_bit,"剩余totallen%d", totallen);
ReNum++;
if(ReNum>3){ break;} //剩余数据重发次数超过3次跳出循环 2022-07-07
continue; /* 如果数据未发送完毕,则继续发送*/
}
break; /* 发送完毕,退出 */
}
}
/*******************************************************************************
* Function Name : MQTT_Connect
* Description : 创建MQTT连接
* Input : UINT8 S套接字
char* clientIDclientID
char *username 设备名
char *password 服务器连接密码
int keepAliveInterval :保持在线时间
* Output : None
* Return : None
*******************************************************************************/
void MQTT_Connect(UINT8 S, char* clientID, char *username, char *password, int keepAliveInterval)
{
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
if(clientID == NULL || username == NULL || password == NULL)
{
Dbg_Print(DBG_BIT_NET_STATUS_bit,"MQTT连接参数为空\r\n");
return;
}
UINT32 len = strlen(clientID) + strlen(username) + strlen(password) + 25;
UINT8* buf = malloc(len);
if(buf == NULL) return;
//data.clientID.cstring = "11";
data.clientID.cstring = clientID;
data.keepAliveInterval = keepAliveInterval;
data.cleansession = 1;
data.username.cstring = username;
data.password.cstring = password;
len=MQTTSerialize_connect(buf, len, &data);
Dbg_Print(DBG_BIT_NET_STATUS_bit,"发起连接长度:%d\r\n", len);
Dbg_Print_Buff(DBG_BIT_NET_STATUS_bit,"Send Buff:",buf, len);
Transport_SendPacket(S, buf, len);
LOG_NET_COMM_Send_Record(S,mqtt_info.des_ip,1883,&buf[0],len);
free(buf);
}
/*******************************************************************************
* Function Name : MQTT_Subscribe
* Description : MQTT订阅一个主题
* Input : UINT8 S套接字
char *topic 订阅的主题名
* Output : None
* Return : None
*******************************************************************************/
void MQTT_Subscribe(UINT8 S, char *topic)
{
MQTTString topicString = MQTTString_initializer;
if(topic == NULL) return;
UINT32 len = strlen(topic)+ 10;
UINT8* buf = malloc(len);
if(buf == NULL) return;
int req_qos=0;
UINT32 msgid=1;
topicString.cstring=topic;
len=MQTTSerialize_subscribe(buf, len, 0, msgid, 1, &topicString, &req_qos);
Dbg_Print(DBG_BIT_NET_STATUS_bit,"发起订阅长度:%d\r\n SocketId:%d", len, S);
Transport_SendPacket(S, buf, len);
LOG_NET_COMM_Send_Record(S,mqtt_info.des_ip,1883,&buf[0],len);
free(buf);
}
/*******************************************************************************
* Function Name : MQTT_Unsubscribe
* Description : MQTT取消订阅一个主题
* Input : UINT8 S套接字
char *topic 取消订阅的主题名
* Output : None
* Return : None
*******************************************************************************/
void MQTT_Unsubscribe(UINT8 S, char *topic)
{
MQTTString topicString = MQTTString_initializer;
if(topic == NULL) return;
UINT32 len = strlen(topic)+ 20;
UINT8* buf = malloc(len);
if(buf == NULL) return;
UINT32 msgid=1;
topicString.cstring=topic;
len=MQTTSerialize_unsubscribe(buf, len, 0, msgid, 1, &topicString);
Dbg_Print(DBG_BIT_NET_STATUS_bit,"取消订阅长度:%d\r\n", len);
Transport_SendPacket(S, buf, len);
LOG_NET_COMM_Send_Record(S,mqtt_info.des_ip,1883,&buf[0],len);
free(buf);
}
/*******************************************************************************
* Function Name : MQTT_Publish
* Description : MQTT发布信息
* Input : UINT8 S套接字
char *topic 发布的主题名
int qos消息等级
* Output : None
* Return : None
*******************************************************************************/
void MQTT_Publish(UINT8 S, char *topic, UINT8 *payload, int payloadlen, int qos)
{
#if MQTT_EN
MQTTString topicString = MQTTString_initializer;
if(topic == NULL || payload == NULL) return;
UINT32 len = strlen(topic) + payloadlen + 10;
UINT8* buf = malloc(len);
if(buf == NULL) return;
topicString.cstring = topic;
len= MQTTSerialize_publish(buf, len, 0, qos, 0, mqtt_info.packetid++, topicString, payload, payloadlen);
Dbg_Print(DBG_BIT_NET_STATUS_bit,"发布消息长度:%d\r\n S:%d", len, S);
Dbg_Print_Buff(DBG_BIT_NET_STATUS_bit,"data :",buf,len);
Transport_SendPacket(S, buf, len);
LOG_NET_COMM_Send_Record(S,mqtt_info.des_ip,1883,&buf[0],len);
Dbg_Print(DBG_BIT_NET_STATUS_bit,"发布数据结束\r\n");
free(buf);
#endif
}
/*******************************************************************************
* Function Name : MQTT_Pingreq
* Description : MQTT发送心跳包
* Input : UINT8 S套接字
* Output : None
* Return : None
*******************************************************************************/
void MQTT_Pingreq(UINT8 S)
{
UINT32 len;
UINT8 buf[20];
len=MQTTSerialize_pingreq(buf,sizeof(buf));
Dbg_Print(DBG_BIT_NET_STATUS_bit,"心跳包长度:%d\r\n", len);
Transport_SendPacket(S, buf, len);
LOG_NET_COMM_Send_Record(S,mqtt_info.des_ip,1883,&buf[0],len);
}
/*******************************************************************************
* Function Name : MQTT_Disconnect
* Description : 断开MQTT连接
* Input : UINT8 S套接字
* Output : None
* Return : None
*******************************************************************************/
void MQTT_Disconnect(UINT8 S)
{
UINT32 len;
UINT8 buf[50];
len=MQTTSerialize_disconnect(buf,sizeof(buf));
Transport_SendPacket(S, buf, len);
LOG_NET_COMM_Send_Record(S,mqtt_info.des_ip,1883,&buf[0],len);
}
/*******************************************************************************
* Function Name : MQTT_Init
* Description : 初始化MQTT
* Input : domain_name域名使用域名需要把ip填写NULL (动态分配函数有free的操作)
* des_ip: MQTT服务器ip此参数用于直接使用IP地址连接的情况
* clientID: clientID (动态分配函数有free的操作)
* username: 设备名 (动态分配函数有free的操作)
* password密码 (动态分配函数有free的操作)
sublish: 订阅地址 (动态分配函数有free的操作)
* keepAliveInterval保持在线时间
* Output : None
* Return : 返回0表示参数配置成功
*******************************************************************************/
UINT8 MQTT_Init(MQTT_INFO* Mqtt_info, char* domain_name, UINT8* des_ip, char* clientID, char *username, char *password, char* sublish, int keepAliveInterval)
{
#if MQTT_EN
if(Mqtt_info == NULL || clientID ==NULL || username == NULL || password == NULL || sublish == NULL) return 1; //参数错误
if(des_ip == NULL) //目的ip为空
{
if(domain_name == NULL) return 1; //域名也为空 参数错误
// if(server_info.net_sta != NET_COMPLETE) return 2; //网络繁忙
Mqtt_info->dns_en = 1; //DNS解析MQTT域名
// server_info.dns_sta = DNS_INIT;
// server_info.net_sta = NET_DNS; //状态置为 NET_DNS
if(Mqtt_info->domain_name)
{
free(Mqtt_info->domain_name);
}
Mqtt_info->domain_name = domain_name;
// server_info.dns_domian_name = domain_name;
}
else
{
memcpy(&Mqtt_info->des_ip, des_ip, 4);
// if(server_info.net_sta != NET_COMPLETE) return 1;
// server_info.net_sta = NET_MQTT_INIT; //状态置为,NET_MQTT_INIT
}
if(Mqtt_info->clientID)
{
free(Mqtt_info->clientID);
}
if(Mqtt_info->username)
{
free(Mqtt_info->username);
}
if(Mqtt_info->password)
{
free(Mqtt_info->password);
}
if(Mqtt_info->sub_topic)
{
free(Mqtt_info->sub_topic);
}
Mqtt_info->clientID = clientID;
Mqtt_info->username = username;
Mqtt_info->password = password;
Mqtt_info->sub_topic = sublish;
Mqtt_info->keepAliveInterval = keepAliveInterval;
Mqtt_info->init_flag = 1;
Mqtt_info->reconnect = 3;
#endif
return 0;
}
/*******************************************************************************
* Function Name : MQTT_SET_SUB_Topic
* Description : 初始化MQTT_订阅参数
* Input : topic订阅参数
* Output : None
* Return : None
*******************************************************************************/
void MQTT_SET_SUB_Topic(MQTT_INFO* Mqtt_info, char* topic)
{
if(topic != NULL)
{
Mqtt_info->sub_topic = topic;
}
}
/*******************************************************************************
* Function Name : MQTT_SET_PUB_Topic
* Description : 初始化MQTT_订阅参数
* Input : topic订阅参数
* Output : None
* Return : None
*******************************************************************************/
void MQTT_SET_PUB_Topic(MQTT_INFO* Mqtt_info, char* topic)
{
if(topic != NULL)
{
Mqtt_info->pub_topic = topic;
}
}
/*******************************************************************************
* Function Name : MQTT_Flash_Parameter_Init
* Description : 从flash获取参数初始化mqtt
* Input : topic订阅参数
* Output : None
* Return : None
*******************************************************************************/
UINT8 MQTT_Flash_Parameter_Init(MQTT_INFO* Mqtt_info)
{
if(Mqtt_info == NULL) return 1;
/*分配内存*/
MQTT_DATA mqtt_data;
mqtt_data.mqtt_basic_info = malloc(sizeof(MQTT_BASIC_INFO));
if(mqtt_data.mqtt_basic_info == NULL)
{
return 2;
}
UINT8 ret = 0;
UINT16 keepAlive = 0;
char* domain_name = NULL;
char* clientID = NULL;
char* userName = NULL;
char* passWord = NULL;
char* sublish = NULL;
char* publish = NULL;
Flash_Read((UINT8*)&mqtt_data ,sizeof(MQTT_DATA)-4, FLASH_MCU_MQTT_START_ADDRESS + sizeof(ALIYUN_INFO) -4-2);
Flash_Read((UINT8*)mqtt_data.mqtt_basic_info ,sizeof(MQTT_BASIC_INFO), FLASH_MCU_MQTT_START_ADDRESS + sizeof(ALIYUN_INFO)-4);
Dbg_Println(DBG_BIT_Debug_STATUS_bit,"keepAliveInterval:%d", mqtt_data.keepAliveInterval);
Dbg_Println(DBG_BIT_Debug_STATUS_bit,"sublish:%s", mqtt_data.mqtt_basic_info->mqtt_theme.sublish);
Dbg_Println(DBG_BIT_Debug_STATUS_bit,"publish:%s", mqtt_data.mqtt_basic_info->mqtt_theme.publish);
Dbg_Println(DBG_BIT_Debug_STATUS_bit,"domain_name:%s", mqtt_data.mqtt_basic_info->domain_name);
Dbg_Println(DBG_BIT_Debug_STATUS_bit,"clientID:%s", mqtt_data.mqtt_basic_info->clientID);
Dbg_Println(DBG_BIT_Debug_STATUS_bit,"username:%s", mqtt_data.mqtt_basic_info->username);
Dbg_Println(DBG_BIT_Debug_STATUS_bit,"password:%s", mqtt_data.mqtt_basic_info->password);
if(mqtt_data.keepAliveInterval < 0xFFFF)
{
keepAlive = mqtt_data.keepAliveInterval;
}
else //参数不合法,使用默认值
{
keepAlive = 120;
}
if(mqtt_data.mqtt_basic_info->mqtt_theme.sublish[0] != 0xFF && mqtt_data.mqtt_basic_info->mqtt_theme.sublish[0] != 0x00)
{
UINT8 len = strlen((char*)mqtt_data.mqtt_basic_info->mqtt_theme.sublish)+1;
sublish = malloc(len);
if(sublish == NULL)
{
ret = 2;
goto reault;
}
memset(sublish, 0, len);
strcpy(sublish, (char*)mqtt_data.mqtt_basic_info->mqtt_theme.sublish);
}
else //参数不合法,返回
{
ret = 3;
goto reault;
}
if(mqtt_data.mqtt_basic_info->domain_name[0] != 0xFF && mqtt_data.mqtt_basic_info->domain_name[0] != 0x00)
{
UINT8 len = strlen((char*)mqtt_data.mqtt_basic_info->domain_name)+1;
domain_name = malloc(len);
if(domain_name == NULL)
{
ret = 2;
goto reault;
}
memset(domain_name, 0, len);
strcpy(domain_name, (char*)mqtt_data.mqtt_basic_info->domain_name);
}
else //参数不合法,返回
{
ret = 3;
goto reault;
}
if(mqtt_data.mqtt_basic_info->clientID[0] != 0xFF && mqtt_data.mqtt_basic_info->clientID[0] != 0x00)
{
UINT8 len = strlen((char*)mqtt_data.mqtt_basic_info->clientID)+1;
clientID = malloc(len);
if(clientID == NULL)
{
ret = 2;
goto reault;
}
memset(clientID, 0, len);
strcpy(clientID, (char*)mqtt_data.mqtt_basic_info->clientID);
}
else //参数不合法,返回
{
ret = 3;
goto reault;
}
if(mqtt_data.mqtt_basic_info->username[0] != 0xFF && mqtt_data.mqtt_basic_info->username[0] != 0x00)
{
UINT8 len = strlen((char*)mqtt_data.mqtt_basic_info->username)+1;
userName = malloc(len);
if(userName == NULL)
{
ret = 2;
goto reault;
}
memset(userName, 0, len);
strcpy(userName, (char*)mqtt_data.mqtt_basic_info->username);
}
else //参数不合法,返回
{
ret = 3;
goto reault;
}
if(mqtt_data.mqtt_basic_info->password[0] != 0xFF && mqtt_data.mqtt_basic_info->password[0] != 0x00)
{
UINT8 len = strlen((char*)mqtt_data.mqtt_basic_info->password)+1;
passWord = malloc(len);
if(passWord == NULL)
{
ret = 2;
goto reault;
}
memset(passWord, 0, len);
strcpy(passWord, (char*)mqtt_data.mqtt_basic_info->password);
}
else //参数不合法,返回
{
ret = 3;
goto reault;
}
if(mqtt_data.mqtt_basic_info->mqtt_theme.publish[0] != 0xFF && mqtt_data.mqtt_basic_info->mqtt_theme.publish[0] != 0x00)
{
UINT8 len = strlen((char*)mqtt_data.mqtt_basic_info->mqtt_theme.publish)+1;
publish = malloc(len);
if(publish == NULL)
{
ret = 4;
goto reault;
}
memset(publish, 0, len);
strcpy(publish, (char*)mqtt_data.mqtt_basic_info->mqtt_theme.publish);
if(Mqtt_info->pub_topic)
{
free(Mqtt_info->pub_topic);
}
Mqtt_info->pub_topic = publish;
}
reault:
switch(ret)
{
case 0: //无错误
case 4: //publish错误不影响初始化
free(mqtt_data.mqtt_basic_info); //释放内存
return MQTT_Init(Mqtt_info, domain_name, NULL, clientID, userName, passWord, sublish, keepAlive); //初始化MQTT
default: //有错误
Dbg_Println(DBG_BIT_Debug_STATUS_bit,"MQTT_Flash_Parameter err");
free(mqtt_data.mqtt_basic_info);
if(domain_name) free(domain_name);
if(clientID) free(clientID);
if(userName) free(userName);
if(passWord) free(passWord);
if(sublish) free(sublish);
if(publish) free(publish);
return ret;
}
}
/*------------------------------------------------------------*/
/* MQTT上报命令 */
/*------------------------------------------------------------*/
void MQTT_CMD_A5(UINT8 S, char* topic, UINT8 cmdhead, UINT8* cmdID, UINT8 result) //形参为命令头和执行结果
{
#if MQTT_EN
uint32_t timetemp;
UINT8 Cmd_buff[19] = {0};
timetemp = RTC_Conversion_To_Unix(&RTC_Raw_Data);
Cmd_buff[0] = 0xA5; //固定A5命令
Cmd_buff[1] = cmdhead;
memcpy(&Cmd_buff[2],cmdID,CmdID_LEN); //加命令
memcpy(&Cmd_buff[2+CmdID_LEN], MACAddr, DeviceID_LEN); //加设备MAC地址
HtolCpy((&Cmd_buff[2+CmdID_LEN+DeviceID_LEN]), timetemp);
Cmd_buff[17] = result;
MQTT_Publish(S, topic, Cmd_buff, 19, 0);
#endif
}
#if MQTT_NORMALDATA_UP_FLAG
/**
* @name 门锁透传数据上报
* @param 无
* @retval 1有门锁透传数据上报 0无门锁透传数据上报
* @attention 找到福瑞狗的蓝牙锁,判断蓝牙锁的全局变量是否置透传标志位,请求开锁标志位
*/
uint8_t MQTT_CMD_A6(void) //u8* cmdID, u8 * DeviceID,u8* UTCTime
{
uint8_t Ret = 0x00;
#if MQTT_EN
uint32_t timetemp = RTC_Conversion_To_Unix(&RTC_Raw_Data); //TIMESTAMP
Device_Public_Information_G BUS_Public;
RS485_WxLock_INFO Rs485WxLockInfo;
uint8_t Cmd_buff[200];
uint8_t KeepFlag = 0x00;
uint32_t dev_addr;
if(NULL == DevActionGlobal.DevLockAddr) //HostRunInfo.CfgDevAddWxLock
{
return Ret; //
}
dev_addr = DevActionGlobal.DevLockAddr;
// Rs485WxLockInfo = HostRunInfo.CfgDevAddWxLock->DevDataStruct;
SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),dev_addr);
SRAM_DMA_Read_Buff((uint8_t *)&Rs485WxLockInfo,sizeof(RS485_WxLock_INFO),dev_addr+Dev_Privately);
if(0x01 == Rs485WxLockInfo.WeixinUpSendFlag) //透传标志
{
Rs485WxLockInfo.WeixinUpSendFlag = 0x00;
KeepFlag = 0x01;
Cmd_buff[1+DeviceID_LEN+UTCTime_LEN] = Rs485WxLockInfo.WeixinUpMessageLen;//
memcpy(&Cmd_buff[1+DeviceID_LEN+UTCTime_LEN+0x01], Rs485WxLockInfo.WeixinUpMessage, Rs485WxLockInfo.WeixinUpMessageLen);
Ret = 0x01;
Cmd_buff[0] = 0xA6;
// MacAddrCpy(&Cmd_buff[1]); //拷贝设备ID即mac地址 6个字节
memcpy(&Cmd_buff[1], MACAddr, DeviceID_LEN); //加设备MAC地址
HtolCpy((&Cmd_buff[1+DeviceID_LEN]), timetemp);
MQTT_Publish(mqtt_info.mqtt_socket, mqtt_info.pub_topic, Cmd_buff, 1+Rs485WxLockInfo.WeixinUpMessageLen+1+DeviceID_LEN+UTCTime_LEN, 0);
Dbg_Println(DBG_BIT_NET_STATUS_bit,"发送A6 透传发送命令\r\n");
Dbg_Print_Buff(DBG_BIT_NET_STATUS_bit,"A6 透传 Send Buff:",Cmd_buff,1+Rs485WxLockInfo.WeixinUpMessageLen+1+DeviceID_LEN+UTCTime_LEN);
// MQTT_PublishQs0(PTopicName,(char *)Cmd_buff ,1+Rs485WxLockInfo->WeixinUpMessageLen+1+DeviceID_LEN+UTCTime_LEN);
}
else if(0x01 == Rs485WxLockInfo.WeixinAskLockFlag)
{
Rs485WxLockInfo.WeixinAskLockFlag = 0x00;
KeepFlag = 0x01;
Cmd_buff[0] = 0xAA;
Ret = 0x01;
memcpy(&Cmd_buff[1], MACAddr, DeviceID_LEN); //加设备MAC地址
// MacAddrCpy(&Cmd_buff[1]); //拷贝设备ID即mac地址 6个字节
HtolCpy((&Cmd_buff[1+DeviceID_LEN]), timetemp);
Cmd_buff[1+DeviceID_LEN+UTCTime_LEN] = 0x01; //请求开锁
MQTT_Publish(mqtt_info.mqtt_socket, mqtt_info.pub_topic, Cmd_buff, 0x01+1+DeviceID_LEN+UTCTime_LEN, 0);
Dbg_Println(DBG_BIT_NET_STATUS_bit,"发送AA请求开锁命令\r\n");
Dbg_Print_Buff(DBG_BIT_NET_STATUS_bit,"AA 开锁Send Buff:",Cmd_buff,0x01+1+DeviceID_LEN+UTCTime_LEN);
// MQTT_PublishQs0(PTopicName,(char *)Cmd_buff ,0x01+1+DeviceID_LEN+UTCTime_LEN);
}
if(0x01 == KeepFlag)
{
BUS_Public.check = 0x00;
BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&Rs485WxLockInfo, sizeof(RS485_WxLock_INFO));
SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),dev_addr);/*将数据保存*/
SRAM_DMA_Write_Buff((uint8_t *)&Rs485WxLockInfo,sizeof(RS485_WxLock_INFO),dev_addr+Dev_Privately);
}
#endif
return Ret;
}
#endif
//#define MqttDevNumMax 50 //设备数量上限
#define Cmd_Buff_LEN (CFG_Dev_Freego_Map_MAX*24+20)
/*上报设备列表*/
void MQTT_CMD_A7(UINT8 S, char* topic) //上报设备启用(uint8_t *)
{
#if MQTT_EN
uint16_t len = 0;
uint32_t timetemp;
UINT8 Cmd_buff[Cmd_Buff_LEN];
timetemp = RTC_Conversion_To_Unix(&RTC_Raw_Data); //+ -8*3600
memset(Cmd_buff, 0x00, Cmd_Buff_LEN); //清0
len = MQTT_DevList_Get(&Cmd_buff[1+DeviceID_LEN+UTCTime_LEN]); //分配内存并读取设备列表
if(len == 0) return;
Cmd_buff[0] = 0xA7;
memcpy(&Cmd_buff[1], MACAddr, DeviceID_LEN);
HtolCpy((&Cmd_buff[1+DeviceID_LEN]), timetemp);
MQTT_Publish(S, topic, Cmd_buff, len+1+DeviceID_LEN+UTCTime_LEN, 0);
// free(Cmd_buff);
Dbg_Println(DBG_BIT_NET_STATUS_bit,"发送A7数据");
// memset(test_buff,0,sizeof(test_buff));
// HexToStr(test_buff,Cmd_buff,len+1+DeviceID_LEN+UTCTime_LEN);
// printf("%s\n",(char *)Cmd_buff);
// printf("\r\n发送A7结束\r\n ");
#endif
}
/**
* @name MQTT核心设备状态得到
* @param
* p 数组
* @retval 核心设备的个数
* @attention 遍历所有的设备,将需要上报的设备填入
*/
uint16_t MQTT_DevCoreStateGet(uint8_t *p)
{
return 0x00;
}
/**
* @name MQTT核心设备状态定期上报
* @param
* buf 上报数据用到的数组,每次只上报一个信息,如果有多个信息,就上报多条消息指令
* @retval 数组填充数据长度 非0有设备状态变化 0无设备状态变化
* @attention 内容固定 (FreegoDevStateLen*DevSum+1)个字节 不包括 消息ID4B设备ID6B和UTC时间4B
* 消息个数 消息详情
* [0] [1][2][3][4][5][6]
*/
uint16_t MQTT_CoreDev_Up(uint8_t *buf)
{
// Service_INFOP ServiceInfo;
// uint8_t i; //用于遍历所有的服务信息
uint16_t Ret = 0x00;
uint16_t DevSum = 0x00;
{
DevSum = MQTT_DevCoreStateGet(&buf[1]); //设备个数已经被限制
}
buf[0] = DevSum;
if(0x00 != DevSum) //
{
Ret = DevSum*0x06+0x01; //固定
}
return Ret;
}
/*MQTT核心数据上报,数据结构跟A8上报指令完全一样*/
uint8_t MQTT_CoreData_Up(void)
{
#if MQTT_EN
uint32_t timetemp; //指令时间
// uint16_t MqttDevContLen;
uint8_t Cmd_buff[50]; //
static uint32_t CoreDataUpTick;
if( SysTick_1ms - CoreDataUpTick > 60*1000) //1分钟执行一次
{
CoreDataUpTick = SysTick_1ms;
}
else
{
return 0x00;
}
// MqttDevContLen = MQTT_CoreDev_Up(&Cmd_buff[1+DeviceID_LEN+UTCTime_LEN]);//MQTT_Dev_Up(&Cmd_buff[1+DeviceID_LEN+UTCTime_LEN]);
// if(0x00 == MqttDevContLen)
// {
// return 0x00; //没有核心设备存在直接返回
// }
timetemp = RTC_Conversion_To_Unix(&RTC_Raw_Data) ; // TIMESTAMP;
Cmd_buff[0] = 0xA8; //固定A8命令
// Cmd_buff[1] = cmdhead;
// memcpy(&Cmd_buff[2],cmdID,CmdID_LEN); //加命令
memcpy(&Cmd_buff[1], MACAddr, DeviceID_LEN); //加设备MAC地址
HtolCpy((&Cmd_buff[1+DeviceID_LEN]), timetemp);
Cmd_buff[1+DeviceID_LEN+UTCTime_LEN] = 0x01; //上报1个设备
Cmd_buff[1+DeviceID_LEN+UTCTime_LEN+1] = 0x04; //服务信息
Cmd_buff[1+DeviceID_LEN+UTCTime_LEN+2] = 0x00;
Cmd_buff[1+DeviceID_LEN+UTCTime_LEN+3] = 0x00; //取电服务信息回路地址
Cmd_buff[1+DeviceID_LEN+UTCTime_LEN+4] = 0x00;
Cmd_buff[1+DeviceID_LEN+UTCTime_LEN+5] = DevActionGlobal.DevActionU64Cond.EleState; //状态
Cmd_buff[1+DeviceID_LEN+UTCTime_LEN+6] = 0x00;
MQTT_Publish(mqtt_info.mqtt_socket, mqtt_info.pub_topic, Cmd_buff, 20, 0);
Dbg_Println(DBG_BIT_NET_STATUS_bit,"发送A8定期数据开始\r\n");
// memset(test_buff,0,sizeof(test_buff));
// HexToStr(test_buff,Cmd_buff,MqttDevContLen+1+DeviceID_LEN+UTCTime_LEN);
Dbg_Println(DBG_BIT_NET_STATUS_bit,"发送A8定期结束\r\n");
#endif
return 0x01;
}
/**
* @name MQTT设备控制非空调类
* @param
* buf 一次传7个字节过来
* @retval 无
* @attention 共3类 1场景窗帘窗纱不调光灯带不调光射灯排气扇。2调光射灯。3调光灯带
* 设备分类 设备地址编码 开关控制 亮度控制 颜色控制
* [0] [1] [2] [3] [4][5][6]
*/
void MQTT_Dev_Ctrl(uint8_t *buf)
{
// CFG_Freego_Map_AddP CfgMapAdd;
// uint8_t DevCtrl[6];
uint8_t i; //灯带控制的3路遍历
for(i = 0; i < buf[0]; i++)
{
switch(buf[1])
{
case Dev_Host_Invalid: //场景
break;
default: //其他设备只要回路不为0就减1
if(0x00 != buf[3]) //回路不为0
{
buf[3]--;
}
break;
}
DevActionCtrl(&buf[1], 6);
}
}
/*用时间戳进行时间设置*/
void TimeSetUseStamp(uint32_t TimeStamp)
{
// uint32_t temp_unix;
S_RTC write_rtc;
memset(&write_rtc,0,sizeof(write_rtc));
Unix_Conversion_To_RTC(&write_rtc,TimeStamp);
RTC_WriteDate(write_rtc);
DevActionGlobal.TimeGetFlag++;
SRAM_Write_DW(TimeStamp,SRAM_Register_Start_ADDRESS + Register_CurrentUsageTime_OFFSET);
// Retain_Flash_Register_Data();
}
/*******************************************************************************
* Function Name : FRG_Data_Processing
* Description : 福瑞狗MQTT数据接收处理
* Input : S: 套接字
topic回复时的发布地址
data接收数据
datalen数据长度
qos: 消息发布等级
* Output : None
* Return : None
*******************************************************************************/
void FREEG_Data_Processing(UINT8 S, char* topic, UINT8* data, uint16_t datalen, int qos)
{
#if MQTT_EN
// UINT8 crc168_val = 0; //用于保存CRC_168校验的值
if(topic == NULL) return;
if((data[datalen-1] == CRC_168(data, datalen-1)) || (0xA4 == data[CMD_PKT]))
{
Dbg_Println(DBG_BIT_NET_STATUS_bit,"MQTT_Revice_crc success");
if(memcmp(MACAddr, &data[DEVICE_ID_PKT], 6) == 0) //设备ID一致
{
switch(data[CMD_PKT])
{
case 0xA0: //时间同步
Dbg_Println(DBG_BIT_NET_STATUS_bit,"MQTT_Time_Update");
{
uint32_t seccount=0;
uint8_t DecUTCTime[4]; //下发的utc时间
memcpy(DecUTCTime, &data[1+CmdID_LEN+DeviceID_LEN], 4);
seccount = (DecUTCTime[0]<<24) + (DecUTCTime[1]<<16) + (DecUTCTime[2]<<8) + DecUTCTime[3];
// seccount += TIME_MISS;
TimeSetUseStamp(seccount); //用时间戳设置计数寄存器,并更新时间
}
MQTT_CMD_A5(S, topic, data[CMD_PKT], &data[CMDID_PKT], CMD_SUCCESS); //指令执行成功
break;
case 0xA1: //平台配置设备工作参数等
Dbg_Println(DBG_BIT_NET_STATUS_bit,"MQTT_Config");
switch(data[PRAM_PKT])
{
case 0x01:
Dbg_Println(DBG_BIT_NET_STATUS_bit,"授权可通电\r\n");
break;
case 0x02:
Dbg_Println(DBG_BIT_NET_STATUS_bit,"授权不可通电\r\n");
break;
case 0x03:
{
Dbg_Println(DBG_BIT_NET_STATUS_bit,"远程立即开电\r\n");
// MQTT_Ele_Ctrl_Open();
// UINT8 control[6] = {0};
// control[0] = 0x04;
// control[1] = 0x00;
// control[2] = LOOPCH01;
// control[3] = 0x00;
// control[4] = 0x01;
// control[5] = 0x00;
// DevActionCtrl(control, 6); //取电 开
Ele_Ctrl_OpenClose(0x01);//取电 开
}
break;
case 0x04:
Dbg_Println(DBG_BIT_NET_STATUS_bit,"远程立即断电\r\n");
// SRAM_Write_Byte(0x02,SRAM_Service_Take_Electricity_State); //取电 关
// UINT8 control[6] = {0};
// control[0] = 0x04;
// control[1] = 0x00;
// control[2] = LOOPCH01;
// control[3] = 0x00;
// control[4] = 0x02;
// control[5] = 0x00;
// DevActionCtrl(control, 6);
Ele_Ctrl_OpenClose(0x02);//取电 关
// Dbg_Println(DBG_BIT_NET_STATUS_bit,"远程立即断电:%d", DevAddrCtr(NULL, control, 6)); //取电 关
break;
case 0x05: //清除设备缓存
Dbg_Println(DBG_BIT_NET_STATUS_bit,"清除设备缓存\r\n ");
break;
case 0x06: //请求设备地址列表
Dbg_Println(DBG_BIT_NET_STATUS_bit,"准备发送A7命令\r\n ");
MQTT_CMD_A7(S, topic);
return;
case 0x07: //请求上报控指令定义
break;
}
MQTT_CMD_A5(S, topic, data[CMD_PKT], &data[CMDID_PKT], CMD_SUCCESS); //指令执行成功
break;
case 0xA3: //RCU设备控制
Dbg_Println(DBG_BIT_NET_STATUS_bit,"MQTT_Device_Control");
MQTT_Dev_Ctrl(&data[1+CmdID_LEN+DeviceID_LEN+UTCTime_LEN]);
MQTT_CMD_A5(S, topic, data[CMD_PKT], &data[CMDID_PKT], CMD_SUCCESS); //指令执行成功
break;
case 0xA4: //门锁透传控制
Dbg_Println(DBG_BIT_NET_STATUS_bit,"MQTT Door Lock transport");
{
uint8_t WxLockSendLen;
WxLockSendLen = datalen - (1+CmdID_LEN+DeviceID_LEN+UTCTime_LEN)-0x01;
// if(WxLockSendLen == Server_Datahex[1+CmdID_LEN+DeviceID_LEN+UTCTime_LEN]) //内容长度判断
{
data[1+CmdID_LEN+DeviceID_LEN+UTCTime_LEN] = WxLockSendLen;
MQTT_WxLock_Ctrl(&data[1+CmdID_LEN+DeviceID_LEN+UTCTime_LEN]);//门锁赋值
}
MQTT_CMD_A5(S, topic, data[CMD_PKT], &data[CMDID_PKT], CMD_SUCCESS); //指令执行成功
}//
break;
default:
Dbg_Println(DBG_BIT_NET_STATUS_bit,"MQTT cmd err");
MQTT_CMD_A5(S, topic, data[CMD_PKT], &data[CMDID_PKT], CMD_HEAD_ERROR); //指令错误
break;
}
}
else
{
// MQTT_CMD_A5(S, topic, data[CMD_PKT], &data[CMDID_PKT], CMD_DEC_ERROR);
Dbg_Println(DBG_BIT_NET_STATUS_bit,"DeviceID err");
}
}
else
{
// MQTT_CMD_A5(S, topic, data[CMD_PKT], &data[CMDID_PKT], CMD_CRC_ERROR);
Dbg_Println(DBG_BIT_NET_STATUS_bit,"MQTT crc ERR%X CRC_168:%X", data[datalen-1], CRC_168(data, datalen-1));
}
#endif
}
/**
* @name MQTT微信锁透传控制
* @param
* buf 一次传4个字节过来
* @retval 0x00 表示失败 0x01 表示成功
* @attention 空调的没有单独的开机,发关机即关机,发其他模式即开机
* 消息长度 消息内容
* [0] N
*/
uint8_t MQTT_WxLock_Ctrl(uint8_t *buf)
{
uint8_t Ret = 0x00;
#if MQTT_EN
Device_Public_Information_G BUS_Public;
RS485_WxLock_INFO Rs485WxLockInfo;
uint32_t dev_addr;
if(buf[0] > WXLOCKDOWNMESSAGELEN) //超过长度直接返回
{
return Ret;
}
if(NULL == DevActionGlobal.DevLockAddr)//定位蓝牙主机模块
{
return Ret;
}
Ret = 0x01;
dev_addr = DevActionGlobal.DevLockAddr;
// Rs485WxLockInfo = HostRunInfo.CfgDevAddWxLock->DevDataStruct;
SRAM_DMA_Read_Buff((uint8_t *)&BUS_Public,sizeof(Device_Public_Information_G),dev_addr);
SRAM_DMA_Read_Buff((uint8_t *)&Rs485WxLockInfo,sizeof(RS485_WxLock_INFO),dev_addr+Dev_Privately);
Rs485WxLockInfo.WeixinDownSendFlag = 0x01; //下发标志置位
Rs485WxLockInfo.WeixinDownSendCnt = WxLockCtrlSendMax;
Rs485WxLockInfo.WeixinDownMessageLen = buf[0];
memcpy(Rs485WxLockInfo.WeixinDownMessage, &buf[1], Rs485WxLockInfo.WeixinDownMessageLen); //拷贝透传数据
BUS_Public.check = 0x00;
BUS_Public.check = DoubleData_CheckSum((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G), (uint8_t *)&Rs485WxLockInfo, sizeof(RS485_WxLock_INFO));
SRAM_DMA_Write_Buff((uint8_t *)&BUS_Public, sizeof(Device_Public_Information_G),dev_addr);/*将数据保存*/
SRAM_DMA_Write_Buff((uint8_t *)&Rs485WxLockInfo,sizeof(RS485_WxLock_INFO),dev_addr+Dev_Privately);
#endif
return Ret ;
}
/*******************************************************************************
* Function Name : MQTT_Receive_Processing
* Description : MQTT数据接收处理
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void MQTT_Receive_Processing(void)
{
#if MQTT_EN
if(0x01 != mqtt_info.con_flag)
{
// Dbg_Println(DBG_BIT_NET_STATUS_bit,"MQTT Con Faild");
return ;
}
if(0x01 != mqtt_info.sub_flag)
{
// Dbg_Println(DBG_BIT_NET_STATUS_bit,"MQTT Sub Faild");
return ;
}
MQTT_CoreData_Up(); //里面自带时间间隔
MQTT_NoramlData_Up(); //每次都会扫描判断,是否有上报
if(mqtt_info.Sram_read_addr != mqtt_info.Sram_write_addr)
{
int DataLen = SRAM_Read_Word(mqtt_info.Sram_read_addr);
uint8_t* Data = malloc(DataLen);
if(Data == NULL) return;
SRAM_Read_Buff(Data, DataLen, mqtt_info.Sram_read_addr +2);
// MQTT_Publish(mqtt_info.mqtt_socket, mqtt_info.pub_topic, Data, DataLen, 0);
FREEG_Data_Processing(mqtt_info.mqtt_socket, mqtt_info.pub_topic, Data, DataLen, 0);
free(Data);
mqtt_info.Sram_read_addr += SRAM_MQTT_RECEIVE_LEN;
if(mqtt_info.Sram_read_addr >= SRAM_MQTT_RECEIVE_END)
{
mqtt_info.Sram_read_addr = SRAM_MQTT_RECEIVE_START;
}
}
#endif
}
#endif
#if MQTT_NORMALDATA_UP_FLAG
/**
* @name MQTT普通数据及时上报
* @para 无
* @return 无
* @brief 每次只上报一个状态
* @attention 在主循环里调用最好1ms调用一次
*/
uint8_t MQTT_NoramlData_Up(void)
{
uint8_t Ret = 0x00;
// if(0x01 == MQTT_CMD_A8())
// {
// Ret = 0x01;
// }else
if(0x01 == MQTT_CMD_A6())
{
Ret = 0x01;
}
// else if(0x01 == MQTT_CMD_A9())
// {
// Ret = 0x01;
// }
return Ret;
}
#endif
/*********************************** endfile **********************************/