#define BC26  //定义引入得通讯模块 BC26 | ESP8266
#include "coap.h"
#include <string.h>
#include "mbedtls_util.h"
#include "COAPHandle.h"
#include "module_wrapper.h"
#include "TypeDefine.h"
#include "SystemAlarm.h"
#include "sys.h"
#include "crc.h"
#include "DrawLCDGUI.h"
#include "ProgramData.h"
#include "Driver.h"
#include "cJSON.h"
#include "ControlSystem.h"
#ifdef BC26
#include "bc26.h"
#elif defined(ESP8266)
#include "esp8266.h"
#endif


void endpoint_setup(void)
{
	
}
coap_endpoint_t endpoints[1]= {0};

#define BUF_SIZE 1024
static uint8_t buf[BUF_SIZE];
extern uint8 tcp_connect_status;
extern valid_data_t valid_data;
extern uint8_t TurnOffACKTone;
static char iv[17] = "543yhjy97ae7fyfg";
static const char *coap_con_path="auth";
static const uint8_t coap_content_json = COAP_CONTENTTYPE_APPLICATION_JSON;

static char* sign_format = "clientId%s.%sdeviceName%sproductKey%sseq%d";
static char* payload_format="{\"clientId\":\"%s.%s\",\"signmethod\":\"%s\",\"sign\":\"%s\",\"productKey\":\"%s\",\"deviceName\":\"%s\",\"seq\":%d}";
int module_check_status; //模块检测
static auth_token_t auth_token = 
{
	.flag = AUTH_FAILURE,
};
static uint16_t coap_auth_id = AUTH_MID;

coap_packet_t coap_send_pkt =  //coap发送包
{
	.hdr.ver=0x01,
	.hdr.t=COAP_TYPE_CON,
	.hdr.tkl=0,
	.hdr.code=COAP_METHOD_POST,
	.numopts=0,
};
coap_packet_t coap_rec_pkt = {0}; //coap接受包

#define PAYLOAD_DATA_LEN 48 //数据包

uint8_t PumpType_Normal=0; 

static uint8_t pumpData[PAYLOAD_DATA_LEN];  //包数据
extern uint8_t StartToRun_flag;             //当按下运行按键的时候，置位该标志
extern char mqtt_publish_topic[100]; //发布主题
extern uint8_t Alarm_flag;  //报警状态

extern uint8_t Start_send  ; //开始发送标志，0：发送
extern uint16_t send_cont;   //数据发送次数

static uint16_t send_num = 0; //发送数据数量
static uint16_t send_suc_num = 0;//发送成功数据数量
uint16_t send_fall_num = 0; //发送失败数据数量
static uint8_t repeat_send_count = 0;//重发次数
static uint16_t pre_send_num = 0;
uint8_t repeat_send_switch = 0; //0关闭重发，1开启重发

static int firstSendFlag = 1;
static int moduleInitCou = 0; //模块连续初始化次数

static uint8_t pumpState = 0; //运行状态标志
static uint16_t pumpAlarm = 0; //报警标志
static uint8_t pumpPreAlarm = 0; //预报标志

static uint8_t pumpStateLast = 0; //上次运行状态标志
static uint16_t pumpAlarmLast = 0; //上次报警标志
static uint8_t pumpPreAlarmLast = 0; //上次预报标志

static uint8_t signData[4]={0};

static void setValue(uint8_t **p,void* data,int len)
{
	memcpy(*p,data,len);
	*p+=len;
}

