// 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); }
bool emberAfEventsClusterPublishEventLogCallback(uint16_t totalNumberOfEvents, uint8_t commandIndex, uint8_t totalCommands, uint8_t logPayloadControl, uint8_t* logPayload) { emberAfEventsClusterPrint("RX: PublishEventLog 0x%2x, 0x%x, 0x%x, 0x%x", totalNumberOfEvents, commandIndex, totalCommands, logPayloadControl); #if defined(EMBER_AF_PRINT_ENABLE) && defined(EMBER_AF_PRINT_EVENTS_CLUSTER) uint16_t logPayloadLen = (emberAfCurrentCommand()->bufLen - (emberAfCurrentCommand()->payloadStartIndex + sizeof(totalNumberOfEvents) + sizeof(commandIndex) + sizeof(totalCommands) + sizeof(logPayloadControl))); uint16_t logPayloadIndex = 0; uint8_t i; if (NULL != logPayload) { for (i = 0; i < numberOfEvents(logPayloadControl); i++) { uint8_t logId; uint16_t eventId; uint32_t eventTime; uint8_t *eventData; uint8_t eventDataLen; logId = emberAfGetInt8u(logPayload, logPayloadIndex, logPayloadLen); logPayloadIndex++; eventId = emberAfGetInt16u(logPayload, logPayloadIndex, logPayloadLen); logPayloadIndex += 2; eventTime = emberAfGetInt32u(logPayload, logPayloadIndex, logPayloadLen); logPayloadIndex += 4; eventData = logPayload + logPayloadIndex; eventDataLen = emberAfGetInt8u(logPayload, logPayloadIndex, logPayloadLen); logPayloadIndex += (1 + eventDataLen); emberAfEventsClusterPrint(" ["); emberAfEventsClusterPrint("0x%x, 0x%2x, 0x%4x, 0x%x", logId, eventId, eventTime, eventDataLen); if (eventDataLen > 0) { emberAfEventsClusterPrint(", "); emberAfEventsClusterPrintString(eventData); } emberAfEventsClusterPrint("]"); } } emberAfEventsClusterPrintln(""); #endif // defined(EMBER_AF_PRINT_ENABLE) && defined(EMBER_AF_PRINT_EVENTS_CLUSTER) emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS); return true; }
bool emberAfPluginInterpanPreMessageReceivedCallback(const EmberAfInterpanHeader *header, uint8_t msgLen, uint8_t *message) { uint32_t transaction; uint8_t frameControl, commandId, msgIndex; // If the message isn't for the ZLL Commissioning cluster, drop it with an // indication that we didn't handle it. After this, everything else will be // considered handled so that the message doesn't end up going through the // normal ZCL processing. if (header->profileId != EMBER_ZLL_PROFILE_ID || header->clusterId != ZCL_ZLL_COMMISSIONING_CLUSTER_ID) { return false; } if (header->messageType != EMBER_AF_INTER_PAN_UNICAST || !(header->options & EMBER_AF_INTERPAN_OPTION_MAC_HAS_LONG_ADDRESS) || msgLen < ZLL_HEADER_OVERHEAD) { return true; } // Verify that the frame control byte makes sense. Accept only the legacy // format or simple client-to-server or server-to-client messages (i.e., no // manufacturer-specific commands, etc.) For non-legacy messages, check that // the frame control is correct for the command. The check is based on // DeviceInformationResponse because it is the only server-to-client command // we care about. frameControl = message[ZLL_HEADER_FRAME_CONTROL_OFFSET]; commandId = message[ZLL_HEADER_COMMAND_ID_OFFSET]; if (frameControl != ZLL_FRAME_CONTROL_LEGACY && (frameControl != ZLL_FRAME_CONTROL_CLIENT_TO_SERVER || commandId == ZCL_DEVICE_INFORMATION_RESPONSE_COMMAND_ID) && (frameControl != ZLL_FRAME_CONTROL_SERVER_TO_CLIENT || commandId != ZCL_DEVICE_INFORMATION_RESPONSE_COMMAND_ID)) { return true; } msgIndex = ZLL_HEADER_TRANSACTION_ID_OFFSET; transaction = emberAfGetInt32u(message, msgIndex, msgLen); msgIndex += 4; switch (commandId) { case ZCL_DEVICE_INFORMATION_REQUEST_COMMAND_ID: if (msgIndex + 1 <= msgLen) { uint8_t startIndex = emberAfGetInt8u(message, msgIndex, msgLen); deviceInformationRequestHandler(header->longAddress, transaction, startIndex); } break; #ifdef EMBER_AF_PLUGIN_ZLL_COMMISSIONING_LINK_INITIATOR case ZCL_DEVICE_INFORMATION_RESPONSE_COMMAND_ID: if (msgIndex + 3 <= msgLen) { uint8_t numberOfSubDevices, startIndex, deviceInformationRecordCount; numberOfSubDevices = emberAfGetInt8u(message, msgIndex, msgLen); msgIndex++; startIndex = emberAfGetInt8u(message, msgIndex, msgLen); msgIndex++; deviceInformationRecordCount = emberAfGetInt8u(message, msgIndex, msgLen); msgIndex++; if ((msgIndex + deviceInformationRecordCount * ZLL_DEVICE_INFORMATION_RECORD_SIZE) <= msgLen) { uint8_t *deviceInformationRecordList = message + msgIndex; deviceInformationResponseHandler(header->longAddress, transaction, numberOfSubDevices, startIndex, deviceInformationRecordCount, deviceInformationRecordList); } } break; #endif //EMBER_AF_PLUGIN_ZLL_COMMISSIONING_LINK_INITIATOR case ZCL_IDENTIFY_REQUEST_COMMAND_ID: if (msgIndex + 2 <= msgLen) { uint16_t identifyDurationS = emberAfGetInt16u(message, msgIndex, msgLen); identifyRequestHandler(header->longAddress, transaction, identifyDurationS); } break; case ZCL_RESET_TO_FACTORY_NEW_REQUEST_COMMAND_ID: resetToFactoryNewRequestHandler(header->longAddress, transaction); break; } // All ZLL Commissioning cluster messages are considered handled, even if we // ended up dropping them because they were malformed, etc. return true; }
// Cluster: Price, server EmberAfStatus emberAfPriceClusterServerCommandParse(EmberAfClusterCommand *cmd) { boolean wasHandled = FALSE; if (!cmd->mfgSpecific) { switch (cmd->commandId) { case ZCL_GET_CURRENT_PRICE_COMMAND_ID: { int16u payloadOffset = cmd->payloadStartIndex; int8u commandOptions; // Ver.: always // Command is fixed length: 1 if (cmd->bufLen < payloadOffset + 1) return EMBER_ZCL_STATUS_MALFORMED_COMMAND; commandOptions = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen); wasHandled = emberAfPriceClusterGetCurrentPriceCallback(commandOptions); break; } case ZCL_GET_SCHEDULED_PRICES_COMMAND_ID: { int16u payloadOffset = cmd->payloadStartIndex; int32u startTime; // Ver.: always int8u numberOfEvents; // Ver.: always // Command is fixed length: 5 if (cmd->bufLen < payloadOffset + 5) return EMBER_ZCL_STATUS_MALFORMED_COMMAND; startTime = emberAfGetInt32u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 4; numberOfEvents = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen); wasHandled = emberAfPriceClusterGetScheduledPricesCallback(startTime, numberOfEvents); break; } case ZCL_GET_TARIFF_INFORMATION_COMMAND_ID: { int16u payloadOffset = cmd->payloadStartIndex; int32u earliestStartTime; // Ver.: always int32u minIssuerEventId; // Ver.: always int8u numberOfCommands; // Ver.: always int8u tariffType; // Ver.: always // Command is fixed length: 10 if (cmd->bufLen < payloadOffset + 10) return EMBER_ZCL_STATUS_MALFORMED_COMMAND; earliestStartTime = emberAfGetInt32u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 4; minIssuerEventId = emberAfGetInt32u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 4; numberOfCommands = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 1; tariffType = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen); wasHandled = emberAfPriceClusterGetTariffInformationCallback(earliestStartTime, minIssuerEventId, numberOfCommands, tariffType); break; } case ZCL_GET_PRICE_MATRIX_COMMAND_ID: { int16u payloadOffset = cmd->payloadStartIndex; int32u issuerTariffId; // Ver.: always // Command is fixed length: 4 if (cmd->bufLen < payloadOffset + 4) return EMBER_ZCL_STATUS_MALFORMED_COMMAND; issuerTariffId = emberAfGetInt32u(cmd->buffer, payloadOffset, cmd->bufLen); wasHandled = emberAfPriceClusterGetPriceMatrixCallback(issuerTariffId); break; } } } return status(wasHandled, cmd->mfgSpecific); }
// Cluster: Simple Metering, server EmberAfStatus emberAfSimpleMeteringClusterServerCommandParse(EmberAfClusterCommand *cmd) { boolean wasHandled = FALSE; if (!cmd->mfgSpecific) { switch (cmd->commandId) { case ZCL_GET_PROFILE_COMMAND_ID: { int16u payloadOffset = cmd->payloadStartIndex; int8u intervalChannel; // Ver.: always int32u endTime; // Ver.: always int8u numberOfPeriods; // Ver.: always // Command is fixed length: 6 if (cmd->bufLen < payloadOffset + 6) return EMBER_ZCL_STATUS_MALFORMED_COMMAND; intervalChannel = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 1; endTime = emberAfGetInt32u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 4; numberOfPeriods = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen); wasHandled = emberAfSimpleMeteringClusterGetProfileCallback(intervalChannel, endTime, numberOfPeriods); break; } case ZCL_REQUEST_FAST_POLL_MODE_COMMAND_ID: { int16u payloadOffset = cmd->payloadStartIndex; int8u fastPollUpdatePeriod; // Ver.: always int8u duration; // Ver.: always // Command is fixed length: 2 if (cmd->bufLen < payloadOffset + 2) return EMBER_ZCL_STATUS_MALFORMED_COMMAND; fastPollUpdatePeriod = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 1; duration = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen); wasHandled = emberAfSimpleMeteringClusterRequestFastPollModeCallback(fastPollUpdatePeriod, duration); break; } case ZCL_SCHEDULE_SNAPSHOT_COMMAND_ID: { int16u payloadOffset = cmd->payloadStartIndex; int32u issuerEventId; // Ver.: always int8u commandIndex; // Ver.: always int8u commandCount; // Ver.: always int8u* snapshotSchedulePayload; // Ver.: always // Command is fixed length: 6 if (cmd->bufLen < payloadOffset + 6) return EMBER_ZCL_STATUS_MALFORMED_COMMAND; issuerEventId = emberAfGetInt32u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 4; commandIndex = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 1; commandCount = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 1; snapshotSchedulePayload = cmd->buffer + payloadOffset; wasHandled = emberAfSimpleMeteringClusterScheduleSnapshotCallback(issuerEventId, commandIndex, commandCount, snapshotSchedulePayload); break; } case ZCL_TAKE_SNAPSHOT_COMMAND_ID: { int16u payloadOffset = cmd->payloadStartIndex; int32u snapshotCause; // Ver.: always // Command is fixed length: 4 if (cmd->bufLen < payloadOffset + 4) return EMBER_ZCL_STATUS_MALFORMED_COMMAND; snapshotCause = emberAfGetInt32u(cmd->buffer, payloadOffset, cmd->bufLen); wasHandled = emberAfSimpleMeteringClusterTakeSnapshotCallback(snapshotCause); break; } case ZCL_GET_SNAPSHOT_COMMAND_ID: { int16u payloadOffset = cmd->payloadStartIndex; int32u earliestStartTime; // Ver.: always int32u latestEndTime; // Ver.: always int8u snapshotOffset; // Ver.: always int32u snapshotCause; // Ver.: always // Command is fixed length: 13 if (cmd->bufLen < payloadOffset + 13) return EMBER_ZCL_STATUS_MALFORMED_COMMAND; earliestStartTime = emberAfGetInt32u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 4; latestEndTime = emberAfGetInt32u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 4; snapshotOffset = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 1; snapshotCause = emberAfGetInt32u(cmd->buffer, payloadOffset, cmd->bufLen); wasHandled = emberAfSimpleMeteringClusterGetSnapshotCallback(earliestStartTime, latestEndTime, snapshotOffset, snapshotCause); break; } } } return status(wasHandled, cmd->mfgSpecific); }
// Cluster: Simple Metering, client EmberAfStatus emberAfSimpleMeteringClusterClientCommandParse(EmberAfClusterCommand *cmd) { boolean wasHandled = FALSE; if (!cmd->mfgSpecific) { switch (cmd->commandId) { case ZCL_GET_PROFILE_RESPONSE_COMMAND_ID: { int16u payloadOffset = cmd->payloadStartIndex; int32u endTime; // Ver.: always int8u status; // Ver.: always int8u profileIntervalPeriod; // Ver.: always int8u numberOfPeriodsDelivered; // Ver.: always int8u* intervals; // Ver.: always // Command is fixed length: 7 if (cmd->bufLen < payloadOffset + 7) return EMBER_ZCL_STATUS_MALFORMED_COMMAND; endTime = emberAfGetInt32u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 4; status = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 1; profileIntervalPeriod = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 1; numberOfPeriodsDelivered = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 1; intervals = cmd->buffer + payloadOffset; wasHandled = emberAfSimpleMeteringClusterGetProfileResponseCallback(endTime, status, profileIntervalPeriod, numberOfPeriodsDelivered, intervals); break; } case ZCL_REQUEST_MIRROR_COMMAND_ID: { // Command is fixed length: 0 wasHandled = emberAfSimpleMeteringClusterRequestMirrorCallback(); break; } case ZCL_REMOVE_MIRROR_COMMAND_ID: { // Command is fixed length: 0 wasHandled = emberAfSimpleMeteringClusterRemoveMirrorCallback(); break; } case ZCL_REQUEST_FAST_POLL_MODE_RESPONSE_COMMAND_ID: { int16u payloadOffset = cmd->payloadStartIndex; int8u appliedUpdatePeriod; // Ver.: always int32u fastPollModeEndtime; // Ver.: always // Command is fixed length: 5 if (cmd->bufLen < payloadOffset + 5) return EMBER_ZCL_STATUS_MALFORMED_COMMAND; appliedUpdatePeriod = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 1; fastPollModeEndtime = emberAfGetInt32u(cmd->buffer, payloadOffset, cmd->bufLen); wasHandled = emberAfSimpleMeteringClusterRequestFastPollModeResponseCallback(appliedUpdatePeriod, fastPollModeEndtime); break; } case ZCL_CONFIGURE_MIRROR_COMMAND_ID: { int16u payloadOffset = cmd->payloadStartIndex; int32u issuerEventId; // Ver.: always int32u reportingInterval; // Ver.: always int8u mirrorNotificationReporting; // Ver.: always int8u notificationScheme; // Ver.: always // Command is fixed length: 9 if (cmd->bufLen < payloadOffset + 9) return EMBER_ZCL_STATUS_MALFORMED_COMMAND; issuerEventId = emberAfGetInt32u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 4; reportingInterval = emberAfGetInt24u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 3; mirrorNotificationReporting = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen); payloadOffset += 1; notificationScheme = emberAfGetInt8u(cmd->buffer, payloadOffset, cmd->bufLen); wasHandled = emberAfSimpleMeteringClusterConfigureMirrorCallback(issuerEventId, reportingInterval, mirrorNotificationReporting, notificationScheme); break; } } } return status(wasHandled, cmd->mfgSpecific); }