#include "user.h"
#include PROJECT_H
#include "ikk-token.h"
#include "ikk-opt-tunnel.h"
#include "ikk-factory-test.h"
#include "ikk-cluster.h"
#include "ikk-pwm.h"
#include "ikk-timer.h"
#include "ikk-uart.h"
#include "ikk-relay.h"
#include "ikk-led.h"
#include "ikk-ota.h"
#include "ikk-command.h"
#include "ikk-common-utils.h"
#include "ikk-interpan.h"
#include "ikk-pwm.h"
#define ZERO_PIN		GPIO_PA0

#define RELAY1_PIN		GPIO_PC0
#define RELAY2_PIN		GPIO_PC4
#define RELAY3_PIN		GPIO_PC6
#define RELAY4_PIN		GPIO_PC5

#define LED_RADAR_PIN	GPIO_PD4
#define LED1_PIN		GPIO_PB5
#define LED2_PIN		GPIO_PA4
#define LED3_PIN		GPIO_PD2
#define LED4_PIN		GPIO_PA3

#define KEY_SYS_PIN		GPIO_PD7
#define KEY1_PIN		GPIO_PC7
#define KEY2_PIN		GPIO_PB4
#define KEY3_PIN		GPIO_PD3
#define KEY4_PIN		GPIO_PA6
#define RADAR_PIN		GPIO_PC1


#define UART_TX_PIN		GPIO_PB7
#define UART_RX_PIN		GPIO_PB1
#define SYS_BUTTON_LONG_PRESS_TIME_MS			(5 * 1000)
#define DELAY_REPORT_DATA_AFTER_NWK_JOINED_MS	(3 * 1000)

#define HEART_RAND_MIN_NUM						(240 * 1000)
#define HEART_RAND_MAX_NUM						(300 * 1000)

#define LED_SLOW_BLINK_ON_TIME_MS				500
#define LED_SLOW_BLINK_OFF_TIME_MS				500
#define LED_FAST_BLINK_ON_TIME_MS				200
#define LED_FAST_BLINK_OFF_TIME_MS				200

#define LED_SLOW_BLINK_CONTINUE_TIME_MS			(60 * 1000)
#define LED_FAST_BLINK_CONTINUE_TIME_MS			(5 * 1000)

#define MIN_JOINED_NWK_DELAY_TIME_MS 			(7 * 1000) //重新上电后最短时间，用于判断是否随机延时10~40S上报心跳和CMEI和ISN

#define RAND_MIN_NUM							(3 * 1000) //最小随机数,单位MS
#define RAND_MAX_NUM 							(6 * 1000) //最大随机数

#define REPORT_ATTR_MAX_RAND_NUM				(7 * 1000) //场景下发控制后随机最大延时上报状态,状态改变后SDK会主动上报
#define REPORT_ATTR_MIN_RAND_NUM				(2.5 * 1000) //场景下发控制后随机最小延时上报状态


#define CHECKED_ZERO_DELAY_ON_TIME_MS			(6000)//因继电器会有延时，检测到零点后，按键开关或命令下发开关延时去开的时间，
#define CHECKED_ZERO_DELAY_OFF_TIME_MS			(5970)//因继电器会有延时，检测到零点后，按键开关或命令下发开关延时去关的时间，
//join nwk timeout
#define NWK_STEERING_TIMEOUT_MS 				(60 * 1000)

#define HEART_DEBUG 							0
#if HEART_DEBUG
#define HEARTBEAT_TIME_MS						(20 * 1000)
#else
#define HEARTBEAT_TIME_MS						kGetRandNum(HEART_RAND_MIN_NUM, HEART_RAND_MAX_NUM)
#endif

#define RADAR_ON_TIME_MS						10000
#define SENSOR_LONG_PRESS_TIME_MS				200
#define MAX_FIRST_USER_KEY_LEAVE_NWK_INTERVAL_TIME_MS (14 * 1000)//第一个按键长按两次退网最大间隔时间

typedef enum {KEY_SYS_ID = 1,KEY1_ID, KEY2_ID, KEY3_ID, KEY4_ID , RADAR_ID}KEY_ID_ENUM;
typedef enum {LED_RADAR_ID = 1,LED1_ID, LED2_ID, LED3_ID, LED4_ID, LED_ALL_ID}LED_ID_ENUM;
typedef enum {RELAY_CHANNEL1_ID=1, RELAY_CHANNEL2_ID, RELAY_CHANNEL3_ID, RELAY_CHANNEL4_ID, RELAY_ALL_ID}RELAY_ID_ENUM;

#define GET_LED_ID(endpoint) 	(endpoint == 1?LED1_ID:(endpoint == 2?LED2_ID:(endpoint == 3?LED3_ID:LED4_ID)))
#define GET_ENDPOINT(led_id) 	(led_id == LED1_ID?1:(led_id == LED2_ID?2:(led_id == LED3_ID?3:4)))
#define GET_LED_ID_BY_ENDPOINT(endpoint, max_endpint) 	(endpoint <= max_endpint?GET_LED_ID(endpoint):LED_UNKNOW_ID)
// BUTTONs CONFIG
BtnConfSt g_btnConfList[] = {
	{KEY_SYS_ID, 	KEY_SYS_PIN, 	EBP_HIGH, false, true, SYS_BUTTON_LONG_PRESS_TIME_MS},	// Key1
	{KEY1_ID, 		KEY1_PIN, 		EBP_HIGH, false, true, SYS_BUTTON_LONG_PRESS_TIME_MS},	// Key2
	{KEY2_ID, 		KEY2_PIN, 		EBP_HIGH, false, false, 0xffffffff},	// Key2
	{KEY3_ID, 		KEY3_PIN, 		EBP_HIGH, false, false, 0xffffffff},	// Key2
	{KEY4_ID, 		KEY4_PIN, 		EBP_HIGH, false, false, 0xffffffff},	// Key2
};
// LEDs CONFIG
LedConfSt g_ledConfList[] = {
	{(uint8_t)LED_RADAR_ID, 1,  {LED_RADAR_PIN, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID}, ELP_HIGH },
	{(uint8_t)LED1_ID, 		1, 	{LED1_PIN, PWM1_ID, PIN_UNKNOW, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID}, ELP_HIGH },
	{(uint8_t)LED2_ID, 		1, 	{LED2_PIN, PWM2_ID, PIN_UNKNOW, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID}, ELP_HIGH },
	{(uint8_t)LED3_ID, 		1, 	{LED3_PIN, PWM3_ID, PIN_UNKNOW, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID}, ELP_HIGH },
	{(uint8_t)LED4_ID, 		1, 	{LED4_PIN, PWM4_ID, PIN_UNKNOW, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID}, ELP_HIGH },
	{(uint8_t)LED_ALL_ID, 	4,  {LED1_PIN, PWM1_ID, LED2_PIN, PWM2_ID, LED3_PIN, PWM3_ID, LED4_PIN, PWM4_ID}, ELP_HIGH },
};
PwmConfSt g_pwmConfList[] = {
	{PWM1_ID, {LED1_PIN, KK_PWM_CC0}},	//
	{PWM2_ID, {LED2_PIN, KK_PWM_CC1}},	//
	{PWM3_ID, {LED3_PIN, KK_PWM_CC2}},	//
	{PWM4_ID, {LED4_PIN, KK_PWM_CC3}},	//
};


// ZERO-ACCESS CONFIG
RelayChannelConfSt g_relayConfList[] = {
	{RELAY_CHANNEL1_ID, 1, {RELAY1_PIN, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW}, EZAP_HIGH },	// Channel1
	{RELAY_CHANNEL2_ID, 1, {RELAY2_PIN, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW}, EZAP_HIGH },	// Channel2
	{RELAY_CHANNEL3_ID, 1, {RELAY3_PIN, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW}, EZAP_HIGH },	// Channel3
	{RELAY_CHANNEL4_ID, 1, {RELAY4_PIN, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW}, EZAP_HIGH },	// Channel3
	{RELAY_ALL_ID, 		4, {RELAY1_PIN, RELAY2_PIN, RELAY3_PIN, RELAY4_PIN, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW, PIN_UNKNOW}, EZAP_HIGH },	//ALL
};

//老化配置
FactoryTestConfSt g_factoryTestConfList[] = {
		{KEY_SYS_ID, LONG_PRESS_1_TIMES, MECHANICAL_KEY_LONG_PRESS_TIME_MS},
		{KEY1_ID, LONG_PRESS_1_TIMES, MECHANICAL_KEY_LONG_PRESS_TIME_MS},
};
BindObjSt cluster_obj_list[] = {
	{ZCL_CLUSTER_GEN_ON_OFF, ZCL_ATTRID_ONOFF,  1},
	{ZCL_CLUSTER_GEN_ON_OFF, ZCL_ATTRID_ONOFF,  2},
	{ZCL_CLUSTER_GEN_ON_OFF, ZCL_ATTRID_ONOFF,  3},
	{ZCL_CLUSTER_GEN_ON_OFF, ZCL_ATTRID_ONOFF,  4},
};


void pOnOffAttributeChangeCallback(uint8_t endpoint,uint16_t cluster,uint16_t attribute,uint8_t *data,uint8_t data_type);

AttributeChangeConfSt attribte_change_list[] = {
	{ZCL_CLUSTER_GEN_ON_OFF, pOnOffAttributeChangeCallback},
};
uint32_t u32PeroidIntervalMS   = 2*1000;
bool Human_body_induction_flag = false;
static bool power_on_sync[4] = {false,false,false,false};