static void generateCoapKey(void)
{
	int i = 0;
	char out[80]={0};
	char sign_content[100]={0};
	if(auth_token.flag == AUTH_SUCCESS)
	{
		snprintf(sign_content, sizeof(sign_content), "%s,%s",registInfo->deviceSecret,auth_token.random);
		utils_sha256(sign_content, strlen(sign_content), out);
		memset(auth_token.key,0,sizeof(auth_token.key));
		memcpy(auth_token.key,out+8,16); //获取key
	}
	
}
/**
* @Title 封装数据并通过mqtt发送
*/
static void packPumbDataCoapSend(void)
{
	int i = 0;
	//if(mqtt_status.ping_status != MQTT_SUCCESS) return;  //外调该接口时，做网络判断
	if(send_num < 0 )
	{
		send_num = 0;
	}
	send_num++;
	send_fall_num=send_num-send_suc_num;
	send_cont = send_num;
	uint8_t *ptr =pumpData;
	if(EngineeringModeValue.test == 1)
	{
		PumpType_Normal=0x15;
	}
	else 
	{
		PumpType_Normal=0x16;
	}
	unsigned short crc = 0;
	if(tcp_connect_status != TCP_OPEN)       
	{
		return;
	}
	memset(pumpData,0,sizeof(pumpData));

	*ptr++ = 0xEF; //[0] 固定值
	*ptr++ = PAYLOAD_DATA_LEN-2; //[1]数据长度
	*ptr++ = PumpType_Normal; //[2]泵类型,网络泵
	setValue(&ptr,classification,4);//[3-6]分类标识
	setValue(&ptr,&send_num,sizeof(send_num));//[7-8]数据编号
	*ptr++=8; //[9]住院号长度
	setValue(&ptr,&verifyInfo.hospitalNO,8); //[10-17]住院号
	setValue(&ptr,&verifyInfo.sickroom,2); //[18-19]病区
	setValue(&ptr,&verifyInfo.bedNO,2); //[20-21]床号
	setValue(&ptr,&setParamInfo.totalDose,2); //[22-23]总量
	setValue(&ptr,&setParamInfo.limitDose1,2); //[24-25]极限零
	setValue(&ptr,&setParamInfo.superaddition1,2); //[26-27] 追加量
	setValue(&ptr,&setParamInfo.lockTime1,2); //[28-29] 锁时时间
	setValue(&ptr,&setParamInfo.continueDose1,2);  //[30,31]持续量
	setValue(&ptr,&realTimeData.inputDose,2);  //[32-33]已输入量
	*ptr++ = (uint8_t)(setParamInfo.firstDose & 0x00ff); //[34]首次量
	*ptr++ = (uint8_t)( realTimeData.validCount & 0x00ff );  //[35]有效次数
	*ptr++ = (uint8_t)( realTimeData.invalidCount & 0x00ff );//[36]无效次数
	if( realTimeData.batteryVolt > 100 )//[37]电池电量，发送电量百分比
	{
		*ptr++ = 100;
	}
	else
	{
		*ptr++ = realTimeData.batteryVolt;
	}
	
	switch( realTimeData.stateRun )  //[38]泵运行状态
	{
		case FirstRun:
		case MainRun:
		case Airout:
		case PCARun:
			pumpData[38] = 0x02;//运行状态 0000 0010
			break;
		case Pause:
			pumpData[38] = 0x04;//暂停状态 0000 0100
			break;
		case Poweroff:
			pumpData[38] = 0x00;//关机状态 0000 0000
			break;
		case Poweron:
			pumpData[38] = 0x01;//开机状态  0000 0001
			break;
		default:
			pumpData[38] = 0x08;//待机状态 0000 1000,
			break;
	}
	ptr++;	
	
	if( sysAlarmFlag.BubbleFault == ALARM_ON )
	{
		pumpData[39] |= 0x01;//气泡或无液故障 0000 0001
	}
	if( sysAlarmFlag.JamFault == ALARM_ON )
	{
		pumpData[39] |= 0x02;//堵塞故障 0000 0010
	}
  if( sysAlarmFlag.InputTotal == ALARM_ON )
	{
		pumpData[39] |= 0x04;//输入总量报警 0000 0100
	}
	if( sysAlarmFlag.MaxFault == ALARM_ON )
	{
		pumpData[39] |= 0x08;//极限量报警 0000 1000
	}
	if( sysAlarmFlag.VoltLowest == ALARM_ON )//电量耗尽
	{
		pumpData[39] |= 0x10;// 0001 0000
	}
	if( sysAlarmFlag.InputEnd == ALARM_ON )//输液结束
	{
		pumpData[39] |= 0x20;// 0010 0000
	}
	if( sysAlarmFlag.MotorFalt == ALARM_ON )//电机失控
	{
		pumpData[39] |= 0x40;// 0100 0000
	}
	if( (sysAlarmFlag.MechanicalFault == ALARM_ON ) || ( sysAlarmFlag.MechanicalFault == ALARM_CONTINUE ) )//机械故障
	{
		pumpData[39] |= 0x80;// 1000 0010; 
	}
	ptr++;
	
	if( sysAlarmFlag.NonePillCase == ALARM_ON )
	{
		pumpData[40] |= 0x01;//未装药盒报警 0000 0001
	}
	ptr++;
	
	if( sysAlarmFlag.InputEnding == ALARM_ON )
	{
		pumpData[41] |= 0x01;//输液将要结束 0000 0001
	}
	if( sysAlarmFlag.Zhentongxiaoguo == ALARM_ON )
	{
		pumpData[41] |= 0x02;//阵痛不足预报 0000 0010
	}
	if( sysAlarmFlag.VoltLowest == ALARM_PREPARE )
	{
		pumpData[41] |= 0x04;//电量偏低预报 0000 0100
	}
	ptr++;
	setValue(&ptr,&signData,4); //[18-19]病区
	
	crc = CRC16_CCITT((unsigned char*)pumpData, sizeof(pumpData)-2);
	setValue(&ptr,&crc,2);  //[42-43]CRC
	UsartPrintf(USART_DEBUG,"发布数据包:%d\r\n",sizeof(pumpData));
	for(i = 0;i<sizeof(pumpData);i++)
	{
		UsartPrintf(USART_DEBUG,"%02x",pumpData[i]);
	}
	UsartPrintf(USART_DEBUG,"\r\n");
	CoapPublish(pumpData,sizeof(pumpData));
}

