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;
}
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;
}
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;
}
/** @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;
}
static CommissioningState_t StopCommissioning(void) {
  emberAfDebugPrintln("DEBUG: Stop commissioning");
  emberAfDebugPrintln("Current state is 0x%X", GetNextState());
  SetNextEvent(SC_EZEV_IDLE);
  // clean up globals
  ClearNetworkTries();

  return SC_EZ_STOP;
}
/*! 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);
}
Esempio n. 7
0
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);
}
Esempio n. 8
0
// This should be called from the Comms Hub Function Plugin Init callback.
void emAfPluginCommsHubFunctionTunnelInit(uint8_t localEndpoint)
{
  uint8_t i;

  emberAfDebugPrintln("CHF: TunnelInit");

  localTunnelEndpoint = localEndpoint;
  for (i = 0; i < EMBER_AF_PLUGIN_COMMS_HUB_FUNCTION_TUNNEL_LIMIT; i++) {
    tunnels[i].state = UNUSED_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.
  //
  // If the tunneling client's configured maximumIncomingTransferSize
  // is less than 1500 we'll log a warning.
  //
  // See equivalent check in emberAfPluginTunnelingClientTunnelOpenedCallback()
  if (EMBER_AF_PLUGIN_TUNNELING_CLIENT_MAXIMUM_INCOMING_TRANSFER_SIZE < 1500) {
    emberAfPluginCommsHubFunctionPrintln("WARN: Tunneling Client MaximumIncomingTransferSize is %d but should be 1500",
                                         EMBER_AF_PLUGIN_TUNNELING_CLIENT_MAXIMUM_INCOMING_TRANSFER_SIZE);
  }
}
static CommissioningState_t FormJoinNetwork(void) {
  emberAfDebugPrintln("DEBUG: Form/Join network");
  // Form or join depends on the device type
  // Coordinator: form a network
  // Router/ZED/SED/MED: find a network
  EmberStatus status = EMBER_SUCCESS;

  if (emAfCurrentZigbeeProNetwork->nodeType == EMBER_COORDINATOR) {
    status = emberAfFindUnusedPanIdAndForm();
  }
  else {
    status = emberAfStartSearchForJoinableNetwork();
  }

  if (status != EMBER_SUCCESS) {
    SetNextEvent(SC_EZEV_UNKNOWN);
  }
  else {
    SetNextEvent(SC_EZEV_CHECK_NETWORK);
  }

  IncNetworkTries();
  // run state machine again after 10 seconds
  emberEventControlSetDelayQS(StateMachineEvent,
                              SIMPLE_COMMISSIONING_NETWORK_CHECK_RETRY_TIME);

  return SC_EZ_START;
}
static CommissioningState_t CheckClusters(void) {
  emberAfDebugPrintln("DEBUG: Check Clusters handler");
  // ask a responded device for providing with info about clusters and call
  // the callback
  MatchDescriptorReq_t *in_dev = GetTopInDeviceDescriptor();
  assert(in_dev != NULL);
  emberAfDebugPrintln("DEBUG: short ID 0x%2X", in_dev->source);
  emberAfDebugPrintln("DEBUG: ep 0x%X", in_dev->source_ep);
  EmberStatus status = emberAfFindClustersByDeviceAndEndpoint(
      in_dev->source, in_dev->source_ep, ProcessServiceDiscovery);

  // Nothing to do here with states as the next event will become clear
  // during the ProcessServiceDiscovery callback call
  SetNextEvent(SC_EZEV_UNKNOWN);

  return (status != EMBER_SUCCESS) ? SC_EZ_UNKNOWN : SC_EZ_DISCOVER;
}
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;
}
static CommissioningState_t UnknownState(void) {
  emberAfDebugPrintln("DEBUG: Unknown operation requested on stage 0x%X",
                      GetNextState());
  // don't want to do anything here, just clean up to the initial state
  // {EZ_STOP, EZEV_IDLE}
  SetNextEvent(SC_EZEV_IDLE);

  return SC_EZ_STOP;
}
/*! Helper inline function for setting an incoming connection info
    during the Identify Query Response
*/
static inline void SetInConnBaseInfo(const EmberNodeId short_id,
                                     const uint8_t endpoint) {
  // try to add the new remote device descriptor to the queue
  if (!AddInDeviceDescriptor(short_id, endpoint)) {
    // queue is probably full
    emberAfDebugPrintln(
        "DEBUG: WARNING: incoming device response will be missed");
  }
}
Esempio n. 14
0
static void colorControlSetColorModeToZero(void)
{
#ifdef ZCL_USING_COLOR_CONTROL_CLUSTER_COLOR_CONTROL_COLOR_MODE_ATTRIBUTE
  // Set the optional Color Mode attribute to zero as per the spec.  If an
  // error occurs, log it, but ignore it.
  uint8_t colorMode = 0;
  EmberAfStatus status = emberAfWriteServerAttribute(emberAfCurrentEndpoint(),
                                                     ZCL_COLOR_CONTROL_CLUSTER_ID, 
                                                     ZCL_COLOR_CONTROL_COLOR_MODE_ATTRIBUTE_ID, 
                                                     &colorMode,
                                                     ZCL_ENUM8_ATTRIBUTE_TYPE);
  if (status != EMBER_ZCL_STATUS_SUCCESS) {
    emberAfColorControlClusterPrintln("ERR: writing color mode%x", status);
  }
  emberAfDebugPrintln("colorMode=%x", colorMode); emberAfColorControlClusterFlush();
#else
  emberAfDebugPrintln("no color mode attribute"); emberAfColorControlClusterFlush();
#endif //ZCL_USING_COLOR_CONTROL_CLUSTER_COLOR_CONTROL_COLOR_MODE_ATTRIBUTE
}
Esempio n. 15
0
void emAfPluginCommsHubFunctionTunnelClose(EmberEUI64 remoteDeviceId)
{
  uint8_t tunnelId;
  tunnelId = findTunnelByDeviceId(remoteDeviceId);
  emberAfDebugPrintln("CHF: TunnelClosed:0x%x", tunnelId);

  if (tunnelId != EM_AF_PLUGIN_COMMS_HUB_FUNCTION_NULL_TUNNEL_INDEX) {
    tunnels[tunnelId].state = CLOSED_TUNNEL;
  }
}
/*! 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;
}
Esempio n. 17
0
/** @brief Tunnel Closed
 *
 * This function is called by the Tunneling server plugin whenever a tunnel is
 * closed.  Clients may close tunnels by sending a Close Tunnel command.  The
 * server can preemptively close inactive tunnels after a timeout.
 *
 * @param tunnelId The identifier of the tunnel that has been closed.  Ver.:
 * always
 * @param clientInitiated true if the client initiated the closing of the tunnel
 * or false if the server closed the tunnel due to inactivity.  Ver.: always
 */
