/*************************** (C) COPYRIGHT 2017 CXHY ****************************
 * 文件名  ：device.c
 * 描  述  ：外部设备控制检测
 * 版  本  ：V1.0
 * 作  者  ：XuZhongPing
 * 日  期  ：2017/09/04
*********************************************************************************/
#include "device.h"
#include "deviceSet.h"
#include "usart2.h"
#include "delay.h"
#include "timer.h"
#include "data_typedef.h"	  
#include "tcp_protocol.h"
#include "lcd.h"  
#include "display.h"
#include "ec200x.h"
#include "door_ctrl.h"
#include "pc_protocol.h"
#include "disinfection.h"

/*
***********************************************************************
*	函 数 名: show
*	功能说明: 以十六进制显示数组里的内容
*	形    参:	无
*	返 回 值: 无
***********************************************************************
*/
void show(uint8_t num[], uint8_t n)
{
    uint8_t i;
		printf("\r\n");
    for(i=0; i<n; i++)
		{
      printf("0x%02X ",num[i]);
		}
		printf("\r\n");
}

/*
***********************************************************************
*	函 数 名: DeviceConfigParamInit
*	功能说明: 设备配置参数初始化
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void DeviceConfigParamInit(void)
{
	//取出保存的参数
	if(GetDeviceConfig())			//没有保存过设备系统参数，则为默认值
	{
		DeviceSetParamInit();								//设备参数修改缓存变量初始化，为了达到当前Cur区参数与设置Set区参数同步
	}else{		//有保存过数据，则根据保存在FLASH中的参数进行设置
		printf("\r\n正在初始化设备系统参数！\r\n");		
		DeviceParamInit();								//将flash中读取出来的Set区参数同步到当前Cur区参数
	}

#ifdef FOUR_DROP_PORTS
	//四投放口专用固件：兼容旧Flash中保存的两路设备类型。
	deviceType = FOUR_CLASSIFICATION;
	devChannelNumbers = 4;
	setDeviceType = deviceType;
	setDevChannelNumbers = devChannelNumbers;
#endif
}

/*
***********************************************************************
*	函 数 名: CalcOverflowStartPointParam
*	功能说明: 计算满溢开始测量点的参数（如30%以下不做测量）
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void CalcOverflowStartPointParam(void)
{
	distanceParamAtStart = devChannel1DisMaxVal - ((devChannel1DisDepthVal*PerCentSetVal)/100);
	printf("\r\nParamAtStart = %d\r\n", distanceParamAtStart);
}

/*
***********************************************************************
*	函 数 名: DeviceInit
*	功能说明: 设备初始化
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void DeviceInit(void)
{
	printf("\r\n设备初始化......\r\n");
	sprintf(VersionStr, "版本:%s", VersionNumber);
	delay_ms(1000);										//系统刚开机，等待供电稳定后再操作
	LED_Init();			     							//LED端口初始化
	BeepInit();												//蜂鸣器控制初始化
	KeyInit();												//按键初始化
	LCD_Init();	 											//12864显示屏初始化
	Screen_SystemInit();							//显示初始化界面
	ElectronicLock_Init();						//电磁锁接口初始化
	RFID_Init();											//RFID接品初始化
	LTE_Init();												//LTE通讯模块初始化
	Audio_Init();											//音频控制初始化
	MotorInit();											//电机接口初始化
	DeviceConfigParamInit();					//设备配置参数初始化
	CalcOverflowStartPointParam();		//计算满溢开始计量点的参数
	while(doorResetMark == 0)					//门复位操作
	{
		DoorResetTask();
	}
	
	DeviceInfoShow();
	LCD_ShowSignal(0);
	
	deviceInitFlag = 1;								//标志设备硬件初始化完成
	printf("\r\n设备初始化完成！！！\r\n");
}

/*
***********************************************************************
*	函 数 名: DeviceTest
*	功能说明: 硬件测试
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void DeviceTest(void)
{
	printf("\r\n硬件测试！\r\n");
	
	printf("\r\n测试喷淋消毒！\r\n");
	StartUpSprayDisinfection();
	delay_ms(1000);
	StopSprayDisinfection();
	delay_ms(1000);
	
	printf("\r\n测试喷淋灭火！\r\n");
	DoorClose(4);
	delay_ms(1000);
	DoorStop(4);
	delay_ms(1000);
	
	printf("\r\n测试UV消毒！\r\n");
	StartUpDisinfection();
	delay_ms(1000);
	StopDisinfection();
	delay_ms(1000);
	
	printf("\r\n测试排气扇！\r\n");
	Unlock(3);
	Unlock(4);
	delay_ms(1000);
	Locked(3);
	Locked(4);
	
	printf("\r\n硬件测试结束！\r\n");
}

/*
***********************************************************************
*	函 数 名: ascii_to_hex
*	功能说明: ascii字符串转十六进制
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void ascii_to_hex(uint8_t* str, uint8_t* hex, uint16_t size)
{
	uint8_t deposit [64];
	uint16_t i = 0;
	uint16_t num = 0;

	for(i=0; i<size; i++)
	{
		switch(str[i])
		{
			case '0':
			  deposit[i]=0x00;
				break;
			case '1':
			  deposit[i]=0x01;
				break;
			case '2':
			  deposit[i]=0x02;
				break;
			case '3':
			  deposit[i]=0x03;
				break;
			case '4':
			  deposit[i]=0x04;
				break;
			case '5':
			  deposit[i]=0x05;
				break;
			case '6':
			  deposit[i]=0x06;
				break;
			case '7':
				deposit[i]=0x07;
				break;
			case '8':
				deposit[i]=0x08;
				break;
			case '9':
				deposit[i]=0x09;
				break;
			case 'A':
			case 'a':
				deposit[i]=0x0A;
				break;
			case 'B':
			case 'b':
				deposit[i]=0x0B;
				break;
			case 'C':
			case 'c':
				deposit[i]=0x0C;
				break;
			case 'D':
			case 'd':
				deposit[i]=0x0D;
				break;
			case 'E':
			case 'e':
				deposit[i]=0x0E;
				break;
			case 'F':
			case 'f':
				deposit[i]=0x0F;
				break;
			default:
				break;
		}
	}
	
	for(i=0; i<size/2; i++)
	{
		hex[i] = (deposit[i*2] << 4) | (deposit[i*2+1]);
	}
	
	show(hex, 16);
}

/*
***********************************************************************
*	函 数 名: DeviceScanning
*	功能说明: 设备扫描（这里有RFID-IC卡和二维码扫描）
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void DeviceScanning(void)
{
	uint8_t hexBuf[16];
	
	if(USART1_RX_STA & 0x8000)		//接收到一次数据了
	{
// 		if((USART1_RX_BUF[0] == 0x04) && (USART1_RX_BUF[1] == 0x16) && (USART1_RX_BUF[2] == 0x03))
		if(((USART1_RX_STA & 0x7FFF) == 34) && ((USART1_RX_BUF[30] == '0') || (USART1_RX_BUF[30] == 'F')) && ((USART1_RX_BUF[31] == '0') || (USART1_RX_BUF[31] == 'F')))
		{
			printf("\r\n刷IC卡\r\n");
// 			show(USART4_RX_BUF, 64);
			ascii_to_hex(USART1_RX_BUF, hexBuf, 32);
			memcpy(RFID_ID, hexBuf, 16);									//保存IC卡身份信息
			IC_CardDecode();
		}else{
			printf("\r\n扫二维码\r\n");
			QR_CodeDecode((char*)USART1_RX_BUF);	
		}
		memset(USART1_RX_BUF, 0x00, 128);														//清除缓存内容
		USART1_RX_STA = 0;
	}
}

/*
***********************************************************************
*	函 数 名: OpenDoorRequestTask
*	功能说明: 开门请求任务
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void OpenDoorRequestTask(void)
{
	static uint8_t controlSteps = 0;
	
	static timer waitingChooseTimer;						//定义一个定时器
	static timer waitingPutInTimer;							//定义一个定时器
	static timer waitingTimer1S;								//定义一个定时器
	
	static uint8_t timer_ok = 0;
	
	if(timer_ok == 0)
	{
		timer_ok = 1;
		
		timer_set(&waitingChooseTimer, CLOCK_SECOND*10);
		timer_set(&waitingPutInTimer, CLOCK_SECOND*200);		//等待投放完成时间
		timer_set(&waitingTimer1S, CLOCK_SECOND*1);
	}
	
	switch(controlSteps)
	{
		case 0x00:		//初始状态
			if(isOpenDoor == 1)		//有开门请求
			{
				printf("\r\n----> 有开门请求，设备就绪 <----\r\n");		
				isOpenDoor = 0;
				
// 				swipingCardStatus = 1;										//开门提示声			
				
// 				keyValue = 0;
				exitMark = 0;
				isOpenDoorRequest_1 = 0;
				isOpenDoorRequest_2 = 0;
				isOpenDoorRequest_3 = 0;
				isOpenDoorRequest_4 = 0;
				putInEndMark = 0;
			
				printf("\r\n等待用户投放\r\n");

				timer_restart(&waitingPutInTimer);
				controlSteps = 0x01;											//有开门请求操作，跳转到正在投放操作流程
			}
			break;
			
		case 0x01:		//等待用户投放
			if(timer_expired(&waitingPutInTimer))				//投放超时
			{
				putInOKMark = 1;
				
				printf("\r\n投放时间到退出\r\n");
				controlSteps = 0x03;
				break;
			}
			
			//是否有延迟投放
			if(delayCloseDoorStatus2 == 1)
			{
				delayCloseDoorStatus2 = 0;
				timer_restart(&waitingPutInTimer);
				printf("\r\nOpenDoorRequestTask延迟!\r\n");
			}
			
			if(openDoorNumber == 255)
			{
				openDoorNumber = 0;
				
				beep_shortBeepMark = 1;
				
				if(fullMark1 == 0) isOpenDoorRequest_1 = 1;
				if(fullMark2 == 0) isOpenDoorRequest_2 = 1;
				if(fullMark3 == 0) isOpenDoorRequest_3 = 1;
				if(fullMark4 == 0) isOpenDoorRequest_4 = 1;
			}
			
			if(openDoorNumber != 0)		//用户选择了投放类型
			{
				beep_shortBeepMark = 1;
				switch(openDoorNumber)
				{
					case 1:
						if(fullMark1 == 0)
						{
							isOpenDoorRequest_1 = 1;					//标志1号设备开始运行
							printf("\r\n1号按键按下\r\n");
						}else{
							printf("\r\n1号已满！\r\n");
						}
						break;
						
					case 2:
						if(fullMark2 == 0)
						{
							isOpenDoorRequest_2 = 1;					//标志1号设备开始运行
							printf("\r\n2号按键按下\r\n");
						}else{
							printf("\r\n2号已满！\r\n");
						}
						break;

					case 3:
						if(fullMark3 == 0)
						{
							isOpenDoorRequest_3 = 1;
							printf("\r\n3号按键按下\r\n");
						}else{
							printf("\r\n3号已满！\r\n");
						}
						break;

					case 4:
						if(fullMark4 == 0)
						{
							isOpenDoorRequest_4 = 1;
							printf("\r\n4号按键按下\r\n");
						}else{
							printf("\r\n4号已满！\r\n");
						}
						break;
						
					default:
						break;
				}
				openDoorNumber = 0;
			}
			
			//判断用户开门投放的箱子是否所有已经投放完成
			if(putInEndMark == 1)
			{
				putInEndMark = 0;
				putInOKMark = 1;
				printf("\r\n用户已经投放完成\r\n");
				
				controlSteps = 0x03;
				break;
			}
			break;
			
		case 0x03:
// 			SetKeyLedOFF(1);
// 			SetKeyLedOFF(2);
			
			//清除本流程中所使用到的变量为下一次做准备
			isOpenDoor = 0;
			keyValue = 0;
			isOpenDoorRequest_1 = 0;
			isOpenDoorRequest_2 = 0;
			isOpenDoorRequest_3 = 0;
			isOpenDoorRequest_4 = 0;
			
			controlSteps = 0x00;
			break;
			
		default:
			break;
	}
}

/*
***********************************************************************
*	函 数 名: ClearDevCtrlVar
*	功能说明: 清除设备控制过程中使用的变量，为下一次请求做准备
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void ClearDevCtrlVar(void)
{
	keyValue = 0;																		//清除按钮按下标志
	
	isOpenDoor = 0;																	//开门请求标志
	isOpenDoorRequest_1 = 0;
	isOpenDoorRequest_2 = 0;
	isOpenDoorRequest_3 = 0;
	isOpenDoorRequest_4 = 0;
}

/*
***********************************************************************
*	函 数 名: DeviceControl
*	功能说明: 设备控制
*	形    参：无
*	返 回 值: 无（更改全局变量putInOK_State，当完成操作后为1，由外部清除）
***********************************************************************
*/
void DeviceControlTask(void)
{
	static uint8_t controlSteps = 0;
	uint16_t tempWeight = 0;
	
	static uint8_t currentOpenDoorStatus_1 = 0;
	static uint8_t currentOpenDoorStatus_2 = 0;
	static uint8_t currentOpenDoorStatus_3 = 0;
	static uint8_t currentOpenDoorStatus_4 = 0;
	
	static uint8_t doorCloseOK_1 = 0;
	static uint8_t doorCloseOK_2 = 0;
	static uint8_t doorCloseOK_3 = 0;
	static uint8_t doorCloseOK_4 = 0;
	
	static uint16_t preChangeWeight1 = 0;
	static uint16_t preChangeWeight2 = 0;
	static uint16_t preChangeWeight3 = 0;
	static uint16_t preChangeWeight4 = 0;
	
	uint16_t tempData1 = 0;
	uint16_t tempData2 = 0;
	
	static uint32_t startTimer = 0;									//开关门开始时间
	static uint32_t endTimer = 0;										//开关门结束时间
	
	static uint32_t preRemainingTimer = 0;					//上一次还剩时间
	
	static timer waitingTimer_100ms;								//等待100ms定时器
	static timer waitingTimer_300ms;								//等待300ms定时器
	static timer waitingTimer_500ms;								//等待500ms定时器
	static timer waitingTimer_1S;										//等待1S定时器
	static timer openDoorTimer;											//用于开门时间限制
	static timer closeDoorTimer;										//用于关门时间限制
	static timer waitingLeaveTimer;									//等待人离开时间
	static timer waitingTimer_300S;									//5分钟后自动关门
	static timer waitingGetWeight;
	static timer waitingGetDis;
	
	static uint8_t timer_ok = 0;
	
	if(timer_ok == 0)
	{
		timer_ok = 1;
		
		timer_set(&waitingTimer_100ms, 1);
		timer_set(&waitingTimer_300ms, 15);
		timer_set(&waitingTimer_500ms, 5);
		timer_set(&waitingTimer_1S, CLOCK_SECOND*1);
		timer_set(&openDoorTimer, 16);											//创建1个定时器，用于开门时间限制
		timer_set(&closeDoorTimer, 60);											//创建1个定时器，用于关门时间限制
		timer_set(&waitingLeaveTimer, CLOCK_SECOND*180);			//创建1个定时器，用于检测人离开
		timer_set(&waitingTimer_300S, CLOCK_SECOND*300);		//创建1个定时器，用于5分钟后自动关门
		timer_set(&waitingGetWeight, CLOCK_SECOND*2);
		timer_set(&waitingGetDis, CLOCK_SECOND*1);
	}

	switch(controlSteps)
	{
		case 0x00:			//初始状态
			if((isOpenDoorRequest_1 == 1) || (isOpenDoorRequest_2 == 1) || (isOpenDoorRequest_3 == 1) || (isOpenDoorRequest_4 == 1))		//有开门请求
			{
				printf("\r\n----> 有开门请求\r\n");
				
//				disinfectingMark = 2;											//开门前中断消毒
//				sprayDisinfectingMark = 2;
				
				updateDistanceMark = 1;											//标志当前正在投放不获取测距数据
				
				pcRequestClooseDoorMark = 0;
				
				isOpenDoor_1 = 0;
				isOpenDoor_2 = 0;
				isOpenDoor_3 = 0;
				isOpenDoor_4 = 0;
				
				currentOpenDoorStatus_1 = 0;
				currentOpenDoorStatus_2 = 0;
				currentOpenDoorStatus_3 = 0;
				currentOpenDoorStatus_4 = 0;
				
				doorCloseOK_1 = 0;
				doorCloseOK_2 = 0;
				doorCloseOK_3 = 0;
				doorCloseOK_4 = 0;
				
				isCloseDoorMark_1 = 0;		
				isCloseDoorMark_2 = 0;
				isCloseDoorMark_3 = 0;
				isCloseDoorMark_4 = 0;
				
				smallBottleCount = 0;											//投放前先清除瓶子的数量
				bigBottleCount = 0;
				cansCount = 0;
				
				getWeightBefore1 = weight1;								//取出开门前的重量（用于上传）
				getWeightBefore2 = weight2;
				getWeightBefore3 = weight3;
				getWeightBefore4 = weight4;
				
				preChangeWeight1 = weight1;								//取出当前秤上面的重量（用于判断称重有没有变化）
				preChangeWeight2 = weight2;				
				preChangeWeight3 = weight3;	
				preChangeWeight4 = weight4;
				
				remainingTimer = 0;
				
				printf("\r\n取出开门前的重量：");	
				printf("W1 = %2.2f Kg, W2 = %2.2f Kg, W3 = %2.2f Kg, W4 = %2.2f Kg\r\n",
							(float)getWeightBefore1/100,
							(float)getWeightBefore2/100,
							(float)getWeightBefore3/100,
							(float)getWeightBefore4/100);
				
				timer_restart(&waitingTimer_100ms);
				controlSteps = 0x01;											//有开门请求操作，跳转到正在投放操作流程
				break;
			}
			break;
			
		case 0x01:		
			if(timer_expired(&waitingTimer_100ms))
			{
				if(isOpenDoorRequest_1 == 1)
				{
					isOpenDoorRequest_1 = 0;
					isOpenDoor_1 = 1;
					currentOpenDoorStatus_1 = 1;						//标志门1有打开
				}
				
				if(isOpenDoorRequest_2 == 1)
				{
					isOpenDoorRequest_2 = 0;
					isOpenDoor_2 = 1;
					currentOpenDoorStatus_2 = 1;						//标志门2有打开
				}
				
				if(isOpenDoorRequest_3 == 1)
				{
					isOpenDoorRequest_3 = 0;
					isOpenDoor_3 = 1;
					currentOpenDoorStatus_3 = 1;						//标志门3有打开
				}
				
				if(isOpenDoorRequest_4 == 1)
				{
					isOpenDoorRequest_4 = 0;
					isOpenDoor_4 = 1;
					currentOpenDoorStatus_4 = 1;						//标志门4有打开
				}
				
				timer_restart(&waitingTimer_300S);
				controlSteps = 0x02;
				break;
			}
			break;
			
		case 0x02:		//检测人是否已经离开
			if(timer_expired(&waitingTimer_300S))
			{
				printf("\r\n5分钟超时自动关门\r\n");
				controlSteps = 0x04;										//转到关门
				break;
			}
			
			timer_restart(&waitingLeaveTimer);
			timer_restart(&waitingTimer_300S);
			controlSteps = 0x03;
			break;
			
		case 0x03:		//确认人离开
			if(timer_expired(&waitingTimer_300S))			//如果5分钟定时时间到了，则开门停止
			{
				controlSteps = 0x04;										//转到关门
				printf("\r\n5分钟超时自动关门\r\n");
				break;
			}
			
			//判断等待过程中是否有继续开门请求
			if(isOpenDoorRequest_1 == 1)
			{
				isOpenDoorRequest_1 = 0;
				isOpenDoor_1 = 1;
				currentOpenDoorStatus_1 = 1;						//标志门1有打开
				timer_restart(&waitingLeaveTimer);
				delayCloseDoorStatus = 1;
				delayCloseDoorStatus2 = 1;
			}
				
			if(isOpenDoorRequest_2 == 1)
			{
				isOpenDoorRequest_2 = 0;
				isOpenDoor_2 = 1;
				currentOpenDoorStatus_2 = 1;						//标志门2有打开
				timer_restart(&waitingLeaveTimer);
				delayCloseDoorStatus = 1;
				delayCloseDoorStatus2 = 1;
			}
			
			if(isOpenDoorRequest_3 == 1)
			{
				isOpenDoorRequest_3 = 0;
				isOpenDoor_3 = 1;
				currentOpenDoorStatus_3 = 1;						//标志门3有打开
				timer_restart(&waitingLeaveTimer);
				delayCloseDoorStatus = 1;
				delayCloseDoorStatus2 = 1;
			}
			
			if(isOpenDoorRequest_4 == 1)
			{
				isOpenDoorRequest_4 = 0;
				isOpenDoor_4 = 1;
				currentOpenDoorStatus_4 = 1;						//标志门4有打开
				timer_restart(&waitingLeaveTimer);
				delayCloseDoorStatus = 1;
				delayCloseDoorStatus2 = 1;
			}
			
			//判断是否有投放，有投放则延迟关门时间
			if(weight1 > preChangeWeight1)
			{
				if((weight1 - preChangeWeight1) >= 5)												//有投放大于50g
				{
					preChangeWeight1 = weight1;
					timer_restart(&waitingLeaveTimer);			//设定等待时间内检测到有人投放，则一直保持开门
					delayCloseDoorStatus = 1;								//标志有延迟关门，让开门请求投放任务延迟同步
					delayCloseDoorStatus2 = 1;
					printf("\r\n延迟关门1\r\n");
				}
			}
			if(weight2 > preChangeWeight2)
			{
				if((weight2 - preChangeWeight2) >= 5)
				{
					preChangeWeight2 = weight2;
					timer_restart(&waitingLeaveTimer);			//设定等待时间内检测到有人投放，则一直保持开门
					delayCloseDoorStatus = 1;								//标志有延迟关门，让开门请求投放任务延迟同步
					delayCloseDoorStatus2 = 1;
					printf("\r\n延迟关门2\r\n");
				}
			}
			if(weight3 > preChangeWeight3)
			{
				if((weight3 - preChangeWeight3) >= 5)
				{
					preChangeWeight3 = weight3;
					timer_restart(&waitingLeaveTimer);
					delayCloseDoorStatus = 1;
					delayCloseDoorStatus2 = 1;
					printf("\r\n延迟关门3\r\n");
				}
			}
			if(weight4 > preChangeWeight4)
			{
				if((weight4 - preChangeWeight4) >= 5)
				{
					preChangeWeight4 = weight4;
					timer_restart(&waitingLeaveTimer);
					delayCloseDoorStatus = 1;
					delayCloseDoorStatus2 = 1;
					printf("\r\n延迟关门4\r\n");
				}
			}
			
			//取出剩余关门时间
			remainingTimer = timer_remaining(&waitingLeaveTimer)/10;
			if(remainingTimer != preRemainingTimer)
			{
				preRemainingTimer = remainingTimer;
				getRemainingTimerStatus = 1;
				
				if(remainingTimer == 3)
				{
					beep_closeDoorBeepMark = 1;
				}
// 				printf("\r\n剩余关门时间 = %d\r\n", remainingTimer);
			}
			
			if(timer_expired(&waitingLeaveTimer))				//如果定时时间到了，则开门停止
			{
				printf("\r\n人已经离开\r\n");
				printf("\r\n关门\r\n");
				controlSteps = 0x04;
				break;
			}
			
			if(pcRequestClooseDoorMark == 1)
			{
				pcRequestClooseDoorMark = 0;
				
				printf("\r\n上位机请求关闭投口\r\n");
				printf("\r\n关门\r\n");
				controlSteps = 0x04;
				break;
			}
			
			break;
			
		case 0x04:			//关门		
			printf("\r\n结束投放，正在关门\r\n");
			isCloseDoorMark_1 = 1;																//关门
			isCloseDoorMark_2 = 1;
			isCloseDoorMark_3 = 1;
			isCloseDoorMark_4 = 1;
			
			controlSteps = 0x05;
			timer_restart(&closeDoorTimer);							//从当前时间重新开始n秒定时器
			break;
			
		case 0x05:			//关门检测
			if(timer_expired(&closeDoorTimer))					//如果定时时间到了，则关门停止
			{
				controlSteps = 0x06;
				printf("\r\n等待关门时间到\r\n");
				timer_restart(&waitingGetWeight);
				break;
			}
			
			//判断对应的门是否已经关闭完成
			if(currentOpenDoorStatus_1 == 1)
			{
				if(openDoorCtrlEndMark_1 == 1)
				{
					doorCloseOK_1 = 1;
				}
			}else{
				doorCloseOK_1 = 1;
			}
			
			if(currentOpenDoorStatus_2 == 1)
			{
				if(openDoorCtrlEndMark_2 == 1)
				{
					doorCloseOK_2 = 1;
				}
			}else{
				doorCloseOK_2 = 1;
			}
			
			if(currentOpenDoorStatus_3 == 1)
			{
				if(openDoorCtrlEndMark_3 == 1)
				{
					doorCloseOK_3 = 1;
				}
			}else{
				doorCloseOK_3 = 1;
			}
			
			if(currentOpenDoorStatus_4 == 1)
			{
				if(openDoorCtrlEndMark_4 == 1)
				{
					doorCloseOK_4 = 1;
				}
			}else{
				doorCloseOK_4 = 1;
			}
			
			if((doorCloseOK_1 == 1) && (doorCloseOK_2 == 1) &&
				 (doorCloseOK_3 == 1) && (doorCloseOK_4 == 1))
			{
				doorCloseOK_1 = 0;
				doorCloseOK_2 = 0;
				doorCloseOK_3 = 0;
				doorCloseOK_4 = 0;
				
				timer_restart(&waitingGetWeight);
				controlSteps = 0x06;
				break;
			}
			break;
			
		case 0x06:		//等待称重稳定后取出称重数据
			if(timer_expired(&waitingGetWeight))
			{
				getWeightAfter1 = weight1;									//取出投放后的重量
				getWeightAfter2 = weight2;
				getWeightAfter3 = weight3;
				getWeightAfter4 = weight4;
				
				updateDistanceMark = 0;											//标志可以获取测距数据
				restartGetDisDataMark = 1;									//重新采集满溢测距数据
				
				timer_restart(&waitingGetDis);
				controlSteps = 0x50;
				break;
			}
			break;
			
		case 0x50:
			if(timer_expired(&waitingGetDis))
			{
				controlSteps = 0x07;
				break;
			}
			break;

		case 0x07:			//计算本次投放重量
			printf("\r\n计算本次投放重量\r\n");
			printf("\r\n秤1重量: %2.2f Kg -> %2.2f Kg\r\n", (float)getWeightBefore1/100, (float)getWeightAfter1/100);
			printf("\r\n秤2重量: %2.2f Kg -> %2.2f Kg\r\n", (float)getWeightBefore2/100, (float)getWeightAfter2/100);
			printf("\r\n秤3重量: %2.2f Kg -> %2.2f Kg\r\n", (float)getWeightBefore3/100, (float)getWeightAfter3/100);
			printf("\r\n秤4重量: %2.2f Kg -> %2.2f Kg\r\n", (float)getWeightBefore4/100, (float)getWeightAfter4/100);

			//第一组称重数据
			if(getWeightAfter1 < getWeightBefore1)
			{
				getWeight1 = 0;
			}else{
				tempWeight = getWeightAfter1 - getWeightBefore1;		//当前重量 - 开门前的重量 = 一次投放的重量
				if(tempWeight >= 10)																//当得量超过100g时，起称值
				{
					getWeight1 = tempWeight;
				}else{
					getWeight1 = 0;
				}
			}
			
			//第二组称重数据
			if(getWeightAfter2 < getWeightBefore2)
			{
				getWeight2 = 0;
			}else{
				tempWeight = getWeightAfter2 - getWeightBefore2;		//当前重量 - 开门前的重量 = 一次投放的重量
				if(tempWeight >= 10)																//当得量超过100g时，起称值
				{
					getWeight2 = tempWeight;
				}else{
					getWeight2 = 0;
				}
			}
			
			//第三组称重数据
			if(getWeightAfter3 < getWeightBefore3)
			{
				getWeight3 = 0;
			}else{
				tempWeight = getWeightAfter3 - getWeightBefore3;
				getWeight3 = (tempWeight >= 10) ? tempWeight : 0;
			}
			
			//第四组称重数据
			if(getWeightAfter4 < getWeightBefore4)
			{
				getWeight4 = 0;
			}else{
				tempWeight = getWeightAfter4 - getWeightBefore4;
				getWeight4 = (tempWeight >= 10) ? tempWeight : 0;
			}

			printf("\r\n正在获取测距数据\r\n");
			controlSteps = 0x11;											//转到获取测距数据
			break;
			
		case 0x11:			//获取测距数据
			printf("\r\n对数据进行汇总\r\n");
			controlSteps = 0x12;
			break;
		
		case 0x12:			//对本次投放情况进行数据汇总				
// 			printf("\r\n---------> 本次投放数据如下：\r\n");
			
			controlSteps = 0x13;
			break;
			
		case 0x13:
			printf("\r\n标志投放数据已生成！\r\n");
			putInEndMark = 1;											//标志投放操作已完成，可以上传投放数据
			
//			disinfectingMark = 1;									//投放结束启动消毒
//			sprayDisinfectingMark = 1;
			
			//增加开法关门异常处理
// 			controlSteps = 0x40;
			controlSteps = 0x14;
// 			timer_restart(&waitingTimer_100ms);
			break;
			
		case 0x40:

			break;
			
		case 0x14:
			ClearDevCtrlVar();										//清除投放过程中使用的变量信息，为下一次投放准备
			
			printf("\r\n---> 投放控制完成！\r\n");
			controlSteps = 0x00;

			break;
			
		case 0x15:		//桶已经装满退出操作
			printf("\r\n给MCU1发送桶已满禁止开门指令\r\n");
			ClearPutInInfo();											//清除投放过程中使用的变量信息，为下一次投放准备
				
// 			SetKeyLedOFF(1);
// 			SetKeyLedOFF(2);
			
			printf("\r\n---------> 结束投放！！！\r\n");
			controlSteps = 0x00;
			break;


		
		case 0x20:		//设备故障退出操作（限位开关没有闭合）
			printf("\r\n给MCU1发送设备故障指令\r\n");
// 			SendEquipmentFailureCMD();						//向主机发送设备故障指令
			ClearPutInInfo();											//清除投放过程中使用的变量信息，为下一次投放准备
				
			SetKeyLedOFF(1);
			SetKeyLedOFF(2);
			
			faultLedFlashMark = 1;								//标志设备故障，闪灯提示
			deviceFault = 1;											//标志设备故障，让异常处理任务重启系统
			
			printf("\r\n---------> 本次投放结束！！！\r\n");
			controlSteps = 0x21;
			break;
			
		case 0x21:
			//当出现限位开关异常就会运行到此处，直到修复
			break;
			
		default:
			controlSteps = 0x00;
			break;
	}
}

