
#include <stdio.h>
#include "ZComDef.h"
#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "zcl_ss.h"
#include "onboard.h"
#include "zcl_includes.h"
#include "zcl_samplelight.h"
/* HAL */
#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_key.h"


/*********************************************************************
 * MACROS
 */

/*********************************************************************
 * CONSTANTS
 */
/*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * GLOBAL VARIABLES
 */
byte zclSampleLight_TaskID;

/*********************************************************************
 * GLOBAL FUNCTIONS
 */

/*********************************************************************
 * LOCAL VARIABLES
 */
static afAddrType_t  zclSampleLight_DstAddr;
 static afAddrType_t ZED1_DstAddr;
 //static zAddrType_t  Tempy_DstAddr;
// Test Endpoint to allow SYS_APP_MSGs
static endPointDesc_t sampleLight_TestEp =
{
	TEST_ENDPOINT,                       	// Test endpoint
	&zclSampleLight_TaskID,
	(SimpleDescriptionFormat_t *)NULL,  	// No Simple description for this test endpoint
	(afNetworkLatencyReq_t)null            // No Network Latency req
};

/*********************************************************************
 * ZCL General Profile Callback table
 */
static zclGeneral_AppCallbacks_t zclSampleLight_CmdCallbacks =
{
	zclSampleLight_BasicResetCB,              	// Basic Cluster Reset cmd
	zclSampleLight_IdentifyCB,                	// Identify command 
	zclSampleLight_IdentifyQueryRspCB,        	// Identify Query Response cmd
	NULL,                 				// On/Off cluster command
	NULL,                                     	// Level Control Move to Level cmd
	NULL,                                     	// Level Control Move command
	NULL,                                     	// Level Control Step command
	NULL,                                     	// Level Control Stop command
	NULL,                                     	// Group Response commands
	NULL,                                     	// Scene Store Request command
	NULL,                                     	// Scene Recall Request command
	NULL,                                     	// Scene Response command
	NULL,                                     	// Alarm (Response) command
	NULL,                                      	// RSSI Location commands
	NULL,                                     	// RSSI Location Response cmds
};

/*********************************************************************
 * ZCL SS Callback table
 */
static zclSS_AppCallbacks_t zclsampleLight_SS_CmdCallbacks = 
{
	zclSS_ChangeNotificationCB,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
};
   
/**************************************************************************
 * @fn	zclSampleLight_Init
 *
 * @brief	Initialization function for the zclGeneral layer and zclss.
 *
 * @param	[IN]	Task id to do Initialization task
 *
 * @return	SUCCESS
 */
void zclSampleLight_Init( byte task_id )
{
	zclSampleLight_TaskID = task_id;

	// This app is part of the Home Automation Profile
	zclHA_Init( &zclSampleLight_SimpleDesc );
	// Register the ZCL General Cluster Library callback functions
	zclGeneral_RegisterCmdCallbacks( SAMPLELIGHT_ENDPOINT, 
										&zclSampleLight_CmdCallbacks );
	//Register the SS IAS Cluster Library callback functions
	zclSS_RegisterCmdCallbacks(SAMPLELIGHT_ENDPOINT, 
										&zclsampleLight_SS_CmdCallbacks);
	// Register the application's attribute list
	zcl_registerAttrList( SAMPLELIGHT_ENDPOINT, 
							SAMPLELIGHT_MAX_ATTRIBUTES, zclSampleLight_Attrs );
	/* Register the Application to receive 
				the unprocessed Foundation command/response messages*/
	zcl_registerForMsg( zclSampleLight_TaskID );
	// Register for all key events - This app will handle all key events
	RegisterForKeys( zclSampleLight_TaskID ); 
	//Register for Device Announcement
	ZDO_RegisterForZDOMsg(zclSampleLight_TaskID, Device_annce);
	ZDO_RegisterForZDOMsg(zclSampleLight_TaskID, Simple_Desc_rsp); 
    ZDO_RegisterForZDOMsg(zclSampleLight_TaskID, IEEE_addr_rsp);
    ZDO_RegisterForZDOMsg(zclSampleLight_TaskID, Active_EP_rsp);
	//Call back function for UART
	initUART(uartRxCB);
	// Register for a test endpoint
	afRegister( &sampleLight_TestEp );
}

  