void emberAfPluginTunnelingServerTunnelClosedCallback(uint16_t tunnelId,
                                                      bool clientInitiated) 
{
  uint8_t tunnelIndex;
  emberAfDebugPrintln("CHF: ServerTunnelClosed:0x%x", tunnelId);

  tunnelIndex = findTunnelByTunnelId(tunnelId, SERVER_TUNNEL);
  if (tunnelIndex != EM_AF_PLUGIN_COMMS_HUB_FUNCTION_NULL_TUNNEL_INDEX) {
    tunnels[tunnelIndex].state = CLOSED_TUNNEL;
  }
}
/*! 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());
  }
}
Esempio n. 19
0
// 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;
}
/*! 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);
}
Esempio n. 21
0
// Sets the hue attribute
static void colorControlSetHue(uint8_t endpoint, uint8_t hue)
{
  EmberAfStatus status = emberAfWriteServerAttribute(endpoint,
                                                     ZCL_COLOR_CONTROL_CLUSTER_ID,
                                                     ZCL_COLOR_CONTROL_CURRENT_HUE_ATTRIBUTE_ID,
                                                     (uint8_t *)&hue,
                                                     ZCL_INT8U_ATTRIBUTE_TYPE);
  if (status != EMBER_ZCL_STATUS_SUCCESS) {
    emberAfColorControlClusterPrintln("ERR: writing current hue %x", status); emberAfColorControlClusterFlush();
    return;
  }
  emberAfDebugPrintln("hue=%x", hue);
}
Esempio n. 22
0
/** @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);
    }
  }
}
Esempio n. 23
0
// Sets the saturation attribute
static void colorControlSetSaturation(uint8_t endpoint, uint8_t saturation)
{
  EmberAfStatus status = emberAfWriteServerAttribute(endpoint,
                                                     ZCL_COLOR_CONTROL_CLUSTER_ID,
                                                     ZCL_COLOR_CONTROL_CURRENT_SATURATION_ATTRIBUTE_ID,
                                                     (uint8_t *)&saturation,
                                                     ZCL_INT8U_ATTRIBUTE_TYPE);
  if (status != EMBER_ZCL_STATUS_SUCCESS) {
    emberAfColorControlClusterPrintln("ERR: writing current saturation %x",
                                      status);
    return;
  }
  emberAfDebugPrintln("saturation=%x", saturation); 
}
Esempio n. 24
0
bool emAfPluginCommsHubFunctionTunnelSendData(EmberEUI64 remoteDeviceId,
                                                 uint16_t headerLen,
                                                 uint8_t *header,
                                                 uint16_t dataLen,
                                                 uint8_t *data)
{
  EmberAfStatus status = EMBER_ZCL_STATUS_FAILURE;
  bool success;
  uint8_t tunnelIndex;

  emberAfDebugPrint("CHF: TunnelSendData ");
  emberAfDebugDebugExec(emberAfPrintBigEndianEui64(remoteDeviceId));
  emberAfDebugPrint(" [");
  emberAfDebugPrintBuffer(header, headerLen, false);
  emberAfDebugPrintBuffer(data, dataLen, false);
  emberAfDebugPrintln("]");

  tunnelIndex = findTunnelByDeviceId(remoteDeviceId);
  if (tunnelIndex != EM_AF_PLUGIN_COMMS_HUB_FUNCTION_NULL_TUNNEL_INDEX) {
    if (tunnels[tunnelIndex].state == ACTIVE_TUNNEL) {
      // Add the header to the output buffers to that we don't copy data twice
      if (headerLen > 0) {
        MEMCOPY(message, header, headerLen);
        MEMCOPY(message+headerLen, data, dataLen);
        data = message;
        dataLen += headerLen;
      }
      status = (tunnels[tunnelIndex].type == CLIENT_TUNNEL)
        ? emberAfPluginTunnelingClientTransferData(tunnels[tunnelIndex].tunnelId, data, dataLen)
        : emberAfPluginTunnelingServerTransferData(tunnels[tunnelIndex].tunnelId, data, dataLen);
    } else if (tunnels[tunnelIndex].state == CLOSED_TUNNEL) {
      // we'll return failure to this message but we'll start the process
      // of bring up the tunnel so that if the message is resent the tunnel
      // should be up.
      emberAfPluginCommsHubFunctionPrintln("Tunnel Closed: New tunnel is requested for the device.");
      requestTunnel(tunnelIndex);
    }
  }

  success = (status == EMBER_ZCL_STATUS_SUCCESS);
  if (!success) {
    emberAfPluginCommsHubFunctionPrintln("%p%p%p0x%x",
                                         "Error: ",
                                         "Tunnel SendData failed: ",
                                         "Tunneling Status: ",
                                         status);

  }
  return success;
}
static bool CreateBindings(const MatchDescriptorReq_t *const in_dev) {
  // here we add bindings to the binding table
  EmberStatus status = EMBER_SUCCESS;

  for (size_t i = 0; i < in_dev->source_cl_arr_len; ++i) {
    if (!IsSkipCluster(i)) {
      uint8_t bindex = FindUnusedBindingIndex();

      if (bindex == EMBER_APPLICATION_ERROR_0 ||
          bindex == EMBER_APPLICATION_ERROR_1) {
        // error during finding an available binding table index for write to
        // Check query in that case
        // TODO: handle error
        return false;
      }

      EmberBindingTableEntry new_binding;
      InitBindingTableEntry(in_dev->source_eui64, in_dev->source_cl_arr[i],
                            in_dev->source_ep, &new_binding);
      status = emberSetBinding(bindex, &new_binding);
      if (status == EMBER_SUCCESS) {
        // Set up the remote short ID for binding for avoiding ZDO broadcast
        emberSetBindingRemoteNodeId(bindex, in_dev->source);
      }
      // DEBUG
      emberGetBinding(bindex, &new_binding);
      emberAfDebugPrintln("DEBUG: remote ep 0x%X", new_binding.remote);
      emberAfDebugPrintln("DEBUG: cluster id 0x%X%X",
                          HIGH_BYTE(new_binding.clusterId),
                          LOW_BYTE(new_binding.clusterId));
    }
  }

  // all bindings successfully added
  return true;
}
Esempio n. 26
0
/** @brief Data Received
 *
 * This function is called by the Tunneling server plugin whenever data is
 * received from a client through a tunnel.
 *
 * @param tunnelId The identifier of the tunnel through which the data was
 * received.  Ver.: always
 * @param data Buffer containing the raw octets of the data.  Ver.: always
 * @param dataLen The length in octets of the data.  Ver.: always
 */
