// gpio sensor Debounce Handler.  This event is used to provide a short,
// parameterized delay between the gpio sensor state initially changing and
// being verified as needing to take action.  In the case of a bounce scenario,
// this event will be cancelled by the debounce state machine before it can
// execute.
void emberAfPluginGpioSensorDebounceEventHandler(void)
{
  emberEventControlSetInactive(emberAfPluginGpioSensorDebounceEventControl);
  lastSensorStatus = newSensorStatus;

  emberAfPluginGpioSensorStateChangedCallback(newSensorStatus);
}
/*! State Machine function */
void emberAfPluginSimpleCommissioningInitiatorStateMachineEventHandler(void) {
  emberEventControlSetInactive(StateMachineEvent);
  // That might happened that ZigBee state machine changed current network
  // So, it is important to switch to the proper network before commissioning
  // state machine might start
  EmberStatus status = emberAfPushNetworkIndex(dev_comm_session.network_index);
  if (status != EMBER_SUCCESS) {
    // TODO: Handle unavailability of switching network
  }
  emberAfDebugPrintln("DEBUG: State Machine");
  // Get state previously set by some handler
  CommissioningState_t cur_state = GetNextState();
  CommissioningEvent_t cur_event = GetNextEvent();
  for (size_t i = 0; i < TRANSIT_TABLE_SIZE(); ++i) {
    if ((cur_state == sm_transition_table[i].state ||
         SC_EZ_UNKNOWN == sm_transition_table[i].state) &&
        ((cur_event == sm_transition_table[i].event) ||
         SC_EZEV_UNKNOWN == sm_transition_table[i].event)) {
      // call handler which set the next_state on return and
      // next_event inside itself
      SetNextState((sm_transition_table[i].handler)());
      break;
    }
  }

  // Don't forget to pop Network Index
  status = emberAfPopNetworkIndex();
  // sanity check that network switched back properly
  EMBER_TEST_ASSERT(status == EMBER_SUCCESS);
}
void emberAfPluginButtonJoiningButton0EventHandler(void)
{
  emberEventControlSetInactive(buttonEvent0);

	if (buttonPressDurationMs >= BUTTON_HOLD_DURATION_MS) {
    emberAfCorePrintln("Leaving network due to button press.");
		emberLeaveNetwork();
		return;
	}

  if (emberAfNetworkState() == EMBER_JOINED_NETWORK) {

		emberAfBroadcastPermitJoin(PERMIT_JOIN_TIMEOUT);

  } else if (emberAfNetworkState() == EMBER_NO_NETWORK) {

#ifdef EMBER_AF_HAS_COORDINATOR_NETWORK
    emberAfCorePrintln("%p: nwk down: do form", "button0");
    emberAfFindUnusedPanIdAndForm();
#else
    emberAfCorePrintln("%p: nwk down: do join", "button0");
    emberAfStartSearchForJoinableNetwork();
#endif

  }
}
void emberAfPluginFormAndJoinCleanupEventHandler(void)
{
  // This takes a bit of explaining.
  // Prior to this release the form-and-join library was not a plugin and was
  // hardcoded in the project templates, thus there was no way to turn it off.
  // We needed to be able to enable/disable it and so we made it into a plugin.

  // The Network Find was another plugin layered on top of the form-and-join library.
  // Any application that used form-and-join without the network-find plugin
  // would need to properly cleanup the form-and-join code.  On the SOC this
  // was done automatically by a timer that fired after 30 seconds, assuming
  // you called emberFormAndJoinTick() regularly.  On the host, there was nno
  // timer and thus an explicit call to emberFormAndJoinCleanup() was required.

  // Now if the network-find plugin was enabled it had its own cleanup 
  // (that also called emberFormAndJoinCleanup()), therefore it was
  // unnecessary to schedule an event.  

  // To maintain backwards compatibility we will run the cleanup code
  // only on SOC when it is not disabled by another piece of code 
  // (e.g. network-find plugin)
#if !defined(EMBER_AF_DISABLE_FORM_AND_JOIN_TICK) && !defined(EZSP_HOST)
  emberFormAndJoinCleanup(EMBER_SUCCESS);
#else
  // This is a workaround put in place to handle bug EMAPPFWKV2-1379.  There are
  // certain circumstances in which the CleanupEvent is set active while the
  // above #if conditions are not met.  This results in the eventHandler taking
  // no action, leaving the event in an active state.  The event then has no
  // means by which it can be made inactive, so the scheduler indefinitely
  // calls the empty event, which prevents the device from sleeping.
  emberEventControlSetInactive(emberAfPluginFormAndJoinCleanupEventControl);
#endif
}
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);
  }
}
// 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;
  }
}
// Event function stubs
void buttonEventHandler(void)
{
  if (emberAfRf4ceZrc11EnableAutoDiscoveryResponse() == EMBER_SUCCESS) {
    halPlayTune_P(waitTune, TRUE);
    halSetLed(LED);
  } else {
    halPlayTune_P(sadTune, TRUE);
  }
  emberEventControlSetInactive(buttonEventControl);
}
void networkEventHandler(void)
{
  if (emberAfRf4ceStart() == EMBER_SUCCESS) {
    emberEventControlSetInactive(networkEventControl);
    halPlayTune_P(waitTune, TRUE);
  } else {
    emberEventControlSetActive(networkEventControl);
    halPlayTune_P(sadTune, TRUE);
  }
}
/** @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;
}
Exemple #11
0
void halLedBlinkLedOff( uint8_t time )
{
  turnLedOff(activeLed);
  ledEventState = LED_OFF;

  if (time > 0) {
    emberEventControlSetDelayQS(emberAfPluginLedBlinkLedEventFunctionEventControl,
                                ((uint16_t) time) * 4);
  } else {
    emberEventControlSetInactive(emberAfPluginLedBlinkLedEventFunctionEventControl);
  }
}
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 emberAfPluginZllCommissioningTouchLinkEventHandler(void)
{
  emberEventControlSetInactive(emberAfPluginZllCommissioningTouchLinkEventControl);
#ifdef EMBER_AF_PLUGIN_ZLL_COMMISSIONING_LINK_INITIATOR
  if (touchLinkInProgress()) {
    EmberStatus status;

    sendIdentifyRequest(0x0000); // exit identify mode

    if (scanForTouchLink()) {
      // If we are not factory new, we want to bring the target into our
      // existing network, so we set the channel to our original channel.
      // Otherwise, we'll use whatever channel the target is on presently.
      if (!amFactoryNew()) {
        network.zigbeeNetwork.channel = channel;
      }
      emberAfZllSetInitialSecurityState();
      status = emberZllJoinTarget(&network);
      if (status != EMBER_SUCCESS) {
        emberAfAppPrintln("%p%p%p0x%x",
                          "Error: ",
                          "Touch linking failed: ",
                          "could not send start/join: ",
                          status);
        abortTouchLink(EMBER_AF_ZLL_SENDING_START_JOIN_FAILED);
        return;
      }
    } else {
      if (scanForReset()) {
        status = sendResetToFactoryNewRequest();
        if (status != EMBER_SUCCESS) {
          emberAfAppPrintln("%p%p%p0x%x",
                            "Error: ",
                            "Touch linking failed: ",
                            "could not send reset: ",
                            status);
          abortTouchLink(EMBER_AF_ZLL_SENDING_RESET_TO_FACTORY_NEW_REQUEST_FAILED);
          return;
        }
      }
      emberSetRadioChannel(channel);
      touchLinkComplete();
    }
  }
#endif //EMBER_AF_PLUGIN_ZLL_COMMISSIONING_LINK_INITIATOR
}
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);
    }
  }
}
// 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);
  }
}
void buttonEventHandler(void)
{
  // On a press-and-hold button event, form a network if we don't have one or
  // permit joining if we do.  If we form, we'll automatically permit joining
  // when we come up.
  emberEventControlSetInactive(buttonEventControl);
  if (halButtonState(BUTTON0) == BUTTON_PRESSED) {
    if (emberNetworkState() == EMBER_NO_NETWORK) {
      halPlayTune_P(((emberFormAndJoinIsScanning()
                      || emberAfFindUnusedPanIdAndForm() == EMBER_SUCCESS)
                     ? waitTune
                     : sadTune),
                    TRUE);
    } else {
      pjoin();
    }
  } else if (halButtonState(BUTTON1) == BUTTON_PRESSED) {
    emberAfEzmodeServerCommission(emberAfPrimaryEndpoint());
  }
}
Exemple #18
0
// 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;
  }
}
void emberAfPluginNetworkSteeringFinishSteeringEventHandler(void)
{
  EmberStatus status;

  emberEventControlSetInactive(finishSteeringEvent);

  if (emAfPluginNetworkSteeringStateVerifyTclk()) {
    // If we get here, then we have failed to verify the TCLK. Therefore,
    // we leave the network.
    emberAfPluginUpdateTcLinkKeyStop();
    emberLeaveNetwork();
    emberAfCorePrintln("%p: %p",
                       PLUGIN_NAME,
                       "Key verification failed. Leaving network");
    cleanupAndStop(EMBER_ERR_FATAL);
  } else if (emAfPluginNetworkSteeringStateUpdateTclk()) {
    // Start the process to update the TC link key. We will set another event
    // for the broadcast permit join.
    status = emberAfPluginUpdateTcLinkKeyStart();
    emberAfCorePrintln("%p: %p: 0x%X",
                       PLUGIN_NAME,
                       "Starting update trust center link key process",
                       status);
    if (status != EMBER_SUCCESS) {
      emberLeaveNetwork();
      cleanupAndStop(status);
    }
  } else {
    // Broadcast permit join to extend the network.
    // We are done!
    status = emberAfPermitJoin(EMBER_AF_PLUGIN_NETWORK_STEERING_COMMISSIONING_TIME_S,
                               true); // Broadcast permit join?
    emberAfCorePrintln("%p: %p: 0x%X",
                       PLUGIN_NAME,
                       "Broadcasting permit join",
                       status);
    cleanupAndStop(status);
  }
}
void buttonEventHandler(void)
{
  emberEventControlSetInactive(buttonEventControl);
  if (halButtonState(BUTTON0) == BUTTON_PRESSED) {
    EmberNetworkStatus state = emberNetworkState();
    if (state == EMBER_JOINED_NETWORK) {
      emberAfEzmodeClientCommission(emberAfPrimaryEndpoint(),
                                    EMBER_AF_EZMODE_COMMISSIONING_SERVER_TO_CLIENT,
                                    clusterIds,
                                    COUNTOF(clusterIds));
    } else if (state == EMBER_NO_NETWORK) {
      halPlayTune_P(((emberFormAndJoinIsScanning()
                      || (emberAfStartSearchForJoinableNetwork()
                          == EMBER_SUCCESS))
                     ? waitTune
                     : sadTune),
                    TRUE);
    }
  } else if (halButtonState(BUTTON1) == BUTTON_PRESSED) {
    emberAfEzmodeServerCommission(emberAfPrimaryEndpoint());
  }
}
static void abortTouchLink(EmberAfZllCommissioningStatus reason)
{
  flags = INITIAL;
#ifdef EMBER_AF_PLUGIN_ZLL_COMMISSIONING_LINK_INITIATOR
  if (emberEventControlGetActive(emberAfPluginZllCommissioningTouchLinkEventControl)) {
    emberEventControlSetInactive(emberAfPluginZllCommissioningTouchLinkEventControl);
    if (network.numberSubDevices != 1) {
      emberZllSetRxOnWhenIdle(0); // restore original idle mode
    }
    sendIdentifyRequest(0x0000); // exit identify mode
  }
  {
    EmberStatus status = emberSetRadioChannel(channel);
    if (status != EMBER_SUCCESS) {
      emberAfAppPrintln("%p%p0x%x",
                        "Error: ",
                        "could not restore channel: ",
                        status);
    }
  }
#endif //EMBER_AF_PLUGIN_ZLL_COMMISSIONING_LINK_INITIATOR
  emberAfPluginZllCommissioningTouchLinkFailedCallback(reason);
}
Exemple #22
0
// gpio sensor state change handler.  This is the handler for the event that is
// activated by the GIC plugin when an interrupt occurs on the gpio sensor.  It
// determines whether the button is asserted or deasserted based on the polarity
// option and GPIO state, and calls the appropriate assert or deassert handler.
void emberAfPluginGpioSensorInterruptEventHandler(void)
{
  uint8_t reedValue;

  emberEventControlSetInactive(emberAfPluginGpioSensorInterruptEventControl);
  
  reedValue = halGenericInterruptControlIrqReadGpio(irqConfig);
  
  // If the gpio sensor was set to active high by the plugin properties, call
  // deassert when the value is 0 and assert when the value is 1.
  if (SENSOR_IS_ACTIVE_HI) {
    if (reedValue == 0) {
      sensorDeassertedCallback();
    } else {
      sensorAssertedCallback();
    }
  } else {
    if (reedValue == 0) {
      sensorAssertedCallback();
    } else {
      sensorDeassertedCallback();
    }
  }
}
void emberAfPluginButtonJoiningButton1EventHandler(void)
{
	emberEventControlSetInactive(buttonEvent1);
	emberAfPluginButtonJoiningButtonEventCallback(1, // button 1 is pressed
                                                buttonPressDurationMs);  
}
void emberAfPluginDeviceQueryServiceEnableDisable(bool enable)
{
  enabled = enable;
  emberEventControlSetInactive(emberAfPluginDeviceQueryServiceMyEventControl);
}
void emberAfPluginDeviceQueryServiceMyEventHandler(void)
{
  emberEventControlSetInactive(emberAfPluginDeviceQueryServiceMyEventControl);
  debugPrintln("%p event", PLUGIN_NAME);
  const EmberAfDeviceInfo* device;
  if (emberAfMemoryByteCompare(currentEui64, EUI64_SIZE, 0xFF)) {
    debugPrintln("%p no current device being queried, looking in database for one.", PLUGIN_NAME);
    device = emberAfPluginDeviceDatabaseFindDeviceByStatus(EMBER_AF_DEVICE_DISCOVERY_STATUS_NEW
                                                           | EMBER_AF_DEVICE_DISCOVERY_STATUS_FIND_ENDPOINTS
                                                           | EMBER_AF_DEVICE_DISCOVERY_STATUS_FIND_CLUSTERS);
    if (device != NULL) {
      debugPrintln("%p found device with status (0x%X): %p",
                   PLUGIN_NAME,
                   device->status,
                   emberAfPluginDeviceDatabaseGetStatusString(device->status));
      if ((device->capabilities & RECEIVER_ON_WHEN_IDLE) == 0) {
        emberAfPluginDeviceDatabaseSetStatus(device->eui64, EMBER_AF_DEVICE_DISCOVERY_STATUS_DONE);
        debugPrintln("%p ignoring sleepy device.");
        scheduleEvent(RIGHT_NOW);
        return;

      } else {
        MEMMOVE(currentEui64, device->eui64, EUI64_SIZE);
      }
    }
  } else {
    device = emberAfPluginDeviceDatabaseFindDeviceByEui64(currentEui64);
    if (device == NULL) {
      emberAfCorePrint("Error: %p the current EUI64 does not correspond to any known device: ", PLUGIN_NAME);
      emberAfPrintLittleEndianEui64(currentEui64);
      emberAfCorePrintln("");
      clearCurrentDevice();
      scheduleEvent(WITH_DELAY);
      return;
    }
  }

  if (device == NULL) {
    clearCurrentDevice();

    if (emberAfPluginDeviceDatabaseClearAllFailedDiscoveryStatus(EMBER_AF_PLUGIN_DEVICE_QUERY_SERVICE_MAX_FAILURES)) {
      emberAfCorePrintln("%p Retrying failed discoveries.", PLUGIN_NAME);
      scheduleEvent(WITH_DELAY);
    } else {
      emberAfCorePrintln("%p All known devices discovered.", PLUGIN_NAME);
    }
    return;
  }

  // Although we could consult our local tables for addresses, we perform a broadcast
  // lookup here to insure that we have a current source route back to the destination.
  // The target of the discovery will unicast the result, along with a route record.
  if (currentNodeId == EMBER_NULL_NODE_ID) {
    debugPrint("%p initiating node ID discovery for: ", PLUGIN_NAME);
    debugPrintEui64(currentEui64);
    debugPrintln("");
    EmberStatus status = emberAfFindNodeId(currentEui64, serviceDiscoveryCallback);
    if (status != EMBER_SUCCESS) {
      emberAfCorePrintln("%p failed to initiate node ID discovery.", PLUGIN_NAME);
      noteFailedDiscovery(device);
      scheduleEvent(WITH_DELAY);
    }
    // Else
    //   Don't schedule event, since service discovery callback returns the results.
    return;
  }

  switch (device->status) {
    case EMBER_AF_DEVICE_DISCOVERY_STATUS_NEW:
    case EMBER_AF_DEVICE_DISCOVERY_STATUS_FIND_ENDPOINTS:
      sendActiveEndpointRequest(device);
    break;

    case EMBER_AF_DEVICE_DISCOVERY_STATUS_FIND_CLUSTERS:
      sendSimpleDescriptorRequest(device);
      break;

    default:
      break;
  }
}
static void serviceDiscoveryCallback(const EmberAfServiceDiscoveryResult* result)
{
  debugPrintln("%p serviceDiscoveryCallback()", PLUGIN_NAME);
  emberEventControlSetInactive(emberAfPluginDeviceQueryServiceMyEventControl);
  if (!enabled) {
    return;
  }

  const EmberAfDeviceInfo* device = emberAfPluginDeviceDatabaseFindDeviceByEui64(currentEui64);
  if (device == NULL) {
    emberAfCorePrint("Error:  %p could not find device in database with EUI64: ", PLUGIN_NAME);
    emberAfPrintLittleEndianEui64(currentEui64);
    emberAfCorePrintln("");
    clearCurrentDevice();
    scheduleEvent(WITH_DELAY);
    return;
  }

  if (!emberAfHaveDiscoveryResponseStatus(result->status)) {
    emberAfCorePrintln("Error: %p service discovery returned no results.", PLUGIN_NAME);
    noteFailedDiscovery(device);
    scheduleEvent(WITH_DELAY);
    return;

  } else if (result->zdoRequestClusterId == NETWORK_ADDRESS_REQUEST) {
    currentNodeId = result->matchAddress;
    emberAfPluginDeviceDatabaseSetStatus(device->eui64, EMBER_AF_DEVICE_DISCOVERY_STATUS_FIND_ENDPOINTS);
    scheduleEvent(RIGHT_NOW);

  } else if (result->zdoRequestClusterId == ACTIVE_ENDPOINTS_REQUEST) {
    const EmberAfEndpointList* listStruct = (const EmberAfEndpointList*)(result->responseData);
    debugPrintln("%p found %d active endpoints.", PLUGIN_NAME, listStruct->count);
    if (!emberAfPluginDeviceDatabaseSetEndpoints(device->eui64, 
                                                 listStruct->list,
                                                 listStruct->count)) {
      emberAfCorePrint("Error: %p failed to set endpoints in device database for:", PLUGIN_NAME);
      emberAfPrintLittleEndianEui64(device->eui64);
      emberAfCorePrintln("");
      noteFailedDiscovery(device);
      scheduleEvent(WITH_DELAY);

    } else {
      currentEndpointIndex = 0;
      emberAfPluginDeviceDatabaseSetStatus(device->eui64, EMBER_AF_DEVICE_DISCOVERY_STATUS_FIND_CLUSTERS);
      scheduleEvent(RIGHT_NOW);
    }

  } else if (result->zdoRequestClusterId == SIMPLE_DESCRIPTOR_REQUEST) {
    const EmberAfClusterList* clusterInfo = (const EmberAfClusterList*)result->responseData;
    debugPrintln("%p found %d server clusters and %d client clusters on EP %d",
                  PLUGIN_NAME,
                  clusterInfo->inClusterCount,
                  clusterInfo->outClusterCount,
                  clusterInfo->endpoint);
    if (!emberAfPluginDeviceDatabaseSetClustersForEndpoint(device->eui64,
                                                           clusterInfo)) {
      emberAfCorePrintln("Error: %p failed to set clusters for device.", PLUGIN_NAME);    
      noteFailedDiscovery(device);
      scheduleEvent(WITH_DELAY);
    } else {
      currentEndpointIndex++;
      scheduleEvent(RIGHT_NOW);
    }
  }
}
void emberAfStopMoveCallback(void)
{
  uint8_t networkIndex = emberGetCurrentNetwork();
  states[networkIndex].moveAttempts = 0;
  emberEventControlSetInactive(emberAfPluginEndDeviceSupportMoveNetworkEventControls[networkIndex]);
}
Exemple #28
0
//------------------------------------------------------------------------------
// 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;
  }
}