static uint8_t g_u8NoDisturbModeMinLevel  = 0x01;
static uint8_t g_u8NoDisturbModeMaxLevel    = 0x64;
//非控客网关首次数据是否上报标志
static bool g_bIsNotKonkeGatewayFirstReportedFlg = false;
static uint8_t g_u8CurrentHeartEndpoint = 1;
static uint8_t g_ucRelayIdBuff[] = {RELAY_CHANNEL1_ID, RELAY_CHANNEL2_ID, RELAY_CHANNEL3_ID, RELAY_CHANNEL4_ID, RELAY_ALL_ID};
void JoinCompleteCallback(NwkJoinCompltEnum nwkcomplt );
void kUserNetworkStatusNotify(NwkStatusEnum nwkst );
void kUserNetworkExitCompleteCallback(void);
void kUserOnOffClusterOnOffStatusCallback(uint8_t endpoint, OnOffStatusEnum estatus );;
kk_err_t kUserOODMessageIncoming(uint8_t channel, uint8_t opcode, uint8_t args_in_out[], uint8_t *length_in_out );

void kUserButtonAcitonCallback(unsigned char button_id, BtnActionEnum action );
void kUserLedActionDoneCallback(unsigned char id);
void kUserPwmActionDoneCallback(unsigned char id, PwmGradientDirectionEnum opt);
#if Z30_DEVICE_AGING_ENABLE
void kUserFactorTestPollCallback(FactoryTestStatusEnum status);
#endif

#if Z30_DEVICE_OTA_ENABLE
void kOTAMoudleUserCallback(OTAStatusEnum status);
#endif

#define UART_ENABLE			false
void kUserRelayLedCallback(RelayStatusSt status);
void kRadarDetectInit(void);
void kRadarLedTragger(void);
static void kSetLedStatus(LED_ID_ENUM id);
#if UART_ENABLE
void UartMsgProcessHandle(UMsgNodeSt *pMsgNode);
bool MsgCRC16(uint8_t *pdat, int length );
uint16_t check_sum( uint8_t* msg, uint8_t len);
uint8_t uart_send(void);
#endif
void Test(void );

static ev_timer_event_t *kkSystemSetUpEvent = NULL;
s32 kkSystemSetUpEventHandler(void *arg );
void kUserInterPanMsgInComingPaser(UMsgNodeSt *pMsgNode);
void pOnOffClusterAttributeChangeCallback(uint8_t endpoint,uint16_t cluster,uint16_t attribute,uint8_t len,uint8_t *data);

AttributeChangeConfSt  g_ClusterAttributeConfList[] = {
		{ZCL_CLUSTER_GEN_ON_OFF, ZCL_ATTRID_ONOFF, pOnOffClusterAttributeChangeCallback},
};

static void kLEDOnAction(LED_ID_ENUM led_id);
static void kLEDOffAction(LED_ID_ENUM led_id);
void App_Init(void)
{
	iKonkeAfSelfPrint("\r\n************************************************\r\n");
	iKonkeAfSelfPrint("\r\n****************APP   Init***********************\r\n");
//	iKonkeAfSelfPrint("xxx Reboot Reason: R-INFO(0x%x: %p), R-EXTEND(0x%x: %p) xxx\r\n"
//		, halGetResetInfo(), halGetResetString()
//		, halGetExtendedResetInfo(), halGetExtendedResetString());
//	iKonkeAfSelfPrint("xxx Network Status: %d, systime: %d xxx\r\n", emberAfNetworkState()
//		, halCommonGetInt32uMillisecondTick());
	iKonkeAfSelfPrint("\r\n************************************************\r\n");
	#if 1
	kk_err_t err = kBtnModuleInit(g_btnConfList, sizeof(g_btnConfList) / sizeof(BtnConfSt), kUserButtonAcitonCallback);
		if( err != KET_OK ) {
			iKonkeAfSelfPrint("Err: Button Module Init failed(%d)!!\r\n", err);
		}
	#endif
	#if 1
		err = kPwmModuleInit(g_pwmConfList, sizeof(g_pwmConfList)/sizeof(PwmConfSt), kUserPwmActionDoneCallback);
		if( err != KET_OK ) {
			iKonkeAfSelfPrint("Err: PWM Module Init failed(%d)!!\r\n", err);
		}
	#endif
		err = kLedModuleInit(g_ledConfList, sizeof(g_ledConfList) / sizeof(LedConfSt), kUserLedActionDoneCallback);
		if( err != KET_OK ) {
			iKonkeAfSelfPrint("Err: Led Module Init failed(%d)!!\r\n", err);
		}
		err = kRelayModuleInit(ZERO_PIN, CHECKED_ZERO_DELAY_ON_TIME_MS, CHECKED_ZERO_DELAY_OFF_TIME_MS \
				, EZAP_LOW, g_relayConfList,  sizeof(g_relayConfList)/sizeof(RelayChannelConfSt), kUserRelayLedCallback);
		if( err != KET_OK ) {
			iKonkeAfSelfPrint("Err: Led Module Init failed(%d)!!\r\n", err);
		}
	#if UART_ENABLE
		uint8_t  recv_header[] = {0xAA,0X55};
		err = kUartModuleInit(UART_TX_PIN,UART_RX_PIN,115200,PARITY_NONE,STOP_BIT_ONE,recv_header,2,3,6,MsgCRC16,UartMsgProcessHandle,true );
	#endif

		kNwkModuleInit(cluster_obj_list,sizeof(cluster_obj_list) / sizeof(cluster_obj_list[0]), kUserNetworkStatusNotify, kUserNetworkExitCompleteCallback);

#if Z30_DEVICE_OTA_ENABLE
	kOTAMoudleInit(kOTAMoudleUserCallback, LED_ALL_ID);
#endif
#if Z30_DEVICE_AGING_ENABLE
	kFactoryTestInit(kUserFactorTestPollCallback, g_factoryTestConfList, sizeof(g_factoryTestConfList)/ sizeof(FactoryTestConfSt));
#endif
		// init the private cluster protocol module.
		err =  kOptTunnelModuleInit(kUserOODMessageIncoming);
		if( err != KET_OK ) {
			iKonkeAfSelfPrint("Err: kUserOODMessageIncoming Register Failed(%d)!!\r\n", err);
		}
		// //注册属性改变回调
		ikkAttributeChangeCallbackRegister(attribte_change_list,sizeof(attribte_change_list)/sizeof(attribte_change_list[0]));
		kZclOnOffClusterServerInit(kUserOnOffClusterOnOffStatusCallback);
		if(!ev_timer_exist(kkSystemSetUpEvent)) {
			kkSystemSetUpEvent = TL_ZB_TIMER_SCHEDULE(kkSystemSetUpEventHandler, NULL, 50);
		}
		//start radar detect event
		kRadarDetectInit();

		kZclClusterPermitReportTableInit(cluster_obj_list, sizeof(cluster_obj_list) / sizeof(BindObjSt));

}

void Test(void )
{

}
void kUserNetworkExitCompleteCallback()
{

	SYSTEM_RESET();
}
static bool kClustePeriodReportCheckIsSet(uint8_t endpoint)
{
	uint16_t u16MinTimeMS = 0;
	uint16_t u16MaxTimeMS = 0;
	if (endpoint <= Support_Endpoint_Num){
		bool status = kkClusterGetReportingPeriod(endpoint,ZCL_CLUSTER_GEN_ON_OFF, ZCL_ATTRID_ONOFF, &u16MinTimeMS, &u16MaxTimeMS);
		if (status == true){
			if (u16MaxTimeMS > 0){
				return true;
			}
		}
	}
	return false;
}

void JoinCompleteCallback(NwkJoinCompltEnum nwkcomplt )
{
	iKonkeAfSelfPrint("#########JoinCompleteCallback = %d\r\n", nwkcomplt);
	switch(nwkcomplt) {
		case (EJC_JOIN_FAILED ):
		{
			LED_OPT_OFF(LED_ALL_ID);
			break;
		}
		case (EJC_JOIN_SUCCEED):
		{

			break;
		}
		default: break;
	}
}

void kUserNetworkStatusNotify(NwkStatusEnum nwkst )
{
	iKonkeAfSelfPrint("#############################kUserNetworkStatusNotify = %d\r\n", nwkst);
	switch(nwkst) {
		case (ENS_ONLINE ):
		{
			uint32_t randTimeMS = DELAY_REPORT_DATA_AFTER_NWK_JOINED_MS;
			//power on after joined network
			uint32_t currentTimeMS = clock_time()/16/1000;
			kSetLedStatus(LED_ALL_ID);

			if ( currentTimeMS < MIN_JOINED_NWK_DELAY_TIME_MS){
				randTimeMS = kGetRandNum(RAND_MIN_NUM, RAND_MAX_NUM);
			}else {
				kPwmOptTrigger(PWM4_ID, PWM_TIMER_MAX_DUTY_CYCLE_NUM, 0, 5*1000);
				kPwmOptTrigger(PWM3_ID, PWM_TIMER_MAX_DUTY_CYCLE_NUM, 0, 5*1000);
				kPwmOptTrigger(PWM2_ID, PWM_TIMER_MAX_DUTY_CYCLE_NUM, 0, 5*1000);
				kPwmOptTrigger(PWM1_ID, PWM_TIMER_MAX_DUTY_CYCLE_NUM, 0, 5*1000);
				//kLedOptTrigger(LED_ALL_ID, 0, 0, 0, LED_OFF, LED_IGNORE);
			}
			if (kIsKonkeRemoteGateway() != true){
				g_bIsNotKonkeGatewayFirstReportedFlg = false;
			}

			kNwkScheduleTaskRegister(randTimeMS);
			iKonkeAfSelfPrint("Joined Network RandTime(%dms) CurrentTime(%d)\r\n", randTimeMS, currentTimeMS);
			break;
		}
		case (ENS_JOINING):
		{
			kLedOptTrigger(LED_ALL_ID, LED_SLOW_BLINK_ON_TIME_MS, LED_SLOW_BLINK_OFF_TIME_MS, \
								LED_SLOW_BLINK_CONTINUE_TIME_MS/(LED_SLOW_BLINK_ON_TIME_MS+LED_SLOW_BLINK_OFF_TIME_MS), LED_ON, LED_IGNORE);
			break;
		}
		case (ENS_LEAVED):
		{
			iKonkeAfSelfPrint("#####Enter Leave\r\n");
			kLedOptTrigger((uint8_t)LED_ALL_ID, LED_FAST_BLINK_ON_TIME_MS, LED_FAST_BLINK_OFF_TIME_MS \
						,LED_FAST_BLINK_CONTINUE_TIME_MS/(LED_FAST_BLINK_ON_TIME_MS+LED_FAST_BLINK_ON_TIME_MS), LED_ON, LED_IGNORE);
			//关闭勿扰模式
			kSetIndicatorNotDisturbModeFlg(false);

			break;
		}
		default:
		{
			break;
		}
	}
}