/*********************************************************************
 * @fn	zclSampleLight_event_loop
 *
 * @brief	Event Loop Processor for Receiving Sensor's value and Sends
			On/off Command to BEE 4.
 *
 * @param task_id [IN]	Task id for Processing Event
 * @param event   [IN]	Events to do for Receiving Sensor value
 
 * @return		SUCESS
 */
uint16 zclSampleLight_event_loop( uint8 task_id, uint16 events )
{
	afIncomingMSGPacket_t *MSGpkt;
	//devStates_t zclSample_NWKstate;
	//zAddrType_t dstAddr;
	(void)task_id;  // Intentionally unreferenced parameter

	if ( events & SYS_EVENT_MSG )
	{
		while ( (MSGpkt = (afIncomingMSGPacket_t *)
					osal_msg_receive( zclSampleLight_TaskID )) )
		{
			switch ( MSGpkt->hdr.event )
			{
				case ZCL_INCOMING_MSG:
					// Incoming ZCL Foundation command/response messages
					zclSampleLight_ProcessIncomingMsg
											((zclIncomingMsg_t *)MSGpkt );
				break;
				case KEY_CHANGE:
					zclSampleLight_HandleKeys(((keyChange_t *)MSGpkt)->state, 
												((keyChange_t *)MSGpkt)->keys);
				break;
				case ZDO_CB_MSG:
					zclSampleLight_ProcessZDOMsgs((zdoIncomingMsg_t *)MSGpkt );
				break;
				default:
				break;
			}
			// Release the memory
			osal_msg_deallocate( (uint8 *)MSGpkt );
		}
		// return unprocessed events
		return (events ^ SYS_EVENT_MSG);
	}
	if ( events & SAMPLELIGHT_IDENTIFY_TIMEOUT_EVT )
	{
		if ( zclSampleLight_IdentifyTime > INIT_VAL )
		{
			zclSampleLight_IdentifyTime--;
		}
		zclSampleLight_ProcessIdentifyTimeChange();
		return ( events ^ SAMPLELIGHT_IDENTIFY_TIMEOUT_EVT );
	}
	// Discard unknown events
	return SUCCESS;
}

/*********************************************************************
 * @fn      zclSampleLight_HandleKeys
 *
 * @brief   Handles all key events for this device.
 *
 * @param   shift - true if in shift/alt.
 * @param   keys - bit field for key events. Valid entries:
 *                 HAL_KEY_SW_4
 *                 HAL_KEY_SW_3
 *                 HAL_KEY_SW_2
 *                 HAL_KEY_SW_1
 *
 * @return  none
 */
static void zclSampleLight_HandleKeys( byte shift, byte keys )
{
	(void)shift;  // Intentionally unreferenced parameter

	if ( keys & HAL_KEY_SW_2 )
	{
    
	}
	if ( keys & HAL_KEY_SW_3 )
	{
    
	}
	if ( keys & HAL_KEY_SW_4 )
	{
	
	}
}