//将泵状态报警信息封装在一起
static void IntePumpStateCoap()
{
	switch( realTimeData.stateRun )  //[38]泵运行状态
	{
		case FirstRun:
		case MainRun:
		case Airout:
		case PCARun:
			pumpState = 0x02;//运行状态 0000 0010
			break;
		case Pause:
			pumpState = 0x04;//暂停状态 0000 0100
			break;
		case Poweroff:
			pumpState = 0x00;//关机状态 0000 0000
			break;
		case Poweron:
			pumpState = 0x01;//开机状态  0000 0001
			break;
		default:
			pumpState = 0x08;//待机状态 0000 1000,
			break;
	}
	
	if( sysAlarmFlag.BubbleFault == ALARM_ON )
	{
		pumpAlarm |= 0x0001;//气泡或无液故障 0000 0001
	}
	if( sysAlarmFlag.JamFault == ALARM_ON )
	{
		pumpAlarm |= 0x0002;//堵塞故障 0000 0010
	}
  if( sysAlarmFlag.InputTotal == ALARM_ON )
	{
		pumpAlarm |= 0x0004;//输入总量报警 0000 0100
	}
	if( sysAlarmFlag.MaxFault == ALARM_ON )
	{
		pumpAlarm |= 0x0008;//极限量报警 0000 1000
	}
	if( sysAlarmFlag.VoltLowest == ALARM_ON )//电量耗尽
	{
		pumpAlarm |= 0x0010;// 0001 0000
	}
	if( sysAlarmFlag.InputEnd == ALARM_ON )//输液结束
	{
		pumpAlarm |= 0x0020;// 0010 0000
	}
	if( sysAlarmFlag.MotorFalt == ALARM_ON )//电机失控
	{
		pumpAlarm |= 0x0040;// 0100 0000
	}
	if( (sysAlarmFlag.MechanicalFault == ALARM_ON ) || ( sysAlarmFlag.MechanicalFault == ALARM_CONTINUE ) )//机械故障
	{
		pumpAlarm |= 0x0080;// 1000 0010; 
	}
	
	if( sysAlarmFlag.NonePillCase == ALARM_ON )
	{
		pumpAlarm |= 0x0100;//未装药盒报警 0000 0001
	}
	
	if( sysAlarmFlag.InputEnding == ALARM_ON )
	{
		pumpPreAlarm |= 0x01;//输液将要结束 0000 0001
	}
	if( sysAlarmFlag.Zhentongxiaoguo == ALARM_ON )
	{
		pumpPreAlarm |= 0x02;//阵痛不足预报 0000 0010
	}
	if( sysAlarmFlag.VoltLowest == ALARM_PREPARE )
	{
		pumpPreAlarm |= 0x04;//电量偏低预报 0000 0100
	}
}

static void DecideSendFlagCoap()
{
	static int addition_active=0;// 报警发送激活
	static int first_dose_active = 0;// 首次量结束发送激活
	
	//开始
	if(firstSendFlag ==1 && StartToRun_flag == 1) 
	{
			firstSendFlag = 0;
			TaskSchedulerFlag.MqttSendFlag = TASK_FLAG_SET;
			//UsartPrintf(USART_DEBUG, "====firstSendFlag=====\r\n");
	}else if(StartToRun_flag == 0)
	{
		firstSendFlag = 1;
	}
	
	//泵状态发生改变
	if(pumpState != pumpStateLast || pumpAlarm != pumpAlarmLast || pumpPreAlarm != pumpPreAlarmLast)
	{
	//	UsartPrintf(USART_DEBUG, "====state change:%d,%d,%d,%d,%d,%d\r\n",pumpState,pumpStateLast,pumpAlarm,pumpAlarmLast,pumpPreAlarm,pumpPreAlarmLast);
		pumpStateLast = pumpState;
		pumpAlarmLast = pumpAlarm;
		pumpPreAlarmLast = pumpPreAlarm;
		TaskSchedulerFlag.MqttSendFlag = TASK_FLAG_SET;
	}
	
	//首次量结束发送数据
	if(realTimeData.firstDose == 0)
	{
		if(first_dose_active == 1)
		{
			first_dose_active = 0;
			TaskSchedulerFlag.MqttSendFlag = TASK_FLAG_SET;
			//UsartPrintf(USART_DEBUG, "====firstDose=====\r\n");
		}
	}	
	else if(realTimeData.firstDose > 0)
	{
		first_dose_active = 1;
	}
	//追加量结束发送数据
	if(realTimeData.superaddition == 0)
	{
		if(addition_active == 1)
		{
			addition_active = 0;
			TaskSchedulerFlag.MqttSendFlag = TASK_FLAG_SET;
			//UsartPrintf(USART_DEBUG, "====superaddition====\r\n");
		}
	}	
	else if(realTimeData.superaddition > 0)
	{
		addition_active = 1;
	}
	
}