void pOnOffAttributeChangeCallback(uint8_t endpoint,uint16_t cluster,uint16_t attribute,uint8_t *data,uint8_t data_type)
{
	if((cluster == ZCL_CLUSTER_GEN_ON_OFF)&&(attribute == ZCL_ATTRID_ONOFF)&&(data_type == ZCL_DATA_TYPE_BOOLEAN))
	{
		OnOffStatusEnum estatus = *data;
		kUserOnOffClusterOnOffStatusCallback(endpoint,estatus);
		iKonkeAfSelfPrint("#####pOnOffAttributeChangeCallback,endpont = %d,value = %d\r\n",endpoint,estatus);
	}
}
//on off 属性改变后的回调函数，一般用来操作继电器，过零检测，如果没有过零检测可以在这里同步LED状态
void kUserOnOffClusterOnOffStatusCallback(uint8_t endpoint, OnOffStatusEnum estatus )
{
	iKonkeAfSelfPrint("OnOff-status: endpoint(%d), estatus(%d)\r\n", endpoint, estatus);
	kRadarLedTragger();
	switch(endpoint) {
		case (1):
		{
			kRelayChannelOpt(RELAY_CHANNEL1_ID,estatus == EOOS_OFF? EZAO_OFF : EZAO_ON);
			break;
		}
		case (2):
		{
			kRelayChannelOpt(RELAY_CHANNEL2_ID,estatus == EOOS_OFF? EZAO_OFF : EZAO_ON);
			break;
		}
		case (3):
		{
			kRelayChannelOpt(RELAY_CHANNEL3_ID,estatus == EOOS_OFF? EZAO_OFF : EZAO_ON);
			break;
		}
		case (4):
		{
			kRelayChannelOpt(RELAY_CHANNEL4_ID,estatus == EOOS_OFF? EZAO_OFF : EZAO_ON);
			break;
		}
		default: break;
	}
	kZclOnOffClusterServerOnOffControl(endpoint, estatus);

}