/*
***********************************************************************
*	函 数 名: CleanHolding
*	功能说明: 收运有效保持处理
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void CleanHolding(void)
{
	static uint8_t currentStatus = 0x00;
	static uint8_t nextStatus = 0x00;
	
	static timer cleanHoldingTimer;									//收运过程有效保持时间（用于控制刷收运卡后，在有效时间内是不执行消毒操作的）
	
	static uint8_t timer_ok = 0;
	if(timer_ok == 0)
	{
		timer_ok = 1;
		
 		timer_set(&cleanHoldingTimer, CLOCK_SECOND*60*3);
	}
	
	currentStatus = nextStatus;
	switch(currentStatus)
	{
		case 0x00:
			if((disinfectingMark == 2) || (sprayDisinfectingMark == 2))
			{
				printf("\r\n当前正在收运，保持一段时间不消毒！\r\n");
				timer_restart(&cleanHoldingTimer);
				nextStatus = 0x01;
				break;
			}
			break;
		
		case 0x01:
			if(timer_expired(&cleanHoldingTimer))
			{
				printf("\r\n收运保持时间到！\r\n");
				disinfectingMark = 0;
				sprayDisinfectingMark = 0;
				nextStatus = 0x00;
				break;
			}
			break;
		
		default: break;
	}
}

/*
***********************************************************************
*	函 数 名: CollectorLockCtrlTask
*	功能说明: 箱体门收运锁控制任务
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void CollectorLockCtrlTask(void)
{
	static uint8_t runningSteps = 0;

	static timer eleLockUnlockingTimer;							//电磁锁开启时间
	static timer waitingTimer;
	
	static uint8_t timer_ok = 0;
	
	if(timer_ok == 0)
	{
		timer_ok = 1;
		timer_set(&eleLockUnlockingTimer, 2);
		timer_set(&waitingTimer, 2);
	}

	switch(runningSteps)
	{
		case 0x00:		//初始状态
			//刷收运卡开门
			if(boxOpenMark == 1)
			{
				boxOpenMark = 0; 
				
				disinfectingMark = 2;		 									//打开收运门时暂停消毒
				sprayDisinfectingMark = 2;
				
				runningSteps = 0x01;
				break;
			}
			break;
			
		case 0x01:		//上传收运人员身份信息
			printf("\r\n打开箱体门！\r\n");
// 			Unlock(5);
			Unlock(6);
			timer_restart(&eleLockUnlockingTimer);
			runningSteps = 0x02;
			break;
			
		case 0x02:		//开锁等待
			if(timer_expired(&eleLockUnlockingTimer))
			{
// 				Locked(5);
				Locked(6);
				timer_restart(&waitingTimer);
				runningSteps = 0x03;
				break;
			}
			break;
			
		case 0x03:		//退出
			if(timer_expired(&waitingTimer))
			{
				boxOpenMark = 0;
				runningSteps = 0x00;
				break;
			}
			break;
			
		default:
			break;
	}
	
	CleanHolding();									//收运有效保持处理，用于控制刷收运卡后，在有效时间内是不执行消毒操作的
}

/*
***********************************************************************
*	函 数 名: FillLightTask
*	功能说明: 拍照补光灯处理任务
*	形    参:	无
*	返 回 值: 无
***********************************************************************
*/
void FillLightTask(void)
{
  static uint8_t ledStatus = 0;
  
  static timer ledOnTimer;	
  static timer ledOffTimer;	
	static uint8_t timer_ok = 0;
	
	if(timer_ok == 0)
	{
		timer_ok = 1;
		timer_set(&ledOnTimer, 150);
	}
  
  switch(ledStatus)
  {
    case 0x00:
      if(fillLightMask == 1)
			{
				Unlock(1);
				Unlock(2);
				printf("\r\n打开补光灯！\r\n");
					
				timer_restart(&ledOnTimer);
				ledStatus = 0x01;
				break;
			}
      break;
      
    case 0x01:
      if(timer_expired(&ledOnTimer))
      {
				Locked(1);
				Locked(2);
				
				printf("\r\n关闭补光灯！\r\n");
					
        fillLightMask = 0;
        ledStatus = 0x00;
      }
      break;
      
    default:
      ledStatus = 0x00;
      break;
  }
}

