#include "gd32f10x.h"
#include "usart.h"
#include "device_message.h"
#include "PC.h"
#include "parseDeviceMessage.h"
#include "ec800m.h"
#include "string.h"
#include "mmodbus.h"
#include "otaEvent.h"
#define Top			0xEE           //自定义协议帧起始符号
#define END     0xBB					 //自定义协议帧结束
#define READ_ID 0x01				   // 读取设备id、固件版本号
#define READ_GATEWAY_MESSAGE 0x02	   // 读取网关设备信息
#define READ_GATEWAY_JSON_CONFIG 0x03  // 读取JSON配置
#define WIRTE_GATEWAY_JSON_CONFIG 0x04 // 写入JSON配置
#define OTA_EVENT 0x05				   // 进入程序更新
#define SET_GATEWAY_PLATFORM 0x06	   // 设置物联网平台



bool WaitField(char *expectStr, int timeout);
void readGatewayConfig(void);    //读取设备系列DTU/LORA等等
void readGatewayMessage(void);	//读取sim卡相关信息
void readSIMCARD(void);
void read_json_config();
void write_json_config();

void ec800m_4G_Data_read(uint8_t *str,uint16_t len);

volatile int RxState;

usart2_data_buf_t RxPacket;
volatile uint32_t uart2_json_buf_num;//串口232配置数据长度
/*
	此中断处理逻辑较为复杂
	总共有两条线路
	1、自定义协议的线路
		对于自定义协议当其接收到了开始位之后、进入功能判断对其具体功能做出具体的响应、
		其中又分为两种情况:
		(1)查询某一属性值、其长度并不会超过5、在接收完毕后即可进行状态归位操作
		(2)写入操作、其在后续会跟一些不定长的数据包、无法判断其具体长度。所以要在空闲中断中进行状态
		归位操作。
	2、OTA升级的线路
		对于OTA升级的操作、其上位机要先导要传一段自定义协议的数据将状态转化为升级状态、之后等待
		从机回应进入等待升级状态、直到最后一个数据包结束标志抵达后才进行状态清零。或者超时之后进行了状态
		归位操作。
*/
void USART2_IRQHandler(void)
{
	if (RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_RBNE)) // 接收寄存器不空
	{
		uint8_t Serial_RxData;
		Serial_RxData = usart_data_receive(USART2);
		if (ota_data.ota_flag==0&&RxState==OTA_EVENT)
		{
			RxState=0;//ota更新中断后状态归位
		}
		
		if (RxState == 0) // 等待包头
		{
			if (Serial_RxData == Top) // 获取到包头则切换到识别功能模式
			{
				RxState = 1;
				RxPacket.data_cnt = 0;
				RxPacket.data[RxPacket.data_cnt] = Serial_RxData;
			}
		}
		else if (RxState == 1) // 接收数据
		{
			RxPacket.data_cnt++;
			RxPacket.data[RxPacket.data_cnt] = Serial_RxData;
			if (RxPacket.data_cnt >= 3) // 接收完数据
			{
				RxState = 2; // 前导数据位已经接收完毕、转化状态接收尾部数据
			}
		}
		else if (RxState == 2) // 等待包尾
		{
			if (Serial_RxData == END) // 进入了结束位
			{
				if (RxPacket.data[1] == WIRTE_GATEWAY_JSON_CONFIG) // 当为写入json数据后进入状态3、将对应数据放到usart0_buf中
				{
					RxState = 3;
					dma_channel_disable(DMA0, DMA_CH4);
					uart2_json_buf_num = 0;
				}
				else if (RxPacket.data[1] == OTA_EVENT) // 进入了OTA事件此时的状态会处于接收程序状态、一直等待OTA的结束标志位
				{
					RxState = 4;
					ota_data.data_cnt=0;
					memset(ota_data.data,0,133);//清空数据
					ota_data.ota_flag=1;
				}

				else // 其他情况则将状态归位
				{
					RxState = 0;
				}
			}
		}
		else if (RxState == 3) // 接收到json信息进入进行处理
		{
			UART0_RX_STAT = 0x01;
			UART0_RX_BUF[uart2_json_buf_num++] = Serial_RxData;
		}
		else if (RxState == 4) //进入OTA升级路线
		{
			ota_data.data[ota_data.data_cnt] = Serial_RxData;
			ota_data.data_cnt++;
		}
		
		// 清除中断标志
		usart_interrupt_flag_clear(USART2, USART_INT_FLAG_RBNE);
	}

	if ((RxPacket.data_cnt > 0) && RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_IDLE))
	{
		// 进入空闲中断后通过功能位进行判断其具体作用，并给予相应响应
		if (RxPacket.data[0] == Top)
		{
			switch (RxPacket.data[1])
			{
				case READ_ID:
				readGatewayMessage();
				break;
			case READ_GATEWAY_MESSAGE:
				readSIMCARD();
				break;
			case READ_GATEWAY_JSON_CONFIG:
				read_json_config();
				break;
			case WIRTE_GATEWAY_JSON_CONFIG:
				dma_channel_enable(DMA0, DMA_CH4);
				write_json_config();
				break;
			case SET_GATEWAY_PLATFORM:
				break;
			default:
				break;
			}
		}
		// 此时不在ota升级的分支时，防止其他错误指令造成的数据状态不归位情况
		if (ota_data.ota_flag == 0) 
		{
			RxState = 0;
		}
		else if(ota_data.ota_flag==1)
		{
			ota_data.done=1;
		}

		usart_data_receive(USART2);
	}
}
/*
 *  函数名：void readGatewayMessage()
 *  输入参数：无
 *  输出参数：无
 *  返回值：无
 *  函数作用:读取gateway内部配置信息
 */