uint8_t  Key_Press_Test_Flag[5]	 = {0};
void kUserButtonAcitonCallback(unsigned char button_id, BtnActionEnum action )
{
	iKonkeAfSelfPrint("kUserButton: ButtonId(%d), Action(%d),%d\r\n", button_id, action,kGetFactoryTestStatus());
	if ( kGetFactoryTestStatus() == FTS_AGING_4HOU || kGetFactoryTestStatus() == FTS_AGING_DONE \
			|| kGetFactoryTestStatus() == FTS_AGING_WAITING \
			|| kGetFactoryTestStatus() == FTS_AGING_WAITING_SECOND_PRESS \
			|| kNwkIsExiting() == true){
		//未老化完成，单击按键不操作继电器
		return;
	}
	switch(button_id)
	{
		case KEY_SYS_ID:												//sys botton
		{
			switch(action)
			{
				case EBA_CLICK:
				{
					Key_Press_Test_Flag[0] = 1;
					if( kNwkGetCurrentStatus() == ENS_ONLINE ) { // report connected!

						if (kLedIsBlinking(LED_ALL_ID) != true)
							kLedOptTrigger(LED_ALL_ID,  LED_FAST_BLINK_ON_TIME_MS, LED_FAST_BLINK_OFF_TIME_MS, 1, LED_ON, LED_OFF);
						kOptTunnelOODReport(0, 0XCD, NULL, 0);
					}
					else if(kNwkGetCurrentStatus() == ENS_LEAVED)
					{
						kNwkFactoryReset(false);
						kNwkJoiningStart(NWK_STEERING_TIMEOUT_MS,JoinCompleteCallback);						//开启组网
					}
				}
					break;
				case EBA_LONGPRESS:
				{
					if(kNwkGetCurrentStatus() == ENS_ONLINE)
					{
						kNwkFactoryReset(true);
						iKonkeAfSelfPrint("Start Leave...........\r\n");
					}
				}
					break;
				default:
					break;
			}
			break;
		}
		case KEY1_ID:
		{
			if(action == EBA_CLICK)
			{
				iKonkeAfSelfPrint("KEY 1 PRESS!!!\r\n");
				Key_Press_Test_Flag[1] = 1;
				OnOffCtrlEnum state = kZclOnOffClusterServerOnOffGet(1)? EOOC_OFF : EOOC_ON;
				kZclClusterSetPermitReportInfo(1,0x0006,true,false);
				//afTest_dataSendDemo();
				kZclOnOffClusterServerOnOffControl(1, state);
			}else if (action == EBA_LONGPRESS){
				if (kNwkIsExiting() == true){
					iKonkeAfSelfPrint("#####NWK is exiting\r\n");
					return;
				}

				static bool firstLongPressFlg = false;
				if (kNwkGetCurrentStatus() == ENS_ONLINE){
					static uint32_t lastTimeMS = 0;
					uint32_t currentTimeMS = clock_time()/16/1000;
					if (firstLongPressFlg != true \
							|| (currentTimeMS - lastTimeMS >= MAX_FIRST_USER_KEY_LEAVE_NWK_INTERVAL_TIME_MS)){
						firstLongPressFlg = true;
						lastTimeMS = currentTimeMS;
						if ( kGetOTAStatus() == OTA_NORMAL){
							kLedOptTrigger(LED_ALL_ID,  LED_FAST_BLINK_ON_TIME_MS, LED_FAST_BLINK_OFF_TIME_MS, 1, LED_ON, LED_OFF);
						}
					}else {
						//second times long press
						if (currentTimeMS - lastTimeMS < MAX_FIRST_USER_KEY_LEAVE_NWK_INTERVAL_TIME_MS){
							//关闭黄色LED
//							LED_OPT_OFF(LED_SYS_ID);
							//leave nwk
							if (kNwkGetCurrentStatus() != ENS_JOINING){
								kNwkFactoryReset(true);
							}
						}
						firstLongPressFlg = false;
					}
				}else if (kNwkGetCurrentStatus() == ENS_LEAVED){
					//开始组网
					kNwkFactoryReset(false);
					//steering timeout can be set
					iKonkeAfSelfPrint("#####Start Steering\r\n");
					kNwkJoiningStart(NWK_STEERING_TIMEOUT_MS, JoinCompleteCallback);
				}
			}
			break;
		}
		case (KEY2_ID):
		{
			if (action == EBA_CLICK){
				//restore report attribute immediately
				iKonkeAfSelfPrint("KEY 2 PRESS!!!\r\n");
				Key_Press_Test_Flag[2] = 1;
				OnOffCtrlEnum state = kZclOnOffClusterServerOnOffGet(2)? EOOC_OFF : EOOC_ON;
				kZclClusterSetPermitReportInfo(2,0x0006,true,false);
				kZclOnOffClusterServerOnOffControl(2, state);
			}
			break;
		}
		case (KEY3_ID):
		{
			if (action == EBA_CLICK){
				//restore report attribute immediately
				iKonkeAfSelfPrint("KEY 3 PRESS!!!\r\n");
				Key_Press_Test_Flag[3] = 1;
				OnOffCtrlEnum state = kZclOnOffClusterServerOnOffGet(3)? EOOC_OFF : EOOC_ON;
				kZclClusterSetPermitReportInfo(3,0x0006,true,false);
				kZclOnOffClusterServerOnOffControl(3, state);
			}
			break;
		}
		case (KEY4_ID):
		{
			if (action == EBA_CLICK){
				//restore report attribute immediately
				iKonkeAfSelfPrint("KEY 4 PRESS!!!\r\n");
				Key_Press_Test_Flag[4] = 1;
				OnOffCtrlEnum state = kZclOnOffClusterServerOnOffGet(4)? EOOC_OFF : EOOC_ON;
				kZclClusterSetPermitReportInfo(4,0x0006,true,false);
				kZclOnOffClusterServerOnOffControl(4, state);
			}
			break;
		}
		default:
			break;
	}
}
//过零检测后继电器操作完成，同步LED状态，不是过零操作继电器也是到这里操作LED
void kUserRelayLedCallback(RelayStatusSt status)
{
	iKonkeAfSelfPrint("#########kUserZaLedCallback channel(%d) opt(%d)\r\n", status.u8RelayChannelId, status.opt);

	if (/*kPwmIsChanging(PWM1_ID) == true ||*/ kLedIsBlinking(LED_ALL_ID) == true 	\
			|| kNwkGetCurrentStatus() == ENS_JOINING)
	{
		return;
	}

	switch (status.u8RelayChannelId)
	{
		case RELAY_CHANNEL1_ID:
			if (kNwkGetCurrentStatus() == ENS_ONLINE || power_on_sync[0] == true \
					|| kGetFactoryTestStatus() == FTS_AGING_4HOU 	\
					|| kGetFactoryTestStatus() == FTS_AGING_DONE 	\
					|| kGetFactoryTestStatus() == FTS_AGING_WAITING 	\
					|| kGetFactoryTestStatus() == FTS_AGING_WAITING_SECOND_PRESS){
				power_on_sync[0] = false;
				if (status.opt == EZAO_OFF){
					kLEDOffAction(LED1_ID);
				}else if (status.opt == EZAO_ON){
					kLEDOnAction(LED1_ID);
				}
			}else if (kNwkGetCurrentStatus() == ENS_LEAVED \
					|| kNwkGetCurrentStatus() == ENS_OFFLINE){
				if(kZclOnOffClusterServerOnOffGet(1)== EOOC_OFF)
					kLedOptTrigger(LED1_ID, LED_FAST_BLINK_ON_TIME_MS, \
							LED_FAST_BLINK_OFF_TIME_MS, 3, EOOC_OFF, EOOC_OFF);
				else
					kLedOptTrigger(LED1_ID, LED_FAST_BLINK_ON_TIME_MS, \
							LED_FAST_BLINK_OFF_TIME_MS, 3, LED_ON, LED_ON);
			}
			break;
		case RELAY_CHANNEL2_ID:
			if (kNwkGetCurrentStatus() == ENS_ONLINE || power_on_sync[1] == true \
					|| kGetFactoryTestStatus() == FTS_AGING_4HOU 	\
					|| kGetFactoryTestStatus() == FTS_AGING_DONE 	\
					|| kGetFactoryTestStatus() == FTS_AGING_WAITING 	\
					|| kGetFactoryTestStatus() == FTS_AGING_WAITING_SECOND_PRESS){
				power_on_sync[1] = false;
				if (status.opt == EZAO_OFF){
					kLEDOffAction(LED2_ID);
				}else if (status.opt == EZAO_ON){
					kLEDOnAction(LED2_ID);
				}
			}else if (kNwkGetCurrentStatus() == ENS_LEAVED \
					|| kNwkGetCurrentStatus() == ENS_OFFLINE){
				if(kZclOnOffClusterServerOnOffGet(2)== EOOC_OFF)
					kLedOptTrigger(LED2_ID, LED_FAST_BLINK_ON_TIME_MS, \
							LED_FAST_BLINK_OFF_TIME_MS, 3, EOOC_OFF, EOOC_OFF);
				else
					kLedOptTrigger(LED2_ID, LED_FAST_BLINK_ON_TIME_MS, \
							LED_FAST_BLINK_OFF_TIME_MS, 3, LED_ON, LED_ON);
			}
			break;
		case RELAY_CHANNEL3_ID:
			if (kNwkGetCurrentStatus() == ENS_ONLINE  || power_on_sync[2] == true \
					|| kGetFactoryTestStatus() == FTS_AGING_4HOU 	\
					|| kGetFactoryTestStatus() == FTS_AGING_DONE 	\
					|| kGetFactoryTestStatus() == FTS_AGING_WAITING 	\
					|| kGetFactoryTestStatus() == FTS_AGING_WAITING_SECOND_PRESS){
				power_on_sync[2] = false;
				if (status.opt == EZAO_OFF){
					kLEDOffAction(LED3_ID);
				}else if (status.opt == EZAO_ON){
					kLEDOnAction(LED3_ID);
				}
			}else if (kNwkGetCurrentStatus() == ENS_LEAVED \
					|| kNwkGetCurrentStatus() == ENS_OFFLINE){
				if(kZclOnOffClusterServerOnOffGet(3)== EOOC_OFF)
					kLedOptTrigger(LED3_ID, LED_FAST_BLINK_ON_TIME_MS, \
							LED_FAST_BLINK_OFF_TIME_MS, 3, EOOC_OFF, EOOC_OFF);
				else
					kLedOptTrigger(LED3_ID, LED_FAST_BLINK_ON_TIME_MS, \
							LED_FAST_BLINK_OFF_TIME_MS, 3, LED_ON, LED_ON);
			}
			break;
		case RELAY_CHANNEL4_ID:
			if (kNwkGetCurrentStatus() == ENS_ONLINE  || power_on_sync[3] == true \
					|| kGetFactoryTestStatus() == FTS_AGING_4HOU 	\
					|| kGetFactoryTestStatus() == FTS_AGING_DONE 	\
					|| kGetFactoryTestStatus() == FTS_AGING_WAITING 	\
					|| kGetFactoryTestStatus() == FTS_AGING_WAITING_SECOND_PRESS){
				power_on_sync[3] = false;
				if (status.opt == EZAO_OFF){
					kLEDOffAction(LED4_ID);
				}else if (status.opt == EZAO_ON){
					kLEDOnAction(LED4_ID);
				}
			}else if (kNwkGetCurrentStatus() == ENS_LEAVED \
					|| kNwkGetCurrentStatus() == ENS_OFFLINE){
				if(kZclOnOffClusterServerOnOffGet(4)== EOOC_OFF)
					kLedOptTrigger(LED4_ID, LED_FAST_BLINK_ON_TIME_MS, \
							LED_FAST_BLINK_OFF_TIME_MS, 3, EOOC_OFF, EOOC_OFF);
				else
					kLedOptTrigger(LED4_ID, LED_FAST_BLINK_ON_TIME_MS, \
							LED_FAST_BLINK_OFF_TIME_MS, 3, LED_ON, LED_ON);
			}
			break;

		default:
			iKonkeAfSelfPrint("###Erro: Relay Channel is invalid\r\n");
			break;
	}
}
//add by zbw
void kUserPwmActionDoneCallback(unsigned char id, PwmGradientDirectionEnum opt)
{
	switch(id)
	{
		case PWM1_ID:
			kSetLedStatus(LED1_ID);
			break;
		case PWM2_ID:
			kSetLedStatus(LED2_ID);
			break;
		case PWM3_ID:
			kSetLedStatus(LED3_ID);
			break;
		case PWM4_ID:
			kSetLedStatus(LED4_ID);
			break;
		default:
			break;
	}

}
//ota升级失败或入网成功和失败后LED闪烁完成后处理，需要根据不同产品来修改
static void kSetLedStatus(LED_ID_ENUM id)
{
	if (id != LED_ALL_ID){
		kPwmClearGradientCounterById(id - 1);
	}else{
		kPwmClearGradientCounterById(PWM1_ID);
		kPwmClearGradientCounterById(PWM2_ID);
		kPwmClearGradientCounterById(PWM3_ID);
		kPwmClearGradientCounterById(PWM4_ID);
	}
	//恢复继电器的LED状态
	if (id == LED_ALL_ID)
	{
		kLedOptTrigger(LED_ALL_ID, 0, 0, 0, LED_OFF, LED_IGNORE);
		for (uint8_t i = 1; i <= Support_Endpoint_Num; i++){
			if (kLedIsBlinking(GET_LED_ID_BY_ENDPOINT(i, Support_Endpoint_Num)) == false){
				if ((kZclOnOffClusterServerOnOffGet(i) == EOOS_ON)&&(!kGetIndicatorNotDisturbModeFlg())){
					kLEDOnAction(GET_LED_ID_BY_ENDPOINT(i, Support_Endpoint_Num));
				}else {
					kLEDOffAction(GET_LED_ID_BY_ENDPOINT(i, Support_Endpoint_Num));
				}
			}
		}
	}else if (id == LED1_ID || id == LED2_ID || id == LED3_ID || id == LED4_ID){
		iKonkeAfSelfPrint("###kSetLedStatus:%d,%d,%d\r\n",kLedIsBlinking(id),kZclOnOffClusterServerOnOffGet(GET_ENDPOINT(id)),kGetIndicatorNotDisturbModeFlg());
		if (kLedIsBlinking(id) == false){
			if ((kZclOnOffClusterServerOnOffGet(GET_ENDPOINT(id)) == EOOS_ON)&&(!kGetIndicatorNotDisturbModeFlg())){
				kLEDOnAction(id);
			}else {
				kLEDOffAction(id);
			}
		}
	}
}
//固定事件，目前用于心跳上报
s32 kUserScheduleTaskHandler(void *arg)
{
	iKonkeAfSelfPrint("##########kUserScheduleTaskHandlerCallback!!\r\n");
	if (kIsKonkeRemoteGateway() == true){
		kOptTunnelCommonReport(ECA_OPTDATA);
		return HEARTBEAT_TIME_MS;
	}else {
		if (cluster_obj_list[0].cluster != CLUSTER_UNKNOW){
			if (cluster_obj_list[0].cluster  == ZCL_CLUSTER_GEN_POWER_CFG){
				//kBatteryMonitorReadADC(true);
			}else {
				//add by maozj 20200512 report on off status
				if ((g_bIsNotKonkeGatewayFirstReportedFlg )&& kClustePeriodReportCheckIsSet(g_u8CurrentHeartEndpoint)== true){
					//网关设置过report interval，使用SDK的report
					//kNwkScheduleTaskStop(SCHEDULE_ALLOPT_ID);
				}else {
					kOptTunnelReportingPlagiarizeOriginal(g_u8CurrentHeartEndpoint, ZCL_CLUSTER_GEN_ON_OFF, ZCL_ATTRID_ONOFF);
				}
			}
		}
		g_u8CurrentHeartEndpoint++;
		if (g_u8CurrentHeartEndpoint > Support_Endpoint_Num){
			g_bIsNotKonkeGatewayFirstReportedFlg = true;
			g_u8CurrentHeartEndpoint = 1;
			//repeat overwrite heartbeat report time
			return HEARTBEAT_TIME_MS;
		}else {
			return 1000;
		}
	}

	return HEARTBEAT_TIME_MS;
}
//LED闪烁完成，可以用来恢复继电器的LED状态
void kUserLedActionDoneCallback(unsigned char id)
{
	iKonkeAfSelfPrint("##############kUserLedActionDoneCallback id(%d)nwk(%d)##################\r\n", id,kNwkGetCurrentStatus());
	kSetLedStatus(id);
}
//网关场景控制下发后的属性延时上报处理，可以根据不同场景cluster修改
/*	DESP: recall scene rand delay report Attribute set
 * 	Auth: maozj.20191224.
 * */