/*
***********************************************************************
*	函 数 名: CoolingFanCtrlTask
*	功能说明: 散热风扇控制任务
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void CoolingFanCtrlTask(void)
{
	static uint8_t currentStatus = 0x00;
	static uint8_t nextStatus = 0x00;
	
	static timer responseTimeout;
	static uint8_t timer_ok = 0;
	
	if(timer_ok == 0)
	{
		timer_ok = 1;
		timer_set(&responseTimeout, CLOCK_SECOND*10);
	}
	
	currentStatus = nextStatus;
	switch(currentStatus)
	{
		case 0x00:
			if(temperature >= 40)
			{
				printf("\r\n温度过热，启动散热风扇！\r\n");
				Unlock(3);
				Unlock(4);
				nextStatus = 0x01;
				break;
			}
			break;
			
		case 0x01:
			if(temperature <= 38)
			{
				printf("\r\n温度恢复正常！\r\n");
				Locked(3);
				Locked(4);
				nextStatus = 0x00;
				break;
			}
			break;
			
		default:
			break;
	}
}

/*
***********************************************************************
*	函 数 名: SprayCtrlTask
*	功能说明: 喷淋控制任务
*	形    参：无
*	返 回 值: 无
***********************************************************************
*/
void SprayCtrlTask(void)
{
	static uint8_t currentStatus = 0x00;
	static uint8_t nextStatus = 0x00;
	
	static timer responseTimeout;
	static uint8_t timer_ok = 0;
	
	if(timer_ok == 0)
	{
		timer_ok = 1;
		timer_set(&responseTimeout, CLOCK_SECOND*10);
	}
	
	currentStatus = nextStatus;
	switch(currentStatus)
	{
		case 0x00:
			if(LIMI_KEY3 == 0)
			{
				printf("\r\n烟雾传感器监测到异常，启动喷淋！\r\n");
				DoorClose(4);
				beep_warningBeepMark = 1;
				
				smokeAlarmStatus = 1;
				PC_ProCommandSend(0x65);
				nextStatus = 0x02;
				break;
			}
			
			if(temperature >= 80)
			{
				printf("\r\n温度过热(>80度)，启动喷淋！\r\n");
// 				DoorClose(4);
				beep_warningBeepMark = 1;
				nextStatus = 0x01;
				break;
			}
			break;
			
		case 0x01:		//温度过热处理
			if(temperature <= 75)
			{
				printf("\r\n温度(<75度)恢复正常！\r\n");
// 				DoorStop(4);
				nextStatus = 0x00;
				break;
			}
			beep_warningBeepMark = 1;
			break;
			
		case 0x02:		//烟雾传感器监测到异常处理
			if(LIMI_KEY3 == 1)
			{
				printf("\r\n烟雾传感器恢复正常！\r\n");
				DoorStop(4);
				
				smokeAlarmStatus = 0;
				PC_ProCommandSend(0x65);
				nextStatus = 0x00;
			}
			beep_warningBeepMark = 1;
			break;
			
		default:
			break;
	}
}

