void emberSetAddressHandler(const uint8_t *addr) { EmberIpv6Address address; MEMCOPY(address.bytes, addr, 16); if (emIsDefaultGlobalPrefix(address.bytes)) { // Store the ULA. MEMCOPY(hostIpAddress.bytes, address.bytes, 16); uint8_t meshLocalIdentifier[8]; emberReverseMemCopy(meshLocalIdentifier, address.bytes + 8, 8); meshLocalIdentifier[7] ^= 0x02; // Configure these for the first time (only once). emSetMeshLocalIdentifier(meshLocalIdentifier); emSetLinkLocalIdentifier(localEui64.bytes); #ifndef UNIX_HOST_SIM emberConfigureDefaultHostAddress(&address); #endif } else { #ifndef UNIX_HOST_SIM emberConfigureGlobalHostAddress(&address); #endif } }
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; }
void emUnmodifyInterfaceId(const uint8_t *interfaceId, uint8_t *longId) { emberReverseMemCopy(longId, interfaceId, 8); longId[7] ^= 0x02; }
void emModifyLongId(const uint8_t *longId, uint8_t *target) { emberReverseMemCopy(target, longId, 8); target[0] ^= 0x02; }