/*********************************************************************
* @fn 	zclSampleLight_ProcessZDOMsgs()
*
* @brief 	Process response messages
*
* @param inMsg	[IN]	Pointer to ZDO incoming Messages
*
* @return 	none
*/
void zclSampleLight_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg )
{	
  zAddrType_t DstAddr;
	switch ( inMsg->clusterID )
	{
		case Device_annce:
		{
			ZDO_DeviceAnnce_t devAnnce;
			ZDO_ParseDeviceAnnce(inMsg, &devAnnce);
			zclSampleLight_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
			zclSampleLight_DstAddr.addr.shortAddr = devAnnce.nwkAddr;
			zclSampleLight_DstAddr.endPoint = 17;//end point of fire sensor
            zclCfgReportCmd_t cfgRptCmd;
                        cfgRptCmd.numAttr = 1;
                        cfgRptCmd.attrList[0].direction = 0;
                        cfgRptCmd.attrList[0].attrID = ATTRID_SS_IAS_ZONE_STATUS;
                        cfgRptCmd.attrList[0].dataType = ZCL_DATATYPE_INT16;
                        cfgRptCmd.attrList[0].minReportInt = 5;
                        cfgRptCmd.attrList[0].maxReportInt = 10;
                        cfgRptCmd.attrList[0].timeoutPeriod = 0;
                        cfgRptCmd.attrList[0].reportableChange = NULL;
                        zcl_SendConfigReportCmd(SAMPLELIGHT_ENDPOINT,
                                                  &zclSampleLight_DstAddr,
                                                  ZCL_CLUSTER_ID_SS_IAS_ZONE,
                                                   &cfgRptCmd,
                                                  ZCL_FRAME_CLIENT_SERVER_DIR,
                                                  0, 1);
			
			/*DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
			DstAddr.addr.shortAddr = devAnnce.nwkAddr;
           ZDP_ActiveEPReq(&DstAddr, devAnnce.nwkAddr, false);*/
		} 
		break;
		/*case Simple_Desc_rsp:
        {
            char buff[10];
			ZDO_SimpleDescRsp_t *pSimpleDescRsp;
            zclCfgReportCmd_t cfgRptCmd;
            pSimpleDescRsp = NULL;
            uint8 *msg;
            uint8 i = INIT_VAL;
            uint8 numInCluster = INIT_VAL;
            uint8 DummyVar = INIT_VAL;
            static uint8 count = 0;
            msg = inMsg->asdu;
            pSimpleDescRsp->status = *msg++;
            pSimpleDescRsp->nwkAddr = BUILD_UINT16( msg[LOW], msg[HIGH] );
            msg += sizeof ( uint16 );
            msg++; // Skip past the length field.
            if ( pSimpleDescRsp->status == ZDP_SUCCESS )
            {
                ZDO_ParseSimpleDescBuf( msg, &(pSimpleDescRsp->simpleDesc));
                numInCluster = pSimpleDescRsp->simpleDesc.AppNumInClusters;
                while(i < numInCluster && DummyVar == LOW)
                {
                    count++;
                    if(pSimpleDescRsp->simpleDesc.pAppInClusterList[i] ==
                                  ZCL_CLUSTER_ID_MS_RELATIVE_HUMIDITY)
                    {
                        HalLcdWriteString ("Humi Match", HAL_LCD_LINE_3);
                        DummyVar = HIGH;
                        ZED1_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
                        ZED1_DstAddr.addr.shortAddr = pSimpleDescRsp->nwkAddr;
                        ZED1_DstAddr.endPoint = pSimpleDescRsp->simpleDesc.EndPoint;
                        cfgRptCmd.attrList[INIT_VAL].direction = LOW;
                        cfgRptCmd.attrList[INIT_VAL].attrID = 
                                      ZCL_CLUSTER_ID_MS_RELATIVE_HUMIDITY;
                        cfgRptCmd.attrList[INIT_VAL].dataType = 
                                                             ZCL_DATATYPE_INT16;
                        cfgRptCmd.attrList[INIT_VAL].minReportInt = HUMI_REPORT;
                        cfgRptCmd.attrList[INIT_VAL].maxReportInt = 10;
                        cfgRptCmd.attrList[INIT_VAL].timeoutPeriod = 0;
                        cfgRptCmd.attrList[INIT_VAL].reportableChange = NULL;
                        zcl_SendConfigReportCmd(SAMPLELIGHT_ENDPOINT,
                                       &ZED1_DstAddr,
                                       ZCL_CLUSTER_ID_MS_RELATIVE_HUMIDITY,
                                       &cfgRptCmd,
                                       ZCL_FRAME_CLIENT_SERVER_DIR,
                                       false, true);
                    }
                    else if(pSimpleDescRsp->simpleDesc.pAppInClusterList[i] ==
                                  ZCL_CLUSTER_ID_SS_IAS_ZONE)
                    {
                        DummyVar = HIGH;
                        ZED2_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
                        ZED1_DstAddr.addr.shortAddr = pSimpleDescRsp->nwkAddr;
                        ZED1_DstAddr.endPoint = 14;
                        cfgRptCmd.attrList[INIT_VAL].direction = LOW;
                        cfgRptCmd.attrList[INIT_VAL].attrID = 
                                      ATTRID_SS_IAS_ZONE_STATUS;
                        cfgRptCmd.attrList[INIT_VAL].dataType = 
                                                             ZCL_DATATYPE_INT16;
                        cfgRptCmd.attrList[INIT_VAL].minReportInt = FIRE_REPORT;
                        cfgRptCmd.attrList[INIT_VAL].maxReportInt = 10;
                        cfgRptCmd.attrList[INIT_VAL].timeoutPeriod = 0;
                        cfgRptCmd.attrList[INIT_VAL].reportableChange = NULL;
                        zcl_SendConfigReportCmd(SAMPLELIGHT_ENDPOINT,
                                                  &ZED1_DstAddr,
                                                  ZCL_CLUSTER_ID_SS_IAS_ZONE,
                                                   &cfgRptCmd,
                                                  ZCL_FRAME_CLIENT_SERVER_DIR,
                                                  0, 1);
                    }
                                    i++;
                }
           }	
		}
		break;*/
             /*case Active_EP_rsp:
        {
           HalLcdWriteString ("Active", HAL_LCD_LINE_2);
            uint8 i = INIT_VAL;
            uint8 dev_endpt = INIT_VAL;
            uint8 ep[MAX_EP] = {INIT_VAL};
          
            ZDO_ActiveEndpointRsp_t *pRsp = ZDO_ParseEPListRsp(inMsg);
            DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
            DstAddr.addr.shortAddr = pRsp->nwkAddr; 
            for(i = INIT_VAL; i< MAX_EP && pRsp->epList[i]; i++)
            {
              dev_endpt++;
            }
            osal_memcpy(&ep, pRsp->epList, dev_endpt);
            for(i = LOW; i < dev_endpt; i++)
            {
                ZDP_SimpleDescReq(&DstAddr, pRsp->nwkAddr, 
										ep[i] , FALSE );
             }
          } 
        break;*/
    }         
}