void CoapConnect(void)
{
  static uint32 seq = 1;
	int buf_len = 0;
	char sign_content[100]={0};
	char out[50]={0};
	char payload_content[512];
	int i=0;
	uint16_t coap_port = my_atoi(registInfo->port);//端口
	
	auth_token.flag = AUTH_HANDLING;
	
	coap_auth_id++;
	if(coap_auth_id < AUTH_MID)
	{
		coap_auth_id = AUTH_MID;
	}
	coap_send_pkt.hdr.id[0]=(uint8_t)(coap_auth_id&0x00ff);
	coap_send_pkt.hdr.id[1]=(uint8_t)(coap_auth_id>>8);
	
//	coap_send_pkt.hdr.id[0]=AUTH_MID;
//	coap_send_pkt.hdr.id[1]=0;
	coap_send_pkt.numopts=5;
	
	coap_send_pkt.opts[0].num=COAP_OPTION_URI_HOST;
	coap_send_pkt.opts[0].buf.len=strlen(registInfo->address);
	coap_send_pkt.opts[0].buf.p=(uint8_t*)registInfo->address;
	
	coap_send_pkt.opts[1].num=COAP_OPTION_URI_PORT;
	coap_send_pkt.opts[1].buf.len=sizeof(coap_port);
	coap_send_pkt.opts[1].buf.p=(uint8_t*)&coap_port;
	
	coap_send_pkt.opts[2].num=COAP_OPTION_URI_PATH;
	coap_send_pkt.opts[2].buf.len=strlen(coap_con_path);
	coap_send_pkt.opts[2].buf.p=(uint8_t*)coap_con_path;
	
	coap_send_pkt.opts[3].num=COAP_OPTION_CONTENT_FORMAT,
	coap_send_pkt.opts[3].buf.len=sizeof(coap_content_json),
	coap_send_pkt.opts[3].buf.p=&coap_content_json,
	
	coap_send_pkt.opts[4].num=COAP_OPTION_ACCEPT,
	coap_send_pkt.opts[4].buf.len=sizeof(coap_content_json),
	coap_send_pkt.opts[4].buf.p=&coap_content_json,
	
	seq++;
	snprintf(sign_content, sizeof(sign_content), sign_format,registInfo->productKey,registInfo->deviceName,registInfo->deviceName,registInfo->productKey,seq);
	utils_hmac_sha1_str(sign_content, strlen(sign_content), out, registInfo->deviceSecret, strlen(registInfo->deviceSecret));
	UsartPrintf(USART_DEBUG,"sign_content:%s,sign:%s\r\n",sign_content,out);
	
	snprintf(payload_content, sizeof(payload_content), payload_format,registInfo->productKey,registInfo->deviceName,"hmacsha1",out,registInfo->productKey,registInfo->deviceName,seq);
	coap_send_pkt.payload.len=strlen(payload_content);
	coap_send_pkt.payload.p=(uint8_t*)payload_content;
	
	UsartPrintf(USART_DEBUG,"auth_payload:%s\r\n",payload_content);
	
	memset(buf,0,BUF_SIZE);
	buf_len = BUF_SIZE;
	coap_build(buf,&buf_len,&coap_send_pkt);
//	UsartPrintf(USART_DEBUG,"\r\nauth byte，%d:\r\n",buf_len);
//	for(i=0;i<buf_len;i++)
//	{
//		UsartPrintf(USART_DEBUG,"%02x",buf[i]);
//	}
	at_module_send_rai(buf,buf_len,ONE_RRC);
	
}