void kZclClusterRecallSceneCallback(uint8_t endpoint,  uint16_t cluster, uint8_t command_id, bool reportEnable, bool sceneRecallFlg)
{
	iKonkeAfSelfPrint("####kZclClusterRecallSceneCallback ep(%d)cluster(%d)command_id(%d),reportEnable(%d),sceneRecallFlg(%d)\r\n");
	if((cluster == ZCL_CLUSTER_GEN_ON_OFF)&&(command_id == ZCL_CMD_SCENE_RECALL_SCENE))
	{
		kZclClusterSetPermitReportInfo(endpoint,ZCL_CLUSTER_GEN_ON_OFF,false,true);
	}
}


static ev_timer_event_t *kEndpoint1DelayReport = NULL;
static ev_timer_event_t *kEndpoint2DelayReport = NULL;
static ev_timer_event_t *kEndpoint3DelayReport = NULL;
static ev_timer_event_t *kEndpoint4DelayReport = NULL;
static s32 kEndpoint1DelayReportAttrEventHandler(void *arg)
{
	iKonkeAfSelfPrint("######kEndpoint1DelayReportAttrEventHandler\r\n" );
	kZclClusterSetPermitReportInfo(1, ZCL_CLUSTER_GEN_ON_OFF, true, false);
	kOptTunnelReportingPlagiarizeOriginal(1, ZCL_CLUSTER_GEN_ON_OFF, ZCL_ATTRID_ONOFF);
	return -1;
}
static s32 kEndpoint2DelayReportAttrEventHandler(void *arg)
{
	iKonkeAfSelfPrint("######kEndpoint2DelayReportAttrEventHandler\r\n" );
	kZclClusterSetPermitReportInfo(2, ZCL_CLUSTER_GEN_ON_OFF, true, false);
	kOptTunnelReportingPlagiarizeOriginal(2, ZCL_CLUSTER_GEN_ON_OFF, ZCL_ATTRID_ONOFF);
	return -1;
}
static s32 kEndpoint3DelayReportAttrEventHandler(void *arg)
{
	iKonkeAfSelfPrint("######kEndpoint3DelayReportAttrEventHandler\r\n" );
	kZclClusterSetPermitReportInfo(3, ZCL_CLUSTER_GEN_ON_OFF, true, false);
	kOptTunnelReportingPlagiarizeOriginal(3, ZCL_CLUSTER_GEN_ON_OFF, ZCL_ATTRID_ONOFF);
	return -1;
}
static s32 kEndpoint4DelayReportAttrEventHandler(void *arg)
{
	iKonkeAfSelfPrint("######kEndpoint4DelayReportAttrEventHandler\r\n" );
	kZclClusterSetPermitReportInfo(4, ZCL_CLUSTER_GEN_ON_OFF, true, false);
	kOptTunnelReportingPlagiarizeOriginal(4, ZCL_CLUSTER_GEN_ON_OFF, ZCL_ATTRID_ONOFF);
	return -1;
}
//网关场景控制下发后的属性延时上报处理，可以根据不同场景cluster修改
/*	DESP: recall scene rand delay report Attribute set
 * 	Auth: maozj.20191224.
 * */
bool kZclClusterReportChangeCallback(uint8_t endpoint, uint16_t clusterId, uint16_t attributeId)
{
	ZclReportTableSt zclReportInfo;
	bool status = kZclClusterGetPermitReportInfo(endpoint,clusterId,&zclReportInfo);
	iKonkeAfSelfPrint("######kZclClusterReportChangeCallback status(%d)ep(%d)enable(%d)scene(%d)\r\n",
			status, endpoint, zclReportInfo.reportEnable, zclReportInfo.sceneRecallFlg );
	if (status == true){
		if (zclReportInfo.reportEnable != true && zclReportInfo.sceneRecallFlg == true){
			uint32_t randDelayTimeMS = kGetRandNum(REPORT_ATTR_MIN_RAND_NUM, REPORT_ATTR_MAX_RAND_NUM);
			if (endpoint == 1){
				if(!ev_timer_exist(kEndpoint1DelayReport)) {
					kEndpoint1DelayReport = TL_ZB_TIMER_SCHEDULE(kEndpoint1DelayReportAttrEventHandler, NULL, randDelayTimeMS);
				}
			}else if (endpoint == 2){
				if(!ev_timer_exist(kEndpoint2DelayReport)) {
					kEndpoint2DelayReport = TL_ZB_TIMER_SCHEDULE(kEndpoint2DelayReportAttrEventHandler, NULL, randDelayTimeMS);
				}
			}else if (endpoint == 3){
				if(!ev_timer_exist(kEndpoint3DelayReport)) {
					kEndpoint3DelayReport = TL_ZB_TIMER_SCHEDULE(kEndpoint3DelayReportAttrEventHandler, NULL, randDelayTimeMS);
				}
			}
			else if (endpoint == 4){
				if(!ev_timer_exist(kEndpoint4DelayReport)) {
					kEndpoint3DelayReport = TL_ZB_TIMER_SCHEDULE(kEndpoint4DelayReportAttrEventHandler, NULL, randDelayTimeMS);
				}
			}
			//有多控绑定发给其它子设备, 不发给网关
//			if( kZclNodeIsBindNotGatewayIeeeAddress(endpoint, ZCL_ON_OFF_CLUSTER_ID) == true) {
//				iKonkeAfSelfPrint("Multi Control\r\n");
//				kZclClusterSetPermitReportInfo(endpoint, true, false, false, true);
//				kOptTunnelReportingPlagiarizeOriginal(endpoint, ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, CLUSTER_MASK_SERVER);
//				//kZclClusterConditionallySendReport(endpoint, ZCL_ON_OFF_CLUSTER_ID, false, true);
//			}
			//不直接上报，随机延时上报
			return false;
		}
		else if(!zclReportInfo.reportEnable)
		{
			return false;
		}
	}


	return true;
}
kk_err_t kUserOODMessageIncoming(uint8_t channel, uint8_t opcode, uint8_t args_in_out[], uint8_t *length_in_out )
{
	if( NULL == args_in_out || NULL == length_in_out ) {
		return KET_ERR_INVALID_POINTER;
	}

	iKonkeAfSelfPrint("OOD-INCOMING: channel(%d), opcode(%x)--\r\n", channel, opcode);
	for(int index = 0; index < *length_in_out; ++index ) {
		iKonkeAfSelfPrint("%x ", args_in_out[index]);
	}
	iKonkeAfSelfPrint("--------------------------------------\r\n");

	switch(opcode) {
		case (0x00): // get the device snap.
		{
			args_in_out[0] = 0x00;
			args_in_out[1] = kZclOnOffClusterServerOnOffGet(1);
			args_in_out[2] = kZclOnOffClusterServerOnOffGet(2);
			args_in_out[3] = kZclOnOffClusterServerOnOffGet(3);
			args_in_out[4] = kZclOnOffClusterServerOnOffGet(4);
			args_in_out[5] = kGetIndicatorNotDisturbModeFlg();
			iKonkeAfSelfPrint("OOOOOOPCODE: 1(%d), 2(%d), 3(%d),4(%d),5(%d)\r\n", args_in_out[1], args_in_out[2], args_in_out[3],args_in_out[4],args_in_out[5]);
			*length_in_out = 6;
			break;
		}
		case (0xFE):
		{
			//set disturb mode
			uint8_t mode = args_in_out[0];
			if (mode != 0x00 && mode != 0x01){
				args_in_out[0] = ERR_NO_COMMAND_FORMAT;
			}else {
				//存储勿扰标志
				kSetIndicatorNotDisturbModeFlg(mode);
				////State Sync////
				if (kLedIsBlinking(LED_ALL_ID) != true)	{
					kSetLedStatus(LED_ALL_ID);
				}
				args_in_out[0] = ERR_NO_NONE;
			}
			iKonkeAfSelfPrint("Disturb Mode(%d)\r\n", mode);
			args_in_out[1] = mode;
			*length_in_out = 2;
			break;
		}
		case (0xFF):
		{
			uint8_t permitJoinTimeS = args_in_out[0]; //unit:s
			iKonkeAfSelfPrint("###Opcode is channel(%d) JoinPermitTime(0x%X)!!\r\n",channel,  permitJoinTimeS);
			//路由协同组网,黄灯闪烁(OTA升级)时不协同组网闪灯
			if (kLedIsBlinking(LED_ALL_ID) != true
					&& permitJoinTimeS != 0
					&& kNwkGetCurrentStatus() != ENS_JOINING){
				iKonkeAfSelfPrint("####LED Blink\r\n");
				kLedOptTrigger(LED_ALL_ID,  LED_SLOW_BLINK_ON_TIME_MS, LED_SLOW_BLINK_OFF_TIME_MS,
						permitJoinTimeS * 1000/(LED_SLOW_BLINK_ON_TIME_MS+LED_SLOW_BLINK_OFF_TIME_MS), LED_ON, LED_OFF);
			}else if (kLedIsBlinking(LED2_ID) == true
					&& permitJoinTimeS == 0
					&& kNwkGetCurrentStatus() != ENS_JOINING){
				kLedOptTrigger(LED_ALL_ID, 0, 0, 0, LED_OFF, LED_IGNORE);
//				kLEDOffAction(LED_ALL_ID);
				kSetLedStatus(LED_ALL_ID);
			}
			return KET_NO_RESPONSE;
		}

		default: {
			iKonkeAfSelfPrint("Err: opcode is not exist(%d:%X)!!\r\n", channel, opcode);
			args_in_out[0] = ERR_NO_OPCODE;
			*length_in_out = 1;
			break;
		}
	}

	return KET_OK;
}


