#include "EC800M.h" #include "usart.h" #include "delay.h" #include "sdram.h" #include "stm32f4xx.h" #include #include #include #include #include "cnn.h" unsigned char Flag_topic; extern UART_BUF buf_uart2; //NBIOT extern UART_BUF buf_uart1; //TTL char *strx,*extstrx; CSTX_4G CSTX_4G_Status; //模块的状态信息 int errcount=0; //发送命令失败次数 防止死循环 int errCountData=0; char ATSTR[BUFLEN]; //组建AT命令的函数 char IMEINUMBER[BUFLEN];//+CGSN: "869523052178994" #define DESTINATION_SIZE 256 char *strx,*extstrx; char destination[DESTINATION_SIZE]; /*云端下发的时间*/ int month_def = 1; int date_def = 0; int hour_def = 0; int min_def = 0; int sec_def= 0; ////////////////////////只要修改三要素///////////////////////////////// #define PRODUCEKEY "k16dsL76w8K" //修改产品秘钥 #define DEVICENAME "device_1" //修改设备名称 #define DEVICESECRET "b36d0f9e35c7fede452a85c59473a411" //设备的API void Clear_Buffer(uint16_t *USARTx_RX_STA, uint8_t *USARTx_RX_BUF) { delay_ms(300); memset(USARTx_RX_BUF, 0, USART_REC_LEN); *USARTx_RX_STA = 0; } void extract_IMSI(uint8_t *input_str, char *output_str) { char *start_ptr = strstr((char *)input_str, "460"); if (start_ptr != NULL) { strncpy(output_str, start_ptr, 15); output_str[15] = '\0'; // 添加字符串结束符 } else { output_str[0] = '\0'; } } /***************************************************** 初始化模块 和单片机连接,获取卡号和信号质量 *****************************************************/ uint8_t CSTX_4G_Init(void) { //打印初始化信息 printf("start init EC800X\r\n"); //发第一个命令ATE1 Uart2_SendStr("ATE1\r\n"); delay_ms(200); strx = strstr((char*)USART2_RX_BUF, "OK"); Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); while(strx==NULL) { printf("单片机正在连接模块......\r\n"); Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); Uart2_SendStr("\n\rATE1\r\nATE1"); delay_ms(300); strx = strstr((char*)USART2_RX_BUF, "OK"); // if(errcount++ > 10) { // printf("\r\n未连接到模块\r\n"); // return 0; // } } printf("****单片机和模块连接成功*****\r\n"); Uart2_SendStr("ATI\r\n");//获取模块的版本 delay_ms(30); Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); Uart2_SendStr("AT+CIMI\r\n");//获取卡号,类似是否存在卡的意思,比较重要。 delay_ms(30); strx = strstr((char*)USART2_RX_BUF, "460"); while(strx==NULL) { printf("****获取卡号*****\r\n"); Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); Uart2_SendStr("AT+CIMI\r\n");//获取卡号,类似是否存在卡的意思,比较重要。 delay_ms(30); strx = strstr((char*)USART2_RX_BUF, "460"); printf("%s",USART2_RX_BUF); } char output_str[16]; extract_IMSI(USART2_RX_BUF, output_str); printf("我的卡号是 : %s \r\n",output_str); Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); Uart2_SendStr("AT+CGATT?\r\n");//查询激活状态 delay_ms(30); strx = strstr((char*)USART2_RX_BUF, "+CGATT: 1"); Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); while(strx==NULL) { Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); Uart2_SendStr("AT+CGATT?\r\n");//获取激活状态 delay_ms(30); strx = strstr((char*)USART2_RX_BUF, "+CGATT: 1"); } Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); Uart2_SendStr("AT+CSQ\r\n");//查看获取CSQ值 delay_ms(30); strx = strstr((char*)USART2_RX_BUF, "+CSQ:"); if(strx)printf("信号质量是:%s 注意:信号最大值是31 \r\n",USART2_RX_BUF); return 1; } /***************************************************** 收到服务器下发的数据就直接打印 +QMTRECV: 0,0,"$creq/a19d2d64-3ee3-5070-8078-ad43e10a52f0","LED11" *****************************************************/ unsigned char CSTX_4G_RECData(void) { strx=strstr((const char*)USART2_RX_BUF,(const char*)"+QMTRECV");//返回+QMTRECV:,表明接收到服务器发回的数据 if(strx) { delay_ms(300); // 必须延时 strncpy(destination, (char *)USART2_RX_BUF, DESTINATION_SIZE - 1); destination[DESTINATION_SIZE - 1] = '\0'; TimeInfo TimeInfo = parseTimeInfo(destination); month_def =TimeInfo.month; date_def =TimeInfo.day; hour_def =TimeInfo.hour; min_def =TimeInfo.minute; sec_def =TimeInfo.second; printf(" Month: %d, Day: %d, Hour: %d, Minute: %d, Second: %d\r\n", TimeInfo.month, TimeInfo.day, TimeInfo.hour, TimeInfo.minute, TimeInfo.second); Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); return 1; } return 0; } /***************************************************** 注册到ONENET topic = 0 -> 自定义topic 用于准备接收下发的时间 topic = 1 -> 物模型topic 用于上传数据 *****************************************************/ void CSTX_4G_RegALiYunIOT(unsigned char topic)//平台注册 { int errcount = 0; static unsigned char flag=0; if(flag == 0){ printf("****初始化完成*****\r\n\r\n"); Uart2_SendStr("AT+QMTDISC=0\r\n");//Disconnect a client from MQTT server delay_ms(30); Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); Uart2_SendStr("AT+QMTCLOSE=0\r\n");//删除句柄 delay_ms(30); Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); delay_ms(30); Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); Uart2_SendStr("AT+QMTCFG=\"version\",0,4\r\n");//切换下版本 delay_ms(30); //等待300ms反馈OK strx = strstr((char*)USART2_RX_BUF, "OK"); while(strx==NULL) { strx = strstr((char*)USART2_RX_BUF, "OK"); } Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); memset(ATSTR,0,BUFLEN); sprintf(ATSTR,"AT+QMTCFG=\"ALIAUTH\",0,\"%s\",\"%s\",\"%s\"\r\n",PRODUCEKEY,DEVICENAME,DEVICESECRET); //+QMTCONN: 0,0,0 printf("ATSTR = %s \r\n",ATSTR); Uart2_SendStr(ATSTR); delay_ms(30); strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTOPEN: 0,0 +QMTOPEN: 0,0 while(strx==NULL) { errcount++; delay_ms(30); strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返回OK if(errcount>10000) //防止死循环 { NVIC_SystemReset(); //没有创建TCP SOCKET就重启系统等到服务器就绪 } } Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); Uart2_SendStr("AT+QMTOPEN=0,\"iot-as-mqtt.cn-shanghai.aliyuncs.com\",1883\r\n");//切换下版本 delay_ms(30); //等待300ms反馈OK strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返OK while(strx==NULL) { strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返OK } Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); Uart2_SendStr("AT+QMTCONN=0,\"-test-\"\r\n");//切换下版本 delay_ms(30); //等待300ms反馈OK strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返OK while(strx==NULL) { strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返OK printf("连接中……\r\n"); } Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); } flag = 1; if(topic == 0){ if(Flag_topic == 1){ memset(ATSTR,0,BUFLEN); sprintf(ATSTR,"AT+QMTUNS=0,100,\"/%s/%s/user/Set_time\"\r\n",PRODUCEKEY,DEVICENAME); //+QMTCONN: 0,0,0 printf("ATSTR = %s \r\n",ATSTR); Uart2_SendStr(ATSTR);//发送链接到阿里云 delay_ms(30); strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTCONN: 0,0,0 while(strx==NULL) { strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTCONN: 0,0,0 } Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); } memset(ATSTR,0,BUFLEN); sprintf(ATSTR,"AT+QMTSUB=0,1,\"/%s/%s/user/Set_time\",0\r\n",PRODUCEKEY,DEVICENAME); //+QMTCONN: 0,0,0 printf("ATSTR = %s \r\n",ATSTR); Uart2_SendStr(ATSTR);//发送链接到阿里云 delay_ms(30); strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTCONN: 0,0,0 while(strx==NULL) { strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTCONN: 0,0,0 } Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); Flag_topic = 0; } else if(topic == 1){ memset(ATSTR,0,BUFLEN); sprintf(ATSTR,"AT+QMTUNS=0,100,\"/%s/%s/user/Set_time\"\r\n",PRODUCEKEY,DEVICENAME); //+QMTCONN: 0,0,0 printf("ATSTR = %s \r\n",ATSTR); Uart2_SendStr(ATSTR);//发送链接到阿里云 delay_ms(30); strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTCONN: 0,0,0 while(strx==NULL) { strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTCONN: 0,0,0 } Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); memset(ATSTR,0,BUFLEN); sprintf(ATSTR,"AT+QMTSUB=0,1,\"/%s/%s/thing/event/property/set\",0\r\n",PRODUCEKEY,DEVICENAME); //+QMTCONN: 0,0,0 printf("ATSTR = %s \r\n",ATSTR); Uart2_SendStr(ATSTR);//发送链接到阿里云 delay_ms(30); strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTCONN: 0,0,0 while(strx==NULL) { strx=strstr((const char*)USART2_RX_BUF,(const char*)"OK");//返+QMTCONN: 0,0,0 } Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); Flag_topic = 1; } } uint16_t MakeALiYunPayload_s(char *Str,char *Data, const char* identifier) { // Onenet有效载荷固定格式的模板 const char PayloadTemplate[60] = "{\"id\":\"123\",\"version\":\"1.0\",\"params\":{\"%s\":{\"value\":\"%s\"}}}"; char JsonBuf[BUFLEN]; // 临时数据缓存 unsigned int StrLen; // 有效载荷数据长度 // 使用snprintf将Data和identifier插入到PayloadTemplate中 snprintf(JsonBuf,sizeof(JsonBuf),PayloadTemplate,identifier,Data); // 计算有效载荷的数据长度 StrLen = strlen((const char*)JsonBuf); // strlen返回的是字节数,无需再除以sizeof(char) // 拷贝有效载荷数据到Str memcpy(Str, JsonBuf, StrLen); // 返回长度 return StrLen; } void convert_to_string(uint8_t *Send_Json, char *output_str, size_t length) { // 将 uint8_t 数组转换为字符串 memcpy(output_str, Send_Json, length); output_str[length] = '\0'; // 添加字符串结束符 } void CSTX_4G_ALiYunIOTSenddata_string(char *Data,const char* identifier)//上发数据,上发的数据跟对应的插件有关系,用户需要注意插件然后对应数据即可 { static char Send_buff[BUFLEN];//AT命令临时缓存 u16 JsonLen; // Json包数据长度 memset((char *)Send_buff, 0, BUFLEN); // 开辟数据缓存 //开辟数据缓存 sprintf((char*)Json,"{\"Temp\":%d,\"Humi\":%d}",Temperature,Humidity);//拷贝数据 装订联网三要素 Temperature,Humidity memset(ATSTR,0,BUFLEN); JsonLen = MakeALiYunPayload_s(Send_buff,Data, identifier); //得到json memset(ATSTR,0,BUFLEN); sprintf(ATSTR,"AT+QMTPUBEX=0,0,0,0,\"/sys/%s/%s/thing/event/property/post\",%d\r\n",PRODUCEKEY,DEVICENAME,JsonLen); printf("ATSTR = %s \r\n",ATSTR); Uart2_SendStr(ATSTR);//mqtt订阅 strx=strstr((const char*)USART2_RX_BUF,(const char*)">");//准备发送数据 errcount=0; while(strx==NULL) { errcount++; strx=strstr((const char*)USART2_RX_BUF,(const char*)">");//准备发送数据 模块的反馈 delay_ms(10); if(errcount>100) //超时退出 { errcount = 0; break; } } printf("Data数据为:%s\r\n",Send_buff); delay_ms(50); Uart2_SendStr(Send_buff); // 发送JSON数据 delay_ms(50); // 等待发送完成响应 errcount = 0; strx = strstr((const char*)USART2_RX_BUF, (const char*)"+QMTPUBEX: 0,0,0"); // 返SEND OK +QMTPUB: 0,0,0 while (strx == NULL) { errcount++; strx = strstr((const char*)USART2_RX_BUF, (const char*)"+QMTPUBEX: 0,0,0"); // 返SEND OK delay_ms(100); if (errcount > 10) // 超时退出 { printf("发送数据超时!\n"); errcount = 0; break; } } Clear_Buffer(&USART2_RX_STA, USART2_RX_BUF); } // 解析函数实现 TimeInfo parseTimeInfo(const char *jsonString) { TimeInfo TimeInfo = {0}; // 初始化结构体为0 // 查找JSON字符串中"params"部分的起始位置 const char *paramsStart = strstr(jsonString, "\"params\""); if (paramsStart != NULL) { // 创建一个临时缓冲区来复制JSON的"params"部分(注意,这里为了简化处理,直接使用了静态缓冲区) char TempBuffer[256]; strncpy(TempBuffer, paramsStart, sizeof(TempBuffer) - 1); TempBuffer[sizeof(TempBuffer) - 1] = '\0'; // 使用简单的字符串解析来提取时间信息(注意,这种方法很脆弱,仅适用于格式固定的字符串) char *token; token = strtok(TempBuffer, ",\"{}:"); while (token != NULL) { if (strcmp(token, "date") == 0) { token = strtok(NULL, ",\"{}:"); TimeInfo.day = atoi(token); // JSON中"date"实际上是日,这里暂存到day字段 } else if (strcmp(token, "month") == 0) { token = strtok(NULL, ",\"{}:"); TimeInfo.month = atoi(token); } else if (strcmp(token, "year") == 0) { // JSON中没有直接的"year"字段,但我们可以从其他信息中推断,或者假设一个默认的年份(这里不处理) // 或者如果"date"和"month"存在,且你有某种方式知道是哪一年(比如当前年份),你可以在这里设置它 } else if (strcmp(token, "hour") == 0) { token = strtok(NULL, ",\"{}:"); TimeInfo.hour = atoi(token); } else if (strcmp(token, "minute") == 0) { token = strtok(NULL, ",\"{}:"); TimeInfo.minute = atoi(token); } else if (strcmp(token, "second") == 0) { token = strtok(NULL, ",\"{}:"); TimeInfo.second = atoi(token); } token = strtok(NULL, ",\"{}:"); } // 注意:上面的代码没有处理"year"字段,因为你的示例JSON中没有提供。 // 你需要根据实际情况来处理这个字段,比如使用当前年份,或者从其他来源获取年份信息。 // 这里为了示例,我们假设年份是固定的(比如2024年),你可以在实际代码中修改这个值。 TimeInfo.year = 2024; // 假设的年份,根据实际情况修改 } return TimeInfo; } ///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数 int fgetc(FILE *f) { RX1_len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度 /* 等待串口输入数据 */ while (__HAL_UART_GET_FLAG(&UART1_Handler, UART_FLAG_RXNE) == RESET); //while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET); return (int)HAL_UART_Receive(&UART1_Handler,(uint8_t*)USART_RX_BUF,RX1_len,1000); //return (int)USART_ReceiveData(USART1); }