void CoapPublish(uint8_t* payload,int len)
{
	int buf_len = 0;
	
	char seq_conent[20] = {0};
	uint8_t seq[8] = {0};
	char paybyte[100] = {0};
	char *topic[] = {"topic","sys",registInfo->productKey, registInfo->deviceName,"thing","model","up_raw"};
	int topic_len = sizeof(topic)/sizeof(topic[0]);
	int optnum = 0;
	
	int i=0;
	
	uint16_t coap_port = my_atoi(registInfo->port);
	coap_send_pkt.hdr.id[0]=(uint8_t)(send_num&0x00ff);
	coap_send_pkt.hdr.id[1]=(uint8_t)(send_num>>8);
	coap_send_pkt.numopts=6+topic_len;

	coap_send_pkt.opts[optnum].num=COAP_OPTION_URI_HOST;
	coap_send_pkt.opts[optnum].buf.len=strlen(registInfo->address);
	coap_send_pkt.opts[optnum++].buf.p=(uint8_t*)registInfo->address;
	
	coap_send_pkt.opts[optnum].num=COAP_OPTION_URI_PORT;
	coap_send_pkt.opts[optnum].buf.len=sizeof(coap_port);
	coap_send_pkt.opts[optnum++].buf.p=(uint8_t*)&coap_port;
	
	for(i=0;i<topic_len;i++)
	{
		coap_send_pkt.opts[optnum].num=COAP_OPTION_URI_PATH;
		coap_send_pkt.opts[optnum].buf.len=strlen(topic[i]);
		coap_send_pkt.opts[optnum++].buf.p=(uint8_t*)topic[i];
	}
	
	coap_send_pkt.opts[optnum].num=COAP_OPTION_CONTENT_FORMAT,
	coap_send_pkt.opts[optnum].buf.len=sizeof(coap_content_json),
	coap_send_pkt.opts[optnum++].buf.p=&coap_content_json,
	
	coap_send_pkt.opts[optnum].num=COAP_OPTION_ACCEPT,
	coap_send_pkt.opts[optnum].buf.len=sizeof(coap_content_json),
	coap_send_pkt.opts[optnum++].buf.p=&coap_content_json,
	
	
	auth_token.seqOffset++;
	//UsartPrintf(USART_DEBUG,"===发送数据认证: %d,%s,%s:\r\n",auth_token.seqOffset,auth_token.random,auth_token.token);
	my_itoa(auth_token.seqOffset,(char*)seq,10);
	int seqlen = utils_aes128_cbc_enc((char*)auth_token.key, iv, (char*)seq, seq_conent);
	coap_send_pkt.opts[optnum].num=2088;
	coap_send_pkt.opts[optnum].buf.len=strlen(auth_token.token);
	coap_send_pkt.opts[optnum++].buf.p=(uint8_t*)auth_token.token;
	
	coap_send_pkt.opts[optnum].num=2089;
	coap_send_pkt.opts[optnum].buf.len=seqlen;
	coap_send_pkt.opts[optnum++].buf.p=(uint8_t*)seq_conent;
	
	
	int paylen = utils_aes128_cbc_base64_enc((char*)auth_token.key, iv, payload,len, paybyte);
	//UsartPrintf(USART_DEBUG,"===发送数据paylen: %d\r\n",paylen);
	
		
	coap_send_pkt.payload.len=paylen;
	coap_send_pkt.payload.p=(uint8_t*)paybyte;
	memset(buf,0,BUF_SIZE);
	
	buf_len = BUF_SIZE;
	coap_build(buf,&buf_len,&coap_send_pkt);
//	UsartPrintf(USART_DEBUG,"\r\npush byte，%d:\r\n",buf_len);
//	for(i=0;i<buf_len;i++)
//	{
//		UsartPrintf(USART_DEBUG,"%02x",buf[i]);
//	}
//	UsartPrintf(USART_DEBUG,"\r\n");
	at_module_send_rai(buf,buf_len,ONE_RRC);
}