void emberAfPluginTunnelingServerDataReceivedCallback(uint16_t tunnelId,
                                                      uint8_t * data,
                                                      uint16_t dataLen)
{
  uint8_t tunnelIndex;
  emberAfDebugPrint("CHF: ServerDataReceived:%x,[", tunnelId);
  emberAfDebugPrintBuffer(data, dataLen, false);
  emberAfDebugPrintln("]");

  tunnelIndex = findTunnelByTunnelId(tunnelId, SERVER_TUNNEL);
  if (tunnelIndex != EM_AF_PLUGIN_COMMS_HUB_FUNCTION_NULL_TUNNEL_INDEX) {
    emAfPluginCommsHubFunctionTunnelDataReceivedCallback(tunnels[tunnelIndex].remoteDeviceId,
                                                         dataLen,
                                                         data);
  }
}
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;
}
Esempio n. 28
0
/** @brief Is Protocol Supported
 *
 * This function is called by the Tunneling server plugin whenever a Request
 * Tunnel command is received.  The application should return true if the
 * protocol is supported and false otherwise.
 *
 * @param protocolId The identifier of the metering communication protocol for
 * which the tunnel is requested.  Ver.: always
 * @param manufacturerCode The manufacturer code for manufacturer-defined
 * protocols or 0xFFFF in unused.  Ver.: always
 */