*******************************************************************************
* @fn	zclSS_ChangeNotificationCB call back Function
*
* @brief	Process incoming Change Notification Command
*
* @param pcmd	[IN]	Zone Status Change Notification command
*
* @return  none
*/
*********************************************************************
 * @fn	zclSampleLight_ProcessIdentifyTimeChange
 *
 * @brief	Called to process any change to the IdentifyTime attribute.
 *
 * @param   none
 *
 * @return  none
 */
static void zclSampleLight_ProcessIdentifyTimeChange( void )
{
	if ( zclSampleLight_IdentifyTime > INIT_VAL )
	{
		osal_start_timerEx( zclSampleLight_TaskID, 
							SAMPLELIGHT_IDENTIFY_TIMEOUT_EVT, IDENTIFY_TIME );
		HalLedBlink ( HAL_LED_4, 0xFF, HAL_LED_DEFAULT_DUTY_CYCLE,
										HAL_LED_DEFAULT_FLASH_TIME );
	}
}

/*********************************************************************
 * @fn      zclSampleLight_BasicResetCB
 *
 * @brief   Callback from the ZCL General Cluster Library
 *          to set all the Basic Cluster attributes to default values.
 *
 * @param   none
 *
 * @return  none
 */
static void zclSampleLight_BasicResetCB( void )
{
	// Reset all attributes to default values
}

/*********************************************************************
 * @fn      zclSampleLight_IdentifyCB
 *
 * @brief   Callback from the ZCL General Cluster Library when
 *          it received an Identity Command for this application.
 *
 * @param srcAddr		[IN]	source address and endpoint of the response message
 * @param identifyTime 	[IN]	the number of seconds to identify 
 *
 * @return  none
 */