static void ModuleKeepOnLine(void)
{	
	if(module_start_status == MODULE_OK && module_init_status == MODULE_OK)
	{
		TaskSchedulerFlag.NET_ONLINE_FLAG = TASK_FLAG_SET;//模块联网		
		if(moduleInitCou > 0) // 连接基站成功
		{
			moduleInitCou = 0;
			DrawSignalDisplay();
			at_module_udpreopen(registInfo->address,registInfo->port);
			if(repeat_send_switch)//有数据发送， 重设重发时间
			{
				TaskSchedulerTimer.MQTTReSendTimer = FIVE_SECOND_TIMER;
				TaskSchedulerFlag.MqttReSendFlag = TASK_FLAG_CLEAR;
			}
			freshSignal((char*)signData,sizeof(signData));
		}
		
		
		if(auth_token.flag == AUTH_FAILURE)
		{
			if(tcp_connect_status == TCP_OPEN)
			{
				freshSignal((char*)signData,sizeof(signData));
				UsartPrintf(USART_DEBUG, "===CoapConnect=====\r\n");
				CoapConnect(); //coap认证
			}
			else
			{
				if(tcp_connect_status == TCP_CLOSED)
				{
					UsartPrintf(USART_DEBUG, "===udp open=====\r\n");
					at_module_udpreopen(registInfo->address,registInfo->port);
				}
			}
		}
		
		if(repeat_send_switch)
		{
			if(TaskSchedulerFlag.MqttReSendFlag == TASK_FLAG_SET)
			{
				TaskSchedulerFlag.MqttReSendFlag = TASK_FLAG_CLEAR;
				repeat_send_count++;
				UsartPrintf(USART_DEBUG, "\r\n===repeat send:%d=====\r\n",repeat_send_count);
//				if(repeat_send_count == 2)
//				{
//					at_module_udpreopen(registInfo->address,registInfo->port);
//					return;
//				}
				
				if(repeat_send_count == 4 || (repeat_send_count == 3 && tcp_connect_status != TCP_OPEN))
				{
					repeat_send_switch = 0; //关闭重发
					repeat_send_count = 0;
					module_start_status = MODULE_FAIL; //模块再次启动
					module_init_status = MODULE_FAIL;
					tcp_connect_status = TCP_CLOSED;
					TaskSchedulerFlag.ModuleInitFlag = TASK_FLAG_CLEAR;
					TaskSchedulerTimer.ModuleInitTimer = ONE_HOUR_TIMER;
					return;
				}
				
				send_num--;
				packPumbDataCoapSend();//重新发送
				
			}
			
		}
		
	}
	else
	{
			TaskSchedulerFlag.NET_ONLINE_FLAG = TASK_FLAG_CLEAR;//模块未联网
			if(TaskSchedulerFlag.ModuleInitFlag == TASK_FLAG_SET)
			{
				TaskSchedulerFlag.ModuleInitFlag = TASK_FLAG_CLEAR;
				TaskSchedulerTimer.ModuleInitTimer = FIFTEEN_SECOND_TIMER;
				moduleInitCou++;
				UsartPrintf(USART_DEBUG, "===start module=====%d\r\n",moduleInitCou);
				if(moduleInitCou >= 2 && module_start_status == MODULE_FAIL)
				{
					moduleInitCou = 0;
					DrawSignalDisplay();
					TaskSchedulerTimer.ModuleInitTimer = ONE_HOUR_TIMER;//连续5次启动失败,启动间隔变为半小时
					if (emSysWorkStep != EnterDetection)
					{
						at_module_low_power();//低功耗
					}
					repeat_send_switch = 0; //关闭重发
					repeat_send_count = 0;
					return;
				}
				
				if(module_start_status == MODULE_FAIL)
				{
					UsartPrintf(USART_DEBUG, "===restart module=====\r\n");
					at_module_start();
				}
				else if(module_init_status == MODULE_FAIL)
				{	
					UsartPrintf(USART_DEBUG, "===init module=====\r\n");
					at_module_init();
				}
				
			}
	 }
	
}

/**
* 处理认证信息
*/
static void AuthHandle(void)
{
	cJSON *json = NULL,*json_seqOffset=NULL,*json_random=NULL,*json_token = NULL;
	json = cJSON_Parse((char*)coap_rec_pkt.payload.p);
	if(!json)
	{
		UsartPrintf(USART_DEBUG, "json parse error,%s\r\n",cJSON_GetErrorPtr());
		goto end;
	}
	json_seqOffset = cJSON_GetObjectItem(json,"seqOffset");
	json_random = cJSON_GetObjectItem(json,"random");
	json_token = cJSON_GetObjectItem(json,"token");
	 
	if(json_random && json_token)
	{
		memset(&auth_token,0,sizeof(auth_token));
		if(json_seqOffset)
		{
			UsartPrintf(USART_DEBUG, "==认证成功=====%d,%s,%s\r\n",json_seqOffset->valueint,json_random->valuestring,json_token->valuestring);
			auth_token.seqOffset = json_seqOffset->valueint;
		}
		else
		{
			UsartPrintf(USART_DEBUG, "==认证成功=====%s,%s\r\n",json_random->valuestring,json_token->valuestring);
			auth_token.seqOffset = 100;
		}
		auth_token.flag = AUTH_SUCCESS;
		memcpy(auth_token.random,json_random->valuestring,strlen(json_random->valuestring));
		memcpy(auth_token.token,json_token->valuestring,strlen(json_token->valuestring));	
		
		generateCoapKey();
	}
	else
	{
		UsartPrintf(USART_DEBUG, "==认证失败=====\r\n");
	//	auth_token.flag = AUTH_FAILURE;
	}
	
	end:
	    cJSON_Delete(json);
}