/*
***********************************************************************
*	函 数 名: SystemExceptionTask
*	功能说明: 系统异常处理任务
*	形    参：无
*	返 回 值: 复位完成后返回1
***********************************************************************
*/
void SystemExceptionTask(void)
{
	static uint8_t restartSteps = 0x00;
	static uint8_t ledFlashStatus = 0;
	
	static timer restartTimer;
	static timer ledFlashTimer;	
	static uint8_t timer_ok = 0;
	
	if(timer_ok == 0)
	{
		timer_ok = 1;
		timer_set(&restartTimer, CLOCK_SECOND*20);	
		timer_set(&ledFlashTimer, 5);							//LED闪烁时间		
	}
	
	switch(restartSteps)
	{
		case 0x00:
			if(deviceFault == 1)		//设备检测到系统异常，则进行异常处理
			{
				restartSteps = 0x01;
				timer_restart(&restartTimer);
				break;
			}
			break;
			
		case 0x01:
			if(timer_expired(&restartTimer))		//进入死循环让看门狗复位系统
			{
				while(1);
			}
			break;
			
		default:
			break;
	}
	
	//出现异常时指示灯闪烁
	switch(ledFlashStatus)
	{
		case 0x00:
			if(faultLedFlashMark == 1)
			{
				SetKeyLedON(3);
				SetKeyLedON(4);
				if(timer_expired(&ledFlashTimer))
				{
					ledFlashStatus = 0x01;
					timer_restart(&ledFlashTimer);
				}
			}
			break;
			
		case 0x01:
			SetKeyLedOFF(3);
			SetKeyLedOFF(4);
			if(timer_expired(&ledFlashTimer))
			{
				ledFlashStatus = 0x00;
				timer_restart(&ledFlashTimer);
			}
			break;
			
		default:
      ledFlashStatus = 0x00;
      break;
	}
}

/******************** (C) COPYRIGHT 2017 CXHY *****END OF FILE*******************/
