void Switch_task(NVINTF_nvFuncts_t *pfnNV)
{
// Save and register the function pointers to the NV drivers
pfnZswNV = pfnNV;
zclport_registerNV(pfnZswNV, ZCL_PORT_SCENE_TABLE_NV_ID);
// Initialize application
Switch_initialization();
// No return from task process
Switch_process();
}
static void Switch_initialization(void)
{
/* Initialize variables */
[Link] = zstack_AFAddrMode_NONE;
[Link] = 0;
[Link] = 0;
[Link] = 0;
#if defined (ZCL_EZMODE)
zclport_registerEZModeTimerCB(Switch_setEzmodeTimerCallback);
#endif
Switch_initializeClocks();
/* Initialize keys */
Board_Key_initialize(Switch_processKeyChangeCallback);
/* Initialize the LCD */
Board_LCD_open();
LCD_WRITE_STRING( (char *)sDeviceName, LCD_PAGE1 );
#if defined (ZCL_EZMODE)
LCD_WRITE_STRING( (char *)sSwEZMode, LCD_PAGE2 );
#elif defined (ZSTACK_MANUAL_START)
LCD_WRITE_STRING( (char *)sSwStart, LCD_PAGE2 );
#else
LCD_WRITE_STRING( (char *)sClearLine, LCD_PAGE2 );
#endif
LCD_WRITE_STRING( (char *)sSwHelp, LCD_PAGE3 );
/* Initialize the LEDS */
Board_Led_initialize();
// Register the current thread as an ICall dispatcher application
// so that the application can send and receive messages.
ICall_registerApp(&zswEntity, &sem);
// Initialize the ZStack
Switch_initializeZStack();
}
static void Switch_initializeZStack(void)
{
// Initialize the ZStack Thread
bool startDev = true; // default to auto-start
// Setup the endpoints
zswRegEndpoints();
// Setup indications from ZStack
zswSetupZStackCallbacks();
#if defined (ZSTACK_MANUAL_START) || defined (ZCL_EZMODE)
// Check to see if the device is already part of a network,
// to see if we need to invoke EZMode or Manual startup
startDev = zclport_isAlreadyPartOfNetwork(zswEntity);
#endif
#if defined (ZSTACK_MANUAL_START)
// Setup the Manual Start module
Switch_initializeZstartDiscovery();
#endif
#if defined (ZCL_EZMODE)
{
// Register EZ-Mode
zcl_RegisterEZMode(&ezmodeRegisterData);
Board_Led_control(board_led_type_LED1, board_led_state_BLINK);
}
#endif
if(startDev)
{
zstack_devStartReq_t startReq = {0};
// Start the ZStack Thread
[Link] = 0;
(void)Zstackapi_DevStartReq(zswEntity, &startReq);
#if defined (ZCL_EZMODE)
// Clear the EZ Mode line
LCD_WRITE_STRING( (char *)sClearLine, LCD_PAGE2 );
#endif
}
// Register the ZCL General Cluster Library callback functions
zclGeneral_RegisterCmdCallbacks(SWITCH_EP, &cmdCallbacks);
// Register the application's attribute list
zcl_registerAttrList(SWITCH_EP, SWITCH_MAX_ATTRIBUTES, zswAttrs);
// Update the ZStack Parameters
zswWriteParameters();
}
static void Switch_process(void)
{
/* Forever loop */
for(;;)
{
ICall_ServiceEnum stackid;
ICall_EntityID dest;
zstackmsg_genericReq_t *pMsg = NULL;
/* Wait for response message */
if(ICall_wait(ICALL_TIMEOUT_FOREVER) == ICALL_ERRNO_SUCCESS)
{
/* Retrieve the response message */
if(ICall_fetchServiceMsg(&stackid, &dest, (void **)&pMsg)
== ICALL_ERRNO_SUCCESS)
{
if( (stackid == ICALL_SERVICE_CLASS_ZSTACK)
&& (dest == zswEntity) )
{
if(pMsg)
{
Switch_processZStackMsgs(pMsg);
// Free any separately allocated memory
Zstackapi_freeIndMsg(pMsg);
}
}
if(pMsg)
{
ICall_freeMsg(pMsg);
}
}
if(events & SWITCH_KEY_EVENT)
{
// Process Key Presses
Switch_handleKeys(keys);
keys = 0;
events &= ~SWITCH_KEY_EVENT;
}
if(events & SWITCH_IDENTIFY_TIMEOUT_EVT)
{
// Process the Identify timer expiration
if(zswIdentifyTime > 0)
{
zswIdentifyTime--;
}
Switch_processIdentifyTimeChange();
events &= ~SWITCH_IDENTIFY_TIMEOUT_EVT;
}
if(events & SWITCH_MAIN_SCREEN_EVT)
{
// Update the display
giSwScreenMode = SWITCH_MAINMODE;
Switch_updateLcdMainScreen();
events &= ~SWITCH_MAIN_SCREEN_EVT;
}
#ifdef ZCL_EZMODE
if(events & SWITCH_EZMODE_NEXTSTATE_EVT)
{
// going on to next state
zcl_EZModeAction(EZMODE_ACTION_PROCESS, NULL);
events &= ~SWITCH_EZMODE_NEXTSTATE_EVT;
}
if(events & SWITCH_EZMODE_TIMEOUT_EVT)
{
// EZ-Mode timed out
zcl_EZModeAction(EZMODE_ACTION_TIMED_OUT, NULL);
events &= ~SWITCH_EZMODE_TIMEOUT_EVT;
}
#endif // ZLC_EZMODE
#if defined (ZSTACK_MANUAL_START)
if(events & SWITCH_MANUAL_START_CLK_EVT)
{
// Manual start timeout
Zstart_processClockEvt();
events &= ~SWITCH_MANUAL_START_CLK_EVT;
}
#endif
}
}
}
-
static void Switch_processZStackMsgs(zstackmsg_genericReq_t *pMsg)
{
switch(pMsg->[Link])
{
case zstackmsg_CmdIDs_DEV_STATE_CHANGE_IND:
{
// The ZStack Thread is indicating a State change
zstackmsg_devStateChangeInd_t *pInd =
(zstackmsg_devStateChangeInd_t *)pMsg;
// Only process the state change if it actually changed.
if(savedState != pInd->[Link])
{
// Save the new state
savedState = pInd->[Link];
if( (pInd->[Link] == zstack_DevState_DEV_ZB_COORD)
|| (pInd->[Link] == zstack_DevState_DEV_ROUTER)
|| (pInd->[Link] == zstack_DevState_DEV_END_DEVICE) )
{
// The device is part of a network, get the device's
// network parameters.
pNwkInfo = zclport_getDeviceInfo(zswEntity);
// Update the display with network information
giSwScreenMode = SWITCH_MAINMODE;
Switch_updateLcdDisplay();
Board_Led_control(board_led_type_LED1,
board_led_state_OFF);
if(pInd->[Link] != zstack_DevState_DEV_END_DEVICE)
{
// Don't turn on LED if Power saving end device
Board_Led_control(board_led_type_LED4,
board_led_state_ON);
}
else
{
// Change the default poll rate from 1 second to
// the config
// setting (znwk_config.h)
Switch_setPollRate(ZNWK_POLL_RATE);
}
}
#if defined (ZSTACK_MANUAL_START)
{
zstart_params *pParams = Zstart_processStateChange(
pInd->[Link]);
if(pParams->state == ZSTART_STATE_JOINED)
{
// Device joined
}
else if(pParams->state == ZSTART_STATE_REJOINED)
{
// Device has rejoined
}
else if(pParams->state == ZSTART_STATE_HOLD)
{
}
}
#endif
}
}
break;
case zstackmsg_CmdIDs_AF_INCOMING_MSG_IND:
{
// Process incoming data messages
zstackmsg_afIncomingMsgInd_t *pInd =
(zstackmsg_afIncomingMsgInd_t *)pMsg;
Switch_processAfIncomingMsgInd( &(pInd->req) );
}
break;
#if defined (ZSTACK_MANUAL_START)
case zstackmsg_CmdIDs_ZDO_BEACON_NOTIFY_IND:
{
// ZStart will process this message
zstackmsg_zdoBeaconNotifyInd_t *pInd
= (zstackmsg_zdoBeaconNotifyInd_t *)pMsg;
Zstart_processBeacon( &(pInd->req) );
}
break;
case zstackmsg_CmdIDs_ZDO_NWK_DISC_CNF:
{
// ZStart will process this message
zstackmsg_zdoNwkDiscCnf_t *pInd =
(zstackmsg_zdoNwkDiscCnf_t *)pMsg;
if(Zstart_processNwkDiscCnf(pInd->[Link]) == true)
{
// Scan process is over
zstart_params *pParams = Zstart_getParameters();
if(pParams->state == ZSTART_STATE_SCAN_COMPLETE)
{
// Scan is complete and it's time to join
// In the zstart_params structure, the zstart has
// selected
// a network and device to join, you could change it by
// looking
// through the found network list
// [Zstart_getNetworkList()] and
// setting your own network(pParams->chosenNetwork) and
// device (pParams->chosenRouter) to join. Or, you
// could go with
// what was selected, like this example.
Zstart_join();
}
else if(pParams->state ==
ZSTART_STATE_SCAN_COMPLETE_NO_RESULTS)
{
// No results means that no networks found (that passed
// filtering)
// If you would like to delay the start of scanning,
// setup a timer
// to start scanning on timeout. For now, start a new
// discovery now.
Switch_initializeZstartDiscovery();
Zstart_discovery();
}
}
}
break;
case zstackmsg_CmdIDs_ZDO_JOIN_CNF:
{
zstackmsg_zdoJoinConf_t *pInd =
(zstackmsg_zdoJoinConf_t *)pMsg;
zstack_ZStatusValues status =
(zstack_ZStatusValues)pInd->[Link];
// ZStart will process this message
Zstart_processJoinCnf( status, &(pInd->req) );
if(status != zstack_ZStatusValues_ZSuccess)
{
zstart_params *pParams = Zstart_getParameters();
if(pParams && pParams->state == ZSTART_STATE_JOINING)
{
// Join didn't go well, let's add this device to the
// blacklist
// to skip this device next time, and restart the
// discovery process
zstart_NwkDiscItem *pNwk;
pNwk = Zstart_getNwk(pParams->chosenNetwork);
if(pNwk)
{
zstack_routerInfo *pRouter = Zstart_getRouter(
pNwk,
pParams
->chosenRouter);
if(pRouter)
{
Zstart_addToBlackList( (uint8_t *)&(pNwk->
extendedPANID),
pRouter->sourceAddr );
}
}
// You could add delay here -> timer, event
// Restart discovery process
Switch_initializeZstartDiscovery();
Zstart_discovery();
}
}
}
break;
#endif // ZSTACK_MANUAL_START
default:
break;
}
}
static void Switch_processAfIncomingMsgInd(zstack_afIncomingMsgInd_t *pInMsg)
{
afIncomingMSGPacket_t afMsg;
/*
* All incoming messages are passed to the ZCL message processor,
* first convert to a structure that ZCL can process.
*/
[Link] = pInMsg->groupID;
[Link] = pInMsg->clusterId;
[Link] = pInMsg->[Link];
[Link] = pInMsg->[Link];
[Link] = (afAddrMode_t)pInMsg->[Link];
if( ([Link] == afAddr16Bit)
|| ([Link] == afAddrGroup)
|| ([Link] == afAddrBroadcast) )
{
[Link] = pInMsg->[Link];
}
else if([Link] == afAddr64Bit)
{
memcpy([Link], &(pInMsg->[Link]),
EXTADDR_LEN);
}
[Link] = pInMsg->macDestAddr;
[Link] = pInMsg->endpoint;
[Link] = pInMsg->wasBroadcast;
[Link] = pInMsg->linkQuality;
[Link] = pInMsg->correlation;
[Link] = pInMsg->rssi;
[Link] = pInMsg->securityUse;
[Link] = pInMsg->timestamp;
[Link] = pInMsg->nwkSeqNum;
[Link] = pInMsg->macSrcAddr;
[Link] = pInMsg->radius;
[Link] = pInMsg->transSeqNum;
[Link] = pInMsg->n_payload;
[Link] = pInMsg->pPayload;
zcl_ProcessMessageMSG(&afMsg);
}
/*******************************************************************************
* @fn Switch_sendToggle
*
* @brief Send an ON/OFF toggle command
*
* @param none
*
* @return none
*/
static void Switch_sendToggle(void)
{
afAddrType_t dstAddr;
[Link] = (afAddrMode_t)[Link];
[Link] = [Link];
[Link] = [Link];
[Link] = [Link];
// Send a toggle
zclGeneral_SendOnOff_CmdToggle(SWITCH_EP, &dstAddr, false, 0);
LCD_WRITE_STRING( (char *)sCmdSent, LCD_PAGE2 );
}
/*******************************************************************************
* @fn Switch_handleKeys
*
* @brief Callback service for keys
*
* @param keys - keys that were pressed
*
* @return void
*/
static void Switch_handleKeys(uint8_t keys)
{
if(keys == KEY_UP)
{
// Send the Toggle command through ZCL
Switch_sendToggle();
}
// toggle permit join
if(keys == KEY_LEFT)
{
giSwScreenMode = SWITCH_MAINMODE; // remove help screen if there
if( pNwkInfo
&& ( (savedState == zstack_DevState_DEV_ZB_COORD)
|| (savedState == zstack_DevState_DEV_ROUTER) ) )
{
zstack_zdoMgmtPermitJoinReq_t req;
// toggle permit join
gPermitDuration = gPermitDuration ? 0 : 0xff;
[Link] = pNwkInfo->nwkAddr;
[Link] = gPermitDuration;
[Link] = true;
Zstackapi_ZdoMgmtPermitJoinReq(zswEntity, &req);
}
}
if(keys == KEY_SELECT)
{
// Switch between Help and Main screens
if(giSwScreenMode == SWITCH_MAINMODE)
{
// Switch from main screen to help screen
giSwScreenMode = SWITCH_HELPMODE;
}
else
{
// Switch from help screen to main screen
giSwScreenMode = SWITCH_MAINMODE;
LCD_WRITE_STRING( (char *)sClearLine, LCD_PAGE2 );
}
}
if(keys == KEY_RIGHT)
{
#if defined (ZCL_EZMODE)
// Start EZMode Commissioning
{
zclEZMode_InvokeData_t ezModeData;
// only bind on the on/off cluster
static uint16_t clusterIDs[] =
{ ZCL_CLUSTER_ID_GEN_ON_OFF};
// Invoke EZ-Mode
[Link] = SWITCH_EP; // endpoint on which to invoke
// EZ-Mode
if( (savedState == zstack_DevState_DEV_ZB_COORD)
|| (savedState == zstack_DevState_DEV_ROUTER)
|| (savedState == zstack_DevState_DEV_END_DEVICE) )
{
[Link] = true; // node is already on the
// network
}
else
{
[Link] = false; // node is not yet on the
// network
}
[Link] = true; // OnOffSwitch is an initiator
[Link] = 1; // active output cluster
[Link] = clusterIDs;
[Link] = 0; // no active input clusters
[Link] = NULL;
zcl_InvokeEZMode(&ezModeData);
LCD_WRITE_STRING("EZMode", LCD_PAGE2);
}
#elif defined (ZSTACK_MANUAL_START)
Zstart_discovery();
#endif // ZCL_EZMODE
}
// update the display
Switch_updateLcdDisplay();
}
/*********************************************************************