/**
* 处理Coap返回消息
*/
static void HandleCoapValidData()
{
		int i = 0;
		uint16_t back_send_num = 0;
		static uint16_t last_send_num = 0;
		int ret = coap_parse(&coap_rec_pkt, (uint8_t*)valid_data.buf, valid_data.len);
		UsartPrintf(USART_DEBUG, "coap back,%d:\r\n",valid_data.len);
		for(i=0;i<valid_data.len;i++)
	  {
			UsartPrintf(USART_DEBUG, "%02x",valid_data.buf[i]);
		}
		if(ret)
		{
			UsartPrintf(USART_DEBUG, "\r\n==解析失败，%d=====\r\n",ret);
		}
		else
		{
			
			//UsartPrintf(USART_DEBUG, "\r\n==解析成功====\r\n");
			back_send_num = (uint16_t)coap_rec_pkt.hdr.id[1]<<8;
			back_send_num |= coap_rec_pkt.hdr.id[0];
			if(coap_rec_pkt.hdr.code == SUC_ACK_CODE)
			{
				if(back_send_num == coap_auth_id) //认证返回
				{
					AuthHandle();
				}
				else if(back_send_num == send_num ) //上传返回
				{
					repeat_send_switch = 0; //收到最新回复关闭重发
					if(last_send_num < send_num)
					{
						last_send_num = send_num;
						send_suc_num++;
					}
					freshSignal((char*)signData,sizeof(signData));
				}
			}
			else if((coap_rec_pkt.hdr.code == UNAUTH_ACK_CODE || coap_rec_pkt.hdr.code == BADREQ_ACK_CODE) && back_send_num == send_num)
			{
				UsartPrintf(USART_DEBUG, "\r\n==未授权的请求=====\r\n");
				repeat_send_switch = 0;
				auth_token.flag = AUTH_FAILURE;
			}
			
		}
		
		valid_data_clear(); //清除有效数据
}
void CoapHandleEvent(void)
{
	at_module_handle_event();
	if(valid_data.len>0)
	{
		HandleCoapValidData();
	}
}

//发送泵数据
static void SendCoapPumpData()
{
	static uint8_t send_flag = 1;
	if(!send_flag) return;
	
	IntePumpStateCoap();
	DecideSendFlagCoap();
	
	if(TaskSchedulerFlag.MqttSendFlag == TASK_FLAG_SET && motorWorkState != MOTOR_WORK_ON )
	{
		TaskSchedulerFlag.MqttSendFlag = TASK_FLAG_CLEAR;
		TaskSchedulerTimer.MQTTSendTimer = TWENTY_MINUTE_TIMER;
		if(EngineeringModeValue.test == 0)
		{
			TaskSchedulerTimer.MQTTSendTimer = TWENTY_SECOND_TIMER;
			if(send_num >= 300) //测试模式下最多发送300条数据
			{
				at_module_low_power();
				send_flag = 0;
				return;
			}
		}
		   
		if(module_init_status == MODULE_FAIL && moduleInitCou == 0)
		{
			TaskSchedulerFlag.ModuleInitFlag = TASK_FLAG_SET;
		}
		if(repeat_send_switch == 0)
		{
			repeat_send_switch = 1;//准备重发
			repeat_send_count = 0;
		}
		packPumbDataCoapSend();
		TaskSchedulerTimer.MQTTReSendTimer = FIVE_SECOND_TIMER;
		TaskSchedulerFlag.MqttReSendFlag = TASK_FLAG_CLEAR;
	}

}


void CoapHandle(void)
{

	ModuleKeepOnLine(); //保持网络连接
	
	CoapHandleEvent();  //处理接收数据
	
	if((Start_send == 0 && TurnOffACKTone == 0) || realTimeData.stateRun == Poweroff) 
	{
		if(realTimeData.stateRun == Poweroff)
		{
			SpeakerCtl( DRIVER_OFF );//蜂鸣器
			LCDBLACtl( DRIVER_OFF );//LCD背光
			TaskSchedulerFlag.lcdBlackFlag = TASK_FLAG_CLEAR;	
		}
		SendCoapPumpData(); //发送数据	
	}
	if(realTimeData.stateRun == Poweroff)
	{

		delay_ms(500);
		TaskSchedulerFlag.sysPowerOffFlag = TASK_FLAG_SET;//关机
	}
			
}