static void zclSampleLight_IdentifyCB( zclIdentify_t *pCmd )
{
	zclSampleLight_IdentifyTime = pCmd->identifyTime;
	zclSampleLight_ProcessIdentifyTimeChange();
}

/*********************************************************************
 * @fn      zclSampleLight_IdentifyQueryRspCB
 *
 * @brief   Callback from the ZCL General Cluster Library when
 *          it received an Identity Query Response Command for this application.
 *
 * @param srcAddr 	[IN]	requestor's address
 * @param timeout	[IN]	number of seconds to identify 
							(valid for query response)
 *
 * @return  none
 */
static void zclSampleLight_IdentifyQueryRspCB(  zclIdentifyQueryRsp_t *pRsp )
{
	// Query Response (with timeout value)
	(void)pRsp;
}

/*********************************************************************
 * @fn      zclSampleLight_ProcessIncomingMsg
 *
 * @brief   Process ZCL Foundation incoming message
 *
 * @param pInMsg	[IN]	pointer to the received message
 *
 * @return  none
 */
static void zclSampleLight_ProcessIncomingMsg( zclIncomingMsg_t *pInMsg)
{
	switch ( pInMsg->zclHdr.commandID )
	{
		#ifdef ZCL_READ
		case ZCL_CMD_READ_RSP:
			zclSampleLight_ProcessInReadRspCmd( pInMsg );
		break;
		#endif
		#ifdef ZCL_WRITE    
		case ZCL_CMD_WRITE_RSP:
			zclSampleLight_ProcessInWriteRspCmd( pInMsg );
		break;
		#endif
		#ifdef ZCL_REPORT
		case ZCL_CMD_CONFIG_REPORT:
				//zclSampleLight_ProcessInConfigReportCmd( pInMsg );
		break;
		case ZCL_CMD_CONFIG_REPORT_RSP:
			//zclSampleLight_ProcessInConfigReportRspCmd( pInMsg );
		break; 
		case ZCL_CMD_READ_REPORT_CFG:
			//zclSampleLight_ProcessInReadReportCfgCmd( pInMsg );
		break;
		case ZCL_CMD_READ_REPORT_CFG_RSP:
			//zclSampleLight_ProcessInReadReportCfgRspCmd( pInMsg );
		break;
		case ZCL_CMD_REPORT:
			zclSampleLight_ProcessInReportCmd( pInMsg );
		break;
		#endif   
		case ZCL_CMD_DEFAULT_RSP:
			zclSampleLight_ProcessInDefaultRspCmd( pInMsg );
		break;
		#ifdef ZCL_ZONE
		case COMMAND_SS_IAS_ZONE_STATUS_CHANGE_NOTIFICATION:
			zclSampleLight_ProcessInReportCmd(pInMsg);
		break;
		#endif
        #ifdef ZCL_DISCOVER     
		case ZCL_CMD_DISCOVER_RSP:
			zclSampleLight_ProcessInDiscRspCmd( pInMsg );
		break;
		#endif  
		default:
		break;
	}
	if ( pInMsg->attrCmd )
		osal_mem_free( pInMsg->attrCmd );
}

#ifdef ZCL_READ
/*********************************************************************
 * @fn      zclSampleLight_ProcessInReadRspCmd
 *
 * @brief   Process the "Profile" Read Response Command
 *
 * @param pInMsg	[IN]	incoming message to process
 *
 * @return  SUCCESS
 */
static uint8 zclSampleLight_ProcessInReadRspCmd( zclIncomingMsg_t *pInMsg )
{
	zclReadRspCmd_t *readRspCmd;
	uint8 i;

	readRspCmd = (zclReadRspCmd_t *)pInMsg->attrCmd;
	for (i = INIT_VAL; i < readRspCmd->numAttr; i++)
	{
		// Notify the originator of the results of the original read attribute 
		// attempt and, for each successfull request,the value of the request
		// attribute
	}
  return SUCCESS; 
}
#endif // ZCL_READ

#ifdef ZCL_WRITE
/*********************************************************************
 * @fn      zclSampleLight_ProcessInWriteRspCmd
 *
 * @brief   Process the "Profile" Write Response Command
 *
 * @param   pInMsg - incoming message to process
 *
 * @return  none
 */
