#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);
}