void readGatewayMessage(void)
{
	CONFIG_PARAMS *gateway;
	gateway = get_config_params();
	uint8_t *gatewayMessageData=malloc(100);
	memset(gatewayMessageData,0,100);
	gatewayMessageData[0]=Top;
	gatewayMessageData[1]=READ_ID;
	uint8_t deviceIdLen=strlen(gateway->deviceId);
	uint8_t versionLen=strlen(gateway->version);
	memcpy(gatewayMessageData+2,gateway->deviceId,deviceIdLen);
	gatewayMessageData[deviceIdLen+2]=0x3B;
	
	memcpy(gatewayMessageData+2+1+deviceIdLen,gateway->version,versionLen);
	uint16_t CRC16=mmodbus_crc16(gatewayMessageData+1,strlen(gatewayMessageData)-1);

	gatewayMessageData[deviceIdLen+2+1+versionLen+1] = (uint8_t) (CRC16 & 0x00FF);
	gatewayMessageData[deviceIdLen+2+1+versionLen] = (uint8_t) ((CRC16 & 0xFF00)>>8);
	
	gatewayMessageData[deviceIdLen+2+1+versionLen+2]=END;
	gatewayMessageData[deviceIdLen+2+1+versionLen+2+1]='\0';
	gd_com_232_send(gatewayMessageData,strlen(gatewayMessageData));
	free(gatewayMessageData);
}
/*
 *  函数名：void readSIMCARD()
 *  输入参数：无
 *  输出参数：无
 *  返回值：无
 *  函数作用:读出sim卡的相关配置
 */
