예제 #1
0
bool emberAfEventsClusterPublishEventCallback(uint8_t logId,
                                                 uint16_t eventId,
                                                 uint32_t eventTime,
                                                 uint8_t eventControl,
                                                 uint8_t* eventData)
{
  emberAfEventsClusterPrint("RX: PublishEvent 0x%x, 0x%2x, 0x%4x, 0x%x, 0x%x",
                            logId,
                            eventId,
                            eventTime,
                            eventControl,
                            *eventData);

#if defined(EMBER_AF_PRINT_ENABLE) && defined(EMBER_AF_PRINT_EVENTS_CLUSTER)
  uint8_t eventDataLen = emberAfStringLength(eventData);
  if (eventDataLen > 0) {
    emberAfEventsClusterPrint(", ");
    emberAfEventsClusterPrintString(eventData);
  }
  emberAfEventsClusterPrintln("");
#endif // defined(EMBER_AF_PRINT_ENABLE) && defined(EMBER_AF_PRINT_EVENTS_CLUSTER)

  emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS);
  return true;
}
예제 #2
0
// Cluster: Messaging, server
EmberAfStatus emberAfMessagingClusterServerCommandParse(EmberAfClusterCommand *cmd)
{
  boolean wasHandled = FALSE;
  if (!cmd->mfgSpecific) {
    switch (cmd->commandId) {
    case ZCL_GET_LAST_MESSAGE_COMMAND_ID:
      {
        // Command is fixed length: 0
        wasHandled = emberAfMessagingClusterGetLastMessageCallback();
        break;
      }
    case ZCL_MESSAGE_CONFIRMATION_COMMAND_ID:
      {
        int16u payloadOffset = cmd->payloadStartIndex;
        int32u messageId;  // Ver.: always
        int32u confirmationTime;  // Ver.: always
        int8u messageConfirmationControl;  // Ver.: since se-1.2a-14-0256-03
        int8u* messageResponse;  // Ver.: since se-1.2a-14-0256-03
        // Command is not a fixed length
        if (cmd->bufLen < payloadOffset + 4) return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
        messageId = emberAfGetInt32u(cmd->buffer, payloadOffset, cmd->bufLen);
        payloadOffset += 4;
        if (cmd->bufLen < payloadOffset + 4) return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
        confirmationTime = emberAfGetInt32u(cmd->buffer, payloadOffset, cmd->bufLen);
        payloadOffset += 4;
        if ( ( cmd->bufLen < payloadOffset + 1)) {
          // Argument is not always present:
          // - it is present only in versions higher than: se-1.2a-14-0256-03
          messageConfirmationControl = 0xFF;
        } else {
          messageConfirmationControl = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen);
          payloadOffset += 1;
        }
        if ( ( cmd->bufLen < payloadOffset + emberAfStringLength(cmd->buffer + payloadOffset) + 1)) {
          // Argument is not always present:
          // - it is present only in versions higher than: se-1.2a-14-0256-03
          messageResponse = NULL;
        } else {
          messageResponse = emberAfGetString(cmd->buffer, payloadOffset, cmd->bufLen);
        }
        wasHandled = emberAfMessagingClusterMessageConfirmationCallback(messageId,
                                                                        confirmationTime,
                                                                        messageConfirmationControl,
                                                                        messageResponse);
        break;
      }
    }
  }
  return status(wasHandled, cmd->mfgSpecific);
}
예제 #3
0
bool emberAfReportAttributesCallback(EmberAfClusterId clusterId,
                                        uint8_t *buffer,
                                        uint16_t bufLen)
{
  EmberEUI64 sendersEui;
  uint16_t bufIndex = 0;
  uint8_t endpoint;
  uint8_t index;
  bool attributeReportingComplete = false;

  if (EMBER_SUCCESS
       != emberLookupEui64ByNodeId(emberAfCurrentCommand()->source, sendersEui)) {
    emberAfSimpleMeteringClusterPrintln("Error: Meter Mirror plugin cannot determine EUI64 for node ID 0x%2X",
                                        emberAfCurrentCommand()->source);
    emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE);
    return true;
  }

  if (emberAfCurrentCommand()->direction
      == ZCL_DIRECTION_CLIENT_TO_SERVER) {
    emberAfSimpleMeteringClusterPrintln("Error:  Meter Mirror Plugin does not accept client to server attributes.\n",
                                        emberAfCurrentCommand()->direction);
    emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_FAILURE);
    return true;
  }
  
  index = findMirrorIndex(sendersEui);
  if (index == INVALID_INDEX) {
    emberAfSimpleMeteringClusterPrint("Error: Meter mirror plugin received unknown report from ");
    emberAfPrintBigEndianEui64(sendersEui);
    emberAfSimpleMeteringClusterPrintln("");
    emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_NOT_AUTHORIZED);
    return true;
  }

  if (emberAfCurrentCommand()->mfgSpecific) {
    // Here is where we could handle a MFG specific Report attributes and interpret 
    // it.  This code does not do that, just politely returns an error.
    emberAfSimpleMeteringClusterPrintln("Error: Unknown MFG Code for mirror: 0x%2X",
                                        emberAfCurrentCommand()->mfgCode);
    emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_UNSUP_MANUF_GENERAL_COMMAND);
    return true;
  }

  endpoint = (index + EMBER_AF_PLUGIN_METER_MIRROR_ENDPOINT_START);
  while (bufIndex + ATTRIBUTE_OVERHEAD < bufLen) {
    EmberAfStatus status;
    EmberAfAttributeId attributeId;
    EmberAfAttributeType dataType;
    uint8_t dataSize;

    attributeId = (EmberAfAttributeId)emberAfGetInt16u(buffer,
                                                       bufIndex,
                                                       bufLen);
    bufIndex += 2;
    dataType = (EmberAfAttributeType)emberAfGetInt8u(buffer, bufIndex, bufLen);
    bufIndex++;

    // For strings, the data size is the length of the string (specified by the
    // first byte of data) plus one for the length byte itself.  For everything
    // else, the size is just the size of the data type.
    dataSize = (emberAfIsThisDataTypeAStringType(dataType)
                ? emberAfStringLength(buffer + bufIndex) + 1
                : emberAfGetDataSize(dataType));

    {
#if (BIGENDIAN_CPU)
      uint8_t data[ATTRIBUTE_LARGEST];
      if (isThisDataTypeSentLittleEndianOTA(dataType)) {
        emberReverseMemCopy(data, buffer + bufIndex, dataSize);
      } else {
        MEMMOVE(data, buffer + bufIndex, dataSize);
      }
#else
      uint8_t *data = buffer + bufIndex;
#endif

      if (attributeId == ZCL_ATTRIBUTE_REPORTING_STATUS_ATTRIBUTE_ID) {
        // From the SE 1.2a Specification within the ConfigureMirror command
        // description..
        // 1.  On powering up, the BOMD will send one or more Report Attribute
        //     commands to the Metering client on the mirror endpoint. The last
        //     attribute to be reported to the mirror shall be an Attribute
        //     Reporting Status attribute, as defined in section A.2.
        // 2.  If MirrorReportAttributeResponse is enabled, the server does not
        //     need to request an APS ACK. If the server requests an APS ACK,
        //     the Metering client on the mirror endpoint shall respond first
        //     with an APS ACK and then send the MirrorReportAttributeResponse.
        //
        // If Mirror Notification Reporting is set to false, the
        // MirrorReportAttributeResponse command shall not be enabled; the
        // Metering server may poll the Notification flags by means of a normal
        // ReadAttribute command, as shown in Figure D 29:
        attributeReportingComplete = (data[0] == EMBER_ZCL_ATTRIBUTE_REPORTING_STATUS_ATTRIBUTE_REPORTING_COMPLETE);
        status = EMBER_ZCL_STATUS_SUCCESS;
      } else {
        if (attributeId == ZCL_METERING_DEVICE_TYPE_ATTRIBUTE_ID
            && data[0] < EMBER_ZCL_METERING_DEVICE_TYPE_MIRRORED_ELECTRIC_METERING) {
          data[0] += 127;
        }

        status = emberAfWriteServerAttribute(endpoint,
                                             clusterId,
                                             attributeId,
                                             data,
                                             dataType);
      }
    }

    emberAfSimpleMeteringClusterPrintln("Mirror attribute 0x%2x: 0x%x", attributeId, status);
    bufIndex += dataSize;
  }

  // If reporting is complete then callback to the application so that if it needs
  // to do any post processing on the reported attributes it can do it now.
  if (attributeReportingComplete) {
    emberAfPluginMeterMirrorReportingCompleteCallback(endpoint);
  }

  // Notification flags
  emberAfSimpleMeteringClusterPrintln("Mirror reporting ep: 0x%x, reporting: 0x%x, scheme: 0x%x",
                                      endpoint,
                                      mirrorList[index].mirrorNotificationReporting,
                                      mirrorList[index].notificationScheme);
  if (mirrorList[index].mirrorNotificationReporting  && attributeReportingComplete) {
    if (mirrorList[index].notificationScheme == EMBER_ZCL_NOTIFICATION_SCHEME_PREDEFINED_NOTIFICATION_SCHEME_A
        || mirrorList[index].notificationScheme == EMBER_ZCL_NOTIFICATION_SCHEME_PREDEFINED_NOTIFICATION_SCHEME_B) {
      return sendMirrorReportAttributeResponse(endpoint, index);
    } else {
      // TODO: for custom notification schemes callback to application
      // return emberAfMeterMirrorSendMirrorReportAttributeResponseCallback(...)
    }
  }

  emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS);
  return true;
}
// Cluster: Scenes, server
EmberAfStatus emberAfScenesClusterServerCommandParse(EmberAfClusterCommand *cmd) {
	boolean wasHandled = FALSE;
	if (!cmd->mfgSpecific) {
		switch (cmd->commandId) {
		case ZCL_ADD_SCENE_COMMAND_ID: {
			int16u payloadOffset = cmd->payloadStartIndex;
			int16u groupId;  // Ver.: always
			int8u sceneId;  // Ver.: always
			int16u transitionTime;  // Ver.: always
			int8u* sceneName;  // Ver.: always
			int8u* extensionFieldSets;  // Ver.: always
			// Command is not a fixed length
			if (cmd->bufLen < payloadOffset + 2)
				return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
			groupId = emberAfGetInt16u(cmd->buffer, payloadOffset, cmd->bufLen);
			payloadOffset += 2;
			if (cmd->bufLen < payloadOffset + 1)
				return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
			sceneId = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen);
			payloadOffset += 1;
			if (cmd->bufLen < payloadOffset + 2)
				return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
			transitionTime = emberAfGetInt16u(cmd->buffer, payloadOffset,
					cmd->bufLen);
			payloadOffset += 2;
			if (cmd->bufLen
					< payloadOffset
					+ emberAfStringLength(cmd->buffer + payloadOffset)
					+ 1)
				return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
			sceneName = emberAfGetString(cmd->buffer, payloadOffset,
					cmd->bufLen);
			payloadOffset += emberAfStringLength(cmd->buffer + payloadOffset)
							+ 1;
			extensionFieldSets = cmd->buffer + payloadOffset;
			wasHandled = emberAfScenesClusterAddSceneCallback(groupId, sceneId,
					transitionTime, sceneName, extensionFieldSets);
			break;
		}
		case ZCL_VIEW_SCENE_COMMAND_ID: {
			int16u payloadOffset = cmd->payloadStartIndex;
			int16u groupId;  // Ver.: always
			int8u sceneId;  // Ver.: always
			// Command is fixed length: 3
			if (cmd->bufLen < payloadOffset + 3)
				return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
			groupId = emberAfGetInt16u(cmd->buffer, payloadOffset, cmd->bufLen);
			payloadOffset += 2;
			sceneId = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen);
			wasHandled = emberAfScenesClusterViewSceneCallback(groupId,
					sceneId);
			break;
		}
		case ZCL_REMOVE_SCENE_COMMAND_ID: {
			int16u payloadOffset = cmd->payloadStartIndex;
			int16u groupId;  // Ver.: always
			int8u sceneId;  // Ver.: always
			// Command is fixed length: 3
			if (cmd->bufLen < payloadOffset + 3)
				return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
			groupId = emberAfGetInt16u(cmd->buffer, payloadOffset, cmd->bufLen);
			payloadOffset += 2;
			sceneId = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen);
			wasHandled = emberAfScenesClusterRemoveSceneCallback(groupId,
					sceneId);
			break;
		}
		case ZCL_REMOVE_ALL_SCENES_COMMAND_ID: {
			int16u payloadOffset = cmd->payloadStartIndex;
			int16u groupId;  // Ver.: always
			// Command is fixed length: 2
			if (cmd->bufLen < payloadOffset + 2)
				return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
			groupId = emberAfGetInt16u(cmd->buffer, payloadOffset, cmd->bufLen);
			wasHandled = emberAfScenesClusterRemoveAllScenesCallback(groupId);
			break;
		}
		case ZCL_STORE_SCENE_COMMAND_ID: {
			int16u payloadOffset = cmd->payloadStartIndex;
			int16u groupId;  // Ver.: always
			int8u sceneId;  // Ver.: always
			// Command is fixed length: 3
			if (cmd->bufLen < payloadOffset + 3)
				return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
			groupId = emberAfGetInt16u(cmd->buffer, payloadOffset, cmd->bufLen);
			payloadOffset += 2;
			sceneId = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen);
			wasHandled = emberAfScenesClusterStoreSceneCallback(groupId,
					sceneId);
			break;
		}
		case ZCL_RECALL_SCENE_COMMAND_ID: {
			int16u payloadOffset = cmd->payloadStartIndex;
			int16u groupId;  // Ver.: always
			int8u sceneId;  // Ver.: always
			// Command is fixed length: 3
			if (cmd->bufLen < payloadOffset + 3)
				return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
			groupId = emberAfGetInt16u(cmd->buffer, payloadOffset, cmd->bufLen);
			payloadOffset += 2;
			sceneId = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen);
			wasHandled = emberAfScenesClusterRecallSceneCallback(groupId,
					sceneId);
			break;
		}
		case ZCL_GET_SCENE_MEMBERSHIP_COMMAND_ID: {
			int16u payloadOffset = cmd->payloadStartIndex;
			int16u groupId;  // Ver.: always
			// Command is fixed length: 2
			if (cmd->bufLen < payloadOffset + 2)
				return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
			groupId = emberAfGetInt16u(cmd->buffer, payloadOffset, cmd->bufLen);
			wasHandled = emberAfScenesClusterGetSceneMembershipCallback(
					groupId);
			break;
		}
		}
	}
	return status(wasHandled, cmd->mfgSpecific);
}
// Cluster: Groups, server
EmberAfStatus emberAfGroupsClusterServerCommandParse(EmberAfClusterCommand *cmd) {
	boolean wasHandled = FALSE;
	if (!cmd->mfgSpecific) {
		switch (cmd->commandId) {
		case ZCL_ADD_GROUP_COMMAND_ID: {
			int16u payloadOffset = cmd->payloadStartIndex;
			int16u groupId;  // Ver.: always
			int8u* groupName;  // Ver.: always
			// Command is not a fixed length
			if (cmd->bufLen < payloadOffset + 2)
				return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
			groupId = emberAfGetInt16u(cmd->buffer, payloadOffset, cmd->bufLen);
			payloadOffset += 2;
			if (cmd->bufLen
					< payloadOffset
					+ emberAfStringLength(cmd->buffer + payloadOffset)
					+ 1)
				return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
			groupName = emberAfGetString(cmd->buffer, payloadOffset,
					cmd->bufLen);
			wasHandled = emberAfGroupsClusterAddGroupCallback(groupId,
					groupName);
			break;
		}
		case ZCL_VIEW_GROUP_COMMAND_ID: {
			int16u payloadOffset = cmd->payloadStartIndex;
			int16u groupId;  // Ver.: always
			// Command is fixed length: 2
			if (cmd->bufLen < payloadOffset + 2)
				return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
			groupId = emberAfGetInt16u(cmd->buffer, payloadOffset, cmd->bufLen);
			wasHandled = emberAfGroupsClusterViewGroupCallback(groupId);
			break;
		}
		case ZCL_GET_GROUP_MEMBERSHIP_COMMAND_ID: {
			int16u payloadOffset = cmd->payloadStartIndex;
			int8u groupCount;  // Ver.: always
			int8u* groupList;  // Ver.: always
			// Command is fixed length: 1
			if (cmd->bufLen < payloadOffset + 1)
				return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
			groupCount = emberAfGetInt8u(cmd->buffer, payloadOffset,
					cmd->bufLen);
			payloadOffset += 1;
			groupList = cmd->buffer + payloadOffset;
			wasHandled = emberAfGroupsClusterGetGroupMembershipCallback(
					groupCount, groupList);
			break;
		}
		case ZCL_REMOVE_GROUP_COMMAND_ID: {
			int16u payloadOffset = cmd->payloadStartIndex;
			int16u groupId;  // Ver.: always
			// Command is fixed length: 2
			if (cmd->bufLen < payloadOffset + 2)
				return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
			groupId = emberAfGetInt16u(cmd->buffer, payloadOffset, cmd->bufLen);
			wasHandled = emberAfGroupsClusterRemoveGroupCallback(groupId);
			break;
		}
		case ZCL_REMOVE_ALL_GROUPS_COMMAND_ID: {
			// Command is fixed length: 0
			wasHandled = emberAfGroupsClusterRemoveAllGroupsCallback();
			break;
		}
		case ZCL_ADD_GROUP_IF_IDENTIFYING_COMMAND_ID: {
			int16u payloadOffset = cmd->payloadStartIndex;
			int16u groupId;  // Ver.: always
			int8u* groupName;  // Ver.: always
			// Command is not a fixed length
			if (cmd->bufLen < payloadOffset + 2)
				return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
			groupId = emberAfGetInt16u(cmd->buffer, payloadOffset, cmd->bufLen);
			payloadOffset += 2;
			if (cmd->bufLen
					< payloadOffset
					+ emberAfStringLength(cmd->buffer + payloadOffset)
					+ 1)
				return EMBER_ZCL_STATUS_MALFORMED_COMMAND;
			groupName = emberAfGetString(cmd->buffer, payloadOffset,
					cmd->bufLen);
			wasHandled = emberAfGroupsClusterAddGroupIfIdentifyingCallback(
					groupId, groupName);
			break;
		}
		}
	}
	return status(wasHandled, cmd->mfgSpecific);
}