bool emberAfPluginTunnelingServerIsProtocolSupportedCallback(uint8_t protocolId,
                                                                uint16_t manufacturerCode)
{
  EmberEUI64 remoteDeviceId;

  emberAfDebugPrintln("CHF: ServerIsProtocolSupported:0x%x 0x%2x", protocolId, manufacturerCode);

  // Since the tunneling cluster server code does not pass the EUI64 or the
  // node ID of the remote end of the tunnel so we need to look them up.
  // Luckily this callback is called in the context of the RequestTunnel
  // command processing and we look into the command for this info.
  emberLookupEui64ByNodeId(emberAfCurrentCommand()->source, remoteDeviceId);

  return (GBCS_TUNNELING_PROTOCOL_ID == protocolId
          && GBCS_TUNNELING_MANUFACTURER_CODE == manufacturerCode
          && emAfPluginCommsHubFunctionTunnelAcceptCallback(remoteDeviceId));
}
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;
}
Esempio n. 30
0
void emAfPluginCommsHubFunctionTunnelCleanup(EmberEUI64 remoteDeviceId)
{
  uint8_t tunnelIndex;

  tunnelIndex = findTunnelByDeviceId(remoteDeviceId);
  if (tunnelIndex < EMBER_AF_PLUGIN_COMMS_HUB_FUNCTION_TUNNEL_LIMIT) {
    emberAfDebugPrint("CHF: TunnelCleanup ");
    emberAfDebugDebugExec(emberAfPrintBigEndianEui64(remoteDeviceId));
    emberAfDebugPrintln("");

    if (tunnels[tunnelIndex].type == CLIENT_TUNNEL) {
      emberAfPluginTunnelingClientCleanup(tunnels[tunnelIndex].tunnelId);
    } else {
      emberAfPluginTunnelingServerCleanup(tunnels[tunnelIndex].tunnelId);
    }
    tunnels[tunnelIndex].state = UNUSED_TUNNEL;
  }
}