void readSIMCARD()
{
	CONFIG_PARAMS *gateway;
	gateway = get_config_params();
	
	uint8_t *gatewayConfigData=malloc(1024);
	memset(gatewayConfigData,0,1024);
	uint8_t Operators[16];
	bool Networkstatu;
	uint8_t SIMCard=0;                          //状态0 正常 状态1异常
	uint8_t ICCID[20];												
	uint8_t IMMIE[15];
	uint8_t Networktyp;                           //0 GSM 2 UTRAN 3 GSM W/EGPRS 4 UTRAN W/HSDPA 5 UTRAN W/HSUPA 6 UTRAN W/HSDPA and HSUPA 7 E-UTRAN 8 UTRAN HSPA+
	uint8_t Signal_strength;                    //信号强度
	//查询运营商
	EC800MSendCmd(CMD_SERVICE_Operatortyp, strlen(CMD_SERVICE_Operatortyp)); 
	if(WaitField("+COPS: 0,0,",100))																						//+COPS:0,0,"%s"为运营商，+COPS:0为无sim卡
	{
		sscanf(UART0_RX_BUF, "AT+COPS?\r\r\n+COPS: 0,0,\"%[^\"]\",%s", Operators, &Networktyp);
	}
	else
	{
		strcpy(Operators,"");																											//未读取到sim卡信息
		Networktyp=NULL;
	}
	Clear_DMA_Buffer();
	//查询注册状态
	EC800MSendCmd(CMD_SERVICE_Networktyp,strlen(CMD_SERVICE_Networktyp));
	WaitField("OK",100);
	
	char* status_str=strstr(UART0_RX_BUF, "+CREG:");
	if(status_str != NULL)																											//不为NULL则为有信号
	{
		sscanf(status_str, "+CREG: %*d,%d", &Networkstatu);																							//原先0未注册 1注册，取反后1未注册0注册
	}
	//查询sim卡iccid
	EC800MSendCmd(CMD_SERVICE_SIMcardICCID,strlen(CMD_SERVICE_SIMcardICCID));
	WaitField("OK",100);
	char* ICCID_str=strstr(UART0_RX_BUF,"+QCCID:");
	if(ICCID_str != NULL)
	{
		sscanf(ICCID_str,"+QCCID: %s",ICCID);
		//查询信号强度
		EC800MSendCmd(CMD_SERVICE_Signalstrength,strlen(CMD_SERVICE_Signalstrength));
		WaitField("OK",100);
		uint8_t rssi;
		sscanf(UART0_RX_BUF,"AT+CSQ\r\r\n+CSQ: %d",&rssi);
		Signal_strength=(int)(((float)rssi/31)*100);            //算出来的百分比不准确log函数的斜率不断降低，此方法算出来的斜线的信号强度，实际信号为log函数，后续修正
		Clear_DMA_Buffer();
	}
	else																													//为没有sim卡状态
	{
		memset(ICCID,0,20);																					//此时无ICCID
		Signal_strength=0;																					//无sim卡直接让其等于0
		SIMCard=0;																										//然后sim状态抛异常
	}
	Clear_DMA_Buffer();
	//查询IMMIE号
	EC800MSendCmd(CMD_SERVICE_IMEInumber,strlen(CMD_SERVICE_IMEInumber));
	WaitField("OK",100);
	sscanf(UART0_RX_BUF,"AT+GSN\r\r\n%s",IMMIE);
	Clear_DMA_Buffer();
	
	//查询结束，开始组装json
	gatewayConfigData[0]=Top;
	gatewayConfigData[1]=READ_GATEWAY_MESSAGE;
	sprintf(gatewayConfigData+2,
			"{\"UniqueId\":\"%s\",\"Equipmentname\":\"%s\",\"Equipmenttype\":\"%s\",\"Workmode\":\"%s\",\"baudrate\":%d,\"dataBit\":%d,\"stopBit\":%d,\"checkBit\":%d,\"Operatortype\":\"%s\",\"Networktype\":\"%c\",\"Networkstatus\":\"%d\",\"SIMcardstatus\":\"%d\",\"SIMcardICCID\":\"%s\",\"IMEInumber\":\"%s\",\"Signalstrength\":\"%d\"}",
	        gateway->deviceId,"4G_DTU",gateway->gateName,gateway->gatewayMode,gateway->baudrate,gateway->dataBits,gateway->stopBit,gateway->checkBit,
				 Operators,Networktyp,Networkstatu,SIMCard,ICCID,IMMIE,Signal_strength);
	
	uint16_t CRC16=mmodbus_crc16(gatewayConfigData+1,strlen(gatewayConfigData)-1);

	gatewayConfigData[strlen(gatewayConfigData)+1] = (uint8_t) (CRC16 & 0x00FF);
	gatewayConfigData[strlen(gatewayConfigData)] = (uint8_t) ((CRC16 & 0xFF00)>>8);
	gatewayConfigData[strlen(gatewayConfigData)]=END;
	gd_com_232_send(gatewayConfigData,strlen(gatewayConfigData));
	free(gatewayConfigData);
}
/*
 *  函数名：void readSIMCARD()
 *  输入参数：无
 *  输出参数：无
 *  返回值：无
 *  函数作用:读取内部json配置
 */