static void kLEDOffAction(LED_ID_ENUM led_id)
{
	iKonkeAfSelfPrint("LED_Off_Action LED_ID (%d).\r\n", led_id);
	kLedOptTrigger(led_id, 0, 0, 0, LED_OFF, LED_IGNORE);
	if (kGetIndicatorNotDisturbModeFlg() == false){
		iKonkeAfSelfPrint("is not NotDisturbMode.\r\n");
		switch (led_id)
		{
			case LED1_ID:
			{
				kPwmDriverhandler(kPwmGetIndexByID(PWM1_ID), ELP_ANY, (uint16_t)(((uint32_t)g_u8NoDisturbModeMinLevel * 65535) / 100) );
				break;
			}
			case LED2_ID:
			{
				kPwmDriverhandler(kPwmGetIndexByID(PWM2_ID), ELP_ANY, (uint16_t)(((uint32_t)g_u8NoDisturbModeMinLevel * 65535) / 100) );
				break;
			}
			case LED3_ID:
			{
				kPwmDriverhandler(kPwmGetIndexByID(PWM3_ID), ELP_ANY, (uint16_t)(((uint32_t)g_u8NoDisturbModeMinLevel * 65535) / 100));
				break;
			}
			case LED4_ID:
			{
				kPwmDriverhandler(kPwmGetIndexByID(PWM4_ID), ELP_ANY, (uint16_t)(((uint32_t)g_u8NoDisturbModeMinLevel * 65535) / 100));
				break;
			}
			case LED_ALL_ID:
			{
				kPwmDriverhandler(kPwmGetIndexByID(PWM1_ID), ELP_ANY, (uint16_t)(((uint32_t)g_u8NoDisturbModeMinLevel * 65535) / 100));
				kPwmDriverhandler(kPwmGetIndexByID(PWM2_ID), ELP_ANY, (uint16_t)(((uint32_t)g_u8NoDisturbModeMinLevel * 65535) / 100));
				kPwmDriverhandler(kPwmGetIndexByID(PWM3_ID), ELP_ANY, (uint16_t)(((uint32_t)g_u8NoDisturbModeMinLevel * 65535) / 100));
				kPwmDriverhandler(kPwmGetIndexByID(PWM4_ID), ELP_ANY, (uint16_t)(((uint32_t)g_u8NoDisturbModeMinLevel * 65535) / 100));
				break;
			}
			default:
				break;
		}
	}
}

static void kLEDOnAction(LED_ID_ENUM led_id)
{
	iKonkeAfSelfPrint("LED_ON_Action LED_ID (%d).\r\n", led_id);
	kLedOptTrigger(led_id, 0, 0, 0, LED_OFF, LED_IGNORE);
	if (kGetIndicatorNotDisturbModeFlg() == false){
		iKonkeAfSelfPrint("is not NotDisturbMode.\r\n");
		switch (led_id)
		{
			case LED1_ID:
			{
				kPwmDriverhandler(kPwmGetIndexByID(PWM1_ID), ELP_ANY, (uint16_t)(((uint32_t)g_u8NoDisturbModeMaxLevel * 65535) / 100) );
				break;
			}
			case LED2_ID:
			{
				kPwmDriverhandler(kPwmGetIndexByID(PWM2_ID), ELP_ANY, (uint16_t)(((uint32_t)g_u8NoDisturbModeMaxLevel * 65535) / 100) );
				break;
			}
			case LED3_ID:
			{
				kPwmDriverhandler(kPwmGetIndexByID(PWM3_ID), ELP_ANY, (uint16_t)(((uint32_t)g_u8NoDisturbModeMaxLevel * 65535) / 100) );
				break;
			}
			case LED4_ID:
			{
				kPwmDriverhandler(kPwmGetIndexByID(PWM4_ID), ELP_ANY, (uint16_t)(((uint32_t)g_u8NoDisturbModeMaxLevel * 65535) / 100) );
				break;
			}
			case LED_ALL_ID:
			{
				kPwmDriverhandler(kPwmGetIndexByID(PWM1_ID), ELP_ANY, (uint16_t)(((uint32_t)g_u8NoDisturbModeMaxLevel * 65535) / 100) );
				kPwmDriverhandler(kPwmGetIndexByID(PWM2_ID), ELP_ANY, (uint16_t)(((uint32_t)g_u8NoDisturbModeMaxLevel * 65535) / 100) );
				kPwmDriverhandler(kPwmGetIndexByID(PWM3_ID), ELP_ANY, (uint16_t)(((uint32_t)g_u8NoDisturbModeMaxLevel * 65535) / 100) );
				kPwmDriverhandler(kPwmGetIndexByID(PWM4_ID), ELP_ANY, (uint16_t)(((uint32_t)g_u8NoDisturbModeMaxLevel * 65535) / 100) );
				break;
			}
			default:
				break;
		}
	}
}
//芯片上电后延时操作事件，一般处理继电器状态恢复或者禁用SWD口作为普通IO,也用来根据gpio读取电平修改同一类型的不同型号
/*	DESP: system setup delay callback handler, called once.
 * 	Auth: dingmz_frc.20190628.
 * */
s32 kkSystemSetUpEventHandler(void *arg )
{
	bool relayStatusBuffer[Support_Endpoint_Num] = {false, false,false,false};
	nv_sts_t st = zcl_onOffAttr_get();

	for (uint8_t i = 1; i <= Support_Endpoint_Num; i++){
		if(st == NV_SUCC)
		{
			relayStatusBuffer[i-1] = g_zcl_onOffAttrs[i-1].onOff;
		}
		power_on_sync[i - 1] = true;
		iKonkeAfSelfPrint("###########EP(%d), status(%d)\r\n", i, relayStatusBuffer[i-1]);
		kZclClusterSetPermitReportInfo(i,CLUSTER_ONOFF_ID, false, false);
		kZclOnOffClusterServerOnOffSet(i,relayStatusBuffer[i-1]);
		kZclClusterSetPermitReportInfo(i,CLUSTER_ONOFF_ID, false, false);

		kRelayChannelOpt(i == 1?RELAY_CHANNEL1_ID:(i == 2?RELAY_CHANNEL2_ID:(i == 3?RELAY_CHANNEL3_ID:RELAY_CHANNEL4_ID)) \
							,relayStatusBuffer[i-1] == false? EZAO_OFF : EZAO_ON);

	}
	//重写attribute
	Update_Local_Attribute_Info();
	#if UART_ENABLE
	kInterPanMoudleInit(kUserInterPanMsgInComingPaser);
	#endif
	return -1;
}

#if Z30_DEVICE_AGING_ENABLE
//老化的轮询回调函数，一般用于实现老化期间的LED闪烁或继电器翻转，也可以只LED闪烁
void kUserFactorTestPollCallback(FactoryTestStatusEnum status)
{
	iKonkeAfSelfPrint("##############kUserFactorTestPollCallback status(%d)##################\r\n", status);
	static RelayOptEnum  eRelayStatus = EZAO_OFF;
	switch(status)
	{
		case FTS_NORMAL:
			break;
		case FTS_START:
			//没有老化完需先都清除网络
			break;
		case FTS_AGING_15MIN:
			break;
		case FTS_AGING_4HOU_START:
			//关闭所有的蓝色LED,有可能之前蓝灯闪烁了
			LED_OPT_OFF(LED_ALL_ID);
			LED_OPT_OFF(LED_RADAR_ID);
			//同步所有的LED和继电器
			for (uint8_t i = 1; i <= Support_Endpoint_Num; i++){
				kRelayChannelOpt(g_ucRelayIdBuff[i-1], EZAO_OFF);
			}
			eRelayStatus = EZAO_ON;
			break;
		case  FTS_AGING_4HOU:
			//翻转继电器，LED也会同步
			eRelayStatus = eRelayStatus == EZAO_ON?EZAO_OFF:EZAO_ON;
			if (eRelayStatus == EZAO_ON){
				LED_OPT_ON(LED_RADAR_ID);
			}else{
				LED_OPT_OFF(LED_RADAR_ID);
			}
			for (uint8_t i = 1; i <= Support_Endpoint_Num; i++){
				kRelayChannelOpt(g_ucRelayIdBuff[i-1], eRelayStatus);
			}
			break;
		case  FTS_AGING_DONE:
			//老化结束后,打开所有的LED和继电器
			LED_OPT_ON(LED_RADAR_ID);
			for (uint8_t i = 1; i <= Support_Endpoint_Num; i++){
				kRelayChannelOpt(g_ucRelayIdBuff[i-1], EZAO_ON);
			}
			eRelayStatus = EZAO_ON;
			//如果有单独系统LED也需要都点亮
//			LED_OPT_ON(LED_SYS_ID);
			break;
		case FTS_AGING_FORCE_EXIT:
			iKonkeAfSelfPrint("############## FactoryTestSatus is FTS_AGING_FORCE_EXIT\r\n");
			//按键强制退老化，快闪
			kLedOptTrigger(LED_ALL_ID, LED_FAST_BLINK_ON_TIME_MS, LED_FAST_BLINK_OFF_TIME_MS, BLINK_DEAD, LED_ON, LED_IGNORE);
			break;
		case FTS_AGING_WAITING:
			break;
		case FTS_AGING_FIRST_LONG_PRESSED:
			//快闪一次，指示第一次长按有效
			kLedOptTrigger(LED_ALL_ID, LED_FAST_BLINK_ON_TIME_MS, LED_FAST_BLINK_OFF_TIME_MS, 1, LED_ON, LED_IGNORE);
			break;
		case FTS_AGING_FORCE_REBOOT:
			SYSTEM_RESET();
			break;
		default:
			iKonkeAfSelfPrint("##############Erro: FactoryTestSatus is not exist\r\n");
			break;
	}
}
#endif