static uint8 zclSampleLight_ProcessInWriteRspCmd( zclIncomingMsg_t *pInMsg )
{
	zclWriteRspCmd_t *writeRspCmd;
	uint8 i;

	writeRspCmd = (zclWriteRspCmd_t *)pInMsg->attrCmd;
	for (i = INIT_VAL; i < writeRspCmd->numAttr; i++)
	{
		// Notify the device of the results of the its original write attributes
		// command.
	}
	return SUCCESS; 
}
#endif // ZCL_WRITE

#ifdef ZCL_REPORT
/*********************************************************************
 * @fn      zclSampleLight_ProcessInReportCmd
 *
 * @brief   Process the "Profile" Report Command
 *
 * @param   pInMsg - incoming message to process
 *
 * @return  none
 */
static void zclSampleLight_ProcessInReportCmd( zclIncomingMsg_t *pInMsg )
{
	zclReportCmd_t *pReportCmd;
	pReportCmd = (zclReportCmd_t *)pInMsg->attrCmd;
	uint8 Data;
	uint16 len = INIT_VAL;
	char Data1[DATA_LENGHT];

		if (pInMsg->clusterId == ZCL_CLUSTER_ID_MS_RELATIVE_HUMIDITY || 
									ZCL_CLUSTER_ID_SS_IAS_ZONE)
	{
		if (pInMsg->clusterId == ZCL_CLUSTER_ID_MS_RELATIVE_HUMIDITY)
		{
			if (pReportCmd->attrList[INIT_VAL].attrID == 
									ATTRID_MS_RELATIVE_HUMIDITY_MEASURED_VALUE)
			{
                uint8 count = INIT_VAL;
				Data = *(int16*)pReportCmd->attrList[INIT_VAL].attrData;
				sprintf(Data1,"%d",Data);
		   }	
		}
		if (pInMsg->clusterId == ZCL_CLUSTER_ID_SS_IAS_ZONE)
		{
			if (pReportCmd->attrList[INIT_VAL].attrID == 
										ATTRID_SS_IAS_ZONE_STATUS)
			{
                uint8 count = INIT_VAL;
                
				Data = *(int16*)pReportCmd->attrList[INIT_VAL].attrData;
				sprintf(Data1,"%d",Data);
				                    #if defined( LCD_SUPPORTED )
                      #ifdef HAL_MCU_CC2530
						HalLcdWriteScreen( "Fire Status", Data1);
                      #endif
                    #endif
                   count++;
                   MicroWait(WAIT_DELAY);
                }
			} 
		}
	}	
}
#endif   /* ZCL_REPORT */

/*********************************************************************
 * @fn      zclSampleLight_ProcessInDefaultRspCmd
 *
 * @brief   Process the "Profile" Default Response Command
 *
 * @param   pInMsg - incoming message to process
 *
 * @return  none
 */
static uint8 zclSampleLight_ProcessInDefaultRspCmd( zclIncomingMsg_t *pInMsg )
{
	// Device is notified of the Default Response command.
	(void)pInMsg; 
	return SUCCESS; 
}

#ifdef ZCL_DISCOVER
/*********************************************************************
 * @fn      zclSampleLight_ProcessInDiscRspCmd
 *
 * @brief   Process the "Profile" Discover Response Command
 *
 * @param   pInMsg - incoming message to process
 *
 * @return  none
 */
static uint8 zclSampleLight_ProcessInDiscRspCmd( zclIncomingMsg_t *pInMsg )
{
	zclDiscoverRspCmd_t *discoverRspCmd;
	uint8 i;
	  
	discoverRspCmd = (zclDiscoverRspCmd_t *)pInMsg->attrCmd;
	for ( i = INIT_VAL; i < discoverRspCmd->numAttr; i++ )
	{
		// Device is notified of the result of its attribute discovery command.
	}
	return SUCCESS;
}
#endif // ZCL_DISCOVER


/****************************************************************************
****************************************************************************/

