bool emberAfPluginUpdateTcLinkKeyStatusCallback(EmberKeyStatus keyStatus) { if (emAfPluginNetworkSteeringStateUpdateTclk()) { emberAfCorePrintln("%p: %p: 0x%X", PLUGIN_NAME, "Trust center link key update status", keyStatus); switch(keyStatus) { case EMBER_TRUST_CENTER_LINK_KEY_ESTABLISHED: // Success! But we should still wait to make sure we verify the key. emAfPluginNetworkSteeringStateSetVerifyTclk(); emberEventControlSetDelayMS(finishSteeringEvent, VERIFY_KEY_TIMEOUT_MS); return false; case EMBER_TRUST_CENTER_IS_PRE_R21: case EMBER_VERIFY_LINK_KEY_SUCCESS: // If the trust center is pre-r21, then we don't update the link key. // If the key status is that the link key has been verified, then we // have successfully updated our trust center link key and we are done! emAfPluginNetworkSteeringStateClearVerifyTclk(); emberEventControlSetDelayMS(finishSteeringEvent, randomJitterMS()); break; default: // Failure! emberLeaveNetwork(); cleanupAndStop(EMBER_NO_LINK_KEY_RECEIVED); } emAfPluginNetworkSteeringStateClearUpdateTclk(); } return true; }
/*! 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()); } }
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); } }
void halLedBlinkPattern( uint8_t count, uint8_t length, uint16_t *pattern) { uint8_t i; if (length < 2) { return; } turnLedOn(activeLed); ledEventState = LED_BLINK_PATTERN; if (length > MAX_BLINK_PATTERN_LENGTH) { length = MAX_BLINK_PATTERN_LENGTH; } blinkPatternLength = length; ledBlinkCount = count; for(i=0; i<blinkPatternLength; i++) { blinkPattern[i] = pattern[i]; } emberEventControlSetDelayMS(emberAfPluginLedBlinkLedEventFunctionEventControl, blinkPattern[0]); blinkPatternPointer = 1; }
void halLedBlinkBlink( uint8_t count, uint16_t blinkTime) { ledBlinkTime = blinkTime; turnLedOff(activeLed); ledEventState = LED_BLINKING_OFF; emberEventControlSetDelayMS(emberAfPluginLedBlinkLedEventFunctionEventControl, ledBlinkTime); ledBlinkCount = count; }
// Tunnel event handler used to retry previously attempted tunnel creations void emberAfPluginCommsHubFunctionTunnelEventHandler(void) { uint8_t tunnelIndex; uint32_t timeNowMs; uint32_t nearestEventTimeoutDelayMs = UINT32_MAX; uint32_t currentTunnelTimeoutMs = 0; emberEventControlSetInactive(emberAfPluginCommsHubFunctionTunnelEventControl); timeNowMs = halCommonGetInt32uMillisecondTick(); emberAfPluginCommsHubFunctionPrintln("CHF: emberAfPluginCommsHubFunctionTunnelEventHandler"); // If we're no longer waiting for a tunnel to come up then find which tunnel // (or tunnels) are ready for another attempt at tunnel creation if (responsePendingIndex == EM_AF_PLUGIN_COMMS_HUB_FUNCTION_NULL_TUNNEL_INDEX) { for (tunnelIndex=0; tunnelIndex<EMBER_AF_PLUGIN_COMMS_HUB_FUNCTION_TUNNEL_LIMIT; tunnelIndex++) { if (tunnels[tunnelIndex].type == CLIENT_TUNNEL && tunnels[tunnelIndex].state == REQUEST_PENDING_TUNNEL) { // JIRA EMAPPFWKV2-1392: Event handler was not registered and was not working properly // if timeout time has passed, then request a tunnel, else retry after least time remaining if (timeGTorEqualInt32u(timeNowMs, tunnels[tunnelIndex].timeoutMSec)) { emberAfPluginCommsHubFunctionPrintln("Retrying tunnel creation to node ID 0x%2x", tunnels[tunnelIndex].remoteNodeId); if (requestTunnel(tunnelIndex)) { emberEventControlSetDelayMS(emberAfPluginCommsHubFunctionTunnelEventControl, MILLISECOND_TICKS_PER_SECOND); return; } } else { currentTunnelTimeoutMs = elapsedTimeInt32u(timeNowMs, tunnels[tunnelIndex].timeoutMSec); if (currentTunnelTimeoutMs < nearestEventTimeoutDelayMs) { nearestEventTimeoutDelayMs = currentTunnelTimeoutMs; } } } } } if (nearestEventTimeoutDelayMs != MAX_INT32U_VALUE) { emberEventControlSetDelayMS(emberAfPluginCommsHubFunctionTunnelEventControl, nearestEventTimeoutDelayMs); } }
// State machine used to debounce the gpio sensor. This function is called on // every transition of the gpio sensor's GPIO pin. A delayed event is used to // take action on the pin transition. If the pin changes back to its original // state before the delayed event can execute, that change is marked as a bounce // and no further action is taken. static void sensorStateChangeDebounce(HalGpioSensorState status) { if (status == lastSensorStatus) { // we went back to last status before debounce. don't send the // message. emberEventControlSetInactive(emberAfPluginGpioSensorDebounceEventControl); return; } if (status == HAL_GPIO_SENSOR_ACTIVE) { newSensorStatus = status; emberEventControlSetDelayMS(emberAfPluginGpioSensorDebounceEventControl, SENSOR_ASSERT_DEBOUNCE); return; } else if (status == HAL_GPIO_SENSOR_NOT_ACTIVE) { newSensorStatus = status; emberEventControlSetDelayMS(emberAfPluginGpioSensorDebounceEventControl, SENSOR_DEASSERT_DEBOUNCE); return; } }
// Shut down for good after the user says it's OK and runs any last-minute logic static void lvShutdown(void) { uint16_t shutdownVoltage = emberAfPluginLowVoltageShutdownGetVoltage(); if (emberAfPluginLowVoltageShutdownOkToShutdownCallback(shutdownVoltage)) { emberAfPluginLowVoltageShutdownPreShutdownCallback(shutdownVoltage); halPowerDown(); halInternalSleep(SLEEPMODE_NOTIMER); } else { // User won't let us shut down yet, so check back after a brief interval emberEventControlSetDelayMS(myEvent, EMBER_AF_PLUGIN_LOW_VOLTAGE_SHUTDOWN_SHUTDOWN_POSTPONE_DURATION_MS); } }
// This is the state machine that emits one frame at a time according to the // format in the ir-database. It is controlled by the halInfraredLedStart and // halInfraredLedStop functions and the event set by itself - only. void halInfraredLedEventHandler(void) { uint32_t delayMs; emberEventControlSetInactive(halInfraredLedEventControl); switch(state) { case IDLE: if (reqStart) { state = START; emberEventControlSetDelayMS( halInfraredLedEventControl, 1); } else if (reqStop) { state = STOP; emberEventControlSetDelayMS( halInfraredLedEventControl, 1); } break; case START: reqStart = false; halInternalInfraredLedEmitPress(); repeateCount = halInternalInfraredLedEmitHeader.uRepeatCount; if (repeateCount > 0) { repeateCount--; } state = REPEATE; delayMs = irGetDelayToNextFrameInMs(irRepeateIntervalInMs); emberEventControlSetDelayMS(halInfraredLedEventControl, delayMs); break; case REPEATE: if (repeateCount > 0) { repeateCount--; halInternalInfraredLedEmitRepeat(); delayMs = irGetDelayToNextFrameInMs( irRepeateIntervalInMs); emberEventControlSetDelayMS( halInfraredLedEventControl, delayMs); } else if (reqStop) { state = STOP; emberEventControlSetDelayMS(halInfraredLedEventControl, 1); } else if (halInternalInfraredLedEmitHeader.bRepeatMode) { halInternalInfraredLedEmitRepeat(); delayMs = irGetDelayToNextFrameInMs(irRepeateIntervalInMs); emberEventControlSetDelayMS(halInfraredLedEventControl, delayMs); } else { state = IDLE; } break; case STOP: halInternalInfraredLedEmitRelease(); halInternalInfraredLedEmitToggleStepToNext(); reqStop = false; state = IDLE; irdPtrCurrent = NULL; irdLenCurrent = 0; break; } }
void identifyEventHandler(void) { if (identifyDurationMs == 0) { halClearLed(LED); emberEventControlSetInactive(identifyEventControl); } else { halToggleLed(LED); if (identifyDurationMs >= MILLISECOND_TICKS_PER_QUARTERSECOND) { identifyDurationMs -= MILLISECOND_TICKS_PER_QUARTERSECOND; } else { identifyDurationMs = 0; } emberEventControlSetDelayMS(identifyEventControl, MILLISECOND_TICKS_PER_QUARTERSECOND); } }
void buttonEventHandler(void) { emberEventControlSetInactive(buttonEventControl); if (halButtonState(BUTTON0) == BUTTON_PRESSED) { EmberNetworkStatus state = emberNetworkState(); if (state == EMBER_JOINED_NETWORK) { emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_CLIENT_TO_SERVER), ZCL_ON_OFF_CLUSTER_ID, (on ? ZCL_OFF_COMMAND_ID : ZCL_ON_COMMAND_ID), ""); emberAfGetCommandApsFrame()->profileId = emberAfPrimaryProfileId(); emberAfGetCommandApsFrame()->sourceEndpoint = emberAfPrimaryEndpoint(); emberAfGetCommandApsFrame()->destinationEndpoint = EMBER_BROADCAST_ENDPOINT; if (emberAfSendCommandUnicastToBindings() == EMBER_SUCCESS) { on = !on; } else { halPlayTune_P(sadTune, TRUE); } } else if (state == EMBER_NO_NETWORK) { halPlayTune_P((emberAfStartSearchForJoinableNetwork() == EMBER_SUCCESS ? waitTune : sadTune), TRUE); } else { if (REPAIR_LIMIT_MS < elapsedTimeInt16u(buttonPressTime, halCommonGetInt16uMillisecondTick())) { halPlayTune_P(sadTune, TRUE); } else { if (state == EMBER_JOINED_NETWORK_NO_PARENT && !emberStackIsPerformingRejoin()) { halPlayTune_P((emberFindAndRejoinNetwork(TRUE, 0) == EMBER_SUCCESS ? waitTune : sadTune), TRUE); } emberEventControlSetDelayMS(buttonEventControl, REPAIR_DELAY_MS); } } } else if (halButtonState(BUTTON1) == BUTTON_PRESSED) { emberAfEzmodeClientCommission(emberAfPrimaryEndpoint(), EMBER_AF_EZMODE_COMMISSIONING_CLIENT_TO_SERVER, clusterIds, COUNTOF(clusterIds)); } }
void emberAfPluginNetworkSteeringStackStatusCallback(EmberStatus status) { if (emAfPluginNetworkSteeringState == EMBER_AF_PLUGIN_NETWORK_STEERING_STATE_NONE) { return; } else if (status == EMBER_NETWORK_UP) { emberAfCorePrintln("%p network joined.", PLUGIN_NAME); if (!emAfPluginNetworkSteeringStateUsesDistributedKey() && !(emAfPluginNetworkSteeringOptionsMask & EMBER_AF_PLUGIN_NETWORK_STEERING_OPTIONS_NO_TCLK_UPDATE)) { emAfPluginNetworkSteeringStateSetUpdateTclk(); } emberEventControlSetDelayMS(finishSteeringEvent, randomJitterMS()); return; } tryToJoinNetwork(); }
static CommissioningState_t MatchingCheck(void) { emberAfDebugPrintln("DEBUG: Matching Check"); MatchDescriptorReq_t *in_dev = GetTopInDeviceDescriptor(); assert(in_dev != NULL); EmberStatus status = emberAfFindIeeeAddress(in_dev->source, ProcessEUI64Discovery); if (status == EMBER_SUCCESS) { SetNextEvent(SC_EZEV_AWAIT_EUI64); } else { SetNextEvent(SC_EZEV_CHECK_QUEUE); } // await for EUI64 response emberEventControlSetDelayMS(StateMachineEvent, SIMPLE_COMMISSIONING_EUI64_RESPONSE_WAIT_TIME()); return SC_EZ_BIND; }
void buttonEventHandler(void) { emberEventControlSetInactive(buttonEventControl); EmberNetworkStatus state = emberNetworkState(); if (state == EMBER_JOINED_NETWORK) { emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_CLIENT_TO_SERVER), ZCL_ON_OFF_CLUSTER_ID, (on ? ZCL_OFF_COMMAND_ID : ZCL_ON_COMMAND_ID), ""); emberAfGetCommandApsFrame()->profileId = emberAfProfileIdFromIndex(0); emberAfGetCommandApsFrame()->sourceEndpoint = emberAfEndpointFromIndex(0); emberAfGetCommandApsFrame()->destinationEndpoint = EMBER_BROADCAST_ENDPOINT; if (emberAfSendCommandBroadcast(EMBER_SLEEPY_BROADCAST_ADDRESS) == EMBER_SUCCESS) { on = !on; } else { halPlayTune_P(sadTune, TRUE); } } else if (state == EMBER_NO_NETWORK) { halPlayTune_P((emberAfZllInitiateTouchLink() == EMBER_SUCCESS ? waitTune : sadTune), TRUE); } else { int16u elapsed = elapsedTimeInt16u(buttonPressTime, halCommonGetInt16uMillisecondTick()); if (REPAIR_LIMIT_MS < elapsedTimeInt16u(buttonPressTime, halCommonGetInt16uMillisecondTick())) { halPlayTune_P(sadTune, TRUE); } else { if (state == EMBER_JOINED_NETWORK_NO_PARENT && !emberStackIsPerformingRejoin()) { halPlayTune_P((emberFindAndRejoinNetwork(TRUE, 0) == EMBER_SUCCESS ? waitTune : sadTune), TRUE); } emberEventControlSetDelayMS(buttonEventControl, REPAIR_DELAY_MS); } } }
static CommissioningState_t BroadcastIdentifyQuery(void) { emberAfDebugPrintln("DEBUG: Broadcast ID Query"); // Make Identify cluster's command to send an Identify Query emberAfFillCommandIdentifyClusterIdentifyQuery(); emberAfSetCommandEndpoints(dev_comm_session.ep, EMBER_BROADCAST_ENDPOINT); // Broadcast Identify Query EmberStatus status = emberAfSendCommandBroadcast(EMBER_SLEEPY_BROADCAST_ADDRESS); if (status != EMBER_SUCCESS) { // Exceptional case. Stop commissioning SetNextEvent(SC_EZEV_UNKNOWN); } // Schedule event for awaiting for responses for 1 second // TODO: Set hardcoded value as plugin's option parameter as optional value emberEventControlSetDelayMS(StateMachineEvent, SIMPLE_COMMISSIONING_IDENTIFY_RESPONSE_WAIT_TIME()); // If Identify Query responses won't be received state machine just will call // Timeout handler SetNextEvent(SC_EZEV_TIMEOUT); return SC_EZ_WAIT_IDENT_RESP; }
void emberZllScanCompleteHandler(EmberStatus status) { #ifdef EMBER_AF_PLUGIN_ZLL_COMMISSIONING_LINK_INITIATOR if (touchLinkInProgress()) { flags |= SCAN_COMPLETE; if (status != EMBER_SUCCESS) { emberAfAppPrintln("%p%p0x%x", "Error: ", "Touch linking failed: ", status); abortTouchLink(EMBER_AF_ZLL_PREEMPTED_BY_STACK); } else if (abortingTouchLink()) { abortTouchLink(EMBER_AF_ZLL_ABORTED_BY_APPLICATION); } else if (targetNetworkFound()) { EmberStatus status = setRadioChannel(network.zigbeeNetwork.channel); if (status != EMBER_SUCCESS) { emberAfAppPrintln("%p%p%p0x%x", "Error: ", "Touch linking failed: ", "could not change channel: ", status); abortTouchLink(EMBER_AF_ZLL_CHANNEL_CHANGE_FAILED); return; } // When scanning for the purposes of touch linking or requesting device // information and the target has more than one sub device, turn the // receiver on (so we can actually receive the response) and send out the // first request. If the target only has one sub device, its data will // have already been received in the ScanRequest. if ((scanForTouchLink() || scanForDeviceInformation()) && network.numberSubDevices != 1) { emberZllSetRxOnWhenIdle(EMBER_AF_PLUGIN_ZLL_COMMISSIONING_TOUCH_LINK_MILLISECONDS_DELAY); status = sendDeviceInformationRequest(0x00); // start index if (status != EMBER_SUCCESS) { emberAfAppPrintln("%p%p%p0x%x", "Error: ", "Touch linking failed: ", "could not send device information request: ", status); if (scanForDeviceInformation()) { abortTouchLink(EMBER_AF_ZLL_SENDING_DEVICE_INFORMATION_REQUEST_FAILED); return; } } } status = sendIdentifyRequest(emAfZllIdentifyDurationS); if (status != EMBER_SUCCESS) { emberAfAppPrintln("%p%p%p0x%x", "Error: ", "Touch linking failed: ", "could not send identify request: ", status); if (scanForIdentify()) { abortTouchLink(EMBER_AF_ZLL_SENDING_IDENTIFY_REQUEST_FAILED); return; } } emberEventControlSetDelayMS(emberAfPluginZllCommissioningTouchLinkEventControl, EMBER_AF_PLUGIN_ZLL_COMMISSIONING_TOUCH_LINK_MILLISECONDS_DELAY); } else { emberAfAppPrintln("%p%p%p", "Error: ", "Touch linking failed: ", "no networks were found"); abortTouchLink(EMBER_AF_ZLL_NO_NETWORKS_FOUND); } } #endif //EMBER_AF_PLUGIN_ZLL_COMMISSIONING_LINK_INITIATOR #ifdef EMBER_AF_PLUGIN_TEST_HARNESS_Z3 emAfPluginTestHarnessZ3ZllScanCompleteCallback(status); #endif }
//------------------------------------------------------------------------------ // Plugin event handlers void emberAfPluginLedBlinkLedEventFunctionEventHandler( void ) { switch(ledEventState) { case LED_ON: // was on. this must be time to turn it off. turnLedOff(activeLed); emberEventControlSetInactive(emberAfPluginLedBlinkLedEventFunctionEventControl); break; case LED_OFF: // was on. this must be time to turn it off. turnLedOn(activeLed); emberEventControlSetInactive(emberAfPluginLedBlinkLedEventFunctionEventControl); break; case LED_BLINKING_ON: turnLedOff(activeLed); if (ledBlinkCount > 0) { if (ledBlinkCount != 255) { // blink forever if count is 255 ledBlinkCount --; } if (ledBlinkCount > 0) { ledEventState = LED_BLINKING_OFF; emberEventControlSetDelayMS(emberAfPluginLedBlinkLedEventFunctionEventControl, ledBlinkTime); } else { ledEventState = LED_OFF; emberEventControlSetInactive(emberAfPluginLedBlinkLedEventFunctionEventControl); } } else { ledEventState = LED_BLINKING_OFF; emberEventControlSetDelayMS(emberAfPluginLedBlinkLedEventFunctionEventControl, ledBlinkTime); } break; case LED_BLINKING_OFF: turnLedOn(activeLed); ledEventState = LED_BLINKING_ON; emberEventControlSetDelayMS(emberAfPluginLedBlinkLedEventFunctionEventControl, ledBlinkTime); break; case LED_BLINK_PATTERN: if (ledBlinkCount == 0) { turnLedOff(activeLed); ledEventState = LED_OFF; emberEventControlSetInactive(emberAfPluginLedBlinkLedEventFunctionEventControl); break; } if (blinkPatternPointer %2 == 1) { turnLedOff(activeLed); } else { turnLedOn(activeLed); } emberEventControlSetDelayMS(emberAfPluginLedBlinkLedEventFunctionEventControl, blinkPattern[blinkPatternPointer]); blinkPatternPointer ++; if (blinkPatternPointer >= blinkPatternLength) { blinkPatternPointer = 0; if (ledBlinkCount != 255) { // blink forever if count is 255 ledBlinkCount --; } } default: break; } }