#if Z30_DEVICE_OTA_ENABLE
//如果初始化OTA增加callback这里处理，否则使用ota模块的默认callback,就不在这里
void kOTAMoudleUserCallback(OTAStatusEnum status)
{
#if 0
	static bool flg = false; //防止网关断电后,ota失败后会间隔快闪
	iKonkeAfSelfPrint("##############kOTAMoudleUserCallback status(%d)##################\r\n", status);
	switch(status)
	{
		case OTA_NORMAL:
			break;
		case OTA_START:
			//关闭所有蓝色LED
//			LED_OPT_OFF(LED_ALL_ID);
			kLedOptTrigger(LED_ALL_ID, 2 * LED_FAST_BLINK_ON_TIME_MS, 14 * LED_FAST_BLINK_ON_TIME_MS,\
					OTA_UPGRADE__CONTINUE_MAX_TIME_MS /(2 * LED_FAST_BLINK_ON_TIME_MS + 14 * LED_FAST_BLINK_ON_TIME_MS), LED_ON, LED_ON);
			kSetOTAStatus(OTA_START);
			flg = false;
			break;
		case OTA_DOWNLOAD_DONE:
		{
			uint8_t buffer[] = {"Konke download disable watchdog.....\r\n"};
		 	  //不能注释掉， 不然无法禁用看门狗，导致第二次连续升级卡死，认为这里是相当于加了延时
		  	emberSerialWriteData((uint8_t)APP_SERIAL, buffer, strlen((char *)buffer));
		  	halInternalDisableWatchDog(MICRO_DISABLE_WATCH_DOG_KEY);//add by maozj 20190308文件快下载好后禁用看门狗
		  	kSetOTAStatus(OTA_DOWNLOAD_DONE);
		  	break;
		}
		case OTA_VERITY_SUCCEED:
		{
			//校验成功，记录继电器状态,需要复位后恢复继电器状态
			//saveRelayStatusWhenOtaSucceed(relayTotalNum);
			//uint8_t relayStatus = 1;
			//halCommonSetToken(TOKEN_OTA_RELAY_STATUS, &relayStatus);
			//常亮5S
			kLedOptTrigger(LED_ALL_ID, 25 * LED_FAST_BLINK_ON_TIME_MS,  LED_FAST_BLINK_ON_TIME_MS, 1, LED_ON, LED_ON);
			kSetOTAStatus(OTA_NORMAL);
			break;
		}
		case OTA_FAILED:
		{
			if (flg != true){
				halInternalWatchDogEnabled();  //使能看门狗
				emberAfOtaStorageClearTempDataCallback();
				kLedOptTrigger(LED_ALL_ID, LED_FAST_BLINK_ON_TIME_MS, LED_FAST_BLINK_ON_TIME_MS,\
									LED_FAST_BLINK_CONTINUE_TIME_MS /(LED_FAST_BLINK_ON_TIME_MS + LED_FAST_BLINK_ON_TIME_MS), LED_ON, LED_ON);
				kSetOTAStatus(OTA_NORMAL);
				//uint8_t status = 0;
				//halCommonSetToken(TOKEN_OTA_RELAY_STATUS, &status);
				//emAfOtaClientStop(); //刚加上， 未测试，防止网关断电后，一直request 5分钟
			}
			flg = true;
			break;
		}
		default:
			iKonkeAfSelfPrint("##############Err: OTA status is not exist\r\n");
			break;
	}

#endif
}
#endif
static ev_timer_event_t *kRadarCheckEventControl 	= NULL;
static ev_timer_event_t *kRadarControlLedEvent		= NULL;


s32 kRadarCheckEventHandler(void *arg)
{
	if (kGetFactoryTestStatus() == FTS_AGING_4HOU 	\
		|| kGetFactoryTestStatus() == FTS_AGING_DONE 	\
		|| kGetFactoryTestStatus() == FTS_AGING_WAITING 	\
		|| kGetFactoryTestStatus() == FTS_AGING_WAITING_SECOND_PRESS){
		return 0;
	}

	static uint8_t Radar_count = 0;
	if (gpio_read(RADAR_PIN)){
		Radar_count ++;
	}else{
		Radar_count = 0;
	}

	if (Radar_count >= 2){
//		iKonkeAfSelfPrint("Radar Action.\r\n");
		Human_body_induction_flag = true;
		Radar_count = 0;
		kRadarLedTragger();
	}
	return 0;
}

s32  kRadarLedEventHandler(void *arg)
{
	if (kGetFactoryTestStatus() == FTS_AGING_4HOU 	\
		|| kGetFactoryTestStatus() == FTS_AGING_DONE 	\
		|| kGetFactoryTestStatus() == FTS_AGING_WAITING 	\
		|| kGetFactoryTestStatus() == FTS_AGING_WAITING_SECOND_PRESS){
		return 0;
	}

	bool OnOffFlag = false;

	OnOffFlag |= kZclOnOffClusterServerOnOffGet(1) == EOOS_ON?true:false;
	//iKonkeAfSelfPrint("OnOffFlag by endpoint1 : (%d).\r\n",OnOffFlag);
	OnOffFlag |= kZclOnOffClusterServerOnOffGet(2) == EOOS_ON?true:false;
	//iKonkeAfSelfPrint("OnOffFlag by endpoint2 : (%d).\r\n",OnOffFlag);
	OnOffFlag |= kZclOnOffClusterServerOnOffGet(3) == EOOS_ON?true:false;
	//iKonkeAfSelfPrint("OnOffFlag by endpoint3 : (%d).\r\n",OnOffFlag);
	OnOffFlag |= kZclOnOffClusterServerOnOffGet(4) == EOOS_ON?true:false;
	//iKonkeAfSelfPrint("OnOffFlag by endpoint4 : (%d).\r\n",OnOffFlag);

	if (OnOffFlag == true){
		kLedOptTrigger(LED_RADAR_ID, 0, 0, 0, LED_ON, LED_IGNORE);
		Human_body_induction_flag = false;
	}else if (Human_body_induction_flag == true){
		kLedOptTrigger(LED_RADAR_ID, RADAR_ON_TIME_MS, 0, 1, LED_ON, LED_OFF);
		Human_body_induction_flag = false;
	}else{
		kLedOptTrigger(LED_RADAR_ID, RADAR_ON_TIME_MS, 0, 1, LED_ON, LED_OFF);
	}
	return -1;
}
void kRadarDetectInit(void)
{
	if(!ev_timer_exist(kRadarCheckEventControl)) {
		kRadarCheckEventControl = TL_ZB_TIMER_SCHEDULE(kRadarCheckEventHandler, NULL, 100);
	}
	GPIO_INPUT_SET(RADAR_PIN,PM_PIN_UP_DOWN_FLOAT);
}
void kRadarLedTragger(void)
{
	if(!ev_timer_exist(kRadarControlLedEvent)){
		TL_ZB_TIMER_CANCEL(&kRadarControlLedEvent);
	}
	kRadarControlLedEvent = TL_ZB_TIMER_SCHEDULE(kRadarLedEventHandler, NULL, 1);

}