void ModelRegister(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct; 	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
	/* enable clock */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	
	
	GPIO_InitStruct.GPIO_Pin 	= GPIO_Pin_7;
	GPIO_InitStruct.GPIO_Mode	= GPIO_Mode_Out_PP;
	//GPIO_InitStruct.Pull 	= GPIO_NOPULL;
	GPIO_InitStruct.GPIO_Speed 	= GPIO_Speed_50MHz;	
	GPIO_Init(GPIOA, &GPIO_InitStruct);
	
//	GPIO_InitStruct.GPIO_Pin 	= GPIO_Pin_4;
//	GPIO_InitStruct.GPIO_Mode	= GPIO_Mode_Out_PP;
//	//GPIO_InitStruct.Pull 	= GPIO_NOPULL;
//	GPIO_InitStruct.GPIO_Speed 	= GPIO_Speed_50MHz;	
//	GPIO_Init(GPIOC, &GPIO_InitStruct);
//	BC26_WAKE_LOW();
	
	#ifdef BC26
	bc26_sal_register();
	#elif defined(ESP8266)
	esp8266_sal_register();
	#endif
}

/**
* 模块信号强度,为负值
*/
int16_t GetModeldBm(void) 
{
	char *recvdiff[9] = {0};//分割字符串地址
	uint8_t data[200]={0};
	uint16 dBm = 0;
	#ifdef BC26
	const char *SIGN = "+QENG: ";
	char *signStr = NULL;
	at_module_cmd_back("AT+QENG=0\r\n",(char*)data,sizeof(data));
	signStr = strstr((const char*)data,SIGN);
	if(signStr)
	{
		signStr+=strlen(SIGN);
		splitCharLimit((char*)data,',',recvdiff,9);
		dBm = my_atoi(recvdiff[7]);
	}
	#elif defined(ESP8266)
	#endif
	return dBm;
}

int16_t GetModelCSQ(void)  
{
	uint8_t data[50]={0};
	uint16 dBm = 0;
	#ifdef BC26
	const char *SIGN = "+CSQ: ";
	char *signStr = NULL;
	at_module_cmd_back("AT+CSQ\r\n",(char*)data,sizeof(data));
	signStr = strstr((const char*)data,SIGN);
	if(signStr)
	{
		signStr+=strlen(SIGN);
		dBm = my_atoi(signStr);
	}
	#endif
	return dBm;
}

/**
* @Title 获取基站信号信息
* @Param backdata1 小区信息， len1 backdata1长度，backdata2 信号强度信息，len2 backdata2长度
*/
void GetSignalDetail(char* backdata1,int len1,char* backdata2,int len2) 
{
 char *recvdiff[10] = {0};
 uint8_t data[200]={0};
 const char *SIGN = "+QENG: ";
 char *signStr = NULL;
 at_module_cmd("AT\r\n");
 delay_ms(5);
 at_module_cmd("AT+QPING=0,\"iot-060a0bgd.coap.iothub.aliyuncs.com\",4,1\r\n");
 delay_ms(200);
 uint16 csq = GetModelCSQ();
 at_module_cmd_back("AT+QENG=0\r\n",(char*)data,sizeof(data));
 signStr = strstr((const char*)data,SIGN);
 if(signStr)
 {
	UsartPrintf(USART_DEBUG, "===signal detail 4=====:%s\r\n",data);
  signStr+=strlen(SIGN);
  int limit = splitCharLimit((char*)data,',',recvdiff,10);
	if(limit > 8)
	{
		*(recvdiff[4]+strlen(recvdiff[4])-1)=0;
		snprintf(backdata1,len1,"%s,%s",recvdiff[3],recvdiff[4]+1);
		//UsartPrintf(USART_DEBUG, "===signal detail 7=====:%s\r\n",backdata1);
		snprintf(backdata2,len2,"%s,%s,%s,%s,%d",recvdiff[5],recvdiff[6],recvdiff[7],recvdiff[8],csq);
		//UsartPrintf(USART_DEBUG, "===signal detail 8=====:%s\r\n",backdata2);
	}
  
 }
 
}

/**
* @Title 刷新信后质量
* @Param signData 信号质量存储位置， signDataLen 存储位置大小
*/
void freshSignal(char* signData,int signDataLen) 
{
	char *recvdiff[10] = {0};
	uint8_t data[200]= {0};
	const char *SIGN = "+QENG: ";
	char *signStr = NULL;
	int i = 0;
	
	at_module_cmd_back("AT+QENG=0\r\n",(char*)data,sizeof(data));
	signStr = strstr((const char*)data,SIGN);
	if(signStr)
	{
		signStr+=strlen(SIGN);
		int limit = splitCharLimit((char*)signStr,',',recvdiff,10);
		
		if(signDataLen >=4 && limit > 8)
		{
			
			signData[0]= my_atoabs(recvdiff[5]);
			signData[1]= my_atoabs(recvdiff[6]);
			
			int num1 = my_atoi(recvdiff[7]);
			if(num1 == 99)
			{
				signData[2] = 255;
			}
			else
			{
				signData[2]= -num1;;
			}
			
			signData[3]= my_atoi(recvdiff[8]);
		}
	}
	
}

