static CommissioningState_t SetBinding(void) { emberAfDebugPrintln("DEBUG: Set Binding"); MatchDescriptorReq_t *in_dev = GetTopInDeviceDescriptor(); assert(in_dev != NULL); // init clusters skip mask length for checking for duplicates in the binding // table InitRemoteSkipCluster(in_dev->source_cl_arr_len); // check the supported clusters list for existence in the binding table MarkDuplicateMatches(in_dev); // nothing to do if we unmarked all clusters if (GetRemoteSkipMask() == 0) { SetNextEvent(SC_EZEV_CHECK_QUEUE); emberEventControlSetActive(StateMachineEvent); } else if (CreateBindings(in_dev)) { // Create bindings for supported clusters SetNextEvent(SC_EZEV_BINDING_DONE); } else { SetNextEvent(SC_EZEV_CHECK_QUEUE); } PopInDeviceDescriptor(); emberAfDebugPrintln("DEBUG: Supported clusters mask 0x%X", skip_mask.skip_clusters); emberEventControlSetActive(StateMachineEvent); return SC_EZ_BIND; }
// See if we can recover from tunnel creation issues. static bool handleRequestTunnelFailure(uint8_t tunnelIndex, EmberAfPluginTunnelingClientStatus status) { uint8_t i; emberAfDebugPrintln("CHF: handleRequestTunnelFailure 0x%x, 0x%x", tunnelIndex, status); if (status == EMBER_AF_PLUGIN_TUNNELING_CLIENT_BUSY) { // Per GBCS send another request 3 minutes from now tunnels[tunnelIndex].state = REQUEST_PENDING_TUNNEL; tunnels[tunnelIndex].timeoutMSec = halCommonGetInt32uMillisecondTick() + (MILLISECOND_TICKS_PER_SECOND * 180); emberEventControlSetActive(emberAfPluginCommsHubFunctionTunnelEventControl); emberAfPluginCommsHubFunctionPrintln("CHF: Busy status received from node ID 0x%2x",tunnels[tunnelIndex].remoteNodeId); return true; } else if (status == EMBER_AF_PLUGIN_TUNNELING_CLIENT_NO_MORE_TUNNEL_IDS) { // Per GBCS close any other tunnels we may have with the device // and once all responses are received try the RequestTunnel again bool retryRequest = false; for (i = 0; i < EMBER_AF_PLUGIN_COMMS_HUB_FUNCTION_TUNNEL_LIMIT; i++) { if (i != tunnelIndex && tunnels[i].remoteNodeId == tunnels[tunnelIndex].remoteNodeId) { retryRequest = true; emAfPluginCommsHubFunctionTunnelDestroy(tunnels[i].remoteDeviceId); } } if (retryRequest) { // We'll retry the request in the tunnel event handler so as to give the // tunnel(s) a chance to clean up. tunnels[tunnelIndex].state = REQUEST_PENDING_TUNNEL; tunnels[tunnelIndex].timeoutMSec = halCommonGetInt32uMillisecondTick() + (MILLISECOND_TICKS_PER_SECOND * 5); emberEventControlSetActive(emberAfPluginCommsHubFunctionTunnelEventControl); return true; } // no tunnels were closed so nothing more we can do emberAfPluginCommsHubFunctionPrintln("%p%p%p", "Error: ", "Tunnel Create failed: ", "No more tunnel ids"); tunnels[tunnelIndex].state = CLOSED_TUNNEL; return false; } // All other errors are either due to mis-configuration or errors that we // cannot recover from so print the error and return false. emberAfPluginCommsHubFunctionPrintln("%p%p%p0x%x", "Error: ", "Tunnel Create failed: ", "Tunneling Client Status: ", status); tunnels[tunnelIndex].state = CLOSED_TUNNEL; return false; }
static CommissioningState_t CheckNetwork(void) { emberAfDebugPrintln("DEBUG: Check Network state"); EmberNetworkStatus nw_status = emberNetworkState(); emberAfDebugPrintln("DEBUG: network state 0x%X", nw_status); if (nw_status == EMBER_JOINING_NETWORK || nw_status == EMBER_LEAVING_NETWORK) { // Try to check again after 5 seconds emberEventControlSetDelayQS(StateMachineEvent, SIMPLE_COMMISSIONING_NETWORK_RETRY_DELAY); return SC_EZ_START; } if (nw_status == EMBER_JOINED_NETWORK) { SetNextEvent(SC_EZEV_BCAST_IDENT_QUERY); // Send Permit Join broadcast to the current network // in case of ZED nothing will happen // TODO: Make this hadrcoded value as plugin's option emberAfPermitJoin(SIMPLE_COMMISSIONING_PERMIT_JOIN_TIME, TRUE); } else if (nw_status == EMBER_NO_NETWORK && GetNetworkTries() < NETWORK_ACCESS_CONS_TRIES) { // Form or join available network SetNextEvent(SC_EZEV_FORM_JOIN_NETWORK); } else { SetNextEvent(SC_EZEV_NETWORK_FAILED); } // if the device is in the network continue commissioning // by sending Identify Query emberEventControlSetActive(StateMachineEvent); return SC_EZ_START; }
static bool requestTunnel(uint8_t tunnelIndex) { EmberAfPluginTunnelingClientStatus status; // The tunneling cluster client code can only process one tunneling reuqest // at a time so if there's already on outstanding then mark this one pending // and let the tunnel event handler take care of the retry. if (responsePendingIndex != EM_AF_PLUGIN_COMMS_HUB_FUNCTION_NULL_TUNNEL_INDEX) { tunnels[tunnelIndex].state = REQUEST_PENDING_TUNNEL; tunnels[tunnelIndex].timeoutMSec = halCommonGetInt32uMillisecondTick(); emberEventControlSetActive(emberAfPluginCommsHubFunctionTunnelEventControl); return true; } status = emberAfPluginTunnelingClientRequestTunnel(tunnels[tunnelIndex].remoteNodeId, localTunnelEndpoint, tunnels[tunnelIndex].remoteEndpoint, GBCS_TUNNELING_PROTOCOL_ID, GBCS_TUNNELING_MANUFACTURER_CODE, GBCS_TUNNELING_FLOW_CONTROL_SUPPORT); if (status != EMBER_AF_PLUGIN_TUNNELING_CLIENT_SUCCESS && !handleRequestTunnelFailure(tunnelIndex, status)) { return false; } responsePendingIndex = tunnelIndex; tunnels[tunnelIndex].state = RESPONSE_PENDING_TUNNEL; return true; }
/** @brief Identify Cluster Identify Query Response * * * * @param timeout Ver.: always */ boolean emberAfIdentifyClusterIdentifyQueryResponseCallback(int16u timeout) { // TODO: !!! IMPORTANT !!! add handling for several responses // now the state machine might be broken as we use only one global variable // for storing incoming connection information like Short ID and endpoint // // ignore broadcasts from yourself and from devices that are not // in the identifying state const EmberAfClusterCommand *const current_cmd = emberAfCurrentCommand(); if (emberAfGetNodeId() != current_cmd->source && timeout != 0) { emberAfDebugPrintln("DEBUG: Got ID Query response"); emberAfDebugPrintln("DEBUG: Sender 0x%2X", emberAfCurrentCommand()->source); // Queue is empty, so we can start commissioning process // otherwise we push it in the queue and will process later if (GetQueueSize() == 0) { // ID Query received -> go to the discover state for getting clusters info emberAfDebugPrintln("DEBUG: QUEUE IS EMPTY"); SetNextState(SC_EZ_DISCOVER); SetNextEvent(SC_EZEV_CHECK_CLUSTERS); emberEventControlSetActive(StateMachineEvent); } // Store information about endpoint and short ID of the incoming response // for further processing in the Matching (SC_EZ_MATCH) state SetInConnBaseInfo(current_cmd->source, current_cmd->apsFrame->sourceEndpoint); emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS); } return TRUE; }
bool emAfPluginCommsHubFunctionTunnelDestroy(EmberEUI64 remoteDeviceId) { EmberAfStatus status = EMBER_ZCL_STATUS_NOT_FOUND; uint8_t tunnelIndex; emberAfDebugPrint("CHF: TunnelDestroy "); emberAfDebugDebugExec(emberAfPrintBigEndianEui64(remoteDeviceId)); emberAfDebugPrintln(""); tunnelIndex = findTunnelByDeviceId(remoteDeviceId); if (tunnelIndex < EMBER_AF_PLUGIN_COMMS_HUB_FUNCTION_TUNNEL_LIMIT) { status = (tunnels[tunnelIndex].type == CLIENT_TUNNEL) ? emberAfPluginTunnelingClientCloseTunnel(tunnels[tunnelIndex].tunnelId) : EMBER_ZCL_STATUS_SUCCESS; if (status == EMBER_ZCL_STATUS_SUCCESS) { tunnels[tunnelIndex].state = UNUSED_TUNNEL; if (tunnelIndex == responsePendingIndex) { responsePendingIndex = EM_AF_PLUGIN_COMMS_HUB_FUNCTION_NULL_TUNNEL_INDEX; // let the tunnel event handler retry any pending create requests emberEventControlSetActive(emberAfPluginCommsHubFunctionTunnelEventControl); } } } return (status == EMBER_ZCL_STATUS_SUCCESS); }
EmberStatus SimpleCommissioningStart(uint8_t endpoint, bool is_server, const uint16_t *clusters, uint8_t length) { if (!clusters || !length) { // meaningless call if ClusterID array was not passed or its length // is zero return EMBER_BAD_ARGUMENT; } emberAfDebugPrintln("DEBUG: Call for starting commissioning"); if (length > emberBindingTableSize) { // passed more clusters than the binding table may handle // TODO: may be it is worth to track available entries to write in // the binding table emberAfDebugPrint("Warning: ask for bind 0x%X clusters. ", length); emberAfDebugPrintln("Binding table size is 0x%X", emberBindingTableSize); } if (CommissioningStateMachineStatus() != SC_EZ_STOP) { // quite implicit, but if our state machine runs then network // probably busy return EMBER_NETWORK_BUSY; } InitDeviceCommissionInfo(&dev_comm_session, endpoint, is_server, clusters, length); // Wake up our state machine emberEventControlSetActive(StateMachineEvent); return EMBER_SUCCESS; }
static void rescheduleUserControlEvent(void) { // Look at all the active records and figure out when to schedule the event. // If any record should have been sent in the past, we immediately schedule // the event to send it as soon as possible. Otherwise, we find the record // that has to be repeated soonest and schedule based on that. If there are // no active records, we are done and cancel the event. uint16_t nowMs = halCommonGetInt16uMillisecondTick(); uint16_t delayMs = MAX_INT16U_VALUE; uint8_t i; for (i = 0; i < COUNTOF(records); i++) { if (records[i].pairingIndex != 0xFF) { if (timeGTorEqualInt16u(nowMs, records[i].timeMs)) { delayMs = 0; break; } else { uint16_t remainingMs = elapsedTimeInt16u(nowMs, records[i].timeMs); if (remainingMs < delayMs) { delayMs = remainingMs; } } } } if (delayMs == MAX_INT16U_VALUE) { emberEventControlSetInactive(emberAfPluginRf4ceZrc11OutgoingUserControlEventControl); } else if (delayMs == 0) { emberEventControlSetActive(emberAfPluginRf4ceZrc11OutgoingUserControlEventControl); } else { emberEventControlSetDelayMS(emberAfPluginRf4ceZrc11OutgoingUserControlEventControl, delayMs); } }
// ****** CLI Command helpers (public APIs) ****** void emberAfPluginLowVoltageShutdownEnable(bool enable) { if (enable) { emberEventControlSetActive(myEvent); } else { emberEventControlSetInactive(myEvent); } }
static CommissioningState_t BindingDone(void) { emberAfDebugPrintln("DEBUG: Binding Done"); // as we've processed the current remote device delete it from the queue SetNextEvent(SC_EZEV_CHECK_QUEUE); emberEventControlSetActive(StateMachineEvent); return SC_EZ_BIND; }
// Hal Button ISR Callback // This callback is called by the framework whenever a button is pressed on the // device. This callback is called within ISR context. void emberAfHalButtonIsrCallback(int8u button, int8u state) { if ((button == BUTTON0 || button == BUTTON1) && state == BUTTON_PRESSED && !emberEventControlGetActive(buttonEventControl)) { buttonPressTime = halCommonGetInt16uMillisecondTick(); emberEventControlSetActive(buttonEventControl); } }
void networkEventHandler(void) { if (emberAfRf4ceStart() == EMBER_SUCCESS) { emberEventControlSetInactive(networkEventControl); halPlayTune_P(waitTune, TRUE); } else { emberEventControlSetActive(networkEventControl); halPlayTune_P(sadTune, TRUE); } }
static void scheduleEvent(bool withDelay) { if (withDelay) { debugPrintln("%p scheduled event for %d qs", PLUGIN_NAME, DISCOVERY_DELAY_QS); emberEventControlSetDelayQS(emberAfPluginDeviceQueryServiceMyEventControl, DISCOVERY_DELAY_QS); } else { emberEventControlSetActive(emberAfPluginDeviceQueryServiceMyEventControl); } }
/** @brief Identify * * This function is called by the ZLL Commissioning plugin to notify the * application that it should take an action to identify itself. This * typically occurs when an Identify Request is received via inter-PAN * messaging. * * @param durationS If the duration is zero, the device should exit identify * mode. If the duration is 0xFFFF, the device should remain in identify mode * for the default time. Otherwise, the duration specifies the length of time * in seconds that the device should remain in identify mode. Ver.: always */ void emberAfPluginZllCommissioningIdentifyCallback(int16u durationS) { if (durationS != 0) { halStackIndicatePresence(); } identifyDurationMs = (durationS == 0xFFFF ? DEFAULT_IDENTIFY_DURATION_MS : durationS * MILLISECOND_TICKS_PER_SECOND); emberEventControlSetActive(identifyEventControl); }
/*! State Machine handlers implementation */ static CommissioningState_t StartCommissioning(void) { emberAfDebugPrintln("DEBUG: Commissioning Start"); // TODO: here we might add some sanity check like cluster existense // or something like that, but now just start commissioning process // init internal queue for processing several remote devices InitQueue(); SetNextEvent(SC_EZEV_CHECK_NETWORK); emberEventControlSetActive(StateMachineEvent); return SC_EZ_START; }
/** @brief Stack Status * * This function is called by the application framework from the stack status * handler. This callbacks provides applications an opportunity to be * notified of changes to the stack status and take appropriate action. The * return code from this callback is ignored by the framework. The framework * will always process the stack status after the callback returns. * * @param status Ver.: always */ boolean emberAfStackStatusCallback(EmberStatus status) { if (status == EMBER_NETWORK_UP) { emberEventControlSetInactive(networkEventControl); halPlayTune_P(happyTune, TRUE); } else if (status == EMBER_NETWORK_DOWN && emberNetworkState() == EMBER_NO_NETWORK) { emberEventControlSetActive(networkEventControl); } return FALSE; }
/*! Callback for Simple Descriptor Request */ static void ProcessServiceDiscovery( const EmberAfServiceDiscoveryResult *result) { // if we get a matche or a default response handle it // otherwise stop commissioning or go to the next incoming device if (emberAfHaveDiscoveryResponseStatus(result->status)) { EmberAfClusterList *discovered_clusters = (EmberAfClusterList *)result->responseData; // if our device requested to bind to server clusters (is_server parameter // during the SimpleCommissioningStart was FALSE) -> use inClusterList of // the incoming device's response // otherwise -> outClusterList (as our device has server clusters) const uint16_t *inc_clusters_arr = (dev_comm_session.is_server) ? discovered_clusters->outClusterList : discovered_clusters->inClusterList; // get correct lenght of the incoming clusters array const uint8_t inc_clusters_arr_len = (dev_comm_session.is_server) ? discovered_clusters->outClusterCount : discovered_clusters->inClusterCount; // init clusters skip mask length for further using InitRemoteSkipCluster(inc_clusters_arr_len); // check how much clusters our device wants to bind to uint8_t supported_clusters = CheckSupportedClusters(inc_clusters_arr, inc_clusters_arr_len); emberAfDebugPrintln("DEBUG: Supported clusters %d", supported_clusters); if (supported_clusters == 0) { // we should not do anything with that, just wait maybe another response // would come SetNextEvent(SC_EZEV_TIMEOUT); SetNextState(SC_EZ_WAIT_IDENT_RESP); emberEventControlSetDelayMS( StateMachineEvent, SIMPLE_COMMISSIONING_IDENTIFY_RESPONSE_WAIT_TIME()); } else { // update our incoming device structure with information about clusters SetInDevicesClustersInfo(inc_clusters_arr, inc_clusters_arr_len, supported_clusters); // Now we have all information about responded device's clusters // Start matching procedure for checking how much of them fit for our // device SetNextEvent(SC_EZEV_CHECK_CLUSTERS); SetNextState(SC_EZ_MATCH); emberEventControlSetActive(StateMachineEvent); } } else { // we should not do anything with that, just wait maybe another response // would come SetNextEvent(SC_EZEV_TIMEOUT); SetNextState(SC_EZ_WAIT_IDENT_RESP); emberEventControlSetDelayMS( StateMachineEvent, SIMPLE_COMMISSIONING_IDENTIFY_RESPONSE_WAIT_TIME()); } }
/*! Callback for IEEE address Request */ static void ProcessEUI64Discovery(const EmberAfServiceDiscoveryResult *result) { if (emberAfHaveDiscoveryResponseStatus(result->status)) { MatchDescriptorReq_t *in_dev = GetTopInDeviceDescriptor(); assert(in_dev != NULL); SetInConnEUI64Address((const uint8_t *)result->responseData); emberAfDebugPrint("DEBUG: EUI64 "); emberAfPrintLittleEndianEui64(in_dev->source_eui64); emberAfDebugPrintln(""); SetNextEvent(SC_EZEV_BIND); } emberEventControlSetActive(StateMachineEvent); }
/** @brief Tunnel Closed * * This function is called by the Tunneling client plugin whenever a server * sends a notification that it preemptively closed an inactive tunnel. * Servers are not required to notify clients of tunnel closures, so * applications cannot rely on this callback being called for all tunnels. * * @param tunnelId The ID of the tunnel that has been closed. Ver.: * always */ void emberAfPluginTunnelingClientTunnelClosedCallback(uint8_t tunnelId) { uint8_t tunnelIndex; emberAfDebugPrintln("CHF: ClientTunnelClosed:0x%x", tunnelId); tunnelIndex = findTunnelByTunnelId(tunnelId, CLIENT_TUNNEL); if (tunnelIndex != EM_AF_PLUGIN_COMMS_HUB_FUNCTION_NULL_TUNNEL_INDEX) { tunnels[tunnelIndex].state = CLOSED_TUNNEL; if (tunnelIndex == responsePendingIndex) { responsePendingIndex = EM_AF_PLUGIN_COMMS_HUB_FUNCTION_NULL_TUNNEL_INDEX; emberEventControlSetActive(emberAfPluginCommsHubFunctionTunnelEventControl); } } }
static CommissioningState_t CheckQuery(void) { emberAfDebugPrintln("DEBUG: Check query"); CommissioningState_t next_st = SC_EZ_UNKNOWN; if (GetQueueSize() != 0) { SetNextEvent(SC_EZEV_CHECK_CLUSTERS); next_st = SC_EZ_DISCOVER; } else { SetNextEvent(SC_EZEV_QUEUE_EMPTY); next_st = SC_EZ_BIND; } emberEventControlSetActive(StateMachineEvent); return next_st; }
/** @brief Tunnel Opened * * This function is called by the Tunneling client plugin whenever a tunnel is * opened. * * @param tunnelId The ID of the tunnel that has been opened. Ver.: * always * @param tunnelStatus The status of the request. Ver.: always * @param maximumIncomingTransferSize The maximum incoming transfer size of * the server. Ver.: always */ void emberAfPluginTunnelingClientTunnelOpenedCallback(uint8_t tunnelId, EmberAfPluginTunnelingClientStatus tunnelStatus, uint16_t maximumIncomingTransferSize) { emberAfDebugPrintln("CHF: ClientTunnelOpened:0x%x,0x%x,0x%2x", tunnelId, tunnelStatus, maximumIncomingTransferSize); if (responsePendingIndex != EM_AF_PLUGIN_COMMS_HUB_FUNCTION_NULL_TUNNEL_INDEX) { uint8_t tunnelIndex = responsePendingIndex; responsePendingIndex = EM_AF_PLUGIN_COMMS_HUB_FUNCTION_NULL_TUNNEL_INDEX; emberEventControlSetActive(emberAfPluginCommsHubFunctionTunnelEventControl); if (tunnelStatus == EMBER_AF_PLUGIN_TUNNELING_CLIENT_SUCCESS) { tunnels[tunnelIndex].tunnelId = tunnelId; tunnels[tunnelIndex].state = ACTIVE_TUNNEL; // Per GBCS v0.8 section 10.2.2, Devices supporting the Tunneling Cluster // as a Server shall have a MaximumIncomingTransferSize set to 1500 octets, // in line with the ZSE default. All Devices supporting the Tunneling // Cluster shall use this value in any RequestTunnelResponse command and // any RequestTunnel command. // // So rather than bring down the tunnel in the case when the maximumIncomingTransferSize // is less than 1500 we'll just log a warning message. if (maximumIncomingTransferSize < 1500) { emberAfPluginCommsHubFunctionPrintln("Warning: tunnel opened but MaximumIncomingTransferSize of server is %d but should be 1500", maximumIncomingTransferSize); } // providing as a stub for the user to re-send data if the tunnel was re-established while sending data // and other cases emberAfPluginCommsHubFunctionTunnelOpenedCallback(tunnels[tunnelIndex].remoteDeviceId); return; } // see if we can recover from the open failure if (handleRequestTunnelFailure(tunnelIndex, tunnelStatus)) { //Jira EMAPPFWKV2-1421: tunnel event handler will take care of retries and request again to setup tunnel, don't need to save //tunnelIndex in responsePendingIndex here, as response to tunnel request is already received. responsePendingIndex = EM_AF_PLUGIN_COMMS_HUB_FUNCTION_NULL_TUNNEL_INDEX; return; } } else { // The tunnel has opened but we no longer require it so close it emberAfPluginTunnelingClientCloseTunnel(tunnelId); } }
// Start the transmissions of a sequence of IR frames. The format must // be specified in the IR database entry. int halInfraredLedStart(HalInfraredLedDbFormat irDbFormat, const uint8_t *ird, uint8_t irdLen) { static uint8_t *irdPtrPrevious; static uint8_t irdLenPrevious; int iSta; // Is there a requests in progress? if ((irdPtrCurrent != 0) || (irdLenCurrent != 0)) { return 1; } irdPtrCurrent = (uint8_t *)ird; irdLenCurrent = irdLen; // Is the current request different from the previous? if ((ird != irdPtrPrevious) || (irdLen != irdLenPrevious)) { //This is a new format irdPtrPrevious = (uint8_t *)ird; irdLenPrevious = irdLen; // Always reset the toggle counter for the SIRD format if (irDbFormat == HAL_INFRARED_LED_DB_FORMAT_SIRD) { halInternalInfraredLedEmitToggleReset(); } } if (ird == 0) { // If the pointer is 0, irdLen shall be interpreted as the index. iSta = infraredLedDecodeIndex(irDbFormat, irdLen); } else { iSta = infraredLedDecodeData(irDbFormat, ird, irdLen); } if (iSta == 0) { reqStart = true; if (state == IDLE) { emberEventControlSetActive(halInfraredLedEventControl); } } return iSta; }
static bool buttonPress(uint8_t button, uint8_t state) { // ISR CONTEXT!!! static uint32_t timeMs; EmberEventControl* event; if (button == BUTTON0) { event = &buttonEvent0; } else if (button == BUTTON1) { event = &buttonEvent1; } else { return false; } if (state == BUTTON_PRESSED) { buttonPressDurationMs = 0; timeMs = halCommonGetInt32uMillisecondTick(); } else { buttonPressDurationMs = elapsedTimeInt32u(timeMs, halCommonGetInt32uMillisecondTick()); emberEventControlSetActive(*event); } return true; }
// Stop the ongoing sequence of IR transmissions and transmit the final // IR frame. The format must be specified in the IR database entry. int halInfraredLedStop(HalInfraredLedDbFormat irDbFormat, const uint8_t *ird, uint8_t irdLen) { int iSta; // Is it the current request that is stopped? if ((ird != irdPtrCurrent) || (irdLen != irdLenCurrent)) { return 1; } if (ird == 0) { // If the pointer is 0, irdLen shall be interpreted as the index. iSta = infraredLedDecodeIndex(irDbFormat, irdLen); } else { iSta = infraredLedDecodeData(irDbFormat, ird, irdLen); } if (iSta == 0) { reqStop = true; if (state == IDLE) { emberEventControlSetActive(halInfraredLedEventControl); } } return iSta; }
/** @brief Main Init * * This function is called from the application's main function. It gives the * application a chance to do any initialization required at system startup. * Any code that you would normally put into the top of the application's * main() routine should be put into this function. Note: No callback * in the Application Framework is associated with resource cleanup. If you * are implementing your application on a Unix host where resource cleanup is * a consideration, we expect that you will use the standard Posix system * calls, including the use of atexit() and handlers for signals such as * SIGTERM, SIGINT, SIGCHLD, SIGPIPE and so on. If you use the signal() * function to register your signal handler, please mind the returned value * which may be an Application Framework function. If the return value is * non-null, please make sure that you call the returned function from your * handler to avoid negating the resource cleanup of the Application Framework * itself. * */ void emberAfMainInitCallback(void) { emberEventControlSetActive(networkEventControl); }
void initAndRunMainLoop(void) { EmberEventControl dataReportControl; EmberStatus status; int counter_reset = 0; emberTaskEnableIdling(true); emAppTask = emberTaskInit(emAppEvents); // Initialize the radio and the stack. If this fails, we have to assert // because something is wrong. status = emberInit(); emberSerialPrintfLine(COM_USART2, "Inititialization: 0x%x", status); //ember success;0x00 so emberinit worked assert(status == EMBER_SUCCESS); emberAfInit(); emberAfMainInitCallback(); //emberNetworkInit() called here emberResetNetworkState(); /////////////////leave network to join coordinator EmberNetworkStatus net_status; EmberNetworkParameters parameters; emberSetSecurityKey(&securityKey); MEMSET(¶meters, 0, sizeof(EmberNetworkParameters)); parameters.radioTxPower = 0; parameters.radioChannel = 1; parameters.panId = 0x01FF; halStackSeedRandom(halCommonGetInt32uMillisecondTick()); while (TRUE) { // Let the stack or EZSP layer run periodic tasks. emberTick(); // Let the application and plugins run periodic tasks. emberAfMainTickCallback(); emberAfTick(); emberEventControlSetActive(dataReportControl); net_status = emberNetworkState(); //emberResetNetworkState(); //emberJoinNetwork(EMBER_STAR_END_DEVICE, ¶meters); /* if(!emberStackIsUp()){ emberAfGuaranteedPrintln("stack wasn't up"); emberJoinNetwork(EMBER_STAR_END_DEVICE, ¶meters); } */ //emberAfGuaranteedPrintln("net_status is: %d", net_status); if(counter_reset == 10000){ emberResetNetworkState(); counter_reset = 0; } else{ counter_reset++; } if (net_status == EMBER_NO_NETWORK){ //emberPermitJoining(0xFF); //emberResetNetworkState(); emberAfGuaranteedPrintln("Network has been reset"); emberJoinNetwork(EMBER_STAR_END_DEVICE, ¶meters); } emberRunTask(emAppTask); } }
void emberAfPluginRf4ceZrc11OutgoingUserControlEventHandler(void) { emberEventControlSetActive(emberAfPluginRf4ceZrc11OutgoingUserControlEventControl); }
// Hal Button ISR Callback // This callback is called by the framework whenever a button is pressed on the // device. This callback is called within ISR context. void emberAfHalButtonIsrCallback(int8u button, int8u state) { if ((button == BUTTON0 || button == BUTTON1) && state == BUTTON_PRESSED) { emberEventControlSetActive(buttonEventControl); } }