#if UART_ENABLE
uint8_t uart_send(void)
{
	UMsgNodeSt MsgNode;
	uint8_t i = 0;
	memset(&MsgNode,0,sizeof(UMsgNodeSt));
	MsgNode.buffer[i++]	= 0xAA;
	MsgNode.buffer[i++] = 0X55;
	MsgNode.buffer[i++]	= 0X05;
	MsgNode.buffer[i++]	= 0x01;
	MsgNode.buffer[i++]  = 0X02;
	MsgNode.buffer[i++]	= 0X03;
	MsgNode.buffer[i++]	= 0X04;
	MsgNode.buffer[i++]	= 0X05;


	uint16_t crc = check_sum(&MsgNode.buffer[0], MsgNode.buffer[2]+3);
	MsgNode.buffer[i++] = crc>>8;
	MsgNode.buffer[i++] = crc;
	MsgNode.length = i;

	// setting for matcher content.

	MsgNode.matcher[0] = 0XAA;
	MsgNode.matcher[0] = 0X55;
	MsgNode.matcher_offset = 4;
	MsgNode.matcher_n = 2;

	MsgNode.sent_try = 3;

	return kUartMsgSent(&MsgNode);
}
void UartMsgProcessHandle(UMsgNodeSt *pMsgNode )
{
	uint16_t opcode;
	uint16_t frameLenth = 0;
	uint8_t *args_in;
	uint8_t reply_control_field;
	DataField_st send_buf;

	if( NULL == pMsgNode ) {
		return ;
	}

#if 1 // Just for debug
	iKonkeAfSelfPrint("\r\n-- RTT MSG INCOMING[%d]:\r\n", pMsgNode->length);

	iKonkeAfSelfPrintBuffer(pMsgNode->buffer, pMsgNode->length);
	iKonkeAfSelfPrint("\r\n--------------------\r\n");
#endif

	// check SOF
	if ((pMsgNode->buffer[0] != 0xAA) || (pMsgNode->buffer[1] != 0x55)) {
		return ;
	}
	frameLenth = UINT16_HL(pMsgNode->buffer[2], pMsgNode->buffer[3]);

	// check for parsable packets
	if( pMsgNode->length < 10 /* Minimum Packet Length */ ) {
		iKonkeAfSelfPrint("Err: Unparsable Packets!!\r\n");
		return ;
	}

	opcode = ((uint16_t)pMsgNode->buffer[9] << 8) |  (uint16_t)(pMsgNode->buffer[10]);
	args_in = &pMsgNode->buffer[8];
	send_buf.seq = UINT16_HL(pMsgNode->buffer[5],pMsgNode->buffer[6] );
	send_buf.u8ChannelID = args_in[0];
	send_buf.u16Opcode = opcode;
	iKonkeAfSelfPrint("opcode(%d)\r\n", opcode);
	reply_control_field = Z_TO_H_NO_ACK;
	switch(opcode){
		case UART_MSG_READ_DEVICE_SNAP_OPCODE:
		case UART_MSG_JOIN_NWK_REQUEST_OPCODE:
		case UART_MSG_LEAVE_NWK_REQUEST_OPCODE:
		case UART_MSG_QUERY_NWK_STATUS_REQUEST_OPCODE:
		case UART_MSG_NWK_STATUS_NOTIFY_OPCODE:
		case UART_MSG_READ_ATTRIBUTE_REQUEST_OPCODE:
		case UART_MSG_WRITE_ATTRIBUTE_REQUEST_OPCODE:
		case UART_MSG_WRITE_CMEI_CODE_OPCODE:
		case UART_MSG_READ_CMEI_CODE_OPCODE:
		case UART_MSG_WRITE_ISN_CODE_OPCODE:
		case UART_MSG_READ_ISN_CODE_OPCODE:
		case UART_MSG_ZCL_COMMAND_REQUEST_OPCODE:
		case UART_MSG_BIND_REQUEST_OPCODE:
		case UART_MSG_WRITE_INSTALL_CODE_OPCODE:
		case UART_MSG_READ_INSTALL_CODE_OPCODE:
		case UART_MSG_WRITE_MAC_CODE_OPCODE:
		case UART_MSG_READ_MAC_CODE_OPCODE:
		case UART_MSG_WRITE_MOUDLE_ID_OPCODE:
		case UART_MSG_READ_MOUDLE_ID_OPCODE:
		case UART_MSG_READ_DEV_RSSI_OPCODE:
		case UART_MSG_WRITE_AGING_TIME_OPCODE:
		case UART_MSG_READ_AGING_TIME_OPCODE:
		case UART_MSG_WRITE_INTERPAN_PARA_OPCODE:
		case UART_MSG_READ_INTERPAN_PARA_OPCODE:
			reply_control_field = Z_TO_H_NO_ACK;
			kCmdGeneralMsgPaser(pMsgNode, ECOM_PORT_UART, &send_buf);
			break;
		case UART_MSG_QUERY_INFO_OPCODE:
		case UART_MSG_QUERY_DEVICE_VERSION_OPCODE:
		case UART_MSG_QUERY_DEVICE_INFO_OPCODE:
		case UART_MSG_CONFIG_DEVICE_SLEEP_OPCODE:
		case UART_MSG_EXIT_FACTORY_TEST_OPCODE:
		case UART_MSG_QUERY_SWITCH_ONOFF_OPCODE:
		case UART_MSG_QUERY_FACTORY_INFO_OPCODE:
		case UART_MSG_ENTER_FACTORY_TEST_OPCODE:
		case UART_MSG_ONOFF_SWITCH_OPCODE:
			kkFactoryMsgInComingPaser(pMsgNode, ECOM_PORT_UART, &send_buf);
			break;

		default:
			send_buf.u8ARG[0] = ERR_NOT_EXIST;
			send_buf.u8ArgLen = 1;
			reply_control_field = Z_TO_H_NO_ACK;
			break;
	}
	kCmdMsgDataSentByPort(reply_control_field, send_buf, false, ECOM_PORT_UART);
}
/*  DESP: rtt command message incoming and process interface.
 *   Auth: kkk.20210222.
 * */
void kUserInterPanMsgInComingPaser(UMsgNodeSt *pMsgNode)
{
	uint16_t opcode;
	uint16_t frameLenth = 0;
	uint16_t crc16DataIn = 0;
	uint16_t crc16Value = 0;
	uint8_t *args_in;
	uint8_t reply_control_field;
	DataField_st send_buf;

	if( NULL == pMsgNode ) {
		return ;
	}

#if 0 // Just for debug
	iKonkeAfSelfPrint("\r\n-- InterPan MSG INCOMING[%d]:\r\n", pMsgNode->length);
	iKonkeAfSelfPrintBuffer(pMsgNode->buffer, pMsgNode->length);
	iKonkeAfSelfPrint("\r\n--------------------\r\n");
#endif

	// check SOF
	if ((pMsgNode->buffer[0] != 0xAA) || (pMsgNode->buffer[1] != 0x55)) {
		return ;
	}

	frameLenth = UINT16_HL(pMsgNode->buffer[2], pMsgNode->buffer[3]);
	// check CRC16
	crc16Value = kCmdGetMsgCrc16Value(&pMsgNode->buffer[4], frameLenth);
	crc16DataIn = UINT16_HL(pMsgNode->buffer[pMsgNode->length - 2], pMsgNode->buffer[pMsgNode->length - 1]);

	if (crc16Value != crc16DataIn) {
		iKonkeAfSelfPrint("Err: CRC(%d)(%d)\r\n", crc16Value, crc16DataIn);
		return ;
	}

	// check for parsable packets
	if( pMsgNode->length < 10 /* Minimum Packet Length */ ) {
		iKonkeAfSelfPrint("Err: Unparsable Packets!!\r\n");
		return ;
	}

	opcode = ((uint16_t)pMsgNode->buffer[9] << 8) |  (uint16_t)(pMsgNode->buffer[10]);
	args_in = &pMsgNode->buffer[8];
	send_buf.seq = UINT16_HL(pMsgNode->buffer[5],pMsgNode->buffer[6] );
	send_buf.u8ChannelID = args_in[0];
	send_buf.u16Opcode = opcode;

	iKonkeAfSelfPrint("opcode(%d)\r\n", opcode);
	  switch(opcode){
		case UART_MSG_READ_DEVICE_SNAP_OPCODE:
		case UART_MSG_JOIN_NWK_REQUEST_OPCODE:
		case UART_MSG_LEAVE_NWK_REQUEST_OPCODE:
		case UART_MSG_QUERY_NWK_STATUS_REQUEST_OPCODE:
		case UART_MSG_NWK_STATUS_NOTIFY_OPCODE:
		case UART_MSG_READ_ATTRIBUTE_REQUEST_OPCODE:
		case UART_MSG_WRITE_ATTRIBUTE_REQUEST_OPCODE:
		case UART_MSG_WRITE_CMEI_CODE_OPCODE:
		case UART_MSG_READ_CMEI_CODE_OPCODE:
		case UART_MSG_WRITE_ISN_CODE_OPCODE:
		case UART_MSG_READ_ISN_CODE_OPCODE:
		case UART_MSG_ZCL_COMMAND_REQUEST_OPCODE:
		case UART_MSG_BIND_REQUEST_OPCODE:
		case UART_MSG_WRITE_INSTALL_CODE_OPCODE:
		case UART_MSG_READ_INSTALL_CODE_OPCODE:
		case UART_MSG_WRITE_MAC_CODE_OPCODE:
		case UART_MSG_READ_MAC_CODE_OPCODE:
		case UART_MSG_WRITE_MOUDLE_ID_OPCODE:
		case UART_MSG_READ_MOUDLE_ID_OPCODE:
		case UART_MSG_READ_DEV_RSSI_OPCODE:
		case UART_MSG_WRITE_AGING_TIME_OPCODE:
		case UART_MSG_READ_AGING_TIME_OPCODE:
		case UART_MSG_WRITE_INTERPAN_PARA_OPCODE:
		case UART_MSG_READ_INTERPAN_PARA_OPCODE:
		  kCmdGeneralMsgPaser(pMsgNode, ECOM_PORT_INTERPAN, &send_buf);
		  break;
		case UART_MSG_QUERY_INFO_OPCODE:
		case UART_MSG_QUERY_DEVICE_VERSION_OPCODE:
		case UART_MSG_QUERY_DEVICE_INFO_OPCODE:
		case UART_MSG_CONFIG_DEVICE_SLEEP_OPCODE:
		case UART_MSG_EXIT_FACTORY_TEST_OPCODE:
		case UART_MSG_QUERY_FACTORY_INFO_OPCODE:
		case UART_MSG_QUERY_SWITCH_ONOFF_OPCODE:
		case UART_MSG_ENTER_FACTORY_TEST_OPCODE:
		case UART_MSG_ONOFF_SWITCH_OPCODE:
		  kkFactoryMsgInComingPaser(pMsgNode, ECOM_PORT_INTERPAN, &send_buf);
		  break;

		default:
			send_buf.u8ARG[0] = ERR_NOT_EXIST;
			send_buf.u8ArgLen = 1;
			reply_control_field = Z_TO_H_NO_ACK;
		  break;
	  }

	  reply_control_field = Z_TO_H_NO_ACK;
	  kCmdMsgDataSentByPort(reply_control_field, send_buf, false, ECOM_PORT_INTERPAN);
}
uint16_t check_sum( uint8_t* msg, uint8_t len)
{
	uint16_t crc = 0xFFFF;
	uint16_t i, j = 0;

    for (i = 0; i < len; i++)
    {
        for (j = 0; j < 8; j++)
        {
        	uint8_t c15 = (uint8_t)((crc >> 15 & 1) == 1);
        	uint8_t bit = (uint8_t)((msg[i] >> (7 - j) & 1) == 1);

            crc <<= 1;

            if (c15 ^ bit)
            {
                crc ^= 0x1021;
            }
        }
    }
    return crc;
}
bool MsgCRC16(uint8_t *pdat, int length )
{
	uint16_t crc_data = 0;
	uint8_t  CRC_H = 0;
	uint8_t  CRC_L = 0;

	if((NULL == pdat) || (length < 9)){
		return false;
	}
	crc_data = check_sum(&pdat[4], pdat[3]);
	CRC_H = (crc_data>>8) & 0xff;
	CRC_L = crc_data & 0xff;
	//iKonkeAfSelfPrint("\r\nMsgCRC16,%d,%d\r\n",CRC_H,CRC_L);
	if((pdat[length - 1] == CRC_L) && (pdat[length - 2]== CRC_H))
	{
		return true;
	}

	return false;
}
#endif
