| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680 |
- /*
- *
- * Copyright (c) 2021 Project CHIP Authors
- * All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include <platform/CHIPDeviceLayer.h>
- #include <platform/PlatformManager.h>
- #include <app-common/zap-generated/af-structs.h>
- #include <app-common/zap-generated/attribute-id.h>
- #include <app-common/zap-generated/cluster-id.h>
- #include <app/chip-zcl-zpro-codec.h>
- #include <app/reporting/reporting.h>
- #include <app/util/af-types.h>
- #include <app/util/af.h>
- #include <app/util/attribute-storage.h>
- #include <app/util/util.h>
- #include <credentials/DeviceAttestationCredsProvider.h>
- #include <credentials/examples/DeviceAttestationCredsExample.h>
- #include <lib/core/CHIPError.h>
- #include <lib/support/CHIPMem.h>
- #include <lib/support/ZclString.h>
- #include <setup_payload/QRCodeSetupPayloadGenerator.h>
- #include <setup_payload/SetupPayload.h>
- #include "Device.h"
- #include "Options.h"
- #include <app/server/Server.h>
- #include <cassert>
- #include <iostream>
- using namespace chip;
- using namespace chip::Credentials;
- using namespace chip::Inet;
- using namespace chip::Transport;
- using namespace chip::DeviceLayer;
- static const int kNodeLabelSize = 32;
- // Current ZCL implementation of Struct uses a max-size array of 254 bytes
- static const int kDescriptorAttributeArraySize = 254;
- static const int kFixedLabelAttributeArraySize = 254;
- // Four attributes in descriptor cluster: DeviceTypeList, ServerList, ClientList, PartsList
- static const int kFixedLabelElementsOctetStringSize = 16;
- static EndpointId gCurrentEndpointId;
- static EndpointId gFirstDynamicEndpointId;
- static Device * gDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT];
- // ENDPOINT DEFINITIONS:
- // =================================================================================
- //
- // Endpoint definitions will be reused across multiple endpoints for every instance of the
- // endpoint type.
- // There will be no intrinsic storage for the endpoint attributes declared here.
- // Instead, all attributes will be treated as EXTERNAL, and therefore all reads
- // or writes to the attributes must be handled within the emberAfExternalAttributeWriteCallback
- // and emberAfExternalAttributeReadCallback functions declared herein. This fits
- // the typical model of a bridge, since a bridge typically maintains its own
- // state database representing the devices connected to it.
- // Device types for dynamic endpoints: TODO Need a generated file from ZAP to define these!
- // (taken from chip-devices.xml)
- #define DEVICE_TYPE_CHIP_BRIDGE 0x0a0b
- // (taken from lo-devices.xml)
- #define DEVICE_TYPE_LO_ON_OFF_LIGHT 0x0100
- // (taken from lo-devices.xml)
- #define DEVICE_TYPE_LO_ON_OFF_LIGHT_SWITCH 0x0103
- // Device Version for dynamic endpoints:
- #define DEVICE_VERSION_DEFAULT 1
- // ---------------------------------------------------------------------------
- //
- // LIGHT ENDPOINT: contains the following clusters:
- // - On/Off
- // - Descriptor
- // - Bridged Device Basic
- // - Fixed Label
- // Declare On/Off cluster attributes
- DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(onOffAttrs)
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_ON_OFF_ATTRIBUTE_ID, BOOLEAN, 1, 0), /* on/off */
- DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
- // Declare Descriptor cluster attributes
- DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(descriptorAttrs)
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_DEVICE_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* device list */
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_SERVER_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* server list */
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CLIENT_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* client list */
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_PARTS_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* parts list */
- DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
- // Declare Bridged Device Basic information cluster attributes
- DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(bridgedDeviceBasicAttrs)
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_NODE_LABEL_ATTRIBUTE_ID, CHAR_STRING, kNodeLabelSize, 0), /* NodeLabel */
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_REACHABLE_ATTRIBUTE_ID, BOOLEAN, 1, 0), /* Reachable */
- DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
- // Declare Fixed Label cluster attributes
- DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(fixedLabelAttrs)
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_LABEL_LIST_ATTRIBUTE_ID, ARRAY, kFixedLabelAttributeArraySize, 0), /* label list */
- DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
- // Declare Cluster List for Bridged Light endpoint
- DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedLightClusters)
- DECLARE_DYNAMIC_CLUSTER(ZCL_ON_OFF_CLUSTER_ID, onOffAttrs), DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, descriptorAttrs),
- DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, bridgedDeviceBasicAttrs),
- DECLARE_DYNAMIC_CLUSTER(ZCL_FIXED_LABEL_CLUSTER_ID, fixedLabelAttrs) DECLARE_DYNAMIC_CLUSTER_LIST_END;
- // Declare Bridged Light endpoint
- DECLARE_DYNAMIC_ENDPOINT(bridgedLightEndpoint, bridgedLightClusters);
- // ---------------------------------------------------------------------------
- //
- // SWITCH ENDPOINT: contains the following clusters:
- // - Switch
- // - Descriptor
- // - Bridged Device Basic
- // - Fixed Label
- // Declare Switch cluster attributes
- DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(switchAttrs)
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_NUMBER_OF_POSITIONS_ATTRIBUTE_ID, INT8U, 1, 0), /* NumberOfPositions */
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CURRENT_POSITION_ATTRIBUTE_ID, INT8U, 1, 0), /* CurrentPosition */
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MULTI_PRESS_MAX_ATTRIBUTE_ID, INT8U, 1, 0), /* MultiPressMax */
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */
- DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
- // Declare Descriptor cluster attributes
- DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(switchDescriptorAttrs)
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_DEVICE_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* device list */
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_SERVER_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* server list */
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CLIENT_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* client list */
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_PARTS_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* parts list */
- DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
- // Declare Bridged Device Basic information cluster attributes
- DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(switchBridgedDeviceBasicAttrs)
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_NODE_LABEL_ATTRIBUTE_ID, CHAR_STRING, kNodeLabelSize, 0), /* NodeLabel */
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_REACHABLE_ATTRIBUTE_ID, BOOLEAN, 1, 0), /* Reachable */
- DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
- // Declare Fixed Label cluster attributes
- DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(switchFixedLabelAttrs)
- DECLARE_DYNAMIC_ATTRIBUTE(ZCL_LABEL_LIST_ATTRIBUTE_ID, ARRAY, kFixedLabelAttributeArraySize, 0), /* label list */
- DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
- // Declare Cluster List for Bridged Switch endpoint
- DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedSwitchClusters)
- DECLARE_DYNAMIC_CLUSTER(ZCL_SWITCH_CLUSTER_ID, switchAttrs),
- DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, switchDescriptorAttrs),
- DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, switchBridgedDeviceBasicAttrs),
- DECLARE_DYNAMIC_CLUSTER(ZCL_FIXED_LABEL_CLUSTER_ID, switchFixedLabelAttrs) DECLARE_DYNAMIC_CLUSTER_LIST_END;
- // Declare Bridged Switch endpoint
- DECLARE_DYNAMIC_ENDPOINT(bridgedSwitchEndpoint, bridgedSwitchClusters);
- // REVISION DEFINITIONS:
- // =================================================================================
- #define ZCL_DESCRIPTOR_CLUSTER_REVISION (1u)
- #define ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_REVISION (1u)
- #define ZCL_FIXED_LABEL_CLUSTER_REVISION (1u)
- #define ZCL_ON_OFF_CLUSTER_REVISION (4u)
- #define ZCL_SWITCH_CLUSTER_REVISION (1u)
- // ---------------------------------------------------------------------------
- int AddDeviceEndpoint(Device * dev, EmberAfEndpointType * ep, uint16_t deviceType)
- {
- uint8_t index = 0;
- while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT)
- {
- if (NULL == gDevices[index])
- {
- gDevices[index] = dev;
- EmberAfStatus ret;
- while (1)
- {
- ret = emberAfSetDynamicEndpoint(index, gCurrentEndpointId, ep, deviceType, DEVICE_VERSION_DEFAULT);
- if (ret == EMBER_ZCL_STATUS_SUCCESS)
- {
- ChipLogProgress(DeviceLayer, "Added device %s to dynamic endpoint %d (index=%d)", dev->GetName(),
- gCurrentEndpointId, index);
- return index;
- }
- else if (ret != EMBER_ZCL_STATUS_DUPLICATE_EXISTS)
- {
- return -1;
- }
- // Handle wrap condition
- if (++gCurrentEndpointId < gFirstDynamicEndpointId)
- {
- gCurrentEndpointId = gFirstDynamicEndpointId;
- }
- }
- }
- index++;
- }
- ChipLogProgress(DeviceLayer, "Failed to add dynamic endpoint: No endpoints available!");
- return -1;
- }
- int RemoveDeviceEndpoint(Device * dev)
- {
- uint8_t index = 0;
- while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT)
- {
- if (gDevices[index] == dev)
- {
- EndpointId ep = emberAfClearDynamicEndpoint(index);
- gDevices[index] = NULL;
- ChipLogProgress(DeviceLayer, "Removed device %s from dynamic endpoint %d (index=%d)", dev->GetName(), ep, index);
- // Silence complaints about unused ep when progress logging
- // disabled.
- UNUSED_VAR(ep);
- return index;
- }
- index++;
- }
- return -1;
- }
- void EncodeFixedLabel(const char * label, const char * value, uint8_t * buffer, uint16_t length,
- const EmberAfAttributeMetadata * am)
- {
- char zclOctetStrBuf[kFixedLabelElementsOctetStringSize];
- _LabelStruct labelStruct;
- // TODO: This size is obviously wrong. See
- // https://github.com/project-chip/connectedhomeip/issues/10743
- labelStruct.label = CharSpan(label, kFixedLabelElementsOctetStringSize);
- strncpy(zclOctetStrBuf, value, sizeof(zclOctetStrBuf));
- // TODO: This size is obviously wrong. See
- // https://github.com/project-chip/connectedhomeip/issues/10743
- labelStruct.value = CharSpan(&zclOctetStrBuf[0], sizeof(zclOctetStrBuf));
- // TODO: Need to set up an AttributeAccessInterface to handle the lists here.
- }
- void HandleDeviceStatusChanged(Device * dev, Device::Changed_t itemChangedMask)
- {
- if (itemChangedMask & Device::kChanged_Reachable)
- {
- uint8_t reachable = dev->IsReachable() ? 1 : 0;
- MatterReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID,
- ZCL_REACHABLE_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, ZCL_BOOLEAN_ATTRIBUTE_TYPE,
- &reachable);
- }
- if (itemChangedMask & Device::kChanged_Name)
- {
- uint8_t zclName[kNodeLabelSize];
- MutableByteSpan zclNameSpan(zclName);
- MakeZclCharString(zclNameSpan, dev->GetName());
- MatterReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID,
- ZCL_NODE_LABEL_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, ZCL_CHAR_STRING_ATTRIBUTE_TYPE,
- zclNameSpan.data());
- }
- if (itemChangedMask & Device::kChanged_Location)
- {
- uint8_t buffer[kFixedLabelAttributeArraySize];
- EmberAfAttributeMetadata am = { .attributeId = ZCL_LABEL_LIST_ATTRIBUTE_ID,
- .size = kFixedLabelAttributeArraySize,
- .defaultValue = static_cast<uint16_t>(0) };
- EncodeFixedLabel("room", dev->GetLocation(), buffer, sizeof(buffer), &am);
- MatterReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_FIXED_LABEL_CLUSTER_ID, ZCL_LABEL_LIST_ATTRIBUTE_ID,
- CLUSTER_MASK_SERVER, ZCL_ARRAY_ATTRIBUTE_TYPE, buffer);
- }
- }
- void HandleDeviceOnOffStatusChanged(DeviceOnOff * dev, DeviceOnOff::Changed_t itemChangedMask)
- {
- if (itemChangedMask & (DeviceOnOff::kChanged_Reachable | DeviceOnOff::kChanged_Name | DeviceOnOff::kChanged_Location))
- {
- HandleDeviceStatusChanged(static_cast<Device *>(dev), (Device::Changed_t) itemChangedMask);
- }
- if (itemChangedMask & DeviceOnOff::kChanged_OnOff)
- {
- uint8_t isOn = dev->IsOn() ? 1 : 0;
- MatterReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID,
- CLUSTER_MASK_SERVER, ZCL_BOOLEAN_ATTRIBUTE_TYPE, &isOn);
- }
- }
- void HandleDeviceSwitchStatusChanged(DeviceSwitch * dev, DeviceSwitch::Changed_t itemChangedMask)
- {
- if (itemChangedMask & (DeviceSwitch::kChanged_Reachable | DeviceSwitch::kChanged_Name | DeviceSwitch::kChanged_Location))
- {
- HandleDeviceStatusChanged(static_cast<Device *>(dev), (Device::Changed_t) itemChangedMask);
- }
- if (itemChangedMask & DeviceSwitch::kChanged_NumberOfPositions)
- {
- uint8_t numberOfPositions = dev->GetNumberOfPositions();
- MatterReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_SWITCH_CLUSTER_ID, ZCL_NUMBER_OF_POSITIONS_ATTRIBUTE_ID,
- CLUSTER_MASK_SERVER, ZCL_INT8U_ATTRIBUTE_TYPE, &numberOfPositions);
- }
- if (itemChangedMask & DeviceSwitch::kChanged_CurrentPosition)
- {
- uint8_t currentPosition = dev->GetCurrentPosition();
- MatterReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_SWITCH_CLUSTER_ID, ZCL_CURRENT_POSITION_ATTRIBUTE_ID,
- CLUSTER_MASK_SERVER, ZCL_INT8U_ATTRIBUTE_TYPE, ¤tPosition);
- }
- if (itemChangedMask & DeviceSwitch::kChanged_MultiPressMax)
- {
- uint8_t multiPressMax = dev->GetMultiPressMax();
- MatterReportingAttributeChangeCallback(dev->GetEndpointId(), ZCL_SWITCH_CLUSTER_ID, ZCL_MULTI_PRESS_MAX_ATTRIBUTE_ID,
- CLUSTER_MASK_SERVER, ZCL_INT8U_ATTRIBUTE_TYPE, &multiPressMax);
- }
- }
- EmberAfStatus HandleReadBridgedDeviceBasicAttribute(Device * dev, chip::AttributeId attributeId, uint8_t * buffer,
- uint16_t maxReadLength)
- {
- ChipLogProgress(DeviceLayer, "HandleReadBridgedDeviceBasicAttribute: attrId=%d, maxReadLength=%d", attributeId, maxReadLength);
- if ((attributeId == ZCL_REACHABLE_ATTRIBUTE_ID) && (maxReadLength == 1))
- {
- *buffer = dev->IsReachable() ? 1 : 0;
- }
- else if ((attributeId == ZCL_NODE_LABEL_ATTRIBUTE_ID) && (maxReadLength == 32))
- {
- uint8_t bufferMemory[254];
- MutableByteSpan zclString(bufferMemory);
- MakeZclCharString(zclString, dev->GetName());
- buffer = zclString.data();
- }
- else if ((attributeId == ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID) && (maxReadLength == 2))
- {
- *buffer = (uint16_t) ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_REVISION;
- }
- else
- {
- return EMBER_ZCL_STATUS_FAILURE;
- }
- return EMBER_ZCL_STATUS_SUCCESS;
- }
- EmberAfStatus HandleReadOnOffAttribute(DeviceOnOff * dev, chip::AttributeId attributeId, uint8_t * buffer, uint16_t maxReadLength)
- {
- ChipLogProgress(DeviceLayer, "HandleReadOnOffAttribute: attrId=%d, maxReadLength=%d", attributeId, maxReadLength);
- if ((attributeId == ZCL_ON_OFF_ATTRIBUTE_ID) && (maxReadLength == 1))
- {
- *buffer = dev->IsOn() ? 1 : 0;
- }
- else if ((attributeId == ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID) && (maxReadLength == 2))
- {
- *buffer = (uint16_t) ZCL_ON_OFF_CLUSTER_REVISION;
- }
- else
- {
- return EMBER_ZCL_STATUS_FAILURE;
- }
- return EMBER_ZCL_STATUS_SUCCESS;
- }
- EmberAfStatus HandleWriteOnOffAttribute(DeviceOnOff * dev, chip::AttributeId attributeId, uint8_t * buffer)
- {
- ChipLogProgress(DeviceLayer, "HandleWriteOnOffAttribute: attrId=%d", attributeId);
- if ((attributeId == ZCL_ON_OFF_ATTRIBUTE_ID) && (dev->IsReachable()))
- {
- if (*buffer)
- {
- dev->SetOnOff(true);
- }
- else
- {
- dev->SetOnOff(false);
- }
- }
- else
- {
- return EMBER_ZCL_STATUS_FAILURE;
- }
- return EMBER_ZCL_STATUS_SUCCESS;
- }
- EmberAfStatus HandleReadFixedLabelAttribute(Device * dev, const EmberAfAttributeMetadata * am, uint8_t * buffer,
- uint16_t maxReadLength)
- {
- if ((am->attributeId == ZCL_LABEL_LIST_ATTRIBUTE_ID) && (maxReadLength <= kFixedLabelAttributeArraySize))
- {
- EncodeFixedLabel("room", dev->GetLocation(), buffer, maxReadLength, am);
- }
- else if ((am->attributeId == ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID) && (maxReadLength == 2))
- {
- *buffer = (uint16_t) ZCL_FIXED_LABEL_CLUSTER_REVISION;
- }
- else
- {
- return EMBER_ZCL_STATUS_FAILURE;
- }
- return EMBER_ZCL_STATUS_SUCCESS;
- }
- EmberAfStatus HandleReadSwitchAttribute(DeviceSwitch * dev, chip::AttributeId attributeId, uint8_t * buffer, uint16_t maxReadLength)
- {
- if ((attributeId == ZCL_NUMBER_OF_POSITIONS_ATTRIBUTE_ID) && (maxReadLength == 1))
- {
- *buffer = dev->GetNumberOfPositions();
- }
- else if ((attributeId == ZCL_CURRENT_POSITION_ATTRIBUTE_ID) && (maxReadLength == 1))
- {
- *buffer = dev->GetCurrentPosition();
- }
- else if ((attributeId == ZCL_MULTI_PRESS_MAX_ATTRIBUTE_ID) && (maxReadLength == 1))
- {
- *buffer = dev->GetMultiPressMax();
- }
- else if ((attributeId == ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID) && (maxReadLength == 4))
- {
- *(uint32_t *) buffer = dev->GetFeatureMap();
- }
- else if ((attributeId == ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID) && (maxReadLength == 2))
- {
- *buffer = (uint16_t) ZCL_SWITCH_CLUSTER_REVISION;
- }
- else
- {
- return EMBER_ZCL_STATUS_FAILURE;
- }
- return EMBER_ZCL_STATUS_SUCCESS;
- }
- EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterId clusterId,
- const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer,
- uint16_t maxReadLength)
- {
- uint16_t endpointIndex = emberAfGetDynamicIndexFromEndpoint(endpoint);
- EmberAfStatus ret = EMBER_ZCL_STATUS_FAILURE;
- if ((endpointIndex < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) && (gDevices[endpointIndex] != NULL))
- {
- Device * dev = gDevices[endpointIndex];
- if (clusterId == ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID)
- {
- ret = HandleReadBridgedDeviceBasicAttribute(dev, attributeMetadata->attributeId, buffer, maxReadLength);
- }
- else if (clusterId == ZCL_FIXED_LABEL_CLUSTER_ID)
- {
- ret = HandleReadFixedLabelAttribute(dev, attributeMetadata, buffer, maxReadLength);
- }
- else if (clusterId == ZCL_ON_OFF_CLUSTER_ID)
- {
- ret = HandleReadOnOffAttribute(static_cast<DeviceOnOff *>(dev), attributeMetadata->attributeId, buffer, maxReadLength);
- }
- else if (clusterId == ZCL_SWITCH_CLUSTER_ID)
- {
- ret =
- HandleReadSwitchAttribute(static_cast<DeviceSwitch *>(dev), attributeMetadata->attributeId, buffer, maxReadLength);
- }
- }
- return ret;
- }
- EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, ClusterId clusterId,
- const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer)
- {
- uint16_t endpointIndex = emberAfGetDynamicIndexFromEndpoint(endpoint);
- EmberAfStatus ret = EMBER_ZCL_STATUS_FAILURE;
- // ChipLogProgress(DeviceLayer, "emberAfExternalAttributeWriteCallback: ep=%d", endpoint);
- if (endpointIndex < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT)
- {
- Device * dev = gDevices[endpointIndex];
- if ((dev->IsReachable()) && (clusterId == ZCL_ON_OFF_CLUSTER_ID))
- {
- ret = HandleWriteOnOffAttribute(static_cast<DeviceOnOff *>(dev), attributeMetadata->attributeId, buffer);
- }
- }
- return ret;
- }
- namespace {
- void EventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg)
- {
- (void) arg;
- if (event->Type == chip::DeviceLayer::DeviceEventType::kCHIPoBLEConnectionEstablished)
- {
- ChipLogProgress(DeviceLayer, "Receive kCHIPoBLEConnectionEstablished");
- }
- }
- CHIP_ERROR PrintQRCodeContent()
- {
- CHIP_ERROR err = CHIP_NO_ERROR;
- // If we do not have a discriminator, generate one
- chip::SetupPayload payload;
- uint32_t setUpPINCode;
- uint16_t setUpDiscriminator;
- uint16_t vendorId;
- uint16_t productId;
- std::string result;
- err = ConfigurationMgr().GetSetupPinCode(setUpPINCode);
- SuccessOrExit(err);
- err = ConfigurationMgr().GetSetupDiscriminator(setUpDiscriminator);
- SuccessOrExit(err);
- err = ConfigurationMgr().GetVendorId(vendorId);
- SuccessOrExit(err);
- err = ConfigurationMgr().GetProductId(productId);
- SuccessOrExit(err);
- payload.version = 0;
- payload.vendorID = vendorId;
- payload.productID = productId;
- payload.setUpPINCode = setUpPINCode;
- payload.discriminator = setUpDiscriminator;
- // Wrap it so SuccessOrExit can work
- {
- chip::QRCodeSetupPayloadGenerator generator(payload);
- err = generator.payloadBase38Representation(result);
- SuccessOrExit(err);
- }
- std::cout << "SetupPINCode: [" << setUpPINCode << "]" << std::endl;
- // There might be whitespace in setup QRCode, add brackets to make it clearer.
- std::cout << "SetupQRCode: [" << result << "]" << std::endl;
- exit:
- if (err != CHIP_NO_ERROR)
- {
- std::cerr << "Failed to generate QR Code: " << ErrorStr(err) << std::endl;
- }
- return err;
- }
- } // namespace
- void ApplicationInit() {}
- int main(int argc, char * argv[])
- {
- CHIP_ERROR err = CHIP_NO_ERROR;
- // Clear out the device database
- memset(gDevices, 0, sizeof(gDevices));
- // Create Mock Devices
- // Define 4 lights
- DeviceOnOff Light1("Light 1", "Office");
- DeviceOnOff Light2("Light 2", "Office");
- DeviceOnOff Light3("Light 3", "Office");
- DeviceOnOff Light4("Light 4", "Den");
- Light1.SetChangeCallback(&HandleDeviceOnOffStatusChanged);
- Light2.SetChangeCallback(&HandleDeviceOnOffStatusChanged);
- Light3.SetChangeCallback(&HandleDeviceOnOffStatusChanged);
- Light4.SetChangeCallback(&HandleDeviceOnOffStatusChanged);
- Light1.SetReachable(true);
- Light2.SetReachable(true);
- Light3.SetReachable(true);
- Light4.SetReachable(true);
- // Define 2 switches
- DeviceSwitch Switch1("Switch 1", "Office", EMBER_AF_SWITCH_FEATURE_LATCHING_SWITCH);
- DeviceSwitch Switch2("Switch 2", "Office",
- EMBER_AF_SWITCH_FEATURE_MOMENTARY_SWITCH | EMBER_AF_SWITCH_FEATURE_MOMENTARY_SWITCH_RELEASE |
- EMBER_AF_SWITCH_FEATURE_MOMENTARY_SWITCH_LONG_PRESS |
- EMBER_AF_SWITCH_FEATURE_MOMENTARY_SWITCH_MULTI_PRESS);
- Switch1.SetChangeCallback(&HandleDeviceSwitchStatusChanged);
- Switch2.SetChangeCallback(&HandleDeviceSwitchStatusChanged);
- Switch1.SetReachable(true);
- Switch2.SetReachable(true);
- // Initialize CHIP
- err = chip::Platform::MemoryInit();
- SuccessOrExit(err);
- err = ParseArguments(argc, argv);
- SuccessOrExit(err);
- err = chip::DeviceLayer::PlatformMgr().InitChipStack();
- SuccessOrExit(err);
- err = PrintQRCodeContent();
- SuccessOrExit(err);
- chip::DeviceLayer::PlatformMgrImpl().AddEventHandler(EventHandler, 0);
- chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName(nullptr); // Use default device name (CHIP-XXXX)
- #if CONFIG_NETWORK_LAYER_BLE
- chip::DeviceLayer::Internal::BLEMgrImpl().ConfigureBle(LinuxDeviceOptions::GetInstance().mBleDevice, false);
- #endif
- chip::DeviceLayer::ConnectivityMgr().SetBLEAdvertisingEnabled(true);
- // Init ZCL Data Model and CHIP App Server
- chip::Server::GetInstance().Init();
- // Initialize device attestation config
- SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
- // Set starting endpoint id where dynamic endpoints will be assigned, which
- // will be the next consecutive endpoint id after the last fixed endpoint.
- gFirstDynamicEndpointId = static_cast<chip::EndpointId>(
- static_cast<int>(emberAfEndpointFromIndex(static_cast<uint16_t>(emberAfFixedEndpointCount() - 1))) + 1);
- gCurrentEndpointId = gFirstDynamicEndpointId;
- // Disable last fixed endpoint, which is used as a placeholder for all of the
- // supported clusters so that ZAP will generated the requisite code.
- emberAfEndpointEnableDisable(emberAfEndpointFromIndex(static_cast<uint16_t>(emberAfFixedEndpointCount() - 1)), false);
- // Add lights 1..3 --> will be mapped to ZCL endpoints 2, 3, 4
- AddDeviceEndpoint(&Light1, &bridgedLightEndpoint, DEVICE_TYPE_LO_ON_OFF_LIGHT);
- AddDeviceEndpoint(&Light2, &bridgedLightEndpoint, DEVICE_TYPE_LO_ON_OFF_LIGHT);
- AddDeviceEndpoint(&Light3, &bridgedLightEndpoint, DEVICE_TYPE_LO_ON_OFF_LIGHT);
- // Remove Light 2 -- Lights 1 & 3 will remain mapped to endpoints 2 & 4
- RemoveDeviceEndpoint(&Light2);
- // Add Light 4 -- > will be mapped to ZCL endpoint 5
- AddDeviceEndpoint(&Light4, &bridgedLightEndpoint, DEVICE_TYPE_LO_ON_OFF_LIGHT);
- // Re-add Light 2 -- > will be mapped to ZCL endpoint 6
- AddDeviceEndpoint(&Light2, &bridgedLightEndpoint, DEVICE_TYPE_LO_ON_OFF_LIGHT);
- // Add switch 1..2 --> will be mapped to ZCL endpoints 7,8
- AddDeviceEndpoint(&Switch1, &bridgedSwitchEndpoint, DEVICE_TYPE_LO_ON_OFF_LIGHT_SWITCH);
- AddDeviceEndpoint(&Switch2, &bridgedSwitchEndpoint, DEVICE_TYPE_LO_ON_OFF_LIGHT_SWITCH);
- // Run CHIP
- chip::DeviceLayer::PlatformMgr().RunEventLoop();
- exit:
- if (err != CHIP_NO_ERROR)
- {
- std::cerr << "Failed to run Linux Bridge App: " << ErrorStr(err) << std::endl;
- // End the program with non zero error code to indicate a error.
- return 1;
- }
- return 0;
- }
|