void	read_json_config()
{
	uint8_t *json_config=malloc(11*1024);//暂时最大空间只能解析10K数据
	memset(json_config,0,11*1024);
	CONFIG_PARAMS *gateway;
	gateway = get_config_params();
	//帧头
	json_config[0]=Top;
	json_config[1]=READ_GATEWAY_JSON_CONFIG;
	//数据包json最外层
	sprintf(json_config+2,"{\"host\":\"%s\",\"port\":%d,\"messageTopic\":\"%s\",\"commandTopic\":\"%s\",\"baudrate\":%d,\"dataBit\":%d,\"stopBit\":%d,\"checkBit\":%d,\"flowControl\":%d,\"deviceId\":\"%s\",\"dataSource\":%d,\"version645\":%d,\"inboundTime\":%d,\"pollTime\":%d,",
				gateway->host,
				gateway->port,
				gateway->messageTopic,
				gateway->commandTopic,
				gateway->baudrate,
				gateway->dataBits,
				gateway->stopBit,
				gateway->checkBit,
				gateway->flowControl,
				gateway->deviceId,
				gateway->dataSource,

				gateway->dataType645,
				gateway->inboundTime,
				gateway->pollTime);
	//读指令头部
	sprintf(json_config+strlen(json_config),"\"sensorData\":[");
	//读指令数据包
	for (int i = 0; i < gateway->device_read_data_num; i++)
	{
		if (gateway->dataSource == MODBUS)
		{
			sprintf(json_config+strlen(json_config),"{\"rFunctionCode\":%d,\"registerAddress\":%d,\"slaveAddress\":%d,\"registerByteNum\":%d,\"identifier\":\"%s\",\"deviceId\":\"%s\",\"precise\":%d,\"bigLittleFormat\":%d},",
						gateway->device_read_data[i].mdbFunctionCode,
						gateway->device_read_data[i].mdbRegister,
						gateway->device_read_data[i].mdbSlave,
						gateway->device_read_data[i].registerLength,
						gateway->device_read_data[i].keyword,
						gateway->device_read_data[i].deviceId,
						gateway->device_read_data[i].decimalPoint,
						gateway->device_read_data[i].bigLittleFormat);
		}
		else if(gateway->dataSource == DLT645)
		{
			sprintf(json_config+strlen(json_config),
						"{\"identifier\":\"%s\",\"deviceID645\":\"%02x%02x%02x%02x%02x%02x\",\"identifier645\":%d,\"deviceId\":\"%s\"},",
						gateway->device_read_data[i].keyword,
						gateway->device_read_data[i].deviceID645[0],
						gateway->device_read_data[i].deviceID645[1],
						gateway->device_read_data[i].deviceID645[2],
						gateway->device_read_data[i].deviceID645[3],
						gateway->device_read_data[i].deviceID645[4],
						gateway->device_read_data[i].deviceID645[5],
						gateway->device_read_data[i].dataType645,
						gateway->device_read_data[i].deviceId);
		}
	}
	//特殊处理数据包括号最后一个逗号，清空
	memset(json_config+strlen(json_config)-1,0,1);
	//读指令数据包尾部以及写指令数据包头部
	sprintf(json_config+strlen(json_config),"],\"commandData\":[");
	//写数据包内容 写数据包目前只有MODBUS含有
	for (int i = 0; i < gateway->device_write_data_num; i++)
	{
		sprintf(json_config+strlen(json_config),"{\"deviceId\":\"%s\",\"identifier\":\"%s\",\"registerAddress\":%d,\"slaveAddress\":%d,\"wFunctionCode\":%d,\"registerByteNum\":%d,\"bigLittleFormat\":%d},",
					gateway->device_write_data[i].deviceId,
					gateway->device_write_data[i].keyword,
					gateway->device_write_data[i].mdbRegister,
					gateway->device_write_data[i].mdbSlave,
					gateway->device_write_data[i].mdbFunctionCode,
					gateway->device_write_data[i].registerLength,
					gateway->device_write_data[i].bigLittleFormat);
	}
	//特殊处理数据包括号最后一个逗号，清空
	memset(json_config+strlen(json_config)-1,0,1);
	//写数据包结尾以及json结尾
	sprintf(json_config+strlen(json_config),"]}");
	//CRC校验
	uint16_t CRC16=mmodbus_crc16(json_config+1,strlen(json_config)-1);
	json_config[strlen(json_config)+1] = (uint8_t) (CRC16 & 0x00FF);
	json_config[strlen(json_config)] = (uint8_t) ((CRC16 & 0xFF00)>>8);
	//帧尾
	json_config[strlen(json_config)]=END;
	gd_com_232_send(json_config,strlen(json_config));
	free(json_config);
}
/*
 *  函数名：void	write_json_config()
 *  输入参数：无
 *  输出参数：无
 *  返回值：无
 *  函数作用:读取内部json配置
 */
