417 lines
15 KiB
C
417 lines
15 KiB
C
#include "EC800M.h"
|
||
#include "usart.h"
|
||
#include "delay.h"
|
||
#include "sdram.h"
|
||
#include "stm32f4xx.h"
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <stdint.h>
|
||
#include <stdlib.h>
|
||
#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);
|
||
}
|
||
|
||
|