369 lines
13 KiB
C
369 lines
13 KiB
C
#include "cat.h"
|
||
|
||
uint32_t current_tick = 0; //当前运行时间 用于LED闪烁 硬件看门狗等
|
||
|
||
|
||
_Bool NetworkingFlag = 0; //联网标志位 1联网 0离线
|
||
|
||
|
||
|
||
char databuff[256]; //构建数据用的临时缓冲区
|
||
uint8_t online_counter = 1; //查询子设备上线的计数变量
|
||
uint8_t data_counter = 1; //查询子设备数据的计数变量
|
||
|
||
void catGpioInit(void) {
|
||
GPIO_InitTypeDef GPIO_Initure = {0};
|
||
|
||
// GPIOA_RCC_ENABLE;
|
||
GPIOC_RCC_ENABLE;
|
||
|
||
GPIO_Initure.Pin= CAT_POW_Pin; //设置电源脚
|
||
GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; //开漏输出
|
||
GPIO_Initure.Pull = GPIO_NOPULL; //不上下拉
|
||
GPIO_Initure.Speed = GPIO_SPEED_FREQ_LOW; //低速 (必需设置!)
|
||
HAL_GPIO_Init(CAT_POW_GPIO_Port,&GPIO_Initure); //设置
|
||
|
||
// GPIO_Initure.Pin= CAT_RST_Pin; //设置复位脚(预留)
|
||
// GPIO_Initure.Pull = GPIO_NOPULL; //不上下拉
|
||
// GPIO_Initure.Mode = GPIO_MODE_OUTPUT_OD; //开漏输出
|
||
// GPIO_Initure.Speed = GPIO_SPEED_FREQ_LOW; //低速
|
||
// HAL_GPIO_Init(CAT_RST_GPIO_Port,&GPIO_Initure); //设置
|
||
|
||
GPIO_Initure.Pin = CAT_RUN_Pin ; //设置运行读取脚
|
||
GPIO_Initure.Mode = GPIO_MODE_INPUT; //输入模式
|
||
GPIO_Initure.Pull = GPIO_PULLUP; //使能上拉
|
||
GPIO_Initure.Speed = GPIO_SPEED_FREQ_LOW; //低速
|
||
HAL_GPIO_Init(CAT_RUN_GPIO_Port,&GPIO_Initure); //设置
|
||
|
||
// GPIO_Initure.Pin = CAT_NET_Pin ; //设置网络读取脚
|
||
// GPIO_Initure.Mode = GPIO_MODE_INPUT; //输入模式
|
||
// GPIO_Initure.Pull = GPIO_PULLUP; //使能上拉
|
||
// GPIO_Initure.Speed = GPIO_SPEED_FREQ_LOW; //低速
|
||
// HAL_GPIO_Init(CAT_NET_GPIO_Port,&GPIO_Initure); //设置
|
||
}
|
||
|
||
|
||
//模块开机后会收到 +NITZ: 24/04/13,12:11:59+32,0 实际时间 2024/4/13 20:11:59秒
|
||
void catReset(void) {
|
||
uint8_t Multiple = 200; //短暂延时 默认100ms
|
||
uint8_t netstep = 0;
|
||
char serverbuff[100] = {0}; //例子:AT+MCONFIG="8c91c2a533b3c573","965669176415378622","ad592e4c3e7117c6",0,0,0,0
|
||
char portbuff[50] = {0}; //例子:AT+MIPSTART="58.17.14.95",1880
|
||
char topicbuff[50]= {0}; //订阅主题 才能收到云平台下发的控制指令
|
||
sprintf(serverbuff,"AT+MCONFIG=\"%s\",\"%s\",\"%s\",0,0,0,0",MqttInfo_Struct.ClientID,MqttInfo_Struct.Username,MqttInfo_Struct.Passward);
|
||
sprintf(portbuff, "AT+MIPSTART=\"%s\",%d",MqttInfo_Struct.ServerIP,MqttInfo_Struct.ServerPort);
|
||
sprintf(topicbuff, "AT+MSUB=\"%s%s\",0",MqttInfo_Struct.Topic,MqttInfo_Struct.ClientID);
|
||
|
||
#if 0
|
||
if(POWER_STA==1) { //如果PB1是高电平,表示目前处于关机状态
|
||
log_info("目前4G模块处于关机状态,准备开机"); //串口输出信息
|
||
POWER_KEY(1); //先拉高
|
||
HAL_Delay(1500); //延时
|
||
POWER_KEY(0); //再拉低,开机
|
||
} else { //反之PA0是低电平,表示目前处于开机状态
|
||
log_info("目前4G模块处于开机状态,准备重启"); //串口输出信息
|
||
POWER_KEY(1); //先拉高
|
||
HAL_Delay(1500); //延时
|
||
POWER_KEY(0); //再拉低,关机
|
||
HAL_Delay(3000); //间隔
|
||
POWER_KEY(1); //先拉高
|
||
HAL_Delay(1500); //延时
|
||
POWER_KEY(0); //再拉低,开机,完成重启
|
||
}
|
||
#endif
|
||
log_info("准备复位");
|
||
POWER_KEY(1); //先拉高 复位
|
||
HAL_Delay(1000); //延时
|
||
POWER_KEY(0); //再拉低
|
||
HAL_Delay(3000); //间隔
|
||
HAL_Delay(3000);
|
||
|
||
HAL_Delay(Multiple);
|
||
if(catSendCmd("AT","OK", 8,30)) {
|
||
log_info("开机失败,准备重启"); //串口输出信息
|
||
NVIC_SystemReset(); //重启!
|
||
} else {
|
||
netstep += 1; //步进增加
|
||
log_info("开机成功"); //串口输出信息
|
||
}
|
||
HAL_Delay(Multiple);
|
||
log_info("关闭回显"); // 串口提示数据
|
||
if(catSendCmd("ATE0","OK", 5, 30)) {
|
||
log_info("关闭回显失败,准备重启"); //串口输出信息
|
||
NVIC_SystemReset(); //重启!
|
||
} else {
|
||
netstep += 1; //步进增加
|
||
log_info("关闭回显成功"); //串口输出信息
|
||
}
|
||
HAL_Delay(Multiple);
|
||
log_info("准备查询卡状态"); // 串口提示数据
|
||
if(catSendCmd("AT+CPIN?","READY", 5, 30)) {
|
||
log_info("查询卡状态失败,准备重启"); //串口输出信息
|
||
NVIC_SystemReset(); //重启!
|
||
} else {
|
||
netstep += 1; //步进增加
|
||
log_info("查询卡状态成功"); //串口输出信息
|
||
}
|
||
HAL_Delay(Multiple);
|
||
log_info("准备设置单连接\r\n"); // 串口提示数据
|
||
if(catSendCmd("AT+CIPMUX=0","OK", 5, 30)) {
|
||
log_info("设置单连接失败,准备重启"); //串口输出信息
|
||
NVIC_SystemReset(); //重启!
|
||
} else {
|
||
netstep += 1; //步进增加
|
||
log_info("设置单连接成功"); //串口输出信息
|
||
}
|
||
HAL_Delay(Multiple);
|
||
log_info("准备配置网络"); // 串口提示数据
|
||
if(catSendCmd("AT+CSTT","OK", 5, 30)) {
|
||
log_info("配置网络失败,准备重启"); //串口输出信息
|
||
NVIC_SystemReset(); //重启!
|
||
} else {
|
||
netstep += 1; //步进增加
|
||
log_info("配置网络成功"); //串口输出信息
|
||
}
|
||
HAL_Delay(Multiple);
|
||
log_info("准备激活网络"); // 串口提示数据
|
||
if(catSendCmd("AT+CIICR","OK", 5, 30)) {
|
||
log_info("激活网络失败,准备重启"); //串口输出信息
|
||
NVIC_SystemReset(); //重启!
|
||
} else {
|
||
netstep += 1; //步进增加
|
||
log_info("激活网络成功"); //串口输出信息
|
||
}
|
||
HAL_Delay(Multiple);
|
||
log_info("准备连接服务器"); // 串口提示数据
|
||
if(catSendCmd(serverbuff,"OK", 5, 30)) {
|
||
log_info("连接服务器失败,准备重启"); //串口输出信息
|
||
NVIC_SystemReset(); //重启!
|
||
} else {
|
||
netstep += 1; //步进增加
|
||
log_info("连接服务器成功"); //串口输出信息
|
||
}
|
||
HAL_Delay(Multiple);
|
||
log_info("准备连接TCP端口");
|
||
if(catSendCmd(portbuff,"OK", 5, 30)) {
|
||
log_info("连接TCP端口失败,准备重启"); //串口输出信息
|
||
NVIC_SystemReset(); //重启!
|
||
} else {
|
||
netstep += 1; //步进增加
|
||
log_info("连接TCP端口成功"); //串口输出信息
|
||
}
|
||
HAL_Delay(Multiple);
|
||
log_info("准备配置保活时间");
|
||
if(catSendCmd("AT+MCONNECT=1,60","OK", 5, 30)) {
|
||
log_info("配置保活时间失败,准备重启"); //串口输出信息
|
||
NVIC_SystemReset(); //重启!
|
||
} else {
|
||
netstep += 1; //步进增加
|
||
log_info("配置保活时间成功"); //串口输出信息
|
||
}
|
||
HAL_Delay(Multiple);
|
||
log_info("准备订阅主题");
|
||
if(catSendCmd(topicbuff,"SUBACK", 5, 30)) {
|
||
log_info("订阅主题失败,准备重启"); //串口输出信息
|
||
NVIC_SystemReset(); //重启!
|
||
} else {
|
||
netstep += 1; //步进增加
|
||
log_info("订阅主题成功"); //串口输出信息
|
||
}
|
||
HAL_Delay(Multiple);
|
||
|
||
log_info("当前来到步:%d",netstep);
|
||
if(netstep >= 10) {
|
||
NetworkingFlag = 1;
|
||
log_info("联网过程一切OK!");
|
||
} else {
|
||
NetworkingFlag = 0;
|
||
log_info("联网失败,重启");
|
||
HAL_Delay(Multiple);
|
||
NVIC_SystemReset(); //重启!
|
||
}
|
||
//CAT1_printf("AT+MPUB=\"/iot/sub/live/post/8c91c2a533b3c573\",0,0,\"{\\22header\\22:\\22iot.sub.live.post\\22,\\22version\\22:\\221.0\\22,\\22body\\22:{\\22online\\22:[{\\22uid\\22:\\2239dde8bcbf424b1b\\22,\\22secret\\22:\\22129460d7f87bd872\\22}]}}\"\r\n");
|
||
|
||
}
|
||
|
||
|
||
|
||
//子设备上线 标准指令 Lora子设备测试-02
|
||
// CAT1_printf("AT+MPUB=\"/iot/sub/live/post/8c91c2a533b3c573\",0,0,\"{\\22header\\22:\\22iot.sub.live.post\\22,\\22version\\22:\\221.0\\22,\\22body\\22:{\\22online\\22:[{\\22uid\\22:\\2239dde8bcbf424b1b\\22,\\22secret\\22:\\22129460d7f87bd872\\22}]}}\"\r\n");
|
||
|
||
//子设备上线 经过测试也可以 Lora子设备测试-02
|
||
// CAT1_printf("AT+MPUB=\"/iot/data/up/8c91c2a533b3c573\",0,0,\"{\\22header\\22:\\22iot.sub.live.post\\22,\\22version\\22:\\221.0\\22,\\22body\\22:{\\22online\\22:[{\\22uid\\22:\\2239dde8bcbf424b1b\\22,\\22secret\\22:\\22129460d7f87bd872\\22}]}}\"\r\n");
|
||
|
||
|
||
//实际串口捕获的数据:
|
||
//AT+MPUB="/iot/sub/live/post/8c91c2a533b3c573",0,0,"{\22header\22:\22iot.sub.live.post\22,\22version\22:\221.0\22,\22body\22:{\22online\22:[{\22uid\22:\2239dde8bcbf424b1b\22,\22secret\22:\22129460d7f87bd872\22}]}}"
|
||
|
||
//转义后:
|
||
// "/iot/sub/live/post/8c91c2a533b3c573",0,0,
|
||
//"{
|
||
//"header":"iot.sub.live.post",
|
||
//"version":"1.0",
|
||
//"body":{
|
||
// "online":[
|
||
// {
|
||
// "uid":"39dde8bcbf424b1b",
|
||
// "secret":"129460d7f87bd872"
|
||
// }
|
||
// ]
|
||
// }
|
||
//}"
|
||
|
||
//发送上线消息后 云平台回复:
|
||
//设备回复数据:+MSUB: "/iot/data/down/8c91c2a533b3c573",47 byte,{"code":200,"message":"success","success":true}
|
||
|
||
//云平台子设备上线后 发送开关指令后 单片机收到数据如下:
|
||
//+MSUB: "/iot/data/down/8c91c2a533b3c573",158 byte,{"extend":{"uid":"39dde8bcbf424b1b"},"id":"976660012242325829","header":"iot.sub.prop.set","version":"1.0","body":{"sw1":{"time":1713020358015,"value":true}}}
|
||
//其中uid是子设备的设备id
|
||
|
||
|
||
|
||
/*-------------------------------------------------*/
|
||
/*函数名:卡模块发送指令 */
|
||
/*参 数:cmd:指令 */
|
||
/*参 数:ret:对比数据 */
|
||
/*参 数:cnt:发送次数 */
|
||
/*参 数:timeout:超时时间(50ms的倍数) */
|
||
/*返回值:0:正确 其他:错误 */
|
||
/*-------------------------------------------------*/
|
||
uint8_t catSendCmd(char *cmd, char *ret, uint8_t cnt, uint8_t timeout) {
|
||
uint8_t result = 1; // 默认结果设为错误(非0值)
|
||
while(cnt > 0 && result != 0) {
|
||
CAT1_printf("%s\r\n", cmd); // 发送指令 结尾加上换行回车
|
||
uint8_t current_timeout = timeout;
|
||
while(--current_timeout) {
|
||
HAL_Delay(50);
|
||
u2flushReceiveBuffer(); //刷新接收缓冲区的数据指针
|
||
if (strstr((char *)U2_CopyBuff, ret)) {//查找匹配字符串
|
||
result = 0; // 找到期望的回复,结果设为正确(0值)
|
||
break;
|
||
}
|
||
}
|
||
if (current_timeout == 0) // 如果timeout<=0,说明超时,但此时未收到期望回复
|
||
log_info("第%d次超时",cnt);
|
||
cnt--; // 发送次数减1
|
||
}
|
||
return result;
|
||
}
|
||
|
||
|
||
|
||
/*-------------------------------------------------*/
|
||
/*函数名:串口3被动事件 */
|
||
/*参 数:data :数据 */
|
||
/*参 数:datalen :数据长度 CLOSED */
|
||
/*返回值:无 */
|
||
/*-------------------------------------------------*/
|
||
void u2PassiveEvent(uint8_t *data, uint16_t datalen) {
|
||
|
||
//主机被平台踢下线 准备重启
|
||
if(strstr((char *)data,"CLOSED")) {
|
||
log_info("主机被迫下线,准备重启!");
|
||
NVIC_SystemReset();//重启
|
||
}
|
||
|
||
//收到主机控制指令:+MSUB: "/iot/data/down/cfd6dba662690a5e",118 byte,{"id":"977013940154814794","header":"iot.prop.set","version":"1.0","body":{"sw1":{"time":1713104741005,"value":true}}}
|
||
if(strstr((char *)data,"iot.prop.set")) {
|
||
log_info("收到控制指令");
|
||
Relay_Action(data); // 继电器响应网络数据
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
// 继电器响应网络数据
|
||
//收到子设备控制指令:+MSUB: "/iot/data/down/a284c67982b089f9",119 byte,{"id":"111750363407137710","header":"iot.prop.set","version":"1.0","body":{"sw1":{"time":1746600094207,"value":false}}}
|
||
void Relay_Action(uint8_t *data) {
|
||
uint8_t i = 0;
|
||
char *TempPointer; // 临时指针
|
||
char CmdId[18] = {0}; // 存贮id的数据,以响应服务器下发的数据
|
||
if(strstr((char *)data,MqttInfo_Struct.Topic)) { //查找 /iot/data/down/ 出现的位置
|
||
|
||
TempPointer = strstr((char *)data, ",\"id\":\"");
|
||
if (TempPointer) {
|
||
TempPointer += 7; // 跳过 ,"id":"
|
||
for (i = 0; i < 18; i++) {
|
||
if ((TempPointer[i] >= '0' && TempPointer[i] <= '9') ||
|
||
((TempPointer[i] >= 'a') && (TempPointer[i] <= 'z')) ||
|
||
((TempPointer[i] >= 'A') && (TempPointer[i] <= 'Z'))) {
|
||
CmdId[i] = TempPointer[i];
|
||
} else {
|
||
log_info("非法字符: %c (ASCII %d)", TempPointer[i], TempPointer[i]);
|
||
break;
|
||
}
|
||
}
|
||
if(i == 18 && TempPointer[18] == '"') { // 验证18位数字后紧跟引号
|
||
log_info("ID校验通过: %s", CmdId);
|
||
}
|
||
}
|
||
|
||
if(strstr((char *)data,"\"sw")) { //先判断收到的数据是不是开关量
|
||
TempPointer = strstr((char *)data,"\"sw"); // 记录sw位置
|
||
switch(TempPointer[3]) { // 判断操作哪个开关
|
||
case '1':
|
||
if (strstr((char *)data, "true")) {
|
||
log_info("开关1打开");
|
||
;;//
|
||
}
|
||
if (strstr((char *)data, "false")) {
|
||
log_info("开关1关闭");
|
||
;;//
|
||
}
|
||
break;
|
||
case '2':
|
||
if (strstr((char *)data, "true")) {
|
||
log_info("开关2打开");
|
||
;;//
|
||
}
|
||
if (strstr((char *)data, "false")) {
|
||
log_info("开关2关闭");
|
||
;;//
|
||
}
|
||
break;
|
||
case '3':
|
||
if (strstr((char *)data, "true")) {
|
||
log_info("开关3打开");
|
||
;;//
|
||
}
|
||
if (strstr((char *)data, "false")) {
|
||
log_info("开关3关闭");
|
||
;;//
|
||
}
|
||
break;
|
||
case '4':
|
||
if (strstr((char *)data, "true")) {
|
||
log_info("开关4打开");
|
||
;;//
|
||
}
|
||
if (strstr((char *)data, "false")) {
|
||
log_info("开关4关闭");
|
||
;;//
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
//推送回复消息 OK
|
||
CAT1_printf("AT+MPUB=\"/iot/data/up/%s\",0,0,\"{\\22id\\22:\\22%s\\22,\\22code\\22:0,\\22message\\22:\\22OK\\22}\"\r\n",MqttInfo_Struct.ClientID, CmdId);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
//主动事件 LED闪烁
|
||
void activeEvents(void) {
|
||
|
||
//LED闪烁:联网 熄灭:离线
|
||
if (HAL_GetTick() - current_tick >= 200) {
|
||
if(NetworkingFlag)//连接成功
|
||
LED1_TOGGLE;
|
||
else
|
||
LED1_OFF;//熄灭网络指示灯
|
||
|
||
current_tick = HAL_GetTick(); //更新时间
|
||
}
|
||
}
|
||
|