void	write_json_config()
{
	bool success=WaitForUpData();
	int8_t resp[10];
	memset(resp,0,10);
	resp[0]=Top;
	resp[1]=WIRTE_GATEWAY_JSON_CONFIG;
	resp[2]=success;
	uint16_t CRC16=mmodbus_crc16(resp+1,strlen(resp)-1);
	resp[strlen(resp)+1] = (uint8_t) (CRC16 & 0x00FF);
	resp[strlen(resp)] = (uint8_t) ((CRC16 & 0xFF00)>>8);
	resp[strlen(resp)]=END;
	gd_com_232_send(resp,strlen(resp));
	//配置完成重启设备
	NVIC_SystemReset();
}
/*
 *  函数名：void ec800m_4G_Data_read(uint8_t *str,uint16_t len)
 *  输入参数：无
 *  输出参数：str读到的首地址,len读到的数据总长
 *  返回值：无
 *  函数作用:读取gateway内部配置信息
 */
void ec800m_4G_Data_read(uint8_t *str,uint16_t len)
{
	EC800MSendCmd(CMD_SERVICE_Operatortyp, strlen(CMD_SERVICE_Operatortyp));
	WaitField("+COPS:",100);
	
}






/*
 *  函数名：bool WaitField(char *expectStr, int timeout)
 *  输入参数：expectStr 需要匹配的关键字 timeout超时时间
 *  输出参数：true flase
 *  返回值：无
*  函数作用：从UART0_RX_BUF缓冲区中匹配有无对应关键字有关键字则返回true无返回false且不会清掉里面的数据
 */
bool WaitField(char *expectStr, int timeout)
{
	bool timeoutFlag = false;
	if (timeout >= 0)
	{
		timeoutFlag = true;
	}
	while (1)
	{
		delay_1ms(50);
		if (UART0_RX_STAT > 0)
		{
			UART0_RX_STAT = 0;
			char *p=strstr((char *)&UART0_RX_BUF, expectStr);
			if (p)
			{
				return true;
			}
		}
		timeout -= 50;
		if (timeoutFlag == true && timeout <= 0)
		{
			return false;
		}
	};
}



