From 6c3f9e1cb452841b1deab9a3a211ca0bd1ff4c84 Mon Sep 17 00:00:00 2001 From: Albert Chaulk Date: Mon, 15 Aug 2022 14:21:35 -0400 Subject: [PATCH 01/14] Update bridge app Cluster definitions are automatically generated from the IDL and devices automatically route read/writes to the appropriate cluster. Writes can be intercepted on a per-cluster basis to talk to whatever bridged backend there is. --- examples/bridge-app/linux/BUILD.gn | 33 +- examples/bridge-app/linux/Clusters.cpp | 75 ++ examples/bridge-app/linux/Device.cpp | 303 +----- examples/bridge-app/linux/DynamicDevice.cpp | 75 ++ .../bridge-app/linux/UserInputBackend.cpp | 589 ++++++++++++ .../bridge-app/linux/bridged-actions-stub.cpp | 16 +- examples/bridge-app/linux/include/Backend.h | 21 + examples/bridge-app/linux/include/Clusters.h | 293 ++++++ examples/bridge-app/linux/include/Device.h | 254 +---- .../bridge-app/linux/include/DeviceImpl.h | 21 + .../bridge-app/linux/include/DynamicDevice.h | 123 +++ examples/bridge-app/linux/include/main.h | 35 +- examples/bridge-app/linux/main.cpp | 910 +----------------- scripts/codegen.py | 5 + scripts/idl/BUILD.gn | 2 + .../generators/cpp/BridgeClustersCpp.jinja | 240 +++++ scripts/idl/generators/cpp/__init__.py | 179 ++++ scripts/idl/test_generators.py | 3 + scripts/idl/tests/available_tests.yaml | 13 + .../cpp/BridgeClustersImpl.h | 148 +++ .../cpp/BridgeClustersImpl.h | 171 ++++ .../several_clusters/cpp/BridgeClustersImpl.h | 334 +++++++ .../simple_attribute/cpp/BridgeClustersImpl.h | 134 +++ 23 files changed, 2597 insertions(+), 1380 deletions(-) create mode 100644 examples/bridge-app/linux/Clusters.cpp create mode 100644 examples/bridge-app/linux/DynamicDevice.cpp create mode 100644 examples/bridge-app/linux/UserInputBackend.cpp create mode 100644 examples/bridge-app/linux/include/Backend.h create mode 100644 examples/bridge-app/linux/include/Clusters.h create mode 100644 examples/bridge-app/linux/include/DeviceImpl.h create mode 100644 examples/bridge-app/linux/include/DynamicDevice.h create mode 100644 scripts/idl/generators/cpp/BridgeClustersCpp.jinja create mode 100644 scripts/idl/generators/cpp/__init__.py create mode 100644 scripts/idl/tests/outputs/cluster_struct_attribute/cpp/BridgeClustersImpl.h create mode 100644 scripts/idl/tests/outputs/global_struct_attribute/cpp/BridgeClustersImpl.h create mode 100644 scripts/idl/tests/outputs/several_clusters/cpp/BridgeClustersImpl.h create mode 100644 scripts/idl/tests/outputs/simple_attribute/cpp/BridgeClustersImpl.h diff --git a/examples/bridge-app/linux/BUILD.gn b/examples/bridge-app/linux/BUILD.gn index 3912e887a846be..fadf198709d7a8 100644 --- a/examples/bridge-app/linux/BUILD.gn +++ b/examples/bridge-app/linux/BUILD.gn @@ -12,31 +12,58 @@ # See the License for the specific language governing permissions and # limitations under the License. +import("//build_overrides/build.gni") import("//build_overrides/chip.gni") import("${chip_root}/build/chip/tools.gni") assert(chip_build_tools) +action("chip-bridge-codegen") { + script = "${chip_root}/scripts/codegen.py" + sources = + [ "${chip_root}/examples/bridge-app/bridge-common/bridge-app.matter" ] + outputs = [ "$target_gen_dir/cpp/BridgeClustersImpl.h" ] + + args = [ + "--generator", + "cpp", + "--output-dir", + rebase_path(target_gen_dir, root_build_dir), + rebase_path( + "${chip_root}/examples/bridge-app/bridge-common/bridge-app.matter", + root_build_dir), + ] + deps = [ "${chip_root}/scripts/idl" ] +} + executable("chip-bridge-app") { sources = [ "${chip_root}/examples/bridge-app/linux/bridged-actions-stub.cpp", "${chip_root}/examples/tv-app/tv-common/include/CHIPProjectAppConfig.h", + "Clusters.cpp", "Device.cpp", + "DynamicDevice.cpp", + "UserInputBackend.cpp", "include/Device.h", "include/main.h", "main.cpp", ] deps = [ + ":chip-bridge-codegen", "${chip_root}/examples/bridge-app/bridge-common", "${chip_root}/examples/platform/linux:app-main", + "${chip_root}/src/app/tests/suites/credentials:dac_provider", "${chip_root}/src/lib", ] cflags = [ "-Wconversion" ] - include_dirs = [ "include" ] + include_dirs = [ + "include", + target_gen_dir, + ] output_dir = root_out_dir } @@ -44,3 +71,7 @@ executable("chip-bridge-app") { group("linux") { deps = [ ":chip-bridge-app" ] } + +group("default") { + deps = [ ":linux" ] +} diff --git a/examples/bridge-app/linux/Clusters.cpp b/examples/bridge-app/linux/Clusters.cpp new file mode 100644 index 00000000000000..24948043580ca5 --- /dev/null +++ b/examples/bridge-app/linux/Clusters.cpp @@ -0,0 +1,75 @@ +#include "Clusters.h" + +#include "Device.h" + +CommonCluster * CommonAttributeAccessInterface::FindCluster(const chip::app::ConcreteClusterPath & path) +{ + Device * dev = FindDeviceEndpoint(path.mEndpointId); + if (dev) + { + for (auto c : dev->clusters()) + { + if (c->GetClusterId() == path.mClusterId) + return static_cast(c); + } + } + return nullptr; +} + +void CommonCluster::SetEndpointId(chip::EndpointId id) +{ + mEndpoint = id; +} +chip::EndpointId CommonCluster::GetEndpointId() const +{ + return mEndpoint; +} + +void CommonCluster::SetCallback(PropagateWriteCB * cb) +{ + mCallback = cb; +} + +bool CommonCluster::active() const +{ + return mEndpoint < 0xFFFF; +} + +CHIP_ERROR CommonCluster::ForwardWriteToBridge(const chip::app::ConcreteDataAttributePath & aPath, + chip::app::AttributeValueDecoder & aDecoder) +{ + if (mCallback) + return (*mCallback)(this, aPath, aDecoder); + return WriteFromBridge(aPath, aDecoder); +} + +void CommonCluster::OnUpdated(chip::AttributeId attr) +{ + if (active()) + MatterReportingAttributeChangeCallback(GetEndpointId(), GetClusterId(), attr); +} + +bool CommonCluster::Push(chip::AttributeId attr, chip::TLV::TLVReader & reader) +{ + chip::app::AttributeValueDecoder decoder(reader, chip::Access::SubjectDescriptor()); + if (WriteFromBridge(chip::app::ConcreteDataAttributePath(GetEndpointId(), GetClusterId(), attr), decoder) != CHIP_NO_ERROR) + return false; + OnUpdated(attr); + return true; +} + +namespace clusters { +BridgedDeviceBasicCluster::BridgedDeviceBasicCluster() {} + +CHIP_ERROR BridgedDeviceBasicCluster::WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, + chip::app::AttributeValueDecoder & aDecoder) +{ + switch (aPath.mAttributeId) + { + case ZCL_REACHABLE_ATTRIBUTE_ID: + return mReachable.Write(aPath, aDecoder); + } + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +} // namespace clusters diff --git a/examples/bridge-app/linux/Device.cpp b/examples/bridge-app/linux/Device.cpp index eae3eff40de3c2..05a78bf94a17ad 100644 --- a/examples/bridge-app/linux/Device.cpp +++ b/examples/bridge-app/linux/Device.cpp @@ -22,298 +22,13 @@ #include #include -using namespace chip::app::Clusters::Actions; - -// LightingManager LightingManager::sLight; - -Device::Device(const char * szDeviceName, std::string szLocation) -{ - strncpy(mName, szDeviceName, sizeof(mName)); - mLocation = szLocation; - mReachable = false; - mEndpointId = 0; -} - -bool Device::IsReachable() -{ - return mReachable; -} - -void Device::SetReachable(bool aReachable) -{ - bool changed = (mReachable != aReachable); - - mReachable = aReachable; - - if (aReachable) - { - ChipLogProgress(DeviceLayer, "Device[%s]: ONLINE", mName); - } - else - { - ChipLogProgress(DeviceLayer, "Device[%s]: OFFLINE", mName); - } - - if (changed) - { - HandleDeviceChange(this, kChanged_Reachable); - } -} - -void Device::SetName(const char * szName) -{ - bool changed = (strncmp(mName, szName, sizeof(mName)) != 0); - - ChipLogProgress(DeviceLayer, "Device[%s]: New Name=\"%s\"", mName, szName); - - strncpy(mName, szName, sizeof(mName)); - - if (changed) - { - HandleDeviceChange(this, kChanged_Name); - } -} - -void Device::SetLocation(std::string szLocation) -{ - bool changed = (mLocation.compare(szLocation) != 0); - - mLocation = szLocation; - - ChipLogProgress(DeviceLayer, "Device[%s]: Location=\"%s\"", mName, mLocation.c_str()); - - if (changed) - { - HandleDeviceChange(this, kChanged_Location); - } -} - -DeviceOnOff::DeviceOnOff(const char * szDeviceName, std::string szLocation) : Device(szDeviceName, szLocation) -{ - mOn = false; -} - -bool DeviceOnOff::IsOn() -{ - return mOn; -} - -void DeviceOnOff::SetOnOff(bool aOn) -{ - bool changed; - - changed = aOn ^ mOn; - mOn = aOn; - ChipLogProgress(DeviceLayer, "Device[%s]: %s", mName, aOn ? "ON" : "OFF"); - - if ((changed) && (mChanged_CB)) - { - mChanged_CB(this, kChanged_OnOff); - } -} - -void DeviceOnOff::Toggle() -{ - bool aOn = !IsOn(); - SetOnOff(aOn); -} - -void DeviceOnOff::SetChangeCallback(DeviceCallback_fn aChanged_CB) -{ - mChanged_CB = aChanged_CB; -} - -void DeviceOnOff::HandleDeviceChange(Device * device, Device::Changed_t changeMask) -{ - if (mChanged_CB) - { - mChanged_CB(this, (DeviceOnOff::Changed_t) changeMask); - } -} - -DeviceSwitch::DeviceSwitch(const char * szDeviceName, std::string szLocation, uint32_t aFeatureMap) : - Device(szDeviceName, szLocation) -{ - mNumberOfPositions = 2; - mCurrentPosition = 0; - mMultiPressMax = 2; - mFeatureMap = aFeatureMap; -} - -void DeviceSwitch::SetNumberOfPositions(uint8_t aNumberOfPositions) -{ - bool changed; - - changed = aNumberOfPositions != mNumberOfPositions; - mNumberOfPositions = aNumberOfPositions; - - if ((changed) && (mChanged_CB)) - { - mChanged_CB(this, kChanged_NumberOfPositions); - } -} - -void DeviceSwitch::SetCurrentPosition(uint8_t aCurrentPosition) -{ - bool changed; - - changed = aCurrentPosition != mCurrentPosition; - mCurrentPosition = aCurrentPosition; - - if ((changed) && (mChanged_CB)) - { - mChanged_CB(this, kChanged_CurrentPosition); - } -} - -void DeviceSwitch::SetMultiPressMax(uint8_t aMultiPressMax) -{ - bool changed; - - changed = aMultiPressMax != mMultiPressMax; - mMultiPressMax = aMultiPressMax; - - if ((changed) && (mChanged_CB)) - { - mChanged_CB(this, kChanged_MultiPressMax); - } -} - -void DeviceSwitch::SetChangeCallback(DeviceCallback_fn aChanged_CB) -{ - mChanged_CB = aChanged_CB; -} - -void DeviceSwitch::HandleDeviceChange(Device * device, Device::Changed_t changeMask) -{ - if (mChanged_CB) - { - mChanged_CB(this, (DeviceSwitch::Changed_t) changeMask); - } -} - -DeviceTempSensor::DeviceTempSensor(const char * szDeviceName, std::string szLocation, int16_t min, int16_t max, - int16_t measuredValue) : - Device(szDeviceName, szLocation), - mMin(min), mMax(max), mMeasurement(measuredValue) -{} - -void DeviceTempSensor::SetMeasuredValue(int16_t measurement) -{ - // Limit measurement based on the min and max. - if (measurement < mMin) - { - measurement = mMin; - } - else if (measurement > mMax) - { - measurement = mMax; - } - - bool changed = mMeasurement != measurement; - - ChipLogProgress(DeviceLayer, "TempSensorDevice[%s]: New measurement=\"%d\"", mName, measurement); - - mMeasurement = measurement; - - if (changed && mChanged_CB) - { - mChanged_CB(this, kChanged_MeasurementValue); - } -} - -void DeviceTempSensor::SetChangeCallback(DeviceCallback_fn aChanged_CB) -{ - mChanged_CB = aChanged_CB; -} - -void DeviceTempSensor::HandleDeviceChange(Device * device, Device::Changed_t changeMask) -{ - if (mChanged_CB) - { - mChanged_CB(this, (DeviceTempSensor::Changed_t) changeMask); - } -} - -void ComposedDevice::HandleDeviceChange(Device * device, Device::Changed_t changeMask) -{ - if (mChanged_CB) - { - mChanged_CB(this, (ComposedDevice::Changed_t) changeMask); - } -} - -void DevicePowerSource::HandleDeviceChange(Device * device, Device::Changed_t changeMask) -{ - if (mChanged_CB) - { - mChanged_CB(this, (DevicePowerSource::Changed_t) changeMask); - } -} - -void DevicePowerSource::SetBatChargeLevel(uint8_t aBatChargeLevel) -{ - bool changed; - - changed = aBatChargeLevel != mBatChargeLevel; - mBatChargeLevel = aBatChargeLevel; - - if ((changed) && (mChanged_CB)) - { - mChanged_CB(this, kChanged_BatLevel); - } -} - -void DevicePowerSource::SetDescription(std::string aDescription) -{ - bool changed; - - changed = aDescription != mDescription; - mDescription = aDescription; - - if ((changed) && (mChanged_CB)) - { - mChanged_CB(this, kChanged_Description); - } -} - -EndpointListInfo::EndpointListInfo(uint16_t endpointListId, std::string name, EndpointListTypeEnum type) -{ - mEndpointListId = endpointListId; - mName = name; - mType = type; -} - -EndpointListInfo::EndpointListInfo(uint16_t endpointListId, std::string name, EndpointListTypeEnum type, - chip::EndpointId endpointId) -{ - mEndpointListId = endpointListId; - mName = name; - mType = type; - mEndpoints.push_back(endpointId); -} - -void EndpointListInfo::AddEndpointId(chip::EndpointId endpointId) -{ - mEndpoints.push_back(endpointId); -} - -Room::Room(std::string name, uint16_t endpointListId, EndpointListTypeEnum type, bool isVisible) -{ - mName = name; - mEndpointListId = endpointListId; - mType = type; - mIsVisible = isVisible; -} - -Action::Action(uint16_t actionId, std::string name, ActionTypeEnum type, uint16_t endpointListId, uint16_t supportedCommands, - ActionStateEnum status, bool isVisible) -{ - mActionId = actionId; - mName = name; - mType = type; - mEndpointListId = endpointListId; - mSupportedCommands = supportedCommands; - mStatus = status; - mIsVisible = isVisible; +Device::Device(chip::Span dataVersions, chip::Span clusters, + chip::Span clusterImpl, const chip::Span & deviceTypeList, + chip::EndpointId parentId) : + mParentEndpointId(parentId), + mDataVersions(dataVersions), mClusters(clusters), mClusterImpl(clusterImpl), mDeviceTypeList(deviceTypeList) +{ + mEndpointId = id; + for (auto * c : mClusterImpl) + c->SetEndpointId(id); } diff --git a/examples/bridge-app/linux/DynamicDevice.cpp b/examples/bridge-app/linux/DynamicDevice.cpp new file mode 100644 index 00000000000000..9f1d3eded05158 --- /dev/null +++ b/examples/bridge-app/linux/DynamicDevice.cpp @@ -0,0 +1,75 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * 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 "DynamicDevice.h" + +void DynamicAttributeList::Add(chip::AttributeId id, EmberAfAttributeType type, uint16_t maxSize, EmberAfClusterMask mask) +{ + // Do what DECLARE_DYNAMIC_ATTRIBUTE does. + mAttributeDecls.emplace_back( + EmberAfAttributeMetadata{ id, type, maxSize, (uint8_t)(mask | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE)), ZAP_EMPTY_DEFAULT() }); +} + +void DynamicAttributeList::Add(EmberAfAttributeMetadata metadata) +{ + mAttributeDecls.emplace_back(metadata); +} + +DynamicDeviceImpl::DynamicDeviceImpl() {} + +void DynamicDeviceImpl::AddDeviceType(EmberAfDeviceType type) +{ + mDeviceTypes.push_back(type); +} + +Device DynamicDeviceImpl::CreateDevice() +{ + // All nodes are bridged devices. + mDeviceTypes.push_back(EmberAfDeviceType{ DEVICE_TYPE_BRIDGED_NODE, DEVICE_VERSION_DEFAULT }); + mVersions.resize(mClusterRawPtrs.size()); + for (auto * c : mClusterRawPtrs) + mClusterBaseRawPtrs.push_back(c); + + return Device(chip::Span(mVersions.data(), mVersions.size()), + chip::Span(mClusterDecls.data(), mClusterDecls.size()), + chip::Span(mClusterBaseRawPtrs.data(), mClusterBaseRawPtrs.size()), + chip::Span(mDeviceTypes.data(), mDeviceTypes.size()), mParentEndpointId); +} + +DynamicDeviceImpl & DynamicDeviceImpl::AddCluster(std::unique_ptr cluster, const DynamicAttributeList & attribs, + const chip::CommandId * incomingCommands, + const chip::CommandId * outgoingCommands) +{ + AddCluster(cluster.get(), attribs, incomingCommands, outgoingCommands); + mClusters.emplace_back(std::move(cluster)); + return *this; +} + +DynamicDeviceImpl & DynamicDeviceImpl::AddCluster(CommonCluster * cluster, const DynamicAttributeList & attribs, + const chip::CommandId * incomingCommands, + const chip::CommandId * outgoingCommands) +{ + mAttribStorage.push_back(attribs.mAttributeDecls); + // Do what DECLARE_DYNAMIC_CLUSTER does. + mClusterDecls.emplace_back(EmberAfCluster{ cluster->GetClusterId(), mAttribStorage.back().data(), + (uint16_t) mAttribStorage.back().size(), 0, ZAP_CLUSTER_MASK(SERVER), nullptr, + incomingCommands, outgoingCommands }); + mClusterRawPtrs.emplace_back(cluster); + return *this; +} diff --git a/examples/bridge-app/linux/UserInputBackend.cpp b/examples/bridge-app/linux/UserInputBackend.cpp new file mode 100644 index 00000000000000..076895cc66a1d1 --- /dev/null +++ b/examples/bridge-app/linux/UserInputBackend.cpp @@ -0,0 +1,589 @@ +#include "Backend.h" +#include "DynamicDevice.h" +#include "main.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace { + +std::vector> g_devices; +std::vector> g_device_impls; +std::unique_ptr g_pending; + +// Pseudo-index representing the device being built. +static constexpr int kPendingDeviceIndex = -1; + +PropagateWriteCB g_write_cb = [](CommonCluster * cluster, const chip::app::ConcreteDataAttributePath & path, + chip::app::AttributeValueDecoder & decoder) -> CHIP_ERROR { + CHIP_ERROR ret = cluster->WriteFromBridge(path, decoder); + printf("Write to ep %d cluster %d attribute %d ret %" CHIP_ERROR_FORMAT "\n", path.mEndpointId, path.mClusterId, + path.mAttributeId, ret.Format()); + return ret; +}; + +const char * ParseValue(const std::vector & tokens, size_t index, std::string * v) +{ + if (index >= tokens.size()) + return "Missing argument"; + *v = tokens[index]; + return nullptr; +} +const char * ParseValue(const std::vector & tokens, size_t index, chip::Optional * v) +{ + if (index < tokens.size()) + v->SetValue(tokens[index]); + return nullptr; +} + +template ::value>> +const char * ParseValue(const std::vector & tokens, size_t index, T * v) +{ + if (index >= tokens.size()) + return "Missing argument"; + const char * start = tokens[index].data(); + const char * end = start + tokens[index].size(); + auto ret = std::from_chars(start, end, *v); + if (ret.ptr != end) + return "Cannot parse as integer"; + return nullptr; +} + +template ::value>> +const char * ParseValue(const std::vector & tokens, size_t index, chip::Optional * v) +{ + uint32_t temp; + if (!ParseValue(tokens, index, &temp)) + v->SetValue(temp); + return nullptr; +} + +const char * Parse(const std::vector & tokens, size_t index) +{ + if (index >= tokens.size()) + return nullptr; + return "Unexpected extra tokens"; +} + +template +const char * Parse(const std::vector & tokens, size_t index, T arg0, Args... args) +{ + auto ret = ParseValue(tokens, index, arg0); + return ret ? ret : Parse(tokens, index + 1, args...); +} + +void NewDevice(const std::vector & tokens) +{ + if (g_pending) + { + printf("Already pending device!\n"); + return; + } + + chip::Optional type; + const char * err = Parse(tokens, 0, &type); + if (err) + { + printf("Error: %s\nExpected [prebuilt-device-type]\n", err); + } + else if (!type.HasValue()) + { + g_pending = std::make_unique(); + } + else if (type.Value() == "switch") + { + g_pending = std::make_unique(); + } + else + { + printf("Unknown device type %s\nSupported types: switch\n", type.Value().c_str()); + } +} + +void AddCluster(const std::vector & tokens) +{ + if (!g_pending) + { + printf("Expected pending device! Run new-device\n"); + return; + } + std::string cluster_name; + const char * err = Parse(tokens, 0, &cluster_name); + if (err) + { + printf("Error: %s\n", err); + return; + } + + for (const auto & cluster : clusters::kKnownClusters) + { + if (cluster_name == cluster.name) + { + std::unique_ptr obj(cluster.ctor(::operator new(cluster.size))); + DynamicAttributeList dynamic_attrs; + auto attrs = obj->GetAllAttributes(); + for (auto & attr : attrs) + dynamic_attrs.Add(attr); + g_pending->AddCluster(std::move(obj), dynamic_attrs, nullptr, nullptr); + printf("Added cluster %s/%d\n", cluster.name, cluster.id); + return; + } + } +} + +void CancelDevice(const std::vector & tokens) +{ + const char * err = Parse(tokens, 0); + if (err) + { + printf("Error: %s\n", err); + return; + } + + g_pending.reset(nullptr); +} + +void FinishDevice(const std::vector & tokens) +{ + if (!g_pending) + { + printf("Expected pending device! Run new-device\n"); + return; + } + + const char * err = Parse(tokens, 0); + if (err) + { + printf("Error: %s\n", err); + return; + } + + for (auto * c : g_pending->clusters()) + c->SetCallback(&g_write_cb); + + auto dev = std::make_unique(g_pending->CreateDevice()); + int ep = AddDeviceEndpoint(dev.get()); + if (ep < 0) + { + printf("Failed to add device\n"); + } + else + { + printf("Added device at index %d\n", ep); + size_t index = (size_t) ep; + if (g_devices.size() <= index) + { + g_devices.resize(index + 1); + g_device_impls.resize(index + 1); + } + g_devices[index] = std::move(dev); + g_device_impls[index] = std::move(g_pending); + } +} + +void RemoveDevice(const std::vector & tokens) +{ + uint32_t index; + const char * err = Parse(tokens, 0, &index); + if (err) + { + printf("Error: %s.\nExpected index of a device\n", err); + return; + } + if (index >= g_devices.size()) + { + printf("%d is an invalid index\n", index); + return; + } + + RemoveDeviceEndpoint(g_devices[index].get()); + + for (auto & room : gRooms) + room.RemoveEndpoint(g_devices[index]->GetEndpointId()); + + g_devices[index] = nullptr; + g_device_impls[index] = nullptr; +} + +void AddType(const std::vector & tokens) +{ + if (!g_pending) + { + printf("Expected pending device! Run new-device\n"); + return; + } + uint32_t type; + chip::Optional version; + const char * err = Parse(tokens, 0, &type, &version); + if (err) + { + printf("Error: %s.\nExpected: type [version]\n", err); + return; + } + EmberAfDeviceType devType = { (uint16_t) type, (uint8_t) version.ValueOr(1u) }; + printf("Adding device type %d ver %d\n", devType.deviceId, devType.deviceVersion); + + g_pending->AddDeviceType(devType); +} + +DynamicDeviceImpl * FindDevice(int32_t index) +{ + if (index == kPendingDeviceIndex) + { + return g_pending.get(); + } + else if ((uint32_t) index < g_device_impls.size()) + { + return g_device_impls[index].get(); + } + else + { + return nullptr; + } +} + +Device * FindEndpoint(int32_t index) +{ + if (index >= 0 && (uint32_t) index < g_device_impls.size()) + { + return g_devices[index].get(); + } + else + { + return nullptr; + } +} + +ClusterImpl * FindCluster(DynamicDeviceImpl * dev, const std::string & clusterId) +{ + uint32_t id; + const char * start = clusterId.data(); + const char * end = start + clusterId.size(); + if (std::from_chars(start, end, id).ptr != end) + { + id = 0; + for (const auto & c : clusters::kKnownClusters) + { + if (clusterId == c.name) + { + id = c.id; + break; + } + } + if (!id) + return nullptr; + } + + for (auto * c : dev->clusters()) + { + if (c->GetClusterId() == id) + { + return c; + } + } + return nullptr; +} + +const EmberAfAttributeMetadata * FindAttrib(ClusterImpl * cluster, const std::string & attrId) +{ + uint32_t id; + const char * start = attrId.data(); + const char * end = start + attrId.size(); + if (std::from_chars(start, end, id).ptr != end) + { + auto clusterId = cluster->GetClusterId(); + id = 0; + for (const auto & c : clusters::kKnownAttributes) + { + if (c.cluster == clusterId && attrId == c.name) + { + id = c.attr; + break; + } + } + if (!id) + return nullptr; + } + + for (auto & attr : cluster->GetAllAttributes()) + { + if (attr.attributeId == id) + { + return &attr; + } + } + return nullptr; +} + +void ParseValue(std::vector * data, uint16_t size, const std::string & str, EmberAfAttributeType type) +{ + chip::TLV::TLVWriter wr; + wr.Init(data->data(), data->size()); + switch (type) + { + case ZCL_OCTET_STRING_ATTRIBUTE_TYPE: + case ZCL_CHAR_STRING_ATTRIBUTE_TYPE: + wr.PutString(chip::TLV::Tag(), str.data(), (uint32_t) str.size()); + break; + case ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE: + case ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE: + wr.PutBytes(chip::TLV::Tag(), (const uint8_t *) str.data(), (uint32_t) str.size()); + break; + case ZCL_STRUCT_ATTRIBUTE_TYPE: + // Writing structs not supported yet + break; + case ZCL_SINGLE_ATTRIBUTE_TYPE: + wr.Put(chip::TLV::Tag(), (float) atof(str.c_str())); + break; + case ZCL_DOUBLE_ATTRIBUTE_TYPE: + wr.Put(chip::TLV::Tag(), atof(str.c_str())); + break; + default: + // Assume integer + wr.Put(chip::TLV::Tag(), (int64_t) strtoll(str.c_str(), nullptr, 10)); + break; + } + wr.Finalize(); + data->resize(wr.GetLengthWritten()); +} + +void SetValue(const std::vector & tokens) +{ + std::string attrId; + int32_t index; + std::string clusterId; + std::string value; + const char * err = Parse(tokens, 0, &index, &clusterId, &attrId, &value); + if (err) + { + printf("Error: %s.\nExpected: deviceIndex clusterId attributeId value\nUse deviceIndex -1 for pending device.\n", err); + return; + } + + DynamicDeviceImpl * dev = FindDevice(index); + if (!dev) + { + printf("Could not find device at index %d\n", index); + return; + } + + ClusterImpl * cluster = FindCluster(dev, clusterId); + if (!cluster) + { + printf("Device does not implement cluster %s\nSupported clusters: ", clusterId.c_str()); + for (auto * c : dev->clusters()) + { + printf("%d ", c->GetClusterId()); + } + printf("\n"); + return; + } + + const EmberAfAttributeMetadata * attr = FindAttrib(cluster, attrId); + if (!attr) + { + printf("Cluster does not implement attr %s\nSupported attributes: ", attrId.c_str()); + for (auto attrMeta : cluster->GetAllAttributes()) + { + printf("%d ", attrMeta.attributeId); + } + printf("\n"); + return; + } + + std::vector data(attr->size + 64); + ParseValue(&data, attr->size, value, attr->attributeType); + + chip::TLV::TLVReader rd; + rd.Init(data.data(), data.size()); + + if (!cluster->Push(attr->attributeId, rd)) + { + printf("Write failed\n"); + } +} + +void AddRoom(const std::vector & tokens) +{ + if (tokens.size() != 1) + { + printf("Expected exactly one string\n"); + return; + } + auto room = FindRoom(tokens[0]); + if (room) + { + printf("Room already exists\n"); + return; + } +} + +void DelRoom(const std::vector & tokens) +{ + if (tokens.size() != 1) + { + printf("Expected exactly one string\n"); + return; + } + auto room = FindRoom(tokens[0]); + if (!room) + { + printf("No such room\n"); + return; + } + + room->SetName(std::string()); + while (room->GetEndpointListSize() > 0) + room->RemoveEndpoint(*room->GetEndpointListData()); +} + +void AddToRoom(const std::vector & tokens) +{ + uint32_t index; + std::string room; + const char * err = Parse(tokens, 0, &room, &index); + if (err) + { + printf("Error: %s.\nExpected: room index.\n", err); + return; + } + auto roomPtr = FindRoom(tokens[0]); + if (!roomPtr) + { + printf("No such room\n"); + return; + } + auto dev = FindEndpoint(index); + if (!dev) + { + printf("No such device\n"); + return; + } + roomPtr->AddEndpoint(dev->GetEndpointId()); +} + +void DelFromRoom(const std::vector & tokens) +{ + uint32_t index; + std::string room; + const char * err = Parse(tokens, 0, &room, &index); + if (err) + { + printf("Error: %s.\nExpected: room index.\n", err); + return; + } + auto roomPtr = FindRoom(tokens[0]); + if (!roomPtr) + { + printf("No such room\n"); + return; + } + auto dev = FindEndpoint(index); + if (!dev) + { + printf("No such device\n"); + return; + } + roomPtr->RemoveEndpoint(dev->GetEndpointId()); +} + +void SetParentId(const std::vector & tokens) +{ + if (!g_pending) + { + printf("Expected pending device! Run new-device\n"); + return; + } + + int32_t index; + const char * err = Parse(tokens, 0, &index); + if (err) + { + printf("Error: %s.\nExpected: deviceIndex\n", err); + return; + } + auto dev = FindEndpoint(index); + if (!dev) + { + printf("No such device\n"); + return; + } + g_pending->SetParentEndpointId(dev->GetEndpointId()); +} + +void Help(const std::vector & tokens); + +struct Command +{ + const char * name; + const char * desc; + void (*fn)(const std::vector & tokens); +} const commands[] = { + { "help", "", &Help }, + { "new-device", "[type] - Begin adding a new device. Add device types and clusters, then finish", &NewDevice }, + { "del-device", "index - Remove a device at the specified index", &RemoveDevice }, + { "add-cluster", "name - Add a cluster by name, eg FixedLabel", &AddCluster }, + { "finish-device", "Finish the currently pending device. Clusters and device types are immutable.", &FinishDevice }, + { "cancel-device", "Abort adding a new device", &CancelDevice }, + { "add-type", "id [version] - Add a device type by ID, optionally with a version", &AddType }, + { "set", "deviceIndex clusterId attributeId value - Set a value. deviceIndex -1 for adding device", &SetValue }, + { "set-parent-id", "deviceIndex - Set the parent endpoint ID to the specified device", &SetParentId }, + { "add-room", "name - Add a new named room", &AddRoom }, + { "del-room", "name - Remove an existing named room", &DelRoom }, + { "add-to-room", "name index - Add a device to a named room", &AddToRoom }, + { "del-from-room", "name index - Remove a device from a named room", &DelFromRoom }, +}; + +void Help(const std::vector & tokens) +{ + for (auto & cmd : commands) + { + printf("%s %s\n", cmd.name, cmd.desc); + } +} + +void ProcessLine(std::vector & tokens) +{ + for (auto & cmd : commands) + { + if (tokens[0] == cmd.name) + { + tokens.erase(tokens.begin()); + cmd.fn(tokens); + return; + } + } + printf("Unknown command '%s'\n", tokens[0].c_str()); +} + +void * UserInputThread(void *) +{ + std::string line; + while (true) + { + printf("? "); + std::cin >> std::ws; + std::getline(std::cin, line); + if (std::cin.eof()) + break; + + std::istringstream iss(line); + std::vector tokens{ std::istream_iterator{ iss }, std::istream_iterator{} }; + + ProcessLine(tokens); + } + return nullptr; +} + +} // namespace + +void StartUserInput() +{ + pthread_t thread; + pthread_create(&thread, nullptr, &UserInputThread, nullptr); +} diff --git a/examples/bridge-app/linux/bridged-actions-stub.cpp b/examples/bridge-app/linux/bridged-actions-stub.cpp index 9f7173e3564421..46be4848d51603 100644 --- a/examples/bridge-app/linux/bridged-actions-stub.cpp +++ b/examples/bridge-app/linux/bridged-actions-stub.cpp @@ -58,7 +58,7 @@ constexpr uint16_t ActionsAttrAccess::ClusterRevision; CHIP_ERROR ActionsAttrAccess::ReadActionListAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder) { CHIP_ERROR err = aEncoder.EncodeList([&endpoint](const auto & encoder) -> CHIP_ERROR { - std::vector actionList = GetActionListInfo(endpoint); + chip::Span actionList = GetActionListInfo(endpoint); for (auto action : actionList) { @@ -81,14 +81,20 @@ CHIP_ERROR ActionsAttrAccess::ReadActionListAttribute(EndpointId endpoint, Attri CHIP_ERROR ActionsAttrAccess::ReadEndpointListAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder) { - std::vector infoList = GetEndpointListInfo(endpoint); - - CHIP_ERROR err = aEncoder.EncodeList([&infoList](const auto & encoder) -> CHIP_ERROR { - for (auto info : infoList) + CHIP_ERROR err = aEncoder.EncodeList([](const auto & encoder) -> CHIP_ERROR { + for (auto & room : gRooms) { +<<<<<<< HEAD Actions::Structs::EndpointListStruct::Type endpointListStruct = { info.GetEndpointListId(), CharSpan::fromCharString(info.GetName().c_str()), info.GetType(), DataModel::List(info.GetEndpointListData(), info.GetEndpointListSize()) +======= + if (room.GetEndpointListSize() == 0) + continue; + BridgedActions::Structs::EndpointListStruct::Type endpointListStruct = { + room.GetEndpointListId(), CharSpan::fromCharString(room.GetName().c_str()), room.GetType(), + DataModel::List(room.GetEndpointListData(), room.GetEndpointListSize()) +>>>>>>> ebb974a33 (Update bridge app) }; ReturnErrorOnFailure(encoder.Encode(endpointListStruct)); } diff --git a/examples/bridge-app/linux/include/Backend.h b/examples/bridge-app/linux/include/Backend.h new file mode 100644 index 00000000000000..6e5ca8ee9c7e34 --- /dev/null +++ b/examples/bridge-app/linux/include/Backend.h @@ -0,0 +1,21 @@ +/* + * + * Copyright (c) 2022 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. + */ + +#pragma once + +void StartUserInput(); diff --git a/examples/bridge-app/linux/include/Clusters.h b/examples/bridge-app/linux/include/Clusters.h new file mode 100644 index 00000000000000..b36f5f2b34ec46 --- /dev/null +++ b/examples/bridge-app/linux/include/Clusters.h @@ -0,0 +1,293 @@ +/* + * + * Copyright (c) 2022 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. + */ + +#pragma once + +#include +#include +#include +#include + +#include +#include + +#include + +static constexpr uint16_t ZCL_DESCRIPTOR_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_FIXED_LABEL_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_ON_OFF_CLUSTER_REVISION = 4; +static constexpr uint16_t ZCL_SWITCH_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_LEVEL_CONTROL_CLUSTER_REVISION = 1; + +// This is the interface to cluster implementations, providing access to manipulate attributes. +class ClusterImpl +{ +public: + virtual ~ClusterImpl() = default; + + virtual void SetEndpointId(chip::EndpointId id) = 0; + virtual chip::ClusterId GetClusterId() = 0; + virtual chip::Span GetAllAttributes() = 0; + virtual bool Push(chip::AttributeId attr, chip::TLV::TLVReader & reader) = 0; +}; + +// This provides storage for a primitive binary type, eg uintN_t, float, double +template +struct PrimitiveType +{ + static constexpr EmberAfAttributeType kMatterType = AfType; + // Note that Bytes can be < sizeof(T) due to non-power-of-two byte lengths. + static constexpr uint16_t kMaxSize = Bytes; + static_assert(Bytes <= sizeof(T), "Incorrect type / byte specification"); + + static constexpr bool kIsFabricScoped = IsFabricScoped; + + PrimitiveType() = default; + PrimitiveType(T initial) : mValue(initial) {} + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) + { + return aDecoder.Decode(*this); + } + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) + { + return aEncoder.Encode(*this); + } + + CHIP_ERROR Decode(chip::TLV::TLVReader & reader) { return reader.Get(mValue); } + + CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const { return writer.Put(tag, mValue); } + + void operator=(T v) { mValue = v; } + operator T() const { return mValue; } + + T Peek() const { return mValue; } + +private: + T mValue; + static_assert(std::is_standard_layout::value, "PrimitiveType not standard layout!"); +}; + +// This provides access to a struct. Each struct generates its own access logic. +template +struct StructType : public T +{ + static constexpr EmberAfAttributeType kMatterType = ZCL_STRUCT_ATTRIBUTE_TYPE; + static constexpr uint16_t kMaxSize = sizeof(T); + static_assert(std::is_standard_layout::value, "StructType not standard layout!"); + static constexpr bool kIsFabricScoped = IsFabricScoped; + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) + { + return aDecoder.Decode(*this); + } + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) + { + return aEncoder.Encode(*this); + } +}; + +// This provides storage for short and long octet and char strings. +template +struct OctetString +{ + static constexpr EmberAfAttributeType kMatterType = AfType; + static constexpr bool kIsChar = (AfType == ZCL_CHAR_STRING_ATTRIBUTE_TYPE || AfType == ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE); + static constexpr uint16_t kMaxSize = Bytes; + + OctetString() = default; + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) + { + chip::app::DataModel::Nullable v; + CHIP_ERROR err = aDecoder.Decode(v); + if (err == CHIP_NO_ERROR) + { + if (v.IsNull() && !IsNull()) + { + mLength = 0xFFFF; + } + else if (v.Value().size() > kMaxSize) + { + err = CHIP_ERROR_BUFFER_TOO_SMALL; + } + else + { + mLength = static_cast(v.Value().size()); + memcpy(mValue, v.Value().data(), mLength); + } + } + return err; + } + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) + { + if (IsNull()) + return aEncoder.EncodeNull(); + if (kIsChar) + return aEncoder.Encode(chip::CharSpan(static_cast(mValue), mLength)); + return aEncoder.Encode(chip::ByteSpan(mValue, mLength)); + } + + chip::ByteSpan Peek() const { return IsNull() ? chip::ByteSpan() : chip::ByteSpan(mValue, mLength); } + + bool IsNull() const { return mLength == 0xFFFF; } + +private: + uint16_t mLength = 0xFFFF; + uint8_t mValue[kMaxSize]; +}; + +// This allows for an array of up to MaxElements of a specified type. +template +struct ArrayType +{ + static constexpr EmberAfAttributeType kMatterType = ZCL_ARRAY_ATTRIBUTE_TYPE; + static constexpr uint16_t kMaxSize = sizeof(T) * MaxElements; + static_assert(std::is_standard_layout::value, "Array element not standard layout!"); + + void ListWriteBegin(const chip::app::ConcreteAttributePath & aPath) {} + + void ListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) {} + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) + { + if (aPath.mListIndex.HasValue()) + { + uint16_t index = aPath.mListIndex.Value(); + if (index >= mLength || IsNull()) + return CHIP_ERROR_INVALID_ARGUMENT; + + return aEncoder.Encode(mArray[index]); + } + + if (IsNull()) + return aEncoder.EncodeNull(); + if (mLength == 0) + return aEncoder.EncodeEmptyList(); + return aEncoder.EncodeList([this](const auto & encoder) { + CHIP_ERROR err = CHIP_NO_ERROR; + for (uint16_t i = 0; i < mLength && err == CHIP_NO_ERROR; i++) + err = encoder.Encode(mArray[i]); + return err; + }); + } + + bool IsNull() const { return mLength == 0xFFFF; } + +private: + uint16_t mLength = 0xFFFF; + T mArray[MaxElements]; +}; + +// This is used by code generation to provide specific attributes. Type should be one of +// PrimitiveType, OctetString, ArrayType, etc to provide storage and type-specific +// functionality. +template +struct Attribute : public Type +{ + static constexpr chip::AttributeId kId = id; + static constexpr EmberAfClusterMask kMask = mask | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE); + + using Type::Type; + using Type::operator=; +}; + +struct CommonCluster; +typedef std::function + PropagateWriteCB; + +// This is the base type of all generated clusters, providing the backend access to +// implementation details. +struct CommonCluster : public ClusterImpl +{ + void SetEndpointId(chip::EndpointId id) override; + chip::EndpointId GetEndpointId() const; + + void SetCallback(PropagateWriteCB * cb); + + bool active() const; + + virtual CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, + chip::app::AttributeValueDecoder & aDecoder) = 0; + + CHIP_ERROR ForwardWriteToBridge(const chip::app::ConcreteDataAttributePath & aPath, + chip::app::AttributeValueDecoder & aDecoder); + + template + void Push(T & attr, U v) + { + attr = v; + OnUpdated(T::kId); + } + bool Push(chip::AttributeId attr, chip::TLV::TLVReader & reader); + + void OnUpdated(chip::AttributeId attr); + template + void OnUpdated(const T & attr) + { + OnUpdated(T::kId); + } + +protected: + chip::EndpointId mEndpoint = 0xFFFF; + PropagateWriteCB * mCallback = nullptr; +}; + +struct CommonAttributeAccessInterface : public chip::app::AttributeAccessInterface +{ + using chip::app::AttributeAccessInterface::AttributeAccessInterface; + static CommonCluster * FindCluster(const chip::app::ConcreteClusterPath & path); +}; + +#include "cpp/BridgeClustersImpl.h" + +namespace clusters { +struct BridgedDeviceBasicCluster : public CommonCluster +{ + static constexpr chip::ClusterId kClusterId = ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID; + + BridgedDeviceBasicCluster(); + + chip::ClusterId GetClusterId() override { return kClusterId; } + CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, + chip::app::AttributeValueDecoder & aDecoder) override; + + template + void AddAllAttributes(T * list) + { + list->Add(mReachable); + } + + chip::Span GetAllAttributes() override + { + static constexpr EmberAfAttributeMetadata kAllAttributes[] = { + { ZCL_REACHABLE_ATTRIBUTE_ID, ZCL_BOOLEAN_ATTRIBUTE_TYPE, 1, 0, 0u }, + }; + return chip::Span(kAllAttributes); + } + + Attribute> mReachable; +}; + +} // namespace clusters diff --git a/examples/bridge-app/linux/include/Device.h b/examples/bridge-app/linux/include/Device.h index b85633ceb3fdf3..2f665193874323 100644 --- a/examples/bridge-app/linux/include/Device.h +++ b/examples/bridge-app/linux/include/Device.h @@ -18,230 +18,58 @@ #pragma once -#include +#include #include #include -#include -#include - +#include "Clusters.h" + +// Device types for dynamic endpoints: TODO Need a generated file from ZAP to define these! +// (taken from chip-devices.xml) +#define DEVICE_TYPE_BRIDGED_NODE 0x0013 +// (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 +// (taken from chip-devices.xml) +#define DEVICE_TYPE_ROOT_NODE 0x0016 +// (taken from chip-devices.xml) +#define DEVICE_TYPE_BRIDGE 0x000e + +// Device Version for dynamic endpoints: +#define DEVICE_VERSION_DEFAULT 1 + +// This represents a single logical device occupying one endpoint. A composed device consists of multiple +// Device objects that reference a tree. class Device { public: - static const int kDeviceNameSize = 32; + Device(chip::Span dataVersions, chip::Span clusters, chip::Span clusterImpl, + const chip::Span & deviceTypeList, chip::EndpointId parentId); + ~Device() = default; - enum Changed_t - { - kChanged_Reachable = 1u << 0, - kChanged_Location = 1u << 1, - kChanged_Name = 1u << 2, - kChanged_Last = kChanged_Name, - } Changed; + const chip::Span & versions() { return mDataVersions; } + const chip::Span & deviceTypes() { return mDeviceTypeList; } + const EmberAfEndpointType * endpointType() { return &mEndpointType; } + const chip::Span & clusters() { return mClusterImpl; } - Device(const char * szDeviceName, std::string szLocation); - virtual ~Device() {} + void SetEndpointId(chip::EndpointId id); + chip::EndpointId GetEndpointId() { return mEndpointId; } + chip::EndpointId GetParentEndpointId() { return mParentEndpointId; } - bool IsReachable(); - void SetReachable(bool aReachable); - void SetName(const char * szDeviceName); - void SetLocation(std::string szLocation); - inline void SetEndpointId(chip::EndpointId id) { mEndpointId = id; }; - inline chip::EndpointId GetEndpointId() { return mEndpointId; }; - inline void SetParentEndpointId(chip::EndpointId id) { mParentEndpointId = id; }; - inline chip::EndpointId GetParentEndpointId() { return mParentEndpointId; }; - inline char * GetName() { return mName; }; - inline std::string GetLocation() { return mLocation; }; - inline std::string GetZone() { return mZone; }; - inline void SetZone(std::string zone) { mZone = zone; }; + const char * GetName(); + void SetName(const char * name); private: - virtual void HandleDeviceChange(Device * device, Device::Changed_t changeMask) = 0; - -protected: - bool mReachable; - char mName[kDeviceNameSize]; - std::string mLocation; - chip::EndpointId mEndpointId; chip::EndpointId mParentEndpointId; - std::string mZone; -}; - -class DeviceOnOff : public Device -{ -public: - enum Changed_t - { - kChanged_OnOff = kChanged_Last << 1, - } Changed; - - DeviceOnOff(const char * szDeviceName, std::string szLocation); - - bool IsOn(); - void SetOnOff(bool aOn); - void Toggle(); - - using DeviceCallback_fn = std::function; - void SetChangeCallback(DeviceCallback_fn aChanged_CB); - -private: - void HandleDeviceChange(Device * device, Device::Changed_t changeMask); - -private: - bool mOn; - DeviceCallback_fn mChanged_CB; -}; - -class DeviceSwitch : public Device -{ -public: - enum Changed_t - { - kChanged_NumberOfPositions = kChanged_Last << 1, - kChanged_CurrentPosition = kChanged_Last << 2, - kChanged_MultiPressMax = kChanged_Last << 3, - } Changed; - - DeviceSwitch(const char * szDeviceName, std::string szLocation, uint32_t aFeatureMap); - - void SetNumberOfPositions(uint8_t aNumberOfPositions); - void SetCurrentPosition(uint8_t aCurrentPosition); - void SetMultiPressMax(uint8_t aMultiPressMax); - - inline uint8_t GetNumberOfPositions() { return mNumberOfPositions; }; - inline uint8_t GetCurrentPosition() { return mCurrentPosition; }; - inline uint8_t GetMultiPressMax() { return mMultiPressMax; }; - inline uint32_t GetFeatureMap() { return mFeatureMap; }; - - using DeviceCallback_fn = std::function; - void SetChangeCallback(DeviceCallback_fn aChanged_CB); - -private: - void HandleDeviceChange(Device * device, Device::Changed_t changeMask); - -private: - uint8_t mNumberOfPositions; - uint8_t mCurrentPosition; - uint8_t mMultiPressMax; - uint32_t mFeatureMap; - DeviceCallback_fn mChanged_CB; -}; - -class DeviceTempSensor : public Device -{ -public: - enum Changed_t - { - kChanged_MeasurementValue = kChanged_Last << 1, - } Changed; - - DeviceTempSensor(const char * szDeviceName, std::string szLocation, int16_t min, int16_t max, int16_t measuredValue); - - inline int16_t GetMeasuredValue() { return mMeasurement; }; - void SetMeasuredValue(int16_t measurement); - - using DeviceCallback_fn = std::function; - void SetChangeCallback(DeviceCallback_fn aChanged_CB); - - const int16_t mMin; - const int16_t mMax; - -private: - void HandleDeviceChange(Device * device, Device::Changed_t changeMask); - -private: - int16_t mMeasurement; - DeviceCallback_fn mChanged_CB; -}; - -class ComposedDevice : public Device -{ -public: - ComposedDevice(const char * szDeviceName, std::string szLocation) : Device(szDeviceName, szLocation){}; - - using DeviceCallback_fn = std::function; - - void SetChangeCallback(DeviceCallback_fn aChanged_CB); - -private: - void HandleDeviceChange(Device * device, Device::Changed_t changeMask); - -private: - DeviceCallback_fn mChanged_CB; -}; - -class DevicePowerSource : public Device -{ -public: - enum Changed_t - { - kChanged_BatLevel = kChanged_Last << 1, - kChanged_Description = kChanged_Last << 2, - } Changed; - - DevicePowerSource(const char * szDeviceName, std::string szLocation, uint32_t aFeatureMap) : - Device(szDeviceName, szLocation), mFeatureMap(aFeatureMap){}; - - using DeviceCallback_fn = std::function; - void SetChangeCallback(DeviceCallback_fn aChanged_CB) { mChanged_CB = aChanged_CB; } - - void SetBatChargeLevel(uint8_t aBatChargeLevel); - void SetDescription(std::string aDescription); - - inline uint32_t GetFeatureMap() { return mFeatureMap; }; - inline uint8_t GetBatChargeLevel() { return mBatChargeLevel; }; - inline uint8_t GetOrder() { return mOrder; }; - inline uint8_t GetStatus() { return mStatus; }; - inline std::string GetDescription() { return mDescription; }; - -private: - void HandleDeviceChange(Device * device, Device::Changed_t changeMask); - -private: - uint8_t mBatChargeLevel = 0; - uint8_t mOrder = 0; - uint8_t mStatus = 0; - std::string mDescription = "Primary Battery"; - uint32_t mFeatureMap; - DeviceCallback_fn mChanged_CB; -}; - -class EndpointListInfo -{ -public: - EndpointListInfo(uint16_t endpointListId, std::string name, chip::app::Clusters::Actions::EndpointListTypeEnum type); - EndpointListInfo(uint16_t endpointListId, std::string name, chip::app::Clusters::Actions::EndpointListTypeEnum type, - chip::EndpointId endpointId); - void AddEndpointId(chip::EndpointId endpointId); - inline uint16_t GetEndpointListId() { return mEndpointListId; }; - std::string GetName() { return mName; }; - inline chip::app::Clusters::Actions::EndpointListTypeEnum GetType() { return mType; }; - inline chip::EndpointId * GetEndpointListData() { return mEndpoints.data(); }; - inline size_t GetEndpointListSize() { return mEndpoints.size(); }; - -private: - uint16_t mEndpointListId = static_cast(0); - std::string mName; - chip::app::Clusters::Actions::EndpointListTypeEnum mType = static_cast(0); - std::vector mEndpoints; -}; - -class Room -{ -public: - Room(std::string name, uint16_t endpointListId, chip::app::Clusters::Actions::EndpointListTypeEnum type, bool isVisible); - inline void setIsVisible(bool isVisible) { mIsVisible = isVisible; }; - inline bool getIsVisible() { return mIsVisible; }; - inline void setName(std::string name) { mName = name; }; - inline std::string getName() { return mName; }; - inline chip::app::Clusters::Actions::EndpointListTypeEnum getType() { return mType; }; - inline uint16_t getEndpointListId() { return mEndpointListId; }; - -private: - bool mIsVisible; - std::string mName; - uint16_t mEndpointListId; - chip::app::Clusters::Actions::EndpointListTypeEnum mType; + chip::EndpointId mEndpointId; + chip::Span mDataVersions; + chip::Span mClusters; + chip::Span mClusterImpl; + chip::Span mDeviceTypeList; + EmberAfEndpointType mEndpointType; + const char * mDeviceName = ""; }; class Action @@ -268,3 +96,7 @@ class Action uint16_t mSupportedCommands; bool mIsVisible; }; + +int AddDeviceEndpoint(Device * dev); +int RemoveDeviceEndpoint(Device * dev); +Device * FindDeviceEndpoint(chip::EndpointId id); diff --git a/examples/bridge-app/linux/include/DeviceImpl.h b/examples/bridge-app/linux/include/DeviceImpl.h new file mode 100644 index 00000000000000..e94a4b4596fb96 --- /dev/null +++ b/examples/bridge-app/linux/include/DeviceImpl.h @@ -0,0 +1,21 @@ +/* + * + * Copyright (c) 2022 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. + */ + +#pragma once + +#include "Device.h" diff --git a/examples/bridge-app/linux/include/DynamicDevice.h b/examples/bridge-app/linux/include/DynamicDevice.h new file mode 100644 index 00000000000000..7fa7419d306dc4 --- /dev/null +++ b/examples/bridge-app/linux/include/DynamicDevice.h @@ -0,0 +1,123 @@ +/* + * + * Copyright (c) 2022 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. + */ + +#pragma once + +#include "Device.h" + +#include +#include + +// This file provides implementations that use dynamic storage + +struct DynamicAttributeList +{ + template + void Add(const T & attrib) + { + Add(T::kId, T::kMatterType, T::kMaxSize, T::kMask); + } + + void Add(EmberAfAttributeMetadata metadata); + + void Add(chip::AttributeId id, EmberAfAttributeType type, uint16_t maxSize, EmberAfClusterMask mask); + + std::vector mAttributeDecls; +}; + +template +struct DynamicCluster : public T +{ + DynamicCluster(const chip::CommandId * incomingCommands = nullptr, const chip::CommandId * outgoingCommands = nullptr) : + mIncomingCommands(incomingCommands), mOutgoingCommands(outgoingCommands) + { + this->AddAllAttributes(&mAttributes); + } + + DynamicAttributeList mAttributes; + const chip::CommandId * mIncomingCommands; + const chip::CommandId * mOutgoingCommands; +}; + +class DynamicDeviceImpl +{ +public: + DynamicDeviceImpl(); + + template + DynamicDeviceImpl(Types &... clusters) + {} + + virtual ~DynamicDeviceImpl() = default; + + void SetParentEndpointId(chip::EndpointId id) { mParentEndpointId = id; } + + void AddDeviceType(EmberAfDeviceType type); + + // Add each cluster that the device will ever use. + DynamicDeviceImpl & AddCluster(std::unique_ptr cluster, const DynamicAttributeList & attribs, + const chip::CommandId * incomingCommands, const chip::CommandId * outgoingCommands); + DynamicDeviceImpl & AddCluster(CommonCluster * cluster, const DynamicAttributeList & attribs, + const chip::CommandId * incomingCommands, const chip::CommandId * outgoingCommands); + template + DynamicDeviceImpl & AddCluster(DynamicCluster & cluster) + { + return AddCluster(&cluster, cluster.mAttributes, cluster.mIncomingCommands, cluster.mOutgoingCommands); + } + + // After setting all options, create the device. + Device CreateDevice(); + + const std::vector & clusters() const { return mClusterRawPtrs; } + +private: + std::vector> mClusters; + std::vector mClusterRawPtrs; + std::vector mClusterBaseRawPtrs; + + std::vector mClusterDecls; + + std::vector mVersions; + + std::vector mDeviceTypes; + + std::list> mAttribStorage; + + chip::EndpointId mParentEndpointId = 1; +}; + +class DynamicSwitchDevice : public DynamicDeviceImpl +{ +public: + DynamicSwitchDevice() { AddCluster(mBridgedDevice).AddCluster(mSwitch).AddCluster(mDescriptor); } + ~DynamicSwitchDevice() override = default; + + void SetNumberOfPositions(uint8_t aNumberOfPositions) { mSwitch.Push(mSwitch.mNumberOfPositions, aNumberOfPositions); } + void SetCurrentPosition(uint8_t aCurrentPosition) { mSwitch.Push(mSwitch.mNumberOfPositions, aCurrentPosition); } + void SetMultiPressMax(uint8_t aMultiPressMax) { mSwitch.Push(mSwitch.mNumberOfPositions, aMultiPressMax); } + + inline uint8_t GetNumberOfPositions() { return mSwitch.mNumberOfPositions.Peek(); }; + inline uint8_t GetCurrentPosition() { return mSwitch.mCurrentPosition.Peek(); }; + inline uint8_t GetMultiPressMax() { return mSwitch.mMultiPressMax.Peek(); }; + inline uint32_t GetFeatureMap() { return mSwitch.mFeatureMap.Peek(); }; + +private: + DynamicCluster mBridgedDevice; + DynamicCluster mSwitch; + DynamicCluster mDescriptor; +}; diff --git a/examples/bridge-app/linux/include/main.h b/examples/bridge-app/linux/include/main.h index df7ba595cd6ece..583ed40992db46 100644 --- a/examples/bridge-app/linux/include/main.h +++ b/examples/bridge-app/linux/include/main.h @@ -18,6 +18,37 @@ #pragma once -std::vector GetEndpointListInfo(chip::EndpointId parentId); +#include "Device.h" -std::vector GetActionListInfo(chip::EndpointId parentId); +class Room +{ +public: + Room() = default; + void SetName(std::string name) { mName = name; } + const std::string & GetName() { return mName; } + chip::app::Clusters::BridgedActions::EndpointListTypeEnum GetType() { return mType; }; + uint16_t GetEndpointListId() { return mEndpointListId; }; + chip::EndpointId * GetEndpointListData() { return mEndpoints.data(); }; + size_t GetEndpointListSize() { return mEndpoints.size(); }; + + void AddEndpoint(chip::EndpointId ep) { mEndpoints.push_back(ep); } + void RemoveEndpoint(chip::EndpointId ep) + { + auto it = std::find(mEndpoints.begin(), mEndpoints.end(), ep); + if (it != mEndpoints.end()) + mEndpoints.erase(it); + } + +private: + std::string mName; + uint16_t mEndpointListId = 0; + chip::app::Clusters::BridgedActions::EndpointListTypeEnum mType; + std::vector mEndpoints; +}; + +static constexpr uint32_t kMaxRooms = 16; +extern Room gRooms[kMaxRooms]; + +Room * FindRoom(const std::string & name); + +chip::Span GetActionListInfo(chip::EndpointId parentId); diff --git a/examples/bridge-app/linux/main.cpp b/examples/bridge-app/linux/main.cpp index ee545d5619feef..69deb96e7ee5ce 100644 --- a/examples/bridge-app/linux/main.cpp +++ b/examples/bridge-app/linux/main.cpp @@ -41,14 +41,15 @@ #include #include -#include -#include +#include "Backend.h" #include "CommissionableInit.h" #include "Device.h" #include "main.h" #include +#include "AppMain.h" + #include #include #include @@ -60,208 +61,31 @@ using namespace chip::Transport; using namespace chip::DeviceLayer; using namespace chip::app::Clusters; -namespace { - -const int kNodeLabelSize = 32; -// Current ZCL implementation of Struct uses a max-size array of 254 bytes -const int kDescriptorAttributeArraySize = 254; - -EndpointId gCurrentEndpointId; -EndpointId gFirstDynamicEndpointId; -Device * gDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT]; -std::vector gRooms; -std::vector gActions; - -const int16_t minMeasuredValue = -27315; -const int16_t maxMeasuredValue = 32766; -const int16_t initialMeasuredValue = 100; - -// 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 matter-devices.xml) -#define DEVICE_TYPE_BRIDGED_NODE 0x0013 -// (taken from lo-devices.xml) -#define DEVICE_TYPE_LO_ON_OFF_LIGHT 0x0100 -// (taken from matter-devices.xml) -#define DEVICE_TYPE_POWER_SOURCE 0x0011 -// (taken from matter-devices.xml) -#define DEVICE_TYPE_TEMP_SENSOR 0x0302 - -// Device Version for dynamic endpoints: -#define DEVICE_VERSION_DEFAULT 1 - -// --------------------------------------------------------------------------- -// -// LIGHT ENDPOINT: contains the following clusters: -// - On/Off -// - Descriptor -// - Bridged Device Basic - -// 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(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* feature map */ - DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); - -// Declare Cluster List for Bridged Light endpoint -// TODO: It's not clear whether it would be better to get the command lists from -// the ZAP config on our last fixed endpoint instead. -constexpr CommandId onOffIncomingCommands[] = { - app::Clusters::OnOff::Commands::Off::Id, - app::Clusters::OnOff::Commands::On::Id, - app::Clusters::OnOff::Commands::Toggle::Id, - app::Clusters::OnOff::Commands::OffWithEffect::Id, - app::Clusters::OnOff::Commands::OnWithRecallGlobalScene::Id, - app::Clusters::OnOff::Commands::OnWithTimedOff::Id, - kInvalidCommandId, -}; - -DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedLightClusters) -DECLARE_DYNAMIC_CLUSTER(ZCL_ON_OFF_CLUSTER_ID, onOffAttrs, onOffIncomingCommands, nullptr), - DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, descriptorAttrs, nullptr, nullptr), - DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, bridgedDeviceBasicAttrs, nullptr, - nullptr) DECLARE_DYNAMIC_CLUSTER_LIST_END; - -// Declare Bridged Light endpoint -DECLARE_DYNAMIC_ENDPOINT(bridgedLightEndpoint, bridgedLightClusters); -DataVersion gLight1DataVersions[ArraySize(bridgedLightClusters)]; -DataVersion gLight2DataVersions[ArraySize(bridgedLightClusters)]; - -DeviceOnOff Light1("Light 1", "Office"); -DeviceOnOff Light2("Light 2", "Office"); - -DeviceTempSensor TempSensor1("TempSensor 1", "Office", minMeasuredValue, maxMeasuredValue, initialMeasuredValue); -DeviceTempSensor TempSensor2("TempSensor 2", "Office", minMeasuredValue, maxMeasuredValue, initialMeasuredValue); - -DeviceTempSensor ComposedTempSensor1("Composed TempSensor 1", "Bedroom", minMeasuredValue, maxMeasuredValue, initialMeasuredValue); -DeviceTempSensor ComposedTempSensor2("Composed TempSensor 2", "Bedroom", minMeasuredValue, maxMeasuredValue, initialMeasuredValue); - -// Declare Bridged endpoints used for Action clusters -DataVersion gActionLight1DataVersions[ArraySize(bridgedLightClusters)]; -DataVersion gActionLight2DataVersions[ArraySize(bridgedLightClusters)]; -DataVersion gActionLight3DataVersions[ArraySize(bridgedLightClusters)]; -DataVersion gActionLight4DataVersions[ArraySize(bridgedLightClusters)]; - -DeviceOnOff ActionLight1("Action Light 1", "Room 1"); -DeviceOnOff ActionLight2("Action Light 2", "Room 1"); -DeviceOnOff ActionLight3("Action Light 3", "Room 2"); -DeviceOnOff ActionLight4("Action Light 4", "Room 2"); - -Room room1("Room 1", 0xE001, Actions::EndpointListTypeEnum::kRoom, true); -Room room2("Room 2", 0xE002, Actions::EndpointListTypeEnum::kRoom, true); -Room room3("Zone 3", 0xE003, Actions::EndpointListTypeEnum::kZone, false); - -Action action1(0x1001, "Room 1 On", Actions::ActionTypeEnum::kAutomation, 0xE001, 0x1, Actions::ActionStateEnum::kInactive, true); -Action action2(0x1002, "Turn On Room 2", Actions::ActionTypeEnum::kAutomation, 0xE002, 0x01, Actions::ActionStateEnum::kInactive, - true); -Action action3(0x1003, "Turn Off Room 1", Actions::ActionTypeEnum::kAutomation, 0xE003, 0x01, Actions::ActionStateEnum::kInactive, - false); +static EndpointId gCurrentEndpointId; +static EndpointId gFirstDynamicEndpointId; +static Device * gDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT]; +Room gRooms[kMaxRooms]; -// --------------------------------------------------------------------------- -// -// POWER SOURCE ENDPOINT: contains the following clusters: -// - Power Source -// - Descriptor -// - Bridged Device Basic - -DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(powerSourceAttrs) -DECLARE_DYNAMIC_ATTRIBUTE(ZCL_POWER_SOURCE_BAT_CHARGE_LEVEL_ATTRIBUTE_ID, ENUM8, 1, 0), - DECLARE_DYNAMIC_ATTRIBUTE(ZCL_POWER_SOURCE_ORDER_ATTRIBUTE_ID, INT8U, 1, 0), - DECLARE_DYNAMIC_ATTRIBUTE(ZCL_POWER_SOURCE_STATUS_ATTRIBUTE_ID, ENUM8, 1, 0), - DECLARE_DYNAMIC_ATTRIBUTE(ZCL_POWER_SOURCE_DESCRIPTION_ATTRIBUTE_ID, CHAR_STRING, 32, 0), DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); - -DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedPowerSourceClusters) -DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, descriptorAttrs, nullptr, nullptr), - DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, bridgedDeviceBasicAttrs, nullptr, nullptr), - DECLARE_DYNAMIC_CLUSTER(ZCL_POWER_SOURCE_CLUSTER_ID, powerSourceAttrs, nullptr, nullptr), DECLARE_DYNAMIC_CLUSTER_LIST_END; - -DECLARE_DYNAMIC_ENDPOINT(bridgedPowerSourceEndpoint, bridgedPowerSourceClusters); - -DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(tempSensorAttrs) -DECLARE_DYNAMIC_ATTRIBUTE(ZCL_TEMP_MEASURED_VALUE_ATTRIBUTE_ID, INT16S, 2, 0), /* Measured Value */ - DECLARE_DYNAMIC_ATTRIBUTE(ZCL_TEMP_MIN_MEASURED_VALUE_ATTRIBUTE_ID, INT16S, 2, 0), /* Min Measured Value */ - DECLARE_DYNAMIC_ATTRIBUTE(ZCL_TEMP_MAX_MEASURED_VALUE_ATTRIBUTE_ID, INT16S, 2, 0), /* Max Measured Value */ - DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */ - DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); - -// --------------------------------------------------------------------------- -// -// TEMPERATURE SENSOR ENDPOINT: contains the following clusters: -// - Temperature measurement -// - Descriptor -// - Bridged Device Basic -DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedTempSensorClusters) -DECLARE_DYNAMIC_CLUSTER(ZCL_TEMP_MEASUREMENT_CLUSTER_ID, tempSensorAttrs, nullptr, nullptr), - DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, descriptorAttrs, nullptr, nullptr), - DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, bridgedDeviceBasicAttrs, nullptr, nullptr), - DECLARE_DYNAMIC_CLUSTER_LIST_END; - -// Declare Bridged Light endpoint -DECLARE_DYNAMIC_ENDPOINT(bridgedTempSensorEndpoint, bridgedTempSensorClusters); -DataVersion gTempSensor1DataVersions[ArraySize(bridgedTempSensorClusters)]; -DataVersion gTempSensor2DataVersions[ArraySize(bridgedTempSensorClusters)]; - -// --------------------------------------------------------------------------- -// -// COMPOSED DEVICE ENDPOINT: contains the following clusters: -// - Descriptor -// - Bridged Device Basic - -// Composed Device Configuration -DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedComposedDeviceClusters) -DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, descriptorAttrs, nullptr, nullptr), - DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, bridgedDeviceBasicAttrs, nullptr, nullptr), - DECLARE_DYNAMIC_CLUSTER_LIST_END; - -DECLARE_DYNAMIC_ENDPOINT(bridgedComposedDeviceEndpoint, bridgedComposedDeviceClusters); -DataVersion gComposedDeviceDataVersions[ArraySize(bridgedComposedDeviceClusters)]; -DataVersion gComposedTempSensor1DataVersions[ArraySize(bridgedTempSensorClusters)]; -DataVersion gComposedTempSensor2DataVersions[ArraySize(bridgedTempSensorClusters)]; -DataVersion gComposedPowerSourceDataVersions[ArraySize(bridgedPowerSourceClusters)]; - -} // namespace - -// REVISION DEFINITIONS: -// ================================================================================= - -#define ZCL_DESCRIPTOR_CLUSTER_REVISION (1u) -#define ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_REVISION (1u) -#define ZCL_BRIDGED_DEVICE_BASIC_FEATURE_MAP (0u) -#define ZCL_FIXED_LABEL_CLUSTER_REVISION (1u) -#define ZCL_ON_OFF_CLUSTER_REVISION (4u) -#define ZCL_TEMPERATURE_SENSOR_CLUSTER_REVISION (1u) -#define ZCL_TEMPERATURE_SENSOR_FEATURE_MAP (0u) -#define ZCL_POWER_SOURCE_CLUSTER_REVISION (1u) +bool emberAfBridgedActionsClusterInstantActionCallback(app::CommandHandler * commandObj, + const app::ConcreteCommandPath & commandPath, + const BridgedActions::Commands::InstantAction::DecodableType & commandData) +{ + // No actions are implemented, just return status NotFound. + commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::NotFound); + return true; +} -// --------------------------------------------------------------------------- +Device * FindDeviceEndpoint(chip::EndpointId id) +{ + for (auto dev : gDevices) + { + if (dev && dev->GetEndpointId() == id) + return dev; + } + return nullptr; +} -int AddDeviceEndpoint(Device * dev, EmberAfEndpointType * ep, const Span & deviceTypeList, - const Span & dataVersionStorage, chip::EndpointId parentEndpointId = chip::kInvalidEndpointId) +int AddDeviceEndpoint(Device * dev) { uint8_t index = 0; while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) @@ -275,9 +99,8 @@ int AddDeviceEndpoint(Device * dev, EmberAfEndpointType * ep, const SpanSetEndpointId(gCurrentEndpointId); - dev->SetParentEndpointId(parentEndpointId); ret = - emberAfSetDynamicEndpoint(index, gCurrentEndpointId, ep, dataVersionStorage, deviceTypeList, parentEndpointId); + emberAfSetDynamicEndpoint(index, gCurrentEndpointId, dev->endpointType(), dev->versions(), dev->deviceTypes()); if (ret == EMBER_ZCL_STATUS_SUCCESS) { ChipLogProgress(DeviceLayer, "Added device %s to dynamic endpoint %d (index=%d)", dev->GetName(), @@ -286,6 +109,8 @@ int AddDeviceEndpoint(Device * dev, EmberAfEndpointType * ep, const Span GetEndpointListInfo(chip::EndpointId parentId) -{ - std::vector infoList; - - for (auto room : gRooms) - { - if (room->getIsVisible()) - { - EndpointListInfo info(room->getEndpointListId(), room->getName(), room->getType()); - int index = 0; - while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) - { - if ((gDevices[index] != nullptr) && (gDevices[index]->GetParentEndpointId() == parentId)) - { - std::string location; - if (room->getType() == Actions::EndpointListTypeEnum::kZone) - { - location = gDevices[index]->GetZone(); - } - else - { - location = gDevices[index]->GetLocation(); - } - if (room->getName().compare(location) == 0) - { - info.AddEndpointId(gDevices[index]->GetEndpointId()); - } - } - index++; - } - if (info.GetEndpointListSize() > 0) - { - infoList.push_back(info); - } - } - } - - return infoList; -} - -std::vector GetActionListInfo(chip::EndpointId parentId) -{ - return gActions; -} - -namespace { -void CallReportingCallback(intptr_t closure) -{ - auto path = reinterpret_cast(closure); - MatterReportingAttributeChangeCallback(*path); - Platform::Delete(path); -} - -void ScheduleReportingCallback(Device * dev, ClusterId cluster, AttributeId attribute) -{ - auto * path = Platform::New(dev->GetEndpointId(), cluster, attribute); - PlatformMgr().ScheduleWork(CallReportingCallback, reinterpret_cast(path)); -} -} // anonymous namespace - -void HandleDeviceStatusChanged(Device * dev, Device::Changed_t itemChangedMask) -{ - if (itemChangedMask & Device::kChanged_Reachable) - { - ScheduleReportingCallback(dev, BridgedDeviceBasic::Id, BridgedDeviceBasic::Attributes::Reachable::Id); - } - - if (itemChangedMask & Device::kChanged_Name) - { - ScheduleReportingCallback(dev, BridgedDeviceBasic::Id, BridgedDeviceBasic::Attributes::NodeLabel::Id); - } -} - -void HandleDeviceOnOffStatusChanged(DeviceOnOff * dev, DeviceOnOff::Changed_t itemChangedMask) -{ - if (itemChangedMask & (DeviceOnOff::kChanged_Reachable | DeviceOnOff::kChanged_Name | DeviceOnOff::kChanged_Location)) - { - HandleDeviceStatusChanged(static_cast(dev), (Device::Changed_t) itemChangedMask); - } - - if (itemChangedMask & DeviceOnOff::kChanged_OnOff) - { - ScheduleReportingCallback(dev, OnOff::Id, OnOff::Attributes::OnOff::Id); - } -} - -void HandleDevicePowerSourceStatusChanged(DevicePowerSource * dev, DevicePowerSource::Changed_t itemChangedMask) -{ - using namespace app::Clusters; - if (itemChangedMask & - (DevicePowerSource::kChanged_Reachable | DevicePowerSource::kChanged_Name | DevicePowerSource::kChanged_Location)) - { - HandleDeviceStatusChanged(static_cast(dev), (Device::Changed_t) itemChangedMask); - } - - if (itemChangedMask & DevicePowerSource::kChanged_BatLevel) - { - uint8_t batChargeLevel = dev->GetBatChargeLevel(); - MatterReportingAttributeChangeCallback(dev->GetEndpointId(), PowerSource::Id, PowerSource::Attributes::BatChargeLevel::Id, - ZCL_INT8U_ATTRIBUTE_TYPE, &batChargeLevel); - } - - if (itemChangedMask & DevicePowerSource::kChanged_Description) - { - MatterReportingAttributeChangeCallback(dev->GetEndpointId(), PowerSource::Id, PowerSource::Attributes::Description::Id); - } -} - -void HandleDeviceTempSensorStatusChanged(DeviceTempSensor * dev, DeviceTempSensor::Changed_t itemChangedMask) -{ - if (itemChangedMask & - (DeviceTempSensor::kChanged_Reachable | DeviceTempSensor::kChanged_Name | DeviceTempSensor::kChanged_Location)) - { - HandleDeviceStatusChanged(static_cast(dev), (Device::Changed_t) itemChangedMask); - } - if (itemChangedMask & DeviceTempSensor::kChanged_MeasurementValue) - { - ScheduleReportingCallback(dev, TemperatureMeasurement::Id, TemperatureMeasurement::Attributes::MeasuredValue::Id); - } -} - -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)) - { - MutableByteSpan zclNameSpan(buffer, maxReadLength); - MakeZclCharString(zclNameSpan, dev->GetName()); - } - else if ((attributeId == ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID) && (maxReadLength == 2)) - { - *buffer = (uint16_t) ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_REVISION; - } - else if ((attributeId == ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID) && (maxReadLength == 4)) - { - *buffer = (uint32_t) ZCL_BRIDGED_DEVICE_BASIC_FEATURE_MAP; - } - 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 HandleReadPowerSourceAttribute(DevicePowerSource * dev, chip::AttributeId attributeId, uint8_t * buffer, - uint16_t maxReadLength) -{ - using namespace app::Clusters; - if ((attributeId == PowerSource::Attributes::BatChargeLevel::Id) && (maxReadLength == 1)) - { - *buffer = dev->GetBatChargeLevel(); - } - else if ((attributeId == PowerSource::Attributes::Order::Id) && (maxReadLength == 1)) - { - *buffer = dev->GetOrder(); - } - else if ((attributeId == PowerSource::Attributes::Status::Id) && (maxReadLength == 1)) - { - *buffer = dev->GetStatus(); - } - else if ((attributeId == PowerSource::Attributes::Description::Id) && (maxReadLength == 32)) - { - MutableByteSpan zclDescpitionSpan(buffer, maxReadLength); - MakeZclCharString(zclDescpitionSpan, dev->GetDescription().c_str()); - } - else if ((attributeId == PowerSource::Attributes::ClusterRevision::Id) && (maxReadLength == 2)) - { - uint16_t rev = ZCL_POWER_SOURCE_CLUSTER_REVISION; - memcpy(buffer, &rev, sizeof(rev)); - } - else if ((attributeId == PowerSource::Attributes::FeatureMap::Id) && (maxReadLength == 4)) - { - uint32_t featureMap = dev->GetFeatureMap(); - memcpy(buffer, &featureMap, sizeof(featureMap)); - } - else - { - return EMBER_ZCL_STATUS_FAILURE; - } - - return EMBER_ZCL_STATUS_SUCCESS; -} - -EmberAfStatus HandleReadTempMeasurementAttribute(DeviceTempSensor * dev, chip::AttributeId attributeId, uint8_t * buffer, - uint16_t maxReadLength) -{ - if ((attributeId == ZCL_TEMP_MEASURED_VALUE_ATTRIBUTE_ID) && (maxReadLength == 2)) - { - int16_t measuredValue = dev->GetMeasuredValue(); - memcpy(buffer, &measuredValue, sizeof(measuredValue)); - } - else if ((attributeId == ZCL_TEMP_MIN_MEASURED_VALUE_ATTRIBUTE_ID) && (maxReadLength == 2)) - { - int16_t minValue = dev->mMin; - memcpy(buffer, &minValue, sizeof(minValue)); - } - else if ((attributeId == ZCL_TEMP_MAX_MEASURED_VALUE_ATTRIBUTE_ID) && (maxReadLength == 2)) - { - int16_t maxValue = dev->mMax; - memcpy(buffer, &maxValue, sizeof(maxValue)); - } - else if ((attributeId == ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID) && (maxReadLength == 4)) - { - uint32_t featureMap = ZCL_TEMPERATURE_SENSOR_FEATURE_MAP; - memcpy(buffer, &featureMap, sizeof(featureMap)); - } - else if ((attributeId == ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID) && (maxReadLength == 2)) - { - uint16_t clusterRevision = ZCL_TEMPERATURE_SENSOR_CLUSTER_REVISION; - memcpy(buffer, &clusterRevision, sizeof(clusterRevision)); - } - 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] != nullptr)) - { - Device * dev = gDevices[endpointIndex]; - - if (clusterId == ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID) - { - ret = HandleReadBridgedDeviceBasicAttribute(dev, attributeMetadata->attributeId, buffer, maxReadLength); - } - else if (clusterId == ZCL_ON_OFF_CLUSTER_ID) - { - ret = HandleReadOnOffAttribute(static_cast(dev), attributeMetadata->attributeId, buffer, maxReadLength); - } - else if (clusterId == chip::app::Clusters::PowerSource::Id) - { - ret = HandleReadPowerSourceAttribute(static_cast(dev), attributeMetadata->attributeId, buffer, - maxReadLength); - } - else if (clusterId == TemperatureMeasurement::Id) - { - ret = HandleReadTempMeasurementAttribute(static_cast(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(dev), attributeMetadata->attributeId, buffer); - } - } - - return ret; -} - -void runOnOffRoomAction(Room * room, bool actionOn, EndpointId endpointId, uint16_t actionID, uint32_t invokeID, bool hasInvokeID) +Room * FindRoom(const std::string & name) { - if (hasInvokeID) + for (auto & room : gRooms) { - Actions::Events::StateChanged::Type event{ actionID, invokeID, Actions::ActionStateEnum::kActive }; - EventNumber eventNumber; - chip::app::LogEvent(event, endpointId, eventNumber); + if (room.GetName() == name) + return &room; } - - // Check and run the action for ActionLight1 - ActionLight4 - if (room->getName().compare(ActionLight1.GetLocation()) == 0) - { - ActionLight1.SetOnOff(actionOn); - } - if (room->getName().compare(ActionLight2.GetLocation()) == 0) - { - ActionLight2.SetOnOff(actionOn); - } - if (room->getName().compare(ActionLight3.GetLocation()) == 0) - { - ActionLight3.SetOnOff(actionOn); - } - if (room->getName().compare(ActionLight4.GetLocation()) == 0) - { - ActionLight4.SetOnOff(actionOn); - } - - if (hasInvokeID) - { - Actions::Events::StateChanged::Type event{ actionID, invokeID, Actions::ActionStateEnum::kInactive }; - EventNumber eventNumber; - chip::app::LogEvent(event, endpointId, eventNumber); - } -} - -bool emberAfActionsClusterInstantActionCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, - const Actions::Commands::InstantAction::DecodableType & commandData) -{ - bool hasInvokeID = false; - uint32_t invokeID = 0; - EndpointId endpointID = commandPath.mEndpointId; - auto & actionID = commandData.actionID; - - if (commandData.invokeID.HasValue()) - { - hasInvokeID = true; - invokeID = commandData.invokeID.Value(); - } - - if (actionID == action1.getActionId() && action1.getIsVisible()) - { - // Turn On Lights in Room 1 - runOnOffRoomAction(&room1, true, endpointID, actionID, invokeID, hasInvokeID); - commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::Success); - return true; - } - if (actionID == action2.getActionId() && action2.getIsVisible()) - { - // Turn On Lights in Room 2 - runOnOffRoomAction(&room2, true, endpointID, actionID, invokeID, hasInvokeID); - commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::Success); - return true; - } - if (actionID == action3.getActionId() && action3.getIsVisible()) - { - // Turn Off Lights in Room 1 - runOnOffRoomAction(&room1, false, endpointID, actionID, invokeID, hasInvokeID); - commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::Success); - return true; - } - - commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::NotFound); - return true; + return nullptr; } -void ApplicationInit() {} - -const EmberAfDeviceType gBridgedOnOffDeviceTypes[] = { { DEVICE_TYPE_LO_ON_OFF_LIGHT, DEVICE_VERSION_DEFAULT }, - { DEVICE_TYPE_BRIDGED_NODE, DEVICE_VERSION_DEFAULT } }; - -const EmberAfDeviceType gBridgedComposedDeviceTypes[] = { { DEVICE_TYPE_BRIDGED_NODE, DEVICE_VERSION_DEFAULT } }; - -const EmberAfDeviceType gComposedTempSensorDeviceTypes[] = { { DEVICE_TYPE_TEMP_SENSOR, DEVICE_VERSION_DEFAULT } }; - -const EmberAfDeviceType gComposedPowerSourceDeviceTypes[] = { { DEVICE_TYPE_POWER_SOURCE, DEVICE_VERSION_DEFAULT } }; - -const EmberAfDeviceType gBridgedTempSensorDeviceTypes[] = { { DEVICE_TYPE_TEMP_SENSOR, DEVICE_VERSION_DEFAULT }, - { DEVICE_TYPE_BRIDGED_NODE, DEVICE_VERSION_DEFAULT } }; - -#define POLL_INTERVAL_MS (100) -uint8_t poll_prescale = 0; - -bool kbhit() +chip::Span GetActionListInfo(chip::EndpointId parentId) { - int byteswaiting; - ioctl(0, FIONREAD, &byteswaiting); - return byteswaiting > 0; + return chip::Span(); } -const int16_t oneDegree = 100; - -void * bridge_polling_thread(void * context) +void ApplicationInit() { - bool light1_added = true; - bool light2_added = false; - while (1) - { - if (kbhit()) - { - int ch = getchar(); + clusters::BridgeRegisterAllAttributeOverrides(); - // Commands used for the actions bridge test plan. - if (ch == '2' && light2_added == false) - { - // TC-BR-2 step 2, Add Light2 - AddDeviceEndpoint(&Light2, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), - Span(gLight2DataVersions), 1); - light2_added = true; - } - else if (ch == '4' && light1_added == true) - { - // TC-BR-2 step 4, Remove Light 1 - RemoveDeviceEndpoint(&Light1); - light1_added = false; - } - if (ch == '5' && light1_added == false) - { - // TC-BR-2 step 5, Add Light 1 back - AddDeviceEndpoint(&Light1, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), - Span(gLight1DataVersions), 1); - light1_added = true; - } - if (ch == 'b') - { - // TC-BR-3 step 1b, rename lights - if (light1_added) - { - Light1.SetName("Light 1b"); - } - if (light2_added) - { - Light2.SetName("Light 2b"); - } - } - if (ch == 'c') - { - // TC-BR-3 step 2c, change the state of the lights - if (light1_added) - { - Light1.Toggle(); - } - if (light2_added) - { - Light2.Toggle(); - } - } - if (ch == 't') - { - // TC-BR-4 step 1g, change the state of the temperature sensors - TempSensor1.SetMeasuredValue(static_cast(TempSensor1.GetMeasuredValue() + oneDegree)); - TempSensor2.SetMeasuredValue(static_cast(TempSensor2.GetMeasuredValue() + oneDegree)); - ComposedTempSensor1.SetMeasuredValue(static_cast(ComposedTempSensor1.GetMeasuredValue() + oneDegree)); - ComposedTempSensor2.SetMeasuredValue(static_cast(ComposedTempSensor2.GetMeasuredValue() + oneDegree)); - } - - // Commands used for the actions cluster test plan. - if (ch == 'r') - { - // TC-ACT-2.2 step 2c, rename "Room 1" - room1.setName("Room 1 renamed"); - ActionLight1.SetLocation(room1.getName()); - ActionLight2.SetLocation(room1.getName()); - } - if (ch == 'f') - { - // TC-ACT-2.2 step 2f, move "Action Light 3" from "Room 2" to "Room 1" - ActionLight3.SetLocation(room1.getName()); - } - if (ch == 'i') - { - // TC-ACT-2.2 step 2i, remove "Room 2" (make it not visible in the endpoint list), do not remove the lights - room2.setIsVisible(false); - } - if (ch == 'l') - { - // TC-ACT-2.2 step 2l, add a new "Zone 3" and add "Action Light 2" to the new zone - room3.setIsVisible(true); - ActionLight2.SetZone("Zone 3"); - } - if (ch == 'm') - { - // TC-ACT-2.2 step 3c, rename "Turn on Room 1 lights" - action1.setName("Turn On Room 1"); - } - if (ch == 'n') - { - // TC-ACT-2.2 step 3f, remove "Turn on Room 2 lights" - action2.setIsVisible(false); - } - if (ch == 'o') - { - // TC-ACT-2.2 step 3i, add "Turn off Room 1 renamed lights" - action3.setIsVisible(true); - } - - // Commands used for the Bridged Device Basic Information test plan - if (ch == 'u') - { - // TC-BRBINFO-2.2 step 2 "Set reachable to false" - TempSensor1.SetReachable(false); - } - if (ch == 'v') - { - // TC-BRBINFO-2.2 step 2 "Set reachable to true" - TempSensor1.SetReachable(true); - } - continue; - } - - // Sleep to avoid tight loop reading commands - usleep(POLL_INTERVAL_MS * 1000); - } - - return nullptr; -} - -int main(int argc, char * argv[]) -{ - // Clear out the device database - memset(gDevices, 0, sizeof(gDevices)); - - // Setup Mock Devices - Light1.SetReachable(true); - Light2.SetReachable(true); - - Light1.SetChangeCallback(&HandleDeviceOnOffStatusChanged); - Light2.SetChangeCallback(&HandleDeviceOnOffStatusChanged); - - TempSensor1.SetReachable(true); - TempSensor1.SetReachable(true); - - TempSensor1.SetChangeCallback(&HandleDeviceTempSensorStatusChanged); - TempSensor2.SetChangeCallback(&HandleDeviceTempSensorStatusChanged); - - // Setup devices for action cluster tests - ActionLight1.SetReachable(true); - ActionLight2.SetReachable(true); - ActionLight3.SetReachable(true); - ActionLight4.SetReachable(true); - - ActionLight1.SetChangeCallback(&HandleDeviceOnOffStatusChanged); - ActionLight2.SetChangeCallback(&HandleDeviceOnOffStatusChanged); - ActionLight3.SetChangeCallback(&HandleDeviceOnOffStatusChanged); - ActionLight4.SetChangeCallback(&HandleDeviceOnOffStatusChanged); - - // Setup composed device with two temperature sensors and a power source - ComposedDevice ComposedDevice("Composed Device", "Bedroom"); - DevicePowerSource ComposedPowerSource("Composed Power Source", "Bedroom", EMBER_AF_POWER_SOURCE_FEATURE_BATTERY); - - ComposedDevice.SetReachable(true); - ComposedTempSensor1.SetReachable(true); - ComposedTempSensor2.SetReachable(true); - ComposedPowerSource.SetReachable(true); - ComposedPowerSource.SetBatChargeLevel(58); - - ComposedTempSensor1.SetChangeCallback(&HandleDeviceTempSensorStatusChanged); - ComposedTempSensor2.SetChangeCallback(&HandleDeviceTempSensorStatusChanged); - ComposedPowerSource.SetChangeCallback(&HandleDevicePowerSourceStatusChanged); - - if (ChipLinuxAppInit(argc, argv) != 0) - { - return -1; - } - - // Init Data Model and CHIP App Server - static chip::CommonCaseDeviceServerInitParams initParams; - (void) initParams.InitializeStaticResourcesBeforeServerInit(); - -#if CHIP_DEVICE_ENABLE_PORT_PARAMS - // use a different service port to make testing possible with other sample devices running on same host - initParams.operationalServicePort = LinuxDeviceOptions::GetInstance().securedDevicePort; -#endif - - initParams.interfaceId = LinuxDeviceOptions::GetInstance().interfaceId; - chip::Server::GetInstance().Init(initParams); - - // 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( static_cast(emberAfEndpointFromIndex(static_cast(emberAfFixedEndpointCount() - 1))) + 1); gCurrentEndpointId = gFirstDynamicEndpointId; + StartUserInput(); +} - // 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(emberAfFixedEndpointCount() - 1)), false); - - // Add light 1 -> will be mapped to ZCL endpoints 3 - AddDeviceEndpoint(&Light1, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), - Span(gLight1DataVersions), 1); - - // Add Temperature Sensor devices --> will be mapped to endpoints 4,5 - AddDeviceEndpoint(&TempSensor1, &bridgedTempSensorEndpoint, Span(gBridgedTempSensorDeviceTypes), - Span(gTempSensor1DataVersions), 1); - AddDeviceEndpoint(&TempSensor2, &bridgedTempSensorEndpoint, Span(gBridgedTempSensorDeviceTypes), - Span(gTempSensor2DataVersions), 1); - - // Add composed Device with two temperature sensors and a power source - AddDeviceEndpoint(&ComposedDevice, &bridgedComposedDeviceEndpoint, Span(gBridgedComposedDeviceTypes), - Span(gComposedDeviceDataVersions), 1); - AddDeviceEndpoint(&ComposedTempSensor1, &bridgedTempSensorEndpoint, - Span(gComposedTempSensorDeviceTypes), - Span(gComposedTempSensor1DataVersions), ComposedDevice.GetEndpointId()); - AddDeviceEndpoint(&ComposedTempSensor2, &bridgedTempSensorEndpoint, - Span(gComposedTempSensorDeviceTypes), - Span(gComposedTempSensor2DataVersions), ComposedDevice.GetEndpointId()); - AddDeviceEndpoint(&ComposedPowerSource, &bridgedPowerSourceEndpoint, - Span(gComposedPowerSourceDeviceTypes), - Span(gComposedPowerSourceDataVersions), ComposedDevice.GetEndpointId()); - - // Add 4 lights for the Action Clusters tests - AddDeviceEndpoint(&ActionLight1, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), - Span(gActionLight1DataVersions), 1); - AddDeviceEndpoint(&ActionLight2, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), - Span(gActionLight2DataVersions), 1); - AddDeviceEndpoint(&ActionLight3, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), - Span(gActionLight3DataVersions), 1); - AddDeviceEndpoint(&ActionLight4, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), - Span(gActionLight4DataVersions), 1); - gRooms.push_back(&room1); - gRooms.push_back(&room2); - gRooms.push_back(&room3); - - gActions.push_back(&action1); - gActions.push_back(&action2); - gActions.push_back(&action3); - - { - pthread_t poll_thread; - int res = pthread_create(&poll_thread, nullptr, bridge_polling_thread, nullptr); - if (res) - { - printf("Error creating polling thread: %d\n", res); - exit(1); - } - } - - // Run CHIP - - chip::DeviceLayer::PlatformMgr().RunEventLoop(); +int main(int argc, char * argv[]) +{ + VerifyOrDie(ChipLinuxAppInit(argc, argv) == 0); + ChipLinuxAppMainLoop(); return 0; } diff --git a/scripts/codegen.py b/scripts/codegen.py index c912ec0b3623bc..26c2ad3dc8eac2 100755 --- a/scripts/codegen.py +++ b/scripts/codegen.py @@ -28,6 +28,7 @@ from idl.generators import FileSystemGeneratorStorage, GeneratorStorage from idl.generators.java import JavaGenerator +from idl.generators.cpp import CppGenerator class CodeGeneratorTypes(enum.Enum): @@ -37,10 +38,13 @@ class CodeGeneratorTypes(enum.Enum): into underlying generators. """ JAVA = enum.auto() + CPP = enum.auto() def CreateGenerator(self, *args, **kargs): if self == CodeGeneratorTypes.JAVA: return JavaGenerator(*args, **kargs) + elif self == CodeGeneratorTypes.CPP: + return CppGenerator(*args, **kargs) else: raise Error("Unknown code generator type") @@ -68,6 +72,7 @@ def write_new_data(self, relative_path: str, content: str): __GENERATORS__ = { 'java': CodeGeneratorTypes.JAVA, + 'cpp': CodeGeneratorTypes.CPP, } diff --git a/scripts/idl/BUILD.gn b/scripts/idl/BUILD.gn index d17697ffb40f1b..28dba784fe5413 100644 --- a/scripts/idl/BUILD.gn +++ b/scripts/idl/BUILD.gn @@ -25,6 +25,7 @@ pw_python_package("idl") { "matter_grammar.lark", # Templates used for generation + "generators/cpp/BridgeClustersCpp.jinja", "generators/java/ChipClustersCpp.jinja", "generators/java/ChipClustersRead.jinja", @@ -54,6 +55,7 @@ pw_python_package("idl") { sources = [ "__init__.py", "generators/__init__.py", + "generators/cpp/__init__.py", "generators/filters.py", "generators/java/__init__.py", "generators/types.py", diff --git a/scripts/idl/generators/cpp/BridgeClustersCpp.jinja b/scripts/idl/generators/cpp/BridgeClustersCpp.jinja new file mode 100644 index 00000000000000..028fe574fa1b4e --- /dev/null +++ b/scripts/idl/generators/cpp/BridgeClustersCpp.jinja @@ -0,0 +1,240 @@ +#include +#include + +#include + +namespace clusters { +{% for struct in structs %} +struct {{struct.name}} +{ + CHIP_ERROR Decode(chip::TLV::TLVReader & reader) + { + chip::app::Clusters::detail::Structs::{{struct.name}}::DecodableType t; + CHIP_ERROR err = t.Decode(reader); + if(err == CHIP_NO_ERROR) { + {%- for field in struct.fields %} + {{field.name}} = t.{{field.name}}; + {%- endfor %} + } + return err; + } + + CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const + { + chip::app::Clusters::detail::Structs::{{struct.name}}::Type t; + {%- for field in struct.fields %} + t.{{field.name}} = {{field.name}}; + {%- endfor %} + return t.Encode(writer, tag); + } + + {%- for field in struct.fields %} + {{field | getField(None, idl)}} {{field.name}}; + {%- endfor %} +}; +{%- endfor %} + +{%- for cluster in clusters %} +{%- if cluster | dynamicCluster(idl) %} +struct {{cluster.name}}Cluster : public CommonCluster +{ + {%- for struct in cluster.structs %} + {%- if struct.tag == None %} + struct {{struct.name}} + { + CHIP_ERROR Decode(chip::TLV::TLVReader & reader) + { + chip::app::Clusters::{{cluster.name}}::Structs::{{struct.name}}::DecodableType t; + CHIP_ERROR err = t.Decode(reader); + if(err == CHIP_NO_ERROR) { + {%- for field in struct.fields %} + {{field.name}} = t.{{field.name}}; + {%- endfor %} + } + return err; + } + + CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const + { + chip::app::Clusters::{{cluster.name}}::Structs::{{struct.name}}::Type t; + {%- for field in struct.fields %} + t.{{field.name}} = {{field.name}}; + {%- endfor %} + return t.Encode(writer, tag); + } + + {%- for field in struct.fields %} + {{field | getField(cluster, idl)}} {{field.name}}; + {%- endfor %} + }; + {%- endif %} + {%- endfor %} + + + static constexpr chip::ClusterId kClusterId = ZCL_{{cluster.name | cameltoconst}}_CLUSTER_ID; + + chip::ClusterId GetClusterId() override { return kClusterId; } + + CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + switch(aPath.mAttributeId) + { + {%- for attr in cluster.attributes %} + case {{attr.definition.code}}: + return m{{attr.definition.name | capitalcase}}.Write(aPath, aDecoder); + {%- endfor %} + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + template + void AddAllAttributes(T *list) + { + {%- for attr in cluster.attributes %} + list->Add(m{{attr.definition.name | capitalcase}}); + {%- endfor %} + } + + chip::Span GetAllAttributes() override + { + static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { +{%- for attr in cluster.attributes %} + { {{attr.definition.code}}, {{attr | getRawSizeAndType(cluster, idl)}}, {{attr | getMask(cluster, idl)}} | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, +{%- endfor %} + }; + return chip::Span(kAllAttributes); + } + +{% for attr in cluster.attributes %} + Attribute<{{attr.definition.code}}, {{attr | getMask(cluster, idl)}}, {{attr | getType(cluster, idl)}}> m{{attr.definition.name | capitalcase}}{{attr | getInit(cluster, idl)}}; +{%- endfor %} +}; + +struct {{cluster.name}}Access : public CommonAttributeAccessInterface +{ + {{cluster.name}}Access() : CommonAttributeAccessInterface(chip::Optional(), {{cluster.name}}Cluster::kClusterId) {} + + {{cluster.name}}Cluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) + { + CommonCluster * cluster = FindCluster(aPath); + return cluster ? static_cast<{{cluster.name}}Cluster*>(cluster) : nullptr; + } + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + + switch(aPath.mAttributeId) { + {%- for attr in cluster.attributes -%} + {%- if attr.is_readable %} + case {{attr.definition.code}}: + return c->m{{attr.definition.name | capitalcase}}.Read(aPath, aEncoder); + {%- endif %} + {%- endfor %} + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + return c->ForwardWriteToBridge(aPath, aDecoder); + } + + void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + {%- for attr in cluster.attributes -%} + {%- if attr.is_writable %} + {%- if attr.definition.is_list %} + case {{attr.definition.code}}: + m{{attr.definition.name | capitalcase}}.ListWriteBegin(aPath); + return; + {%- endif %} + {%- endif %} + {%- endfor %} + } + } + + void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + {%- for attr in cluster.attributes -%} + {%- if attr.is_writable %} + {%- if attr.definition.is_list %} + case {{attr.definition.code}}: + m{{attr.definition.name | capitalcase}}.ListWriteEnd(aPath, aWriteWasSuccessful); + return; + {%- endif %} + {%- endif %} + {%- endfor %} + } + } +}; +{%- endif %} +{%- endfor %} + +struct ClusterInfo +{ + chip::ClusterId id; + const char *name; + uint16_t size; + CommonCluster* (*ctor)(void*); +} static const kKnownClusters[] = { +{% for cluster in clusters %} +{%- if cluster | dynamicCluster(idl) %} + { + ZCL_{{cluster.name | cameltoconst}}_CLUSTER_ID, + "{{cluster.name}}", + sizeof({{cluster.name}}Cluster), + [](void *mem) -> CommonCluster* { + return new(mem) {{cluster.name}}Cluster(); + }, + }, +{%- endif %} +{%- endfor %} +}; + +inline void BridgeRegisterAllAttributeOverrides() +{ +{% for cluster in clusters %} +{%- if cluster | dynamicCluster(idl) %} + static {{cluster.name}}Access {{cluster.name}}; + registerAttributeAccessOverride(&{{cluster.name}}); +{%- endif %} +{%- endfor %} +} + +struct AttrInfo +{ + chip::ClusterId cluster; + chip::AttributeId attr; + const char *name; +} static const kKnownAttributes[] = { +{% for cluster in clusters %} +{%- if cluster | dynamicCluster(idl) %} + +{%- for attr in cluster.attributes %} + {ZCL_{{cluster.name | cameltoconst}}_CLUSTER_ID, {{attr.definition.code}}, "{{attr.definition.name | capitalcase}}" }, +{%- endfor %} + +{%- endif %} +{%- endfor %} + +}; + +} diff --git a/scripts/idl/generators/cpp/__init__.py b/scripts/idl/generators/cpp/__init__.py new file mode 100644 index 00000000000000..19545ef3bb099e --- /dev/null +++ b/scripts/idl/generators/cpp/__init__.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python +# Copyright (c) 2022 Project CHIP Authors +# +# 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. + +import enum +import logging +import re + +from idl.generators import CodeGenerator, GeneratorStorage +from idl.matter_idl_types import (Idl, ClusterSide, Field, Attribute, Cluster, + FieldAttribute, Command, DataType, Struct) +from idl import matter_idl_types +from idl.generators.types import (ParseDataType, BasicString, BasicInteger, FundamentalType, + IdlType, IdlItemType, IdlEnumType, IdlBitmapType, TypeLookupContext) +from typing import Union, List, Set + + +def camel_to_const(s): + return re.sub("([a-z])([A-Z])", lambda y: y.group(1) + "_" + y.group(2), s).upper() + + +def create_lookup_context(idl: Idl, cluster: Cluster) -> TypeLookupContext: + """ + A filter to mark a lookup context to be within a specific cluster. + + This is used to specify how structure/enum/other names are looked up. + Generally one looks up within the specific cluster then if cluster does + not contain a definition, we loop at global namespacing. + """ + return TypeLookupContext(idl, cluster) + + +def get_field_info(definition: Field, cluster: Cluster, idl: Idl): + context = create_lookup_context(idl, cluster) + actual = ParseDataType(definition.data_type, context) + + orig = actual + is_enum = type(actual) == IdlEnumType + + if type(actual) == IdlEnumType: + actual = actual.base_type + elif type(actual) == IdlBitmapType: + actual = actual.base_type + + if type(actual) == BasicString: + return 'OctetString', 'char', actual.max_length, \ + 'ZCL_%s_ATTRIBUTE_TYPE' % orig.idl_name.upper() + + if type(actual) == BasicInteger: + name = orig.idl_name.upper() + if is_enum: + name = actual.idl_name.upper() + ty = "int%d_t" % actual.power_of_two_bits + if not actual.is_signed: + ty = "u" + ty + return "PrimitiveType", ty, actual.byte_count, "ZCL_%s_ATTRIBUTE_TYPE" % name + if type(actual) == FundamentalType: + if actual == FundamentalType.BOOL: + return "PrimitiveType", "bool", 1, "ZCL_BOOLEAN_ATTRIBUTE_TYPE" + if actual == FundamentalType.FLOAT: + return "PrimitiveType", "float", 4, "ZCL_SINGLE_ATTRIBUTE_TYPE" + if actual == FundamentalType.DOUBLE: + return "PrimitiveType", "double", 8, "ZCL_DOUBLE_ATTRIBUTE_TYPE" + logging.warn('Unknown fundamental type: %r' % actual) + return None + if type(actual) == IdlType: + return 'StructType', actual.idl_name, 'sizeof(%s)' % actual.idl_name, \ + 'ZCL_STRUCT_ATTRIBUTE_TYPE' + logging.warn('Unknown type: %r' % actual) + return None + + +def get_array_count(attr: Attribute): + # TBD how to determine array lengths? + return 1 + + +def get_raw_size_and_type(attr: Attribute, cluster: Cluster, idl: Idl): + container, cType, size, matterType = get_field_info(attr.definition, cluster, idl) + if attr.definition.is_list: + return 'ZCL_ARRAY_ATTRIBUTE_TYPE, {} * {} + 2'.format(size, get_array_count(attr)) + return '{}, {}'.format(matterType, size) + + +def get_field_type(definition: Field, cluster: Cluster, idl: Idl): + container, cType, size, matterType = get_field_info(definition, cluster, idl) + if container == 'StructType': + return 'StructType<{}>'.format(cType) + if container == 'OctetString': + return 'OctetString<{}, {}>'.format(size, matterType) + return '{}<{}, {}, {}>'.format(container, cType, size, matterType) + + +def get_attr_type(attr: Attribute, cluster: Cluster, idl: Idl): + decl = get_field_type(attr.definition, cluster, idl) + if attr.definition.is_list: + count = get_array_count(attr) + return 'ArrayType<{}, {}>'.format(count, decl) + return decl + + +def get_attr_init(attr: Attribute, cluster: Cluster, idl: Idl): + if attr.definition.name == 'clusterRevision': + return ' = ZCL_' + camel_to_const(cluster.name) + '_CLUSTER_REVISION' + return '' + + +def get_attr_mask(attr: Attribute, cluster: Cluster, idl: Idl): + masks = [] + if attr.is_writable: + masks.append('ATTRIBUTE_MASK_WRITABLE') + if masks: + return ' | '.join(masks) + return '0' + + +def get_dynamic_endpoint(idl: Idl): + for ep in idl.endpoints: + if ep.number == 2: + return ep + + +def is_dynamic_cluster(cluster: Cluster, idl: Idl): + ep = get_dynamic_endpoint(idl) + if not ep: + return True + for c in ep.server_clusters: + if cluster.name == c.name: + return True + return False + + +class CppGenerator(CodeGenerator): + """ + Generation of cpp code for matter. + """ + + def __init__(self, storage: GeneratorStorage, idl: Idl): + """ + Inintialization is specific for cpp generation and will add + filters as required by the cpp .jinja templates to function. + """ + super().__init__(storage, idl) + + self.jinja_env.filters['getType'] = get_attr_type + self.jinja_env.filters['getRawSizeAndType'] = get_raw_size_and_type + self.jinja_env.filters['getField'] = get_field_type + self.jinja_env.filters['getMask'] = get_attr_mask + self.jinja_env.filters['getInit'] = get_attr_init + self.jinja_env.filters['dynamicCluster'] = is_dynamic_cluster + # constcase will transform ID to I_D which is not what we want + # instead make the requirement a transition from lower to upper + self.jinja_env.filters['cameltoconst'] = camel_to_const + + def internal_render_all(self): + """ + Renders C++ + """ + + self.internal_render_one_output( + template_path="cpp/BridgeClustersCpp.jinja", + output_file_name="cpp/BridgeClustersImpl.h", + vars={ + 'clusters': self.idl.clusters, + 'idl': self.idl, + 'structs': self.idl.structs, + } + ) diff --git a/scripts/idl/test_generators.py b/scripts/idl/test_generators.py index 325ebb0b0d01f9..bdb2655a2faa7a 100755 --- a/scripts/idl/test_generators.py +++ b/scripts/idl/test_generators.py @@ -32,6 +32,7 @@ from idl.matter_idl_types import Idl from idl.generators.java import JavaGenerator +from idl.generators.cpp import CppGenerator from idl.generators import GeneratorStorage @@ -100,6 +101,8 @@ def add_test_cases(self, yaml_test_case_dict): def _create_generator(self, storage: GeneratorStorage, idl: Idl): if self.generator_name.lower() == 'java': return JavaGenerator(storage, idl) + if self.generator_name.lower() == 'cpp': + return CppGenerator(storage, idl) else: raise Exception("Unknown generator for testing: %s", self.generator_name.lower()) diff --git a/scripts/idl/tests/available_tests.yaml b/scripts/idl/tests/available_tests.yaml index 107eb0ad4fb42a..54202c8473fe83 100644 --- a/scripts/idl/tests/available_tests.yaml +++ b/scripts/idl/tests/available_tests.yaml @@ -34,3 +34,16 @@ java: inputs/optional_argument.matter: jni/MyClusterClient-ReadImpl.cpp: outputs/optional_argument/jni/MyClusterClient-ReadImpl.cpp jni/MyClusterClient-InvokeSubscribeImpl.cpp: outputs/optional_argument/jni/MyClusterClient-InvokeSubscribeImpl.cpp + +cpp: + inputs/simple_attribute.matter: + cpp/BridgeClustersImpl.h: outputs/simple_attribute/cpp/BridgeClustersImpl.h + + inputs/global_struct_attribute.matter: + cpp/BridgeClustersImpl.h: outputs/global_struct_attribute/cpp/BridgeClustersImpl.h + + inputs/cluster_struct_attribute.matter: + cpp/BridgeClustersImpl.h: outputs/cluster_struct_attribute/cpp/BridgeClustersImpl.h + + inputs/several_clusters.matter: + cpp/BridgeClustersImpl.h: outputs/several_clusters/cpp/BridgeClustersImpl.h diff --git a/scripts/idl/tests/outputs/cluster_struct_attribute/cpp/BridgeClustersImpl.h b/scripts/idl/tests/outputs/cluster_struct_attribute/cpp/BridgeClustersImpl.h new file mode 100644 index 00000000000000..8b33c1698d9291 --- /dev/null +++ b/scripts/idl/tests/outputs/cluster_struct_attribute/cpp/BridgeClustersImpl.h @@ -0,0 +1,148 @@ +#include +#include + +#include + +namespace clusters { + +struct DemoClusterCluster : public CommonCluster +{ + + + static constexpr chip::ClusterId kClusterId = ZCL_DEMO_CLUSTER_CLUSTER_ID; + + chip::ClusterId GetClusterId() override { return kClusterId; } + + CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + switch(aPath.mAttributeId) + { + case 5: + return mSingleFailSafe.Write(aPath, aDecoder); + case 100: + return mArmFailsafes.Write(aPath, aDecoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + template + void AddAllAttributes(T *list) + { + list->Add(mSingleFailSafe); + list->Add(mArmFailsafes); + } + + chip::Span GetAllAttributes() override + { + static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { + { 5, ZCL_STRUCT_ATTRIBUTE_TYPE, sizeof(ArmFailSafeRequest), ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, + { 100, ZCL_ARRAY_ATTRIBUTE_TYPE, sizeof(ArmFailSafeRequest) * 1 + 2, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, + }; + return chip::Span(kAllAttributes); + } + + + Attribute<5, ATTRIBUTE_MASK_WRITABLE, StructType> mSingleFailSafe; + Attribute<100, ATTRIBUTE_MASK_WRITABLE, ArrayType<1, StructType>> mArmFailsafes; +}; + +struct DemoClusterAccess : public CommonAttributeAccessInterface +{ + DemoClusterAccess() : CommonAttributeAccessInterface(chip::Optional(), DemoClusterCluster::kClusterId) {} + + DemoClusterCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) + { + CommonCluster * cluster = FindCluster(aPath); + return cluster ? static_cast(cluster) : nullptr; + } + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + + switch(aPath.mAttributeId) { + case 5: + return c->mSingleFailSafe.Read(aPath, aEncoder); + case 100: + return c->mArmFailsafes.Read(aPath, aEncoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + return c->ForwardWriteToBridge(aPath, aDecoder); + } + + void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + case 100: + mArmFailsafes.ListWriteBegin(aPath); + return; + } + } + + void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + case 100: + mArmFailsafes.ListWriteEnd(aPath, aWriteWasSuccessful); + return; + } + } +}; + +struct ClusterInfo +{ + chip::ClusterId id; + const char *name; + uint16_t size; + CommonCluster* (*ctor)(void*); +} static const kKnownClusters[] = { + + { + ZCL_DEMO_CLUSTER_CLUSTER_ID, + "DemoCluster", + sizeof(DemoClusterCluster), + [](void *mem) -> CommonCluster* { + return new(mem) DemoClusterCluster(); + }, + }, +}; + +inline void BridgeRegisterAllAttributeOverrides() +{ + + static DemoClusterAccess DemoCluster; + registerAttributeAccessOverride(&DemoCluster); +} + +struct AttrInfo +{ + chip::ClusterId cluster; + chip::AttributeId attr; + const char *name; +} static const kKnownAttributes[] = { + + {ZCL_DEMO_CLUSTER_CLUSTER_ID, 5, "SingleFailSafe" }, + {ZCL_DEMO_CLUSTER_CLUSTER_ID, 100, "ArmFailsafes" }, + +}; + +} \ No newline at end of file diff --git a/scripts/idl/tests/outputs/global_struct_attribute/cpp/BridgeClustersImpl.h b/scripts/idl/tests/outputs/global_struct_attribute/cpp/BridgeClustersImpl.h new file mode 100644 index 00000000000000..66c25877e96956 --- /dev/null +++ b/scripts/idl/tests/outputs/global_struct_attribute/cpp/BridgeClustersImpl.h @@ -0,0 +1,171 @@ +#include +#include + +#include + +namespace clusters { + +struct LabelStruct +{ + CHIP_ERROR Decode(chip::TLV::TLVReader & reader) + { + chip::app::Clusters::detail::Structs::LabelStruct::DecodableType t; + CHIP_ERROR err = t.Decode(reader); + if(err == CHIP_NO_ERROR) { + label = t.label; + value = t.value; + } + return err; + } + + CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const + { + chip::app::Clusters::detail::Structs::LabelStruct::Type t; + t.label = label; + t.value = value; + return t.Encode(writer, tag); + } + OctetString<16, ZCL_CHAR_STRING_ATTRIBUTE_TYPE> label; + OctetString<16, ZCL_CHAR_STRING_ATTRIBUTE_TYPE> value; +}; +struct DemoClusterCluster : public CommonCluster +{ + + + static constexpr chip::ClusterId kClusterId = ZCL_DEMO_CLUSTER_CLUSTER_ID; + + chip::ClusterId GetClusterId() override { return kClusterId; } + + CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + switch(aPath.mAttributeId) + { + case 32: + return mSingleLabel.Write(aPath, aDecoder); + case 33: + return mSomeLabels.Write(aPath, aDecoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + template + void AddAllAttributes(T *list) + { + list->Add(mSingleLabel); + list->Add(mSomeLabels); + } + + chip::Span GetAllAttributes() override + { + static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { + { 32, ZCL_STRUCT_ATTRIBUTE_TYPE, sizeof(LabelStruct), ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, + { 33, ZCL_ARRAY_ATTRIBUTE_TYPE, sizeof(LabelStruct) * 1 + 2, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, + }; + return chip::Span(kAllAttributes); + } + + + Attribute<32, ATTRIBUTE_MASK_WRITABLE, StructType> mSingleLabel; + Attribute<33, ATTRIBUTE_MASK_WRITABLE, ArrayType<1, StructType>> mSomeLabels; +}; + +struct DemoClusterAccess : public CommonAttributeAccessInterface +{ + DemoClusterAccess() : CommonAttributeAccessInterface(chip::Optional(), DemoClusterCluster::kClusterId) {} + + DemoClusterCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) + { + CommonCluster * cluster = FindCluster(aPath); + return cluster ? static_cast(cluster) : nullptr; + } + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + + switch(aPath.mAttributeId) { + case 32: + return c->mSingleLabel.Read(aPath, aEncoder); + case 33: + return c->mSomeLabels.Read(aPath, aEncoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + return c->ForwardWriteToBridge(aPath, aDecoder); + } + + void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + case 33: + mSomeLabels.ListWriteBegin(aPath); + return; + } + } + + void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + case 33: + mSomeLabels.ListWriteEnd(aPath, aWriteWasSuccessful); + return; + } + } +}; + +struct ClusterInfo +{ + chip::ClusterId id; + const char *name; + uint16_t size; + CommonCluster* (*ctor)(void*); +} static const kKnownClusters[] = { + + { + ZCL_DEMO_CLUSTER_CLUSTER_ID, + "DemoCluster", + sizeof(DemoClusterCluster), + [](void *mem) -> CommonCluster* { + return new(mem) DemoClusterCluster(); + }, + }, +}; + +inline void BridgeRegisterAllAttributeOverrides() +{ + + static DemoClusterAccess DemoCluster; + registerAttributeAccessOverride(&DemoCluster); +} + +struct AttrInfo +{ + chip::ClusterId cluster; + chip::AttributeId attr; + const char *name; +} static const kKnownAttributes[] = { + + {ZCL_DEMO_CLUSTER_CLUSTER_ID, 32, "SingleLabel" }, + {ZCL_DEMO_CLUSTER_CLUSTER_ID, 33, "SomeLabels" }, + +}; + +} \ No newline at end of file diff --git a/scripts/idl/tests/outputs/several_clusters/cpp/BridgeClustersImpl.h b/scripts/idl/tests/outputs/several_clusters/cpp/BridgeClustersImpl.h new file mode 100644 index 00000000000000..dd2eadd39dcf6f --- /dev/null +++ b/scripts/idl/tests/outputs/several_clusters/cpp/BridgeClustersImpl.h @@ -0,0 +1,334 @@ +#include +#include + +#include + +namespace clusters { + +struct FirstCluster : public CommonCluster +{ + + + static constexpr chip::ClusterId kClusterId = ZCL_FIRST_CLUSTER_ID; + + chip::ClusterId GetClusterId() override { return kClusterId; } + + CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + switch(aPath.mAttributeId) + { + case 1: + return mSomeInteger.Write(aPath, aDecoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + template + void AddAllAttributes(T *list) + { + list->Add(mSomeInteger); + } + + chip::Span GetAllAttributes() override + { + static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { + { 1, ZCL_INT16U_ATTRIBUTE_TYPE, 2, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, + }; + return chip::Span(kAllAttributes); + } + + + Attribute<1, ATTRIBUTE_MASK_WRITABLE, PrimitiveType> mSomeInteger; +}; + +struct FirstAccess : public CommonAttributeAccessInterface +{ + FirstAccess() : CommonAttributeAccessInterface(chip::Optional(), FirstCluster::kClusterId) {} + + FirstCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) + { + CommonCluster * cluster = FindCluster(aPath); + return cluster ? static_cast(cluster) : nullptr; + } + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + + switch(aPath.mAttributeId) { + case 1: + return c->mSomeInteger.Read(aPath, aEncoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + return c->ForwardWriteToBridge(aPath, aDecoder); + } + + void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + } + } + + void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + } + } +}; +struct SecondCluster : public CommonCluster +{ + + + static constexpr chip::ClusterId kClusterId = ZCL_SECOND_CLUSTER_ID; + + chip::ClusterId GetClusterId() override { return kClusterId; } + + CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + switch(aPath.mAttributeId) + { + case 123: + return mSomeBytes.Write(aPath, aDecoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + template + void AddAllAttributes(T *list) + { + list->Add(mSomeBytes); + } + + chip::Span GetAllAttributes() override + { + static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { + { 123, ZCL_OCTET_STRING_ATTRIBUTE_TYPE, 32, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, + }; + return chip::Span(kAllAttributes); + } + + + Attribute<123, 0, OctetString<32, ZCL_OCTET_STRING_ATTRIBUTE_TYPE>> mSomeBytes; +}; + +struct SecondAccess : public CommonAttributeAccessInterface +{ + SecondAccess() : CommonAttributeAccessInterface(chip::Optional(), SecondCluster::kClusterId) {} + + SecondCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) + { + CommonCluster * cluster = FindCluster(aPath); + return cluster ? static_cast(cluster) : nullptr; + } + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + + switch(aPath.mAttributeId) { + case 123: + return c->mSomeBytes.Read(aPath, aEncoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + return c->ForwardWriteToBridge(aPath, aDecoder); + } + + void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + } + } + + void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + } + } +}; +struct ThirdCluster : public CommonCluster +{ + + + static constexpr chip::ClusterId kClusterId = ZCL_THIRD_CLUSTER_ID; + + chip::ClusterId GetClusterId() override { return kClusterId; } + + CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + switch(aPath.mAttributeId) + { + case 10: + return mSomeEnum.Write(aPath, aDecoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + template + void AddAllAttributes(T *list) + { + list->Add(mSomeEnum); + } + + chip::Span GetAllAttributes() override + { + static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { + { 10, ZCL_ENUM8_ATTRIBUTE_TYPE, 1, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, + }; + return chip::Span(kAllAttributes); + } + + + Attribute<10, ATTRIBUTE_MASK_WRITABLE, PrimitiveType> mSomeEnum; +}; + +struct ThirdAccess : public CommonAttributeAccessInterface +{ + ThirdAccess() : CommonAttributeAccessInterface(chip::Optional(), ThirdCluster::kClusterId) {} + + ThirdCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) + { + CommonCluster * cluster = FindCluster(aPath); + return cluster ? static_cast(cluster) : nullptr; + } + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + + switch(aPath.mAttributeId) { + case 10: + return c->mSomeEnum.Read(aPath, aEncoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + return c->ForwardWriteToBridge(aPath, aDecoder); + } + + void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + } + } + + void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + } + } +}; + +struct ClusterInfo +{ + chip::ClusterId id; + const char *name; + uint16_t size; + CommonCluster* (*ctor)(void*); +} static const kKnownClusters[] = { + + { + ZCL_FIRST_CLUSTER_ID, + "First", + sizeof(FirstCluster), + [](void *mem) -> CommonCluster* { + return new(mem) FirstCluster(); + }, + }, + { + ZCL_SECOND_CLUSTER_ID, + "Second", + sizeof(SecondCluster), + [](void *mem) -> CommonCluster* { + return new(mem) SecondCluster(); + }, + }, + { + ZCL_THIRD_CLUSTER_ID, + "Third", + sizeof(ThirdCluster), + [](void *mem) -> CommonCluster* { + return new(mem) ThirdCluster(); + }, + }, +}; + +inline void BridgeRegisterAllAttributeOverrides() +{ + + static FirstAccess First; + registerAttributeAccessOverride(&First); + static SecondAccess Second; + registerAttributeAccessOverride(&Second); + static ThirdAccess Third; + registerAttributeAccessOverride(&Third); +} + +struct AttrInfo +{ + chip::ClusterId cluster; + chip::AttributeId attr; + const char *name; +} static const kKnownAttributes[] = { + + {ZCL_FIRST_CLUSTER_ID, 1, "SomeInteger" }, + {ZCL_SECOND_CLUSTER_ID, 123, "SomeBytes" }, + {ZCL_THIRD_CLUSTER_ID, 10, "SomeEnum" }, + +}; + +} \ No newline at end of file diff --git a/scripts/idl/tests/outputs/simple_attribute/cpp/BridgeClustersImpl.h b/scripts/idl/tests/outputs/simple_attribute/cpp/BridgeClustersImpl.h new file mode 100644 index 00000000000000..f1ab64679102e1 --- /dev/null +++ b/scripts/idl/tests/outputs/simple_attribute/cpp/BridgeClustersImpl.h @@ -0,0 +1,134 @@ +#include +#include + +#include + +namespace clusters { + +struct MyClusterCluster : public CommonCluster +{ + + + static constexpr chip::ClusterId kClusterId = ZCL_MY_CLUSTER_CLUSTER_ID; + + chip::ClusterId GetClusterId() override { return kClusterId; } + + CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + switch(aPath.mAttributeId) + { + case 1: + return mClusterAttr.Write(aPath, aDecoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + template + void AddAllAttributes(T *list) + { + list->Add(mClusterAttr); + } + + chip::Span GetAllAttributes() override + { + static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { + { 1, ZCL_INT16U_ATTRIBUTE_TYPE, 2, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, + }; + return chip::Span(kAllAttributes); + } + + + Attribute<1, ATTRIBUTE_MASK_WRITABLE, PrimitiveType> mClusterAttr; +}; + +struct MyClusterAccess : public CommonAttributeAccessInterface +{ + MyClusterAccess() : CommonAttributeAccessInterface(chip::Optional(), MyClusterCluster::kClusterId) {} + + MyClusterCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) + { + CommonCluster * cluster = FindCluster(aPath); + return cluster ? static_cast(cluster) : nullptr; + } + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + + switch(aPath.mAttributeId) { + case 1: + return c->mClusterAttr.Read(aPath, aEncoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + return c->ForwardWriteToBridge(aPath, aDecoder); + } + + void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + } + } + + void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + } + } +}; + +struct ClusterInfo +{ + chip::ClusterId id; + const char *name; + uint16_t size; + CommonCluster* (*ctor)(void*); +} static const kKnownClusters[] = { + + { + ZCL_MY_CLUSTER_CLUSTER_ID, + "MyCluster", + sizeof(MyClusterCluster), + [](void *mem) -> CommonCluster* { + return new(mem) MyClusterCluster(); + }, + }, +}; + +inline void BridgeRegisterAllAttributeOverrides() +{ + + static MyClusterAccess MyCluster; + registerAttributeAccessOverride(&MyCluster); +} + +struct AttrInfo +{ + chip::ClusterId cluster; + chip::AttributeId attr; + const char *name; +} static const kKnownAttributes[] = { + + {ZCL_MY_CLUSTER_CLUSTER_ID, 1, "ClusterAttr" }, + +}; + +} \ No newline at end of file From 9a5d3b72ec45aaf2a9ebe7d63e9301e9773dd11e Mon Sep 17 00:00:00 2001 From: Albert Chaulk Date: Mon, 15 Aug 2022 14:21:35 -0400 Subject: [PATCH 02/14] fix build --- examples/bridge-app/linux/Device.cpp | 13 +++++++++++++ examples/bridge-app/linux/bridged-actions-stub.cpp | 8 +------- examples/bridge-app/linux/include/Clusters.h | 13 +++++++------ examples/bridge-app/linux/include/Device.h | 1 + examples/bridge-app/linux/include/main.h | 4 ++-- examples/bridge-app/linux/main.cpp | 5 ++--- scripts/idl/generators/cpp/BridgeClustersCpp.jinja | 6 +++--- 7 files changed, 29 insertions(+), 21 deletions(-) diff --git a/examples/bridge-app/linux/Device.cpp b/examples/bridge-app/linux/Device.cpp index 05a78bf94a17ad..490297f22ccc4e 100644 --- a/examples/bridge-app/linux/Device.cpp +++ b/examples/bridge-app/linux/Device.cpp @@ -27,8 +27,21 @@ Device::Device(chip::Span dataVersions, chip::SpanSetEndpointId(id); } + +const char * Device::GetName() +{ + return mDeviceName; +} + +void Device::SetName(const char * name) +{ + mDeviceName = name; +} diff --git a/examples/bridge-app/linux/bridged-actions-stub.cpp b/examples/bridge-app/linux/bridged-actions-stub.cpp index 46be4848d51603..6c0f7cf8eb680e 100644 --- a/examples/bridge-app/linux/bridged-actions-stub.cpp +++ b/examples/bridge-app/linux/bridged-actions-stub.cpp @@ -84,17 +84,11 @@ CHIP_ERROR ActionsAttrAccess::ReadEndpointListAttribute(EndpointId endpoint, Att CHIP_ERROR err = aEncoder.EncodeList([](const auto & encoder) -> CHIP_ERROR { for (auto & room : gRooms) { -<<<<<<< HEAD - Actions::Structs::EndpointListStruct::Type endpointListStruct = { - info.GetEndpointListId(), CharSpan::fromCharString(info.GetName().c_str()), info.GetType(), - DataModel::List(info.GetEndpointListData(), info.GetEndpointListSize()) -======= if (room.GetEndpointListSize() == 0) continue; - BridgedActions::Structs::EndpointListStruct::Type endpointListStruct = { + Actions::Structs::EndpointListStruct::Type endpointListStruct = { room.GetEndpointListId(), CharSpan::fromCharString(room.GetName().c_str()), room.GetType(), DataModel::List(room.GetEndpointListData(), room.GetEndpointListSize()) ->>>>>>> ebb974a33 (Update bridge app) }; ReturnErrorOnFailure(encoder.Encode(endpointListStruct)); } diff --git a/examples/bridge-app/linux/include/Clusters.h b/examples/bridge-app/linux/include/Clusters.h index b36f5f2b34ec46..e6791985d0c927 100644 --- a/examples/bridge-app/linux/include/Clusters.h +++ b/examples/bridge-app/linux/include/Clusters.h @@ -28,12 +28,13 @@ #include -static constexpr uint16_t ZCL_DESCRIPTOR_CLUSTER_REVISION = 1; -static constexpr uint16_t ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_REVISION = 1; -static constexpr uint16_t ZCL_FIXED_LABEL_CLUSTER_REVISION = 1; -static constexpr uint16_t ZCL_ON_OFF_CLUSTER_REVISION = 4; -static constexpr uint16_t ZCL_SWITCH_CLUSTER_REVISION = 1; -static constexpr uint16_t ZCL_LEVEL_CONTROL_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_DESCRIPTOR_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_FIXED_LABEL_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_ON_OFF_CLUSTER_REVISION = 4; +static constexpr uint16_t ZCL_SWITCH_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_LEVEL_CONTROL_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_TEMPERATURE_MEASUREMENT_CLUSTER_REVISION = 1; // This is the interface to cluster implementations, providing access to manipulate attributes. class ClusterImpl diff --git a/examples/bridge-app/linux/include/Device.h b/examples/bridge-app/linux/include/Device.h index 2f665193874323..2a127694c348f4 100644 --- a/examples/bridge-app/linux/include/Device.h +++ b/examples/bridge-app/linux/include/Device.h @@ -19,6 +19,7 @@ #pragma once #include +#include #include #include diff --git a/examples/bridge-app/linux/include/main.h b/examples/bridge-app/linux/include/main.h index 583ed40992db46..77342a5c5e3ca3 100644 --- a/examples/bridge-app/linux/include/main.h +++ b/examples/bridge-app/linux/include/main.h @@ -26,7 +26,7 @@ class Room Room() = default; void SetName(std::string name) { mName = name; } const std::string & GetName() { return mName; } - chip::app::Clusters::BridgedActions::EndpointListTypeEnum GetType() { return mType; }; + chip::app::Clusters::Actions::EndpointListTypeEnum GetType() { return mType; }; uint16_t GetEndpointListId() { return mEndpointListId; }; chip::EndpointId * GetEndpointListData() { return mEndpoints.data(); }; size_t GetEndpointListSize() { return mEndpoints.size(); }; @@ -42,7 +42,7 @@ class Room private: std::string mName; uint16_t mEndpointListId = 0; - chip::app::Clusters::BridgedActions::EndpointListTypeEnum mType; + chip::app::Clusters::Actions::EndpointListTypeEnum mType; std::vector mEndpoints; }; diff --git a/examples/bridge-app/linux/main.cpp b/examples/bridge-app/linux/main.cpp index 69deb96e7ee5ce..867d89838abcec 100644 --- a/examples/bridge-app/linux/main.cpp +++ b/examples/bridge-app/linux/main.cpp @@ -66,9 +66,8 @@ static EndpointId gFirstDynamicEndpointId; static Device * gDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT]; Room gRooms[kMaxRooms]; -bool emberAfBridgedActionsClusterInstantActionCallback(app::CommandHandler * commandObj, - const app::ConcreteCommandPath & commandPath, - const BridgedActions::Commands::InstantAction::DecodableType & commandData) +bool emberAfActionsClusterInstantActionCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, + const Actions::Commands::InstantAction::DecodableType & commandData) { // No actions are implemented, just return status NotFound. commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::NotFound); diff --git a/scripts/idl/generators/cpp/BridgeClustersCpp.jinja b/scripts/idl/generators/cpp/BridgeClustersCpp.jinja index 028fe574fa1b4e..f3f3746e10dfbd 100644 --- a/scripts/idl/generators/cpp/BridgeClustersCpp.jinja +++ b/scripts/idl/generators/cpp/BridgeClustersCpp.jinja @@ -71,7 +71,7 @@ struct {{cluster.name}}Cluster : public CommonCluster {%- endfor %} - static constexpr chip::ClusterId kClusterId = ZCL_{{cluster.name | cameltoconst}}_CLUSTER_ID; + static constexpr chip::ClusterId kClusterId = {{cluster.code}}; chip::ClusterId GetClusterId() override { return kClusterId; } @@ -198,7 +198,7 @@ struct ClusterInfo {% for cluster in clusters %} {%- if cluster | dynamicCluster(idl) %} { - ZCL_{{cluster.name | cameltoconst}}_CLUSTER_ID, + {{cluster.code}}, "{{cluster.name}}", sizeof({{cluster.name}}Cluster), [](void *mem) -> CommonCluster* { @@ -229,7 +229,7 @@ struct AttrInfo {%- if cluster | dynamicCluster(idl) %} {%- for attr in cluster.attributes %} - {ZCL_{{cluster.name | cameltoconst}}_CLUSTER_ID, {{attr.definition.code}}, "{{attr.definition.name | capitalcase}}" }, + { {{cluster.code}}, {{attr.definition.code}}, "{{attr.definition.name | capitalcase}}" }, {%- endfor %} {%- endif %} From 035b8a5eede57f486f8e50a68484c11ebec6e375 Mon Sep 17 00:00:00 2001 From: Albert Chaulk Date: Tue, 16 Aug 2022 16:44:09 -0400 Subject: [PATCH 03/14] fix test outputs --- .../cpp/BridgeClustersImpl.h | 8 ++++---- .../cpp/BridgeClustersImpl.h | 8 ++++---- .../several_clusters/cpp/BridgeClustersImpl.h | 18 +++++++++--------- .../simple_attribute/cpp/BridgeClustersImpl.h | 6 +++--- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/scripts/idl/tests/outputs/cluster_struct_attribute/cpp/BridgeClustersImpl.h b/scripts/idl/tests/outputs/cluster_struct_attribute/cpp/BridgeClustersImpl.h index 8b33c1698d9291..78ec3c5ab7be5e 100644 --- a/scripts/idl/tests/outputs/cluster_struct_attribute/cpp/BridgeClustersImpl.h +++ b/scripts/idl/tests/outputs/cluster_struct_attribute/cpp/BridgeClustersImpl.h @@ -9,7 +9,7 @@ struct DemoClusterCluster : public CommonCluster { - static constexpr chip::ClusterId kClusterId = ZCL_DEMO_CLUSTER_CLUSTER_ID; + static constexpr chip::ClusterId kClusterId = 10; chip::ClusterId GetClusterId() override { return kClusterId; } @@ -117,7 +117,7 @@ struct ClusterInfo } static const kKnownClusters[] = { { - ZCL_DEMO_CLUSTER_CLUSTER_ID, + 10, "DemoCluster", sizeof(DemoClusterCluster), [](void *mem) -> CommonCluster* { @@ -140,8 +140,8 @@ struct AttrInfo const char *name; } static const kKnownAttributes[] = { - {ZCL_DEMO_CLUSTER_CLUSTER_ID, 5, "SingleFailSafe" }, - {ZCL_DEMO_CLUSTER_CLUSTER_ID, 100, "ArmFailsafes" }, + { 10, 5, "SingleFailSafe" }, + { 10, 100, "ArmFailsafes" }, }; diff --git a/scripts/idl/tests/outputs/global_struct_attribute/cpp/BridgeClustersImpl.h b/scripts/idl/tests/outputs/global_struct_attribute/cpp/BridgeClustersImpl.h index 66c25877e96956..f92843f069280f 100644 --- a/scripts/idl/tests/outputs/global_struct_attribute/cpp/BridgeClustersImpl.h +++ b/scripts/idl/tests/outputs/global_struct_attribute/cpp/BridgeClustersImpl.h @@ -32,7 +32,7 @@ struct DemoClusterCluster : public CommonCluster { - static constexpr chip::ClusterId kClusterId = ZCL_DEMO_CLUSTER_CLUSTER_ID; + static constexpr chip::ClusterId kClusterId = 18; chip::ClusterId GetClusterId() override { return kClusterId; } @@ -140,7 +140,7 @@ struct ClusterInfo } static const kKnownClusters[] = { { - ZCL_DEMO_CLUSTER_CLUSTER_ID, + 18, "DemoCluster", sizeof(DemoClusterCluster), [](void *mem) -> CommonCluster* { @@ -163,8 +163,8 @@ struct AttrInfo const char *name; } static const kKnownAttributes[] = { - {ZCL_DEMO_CLUSTER_CLUSTER_ID, 32, "SingleLabel" }, - {ZCL_DEMO_CLUSTER_CLUSTER_ID, 33, "SomeLabels" }, + { 18, 32, "SingleLabel" }, + { 18, 33, "SomeLabels" }, }; diff --git a/scripts/idl/tests/outputs/several_clusters/cpp/BridgeClustersImpl.h b/scripts/idl/tests/outputs/several_clusters/cpp/BridgeClustersImpl.h index dd2eadd39dcf6f..6cea2430bd0c86 100644 --- a/scripts/idl/tests/outputs/several_clusters/cpp/BridgeClustersImpl.h +++ b/scripts/idl/tests/outputs/several_clusters/cpp/BridgeClustersImpl.h @@ -9,7 +9,7 @@ struct FirstCluster : public CommonCluster { - static constexpr chip::ClusterId kClusterId = ZCL_FIRST_CLUSTER_ID; + static constexpr chip::ClusterId kClusterId = 1; chip::ClusterId GetClusterId() override { return kClusterId; } @@ -98,7 +98,7 @@ struct SecondCluster : public CommonCluster { - static constexpr chip::ClusterId kClusterId = ZCL_SECOND_CLUSTER_ID; + static constexpr chip::ClusterId kClusterId = 2; chip::ClusterId GetClusterId() override { return kClusterId; } @@ -187,7 +187,7 @@ struct ThirdCluster : public CommonCluster { - static constexpr chip::ClusterId kClusterId = ZCL_THIRD_CLUSTER_ID; + static constexpr chip::ClusterId kClusterId = 3; chip::ClusterId GetClusterId() override { return kClusterId; } @@ -282,7 +282,7 @@ struct ClusterInfo } static const kKnownClusters[] = { { - ZCL_FIRST_CLUSTER_ID, + 1, "First", sizeof(FirstCluster), [](void *mem) -> CommonCluster* { @@ -290,7 +290,7 @@ struct ClusterInfo }, }, { - ZCL_SECOND_CLUSTER_ID, + 2, "Second", sizeof(SecondCluster), [](void *mem) -> CommonCluster* { @@ -298,7 +298,7 @@ struct ClusterInfo }, }, { - ZCL_THIRD_CLUSTER_ID, + 3, "Third", sizeof(ThirdCluster), [](void *mem) -> CommonCluster* { @@ -325,9 +325,9 @@ struct AttrInfo const char *name; } static const kKnownAttributes[] = { - {ZCL_FIRST_CLUSTER_ID, 1, "SomeInteger" }, - {ZCL_SECOND_CLUSTER_ID, 123, "SomeBytes" }, - {ZCL_THIRD_CLUSTER_ID, 10, "SomeEnum" }, + { 1, 1, "SomeInteger" }, + { 2, 123, "SomeBytes" }, + { 3, 10, "SomeEnum" }, }; diff --git a/scripts/idl/tests/outputs/simple_attribute/cpp/BridgeClustersImpl.h b/scripts/idl/tests/outputs/simple_attribute/cpp/BridgeClustersImpl.h index f1ab64679102e1..e276240132a6fa 100644 --- a/scripts/idl/tests/outputs/simple_attribute/cpp/BridgeClustersImpl.h +++ b/scripts/idl/tests/outputs/simple_attribute/cpp/BridgeClustersImpl.h @@ -9,7 +9,7 @@ struct MyClusterCluster : public CommonCluster { - static constexpr chip::ClusterId kClusterId = ZCL_MY_CLUSTER_CLUSTER_ID; + static constexpr chip::ClusterId kClusterId = 123; chip::ClusterId GetClusterId() override { return kClusterId; } @@ -104,7 +104,7 @@ struct ClusterInfo } static const kKnownClusters[] = { { - ZCL_MY_CLUSTER_CLUSTER_ID, + 123, "MyCluster", sizeof(MyClusterCluster), [](void *mem) -> CommonCluster* { @@ -127,7 +127,7 @@ struct AttrInfo const char *name; } static const kKnownAttributes[] = { - {ZCL_MY_CLUSTER_CLUSTER_ID, 1, "ClusterAttr" }, + { 123, 1, "ClusterAttr" }, }; From 4886516d9c9bf61cbe2d5490197fca61b3839d37 Mon Sep 17 00:00:00 2001 From: Albert Chaulk Date: Mon, 22 Aug 2022 15:53:59 -0400 Subject: [PATCH 04/14] Split generated files out Updates userinput backend to run commands on matter thread --- examples/bridge-app/linux/BUILD.gn | 2 +- examples/bridge-app/linux/Device.cpp | 6 +- .../bridge-app/linux/UserInputBackend.cpp | 45 ++- examples/bridge-app/linux/include/Clusters.h | 2 +- examples/bridge-app/linux/main.cpp | 1 - scripts/codegen.py | 10 +- scripts/idl/BUILD.gn | 20 +- .../bridge/BridgeClustersCommon.jinja | 61 ++++ .../{cpp => bridge}/BridgeClustersCpp.jinja | 92 +---- .../bridge/BridgeClustersGlobalStructs.jinja | 38 ++ .../generators/{cpp => bridge}/__init__.py | 28 +- .../bridge/BridgeClustersImpl.h | 44 +++ .../bridge/BridgeGlobalStructs.h | 10 + .../DemoCluster.h} | 47 +-- .../bridge/BridgeClustersImpl.h | 44 +++ .../bridge/BridgeGlobalStructs.h | 33 ++ .../DemoCluster.h} | 70 +--- .../bridge/BridgeClustersImpl.h | 67 ++++ .../bridge/BridgeGlobalStructs.h | 10 + .../outputs/several_clusters/bridge/First.h | 96 +++++ .../outputs/several_clusters/bridge/Second.h | 96 +++++ .../outputs/several_clusters/bridge/Third.h | 96 +++++ .../several_clusters/cpp/BridgeClustersImpl.h | 334 ------------------ .../bridge/BridgeClustersImpl.h | 43 +++ .../bridge/BridgeGlobalStructs.h | 10 + .../MyCluster.h} | 42 +-- 26 files changed, 760 insertions(+), 587 deletions(-) create mode 100644 scripts/idl/generators/bridge/BridgeClustersCommon.jinja rename scripts/idl/generators/{cpp => bridge}/BridgeClustersCpp.jinja (66%) create mode 100644 scripts/idl/generators/bridge/BridgeClustersGlobalStructs.jinja rename scripts/idl/generators/{cpp => bridge}/__init__.py (87%) create mode 100644 scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeClustersImpl.h create mode 100644 scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeGlobalStructs.h rename scripts/idl/tests/outputs/cluster_struct_attribute/{cpp/BridgeClustersImpl.h => bridge/DemoCluster.h} (77%) create mode 100644 scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeClustersImpl.h create mode 100644 scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeGlobalStructs.h rename scripts/idl/tests/outputs/global_struct_attribute/{cpp/BridgeClustersImpl.h => bridge/DemoCluster.h} (66%) create mode 100644 scripts/idl/tests/outputs/several_clusters/bridge/BridgeClustersImpl.h create mode 100644 scripts/idl/tests/outputs/several_clusters/bridge/BridgeGlobalStructs.h create mode 100644 scripts/idl/tests/outputs/several_clusters/bridge/First.h create mode 100644 scripts/idl/tests/outputs/several_clusters/bridge/Second.h create mode 100644 scripts/idl/tests/outputs/several_clusters/bridge/Third.h delete mode 100644 scripts/idl/tests/outputs/several_clusters/cpp/BridgeClustersImpl.h create mode 100644 scripts/idl/tests/outputs/simple_attribute/bridge/BridgeClustersImpl.h create mode 100644 scripts/idl/tests/outputs/simple_attribute/bridge/BridgeGlobalStructs.h rename scripts/idl/tests/outputs/simple_attribute/{cpp/BridgeClustersImpl.h => bridge/MyCluster.h} (77%) diff --git a/examples/bridge-app/linux/BUILD.gn b/examples/bridge-app/linux/BUILD.gn index fadf198709d7a8..2bf6bf7988f91b 100644 --- a/examples/bridge-app/linux/BUILD.gn +++ b/examples/bridge-app/linux/BUILD.gn @@ -27,7 +27,7 @@ action("chip-bridge-codegen") { args = [ "--generator", - "cpp", + "bridge", "--output-dir", rebase_path(target_gen_dir, root_build_dir), rebase_path( diff --git a/examples/bridge-app/linux/Device.cpp b/examples/bridge-app/linux/Device.cpp index 490297f22ccc4e..31d8b5c960fb0c 100644 --- a/examples/bridge-app/linux/Device.cpp +++ b/examples/bridge-app/linux/Device.cpp @@ -27,7 +27,11 @@ Device::Device(chip::Span dataVersions, chip::Span + #include #include +#include #include #include #include @@ -343,6 +346,28 @@ void ParseValue(std::vector * data, uint16_t size, const std::string & case ZCL_DOUBLE_ATTRIBUTE_TYPE: wr.Put(chip::TLV::Tag(), atof(str.c_str())); break; + case ZCL_INT8S_ATTRIBUTE_TYPE: + case ZCL_INT16S_ATTRIBUTE_TYPE: + case ZCL_INT24S_ATTRIBUTE_TYPE: + case ZCL_INT32S_ATTRIBUTE_TYPE: + case ZCL_INT40S_ATTRIBUTE_TYPE: + case ZCL_INT48S_ATTRIBUTE_TYPE: + case ZCL_INT56S_ATTRIBUTE_TYPE: + case ZCL_INT64S_ATTRIBUTE_TYPE: + wr.Put(chip::TLV::Tag(), (int64_t) strtoll(str.c_str(), nullptr, 10)); + break; + + case ZCL_INT8U_ATTRIBUTE_TYPE: + case ZCL_INT16U_ATTRIBUTE_TYPE: + case ZCL_INT24U_ATTRIBUTE_TYPE: + case ZCL_INT32U_ATTRIBUTE_TYPE: + case ZCL_INT40U_ATTRIBUTE_TYPE: + case ZCL_INT48U_ATTRIBUTE_TYPE: + case ZCL_INT56U_ATTRIBUTE_TYPE: + case ZCL_INT64U_ATTRIBUTE_TYPE: + wr.Put(chip::TLV::Tag(), (uint64_t) strtoll(str.c_str(), nullptr, 10)); + break; + default: // Assume integer wr.Put(chip::TLV::Tag(), (int64_t) strtoll(str.c_str(), nullptr, 10)); @@ -401,6 +426,7 @@ void SetValue(const std::vector & tokens) chip::TLV::TLVReader rd; rd.Init(data.data(), data.size()); + rd.Next(); if (!cluster->Push(attr->attributeId, rd)) { @@ -547,6 +573,19 @@ void Help(const std::vector & tokens) } } +struct Op +{ + std::vector * tokens; + const Command * command; + std::promise lock; +}; +void ProcessLineOnMatterThread(intptr_t arg) +{ + Op * op = reinterpret_cast(arg); + op->command->fn(*op->tokens); + op->lock.set_value(); +} + void ProcessLine(std::vector & tokens) { for (auto & cmd : commands) @@ -554,7 +593,11 @@ void ProcessLine(std::vector & tokens) if (tokens[0] == cmd.name) { tokens.erase(tokens.begin()); - cmd.fn(tokens); + + Op op{ &tokens, &cmd }; + chip::DeviceLayer::PlatformMgr().ScheduleWork(&ProcessLineOnMatterThread, reinterpret_cast(&op)); + // Wait for command completion + op.lock.get_future().wait(); return; } } diff --git a/examples/bridge-app/linux/include/Clusters.h b/examples/bridge-app/linux/include/Clusters.h index e6791985d0c927..171b3c869fb124 100644 --- a/examples/bridge-app/linux/include/Clusters.h +++ b/examples/bridge-app/linux/include/Clusters.h @@ -261,7 +261,7 @@ struct CommonAttributeAccessInterface : public chip::app::AttributeAccessInterfa static CommonCluster * FindCluster(const chip::app::ConcreteClusterPath & path); }; -#include "cpp/BridgeClustersImpl.h" +#include "bridge/BridgeClustersImpl.h" namespace clusters { struct BridgedDeviceBasicCluster : public CommonCluster diff --git a/examples/bridge-app/linux/main.cpp b/examples/bridge-app/linux/main.cpp index 867d89838abcec..3f8c42104c05c3 100644 --- a/examples/bridge-app/linux/main.cpp +++ b/examples/bridge-app/linux/main.cpp @@ -96,7 +96,6 @@ int AddDeviceEndpoint(Device * dev) while (1) { // Todo: Update this to schedule the work rather than use this lock - DeviceLayer::StackLock lock; dev->SetEndpointId(gCurrentEndpointId); ret = emberAfSetDynamicEndpoint(index, gCurrentEndpointId, dev->endpointType(), dev->versions(), dev->deviceTypes()); diff --git a/scripts/codegen.py b/scripts/codegen.py index 26c2ad3dc8eac2..3eb6acd047f760 100755 --- a/scripts/codegen.py +++ b/scripts/codegen.py @@ -28,7 +28,7 @@ from idl.generators import FileSystemGeneratorStorage, GeneratorStorage from idl.generators.java import JavaGenerator -from idl.generators.cpp import CppGenerator +from idl.generators.bridge import BridgeGenerator class CodeGeneratorTypes(enum.Enum): @@ -38,13 +38,13 @@ class CodeGeneratorTypes(enum.Enum): into underlying generators. """ JAVA = enum.auto() - CPP = enum.auto() + BRIDGE = enum.auto() def CreateGenerator(self, *args, **kargs): if self == CodeGeneratorTypes.JAVA: return JavaGenerator(*args, **kargs) - elif self == CodeGeneratorTypes.CPP: - return CppGenerator(*args, **kargs) + elif self == CodeGeneratorTypes.BRIDGE: + return BridgeGenerator(*args, **kargs) else: raise Error("Unknown code generator type") @@ -72,7 +72,7 @@ def write_new_data(self, relative_path: str, content: str): __GENERATORS__ = { 'java': CodeGeneratorTypes.JAVA, - 'cpp': CodeGeneratorTypes.CPP, + 'bridge': CodeGeneratorTypes.BRIDGE, } diff --git a/scripts/idl/BUILD.gn b/scripts/idl/BUILD.gn index 28dba784fe5413..d9616391c3baa4 100644 --- a/scripts/idl/BUILD.gn +++ b/scripts/idl/BUILD.gn @@ -25,7 +25,9 @@ pw_python_package("idl") { "matter_grammar.lark", # Templates used for generation - "generators/cpp/BridgeClustersCpp.jinja", + "generators/bridge/BridgeClustersCpp.jinja", + "generators/bridge/BridgeClustersCommon.jinja", + "generators/bridge/BridgeClustersGlobalStructs.jinja", "generators/java/ChipClustersCpp.jinja", "generators/java/ChipClustersRead.jinja", @@ -36,18 +38,32 @@ pw_python_package("idl") { "tests/inputs/optional_argument.matter", "tests/inputs/several_clusters.matter", "tests/inputs/simple_attribute.matter", + "tests/outputs/cluster_struct_attribute/bridge/BridgeClustersImpl.h", + "tests/outputs/cluster_struct_attribute/bridge/BridgeGlobalStructs.h", + "tests/outputs/cluster_struct_attribute/bridge/DemoCluster.h", "tests/outputs/cluster_struct_attribute/jni/DemoClusterClient-ReadImpl.cpp", "tests/outputs/cluster_struct_attribute/jni/DemoClusterClient-InvokeSubscribeImpl.cpp", + "tests/outputs/global_struct_attribute/bridge/BridgeClustersImpl.h", + "tests/outputs/global_struct_attribute/bridge/BridgeGlobalStructs.h", + "tests/outputs/global_struct_attribute/bridge/DemoCluster.h", "tests/outputs/global_struct_attribute/jni/DemoClusterClient-ReadImpl.cpp", "tests/outputs/global_struct_attribute/jni/DemoClusterClient-InvokeSubscribeImpl.cpp", "tests/outputs/optional_argument/jni/MyClusterClient-ReadImpl.cpp", "tests/outputs/optional_argument/jni/MyClusterClient-InvokeSubscribeImpl.cpp", + "tests/outputs/several_clusters/bridge/BridgeClustersImpl.h", + "tests/outputs/several_clusters/bridge/BridgeGlobalStructs.h", + "tests/outputs/several_clusters/bridge/First.h", + "tests/outputs/several_clusters/bridge/Second.h", + "tests/outputs/several_clusters/bridge/Third.h", "tests/outputs/several_clusters/jni/FirstClient-ReadImpl.cpp", "tests/outputs/several_clusters/jni/SecondClient-ReadImpl.cpp", "tests/outputs/several_clusters/jni/ThirdClient-ReadImpl.cpp", "tests/outputs/several_clusters/jni/FirstClient-InvokeSubscribeImpl.cpp", "tests/outputs/several_clusters/jni/SecondClient-InvokeSubscribeImpl.cpp", "tests/outputs/several_clusters/jni/ThirdClient-InvokeSubscribeImpl.cpp", + "tests/outputs/simple_attribute/bridge/BridgeClustersImpl.h", + "tests/outputs/simple_attribute/bridge/BridgeGlobalStructs.h", + "tests/outputs/simple_attribute/bridge/MyCluster.h", "tests/outputs/simple_attribute/jni/MyClusterClient-ReadImpl.cpp", "tests/outputs/simple_attribute/jni/MyClusterClient-InvokeSubscribeImpl.cpp", ] @@ -55,7 +71,7 @@ pw_python_package("idl") { sources = [ "__init__.py", "generators/__init__.py", - "generators/cpp/__init__.py", + "generators/bridge/__init__.py", "generators/filters.py", "generators/java/__init__.py", "generators/types.py", diff --git a/scripts/idl/generators/bridge/BridgeClustersCommon.jinja b/scripts/idl/generators/bridge/BridgeClustersCommon.jinja new file mode 100644 index 00000000000000..0631595d380ebd --- /dev/null +++ b/scripts/idl/generators/bridge/BridgeClustersCommon.jinja @@ -0,0 +1,61 @@ +#pragma once + +#include + +{%- for cluster in clusters %} +{%- if cluster | dynamicCluster(idl) %} +#include "bridge/{{cluster.name}}.h" +{%- endif %} +{%- endfor %} + +namespace clusters { + +struct ClusterInfo +{ + chip::ClusterId id; + const char *name; + uint16_t size; + CommonCluster* (*ctor)(void*); +} static const kKnownClusters[] = { +{% for cluster in clusters %} +{%- if cluster | dynamicCluster(idl) %} + { + {{cluster.code}}, + "{{cluster.name}}", + sizeof({{cluster.name}}Cluster), + [](void *mem) -> CommonCluster* { + return new(mem) {{cluster.name}}Cluster(); + }, + }, +{%- endif %} +{%- endfor %} +}; + +inline void BridgeRegisterAllAttributeOverrides() +{ +{% for cluster in clusters %} +{%- if cluster | dynamicCluster(idl) %} + static {{cluster.name}}Access {{cluster.name}}; + registerAttributeAccessOverride(&{{cluster.name}}); +{%- endif %} +{%- endfor %} +} + +struct AttrInfo +{ + chip::ClusterId cluster; + chip::AttributeId attr; + const char *name; +} static const kKnownAttributes[] = { +{% for cluster in clusters %} +{%- if cluster | dynamicCluster(idl) %} + +{%- for attr in cluster.attributes %} + { {{cluster.code}}, {{attr.definition.code}}, "{{attr.definition.name | capitalcase}}" }, +{%- endfor %} + +{%- endif %} +{%- endfor %} +}; + +} diff --git a/scripts/idl/generators/cpp/BridgeClustersCpp.jinja b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja similarity index 66% rename from scripts/idl/generators/cpp/BridgeClustersCpp.jinja rename to scripts/idl/generators/bridge/BridgeClustersCpp.jinja index f3f3746e10dfbd..51b9383e956551 100644 --- a/scripts/idl/generators/cpp/BridgeClustersCpp.jinja +++ b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja @@ -1,41 +1,8 @@ -#include -#include +#pragma once -#include +#include "BridgeGlobalStructs.h" namespace clusters { -{% for struct in structs %} -struct {{struct.name}} -{ - CHIP_ERROR Decode(chip::TLV::TLVReader & reader) - { - chip::app::Clusters::detail::Structs::{{struct.name}}::DecodableType t; - CHIP_ERROR err = t.Decode(reader); - if(err == CHIP_NO_ERROR) { - {%- for field in struct.fields %} - {{field.name}} = t.{{field.name}}; - {%- endfor %} - } - return err; - } - - CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const - { - chip::app::Clusters::detail::Structs::{{struct.name}}::Type t; - {%- for field in struct.fields %} - t.{{field.name}} = {{field.name}}; - {%- endfor %} - return t.Encode(writer, tag); - } - - {%- for field in struct.fields %} - {{field | getField(None, idl)}} {{field.name}}; - {%- endfor %} -}; -{%- endfor %} - -{%- for cluster in clusters %} -{%- if cluster | dynamicCluster(idl) %} struct {{cluster.name}}Cluster : public CommonCluster { {%- for struct in cluster.structs %} @@ -158,7 +125,7 @@ struct {{cluster.name}}Access : public CommonAttributeAccessInterface {%- if attr.is_writable %} {%- if attr.definition.is_list %} case {{attr.definition.code}}: - m{{attr.definition.name | capitalcase}}.ListWriteBegin(aPath); + c->m{{attr.definition.name | capitalcase}}.ListWriteBegin(aPath); return; {%- endif %} {%- endif %} @@ -177,7 +144,7 @@ struct {{cluster.name}}Access : public CommonAttributeAccessInterface {%- if attr.is_writable %} {%- if attr.definition.is_list %} case {{attr.definition.code}}: - m{{attr.definition.name | capitalcase}}.ListWriteEnd(aPath, aWriteWasSuccessful); + c->m{{attr.definition.name | capitalcase}}.ListWriteEnd(aPath, aWriteWasSuccessful); return; {%- endif %} {%- endif %} @@ -185,56 +152,5 @@ struct {{cluster.name}}Access : public CommonAttributeAccessInterface } } }; -{%- endif %} -{%- endfor %} - -struct ClusterInfo -{ - chip::ClusterId id; - const char *name; - uint16_t size; - CommonCluster* (*ctor)(void*); -} static const kKnownClusters[] = { -{% for cluster in clusters %} -{%- if cluster | dynamicCluster(idl) %} - { - {{cluster.code}}, - "{{cluster.name}}", - sizeof({{cluster.name}}Cluster), - [](void *mem) -> CommonCluster* { - return new(mem) {{cluster.name}}Cluster(); - }, - }, -{%- endif %} -{%- endfor %} -}; - -inline void BridgeRegisterAllAttributeOverrides() -{ -{% for cluster in clusters %} -{%- if cluster | dynamicCluster(idl) %} - static {{cluster.name}}Access {{cluster.name}}; - registerAttributeAccessOverride(&{{cluster.name}}); -{%- endif %} -{%- endfor %} -} - -struct AttrInfo -{ - chip::ClusterId cluster; - chip::AttributeId attr; - const char *name; -} static const kKnownAttributes[] = { -{% for cluster in clusters %} -{%- if cluster | dynamicCluster(idl) %} - -{%- for attr in cluster.attributes %} - { {{cluster.code}}, {{attr.definition.code}}, "{{attr.definition.name | capitalcase}}" }, -{%- endfor %} - -{%- endif %} -{%- endfor %} - -}; } diff --git a/scripts/idl/generators/bridge/BridgeClustersGlobalStructs.jinja b/scripts/idl/generators/bridge/BridgeClustersGlobalStructs.jinja new file mode 100644 index 00000000000000..ccad20e0b5336c --- /dev/null +++ b/scripts/idl/generators/bridge/BridgeClustersGlobalStructs.jinja @@ -0,0 +1,38 @@ +#pragma once + +#include +#include + +namespace clusters { + +{% for struct in structs %} +struct {{struct.name}} +{ + CHIP_ERROR Decode(chip::TLV::TLVReader & reader) + { + chip::app::Clusters::detail::Structs::{{struct.name}}::DecodableType t; + CHIP_ERROR err = t.Decode(reader); + if(err == CHIP_NO_ERROR) { + {%- for field in struct.fields %} + {{field.name}} = t.{{field.name}}; + {%- endfor %} + } + return err; + } + + CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const + { + chip::app::Clusters::detail::Structs::{{struct.name}}::Type t; + {%- for field in struct.fields %} + t.{{field.name}} = {{field.name}}; + {%- endfor %} + return t.Encode(writer, tag); + } + + {%- for field in struct.fields %} + {{field | getField(None, idl)}} {{field.name}}; + {%- endfor %} +}; +{%- endfor %} + +} diff --git a/scripts/idl/generators/cpp/__init__.py b/scripts/idl/generators/bridge/__init__.py similarity index 87% rename from scripts/idl/generators/cpp/__init__.py rename to scripts/idl/generators/bridge/__init__.py index 19545ef3bb099e..b955a4a8cedbce 100644 --- a/scripts/idl/generators/cpp/__init__.py +++ b/scripts/idl/generators/bridge/__init__.py @@ -141,9 +141,9 @@ def is_dynamic_cluster(cluster: Cluster, idl: Idl): return False -class CppGenerator(CodeGenerator): +class BridgeGenerator(CodeGenerator): """ - Generation of cpp code for matter. + Generation of bridge cpp code for matter. """ def __init__(self, storage: GeneratorStorage, idl: Idl): @@ -167,13 +167,33 @@ def internal_render_all(self): """ Renders C++ """ + for cluster in self.idl.clusters: + if not is_dynamic_cluster(cluster, self.idl): + continue + + self.internal_render_one_output( + template_path="bridge/BridgeClustersCpp.jinja", + output_file_name="bridge/%s.h" % cluster.name, + vars={ + 'cluster': cluster, + 'idl': self.idl, + } + ) self.internal_render_one_output( - template_path="cpp/BridgeClustersCpp.jinja", - output_file_name="cpp/BridgeClustersImpl.h", + template_path="bridge/BridgeClustersCommon.jinja", + output_file_name="bridge/BridgeClustersImpl.h", vars={ 'clusters': self.idl.clusters, 'idl': self.idl, + } + ) + + self.internal_render_one_output( + template_path="bridge/BridgeClustersGlobalStructs.jinja", + output_file_name="bridge/BridgeGlobalStructs.h", + vars={ + 'idl': self.idl, 'structs': self.idl.structs, } ) diff --git a/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeClustersImpl.h b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeClustersImpl.h new file mode 100644 index 00000000000000..8a3b84eeea5281 --- /dev/null +++ b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeClustersImpl.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include "bridge/DemoCluster.h" + +namespace clusters { + +struct ClusterInfo +{ + chip::ClusterId id; + const char *name; + uint16_t size; + CommonCluster* (*ctor)(void*); +} static const kKnownClusters[] = { + + { + 10, + "DemoCluster", + sizeof(DemoClusterCluster), + [](void *mem) -> CommonCluster* { + return new(mem) DemoClusterCluster(); + }, + }, +}; + +inline void BridgeRegisterAllAttributeOverrides() +{ + + static DemoClusterAccess DemoCluster; + registerAttributeAccessOverride(&DemoCluster); +} + +struct AttrInfo +{ + chip::ClusterId cluster; + chip::AttributeId attr; + const char *name; +} static const kKnownAttributes[] = { + + { 10, 5, "SingleFailSafe" }, + { 10, 100, "ArmFailsafes" }, +}; + +} \ No newline at end of file diff --git a/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeGlobalStructs.h b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeGlobalStructs.h new file mode 100644 index 00000000000000..9dc0e1e1dec340 --- /dev/null +++ b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeGlobalStructs.h @@ -0,0 +1,10 @@ +#pragma once + +#include +#include + +namespace clusters { + + + +} \ No newline at end of file diff --git a/scripts/idl/tests/outputs/cluster_struct_attribute/cpp/BridgeClustersImpl.h b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoCluster.h similarity index 77% rename from scripts/idl/tests/outputs/cluster_struct_attribute/cpp/BridgeClustersImpl.h rename to scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoCluster.h index 78ec3c5ab7be5e..19bbf08dd098f2 100644 --- a/scripts/idl/tests/outputs/cluster_struct_attribute/cpp/BridgeClustersImpl.h +++ b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoCluster.h @@ -1,10 +1,8 @@ -#include -#include +#pragma once -#include +#include "BridgeGlobalStructs.h" namespace clusters { - struct DemoClusterCluster : public CommonCluster { @@ -89,7 +87,7 @@ struct DemoClusterAccess : public CommonAttributeAccessInterface switch(aPath.mAttributeId) { case 100: - mArmFailsafes.ListWriteBegin(aPath); + c->mArmFailsafes.ListWriteBegin(aPath); return; } } @@ -102,47 +100,10 @@ struct DemoClusterAccess : public CommonAttributeAccessInterface switch(aPath.mAttributeId) { case 100: - mArmFailsafes.ListWriteEnd(aPath, aWriteWasSuccessful); + c->mArmFailsafes.ListWriteEnd(aPath, aWriteWasSuccessful); return; } } }; -struct ClusterInfo -{ - chip::ClusterId id; - const char *name; - uint16_t size; - CommonCluster* (*ctor)(void*); -} static const kKnownClusters[] = { - - { - 10, - "DemoCluster", - sizeof(DemoClusterCluster), - [](void *mem) -> CommonCluster* { - return new(mem) DemoClusterCluster(); - }, - }, -}; - -inline void BridgeRegisterAllAttributeOverrides() -{ - - static DemoClusterAccess DemoCluster; - registerAttributeAccessOverride(&DemoCluster); -} - -struct AttrInfo -{ - chip::ClusterId cluster; - chip::AttributeId attr; - const char *name; -} static const kKnownAttributes[] = { - - { 10, 5, "SingleFailSafe" }, - { 10, 100, "ArmFailsafes" }, - -}; - } \ No newline at end of file diff --git a/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeClustersImpl.h b/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeClustersImpl.h new file mode 100644 index 00000000000000..3b102344a117c4 --- /dev/null +++ b/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeClustersImpl.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include "bridge/DemoCluster.h" + +namespace clusters { + +struct ClusterInfo +{ + chip::ClusterId id; + const char *name; + uint16_t size; + CommonCluster* (*ctor)(void*); +} static const kKnownClusters[] = { + + { + 18, + "DemoCluster", + sizeof(DemoClusterCluster), + [](void *mem) -> CommonCluster* { + return new(mem) DemoClusterCluster(); + }, + }, +}; + +inline void BridgeRegisterAllAttributeOverrides() +{ + + static DemoClusterAccess DemoCluster; + registerAttributeAccessOverride(&DemoCluster); +} + +struct AttrInfo +{ + chip::ClusterId cluster; + chip::AttributeId attr; + const char *name; +} static const kKnownAttributes[] = { + + { 18, 32, "SingleLabel" }, + { 18, 33, "SomeLabels" }, +}; + +} \ No newline at end of file diff --git a/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeGlobalStructs.h b/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeGlobalStructs.h new file mode 100644 index 00000000000000..82d6f174b2e95e --- /dev/null +++ b/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeGlobalStructs.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +namespace clusters { + + +struct LabelStruct +{ + CHIP_ERROR Decode(chip::TLV::TLVReader & reader) + { + chip::app::Clusters::detail::Structs::LabelStruct::DecodableType t; + CHIP_ERROR err = t.Decode(reader); + if(err == CHIP_NO_ERROR) { + label = t.label; + value = t.value; + } + return err; + } + + CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const + { + chip::app::Clusters::detail::Structs::LabelStruct::Type t; + t.label = label; + t.value = value; + return t.Encode(writer, tag); + } + OctetString<16, ZCL_CHAR_STRING_ATTRIBUTE_TYPE> label; + OctetString<16, ZCL_CHAR_STRING_ATTRIBUTE_TYPE> value; +}; + +} \ No newline at end of file diff --git a/scripts/idl/tests/outputs/global_struct_attribute/cpp/BridgeClustersImpl.h b/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoCluster.h similarity index 66% rename from scripts/idl/tests/outputs/global_struct_attribute/cpp/BridgeClustersImpl.h rename to scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoCluster.h index f92843f069280f..2293e82818ef63 100644 --- a/scripts/idl/tests/outputs/global_struct_attribute/cpp/BridgeClustersImpl.h +++ b/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoCluster.h @@ -1,33 +1,8 @@ -#include -#include +#pragma once -#include +#include "BridgeGlobalStructs.h" namespace clusters { - -struct LabelStruct -{ - CHIP_ERROR Decode(chip::TLV::TLVReader & reader) - { - chip::app::Clusters::detail::Structs::LabelStruct::DecodableType t; - CHIP_ERROR err = t.Decode(reader); - if(err == CHIP_NO_ERROR) { - label = t.label; - value = t.value; - } - return err; - } - - CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const - { - chip::app::Clusters::detail::Structs::LabelStruct::Type t; - t.label = label; - t.value = value; - return t.Encode(writer, tag); - } - OctetString<16, ZCL_CHAR_STRING_ATTRIBUTE_TYPE> label; - OctetString<16, ZCL_CHAR_STRING_ATTRIBUTE_TYPE> value; -}; struct DemoClusterCluster : public CommonCluster { @@ -112,7 +87,7 @@ struct DemoClusterAccess : public CommonAttributeAccessInterface switch(aPath.mAttributeId) { case 33: - mSomeLabels.ListWriteBegin(aPath); + c->mSomeLabels.ListWriteBegin(aPath); return; } } @@ -125,47 +100,10 @@ struct DemoClusterAccess : public CommonAttributeAccessInterface switch(aPath.mAttributeId) { case 33: - mSomeLabels.ListWriteEnd(aPath, aWriteWasSuccessful); + c->mSomeLabels.ListWriteEnd(aPath, aWriteWasSuccessful); return; } } }; -struct ClusterInfo -{ - chip::ClusterId id; - const char *name; - uint16_t size; - CommonCluster* (*ctor)(void*); -} static const kKnownClusters[] = { - - { - 18, - "DemoCluster", - sizeof(DemoClusterCluster), - [](void *mem) -> CommonCluster* { - return new(mem) DemoClusterCluster(); - }, - }, -}; - -inline void BridgeRegisterAllAttributeOverrides() -{ - - static DemoClusterAccess DemoCluster; - registerAttributeAccessOverride(&DemoCluster); -} - -struct AttrInfo -{ - chip::ClusterId cluster; - chip::AttributeId attr; - const char *name; -} static const kKnownAttributes[] = { - - { 18, 32, "SingleLabel" }, - { 18, 33, "SomeLabels" }, - -}; - } \ No newline at end of file diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/BridgeClustersImpl.h b/scripts/idl/tests/outputs/several_clusters/bridge/BridgeClustersImpl.h new file mode 100644 index 00000000000000..b008f6743cf09d --- /dev/null +++ b/scripts/idl/tests/outputs/several_clusters/bridge/BridgeClustersImpl.h @@ -0,0 +1,67 @@ +#pragma once + +#include +#include "bridge/First.h" +#include "bridge/Second.h" +#include "bridge/Third.h" + +namespace clusters { + +struct ClusterInfo +{ + chip::ClusterId id; + const char *name; + uint16_t size; + CommonCluster* (*ctor)(void*); +} static const kKnownClusters[] = { + + { + 1, + "First", + sizeof(FirstCluster), + [](void *mem) -> CommonCluster* { + return new(mem) FirstCluster(); + }, + }, + { + 2, + "Second", + sizeof(SecondCluster), + [](void *mem) -> CommonCluster* { + return new(mem) SecondCluster(); + }, + }, + { + 3, + "Third", + sizeof(ThirdCluster), + [](void *mem) -> CommonCluster* { + return new(mem) ThirdCluster(); + }, + }, +}; + +inline void BridgeRegisterAllAttributeOverrides() +{ + + static FirstAccess First; + registerAttributeAccessOverride(&First); + static SecondAccess Second; + registerAttributeAccessOverride(&Second); + static ThirdAccess Third; + registerAttributeAccessOverride(&Third); +} + +struct AttrInfo +{ + chip::ClusterId cluster; + chip::AttributeId attr; + const char *name; +} static const kKnownAttributes[] = { + + { 1, 1, "SomeInteger" }, + { 2, 123, "SomeBytes" }, + { 3, 10, "SomeEnum" }, +}; + +} \ No newline at end of file diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/BridgeGlobalStructs.h b/scripts/idl/tests/outputs/several_clusters/bridge/BridgeGlobalStructs.h new file mode 100644 index 00000000000000..9dc0e1e1dec340 --- /dev/null +++ b/scripts/idl/tests/outputs/several_clusters/bridge/BridgeGlobalStructs.h @@ -0,0 +1,10 @@ +#pragma once + +#include +#include + +namespace clusters { + + + +} \ No newline at end of file diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/First.h b/scripts/idl/tests/outputs/several_clusters/bridge/First.h new file mode 100644 index 00000000000000..c5bae7b40c51bc --- /dev/null +++ b/scripts/idl/tests/outputs/several_clusters/bridge/First.h @@ -0,0 +1,96 @@ +#pragma once + +#include "BridgeGlobalStructs.h" + +namespace clusters { +struct FirstCluster : public CommonCluster +{ + + + static constexpr chip::ClusterId kClusterId = 1; + + chip::ClusterId GetClusterId() override { return kClusterId; } + + CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + switch(aPath.mAttributeId) + { + case 1: + return mSomeInteger.Write(aPath, aDecoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + template + void AddAllAttributes(T *list) + { + list->Add(mSomeInteger); + } + + chip::Span GetAllAttributes() override + { + static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { + { 1, ZCL_INT16U_ATTRIBUTE_TYPE, 2, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, + }; + return chip::Span(kAllAttributes); + } + + + Attribute<1, ATTRIBUTE_MASK_WRITABLE, PrimitiveType> mSomeInteger; +}; + +struct FirstAccess : public CommonAttributeAccessInterface +{ + FirstAccess() : CommonAttributeAccessInterface(chip::Optional(), FirstCluster::kClusterId) {} + + FirstCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) + { + CommonCluster * cluster = FindCluster(aPath); + return cluster ? static_cast(cluster) : nullptr; + } + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + + switch(aPath.mAttributeId) { + case 1: + return c->mSomeInteger.Read(aPath, aEncoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + return c->ForwardWriteToBridge(aPath, aDecoder); + } + + void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + } + } + + void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + } + } +}; + +} \ No newline at end of file diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/Second.h b/scripts/idl/tests/outputs/several_clusters/bridge/Second.h new file mode 100644 index 00000000000000..6b0b74e5021897 --- /dev/null +++ b/scripts/idl/tests/outputs/several_clusters/bridge/Second.h @@ -0,0 +1,96 @@ +#pragma once + +#include "BridgeGlobalStructs.h" + +namespace clusters { +struct SecondCluster : public CommonCluster +{ + + + static constexpr chip::ClusterId kClusterId = 2; + + chip::ClusterId GetClusterId() override { return kClusterId; } + + CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + switch(aPath.mAttributeId) + { + case 123: + return mSomeBytes.Write(aPath, aDecoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + template + void AddAllAttributes(T *list) + { + list->Add(mSomeBytes); + } + + chip::Span GetAllAttributes() override + { + static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { + { 123, ZCL_OCTET_STRING_ATTRIBUTE_TYPE, 32, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, + }; + return chip::Span(kAllAttributes); + } + + + Attribute<123, 0, OctetString<32, ZCL_OCTET_STRING_ATTRIBUTE_TYPE>> mSomeBytes; +}; + +struct SecondAccess : public CommonAttributeAccessInterface +{ + SecondAccess() : CommonAttributeAccessInterface(chip::Optional(), SecondCluster::kClusterId) {} + + SecondCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) + { + CommonCluster * cluster = FindCluster(aPath); + return cluster ? static_cast(cluster) : nullptr; + } + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + + switch(aPath.mAttributeId) { + case 123: + return c->mSomeBytes.Read(aPath, aEncoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + return c->ForwardWriteToBridge(aPath, aDecoder); + } + + void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + } + } + + void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + } + } +}; + +} \ No newline at end of file diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/Third.h b/scripts/idl/tests/outputs/several_clusters/bridge/Third.h new file mode 100644 index 00000000000000..18833218b504a1 --- /dev/null +++ b/scripts/idl/tests/outputs/several_clusters/bridge/Third.h @@ -0,0 +1,96 @@ +#pragma once + +#include "BridgeGlobalStructs.h" + +namespace clusters { +struct ThirdCluster : public CommonCluster +{ + + + static constexpr chip::ClusterId kClusterId = 3; + + chip::ClusterId GetClusterId() override { return kClusterId; } + + CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + switch(aPath.mAttributeId) + { + case 10: + return mSomeEnum.Write(aPath, aDecoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + template + void AddAllAttributes(T *list) + { + list->Add(mSomeEnum); + } + + chip::Span GetAllAttributes() override + { + static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { + { 10, ZCL_ENUM8_ATTRIBUTE_TYPE, 1, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, + }; + return chip::Span(kAllAttributes); + } + + + Attribute<10, ATTRIBUTE_MASK_WRITABLE, PrimitiveType> mSomeEnum; +}; + +struct ThirdAccess : public CommonAttributeAccessInterface +{ + ThirdAccess() : CommonAttributeAccessInterface(chip::Optional(), ThirdCluster::kClusterId) {} + + ThirdCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) + { + CommonCluster * cluster = FindCluster(aPath); + return cluster ? static_cast(cluster) : nullptr; + } + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + + switch(aPath.mAttributeId) { + case 10: + return c->mSomeEnum.Read(aPath, aEncoder); + default: + return CHIP_ERROR_NOT_IMPLEMENTED; + } + } + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + auto * c = GetCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + return c->ForwardWriteToBridge(aPath, aDecoder); + } + + void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + } + } + + void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override + { + auto * c = GetCluster(aPath); + if (!c) + return; + + switch(aPath.mAttributeId) { + } + } +}; + +} \ No newline at end of file diff --git a/scripts/idl/tests/outputs/several_clusters/cpp/BridgeClustersImpl.h b/scripts/idl/tests/outputs/several_clusters/cpp/BridgeClustersImpl.h deleted file mode 100644 index 6cea2430bd0c86..00000000000000 --- a/scripts/idl/tests/outputs/several_clusters/cpp/BridgeClustersImpl.h +++ /dev/null @@ -1,334 +0,0 @@ -#include -#include - -#include - -namespace clusters { - -struct FirstCluster : public CommonCluster -{ - - - static constexpr chip::ClusterId kClusterId = 1; - - chip::ClusterId GetClusterId() override { return kClusterId; } - - CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - switch(aPath.mAttributeId) - { - case 1: - return mSomeInteger.Write(aPath, aDecoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - template - void AddAllAttributes(T *list) - { - list->Add(mSomeInteger); - } - - chip::Span GetAllAttributes() override - { - static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { - { 1, ZCL_INT16U_ATTRIBUTE_TYPE, 2, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, - }; - return chip::Span(kAllAttributes); - } - - - Attribute<1, ATTRIBUTE_MASK_WRITABLE, PrimitiveType> mSomeInteger; -}; - -struct FirstAccess : public CommonAttributeAccessInterface -{ - FirstAccess() : CommonAttributeAccessInterface(chip::Optional(), FirstCluster::kClusterId) {} - - FirstCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) - { - CommonCluster * cluster = FindCluster(aPath); - return cluster ? static_cast(cluster) : nullptr; - } - - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - - switch(aPath.mAttributeId) { - case 1: - return c->mSomeInteger.Read(aPath, aEncoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - return c->ForwardWriteToBridge(aPath, aDecoder); - } - - void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - } - } - - void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - } - } -}; -struct SecondCluster : public CommonCluster -{ - - - static constexpr chip::ClusterId kClusterId = 2; - - chip::ClusterId GetClusterId() override { return kClusterId; } - - CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - switch(aPath.mAttributeId) - { - case 123: - return mSomeBytes.Write(aPath, aDecoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - template - void AddAllAttributes(T *list) - { - list->Add(mSomeBytes); - } - - chip::Span GetAllAttributes() override - { - static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { - { 123, ZCL_OCTET_STRING_ATTRIBUTE_TYPE, 32, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, - }; - return chip::Span(kAllAttributes); - } - - - Attribute<123, 0, OctetString<32, ZCL_OCTET_STRING_ATTRIBUTE_TYPE>> mSomeBytes; -}; - -struct SecondAccess : public CommonAttributeAccessInterface -{ - SecondAccess() : CommonAttributeAccessInterface(chip::Optional(), SecondCluster::kClusterId) {} - - SecondCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) - { - CommonCluster * cluster = FindCluster(aPath); - return cluster ? static_cast(cluster) : nullptr; - } - - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - - switch(aPath.mAttributeId) { - case 123: - return c->mSomeBytes.Read(aPath, aEncoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - return c->ForwardWriteToBridge(aPath, aDecoder); - } - - void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - } - } - - void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - } - } -}; -struct ThirdCluster : public CommonCluster -{ - - - static constexpr chip::ClusterId kClusterId = 3; - - chip::ClusterId GetClusterId() override { return kClusterId; } - - CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - switch(aPath.mAttributeId) - { - case 10: - return mSomeEnum.Write(aPath, aDecoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - template - void AddAllAttributes(T *list) - { - list->Add(mSomeEnum); - } - - chip::Span GetAllAttributes() override - { - static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { - { 10, ZCL_ENUM8_ATTRIBUTE_TYPE, 1, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, - }; - return chip::Span(kAllAttributes); - } - - - Attribute<10, ATTRIBUTE_MASK_WRITABLE, PrimitiveType> mSomeEnum; -}; - -struct ThirdAccess : public CommonAttributeAccessInterface -{ - ThirdAccess() : CommonAttributeAccessInterface(chip::Optional(), ThirdCluster::kClusterId) {} - - ThirdCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) - { - CommonCluster * cluster = FindCluster(aPath); - return cluster ? static_cast(cluster) : nullptr; - } - - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - - switch(aPath.mAttributeId) { - case 10: - return c->mSomeEnum.Read(aPath, aEncoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - return c->ForwardWriteToBridge(aPath, aDecoder); - } - - void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - } - } - - void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - } - } -}; - -struct ClusterInfo -{ - chip::ClusterId id; - const char *name; - uint16_t size; - CommonCluster* (*ctor)(void*); -} static const kKnownClusters[] = { - - { - 1, - "First", - sizeof(FirstCluster), - [](void *mem) -> CommonCluster* { - return new(mem) FirstCluster(); - }, - }, - { - 2, - "Second", - sizeof(SecondCluster), - [](void *mem) -> CommonCluster* { - return new(mem) SecondCluster(); - }, - }, - { - 3, - "Third", - sizeof(ThirdCluster), - [](void *mem) -> CommonCluster* { - return new(mem) ThirdCluster(); - }, - }, -}; - -inline void BridgeRegisterAllAttributeOverrides() -{ - - static FirstAccess First; - registerAttributeAccessOverride(&First); - static SecondAccess Second; - registerAttributeAccessOverride(&Second); - static ThirdAccess Third; - registerAttributeAccessOverride(&Third); -} - -struct AttrInfo -{ - chip::ClusterId cluster; - chip::AttributeId attr; - const char *name; -} static const kKnownAttributes[] = { - - { 1, 1, "SomeInteger" }, - { 2, 123, "SomeBytes" }, - { 3, 10, "SomeEnum" }, - -}; - -} \ No newline at end of file diff --git a/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeClustersImpl.h b/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeClustersImpl.h new file mode 100644 index 00000000000000..3375275f87ee02 --- /dev/null +++ b/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeClustersImpl.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include "bridge/MyCluster.h" + +namespace clusters { + +struct ClusterInfo +{ + chip::ClusterId id; + const char *name; + uint16_t size; + CommonCluster* (*ctor)(void*); +} static const kKnownClusters[] = { + + { + 123, + "MyCluster", + sizeof(MyClusterCluster), + [](void *mem) -> CommonCluster* { + return new(mem) MyClusterCluster(); + }, + }, +}; + +inline void BridgeRegisterAllAttributeOverrides() +{ + + static MyClusterAccess MyCluster; + registerAttributeAccessOverride(&MyCluster); +} + +struct AttrInfo +{ + chip::ClusterId cluster; + chip::AttributeId attr; + const char *name; +} static const kKnownAttributes[] = { + + { 123, 1, "ClusterAttr" }, +}; + +} \ No newline at end of file diff --git a/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeGlobalStructs.h b/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeGlobalStructs.h new file mode 100644 index 00000000000000..9dc0e1e1dec340 --- /dev/null +++ b/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeGlobalStructs.h @@ -0,0 +1,10 @@ +#pragma once + +#include +#include + +namespace clusters { + + + +} \ No newline at end of file diff --git a/scripts/idl/tests/outputs/simple_attribute/cpp/BridgeClustersImpl.h b/scripts/idl/tests/outputs/simple_attribute/bridge/MyCluster.h similarity index 77% rename from scripts/idl/tests/outputs/simple_attribute/cpp/BridgeClustersImpl.h rename to scripts/idl/tests/outputs/simple_attribute/bridge/MyCluster.h index e276240132a6fa..813f722913c412 100644 --- a/scripts/idl/tests/outputs/simple_attribute/cpp/BridgeClustersImpl.h +++ b/scripts/idl/tests/outputs/simple_attribute/bridge/MyCluster.h @@ -1,10 +1,8 @@ -#include -#include +#pragma once -#include +#include "BridgeGlobalStructs.h" namespace clusters { - struct MyClusterCluster : public CommonCluster { @@ -95,40 +93,4 @@ struct MyClusterAccess : public CommonAttributeAccessInterface } }; -struct ClusterInfo -{ - chip::ClusterId id; - const char *name; - uint16_t size; - CommonCluster* (*ctor)(void*); -} static const kKnownClusters[] = { - - { - 123, - "MyCluster", - sizeof(MyClusterCluster), - [](void *mem) -> CommonCluster* { - return new(mem) MyClusterCluster(); - }, - }, -}; - -inline void BridgeRegisterAllAttributeOverrides() -{ - - static MyClusterAccess MyCluster; - registerAttributeAccessOverride(&MyCluster); -} - -struct AttrInfo -{ - chip::ClusterId cluster; - chip::AttributeId attr; - const char *name; -} static const kKnownAttributes[] = { - - { 123, 1, "ClusterAttr" }, - -}; - } \ No newline at end of file From f7629b1f7935a218078331b2821163604aec6b95 Mon Sep 17 00:00:00 2001 From: Albert Chaulk Date: Wed, 24 Aug 2022 15:50:34 -0400 Subject: [PATCH 05/14] Add PW RPC --- examples/bridge-app/bridge-common/BUILD.gn | 13 +++ .../protos/bridge_service.options | 2 + .../bridge-common/protos/bridge_service.proto | 33 +++++++ examples/bridge-app/linux/BUILD.gn | 60 ++++++++++++- examples/bridge-app/linux/Backend.cpp | 62 +++++++++++++ examples/bridge-app/linux/Device.cpp | 2 +- .../bridge-app/linux/UserInputBackend.cpp | 25 +----- examples/bridge-app/linux/bridge_service.cpp | 90 +++++++++++++++++++ examples/bridge-app/linux/bridge_service.h | 45 ++++++++++ examples/bridge-app/linux/include/Backend.h | 8 ++ examples/bridge-app/linux/include/Device.h | 4 +- examples/bridge-app/linux/main.cpp | 14 +++ examples/bridge-app/linux/with_pw_rpc.gni | 44 +++++++++ 13 files changed, 374 insertions(+), 28 deletions(-) create mode 100644 examples/bridge-app/bridge-common/protos/bridge_service.options create mode 100644 examples/bridge-app/bridge-common/protos/bridge_service.proto create mode 100644 examples/bridge-app/linux/Backend.cpp create mode 100644 examples/bridge-app/linux/bridge_service.cpp create mode 100644 examples/bridge-app/linux/bridge_service.h create mode 100644 examples/bridge-app/linux/with_pw_rpc.gni diff --git a/examples/bridge-app/bridge-common/BUILD.gn b/examples/bridge-app/bridge-common/BUILD.gn index ac3aa414ae3791..1e7c59526db959 100644 --- a/examples/bridge-app/bridge-common/BUILD.gn +++ b/examples/bridge-app/bridge-common/BUILD.gn @@ -15,6 +15,7 @@ import("//build_overrides/chip.gni") import("${chip_root}/src/app/chip_data_model.gni") +import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") chip_data_model("bridge-common") { zap_file = "bridge-app.zap" @@ -25,3 +26,15 @@ chip_data_model("bridge-common") { # TODO: the definition of DYNAMIC_ENDPOINT_COUNT needs find a common home! cflags = [ "-DDYNAMIC_ENDPOINT_COUNT=16" ] } + +if (chip_enable_pw_rpc) { + import("//build_overrides/pigweed.gni") + import("$dir_pw_protobuf_compiler/proto.gni") + + pw_proto_library("bridge_service") { + sources = [ "protos/bridge_service.proto" ] + inputs = [ "protos/bridge_service.options" ] + strip_prefix = "protos" + prefix = "bridge_service" + } +} diff --git a/examples/bridge-app/bridge-common/protos/bridge_service.options b/examples/bridge-app/bridge-common/protos/bridge_service.options new file mode 100644 index 00000000000000..11b8dfc097fba5 --- /dev/null +++ b/examples/bridge-app/bridge-common/protos/bridge_service.options @@ -0,0 +1,2 @@ +chip.rpc.bridge.AddDevice.device_types max_count:32 +chip.rpc.bridge.AddDevice.clusters max_count:64 diff --git a/examples/bridge-app/bridge-common/protos/bridge_service.proto b/examples/bridge-app/bridge-common/protos/bridge_service.proto new file mode 100644 index 00000000000000..1917ba1f0c4c00 --- /dev/null +++ b/examples/bridge-app/bridge-common/protos/bridge_service.proto @@ -0,0 +1,33 @@ +syntax = "proto3"; + +package chip.rpc.bridge; + +message Empty {} + +message RemoveDevice { + uint32 id = 1; +} + +message Cluster { + uint32 cluster_id = 1; +} + +message DeviceType { + uint32 id = 1; + uint32 version = 2; +} + +message AddDevice { + repeated Cluster clusters = 1; + repeated DeviceType device_types = 2; + uint32 parent_endpoint = 3; +} + +message AddDeviceResponse { + uint32 id = 1; +} + +service Bridge { + rpc Add(AddDevice) returns (AddDeviceResponse){}; + rpc Remove(RemoveDevice) returns (Empty){}; +} diff --git a/examples/bridge-app/linux/BUILD.gn b/examples/bridge-app/linux/BUILD.gn index 2bf6bf7988f91b..da54ebe03f2a76 100644 --- a/examples/bridge-app/linux/BUILD.gn +++ b/examples/bridge-app/linux/BUILD.gn @@ -16,6 +16,14 @@ import("//build_overrides/build.gni") import("//build_overrides/chip.gni") import("${chip_root}/build/chip/tools.gni") +import("${chip_root}/src/app/common_flags.gni") + +import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") + +if (chip_enable_pw_rpc) { + import("//build_overrides/pigweed.gni") + import("$dir_pw_build/target_types.gni") +} assert(chip_build_tools) @@ -23,7 +31,8 @@ action("chip-bridge-codegen") { script = "${chip_root}/scripts/codegen.py" sources = [ "${chip_root}/examples/bridge-app/bridge-common/bridge-app.matter" ] - outputs = [ "$target_gen_dir/cpp/BridgeClustersImpl.h" ] + # Also several other files, but this is sufficient for dependency purposes. + outputs = [ "$target_gen_dir/bridge/BridgeClustersImpl.h" ] args = [ "--generator", @@ -41,6 +50,7 @@ executable("chip-bridge-app") { sources = [ "${chip_root}/examples/bridge-app/linux/bridged-actions-stub.cpp", "${chip_root}/examples/tv-app/tv-common/include/CHIPProjectAppConfig.h", + "Backend.cpp", "Clusters.cpp", "Device.cpp", "DynamicDevice.cpp", @@ -58,13 +68,57 @@ executable("chip-bridge-app") { "${chip_root}/src/lib", ] - cflags = [ "-Wconversion" ] - include_dirs = [ "include", target_gen_dir, ] + if (chip_enable_pw_rpc) { + defines = [ + "PW_RPC_ENABLED", + "PW_RPC_ATTRIBUTE_SERVICE=1", + "PW_RPC_DESCRIPTOR_SERVICE=1", + "PW_RPC_DEVICE_SERVICE=1", + "PW_RPC_TRACING_SERVICE=1" + ] + + sources += [ + "${chip_root}/examples/platform/linux/Rpc.cpp", + "${chip_root}/examples/platform/linux/system_rpc_server.cc", + "bridge_service.cpp" + ] + + deps += [ + "$dir_pw_hdlc:pw_rpc", + "$dir_pw_hdlc:rpc_channel_output", + "$dir_pw_log", + "$dir_pw_rpc:server", + "$dir_pw_rpc/system_server:facade", + "$dir_pw_stream:socket_stream", + "$dir_pw_stream:sys_io_stream", + "$dir_pw_sync:mutex", + "$dir_pw_trace", + "$dir_pw_trace_tokenized", + "$dir_pw_trace_tokenized:trace_rpc_service", + "${chip_root}/config/linux/lib/pw_rpc:pw_rpc", + "${chip_root}/examples/bridge-app/bridge-common:bridge_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:attributes_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:button_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:descriptor_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:device_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:lighting_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:rpc_services", + ] + + deps += pw_build_LINK_DEPS + + include_dirs += [ "${chip_root}/examples/common" ] + } else { + # The system_rpc_server.cc file is in pigweed and doesn't compile with + # -Wconversion, remove check for RPC build only. + cflags = [ "-Wconversion" ] + } + output_dir = root_out_dir } diff --git a/examples/bridge-app/linux/Backend.cpp b/examples/bridge-app/linux/Backend.cpp new file mode 100644 index 00000000000000..4cd3b6503a2cd5 --- /dev/null +++ b/examples/bridge-app/linux/Backend.cpp @@ -0,0 +1,62 @@ +/* + * + * Copyright (c) 2022 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 "Backend.h" + +#include "main.h" + +std::vector> g_devices; +std::vector> g_device_impls; + +bool RemoveDeviceAt(uint32_t index) +{ + if (index >= g_devices.size() || !g_devices[index]) + { + return false; + } + + RemoveDeviceEndpoint(g_devices[index].get()); + + for (auto & room : gRooms) + room.RemoveEndpoint(g_devices[index]->GetEndpointId()); + + g_devices[index] = nullptr; + g_device_impls[index] = nullptr; + + return true; +} + +int AddDevice(std::unique_ptr device) +{ + auto dev = std::make_unique(device->CreateDevice()); + int ep = AddDeviceEndpoint(dev.get()); + if (ep < 0) + { + return -1; + } + + size_t index = (size_t) ep; + if (g_devices.size() <= index) + { + g_devices.resize(index + 1); + g_device_impls.resize(index + 1); + } + g_devices[index] = std::move(dev); + g_device_impls[index] = std::move(device); + return ep; +} diff --git a/examples/bridge-app/linux/Device.cpp b/examples/bridge-app/linux/Device.cpp index 31d8b5c960fb0c..268feca462e9a0 100644 --- a/examples/bridge-app/linux/Device.cpp +++ b/examples/bridge-app/linux/Device.cpp @@ -42,7 +42,7 @@ void Device::SetEndpointId(chip::EndpointId id) const char * Device::GetName() { - return mDeviceName; + return mDeviceName.c_str(); } void Device::SetName(const char * name) diff --git a/examples/bridge-app/linux/UserInputBackend.cpp b/examples/bridge-app/linux/UserInputBackend.cpp index 6c3eb1e1a2924b..8b613cbd976e59 100644 --- a/examples/bridge-app/linux/UserInputBackend.cpp +++ b/examples/bridge-app/linux/UserInputBackend.cpp @@ -15,8 +15,6 @@ namespace { -std::vector> g_devices; -std::vector> g_device_impls; std::unique_ptr g_pending; // Pseudo-index representing the device being built. @@ -169,8 +167,8 @@ void FinishDevice(const std::vector & tokens) for (auto * c : g_pending->clusters()) c->SetCallback(&g_write_cb); - auto dev = std::make_unique(g_pending->CreateDevice()); - int ep = AddDeviceEndpoint(dev.get()); + int ep = AddDevice(std::move(g_pending)); + if (ep < 0) { printf("Failed to add device\n"); @@ -178,14 +176,6 @@ void FinishDevice(const std::vector & tokens) else { printf("Added device at index %d\n", ep); - size_t index = (size_t) ep; - if (g_devices.size() <= index) - { - g_devices.resize(index + 1); - g_device_impls.resize(index + 1); - } - g_devices[index] = std::move(dev); - g_device_impls[index] = std::move(g_pending); } } @@ -198,19 +188,10 @@ void RemoveDevice(const std::vector & tokens) printf("Error: %s.\nExpected index of a device\n", err); return; } - if (index >= g_devices.size()) + if (!RemoveDeviceAt(index)) { printf("%d is an invalid index\n", index); - return; } - - RemoveDeviceEndpoint(g_devices[index].get()); - - for (auto & room : gRooms) - room.RemoveEndpoint(g_devices[index]->GetEndpointId()); - - g_devices[index] = nullptr; - g_device_impls[index] = nullptr; } void AddType(const std::vector & tokens) diff --git a/examples/bridge-app/linux/bridge_service.cpp b/examples/bridge-app/linux/bridge_service.cpp new file mode 100644 index 00000000000000..af096e8371a76b --- /dev/null +++ b/examples/bridge-app/linux/bridge_service.cpp @@ -0,0 +1,90 @@ +/* + * + * Copyright (c) 2022 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 "bridge_service.h" + +#include "Backend.h" +#include "main.h" + +namespace chip { +namespace rpc { + +namespace { +const clusters::ClusterInfo * FindCluster(uint32_t id) +{ + for (const auto & cluster : clusters::kKnownClusters) + { + if (id == cluster.id) + return &cluster; + } + return nullptr; +} +} // namespace + +::pw::Status Bridge::Add(const ::chip_rpc_bridge_AddDevice & request, ::chip_rpc_bridge_AddDeviceResponse & response) +{ + std::unique_ptr pending; + + pending = std::make_unique(); + pending->SetParentEndpointId(request.parent_endpoint); + + for (pb_size_t i = 0; i < request.clusters_count; i++) + { + const chip_rpc_bridge_Cluster & c = request.clusters[i]; + + auto cluster = FindCluster(c.cluster_id); + if (!cluster) + { + return pw::Status::InvalidArgument(); + } + + std::unique_ptr obj(cluster->ctor(::operator new(cluster->size))); + DynamicAttributeList dynamic_attrs; + auto attrs = obj->GetAllAttributes(); + for (auto & attr : attrs) + dynamic_attrs.Add(attr); + pending->AddCluster(std::move(obj), dynamic_attrs, nullptr, nullptr); + } + + for (pb_size_t i = 0; i < request.device_types_count; i++) + { + EmberAfDeviceType devType = { (uint16_t) request.device_types[i].id, (uint8_t) request.device_types[i].version }; + pending->AddDeviceType(devType); + } + + int ret = AddDevice(std::move(pending)); + if (ret < 0) + { + return pw::Status::Aborted(); + } + response.id = ret; + return pw::OkStatus(); +} + +::pw::Status Bridge::Remove(const ::chip_rpc_bridge_RemoveDevice & request, ::chip_rpc_bridge_Empty & response) +{ + if (!RemoveDeviceAt(request.id)) + { + return pw::Status::NotFound(); + } + + return pw::OkStatus(); +} + +} // namespace rpc +} // namespace chip diff --git a/examples/bridge-app/linux/bridge_service.h b/examples/bridge-app/linux/bridge_service.h new file mode 100644 index 00000000000000..d2e05416a0a74f --- /dev/null +++ b/examples/bridge-app/linux/bridge_service.h @@ -0,0 +1,45 @@ +/* + * + * Copyright (c) 2022 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. + */ + +#pragma once + +#include "app/util/attribute-storage.h" +#include "bridge_service/bridge_service.rpc.pb.h" +#include "pigweed/rpc_services/internal/StatusUtils.h" +#include +#include +#include +#include + +namespace chip { +namespace rpc { + +class Bridge : public bridge::pw_rpc::nanopb::Bridge::Service +{ +public: + Bridge() = default; + + virtual ~Bridge() = default; + + ::pw::Status Add(const ::chip_rpc_bridge_AddDevice & request, ::chip_rpc_bridge_AddDeviceResponse & response); + + ::pw::Status Remove(const ::chip_rpc_bridge_RemoveDevice & request, ::chip_rpc_bridge_Empty & response); +}; + +} // namespace rpc +} // namespace chip diff --git a/examples/bridge-app/linux/include/Backend.h b/examples/bridge-app/linux/include/Backend.h index 6e5ca8ee9c7e34..5058eeea69b5f5 100644 --- a/examples/bridge-app/linux/include/Backend.h +++ b/examples/bridge-app/linux/include/Backend.h @@ -18,4 +18,12 @@ #pragma once +#include "DynamicDevice.h" + void StartUserInput(); + +extern std::vector> g_devices; +extern std::vector> g_device_impls; + +bool RemoveDeviceAt(uint32_t index); +int AddDevice(std::unique_ptr device); diff --git a/examples/bridge-app/linux/include/Device.h b/examples/bridge-app/linux/include/Device.h index 2a127694c348f4..b65186b7fff8c0 100644 --- a/examples/bridge-app/linux/include/Device.h +++ b/examples/bridge-app/linux/include/Device.h @@ -18,8 +18,8 @@ #pragma once -#include #include +#include #include #include @@ -70,7 +70,7 @@ class Device chip::Span mClusterImpl; chip::Span mDeviceTypeList; EmberAfEndpointType mEndpointType; - const char * mDeviceName = ""; + std::string mDeviceName; }; class Action diff --git a/examples/bridge-app/linux/main.cpp b/examples/bridge-app/linux/main.cpp index 3f8c42104c05c3..9cdbc6af4b3144 100644 --- a/examples/bridge-app/linux/main.cpp +++ b/examples/bridge-app/linux/main.cpp @@ -50,6 +50,14 @@ #include "AppMain.h" +#ifdef PW_RPC_ENABLED +#include "bridge_service.h" +#include "Rpc.h" +#include "pw_rpc_system_server/rpc_server.h" +static chip::rpc::Bridge bridge_service; +#endif + + #include #include #include @@ -163,6 +171,12 @@ chip::Span GetActionListInfo(chip::EndpointId parentId) void ApplicationInit() { +#ifdef PW_RPC_ENABLED + chip::rpc::Init(); + + pw::rpc::system_server::Server().RegisterService(bridge_service); +#endif + clusters::BridgeRegisterAllAttributeOverrides(); gFirstDynamicEndpointId = static_cast( diff --git a/examples/bridge-app/linux/with_pw_rpc.gni b/examples/bridge-app/linux/with_pw_rpc.gni new file mode 100644 index 00000000000000..756a93469bf072 --- /dev/null +++ b/examples/bridge-app/linux/with_pw_rpc.gni @@ -0,0 +1,44 @@ +# Copyright (c) 2021 Project CHIP Authors +# +# 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. + +# add this gni as import in your build args to use pigweed in the example +# 'import("//with_pw_rpc.gni")' + +import("//build_overrides/chip.gni") + +import("${chip_root}/config/standalone/args.gni") + +import("//build_overrides/pigweed.gni") + +cpp_standard = "gnu++17" + +pw_log_BACKEND = "$dir_pw_log_basic" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" +pw_sys_io_BACKEND = "$dir_pw_sys_io_stdio" +pw_trace_BACKEND = "$dir_pw_trace_tokenized" +pw_unit_test_MAIN = "$dir_pw_unit_test:logging_main" +pw_rpc_system_server_BACKEND = "${chip_root}/config/linux/lib/pw_rpc:pw_rpc" +dir_pw_third_party_nanopb = "${chip_root}/third_party/nanopb/repo" +pw_chrono_SYSTEM_CLOCK_BACKEND = "$dir_pw_chrono_stl:system_clock" +pw_sync_MUTEX_BACKEND = "$dir_pw_sync_stl:mutex_backend" +pw_span_ENABLE_STD_SPAN_POLYFILL = false + +pw_build_LINK_DEPS = [ + "$dir_pw_assert:impl", + "$dir_pw_log:impl", +] + +chip_enable_pw_rpc = true +chip_build_pw_trace_lib = true +chip_use_pw_logging = true From ff779481754db0c5511c0487c61e8f45d48948b0 Mon Sep 17 00:00:00 2001 From: Albert Chaulk Date: Thu, 25 Aug 2022 17:37:30 -0400 Subject: [PATCH 06/14] addressing comments --- examples/bridge-app/linux/include/Clusters.h | 172 +++++++----------- .../bridge-app/linux/include/DynamicDevice.h | 3 +- .../generators/bridge/BridgeClustersCpp.jinja | 13 +- .../bridge/BridgeClustersGlobalStructs.jinja | 1 + scripts/idl/generators/bridge/__init__.py | 26 +-- .../bridge/BridgeGlobalStructs.h | 1 + .../bridge/DemoCluster.h | 11 +- .../bridge/BridgeGlobalStructs.h | 5 +- .../bridge/DemoCluster.h | 11 +- .../bridge/BridgeGlobalStructs.h | 1 + .../outputs/several_clusters/bridge/First.h | 8 +- .../outputs/several_clusters/bridge/Second.h | 8 +- .../outputs/several_clusters/bridge/Third.h | 8 +- .../bridge/BridgeGlobalStructs.h | 1 + .../simple_attribute/bridge/MyCluster.h | 8 +- 15 files changed, 102 insertions(+), 175 deletions(-) diff --git a/examples/bridge-app/linux/include/Clusters.h b/examples/bridge-app/linux/include/Clusters.h index 171b3c869fb124..2d0023103a2b8d 100644 --- a/examples/bridge-app/linux/include/Clusters.h +++ b/examples/bridge-app/linux/include/Clusters.h @@ -48,119 +48,56 @@ class ClusterImpl virtual bool Push(chip::AttributeId attr, chip::TLV::TLVReader & reader) = 0; }; -// This provides storage for a primitive binary type, eg uintN_t, float, double -template -struct PrimitiveType +// This provides storage for octet strings +template +struct FixedOctetString { - static constexpr EmberAfAttributeType kMatterType = AfType; - // Note that Bytes can be < sizeof(T) due to non-power-of-two byte lengths. - static constexpr uint16_t kMaxSize = Bytes; - static_assert(Bytes <= sizeof(T), "Incorrect type / byte specification"); - - static constexpr bool kIsFabricScoped = IsFabricScoped; - - PrimitiveType() = default; - PrimitiveType(T initial) : mValue(initial) {} - - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) + CHIP_ERROR Decode(chip::TLV::TLVReader & reader) { - return aDecoder.Decode(*this); - } - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) - { - return aEncoder.Encode(*this); - } - - CHIP_ERROR Decode(chip::TLV::TLVReader & reader) { return reader.Get(mValue); } - - CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const { return writer.Put(tag, mValue); } - - void operator=(T v) { mValue = v; } - operator T() const { return mValue; } - - T Peek() const { return mValue; } - -private: - T mValue; - static_assert(std::is_standard_layout::value, "PrimitiveType not standard layout!"); -}; - -// This provides access to a struct. Each struct generates its own access logic. -template -struct StructType : public T -{ - static constexpr EmberAfAttributeType kMatterType = ZCL_STRUCT_ATTRIBUTE_TYPE; - static constexpr uint16_t kMaxSize = sizeof(T); - static_assert(std::is_standard_layout::value, "StructType not standard layout!"); - static constexpr bool kIsFabricScoped = IsFabricScoped; - - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) - { - return aDecoder.Decode(*this); - } - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) - { - return aEncoder.Encode(*this); - } -}; - -// This provides storage for short and long octet and char strings. -template -struct OctetString -{ - static constexpr EmberAfAttributeType kMatterType = AfType; - static constexpr bool kIsChar = (AfType == ZCL_CHAR_STRING_ATTRIBUTE_TYPE || AfType == ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE); - static constexpr uint16_t kMaxSize = Bytes; - - OctetString() = default; - - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) - { - chip::app::DataModel::Nullable v; - CHIP_ERROR err = aDecoder.Decode(v); + chip::ByteSpan v; + CHIP_ERROR err = chip::app::DataModel::Decode(reader, v); if (err == CHIP_NO_ERROR) { - if (v.IsNull() && !IsNull()) - { - mLength = 0xFFFF; - } - else if (v.Value().size() > kMaxSize) - { - err = CHIP_ERROR_BUFFER_TOO_SMALL; - } - else + if (v.size() > Bytes) { - mLength = static_cast(v.Value().size()); - memcpy(mValue, v.Value().data(), mLength); + return CHIP_ERROR_BUFFER_TOO_SMALL; } + mLength = static_cast(v.size()); + memcpy(mValue, v.data(), mLength); } return err; } - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) + + CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const { - if (IsNull()) - return aEncoder.EncodeNull(); - if (kIsChar) - return aEncoder.Encode(chip::CharSpan(static_cast(mValue), mLength)); - return aEncoder.Encode(chip::ByteSpan(mValue, mLength)); + if (IsChar) + return chip::app::DataModel::Encode(writer, tag, chip::CharSpan(static_cast(mValue), mLength)); + return chip::app::DataModel::Encode(writer, tag, chip::ByteSpan(mValue, mLength)); } - chip::ByteSpan Peek() const { return IsNull() ? chip::ByteSpan() : chip::ByteSpan(mValue, mLength); } + operator chip::ByteSpan() const { return chip::ByteSpan(mValue, mLength); } + operator chip::CharSpan() const { return chip::CharSpan(static_cast(mValue), mLength); } - bool IsNull() const { return mLength == 0xFFFF; } + void operator=(const FixedOctetString&) = default; private: - uint16_t mLength = 0xFFFF; - uint8_t mValue[kMaxSize]; + uint16_t mLength = 0; + uint8_t mValue[Bytes]; }; // This allows for an array of up to MaxElements of a specified type. -template -struct ArrayType +template +struct ArrayAttribute { - static constexpr EmberAfAttributeType kMatterType = ZCL_ARRAY_ATTRIBUTE_TYPE; - static constexpr uint16_t kMaxSize = sizeof(T) * MaxElements; - static_assert(std::is_standard_layout::value, "Array element not standard layout!"); + static constexpr chip::AttributeId kId = id; + static constexpr EmberAfClusterMask kMask = mask | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE); + static constexpr EmberAfAttributeType kMatterType = AfType; + // Bytes is the total length, including the length prefix + static constexpr uint16_t kMaxSize = Bytes; + static_assert(Bytes <= MaxElements * sizeof(Type) + 2, "Incorrect type / byte specification"); + static_assert(std::is_standard_layout::value, "Array element not standard layout!"); + + static constexpr bool kIsFabricScoped = IsFabricScoped; void ListWriteBegin(const chip::app::ConcreteAttributePath & aPath) {} @@ -188,8 +125,9 @@ struct ArrayType return aEncoder.EncodeEmptyList(); return aEncoder.EncodeList([this](const auto & encoder) { CHIP_ERROR err = CHIP_NO_ERROR; - for (uint16_t i = 0; i < mLength && err == CHIP_NO_ERROR; i++) + for (uint16_t i = 0; i < mLength && err == CHIP_NO_ERROR; i++) { err = encoder.Encode(mArray[i]); + } return err; }); } @@ -197,21 +135,45 @@ struct ArrayType bool IsNull() const { return mLength == 0xFFFF; } private: - uint16_t mLength = 0xFFFF; - T mArray[MaxElements]; + uint16_t mLength = Nullable ? 0xFFFF : 0; + Type mArray[MaxElements]; }; -// This is used by code generation to provide specific attributes. Type should be one of -// PrimitiveType, OctetString, ArrayType, etc to provide storage and type-specific -// functionality. -template -struct Attribute : public Type +// This is used by code generation to provide specific attributes. Type should be a primitive that works with Encode()/Decode(). +template +struct Attribute { static constexpr chip::AttributeId kId = id; static constexpr EmberAfClusterMask kMask = mask | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE); + static constexpr EmberAfAttributeType kMatterType = AfType; + // Note that Bytes can be < sizeof(T) due to non-power-of-two byte lengths. + static constexpr uint16_t kMaxSize = Bytes; + static_assert(Bytes <= sizeof(Type), "Incorrect type / byte specification"); + + static constexpr bool kIsFabricScoped = IsFabricScoped; + + Attribute(Type v = Type()) : mData(v) {} + + const Type& Peek() const + { + return mData; + } + void operator=(const Type& v) + { + mData = v; + } + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) + { + return aDecoder.Decode(mData); + } + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) + { + return aEncoder.Encode(mData); + } - using Type::Type; - using Type::operator=; + Type mData; }; struct CommonCluster; @@ -288,7 +250,7 @@ struct BridgedDeviceBasicCluster : public CommonCluster return chip::Span(kAllAttributes); } - Attribute> mReachable; + Attribute mReachable; }; } // namespace clusters diff --git a/examples/bridge-app/linux/include/DynamicDevice.h b/examples/bridge-app/linux/include/DynamicDevice.h index 7fa7419d306dc4..5e7677f1bd8386 100644 --- a/examples/bridge-app/linux/include/DynamicDevice.h +++ b/examples/bridge-app/linux/include/DynamicDevice.h @@ -46,7 +46,8 @@ struct DynamicCluster : public T DynamicCluster(const chip::CommandId * incomingCommands = nullptr, const chip::CommandId * outgoingCommands = nullptr) : mIncomingCommands(incomingCommands), mOutgoingCommands(outgoingCommands) { - this->AddAllAttributes(&mAttributes); + for(auto& attr : this->GetAllAttributes()) + mAttributes.Add(attr); } DynamicAttributeList mAttributes; diff --git a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja index 51b9383e956551..531c93e7da549a 100644 --- a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja +++ b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja @@ -30,6 +30,8 @@ struct {{cluster.name}}Cluster : public CommonCluster return t.Encode(writer, tag); } + static constexpr bool kIsFabricScoped = false; + {%- for field in struct.fields %} {{field | getField(cluster, idl)}} {{field.name}}; {%- endfor %} @@ -55,14 +57,6 @@ struct {{cluster.name}}Cluster : public CommonCluster } } - template - void AddAllAttributes(T *list) - { - {%- for attr in cluster.attributes %} - list->Add(m{{attr.definition.name | capitalcase}}); - {%- endfor %} - } - chip::Span GetAllAttributes() override { static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { @@ -74,7 +68,7 @@ struct {{cluster.name}}Cluster : public CommonCluster } {% for attr in cluster.attributes %} - Attribute<{{attr.definition.code}}, {{attr | getMask(cluster, idl)}}, {{attr | getType(cluster, idl)}}> m{{attr.definition.name | capitalcase}}{{attr | getInit(cluster, idl)}}; + {{attr | getType(cluster, idl)}}{{attr.definition.code}}, {{attr | getMask(cluster, idl)}}, {{attr | getRawSizeAndType(cluster, idl)}}, {{attr.definition | getField(cluster, idl)}}, false> m{{attr.definition.name | capitalcase}}{{attr | getInit(cluster, idl)}}; {%- endfor %} }; @@ -99,6 +93,7 @@ struct {{cluster.name}}Access : public CommonAttributeAccessInterface {%- if attr.is_readable %} case {{attr.definition.code}}: return c->m{{attr.definition.name | capitalcase}}.Read(aPath, aEncoder); + {%- endif %} {%- endfor %} default: diff --git a/scripts/idl/generators/bridge/BridgeClustersGlobalStructs.jinja b/scripts/idl/generators/bridge/BridgeClustersGlobalStructs.jinja index ccad20e0b5336c..45aaef72650015 100644 --- a/scripts/idl/generators/bridge/BridgeClustersGlobalStructs.jinja +++ b/scripts/idl/generators/bridge/BridgeClustersGlobalStructs.jinja @@ -2,6 +2,7 @@ #include #include +#include namespace clusters { diff --git a/scripts/idl/generators/bridge/__init__.py b/scripts/idl/generators/bridge/__init__.py index b955a4a8cedbce..f3514ba9ce5bcd 100644 --- a/scripts/idl/generators/bridge/__init__.py +++ b/scripts/idl/generators/bridge/__init__.py @@ -64,18 +64,18 @@ def get_field_info(definition: Field, cluster: Cluster, idl: Idl): ty = "int%d_t" % actual.power_of_two_bits if not actual.is_signed: ty = "u" + ty - return "PrimitiveType", ty, actual.byte_count, "ZCL_%s_ATTRIBUTE_TYPE" % name + return "", ty, actual.byte_count, "ZCL_%s_ATTRIBUTE_TYPE" % name if type(actual) == FundamentalType: if actual == FundamentalType.BOOL: - return "PrimitiveType", "bool", 1, "ZCL_BOOLEAN_ATTRIBUTE_TYPE" + return "", "bool", 1, "ZCL_BOOLEAN_ATTRIBUTE_TYPE" if actual == FundamentalType.FLOAT: - return "PrimitiveType", "float", 4, "ZCL_SINGLE_ATTRIBUTE_TYPE" + return "", "float", 4, "ZCL_SINGLE_ATTRIBUTE_TYPE" if actual == FundamentalType.DOUBLE: - return "PrimitiveType", "double", 8, "ZCL_DOUBLE_ATTRIBUTE_TYPE" + return "", "double", 8, "ZCL_DOUBLE_ATTRIBUTE_TYPE" logging.warn('Unknown fundamental type: %r' % actual) return None if type(actual) == IdlType: - return 'StructType', actual.idl_name, 'sizeof(%s)' % actual.idl_name, \ + return '', actual.idl_name, 'sizeof(%s)' % actual.idl_name, \ 'ZCL_STRUCT_ATTRIBUTE_TYPE' logging.warn('Unknown type: %r' % actual) return None @@ -95,19 +95,21 @@ def get_raw_size_and_type(attr: Attribute, cluster: Cluster, idl: Idl): def get_field_type(definition: Field, cluster: Cluster, idl: Idl): container, cType, size, matterType = get_field_info(definition, cluster, idl) - if container == 'StructType': - return 'StructType<{}>'.format(cType) if container == 'OctetString': - return 'OctetString<{}, {}>'.format(size, matterType) - return '{}<{}, {}, {}>'.format(container, cType, size, matterType) + return 'FixedOctetString<{}, {}>'.format(size, matterType) + if definition.is_nullable: + cType = '::chip::app::DataModel::Nullable<{}>'.format(cType) + return cType def get_attr_type(attr: Attribute, cluster: Cluster, idl: Idl): - decl = get_field_type(attr.definition, cluster, idl) if attr.definition.is_list: count = get_array_count(attr) - return 'ArrayType<{}, {}>'.format(count, decl) - return decl + nullable = 'false' + if attr.definition.is_nullable: + nullable = 'true' + return 'ArrayAttribute<{}, {}, '.format(count, nullable) + return 'Attribute<' def get_attr_init(attr: Attribute, cluster: Cluster, idl: Idl): diff --git a/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeGlobalStructs.h b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeGlobalStructs.h index 9dc0e1e1dec340..5fcca27baf8f3d 100644 --- a/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeGlobalStructs.h +++ b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeGlobalStructs.h @@ -2,6 +2,7 @@ #include #include +#include namespace clusters { diff --git a/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoCluster.h b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoCluster.h index 19bbf08dd098f2..f94e465d8d4a58 100644 --- a/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoCluster.h +++ b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoCluster.h @@ -24,13 +24,6 @@ struct DemoClusterCluster : public CommonCluster } } - template - void AddAllAttributes(T *list) - { - list->Add(mSingleFailSafe); - list->Add(mArmFailsafes); - } - chip::Span GetAllAttributes() override { static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { @@ -41,8 +34,8 @@ struct DemoClusterCluster : public CommonCluster } - Attribute<5, ATTRIBUTE_MASK_WRITABLE, StructType> mSingleFailSafe; - Attribute<100, ATTRIBUTE_MASK_WRITABLE, ArrayType<1, StructType>> mArmFailsafes; + Attribute<5, ATTRIBUTE_MASK_WRITABLE, ZCL_STRUCT_ATTRIBUTE_TYPE, sizeof(ArmFailSafeRequest), ArmFailSafeRequest, false> mSingleFailSafe; + ArrayAttribute<1, false, 100, ATTRIBUTE_MASK_WRITABLE, ZCL_ARRAY_ATTRIBUTE_TYPE, sizeof(ArmFailSafeRequest) * 1 + 2, ArmFailSafeRequest, false> mArmFailsafes; }; struct DemoClusterAccess : public CommonAttributeAccessInterface diff --git a/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeGlobalStructs.h b/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeGlobalStructs.h index 82d6f174b2e95e..3b139c394cd5e7 100644 --- a/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeGlobalStructs.h +++ b/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeGlobalStructs.h @@ -2,6 +2,7 @@ #include #include +#include namespace clusters { @@ -26,8 +27,8 @@ struct LabelStruct t.value = value; return t.Encode(writer, tag); } - OctetString<16, ZCL_CHAR_STRING_ATTRIBUTE_TYPE> label; - OctetString<16, ZCL_CHAR_STRING_ATTRIBUTE_TYPE> value; + FixedOctetString<16, ZCL_CHAR_STRING_ATTRIBUTE_TYPE> label; + FixedOctetString<16, ZCL_CHAR_STRING_ATTRIBUTE_TYPE> value; }; } \ No newline at end of file diff --git a/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoCluster.h b/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoCluster.h index 2293e82818ef63..47dca69f6106a8 100644 --- a/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoCluster.h +++ b/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoCluster.h @@ -24,13 +24,6 @@ struct DemoClusterCluster : public CommonCluster } } - template - void AddAllAttributes(T *list) - { - list->Add(mSingleLabel); - list->Add(mSomeLabels); - } - chip::Span GetAllAttributes() override { static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { @@ -41,8 +34,8 @@ struct DemoClusterCluster : public CommonCluster } - Attribute<32, ATTRIBUTE_MASK_WRITABLE, StructType> mSingleLabel; - Attribute<33, ATTRIBUTE_MASK_WRITABLE, ArrayType<1, StructType>> mSomeLabels; + Attribute<32, ATTRIBUTE_MASK_WRITABLE, ZCL_STRUCT_ATTRIBUTE_TYPE, sizeof(LabelStruct), LabelStruct, false> mSingleLabel; + ArrayAttribute<1, false, 33, ATTRIBUTE_MASK_WRITABLE, ZCL_ARRAY_ATTRIBUTE_TYPE, sizeof(LabelStruct) * 1 + 2, LabelStruct, false> mSomeLabels; }; struct DemoClusterAccess : public CommonAttributeAccessInterface diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/BridgeGlobalStructs.h b/scripts/idl/tests/outputs/several_clusters/bridge/BridgeGlobalStructs.h index 9dc0e1e1dec340..5fcca27baf8f3d 100644 --- a/scripts/idl/tests/outputs/several_clusters/bridge/BridgeGlobalStructs.h +++ b/scripts/idl/tests/outputs/several_clusters/bridge/BridgeGlobalStructs.h @@ -2,6 +2,7 @@ #include #include +#include namespace clusters { diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/First.h b/scripts/idl/tests/outputs/several_clusters/bridge/First.h index c5bae7b40c51bc..bff536ec7a1596 100644 --- a/scripts/idl/tests/outputs/several_clusters/bridge/First.h +++ b/scripts/idl/tests/outputs/several_clusters/bridge/First.h @@ -22,12 +22,6 @@ struct FirstCluster : public CommonCluster } } - template - void AddAllAttributes(T *list) - { - list->Add(mSomeInteger); - } - chip::Span GetAllAttributes() override { static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { @@ -37,7 +31,7 @@ struct FirstCluster : public CommonCluster } - Attribute<1, ATTRIBUTE_MASK_WRITABLE, PrimitiveType> mSomeInteger; + Attribute<1, ATTRIBUTE_MASK_WRITABLE, ZCL_INT16U_ATTRIBUTE_TYPE, 2, uint16_t, false> mSomeInteger; }; struct FirstAccess : public CommonAttributeAccessInterface diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/Second.h b/scripts/idl/tests/outputs/several_clusters/bridge/Second.h index 6b0b74e5021897..ac765945057e50 100644 --- a/scripts/idl/tests/outputs/several_clusters/bridge/Second.h +++ b/scripts/idl/tests/outputs/several_clusters/bridge/Second.h @@ -22,12 +22,6 @@ struct SecondCluster : public CommonCluster } } - template - void AddAllAttributes(T *list) - { - list->Add(mSomeBytes); - } - chip::Span GetAllAttributes() override { static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { @@ -37,7 +31,7 @@ struct SecondCluster : public CommonCluster } - Attribute<123, 0, OctetString<32, ZCL_OCTET_STRING_ATTRIBUTE_TYPE>> mSomeBytes; + Attribute<123, 0, ZCL_OCTET_STRING_ATTRIBUTE_TYPE, 32, FixedOctetString<32, ZCL_OCTET_STRING_ATTRIBUTE_TYPE>, false> mSomeBytes; }; struct SecondAccess : public CommonAttributeAccessInterface diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/Third.h b/scripts/idl/tests/outputs/several_clusters/bridge/Third.h index 18833218b504a1..c19611202e0c24 100644 --- a/scripts/idl/tests/outputs/several_clusters/bridge/Third.h +++ b/scripts/idl/tests/outputs/several_clusters/bridge/Third.h @@ -22,12 +22,6 @@ struct ThirdCluster : public CommonCluster } } - template - void AddAllAttributes(T *list) - { - list->Add(mSomeEnum); - } - chip::Span GetAllAttributes() override { static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { @@ -37,7 +31,7 @@ struct ThirdCluster : public CommonCluster } - Attribute<10, ATTRIBUTE_MASK_WRITABLE, PrimitiveType> mSomeEnum; + Attribute<10, ATTRIBUTE_MASK_WRITABLE, ZCL_ENUM8_ATTRIBUTE_TYPE, 1, uint8_t, false> mSomeEnum; }; struct ThirdAccess : public CommonAttributeAccessInterface diff --git a/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeGlobalStructs.h b/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeGlobalStructs.h index 9dc0e1e1dec340..5fcca27baf8f3d 100644 --- a/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeGlobalStructs.h +++ b/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeGlobalStructs.h @@ -2,6 +2,7 @@ #include #include +#include namespace clusters { diff --git a/scripts/idl/tests/outputs/simple_attribute/bridge/MyCluster.h b/scripts/idl/tests/outputs/simple_attribute/bridge/MyCluster.h index 813f722913c412..709d83ad748dc1 100644 --- a/scripts/idl/tests/outputs/simple_attribute/bridge/MyCluster.h +++ b/scripts/idl/tests/outputs/simple_attribute/bridge/MyCluster.h @@ -22,12 +22,6 @@ struct MyClusterCluster : public CommonCluster } } - template - void AddAllAttributes(T *list) - { - list->Add(mClusterAttr); - } - chip::Span GetAllAttributes() override { static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { @@ -37,7 +31,7 @@ struct MyClusterCluster : public CommonCluster } - Attribute<1, ATTRIBUTE_MASK_WRITABLE, PrimitiveType> mClusterAttr; + Attribute<1, ATTRIBUTE_MASK_WRITABLE, ZCL_INT16U_ATTRIBUTE_TYPE, 2, uint16_t, false> mClusterAttr; }; struct MyClusterAccess : public CommonAttributeAccessInterface From 390439953b55abf34e6f964c42b2528acbc2c3ed Mon Sep 17 00:00:00 2001 From: Albert Chaulk Date: Wed, 31 Aug 2022 17:13:13 -0400 Subject: [PATCH 07/14] update for CR comments --- examples/bridge-app/linux/Clusters.cpp | 2 +- examples/bridge-app/linux/Device.cpp | 2 +- examples/bridge-app/linux/DynamicDevice.cpp | 2 +- .../bridge-app/linux/UserInputBackend.cpp | 6 +- examples/bridge-app/linux/include/Clusters.h | 224 +---------------- examples/bridge-app/linux/include/Device.h | 6 +- .../bridge-app/linux/include/DynamicDevice.h | 3 +- .../linux/include/GeneratedClusters.h | 235 ++++++++++++++++++ scripts/idl/tests/available_tests.yaml | 10 +- 9 files changed, 258 insertions(+), 232 deletions(-) create mode 100644 examples/bridge-app/linux/include/GeneratedClusters.h diff --git a/examples/bridge-app/linux/Clusters.cpp b/examples/bridge-app/linux/Clusters.cpp index 24948043580ca5..4461de1acb9e59 100644 --- a/examples/bridge-app/linux/Clusters.cpp +++ b/examples/bridge-app/linux/Clusters.cpp @@ -1,4 +1,4 @@ -#include "Clusters.h" +#include "GeneratedClusters.h" #include "Device.h" diff --git a/examples/bridge-app/linux/Device.cpp b/examples/bridge-app/linux/Device.cpp index 268feca462e9a0..c749f9bb5babd4 100644 --- a/examples/bridge-app/linux/Device.cpp +++ b/examples/bridge-app/linux/Device.cpp @@ -23,7 +23,7 @@ #include Device::Device(chip::Span dataVersions, chip::Span clusters, - chip::Span clusterImpl, const chip::Span & deviceTypeList, + chip::Span clusterImpl, const chip::Span & deviceTypeList, chip::EndpointId parentId) : mParentEndpointId(parentId), mDataVersions(dataVersions), mClusters(clusters), mClusterImpl(clusterImpl), mDeviceTypeList(deviceTypeList) diff --git a/examples/bridge-app/linux/DynamicDevice.cpp b/examples/bridge-app/linux/DynamicDevice.cpp index 9f1d3eded05158..cc8063e2a0f6f2 100644 --- a/examples/bridge-app/linux/DynamicDevice.cpp +++ b/examples/bridge-app/linux/DynamicDevice.cpp @@ -48,7 +48,7 @@ Device DynamicDeviceImpl::CreateDevice() return Device(chip::Span(mVersions.data(), mVersions.size()), chip::Span(mClusterDecls.data(), mClusterDecls.size()), - chip::Span(mClusterBaseRawPtrs.data(), mClusterBaseRawPtrs.size()), + chip::Span(mClusterBaseRawPtrs.data(), mClusterBaseRawPtrs.size()), chip::Span(mDeviceTypes.data(), mDeviceTypes.size()), mParentEndpointId); } diff --git a/examples/bridge-app/linux/UserInputBackend.cpp b/examples/bridge-app/linux/UserInputBackend.cpp index 8b613cbd976e59..3105fa5b592014 100644 --- a/examples/bridge-app/linux/UserInputBackend.cpp +++ b/examples/bridge-app/linux/UserInputBackend.cpp @@ -243,7 +243,7 @@ Device * FindEndpoint(int32_t index) } } -ClusterImpl * FindCluster(DynamicDeviceImpl * dev, const std::string & clusterId) +ClusterInterface * FindCluster(DynamicDeviceImpl * dev, const std::string & clusterId) { uint32_t id; const char * start = clusterId.data(); @@ -273,7 +273,7 @@ ClusterImpl * FindCluster(DynamicDeviceImpl * dev, const std::string & clusterId return nullptr; } -const EmberAfAttributeMetadata * FindAttrib(ClusterImpl * cluster, const std::string & attrId) +const EmberAfAttributeMetadata * FindAttrib(ClusterInterface * cluster, const std::string & attrId) { uint32_t id; const char * start = attrId.data(); @@ -378,7 +378,7 @@ void SetValue(const std::vector & tokens) return; } - ClusterImpl * cluster = FindCluster(dev, clusterId); + ClusterInterface * cluster = FindCluster(dev, clusterId); if (!cluster) { printf("Device does not implement cluster %s\nSupported clusters: ", clusterId.c_str()); diff --git a/examples/bridge-app/linux/include/Clusters.h b/examples/bridge-app/linux/include/Clusters.h index 2d0023103a2b8d..133d139c308e38 100644 --- a/examples/bridge-app/linux/include/Clusters.h +++ b/examples/bridge-app/linux/include/Clusters.h @@ -28,229 +28,19 @@ #include -static constexpr uint16_t ZCL_DESCRIPTOR_CLUSTER_REVISION = 1; -static constexpr uint16_t ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_REVISION = 1; -static constexpr uint16_t ZCL_FIXED_LABEL_CLUSTER_REVISION = 1; -static constexpr uint16_t ZCL_ON_OFF_CLUSTER_REVISION = 4; -static constexpr uint16_t ZCL_SWITCH_CLUSTER_REVISION = 1; -static constexpr uint16_t ZCL_LEVEL_CONTROL_CLUSTER_REVISION = 1; -static constexpr uint16_t ZCL_TEMPERATURE_MEASUREMENT_CLUSTER_REVISION = 1; - // This is the interface to cluster implementations, providing access to manipulate attributes. -class ClusterImpl +class ClusterInterface { public: - virtual ~ClusterImpl() = default; + virtual ~ClusterInterface() = default; + // Set the endpoint for this cluster. virtual void SetEndpointId(chip::EndpointId id) = 0; + // Get the ID for this cluster. virtual chip::ClusterId GetClusterId() = 0; + // Gets the list of enabled attributes for this cluster. virtual chip::Span GetAllAttributes() = 0; + // Write the given TLV encoded value to the given attribute. Can write + // normally read-only values. Nofitied matter that the value has changed. virtual bool Push(chip::AttributeId attr, chip::TLV::TLVReader & reader) = 0; }; - -// This provides storage for octet strings -template -struct FixedOctetString -{ - CHIP_ERROR Decode(chip::TLV::TLVReader & reader) - { - chip::ByteSpan v; - CHIP_ERROR err = chip::app::DataModel::Decode(reader, v); - if (err == CHIP_NO_ERROR) - { - if (v.size() > Bytes) - { - return CHIP_ERROR_BUFFER_TOO_SMALL; - } - mLength = static_cast(v.size()); - memcpy(mValue, v.data(), mLength); - } - return err; - } - - CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const - { - if (IsChar) - return chip::app::DataModel::Encode(writer, tag, chip::CharSpan(static_cast(mValue), mLength)); - return chip::app::DataModel::Encode(writer, tag, chip::ByteSpan(mValue, mLength)); - } - - operator chip::ByteSpan() const { return chip::ByteSpan(mValue, mLength); } - operator chip::CharSpan() const { return chip::CharSpan(static_cast(mValue), mLength); } - - void operator=(const FixedOctetString&) = default; - -private: - uint16_t mLength = 0; - uint8_t mValue[Bytes]; -}; - -// This allows for an array of up to MaxElements of a specified type. -template -struct ArrayAttribute -{ - static constexpr chip::AttributeId kId = id; - static constexpr EmberAfClusterMask kMask = mask | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE); - static constexpr EmberAfAttributeType kMatterType = AfType; - // Bytes is the total length, including the length prefix - static constexpr uint16_t kMaxSize = Bytes; - static_assert(Bytes <= MaxElements * sizeof(Type) + 2, "Incorrect type / byte specification"); - static_assert(std::is_standard_layout::value, "Array element not standard layout!"); - - static constexpr bool kIsFabricScoped = IsFabricScoped; - - void ListWriteBegin(const chip::app::ConcreteAttributePath & aPath) {} - - void ListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) {} - - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) - { - return CHIP_NO_ERROR; - } - - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) - { - if (aPath.mListIndex.HasValue()) - { - uint16_t index = aPath.mListIndex.Value(); - if (index >= mLength || IsNull()) - return CHIP_ERROR_INVALID_ARGUMENT; - - return aEncoder.Encode(mArray[index]); - } - - if (IsNull()) - return aEncoder.EncodeNull(); - if (mLength == 0) - return aEncoder.EncodeEmptyList(); - return aEncoder.EncodeList([this](const auto & encoder) { - CHIP_ERROR err = CHIP_NO_ERROR; - for (uint16_t i = 0; i < mLength && err == CHIP_NO_ERROR; i++) { - err = encoder.Encode(mArray[i]); - } - return err; - }); - } - - bool IsNull() const { return mLength == 0xFFFF; } - -private: - uint16_t mLength = Nullable ? 0xFFFF : 0; - Type mArray[MaxElements]; -}; - -// This is used by code generation to provide specific attributes. Type should be a primitive that works with Encode()/Decode(). -template -struct Attribute -{ - static constexpr chip::AttributeId kId = id; - static constexpr EmberAfClusterMask kMask = mask | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE); - static constexpr EmberAfAttributeType kMatterType = AfType; - // Note that Bytes can be < sizeof(T) due to non-power-of-two byte lengths. - static constexpr uint16_t kMaxSize = Bytes; - static_assert(Bytes <= sizeof(Type), "Incorrect type / byte specification"); - - static constexpr bool kIsFabricScoped = IsFabricScoped; - - Attribute(Type v = Type()) : mData(v) {} - - const Type& Peek() const - { - return mData; - } - void operator=(const Type& v) - { - mData = v; - } - - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) - { - return aDecoder.Decode(mData); - } - - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) - { - return aEncoder.Encode(mData); - } - - Type mData; -}; - -struct CommonCluster; -typedef std::function - PropagateWriteCB; - -// This is the base type of all generated clusters, providing the backend access to -// implementation details. -struct CommonCluster : public ClusterImpl -{ - void SetEndpointId(chip::EndpointId id) override; - chip::EndpointId GetEndpointId() const; - - void SetCallback(PropagateWriteCB * cb); - - bool active() const; - - virtual CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, - chip::app::AttributeValueDecoder & aDecoder) = 0; - - CHIP_ERROR ForwardWriteToBridge(const chip::app::ConcreteDataAttributePath & aPath, - chip::app::AttributeValueDecoder & aDecoder); - - template - void Push(T & attr, U v) - { - attr = v; - OnUpdated(T::kId); - } - bool Push(chip::AttributeId attr, chip::TLV::TLVReader & reader); - - void OnUpdated(chip::AttributeId attr); - template - void OnUpdated(const T & attr) - { - OnUpdated(T::kId); - } - -protected: - chip::EndpointId mEndpoint = 0xFFFF; - PropagateWriteCB * mCallback = nullptr; -}; - -struct CommonAttributeAccessInterface : public chip::app::AttributeAccessInterface -{ - using chip::app::AttributeAccessInterface::AttributeAccessInterface; - static CommonCluster * FindCluster(const chip::app::ConcreteClusterPath & path); -}; - -#include "bridge/BridgeClustersImpl.h" - -namespace clusters { -struct BridgedDeviceBasicCluster : public CommonCluster -{ - static constexpr chip::ClusterId kClusterId = ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID; - - BridgedDeviceBasicCluster(); - - chip::ClusterId GetClusterId() override { return kClusterId; } - CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, - chip::app::AttributeValueDecoder & aDecoder) override; - - template - void AddAllAttributes(T * list) - { - list->Add(mReachable); - } - - chip::Span GetAllAttributes() override - { - static constexpr EmberAfAttributeMetadata kAllAttributes[] = { - { ZCL_REACHABLE_ATTRIBUTE_ID, ZCL_BOOLEAN_ATTRIBUTE_TYPE, 1, 0, 0u }, - }; - return chip::Span(kAllAttributes); - } - - Attribute mReachable; -}; - -} // namespace clusters diff --git a/examples/bridge-app/linux/include/Device.h b/examples/bridge-app/linux/include/Device.h index b65186b7fff8c0..a4a6794b60001a 100644 --- a/examples/bridge-app/linux/include/Device.h +++ b/examples/bridge-app/linux/include/Device.h @@ -46,14 +46,14 @@ class Device { public: - Device(chip::Span dataVersions, chip::Span clusters, chip::Span clusterImpl, + Device(chip::Span dataVersions, chip::Span clusters, chip::Span clusterImpl, const chip::Span & deviceTypeList, chip::EndpointId parentId); ~Device() = default; const chip::Span & versions() { return mDataVersions; } const chip::Span & deviceTypes() { return mDeviceTypeList; } const EmberAfEndpointType * endpointType() { return &mEndpointType; } - const chip::Span & clusters() { return mClusterImpl; } + const chip::Span & clusters() { return mClusterImpl; } void SetEndpointId(chip::EndpointId id); chip::EndpointId GetEndpointId() { return mEndpointId; } @@ -67,7 +67,7 @@ class Device chip::EndpointId mEndpointId; chip::Span mDataVersions; chip::Span mClusters; - chip::Span mClusterImpl; + chip::Span mClusterImpl; chip::Span mDeviceTypeList; EmberAfEndpointType mEndpointType; std::string mDeviceName; diff --git a/examples/bridge-app/linux/include/DynamicDevice.h b/examples/bridge-app/linux/include/DynamicDevice.h index 5e7677f1bd8386..8171ab8b2b4731 100644 --- a/examples/bridge-app/linux/include/DynamicDevice.h +++ b/examples/bridge-app/linux/include/DynamicDevice.h @@ -19,6 +19,7 @@ #pragma once #include "Device.h" +#include "GeneratedClusters.h" #include #include @@ -89,7 +90,7 @@ class DynamicDeviceImpl private: std::vector> mClusters; std::vector mClusterRawPtrs; - std::vector mClusterBaseRawPtrs; + std::vector mClusterBaseRawPtrs; std::vector mClusterDecls; diff --git a/examples/bridge-app/linux/include/GeneratedClusters.h b/examples/bridge-app/linux/include/GeneratedClusters.h new file mode 100644 index 00000000000000..1efde025290824 --- /dev/null +++ b/examples/bridge-app/linux/include/GeneratedClusters.h @@ -0,0 +1,235 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include + +#include + +#include "Clusters.h" + +// This provides storage for octet strings +template +struct FixedOctetString +{ + CHIP_ERROR Decode(chip::TLV::TLVReader & reader) + { + chip::ByteSpan v; + CHIP_ERROR err = chip::app::DataModel::Decode(reader, v); + if (err == CHIP_NO_ERROR) + { + if (v.size() > Bytes) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + mLength = static_cast(v.size()); + memcpy(mValue, v.data(), mLength); + } + return err; + } + + CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const + { + if (IsChar) + return chip::app::DataModel::Encode(writer, tag, chip::CharSpan(static_cast(mValue), mLength)); + return chip::app::DataModel::Encode(writer, tag, chip::ByteSpan(mValue, mLength)); + } + + operator chip::ByteSpan() const { return chip::ByteSpan(mValue, mLength); } + operator chip::CharSpan() const { return chip::CharSpan(static_cast(mValue), mLength); } + + void operator=(const FixedOctetString&) = default; + +private: + uint16_t mLength = 0; + uint8_t mValue[Bytes]; +}; + +// This allows for an array of up to MaxElements of a specified type. +template +struct ArrayAttribute +{ + static constexpr chip::AttributeId kId = id; + static constexpr EmberAfClusterMask kMask = mask | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE); + static constexpr EmberAfAttributeType kMatterType = AfType; + // Bytes is the total length, including the length prefix + static constexpr uint16_t kMaxSize = Bytes; + static_assert(Bytes <= MaxElements * sizeof(Type) + 2, "Incorrect type / byte specification"); + static_assert(std::is_standard_layout::value, "Array element not standard layout!"); + + static constexpr bool kIsFabricScoped = IsFabricScoped; + + void ListWriteBegin(const chip::app::ConcreteAttributePath & aPath) {} + + void ListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) {} + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) + { + return CHIP_NO_ERROR; + } + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) + { + if (aPath.mListIndex.HasValue()) + { + uint16_t index = aPath.mListIndex.Value(); + if (index >= mLength || IsNull()) + return CHIP_ERROR_INVALID_ARGUMENT; + + return aEncoder.Encode(mArray[index]); + } + + if (IsNull()) + return aEncoder.EncodeNull(); + if (mLength == 0) + return aEncoder.EncodeEmptyList(); + return aEncoder.EncodeList([this](const auto & encoder) { + CHIP_ERROR err = CHIP_NO_ERROR; + for (uint16_t i = 0; i < mLength && err == CHIP_NO_ERROR; i++) { + err = encoder.Encode(mArray[i]); + } + return err; + }); + } + + bool IsNull() const { return mLength == 0xFFFF; } + +private: + uint16_t mLength = Nullable ? 0xFFFF : 0; + Type mArray[MaxElements]; +}; + +// This is used by code generation to provide specific attributes. Type should be a primitive that works with Encode()/Decode(). +template +struct Attribute +{ + static constexpr chip::AttributeId kId = id; + static constexpr EmberAfClusterMask kMask = mask | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE); + static constexpr EmberAfAttributeType kMatterType = AfType; + // Note that Bytes can be < sizeof(T) due to non-power-of-two byte lengths. + static constexpr uint16_t kMaxSize = Bytes; + static_assert(Bytes <= sizeof(Type), "Incorrect type / byte specification"); + + static constexpr bool kIsFabricScoped = IsFabricScoped; + + Attribute(Type v = Type()) : mData(v) {} + + const Type& Peek() const + { + return mData; + } + void operator=(const Type& v) + { + mData = v; + } + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) + { + return aDecoder.Decode(mData); + } + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) + { + return aEncoder.Encode(mData); + } + + Type mData; +}; + +struct CommonCluster; +typedef std::function + PropagateWriteCB; + +// This is the base type of all generated clusters, providing the backend access to +// implementation details. +struct CommonCluster : public ClusterInterface +{ + void SetEndpointId(chip::EndpointId id) override; + chip::EndpointId GetEndpointId() const; + + void SetCallback(PropagateWriteCB * cb); + + bool active() const; + + // Implemented by generated code. Valid writes should be forwarded to ForwardWriteToBridge. + virtual CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, + chip::app::AttributeValueDecoder & aDecoder) = 0; + + // Calls the registered callback if one exists, otherwise triggers a write of the actual + // stored value. + CHIP_ERROR ForwardWriteToBridge(const chip::app::ConcreteDataAttributePath & aPath, + chip::app::AttributeValueDecoder & aDecoder); + + template + void Push(T & attr, U v) + { + attr = v; + OnUpdated(T::kId); + } + + // Force a write of a given attribute. Can write normally read-only values. + // Calls OnUpdated after the write finishes. + bool Push(chip::AttributeId attr, chip::TLV::TLVReader & reader); + + // Push an attribute update notification to the matter stack. + void OnUpdated(chip::AttributeId attr); + template + void OnUpdated(const T & attr) + { + OnUpdated(T::kId); + } + +protected: + chip::EndpointId mEndpoint = 0xFFFF; + PropagateWriteCB * mCallback = nullptr; +}; + +struct CommonAttributeAccessInterface : public chip::app::AttributeAccessInterface +{ + using chip::app::AttributeAccessInterface::AttributeAccessInterface; + + // Find a cluster given a specific endpoint/cluster. Returns nullptr if no such + // cluster exists at that path. + static CommonCluster * FindCluster(const chip::app::ConcreteClusterPath & path); +}; + +// Required for default initialization of cluster revisions. +static constexpr uint16_t ZCL_DESCRIPTOR_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_FIXED_LABEL_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_ON_OFF_CLUSTER_REVISION = 4; +static constexpr uint16_t ZCL_SWITCH_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_LEVEL_CONTROL_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_TEMPERATURE_MEASUREMENT_CLUSTER_REVISION = 1; + +#include "bridge/BridgeClustersImpl.h" + + + +namespace clusters { +struct BridgedDeviceBasicCluster : public CommonCluster +{ + static constexpr chip::ClusterId kClusterId = ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID; + + BridgedDeviceBasicCluster(); + + chip::ClusterId GetClusterId() override { return kClusterId; } + CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, + chip::app::AttributeValueDecoder & aDecoder) override; + + chip::Span GetAllAttributes() override + { + static constexpr EmberAfAttributeMetadata kAllAttributes[] = { + { ZCL_REACHABLE_ATTRIBUTE_ID, ZCL_BOOLEAN_ATTRIBUTE_TYPE, 1, 0, 0u }, + }; + return chip::Span(kAllAttributes); + } + + Attribute mReachable; +}; + +} // namespace clusters diff --git a/scripts/idl/tests/available_tests.yaml b/scripts/idl/tests/available_tests.yaml index 54202c8473fe83..719f861db14fd9 100644 --- a/scripts/idl/tests/available_tests.yaml +++ b/scripts/idl/tests/available_tests.yaml @@ -35,15 +35,15 @@ java: jni/MyClusterClient-ReadImpl.cpp: outputs/optional_argument/jni/MyClusterClient-ReadImpl.cpp jni/MyClusterClient-InvokeSubscribeImpl.cpp: outputs/optional_argument/jni/MyClusterClient-InvokeSubscribeImpl.cpp -cpp: +bridge: inputs/simple_attribute.matter: - cpp/BridgeClustersImpl.h: outputs/simple_attribute/cpp/BridgeClustersImpl.h + bridge/BridgeClustersImpl.h: outputs/simple_attribute/bridge/BridgeClustersImpl.h inputs/global_struct_attribute.matter: - cpp/BridgeClustersImpl.h: outputs/global_struct_attribute/cpp/BridgeClustersImpl.h + bridge/BridgeClustersImpl.h: outputs/global_struct_attribute/bridge/BridgeClustersImpl.h inputs/cluster_struct_attribute.matter: - cpp/BridgeClustersImpl.h: outputs/cluster_struct_attribute/cpp/BridgeClustersImpl.h + bridge/BridgeClustersImpl.h: outputs/cluster_struct_attribute/bridge/BridgeClustersImpl.h inputs/several_clusters.matter: - cpp/BridgeClustersImpl.h: outputs/several_clusters/cpp/BridgeClustersImpl.h + bridge/BridgeClustersImpl.h: outputs/several_clusters/bridge/BridgeClustersImpl.h From 0be5bce57fd93374d17f7373f728689e46d46b78 Mon Sep 17 00:00:00 2001 From: Albert Chaulk Date: Wed, 21 Sep 2022 17:51:21 -0400 Subject: [PATCH 08/14] Rename app, move to using STL --- examples/bridge-app/bridge-common/BUILD.gn | 13 - examples/bridge-app/linux/BUILD.gn | 89 +- examples/bridge-app/linux/Clusters.cpp | 75 - examples/bridge-app/linux/Device.cpp | 300 +- .../bridge-app/linux/bridged-actions-stub.cpp | 14 +- examples/bridge-app/linux/include/Clusters.h | 46 - examples/bridge-app/linux/include/Device.h | 255 +- .../bridge-app/linux/include/DynamicDevice.h | 125 - .../linux/include/GeneratedClusters.h | 235 - examples/bridge-app/linux/include/main.h | 35 +- examples/bridge-app/linux/main.cpp | 918 +- .../dynamic-bridge-app/bridge-common/BUILD.gn | 40 + .../bridge-common/bridge-app.matter | 1826 ++++ .../bridge-common/bridge-app.zap | 7547 +++++++++++++++++ .../include/CHIPProjectAppConfig.h | 34 + .../protos/bridge_service.options | 0 .../bridge-common/protos/bridge_service.proto | 0 examples/dynamic-bridge-app/linux/.gn | 25 + examples/dynamic-bridge-app/linux/BUILD.gn | 128 + .../linux/Backend.cpp | 4 +- .../dynamic-bridge-app/linux/Clusters.cpp | 143 + examples/dynamic-bridge-app/linux/Device.cpp | 51 + examples/dynamic-bridge-app/linux/Dockerfile | 23 + .../linux/DynamicDevice.cpp | 43 +- examples/dynamic-bridge-app/linux/README.md | 185 + .../linux/UserInputBackend.cpp | 59 +- examples/dynamic-bridge-app/linux/args.gni | 25 + .../linux/bridge_service.cpp | 12 +- .../linux/bridge_service.h | 0 .../linux/bridged-actions-stub.cpp | 137 + examples/dynamic-bridge-app/linux/build | 1 + .../dynamic-bridge-app/linux/build_overrides | 1 + .../dynamic-bridge-app/linux/entrypoint.sh | 12 + .../linux/include/Attribute.h | 80 + .../linux/include/Backend.h | 4 +- .../linux/include/Clusters.h | 107 + .../linux/include/DataModel.h | 218 + .../dynamic-bridge-app/linux/include/Device.h | 103 + .../linux/include/DeviceImpl.h | 0 .../linux/include/DynamicDevice.h | 84 + .../linux/include/GeneratedClusters.h | 77 + .../dynamic-bridge-app/linux/include/main.h | 54 + examples/dynamic-bridge-app/linux/main.cpp | 197 + .../linux/third_party/connectedhomeip | 1 + .../linux/with_pw_rpc.gni | 0 scripts/build/build/targets.py | 1 + scripts/build/builders/host.py | 3 + .../bridge/BridgeClustersCommon.jinja | 31 +- .../generators/bridge/BridgeClustersCpp.jinja | 111 +- .../bridge/BridgeClustersGlobalStructs.jinja | 3 + .../bridge/BridgeClustersHeader.jinja | 67 + scripts/idl/generators/bridge/__init__.py | 23 +- .../bridge/BridgeClustersImpl.h | 22 +- .../bridge/BridgeGlobalStructs.h | 3 + .../bridge/DemoCluster.h | 96 +- .../bridge/BridgeClustersImpl.h | 22 +- .../bridge/BridgeGlobalStructs.h | 7 +- .../bridge/DemoCluster.h | 96 +- .../bridge/BridgeClustersImpl.h | 31 +- .../bridge/BridgeGlobalStructs.h | 3 + .../outputs/several_clusters/bridge/First.h | 81 +- .../outputs/several_clusters/bridge/Second.h | 81 +- .../outputs/several_clusters/bridge/Third.h | 81 +- .../bridge/BridgeClustersImpl.h | 21 +- .../bridge/BridgeGlobalStructs.h | 3 + .../simple_attribute/bridge/MyCluster.h | 81 +- src/app/AttributeAccessInterface.h | 5 + 67 files changed, 12701 insertions(+), 1497 deletions(-) delete mode 100644 examples/bridge-app/linux/Clusters.cpp delete mode 100644 examples/bridge-app/linux/include/Clusters.h delete mode 100644 examples/bridge-app/linux/include/DynamicDevice.h delete mode 100644 examples/bridge-app/linux/include/GeneratedClusters.h create mode 100644 examples/dynamic-bridge-app/bridge-common/BUILD.gn create mode 100644 examples/dynamic-bridge-app/bridge-common/bridge-app.matter create mode 100644 examples/dynamic-bridge-app/bridge-common/bridge-app.zap create mode 100644 examples/dynamic-bridge-app/bridge-common/include/CHIPProjectAppConfig.h rename examples/{bridge-app => dynamic-bridge-app}/bridge-common/protos/bridge_service.options (100%) rename examples/{bridge-app => dynamic-bridge-app}/bridge-common/protos/bridge_service.proto (100%) create mode 100644 examples/dynamic-bridge-app/linux/.gn create mode 100644 examples/dynamic-bridge-app/linux/BUILD.gn rename examples/{bridge-app => dynamic-bridge-app}/linux/Backend.cpp (92%) create mode 100644 examples/dynamic-bridge-app/linux/Clusters.cpp create mode 100644 examples/dynamic-bridge-app/linux/Device.cpp create mode 100644 examples/dynamic-bridge-app/linux/Dockerfile rename examples/{bridge-app => dynamic-bridge-app}/linux/DynamicDevice.cpp (53%) create mode 100644 examples/dynamic-bridge-app/linux/README.md rename examples/{bridge-app => dynamic-bridge-app}/linux/UserInputBackend.cpp (90%) create mode 100644 examples/dynamic-bridge-app/linux/args.gni rename examples/{bridge-app => dynamic-bridge-app}/linux/bridge_service.cpp (83%) rename examples/{bridge-app => dynamic-bridge-app}/linux/bridge_service.h (100%) create mode 100644 examples/dynamic-bridge-app/linux/bridged-actions-stub.cpp create mode 120000 examples/dynamic-bridge-app/linux/build create mode 120000 examples/dynamic-bridge-app/linux/build_overrides create mode 100755 examples/dynamic-bridge-app/linux/entrypoint.sh create mode 100644 examples/dynamic-bridge-app/linux/include/Attribute.h rename examples/{bridge-app => dynamic-bridge-app}/linux/include/Backend.h (86%) create mode 100644 examples/dynamic-bridge-app/linux/include/Clusters.h create mode 100644 examples/dynamic-bridge-app/linux/include/DataModel.h create mode 100644 examples/dynamic-bridge-app/linux/include/Device.h rename examples/{bridge-app => dynamic-bridge-app}/linux/include/DeviceImpl.h (100%) create mode 100644 examples/dynamic-bridge-app/linux/include/DynamicDevice.h create mode 100644 examples/dynamic-bridge-app/linux/include/GeneratedClusters.h create mode 100644 examples/dynamic-bridge-app/linux/include/main.h create mode 100644 examples/dynamic-bridge-app/linux/main.cpp create mode 120000 examples/dynamic-bridge-app/linux/third_party/connectedhomeip rename examples/{bridge-app => dynamic-bridge-app}/linux/with_pw_rpc.gni (100%) create mode 100644 scripts/idl/generators/bridge/BridgeClustersHeader.jinja diff --git a/examples/bridge-app/bridge-common/BUILD.gn b/examples/bridge-app/bridge-common/BUILD.gn index 1e7c59526db959..ac3aa414ae3791 100644 --- a/examples/bridge-app/bridge-common/BUILD.gn +++ b/examples/bridge-app/bridge-common/BUILD.gn @@ -15,7 +15,6 @@ import("//build_overrides/chip.gni") import("${chip_root}/src/app/chip_data_model.gni") -import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") chip_data_model("bridge-common") { zap_file = "bridge-app.zap" @@ -26,15 +25,3 @@ chip_data_model("bridge-common") { # TODO: the definition of DYNAMIC_ENDPOINT_COUNT needs find a common home! cflags = [ "-DDYNAMIC_ENDPOINT_COUNT=16" ] } - -if (chip_enable_pw_rpc) { - import("//build_overrides/pigweed.gni") - import("$dir_pw_protobuf_compiler/proto.gni") - - pw_proto_library("bridge_service") { - sources = [ "protos/bridge_service.proto" ] - inputs = [ "protos/bridge_service.options" ] - strip_prefix = "protos" - prefix = "bridge_service" - } -} diff --git a/examples/bridge-app/linux/BUILD.gn b/examples/bridge-app/linux/BUILD.gn index da54ebe03f2a76..3912e887a846be 100644 --- a/examples/bridge-app/linux/BUILD.gn +++ b/examples/bridge-app/linux/BUILD.gn @@ -12,112 +12,31 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("//build_overrides/build.gni") import("//build_overrides/chip.gni") import("${chip_root}/build/chip/tools.gni") -import("${chip_root}/src/app/common_flags.gni") - -import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") - -if (chip_enable_pw_rpc) { - import("//build_overrides/pigweed.gni") - import("$dir_pw_build/target_types.gni") -} assert(chip_build_tools) -action("chip-bridge-codegen") { - script = "${chip_root}/scripts/codegen.py" - sources = - [ "${chip_root}/examples/bridge-app/bridge-common/bridge-app.matter" ] - # Also several other files, but this is sufficient for dependency purposes. - outputs = [ "$target_gen_dir/bridge/BridgeClustersImpl.h" ] - - args = [ - "--generator", - "bridge", - "--output-dir", - rebase_path(target_gen_dir, root_build_dir), - rebase_path( - "${chip_root}/examples/bridge-app/bridge-common/bridge-app.matter", - root_build_dir), - ] - deps = [ "${chip_root}/scripts/idl" ] -} - executable("chip-bridge-app") { sources = [ "${chip_root}/examples/bridge-app/linux/bridged-actions-stub.cpp", "${chip_root}/examples/tv-app/tv-common/include/CHIPProjectAppConfig.h", - "Backend.cpp", - "Clusters.cpp", "Device.cpp", - "DynamicDevice.cpp", - "UserInputBackend.cpp", "include/Device.h", "include/main.h", "main.cpp", ] deps = [ - ":chip-bridge-codegen", "${chip_root}/examples/bridge-app/bridge-common", "${chip_root}/examples/platform/linux:app-main", - "${chip_root}/src/app/tests/suites/credentials:dac_provider", "${chip_root}/src/lib", ] - include_dirs = [ - "include", - target_gen_dir, - ] - - if (chip_enable_pw_rpc) { - defines = [ - "PW_RPC_ENABLED", - "PW_RPC_ATTRIBUTE_SERVICE=1", - "PW_RPC_DESCRIPTOR_SERVICE=1", - "PW_RPC_DEVICE_SERVICE=1", - "PW_RPC_TRACING_SERVICE=1" - ] - - sources += [ - "${chip_root}/examples/platform/linux/Rpc.cpp", - "${chip_root}/examples/platform/linux/system_rpc_server.cc", - "bridge_service.cpp" - ] - - deps += [ - "$dir_pw_hdlc:pw_rpc", - "$dir_pw_hdlc:rpc_channel_output", - "$dir_pw_log", - "$dir_pw_rpc:server", - "$dir_pw_rpc/system_server:facade", - "$dir_pw_stream:socket_stream", - "$dir_pw_stream:sys_io_stream", - "$dir_pw_sync:mutex", - "$dir_pw_trace", - "$dir_pw_trace_tokenized", - "$dir_pw_trace_tokenized:trace_rpc_service", - "${chip_root}/config/linux/lib/pw_rpc:pw_rpc", - "${chip_root}/examples/bridge-app/bridge-common:bridge_service.nanopb_rpc", - "${chip_root}/examples/common/pigweed:attributes_service.nanopb_rpc", - "${chip_root}/examples/common/pigweed:button_service.nanopb_rpc", - "${chip_root}/examples/common/pigweed:descriptor_service.nanopb_rpc", - "${chip_root}/examples/common/pigweed:device_service.nanopb_rpc", - "${chip_root}/examples/common/pigweed:lighting_service.nanopb_rpc", - "${chip_root}/examples/common/pigweed:rpc_services", - ] + cflags = [ "-Wconversion" ] - deps += pw_build_LINK_DEPS - - include_dirs += [ "${chip_root}/examples/common" ] - } else { - # The system_rpc_server.cc file is in pigweed and doesn't compile with - # -Wconversion, remove check for RPC build only. - cflags = [ "-Wconversion" ] - } + include_dirs = [ "include" ] output_dir = root_out_dir } @@ -125,7 +44,3 @@ executable("chip-bridge-app") { group("linux") { deps = [ ":chip-bridge-app" ] } - -group("default") { - deps = [ ":linux" ] -} diff --git a/examples/bridge-app/linux/Clusters.cpp b/examples/bridge-app/linux/Clusters.cpp deleted file mode 100644 index 4461de1acb9e59..00000000000000 --- a/examples/bridge-app/linux/Clusters.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "GeneratedClusters.h" - -#include "Device.h" - -CommonCluster * CommonAttributeAccessInterface::FindCluster(const chip::app::ConcreteClusterPath & path) -{ - Device * dev = FindDeviceEndpoint(path.mEndpointId); - if (dev) - { - for (auto c : dev->clusters()) - { - if (c->GetClusterId() == path.mClusterId) - return static_cast(c); - } - } - return nullptr; -} - -void CommonCluster::SetEndpointId(chip::EndpointId id) -{ - mEndpoint = id; -} -chip::EndpointId CommonCluster::GetEndpointId() const -{ - return mEndpoint; -} - -void CommonCluster::SetCallback(PropagateWriteCB * cb) -{ - mCallback = cb; -} - -bool CommonCluster::active() const -{ - return mEndpoint < 0xFFFF; -} - -CHIP_ERROR CommonCluster::ForwardWriteToBridge(const chip::app::ConcreteDataAttributePath & aPath, - chip::app::AttributeValueDecoder & aDecoder) -{ - if (mCallback) - return (*mCallback)(this, aPath, aDecoder); - return WriteFromBridge(aPath, aDecoder); -} - -void CommonCluster::OnUpdated(chip::AttributeId attr) -{ - if (active()) - MatterReportingAttributeChangeCallback(GetEndpointId(), GetClusterId(), attr); -} - -bool CommonCluster::Push(chip::AttributeId attr, chip::TLV::TLVReader & reader) -{ - chip::app::AttributeValueDecoder decoder(reader, chip::Access::SubjectDescriptor()); - if (WriteFromBridge(chip::app::ConcreteDataAttributePath(GetEndpointId(), GetClusterId(), attr), decoder) != CHIP_NO_ERROR) - return false; - OnUpdated(attr); - return true; -} - -namespace clusters { -BridgedDeviceBasicCluster::BridgedDeviceBasicCluster() {} - -CHIP_ERROR BridgedDeviceBasicCluster::WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, - chip::app::AttributeValueDecoder & aDecoder) -{ - switch (aPath.mAttributeId) - { - case ZCL_REACHABLE_ATTRIBUTE_ID: - return mReachable.Write(aPath, aDecoder); - } - return CHIP_ERROR_NOT_IMPLEMENTED; -} - -} // namespace clusters diff --git a/examples/bridge-app/linux/Device.cpp b/examples/bridge-app/linux/Device.cpp index c749f9bb5babd4..eae3eff40de3c2 100644 --- a/examples/bridge-app/linux/Device.cpp +++ b/examples/bridge-app/linux/Device.cpp @@ -22,30 +22,298 @@ #include #include -Device::Device(chip::Span dataVersions, chip::Span clusters, - chip::Span clusterImpl, const chip::Span & deviceTypeList, - chip::EndpointId parentId) : - mParentEndpointId(parentId), - mDataVersions(dataVersions), mClusters(clusters), mClusterImpl(clusterImpl), mDeviceTypeList(deviceTypeList) +using namespace chip::app::Clusters::Actions; + +// LightingManager LightingManager::sLight; + +Device::Device(const char * szDeviceName, std::string szLocation) +{ + strncpy(mName, szDeviceName, sizeof(mName)); + mLocation = szLocation; + mReachable = false; + mEndpointId = 0; +} + +bool Device::IsReachable() +{ + return mReachable; +} + +void Device::SetReachable(bool aReachable) +{ + bool changed = (mReachable != aReachable); + + mReachable = aReachable; + + if (aReachable) + { + ChipLogProgress(DeviceLayer, "Device[%s]: ONLINE", mName); + } + else + { + ChipLogProgress(DeviceLayer, "Device[%s]: OFFLINE", mName); + } + + if (changed) + { + HandleDeviceChange(this, kChanged_Reachable); + } +} + +void Device::SetName(const char * szName) +{ + bool changed = (strncmp(mName, szName, sizeof(mName)) != 0); + + ChipLogProgress(DeviceLayer, "Device[%s]: New Name=\"%s\"", mName, szName); + + strncpy(mName, szName, sizeof(mName)); + + if (changed) + { + HandleDeviceChange(this, kChanged_Name); + } +} + +void Device::SetLocation(std::string szLocation) +{ + bool changed = (mLocation.compare(szLocation) != 0); + + mLocation = szLocation; + + ChipLogProgress(DeviceLayer, "Device[%s]: Location=\"%s\"", mName, mLocation.c_str()); + + if (changed) + { + HandleDeviceChange(this, kChanged_Location); + } +} + +DeviceOnOff::DeviceOnOff(const char * szDeviceName, std::string szLocation) : Device(szDeviceName, szLocation) +{ + mOn = false; +} + +bool DeviceOnOff::IsOn() +{ + return mOn; +} + +void DeviceOnOff::SetOnOff(bool aOn) +{ + bool changed; + + changed = aOn ^ mOn; + mOn = aOn; + ChipLogProgress(DeviceLayer, "Device[%s]: %s", mName, aOn ? "ON" : "OFF"); + + if ((changed) && (mChanged_CB)) + { + mChanged_CB(this, kChanged_OnOff); + } +} + +void DeviceOnOff::Toggle() +{ + bool aOn = !IsOn(); + SetOnOff(aOn); +} + +void DeviceOnOff::SetChangeCallback(DeviceCallback_fn aChanged_CB) +{ + mChanged_CB = aChanged_CB; +} + +void DeviceOnOff::HandleDeviceChange(Device * device, Device::Changed_t changeMask) +{ + if (mChanged_CB) + { + mChanged_CB(this, (DeviceOnOff::Changed_t) changeMask); + } +} + +DeviceSwitch::DeviceSwitch(const char * szDeviceName, std::string szLocation, uint32_t aFeatureMap) : + Device(szDeviceName, szLocation) +{ + mNumberOfPositions = 2; + mCurrentPosition = 0; + mMultiPressMax = 2; + mFeatureMap = aFeatureMap; +} + +void DeviceSwitch::SetNumberOfPositions(uint8_t aNumberOfPositions) +{ + bool changed; + + changed = aNumberOfPositions != mNumberOfPositions; + mNumberOfPositions = aNumberOfPositions; + + if ((changed) && (mChanged_CB)) + { + mChanged_CB(this, kChanged_NumberOfPositions); + } +} + +void DeviceSwitch::SetCurrentPosition(uint8_t aCurrentPosition) +{ + bool changed; + + changed = aCurrentPosition != mCurrentPosition; + mCurrentPosition = aCurrentPosition; + + if ((changed) && (mChanged_CB)) + { + mChanged_CB(this, kChanged_CurrentPosition); + } +} + +void DeviceSwitch::SetMultiPressMax(uint8_t aMultiPressMax) +{ + bool changed; + + changed = aMultiPressMax != mMultiPressMax; + mMultiPressMax = aMultiPressMax; + + if ((changed) && (mChanged_CB)) + { + mChanged_CB(this, kChanged_MultiPressMax); + } +} + +void DeviceSwitch::SetChangeCallback(DeviceCallback_fn aChanged_CB) +{ + mChanged_CB = aChanged_CB; +} + +void DeviceSwitch::HandleDeviceChange(Device * device, Device::Changed_t changeMask) +{ + if (mChanged_CB) + { + mChanged_CB(this, (DeviceSwitch::Changed_t) changeMask); + } +} + +DeviceTempSensor::DeviceTempSensor(const char * szDeviceName, std::string szLocation, int16_t min, int16_t max, + int16_t measuredValue) : + Device(szDeviceName, szLocation), + mMin(min), mMax(max), mMeasurement(measuredValue) +{} + +void DeviceTempSensor::SetMeasuredValue(int16_t measurement) +{ + // Limit measurement based on the min and max. + if (measurement < mMin) + { + measurement = mMin; + } + else if (measurement > mMax) + { + measurement = mMax; + } + + bool changed = mMeasurement != measurement; + + ChipLogProgress(DeviceLayer, "TempSensorDevice[%s]: New measurement=\"%d\"", mName, measurement); + + mMeasurement = measurement; + + if (changed && mChanged_CB) + { + mChanged_CB(this, kChanged_MeasurementValue); + } +} + +void DeviceTempSensor::SetChangeCallback(DeviceCallback_fn aChanged_CB) +{ + mChanged_CB = aChanged_CB; +} + +void DeviceTempSensor::HandleDeviceChange(Device * device, Device::Changed_t changeMask) +{ + if (mChanged_CB) + { + mChanged_CB(this, (DeviceTempSensor::Changed_t) changeMask); + } +} + +void ComposedDevice::HandleDeviceChange(Device * device, Device::Changed_t changeMask) +{ + if (mChanged_CB) + { + mChanged_CB(this, (ComposedDevice::Changed_t) changeMask); + } +} + +void DevicePowerSource::HandleDeviceChange(Device * device, Device::Changed_t changeMask) +{ + if (mChanged_CB) + { + mChanged_CB(this, (DevicePowerSource::Changed_t) changeMask); + } +} + +void DevicePowerSource::SetBatChargeLevel(uint8_t aBatChargeLevel) +{ + bool changed; + + changed = aBatChargeLevel != mBatChargeLevel; + mBatChargeLevel = aBatChargeLevel; + + if ((changed) && (mChanged_CB)) + { + mChanged_CB(this, kChanged_BatLevel); + } +} + +void DevicePowerSource::SetDescription(std::string aDescription) +{ + bool changed; + + changed = aDescription != mDescription; + mDescription = aDescription; + + if ((changed) && (mChanged_CB)) + { + mChanged_CB(this, kChanged_Description); + } +} + +EndpointListInfo::EndpointListInfo(uint16_t endpointListId, std::string name, EndpointListTypeEnum type) +{ + mEndpointListId = endpointListId; + mName = name; + mType = type; +} + +EndpointListInfo::EndpointListInfo(uint16_t endpointListId, std::string name, EndpointListTypeEnum type, + chip::EndpointId endpointId) { - mEndpointType.cluster = clusters.data(); - mEndpointType.clusterCount = (uint8_t) clusters.size(); - mEndpointType.endpointSize = 0; + mEndpointListId = endpointListId; + mName = name; + mType = type; + mEndpoints.push_back(endpointId); } -void Device::SetEndpointId(chip::EndpointId id) +void EndpointListInfo::AddEndpointId(chip::EndpointId endpointId) { - mEndpointId = id; - for (auto * c : mClusterImpl) - c->SetEndpointId(id); + mEndpoints.push_back(endpointId); } -const char * Device::GetName() +Room::Room(std::string name, uint16_t endpointListId, EndpointListTypeEnum type, bool isVisible) { - return mDeviceName.c_str(); + mName = name; + mEndpointListId = endpointListId; + mType = type; + mIsVisible = isVisible; } -void Device::SetName(const char * name) +Action::Action(uint16_t actionId, std::string name, ActionTypeEnum type, uint16_t endpointListId, uint16_t supportedCommands, + ActionStateEnum status, bool isVisible) { - mDeviceName = name; + mActionId = actionId; + mName = name; + mType = type; + mEndpointListId = endpointListId; + mSupportedCommands = supportedCommands; + mStatus = status; + mIsVisible = isVisible; } diff --git a/examples/bridge-app/linux/bridged-actions-stub.cpp b/examples/bridge-app/linux/bridged-actions-stub.cpp index 6c0f7cf8eb680e..9f7173e3564421 100644 --- a/examples/bridge-app/linux/bridged-actions-stub.cpp +++ b/examples/bridge-app/linux/bridged-actions-stub.cpp @@ -58,7 +58,7 @@ constexpr uint16_t ActionsAttrAccess::ClusterRevision; CHIP_ERROR ActionsAttrAccess::ReadActionListAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder) { CHIP_ERROR err = aEncoder.EncodeList([&endpoint](const auto & encoder) -> CHIP_ERROR { - chip::Span actionList = GetActionListInfo(endpoint); + std::vector actionList = GetActionListInfo(endpoint); for (auto action : actionList) { @@ -81,14 +81,14 @@ CHIP_ERROR ActionsAttrAccess::ReadActionListAttribute(EndpointId endpoint, Attri CHIP_ERROR ActionsAttrAccess::ReadEndpointListAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder) { - CHIP_ERROR err = aEncoder.EncodeList([](const auto & encoder) -> CHIP_ERROR { - for (auto & room : gRooms) + std::vector infoList = GetEndpointListInfo(endpoint); + + CHIP_ERROR err = aEncoder.EncodeList([&infoList](const auto & encoder) -> CHIP_ERROR { + for (auto info : infoList) { - if (room.GetEndpointListSize() == 0) - continue; Actions::Structs::EndpointListStruct::Type endpointListStruct = { - room.GetEndpointListId(), CharSpan::fromCharString(room.GetName().c_str()), room.GetType(), - DataModel::List(room.GetEndpointListData(), room.GetEndpointListSize()) + info.GetEndpointListId(), CharSpan::fromCharString(info.GetName().c_str()), info.GetType(), + DataModel::List(info.GetEndpointListData(), info.GetEndpointListSize()) }; ReturnErrorOnFailure(encoder.Encode(endpointListStruct)); } diff --git a/examples/bridge-app/linux/include/Clusters.h b/examples/bridge-app/linux/include/Clusters.h deleted file mode 100644 index 133d139c308e38..00000000000000 --- a/examples/bridge-app/linux/include/Clusters.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - * Copyright (c) 2022 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. - */ - -#pragma once - -#include -#include -#include -#include - -#include -#include - -#include - -// This is the interface to cluster implementations, providing access to manipulate attributes. -class ClusterInterface -{ -public: - virtual ~ClusterInterface() = default; - - // Set the endpoint for this cluster. - virtual void SetEndpointId(chip::EndpointId id) = 0; - // Get the ID for this cluster. - virtual chip::ClusterId GetClusterId() = 0; - // Gets the list of enabled attributes for this cluster. - virtual chip::Span GetAllAttributes() = 0; - // Write the given TLV encoded value to the given attribute. Can write - // normally read-only values. Nofitied matter that the value has changed. - virtual bool Push(chip::AttributeId attr, chip::TLV::TLVReader & reader) = 0; -}; diff --git a/examples/bridge-app/linux/include/Device.h b/examples/bridge-app/linux/include/Device.h index a4a6794b60001a..b85633ceb3fdf3 100644 --- a/examples/bridge-app/linux/include/Device.h +++ b/examples/bridge-app/linux/include/Device.h @@ -18,59 +18,230 @@ #pragma once -#include -#include +#include #include #include -#include "Clusters.h" - -// Device types for dynamic endpoints: TODO Need a generated file from ZAP to define these! -// (taken from chip-devices.xml) -#define DEVICE_TYPE_BRIDGED_NODE 0x0013 -// (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 -// (taken from chip-devices.xml) -#define DEVICE_TYPE_ROOT_NODE 0x0016 -// (taken from chip-devices.xml) -#define DEVICE_TYPE_BRIDGE 0x000e - -// Device Version for dynamic endpoints: -#define DEVICE_VERSION_DEFAULT 1 - -// This represents a single logical device occupying one endpoint. A composed device consists of multiple -// Device objects that reference a tree. +#include +#include + class Device { public: - Device(chip::Span dataVersions, chip::Span clusters, chip::Span clusterImpl, - const chip::Span & deviceTypeList, chip::EndpointId parentId); - ~Device() = default; + static const int kDeviceNameSize = 32; - const chip::Span & versions() { return mDataVersions; } - const chip::Span & deviceTypes() { return mDeviceTypeList; } - const EmberAfEndpointType * endpointType() { return &mEndpointType; } - const chip::Span & clusters() { return mClusterImpl; } + enum Changed_t + { + kChanged_Reachable = 1u << 0, + kChanged_Location = 1u << 1, + kChanged_Name = 1u << 2, + kChanged_Last = kChanged_Name, + } Changed; - void SetEndpointId(chip::EndpointId id); - chip::EndpointId GetEndpointId() { return mEndpointId; } - chip::EndpointId GetParentEndpointId() { return mParentEndpointId; } + Device(const char * szDeviceName, std::string szLocation); + virtual ~Device() {} - const char * GetName(); - void SetName(const char * name); + bool IsReachable(); + void SetReachable(bool aReachable); + void SetName(const char * szDeviceName); + void SetLocation(std::string szLocation); + inline void SetEndpointId(chip::EndpointId id) { mEndpointId = id; }; + inline chip::EndpointId GetEndpointId() { return mEndpointId; }; + inline void SetParentEndpointId(chip::EndpointId id) { mParentEndpointId = id; }; + inline chip::EndpointId GetParentEndpointId() { return mParentEndpointId; }; + inline char * GetName() { return mName; }; + inline std::string GetLocation() { return mLocation; }; + inline std::string GetZone() { return mZone; }; + inline void SetZone(std::string zone) { mZone = zone; }; private: - chip::EndpointId mParentEndpointId; + virtual void HandleDeviceChange(Device * device, Device::Changed_t changeMask) = 0; + +protected: + bool mReachable; + char mName[kDeviceNameSize]; + std::string mLocation; chip::EndpointId mEndpointId; - chip::Span mDataVersions; - chip::Span mClusters; - chip::Span mClusterImpl; - chip::Span mDeviceTypeList; - EmberAfEndpointType mEndpointType; - std::string mDeviceName; + chip::EndpointId mParentEndpointId; + std::string mZone; +}; + +class DeviceOnOff : public Device +{ +public: + enum Changed_t + { + kChanged_OnOff = kChanged_Last << 1, + } Changed; + + DeviceOnOff(const char * szDeviceName, std::string szLocation); + + bool IsOn(); + void SetOnOff(bool aOn); + void Toggle(); + + using DeviceCallback_fn = std::function; + void SetChangeCallback(DeviceCallback_fn aChanged_CB); + +private: + void HandleDeviceChange(Device * device, Device::Changed_t changeMask); + +private: + bool mOn; + DeviceCallback_fn mChanged_CB; +}; + +class DeviceSwitch : public Device +{ +public: + enum Changed_t + { + kChanged_NumberOfPositions = kChanged_Last << 1, + kChanged_CurrentPosition = kChanged_Last << 2, + kChanged_MultiPressMax = kChanged_Last << 3, + } Changed; + + DeviceSwitch(const char * szDeviceName, std::string szLocation, uint32_t aFeatureMap); + + void SetNumberOfPositions(uint8_t aNumberOfPositions); + void SetCurrentPosition(uint8_t aCurrentPosition); + void SetMultiPressMax(uint8_t aMultiPressMax); + + inline uint8_t GetNumberOfPositions() { return mNumberOfPositions; }; + inline uint8_t GetCurrentPosition() { return mCurrentPosition; }; + inline uint8_t GetMultiPressMax() { return mMultiPressMax; }; + inline uint32_t GetFeatureMap() { return mFeatureMap; }; + + using DeviceCallback_fn = std::function; + void SetChangeCallback(DeviceCallback_fn aChanged_CB); + +private: + void HandleDeviceChange(Device * device, Device::Changed_t changeMask); + +private: + uint8_t mNumberOfPositions; + uint8_t mCurrentPosition; + uint8_t mMultiPressMax; + uint32_t mFeatureMap; + DeviceCallback_fn mChanged_CB; +}; + +class DeviceTempSensor : public Device +{ +public: + enum Changed_t + { + kChanged_MeasurementValue = kChanged_Last << 1, + } Changed; + + DeviceTempSensor(const char * szDeviceName, std::string szLocation, int16_t min, int16_t max, int16_t measuredValue); + + inline int16_t GetMeasuredValue() { return mMeasurement; }; + void SetMeasuredValue(int16_t measurement); + + using DeviceCallback_fn = std::function; + void SetChangeCallback(DeviceCallback_fn aChanged_CB); + + const int16_t mMin; + const int16_t mMax; + +private: + void HandleDeviceChange(Device * device, Device::Changed_t changeMask); + +private: + int16_t mMeasurement; + DeviceCallback_fn mChanged_CB; +}; + +class ComposedDevice : public Device +{ +public: + ComposedDevice(const char * szDeviceName, std::string szLocation) : Device(szDeviceName, szLocation){}; + + using DeviceCallback_fn = std::function; + + void SetChangeCallback(DeviceCallback_fn aChanged_CB); + +private: + void HandleDeviceChange(Device * device, Device::Changed_t changeMask); + +private: + DeviceCallback_fn mChanged_CB; +}; + +class DevicePowerSource : public Device +{ +public: + enum Changed_t + { + kChanged_BatLevel = kChanged_Last << 1, + kChanged_Description = kChanged_Last << 2, + } Changed; + + DevicePowerSource(const char * szDeviceName, std::string szLocation, uint32_t aFeatureMap) : + Device(szDeviceName, szLocation), mFeatureMap(aFeatureMap){}; + + using DeviceCallback_fn = std::function; + void SetChangeCallback(DeviceCallback_fn aChanged_CB) { mChanged_CB = aChanged_CB; } + + void SetBatChargeLevel(uint8_t aBatChargeLevel); + void SetDescription(std::string aDescription); + + inline uint32_t GetFeatureMap() { return mFeatureMap; }; + inline uint8_t GetBatChargeLevel() { return mBatChargeLevel; }; + inline uint8_t GetOrder() { return mOrder; }; + inline uint8_t GetStatus() { return mStatus; }; + inline std::string GetDescription() { return mDescription; }; + +private: + void HandleDeviceChange(Device * device, Device::Changed_t changeMask); + +private: + uint8_t mBatChargeLevel = 0; + uint8_t mOrder = 0; + uint8_t mStatus = 0; + std::string mDescription = "Primary Battery"; + uint32_t mFeatureMap; + DeviceCallback_fn mChanged_CB; +}; + +class EndpointListInfo +{ +public: + EndpointListInfo(uint16_t endpointListId, std::string name, chip::app::Clusters::Actions::EndpointListTypeEnum type); + EndpointListInfo(uint16_t endpointListId, std::string name, chip::app::Clusters::Actions::EndpointListTypeEnum type, + chip::EndpointId endpointId); + void AddEndpointId(chip::EndpointId endpointId); + inline uint16_t GetEndpointListId() { return mEndpointListId; }; + std::string GetName() { return mName; }; + inline chip::app::Clusters::Actions::EndpointListTypeEnum GetType() { return mType; }; + inline chip::EndpointId * GetEndpointListData() { return mEndpoints.data(); }; + inline size_t GetEndpointListSize() { return mEndpoints.size(); }; + +private: + uint16_t mEndpointListId = static_cast(0); + std::string mName; + chip::app::Clusters::Actions::EndpointListTypeEnum mType = static_cast(0); + std::vector mEndpoints; +}; + +class Room +{ +public: + Room(std::string name, uint16_t endpointListId, chip::app::Clusters::Actions::EndpointListTypeEnum type, bool isVisible); + inline void setIsVisible(bool isVisible) { mIsVisible = isVisible; }; + inline bool getIsVisible() { return mIsVisible; }; + inline void setName(std::string name) { mName = name; }; + inline std::string getName() { return mName; }; + inline chip::app::Clusters::Actions::EndpointListTypeEnum getType() { return mType; }; + inline uint16_t getEndpointListId() { return mEndpointListId; }; + +private: + bool mIsVisible; + std::string mName; + uint16_t mEndpointListId; + chip::app::Clusters::Actions::EndpointListTypeEnum mType; }; class Action @@ -97,7 +268,3 @@ class Action uint16_t mSupportedCommands; bool mIsVisible; }; - -int AddDeviceEndpoint(Device * dev); -int RemoveDeviceEndpoint(Device * dev); -Device * FindDeviceEndpoint(chip::EndpointId id); diff --git a/examples/bridge-app/linux/include/DynamicDevice.h b/examples/bridge-app/linux/include/DynamicDevice.h deleted file mode 100644 index 8171ab8b2b4731..00000000000000 --- a/examples/bridge-app/linux/include/DynamicDevice.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * - * Copyright (c) 2022 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. - */ - -#pragma once - -#include "Device.h" -#include "GeneratedClusters.h" - -#include -#include - -// This file provides implementations that use dynamic storage - -struct DynamicAttributeList -{ - template - void Add(const T & attrib) - { - Add(T::kId, T::kMatterType, T::kMaxSize, T::kMask); - } - - void Add(EmberAfAttributeMetadata metadata); - - void Add(chip::AttributeId id, EmberAfAttributeType type, uint16_t maxSize, EmberAfClusterMask mask); - - std::vector mAttributeDecls; -}; - -template -struct DynamicCluster : public T -{ - DynamicCluster(const chip::CommandId * incomingCommands = nullptr, const chip::CommandId * outgoingCommands = nullptr) : - mIncomingCommands(incomingCommands), mOutgoingCommands(outgoingCommands) - { - for(auto& attr : this->GetAllAttributes()) - mAttributes.Add(attr); - } - - DynamicAttributeList mAttributes; - const chip::CommandId * mIncomingCommands; - const chip::CommandId * mOutgoingCommands; -}; - -class DynamicDeviceImpl -{ -public: - DynamicDeviceImpl(); - - template - DynamicDeviceImpl(Types &... clusters) - {} - - virtual ~DynamicDeviceImpl() = default; - - void SetParentEndpointId(chip::EndpointId id) { mParentEndpointId = id; } - - void AddDeviceType(EmberAfDeviceType type); - - // Add each cluster that the device will ever use. - DynamicDeviceImpl & AddCluster(std::unique_ptr cluster, const DynamicAttributeList & attribs, - const chip::CommandId * incomingCommands, const chip::CommandId * outgoingCommands); - DynamicDeviceImpl & AddCluster(CommonCluster * cluster, const DynamicAttributeList & attribs, - const chip::CommandId * incomingCommands, const chip::CommandId * outgoingCommands); - template - DynamicDeviceImpl & AddCluster(DynamicCluster & cluster) - { - return AddCluster(&cluster, cluster.mAttributes, cluster.mIncomingCommands, cluster.mOutgoingCommands); - } - - // After setting all options, create the device. - Device CreateDevice(); - - const std::vector & clusters() const { return mClusterRawPtrs; } - -private: - std::vector> mClusters; - std::vector mClusterRawPtrs; - std::vector mClusterBaseRawPtrs; - - std::vector mClusterDecls; - - std::vector mVersions; - - std::vector mDeviceTypes; - - std::list> mAttribStorage; - - chip::EndpointId mParentEndpointId = 1; -}; - -class DynamicSwitchDevice : public DynamicDeviceImpl -{ -public: - DynamicSwitchDevice() { AddCluster(mBridgedDevice).AddCluster(mSwitch).AddCluster(mDescriptor); } - ~DynamicSwitchDevice() override = default; - - void SetNumberOfPositions(uint8_t aNumberOfPositions) { mSwitch.Push(mSwitch.mNumberOfPositions, aNumberOfPositions); } - void SetCurrentPosition(uint8_t aCurrentPosition) { mSwitch.Push(mSwitch.mNumberOfPositions, aCurrentPosition); } - void SetMultiPressMax(uint8_t aMultiPressMax) { mSwitch.Push(mSwitch.mNumberOfPositions, aMultiPressMax); } - - inline uint8_t GetNumberOfPositions() { return mSwitch.mNumberOfPositions.Peek(); }; - inline uint8_t GetCurrentPosition() { return mSwitch.mCurrentPosition.Peek(); }; - inline uint8_t GetMultiPressMax() { return mSwitch.mMultiPressMax.Peek(); }; - inline uint32_t GetFeatureMap() { return mSwitch.mFeatureMap.Peek(); }; - -private: - DynamicCluster mBridgedDevice; - DynamicCluster mSwitch; - DynamicCluster mDescriptor; -}; diff --git a/examples/bridge-app/linux/include/GeneratedClusters.h b/examples/bridge-app/linux/include/GeneratedClusters.h deleted file mode 100644 index 1efde025290824..00000000000000 --- a/examples/bridge-app/linux/include/GeneratedClusters.h +++ /dev/null @@ -1,235 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include -#include - -#include - -#include "Clusters.h" - -// This provides storage for octet strings -template -struct FixedOctetString -{ - CHIP_ERROR Decode(chip::TLV::TLVReader & reader) - { - chip::ByteSpan v; - CHIP_ERROR err = chip::app::DataModel::Decode(reader, v); - if (err == CHIP_NO_ERROR) - { - if (v.size() > Bytes) - { - return CHIP_ERROR_BUFFER_TOO_SMALL; - } - mLength = static_cast(v.size()); - memcpy(mValue, v.data(), mLength); - } - return err; - } - - CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const - { - if (IsChar) - return chip::app::DataModel::Encode(writer, tag, chip::CharSpan(static_cast(mValue), mLength)); - return chip::app::DataModel::Encode(writer, tag, chip::ByteSpan(mValue, mLength)); - } - - operator chip::ByteSpan() const { return chip::ByteSpan(mValue, mLength); } - operator chip::CharSpan() const { return chip::CharSpan(static_cast(mValue), mLength); } - - void operator=(const FixedOctetString&) = default; - -private: - uint16_t mLength = 0; - uint8_t mValue[Bytes]; -}; - -// This allows for an array of up to MaxElements of a specified type. -template -struct ArrayAttribute -{ - static constexpr chip::AttributeId kId = id; - static constexpr EmberAfClusterMask kMask = mask | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE); - static constexpr EmberAfAttributeType kMatterType = AfType; - // Bytes is the total length, including the length prefix - static constexpr uint16_t kMaxSize = Bytes; - static_assert(Bytes <= MaxElements * sizeof(Type) + 2, "Incorrect type / byte specification"); - static_assert(std::is_standard_layout::value, "Array element not standard layout!"); - - static constexpr bool kIsFabricScoped = IsFabricScoped; - - void ListWriteBegin(const chip::app::ConcreteAttributePath & aPath) {} - - void ListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) {} - - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) - { - return CHIP_NO_ERROR; - } - - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) - { - if (aPath.mListIndex.HasValue()) - { - uint16_t index = aPath.mListIndex.Value(); - if (index >= mLength || IsNull()) - return CHIP_ERROR_INVALID_ARGUMENT; - - return aEncoder.Encode(mArray[index]); - } - - if (IsNull()) - return aEncoder.EncodeNull(); - if (mLength == 0) - return aEncoder.EncodeEmptyList(); - return aEncoder.EncodeList([this](const auto & encoder) { - CHIP_ERROR err = CHIP_NO_ERROR; - for (uint16_t i = 0; i < mLength && err == CHIP_NO_ERROR; i++) { - err = encoder.Encode(mArray[i]); - } - return err; - }); - } - - bool IsNull() const { return mLength == 0xFFFF; } - -private: - uint16_t mLength = Nullable ? 0xFFFF : 0; - Type mArray[MaxElements]; -}; - -// This is used by code generation to provide specific attributes. Type should be a primitive that works with Encode()/Decode(). -template -struct Attribute -{ - static constexpr chip::AttributeId kId = id; - static constexpr EmberAfClusterMask kMask = mask | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE); - static constexpr EmberAfAttributeType kMatterType = AfType; - // Note that Bytes can be < sizeof(T) due to non-power-of-two byte lengths. - static constexpr uint16_t kMaxSize = Bytes; - static_assert(Bytes <= sizeof(Type), "Incorrect type / byte specification"); - - static constexpr bool kIsFabricScoped = IsFabricScoped; - - Attribute(Type v = Type()) : mData(v) {} - - const Type& Peek() const - { - return mData; - } - void operator=(const Type& v) - { - mData = v; - } - - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) - { - return aDecoder.Decode(mData); - } - - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) - { - return aEncoder.Encode(mData); - } - - Type mData; -}; - -struct CommonCluster; -typedef std::function - PropagateWriteCB; - -// This is the base type of all generated clusters, providing the backend access to -// implementation details. -struct CommonCluster : public ClusterInterface -{ - void SetEndpointId(chip::EndpointId id) override; - chip::EndpointId GetEndpointId() const; - - void SetCallback(PropagateWriteCB * cb); - - bool active() const; - - // Implemented by generated code. Valid writes should be forwarded to ForwardWriteToBridge. - virtual CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, - chip::app::AttributeValueDecoder & aDecoder) = 0; - - // Calls the registered callback if one exists, otherwise triggers a write of the actual - // stored value. - CHIP_ERROR ForwardWriteToBridge(const chip::app::ConcreteDataAttributePath & aPath, - chip::app::AttributeValueDecoder & aDecoder); - - template - void Push(T & attr, U v) - { - attr = v; - OnUpdated(T::kId); - } - - // Force a write of a given attribute. Can write normally read-only values. - // Calls OnUpdated after the write finishes. - bool Push(chip::AttributeId attr, chip::TLV::TLVReader & reader); - - // Push an attribute update notification to the matter stack. - void OnUpdated(chip::AttributeId attr); - template - void OnUpdated(const T & attr) - { - OnUpdated(T::kId); - } - -protected: - chip::EndpointId mEndpoint = 0xFFFF; - PropagateWriteCB * mCallback = nullptr; -}; - -struct CommonAttributeAccessInterface : public chip::app::AttributeAccessInterface -{ - using chip::app::AttributeAccessInterface::AttributeAccessInterface; - - // Find a cluster given a specific endpoint/cluster. Returns nullptr if no such - // cluster exists at that path. - static CommonCluster * FindCluster(const chip::app::ConcreteClusterPath & path); -}; - -// Required for default initialization of cluster revisions. -static constexpr uint16_t ZCL_DESCRIPTOR_CLUSTER_REVISION = 1; -static constexpr uint16_t ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_REVISION = 1; -static constexpr uint16_t ZCL_FIXED_LABEL_CLUSTER_REVISION = 1; -static constexpr uint16_t ZCL_ON_OFF_CLUSTER_REVISION = 4; -static constexpr uint16_t ZCL_SWITCH_CLUSTER_REVISION = 1; -static constexpr uint16_t ZCL_LEVEL_CONTROL_CLUSTER_REVISION = 1; -static constexpr uint16_t ZCL_TEMPERATURE_MEASUREMENT_CLUSTER_REVISION = 1; - -#include "bridge/BridgeClustersImpl.h" - - - -namespace clusters { -struct BridgedDeviceBasicCluster : public CommonCluster -{ - static constexpr chip::ClusterId kClusterId = ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID; - - BridgedDeviceBasicCluster(); - - chip::ClusterId GetClusterId() override { return kClusterId; } - CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, - chip::app::AttributeValueDecoder & aDecoder) override; - - chip::Span GetAllAttributes() override - { - static constexpr EmberAfAttributeMetadata kAllAttributes[] = { - { ZCL_REACHABLE_ATTRIBUTE_ID, ZCL_BOOLEAN_ATTRIBUTE_TYPE, 1, 0, 0u }, - }; - return chip::Span(kAllAttributes); - } - - Attribute mReachable; -}; - -} // namespace clusters diff --git a/examples/bridge-app/linux/include/main.h b/examples/bridge-app/linux/include/main.h index 77342a5c5e3ca3..df7ba595cd6ece 100644 --- a/examples/bridge-app/linux/include/main.h +++ b/examples/bridge-app/linux/include/main.h @@ -18,37 +18,6 @@ #pragma once -#include "Device.h" +std::vector GetEndpointListInfo(chip::EndpointId parentId); -class Room -{ -public: - Room() = default; - void SetName(std::string name) { mName = name; } - const std::string & GetName() { return mName; } - chip::app::Clusters::Actions::EndpointListTypeEnum GetType() { return mType; }; - uint16_t GetEndpointListId() { return mEndpointListId; }; - chip::EndpointId * GetEndpointListData() { return mEndpoints.data(); }; - size_t GetEndpointListSize() { return mEndpoints.size(); }; - - void AddEndpoint(chip::EndpointId ep) { mEndpoints.push_back(ep); } - void RemoveEndpoint(chip::EndpointId ep) - { - auto it = std::find(mEndpoints.begin(), mEndpoints.end(), ep); - if (it != mEndpoints.end()) - mEndpoints.erase(it); - } - -private: - std::string mName; - uint16_t mEndpointListId = 0; - chip::app::Clusters::Actions::EndpointListTypeEnum mType; - std::vector mEndpoints; -}; - -static constexpr uint32_t kMaxRooms = 16; -extern Room gRooms[kMaxRooms]; - -Room * FindRoom(const std::string & name); - -chip::Span GetActionListInfo(chip::EndpointId parentId); +std::vector GetActionListInfo(chip::EndpointId parentId); diff --git a/examples/bridge-app/linux/main.cpp b/examples/bridge-app/linux/main.cpp index 9cdbc6af4b3144..ee545d5619feef 100644 --- a/examples/bridge-app/linux/main.cpp +++ b/examples/bridge-app/linux/main.cpp @@ -41,23 +41,14 @@ #include #include -#include "Backend.h" +#include +#include #include "CommissionableInit.h" #include "Device.h" #include "main.h" #include -#include "AppMain.h" - -#ifdef PW_RPC_ENABLED -#include "bridge_service.h" -#include "Rpc.h" -#include "pw_rpc_system_server/rpc_server.h" -static chip::rpc::Bridge bridge_service; -#endif - - #include #include #include @@ -69,30 +60,208 @@ using namespace chip::Transport; using namespace chip::DeviceLayer; using namespace chip::app::Clusters; -static EndpointId gCurrentEndpointId; -static EndpointId gFirstDynamicEndpointId; -static Device * gDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT]; -Room gRooms[kMaxRooms]; +namespace { -bool emberAfActionsClusterInstantActionCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, - const Actions::Commands::InstantAction::DecodableType & commandData) -{ - // No actions are implemented, just return status NotFound. - commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::NotFound); - return true; -} +const int kNodeLabelSize = 32; +// Current ZCL implementation of Struct uses a max-size array of 254 bytes +const int kDescriptorAttributeArraySize = 254; -Device * FindDeviceEndpoint(chip::EndpointId id) -{ - for (auto dev : gDevices) - { - if (dev && dev->GetEndpointId() == id) - return dev; - } - return nullptr; -} +EndpointId gCurrentEndpointId; +EndpointId gFirstDynamicEndpointId; +Device * gDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT]; +std::vector gRooms; +std::vector gActions; + +const int16_t minMeasuredValue = -27315; +const int16_t maxMeasuredValue = 32766; +const int16_t initialMeasuredValue = 100; + +// 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 matter-devices.xml) +#define DEVICE_TYPE_BRIDGED_NODE 0x0013 +// (taken from lo-devices.xml) +#define DEVICE_TYPE_LO_ON_OFF_LIGHT 0x0100 +// (taken from matter-devices.xml) +#define DEVICE_TYPE_POWER_SOURCE 0x0011 +// (taken from matter-devices.xml) +#define DEVICE_TYPE_TEMP_SENSOR 0x0302 + +// Device Version for dynamic endpoints: +#define DEVICE_VERSION_DEFAULT 1 + +// --------------------------------------------------------------------------- +// +// LIGHT ENDPOINT: contains the following clusters: +// - On/Off +// - Descriptor +// - Bridged Device Basic + +// 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(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* feature map */ + DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); + +// Declare Cluster List for Bridged Light endpoint +// TODO: It's not clear whether it would be better to get the command lists from +// the ZAP config on our last fixed endpoint instead. +constexpr CommandId onOffIncomingCommands[] = { + app::Clusters::OnOff::Commands::Off::Id, + app::Clusters::OnOff::Commands::On::Id, + app::Clusters::OnOff::Commands::Toggle::Id, + app::Clusters::OnOff::Commands::OffWithEffect::Id, + app::Clusters::OnOff::Commands::OnWithRecallGlobalScene::Id, + app::Clusters::OnOff::Commands::OnWithTimedOff::Id, + kInvalidCommandId, +}; + +DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedLightClusters) +DECLARE_DYNAMIC_CLUSTER(ZCL_ON_OFF_CLUSTER_ID, onOffAttrs, onOffIncomingCommands, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, descriptorAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, bridgedDeviceBasicAttrs, nullptr, + nullptr) DECLARE_DYNAMIC_CLUSTER_LIST_END; + +// Declare Bridged Light endpoint +DECLARE_DYNAMIC_ENDPOINT(bridgedLightEndpoint, bridgedLightClusters); +DataVersion gLight1DataVersions[ArraySize(bridgedLightClusters)]; +DataVersion gLight2DataVersions[ArraySize(bridgedLightClusters)]; + +DeviceOnOff Light1("Light 1", "Office"); +DeviceOnOff Light2("Light 2", "Office"); + +DeviceTempSensor TempSensor1("TempSensor 1", "Office", minMeasuredValue, maxMeasuredValue, initialMeasuredValue); +DeviceTempSensor TempSensor2("TempSensor 2", "Office", minMeasuredValue, maxMeasuredValue, initialMeasuredValue); + +DeviceTempSensor ComposedTempSensor1("Composed TempSensor 1", "Bedroom", minMeasuredValue, maxMeasuredValue, initialMeasuredValue); +DeviceTempSensor ComposedTempSensor2("Composed TempSensor 2", "Bedroom", minMeasuredValue, maxMeasuredValue, initialMeasuredValue); + +// Declare Bridged endpoints used for Action clusters +DataVersion gActionLight1DataVersions[ArraySize(bridgedLightClusters)]; +DataVersion gActionLight2DataVersions[ArraySize(bridgedLightClusters)]; +DataVersion gActionLight3DataVersions[ArraySize(bridgedLightClusters)]; +DataVersion gActionLight4DataVersions[ArraySize(bridgedLightClusters)]; + +DeviceOnOff ActionLight1("Action Light 1", "Room 1"); +DeviceOnOff ActionLight2("Action Light 2", "Room 1"); +DeviceOnOff ActionLight3("Action Light 3", "Room 2"); +DeviceOnOff ActionLight4("Action Light 4", "Room 2"); + +Room room1("Room 1", 0xE001, Actions::EndpointListTypeEnum::kRoom, true); +Room room2("Room 2", 0xE002, Actions::EndpointListTypeEnum::kRoom, true); +Room room3("Zone 3", 0xE003, Actions::EndpointListTypeEnum::kZone, false); + +Action action1(0x1001, "Room 1 On", Actions::ActionTypeEnum::kAutomation, 0xE001, 0x1, Actions::ActionStateEnum::kInactive, true); +Action action2(0x1002, "Turn On Room 2", Actions::ActionTypeEnum::kAutomation, 0xE002, 0x01, Actions::ActionStateEnum::kInactive, + true); +Action action3(0x1003, "Turn Off Room 1", Actions::ActionTypeEnum::kAutomation, 0xE003, 0x01, Actions::ActionStateEnum::kInactive, + false); + +// --------------------------------------------------------------------------- +// +// POWER SOURCE ENDPOINT: contains the following clusters: +// - Power Source +// - Descriptor +// - Bridged Device Basic + +DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(powerSourceAttrs) +DECLARE_DYNAMIC_ATTRIBUTE(ZCL_POWER_SOURCE_BAT_CHARGE_LEVEL_ATTRIBUTE_ID, ENUM8, 1, 0), + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_POWER_SOURCE_ORDER_ATTRIBUTE_ID, INT8U, 1, 0), + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_POWER_SOURCE_STATUS_ATTRIBUTE_ID, ENUM8, 1, 0), + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_POWER_SOURCE_DESCRIPTION_ATTRIBUTE_ID, CHAR_STRING, 32, 0), DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); + +DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedPowerSourceClusters) +DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, descriptorAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, bridgedDeviceBasicAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_POWER_SOURCE_CLUSTER_ID, powerSourceAttrs, nullptr, nullptr), DECLARE_DYNAMIC_CLUSTER_LIST_END; + +DECLARE_DYNAMIC_ENDPOINT(bridgedPowerSourceEndpoint, bridgedPowerSourceClusters); + +DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(tempSensorAttrs) +DECLARE_DYNAMIC_ATTRIBUTE(ZCL_TEMP_MEASURED_VALUE_ATTRIBUTE_ID, INT16S, 2, 0), /* Measured Value */ + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_TEMP_MIN_MEASURED_VALUE_ATTRIBUTE_ID, INT16S, 2, 0), /* Min Measured Value */ + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_TEMP_MAX_MEASURED_VALUE_ATTRIBUTE_ID, INT16S, 2, 0), /* Max Measured Value */ + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */ + DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); + +// --------------------------------------------------------------------------- +// +// TEMPERATURE SENSOR ENDPOINT: contains the following clusters: +// - Temperature measurement +// - Descriptor +// - Bridged Device Basic +DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedTempSensorClusters) +DECLARE_DYNAMIC_CLUSTER(ZCL_TEMP_MEASUREMENT_CLUSTER_ID, tempSensorAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, descriptorAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, bridgedDeviceBasicAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER_LIST_END; + +// Declare Bridged Light endpoint +DECLARE_DYNAMIC_ENDPOINT(bridgedTempSensorEndpoint, bridgedTempSensorClusters); +DataVersion gTempSensor1DataVersions[ArraySize(bridgedTempSensorClusters)]; +DataVersion gTempSensor2DataVersions[ArraySize(bridgedTempSensorClusters)]; + +// --------------------------------------------------------------------------- +// +// COMPOSED DEVICE ENDPOINT: contains the following clusters: +// - Descriptor +// - Bridged Device Basic -int AddDeviceEndpoint(Device * dev) +// Composed Device Configuration +DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(bridgedComposedDeviceClusters) +DECLARE_DYNAMIC_CLUSTER(ZCL_DESCRIPTOR_CLUSTER_ID, descriptorAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER(ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID, bridgedDeviceBasicAttrs, nullptr, nullptr), + DECLARE_DYNAMIC_CLUSTER_LIST_END; + +DECLARE_DYNAMIC_ENDPOINT(bridgedComposedDeviceEndpoint, bridgedComposedDeviceClusters); +DataVersion gComposedDeviceDataVersions[ArraySize(bridgedComposedDeviceClusters)]; +DataVersion gComposedTempSensor1DataVersions[ArraySize(bridgedTempSensorClusters)]; +DataVersion gComposedTempSensor2DataVersions[ArraySize(bridgedTempSensorClusters)]; +DataVersion gComposedPowerSourceDataVersions[ArraySize(bridgedPowerSourceClusters)]; + +} // namespace + +// REVISION DEFINITIONS: +// ================================================================================= + +#define ZCL_DESCRIPTOR_CLUSTER_REVISION (1u) +#define ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_REVISION (1u) +#define ZCL_BRIDGED_DEVICE_BASIC_FEATURE_MAP (0u) +#define ZCL_FIXED_LABEL_CLUSTER_REVISION (1u) +#define ZCL_ON_OFF_CLUSTER_REVISION (4u) +#define ZCL_TEMPERATURE_SENSOR_CLUSTER_REVISION (1u) +#define ZCL_TEMPERATURE_SENSOR_FEATURE_MAP (0u) +#define ZCL_POWER_SOURCE_CLUSTER_REVISION (1u) + +// --------------------------------------------------------------------------- + +int AddDeviceEndpoint(Device * dev, EmberAfEndpointType * ep, const Span & deviceTypeList, + const Span & dataVersionStorage, chip::EndpointId parentEndpointId = chip::kInvalidEndpointId) { uint8_t index = 0; while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) @@ -104,9 +273,11 @@ int AddDeviceEndpoint(Device * dev) while (1) { // Todo: Update this to schedule the work rather than use this lock + DeviceLayer::StackLock lock; dev->SetEndpointId(gCurrentEndpointId); + dev->SetParentEndpointId(parentEndpointId); ret = - emberAfSetDynamicEndpoint(index, gCurrentEndpointId, dev->endpointType(), dev->versions(), dev->deviceTypes()); + emberAfSetDynamicEndpoint(index, gCurrentEndpointId, ep, dataVersionStorage, deviceTypeList, parentEndpointId); if (ret == EMBER_ZCL_STATUS_SUCCESS) { ChipLogProgress(DeviceLayer, "Added device %s to dynamic endpoint %d (index=%d)", dev->GetName(), @@ -115,8 +286,6 @@ int AddDeviceEndpoint(Device * dev) } if (ret != EMBER_ZCL_STATUS_DUPLICATE_EXISTS) { - ChipLogProgress(DeviceLayer, "Failed to add dynamic endpoint: %d!", ret); - gDevices[index] = nullptr; return -1; } // Handle wrap condition @@ -154,41 +323,684 @@ int RemoveDeviceEndpoint(Device * dev) return -1; } -Room * FindRoom(const std::string & name) +std::vector GetEndpointListInfo(chip::EndpointId parentId) { - for (auto & room : gRooms) + std::vector infoList; + + for (auto room : gRooms) { - if (room.GetName() == name) - return &room; + if (room->getIsVisible()) + { + EndpointListInfo info(room->getEndpointListId(), room->getName(), room->getType()); + int index = 0; + while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) + { + if ((gDevices[index] != nullptr) && (gDevices[index]->GetParentEndpointId() == parentId)) + { + std::string location; + if (room->getType() == Actions::EndpointListTypeEnum::kZone) + { + location = gDevices[index]->GetZone(); + } + else + { + location = gDevices[index]->GetLocation(); + } + if (room->getName().compare(location) == 0) + { + info.AddEndpointId(gDevices[index]->GetEndpointId()); + } + } + index++; + } + if (info.GetEndpointListSize() > 0) + { + infoList.push_back(info); + } + } } - return nullptr; + + return infoList; +} + +std::vector GetActionListInfo(chip::EndpointId parentId) +{ + return gActions; +} + +namespace { +void CallReportingCallback(intptr_t closure) +{ + auto path = reinterpret_cast(closure); + MatterReportingAttributeChangeCallback(*path); + Platform::Delete(path); +} + +void ScheduleReportingCallback(Device * dev, ClusterId cluster, AttributeId attribute) +{ + auto * path = Platform::New(dev->GetEndpointId(), cluster, attribute); + PlatformMgr().ScheduleWork(CallReportingCallback, reinterpret_cast(path)); +} +} // anonymous namespace + +void HandleDeviceStatusChanged(Device * dev, Device::Changed_t itemChangedMask) +{ + if (itemChangedMask & Device::kChanged_Reachable) + { + ScheduleReportingCallback(dev, BridgedDeviceBasic::Id, BridgedDeviceBasic::Attributes::Reachable::Id); + } + + if (itemChangedMask & Device::kChanged_Name) + { + ScheduleReportingCallback(dev, BridgedDeviceBasic::Id, BridgedDeviceBasic::Attributes::NodeLabel::Id); + } +} + +void HandleDeviceOnOffStatusChanged(DeviceOnOff * dev, DeviceOnOff::Changed_t itemChangedMask) +{ + if (itemChangedMask & (DeviceOnOff::kChanged_Reachable | DeviceOnOff::kChanged_Name | DeviceOnOff::kChanged_Location)) + { + HandleDeviceStatusChanged(static_cast(dev), (Device::Changed_t) itemChangedMask); + } + + if (itemChangedMask & DeviceOnOff::kChanged_OnOff) + { + ScheduleReportingCallback(dev, OnOff::Id, OnOff::Attributes::OnOff::Id); + } +} + +void HandleDevicePowerSourceStatusChanged(DevicePowerSource * dev, DevicePowerSource::Changed_t itemChangedMask) +{ + using namespace app::Clusters; + if (itemChangedMask & + (DevicePowerSource::kChanged_Reachable | DevicePowerSource::kChanged_Name | DevicePowerSource::kChanged_Location)) + { + HandleDeviceStatusChanged(static_cast(dev), (Device::Changed_t) itemChangedMask); + } + + if (itemChangedMask & DevicePowerSource::kChanged_BatLevel) + { + uint8_t batChargeLevel = dev->GetBatChargeLevel(); + MatterReportingAttributeChangeCallback(dev->GetEndpointId(), PowerSource::Id, PowerSource::Attributes::BatChargeLevel::Id, + ZCL_INT8U_ATTRIBUTE_TYPE, &batChargeLevel); + } + + if (itemChangedMask & DevicePowerSource::kChanged_Description) + { + MatterReportingAttributeChangeCallback(dev->GetEndpointId(), PowerSource::Id, PowerSource::Attributes::Description::Id); + } +} + +void HandleDeviceTempSensorStatusChanged(DeviceTempSensor * dev, DeviceTempSensor::Changed_t itemChangedMask) +{ + if (itemChangedMask & + (DeviceTempSensor::kChanged_Reachable | DeviceTempSensor::kChanged_Name | DeviceTempSensor::kChanged_Location)) + { + HandleDeviceStatusChanged(static_cast(dev), (Device::Changed_t) itemChangedMask); + } + if (itemChangedMask & DeviceTempSensor::kChanged_MeasurementValue) + { + ScheduleReportingCallback(dev, TemperatureMeasurement::Id, TemperatureMeasurement::Attributes::MeasuredValue::Id); + } +} + +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)) + { + MutableByteSpan zclNameSpan(buffer, maxReadLength); + MakeZclCharString(zclNameSpan, dev->GetName()); + } + else if ((attributeId == ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID) && (maxReadLength == 2)) + { + *buffer = (uint16_t) ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_REVISION; + } + else if ((attributeId == ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID) && (maxReadLength == 4)) + { + *buffer = (uint32_t) ZCL_BRIDGED_DEVICE_BASIC_FEATURE_MAP; + } + 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; } -chip::Span GetActionListInfo(chip::EndpointId parentId) +EmberAfStatus HandleWriteOnOffAttribute(DeviceOnOff * dev, chip::AttributeId attributeId, uint8_t * buffer) { - return chip::Span(); + 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; } -void ApplicationInit() +EmberAfStatus HandleReadPowerSourceAttribute(DevicePowerSource * dev, chip::AttributeId attributeId, uint8_t * buffer, + uint16_t maxReadLength) { -#ifdef PW_RPC_ENABLED - chip::rpc::Init(); + using namespace app::Clusters; + if ((attributeId == PowerSource::Attributes::BatChargeLevel::Id) && (maxReadLength == 1)) + { + *buffer = dev->GetBatChargeLevel(); + } + else if ((attributeId == PowerSource::Attributes::Order::Id) && (maxReadLength == 1)) + { + *buffer = dev->GetOrder(); + } + else if ((attributeId == PowerSource::Attributes::Status::Id) && (maxReadLength == 1)) + { + *buffer = dev->GetStatus(); + } + else if ((attributeId == PowerSource::Attributes::Description::Id) && (maxReadLength == 32)) + { + MutableByteSpan zclDescpitionSpan(buffer, maxReadLength); + MakeZclCharString(zclDescpitionSpan, dev->GetDescription().c_str()); + } + else if ((attributeId == PowerSource::Attributes::ClusterRevision::Id) && (maxReadLength == 2)) + { + uint16_t rev = ZCL_POWER_SOURCE_CLUSTER_REVISION; + memcpy(buffer, &rev, sizeof(rev)); + } + else if ((attributeId == PowerSource::Attributes::FeatureMap::Id) && (maxReadLength == 4)) + { + uint32_t featureMap = dev->GetFeatureMap(); + memcpy(buffer, &featureMap, sizeof(featureMap)); + } + else + { + return EMBER_ZCL_STATUS_FAILURE; + } - pw::rpc::system_server::Server().RegisterService(bridge_service); + return EMBER_ZCL_STATUS_SUCCESS; +} + +EmberAfStatus HandleReadTempMeasurementAttribute(DeviceTempSensor * dev, chip::AttributeId attributeId, uint8_t * buffer, + uint16_t maxReadLength) +{ + if ((attributeId == ZCL_TEMP_MEASURED_VALUE_ATTRIBUTE_ID) && (maxReadLength == 2)) + { + int16_t measuredValue = dev->GetMeasuredValue(); + memcpy(buffer, &measuredValue, sizeof(measuredValue)); + } + else if ((attributeId == ZCL_TEMP_MIN_MEASURED_VALUE_ATTRIBUTE_ID) && (maxReadLength == 2)) + { + int16_t minValue = dev->mMin; + memcpy(buffer, &minValue, sizeof(minValue)); + } + else if ((attributeId == ZCL_TEMP_MAX_MEASURED_VALUE_ATTRIBUTE_ID) && (maxReadLength == 2)) + { + int16_t maxValue = dev->mMax; + memcpy(buffer, &maxValue, sizeof(maxValue)); + } + else if ((attributeId == ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID) && (maxReadLength == 4)) + { + uint32_t featureMap = ZCL_TEMPERATURE_SENSOR_FEATURE_MAP; + memcpy(buffer, &featureMap, sizeof(featureMap)); + } + else if ((attributeId == ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID) && (maxReadLength == 2)) + { + uint16_t clusterRevision = ZCL_TEMPERATURE_SENSOR_CLUSTER_REVISION; + memcpy(buffer, &clusterRevision, sizeof(clusterRevision)); + } + 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] != nullptr)) + { + Device * dev = gDevices[endpointIndex]; + + if (clusterId == ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID) + { + ret = HandleReadBridgedDeviceBasicAttribute(dev, attributeMetadata->attributeId, buffer, maxReadLength); + } + else if (clusterId == ZCL_ON_OFF_CLUSTER_ID) + { + ret = HandleReadOnOffAttribute(static_cast(dev), attributeMetadata->attributeId, buffer, maxReadLength); + } + else if (clusterId == chip::app::Clusters::PowerSource::Id) + { + ret = HandleReadPowerSourceAttribute(static_cast(dev), attributeMetadata->attributeId, buffer, + maxReadLength); + } + else if (clusterId == TemperatureMeasurement::Id) + { + ret = HandleReadTempMeasurementAttribute(static_cast(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(dev), attributeMetadata->attributeId, buffer); + } + } + + return ret; +} + +void runOnOffRoomAction(Room * room, bool actionOn, EndpointId endpointId, uint16_t actionID, uint32_t invokeID, bool hasInvokeID) +{ + if (hasInvokeID) + { + Actions::Events::StateChanged::Type event{ actionID, invokeID, Actions::ActionStateEnum::kActive }; + EventNumber eventNumber; + chip::app::LogEvent(event, endpointId, eventNumber); + } + + // Check and run the action for ActionLight1 - ActionLight4 + if (room->getName().compare(ActionLight1.GetLocation()) == 0) + { + ActionLight1.SetOnOff(actionOn); + } + if (room->getName().compare(ActionLight2.GetLocation()) == 0) + { + ActionLight2.SetOnOff(actionOn); + } + if (room->getName().compare(ActionLight3.GetLocation()) == 0) + { + ActionLight3.SetOnOff(actionOn); + } + if (room->getName().compare(ActionLight4.GetLocation()) == 0) + { + ActionLight4.SetOnOff(actionOn); + } + + if (hasInvokeID) + { + Actions::Events::StateChanged::Type event{ actionID, invokeID, Actions::ActionStateEnum::kInactive }; + EventNumber eventNumber; + chip::app::LogEvent(event, endpointId, eventNumber); + } +} + +bool emberAfActionsClusterInstantActionCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, + const Actions::Commands::InstantAction::DecodableType & commandData) +{ + bool hasInvokeID = false; + uint32_t invokeID = 0; + EndpointId endpointID = commandPath.mEndpointId; + auto & actionID = commandData.actionID; + + if (commandData.invokeID.HasValue()) + { + hasInvokeID = true; + invokeID = commandData.invokeID.Value(); + } + + if (actionID == action1.getActionId() && action1.getIsVisible()) + { + // Turn On Lights in Room 1 + runOnOffRoomAction(&room1, true, endpointID, actionID, invokeID, hasInvokeID); + commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::Success); + return true; + } + if (actionID == action2.getActionId() && action2.getIsVisible()) + { + // Turn On Lights in Room 2 + runOnOffRoomAction(&room2, true, endpointID, actionID, invokeID, hasInvokeID); + commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::Success); + return true; + } + if (actionID == action3.getActionId() && action3.getIsVisible()) + { + // Turn Off Lights in Room 1 + runOnOffRoomAction(&room1, false, endpointID, actionID, invokeID, hasInvokeID); + commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::Success); + return true; + } + + commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::NotFound); + return true; +} + +void ApplicationInit() {} + +const EmberAfDeviceType gBridgedOnOffDeviceTypes[] = { { DEVICE_TYPE_LO_ON_OFF_LIGHT, DEVICE_VERSION_DEFAULT }, + { DEVICE_TYPE_BRIDGED_NODE, DEVICE_VERSION_DEFAULT } }; + +const EmberAfDeviceType gBridgedComposedDeviceTypes[] = { { DEVICE_TYPE_BRIDGED_NODE, DEVICE_VERSION_DEFAULT } }; + +const EmberAfDeviceType gComposedTempSensorDeviceTypes[] = { { DEVICE_TYPE_TEMP_SENSOR, DEVICE_VERSION_DEFAULT } }; + +const EmberAfDeviceType gComposedPowerSourceDeviceTypes[] = { { DEVICE_TYPE_POWER_SOURCE, DEVICE_VERSION_DEFAULT } }; + +const EmberAfDeviceType gBridgedTempSensorDeviceTypes[] = { { DEVICE_TYPE_TEMP_SENSOR, DEVICE_VERSION_DEFAULT }, + { DEVICE_TYPE_BRIDGED_NODE, DEVICE_VERSION_DEFAULT } }; + +#define POLL_INTERVAL_MS (100) +uint8_t poll_prescale = 0; + +bool kbhit() +{ + int byteswaiting; + ioctl(0, FIONREAD, &byteswaiting); + return byteswaiting > 0; +} + +const int16_t oneDegree = 100; + +void * bridge_polling_thread(void * context) +{ + bool light1_added = true; + bool light2_added = false; + while (1) + { + if (kbhit()) + { + int ch = getchar(); + + // Commands used for the actions bridge test plan. + if (ch == '2' && light2_added == false) + { + // TC-BR-2 step 2, Add Light2 + AddDeviceEndpoint(&Light2, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), + Span(gLight2DataVersions), 1); + light2_added = true; + } + else if (ch == '4' && light1_added == true) + { + // TC-BR-2 step 4, Remove Light 1 + RemoveDeviceEndpoint(&Light1); + light1_added = false; + } + if (ch == '5' && light1_added == false) + { + // TC-BR-2 step 5, Add Light 1 back + AddDeviceEndpoint(&Light1, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), + Span(gLight1DataVersions), 1); + light1_added = true; + } + if (ch == 'b') + { + // TC-BR-3 step 1b, rename lights + if (light1_added) + { + Light1.SetName("Light 1b"); + } + if (light2_added) + { + Light2.SetName("Light 2b"); + } + } + if (ch == 'c') + { + // TC-BR-3 step 2c, change the state of the lights + if (light1_added) + { + Light1.Toggle(); + } + if (light2_added) + { + Light2.Toggle(); + } + } + if (ch == 't') + { + // TC-BR-4 step 1g, change the state of the temperature sensors + TempSensor1.SetMeasuredValue(static_cast(TempSensor1.GetMeasuredValue() + oneDegree)); + TempSensor2.SetMeasuredValue(static_cast(TempSensor2.GetMeasuredValue() + oneDegree)); + ComposedTempSensor1.SetMeasuredValue(static_cast(ComposedTempSensor1.GetMeasuredValue() + oneDegree)); + ComposedTempSensor2.SetMeasuredValue(static_cast(ComposedTempSensor2.GetMeasuredValue() + oneDegree)); + } + + // Commands used for the actions cluster test plan. + if (ch == 'r') + { + // TC-ACT-2.2 step 2c, rename "Room 1" + room1.setName("Room 1 renamed"); + ActionLight1.SetLocation(room1.getName()); + ActionLight2.SetLocation(room1.getName()); + } + if (ch == 'f') + { + // TC-ACT-2.2 step 2f, move "Action Light 3" from "Room 2" to "Room 1" + ActionLight3.SetLocation(room1.getName()); + } + if (ch == 'i') + { + // TC-ACT-2.2 step 2i, remove "Room 2" (make it not visible in the endpoint list), do not remove the lights + room2.setIsVisible(false); + } + if (ch == 'l') + { + // TC-ACT-2.2 step 2l, add a new "Zone 3" and add "Action Light 2" to the new zone + room3.setIsVisible(true); + ActionLight2.SetZone("Zone 3"); + } + if (ch == 'm') + { + // TC-ACT-2.2 step 3c, rename "Turn on Room 1 lights" + action1.setName("Turn On Room 1"); + } + if (ch == 'n') + { + // TC-ACT-2.2 step 3f, remove "Turn on Room 2 lights" + action2.setIsVisible(false); + } + if (ch == 'o') + { + // TC-ACT-2.2 step 3i, add "Turn off Room 1 renamed lights" + action3.setIsVisible(true); + } + + // Commands used for the Bridged Device Basic Information test plan + if (ch == 'u') + { + // TC-BRBINFO-2.2 step 2 "Set reachable to false" + TempSensor1.SetReachable(false); + } + if (ch == 'v') + { + // TC-BRBINFO-2.2 step 2 "Set reachable to true" + TempSensor1.SetReachable(true); + } + continue; + } + + // Sleep to avoid tight loop reading commands + usleep(POLL_INTERVAL_MS * 1000); + } + + return nullptr; +} + +int main(int argc, char * argv[]) +{ + // Clear out the device database + memset(gDevices, 0, sizeof(gDevices)); + + // Setup Mock Devices + Light1.SetReachable(true); + Light2.SetReachable(true); + + Light1.SetChangeCallback(&HandleDeviceOnOffStatusChanged); + Light2.SetChangeCallback(&HandleDeviceOnOffStatusChanged); + + TempSensor1.SetReachable(true); + TempSensor1.SetReachable(true); + + TempSensor1.SetChangeCallback(&HandleDeviceTempSensorStatusChanged); + TempSensor2.SetChangeCallback(&HandleDeviceTempSensorStatusChanged); + + // Setup devices for action cluster tests + ActionLight1.SetReachable(true); + ActionLight2.SetReachable(true); + ActionLight3.SetReachable(true); + ActionLight4.SetReachable(true); + + ActionLight1.SetChangeCallback(&HandleDeviceOnOffStatusChanged); + ActionLight2.SetChangeCallback(&HandleDeviceOnOffStatusChanged); + ActionLight3.SetChangeCallback(&HandleDeviceOnOffStatusChanged); + ActionLight4.SetChangeCallback(&HandleDeviceOnOffStatusChanged); + + // Setup composed device with two temperature sensors and a power source + ComposedDevice ComposedDevice("Composed Device", "Bedroom"); + DevicePowerSource ComposedPowerSource("Composed Power Source", "Bedroom", EMBER_AF_POWER_SOURCE_FEATURE_BATTERY); + + ComposedDevice.SetReachable(true); + ComposedTempSensor1.SetReachable(true); + ComposedTempSensor2.SetReachable(true); + ComposedPowerSource.SetReachable(true); + ComposedPowerSource.SetBatChargeLevel(58); + + ComposedTempSensor1.SetChangeCallback(&HandleDeviceTempSensorStatusChanged); + ComposedTempSensor2.SetChangeCallback(&HandleDeviceTempSensorStatusChanged); + ComposedPowerSource.SetChangeCallback(&HandleDevicePowerSourceStatusChanged); + + if (ChipLinuxAppInit(argc, argv) != 0) + { + return -1; + } + + // Init Data Model and CHIP App Server + static chip::CommonCaseDeviceServerInitParams initParams; + (void) initParams.InitializeStaticResourcesBeforeServerInit(); + +#if CHIP_DEVICE_ENABLE_PORT_PARAMS + // use a different service port to make testing possible with other sample devices running on same host + initParams.operationalServicePort = LinuxDeviceOptions::GetInstance().securedDevicePort; #endif - clusters::BridgeRegisterAllAttributeOverrides(); + initParams.interfaceId = LinuxDeviceOptions::GetInstance().interfaceId; + chip::Server::GetInstance().Init(initParams); + + // 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( static_cast(emberAfEndpointFromIndex(static_cast(emberAfFixedEndpointCount() - 1))) + 1); gCurrentEndpointId = gFirstDynamicEndpointId; - StartUserInput(); -} -int main(int argc, char * argv[]) -{ - VerifyOrDie(ChipLinuxAppInit(argc, argv) == 0); + // 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(emberAfFixedEndpointCount() - 1)), false); + + // Add light 1 -> will be mapped to ZCL endpoints 3 + AddDeviceEndpoint(&Light1, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), + Span(gLight1DataVersions), 1); + + // Add Temperature Sensor devices --> will be mapped to endpoints 4,5 + AddDeviceEndpoint(&TempSensor1, &bridgedTempSensorEndpoint, Span(gBridgedTempSensorDeviceTypes), + Span(gTempSensor1DataVersions), 1); + AddDeviceEndpoint(&TempSensor2, &bridgedTempSensorEndpoint, Span(gBridgedTempSensorDeviceTypes), + Span(gTempSensor2DataVersions), 1); + + // Add composed Device with two temperature sensors and a power source + AddDeviceEndpoint(&ComposedDevice, &bridgedComposedDeviceEndpoint, Span(gBridgedComposedDeviceTypes), + Span(gComposedDeviceDataVersions), 1); + AddDeviceEndpoint(&ComposedTempSensor1, &bridgedTempSensorEndpoint, + Span(gComposedTempSensorDeviceTypes), + Span(gComposedTempSensor1DataVersions), ComposedDevice.GetEndpointId()); + AddDeviceEndpoint(&ComposedTempSensor2, &bridgedTempSensorEndpoint, + Span(gComposedTempSensorDeviceTypes), + Span(gComposedTempSensor2DataVersions), ComposedDevice.GetEndpointId()); + AddDeviceEndpoint(&ComposedPowerSource, &bridgedPowerSourceEndpoint, + Span(gComposedPowerSourceDeviceTypes), + Span(gComposedPowerSourceDataVersions), ComposedDevice.GetEndpointId()); + + // Add 4 lights for the Action Clusters tests + AddDeviceEndpoint(&ActionLight1, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), + Span(gActionLight1DataVersions), 1); + AddDeviceEndpoint(&ActionLight2, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), + Span(gActionLight2DataVersions), 1); + AddDeviceEndpoint(&ActionLight3, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), + Span(gActionLight3DataVersions), 1); + AddDeviceEndpoint(&ActionLight4, &bridgedLightEndpoint, Span(gBridgedOnOffDeviceTypes), + Span(gActionLight4DataVersions), 1); + gRooms.push_back(&room1); + gRooms.push_back(&room2); + gRooms.push_back(&room3); + + gActions.push_back(&action1); + gActions.push_back(&action2); + gActions.push_back(&action3); + + { + pthread_t poll_thread; + int res = pthread_create(&poll_thread, nullptr, bridge_polling_thread, nullptr); + if (res) + { + printf("Error creating polling thread: %d\n", res); + exit(1); + } + } + + // Run CHIP + + chip::DeviceLayer::PlatformMgr().RunEventLoop(); - ChipLinuxAppMainLoop(); return 0; } diff --git a/examples/dynamic-bridge-app/bridge-common/BUILD.gn b/examples/dynamic-bridge-app/bridge-common/BUILD.gn new file mode 100644 index 00000000000000..a04cd6ec8b2010 --- /dev/null +++ b/examples/dynamic-bridge-app/bridge-common/BUILD.gn @@ -0,0 +1,40 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# 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. + +import("//build_overrides/chip.gni") + +import("${chip_root}/src/app/chip_data_model.gni") +import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") + +chip_data_model("dynamic-bridge-common") { + zap_file = "bridge-app.zap" + + zap_pregenerated_dir = "${chip_root}/zzz_generated/bridge-app/zap-generated" + is_server = true + + # TODO: the definition of DYNAMIC_ENDPOINT_COUNT needs find a common home! + cflags = [ "-DDYNAMIC_ENDPOINT_COUNT=16" ] +} + +if (chip_enable_pw_rpc) { + import("//build_overrides/pigweed.gni") + import("$dir_pw_protobuf_compiler/proto.gni") + + pw_proto_library("bridge_service") { + sources = [ "protos/bridge_service.proto" ] + inputs = [ "protos/bridge_service.options" ] + strip_prefix = "protos" + prefix = "bridge_service" + } +} diff --git a/examples/dynamic-bridge-app/bridge-common/bridge-app.matter b/examples/dynamic-bridge-app/bridge-common/bridge-app.matter new file mode 100644 index 00000000000000..4ba029df533fff --- /dev/null +++ b/examples/dynamic-bridge-app/bridge-common/bridge-app.matter @@ -0,0 +1,1826 @@ +// This IDL was generated automatically by ZAP. +// It is for view/code review purposes only. + +server cluster Identify = 3 { + enum IdentifyEffectIdentifier : ENUM8 { + kBlink = 0; + kBreathe = 1; + kOkay = 2; + kChannelChange = 11; + kFinishEffect = 254; + kStopEffect = 255; + } + + enum IdentifyEffectVariant : ENUM8 { + kDefault = 0; + } + + enum IdentifyIdentifyType : ENUM8 { + kNone = 0; + kVisibleLight = 1; + kVisibleLED = 2; + kAudibleBeep = 3; + kDisplay = 4; + kActuator = 5; + } + + attribute int16u identifyTime = 0; + readonly attribute enum8 identifyType = 1; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct IdentifyRequest { + INT16U identifyTime = 0; + } + + request struct TriggerEffectRequest { + IdentifyEffectIdentifier effectIdentifier = 0; + IdentifyEffectVariant effectVariant = 1; + } + + command access(invoke: manage) Identify(IdentifyRequest): DefaultSuccess = 0; + command access(invoke: manage) TriggerEffect(TriggerEffectRequest): DefaultSuccess = 64; +} + +server cluster OnOff = 6 { + enum OnOffDelayedAllOffEffectVariant : ENUM8 { + kFadeToOffIn0p8Seconds = 0; + kNoFade = 1; + k50PercentDimDownIn0p8SecondsThenFadeToOffIn12Seconds = 2; + } + + enum OnOffDyingLightEffectVariant : ENUM8 { + k20PercenterDimUpIn0p5SecondsThenFadeToOffIn1Second = 0; + } + + enum OnOffEffectIdentifier : ENUM8 { + kDelayedAllOff = 0; + kDyingLight = 1; + } + + enum OnOffStartUpOnOff : ENUM8 { + kOff = 0; + kOn = 1; + kTogglePreviousOnOff = 2; + } + + bitmap OnOffControl : BITMAP8 { + kAcceptOnlyWhenOn = 0x1; + } + + bitmap OnOffFeature : BITMAP32 { + kLighting = 0x1; + } + + bitmap SceneFeatures : BITMAP32 { + kSceneNames = 0x1; + } + + readonly attribute boolean onOff = 0; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + command Off(): DefaultSuccess = 0; + command On(): DefaultSuccess = 1; + command Toggle(): DefaultSuccess = 2; +} + +server cluster LevelControl = 8 { + enum MoveMode : ENUM8 { + kUp = 0; + kDown = 1; + } + + enum StepMode : ENUM8 { + kUp = 0; + kDown = 1; + } + + bitmap LevelControlFeature : BITMAP32 { + kOnOff = 0x1; + kLighting = 0x2; + kFrequency = 0x4; + } + + readonly attribute nullable int8u currentLevel = 0; + readonly attribute int16u remainingTime = 1; + readonly attribute int8u minLevel = 2; + readonly attribute int8u maxLevel = 3; + readonly attribute int16u currentFrequency = 4; + readonly attribute int16u minFrequency = 5; + readonly attribute int16u maxFrequency = 6; + attribute bitmap8 options = 15; + attribute int16u onOffTransitionTime = 16; + attribute nullable int8u onLevel = 17; + attribute nullable int16u onTransitionTime = 18; + attribute nullable int16u offTransitionTime = 19; + attribute nullable int8u defaultMoveRate = 20; + attribute access(write: manage) nullable int8u startUpCurrentLevel = 16384; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct MoveToLevelRequest { + INT8U level = 0; + nullable INT16U transitionTime = 1; + BITMAP8 optionsMask = 2; + BITMAP8 optionsOverride = 3; + } + + request struct MoveRequest { + MoveMode moveMode = 0; + nullable INT8U rate = 1; + BITMAP8 optionsMask = 2; + BITMAP8 optionsOverride = 3; + } + + request struct StepRequest { + StepMode stepMode = 0; + INT8U stepSize = 1; + nullable INT16U transitionTime = 2; + BITMAP8 optionsMask = 3; + BITMAP8 optionsOverride = 4; + } + + request struct StopRequest { + BITMAP8 optionsMask = 0; + BITMAP8 optionsOverride = 1; + } + + request struct MoveToLevelWithOnOffRequest { + INT8U level = 0; + nullable INT16U transitionTime = 1; + BITMAP8 optionsMask = 2; + BITMAP8 optionsOverride = 3; + } + + request struct MoveWithOnOffRequest { + MoveMode moveMode = 0; + nullable INT8U rate = 1; + BITMAP8 optionsMask = 2; + BITMAP8 optionsOverride = 3; + } + + request struct StepWithOnOffRequest { + StepMode stepMode = 0; + INT8U stepSize = 1; + nullable INT16U transitionTime = 2; + BITMAP8 optionsMask = 3; + BITMAP8 optionsOverride = 4; + } + + request struct StopWithOnOffRequest { + BITMAP8 optionsMask = 0; + BITMAP8 optionsOverride = 1; + } + + command MoveToLevel(MoveToLevelRequest): DefaultSuccess = 0; + command Move(MoveRequest): DefaultSuccess = 1; + command Step(StepRequest): DefaultSuccess = 2; + command Stop(StopRequest): DefaultSuccess = 3; + command MoveToLevelWithOnOff(MoveToLevelWithOnOffRequest): DefaultSuccess = 4; + command MoveWithOnOff(MoveWithOnOffRequest): DefaultSuccess = 5; + command StepWithOnOff(StepWithOnOffRequest): DefaultSuccess = 6; + command StopWithOnOff(StopWithOnOffRequest): DefaultSuccess = 7; +} + +server cluster Descriptor = 29 { + struct DeviceType { + devtype_id type = 0; + int16u revision = 1; + } + + readonly attribute DeviceType deviceList[] = 0; + readonly attribute CLUSTER_ID serverList[] = 1; + readonly attribute CLUSTER_ID clientList[] = 2; + readonly attribute ENDPOINT_NO partsList[] = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +client cluster Binding = 30 { + struct TargetStruct { + optional node_id node = 1; + optional group_id group = 2; + optional endpoint_no endpoint = 3; + optional cluster_id cluster = 4; + fabric_idx fabricIndex = 254; + } + + attribute TargetStruct binding[] = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +client cluster AccessControl = 31 { + enum AuthMode : ENUM8 { + kPase = 1; + kCase = 2; + kGroup = 3; + } + + enum ChangeTypeEnum : ENUM8 { + kChanged = 0; + kAdded = 1; + kRemoved = 2; + } + + enum Privilege : ENUM8 { + kView = 1; + kProxyView = 2; + kOperate = 3; + kManage = 4; + kAdminister = 5; + } + + struct AccessControlEntry { + Privilege privilege = 1; + AuthMode authMode = 2; + nullable int64u subjects[] = 3; + nullable Target targets[] = 4; + fabric_idx fabricIndex = 254; + } + + struct Target { + nullable cluster_id cluster = 0; + nullable endpoint_no endpoint = 1; + nullable devtype_id deviceType = 2; + } + + struct ExtensionEntry { + octet_string<128> data = 1; + fabric_idx fabricIndex = 254; + } + + info event access(read: administer) AccessControlEntryChanged = 0 { + nullable node_id adminNodeID = 1; + nullable INT16U adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable AccessControlEntry latestValue = 4; + fabric_idx fabricIndex = 254; + } + + info event access(read: administer) AccessControlExtensionChanged = 1 { + nullable node_id adminNodeID = 1; + nullable INT16U adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable ExtensionEntry latestValue = 4; + fabric_idx fabricIndex = 254; + } + + attribute access(read: administer, write: administer) AccessControlEntry acl[] = 0; + attribute access(read: administer, write: administer) ExtensionEntry extension[] = 1; + readonly attribute int16u subjectsPerAccessControlEntry = 2; + readonly attribute int16u targetsPerAccessControlEntry = 3; + readonly attribute int16u accessControlEntriesPerFabric = 4; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +server cluster AccessControl = 31 { + enum AuthMode : ENUM8 { + kPase = 1; + kCase = 2; + kGroup = 3; + } + + enum ChangeTypeEnum : ENUM8 { + kChanged = 0; + kAdded = 1; + kRemoved = 2; + } + + enum Privilege : ENUM8 { + kView = 1; + kProxyView = 2; + kOperate = 3; + kManage = 4; + kAdminister = 5; + } + + struct AccessControlEntry { + Privilege privilege = 1; + AuthMode authMode = 2; + nullable int64u subjects[] = 3; + nullable Target targets[] = 4; + fabric_idx fabricIndex = 254; + } + + struct Target { + nullable cluster_id cluster = 0; + nullable endpoint_no endpoint = 1; + nullable devtype_id deviceType = 2; + } + + struct ExtensionEntry { + octet_string<128> data = 1; + fabric_idx fabricIndex = 254; + } + + info event access(read: administer) AccessControlEntryChanged = 0 { + nullable node_id adminNodeID = 1; + nullable INT16U adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable AccessControlEntry latestValue = 4; + fabric_idx fabricIndex = 254; + } + + info event access(read: administer) AccessControlExtensionChanged = 1 { + nullable node_id adminNodeID = 1; + nullable INT16U adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable ExtensionEntry latestValue = 4; + fabric_idx fabricIndex = 254; + } + + attribute access(read: administer, write: administer) AccessControlEntry acl[] = 0; + attribute access(read: administer, write: administer) ExtensionEntry extension[] = 1; + readonly attribute int16u subjectsPerAccessControlEntry = 2; + readonly attribute int16u targetsPerAccessControlEntry = 3; + readonly attribute int16u accessControlEntriesPerFabric = 4; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +server cluster Actions = 37 { + enum ActionErrorEnum : ENUM8 { + kUnknown = 0; + kInterrupted = 1; + } + + enum ActionStateEnum : ENUM8 { + kInactive = 0; + kActive = 1; + kPaused = 2; + kDisabled = 3; + } + + enum ActionTypeEnum : ENUM8 { + kOther = 0; + kScene = 1; + kSequence = 2; + kAutomation = 3; + kException = 4; + kNotification = 5; + kAlarm = 6; + } + + enum EndpointListTypeEnum : ENUM8 { + kOther = 0; + kRoom = 1; + kZone = 2; + } + + bitmap CommandBits : BITMAP16 { + kInstantAction = 0x1; + kInstantActionWithTransition = 0x2; + kStartAction = 0x4; + kStartActionWithDuration = 0x8; + kStopAction = 0x10; + kPauseAction = 0x20; + kPauseActionWithDuration = 0x40; + kResumeAction = 0x80; + kEnableAction = 0x100; + kEnableActionWithDuration = 0x200; + kDisableAction = 0x400; + kDisableActionWithDuration = 0x800; + } + + struct ActionStruct { + int16u actionID = 0; + char_string<32> name = 1; + ActionTypeEnum type = 2; + int16u endpointListID = 3; + CommandBits supportedCommands = 4; + ActionStateEnum state = 5; + } + + struct EndpointListStruct { + int16u endpointListID = 0; + char_string<32> name = 1; + EndpointListTypeEnum type = 2; + endpoint_no endpoints[] = 3; + } + + info event StateChanged = 0 { + INT16U actionID = 0; + INT32U invokeID = 1; + ActionStateEnum newState = 2; + } + + info event ActionFailed = 1 { + INT16U actionID = 0; + INT32U invokeID = 1; + ActionStateEnum newState = 2; + ActionErrorEnum error = 3; + } + + readonly attribute ActionStruct actionList[] = 0; + readonly attribute EndpointListStruct endpointLists[] = 1; + readonly attribute long_char_string<512> setupURL = 2; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct InstantActionRequest { + INT16U actionID = 0; + optional INT32U invokeID = 1; + } + + command InstantAction(InstantActionRequest): DefaultSuccess = 0; +} + +server cluster Basic = 40 { + struct CapabilityMinimaStruct { + int16u caseSessionsPerFabric = 0; + int16u subscriptionsPerFabric = 1; + } + + critical event StartUp = 0 { + INT32U softwareVersion = 0; + } + + critical event ShutDown = 1 { + } + + info event Leave = 2 { + fabric_idx fabricIndex = 0; + } + + info event ReachableChanged = 3 { + boolean reachableNewValue = 0; + } + + readonly attribute int16u dataModelRevision = 0; + readonly attribute char_string<32> vendorName = 1; + readonly attribute vendor_id vendorID = 2; + readonly attribute char_string<32> productName = 3; + readonly attribute int16u productID = 4; + attribute access(write: manage) char_string<32> nodeLabel = 5; + attribute access(write: administer) char_string<2> location = 6; + readonly attribute int16u hardwareVersion = 7; + readonly attribute char_string<64> hardwareVersionString = 8; + readonly attribute int32u softwareVersion = 9; + readonly attribute char_string<64> softwareVersionString = 10; + readonly attribute char_string<16> manufacturingDate = 11; + readonly attribute char_string<32> partNumber = 12; + readonly attribute long_char_string<256> productURL = 13; + readonly attribute char_string<64> productLabel = 14; + readonly attribute char_string<32> serialNumber = 15; + attribute access(write: manage) boolean localConfigDisabled = 16; + readonly attribute boolean reachable = 17; + readonly attribute char_string<32> uniqueID = 18; + readonly attribute CapabilityMinimaStruct capabilityMinima = 19; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +server cluster LocalizationConfiguration = 43 { + attribute char_string<35> activeLocale = 0; + readonly attribute CHAR_STRING supportedLocales[] = 1; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +server cluster TimeFormatLocalization = 44 { + enum CalendarType : ENUM8 { + kBuddhist = 0; + kChinese = 1; + kCoptic = 2; + kEthiopian = 3; + kGregorian = 4; + kHebrew = 5; + kIndian = 6; + kIslamic = 7; + kJapanese = 8; + kKorean = 9; + kPersian = 10; + kTaiwanese = 11; + } + + enum HourFormat : ENUM8 { + k12hr = 0; + k24hr = 1; + } + + attribute HourFormat hourFormat = 0; + attribute CalendarType activeCalendarType = 1; + readonly attribute CalendarType supportedCalendarTypes[] = 2; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +server cluster UnitLocalization = 45 { + enum TempUnit : ENUM8 { + kFahrenheit = 0; + kCelsius = 1; + kKelvin = 2; + } + + bitmap UnitLocalizationFeature : BITMAP32 { + kTemperatureUnit = 0x1; + } + + attribute TempUnit temperatureUnit = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +server cluster GeneralCommissioning = 48 { + enum CommissioningError : ENUM8 { + kOk = 0; + kValueOutsideRange = 1; + kInvalidAuthentication = 2; + kNoFailSafe = 3; + kBusyWithOtherAdmin = 4; + } + + enum RegulatoryLocationType : ENUM8 { + kIndoor = 0; + kOutdoor = 1; + kIndoorOutdoor = 2; + } + + struct BasicCommissioningInfo { + int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; + } + + attribute access(write: administer) int64u breadcrumb = 0; + readonly attribute BasicCommissioningInfo basicCommissioningInfo = 1; + readonly attribute RegulatoryLocationType regulatoryConfig = 2; + readonly attribute RegulatoryLocationType locationCapability = 3; + readonly attribute boolean supportsConcurrentConnection = 4; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct ArmFailSafeRequest { + INT16U expiryLengthSeconds = 0; + INT64U breadcrumb = 1; + } + + request struct SetRegulatoryConfigRequest { + RegulatoryLocationType newRegulatoryConfig = 0; + CHAR_STRING countryCode = 1; + INT64U breadcrumb = 2; + } + + response struct ArmFailSafeResponse = 1 { + CommissioningError errorCode = 0; + CHAR_STRING debugText = 1; + } + + response struct SetRegulatoryConfigResponse = 3 { + CommissioningError errorCode = 0; + CHAR_STRING debugText = 1; + } + + response struct CommissioningCompleteResponse = 5 { + CommissioningError errorCode = 0; + CHAR_STRING debugText = 1; + } + + command access(invoke: administer) ArmFailSafe(ArmFailSafeRequest): ArmFailSafeResponse = 0; + command access(invoke: administer) SetRegulatoryConfig(SetRegulatoryConfigRequest): SetRegulatoryConfigResponse = 2; + fabric command access(invoke: administer) CommissioningComplete(): CommissioningCompleteResponse = 4; +} + +server cluster NetworkCommissioning = 49 { + enum NetworkCommissioningStatus : ENUM8 { + kSuccess = 0; + kOutOfRange = 1; + kBoundsExceeded = 2; + kNetworkIDNotFound = 3; + kDuplicateNetworkID = 4; + kNetworkNotFound = 5; + kRegulatoryError = 6; + kAuthFailure = 7; + kUnsupportedSecurity = 8; + kOtherConnectionFailure = 9; + kIPV6Failed = 10; + kIPBindFailed = 11; + kUnknownError = 12; + } + + enum WiFiBand : ENUM8 { + k2g4 = 0; + k3g65 = 1; + k5g = 2; + k6g = 3; + k60g = 4; + } + + bitmap NetworkCommissioningFeature : BITMAP32 { + kWiFiNetworkInterface = 0x1; + kThreadNetworkInterface = 0x2; + kEthernetNetworkInterface = 0x4; + } + + bitmap WiFiSecurity : BITMAP8 { + kUnencrypted = 0x1; + kWepPersonal = 0x2; + kWpaPersonal = 0x4; + kWpa2Personal = 0x8; + kWpa3Personal = 0x10; + } + + struct NetworkInfo { + octet_string<32> networkID = 0; + boolean connected = 1; + } + + struct WiFiInterfaceScanResult { + WiFiSecurity security = 0; + octet_string<32> ssid = 1; + octet_string<6> bssid = 2; + int16u channel = 3; + WiFiBand wiFiBand = 4; + int8s rssi = 5; + } + + struct ThreadInterfaceScanResult { + int16u panId = 0; + int64u extendedPanId = 1; + char_string<16> networkName = 2; + int16u channel = 3; + int8u version = 4; + octet_string<8> extendedAddress = 5; + int8s rssi = 6; + int8u lqi = 7; + } + + readonly attribute access(read: administer) int8u maxNetworks = 0; + readonly attribute access(read: administer) NetworkInfo networks[] = 1; + readonly attribute int8u scanMaxTimeSeconds = 2; + readonly attribute int8u connectMaxTimeSeconds = 3; + attribute access(write: administer) boolean interfaceEnabled = 4; + readonly attribute access(read: administer) nullable NetworkCommissioningStatus lastNetworkingStatus = 5; + readonly attribute access(read: administer) nullable octet_string<32> lastNetworkID = 6; + readonly attribute access(read: administer) nullable int32s lastConnectErrorValue = 7; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct ScanNetworksRequest { + optional nullable OCTET_STRING ssid = 0; + optional INT64U breadcrumb = 1; + } + + request struct AddOrUpdateWiFiNetworkRequest { + OCTET_STRING ssid = 0; + OCTET_STRING credentials = 1; + optional INT64U breadcrumb = 2; + } + + request struct AddOrUpdateThreadNetworkRequest { + OCTET_STRING operationalDataset = 0; + optional INT64U breadcrumb = 1; + } + + request struct RemoveNetworkRequest { + OCTET_STRING networkID = 0; + optional INT64U breadcrumb = 1; + } + + request struct ConnectNetworkRequest { + OCTET_STRING networkID = 0; + optional INT64U breadcrumb = 1; + } + + request struct ReorderNetworkRequest { + OCTET_STRING networkID = 0; + INT8U networkIndex = 1; + optional INT64U breadcrumb = 2; + } + + response struct ScanNetworksResponse = 1 { + NetworkCommissioningStatus networkingStatus = 0; + optional CHAR_STRING debugText = 1; + optional WiFiInterfaceScanResult wiFiScanResults[] = 2; + optional ThreadInterfaceScanResult threadScanResults[] = 3; + } + + response struct NetworkConfigResponse = 5 { + NetworkCommissioningStatus networkingStatus = 0; + optional CHAR_STRING debugText = 1; + optional INT8U networkIndex = 2; + } + + response struct ConnectNetworkResponse = 7 { + NetworkCommissioningStatus networkingStatus = 0; + optional CHAR_STRING debugText = 1; + nullable INT32S errorValue = 2; + } + + command access(invoke: administer) ScanNetworks(ScanNetworksRequest): ScanNetworksResponse = 0; + command access(invoke: administer) AddOrUpdateWiFiNetwork(AddOrUpdateWiFiNetworkRequest): NetworkConfigResponse = 2; + command access(invoke: administer) AddOrUpdateThreadNetwork(AddOrUpdateThreadNetworkRequest): NetworkConfigResponse = 3; + command access(invoke: administer) RemoveNetwork(RemoveNetworkRequest): NetworkConfigResponse = 4; + command access(invoke: administer) ConnectNetwork(ConnectNetworkRequest): ConnectNetworkResponse = 6; + command access(invoke: administer) ReorderNetwork(ReorderNetworkRequest): NetworkConfigResponse = 8; +} + +server cluster DiagnosticLogs = 50 { + enum LogsIntent : ENUM8 { + kEndUserSupport = 0; + kNetworkDiag = 1; + kCrashLogs = 2; + } + + enum LogsStatus : ENUM8 { + kSuccess = 0; + kExhausted = 1; + kNoLogs = 2; + kBusy = 3; + kDenied = 4; + } + + enum LogsTransferProtocol : ENUM8 { + kResponsePayload = 0; + kBdx = 1; + } + + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct RetrieveLogsRequestRequest { + LogsIntent intent = 0; + LogsTransferProtocol requestedProtocol = 1; + OCTET_STRING transferFileDesignator = 2; + } + + command RetrieveLogsRequest(RetrieveLogsRequestRequest): RetrieveLogsResponse = 0; +} + +server cluster GeneralDiagnostics = 51 { + enum BootReasonType : ENUM8 { + kUnspecified = 0; + kPowerOnReboot = 1; + kBrownOutReset = 2; + kSoftwareWatchdogReset = 3; + kHardwareWatchdogReset = 4; + kSoftwareUpdateCompleted = 5; + kSoftwareReset = 6; + } + + enum HardwareFaultType : ENUM8 { + kUnspecified = 0; + kRadio = 1; + kSensor = 2; + kResettableOverTemp = 3; + kNonResettableOverTemp = 4; + kPowerSource = 5; + kVisualDisplayFault = 6; + kAudioOutputFault = 7; + kUserInterfaceFault = 8; + kNonVolatileMemoryError = 9; + kTamperDetected = 10; + } + + enum InterfaceType : ENUM8 { + kUnspecified = 0; + kWiFi = 1; + kEthernet = 2; + kCellular = 3; + kThread = 4; + } + + enum NetworkFaultType : ENUM8 { + kUnspecified = 0; + kHardwareFailure = 1; + kNetworkJammed = 2; + kConnectionFailed = 3; + } + + enum RadioFaultType : ENUM8 { + kUnspecified = 0; + kWiFiFault = 1; + kCellularFault = 2; + kThreadFault = 3; + kNFCFault = 4; + kBLEFault = 5; + kEthernetFault = 6; + } + + struct NetworkInterfaceType { + char_string<32> name = 0; + boolean isOperational = 1; + nullable boolean offPremiseServicesReachableIPv4 = 2; + nullable boolean offPremiseServicesReachableIPv6 = 3; + octet_string<8> hardwareAddress = 4; + octet_string IPv4Addresses[] = 5; + octet_string IPv6Addresses[] = 6; + InterfaceType type = 7; + } + + critical event HardwareFaultChange = 0 { + HardwareFaultType current[] = 0; + HardwareFaultType previous[] = 1; + } + + critical event RadioFaultChange = 1 { + RadioFaultType current[] = 0; + RadioFaultType previous[] = 1; + } + + critical event NetworkFaultChange = 2 { + NetworkFaultType current[] = 0; + NetworkFaultType previous[] = 1; + } + + critical event BootReason = 3 { + BootReasonType bootReason = 0; + } + + readonly attribute NetworkInterfaceType networkInterfaces[] = 0; + readonly attribute int16u rebootCount = 1; + readonly attribute int64u upTime = 2; + readonly attribute int32u totalOperationalHours = 3; + readonly attribute enum8 bootReasons = 4; + readonly attribute ENUM8 activeHardwareFaults[] = 5; + readonly attribute ENUM8 activeRadioFaults[] = 6; + readonly attribute ENUM8 activeNetworkFaults[] = 7; + readonly attribute boolean testEventTriggersEnabled = 8; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct TestEventTriggerRequest { + OCTET_STRING enableKey = 0; + INT64U eventTrigger = 1; + } + + command access(invoke: manage) TestEventTrigger(TestEventTriggerRequest): DefaultSuccess = 0; +} + +server cluster SoftwareDiagnostics = 52 { + bitmap SoftwareDiagnosticsFeature : BITMAP32 { + kWaterMarks = 0x1; + } + + struct ThreadMetrics { + int64u id = 0; + optional char_string<8> name = 1; + optional int32u stackFreeCurrent = 2; + optional int32u stackFreeMinimum = 3; + optional int32u stackSize = 4; + } + + info event SoftwareFault = 0 { + INT64U id = 0; + optional CHAR_STRING name = 1; + optional OCTET_STRING faultRecording = 2; + } + + readonly attribute ThreadMetrics threadMetrics[] = 0; + readonly attribute int64u currentHeapFree = 1; + readonly attribute int64u currentHeapUsed = 2; + readonly attribute int64u currentHeapHighWatermark = 3; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +server cluster ThreadNetworkDiagnostics = 53 { + enum NetworkFault : ENUM8 { + kUnspecified = 0; + kLinkDown = 1; + kHardwareFailure = 2; + kNetworkJammed = 3; + } + + enum RoutingRole : ENUM8 { + kUnspecified = 0; + kUnassigned = 1; + kSleepyEndDevice = 2; + kEndDevice = 3; + kReed = 4; + kRouter = 5; + kLeader = 6; + } + + enum ThreadConnectionStatus : ENUM8 { + kConnected = 0; + kNotConnected = 1; + } + + bitmap ThreadNetworkDiagnosticsFeature : BITMAP32 { + kPacketCounts = 0x1; + kErrorCounts = 0x2; + kMLECounts = 0x4; + kMACCounts = 0x8; + } + + struct NeighborTable { + int64u extAddress = 0; + int32u age = 1; + int16u rloc16 = 2; + int32u linkFrameCounter = 3; + int32u mleFrameCounter = 4; + int8u lqi = 5; + nullable int8s averageRssi = 6; + nullable int8s lastRssi = 7; + int8u frameErrorRate = 8; + int8u messageErrorRate = 9; + boolean rxOnWhenIdle = 10; + boolean fullThreadDevice = 11; + boolean fullNetworkData = 12; + boolean isChild = 13; + } + + struct RouteTable { + int64u extAddress = 0; + int16u rloc16 = 1; + int8u routerId = 2; + int8u nextHop = 3; + int8u pathCost = 4; + int8u LQIIn = 5; + int8u LQIOut = 6; + int8u age = 7; + boolean allocated = 8; + boolean linkEstablished = 9; + } + + struct SecurityPolicy { + int16u rotationTime = 0; + bitmap16 flags = 1; + } + + struct OperationalDatasetComponents { + boolean activeTimestampPresent = 0; + boolean pendingTimestampPresent = 1; + boolean masterKeyPresent = 2; + boolean networkNamePresent = 3; + boolean extendedPanIdPresent = 4; + boolean meshLocalPrefixPresent = 5; + boolean delayPresent = 6; + boolean panIdPresent = 7; + boolean channelPresent = 8; + boolean pskcPresent = 9; + boolean securityPolicyPresent = 10; + boolean channelMaskPresent = 11; + } + + info event ConnectionStatus = 0 { + ThreadConnectionStatus connectionStatus = 0; + } + + info event NetworkFaultChange = 1 { + NetworkFault current[] = 0; + NetworkFault previous[] = 1; + } + + readonly attribute nullable int16u channel = 0; + readonly attribute nullable RoutingRole routingRole = 1; + readonly attribute nullable char_string<16> networkName = 2; + readonly attribute nullable int16u panId = 3; + readonly attribute nullable int64u extendedPanId = 4; + readonly attribute nullable octet_string<17> meshLocalPrefix = 5; + readonly attribute int64u overrunCount = 6; + readonly attribute NeighborTable neighborTableList[] = 7; + readonly attribute RouteTable routeTableList[] = 8; + readonly attribute nullable int32u partitionId = 9; + readonly attribute nullable int8u weighting = 10; + readonly attribute nullable int8u dataVersion = 11; + readonly attribute nullable int8u stableDataVersion = 12; + readonly attribute nullable int8u leaderRouterId = 13; + readonly attribute int16u detachedRoleCount = 14; + readonly attribute int16u childRoleCount = 15; + readonly attribute int16u routerRoleCount = 16; + readonly attribute int16u leaderRoleCount = 17; + readonly attribute int16u attachAttemptCount = 18; + readonly attribute int16u partitionIdChangeCount = 19; + readonly attribute int16u betterPartitionAttachAttemptCount = 20; + readonly attribute int16u parentChangeCount = 21; + readonly attribute int32u txTotalCount = 22; + readonly attribute int32u txUnicastCount = 23; + readonly attribute int32u txBroadcastCount = 24; + readonly attribute int32u txAckRequestedCount = 25; + readonly attribute int32u txAckedCount = 26; + readonly attribute int32u txNoAckRequestedCount = 27; + readonly attribute int32u txDataCount = 28; + readonly attribute int32u txDataPollCount = 29; + readonly attribute int32u txBeaconCount = 30; + readonly attribute int32u txBeaconRequestCount = 31; + readonly attribute int32u txOtherCount = 32; + readonly attribute int32u txRetryCount = 33; + readonly attribute int32u txDirectMaxRetryExpiryCount = 34; + readonly attribute int32u txIndirectMaxRetryExpiryCount = 35; + readonly attribute int32u txErrCcaCount = 36; + readonly attribute int32u txErrAbortCount = 37; + readonly attribute int32u txErrBusyChannelCount = 38; + readonly attribute int32u rxTotalCount = 39; + readonly attribute int32u rxUnicastCount = 40; + readonly attribute int32u rxBroadcastCount = 41; + readonly attribute int32u rxDataCount = 42; + readonly attribute int32u rxDataPollCount = 43; + readonly attribute int32u rxBeaconCount = 44; + readonly attribute int32u rxBeaconRequestCount = 45; + readonly attribute int32u rxOtherCount = 46; + readonly attribute int32u rxAddressFilteredCount = 47; + readonly attribute int32u rxDestAddrFilteredCount = 48; + readonly attribute int32u rxDuplicatedCount = 49; + readonly attribute int32u rxErrNoFrameCount = 50; + readonly attribute int32u rxErrUnknownNeighborCount = 51; + readonly attribute int32u rxErrInvalidSrcAddrCount = 52; + readonly attribute int32u rxErrSecCount = 53; + readonly attribute int32u rxErrFcsCount = 54; + readonly attribute int32u rxErrOtherCount = 55; + readonly attribute nullable int64u activeTimestamp = 56; + readonly attribute nullable int64u pendingTimestamp = 57; + readonly attribute nullable int32u delay = 58; + readonly attribute nullable SecurityPolicy securityPolicy = 59; + readonly attribute nullable octet_string<4> channelPage0Mask = 60; + readonly attribute nullable OperationalDatasetComponents operationalDatasetComponents = 61; + readonly attribute NetworkFault activeNetworkFaultsList[] = 62; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +server cluster WiFiNetworkDiagnostics = 54 { + enum AssociationFailureCause : ENUM8 { + kUnknown = 0; + kAssociationFailed = 1; + kAuthenticationFailed = 2; + kSsidNotFound = 3; + } + + enum SecurityType : ENUM8 { + kUnspecified = 0; + kNone = 1; + kWep = 2; + kWpa = 3; + kWpa2 = 4; + kWpa3 = 5; + } + + enum WiFiConnectionStatus : ENUM8 { + kConnected = 0; + kNotConnected = 1; + } + + enum WiFiVersionType : ENUM8 { + k80211a = 0; + k80211b = 1; + k80211g = 2; + k80211n = 3; + k80211ac = 4; + k80211ax = 5; + } + + info event Disconnection = 0 { + INT16U reasonCode = 0; + } + + info event AssociationFailure = 1 { + AssociationFailureCause associationFailure = 0; + INT16U status = 1; + } + + info event ConnectionStatus = 2 { + WiFiConnectionStatus connectionStatus = 0; + } + + readonly attribute nullable octet_string<6> bssid = 0; + readonly attribute nullable SecurityType securityType = 1; + readonly attribute nullable WiFiVersionType wiFiVersion = 2; + readonly attribute nullable int16u channelNumber = 3; + readonly attribute nullable int8s rssi = 4; + readonly attribute nullable int32u beaconLostCount = 5; + readonly attribute nullable int32u beaconRxCount = 6; + readonly attribute nullable int32u packetMulticastRxCount = 7; + readonly attribute nullable int32u packetMulticastTxCount = 8; + readonly attribute nullable int32u packetUnicastRxCount = 9; + readonly attribute nullable int32u packetUnicastTxCount = 10; + readonly attribute nullable int64u currentMaxRate = 11; + readonly attribute nullable int64u overrunCount = 12; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +server cluster EthernetNetworkDiagnostics = 55 { + enum PHYRateType : ENUM8 { + k10m = 0; + k100m = 1; + k1000m = 2; + k25g = 3; + k5g = 4; + k10g = 5; + k40g = 6; + k100g = 7; + k200g = 8; + k400g = 9; + } + + readonly attribute nullable PHYRateType PHYRate = 0; + readonly attribute nullable boolean fullDuplex = 1; + readonly attribute int64u packetRxCount = 2; + readonly attribute int64u packetTxCount = 3; + readonly attribute int64u txErrCount = 4; + readonly attribute int64u collisionCount = 5; + readonly attribute int64u overrunCount = 6; + readonly attribute nullable boolean carrierDetect = 7; + readonly attribute int64u timeSinceReset = 8; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + command ResetCounts(): DefaultSuccess = 0; +} + +server cluster Switch = 59 { + info event SwitchLatched = 0 { + INT8U newPosition = 0; + } + + info event InitialPress = 1 { + INT8U newPosition = 0; + } + + info event LongPress = 2 { + INT8U newPosition = 0; + } + + info event ShortRelease = 3 { + INT8U previousPosition = 0; + } + + info event LongRelease = 4 { + INT8U previousPosition = 0; + } + + info event MultiPressOngoing = 5 { + INT8U newPosition = 0; + INT8U currentNumberOfPressesCounted = 1; + } + + info event MultiPressComplete = 6 { + INT8U newPosition = 0; + INT8U totalNumberOfPressesCounted = 1; + } + + readonly attribute int8u numberOfPositions = 0; + readonly attribute int8u currentPosition = 1; + readonly attribute int8u multiPressMax = 2; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +server cluster AdministratorCommissioning = 60 { + enum CommissioningWindowStatus : ENUM8 { + kWindowNotOpen = 0; + kEnhancedWindowOpen = 1; + kBasicWindowOpen = 2; + } + + enum StatusCode : ENUM8 { + kBusy = 2; + kPAKEParameterError = 3; + kWindowNotOpen = 4; + } + + readonly attribute CommissioningWindowStatus windowStatus = 0; + readonly attribute nullable fabric_idx adminFabricIndex = 1; + readonly attribute nullable int16u adminVendorId = 2; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct OpenCommissioningWindowRequest { + INT16U commissioningTimeout = 0; + OCTET_STRING PAKEVerifier = 1; + INT16U discriminator = 2; + INT32U iterations = 3; + OCTET_STRING salt = 4; + } + + request struct OpenBasicCommissioningWindowRequest { + INT16U commissioningTimeout = 0; + } + + timed command access(invoke: administer) OpenCommissioningWindow(OpenCommissioningWindowRequest): DefaultSuccess = 0; + timed command access(invoke: administer) OpenBasicCommissioningWindow(OpenBasicCommissioningWindowRequest): DefaultSuccess = 1; + timed command access(invoke: administer) RevokeCommissioning(): DefaultSuccess = 2; +} + +server cluster OperationalCredentials = 62 { + enum OperationalCertStatus : ENUM8 { + kSuccess = 0; + kInvalidPublicKey = 1; + kInvalidNodeOpId = 2; + kInvalidNOC = 3; + kMissingCsr = 4; + kTableFull = 5; + kInvalidAdminSubject = 6; + kFabricConflict = 9; + kLabelConflict = 10; + kInvalidFabricIndex = 11; + } + + struct NOCStruct { + octet_string noc = 1; + nullable octet_string icac = 2; + fabric_idx fabricIndex = 254; + } + + struct FabricDescriptor { + octet_string<65> rootPublicKey = 1; + vendor_id vendorId = 2; + fabric_id fabricId = 3; + node_id nodeId = 4; + char_string<32> label = 5; + fabric_idx fabricIndex = 254; + } + + readonly attribute access(read: administer) NOCStruct NOCs[] = 0; + readonly attribute FabricDescriptor fabrics[] = 1; + readonly attribute int8u supportedFabrics = 2; + readonly attribute int8u commissionedFabrics = 3; + readonly attribute OCTET_STRING trustedRootCertificates[] = 4; + readonly attribute int8u currentFabricIndex = 5; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct AttestationRequestRequest { + OCTET_STRING attestationNonce = 0; + } + + request struct CertificateChainRequestRequest { + INT8U certificateType = 0; + } + + request struct CSRRequestRequest { + OCTET_STRING CSRNonce = 0; + optional boolean isForUpdateNOC = 1; + } + + request struct AddNOCRequest { + OCTET_STRING NOCValue = 0; + optional OCTET_STRING ICACValue = 1; + OCTET_STRING IPKValue = 2; + Int64u caseAdminSubject = 3; + VENDOR_ID adminVendorId = 4; + } + + request struct UpdateNOCRequest { + OCTET_STRING NOCValue = 0; + optional OCTET_STRING ICACValue = 1; + } + + request struct UpdateFabricLabelRequest { + CHAR_STRING label = 0; + } + + request struct RemoveFabricRequest { + fabric_idx fabricIndex = 0; + } + + request struct AddTrustedRootCertificateRequest { + OCTET_STRING rootCertificate = 0; + } + + response struct AttestationResponse = 1 { + OCTET_STRING attestationElements = 0; + OCTET_STRING signature = 1; + } + + response struct CertificateChainResponse = 3 { + OCTET_STRING certificate = 0; + } + + response struct CSRResponse = 5 { + OCTET_STRING NOCSRElements = 0; + OCTET_STRING attestationSignature = 1; + } + + response struct NOCResponse = 8 { + OperationalCertStatus statusCode = 0; + optional fabric_idx fabricIndex = 1; + optional CHAR_STRING debugText = 2; + } + + command access(invoke: administer) AttestationRequest(AttestationRequestRequest): AttestationResponse = 0; + command access(invoke: administer) CertificateChainRequest(CertificateChainRequestRequest): CertificateChainResponse = 2; + command access(invoke: administer) CSRRequest(CSRRequestRequest): CSRResponse = 4; + command access(invoke: administer) AddNOC(AddNOCRequest): NOCResponse = 6; + fabric command access(invoke: administer) UpdateNOC(UpdateNOCRequest): NOCResponse = 7; + fabric command access(invoke: administer) UpdateFabricLabel(UpdateFabricLabelRequest): NOCResponse = 9; + command access(invoke: administer) RemoveFabric(RemoveFabricRequest): NOCResponse = 10; + command access(invoke: administer) AddTrustedRootCertificate(AddTrustedRootCertificateRequest): DefaultSuccess = 11; +} + +server cluster GroupKeyManagement = 63 { + enum GroupKeySecurityPolicy : ENUM8 { + kTrustFirst = 0; + kCacheAndSync = 1; + } + + struct GroupKeyMapStruct { + group_id groupId = 1; + int16u groupKeySetID = 2; + fabric_idx fabricIndex = 254; + } + + struct GroupInfoMapStruct { + group_id groupId = 1; + endpoint_no endpoints[] = 2; + optional char_string<16> groupName = 3; + fabric_idx fabricIndex = 254; + } + + struct GroupKeySetStruct { + int16u groupKeySetID = 0; + GroupKeySecurityPolicy groupKeySecurityPolicy = 1; + nullable octet_string<16> epochKey0 = 2; + nullable epoch_us epochStartTime0 = 3; + nullable octet_string<16> epochKey1 = 4; + nullable epoch_us epochStartTime1 = 5; + nullable octet_string<16> epochKey2 = 6; + nullable epoch_us epochStartTime2 = 7; + } + + attribute access(write: manage) GroupKeyMapStruct groupKeyMap[] = 0; + readonly attribute GroupInfoMapStruct groupTable[] = 1; + readonly attribute int16u maxGroupsPerFabric = 2; + readonly attribute int16u maxGroupKeysPerFabric = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct KeySetWriteRequest { + GroupKeySetStruct groupKeySet = 0; + } + + request struct KeySetReadRequest { + INT16U groupKeySetID = 0; + } + + request struct KeySetRemoveRequest { + INT16U groupKeySetID = 0; + } + + request struct KeySetReadAllIndicesRequest { + INT16U groupKeySetIDs[] = 0; + } + + response struct KeySetReadResponse = 2 { + GroupKeySetStruct groupKeySet = 0; + } + + response struct KeySetReadAllIndicesResponse = 5 { + INT16U groupKeySetIDs[] = 0; + } + + fabric command access(invoke: administer) KeySetWrite(KeySetWriteRequest): DefaultSuccess = 0; + fabric command access(invoke: administer) KeySetRead(KeySetReadRequest): KeySetReadResponse = 1; + fabric command access(invoke: administer) KeySetRemove(KeySetRemoveRequest): DefaultSuccess = 3; + fabric command access(invoke: administer) KeySetReadAllIndices(KeySetReadAllIndicesRequest): KeySetReadAllIndicesResponse = 4; +} + +server cluster UserLabel = 65 { + struct LabelStruct { + char_string<16> label = 0; + char_string<16> value = 1; + } + + attribute access(write: manage) LabelStruct labelList[] = 0; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +server cluster TemperatureMeasurement = 1026 { + readonly attribute nullable int16s measuredValue = 0; + readonly attribute nullable int16s minMeasuredValue = 1; + readonly attribute nullable int16s maxMeasuredValue = 2; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +endpoint 0 { + device type bridge = 22; + binding cluster AccessControl; + + server cluster Descriptor { + callback attribute deviceList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap; + callback attribute clusterRevision default = 1; + } + + server cluster AccessControl { + callback attribute acl; + callback attribute extension; + callback attribute subjectsPerAccessControlEntry default = 4; + callback attribute targetsPerAccessControlEntry default = 3; + callback attribute accessControlEntriesPerFabric default = 3; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster Basic { + callback attribute dataModelRevision default = 10; + callback attribute vendorName; + callback attribute vendorID; + callback attribute productName; + callback attribute productID; + persist attribute nodeLabel; + callback attribute location default = "XX"; + callback attribute hardwareVersion; + callback attribute hardwareVersionString; + callback attribute softwareVersion; + callback attribute softwareVersionString; + callback attribute manufacturingDate default = "20210614123456ZZ"; + callback attribute partNumber; + callback attribute productURL; + callback attribute productLabel; + callback attribute serialNumber; + persist attribute localConfigDisabled; + ram attribute reachable default = 1; + callback attribute uniqueID; + callback attribute capabilityMinima; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster LocalizationConfiguration { + persist attribute activeLocale default = "en-US"; + callback attribute supportedLocales; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster TimeFormatLocalization { + persist attribute hourFormat; + persist attribute activeCalendarType; + callback attribute supportedCalendarTypes; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster UnitLocalization { + persist attribute temperatureUnit; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0x1; + ram attribute clusterRevision default = 1; + } + + server cluster GeneralCommissioning { + ram attribute breadcrumb; + callback attribute basicCommissioningInfo; + callback attribute regulatoryConfig; + callback attribute locationCapability; + callback attribute supportsConcurrentConnection default = 1; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster NetworkCommissioning { + ram attribute maxNetworks; + callback attribute networks; + ram attribute scanMaxTimeSeconds; + ram attribute connectMaxTimeSeconds; + ram attribute interfaceEnabled; + ram attribute lastNetworkingStatus; + ram attribute lastNetworkID; + ram attribute lastConnectErrorValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 2; + ram attribute clusterRevision default = 1; + } + + server cluster DiagnosticLogs { + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster GeneralDiagnostics { + callback attribute networkInterfaces; + callback attribute rebootCount; + callback attribute upTime; + callback attribute totalOperationalHours; + callback attribute bootReasons; + callback attribute activeHardwareFaults; + callback attribute activeRadioFaults; + callback attribute activeNetworkFaults; + callback attribute testEventTriggersEnabled; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster SoftwareDiagnostics { + callback attribute threadMetrics; + callback attribute currentHeapFree; + callback attribute currentHeapUsed; + callback attribute currentHeapHighWatermark; + ram attribute featureMap default = 1; + ram attribute clusterRevision default = 1; + } + + server cluster ThreadNetworkDiagnostics { + callback attribute channel; + callback attribute routingRole; + callback attribute networkName; + callback attribute panId; + callback attribute extendedPanId; + callback attribute meshLocalPrefix; + callback attribute overrunCount; + callback attribute neighborTableList; + callback attribute routeTableList; + callback attribute partitionId; + callback attribute weighting; + callback attribute dataVersion; + callback attribute stableDataVersion; + callback attribute leaderRouterId; + callback attribute detachedRoleCount; + callback attribute childRoleCount; + callback attribute routerRoleCount; + callback attribute leaderRoleCount; + callback attribute attachAttemptCount; + callback attribute partitionIdChangeCount; + callback attribute betterPartitionAttachAttemptCount; + callback attribute parentChangeCount; + callback attribute txTotalCount; + callback attribute txUnicastCount; + callback attribute txBroadcastCount; + callback attribute txAckRequestedCount; + callback attribute txAckedCount; + callback attribute txNoAckRequestedCount; + callback attribute txDataCount; + callback attribute txDataPollCount; + callback attribute txBeaconCount; + callback attribute txBeaconRequestCount; + callback attribute txOtherCount; + callback attribute txRetryCount; + callback attribute txDirectMaxRetryExpiryCount; + callback attribute txIndirectMaxRetryExpiryCount; + callback attribute txErrCcaCount; + callback attribute txErrAbortCount; + callback attribute txErrBusyChannelCount; + callback attribute rxTotalCount; + callback attribute rxUnicastCount; + callback attribute rxBroadcastCount; + callback attribute rxDataCount; + callback attribute rxDataPollCount; + callback attribute rxBeaconCount; + callback attribute rxBeaconRequestCount; + callback attribute rxOtherCount; + callback attribute rxAddressFilteredCount; + callback attribute rxDestAddrFilteredCount; + callback attribute rxDuplicatedCount; + callback attribute rxErrNoFrameCount; + callback attribute rxErrUnknownNeighborCount; + callback attribute rxErrInvalidSrcAddrCount; + callback attribute rxErrSecCount; + callback attribute rxErrFcsCount; + callback attribute rxErrOtherCount; + callback attribute activeTimestamp; + callback attribute pendingTimestamp; + callback attribute delay; + callback attribute securityPolicy; + callback attribute channelPage0Mask; + callback attribute operationalDatasetComponents; + callback attribute activeNetworkFaultsList; + ram attribute featureMap default = 15; + ram attribute clusterRevision default = 1; + } + + server cluster WiFiNetworkDiagnostics { + callback attribute bssid; + callback attribute securityType; + callback attribute wiFiVersion; + callback attribute channelNumber; + callback attribute rssi; + callback attribute beaconLostCount; + callback attribute beaconRxCount; + callback attribute packetMulticastRxCount; + callback attribute packetMulticastTxCount; + callback attribute packetUnicastRxCount; + callback attribute packetUnicastTxCount; + callback attribute currentMaxRate; + callback attribute overrunCount; + ram attribute featureMap default = 3; + ram attribute clusterRevision default = 1; + } + + server cluster EthernetNetworkDiagnostics { + callback attribute PHYRate; + callback attribute fullDuplex; + callback attribute packetRxCount; + callback attribute packetTxCount; + callback attribute txErrCount; + callback attribute collisionCount; + callback attribute overrunCount; + callback attribute carrierDetect; + callback attribute timeSinceReset; + ram attribute featureMap default = 3; + ram attribute clusterRevision default = 1; + } + + server cluster AdministratorCommissioning { + callback attribute windowStatus; + callback attribute adminFabricIndex default = 1; + callback attribute adminVendorId; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster OperationalCredentials { + callback attribute NOCs; + callback attribute fabrics; + callback attribute supportedFabrics; + callback attribute commissionedFabrics; + callback attribute trustedRootCertificates; + callback attribute currentFabricIndex; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster GroupKeyManagement { + callback attribute groupKeyMap; + callback attribute groupTable; + callback attribute maxGroupsPerFabric; + callback attribute maxGroupKeysPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster UserLabel { + callback attribute labelList; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } +} +endpoint 1 { + device type anonymousEndpointType = 14; + binding cluster Binding; + + server cluster Identify { + ram attribute identifyTime; + ram attribute identifyType; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap; + ram attribute clusterRevision default = 2; + } + + server cluster Descriptor { + callback attribute deviceList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster Actions { + callback attribute actionList; + callback attribute endpointLists; + ram attribute setupURL default = "https://example.com"; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } +} +endpoint 2 { + device type dimmablelight = 257; + + server cluster OnOff { + ram attribute onOff; + ram attribute featureMap; + ram attribute clusterRevision default = 4; + } + + server cluster LevelControl { + persist attribute currentLevel; + ram attribute remainingTime; + ram attribute minLevel default = 0x01; + ram attribute maxLevel default = 0xFE; + ram attribute currentFrequency; + ram attribute minFrequency; + ram attribute maxFrequency; + ram attribute options; + ram attribute onOffTransitionTime; + ram attribute onLevel default = 0xFE; + ram attribute onTransitionTime; + ram attribute offTransitionTime; + ram attribute defaultMoveRate; + persist attribute startUpCurrentLevel default = 255; + ram attribute featureMap default = 3; + ram attribute clusterRevision default = 5; + } + + server cluster Descriptor { + callback attribute deviceList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + ram attribute featureMap; + callback attribute clusterRevision default = 1; + } + + server cluster Switch { + ram attribute numberOfPositions default = 2; + ram attribute currentPosition default = 1; + ram attribute multiPressMax default = 2; + ram attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster TemperatureMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue default = 0x954D; + callback attribute maxMeasuredValue default = 0x7FFF; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision default = 1; + } +} + + diff --git a/examples/dynamic-bridge-app/bridge-common/bridge-app.zap b/examples/dynamic-bridge-app/bridge-common/bridge-app.zap new file mode 100644 index 00000000000000..e2eeb1a3620ff4 --- /dev/null +++ b/examples/dynamic-bridge-app/bridge-common/bridge-app.zap @@ -0,0 +1,7547 @@ +{ + "featureLevel": 80, + "creator": "zap", + "keyValuePairs": [ + { + "key": "commandDiscovery", + "value": "1" + }, + { + "key": "defaultResponsePolicy", + "value": "always" + }, + { + "key": "manufacturerCodes", + "value": "0x1002" + } + ], + "package": [ + { + "pathRelativity": "relativeToZap", + "path": "../../../src/app/zap-templates/zcl/zcl.json", + "type": "zcl-properties", + "category": "matter", + "version": 1, + "description": "Matter SDK ZCL data" + }, + { + "pathRelativity": "relativeToZap", + "path": "../../../src/app/zap-templates/app-templates.json", + "type": "gen-templates-json", + "version": "chip-v1" + } + ], + "endpointTypes": [ + { + "name": "MA-bridge", + "deviceTypeName": "MA-rootdevice", + "deviceTypeCode": 22, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "device list", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "server list", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "client list", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "parts list", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Access Control", + "code": 31, + "mfgCode": null, + "define": "ACCESS_CONTROL_CLUSTER", + "side": "client", + "enabled": 1, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Access Control", + "code": 31, + "mfgCode": null, + "define": "ACCESS_CONTROL_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "ACL", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Extension", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SubjectsPerAccessControlEntry", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TargetsPerAccessControlEntry", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AccessControlEntriesPerFabric", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Basic", + "code": 40, + "mfgCode": null, + "define": "BASIC_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Basic", + "code": 40, + "mfgCode": null, + "define": "BASIC_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DataModelRevision", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "10", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorName", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorID", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductName", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductID", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NodeLabel", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Location", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "XX", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersion", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersionString", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersion", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersionString", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ManufacturingDate", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "20210614123456ZZ", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartNumber", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductURL", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "long_char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductLabel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SerialNumber", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LocalConfigDisabled", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Reachable", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UniqueID", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CapabilityMinima", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "CapabilityMinimaStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Localization Configuration", + "code": 43, + "mfgCode": null, + "define": "LOCALIZATION_CONFIGURATION_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Localization Configuration", + "code": 43, + "mfgCode": null, + "define": "LOCALIZATION_CONFIGURATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "ActiveLocale", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "en-US", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportedLocales", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Time Format Localization", + "code": 44, + "mfgCode": null, + "define": "TIME_FORMAT_LOCALIZATION_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Time Format Localization", + "code": 44, + "mfgCode": null, + "define": "TIME_FORMAT_LOCALIZATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "HourFormat", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "HourFormat", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveCalendarType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "CalendarType", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportedCalendarTypes", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Unit Localization", + "code": 45, + "mfgCode": null, + "define": "UNIT_LOCALIZATION_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Unit Localization", + "code": 45, + "mfgCode": null, + "define": "UNIT_LOCALIZATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "TemperatureUnit", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "TempUnit", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ArmFailSafe", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetRegulatoryConfig", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "CommissioningComplete", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ArmFailSafeResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "SetRegulatoryConfigResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "CommissioningCompleteResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "Breadcrumb", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BasicCommissioningInfo", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "BasicCommissioningInfo", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RegulatoryConfig", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationType", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LocationCapability", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationType", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportsConcurrentConnection", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ScanNetworks", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddOrUpdateWiFiNetwork", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "AddOrUpdateThreadNetwork", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveNetwork", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ConnectNetwork", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ReorderNetwork", + "code": 8, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ScanNetworksResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "NetworkConfigResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ConnectNetworkResponse", + "code": 7, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "MaxNetworks", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Networks", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ScanMaxTimeSeconds", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ConnectMaxTimeSeconds", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "InterfaceEnabled", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkingStatus", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "NetworkCommissioningStatus", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkID", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastConnectErrorValue", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "TestEventTrigger", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "TestEventTrigger", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "NetworkInterfaces", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RebootCount", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UpTime", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TotalOperationalHours", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BootReasons", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveHardwareFaults", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveRadioFaults", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveNetworkFaults", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TestEventTriggersEnabled", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "false", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Software Diagnostics", + "code": 52, + "mfgCode": null, + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetWatermarks", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Software Diagnostics", + "code": 52, + "mfgCode": null, + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "ThreadMetrics", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapFree", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapUsed", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapHighWatermark", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Thread Network Diagnostics", + "code": 53, + "mfgCode": null, + "define": "THREAD_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "channel", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RoutingRole", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "RoutingRole", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NetworkName", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PanId", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ExtendedPanId", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MeshLocalPrefix", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OverrunCount", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NeighborTableList", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RouteTableList", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartitionId", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "weighting", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DataVersion", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "StableDataVersion", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LeaderRouterId", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "DetachedRoleCount", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ChildRoleCount", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RouterRoleCount", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LeaderRoleCount", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "AttachAttemptCount", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartitionIdChangeCount", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BetterPartitionAttachAttemptCount", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ParentChangeCount", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxTotalCount", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxUnicastCount", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBroadcastCount", + "code": 24, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxAckRequestedCount", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxAckedCount", + "code": 26, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxNoAckRequestedCount", + "code": 27, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDataCount", + "code": 28, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDataPollCount", + "code": 29, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBeaconCount", + "code": 30, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxBeaconRequestCount", + "code": 31, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxOtherCount", + "code": 32, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxRetryCount", + "code": 33, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxDirectMaxRetryExpiryCount", + "code": 34, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxIndirectMaxRetryExpiryCount", + "code": 35, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrCcaCount", + "code": 36, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrAbortCount", + "code": 37, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrBusyChannelCount", + "code": 38, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxTotalCount", + "code": 39, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxUnicastCount", + "code": 40, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBroadcastCount", + "code": 41, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDataCount", + "code": 42, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDataPollCount", + "code": 43, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBeaconCount", + "code": 44, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxBeaconRequestCount", + "code": 45, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxOtherCount", + "code": 46, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxAddressFilteredCount", + "code": 47, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDestAddrFilteredCount", + "code": 48, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxDuplicatedCount", + "code": 49, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrNoFrameCount", + "code": 50, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrUnknownNeighborCount", + "code": 51, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrInvalidSrcAddrCount", + "code": 52, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrSecCount", + "code": 53, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrFcsCount", + "code": 54, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RxErrOtherCount", + "code": 55, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ActiveTimestamp", + "code": 56, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PendingTimestamp", + "code": 57, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Delay", + "code": 58, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SecurityPolicy", + "code": 59, + "mfgCode": null, + "side": "server", + "type": "SecurityPolicy", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ChannelPage0Mask", + "code": 60, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OperationalDatasetComponents", + "code": 61, + "mfgCode": null, + "side": "server", + "type": "OperationalDatasetComponents", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ActiveNetworkFaultsList", + "code": 62, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "15", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "WiFi Network Diagnostics", + "code": 54, + "mfgCode": null, + "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "WiFi Network Diagnostics", + "code": 54, + "mfgCode": null, + "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "bssid", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SecurityType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "SecurityType", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "WiFiVersion", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "WiFiVersionType", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ChannelNumber", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Rssi", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int8s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BeaconLostCount", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BeaconRxCount", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PacketMulticastRxCount", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PacketMulticastTxCount", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PacketUnicastRxCount", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PacketUnicastTxCount", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentMaxRate", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OverrunCount", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Ethernet Network Diagnostics", + "code": 55, + "mfgCode": null, + "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetCounts", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Ethernet Network Diagnostics", + "code": 55, + "mfgCode": null, + "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "PHYRate", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "PHYRateType", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FullDuplex", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PacketRxCount", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PacketTxCount", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TxErrCount", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CollisionCount", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "OverrunCount", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CarrierDetect", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TimeSinceReset", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "WindowStatus", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "CommissioningWindowStatus", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminFabricIndex", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "fabric_idx", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminVendorId", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Operational Credentials", + "code": 62, + "mfgCode": null, + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AttestationRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "CertificateChainRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "CSRRequest", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddNOC", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "UpdateNOC", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "UpdateFabricLabel", + "code": 9, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveFabric", + "code": 10, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddTrustedRootCertificate", + "code": 11, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Operational Credentials", + "code": 62, + "mfgCode": null, + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AttestationResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "CertificateChainResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "CSRResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "NOCResponse", + "code": 8, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "NOCs", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Fabrics", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SupportedFabrics", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CommissionedFabrics", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TrustedRootCertificates", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentFabricIndex", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "KeySetWrite", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetRead", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetRemove", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "KeySetReadAllIndices", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "KeySetReadResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "KeySetReadAllIndicesResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "GroupKeyMap", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GroupTable", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxGroupsPerFabric", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxGroupKeysPerFabric", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "label list", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "User Label", + "code": 65, + "mfgCode": null, + "define": "USER_LABEL_CLUSTER", + "side": "client", + "enabled": 0 + }, + { + "name": "User Label", + "code": 65, + "mfgCode": null, + "define": "USER_LABEL_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "label list", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "name": "Anonymous Endpoint Type", + "deviceTypeName": "MA-aggregator", + "deviceTypeCode": 14, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "identify time", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "identify type", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "enum8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "device list", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "server list", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "client list", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "parts list", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 1, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "Binding", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Actions", + "code": 37, + "mfgCode": null, + "define": "ACTIONS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "InstantAction", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Actions", + "code": 37, + "mfgCode": null, + "define": "ACTIONS_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "ActionList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EndpointLists", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SetupURL", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "long_char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "https://example.com", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "name": "MA-dimmablelight", + "deviceTypeName": "MA-dimmablelight", + "deviceTypeCode": 257, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "identify time", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddGroup", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ViewGroup", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "GetGroupMembership", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveGroup", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveAllGroups", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "AddGroupIfIdentifying", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "AddGroupResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ViewGroupResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "GetGroupMembershipResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RemoveGroupResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "name support", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddScene", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ViewScene", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveScene", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveAllScenes", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "StoreScene", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RecallScene", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "GetSceneMembership", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "AddSceneResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "ViewSceneResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RemoveSceneResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RemoveAllScenesResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "StoreSceneResponse", + "code": 4, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "GetSceneMembershipResponse", + "code": 6, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "SceneCount", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentScene", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentGroup", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "group_id", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SceneValid", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NameSupport", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/Off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Off", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "On", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "Toggle", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "On/Off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "OnOff", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "MoveToLevel", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "Move", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "Step", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "Stop", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "MoveToLevelWithOnOff", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "MoveWithOnOff", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "StepWithOnOff", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "StopWithOnOff", + "code": 7, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Level Control", + "code": 8, + "mfgCode": null, + "define": "LEVEL_CONTROL_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "CurrentLevel", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RemainingTime", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinLevel", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x01", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxLevel", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFE", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentFrequency", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinFrequency", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxFrequency", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Options", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "bitmap8", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OnOffTransitionTime", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OnLevel", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFE", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OnTransitionTime", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OffTransitionTime", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "DefaultMoveRate", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "StartUpCurrentLevel", + "code": 16384, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "255", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "device list", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "server list", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "client list", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "parts list", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Basic", + "code": 40, + "mfgCode": null, + "define": "BASIC_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Basic", + "code": 40, + "mfgCode": null, + "define": "BASIC_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "DataModelRevision", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "10", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorName", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorID", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductName", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductID", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NodeLabel", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Location", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "XX", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersion", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersionString", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersion", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersionString", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ManufacturingDate", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "20210614123456ZZ", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartNumber", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductURL", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "long_char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductLabel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SerialNumber", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LocalConfigDisabled", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Reachable", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UniqueID", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CapabilityMinima", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "CapabilityMinimaStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Switch", + "code": 59, + "mfgCode": null, + "define": "SWITCH_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Switch", + "code": 59, + "mfgCode": null, + "define": "SWITCH_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "number of positions", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "current position", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "multi press max", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "server", + "enabled": 0, + "attributes": [ + { + "name": "label list", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Temperature Measurement", + "code": 1026, + "mfgCode": null, + "define": "TEMP_MEASUREMENT_CLUSTER", + "side": "client", + "enabled": 0, + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Temperature Measurement", + "code": 1026, + "mfgCode": null, + "define": "TEMP_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x954D", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x7FFF", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + } + ], + "endpoints": [ + { + "endpointTypeName": "MA-bridge", + "endpointTypeIndex": 0, + "profileId": 259, + "endpointId": 0, + "networkId": 0, + "endpointVersion": 1, + "deviceIdentifier": 22 + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 1, + "profileId": 259, + "endpointId": 1, + "networkId": 0, + "endpointVersion": 1, + "deviceIdentifier": 14 + }, + { + "endpointTypeName": "MA-dimmablelight", + "endpointTypeIndex": 2, + "profileId": 259, + "endpointId": 2, + "networkId": 0, + "endpointVersion": 1, + "deviceIdentifier": 257 + } + ] +} \ No newline at end of file diff --git a/examples/dynamic-bridge-app/bridge-common/include/CHIPProjectAppConfig.h b/examples/dynamic-bridge-app/bridge-common/include/CHIPProjectAppConfig.h new file mode 100644 index 00000000000000..036cbda81ad736 --- /dev/null +++ b/examples/dynamic-bridge-app/bridge-common/include/CHIPProjectAppConfig.h @@ -0,0 +1,34 @@ +/* + * + * Copyright (c) 2020 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. + */ + +/** + * @file + * Example project configuration file for CHIP. + * + * This is a place to put application or project-specific overrides + * to the default configuration values for general CHIP features. + * + */ + +#pragma once + +// overrides CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT in CHIPProjectConfig +#define CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT 16 + +// include the CHIPProjectConfig from config/standalone +#include diff --git a/examples/bridge-app/bridge-common/protos/bridge_service.options b/examples/dynamic-bridge-app/bridge-common/protos/bridge_service.options similarity index 100% rename from examples/bridge-app/bridge-common/protos/bridge_service.options rename to examples/dynamic-bridge-app/bridge-common/protos/bridge_service.options diff --git a/examples/bridge-app/bridge-common/protos/bridge_service.proto b/examples/dynamic-bridge-app/bridge-common/protos/bridge_service.proto similarity index 100% rename from examples/bridge-app/bridge-common/protos/bridge_service.proto rename to examples/dynamic-bridge-app/bridge-common/protos/bridge_service.proto diff --git a/examples/dynamic-bridge-app/linux/.gn b/examples/dynamic-bridge-app/linux/.gn new file mode 100644 index 00000000000000..70728706ea4a14 --- /dev/null +++ b/examples/dynamic-bridge-app/linux/.gn @@ -0,0 +1,25 @@ +# Copyright (c) 2021 Project CHIP Authors +# +# 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. + +import("//build_overrides/build.gni") + +# The location of the build configuration file. +buildconfig = "${build_root}/config/BUILDCONFIG.gn" + +# CHIP uses angle bracket includes. +check_system_includes = true + +default_args = { + import("//args.gni") +} diff --git a/examples/dynamic-bridge-app/linux/BUILD.gn b/examples/dynamic-bridge-app/linux/BUILD.gn new file mode 100644 index 00000000000000..9f65fccf947d08 --- /dev/null +++ b/examples/dynamic-bridge-app/linux/BUILD.gn @@ -0,0 +1,128 @@ +# Copyright (c) 2021 Project CHIP Authors +# +# 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. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +import("${chip_root}/build/chip/tools.gni") +import("${chip_root}/src/app/common_flags.gni") + +import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") + +if (chip_enable_pw_rpc) { + import("//build_overrides/pigweed.gni") + import("$dir_pw_build/target_types.gni") +} + +assert(chip_build_tools) + +action("chip-bridge-codegen") { + script = "${chip_root}/scripts/codegen.py" + sources = + [ "${chip_root}/examples/bridge-app/bridge-common/bridge-app.matter" ] + # Also several other files, but this is sufficient for dependency purposes. + outputs = [ "$target_gen_dir/bridge/BridgeClustersImpl.h" ] + + args = [ + "--generator", + "bridge", + "--output-dir", + rebase_path(target_gen_dir, root_build_dir), + rebase_path( + "${chip_root}/examples/bridge-app/bridge-common/bridge-app.matter", + root_build_dir), + ] + deps = [ "${chip_root}/scripts/idl" ] +} + +executable("dynamic-chip-bridge-app") { + sources = [ + "bridged-actions-stub.cpp", + "Backend.cpp", + "Clusters.cpp", + "Device.cpp", + "DynamicDevice.cpp", + "UserInputBackend.cpp", + "main.cpp", + ] + + deps = [ + ":chip-bridge-codegen", + "${chip_root}/examples/bridge-app/bridge-common", + "${chip_root}/examples/platform/linux:app-main", + "${chip_root}/src/app/tests/suites/credentials:dac_provider", + "${chip_root}/src/lib", + ] + + include_dirs = [ + "include", + target_gen_dir, + ] + + if (chip_enable_pw_rpc) { + defines = [ + "PW_RPC_ENABLED", + "PW_RPC_ATTRIBUTE_SERVICE=1", + "PW_RPC_DESCRIPTOR_SERVICE=1", + "PW_RPC_DEVICE_SERVICE=1", + "PW_RPC_TRACING_SERVICE=1" + ] + + sources += [ + "${chip_root}/examples/platform/linux/Rpc.cpp", + "${chip_root}/examples/platform/linux/system_rpc_server.cc", + "bridge_service.cpp" + ] + + deps += [ + "$dir_pw_hdlc:pw_rpc", + "$dir_pw_hdlc:rpc_channel_output", + "$dir_pw_log", + "$dir_pw_rpc:server", + "$dir_pw_rpc/system_server:facade", + "$dir_pw_stream:socket_stream", + "$dir_pw_stream:sys_io_stream", + "$dir_pw_sync:mutex", + "$dir_pw_trace", + "$dir_pw_trace_tokenized", + "$dir_pw_trace_tokenized:trace_rpc_service", + "${chip_root}/config/linux/lib/pw_rpc:pw_rpc", + "${chip_root}/examples/dynamic-bridge-app/bridge-common:bridge_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:attributes_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:button_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:descriptor_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:device_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:lighting_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:rpc_services", + ] + + deps += pw_build_LINK_DEPS + + include_dirs += [ "${chip_root}/examples/common" ] + } else { + # The system_rpc_server.cc file is in pigweed and doesn't compile with + # -Wconversion, remove check for RPC build only. + cflags = [ "-Wconversion" ] + } + + output_dir = root_out_dir +} + +group("linux") { + deps = [ ":dynamic-chip-bridge-app" ] +} + +group("default") { + deps = [ ":linux" ] +} diff --git a/examples/bridge-app/linux/Backend.cpp b/examples/dynamic-bridge-app/linux/Backend.cpp similarity index 92% rename from examples/bridge-app/linux/Backend.cpp rename to examples/dynamic-bridge-app/linux/Backend.cpp index 4cd3b6503a2cd5..6b7c0628e709c2 100644 --- a/examples/bridge-app/linux/Backend.cpp +++ b/examples/dynamic-bridge-app/linux/Backend.cpp @@ -21,7 +21,7 @@ #include "main.h" std::vector> g_devices; -std::vector> g_device_impls; +std::vector> g_device_impls; bool RemoveDeviceAt(uint32_t index) { @@ -41,7 +41,7 @@ bool RemoveDeviceAt(uint32_t index) return true; } -int AddDevice(std::unique_ptr device) +int AddDevice(std::unique_ptr device) { auto dev = std::make_unique(device->CreateDevice()); int ep = AddDeviceEndpoint(dev.get()); diff --git a/examples/dynamic-bridge-app/linux/Clusters.cpp b/examples/dynamic-bridge-app/linux/Clusters.cpp new file mode 100644 index 00000000000000..28b5b1945e3c37 --- /dev/null +++ b/examples/dynamic-bridge-app/linux/Clusters.cpp @@ -0,0 +1,143 @@ +#include "GeneratedClusters.h" + +#include "Device.h" + +CommonCluster * CommonAttributeAccessInterface::FindCluster(const chip::app::ConcreteClusterPath & path) +{ + Device * dev = FindDeviceEndpoint(path.mEndpointId); + if (dev) + { + for (auto c : dev->clusters()) + { + if (c->GetClusterId() == path.mClusterId) + return static_cast(c); + } + } + return nullptr; +} + +CHIP_ERROR CommonAttributeAccessInterface::Read(const chip::app::ConcreteReadAttributePath & aPath, + chip::app::AttributeValueEncoder & aEncoder) +{ + CommonCluster * c = FindCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + AttributeInterface * a = c->FindAttribute(aPath.mAttributeId); + if (!a) + return CHIP_ERROR_NOT_IMPLEMENTED; + return a->Read(aPath, aEncoder); +} + +CHIP_ERROR CommonAttributeAccessInterface::Write(const chip::app::ConcreteDataAttributePath & aPath, + chip::app::AttributeValueDecoder & aDecoder) +{ + CommonCluster * c = FindCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + return c->ForwardWriteToBridge(aPath, aDecoder); +} + +void CommonAttributeAccessInterface::OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) +{ + CommonCluster * c = FindCluster(aPath); + if (c) + { + AttributeInterface * a = c->FindAttribute(aPath.mAttributeId); + if (a) + a->ListWriteBegin(aPath); + } +} + +void CommonAttributeAccessInterface::OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) +{ + CommonCluster * c = FindCluster(aPath); + if (c) + { + AttributeInterface * a = c->FindAttribute(aPath.mAttributeId); + if (a) + a->ListWriteEnd(aPath, aWriteWasSuccessful); + } +} + +CommonCluster::CommonCluster(std::unique_ptr cluster) : + mAttributes(cluster->GetAttributes()), mStorage(std::move(cluster)) +{} +CommonCluster::~CommonCluster() = default; + +chip::ClusterId CommonCluster::GetClusterId() +{ + return mStorage->GetClusterId(); +} + +void CommonCluster::SetEndpointId(chip::EndpointId id) +{ + mEndpoint = id; +} + +chip::EndpointId CommonCluster::GetEndpointId() const +{ + return mEndpoint; +} + +void CommonCluster::SetCallback(PropagateWriteCB * cb) +{ + mCallback = cb; +} + +bool CommonCluster::active() const +{ + return mEndpoint < 0xFFFF; +} + +CHIP_ERROR CommonCluster::ForwardWriteToBridge(const chip::app::ConcreteDataAttributePath & aPath, + chip::app::AttributeValueDecoder & aDecoder) +{ + if (mCallback) + return (*mCallback)(this, aPath, aDecoder); + return WriteFromBridge(aPath, aDecoder); +} + +CHIP_ERROR CommonCluster::WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, + chip::app::AttributeValueDecoder & aDecoder) +{ + AttributeInterface * a = FindAttribute(aPath.mAttributeId); + if (!a) + return CHIP_ERROR_NOT_IMPLEMENTED; + return a->Write(aPath, aDecoder); +} + +chip::Span CommonCluster::GetAllAttributes() +{ + return chip::Span(mAttributes.data(), mAttributes.size()); +} + +AttributeInterface * CommonCluster::FindAttribute(chip::AttributeId id) +{ + for (auto * attr : mAttributes) + if (attr->GetId() == id) + return attr; + return nullptr; +} + +AttributeInterface * CommonCluster::FindAttributeByName(chip::CharSpan name) +{ + for (auto * attr : mAttributes) + if (name.data_equal(attr->GetName())) + return attr; + return nullptr; +} + +void CommonCluster::OnUpdated(chip::AttributeId attr) +{ + if (active()) + MatterReportingAttributeChangeCallback(GetEndpointId(), GetClusterId(), attr); +} + +bool CommonCluster::Push(chip::AttributeId attr, chip::TLV::TLVReader & reader) +{ + chip::app::AttributeValueDecoder decoder(reader, chip::Access::SubjectDescriptor()); + if (WriteFromBridge(chip::app::ConcreteDataAttributePath(GetEndpointId(), GetClusterId(), attr), decoder) != CHIP_NO_ERROR) + return false; + OnUpdated(attr); + return true; +} diff --git a/examples/dynamic-bridge-app/linux/Device.cpp b/examples/dynamic-bridge-app/linux/Device.cpp new file mode 100644 index 00000000000000..c749f9bb5babd4 --- /dev/null +++ b/examples/dynamic-bridge-app/linux/Device.cpp @@ -0,0 +1,51 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * 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 "Device.h" + +#include +#include + +Device::Device(chip::Span dataVersions, chip::Span clusters, + chip::Span clusterImpl, const chip::Span & deviceTypeList, + chip::EndpointId parentId) : + mParentEndpointId(parentId), + mDataVersions(dataVersions), mClusters(clusters), mClusterImpl(clusterImpl), mDeviceTypeList(deviceTypeList) +{ + mEndpointType.cluster = clusters.data(); + mEndpointType.clusterCount = (uint8_t) clusters.size(); + mEndpointType.endpointSize = 0; +} + +void Device::SetEndpointId(chip::EndpointId id) +{ + mEndpointId = id; + for (auto * c : mClusterImpl) + c->SetEndpointId(id); +} + +const char * Device::GetName() +{ + return mDeviceName.c_str(); +} + +void Device::SetName(const char * name) +{ + mDeviceName = name; +} diff --git a/examples/dynamic-bridge-app/linux/Dockerfile b/examples/dynamic-bridge-app/linux/Dockerfile new file mode 100644 index 00000000000000..965e82a664266c --- /dev/null +++ b/examples/dynamic-bridge-app/linux/Dockerfile @@ -0,0 +1,23 @@ +# +# Copyright (c) 2020-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. +# + +FROM connectedhomeip/chip-cirque-device-base:latest + +COPY out/debug/chip-bridge-app /usr/bin/ +COPY entrypoint.sh / + +ENTRYPOINT ["/entrypoint.sh", "server"] diff --git a/examples/bridge-app/linux/DynamicDevice.cpp b/examples/dynamic-bridge-app/linux/DynamicDevice.cpp similarity index 53% rename from examples/bridge-app/linux/DynamicDevice.cpp rename to examples/dynamic-bridge-app/linux/DynamicDevice.cpp index cc8063e2a0f6f2..415dbac8be9fa5 100644 --- a/examples/bridge-app/linux/DynamicDevice.cpp +++ b/examples/dynamic-bridge-app/linux/DynamicDevice.cpp @@ -19,26 +19,14 @@ #include "DynamicDevice.h" -void DynamicAttributeList::Add(chip::AttributeId id, EmberAfAttributeType type, uint16_t maxSize, EmberAfClusterMask mask) -{ - // Do what DECLARE_DYNAMIC_ATTRIBUTE does. - mAttributeDecls.emplace_back( - EmberAfAttributeMetadata{ id, type, maxSize, (uint8_t)(mask | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE)), ZAP_EMPTY_DEFAULT() }); -} +DynamicDevice::DynamicDevice() {} -void DynamicAttributeList::Add(EmberAfAttributeMetadata metadata) -{ - mAttributeDecls.emplace_back(metadata); -} - -DynamicDeviceImpl::DynamicDeviceImpl() {} - -void DynamicDeviceImpl::AddDeviceType(EmberAfDeviceType type) +void DynamicDevice::AddDeviceType(EmberAfDeviceType type) { mDeviceTypes.push_back(type); } -Device DynamicDeviceImpl::CreateDevice() +Device DynamicDevice::CreateDevice() { // All nodes are bridged devices. mDeviceTypes.push_back(EmberAfDeviceType{ DEVICE_TYPE_BRIDGED_NODE, DEVICE_VERSION_DEFAULT }); @@ -52,24 +40,29 @@ Device DynamicDeviceImpl::CreateDevice() chip::Span(mDeviceTypes.data(), mDeviceTypes.size()), mParentEndpointId); } -DynamicDeviceImpl & DynamicDeviceImpl::AddCluster(std::unique_ptr cluster, const DynamicAttributeList & attribs, - const chip::CommandId * incomingCommands, - const chip::CommandId * outgoingCommands) +DynamicDevice & DynamicDevice::AddCluster(std::unique_ptr cluster, + const chip::Span & attribs, + const chip::CommandId * incomingCommands, const chip::CommandId * outgoingCommands) { AddCluster(cluster.get(), attribs, incomingCommands, outgoingCommands); mClusters.emplace_back(std::move(cluster)); return *this; } -DynamicDeviceImpl & DynamicDeviceImpl::AddCluster(CommonCluster * cluster, const DynamicAttributeList & attribs, - const chip::CommandId * incomingCommands, - const chip::CommandId * outgoingCommands) +DynamicDevice & DynamicDevice::AddCluster(CommonCluster * cluster, const chip::Span & attribs, + const chip::CommandId * incomingCommands, const chip::CommandId * outgoingCommands) { - mAttribStorage.push_back(attribs.mAttributeDecls); // Do what DECLARE_DYNAMIC_CLUSTER does. - mClusterDecls.emplace_back(EmberAfCluster{ cluster->GetClusterId(), mAttribStorage.back().data(), - (uint16_t) mAttribStorage.back().size(), 0, ZAP_CLUSTER_MASK(SERVER), nullptr, - incomingCommands, outgoingCommands }); + mClusterDecls.emplace_back(EmberAfCluster{ cluster->GetClusterId(), attribs.data(), (uint16_t) attribs.size(), 0, + ZAP_CLUSTER_MASK(SERVER), nullptr, incomingCommands, outgoingCommands }); mClusterRawPtrs.emplace_back(cluster); return *this; } + +DynamicDevice & DynamicDevice::AddCluster(std::unique_ptr cluster) +{ + auto ptr = cluster.get(); + return AddCluster(std::move(cluster), + chip::Span(ptr->mAttributeDecls.data(), ptr->mAttributeDecls.size()), + ptr->mIncomingCommands, ptr->mOutgoingCommands); +} diff --git a/examples/dynamic-bridge-app/linux/README.md b/examples/dynamic-bridge-app/linux/README.md new file mode 100644 index 00000000000000..9960be56f504a3 --- /dev/null +++ b/examples/dynamic-bridge-app/linux/README.md @@ -0,0 +1,185 @@ +# CHIP Linux Bridge Example + +An example demonstrating a simple lighting bridge and the use of dynamic +endpoints. The document will describe the theory of operation and how to build +and run CHIP Linux Bridge Example on Raspberry Pi. This doc is tested on +**Ubuntu for Raspberry Pi Server 20.04 LTS (aarch64)** and **Ubuntu for +Raspberry Pi Desktop 20.10 (aarch64)** + +
+ +- [CHIP Linux Bridge Example](#chip-linux-bridge-example) + - [Theory of Operation](#operation) + - [Building](#building) + - [Running the Complete Example on Raspberry Pi 4](#running-complete-example) + +
+ + + +## Theory of Operation + +### Dynamic Endpoints + +The Bridge Example makes use of Dynamic Endpoints. Current SDK support is +limited for dynamic endpoints, since endpoints are typically defined (along with +the clusters and attributes they contain) in a .zap file which then generates +code and static structures to define the endpoints. + +To support endpoints that are not statically defined, the ZCL attribute storage +mechanisms will hold additional endpoint information for `NUM_DYNAMIC_ENDPOINTS` +additional endpoints. These additional endpoint structures must be defined by +the application and can change at runtime. + +To facilitate the creation of these endpoint structures, several macros are +defined: + +`DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(attrListName)` +`DECLARE_DYNAMIC_ATTRIBUTE(attId, attType, attSizeBytes, attrMask)` +`DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(clusterRevision)` + +- These three macros are used to declare a list of attributes for use within a + cluster. The declaration must begin with the + `DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN` macro which will define the name of + the allocated attribute structure. Each attribute is then added by the + `DECLARE_DYNAMIC_ATTRIBUTE` macro. Finally, + `DECLARE_DYNAMIC_ATTRIBUTE_LIST_END` macro should be used to close the + definition. + +- All attributes defined with these macros will be configured as + `ATTRIBUTE_MASK_EXTERNAL_STORAGE` in the ZCL database and therefore will + rely on the application to maintain storage for the attribute. Consequently, + reads or writes to these attributes must be handled within the application + by the `emberAfExternalAttributeWriteCallback` and + `emberAfExternalAttributeReadCallback` functions. See the bridge + application's `main.cpp` for an example of this implementation. + +`DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN(clusterListName)` +`DECLARE_DYNAMIC_CLUSTER(clusterId, clusterAttrs, incomingCommands, outgoingCommands)` +`DECLARE_DYNAMIC_CLUSTER_LIST_END` + +- These three macros are used to declare a list of clusters for use within a + endpoint. The declaration must begin with the + `DECLARE_DYNAMIC_CLUSTER_LIST_BEGIN` macro which will define the name of the + allocated cluster structure. Each cluster is then added by the + `DECLARE_DYNAMIC_CLUSTER` macro referencing attribute list previously + defined by the `DECLARE_DYNAMIC_ATTRIBUTE...` macros and the lists of + incoming/outgoing commands terminated by kInvalidCommandId (or nullptr if + there aren't any commands in the list). Finally, + `DECLARE_DYNAMIC_CLUSTER_LIST_END` macro should be used to close the + definition. + +`DECLARE_DYNAMIC_ENDPOINT(endpointName, clusterList)` + +- This macro is used to declare an endpoint and its associated cluster list, + which must be previously defined by the `DECLARE_DYNAMIC_CLUSTER...` macros. + +### Limitations + +Because code generation is dependent upon the clusters and attributes defined in +the .zap file (for static endpoint generation), it is necessary to include a +defined endpoint within the .zap that contains _all_ the clusters that may be +used on dynamic endpoints. On the bridge example, this is done on endpoint 1, +which is used as a 'dummy' endpoint that will be disabled at runtime. Endpoint 0 +is also defined in the .zap and contains the bridge basic and configuration +clusters as well as the root descriptor cluster. + +### Bridge Implementation Example + +The example demonstrates the use of dynamic endpoints and the concept of adding +and removing endpoints at runtime. First, the example declares a +`bridgedLightEndpoint` data structure for a Light endpoint with `OnOff`, +`Descriptor`, `BridgedDeviceBasic`, and `FixedLabel` clusters. + +Using this declared endpoint structure, three endpoints for three bridged lights +are dynamically added at endpoint ID's `2`, `3`, and `4`, representing +`Light 1`, `Light 2`, and `Light 3` respectively. + +Then, endpoint `3` is removed, simulating the deletion of `Light 2`. + +A fourth light, `Light 4`, is then added occupying endpoint ID `5`. + +Finally, `Light 2` is re-added, and will occupy endpoint ID `6`. + +All endpoints populate the `Bridged Device Basic` and `Fixed Label` clusters. In +the `Bridged Device Basic` cluster, the `reachable` attribute is simulated. In +the `Fixed Label` cluster, the `LabelList` attribute is simulated with the +value/label pair `"room"`/`[light name]`. + + + +## Building + +- Install tool chain + + ``` + $ sudo apt-get install git gcc g++ python pkg-config libssl-dev libdbus-1-dev libglib2.0-dev ninja-build python3-venv python3-dev unzip + ``` + +- Build the example application: + + ``` + $ cd ~/connectedhomeip/examples/bridge-app/linux + $ git submodule update --init + $ source third_party/connectedhomeip/scripts/activate.sh + $ gn gen out/debug + $ ninja -C out/debug + ``` + +- To delete generated executable, libraries and object files use: + + ``` + $ cd ~/connectedhomeip/examples/bridge-app/linux + $ rm -rf out/ + ``` + + + +## Running the Complete Example on Raspberry Pi 4 + +- Prerequisites + + 1. A Raspberry Pi 4 board + 2. A USB Bluetooth Dongle, Ubuntu desktop will send Bluetooth advertisement, + which will block CHIP from connecting via BLE. On Ubuntu server, you need + to install `pi-bluetooth` via APT. + 3. Ubuntu 20.04 or newer image for ARM64 platform. + +- Building + + Follow [Building](#building) section of this document. + +- Running + + - [Optional] Plug USB Bluetooth dongle + + - Plug USB Bluetooth dongle and find its bluetooth device number. The + number after `hci` is the bluetooth device number, `1` in this + example. + + ``` + $ hciconfig + hci1: Type: Primary Bus: USB + BD Address: 00:1A:7D:AA:BB:CC ACL MTU: 310:10 SCO MTU: 64:8 + UP RUNNING PSCAN ISCAN + RX bytes:20942 acl:1023 sco:0 events:1140 errors:0 + TX bytes:16559 acl:1011 sco:0 commands:121 errors:0 + + hci0: Type: Primary Bus: UART + BD Address: B8:27:EB:AA:BB:CC ACL MTU: 1021:8 SCO MTU: 64:1 + UP RUNNING PSCAN ISCAN + RX bytes:8609495 acl:14 sco:0 events:217484 errors:0 + TX bytes:92185 acl:20 sco:0 commands:5259 errors:0 + ``` + + - Run Linux Bridge Example App + + ``` + $ cd ~/connectedhomeip/examples/bridge-app/linux + $ sudo out/debug/chip-bridge-app --ble-device [bluetooth device number] + # In this example, the device we want to use is hci1 + $ sudo out/debug/chip-bridge-app --ble-device 1 + ``` + + - Test the device using ChipDeviceController on your laptop / + workstation etc. diff --git a/examples/bridge-app/linux/UserInputBackend.cpp b/examples/dynamic-bridge-app/linux/UserInputBackend.cpp similarity index 90% rename from examples/bridge-app/linux/UserInputBackend.cpp rename to examples/dynamic-bridge-app/linux/UserInputBackend.cpp index 3105fa5b592014..3905e309ae8097 100644 --- a/examples/bridge-app/linux/UserInputBackend.cpp +++ b/examples/dynamic-bridge-app/linux/UserInputBackend.cpp @@ -15,7 +15,7 @@ namespace { -std::unique_ptr g_pending; +std::unique_ptr g_pending; // Pseudo-index representing the device being built. static constexpr int kPendingDeviceIndex = -1; @@ -94,11 +94,7 @@ void NewDevice(const std::vector & tokens) } else if (!type.HasValue()) { - g_pending = std::make_unique(); - } - else if (type.Value() == "switch") - { - g_pending = std::make_unique(); + g_pending = std::make_unique(); } else { @@ -125,12 +121,8 @@ void AddCluster(const std::vector & tokens) { if (cluster_name == cluster.name) { - std::unique_ptr obj(cluster.ctor(::operator new(cluster.size))); - DynamicAttributeList dynamic_attrs; - auto attrs = obj->GetAllAttributes(); - for (auto & attr : attrs) - dynamic_attrs.Add(attr); - g_pending->AddCluster(std::move(obj), dynamic_attrs, nullptr, nullptr); + g_pending->AddCluster( + std::make_unique(std::unique_ptr(cluster.ctor(::operator new(cluster.size))))); printf("Added cluster %s/%d\n", cluster.name, cluster.id); return; } @@ -215,7 +207,7 @@ void AddType(const std::vector & tokens) g_pending->AddDeviceType(devType); } -DynamicDeviceImpl * FindDevice(int32_t index) +DynamicDevice * FindDevice(int32_t index) { if (index == kPendingDeviceIndex) { @@ -223,7 +215,7 @@ DynamicDeviceImpl * FindDevice(int32_t index) } else if ((uint32_t) index < g_device_impls.size()) { - return g_device_impls[index].get(); + return g_device_impls[(uint32_t) index].get(); } else { @@ -235,7 +227,7 @@ Device * FindEndpoint(int32_t index) { if (index >= 0 && (uint32_t) index < g_device_impls.size()) { - return g_devices[index].get(); + return g_devices[(uint32_t) index].get(); } else { @@ -243,7 +235,7 @@ Device * FindEndpoint(int32_t index) } } -ClusterInterface * FindCluster(DynamicDeviceImpl * dev, const std::string & clusterId) +ClusterInterface * FindCluster(DynamicDevice * dev, const std::string & clusterId) { uint32_t id; const char * start = clusterId.data(); @@ -275,33 +267,20 @@ ClusterInterface * FindCluster(DynamicDeviceImpl * dev, const std::string & clus const EmberAfAttributeMetadata * FindAttrib(ClusterInterface * cluster, const std::string & attrId) { + AttributeInterface * attr = nullptr; uint32_t id; const char * start = attrId.data(); const char * end = start + attrId.size(); - if (std::from_chars(start, end, id).ptr != end) + if (std::from_chars(start, end, id).ptr == end) { - auto clusterId = cluster->GetClusterId(); - id = 0; - for (const auto & c : clusters::kKnownAttributes) - { - if (c.cluster == clusterId && attrId == c.name) - { - id = c.attr; - break; - } - } - if (!id) - return nullptr; + attr = cluster->FindAttribute(id); } - - for (auto & attr : cluster->GetAllAttributes()) + if (!attr) { - if (attr.attributeId == id) - { - return &attr; - } + attr = cluster->FindAttributeByName(chip::CharSpan(attrId.data(), attrId.size())); } - return nullptr; + + return attr ? &attr->GetMetadata() : nullptr; } void ParseValue(std::vector * data, uint16_t size, const std::string & str, EmberAfAttributeType type) @@ -371,7 +350,7 @@ void SetValue(const std::vector & tokens) return; } - DynamicDeviceImpl * dev = FindDevice(index); + DynamicDevice * dev = FindDevice(index); if (!dev) { printf("Could not find device at index %d\n", index); @@ -396,7 +375,7 @@ void SetValue(const std::vector & tokens) printf("Cluster does not implement attr %s\nSupported attributes: ", attrId.c_str()); for (auto attrMeta : cluster->GetAllAttributes()) { - printf("%d ", attrMeta.attributeId); + printf("%d ", attrMeta->GetId()); } printf("\n"); return; @@ -451,7 +430,7 @@ void DelRoom(const std::vector & tokens) void AddToRoom(const std::vector & tokens) { - uint32_t index; + int32_t index; std::string room; const char * err = Parse(tokens, 0, &room, &index); if (err) @@ -476,7 +455,7 @@ void AddToRoom(const std::vector & tokens) void DelFromRoom(const std::vector & tokens) { - uint32_t index; + int32_t index; std::string room; const char * err = Parse(tokens, 0, &room, &index); if (err) diff --git a/examples/dynamic-bridge-app/linux/args.gni b/examples/dynamic-bridge-app/linux/args.gni new file mode 100644 index 00000000000000..7039d20e181994 --- /dev/null +++ b/examples/dynamic-bridge-app/linux/args.gni @@ -0,0 +1,25 @@ +# Copyright (c) 2021 Project CHIP Authors +# +# 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. + +import("//build_overrides/chip.gni") + +import("${chip_root}/config/standalone/args.gni") + +chip_device_project_config_include = "" +chip_project_config_include = "" +chip_system_project_config_include = "" + +chip_project_config_include_dirs = + [ "${chip_root}/examples/bridge-app/bridge-common/include" ] +chip_project_config_include_dirs += [ "${chip_root}/config/standalone" ] diff --git a/examples/bridge-app/linux/bridge_service.cpp b/examples/dynamic-bridge-app/linux/bridge_service.cpp similarity index 83% rename from examples/bridge-app/linux/bridge_service.cpp rename to examples/dynamic-bridge-app/linux/bridge_service.cpp index af096e8371a76b..c5b55dfbfde785 100644 --- a/examples/bridge-app/linux/bridge_service.cpp +++ b/examples/dynamic-bridge-app/linux/bridge_service.cpp @@ -38,9 +38,9 @@ const clusters::ClusterInfo * FindCluster(uint32_t id) ::pw::Status Bridge::Add(const ::chip_rpc_bridge_AddDevice & request, ::chip_rpc_bridge_AddDeviceResponse & response) { - std::unique_ptr pending; + std::unique_ptr pending; - pending = std::make_unique(); + pending = std::make_unique(); pending->SetParentEndpointId(request.parent_endpoint); for (pb_size_t i = 0; i < request.clusters_count; i++) @@ -53,12 +53,8 @@ ::pw::Status Bridge::Add(const ::chip_rpc_bridge_AddDevice & request, ::chip_rpc return pw::Status::InvalidArgument(); } - std::unique_ptr obj(cluster->ctor(::operator new(cluster->size))); - DynamicAttributeList dynamic_attrs; - auto attrs = obj->GetAllAttributes(); - for (auto & attr : attrs) - dynamic_attrs.Add(attr); - pending->AddCluster(std::move(obj), dynamic_attrs, nullptr, nullptr); + pending->AddCluster( + std::make_unique(std::unique_ptr(cluster->ctor(::operator new(cluster->size))))); } for (pb_size_t i = 0; i < request.device_types_count; i++) diff --git a/examples/bridge-app/linux/bridge_service.h b/examples/dynamic-bridge-app/linux/bridge_service.h similarity index 100% rename from examples/bridge-app/linux/bridge_service.h rename to examples/dynamic-bridge-app/linux/bridge_service.h diff --git a/examples/dynamic-bridge-app/linux/bridged-actions-stub.cpp b/examples/dynamic-bridge-app/linux/bridged-actions-stub.cpp new file mode 100644 index 00000000000000..6c0f7cf8eb680e --- /dev/null +++ b/examples/dynamic-bridge-app/linux/bridged-actions-stub.cpp @@ -0,0 +1,137 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Device.h" +#include "main.h" + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::Actions::Attributes; + +namespace { + +class ActionsAttrAccess : public AttributeAccessInterface +{ +public: + // Register for the Actions cluster on all endpoints. + ActionsAttrAccess() : AttributeAccessInterface(Optional::Missing(), Actions::Id) {} + + CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; + +private: + static constexpr uint16_t ClusterRevision = 1; + + CHIP_ERROR ReadActionListAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder); + CHIP_ERROR ReadEndpointListAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder); + CHIP_ERROR ReadSetupUrlAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder); + CHIP_ERROR ReadClusterRevision(EndpointId endpoint, AttributeValueEncoder & aEncoder); +}; + +constexpr uint16_t ActionsAttrAccess::ClusterRevision; + +CHIP_ERROR ActionsAttrAccess::ReadActionListAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder) +{ + CHIP_ERROR err = aEncoder.EncodeList([&endpoint](const auto & encoder) -> CHIP_ERROR { + chip::Span actionList = GetActionListInfo(endpoint); + + for (auto action : actionList) + { + if (action->getIsVisible()) + { + Actions::Structs::ActionStruct::Type actionStruct = { action->getActionId(), + CharSpan::fromCharString(action->getName().c_str()), + action->getType(), + action->getEndpointListId(), + action->getSupportedCommands(), + action->getStatus() }; + ReturnErrorOnFailure(encoder.Encode(actionStruct)); + } + } + + return CHIP_NO_ERROR; + }); + return err; +} + +CHIP_ERROR ActionsAttrAccess::ReadEndpointListAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder) +{ + CHIP_ERROR err = aEncoder.EncodeList([](const auto & encoder) -> CHIP_ERROR { + for (auto & room : gRooms) + { + if (room.GetEndpointListSize() == 0) + continue; + Actions::Structs::EndpointListStruct::Type endpointListStruct = { + room.GetEndpointListId(), CharSpan::fromCharString(room.GetName().c_str()), room.GetType(), + DataModel::List(room.GetEndpointListData(), room.GetEndpointListSize()) + }; + ReturnErrorOnFailure(encoder.Encode(endpointListStruct)); + } + return CHIP_NO_ERROR; + }); + return err; +} + +CHIP_ERROR ActionsAttrAccess::ReadSetupUrlAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder) +{ + const char SetupUrl[] = "https://example.com"; + return aEncoder.Encode(chip::CharSpan::fromCharString(SetupUrl)); +} + +CHIP_ERROR ActionsAttrAccess::ReadClusterRevision(EndpointId endpoint, AttributeValueEncoder & aEncoder) +{ + return aEncoder.Encode(ClusterRevision); +} + +ActionsAttrAccess gAttrAccess; + +CHIP_ERROR ActionsAttrAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) +{ + VerifyOrDie(aPath.mClusterId == Actions::Id); + + switch (aPath.mAttributeId) + { + case ActionList::Id: + return ReadActionListAttribute(aPath.mEndpointId, aEncoder); + case EndpointLists::Id: + return ReadEndpointListAttribute(aPath.mEndpointId, aEncoder); + case SetupURL::Id: + return ReadSetupUrlAttribute(aPath.mEndpointId, aEncoder); + case ClusterRevision::Id: + return ReadClusterRevision(aPath.mEndpointId, aEncoder); + default: + break; + } + return CHIP_NO_ERROR; +} +} // anonymous namespace + +void MatterActionsPluginServerInitCallback(void) +{ + registerAttributeAccessOverride(&gAttrAccess); +} diff --git a/examples/dynamic-bridge-app/linux/build b/examples/dynamic-bridge-app/linux/build new file mode 120000 index 00000000000000..d56ed62ae4d1ff --- /dev/null +++ b/examples/dynamic-bridge-app/linux/build @@ -0,0 +1 @@ +third_party/connectedhomeip/build \ No newline at end of file diff --git a/examples/dynamic-bridge-app/linux/build_overrides b/examples/dynamic-bridge-app/linux/build_overrides new file mode 120000 index 00000000000000..e578e73312ebd1 --- /dev/null +++ b/examples/dynamic-bridge-app/linux/build_overrides @@ -0,0 +1 @@ +../../build_overrides \ No newline at end of file diff --git a/examples/dynamic-bridge-app/linux/entrypoint.sh b/examples/dynamic-bridge-app/linux/entrypoint.sh new file mode 100755 index 00000000000000..9d33bdd92ce434 --- /dev/null +++ b/examples/dynamic-bridge-app/linux/entrypoint.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +service dbus start +sleep 1 +service avahi-daemon start +/usr/sbin/otbr-agent -I wpan0 spinel+hdlc+uart:///dev/ttyUSB0 & +sleep 1 +ot-ctl panid 0x1234 +ot-ctl ifconfig up +ot-ctl thread start + +chip-bridge-app diff --git a/examples/dynamic-bridge-app/linux/include/Attribute.h b/examples/dynamic-bridge-app/linux/include/Attribute.h new file mode 100644 index 00000000000000..5224ab4a0d936c --- /dev/null +++ b/examples/dynamic-bridge-app/linux/include/Attribute.h @@ -0,0 +1,80 @@ +#pragma once + +#include + +#include "DataModel.h" + +// This is the interface to the attribute implementation +class AttributeInterface +{ +public: + virtual ~AttributeInterface() = default; + + // Get the ID of this attribute. Shortcut for GetMetadata().attributeId + virtual chip::AttributeId GetId() = 0; + // Get the metadata of this attribute, suitable for advertising. + virtual const EmberAfAttributeMetadata& GetMetadata() = 0; + + virtual chip::CharSpan GetName() = 0; + + // List attribes should override these to get list write notifications. + virtual void ListWriteBegin(const chip::app::ConcreteAttributePath & aPath) {} + virtual void ListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) {} + + // Write a single value to the attribute. + virtual CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) = 0; + + // Read the contents of the attribute. + virtual CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) = 0; +}; + +// This is the base type for implementing an attribute +template +struct Attribute : public AttributeInterface +{ + Attribute(chip::CharSpan name, chip::AttributeId id, EmberAfAttributeMask mask, EmberAfAttributeType type, size_t size, Type value = Type()) + : mMetadata(EmberAfAttributeMetadata{id, type, (uint16_t)size, mask, ZAP_EMPTY_DEFAULT()}), mData(value), mName(name) + { + } + + chip::AttributeId GetId() override { return mMetadata.attributeId; } + const EmberAfAttributeMetadata& GetMetadata() override { return mMetadata; } + chip::CharSpan GetName() override { return mName; } + + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override + { + return chip::app::DataModel::Decode(aPath, aDecoder, mData); + } + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override + { + return chip::app::DataModel::Encode(aPath, aEncoder, mData); + } + + void operator=(const Type& value) { mData = value; } + const Type& Peek() const { return mData; } + +protected: + EmberAfAttributeMetadata mMetadata; + Type mData; + chip::CharSpan mName; +}; + +// This specialization handles list writes and reverts if the write fails. +template +struct ListAttribute : public Attribute +{ + using Attribute::Attribute; + + void ListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override + { + mBackup = std::move(this->mData); + } + void ListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override + { + if (!aWriteWasSuccessful) + this->mData = std::move(mBackup); + mBackup = Type(); + } + + Type mBackup; +}; diff --git a/examples/bridge-app/linux/include/Backend.h b/examples/dynamic-bridge-app/linux/include/Backend.h similarity index 86% rename from examples/bridge-app/linux/include/Backend.h rename to examples/dynamic-bridge-app/linux/include/Backend.h index 5058eeea69b5f5..d709bf17b74937 100644 --- a/examples/bridge-app/linux/include/Backend.h +++ b/examples/dynamic-bridge-app/linux/include/Backend.h @@ -23,7 +23,7 @@ void StartUserInput(); extern std::vector> g_devices; -extern std::vector> g_device_impls; +extern std::vector> g_device_impls; bool RemoveDeviceAt(uint32_t index); -int AddDevice(std::unique_ptr device); +int AddDevice(std::unique_ptr device); diff --git a/examples/dynamic-bridge-app/linux/include/Clusters.h b/examples/dynamic-bridge-app/linux/include/Clusters.h new file mode 100644 index 00000000000000..755c882eefbcbf --- /dev/null +++ b/examples/dynamic-bridge-app/linux/include/Clusters.h @@ -0,0 +1,107 @@ +/* + * + * Copyright (c) 2022 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. + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "Attribute.h" + +// This is the interface to cluster implementations, providing access to manipulate attributes. +class ClusterInterface +{ +public: + virtual ~ClusterInterface() = default; + + // Set the endpoint for this cluster. + virtual void SetEndpointId(chip::EndpointId id) = 0; + // Get the ID for this cluster. + virtual chip::ClusterId GetClusterId() = 0; + // Gets the list of enabled attributes for this cluster. + virtual chip::Span GetAllAttributes() = 0; + // Find an attribute of this cluster, if present. + virtual AttributeInterface * FindAttribute(chip::AttributeId id) = 0; + // Find an attribute of this cluster, if present, given its name. + virtual AttributeInterface * FindAttributeByName(chip::CharSpan name) = 0; + // Write the given TLV encoded value to the given attribute. Can write + // normally read-only values. Nofitied matter that the value has changed. + virtual bool Push(chip::AttributeId attr, chip::TLV::TLVReader & reader) = 0; +}; + +class GeneratedCluster; + +struct CommonCluster; +typedef std::function + PropagateWriteCB; + +// This provides the backend access to implementation details. +struct CommonCluster : public ClusterInterface +{ + CommonCluster(std::unique_ptr cluster); + ~CommonCluster(); + + void SetEndpointId(chip::EndpointId id) override; + chip::EndpointId GetEndpointId() const; + + chip::ClusterId GetClusterId() override; + + void SetCallback(PropagateWriteCB * cb); + + bool active() const; + + // Implemented by generated code. Valid writes should be forwarded to ForwardWriteToBridge. + virtual CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, + chip::app::AttributeValueDecoder & aDecoder); + + // Calls the registered callback if one exists, otherwise triggers a write of the actual + // stored value. + CHIP_ERROR ForwardWriteToBridge(const chip::app::ConcreteDataAttributePath & aPath, + chip::app::AttributeValueDecoder & aDecoder); + + chip::Span GetAllAttributes() override; + AttributeInterface * FindAttribute(chip::AttributeId id) override; + AttributeInterface * FindAttributeByName(chip::CharSpan name) override; + + // Force a write of a given attribute. Can write normally read-only values. + // Calls OnUpdated after the write finishes. + bool Push(chip::AttributeId attr, chip::TLV::TLVReader & reader) override; + + // Push an attribute update notification to the matter stack. + void OnUpdated(chip::AttributeId attr); + + template + void OnUpdated(const T & attr) + { + OnUpdated(attr.GetId()); + } + +protected: + chip::EndpointId mEndpoint = 0xFFFF; + PropagateWriteCB * mCallback = nullptr; + std::vector mAttributes; + std::unique_ptr mStorage; +}; diff --git a/examples/dynamic-bridge-app/linux/include/DataModel.h b/examples/dynamic-bridge-app/linux/include/DataModel.h new file mode 100644 index 00000000000000..57240b6478ac09 --- /dev/null +++ b/examples/dynamic-bridge-app/linux/include/DataModel.h @@ -0,0 +1,218 @@ +#pragma once + +#include +#include +#include +#include + +#include + +namespace chip { +namespace app { +namespace DataModel { + +template +class IsList +{ + typedef char yes; + typedef long no; + + template static yes test(decltype(&U::size)) ; + template static no test(...); + +public: + static constexpr bool value = sizeof(test(0)) == sizeof(yes); +}; + +template +struct IsOptionalOrNullable { static constexpr bool value = false; }; +template +struct IsOptionalOrNullable> { static constexpr bool value = true; }; +template +struct IsOptionalOrNullable> { static constexpr bool value = true; }; + +static_assert(IsList>::value); + +template>::value && !IsList>::value, bool> = true> +CHIP_ERROR Encode(const ConcreteReadAttributePath&, AttributeValueEncoder & aEncoder, const X& x) +{ + return aEncoder.Encode(x); +} + +/* + * @brief + * Lists that are string-like should be encoded as char/byte spans. + */ +template>::value && sizeof(std::decay_t) == sizeof(char), bool> = true> +CHIP_ERROR Encode(const ConcreteReadAttributePath& aPath, AttributeValueEncoder & aEncoder, const X& x) +{ + return aEncoder.Encode(Span>(x.data(), x.size())); +} + + +/* + * @brief + * + * If an item is requested from a list, encode just that single item, or the entire list otherwise. + * + * The object must satisfy the following constraints + * size() must return an integer + * begin() must return a type conforming to LegacyRandomAccessIterator + * + * This is const X& instead of X&& because it is "more specialized" and so this overload will + * be chosen if possible. + */ +template>::value && (sizeof(std::decay_t) > sizeof(char)), bool> = true> +CHIP_ERROR Encode(const ConcreteReadAttributePath& aPath, AttributeValueEncoder & aEncoder, const X& x) +{ + if (aPath.mListIndex.HasValue()) + { + uint16_t index = aPath.mListIndex.Value(); + if (index >= x.size()) + return CHIP_ERROR_INVALID_ARGUMENT; + + return aEncoder.Encode(x.data()[index]); + } + return aEncoder.EncodeList([x](const auto & encoder) { + CHIP_ERROR err = CHIP_NO_ERROR; + for(auto& v : x) { + err = encoder.Encode(v); + if (err != CHIP_NO_ERROR) + break; + } + return err; + }); +} + +/* + * @brief + * Set of overloaded encode methods that can be called from AttributeAccessInterface::Read + */ +template +CHIP_ERROR Encode(const ConcreteReadAttributePath& aPath, AttributeValueEncoder & aEncoder, const Optional & x) +{ + if (x.HasValue()) + { + return Encode(aPath, aEncoder, x.Value()); + } + // If no value, just do nothing. + return CHIP_NO_ERROR; +} + +/* + * @brief + * + * Encodes a nullable value. + */ +template +CHIP_ERROR Encode(const ConcreteReadAttributePath& aPath, AttributeValueEncoder & aEncoder, const Nullable & x) +{ + if (x.IsNull()) + { + return aEncoder.EncodeNull(); + } + + // Allow sending invalid values for nullables when + // CONFIG_BUILD_FOR_HOST_UNIT_TEST is true, so we can test how the other side + // responds. +#if !CONFIG_BUILD_FOR_HOST_UNIT_TEST + if (!x.HasValidValue()) + { + return CHIP_IM_GLOBAL_STATUS(ConstraintError); + } +#endif // !CONFIG_BUILD_FOR_HOST_UNIT_TEST + + // The -Wmaybe-uninitialized warning gets confused about the fact + // that x.mValue is always initialized if x.IsNull() is not + // true, so suppress it for our access to x.Value(). +#pragma GCC diagnostic push +#if !defined(__clang__) +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif // !defined(__clang__) + return Encode(aPath, aEncoder, x.Value()); +#pragma GCC diagnostic pop +} + + +template>::value && !IsList>::value, bool> = true> +CHIP_ERROR Decode(const ConcreteDataAttributePath&, AttributeValueDecoder & aDecoder, X& x) +{ + return aDecoder.Decode(x); +} + +/* + * @brief + * Lists that are string-like should be decoded as char/byte spans. + */ +template>::value && sizeof(std::decay_t) == sizeof(char), bool> = true> +CHIP_ERROR Decode(const ConcreteDataAttributePath& aPath, AttributeValueDecoder & aDecoder, X& x) +{ + Span> span; + CHIP_ERROR err = aDecoder.Decode(span); + if (err = CHIP_NO_ERROR) { + x = X(span.data(), span.size()); + } + return err; +} + + +template>::value && (sizeof(std::decay_t) > sizeof(char)), bool> = true> +CHIP_ERROR Decode(const ConcreteDataAttributePath& aPath, AttributeValueDecoder & aDecoder, X& x) +{ + switch(aPath.mListOp) { + case ConcreteDataAttributePath::ListOperation::DeleteItem: + if (aPath.mListIndex >= x.size()) + return CHIP_ERROR_INVALID_LIST_LENGTH; + x.erase(x.begin() + aPath.mListIndex); + return CHIP_NO_ERROR; + + case ConcreteDataAttributePath::ListOperation::ReplaceItem: + if (aPath.mListIndex >= x.size()) + return CHIP_ERROR_INVALID_LIST_LENGTH; + return aDecoder.Decode(x.begin()[aPath.mListIndex]); + + default: + x.emplace_back(); + return aDecoder.Decode(x.back()); + } +} + +/* + * @brief + * + * Decodes an optional value (struct field, command field, event field). + */ +template +CHIP_ERROR Decode(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder, Optional & x) +{ + // If we are calling this, it means we found the right tag, so just decode + // the item. + return Decode(aPath, aDecoder, x.HasValue() ? x.Value() : x.Emplace()); +} + +/* + * @brief + * + * Decodes a nullable value. + */ +template +CHIP_ERROR Decode(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder, Nullable & x) +{ + if (aDecoder.WillDecodeNull()) + { + x.SetNull(); + return CHIP_NO_ERROR; + } + + // We have a value; decode it. + ReturnErrorOnFailure(Decode(aPath, aDecoder, x.SetNonNull())); + if (!x.HasValidValue()) + { + return CHIP_IM_GLOBAL_STATUS(ConstraintError); + } + return CHIP_NO_ERROR; +} + +} // namespace DataModel +} // namespace app +} // namespace chip diff --git a/examples/dynamic-bridge-app/linux/include/Device.h b/examples/dynamic-bridge-app/linux/include/Device.h new file mode 100644 index 00000000000000..a4a6794b60001a --- /dev/null +++ b/examples/dynamic-bridge-app/linux/include/Device.h @@ -0,0 +1,103 @@ +/* + * + * Copyright (c) 2020 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. + */ + +#pragma once + +#include +#include + +#include +#include + +#include "Clusters.h" + +// Device types for dynamic endpoints: TODO Need a generated file from ZAP to define these! +// (taken from chip-devices.xml) +#define DEVICE_TYPE_BRIDGED_NODE 0x0013 +// (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 +// (taken from chip-devices.xml) +#define DEVICE_TYPE_ROOT_NODE 0x0016 +// (taken from chip-devices.xml) +#define DEVICE_TYPE_BRIDGE 0x000e + +// Device Version for dynamic endpoints: +#define DEVICE_VERSION_DEFAULT 1 + +// This represents a single logical device occupying one endpoint. A composed device consists of multiple +// Device objects that reference a tree. +class Device +{ +public: + Device(chip::Span dataVersions, chip::Span clusters, chip::Span clusterImpl, + const chip::Span & deviceTypeList, chip::EndpointId parentId); + ~Device() = default; + + const chip::Span & versions() { return mDataVersions; } + const chip::Span & deviceTypes() { return mDeviceTypeList; } + const EmberAfEndpointType * endpointType() { return &mEndpointType; } + const chip::Span & clusters() { return mClusterImpl; } + + void SetEndpointId(chip::EndpointId id); + chip::EndpointId GetEndpointId() { return mEndpointId; } + chip::EndpointId GetParentEndpointId() { return mParentEndpointId; } + + const char * GetName(); + void SetName(const char * name); + +private: + chip::EndpointId mParentEndpointId; + chip::EndpointId mEndpointId; + chip::Span mDataVersions; + chip::Span mClusters; + chip::Span mClusterImpl; + chip::Span mDeviceTypeList; + EmberAfEndpointType mEndpointType; + std::string mDeviceName; +}; + +class Action +{ +public: + Action(uint16_t actionId, std::string name, chip::app::Clusters::Actions::ActionTypeEnum type, uint16_t endpointListId, + uint16_t supportedCommands, chip::app::Clusters::Actions::ActionStateEnum status, bool isVisible); + inline void setName(std::string name) { mName = name; }; + inline std::string getName() { return mName; }; + inline chip::app::Clusters::Actions::ActionTypeEnum getType() { return mType; }; + inline chip::app::Clusters::Actions::ActionStateEnum getStatus() { return mStatus; }; + inline uint16_t getActionId() { return mActionId; }; + inline uint16_t getEndpointListId() { return mEndpointListId; }; + inline uint16_t getSupportedCommands() { return mSupportedCommands; }; + inline void setIsVisible(bool isVisible) { mIsVisible = isVisible; }; + inline bool getIsVisible() { return mIsVisible; }; + +private: + std::string mName; + chip::app::Clusters::Actions::ActionTypeEnum mType; + chip::app::Clusters::Actions::ActionStateEnum mStatus; + uint16_t mActionId; + uint16_t mEndpointListId; + uint16_t mSupportedCommands; + bool mIsVisible; +}; + +int AddDeviceEndpoint(Device * dev); +int RemoveDeviceEndpoint(Device * dev); +Device * FindDeviceEndpoint(chip::EndpointId id); diff --git a/examples/bridge-app/linux/include/DeviceImpl.h b/examples/dynamic-bridge-app/linux/include/DeviceImpl.h similarity index 100% rename from examples/bridge-app/linux/include/DeviceImpl.h rename to examples/dynamic-bridge-app/linux/include/DeviceImpl.h diff --git a/examples/dynamic-bridge-app/linux/include/DynamicDevice.h b/examples/dynamic-bridge-app/linux/include/DynamicDevice.h new file mode 100644 index 00000000000000..07bddb237e76ae --- /dev/null +++ b/examples/dynamic-bridge-app/linux/include/DynamicDevice.h @@ -0,0 +1,84 @@ +/* + * + * Copyright (c) 2022 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. + */ + +#pragma once + +#include "Device.h" +#include "GeneratedClusters.h" + +#include +#include + +// This file provides implementations that use dynamic storage +struct DynamicCluster : public CommonCluster +{ + DynamicCluster(std::unique_ptr impl, const chip::CommandId * incomingCommands = nullptr, + const chip::CommandId * outgoingCommands = nullptr) : + CommonCluster(std::move(impl)), + mIncomingCommands(incomingCommands), mOutgoingCommands(outgoingCommands) + { + for (auto & attr : mAttributes) + mAttributeDecls.push_back(attr->GetMetadata()); + } + + std::vector mAttributeDecls; + const chip::CommandId * mIncomingCommands; + const chip::CommandId * mOutgoingCommands; +}; + +class DynamicDevice +{ +public: + DynamicDevice(); + + template + DynamicDevice(Types &... clusters) + {} + + virtual ~DynamicDevice() = default; + + void SetParentEndpointId(chip::EndpointId id) { mParentEndpointId = id; } + + void AddDeviceType(EmberAfDeviceType type); + + // Add each cluster that the device will ever use. + DynamicDevice & AddCluster(std::unique_ptr cluster, const chip::Span & attribs, + const chip::CommandId * incomingCommands, const chip::CommandId * outgoingCommands); + DynamicDevice & AddCluster(CommonCluster * cluster, const chip::Span & attribs, + const chip::CommandId * incomingCommands, const chip::CommandId * outgoingCommands); + + DynamicDevice & AddCluster(std::unique_ptr cluster); + + // After setting all options, create the device. + Device CreateDevice(); + + const std::vector & clusters() const { return mClusterRawPtrs; } + +private: + std::vector> mClusters; + std::vector mClusterRawPtrs; + std::vector mClusterBaseRawPtrs; + + std::vector mClusterDecls; + + std::vector mVersions; + + std::vector mDeviceTypes; + + chip::EndpointId mParentEndpointId = 1; +}; diff --git a/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h new file mode 100644 index 00000000000000..9d826e10fcc289 --- /dev/null +++ b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h @@ -0,0 +1,77 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include + +#include + +#include "Attribute.h" +#include "Clusters.h" +#include "DataModel.h" + +struct CommonAttributeAccessInterface : public chip::app::AttributeAccessInterface +{ + using chip::app::AttributeAccessInterface::AttributeAccessInterface; + + // Find a cluster given a specific endpoint/cluster. Returns nullptr if no such + // cluster exists at that path. + static CommonCluster * FindCluster(const chip::app::ConcreteClusterPath & path); + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override; + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override; + + void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override; + void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override; +}; + +// Required for default initialization of cluster revisions. +static constexpr uint16_t ZCL_DESCRIPTOR_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_FIXED_LABEL_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_ON_OFF_CLUSTER_REVISION = 4; +static constexpr uint16_t ZCL_SWITCH_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_LEVEL_CONTROL_CLUSTER_REVISION = 1; +static constexpr uint16_t ZCL_TEMPERATURE_MEASUREMENT_CLUSTER_REVISION = 1; + +class GeneratedCluster +{ +public: + virtual ~GeneratedCluster() = default; + // Get the ID for this cluster. + virtual chip::ClusterId GetClusterId() = 0; + // Gets the list of available attributes for this cluster. + virtual std::vector GetAttributes() = 0; +}; + +#include "bridge/BridgeClustersImpl.h" + +/* + +namespace clusters { +struct BridgedDeviceBasicCluster : public CommonCluster +{ + static constexpr chip::ClusterId kClusterId = ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID; + + BridgedDeviceBasicCluster(); + + chip::ClusterId GetClusterId() override { return kClusterId; } + CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, + chip::app::AttributeValueDecoder & aDecoder) override; + + chip::Span GetAllAttributes() override + { + static constexpr EmberAfAttributeMetadata kAllAttributes[] = { + { ZCL_REACHABLE_ATTRIBUTE_ID, ZCL_BOOLEAN_ATTRIBUTE_TYPE, 1, 0, 0u }, + }; + return chip::Span(kAllAttributes); + } + + Attribute mReachable; +}; +} // namespace clusters +*/ diff --git a/examples/dynamic-bridge-app/linux/include/main.h b/examples/dynamic-bridge-app/linux/include/main.h new file mode 100644 index 00000000000000..77342a5c5e3ca3 --- /dev/null +++ b/examples/dynamic-bridge-app/linux/include/main.h @@ -0,0 +1,54 @@ +/* + * + * Copyright (c) 2022 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. + */ + +#pragma once + +#include "Device.h" + +class Room +{ +public: + Room() = default; + void SetName(std::string name) { mName = name; } + const std::string & GetName() { return mName; } + chip::app::Clusters::Actions::EndpointListTypeEnum GetType() { return mType; }; + uint16_t GetEndpointListId() { return mEndpointListId; }; + chip::EndpointId * GetEndpointListData() { return mEndpoints.data(); }; + size_t GetEndpointListSize() { return mEndpoints.size(); }; + + void AddEndpoint(chip::EndpointId ep) { mEndpoints.push_back(ep); } + void RemoveEndpoint(chip::EndpointId ep) + { + auto it = std::find(mEndpoints.begin(), mEndpoints.end(), ep); + if (it != mEndpoints.end()) + mEndpoints.erase(it); + } + +private: + std::string mName; + uint16_t mEndpointListId = 0; + chip::app::Clusters::Actions::EndpointListTypeEnum mType; + std::vector mEndpoints; +}; + +static constexpr uint32_t kMaxRooms = 16; +extern Room gRooms[kMaxRooms]; + +Room * FindRoom(const std::string & name); + +chip::Span GetActionListInfo(chip::EndpointId parentId); diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp new file mode 100644 index 00000000000000..afd5d208772126 --- /dev/null +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -0,0 +1,197 @@ +/* + * + * 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 +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Backend.h" + +#include "CommissionableInit.h" +#include "Device.h" +#include "main.h" +#include + +#include "AppMain.h" + +#ifdef PW_RPC_ENABLED +#include "bridge_service.h" +#include "Rpc.h" +#include "pw_rpc_system_server/rpc_server.h" +static chip::rpc::Bridge bridge_service; +#endif + + +#include +#include +#include + +using namespace chip; +using namespace chip::Credentials; +using namespace chip::Inet; +using namespace chip::Transport; +using namespace chip::DeviceLayer; +using namespace chip::app::Clusters; + +static EndpointId gCurrentEndpointId; +static EndpointId gFirstDynamicEndpointId; +static Device * gDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT]; +Room gRooms[kMaxRooms]; + +bool emberAfActionsClusterInstantActionCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, + const Actions::Commands::InstantAction::DecodableType & commandData) +{ + // No actions are implemented, just return status NotFound. + commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::NotFound); + return true; +} + +Device * FindDeviceEndpoint(chip::EndpointId id) +{ + for (auto dev : gDevices) + { + if (dev && dev->GetEndpointId() == id) + return dev; + } + return nullptr; +} + +int AddDeviceEndpoint(Device * dev) +{ + uint8_t index = 0; + while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) + { + if (nullptr == gDevices[index]) + { + gDevices[index] = dev; + EmberAfStatus ret; + while (1) + { + // Todo: Update this to schedule the work rather than use this lock + dev->SetEndpointId(gCurrentEndpointId); + ret = + emberAfSetDynamicEndpoint(index, gCurrentEndpointId, dev->endpointType(), dev->versions(), dev->deviceTypes()); + if (ret == EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(DeviceLayer, "Added device %s to dynamic endpoint %d (index=%d)", dev->GetName(), + gCurrentEndpointId, index); + return index; + } + if (ret != EMBER_ZCL_STATUS_DUPLICATE_EXISTS) + { + ChipLogProgress(DeviceLayer, "Failed to add dynamic endpoint: %d!", ret); + gDevices[index] = nullptr; + 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) + { + // Todo: Update this to schedule the work rather than use this lock + DeviceLayer::StackLock lock; + EndpointId ep = emberAfClearDynamicEndpoint(index); + gDevices[index] = nullptr; + 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; +} + +Room * FindRoom(const std::string & name) +{ + for (auto & room : gRooms) + { + if (room.GetName() == name) + return &room; + } + return nullptr; +} + +chip::Span GetActionListInfo(chip::EndpointId parentId) +{ + return chip::Span(); +} + +void ApplicationInit() +{ +#ifdef PW_RPC_ENABLED + chip::rpc::Init(); + + pw::rpc::system_server::Server().RegisterService(bridge_service); +#endif + + gFirstDynamicEndpointId = static_cast( + static_cast(emberAfEndpointFromIndex(static_cast(emberAfFixedEndpointCount() - 1))) + 1); + gCurrentEndpointId = gFirstDynamicEndpointId; + StartUserInput(); +} + +int main(int argc, char * argv[]) +{ + VerifyOrDie(ChipLinuxAppInit(argc, argv) == 0); + + std::vector clusterAccess; + for(auto& entry : clusters::kKnownClusters) { + clusterAccess.emplace_back(chip::Optional(), entry.id); + } + + ChipLinuxAppMainLoop(); + return 0; +} diff --git a/examples/dynamic-bridge-app/linux/third_party/connectedhomeip b/examples/dynamic-bridge-app/linux/third_party/connectedhomeip new file mode 120000 index 00000000000000..11a54ed360106c --- /dev/null +++ b/examples/dynamic-bridge-app/linux/third_party/connectedhomeip @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/examples/bridge-app/linux/with_pw_rpc.gni b/examples/dynamic-bridge-app/linux/with_pw_rpc.gni similarity index 100% rename from examples/bridge-app/linux/with_pw_rpc.gni rename to examples/dynamic-bridge-app/linux/with_pw_rpc.gni diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index 2f401b5958225d..933306b47849ce 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -270,6 +270,7 @@ def HostTargets(): app_targets.append(target.Extend('tv-app', app=HostApp.TV_APP)) app_targets.append(target.Extend('tv-casting-app', app=HostApp.TV_CASTING)) app_targets.append(target.Extend('bridge', app=HostApp.BRIDGE)) + app_targets.append(target.Extend('dynamic-bridge', app=HostApp.DYNAMIC_BRIDGE)) nodeps_args = dict(enable_ble=False, enable_wifi=False, enable_thread=False, crypto_library=HostCryptoLibrary.MBEDTLS, use_clang=True) diff --git a/scripts/build/builders/host.py b/scripts/build/builders/host.py index a536d6650b5e8f..8c2d602251874f 100644 --- a/scripts/build/builders/host.py +++ b/scripts/build/builders/host.py @@ -57,6 +57,7 @@ class HostApp(Enum): NL_TEST_RUNNER = auto() TV_CASTING = auto() BRIDGE = auto() + DYNAMIC_BRIDGE = auto() def ExamplePath(self): if self == HostApp.ALL_CLUSTERS: @@ -95,6 +96,8 @@ def ExamplePath(self): return 'tv-casting-app/linux' elif self == HostApp.BRIDGE: return 'bridge-app/linux' + elif self == HostApp.DYNAMIC_BRIDGE: + return 'dynamic-bridge-app/linux' else: raise Exception('Unknown app type: %r' % self) diff --git a/scripts/idl/generators/bridge/BridgeClustersCommon.jinja b/scripts/idl/generators/bridge/BridgeClustersCommon.jinja index 0631595d380ebd..9313cb4dffbba7 100644 --- a/scripts/idl/generators/bridge/BridgeClustersCommon.jinja +++ b/scripts/idl/generators/bridge/BridgeClustersCommon.jinja @@ -15,7 +15,7 @@ struct ClusterInfo chip::ClusterId id; const char *name; uint16_t size; - CommonCluster* (*ctor)(void*); + GeneratedCluster* (*ctor)(void*); } static const kKnownClusters[] = { {% for cluster in clusters %} {%- if cluster | dynamicCluster(idl) %} @@ -23,7 +23,7 @@ struct ClusterInfo {{cluster.code}}, "{{cluster.name}}", sizeof({{cluster.name}}Cluster), - [](void *mem) -> CommonCluster* { + [](void *mem) -> GeneratedCluster* { return new(mem) {{cluster.name}}Cluster(); }, }, @@ -31,31 +31,4 @@ struct ClusterInfo {%- endfor %} }; -inline void BridgeRegisterAllAttributeOverrides() -{ -{% for cluster in clusters %} -{%- if cluster | dynamicCluster(idl) %} - static {{cluster.name}}Access {{cluster.name}}; - registerAttributeAccessOverride(&{{cluster.name}}); -{%- endif %} -{%- endfor %} -} - -struct AttrInfo -{ - chip::ClusterId cluster; - chip::AttributeId attr; - const char *name; -} static const kKnownAttributes[] = { -{% for cluster in clusters %} -{%- if cluster | dynamicCluster(idl) %} - -{%- for attr in cluster.attributes %} - { {{cluster.code}}, {{attr.definition.code}}, "{{attr.definition.name | capitalcase}}" }, -{%- endfor %} - -{%- endif %} -{%- endfor %} -}; - } diff --git a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja index 531c93e7da549a..021b7184044b2e 100644 --- a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja +++ b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja @@ -3,7 +3,7 @@ #include "BridgeGlobalStructs.h" namespace clusters { -struct {{cluster.name}}Cluster : public CommonCluster +struct {{cluster.name}}Cluster : public GeneratedCluster { {%- for struct in cluster.structs %} {%- if struct.tag == None %} @@ -39,113 +39,28 @@ struct {{cluster.name}}Cluster : public CommonCluster {%- endif %} {%- endfor %} - - static constexpr chip::ClusterId kClusterId = {{cluster.code}}; - - chip::ClusterId GetClusterId() override { return kClusterId; } - - CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - switch(aPath.mAttributeId) - { + {{cluster.name}}Cluster() : {%- for attr in cluster.attributes %} - case {{attr.definition.code}}: - return m{{attr.definition.name | capitalcase}}.Write(aPath, aDecoder); + m{{attr.definition.name | capitalcase}}(chip::CharSpan("{{attr.definition.name}}"), {{attr.definition.code}}, {{attr | getMask(cluster, idl)}}, {{attr | getRawSizeAndType(cluster, idl)}}{{attr | getInit(cluster, idl)}}){{"," if not loop.last}} {%- endfor %} - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - chip::Span GetAllAttributes() override - { - static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { -{%- for attr in cluster.attributes %} - { {{attr.definition.code}}, {{attr | getRawSizeAndType(cluster, idl)}}, {{attr | getMask(cluster, idl)}} | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, -{%- endfor %} - }; - return chip::Span(kAllAttributes); - } - -{% for attr in cluster.attributes %} - {{attr | getType(cluster, idl)}}{{attr.definition.code}}, {{attr | getMask(cluster, idl)}}, {{attr | getRawSizeAndType(cluster, idl)}}, {{attr.definition | getField(cluster, idl)}}, false> m{{attr.definition.name | capitalcase}}{{attr | getInit(cluster, idl)}}; -{%- endfor %} -}; - -struct {{cluster.name}}Access : public CommonAttributeAccessInterface -{ - {{cluster.name}}Access() : CommonAttributeAccessInterface(chip::Optional(), {{cluster.name}}Cluster::kClusterId) {} - - {{cluster.name}}Cluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) { - CommonCluster * cluster = FindCluster(aPath); - return cluster ? static_cast<{{cluster.name}}Cluster*>(cluster) : nullptr; } - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - - switch(aPath.mAttributeId) { - {%- for attr in cluster.attributes -%} - {%- if attr.is_readable %} - case {{attr.definition.code}}: - return c->m{{attr.definition.name | capitalcase}}.Read(aPath, aEncoder); - - {%- endif %} - {%- endfor %} - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - return c->ForwardWriteToBridge(aPath, aDecoder); - } + static constexpr uint32_t kClusterId ={{cluster.code}}; + chip::ClusterId GetClusterId() override { return kClusterId; } - void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override + std::vector GetAttributes() override { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - {%- for attr in cluster.attributes -%} - {%- if attr.is_writable %} - {%- if attr.definition.is_list %} - case {{attr.definition.code}}: - c->m{{attr.definition.name | capitalcase}}.ListWriteBegin(aPath); - return; - {%- endif %} - {%- endif %} + return std::vector({ + {%- for attr in cluster.attributes %} + static_cast(&m{{attr.definition.name | capitalcase}}), {%- endfor %} - } + }); } - void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - {%- for attr in cluster.attributes -%} - {%- if attr.is_writable %} - {%- if attr.definition.is_list %} - case {{attr.definition.code}}: - c->m{{attr.definition.name | capitalcase}}.ListWriteEnd(aPath, aWriteWasSuccessful); - return; - {%- endif %} - {%- endif %} - {%- endfor %} - } - } +{% for attr in cluster.attributes %} + {{"List" if attr.definition.is_list}}Attribute<{{attr | getType(cluster, idl)}}> m{{attr.definition.name | capitalcase}}; +{%- endfor %} }; } diff --git a/scripts/idl/generators/bridge/BridgeClustersGlobalStructs.jinja b/scripts/idl/generators/bridge/BridgeClustersGlobalStructs.jinja index 45aaef72650015..26a8dfa2ec4d81 100644 --- a/scripts/idl/generators/bridge/BridgeClustersGlobalStructs.jinja +++ b/scripts/idl/generators/bridge/BridgeClustersGlobalStructs.jinja @@ -4,6 +4,9 @@ #include #include +#include +#include + namespace clusters { {% for struct in structs %} diff --git a/scripts/idl/generators/bridge/BridgeClustersHeader.jinja b/scripts/idl/generators/bridge/BridgeClustersHeader.jinja new file mode 100644 index 00000000000000..3ad37a63ed5821 --- /dev/null +++ b/scripts/idl/generators/bridge/BridgeClustersHeader.jinja @@ -0,0 +1,67 @@ +#include +#include + +#include + +#include "bridge/BridgeGlobalStructs.h" + +namespace clusters { + +{%- for cluster in clusters %} +{%- if cluster | dynamicCluster(idl) %} +struct {{cluster.name}}Cluster : public CommonCluster +{ + {%- for struct in cluster.structs %} + {%- if struct.tag == None %} + struct {{struct.name}} + { + CHIP_ERROR Decode(chip::TLV::TLVReader & reader); + CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, chip::TLV::Tag tag) const; + + {%- for field in struct.fields %} + {{field | getField(cluster, idl)}} {{field.name}}; + {%- endfor %} + }; + {%- endif %} + {%- endfor %} + + static constexpr chip::ClusterId kClusterId = {{cluster.code}}; + + chip::ClusterId GetClusterId() override { return kClusterId; } + + CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override; + + template + void AddAllAttributes(T *list) + { + {%- for attr in cluster.attributes %} + list->Add(m{{attr.definition.name | capitalcase}}); + {%- endfor %} + } + + chip::Span GetAllAttributes() override; + +{% for attr in cluster.attributes %} + Attribute<{{attr.definition.code}}, {{attr | getMask(cluster, idl)}}, {{attr | getType(cluster, idl)}}> m{{attr.definition.name | capitalcase}}{{attr | getInit(cluster, idl)}}; +{%- endfor %} +}; + +struct {{cluster.name}}Access : public CommonAttributeAccessInterface +{ + {{cluster.name}}Access(); + + {{cluster.name}}Cluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) + { + CommonCluster * cluster = FindCluster(aPath); + return cluster ? static_cast<{{cluster.name}}Cluster*>(cluster) : nullptr; + } + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override; + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override; + void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override; + void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override; +}; +{%- endif %} +{%- endfor %} + +} diff --git a/scripts/idl/generators/bridge/__init__.py b/scripts/idl/generators/bridge/__init__.py index f3514ba9ce5bcd..2b6f8e7b208250 100644 --- a/scripts/idl/generators/bridge/__init__.py +++ b/scripts/idl/generators/bridge/__init__.py @@ -81,40 +81,33 @@ def get_field_info(definition: Field, cluster: Cluster, idl: Idl): return None -def get_array_count(attr: Attribute): - # TBD how to determine array lengths? - return 1 - - def get_raw_size_and_type(attr: Attribute, cluster: Cluster, idl: Idl): container, cType, size, matterType = get_field_info(attr.definition, cluster, idl) if attr.definition.is_list: - return 'ZCL_ARRAY_ATTRIBUTE_TYPE, {} * {} + 2'.format(size, get_array_count(attr)) + return 'ZCL_ARRAY_ATTRIBUTE_TYPE, {}'.format(size) return '{}, {}'.format(matterType, size) def get_field_type(definition: Field, cluster: Cluster, idl: Idl): container, cType, size, matterType = get_field_info(definition, cluster, idl) if container == 'OctetString': - return 'FixedOctetString<{}, {}>'.format(size, matterType) + return 'std::string' + if definition.is_list: + cType = 'std::vector<{}>'.format(cType) if definition.is_nullable: cType = '::chip::app::DataModel::Nullable<{}>'.format(cType) + if definition.is_nullable: + cType = '::chip::Optional<{}>'.format(cType) return cType def get_attr_type(attr: Attribute, cluster: Cluster, idl: Idl): - if attr.definition.is_list: - count = get_array_count(attr) - nullable = 'false' - if attr.definition.is_nullable: - nullable = 'true' - return 'ArrayAttribute<{}, {}, '.format(count, nullable) - return 'Attribute<' + return get_field_type(attr.definition, cluster, idl) def get_attr_init(attr: Attribute, cluster: Cluster, idl: Idl): if attr.definition.name == 'clusterRevision': - return ' = ZCL_' + camel_to_const(cluster.name) + '_CLUSTER_REVISION' + return ', ZCL_' + camel_to_const(cluster.name) + '_CLUSTER_REVISION' return '' diff --git a/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeClustersImpl.h b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeClustersImpl.h index 8a3b84eeea5281..bb1f891a88538e 100644 --- a/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeClustersImpl.h +++ b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeClustersImpl.h @@ -10,35 +10,17 @@ struct ClusterInfo chip::ClusterId id; const char *name; uint16_t size; - CommonCluster* (*ctor)(void*); + GeneratedCluster* (*ctor)(void*); } static const kKnownClusters[] = { { 10, "DemoCluster", sizeof(DemoClusterCluster), - [](void *mem) -> CommonCluster* { + [](void *mem) -> GeneratedCluster* { return new(mem) DemoClusterCluster(); }, }, }; -inline void BridgeRegisterAllAttributeOverrides() -{ - - static DemoClusterAccess DemoCluster; - registerAttributeAccessOverride(&DemoCluster); -} - -struct AttrInfo -{ - chip::ClusterId cluster; - chip::AttributeId attr; - const char *name; -} static const kKnownAttributes[] = { - - { 10, 5, "SingleFailSafe" }, - { 10, 100, "ArmFailsafes" }, -}; - } \ No newline at end of file diff --git a/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeGlobalStructs.h b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeGlobalStructs.h index 5fcca27baf8f3d..59d383a227efbf 100644 --- a/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeGlobalStructs.h +++ b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/BridgeGlobalStructs.h @@ -4,6 +4,9 @@ #include #include +#include +#include + namespace clusters { diff --git a/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoCluster.h b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoCluster.h index f94e465d8d4a58..96d7f49db331b9 100644 --- a/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoCluster.h +++ b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoCluster.h @@ -3,100 +3,28 @@ #include "BridgeGlobalStructs.h" namespace clusters { -struct DemoClusterCluster : public CommonCluster +struct DemoClusterCluster : public GeneratedCluster { - - static constexpr chip::ClusterId kClusterId = 10; - - chip::ClusterId GetClusterId() override { return kClusterId; } - - CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - switch(aPath.mAttributeId) - { - case 5: - return mSingleFailSafe.Write(aPath, aDecoder); - case 100: - return mArmFailsafes.Write(aPath, aDecoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - chip::Span GetAllAttributes() override + DemoClusterCluster() : + mSingleFailSafe(chip::CharSpan("singleFailSafe"), 5, ATTRIBUTE_MASK_WRITABLE, ZCL_STRUCT_ATTRIBUTE_TYPE, sizeof(ArmFailSafeRequest)), + mArmFailsafes(chip::CharSpan("armFailsafes"), 100, ATTRIBUTE_MASK_WRITABLE, ZCL_ARRAY_ATTRIBUTE_TYPE, sizeof(ArmFailSafeRequest)) { - static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { - { 5, ZCL_STRUCT_ATTRIBUTE_TYPE, sizeof(ArmFailSafeRequest), ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, - { 100, ZCL_ARRAY_ATTRIBUTE_TYPE, sizeof(ArmFailSafeRequest) * 1 + 2, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, - }; - return chip::Span(kAllAttributes); } + chip::ClusterId GetClusterId() override { return 10; } - Attribute<5, ATTRIBUTE_MASK_WRITABLE, ZCL_STRUCT_ATTRIBUTE_TYPE, sizeof(ArmFailSafeRequest), ArmFailSafeRequest, false> mSingleFailSafe; - ArrayAttribute<1, false, 100, ATTRIBUTE_MASK_WRITABLE, ZCL_ARRAY_ATTRIBUTE_TYPE, sizeof(ArmFailSafeRequest) * 1 + 2, ArmFailSafeRequest, false> mArmFailsafes; -}; - -struct DemoClusterAccess : public CommonAttributeAccessInterface -{ - DemoClusterAccess() : CommonAttributeAccessInterface(chip::Optional(), DemoClusterCluster::kClusterId) {} - - DemoClusterCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) + std::vector GetAttributes() override { - CommonCluster * cluster = FindCluster(aPath); - return cluster ? static_cast(cluster) : nullptr; + return std::vector({ + static_cast(&mSingleFailSafe), + static_cast(&mArmFailsafes), + }); } - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - switch(aPath.mAttributeId) { - case 5: - return c->mSingleFailSafe.Read(aPath, aEncoder); - case 100: - return c->mArmFailsafes.Read(aPath, aEncoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - return c->ForwardWriteToBridge(aPath, aDecoder); - } - - void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - case 100: - c->mArmFailsafes.ListWriteBegin(aPath); - return; - } - } - - void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - case 100: - c->mArmFailsafes.ListWriteEnd(aPath, aWriteWasSuccessful); - return; - } - } + Attribute mSingleFailSafe; + ListAttribute> mArmFailsafes; }; } \ No newline at end of file diff --git a/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeClustersImpl.h b/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeClustersImpl.h index 3b102344a117c4..d56fe18f98808d 100644 --- a/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeClustersImpl.h +++ b/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeClustersImpl.h @@ -10,35 +10,17 @@ struct ClusterInfo chip::ClusterId id; const char *name; uint16_t size; - CommonCluster* (*ctor)(void*); + GeneratedCluster* (*ctor)(void*); } static const kKnownClusters[] = { { 18, "DemoCluster", sizeof(DemoClusterCluster), - [](void *mem) -> CommonCluster* { + [](void *mem) -> GeneratedCluster* { return new(mem) DemoClusterCluster(); }, }, }; -inline void BridgeRegisterAllAttributeOverrides() -{ - - static DemoClusterAccess DemoCluster; - registerAttributeAccessOverride(&DemoCluster); -} - -struct AttrInfo -{ - chip::ClusterId cluster; - chip::AttributeId attr; - const char *name; -} static const kKnownAttributes[] = { - - { 18, 32, "SingleLabel" }, - { 18, 33, "SomeLabels" }, -}; - } \ No newline at end of file diff --git a/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeGlobalStructs.h b/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeGlobalStructs.h index 3b139c394cd5e7..8ebe77751e6457 100644 --- a/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeGlobalStructs.h +++ b/scripts/idl/tests/outputs/global_struct_attribute/bridge/BridgeGlobalStructs.h @@ -4,6 +4,9 @@ #include #include +#include +#include + namespace clusters { @@ -27,8 +30,8 @@ struct LabelStruct t.value = value; return t.Encode(writer, tag); } - FixedOctetString<16, ZCL_CHAR_STRING_ATTRIBUTE_TYPE> label; - FixedOctetString<16, ZCL_CHAR_STRING_ATTRIBUTE_TYPE> value; + std::string label; + std::string value; }; } \ No newline at end of file diff --git a/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoCluster.h b/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoCluster.h index 47dca69f6106a8..e52cc156a5c7ce 100644 --- a/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoCluster.h +++ b/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoCluster.h @@ -3,100 +3,28 @@ #include "BridgeGlobalStructs.h" namespace clusters { -struct DemoClusterCluster : public CommonCluster +struct DemoClusterCluster : public GeneratedCluster { - - static constexpr chip::ClusterId kClusterId = 18; - - chip::ClusterId GetClusterId() override { return kClusterId; } - - CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - switch(aPath.mAttributeId) - { - case 32: - return mSingleLabel.Write(aPath, aDecoder); - case 33: - return mSomeLabels.Write(aPath, aDecoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - chip::Span GetAllAttributes() override + DemoClusterCluster() : + mSingleLabel(chip::CharSpan("singleLabel"), 32, ATTRIBUTE_MASK_WRITABLE, ZCL_STRUCT_ATTRIBUTE_TYPE, sizeof(LabelStruct)), + mSomeLabels(chip::CharSpan("someLabels"), 33, ATTRIBUTE_MASK_WRITABLE, ZCL_ARRAY_ATTRIBUTE_TYPE, sizeof(LabelStruct)) { - static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { - { 32, ZCL_STRUCT_ATTRIBUTE_TYPE, sizeof(LabelStruct), ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, - { 33, ZCL_ARRAY_ATTRIBUTE_TYPE, sizeof(LabelStruct) * 1 + 2, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, - }; - return chip::Span(kAllAttributes); } + chip::ClusterId GetClusterId() override { return 18; } - Attribute<32, ATTRIBUTE_MASK_WRITABLE, ZCL_STRUCT_ATTRIBUTE_TYPE, sizeof(LabelStruct), LabelStruct, false> mSingleLabel; - ArrayAttribute<1, false, 33, ATTRIBUTE_MASK_WRITABLE, ZCL_ARRAY_ATTRIBUTE_TYPE, sizeof(LabelStruct) * 1 + 2, LabelStruct, false> mSomeLabels; -}; - -struct DemoClusterAccess : public CommonAttributeAccessInterface -{ - DemoClusterAccess() : CommonAttributeAccessInterface(chip::Optional(), DemoClusterCluster::kClusterId) {} - - DemoClusterCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) + std::vector GetAttributes() override { - CommonCluster * cluster = FindCluster(aPath); - return cluster ? static_cast(cluster) : nullptr; + return std::vector({ + static_cast(&mSingleLabel), + static_cast(&mSomeLabels), + }); } - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - switch(aPath.mAttributeId) { - case 32: - return c->mSingleLabel.Read(aPath, aEncoder); - case 33: - return c->mSomeLabels.Read(aPath, aEncoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - return c->ForwardWriteToBridge(aPath, aDecoder); - } - - void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - case 33: - c->mSomeLabels.ListWriteBegin(aPath); - return; - } - } - - void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - case 33: - c->mSomeLabels.ListWriteEnd(aPath, aWriteWasSuccessful); - return; - } - } + Attribute mSingleLabel; + ListAttribute> mSomeLabels; }; } \ No newline at end of file diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/BridgeClustersImpl.h b/scripts/idl/tests/outputs/several_clusters/bridge/BridgeClustersImpl.h index b008f6743cf09d..33e1f029b90193 100644 --- a/scripts/idl/tests/outputs/several_clusters/bridge/BridgeClustersImpl.h +++ b/scripts/idl/tests/outputs/several_clusters/bridge/BridgeClustersImpl.h @@ -12,14 +12,14 @@ struct ClusterInfo chip::ClusterId id; const char *name; uint16_t size; - CommonCluster* (*ctor)(void*); + GeneratedCluster* (*ctor)(void*); } static const kKnownClusters[] = { { 1, "First", sizeof(FirstCluster), - [](void *mem) -> CommonCluster* { + [](void *mem) -> GeneratedCluster* { return new(mem) FirstCluster(); }, }, @@ -27,7 +27,7 @@ struct ClusterInfo 2, "Second", sizeof(SecondCluster), - [](void *mem) -> CommonCluster* { + [](void *mem) -> GeneratedCluster* { return new(mem) SecondCluster(); }, }, @@ -35,33 +35,10 @@ struct ClusterInfo 3, "Third", sizeof(ThirdCluster), - [](void *mem) -> CommonCluster* { + [](void *mem) -> GeneratedCluster* { return new(mem) ThirdCluster(); }, }, }; -inline void BridgeRegisterAllAttributeOverrides() -{ - - static FirstAccess First; - registerAttributeAccessOverride(&First); - static SecondAccess Second; - registerAttributeAccessOverride(&Second); - static ThirdAccess Third; - registerAttributeAccessOverride(&Third); -} - -struct AttrInfo -{ - chip::ClusterId cluster; - chip::AttributeId attr; - const char *name; -} static const kKnownAttributes[] = { - - { 1, 1, "SomeInteger" }, - { 2, 123, "SomeBytes" }, - { 3, 10, "SomeEnum" }, -}; - } \ No newline at end of file diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/BridgeGlobalStructs.h b/scripts/idl/tests/outputs/several_clusters/bridge/BridgeGlobalStructs.h index 5fcca27baf8f3d..59d383a227efbf 100644 --- a/scripts/idl/tests/outputs/several_clusters/bridge/BridgeGlobalStructs.h +++ b/scripts/idl/tests/outputs/several_clusters/bridge/BridgeGlobalStructs.h @@ -4,6 +4,9 @@ #include #include +#include +#include + namespace clusters { diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/First.h b/scripts/idl/tests/outputs/several_clusters/bridge/First.h index bff536ec7a1596..1dd55b2b7e8de7 100644 --- a/scripts/idl/tests/outputs/several_clusters/bridge/First.h +++ b/scripts/idl/tests/outputs/several_clusters/bridge/First.h @@ -3,88 +3,25 @@ #include "BridgeGlobalStructs.h" namespace clusters { -struct FirstCluster : public CommonCluster +struct FirstCluster : public GeneratedCluster { - - static constexpr chip::ClusterId kClusterId = 1; - - chip::ClusterId GetClusterId() override { return kClusterId; } - - CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - switch(aPath.mAttributeId) - { - case 1: - return mSomeInteger.Write(aPath, aDecoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - chip::Span GetAllAttributes() override + FirstCluster() : + mSomeInteger(chip::CharSpan("someInteger"), 1, ATTRIBUTE_MASK_WRITABLE, ZCL_INT16U_ATTRIBUTE_TYPE, 2) { - static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { - { 1, ZCL_INT16U_ATTRIBUTE_TYPE, 2, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, - }; - return chip::Span(kAllAttributes); } + chip::ClusterId GetClusterId() override { return 1; } - Attribute<1, ATTRIBUTE_MASK_WRITABLE, ZCL_INT16U_ATTRIBUTE_TYPE, 2, uint16_t, false> mSomeInteger; -}; - -struct FirstAccess : public CommonAttributeAccessInterface -{ - FirstAccess() : CommonAttributeAccessInterface(chip::Optional(), FirstCluster::kClusterId) {} - - FirstCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) + std::vector GetAttributes() override { - CommonCluster * cluster = FindCluster(aPath); - return cluster ? static_cast(cluster) : nullptr; + return std::vector({ + static_cast(&mSomeInteger), + }); } - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - switch(aPath.mAttributeId) { - case 1: - return c->mSomeInteger.Read(aPath, aEncoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - return c->ForwardWriteToBridge(aPath, aDecoder); - } - - void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - } - } - - void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - } - } + Attribute mSomeInteger; }; } \ No newline at end of file diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/Second.h b/scripts/idl/tests/outputs/several_clusters/bridge/Second.h index ac765945057e50..e31850db1e6c28 100644 --- a/scripts/idl/tests/outputs/several_clusters/bridge/Second.h +++ b/scripts/idl/tests/outputs/several_clusters/bridge/Second.h @@ -3,88 +3,25 @@ #include "BridgeGlobalStructs.h" namespace clusters { -struct SecondCluster : public CommonCluster +struct SecondCluster : public GeneratedCluster { - - static constexpr chip::ClusterId kClusterId = 2; - - chip::ClusterId GetClusterId() override { return kClusterId; } - - CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - switch(aPath.mAttributeId) - { - case 123: - return mSomeBytes.Write(aPath, aDecoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - chip::Span GetAllAttributes() override + SecondCluster() : + mSomeBytes(chip::CharSpan("someBytes"), 123, 0, ZCL_OCTET_STRING_ATTRIBUTE_TYPE, 32) { - static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { - { 123, ZCL_OCTET_STRING_ATTRIBUTE_TYPE, 32, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, - }; - return chip::Span(kAllAttributes); } + chip::ClusterId GetClusterId() override { return 2; } - Attribute<123, 0, ZCL_OCTET_STRING_ATTRIBUTE_TYPE, 32, FixedOctetString<32, ZCL_OCTET_STRING_ATTRIBUTE_TYPE>, false> mSomeBytes; -}; - -struct SecondAccess : public CommonAttributeAccessInterface -{ - SecondAccess() : CommonAttributeAccessInterface(chip::Optional(), SecondCluster::kClusterId) {} - - SecondCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) + std::vector GetAttributes() override { - CommonCluster * cluster = FindCluster(aPath); - return cluster ? static_cast(cluster) : nullptr; + return std::vector({ + static_cast(&mSomeBytes), + }); } - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - switch(aPath.mAttributeId) { - case 123: - return c->mSomeBytes.Read(aPath, aEncoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - return c->ForwardWriteToBridge(aPath, aDecoder); - } - - void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - } - } - - void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - } - } + Attribute mSomeBytes; }; } \ No newline at end of file diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/Third.h b/scripts/idl/tests/outputs/several_clusters/bridge/Third.h index c19611202e0c24..5ec29b498bb170 100644 --- a/scripts/idl/tests/outputs/several_clusters/bridge/Third.h +++ b/scripts/idl/tests/outputs/several_clusters/bridge/Third.h @@ -3,88 +3,25 @@ #include "BridgeGlobalStructs.h" namespace clusters { -struct ThirdCluster : public CommonCluster +struct ThirdCluster : public GeneratedCluster { - - static constexpr chip::ClusterId kClusterId = 3; - - chip::ClusterId GetClusterId() override { return kClusterId; } - - CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - switch(aPath.mAttributeId) - { - case 10: - return mSomeEnum.Write(aPath, aDecoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - chip::Span GetAllAttributes() override + ThirdCluster() : + mSomeEnum(chip::CharSpan("someEnum"), 10, ATTRIBUTE_MASK_WRITABLE, ZCL_ENUM8_ATTRIBUTE_TYPE, 1) { - static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { - { 10, ZCL_ENUM8_ATTRIBUTE_TYPE, 1, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, - }; - return chip::Span(kAllAttributes); } + chip::ClusterId GetClusterId() override { return 3; } - Attribute<10, ATTRIBUTE_MASK_WRITABLE, ZCL_ENUM8_ATTRIBUTE_TYPE, 1, uint8_t, false> mSomeEnum; -}; - -struct ThirdAccess : public CommonAttributeAccessInterface -{ - ThirdAccess() : CommonAttributeAccessInterface(chip::Optional(), ThirdCluster::kClusterId) {} - - ThirdCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) + std::vector GetAttributes() override { - CommonCluster * cluster = FindCluster(aPath); - return cluster ? static_cast(cluster) : nullptr; + return std::vector({ + static_cast(&mSomeEnum), + }); } - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - switch(aPath.mAttributeId) { - case 10: - return c->mSomeEnum.Read(aPath, aEncoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - return c->ForwardWriteToBridge(aPath, aDecoder); - } - - void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - } - } - - void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - } - } + Attribute mSomeEnum; }; } \ No newline at end of file diff --git a/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeClustersImpl.h b/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeClustersImpl.h index 3375275f87ee02..ae31264ddd048d 100644 --- a/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeClustersImpl.h +++ b/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeClustersImpl.h @@ -10,34 +10,17 @@ struct ClusterInfo chip::ClusterId id; const char *name; uint16_t size; - CommonCluster* (*ctor)(void*); + GeneratedCluster* (*ctor)(void*); } static const kKnownClusters[] = { { 123, "MyCluster", sizeof(MyClusterCluster), - [](void *mem) -> CommonCluster* { + [](void *mem) -> GeneratedCluster* { return new(mem) MyClusterCluster(); }, }, }; -inline void BridgeRegisterAllAttributeOverrides() -{ - - static MyClusterAccess MyCluster; - registerAttributeAccessOverride(&MyCluster); -} - -struct AttrInfo -{ - chip::ClusterId cluster; - chip::AttributeId attr; - const char *name; -} static const kKnownAttributes[] = { - - { 123, 1, "ClusterAttr" }, -}; - } \ No newline at end of file diff --git a/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeGlobalStructs.h b/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeGlobalStructs.h index 5fcca27baf8f3d..59d383a227efbf 100644 --- a/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeGlobalStructs.h +++ b/scripts/idl/tests/outputs/simple_attribute/bridge/BridgeGlobalStructs.h @@ -4,6 +4,9 @@ #include #include +#include +#include + namespace clusters { diff --git a/scripts/idl/tests/outputs/simple_attribute/bridge/MyCluster.h b/scripts/idl/tests/outputs/simple_attribute/bridge/MyCluster.h index 709d83ad748dc1..30c9636034054f 100644 --- a/scripts/idl/tests/outputs/simple_attribute/bridge/MyCluster.h +++ b/scripts/idl/tests/outputs/simple_attribute/bridge/MyCluster.h @@ -3,88 +3,25 @@ #include "BridgeGlobalStructs.h" namespace clusters { -struct MyClusterCluster : public CommonCluster +struct MyClusterCluster : public GeneratedCluster { - - static constexpr chip::ClusterId kClusterId = 123; - - chip::ClusterId GetClusterId() override { return kClusterId; } - - CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - switch(aPath.mAttributeId) - { - case 1: - return mClusterAttr.Write(aPath, aDecoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - chip::Span GetAllAttributes() override + MyClusterCluster() : + mClusterAttr(chip::CharSpan("clusterAttr"), 1, ATTRIBUTE_MASK_WRITABLE, ZCL_INT16U_ATTRIBUTE_TYPE, 2) { - static constexpr const EmberAfAttributeMetadata kAllAttributes[] = { - { 1, ZCL_INT16U_ATTRIBUTE_TYPE, 2, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, - }; - return chip::Span(kAllAttributes); } + chip::ClusterId GetClusterId() override { return 123; } - Attribute<1, ATTRIBUTE_MASK_WRITABLE, ZCL_INT16U_ATTRIBUTE_TYPE, 2, uint16_t, false> mClusterAttr; -}; - -struct MyClusterAccess : public CommonAttributeAccessInterface -{ - MyClusterAccess() : CommonAttributeAccessInterface(chip::Optional(), MyClusterCluster::kClusterId) {} - - MyClusterCluster* GetCluster(const chip::app::ConcreteClusterPath & aPath) + std::vector GetAttributes() override { - CommonCluster * cluster = FindCluster(aPath); - return cluster ? static_cast(cluster) : nullptr; + return std::vector({ + static_cast(&mClusterAttr), + }); } - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - switch(aPath.mAttributeId) { - case 1: - return c->mClusterAttr.Read(aPath, aEncoder); - default: - return CHIP_ERROR_NOT_IMPLEMENTED; - } - } - - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override - { - auto * c = GetCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - return c->ForwardWriteToBridge(aPath, aDecoder); - } - - void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - } - } - - void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override - { - auto * c = GetCluster(aPath); - if (!c) - return; - - switch(aPath.mAttributeId) { - } - } + Attribute mClusterAttr; }; } \ No newline at end of file diff --git a/src/app/AttributeAccessInterface.h b/src/app/AttributeAccessInterface.h index fb308263e40c18..37e90c90159ba1 100644 --- a/src/app/AttributeAccessInterface.h +++ b/src/app/AttributeAccessInterface.h @@ -344,6 +344,11 @@ class AttributeValueDecoder return CHIP_NO_ERROR; } + /** + * Is the next element of the stream NULL. + */ + bool WillDecodeNull() const { return mReader.GetType() == TLV::kTLVType_Null; } + bool TriedDecode() const { return mTriedDecode; } /** From b0b366c14e17e356008f9fb34d114b5163fe66a7 Mon Sep 17 00:00:00 2001 From: Albert Chaulk Date: Wed, 28 Sep 2022 12:02:19 -0400 Subject: [PATCH 09/14] comments --- .../dynamic-bridge-app/linux/Clusters.cpp | 59 +-------- .../linux/DynamicDevice.cpp | 4 + .../linux/UserInputBackend.cpp | 30 ++--- .../linux/bridge_service.cpp | 17 +-- .../linux/bridged-actions-stub.cpp | 2 +- .../linux/include/ActionCluster.h | 50 +++++++ .../linux/include/Clusters.h | 9 +- .../dynamic-bridge-app/linux/include/Device.h | 45 +------ .../linux/include/DeviceImpl.h | 21 --- .../linux/include/GeneratedClusters.h | 54 +------- .../include/{ => data-model}/Attribute.h | 38 +++--- .../include/{ => data-model}/DataModel.h | 123 ++++++++++++------ .../dynamic-bridge-app/linux/include/main.h | 10 ++ examples/dynamic-bridge-app/linux/main.cpp | 112 +++++++++++++++- .../generators/bridge/BridgeClustersCpp.jinja | 1 + 15 files changed, 303 insertions(+), 272 deletions(-) create mode 100644 examples/dynamic-bridge-app/linux/include/ActionCluster.h delete mode 100644 examples/dynamic-bridge-app/linux/include/DeviceImpl.h rename examples/dynamic-bridge-app/linux/include/{ => data-model}/Attribute.h (71%) rename examples/dynamic-bridge-app/linux/include/{ => data-model}/DataModel.h (55%) diff --git a/examples/dynamic-bridge-app/linux/Clusters.cpp b/examples/dynamic-bridge-app/linux/Clusters.cpp index 28b5b1945e3c37..016526c3dfb7ef 100644 --- a/examples/dynamic-bridge-app/linux/Clusters.cpp +++ b/examples/dynamic-bridge-app/linux/Clusters.cpp @@ -2,63 +2,6 @@ #include "Device.h" -CommonCluster * CommonAttributeAccessInterface::FindCluster(const chip::app::ConcreteClusterPath & path) -{ - Device * dev = FindDeviceEndpoint(path.mEndpointId); - if (dev) - { - for (auto c : dev->clusters()) - { - if (c->GetClusterId() == path.mClusterId) - return static_cast(c); - } - } - return nullptr; -} - -CHIP_ERROR CommonAttributeAccessInterface::Read(const chip::app::ConcreteReadAttributePath & aPath, - chip::app::AttributeValueEncoder & aEncoder) -{ - CommonCluster * c = FindCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - AttributeInterface * a = c->FindAttribute(aPath.mAttributeId); - if (!a) - return CHIP_ERROR_NOT_IMPLEMENTED; - return a->Read(aPath, aEncoder); -} - -CHIP_ERROR CommonAttributeAccessInterface::Write(const chip::app::ConcreteDataAttributePath & aPath, - chip::app::AttributeValueDecoder & aDecoder) -{ - CommonCluster * c = FindCluster(aPath); - if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; - return c->ForwardWriteToBridge(aPath, aDecoder); -} - -void CommonAttributeAccessInterface::OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) -{ - CommonCluster * c = FindCluster(aPath); - if (c) - { - AttributeInterface * a = c->FindAttribute(aPath.mAttributeId); - if (a) - a->ListWriteBegin(aPath); - } -} - -void CommonAttributeAccessInterface::OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) -{ - CommonCluster * c = FindCluster(aPath); - if (c) - { - AttributeInterface * a = c->FindAttribute(aPath.mAttributeId); - if (a) - a->ListWriteEnd(aPath, aWriteWasSuccessful); - } -} - CommonCluster::CommonCluster(std::unique_ptr cluster) : mAttributes(cluster->GetAttributes()), mStorage(std::move(cluster)) {} @@ -133,7 +76,7 @@ void CommonCluster::OnUpdated(chip::AttributeId attr) MatterReportingAttributeChangeCallback(GetEndpointId(), GetClusterId(), attr); } -bool CommonCluster::Push(chip::AttributeId attr, chip::TLV::TLVReader & reader) +bool CommonCluster::Write(chip::AttributeId attr, chip::TLV::TLVReader & reader) { chip::app::AttributeValueDecoder decoder(reader, chip::Access::SubjectDescriptor()); if (WriteFromBridge(chip::app::ConcreteDataAttributePath(GetEndpointId(), GetClusterId(), attr), decoder) != CHIP_NO_ERROR) diff --git a/examples/dynamic-bridge-app/linux/DynamicDevice.cpp b/examples/dynamic-bridge-app/linux/DynamicDevice.cpp index 415dbac8be9fa5..98b411a6e631f1 100644 --- a/examples/dynamic-bridge-app/linux/DynamicDevice.cpp +++ b/examples/dynamic-bridge-app/linux/DynamicDevice.cpp @@ -19,6 +19,10 @@ #include "DynamicDevice.h" +#define DEVICE_TYPE_BRIDGED_NODE 0x0013 +// Device Version for dynamic endpoints: +#define DEVICE_VERSION_DEFAULT 1 + DynamicDevice::DynamicDevice() {} void DynamicDevice::AddDeviceType(EmberAfDeviceType type) diff --git a/examples/dynamic-bridge-app/linux/UserInputBackend.cpp b/examples/dynamic-bridge-app/linux/UserInputBackend.cpp index 3905e309ae8097..9bdf4b8e689710 100644 --- a/examples/dynamic-bridge-app/linux/UserInputBackend.cpp +++ b/examples/dynamic-bridge-app/linux/UserInputBackend.cpp @@ -117,15 +117,14 @@ void AddCluster(const std::vector & tokens) return; } - for (const auto & cluster : clusters::kKnownClusters) + auto c = CreateCluster(cluster_name.c_str()); + if (c) { - if (cluster_name == cluster.name) - { - g_pending->AddCluster( - std::make_unique(std::unique_ptr(cluster.ctor(::operator new(cluster.size))))); - printf("Added cluster %s/%d\n", cluster.name, cluster.id); - return; - } + g_pending->AddCluster(std::make_unique(std::move(c))); + } + else + { + printf("No such cluster '%s'\n", cluster_name.c_str()); } } @@ -242,17 +241,12 @@ ClusterInterface * FindCluster(DynamicDevice * dev, const std::string & clusterI const char * end = start + clusterId.size(); if (std::from_chars(start, end, id).ptr != end) { - id = 0; - for (const auto & c : clusters::kKnownClusters) + auto r = LookupClusterByName(clusterId.c_str()); + if (r.HasValue()) { - if (clusterId == c.name) - { - id = c.id; - break; - } - } - if (!id) return nullptr; + } + id = r.Value(); } for (auto * c : dev->clusters()) @@ -388,7 +382,7 @@ void SetValue(const std::vector & tokens) rd.Init(data.data(), data.size()); rd.Next(); - if (!cluster->Push(attr->attributeId, rd)) + if (!cluster->Write(attr->attributeId, rd)) { printf("Write failed\n"); } diff --git a/examples/dynamic-bridge-app/linux/bridge_service.cpp b/examples/dynamic-bridge-app/linux/bridge_service.cpp index c5b55dfbfde785..9a45fbd36c49d0 100644 --- a/examples/dynamic-bridge-app/linux/bridge_service.cpp +++ b/examples/dynamic-bridge-app/linux/bridge_service.cpp @@ -24,18 +24,6 @@ namespace chip { namespace rpc { -namespace { -const clusters::ClusterInfo * FindCluster(uint32_t id) -{ - for (const auto & cluster : clusters::kKnownClusters) - { - if (id == cluster.id) - return &cluster; - } - return nullptr; -} -} // namespace - ::pw::Status Bridge::Add(const ::chip_rpc_bridge_AddDevice & request, ::chip_rpc_bridge_AddDeviceResponse & response) { std::unique_ptr pending; @@ -47,14 +35,13 @@ ::pw::Status Bridge::Add(const ::chip_rpc_bridge_AddDevice & request, ::chip_rpc { const chip_rpc_bridge_Cluster & c = request.clusters[i]; - auto cluster = FindCluster(c.cluster_id); + auto cluster = CreateCluster(c.cluster_id); if (!cluster) { return pw::Status::InvalidArgument(); } - pending->AddCluster( - std::make_unique(std::unique_ptr(cluster->ctor(::operator new(cluster->size))))); + pending->AddCluster(std::make_unique(std::move(cluster))); } for (pb_size_t i = 0; i < request.device_types_count; i++) diff --git a/examples/dynamic-bridge-app/linux/bridged-actions-stub.cpp b/examples/dynamic-bridge-app/linux/bridged-actions-stub.cpp index 6c0f7cf8eb680e..f65dde8a3c9da6 100644 --- a/examples/dynamic-bridge-app/linux/bridged-actions-stub.cpp +++ b/examples/dynamic-bridge-app/linux/bridged-actions-stub.cpp @@ -26,7 +26,7 @@ #include -#include "Device.h" +#include "ActionCluster.h" #include "main.h" using namespace chip; diff --git a/examples/dynamic-bridge-app/linux/include/ActionCluster.h b/examples/dynamic-bridge-app/linux/include/ActionCluster.h new file mode 100644 index 00000000000000..4253cb1d3244ff --- /dev/null +++ b/examples/dynamic-bridge-app/linux/include/ActionCluster.h @@ -0,0 +1,50 @@ +/* + * + * Copyright (c) 2020 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. + */ + +#pragma once + +#include +#include + +#include +#include + +class Action +{ +public: + Action(uint16_t actionId, std::string name, chip::app::Clusters::Actions::ActionTypeEnum type, uint16_t endpointListId, + uint16_t supportedCommands, chip::app::Clusters::Actions::ActionStateEnum status, bool isVisible); + inline void setName(std::string name) { mName = name; }; + inline std::string getName() { return mName; }; + inline chip::app::Clusters::Actions::ActionTypeEnum getType() { return mType; }; + inline chip::app::Clusters::Actions::ActionStateEnum getStatus() { return mStatus; }; + inline uint16_t getActionId() { return mActionId; }; + inline uint16_t getEndpointListId() { return mEndpointListId; }; + inline uint16_t getSupportedCommands() { return mSupportedCommands; }; + inline void setIsVisible(bool isVisible) { mIsVisible = isVisible; }; + inline bool getIsVisible() { return mIsVisible; }; + +private: + std::string mName; + chip::app::Clusters::Actions::ActionTypeEnum mType; + chip::app::Clusters::Actions::ActionStateEnum mStatus; + uint16_t mActionId; + uint16_t mEndpointListId; + uint16_t mSupportedCommands; + bool mIsVisible; +}; diff --git a/examples/dynamic-bridge-app/linux/include/Clusters.h b/examples/dynamic-bridge-app/linux/include/Clusters.h index 755c882eefbcbf..94c50f95004de7 100644 --- a/examples/dynamic-bridge-app/linux/include/Clusters.h +++ b/examples/dynamic-bridge-app/linux/include/Clusters.h @@ -29,7 +29,8 @@ #include -#include "Attribute.h" +#include "data-model/Attribute.h" +#include "GeneratedClusters.h" // This is the interface to cluster implementations, providing access to manipulate attributes. class ClusterInterface @@ -49,11 +50,9 @@ class ClusterInterface virtual AttributeInterface * FindAttributeByName(chip::CharSpan name) = 0; // Write the given TLV encoded value to the given attribute. Can write // normally read-only values. Nofitied matter that the value has changed. - virtual bool Push(chip::AttributeId attr, chip::TLV::TLVReader & reader) = 0; + virtual bool Write(chip::AttributeId attr, chip::TLV::TLVReader & reader) = 0; }; -class GeneratedCluster; - struct CommonCluster; typedef std::function PropagateWriteCB; @@ -88,7 +87,7 @@ struct CommonCluster : public ClusterInterface // Force a write of a given attribute. Can write normally read-only values. // Calls OnUpdated after the write finishes. - bool Push(chip::AttributeId attr, chip::TLV::TLVReader & reader) override; + bool Write(chip::AttributeId attr, chip::TLV::TLVReader & reader) override; // Push an attribute update notification to the matter stack. void OnUpdated(chip::AttributeId attr); diff --git a/examples/dynamic-bridge-app/linux/include/Device.h b/examples/dynamic-bridge-app/linux/include/Device.h index a4a6794b60001a..9cac09efe6f699 100644 --- a/examples/dynamic-bridge-app/linux/include/Device.h +++ b/examples/dynamic-bridge-app/linux/include/Device.h @@ -26,28 +26,14 @@ #include "Clusters.h" -// Device types for dynamic endpoints: TODO Need a generated file from ZAP to define these! -// (taken from chip-devices.xml) -#define DEVICE_TYPE_BRIDGED_NODE 0x0013 -// (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 -// (taken from chip-devices.xml) -#define DEVICE_TYPE_ROOT_NODE 0x0016 -// (taken from chip-devices.xml) -#define DEVICE_TYPE_BRIDGE 0x000e - -// Device Version for dynamic endpoints: -#define DEVICE_VERSION_DEFAULT 1 - // This represents a single logical device occupying one endpoint. A composed device consists of multiple // Device objects that reference a tree. class Device { public: - Device(chip::Span dataVersions, chip::Span clusters, chip::Span clusterImpl, - const chip::Span & deviceTypeList, chip::EndpointId parentId); + Device(chip::Span dataVersions, chip::Span clusters, + chip::Span clusterImpl, const chip::Span & deviceTypeList, + chip::EndpointId parentId); ~Device() = default; const chip::Span & versions() { return mDataVersions; } @@ -73,31 +59,6 @@ class Device std::string mDeviceName; }; -class Action -{ -public: - Action(uint16_t actionId, std::string name, chip::app::Clusters::Actions::ActionTypeEnum type, uint16_t endpointListId, - uint16_t supportedCommands, chip::app::Clusters::Actions::ActionStateEnum status, bool isVisible); - inline void setName(std::string name) { mName = name; }; - inline std::string getName() { return mName; }; - inline chip::app::Clusters::Actions::ActionTypeEnum getType() { return mType; }; - inline chip::app::Clusters::Actions::ActionStateEnum getStatus() { return mStatus; }; - inline uint16_t getActionId() { return mActionId; }; - inline uint16_t getEndpointListId() { return mEndpointListId; }; - inline uint16_t getSupportedCommands() { return mSupportedCommands; }; - inline void setIsVisible(bool isVisible) { mIsVisible = isVisible; }; - inline bool getIsVisible() { return mIsVisible; }; - -private: - std::string mName; - chip::app::Clusters::Actions::ActionTypeEnum mType; - chip::app::Clusters::Actions::ActionStateEnum mStatus; - uint16_t mActionId; - uint16_t mEndpointListId; - uint16_t mSupportedCommands; - bool mIsVisible; -}; - int AddDeviceEndpoint(Device * dev); int RemoveDeviceEndpoint(Device * dev); Device * FindDeviceEndpoint(chip::EndpointId id); diff --git a/examples/dynamic-bridge-app/linux/include/DeviceImpl.h b/examples/dynamic-bridge-app/linux/include/DeviceImpl.h deleted file mode 100644 index e94a4b4596fb96..00000000000000 --- a/examples/dynamic-bridge-app/linux/include/DeviceImpl.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * - * Copyright (c) 2022 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. - */ - -#pragma once - -#include "Device.h" diff --git a/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h index 9d826e10fcc289..99f1c5e06bc98b 100644 --- a/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h +++ b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h @@ -1,33 +1,11 @@ #pragma once #include -#include -#include #include -#include -#include +#include -#include - -#include "Attribute.h" -#include "Clusters.h" -#include "DataModel.h" - -struct CommonAttributeAccessInterface : public chip::app::AttributeAccessInterface -{ - using chip::app::AttributeAccessInterface::AttributeAccessInterface; - - // Find a cluster given a specific endpoint/cluster. Returns nullptr if no such - // cluster exists at that path. - static CommonCluster * FindCluster(const chip::app::ConcreteClusterPath & path); - - CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override; - CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override; - - void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override; - void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override; -}; +#include "data-model/Attribute.h" // Required for default initialization of cluster revisions. static constexpr uint16_t ZCL_DESCRIPTOR_CLUSTER_REVISION = 1; @@ -47,31 +25,3 @@ class GeneratedCluster // Gets the list of available attributes for this cluster. virtual std::vector GetAttributes() = 0; }; - -#include "bridge/BridgeClustersImpl.h" - -/* - -namespace clusters { -struct BridgedDeviceBasicCluster : public CommonCluster -{ - static constexpr chip::ClusterId kClusterId = ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID; - - BridgedDeviceBasicCluster(); - - chip::ClusterId GetClusterId() override { return kClusterId; } - CHIP_ERROR WriteFromBridge(const chip::app::ConcreteDataAttributePath & aPath, - chip::app::AttributeValueDecoder & aDecoder) override; - - chip::Span GetAllAttributes() override - { - static constexpr EmberAfAttributeMetadata kAllAttributes[] = { - { ZCL_REACHABLE_ATTRIBUTE_ID, ZCL_BOOLEAN_ATTRIBUTE_TYPE, 1, 0, 0u }, - }; - return chip::Span(kAllAttributes); - } - - Attribute mReachable; -}; -} // namespace clusters -*/ diff --git a/examples/dynamic-bridge-app/linux/include/Attribute.h b/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h similarity index 71% rename from examples/dynamic-bridge-app/linux/include/Attribute.h rename to examples/dynamic-bridge-app/linux/include/data-model/Attribute.h index 5224ab4a0d936c..66d4388df6d565 100644 --- a/examples/dynamic-bridge-app/linux/include/Attribute.h +++ b/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h @@ -4,7 +4,8 @@ #include "DataModel.h" -// This is the interface to the attribute implementation +// This is the interface to the attribute implementation that permits retrieval of metadata about +// the attribute as well as set/get the underlying value. class AttributeInterface { public: @@ -13,7 +14,7 @@ class AttributeInterface // Get the ID of this attribute. Shortcut for GetMetadata().attributeId virtual chip::AttributeId GetId() = 0; // Get the metadata of this attribute, suitable for advertising. - virtual const EmberAfAttributeMetadata& GetMetadata() = 0; + virtual const EmberAfAttributeMetadata & GetMetadata() = 0; virtual chip::CharSpan GetName() = 0; @@ -32,13 +33,14 @@ class AttributeInterface template struct Attribute : public AttributeInterface { - Attribute(chip::CharSpan name, chip::AttributeId id, EmberAfAttributeMask mask, EmberAfAttributeType type, size_t size, Type value = Type()) - : mMetadata(EmberAfAttributeMetadata{id, type, (uint16_t)size, mask, ZAP_EMPTY_DEFAULT()}), mData(value), mName(name) - { - } + Attribute(chip::CharSpan name, chip::AttributeId id, EmberAfAttributeMask mask, EmberAfAttributeType type, size_t size, + Type value = Type()) : + mMetadata(EmberAfAttributeMetadata{ id, type, (uint16_t) size, mask, ZAP_EMPTY_DEFAULT() }), + mData(value), mName(name) + {} chip::AttributeId GetId() override { return mMetadata.attributeId; } - const EmberAfAttributeMetadata& GetMetadata() override { return mMetadata; } + const EmberAfAttributeMetadata & GetMetadata() override { return mMetadata; } chip::CharSpan GetName() override { return mName; } CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override @@ -50,8 +52,8 @@ struct Attribute : public AttributeInterface return chip::app::DataModel::Encode(aPath, aEncoder, mData); } - void operator=(const Type& value) { mData = value; } - const Type& Peek() const { return mData; } + void operator=(const Type & value) { mData = value; } + const Type & Peek() const { return mData; } protected: EmberAfAttributeMetadata mMetadata; @@ -60,20 +62,22 @@ struct Attribute : public AttributeInterface }; // This specialization handles list writes and reverts if the write fails. -template +template struct ListAttribute : public Attribute { - using Attribute::Attribute; + using Attribute::Attribute; - void ListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override - { - mBackup = std::move(this->mData); - } + void ListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override { mBackup = this->mData; } void ListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override { - if (!aWriteWasSuccessful) + if (aWriteWasSuccessful) + { + mBackup = Type(); + } + else + { this->mData = std::move(mBackup); - mBackup = Type(); + } } Type mBackup; diff --git a/examples/dynamic-bridge-app/linux/include/DataModel.h b/examples/dynamic-bridge-app/linux/include/data-model/DataModel.h similarity index 55% rename from examples/dynamic-bridge-app/linux/include/DataModel.h rename to examples/dynamic-bridge-app/linux/include/data-model/DataModel.h index 57240b6478ac09..5c8bb7e7fd11a2 100644 --- a/examples/dynamic-bridge-app/linux/include/DataModel.h +++ b/examples/dynamic-bridge-app/linux/include/data-model/DataModel.h @@ -1,40 +1,63 @@ #pragma once #include -#include #include +#include #include +#include #include namespace chip { namespace app { namespace DataModel { -template +// Container requirements. +// To encode and decode as a list the following must be present +// void clear(); +// size_type size(); +// T& back(); +// void emplace_back(); +// iterator_type begin(); +// iterator_type end(); +// iterator_type must conform to LegacyForwardIterator +// The contained type must be default-constructible +template class IsList { typedef char yes; typedef long no; - template static yes test(decltype(&U::size)) ; - template static no test(...); + template + static yes test(decltype(&U::size)); + template + static no test(...); public: static constexpr bool value = sizeof(test(0)) == sizeof(yes); }; -template -struct IsOptionalOrNullable { static constexpr bool value = false; }; -template -struct IsOptionalOrNullable> { static constexpr bool value = true; }; -template -struct IsOptionalOrNullable> { static constexpr bool value = true; }; +template +struct IsOptionalOrNullable +{ + static constexpr bool value = false; +}; +template +struct IsOptionalOrNullable> +{ + static constexpr bool value = true; +}; +template +struct IsOptionalOrNullable> +{ + static constexpr bool value = true; +}; static_assert(IsList>::value); -template>::value && !IsList>::value, bool> = true> -CHIP_ERROR Encode(const ConcreteReadAttributePath&, AttributeValueEncoder & aEncoder, const X& x) +template >::value && !IsList>::value, bool> = true> +CHIP_ERROR Encode(const ConcreteReadAttributePath &, AttributeValueEncoder & aEncoder, const X & x) { return aEncoder.Encode(x); } @@ -43,13 +66,14 @@ CHIP_ERROR Encode(const ConcreteReadAttributePath&, AttributeValueEncoder & aEnc * @brief * Lists that are string-like should be encoded as char/byte spans. */ -template>::value && sizeof(std::decay_t) == sizeof(char), bool> = true> -CHIP_ERROR Encode(const ConcreteReadAttributePath& aPath, AttributeValueEncoder & aEncoder, const X& x) +template < + typename X, + std::enable_if_t>::value && sizeof(std::decay_t) == sizeof(char), bool> = true> +CHIP_ERROR Encode(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder, const X & x) { return aEncoder.Encode(Span>(x.data(), x.size())); } - /* * @brief * @@ -62,8 +86,10 @@ CHIP_ERROR Encode(const ConcreteReadAttributePath& aPath, AttributeValueEncoder * This is const X& instead of X&& because it is "more specialized" and so this overload will * be chosen if possible. */ -template>::value && (sizeof(std::decay_t) > sizeof(char)), bool> = true> -CHIP_ERROR Encode(const ConcreteReadAttributePath& aPath, AttributeValueEncoder & aEncoder, const X& x) +template < + typename X, + std::enable_if_t>::value && (sizeof(std::decay_t) > sizeof(char)), bool> = true> +CHIP_ERROR Encode(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder, const X & x) { if (aPath.mListIndex.HasValue()) { @@ -71,11 +97,14 @@ CHIP_ERROR Encode(const ConcreteReadAttributePath& aPath, AttributeValueEncoder if (index >= x.size()) return CHIP_ERROR_INVALID_ARGUMENT; - return aEncoder.Encode(x.data()[index]); + auto it = x.begin(); + std::advance(it, index); + return aEncoder.Encode(*it); } return aEncoder.EncodeList([x](const auto & encoder) { CHIP_ERROR err = CHIP_NO_ERROR; - for(auto& v : x) { + for (auto & v : x) + { err = encoder.Encode(v); if (err != CHIP_NO_ERROR) break; @@ -89,7 +118,7 @@ CHIP_ERROR Encode(const ConcreteReadAttributePath& aPath, AttributeValueEncoder * Set of overloaded encode methods that can be called from AttributeAccessInterface::Read */ template -CHIP_ERROR Encode(const ConcreteReadAttributePath& aPath, AttributeValueEncoder & aEncoder, const Optional & x) +CHIP_ERROR Encode(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder, const Optional & x) { if (x.HasValue()) { @@ -105,7 +134,7 @@ CHIP_ERROR Encode(const ConcreteReadAttributePath& aPath, AttributeValueEncoder * Encodes a nullable value. */ template -CHIP_ERROR Encode(const ConcreteReadAttributePath& aPath, AttributeValueEncoder & aEncoder, const Nullable & x) +CHIP_ERROR Encode(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder, const Nullable & x) { if (x.IsNull()) { @@ -133,9 +162,9 @@ CHIP_ERROR Encode(const ConcreteReadAttributePath& aPath, AttributeValueEncoder #pragma GCC diagnostic pop } - -template>::value && !IsList>::value, bool> = true> -CHIP_ERROR Decode(const ConcreteDataAttributePath&, AttributeValueDecoder & aDecoder, X& x) +template >::value && !IsList>::value, bool> = true> +CHIP_ERROR Decode(const ConcreteDataAttributePath &, AttributeValueDecoder & aDecoder, X & x) { return aDecoder.Decode(x); } @@ -144,33 +173,49 @@ CHIP_ERROR Decode(const ConcreteDataAttributePath&, AttributeValueDecoder & aDec * @brief * Lists that are string-like should be decoded as char/byte spans. */ -template>::value && sizeof(std::decay_t) == sizeof(char), bool> = true> -CHIP_ERROR Decode(const ConcreteDataAttributePath& aPath, AttributeValueDecoder & aDecoder, X& x) +template < + typename X, + std::enable_if_t>::value && sizeof(std::decay_t) == sizeof(char), bool> = true> +CHIP_ERROR Decode(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder, X & x) { Span> span; CHIP_ERROR err = aDecoder.Decode(span); - if (err = CHIP_NO_ERROR) { + if (err = CHIP_NO_ERROR) + { x = X(span.data(), span.size()); } return err; } - -template>::value && (sizeof(std::decay_t) > sizeof(char)), bool> = true> -CHIP_ERROR Decode(const ConcreteDataAttributePath& aPath, AttributeValueDecoder & aDecoder, X& x) +template < + typename X, + std::enable_if_t>::value && (sizeof(std::decay_t) > sizeof(char)), bool> = true> +CHIP_ERROR Decode(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder, X & x) { - switch(aPath.mListOp) { + switch (aPath.mListOp) + { case ConcreteDataAttributePath::ListOperation::DeleteItem: - if (aPath.mListIndex >= x.size()) + if (aPath.mListIndex >= x.size()) { return CHIP_ERROR_INVALID_LIST_LENGTH; - x.erase(x.begin() + aPath.mListIndex); - return CHIP_NO_ERROR; + } else { + auto it = x.begin(); + std::advance(it, aPath.mListIndex); + x.erase(it); + return CHIP_NO_ERROR; + } case ConcreteDataAttributePath::ListOperation::ReplaceItem: - if (aPath.mListIndex >= x.size()) + if (aPath.mListIndex >= x.size()) { return CHIP_ERROR_INVALID_LIST_LENGTH; - return aDecoder.Decode(x.begin()[aPath.mListIndex]); + } else { + auto it = x.begin(); + std::advance(it, aPath.mListIndex); + return aDecoder.Decode(*it); + } + case ConcreteDataAttributePath::ListOperation::ReplaceAll: + x.clear(); + // fallthrough default: x.emplace_back(); return aDecoder.Decode(x.back()); @@ -213,6 +258,6 @@ CHIP_ERROR Decode(const ConcreteDataAttributePath & aPath, AttributeValueDecoder return CHIP_NO_ERROR; } -} // namespace DataModel -} // namespace app -} // namespace chip +} // namespace DataModel +} // namespace app +} // namespace chip diff --git a/examples/dynamic-bridge-app/linux/include/main.h b/examples/dynamic-bridge-app/linux/include/main.h index 77342a5c5e3ca3..acb609fcf8e17b 100644 --- a/examples/dynamic-bridge-app/linux/include/main.h +++ b/examples/dynamic-bridge-app/linux/include/main.h @@ -18,7 +18,13 @@ #pragma once +#include + +#include "ActionList.h" #include "Device.h" +#include "GeneratedClusters.h" + +#include class Room { @@ -52,3 +58,7 @@ extern Room gRooms[kMaxRooms]; Room * FindRoom(const std::string & name); chip::Span GetActionListInfo(chip::EndpointId parentId); + +chip::Optional LookupClusterByName(const char * name); +std::unique_ptr CreateCluster(const char * name); +std::unique_ptr CreateCluster(chip::ClusterId id); diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index afd5d208772126..2c618311742774 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -41,8 +41,8 @@ #include #include +#include "ActionCluster.h" #include "Backend.h" - #include "CommissionableInit.h" #include "Device.h" #include "main.h" @@ -50,14 +50,15 @@ #include "AppMain.h" +#include "bridge/BridgeClustersImpl.h" + #ifdef PW_RPC_ENABLED -#include "bridge_service.h" #include "Rpc.h" +#include "bridge_service.h" #include "pw_rpc_system_server/rpc_server.h" static chip::rpc::Bridge bridge_service; #endif - #include #include #include @@ -74,6 +75,108 @@ static EndpointId gFirstDynamicEndpointId; static Device * gDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT]; Room gRooms[kMaxRooms]; +struct CommonAttributeAccessInterface : public chip::app::AttributeAccessInterface +{ + using chip::app::AttributeAccessInterface::AttributeAccessInterface; + + // Find a cluster given a specific endpoint/cluster. Returns nullptr if no such + // cluster exists at that path. + static CommonCluster * FindCluster(const chip::app::ConcreteClusterPath & path); + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override; + CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override; + + void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override; + void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override; +}; + +CommonCluster * CommonAttributeAccessInterface::FindCluster(const chip::app::ConcreteClusterPath & path) +{ + Device * dev = FindDeviceEndpoint(path.mEndpointId); + if (dev) + { + for (auto c : dev->clusters()) + { + if (c->GetClusterId() == path.mClusterId) + return static_cast(c); + } + } + return nullptr; +} + +CHIP_ERROR CommonAttributeAccessInterface::Read(const chip::app::ConcreteReadAttributePath & aPath, + chip::app::AttributeValueEncoder & aEncoder) +{ + CommonCluster * c = FindCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + AttributeInterface * a = c->FindAttribute(aPath.mAttributeId); + if (!a) + return CHIP_ERROR_NOT_IMPLEMENTED; + return a->Read(aPath, aEncoder); +} + +CHIP_ERROR CommonAttributeAccessInterface::Write(const chip::app::ConcreteDataAttributePath & aPath, + chip::app::AttributeValueDecoder & aDecoder) +{ + CommonCluster * c = FindCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + return c->ForwardWriteToBridge(aPath, aDecoder); +} + +void CommonAttributeAccessInterface::OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) +{ + CommonCluster * c = FindCluster(aPath); + if (c) + { + AttributeInterface * a = c->FindAttribute(aPath.mAttributeId); + if (a) + a->ListWriteBegin(aPath); + } +} + +void CommonAttributeAccessInterface::OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) +{ + CommonCluster * c = FindCluster(aPath); + if (c) + { + AttributeInterface * a = c->FindAttribute(aPath.mAttributeId); + if (a) + a->ListWriteEnd(aPath, aWriteWasSuccessful); + } +} + +chip::Optional LookupClusterByName(const char * name) +{ + for (const auto & cluster : clusters::kKnownClusters) + { + if (!strcmp(name, cluster.name)) + { + return chip::Optional(cluster.id); + } + } + return chip::Optional(); +} + +std::unique_ptr CreateCluster(const char * name) +{ + auto id = LookupClusterByName(name); + return id.HasValue() ? CreateCluster(id.Value()) : nullptr; +} + +std::unique_ptr CreateCluster(chip::ClusterId id) +{ + for (const auto & cluster : clusters::kKnownClusters) + { + if (id == cluster.id) + { + return std::unique_ptr(cluster.ctor(::operator new(cluster.size))); + } + } + return nullptr; +} + bool emberAfActionsClusterInstantActionCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Actions::Commands::InstantAction::DecodableType & commandData) { @@ -188,7 +291,8 @@ int main(int argc, char * argv[]) VerifyOrDie(ChipLinuxAppInit(argc, argv) == 0); std::vector clusterAccess; - for(auto& entry : clusters::kKnownClusters) { + for (auto & entry : clusters::kKnownClusters) + { clusterAccess.emplace_back(chip::Optional(), entry.id); } diff --git a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja index 021b7184044b2e..62c1f41e77ac26 100644 --- a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja +++ b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja @@ -1,6 +1,7 @@ #pragma once #include "BridgeGlobalStructs.h" +#include "third_party/connectedhomeip/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h" namespace clusters { struct {{cluster.name}}Cluster : public GeneratedCluster From 7ffc053be75e3483eb42539032db2e20ef5412e1 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Wed, 28 Sep 2022 16:06:51 +0000 Subject: [PATCH 10/14] Fix build, resyled changed --- examples/dynamic-bridge-app/bridge-common/BUILD.gn | 2 +- examples/dynamic-bridge-app/linux/BUILD.gn | 9 +++++---- .../dynamic-bridge-app/linux/include/Clusters.h | 2 +- .../linux/include/data-model/DataModel.h | 14 ++++++++++---- examples/dynamic-bridge-app/linux/include/main.h | 2 +- examples/dynamic-bridge-app/linux/main.cpp | 2 ++ 6 files changed, 20 insertions(+), 11 deletions(-) diff --git a/examples/dynamic-bridge-app/bridge-common/BUILD.gn b/examples/dynamic-bridge-app/bridge-common/BUILD.gn index a04cd6ec8b2010..eca58425fdcb62 100644 --- a/examples/dynamic-bridge-app/bridge-common/BUILD.gn +++ b/examples/dynamic-bridge-app/bridge-common/BUILD.gn @@ -14,8 +14,8 @@ import("//build_overrides/chip.gni") -import("${chip_root}/src/app/chip_data_model.gni") import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") +import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("dynamic-bridge-common") { zap_file = "bridge-app.zap" diff --git a/examples/dynamic-bridge-app/linux/BUILD.gn b/examples/dynamic-bridge-app/linux/BUILD.gn index 9f65fccf947d08..71b5dc877cd8f2 100644 --- a/examples/dynamic-bridge-app/linux/BUILD.gn +++ b/examples/dynamic-bridge-app/linux/BUILD.gn @@ -31,6 +31,7 @@ action("chip-bridge-codegen") { script = "${chip_root}/scripts/codegen.py" sources = [ "${chip_root}/examples/bridge-app/bridge-common/bridge-app.matter" ] + # Also several other files, but this is sufficient for dependency purposes. outputs = [ "$target_gen_dir/bridge/BridgeClustersImpl.h" ] @@ -48,12 +49,12 @@ action("chip-bridge-codegen") { executable("dynamic-chip-bridge-app") { sources = [ - "bridged-actions-stub.cpp", "Backend.cpp", "Clusters.cpp", "Device.cpp", "DynamicDevice.cpp", "UserInputBackend.cpp", + "bridged-actions-stub.cpp", "main.cpp", ] @@ -76,13 +77,13 @@ executable("dynamic-chip-bridge-app") { "PW_RPC_ATTRIBUTE_SERVICE=1", "PW_RPC_DESCRIPTOR_SERVICE=1", "PW_RPC_DEVICE_SERVICE=1", - "PW_RPC_TRACING_SERVICE=1" + "PW_RPC_TRACING_SERVICE=1", ] sources += [ "${chip_root}/examples/platform/linux/Rpc.cpp", "${chip_root}/examples/platform/linux/system_rpc_server.cc", - "bridge_service.cpp" + "bridge_service.cpp", ] deps += [ @@ -98,13 +99,13 @@ executable("dynamic-chip-bridge-app") { "$dir_pw_trace_tokenized", "$dir_pw_trace_tokenized:trace_rpc_service", "${chip_root}/config/linux/lib/pw_rpc:pw_rpc", - "${chip_root}/examples/dynamic-bridge-app/bridge-common:bridge_service.nanopb_rpc", "${chip_root}/examples/common/pigweed:attributes_service.nanopb_rpc", "${chip_root}/examples/common/pigweed:button_service.nanopb_rpc", "${chip_root}/examples/common/pigweed:descriptor_service.nanopb_rpc", "${chip_root}/examples/common/pigweed:device_service.nanopb_rpc", "${chip_root}/examples/common/pigweed:lighting_service.nanopb_rpc", "${chip_root}/examples/common/pigweed:rpc_services", + "${chip_root}/examples/dynamic-bridge-app/bridge-common:bridge_service.nanopb_rpc", ] deps += pw_build_LINK_DEPS diff --git a/examples/dynamic-bridge-app/linux/include/Clusters.h b/examples/dynamic-bridge-app/linux/include/Clusters.h index 94c50f95004de7..18bfbbaf07b71b 100644 --- a/examples/dynamic-bridge-app/linux/include/Clusters.h +++ b/examples/dynamic-bridge-app/linux/include/Clusters.h @@ -29,8 +29,8 @@ #include -#include "data-model/Attribute.h" #include "GeneratedClusters.h" +#include "data-model/Attribute.h" // This is the interface to cluster implementations, providing access to manipulate attributes. class ClusterInterface diff --git a/examples/dynamic-bridge-app/linux/include/data-model/DataModel.h b/examples/dynamic-bridge-app/linux/include/data-model/DataModel.h index 5c8bb7e7fd11a2..0aef40aa84ae61 100644 --- a/examples/dynamic-bridge-app/linux/include/data-model/DataModel.h +++ b/examples/dynamic-bridge-app/linux/include/data-model/DataModel.h @@ -195,9 +195,12 @@ CHIP_ERROR Decode(const ConcreteDataAttributePath & aPath, AttributeValueDecoder switch (aPath.mListOp) { case ConcreteDataAttributePath::ListOperation::DeleteItem: - if (aPath.mListIndex >= x.size()) { + if (aPath.mListIndex >= x.size()) + { return CHIP_ERROR_INVALID_LIST_LENGTH; - } else { + } + else + { auto it = x.begin(); std::advance(it, aPath.mListIndex); x.erase(it); @@ -205,9 +208,12 @@ CHIP_ERROR Decode(const ConcreteDataAttributePath & aPath, AttributeValueDecoder } case ConcreteDataAttributePath::ListOperation::ReplaceItem: - if (aPath.mListIndex >= x.size()) { + if (aPath.mListIndex >= x.size()) + { return CHIP_ERROR_INVALID_LIST_LENGTH; - } else { + } + else + { auto it = x.begin(); std::advance(it, aPath.mListIndex); return aDecoder.Decode(*it); diff --git a/examples/dynamic-bridge-app/linux/include/main.h b/examples/dynamic-bridge-app/linux/include/main.h index acb609fcf8e17b..30df5ae0248f9c 100644 --- a/examples/dynamic-bridge-app/linux/include/main.h +++ b/examples/dynamic-bridge-app/linux/include/main.h @@ -20,7 +20,7 @@ #include -#include "ActionList.h" +#include "ActionCluster.h" #include "Device.h" #include "GeneratedClusters.h" diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index 2c618311742774..652637a48bc8e3 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -291,9 +291,11 @@ int main(int argc, char * argv[]) VerifyOrDie(ChipLinuxAppInit(argc, argv) == 0); std::vector clusterAccess; + clusterAccess.reserve(std::extent::value); for (auto & entry : clusters::kKnownClusters) { clusterAccess.emplace_back(chip::Optional(), entry.id); + registerAttributeAccessOverride(&clusterAccess.back()); } ChipLinuxAppMainLoop(); From 3a2f3d33abb2c0538705e55864dcc5df8553377a Mon Sep 17 00:00:00 2001 From: Albert Chaulk Date: Fri, 30 Sep 2022 14:05:43 -0400 Subject: [PATCH 11/14] fix tests --- scripts/build/testdata/build_linux_on_x64.txt | 32 +++++++++++++++++++ .../bridge/DemoCluster.h | 4 ++- .../bridge/DemoCluster.h | 4 ++- .../outputs/several_clusters/bridge/First.h | 4 ++- .../outputs/several_clusters/bridge/Second.h | 4 ++- .../outputs/several_clusters/bridge/Third.h | 4 ++- .../simple_attribute/bridge/MyCluster.h | 4 ++- 7 files changed, 50 insertions(+), 6 deletions(-) diff --git a/scripts/build/testdata/build_linux_on_x64.txt b/scripts/build/testdata/build_linux_on_x64.txt index dbf58430c638a3..9f6255054ba7d5 100644 --- a/scripts/build/testdata/build_linux_on_x64.txt +++ b/scripts/build/testdata/build_linux_on_x64.txt @@ -61,6 +61,16 @@ bash -c ' PKG_CONFIG_PATH="SYSROOT_AARCH64/lib/aarch64-linux-gnu/pkgconfig" \ gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/chip-tool '"'"'--args=chip_inet_config_enable_ipv4=false chip_config_network_layer_ble=false chip_enable_wifi=false chip_enable_openthread=false is_clang=true chip_crypto="mbedtls" target_cpu="arm64" sysroot="SYSROOT_AARCH64"'"'"' {out}/linux-arm64-clang-chip-tool-nodeps-ipv6only' +# Generating linux-arm64-clang-dynamic-bridge +bash -c ' +PKG_CONFIG_PATH="SYSROOT_AARCH64/lib/aarch64-linux-gnu/pkgconfig" \ + gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/dynamic-bridge-app/linux '"'"'--args=is_clang=true target_cpu="arm64" sysroot="SYSROOT_AARCH64"'"'"' {out}/linux-arm64-clang-dynamic-bridge' + +# Generating linux-arm64-clang-dynamic-bridge-ipv6only +bash -c ' +PKG_CONFIG_PATH="SYSROOT_AARCH64/lib/aarch64-linux-gnu/pkgconfig" \ + gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/dynamic-bridge-app/linux '"'"'--args=chip_inet_config_enable_ipv4=false is_clang=true target_cpu="arm64" sysroot="SYSROOT_AARCH64"'"'"' {out}/linux-arm64-clang-dynamic-bridge-ipv6only' + # Generating linux-arm64-clang-light bash -c ' PKG_CONFIG_PATH="SYSROOT_AARCH64/lib/aarch64-linux-gnu/pkgconfig" \ @@ -237,6 +247,12 @@ gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/exa # Generating linux-x64-chip-tool-nodeps-ipv6only gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/chip-tool '--args=chip_inet_config_enable_ipv4=false chip_config_network_layer_ble=false chip_enable_wifi=false chip_enable_openthread=false is_clang=true chip_crypto="mbedtls"' {out}/linux-x64-chip-tool-nodeps-ipv6only +# Generating linux-x64-dynamic-bridge +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/dynamic-bridge-app/linux {out}/linux-x64-dynamic-bridge + +# Generating linux-x64-dynamic-bridge-ipv6only +gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/dynamic-bridge-app/linux --args=chip_inet_config_enable_ipv4=false {out}/linux-x64-dynamic-bridge-ipv6only + # Generating linux-x64-light gn gen --check --fail-on-unused-args --export-compile-commands --root={root}/examples/lighting-app/linux {out}/linux-x64-light @@ -381,6 +397,16 @@ bash -c ' PKG_CONFIG_PATH="SYSROOT_AARCH64/lib/aarch64-linux-gnu/pkgconfig" \ ninja -C {out}/linux-arm64-clang-chip-tool-nodeps-ipv6only' +# Building linux-arm64-clang-dynamic-bridge +bash -c ' +PKG_CONFIG_PATH="SYSROOT_AARCH64/lib/aarch64-linux-gnu/pkgconfig" \ + ninja -C {out}/linux-arm64-clang-dynamic-bridge' + +# Building linux-arm64-clang-dynamic-bridge-ipv6only +bash -c ' +PKG_CONFIG_PATH="SYSROOT_AARCH64/lib/aarch64-linux-gnu/pkgconfig" \ + ninja -C {out}/linux-arm64-clang-dynamic-bridge-ipv6only' + # Building linux-arm64-clang-light bash -c ' PKG_CONFIG_PATH="SYSROOT_AARCH64/lib/aarch64-linux-gnu/pkgconfig" \ @@ -557,6 +583,12 @@ ninja -C {out}/linux-x64-chip-tool-nodeps # Building linux-x64-chip-tool-nodeps-ipv6only ninja -C {out}/linux-x64-chip-tool-nodeps-ipv6only +# Building linux-x64-dynamic-bridge +ninja -C {out}/linux-x64-dynamic-bridge + +# Building linux-x64-dynamic-bridge-ipv6only +ninja -C {out}/linux-x64-dynamic-bridge-ipv6only + # Building linux-x64-light ninja -C {out}/linux-x64-light diff --git a/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoCluster.h b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoCluster.h index 96d7f49db331b9..6e25cee804d23e 100644 --- a/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoCluster.h +++ b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoCluster.h @@ -1,6 +1,7 @@ #pragma once #include "BridgeGlobalStructs.h" +#include "third_party/connectedhomeip/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h" namespace clusters { struct DemoClusterCluster : public GeneratedCluster @@ -12,7 +13,8 @@ struct DemoClusterCluster : public GeneratedCluster { } - chip::ClusterId GetClusterId() override { return 10; } + static constexpr uint32_t kClusterId =10; + chip::ClusterId GetClusterId() override { return kClusterId; } std::vector GetAttributes() override { diff --git a/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoCluster.h b/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoCluster.h index e52cc156a5c7ce..13467fc6af4383 100644 --- a/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoCluster.h +++ b/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoCluster.h @@ -1,6 +1,7 @@ #pragma once #include "BridgeGlobalStructs.h" +#include "third_party/connectedhomeip/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h" namespace clusters { struct DemoClusterCluster : public GeneratedCluster @@ -12,7 +13,8 @@ struct DemoClusterCluster : public GeneratedCluster { } - chip::ClusterId GetClusterId() override { return 18; } + static constexpr uint32_t kClusterId =18; + chip::ClusterId GetClusterId() override { return kClusterId; } std::vector GetAttributes() override { diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/First.h b/scripts/idl/tests/outputs/several_clusters/bridge/First.h index 1dd55b2b7e8de7..2266f4f67d344d 100644 --- a/scripts/idl/tests/outputs/several_clusters/bridge/First.h +++ b/scripts/idl/tests/outputs/several_clusters/bridge/First.h @@ -1,6 +1,7 @@ #pragma once #include "BridgeGlobalStructs.h" +#include "third_party/connectedhomeip/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h" namespace clusters { struct FirstCluster : public GeneratedCluster @@ -11,7 +12,8 @@ struct FirstCluster : public GeneratedCluster { } - chip::ClusterId GetClusterId() override { return 1; } + static constexpr uint32_t kClusterId =1; + chip::ClusterId GetClusterId() override { return kClusterId; } std::vector GetAttributes() override { diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/Second.h b/scripts/idl/tests/outputs/several_clusters/bridge/Second.h index e31850db1e6c28..acdd0b959ef179 100644 --- a/scripts/idl/tests/outputs/several_clusters/bridge/Second.h +++ b/scripts/idl/tests/outputs/several_clusters/bridge/Second.h @@ -1,6 +1,7 @@ #pragma once #include "BridgeGlobalStructs.h" +#include "third_party/connectedhomeip/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h" namespace clusters { struct SecondCluster : public GeneratedCluster @@ -11,7 +12,8 @@ struct SecondCluster : public GeneratedCluster { } - chip::ClusterId GetClusterId() override { return 2; } + static constexpr uint32_t kClusterId =2; + chip::ClusterId GetClusterId() override { return kClusterId; } std::vector GetAttributes() override { diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/Third.h b/scripts/idl/tests/outputs/several_clusters/bridge/Third.h index 5ec29b498bb170..70525f94326595 100644 --- a/scripts/idl/tests/outputs/several_clusters/bridge/Third.h +++ b/scripts/idl/tests/outputs/several_clusters/bridge/Third.h @@ -1,6 +1,7 @@ #pragma once #include "BridgeGlobalStructs.h" +#include "third_party/connectedhomeip/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h" namespace clusters { struct ThirdCluster : public GeneratedCluster @@ -11,7 +12,8 @@ struct ThirdCluster : public GeneratedCluster { } - chip::ClusterId GetClusterId() override { return 3; } + static constexpr uint32_t kClusterId =3; + chip::ClusterId GetClusterId() override { return kClusterId; } std::vector GetAttributes() override { diff --git a/scripts/idl/tests/outputs/simple_attribute/bridge/MyCluster.h b/scripts/idl/tests/outputs/simple_attribute/bridge/MyCluster.h index 30c9636034054f..69a14b8ab392e5 100644 --- a/scripts/idl/tests/outputs/simple_attribute/bridge/MyCluster.h +++ b/scripts/idl/tests/outputs/simple_attribute/bridge/MyCluster.h @@ -1,6 +1,7 @@ #pragma once #include "BridgeGlobalStructs.h" +#include "third_party/connectedhomeip/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h" namespace clusters { struct MyClusterCluster : public GeneratedCluster @@ -11,7 +12,8 @@ struct MyClusterCluster : public GeneratedCluster { } - chip::ClusterId GetClusterId() override { return 123; } + static constexpr uint32_t kClusterId =123; + chip::ClusterId GetClusterId() override { return kClusterId; } std::vector GetAttributes() override { From a8d94ff411f2551b3b46a2e7071a6a61984446eb Mon Sep 17 00:00:00 2001 From: Albert Chaulk Date: Fri, 30 Sep 2022 14:54:27 -0400 Subject: [PATCH 12/14] add zap, fix paths pointing to old app --- .../dynamic-bridge-app/bridge-common/BUILD.gn | 2 +- .../bridge-common/bridge-app.matter | 40 +- examples/dynamic-bridge-app/linux/BUILD.gn | 4 +- examples/dynamic-bridge-app/linux/Dockerfile | 2 +- examples/dynamic-bridge-app/linux/args.gni | 2 +- .../dynamic-bridge-app/linux/entrypoint.sh | 2 +- .../zap-generated/CHIPClientCallbacks.h | 54 + .../zap-generated/CHIPClusters.h | 52 + .../zap-generated/IMClusterCommandHandler.cpp | 812 +++++++++++++ .../PluginApplicationCallbacks.h | 50 + .../dynamic-bridge-app/zap-generated/access.h | 260 ++++ .../zap-generated/callback-stub.cpp | 327 ++++++ .../zap-generated/endpoint_config.h | 1041 +++++++++++++++++ .../zap-generated/gen_config.h | 191 +++ .../zap-generated/gen_tokens.h | 45 + 15 files changed, 2862 insertions(+), 22 deletions(-) create mode 100644 zzz_generated/dynamic-bridge-app/zap-generated/CHIPClientCallbacks.h create mode 100644 zzz_generated/dynamic-bridge-app/zap-generated/CHIPClusters.h create mode 100644 zzz_generated/dynamic-bridge-app/zap-generated/IMClusterCommandHandler.cpp create mode 100644 zzz_generated/dynamic-bridge-app/zap-generated/PluginApplicationCallbacks.h create mode 100644 zzz_generated/dynamic-bridge-app/zap-generated/access.h create mode 100644 zzz_generated/dynamic-bridge-app/zap-generated/callback-stub.cpp create mode 100644 zzz_generated/dynamic-bridge-app/zap-generated/endpoint_config.h create mode 100644 zzz_generated/dynamic-bridge-app/zap-generated/gen_config.h create mode 100644 zzz_generated/dynamic-bridge-app/zap-generated/gen_tokens.h diff --git a/examples/dynamic-bridge-app/bridge-common/BUILD.gn b/examples/dynamic-bridge-app/bridge-common/BUILD.gn index eca58425fdcb62..2f91f4fccd5156 100644 --- a/examples/dynamic-bridge-app/bridge-common/BUILD.gn +++ b/examples/dynamic-bridge-app/bridge-common/BUILD.gn @@ -20,7 +20,7 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("dynamic-bridge-common") { zap_file = "bridge-app.zap" - zap_pregenerated_dir = "${chip_root}/zzz_generated/bridge-app/zap-generated" + zap_pregenerated_dir = "${chip_root}/zzz_generated/dynamic-bridge-app/zap-generated" is_server = true # TODO: the definition of DYNAMIC_ENDPOINT_COUNT needs find a common home! diff --git a/examples/dynamic-bridge-app/bridge-common/bridge-app.matter b/examples/dynamic-bridge-app/bridge-common/bridge-app.matter index 4ba029df533fff..138789996e7852 100644 --- a/examples/dynamic-bridge-app/bridge-common/bridge-app.matter +++ b/examples/dynamic-bridge-app/bridge-common/bridge-app.matter @@ -187,12 +187,12 @@ server cluster LevelControl = 8 { } server cluster Descriptor = 29 { - struct DeviceType { + struct DeviceTypeStruct { devtype_id type = 0; int16u revision = 1; } - readonly attribute DeviceType deviceList[] = 0; + readonly attribute DeviceTypeStruct deviceTypeList[] = 0; readonly attribute CLUSTER_ID serverList[] = 1; readonly attribute CLUSTER_ID clientList[] = 2; readonly attribute ENDPOINT_NO partsList[] = 3; @@ -695,33 +695,33 @@ server cluster NetworkCommissioning = 49 { readonly attribute int16u clusterRevision = 65533; request struct ScanNetworksRequest { - optional nullable OCTET_STRING ssid = 0; + optional nullable OCTET_STRING<32> ssid = 0; optional INT64U breadcrumb = 1; } request struct AddOrUpdateWiFiNetworkRequest { - OCTET_STRING ssid = 0; - OCTET_STRING credentials = 1; + OCTET_STRING<32> ssid = 0; + OCTET_STRING<64> credentials = 1; optional INT64U breadcrumb = 2; } request struct AddOrUpdateThreadNetworkRequest { - OCTET_STRING operationalDataset = 0; + OCTET_STRING<254> operationalDataset = 0; optional INT64U breadcrumb = 1; } request struct RemoveNetworkRequest { - OCTET_STRING networkID = 0; + OCTET_STRING<32> networkID = 0; optional INT64U breadcrumb = 1; } request struct ConnectNetworkRequest { - OCTET_STRING networkID = 0; + OCTET_STRING<32> networkID = 0; optional INT64U breadcrumb = 1; } request struct ReorderNetworkRequest { - OCTET_STRING networkID = 0; + OCTET_STRING<32> networkID = 0; INT8U networkIndex = 1; optional INT64U breadcrumb = 2; } @@ -735,7 +735,7 @@ server cluster NetworkCommissioning = 49 { response struct NetworkConfigResponse = 5 { NetworkCommissioningStatus networkingStatus = 0; - optional CHAR_STRING debugText = 1; + optional CHAR_STRING<512> debugText = 1; optional INT8U networkIndex = 2; } @@ -779,7 +779,7 @@ server cluster DiagnosticLogs = 50 { request struct RetrieveLogsRequestRequest { LogsIntent intent = 0; LogsTransferProtocol requestedProtocol = 1; - OCTET_STRING transferFileDesignator = 2; + OCTET_STRING<32> transferFileDesignator = 2; } command RetrieveLogsRequest(RetrieveLogsRequestRequest): RetrieveLogsResponse = 0; @@ -881,7 +881,7 @@ server cluster GeneralDiagnostics = 51 { readonly attribute int16u clusterRevision = 65533; request struct TestEventTriggerRequest { - OCTET_STRING enableKey = 0; + OCTET_STRING<16> enableKey = 0; INT64U eventTrigger = 1; } @@ -1162,6 +1162,14 @@ server cluster EthernetNetworkDiagnostics = 55 { } server cluster Switch = 59 { + bitmap SwitchFeature : BITMAP32 { + kLatchingSwitch = 0x1; + kMomentarySwitch = 0x2; + kMomentarySwitchRelease = 0x4; + kMomentarySwitchLongPress = 0x8; + kMomentarySwitchMultiPress = 0x10; + } + info event SwitchLatched = 0 { INT8U newPosition = 0; } @@ -1306,7 +1314,7 @@ server cluster OperationalCredentials = 62 { } request struct UpdateFabricLabelRequest { - CHAR_STRING label = 0; + CHAR_STRING<32> label = 0; } request struct RemoveFabricRequest { @@ -1444,7 +1452,7 @@ endpoint 0 { binding cluster AccessControl; server cluster Descriptor { - callback attribute deviceList; + callback attribute deviceTypeList; callback attribute serverList; callback attribute clientList; callback attribute partsList; @@ -1744,7 +1752,7 @@ endpoint 1 { } server cluster Descriptor { - callback attribute deviceList; + callback attribute deviceTypeList; callback attribute serverList; callback attribute clientList; callback attribute partsList; @@ -1795,7 +1803,7 @@ endpoint 2 { } server cluster Descriptor { - callback attribute deviceList; + callback attribute deviceTypeList; callback attribute serverList; callback attribute clientList; callback attribute partsList; diff --git a/examples/dynamic-bridge-app/linux/BUILD.gn b/examples/dynamic-bridge-app/linux/BUILD.gn index 71b5dc877cd8f2..03eee3e08a3f33 100644 --- a/examples/dynamic-bridge-app/linux/BUILD.gn +++ b/examples/dynamic-bridge-app/linux/BUILD.gn @@ -41,7 +41,7 @@ action("chip-bridge-codegen") { "--output-dir", rebase_path(target_gen_dir, root_build_dir), rebase_path( - "${chip_root}/examples/bridge-app/bridge-common/bridge-app.matter", + "${chip_root}/examples/dynamic-bridge-app/bridge-common/bridge-app.matter", root_build_dir), ] deps = [ "${chip_root}/scripts/idl" ] @@ -60,7 +60,7 @@ executable("dynamic-chip-bridge-app") { deps = [ ":chip-bridge-codegen", - "${chip_root}/examples/bridge-app/bridge-common", + "${chip_root}/examples/dynamic-bridge-app/bridge-common:dynamic-bridge-common", "${chip_root}/examples/platform/linux:app-main", "${chip_root}/src/app/tests/suites/credentials:dac_provider", "${chip_root}/src/lib", diff --git a/examples/dynamic-bridge-app/linux/Dockerfile b/examples/dynamic-bridge-app/linux/Dockerfile index 965e82a664266c..8578398312602b 100644 --- a/examples/dynamic-bridge-app/linux/Dockerfile +++ b/examples/dynamic-bridge-app/linux/Dockerfile @@ -17,7 +17,7 @@ FROM connectedhomeip/chip-cirque-device-base:latest -COPY out/debug/chip-bridge-app /usr/bin/ +COPY out/debug/dynamic-chip-bridge-app /usr/bin/ COPY entrypoint.sh / ENTRYPOINT ["/entrypoint.sh", "server"] diff --git a/examples/dynamic-bridge-app/linux/args.gni b/examples/dynamic-bridge-app/linux/args.gni index 7039d20e181994..8f80ea257faab2 100644 --- a/examples/dynamic-bridge-app/linux/args.gni +++ b/examples/dynamic-bridge-app/linux/args.gni @@ -21,5 +21,5 @@ chip_project_config_include = "" chip_system_project_config_include = "" chip_project_config_include_dirs = - [ "${chip_root}/examples/bridge-app/bridge-common/include" ] + [ "${chip_root}/examples/dynamic-bridge-app/bridge-common/include" ] chip_project_config_include_dirs += [ "${chip_root}/config/standalone" ] diff --git a/examples/dynamic-bridge-app/linux/entrypoint.sh b/examples/dynamic-bridge-app/linux/entrypoint.sh index 9d33bdd92ce434..6551db22f262ef 100755 --- a/examples/dynamic-bridge-app/linux/entrypoint.sh +++ b/examples/dynamic-bridge-app/linux/entrypoint.sh @@ -9,4 +9,4 @@ ot-ctl panid 0x1234 ot-ctl ifconfig up ot-ctl thread start -chip-bridge-app +dynamic-chip-bridge-app diff --git a/zzz_generated/dynamic-bridge-app/zap-generated/CHIPClientCallbacks.h b/zzz_generated/dynamic-bridge-app/zap-generated/CHIPClientCallbacks.h new file mode 100644 index 00000000000000..70ca3e88c274a6 --- /dev/null +++ b/zzz_generated/dynamic-bridge-app/zap-generated/CHIPClientCallbacks.h @@ -0,0 +1,54 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * + * 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. + */ + +// THIS FILE IS GENERATED BY ZAP + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// List specific responses +typedef void (*BindingBindingListAttributeCallback)( + void * context, + const chip::app::DataModel::DecodableList & data); +typedef void (*BindingGeneratedCommandListListAttributeCallback)(void * context, + const chip::app::DataModel::DecodableList & data); +typedef void (*BindingAcceptedCommandListListAttributeCallback)(void * context, + const chip::app::DataModel::DecodableList & data); +typedef void (*BindingAttributeListListAttributeCallback)(void * context, + const chip::app::DataModel::DecodableList & data); +typedef void (*AccessControlAclListAttributeCallback)( + void * context, + const chip::app::DataModel::DecodableList & + data); +typedef void (*AccessControlExtensionListAttributeCallback)( + void * context, + const chip::app::DataModel::DecodableList & data); +typedef void (*AccessControlGeneratedCommandListListAttributeCallback)( + void * context, const chip::app::DataModel::DecodableList & data); +typedef void (*AccessControlAcceptedCommandListListAttributeCallback)( + void * context, const chip::app::DataModel::DecodableList & data); +typedef void (*AccessControlAttributeListListAttributeCallback)( + void * context, const chip::app::DataModel::DecodableList & data); diff --git a/zzz_generated/dynamic-bridge-app/zap-generated/CHIPClusters.h b/zzz_generated/dynamic-bridge-app/zap-generated/CHIPClusters.h new file mode 100644 index 00000000000000..ca9ff71b7644f9 --- /dev/null +++ b/zzz_generated/dynamic-bridge-app/zap-generated/CHIPClusters.h @@ -0,0 +1,52 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * + * 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. + */ + +// THIS FILE IS GENERATED BY ZAP + +// Prevent multiple inclusion +#pragma once + +#include +#include + +#include +#include +#include + +namespace chip { +namespace Controller { + +class DLL_EXPORT BindingCluster : public ClusterBase +{ +public: + BindingCluster(Messaging::ExchangeManager & exchangeManager, const SessionHandle & session, EndpointId endpoint) : + ClusterBase(exchangeManager, session, app::Clusters::Binding::Id, endpoint) + {} + ~BindingCluster() {} +}; + +class DLL_EXPORT AccessControlCluster : public ClusterBase +{ +public: + AccessControlCluster(Messaging::ExchangeManager & exchangeManager, const SessionHandle & session, EndpointId endpoint) : + ClusterBase(exchangeManager, session, app::Clusters::AccessControl::Id, endpoint) + {} + ~AccessControlCluster() {} +}; + +} // namespace Controller +} // namespace chip diff --git a/zzz_generated/dynamic-bridge-app/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/dynamic-bridge-app/zap-generated/IMClusterCommandHandler.cpp new file mode 100644 index 00000000000000..1fb800496f23c2 --- /dev/null +++ b/zzz_generated/dynamic-bridge-app/zap-generated/IMClusterCommandHandler.cpp @@ -0,0 +1,812 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * + * 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. + */ + +// THIS FILE IS GENERATED BY ZAP + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Currently we need some work to keep compatible with ember lib. +#include + +namespace chip { +namespace app { + +// Cluster specific command parsing + +namespace Clusters { + +namespace Actions { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::InstantAction::Id: { + Commands::InstantAction::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfActionsClusterInstantActionCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, + ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace Actions + +namespace AdministratorCommissioning { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::OpenCommissioningWindow::Id: { + Commands::OpenCommissioningWindow::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback(apCommandObj, aCommandPath, + commandData); + } + break; + } + case Commands::OpenBasicCommissioningWindow::Id: { + Commands::OpenBasicCommissioningWindow::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback( + apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::RevokeCommissioning::Id: { + Commands::RevokeCommissioning::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, + ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace AdministratorCommissioning + +namespace DiagnosticLogs { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::RetrieveLogsRequest::Id: { + Commands::RetrieveLogsRequest::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, + ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace DiagnosticLogs + +namespace EthernetNetworkDiagnostics { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::ResetCounts::Id: { + Commands::ResetCounts::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfEthernetNetworkDiagnosticsClusterResetCountsCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, + ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace EthernetNetworkDiagnostics + +namespace GeneralCommissioning { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::ArmFailSafe::Id: { + Commands::ArmFailSafe::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::SetRegulatoryConfig::Id: { + Commands::SetRegulatoryConfig::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::CommissioningComplete::Id: { + Commands::CommissioningComplete::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, + ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace GeneralCommissioning + +namespace GeneralDiagnostics { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::TestEventTrigger::Id: { + Commands::TestEventTrigger::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGeneralDiagnosticsClusterTestEventTriggerCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, + ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace GeneralDiagnostics + +namespace GroupKeyManagement { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::KeySetWrite::Id: { + Commands::KeySetWrite::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGroupKeyManagementClusterKeySetWriteCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::KeySetRead::Id: { + Commands::KeySetRead::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGroupKeyManagementClusterKeySetReadCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::KeySetRemove::Id: { + Commands::KeySetRemove::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGroupKeyManagementClusterKeySetRemoveCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::KeySetReadAllIndices::Id: { + Commands::KeySetReadAllIndices::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGroupKeyManagementClusterKeySetReadAllIndicesCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, + ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace GroupKeyManagement + +namespace Identify { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::Identify::Id: { + Commands::Identify::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfIdentifyClusterIdentifyCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::TriggerEffect::Id: { + Commands::TriggerEffect::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfIdentifyClusterTriggerEffectCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, + ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace Identify + +namespace LevelControl { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::MoveToLevel::Id: { + Commands::MoveToLevel::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::Move::Id: { + Commands::Move::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfLevelControlClusterMoveCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::Step::Id: { + Commands::Step::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfLevelControlClusterStepCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::Stop::Id: { + Commands::Stop::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfLevelControlClusterStopCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::MoveToLevelWithOnOff::Id: { + Commands::MoveToLevelWithOnOff::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::MoveWithOnOff::Id: { + Commands::MoveWithOnOff::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::StepWithOnOff::Id: { + Commands::StepWithOnOff::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::StopWithOnOff::Id: { + Commands::StopWithOnOff::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, + ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace LevelControl + +namespace NetworkCommissioning { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::ScanNetworks::Id: { + Commands::ScanNetworks::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::AddOrUpdateWiFiNetwork::Id: { + Commands::AddOrUpdateWiFiNetwork::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfNetworkCommissioningClusterAddOrUpdateWiFiNetworkCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::AddOrUpdateThreadNetwork::Id: { + Commands::AddOrUpdateThreadNetwork::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfNetworkCommissioningClusterAddOrUpdateThreadNetworkCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::RemoveNetwork::Id: { + Commands::RemoveNetwork::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::ConnectNetwork::Id: { + Commands::ConnectNetwork::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfNetworkCommissioningClusterConnectNetworkCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::ReorderNetwork::Id: { + Commands::ReorderNetwork::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfNetworkCommissioningClusterReorderNetworkCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, + ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace NetworkCommissioning + +namespace OnOff { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::Off::Id: { + Commands::Off::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOffCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::On::Id: { + Commands::On::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterOnCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::Toggle::Id: { + Commands::Toggle::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, + ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace OnOff + +namespace OperationalCredentials { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::AttestationRequest::Id: { + Commands::AttestationRequest::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfOperationalCredentialsClusterAttestationRequestCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::CertificateChainRequest::Id: { + Commands::CertificateChainRequest::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfOperationalCredentialsClusterCertificateChainRequestCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::CSRRequest::Id: { + Commands::CSRRequest::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOperationalCredentialsClusterCSRRequestCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::AddNOC::Id: { + Commands::AddNOC::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::UpdateNOC::Id: { + Commands::UpdateNOC::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOperationalCredentialsClusterUpdateNOCCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::UpdateFabricLabel::Id: { + Commands::UpdateFabricLabel::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOperationalCredentialsClusterUpdateFabricLabelCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::RemoveFabric::Id: { + Commands::RemoveFabric::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfOperationalCredentialsClusterRemoveFabricCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::AddTrustedRootCertificate::Id: { + Commands::AddTrustedRootCertificate::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = + emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, + ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace OperationalCredentials + +} // namespace Clusters + +void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aReader, CommandHandler * apCommandObj) +{ + Compatibility::SetupEmberAfCommandHandler(apCommandObj, aCommandPath); + + switch (aCommandPath.mClusterId) + { + case Clusters::Actions::Id: + Clusters::Actions::DispatchServerCommand(apCommandObj, aCommandPath, aReader); + break; + case Clusters::AdministratorCommissioning::Id: + Clusters::AdministratorCommissioning::DispatchServerCommand(apCommandObj, aCommandPath, aReader); + break; + case Clusters::DiagnosticLogs::Id: + Clusters::DiagnosticLogs::DispatchServerCommand(apCommandObj, aCommandPath, aReader); + break; + case Clusters::EthernetNetworkDiagnostics::Id: + Clusters::EthernetNetworkDiagnostics::DispatchServerCommand(apCommandObj, aCommandPath, aReader); + break; + case Clusters::GeneralCommissioning::Id: + Clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandPath, aReader); + break; + case Clusters::GeneralDiagnostics::Id: + Clusters::GeneralDiagnostics::DispatchServerCommand(apCommandObj, aCommandPath, aReader); + break; + case Clusters::GroupKeyManagement::Id: + Clusters::GroupKeyManagement::DispatchServerCommand(apCommandObj, aCommandPath, aReader); + break; + case Clusters::Identify::Id: + Clusters::Identify::DispatchServerCommand(apCommandObj, aCommandPath, aReader); + break; + case Clusters::LevelControl::Id: + Clusters::LevelControl::DispatchServerCommand(apCommandObj, aCommandPath, aReader); + break; + case Clusters::NetworkCommissioning::Id: + Clusters::NetworkCommissioning::DispatchServerCommand(apCommandObj, aCommandPath, aReader); + break; + case Clusters::OnOff::Id: + Clusters::OnOff::DispatchServerCommand(apCommandObj, aCommandPath, aReader); + break; + case Clusters::OperationalCredentials::Id: + Clusters::OperationalCredentials::DispatchServerCommand(apCommandObj, aCommandPath, aReader); + break; + default: + ChipLogError(Zcl, "Unknown cluster " ChipLogFormatMEI, ChipLogValueMEI(aCommandPath.mClusterId)); + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCluster); + break; + } + + Compatibility::ResetEmberAfObjects(); +} + +} // namespace app +} // namespace chip diff --git a/zzz_generated/dynamic-bridge-app/zap-generated/PluginApplicationCallbacks.h b/zzz_generated/dynamic-bridge-app/zap-generated/PluginApplicationCallbacks.h new file mode 100644 index 00000000000000..f0368e6a64bb30 --- /dev/null +++ b/zzz_generated/dynamic-bridge-app/zap-generated/PluginApplicationCallbacks.h @@ -0,0 +1,50 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * + * 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. + */ + +// THIS FILE IS GENERATED BY ZAP + +#pragma once + +#include + +#define MATTER_PLUGINS_INIT \ + MatterIdentifyPluginServerInitCallback(); \ + MatterOnOffPluginServerInitCallback(); \ + MatterLevelControlPluginServerInitCallback(); \ + MatterDescriptorPluginServerInitCallback(); \ + MatterBindingPluginClientInitCallback(); \ + MatterAccessControlPluginClientInitCallback(); \ + MatterAccessControlPluginServerInitCallback(); \ + MatterActionsPluginServerInitCallback(); \ + MatterBasicPluginServerInitCallback(); \ + MatterLocalizationConfigurationPluginServerInitCallback(); \ + MatterTimeFormatLocalizationPluginServerInitCallback(); \ + MatterUnitLocalizationPluginServerInitCallback(); \ + MatterGeneralCommissioningPluginServerInitCallback(); \ + MatterNetworkCommissioningPluginServerInitCallback(); \ + MatterDiagnosticLogsPluginServerInitCallback(); \ + MatterGeneralDiagnosticsPluginServerInitCallback(); \ + MatterSoftwareDiagnosticsPluginServerInitCallback(); \ + MatterThreadNetworkDiagnosticsPluginServerInitCallback(); \ + MatterWiFiNetworkDiagnosticsPluginServerInitCallback(); \ + MatterEthernetNetworkDiagnosticsPluginServerInitCallback(); \ + MatterSwitchPluginServerInitCallback(); \ + MatterAdministratorCommissioningPluginServerInitCallback(); \ + MatterOperationalCredentialsPluginServerInitCallback(); \ + MatterGroupKeyManagementPluginServerInitCallback(); \ + MatterUserLabelPluginServerInitCallback(); \ + MatterTemperatureMeasurementPluginServerInitCallback(); diff --git a/zzz_generated/dynamic-bridge-app/zap-generated/access.h b/zzz_generated/dynamic-bridge-app/zap-generated/access.h new file mode 100644 index 00000000000000..398e4e77d351c2 --- /dev/null +++ b/zzz_generated/dynamic-bridge-app/zap-generated/access.h @@ -0,0 +1,260 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * + * 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. + */ + +// THIS FILE IS GENERATED BY ZAP + +// Prevent multiple inclusion +#pragma once + +#include + +// Prevent changing generated format +// clang-format off + +//////////////////////////////////////////////////////////////////////////////// + +// Parallel array data (*cluster*, attribute, privilege) for read attribute +#define GENERATED_ACCESS_READ_ATTRIBUTE__CLUSTER { \ + /* Cluster: Level Control, Attribute: StartUpCurrentLevel, Privilege: view */ \ + 31, /* Cluster: Access Control, Attribute: ACL, Privilege: administer */ \ + 31, /* Cluster: Access Control, Attribute: Extension, Privilege: administer */ \ + /* Cluster: Access Control, Attribute: SubjectsPerAccessControlEntry, Privilege: view */ \ + /* Cluster: Access Control, Attribute: TargetsPerAccessControlEntry, Privilege: view */ \ + /* Cluster: Access Control, Attribute: AccessControlEntriesPerFabric, Privilege: view */ \ + /* Cluster: Basic, Attribute: NodeLabel, Privilege: view */ \ + /* Cluster: Basic, Attribute: Location, Privilege: view */ \ + /* Cluster: Basic, Attribute: LocalConfigDisabled, Privilege: view */ \ + /* Cluster: General Commissioning, Attribute: Breadcrumb, Privilege: view */ \ + 49, /* Cluster: Network Commissioning, Attribute: MaxNetworks, Privilege: administer */ \ + 49, /* Cluster: Network Commissioning, Attribute: Networks, Privilege: administer */ \ + /* Cluster: Network Commissioning, Attribute: InterfaceEnabled, Privilege: view */ \ + 49, /* Cluster: Network Commissioning, Attribute: LastNetworkingStatus, Privilege: administer */ \ + 49, /* Cluster: Network Commissioning, Attribute: LastNetworkID, Privilege: administer */ \ + 49, /* Cluster: Network Commissioning, Attribute: LastConnectErrorValue, Privilege: administer */ \ + 62, /* Cluster: Operational Credentials, Attribute: NOCs, Privilege: administer */ \ + /* Cluster: Group Key Management, Attribute: GroupKeyMap, Privilege: view */ \ + /* Cluster: User Label, Attribute: label list, Privilege: view */ \ +} + +// Parallel array data (cluster, *attribute*, privilege) for read attribute +#define GENERATED_ACCESS_READ_ATTRIBUTE__ATTRIBUTE { \ + /* Cluster: Level Control, Attribute: StartUpCurrentLevel, Privilege: view */ \ + 0, /* Cluster: Access Control, Attribute: ACL, Privilege: administer */ \ + 1, /* Cluster: Access Control, Attribute: Extension, Privilege: administer */ \ + /* Cluster: Access Control, Attribute: SubjectsPerAccessControlEntry, Privilege: view */ \ + /* Cluster: Access Control, Attribute: TargetsPerAccessControlEntry, Privilege: view */ \ + /* Cluster: Access Control, Attribute: AccessControlEntriesPerFabric, Privilege: view */ \ + /* Cluster: Basic, Attribute: NodeLabel, Privilege: view */ \ + /* Cluster: Basic, Attribute: Location, Privilege: view */ \ + /* Cluster: Basic, Attribute: LocalConfigDisabled, Privilege: view */ \ + /* Cluster: General Commissioning, Attribute: Breadcrumb, Privilege: view */ \ + 0, /* Cluster: Network Commissioning, Attribute: MaxNetworks, Privilege: administer */ \ + 1, /* Cluster: Network Commissioning, Attribute: Networks, Privilege: administer */ \ + /* Cluster: Network Commissioning, Attribute: InterfaceEnabled, Privilege: view */ \ + 5, /* Cluster: Network Commissioning, Attribute: LastNetworkingStatus, Privilege: administer */ \ + 6, /* Cluster: Network Commissioning, Attribute: LastNetworkID, Privilege: administer */ \ + 7, /* Cluster: Network Commissioning, Attribute: LastConnectErrorValue, Privilege: administer */ \ + 0, /* Cluster: Operational Credentials, Attribute: NOCs, Privilege: administer */ \ + /* Cluster: Group Key Management, Attribute: GroupKeyMap, Privilege: view */ \ + /* Cluster: User Label, Attribute: label list, Privilege: view */ \ +} + +// Parallel array data (cluster, attribute, *privilege*) for read attribute +#define GENERATED_ACCESS_READ_ATTRIBUTE__PRIVILEGE { \ + /* Cluster: Level Control, Attribute: StartUpCurrentLevel, Privilege: view */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Access Control, Attribute: ACL, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Access Control, Attribute: Extension, Privilege: administer */ \ + /* Cluster: Access Control, Attribute: SubjectsPerAccessControlEntry, Privilege: view */ \ + /* Cluster: Access Control, Attribute: TargetsPerAccessControlEntry, Privilege: view */ \ + /* Cluster: Access Control, Attribute: AccessControlEntriesPerFabric, Privilege: view */ \ + /* Cluster: Basic, Attribute: NodeLabel, Privilege: view */ \ + /* Cluster: Basic, Attribute: Location, Privilege: view */ \ + /* Cluster: Basic, Attribute: LocalConfigDisabled, Privilege: view */ \ + /* Cluster: General Commissioning, Attribute: Breadcrumb, Privilege: view */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Network Commissioning, Attribute: MaxNetworks, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Network Commissioning, Attribute: Networks, Privilege: administer */ \ + /* Cluster: Network Commissioning, Attribute: InterfaceEnabled, Privilege: view */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Network Commissioning, Attribute: LastNetworkingStatus, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Network Commissioning, Attribute: LastNetworkID, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Network Commissioning, Attribute: LastConnectErrorValue, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Operational Credentials, Attribute: NOCs, Privilege: administer */ \ + /* Cluster: Group Key Management, Attribute: GroupKeyMap, Privilege: view */ \ + /* Cluster: User Label, Attribute: label list, Privilege: view */ \ +} + +//////////////////////////////////////////////////////////////////////////////// + +// Parallel array data (*cluster*, attribute, privilege) for write attribute +#define GENERATED_ACCESS_WRITE_ATTRIBUTE__CLUSTER { \ + 8, /* Cluster: Level Control, Attribute: StartUpCurrentLevel, Privilege: manage */ \ + 31, /* Cluster: Access Control, Attribute: ACL, Privilege: administer */ \ + 31, /* Cluster: Access Control, Attribute: Extension, Privilege: administer */ \ + 40, /* Cluster: Basic, Attribute: NodeLabel, Privilege: manage */ \ + 40, /* Cluster: Basic, Attribute: Location, Privilege: administer */ \ + 40, /* Cluster: Basic, Attribute: LocalConfigDisabled, Privilege: manage */ \ + 48, /* Cluster: General Commissioning, Attribute: Breadcrumb, Privilege: administer */ \ + 49, /* Cluster: Network Commissioning, Attribute: InterfaceEnabled, Privilege: administer */ \ + 63, /* Cluster: Group Key Management, Attribute: GroupKeyMap, Privilege: manage */ \ + 65, /* Cluster: User Label, Attribute: label list, Privilege: manage */ \ +} + +// Parallel array data (cluster, *attribute*, privilege) for write attribute +#define GENERATED_ACCESS_WRITE_ATTRIBUTE__ATTRIBUTE { \ + 16384, /* Cluster: Level Control, Attribute: StartUpCurrentLevel, Privilege: manage */ \ + 0, /* Cluster: Access Control, Attribute: ACL, Privilege: administer */ \ + 1, /* Cluster: Access Control, Attribute: Extension, Privilege: administer */ \ + 5, /* Cluster: Basic, Attribute: NodeLabel, Privilege: manage */ \ + 6, /* Cluster: Basic, Attribute: Location, Privilege: administer */ \ + 16, /* Cluster: Basic, Attribute: LocalConfigDisabled, Privilege: manage */ \ + 0, /* Cluster: General Commissioning, Attribute: Breadcrumb, Privilege: administer */ \ + 4, /* Cluster: Network Commissioning, Attribute: InterfaceEnabled, Privilege: administer */ \ + 0, /* Cluster: Group Key Management, Attribute: GroupKeyMap, Privilege: manage */ \ + 0, /* Cluster: User Label, Attribute: label list, Privilege: manage */ \ +} + +// Parallel array data (cluster, attribute, *privilege*) for write attribute +#define GENERATED_ACCESS_WRITE_ATTRIBUTE__PRIVILEGE { \ + kMatterAccessPrivilegeManage, /* Cluster: Level Control, Attribute: StartUpCurrentLevel, Privilege: manage */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Access Control, Attribute: ACL, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Access Control, Attribute: Extension, Privilege: administer */ \ + kMatterAccessPrivilegeManage, /* Cluster: Basic, Attribute: NodeLabel, Privilege: manage */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Basic, Attribute: Location, Privilege: administer */ \ + kMatterAccessPrivilegeManage, /* Cluster: Basic, Attribute: LocalConfigDisabled, Privilege: manage */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: General Commissioning, Attribute: Breadcrumb, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Network Commissioning, Attribute: InterfaceEnabled, Privilege: administer */ \ + kMatterAccessPrivilegeManage, /* Cluster: Group Key Management, Attribute: GroupKeyMap, Privilege: manage */ \ + kMatterAccessPrivilegeManage, /* Cluster: User Label, Attribute: label list, Privilege: manage */ \ +} + +//////////////////////////////////////////////////////////////////////////////// + +// Parallel array data (*cluster*, command, privilege) for invoke command +#define GENERATED_ACCESS_INVOKE_COMMAND__CLUSTER { \ + 3, /* Cluster: Identify, Command: Identify, Privilege: manage */ \ + 3, /* Cluster: Identify, Command: TriggerEffect, Privilege: manage */ \ + 48, /* Cluster: General Commissioning, Command: ArmFailSafe, Privilege: administer */ \ + 48, /* Cluster: General Commissioning, Command: SetRegulatoryConfig, Privilege: administer */ \ + 48, /* Cluster: General Commissioning, Command: CommissioningComplete, Privilege: administer */ \ + 49, /* Cluster: Network Commissioning, Command: ScanNetworks, Privilege: administer */ \ + 49, /* Cluster: Network Commissioning, Command: AddOrUpdateWiFiNetwork, Privilege: administer */ \ + 49, /* Cluster: Network Commissioning, Command: AddOrUpdateThreadNetwork, Privilege: administer */ \ + 49, /* Cluster: Network Commissioning, Command: RemoveNetwork, Privilege: administer */ \ + 49, /* Cluster: Network Commissioning, Command: ConnectNetwork, Privilege: administer */ \ + 49, /* Cluster: Network Commissioning, Command: ReorderNetwork, Privilege: administer */ \ + 51, /* Cluster: General Diagnostics, Command: TestEventTrigger, Privilege: manage */ \ + 60, /* Cluster: AdministratorCommissioning, Command: OpenCommissioningWindow, Privilege: administer */ \ + 60, /* Cluster: AdministratorCommissioning, Command: OpenBasicCommissioningWindow, Privilege: administer */ \ + 60, /* Cluster: AdministratorCommissioning, Command: RevokeCommissioning, Privilege: administer */ \ + 62, /* Cluster: Operational Credentials, Command: AttestationRequest, Privilege: administer */ \ + 62, /* Cluster: Operational Credentials, Command: CertificateChainRequest, Privilege: administer */ \ + 62, /* Cluster: Operational Credentials, Command: CSRRequest, Privilege: administer */ \ + 62, /* Cluster: Operational Credentials, Command: AddNOC, Privilege: administer */ \ + 62, /* Cluster: Operational Credentials, Command: UpdateNOC, Privilege: administer */ \ + 62, /* Cluster: Operational Credentials, Command: UpdateFabricLabel, Privilege: administer */ \ + 62, /* Cluster: Operational Credentials, Command: RemoveFabric, Privilege: administer */ \ + 62, /* Cluster: Operational Credentials, Command: AddTrustedRootCertificate, Privilege: administer */ \ + 63, /* Cluster: Group Key Management, Command: KeySetWrite, Privilege: administer */ \ + 63, /* Cluster: Group Key Management, Command: KeySetRead, Privilege: administer */ \ + 63, /* Cluster: Group Key Management, Command: KeySetRemove, Privilege: administer */ \ + 63, /* Cluster: Group Key Management, Command: KeySetReadAllIndices, Privilege: administer */ \ +} + +// Parallel array data (cluster, *command*, privilege) for invoke command +#define GENERATED_ACCESS_INVOKE_COMMAND__COMMAND { \ + 0, /* Cluster: Identify, Command: Identify, Privilege: manage */ \ + 64, /* Cluster: Identify, Command: TriggerEffect, Privilege: manage */ \ + 0, /* Cluster: General Commissioning, Command: ArmFailSafe, Privilege: administer */ \ + 2, /* Cluster: General Commissioning, Command: SetRegulatoryConfig, Privilege: administer */ \ + 4, /* Cluster: General Commissioning, Command: CommissioningComplete, Privilege: administer */ \ + 0, /* Cluster: Network Commissioning, Command: ScanNetworks, Privilege: administer */ \ + 2, /* Cluster: Network Commissioning, Command: AddOrUpdateWiFiNetwork, Privilege: administer */ \ + 3, /* Cluster: Network Commissioning, Command: AddOrUpdateThreadNetwork, Privilege: administer */ \ + 4, /* Cluster: Network Commissioning, Command: RemoveNetwork, Privilege: administer */ \ + 6, /* Cluster: Network Commissioning, Command: ConnectNetwork, Privilege: administer */ \ + 8, /* Cluster: Network Commissioning, Command: ReorderNetwork, Privilege: administer */ \ + 0, /* Cluster: General Diagnostics, Command: TestEventTrigger, Privilege: manage */ \ + 0, /* Cluster: AdministratorCommissioning, Command: OpenCommissioningWindow, Privilege: administer */ \ + 1, /* Cluster: AdministratorCommissioning, Command: OpenBasicCommissioningWindow, Privilege: administer */ \ + 2, /* Cluster: AdministratorCommissioning, Command: RevokeCommissioning, Privilege: administer */ \ + 0, /* Cluster: Operational Credentials, Command: AttestationRequest, Privilege: administer */ \ + 2, /* Cluster: Operational Credentials, Command: CertificateChainRequest, Privilege: administer */ \ + 4, /* Cluster: Operational Credentials, Command: CSRRequest, Privilege: administer */ \ + 6, /* Cluster: Operational Credentials, Command: AddNOC, Privilege: administer */ \ + 7, /* Cluster: Operational Credentials, Command: UpdateNOC, Privilege: administer */ \ + 9, /* Cluster: Operational Credentials, Command: UpdateFabricLabel, Privilege: administer */ \ + 10, /* Cluster: Operational Credentials, Command: RemoveFabric, Privilege: administer */ \ + 11, /* Cluster: Operational Credentials, Command: AddTrustedRootCertificate, Privilege: administer */ \ + 0, /* Cluster: Group Key Management, Command: KeySetWrite, Privilege: administer */ \ + 1, /* Cluster: Group Key Management, Command: KeySetRead, Privilege: administer */ \ + 3, /* Cluster: Group Key Management, Command: KeySetRemove, Privilege: administer */ \ + 4, /* Cluster: Group Key Management, Command: KeySetReadAllIndices, Privilege: administer */ \ +} + +// Parallel array data (cluster, command, *privilege*) for invoke command +#define GENERATED_ACCESS_INVOKE_COMMAND__PRIVILEGE { \ + kMatterAccessPrivilegeManage, /* Cluster: Identify, Command: Identify, Privilege: manage */ \ + kMatterAccessPrivilegeManage, /* Cluster: Identify, Command: TriggerEffect, Privilege: manage */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: General Commissioning, Command: ArmFailSafe, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: General Commissioning, Command: SetRegulatoryConfig, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: General Commissioning, Command: CommissioningComplete, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Network Commissioning, Command: ScanNetworks, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Network Commissioning, Command: AddOrUpdateWiFiNetwork, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Network Commissioning, Command: AddOrUpdateThreadNetwork, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Network Commissioning, Command: RemoveNetwork, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Network Commissioning, Command: ConnectNetwork, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Network Commissioning, Command: ReorderNetwork, Privilege: administer */ \ + kMatterAccessPrivilegeManage, /* Cluster: General Diagnostics, Command: TestEventTrigger, Privilege: manage */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: AdministratorCommissioning, Command: OpenCommissioningWindow, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: AdministratorCommissioning, Command: OpenBasicCommissioningWindow, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: AdministratorCommissioning, Command: RevokeCommissioning, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Operational Credentials, Command: AttestationRequest, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Operational Credentials, Command: CertificateChainRequest, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Operational Credentials, Command: CSRRequest, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Operational Credentials, Command: AddNOC, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Operational Credentials, Command: UpdateNOC, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Operational Credentials, Command: UpdateFabricLabel, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Operational Credentials, Command: RemoveFabric, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Operational Credentials, Command: AddTrustedRootCertificate, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Group Key Management, Command: KeySetWrite, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Group Key Management, Command: KeySetRead, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Group Key Management, Command: KeySetRemove, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Group Key Management, Command: KeySetReadAllIndices, Privilege: administer */ \ +} + +//////////////////////////////////////////////////////////////////////////////// + +// Parallel array data (*cluster*, event, privilege) for read event +#define GENERATED_ACCESS_READ_EVENT__CLUSTER { \ + 31, /* Cluster: Access Control, Event: AccessControlEntryChanged, Privilege: administer */ \ + 31, /* Cluster: Access Control, Event: AccessControlExtensionChanged, Privilege: administer */ \ +} + +// Parallel array data (cluster, *event*, privilege) for read event +#define GENERATED_ACCESS_READ_EVENT__EVENT { \ + 0, /* Cluster: Access Control, Event: AccessControlEntryChanged, Privilege: administer */ \ + 1, /* Cluster: Access Control, Event: AccessControlExtensionChanged, Privilege: administer */ \ +} + +// Parallel array data (cluster, event, *privilege*) for read event +#define GENERATED_ACCESS_READ_EVENT__PRIVILEGE { \ + kMatterAccessPrivilegeAdminister, /* Cluster: Access Control, Event: AccessControlEntryChanged, Privilege: administer */ \ + kMatterAccessPrivilegeAdminister, /* Cluster: Access Control, Event: AccessControlExtensionChanged, Privilege: administer */ \ +} + +//////////////////////////////////////////////////////////////////////////////// + +// clang-format on diff --git a/zzz_generated/dynamic-bridge-app/zap-generated/callback-stub.cpp b/zzz_generated/dynamic-bridge-app/zap-generated/callback-stub.cpp new file mode 100644 index 00000000000000..d8149a41611f21 --- /dev/null +++ b/zzz_generated/dynamic-bridge-app/zap-generated/callback-stub.cpp @@ -0,0 +1,327 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * + * 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. + */ + +// THIS FILE IS GENERATED BY ZAP + +#include +#include +#include +#include + +using namespace chip; + +// Cluster Init Functions +void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) +{ + switch (clusterId) + { + case ZCL_ACCESS_CONTROL_CLUSTER_ID: + emberAfAccessControlClusterInitCallback(endpoint); + break; + case ZCL_ACTIONS_CLUSTER_ID: + emberAfActionsClusterInitCallback(endpoint); + break; + case ZCL_ADMINISTRATOR_COMMISSIONING_CLUSTER_ID: + emberAfAdministratorCommissioningClusterInitCallback(endpoint); + break; + case ZCL_BASIC_CLUSTER_ID: + emberAfBasicClusterInitCallback(endpoint); + break; + case ZCL_BINDING_CLUSTER_ID: + emberAfBindingClusterInitCallback(endpoint); + break; + case ZCL_DESCRIPTOR_CLUSTER_ID: + emberAfDescriptorClusterInitCallback(endpoint); + break; + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + emberAfDiagnosticLogsClusterInitCallback(endpoint); + break; + case ZCL_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_ID: + emberAfEthernetNetworkDiagnosticsClusterInitCallback(endpoint); + break; + case ZCL_GENERAL_COMMISSIONING_CLUSTER_ID: + emberAfGeneralCommissioningClusterInitCallback(endpoint); + break; + case ZCL_GENERAL_DIAGNOSTICS_CLUSTER_ID: + emberAfGeneralDiagnosticsClusterInitCallback(endpoint); + break; + case ZCL_GROUP_KEY_MANAGEMENT_CLUSTER_ID: + emberAfGroupKeyManagementClusterInitCallback(endpoint); + break; + case ZCL_IDENTIFY_CLUSTER_ID: + emberAfIdentifyClusterInitCallback(endpoint); + break; + case ZCL_LEVEL_CONTROL_CLUSTER_ID: + emberAfLevelControlClusterInitCallback(endpoint); + break; + case ZCL_LOCALIZATION_CONFIGURATION_CLUSTER_ID: + emberAfLocalizationConfigurationClusterInitCallback(endpoint); + break; + case ZCL_NETWORK_COMMISSIONING_CLUSTER_ID: + emberAfNetworkCommissioningClusterInitCallback(endpoint); + break; + case ZCL_ON_OFF_CLUSTER_ID: + emberAfOnOffClusterInitCallback(endpoint); + break; + case ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID: + emberAfOperationalCredentialsClusterInitCallback(endpoint); + break; + case ZCL_SOFTWARE_DIAGNOSTICS_CLUSTER_ID: + emberAfSoftwareDiagnosticsClusterInitCallback(endpoint); + break; + case ZCL_SWITCH_CLUSTER_ID: + emberAfSwitchClusterInitCallback(endpoint); + break; + case ZCL_TEMP_MEASUREMENT_CLUSTER_ID: + emberAfTemperatureMeasurementClusterInitCallback(endpoint); + break; + case ZCL_THREAD_NETWORK_DIAGNOSTICS_CLUSTER_ID: + emberAfThreadNetworkDiagnosticsClusterInitCallback(endpoint); + break; + case ZCL_TIME_FORMAT_LOCALIZATION_CLUSTER_ID: + emberAfTimeFormatLocalizationClusterInitCallback(endpoint); + break; + case ZCL_UNIT_LOCALIZATION_CLUSTER_ID: + emberAfUnitLocalizationClusterInitCallback(endpoint); + break; + case ZCL_USER_LABEL_CLUSTER_ID: + emberAfUserLabelClusterInitCallback(endpoint); + break; + case ZCL_WIFI_NETWORK_DIAGNOSTICS_CLUSTER_ID: + emberAfWiFiNetworkDiagnosticsClusterInitCallback(endpoint); + break; + default: + // Unrecognized cluster ID + break; + } +} + +void __attribute__((weak)) emberAfAccessControlClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfActionsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfAdministratorCommissioningClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfBasicClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfBindingClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfDescriptorClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfDiagnosticLogsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfEthernetNetworkDiagnosticsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfGeneralCommissioningClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfGeneralDiagnosticsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfGroupKeyManagementClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfIdentifyClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfLevelControlClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfLocalizationConfigurationClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfNetworkCommissioningClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfOnOffClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfOperationalCredentialsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfSoftwareDiagnosticsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfSwitchClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfTemperatureMeasurementClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfThreadNetworkDiagnosticsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfTimeFormatLocalizationClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfUnitLocalizationClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfUserLabelClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} +void __attribute__((weak)) emberAfWiFiNetworkDiagnosticsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} + +// +// Non-Cluster Related Callbacks +// + +void __attribute__((weak)) emberAfAddToCurrentAppTasksCallback(EmberAfApplicationTask tasks) {} + +void __attribute__((weak)) emberAfRemoveFromCurrentAppTasksCallback(EmberAfApplicationTask tasks) {} + +EmberAfAttributeWritePermission __attribute__((weak)) +emberAfAllowNetworkWriteAttributeCallback(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId, uint8_t * value, + uint8_t type) +{ + return EMBER_ZCL_ATTRIBUTE_WRITE_PERMISSION_ALLOW_WRITE_NORMAL; // Default +} + +bool __attribute__((weak)) emberAfAttributeReadAccessCallback(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId) +{ + return true; +} + +bool __attribute__((weak)) emberAfAttributeWriteAccessCallback(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId) +{ + return true; +} + +bool __attribute__((weak)) emberAfDefaultResponseCallback(ClusterId clusterId, CommandId commandId, EmberAfStatus status) +{ + return false; +} + +bool __attribute__((weak)) emberAfPreMessageSendCallback(EmberAfMessageStruct * messageStruct, EmberStatus * status) +{ + return false; +} + +bool __attribute__((weak)) emberAfMessageSentCallback(const MessageSendDestination & destination, EmberApsFrame * apsFrame, + uint16_t msgLen, uint8_t * message, EmberStatus status) +{ + return false; +} + +EmberAfStatus __attribute__((weak)) +emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterId clusterId, const EmberAfAttributeMetadata * attributeMetadata, + uint8_t * buffer, uint16_t maxReadLength) +{ + return EMBER_ZCL_STATUS_FAILURE; +} + +EmberAfStatus __attribute__((weak)) +emberAfExternalAttributeWriteCallback(EndpointId endpoint, ClusterId clusterId, const EmberAfAttributeMetadata * attributeMetadata, + uint8_t * buffer) +{ + return EMBER_ZCL_STATUS_FAILURE; +} + +uint32_t __attribute__((weak)) emberAfGetCurrentTimeCallback() +{ + return 0; +} + +bool __attribute__((weak)) +emberAfGetEndpointInfoCallback(EndpointId endpoint, uint8_t * returnNetworkIndex, EmberAfEndpointInfoStruct * returnEndpointInfo) +{ + return false; +} + +void __attribute__((weak)) emberAfRegistrationAbortCallback() {} + +EmberStatus __attribute__((weak)) +emberAfInterpanSendMessageCallback(EmberAfInterpanHeader * header, uint16_t messageLength, uint8_t * message) +{ + return EMBER_LIBRARY_NOT_PRESENT; +} + +bool __attribute__((weak)) emberAfStartMoveCallback() +{ + return false; +} + +chip::Protocols::InteractionModel::Status __attribute__((weak)) +MatterPreAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size, + uint8_t * value) +{ + return chip::Protocols::InteractionModel::Status::Success; +} + +void __attribute__((weak)) MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, + uint16_t size, uint8_t * value) +{} diff --git a/zzz_generated/dynamic-bridge-app/zap-generated/endpoint_config.h b/zzz_generated/dynamic-bridge-app/zap-generated/endpoint_config.h new file mode 100644 index 00000000000000..d64812972df90f --- /dev/null +++ b/zzz_generated/dynamic-bridge-app/zap-generated/endpoint_config.h @@ -0,0 +1,1041 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * + * 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. + */ + +// THIS FILE IS GENERATED BY ZAP + +// Prevent multiple inclusion +#pragma once + +#include + +// Default values for the attributes longer than a pointer, +// in a form of a binary blob +// Separate block is generated for big-endian and little-endian cases. +#if BIGENDIAN_CPU +#define GENERATED_DEFAULTS \ + { \ + \ + /* Endpoint: 0, Cluster: Localization Configuration (server), big-endian */ \ + \ + /* 0 - ActiveLocale, */ \ + 5, 'e', 'n', '-', 'U', 'S', \ + \ + /* Endpoint: 0, Cluster: General Commissioning (server), big-endian */ \ + \ + /* 6 - Breadcrumb, */ \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + \ + /* Endpoint: 1, Cluster: Actions (server), big-endian */ \ + \ + /* 14 - SetupURL, */ \ + 19, 0, 'h', 't', 't', 'p', 's', ':', '/', '/', 'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', \ + } + +#else // !BIGENDIAN_CPU +#define GENERATED_DEFAULTS \ + { \ + \ + /* Endpoint: 0, Cluster: Localization Configuration (server), little-endian */ \ + \ + /* 0 - ActiveLocale, */ \ + 5, 'e', 'n', '-', 'U', 'S', \ + \ + /* Endpoint: 0, Cluster: General Commissioning (server), little-endian */ \ + \ + /* 6 - Breadcrumb, */ \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + \ + /* Endpoint: 1, Cluster: Actions (server), little-endian */ \ + \ + /* 14 - SetupURL, */ \ + 19, 0, 'h', 't', 't', 'p', 's', ':', '/', '/', 'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', \ + } + +#endif // BIGENDIAN_CPU + +#define GENERATED_DEFAULTS_COUNT (3) + +#define ZAP_TYPE(type) ZCL_##type##_ATTRIBUTE_TYPE +#define ZAP_LONG_DEFAULTS_INDEX(index) \ + { \ + &generatedDefaults[index] \ + } +#define ZAP_MIN_MAX_DEFAULTS_INDEX(index) \ + { \ + &minMaxDefaults[index] \ + } +#define ZAP_EMPTY_DEFAULT() \ + { \ + (uint32_t) 0 \ + } +#define ZAP_SIMPLE_DEFAULT(x) \ + { \ + (uint32_t) x \ + } + +// This is an array of EmberAfAttributeMinMaxValue structures. +#define GENERATED_MIN_MAX_DEFAULT_COUNT 3 +#define GENERATED_MIN_MAX_DEFAULTS \ + { \ + \ + /* Endpoint: 0, Cluster: Time Format Localization (server) */ \ + { (uint16_t) 0x0, (uint16_t) 0x0, (uint16_t) 0x1 }, /* HourFormat */ \ + \ + /* Endpoint: 0, Cluster: Unit Localization (server) */ \ + { (uint16_t) 0x0, (uint16_t) 0x0, (uint16_t) 0x2 }, /* TemperatureUnit */ \ + \ + /* Endpoint: 2, Cluster: Level Control (server) */ { (uint16_t) 0x0, (uint16_t) 0x0, (uint16_t) 0x3 } /* Options */ \ + } + +#define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask +// This is an array of EmberAfAttributeMetadata structures. +#define GENERATED_ATTRIBUTE_COUNT 246 +#define GENERATED_ATTRIBUTES \ + { \ + \ + /* Endpoint: 0, Cluster: Descriptor (server) */ \ + { 0x00000000, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* DeviceTypeList */ \ + { 0x00000001, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* ServerList */ \ + { 0x00000002, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* ClientList */ \ + { 0x00000003, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* PartsList */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: Access Control (server) */ \ + { 0x00000000, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ + ZAP_EMPTY_DEFAULT() }, /* ACL */ \ + { 0x00000001, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ + ZAP_EMPTY_DEFAULT() }, /* Extension */ \ + { 0x00000002, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* SubjectsPerAccessControlEntry */ \ + { 0x00000003, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* TargetsPerAccessControlEntry */ \ + { 0x00000004, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* AccessControlEntriesPerFabric */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: Basic (server) */ \ + { 0x00000000, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \ + ZAP_EMPTY_DEFAULT() }, /* DataModelRevision */ \ + { 0x00000001, ZAP_TYPE(CHAR_STRING), 33, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \ + ZAP_EMPTY_DEFAULT() }, /* VendorName */ \ + { 0x00000002, ZAP_TYPE(VENDOR_ID), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \ + ZAP_EMPTY_DEFAULT() }, /* VendorID */ \ + { 0x00000003, ZAP_TYPE(CHAR_STRING), 33, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \ + ZAP_EMPTY_DEFAULT() }, /* ProductName */ \ + { 0x00000004, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \ + ZAP_EMPTY_DEFAULT() }, /* ProductID */ \ + { 0x00000005, ZAP_TYPE(CHAR_STRING), 33, \ + ZAP_ATTRIBUTE_MASK(TOKENIZE) | ZAP_ATTRIBUTE_MASK(SINGLETON) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ + ZAP_EMPTY_DEFAULT() }, /* NodeLabel */ \ + { 0x00000006, ZAP_TYPE(CHAR_STRING), 3, \ + ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ + ZAP_EMPTY_DEFAULT() }, /* Location */ \ + { 0x00000007, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \ + ZAP_EMPTY_DEFAULT() }, /* HardwareVersion */ \ + { 0x00000008, ZAP_TYPE(CHAR_STRING), 65, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \ + ZAP_EMPTY_DEFAULT() }, /* HardwareVersionString */ \ + { 0x00000009, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \ + ZAP_EMPTY_DEFAULT() }, /* SoftwareVersion */ \ + { 0x0000000A, ZAP_TYPE(CHAR_STRING), 65, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \ + ZAP_EMPTY_DEFAULT() }, /* SoftwareVersionString */ \ + { 0x0000000B, ZAP_TYPE(CHAR_STRING), 17, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \ + ZAP_EMPTY_DEFAULT() }, /* ManufacturingDate */ \ + { 0x0000000C, ZAP_TYPE(CHAR_STRING), 33, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \ + ZAP_EMPTY_DEFAULT() }, /* PartNumber */ \ + { 0x0000000D, ZAP_TYPE(LONG_CHAR_STRING), 258, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \ + ZAP_EMPTY_DEFAULT() }, /* ProductURL */ \ + { 0x0000000E, ZAP_TYPE(CHAR_STRING), 65, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \ + ZAP_EMPTY_DEFAULT() }, /* ProductLabel */ \ + { 0x0000000F, ZAP_TYPE(CHAR_STRING), 33, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \ + ZAP_EMPTY_DEFAULT() }, /* SerialNumber */ \ + { 0x00000010, ZAP_TYPE(BOOLEAN), 1, \ + ZAP_ATTRIBUTE_MASK(TOKENIZE) | ZAP_ATTRIBUTE_MASK(SINGLETON) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ + ZAP_SIMPLE_DEFAULT(0) }, /* LocalConfigDisabled */ \ + { 0x00000011, ZAP_TYPE(BOOLEAN), 1, ZAP_ATTRIBUTE_MASK(SINGLETON), ZAP_SIMPLE_DEFAULT(1) }, /* Reachable */ \ + { 0x00000012, ZAP_TYPE(CHAR_STRING), 33, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \ + ZAP_EMPTY_DEFAULT() }, /* UniqueID */ \ + { 0x00000013, ZAP_TYPE(STRUCT), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* CapabilityMinima */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(SINGLETON), ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: Localization Configuration (server) */ \ + { 0x00000000, ZAP_TYPE(CHAR_STRING), 36, ZAP_ATTRIBUTE_MASK(TOKENIZE) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ + ZAP_LONG_DEFAULTS_INDEX(0) }, /* ActiveLocale */ \ + { 0x00000001, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* SupportedLocales */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: Time Format Localization (server) */ \ + { 0x00000000, ZAP_TYPE(ENUM8), 1, \ + ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(TOKENIZE) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ + ZAP_MIN_MAX_DEFAULTS_INDEX(0) }, /* HourFormat */ \ + { 0x00000001, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(TOKENIZE) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ + ZAP_SIMPLE_DEFAULT(0) }, /* ActiveCalendarType */ \ + { 0x00000002, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* SupportedCalendarTypes */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: Unit Localization (server) */ \ + { 0x00000000, ZAP_TYPE(ENUM8), 1, \ + ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(TOKENIZE) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ + ZAP_MIN_MAX_DEFAULTS_INDEX(1) }, /* TemperatureUnit */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0x1) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: General Commissioning (server) */ \ + { 0x00000000, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_LONG_DEFAULTS_INDEX(6) }, /* Breadcrumb */ \ + { 0x00000001, ZAP_TYPE(STRUCT), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* BasicCommissioningInfo */ \ + { 0x00000002, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* RegulatoryConfig */ \ + { 0x00000003, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* LocationCapability */ \ + { 0x00000004, ZAP_TYPE(BOOLEAN), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* SupportsConcurrentConnection */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: Network Commissioning (server) */ \ + { 0x00000000, ZAP_TYPE(INT8U), 1, 0, ZAP_EMPTY_DEFAULT() }, /* MaxNetworks */ \ + { 0x00000001, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* Networks */ \ + { 0x00000002, ZAP_TYPE(INT8U), 1, 0, ZAP_EMPTY_DEFAULT() }, /* ScanMaxTimeSeconds */ \ + { 0x00000003, ZAP_TYPE(INT8U), 1, 0, ZAP_EMPTY_DEFAULT() }, /* ConnectMaxTimeSeconds */ \ + { 0x00000004, ZAP_TYPE(BOOLEAN), 1, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_EMPTY_DEFAULT() }, /* InterfaceEnabled */ \ + { 0x00000005, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(NULLABLE), ZAP_EMPTY_DEFAULT() }, /* LastNetworkingStatus */ \ + { 0x00000006, ZAP_TYPE(OCTET_STRING), 33, ZAP_ATTRIBUTE_MASK(NULLABLE), ZAP_EMPTY_DEFAULT() }, /* LastNetworkID */ \ + { 0x00000007, ZAP_TYPE(INT32S), 4, ZAP_ATTRIBUTE_MASK(NULLABLE), ZAP_EMPTY_DEFAULT() }, /* LastConnectErrorValue */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(2) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: General Diagnostics (server) */ \ + { 0x00000000, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* NetworkInterfaces */ \ + { 0x00000001, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* RebootCount */ \ + { 0x00000002, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* UpTime */ \ + { 0x00000003, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* TotalOperationalHours */ \ + { 0x00000004, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* BootReasons */ \ + { 0x00000005, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* ActiveHardwareFaults */ \ + { 0x00000006, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* ActiveRadioFaults */ \ + { 0x00000007, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* ActiveNetworkFaults */ \ + { 0x00000008, ZAP_TYPE(BOOLEAN), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* TestEventTriggersEnabled */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: Software Diagnostics (server) */ \ + { 0x00000000, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* ThreadMetrics */ \ + { 0x00000001, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* CurrentHeapFree */ \ + { 0x00000002, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* CurrentHeapUsed */ \ + { 0x00000003, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* CurrentHeapHighWatermark */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(1) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: Thread Network Diagnostics (server) */ \ + { 0x00000000, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* channel */ \ + { 0x00000001, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* RoutingRole */ \ + { 0x00000002, ZAP_TYPE(CHAR_STRING), 17, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* NetworkName */ \ + { 0x00000003, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* PanId */ \ + { 0x00000004, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* ExtendedPanId */ \ + { 0x00000005, ZAP_TYPE(OCTET_STRING), 18, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* MeshLocalPrefix */ \ + { 0x00000006, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* OverrunCount */ \ + { 0x00000007, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* NeighborTableList */ \ + { 0x00000008, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* RouteTableList */ \ + { 0x00000009, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* PartitionId */ \ + { 0x0000000A, ZAP_TYPE(INT8U), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* weighting */ \ + { 0x0000000B, ZAP_TYPE(INT8U), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* DataVersion */ \ + { 0x0000000C, ZAP_TYPE(INT8U), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* StableDataVersion */ \ + { 0x0000000D, ZAP_TYPE(INT8U), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* LeaderRouterId */ \ + { 0x0000000E, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* DetachedRoleCount */ \ + { 0x0000000F, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* ChildRoleCount */ \ + { 0x00000010, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* RouterRoleCount */ \ + { 0x00000011, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* LeaderRoleCount */ \ + { 0x00000012, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* AttachAttemptCount */ \ + { 0x00000013, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* PartitionIdChangeCount */ \ + { 0x00000014, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* BetterPartitionAttachAttemptCount */ \ + { 0x00000015, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* ParentChangeCount */ \ + { 0x00000016, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* TxTotalCount */ \ + { 0x00000017, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* TxUnicastCount */ \ + { 0x00000018, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* TxBroadcastCount */ \ + { 0x00000019, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* TxAckRequestedCount */ \ + { 0x0000001A, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* TxAckedCount */ \ + { 0x0000001B, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* TxNoAckRequestedCount */ \ + { 0x0000001C, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* TxDataCount */ \ + { 0x0000001D, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* TxDataPollCount */ \ + { 0x0000001E, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* TxBeaconCount */ \ + { 0x0000001F, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* TxBeaconRequestCount */ \ + { 0x00000020, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* TxOtherCount */ \ + { 0x00000021, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* TxRetryCount */ \ + { 0x00000022, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* TxDirectMaxRetryExpiryCount */ \ + { 0x00000023, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* TxIndirectMaxRetryExpiryCount */ \ + { 0x00000024, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* TxErrCcaCount */ \ + { 0x00000025, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* TxErrAbortCount */ \ + { 0x00000026, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* TxErrBusyChannelCount */ \ + { 0x00000027, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* RxTotalCount */ \ + { 0x00000028, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* RxUnicastCount */ \ + { 0x00000029, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* RxBroadcastCount */ \ + { 0x0000002A, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* RxDataCount */ \ + { 0x0000002B, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* RxDataPollCount */ \ + { 0x0000002C, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* RxBeaconCount */ \ + { 0x0000002D, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* RxBeaconRequestCount */ \ + { 0x0000002E, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* RxOtherCount */ \ + { 0x0000002F, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* RxAddressFilteredCount */ \ + { 0x00000030, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* RxDestAddrFilteredCount */ \ + { 0x00000031, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* RxDuplicatedCount */ \ + { 0x00000032, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* RxErrNoFrameCount */ \ + { 0x00000033, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* RxErrUnknownNeighborCount */ \ + { 0x00000034, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* RxErrInvalidSrcAddrCount */ \ + { 0x00000035, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* RxErrSecCount */ \ + { 0x00000036, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* RxErrFcsCount */ \ + { 0x00000037, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* RxErrOtherCount */ \ + { 0x00000038, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* ActiveTimestamp */ \ + { 0x00000039, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* PendingTimestamp */ \ + { 0x0000003A, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* Delay */ \ + { 0x0000003B, ZAP_TYPE(STRUCT), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* SecurityPolicy */ \ + { 0x0000003C, ZAP_TYPE(OCTET_STRING), 5, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* ChannelPage0Mask */ \ + { 0x0000003D, ZAP_TYPE(STRUCT), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* OperationalDatasetComponents */ \ + { 0x0000003E, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* ActiveNetworkFaultsList */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(15) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: WiFi Network Diagnostics (server) */ \ + { 0x00000000, ZAP_TYPE(OCTET_STRING), 7, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* bssid */ \ + { 0x00000001, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* SecurityType */ \ + { 0x00000002, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* WiFiVersion */ \ + { 0x00000003, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* ChannelNumber */ \ + { 0x00000004, ZAP_TYPE(INT8S), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* Rssi */ \ + { 0x00000005, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* BeaconLostCount */ \ + { 0x00000006, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* BeaconRxCount */ \ + { 0x00000007, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* PacketMulticastRxCount */ \ + { 0x00000008, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* PacketMulticastTxCount */ \ + { 0x00000009, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* PacketUnicastRxCount */ \ + { 0x0000000A, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* PacketUnicastTxCount */ \ + { 0x0000000B, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* CurrentMaxRate */ \ + { 0x0000000C, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* OverrunCount */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(3) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ + { 0x00000000, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* PHYRate */ \ + { 0x00000001, ZAP_TYPE(BOOLEAN), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* FullDuplex */ \ + { 0x00000002, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* PacketRxCount */ \ + { 0x00000003, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* PacketTxCount */ \ + { 0x00000004, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* TxErrCount */ \ + { 0x00000005, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* CollisionCount */ \ + { 0x00000006, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* OverrunCount */ \ + { 0x00000007, ZAP_TYPE(BOOLEAN), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* CarrierDetect */ \ + { 0x00000008, ZAP_TYPE(INT64U), 8, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* TimeSinceReset */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(3) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0x00000000, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* WindowStatus */ \ + { 0x00000001, ZAP_TYPE(FABRIC_IDX), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* AdminFabricIndex */ \ + { 0x00000002, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* AdminVendorId */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ + { 0x00000000, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* NOCs */ \ + { 0x00000001, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* Fabrics */ \ + { 0x00000002, ZAP_TYPE(INT8U), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* SupportedFabrics */ \ + { 0x00000003, ZAP_TYPE(INT8U), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* CommissionedFabrics */ \ + { 0x00000004, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* TrustedRootCertificates */ \ + { 0x00000005, ZAP_TYPE(INT8U), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* CurrentFabricIndex */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: Group Key Management (server) */ \ + { 0x00000000, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ + ZAP_EMPTY_DEFAULT() }, /* GroupKeyMap */ \ + { 0x00000001, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* GroupTable */ \ + { 0x00000002, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* MaxGroupsPerFabric */ \ + { 0x00000003, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), \ + ZAP_EMPTY_DEFAULT() }, /* MaxGroupKeysPerFabric */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: User Label (server) */ \ + { 0x00000000, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ + ZAP_EMPTY_DEFAULT() }, /* label list */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 1, Cluster: Identify (server) */ \ + { 0x00000000, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(WRITABLE), ZAP_SIMPLE_DEFAULT(0x0) }, /* identify time */ \ + { 0x00000001, ZAP_TYPE(ENUM8), 1, 0, ZAP_SIMPLE_DEFAULT(0x0) }, /* identify type */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(2) }, /* ClusterRevision */ \ + \ + /* Endpoint: 1, Cluster: Descriptor (server) */ \ + { 0x00000000, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* DeviceTypeList */ \ + { 0x00000001, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* ServerList */ \ + { 0x00000002, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* ClientList */ \ + { 0x00000003, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* PartsList */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 1, Cluster: Actions (server) */ \ + { 0x00000000, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* ActionList */ \ + { 0x00000001, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* EndpointLists */ \ + { 0x00000002, ZAP_TYPE(LONG_CHAR_STRING), 514, 0, ZAP_LONG_DEFAULTS_INDEX(14) }, /* SetupURL */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 2, Cluster: On/Off (server) */ \ + { 0x00000000, ZAP_TYPE(BOOLEAN), 1, 0, ZAP_SIMPLE_DEFAULT(0x00) }, /* OnOff */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(4) }, /* ClusterRevision */ \ + \ + /* Endpoint: 2, Cluster: Level Control (server) */ \ + { 0x00000000, ZAP_TYPE(INT8U), 1, ZAP_ATTRIBUTE_MASK(TOKENIZE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_SIMPLE_DEFAULT(0x00) }, /* CurrentLevel */ \ + { 0x00000001, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0000) }, /* RemainingTime */ \ + { 0x00000002, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(0x01) }, /* MinLevel */ \ + { 0x00000003, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(0xFE) }, /* MaxLevel */ \ + { 0x00000004, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0000) }, /* CurrentFrequency */ \ + { 0x00000005, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0000) }, /* MinFrequency */ \ + { 0x00000006, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0000) }, /* MaxFrequency */ \ + { 0x0000000F, ZAP_TYPE(BITMAP8), 1, ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ + ZAP_MIN_MAX_DEFAULTS_INDEX(2) }, /* Options */ \ + { 0x00000010, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(WRITABLE), \ + ZAP_SIMPLE_DEFAULT(0x0000) }, /* OnOffTransitionTime */ \ + { 0x00000011, ZAP_TYPE(INT8U), 1, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_SIMPLE_DEFAULT(0xFE) }, /* OnLevel */ \ + { 0x00000012, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* OnTransitionTime */ \ + { 0x00000013, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* OffTransitionTime */ \ + { 0x00000014, ZAP_TYPE(INT8U), 1, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* DefaultMoveRate */ \ + { 0x00004000, ZAP_TYPE(INT8U), 1, \ + ZAP_ATTRIBUTE_MASK(TOKENIZE) | ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_SIMPLE_DEFAULT(255) }, /* StartUpCurrentLevel */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(3) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(5) }, /* ClusterRevision */ \ + \ + /* Endpoint: 2, Cluster: Descriptor (server) */ \ + { 0x00000000, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* DeviceTypeList */ \ + { 0x00000001, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* ServerList */ \ + { 0x00000002, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* ClientList */ \ + { 0x00000003, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* PartsList */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* ClusterRevision */ \ + \ + /* Endpoint: 2, Cluster: Switch (server) */ \ + { 0x00000000, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(2) }, /* number of positions */ \ + { 0x00000001, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(1) }, /* current position */ \ + { 0x00000002, ZAP_TYPE(INT8U), 1, 0, ZAP_SIMPLE_DEFAULT(2) }, /* multi press max */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ + \ + /* Endpoint: 2, Cluster: Temperature Measurement (server) */ \ + { 0x00000000, ZAP_TYPE(INT16S), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* MeasuredValue */ \ + { 0x00000001, ZAP_TYPE(INT16S), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* MinMeasuredValue */ \ + { 0x00000002, ZAP_TYPE(INT16S), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ + ZAP_EMPTY_DEFAULT() }, /* MaxMeasuredValue */ \ + { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* FeatureMap */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* ClusterRevision */ \ + } + +// This is an array of EmberAfCluster structures. +#define ZAP_ATTRIBUTE_INDEX(index) (&generatedAttributes[index]) + +#define ZAP_GENERATED_COMMANDS_INDEX(index) ((chip::CommandId *) (&generatedCommands[index])) + +// Cluster function static arrays +#define GENERATED_FUNCTION_ARRAYS \ + const EmberAfGenericClusterFunction chipFuncArrayBasicServer[] = { \ + (EmberAfGenericClusterFunction) emberAfBasicClusterServerInitCallback, \ + }; \ + const EmberAfGenericClusterFunction chipFuncArrayLocalizationConfigurationServer[] = { \ + (EmberAfGenericClusterFunction) emberAfLocalizationConfigurationClusterServerInitCallback, \ + (EmberAfGenericClusterFunction) MatterLocalizationConfigurationClusterServerPreAttributeChangedCallback, \ + }; \ + const EmberAfGenericClusterFunction chipFuncArrayTimeFormatLocalizationServer[] = { \ + (EmberAfGenericClusterFunction) emberAfTimeFormatLocalizationClusterServerInitCallback, \ + (EmberAfGenericClusterFunction) MatterTimeFormatLocalizationClusterServerPreAttributeChangedCallback, \ + }; \ + const EmberAfGenericClusterFunction chipFuncArrayIdentifyServer[] = { \ + (EmberAfGenericClusterFunction) emberAfIdentifyClusterServerInitCallback, \ + (EmberAfGenericClusterFunction) MatterIdentifyClusterServerAttributeChangedCallback, \ + }; \ + const EmberAfGenericClusterFunction chipFuncArrayOnOffServer[] = { \ + (EmberAfGenericClusterFunction) emberAfOnOffClusterServerInitCallback, \ + }; \ + const EmberAfGenericClusterFunction chipFuncArrayLevelControlServer[] = { \ + (EmberAfGenericClusterFunction) emberAfLevelControlClusterServerInitCallback, \ + }; + +// clang-format off +#define GENERATED_COMMANDS { \ + /* Endpoint: 0, Cluster: General Commissioning (server) */\ + /* AcceptedCommandList (index=0) */ \ + 0x00000000 /* ArmFailSafe */, \ + 0x00000002 /* SetRegulatoryConfig */, \ + 0x00000004 /* CommissioningComplete */, \ + chip::kInvalidCommandId /* end of list */, \ + /* GeneratedCommandList (index=4)*/ \ + 0x00000001 /* ArmFailSafeResponse */, \ + 0x00000003 /* SetRegulatoryConfigResponse */, \ + 0x00000005 /* CommissioningCompleteResponse */, \ + chip::kInvalidCommandId /* end of list */, \ + /* Endpoint: 0, Cluster: Network Commissioning (server) */\ + /* AcceptedCommandList (index=8) */ \ + 0x00000000 /* ScanNetworks */, \ + 0x00000002 /* AddOrUpdateWiFiNetwork */, \ + 0x00000003 /* AddOrUpdateThreadNetwork */, \ + 0x00000004 /* RemoveNetwork */, \ + 0x00000006 /* ConnectNetwork */, \ + 0x00000008 /* ReorderNetwork */, \ + chip::kInvalidCommandId /* end of list */, \ + /* GeneratedCommandList (index=15)*/ \ + 0x00000001 /* ScanNetworksResponse */, \ + 0x00000005 /* NetworkConfigResponse */, \ + 0x00000007 /* ConnectNetworkResponse */, \ + chip::kInvalidCommandId /* end of list */, \ + /* Endpoint: 0, Cluster: Diagnostic Logs (server) */\ + /* AcceptedCommandList (index=19) */ \ + 0x00000000 /* RetrieveLogsRequest */, \ + chip::kInvalidCommandId /* end of list */, \ + /* GeneratedCommandList (index=21)*/ \ + 0x00000001 /* RetrieveLogsResponse */, \ + chip::kInvalidCommandId /* end of list */, \ + /* Endpoint: 0, Cluster: General Diagnostics (server) */\ + /* AcceptedCommandList (index=23) */ \ + 0x00000000 /* TestEventTrigger */, \ + 0x00000000 /* TestEventTrigger */, \ + chip::kInvalidCommandId /* end of list */, \ + /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */\ + /* AcceptedCommandList (index=26) */ \ + 0x00000000 /* ResetCounts */, \ + chip::kInvalidCommandId /* end of list */, \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */\ + /* AcceptedCommandList (index=28) */ \ + 0x00000000 /* OpenCommissioningWindow */, \ + 0x00000001 /* OpenBasicCommissioningWindow */, \ + 0x00000002 /* RevokeCommissioning */, \ + chip::kInvalidCommandId /* end of list */, \ + /* Endpoint: 0, Cluster: Operational Credentials (server) */\ + /* AcceptedCommandList (index=32) */ \ + 0x00000000 /* AttestationRequest */, \ + 0x00000002 /* CertificateChainRequest */, \ + 0x00000004 /* CSRRequest */, \ + 0x00000006 /* AddNOC */, \ + 0x00000007 /* UpdateNOC */, \ + 0x00000009 /* UpdateFabricLabel */, \ + 0x0000000A /* RemoveFabric */, \ + 0x0000000B /* AddTrustedRootCertificate */, \ + chip::kInvalidCommandId /* end of list */, \ + /* GeneratedCommandList (index=41)*/ \ + 0x00000001 /* AttestationResponse */, \ + 0x00000003 /* CertificateChainResponse */, \ + 0x00000005 /* CSRResponse */, \ + 0x00000008 /* NOCResponse */, \ + chip::kInvalidCommandId /* end of list */, \ + /* Endpoint: 0, Cluster: Group Key Management (server) */\ + /* AcceptedCommandList (index=46) */ \ + 0x00000000 /* KeySetWrite */, \ + 0x00000001 /* KeySetRead */, \ + 0x00000003 /* KeySetRemove */, \ + 0x00000004 /* KeySetReadAllIndices */, \ + chip::kInvalidCommandId /* end of list */, \ + /* GeneratedCommandList (index=51)*/ \ + 0x00000002 /* KeySetReadResponse */, \ + 0x00000005 /* KeySetReadAllIndicesResponse */, \ + chip::kInvalidCommandId /* end of list */, \ + /* Endpoint: 1, Cluster: Identify (server) */\ + /* AcceptedCommandList (index=54) */ \ + 0x00000000 /* Identify */, \ + 0x00000040 /* TriggerEffect */, \ + chip::kInvalidCommandId /* end of list */, \ + /* Endpoint: 1, Cluster: Actions (server) */\ + /* AcceptedCommandList (index=57) */ \ + 0x00000000 /* InstantAction */, \ + chip::kInvalidCommandId /* end of list */, \ + /* Endpoint: 2, Cluster: On/Off (server) */\ + /* AcceptedCommandList (index=59) */ \ + 0x00000000 /* Off */, \ + 0x00000001 /* On */, \ + 0x00000002 /* Toggle */, \ + chip::kInvalidCommandId /* end of list */, \ + /* Endpoint: 2, Cluster: Level Control (server) */\ + /* AcceptedCommandList (index=63) */ \ + 0x00000000 /* MoveToLevel */, \ + 0x00000001 /* Move */, \ + 0x00000002 /* Step */, \ + 0x00000003 /* Stop */, \ + 0x00000004 /* MoveToLevelWithOnOff */, \ + 0x00000005 /* MoveWithOnOff */, \ + 0x00000006 /* StepWithOnOff */, \ + 0x00000007 /* StopWithOnOff */, \ + chip::kInvalidCommandId /* end of list */, \ +} + +// clang-format on + +#define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask +#define GENERATED_CLUSTER_COUNT 28 + +// clang-format off +#define GENERATED_CLUSTERS { \ + { \ + /* Endpoint: 0, Cluster: Descriptor (server) */ \ + .clusterId = 0x0000001D, \ + .attributes = ZAP_ATTRIBUTE_INDEX(0), \ + .attributeCount = 6, \ + .clusterSize = 4, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = nullptr ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 0, Cluster: Access Control (client) */ \ + .clusterId = 0x0000001F, \ + .attributes = ZAP_ATTRIBUTE_INDEX(6), \ + .attributeCount = 0, \ + .clusterSize = 0, \ + .mask = ZAP_CLUSTER_MASK(CLIENT), \ + .functions = NULL, \ + .acceptedCommandList = nullptr ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 0, Cluster: Access Control (server) */ \ + .clusterId = 0x0000001F, \ + .attributes = ZAP_ATTRIBUTE_INDEX(6), \ + .attributeCount = 7, \ + .clusterSize = 6, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = nullptr ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 0, Cluster: Basic (server) */ \ + .clusterId = 0x00000028, \ + .attributes = ZAP_ATTRIBUTE_INDEX(13), \ + .attributeCount = 22, \ + .clusterSize = 41, \ + .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ + .functions = chipFuncArrayBasicServer, \ + .acceptedCommandList = nullptr ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 0, Cluster: Localization Configuration (server) */ \ + .clusterId = 0x0000002B, \ + .attributes = ZAP_ATTRIBUTE_INDEX(35), \ + .attributeCount = 4, \ + .clusterSize = 42, \ + .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(PRE_ATTRIBUTE_CHANGED_FUNCTION), \ + .functions = chipFuncArrayLocalizationConfigurationServer, \ + .acceptedCommandList = nullptr ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 0, Cluster: Time Format Localization (server) */ \ + .clusterId = 0x0000002C, \ + .attributes = ZAP_ATTRIBUTE_INDEX(39), \ + .attributeCount = 5, \ + .clusterSize = 8, \ + .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(PRE_ATTRIBUTE_CHANGED_FUNCTION), \ + .functions = chipFuncArrayTimeFormatLocalizationServer, \ + .acceptedCommandList = nullptr ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 0, Cluster: Unit Localization (server) */ \ + .clusterId = 0x0000002D, \ + .attributes = ZAP_ATTRIBUTE_INDEX(44), \ + .attributeCount = 3, \ + .clusterSize = 7, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = nullptr ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 0, Cluster: General Commissioning (server) */ \ + .clusterId = 0x00000030, \ + .attributes = ZAP_ATTRIBUTE_INDEX(47), \ + .attributeCount = 7, \ + .clusterSize = 14, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 0 ) ,\ + .generatedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 4 ) ,\ + },\ + { \ + /* Endpoint: 0, Cluster: Network Commissioning (server) */ \ + .clusterId = 0x00000031, \ + .attributes = ZAP_ATTRIBUTE_INDEX(54), \ + .attributeCount = 10, \ + .clusterSize = 48, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 8 ) ,\ + .generatedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 15 ) ,\ + },\ + { \ + /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ + .clusterId = 0x00000032, \ + .attributes = ZAP_ATTRIBUTE_INDEX(64), \ + .attributeCount = 2, \ + .clusterSize = 6, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 19 ) ,\ + .generatedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 21 ) ,\ + },\ + { \ + /* Endpoint: 0, Cluster: General Diagnostics (server) */ \ + .clusterId = 0x00000033, \ + .attributes = ZAP_ATTRIBUTE_INDEX(66), \ + .attributeCount = 11, \ + .clusterSize = 6, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 23 ) ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 0, Cluster: Software Diagnostics (server) */ \ + .clusterId = 0x00000034, \ + .attributes = ZAP_ATTRIBUTE_INDEX(77), \ + .attributeCount = 6, \ + .clusterSize = 6, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = nullptr ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 0, Cluster: Thread Network Diagnostics (server) */ \ + .clusterId = 0x00000035, \ + .attributes = ZAP_ATTRIBUTE_INDEX(83), \ + .attributeCount = 65, \ + .clusterSize = 6, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = nullptr ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 0, Cluster: WiFi Network Diagnostics (server) */ \ + .clusterId = 0x00000036, \ + .attributes = ZAP_ATTRIBUTE_INDEX(148), \ + .attributeCount = 15, \ + .clusterSize = 6, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = nullptr ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ + .clusterId = 0x00000037, \ + .attributes = ZAP_ATTRIBUTE_INDEX(163), \ + .attributeCount = 11, \ + .clusterSize = 6, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 26 ) ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + .clusterId = 0x0000003C, \ + .attributes = ZAP_ATTRIBUTE_INDEX(174), \ + .attributeCount = 5, \ + .clusterSize = 6, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 28 ) ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ + .clusterId = 0x0000003E, \ + .attributes = ZAP_ATTRIBUTE_INDEX(179), \ + .attributeCount = 8, \ + .clusterSize = 6, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 32 ) ,\ + .generatedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 41 ) ,\ + },\ + { \ + /* Endpoint: 0, Cluster: Group Key Management (server) */ \ + .clusterId = 0x0000003F, \ + .attributes = ZAP_ATTRIBUTE_INDEX(187), \ + .attributeCount = 6, \ + .clusterSize = 6, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 46 ) ,\ + .generatedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 51 ) ,\ + },\ + { \ + /* Endpoint: 0, Cluster: User Label (server) */ \ + .clusterId = 0x00000041, \ + .attributes = ZAP_ATTRIBUTE_INDEX(193), \ + .attributeCount = 3, \ + .clusterSize = 6, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = nullptr ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 1, Cluster: Identify (server) */ \ + .clusterId = 0x00000003, \ + .attributes = ZAP_ATTRIBUTE_INDEX(196), \ + .attributeCount = 4, \ + .clusterSize = 9, \ + .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(ATTRIBUTE_CHANGED_FUNCTION), \ + .functions = chipFuncArrayIdentifyServer, \ + .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 54 ) ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 1, Cluster: Descriptor (server) */ \ + .clusterId = 0x0000001D, \ + .attributes = ZAP_ATTRIBUTE_INDEX(200), \ + .attributeCount = 6, \ + .clusterSize = 6, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = nullptr ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 1, Cluster: Binding (client) */ \ + .clusterId = 0x0000001E, \ + .attributes = ZAP_ATTRIBUTE_INDEX(206), \ + .attributeCount = 0, \ + .clusterSize = 0, \ + .mask = ZAP_CLUSTER_MASK(CLIENT), \ + .functions = NULL, \ + .acceptedCommandList = nullptr ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 1, Cluster: Actions (server) */ \ + .clusterId = 0x00000025, \ + .attributes = ZAP_ATTRIBUTE_INDEX(206), \ + .attributeCount = 5, \ + .clusterSize = 520, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 57 ) ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 2, Cluster: On/Off (server) */ \ + .clusterId = 0x00000006, \ + .attributes = ZAP_ATTRIBUTE_INDEX(211), \ + .attributeCount = 3, \ + .clusterSize = 7, \ + .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ + .functions = chipFuncArrayOnOffServer, \ + .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 59 ) ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 2, Cluster: Level Control (server) */ \ + .clusterId = 0x00000008, \ + .attributes = ZAP_ATTRIBUTE_INDEX(214), \ + .attributeCount = 16, \ + .clusterSize = 27, \ + .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ + .functions = chipFuncArrayLevelControlServer, \ + .acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 63 ) ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 2, Cluster: Descriptor (server) */ \ + .clusterId = 0x0000001D, \ + .attributes = ZAP_ATTRIBUTE_INDEX(230), \ + .attributeCount = 6, \ + .clusterSize = 4, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = nullptr ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 2, Cluster: Switch (server) */ \ + .clusterId = 0x0000003B, \ + .attributes = ZAP_ATTRIBUTE_INDEX(236), \ + .attributeCount = 5, \ + .clusterSize = 9, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = nullptr ,\ + .generatedCommandList = nullptr ,\ + },\ + { \ + /* Endpoint: 2, Cluster: Temperature Measurement (server) */ \ + .clusterId = 0x00000402, \ + .attributes = ZAP_ATTRIBUTE_INDEX(241), \ + .attributeCount = 5, \ + .clusterSize = 0, \ + .mask = ZAP_CLUSTER_MASK(SERVER), \ + .functions = NULL, \ + .acceptedCommandList = nullptr ,\ + .generatedCommandList = nullptr ,\ + },\ +} + +// clang-format on + +#define ZAP_CLUSTER_INDEX(index) (&generatedClusters[index]) + +#define ZAP_FIXED_ENDPOINT_DATA_VERSION_COUNT 26 + +// This is an array of EmberAfEndpointType structures. +#define GENERATED_ENDPOINT_TYPES \ + { \ + { ZAP_CLUSTER_INDEX(0), 19, 230 }, { ZAP_CLUSTER_INDEX(19), 4, 535 }, { ZAP_CLUSTER_INDEX(23), 5, 47 }, \ + } + +// Largest attribute size is needed for various buffers +#define ATTRIBUTE_LARGEST (515) + +static_assert(ATTRIBUTE_LARGEST <= CHIP_CONFIG_MAX_ATTRIBUTE_STORE_ELEMENT_SIZE, "ATTRIBUTE_LARGEST larger than expected"); + +// Total size of singleton attributes +#define ATTRIBUTE_SINGLETONS_SIZE (37) + +// Total size of attribute storage +#define ATTRIBUTE_MAX_SIZE (812) + +// Number of fixed endpoints +#define FIXED_ENDPOINT_COUNT (3) + +// Array of endpoints that are supported, the data inside +// the array is the endpoint number. +#define FIXED_ENDPOINT_ARRAY \ + { \ + 0x0000, 0x0001, 0x0002 \ + } + +// Array of profile ids +#define FIXED_PROFILE_IDS \ + { \ + 0x0103, 0x0103, 0x0103 \ + } + +// Array of device types +#define FIXED_DEVICE_TYPES \ + { \ + { 0x0016, 1 }, { 0x000E, 1 }, { 0x0101, 1 } \ + } + +// Array of device type offsets +#define FIXED_DEVICE_TYPE_OFFSETS \ + { \ + 0, 1, 2 \ + } + +// Array of device type lengths +#define FIXED_DEVICE_TYPE_LENGTHS \ + { \ + 1, 1, 1 \ + } + +// Array of endpoint types supported on each endpoint +#define FIXED_ENDPOINT_TYPES \ + { \ + 0, 1, 2 \ + } + +// Array of networks supported on each endpoint +#define FIXED_NETWORKS \ + { \ + 0, 0, 0 \ + } diff --git a/zzz_generated/dynamic-bridge-app/zap-generated/gen_config.h b/zzz_generated/dynamic-bridge-app/zap-generated/gen_config.h new file mode 100644 index 00000000000000..f675999cfb095f --- /dev/null +++ b/zzz_generated/dynamic-bridge-app/zap-generated/gen_config.h @@ -0,0 +1,191 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * + * 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. + */ + +// THIS FILE IS GENERATED BY ZAP + +// Prevent multiple inclusion +#pragma once + +// User options for plugin Binding Table Library +#define EMBER_BINDING_TABLE_SIZE 10 + +/**** Network Section ****/ +#define EMBER_SUPPORTED_NETWORKS (1) + +#define EMBER_APS_UNICAST_MESSAGE_COUNT 10 + +/**** Cluster endpoint counts ****/ +#define EMBER_AF_IDENTIFY_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_ON_OFF_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_LEVEL_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_DESCRIPTOR_CLUSTER_SERVER_ENDPOINT_COUNT (3) +#define EMBER_AF_BINDING_CLUSTER_CLIENT_ENDPOINT_COUNT (1) +#define EMBER_AF_ACCESS_CONTROL_CLUSTER_CLIENT_ENDPOINT_COUNT (1) +#define EMBER_AF_ACCESS_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_ACTIONS_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_LOCALIZATION_CONFIGURATION_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_TIME_FORMAT_LOCALIZATION_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_UNIT_LOCALIZATION_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_GENERAL_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_NETWORK_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_DIAGNOSTIC_LOGS_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_GENERAL_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_SOFTWARE_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_THREAD_NETWORK_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_WIFI_NETWORK_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_SWITCH_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_OPERATIONAL_CREDENTIALS_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_GROUP_KEY_MANAGEMENT_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_USER_LABEL_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_TEMP_MEASUREMENT_CLUSTER_SERVER_ENDPOINT_COUNT (1) + +/**** Cluster Plugins ****/ + +// Use this macro to check if the server side of the Identify cluster is included +#define ZCL_USING_IDENTIFY_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_IDENTIFY_SERVER +#define EMBER_AF_PLUGIN_IDENTIFY + +// Use this macro to check if the server side of the On/Off cluster is included +#define ZCL_USING_ON_OFF_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_ON_OFF_SERVER +#define EMBER_AF_PLUGIN_ON_OFF + +// Use this macro to check if the server side of the Level Control cluster is included +#define ZCL_USING_LEVEL_CONTROL_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_LEVEL_CONTROL_SERVER +#define EMBER_AF_PLUGIN_LEVEL_CONTROL +// User options for server plugin Level Control +#define EMBER_AF_PLUGIN_LEVEL_CONTROL_MAXIMUM_LEVEL 254 +#define EMBER_AF_PLUGIN_LEVEL_CONTROL_MINIMUM_LEVEL 0 +#define EMBER_AF_PLUGIN_LEVEL_CONTROL_RATE 0 + +// Use this macro to check if the server side of the Descriptor cluster is included +#define ZCL_USING_DESCRIPTOR_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_DESCRIPTOR_SERVER +#define EMBER_AF_PLUGIN_DESCRIPTOR + +// Use this macro to check if the client side of the Binding cluster is included +#define ZCL_USING_BINDING_CLUSTER_CLIENT +#define EMBER_AF_PLUGIN_BINDING_CLIENT + +// Use this macro to check if the client side of the Access Control cluster is included +#define ZCL_USING_ACCESS_CONTROL_CLUSTER_CLIENT +#define EMBER_AF_PLUGIN_ACCESS_CONTROL_CLIENT + +// Use this macro to check if the server side of the Access Control cluster is included +#define ZCL_USING_ACCESS_CONTROL_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_ACCESS_CONTROL_SERVER +#define EMBER_AF_PLUGIN_ACCESS_CONTROL + +// Use this macro to check if the server side of the Actions cluster is included +#define ZCL_USING_ACTIONS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_ACTIONS_SERVER +#define EMBER_AF_PLUGIN_ACTIONS + +// Use this macro to check if the server side of the Basic cluster is included +#define ZCL_USING_BASIC_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_BASIC_SERVER +#define EMBER_AF_PLUGIN_BASIC + +// Use this macro to check if the server side of the Localization Configuration cluster is included +#define ZCL_USING_LOCALIZATION_CONFIGURATION_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_LOCALIZATION_CONFIGURATION_SERVER +#define EMBER_AF_PLUGIN_LOCALIZATION_CONFIGURATION + +// Use this macro to check if the server side of the Time Format Localization cluster is included +#define ZCL_USING_TIME_FORMAT_LOCALIZATION_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_TIME_FORMAT_LOCALIZATION_SERVER +#define EMBER_AF_PLUGIN_TIME_FORMAT_LOCALIZATION + +// Use this macro to check if the server side of the Unit Localization cluster is included +#define ZCL_USING_UNIT_LOCALIZATION_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_UNIT_LOCALIZATION_SERVER +#define EMBER_AF_PLUGIN_UNIT_LOCALIZATION + +// Use this macro to check if the server side of the General Commissioning cluster is included +#define ZCL_USING_GENERAL_COMMISSIONING_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_GENERAL_COMMISSIONING_SERVER +#define EMBER_AF_PLUGIN_GENERAL_COMMISSIONING + +// Use this macro to check if the server side of the Network Commissioning cluster is included +#define ZCL_USING_NETWORK_COMMISSIONING_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_NETWORK_COMMISSIONING_SERVER +#define EMBER_AF_PLUGIN_NETWORK_COMMISSIONING + +// Use this macro to check if the server side of the Diagnostic Logs cluster is included +#define ZCL_USING_DIAGNOSTIC_LOGS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS + +// Use this macro to check if the server side of the General Diagnostics cluster is included +#define ZCL_USING_GENERAL_DIAGNOSTICS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_GENERAL_DIAGNOSTICS_SERVER +#define EMBER_AF_PLUGIN_GENERAL_DIAGNOSTICS + +// Use this macro to check if the server side of the Software Diagnostics cluster is included +#define ZCL_USING_SOFTWARE_DIAGNOSTICS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_SOFTWARE_DIAGNOSTICS_SERVER +#define EMBER_AF_PLUGIN_SOFTWARE_DIAGNOSTICS + +// Use this macro to check if the server side of the Thread Network Diagnostics cluster is included +#define ZCL_USING_THREAD_NETWORK_DIAGNOSTICS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_THREAD_NETWORK_DIAGNOSTICS_SERVER +#define EMBER_AF_PLUGIN_THREAD_NETWORK_DIAGNOSTICS + +// Use this macro to check if the server side of the WiFi Network Diagnostics cluster is included +#define ZCL_USING_WIFI_NETWORK_DIAGNOSTICS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_WI_FI_NETWORK_DIAGNOSTICS_SERVER +#define EMBER_AF_PLUGIN_WI_FI_NETWORK_DIAGNOSTICS + +// Use this macro to check if the server side of the Ethernet Network Diagnostics cluster is included +#define ZCL_USING_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_ETHERNET_NETWORK_DIAGNOSTICS_SERVER +#define EMBER_AF_PLUGIN_ETHERNET_NETWORK_DIAGNOSTICS + +// Use this macro to check if the server side of the Switch cluster is included +#define ZCL_USING_SWITCH_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_SWITCH_SERVER +#define EMBER_AF_PLUGIN_SWITCH + +// Use this macro to check if the server side of the AdministratorCommissioning cluster is included +#define ZCL_USING_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING + +// Use this macro to check if the server side of the Operational Credentials cluster is included +#define ZCL_USING_OPERATIONAL_CREDENTIALS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_OPERATIONAL_CREDENTIALS_SERVER +#define EMBER_AF_PLUGIN_OPERATIONAL_CREDENTIALS + +// Use this macro to check if the server side of the Group Key Management cluster is included +#define ZCL_USING_GROUP_KEY_MANAGEMENT_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_GROUP_KEY_MANAGEMENT_SERVER +#define EMBER_AF_PLUGIN_GROUP_KEY_MANAGEMENT + +// Use this macro to check if the server side of the User Label cluster is included +#define ZCL_USING_USER_LABEL_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_USER_LABEL_SERVER +#define EMBER_AF_PLUGIN_USER_LABEL + +// Use this macro to check if the server side of the Temperature Measurement cluster is included +#define ZCL_USING_TEMP_MEASUREMENT_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_TEMPERATURE_MEASUREMENT_SERVER +#define EMBER_AF_PLUGIN_TEMPERATURE_MEASUREMENT diff --git a/zzz_generated/dynamic-bridge-app/zap-generated/gen_tokens.h b/zzz_generated/dynamic-bridge-app/zap-generated/gen_tokens.h new file mode 100644 index 00000000000000..dcc229f5b2c306 --- /dev/null +++ b/zzz_generated/dynamic-bridge-app/zap-generated/gen_tokens.h @@ -0,0 +1,45 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * + * 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. + */ + +// THIS FILE IS GENERATED BY ZAP + +// Prevent multiple inclusion +#pragma once + +// This file contains the tokens for attributes stored in flash + +// Identifier tags for tokens + +// Types for the tokens +#ifdef DEFINETYPES +#endif // DEFINETYPES + +// Actual token definitions +#ifdef DEFINETOKENS +#endif // DEFINETOKENS + +// Macro snippet that loads all the attributes from tokens +#define GENERATED_TOKEN_LOADER(endpoint) \ + do \ + { \ + } while (false) + +// Macro snippet that saves the attribute to token +#define GENERATED_TOKEN_SAVER \ + do \ + { \ + } while (false) From b9352073410d7244a55a4e45588ea28a93025e22 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Fri, 30 Sep 2022 18:56:14 +0000 Subject: [PATCH 13/14] Restyled by gn & fix codegen test --- examples/dynamic-bridge-app/bridge-common/BUILD.gn | 3 ++- scripts/idl/test_generators.py | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/dynamic-bridge-app/bridge-common/BUILD.gn b/examples/dynamic-bridge-app/bridge-common/BUILD.gn index 2f91f4fccd5156..22fc176dcd69d6 100644 --- a/examples/dynamic-bridge-app/bridge-common/BUILD.gn +++ b/examples/dynamic-bridge-app/bridge-common/BUILD.gn @@ -20,7 +20,8 @@ import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("dynamic-bridge-common") { zap_file = "bridge-app.zap" - zap_pregenerated_dir = "${chip_root}/zzz_generated/dynamic-bridge-app/zap-generated" + zap_pregenerated_dir = + "${chip_root}/zzz_generated/dynamic-bridge-app/zap-generated" is_server = true # TODO: the definition of DYNAMIC_ENDPOINT_COUNT needs find a common home! diff --git a/scripts/idl/test_generators.py b/scripts/idl/test_generators.py index bdb2655a2faa7a..0282dd8e9c3afe 100755 --- a/scripts/idl/test_generators.py +++ b/scripts/idl/test_generators.py @@ -32,7 +32,7 @@ from idl.matter_idl_types import Idl from idl.generators.java import JavaGenerator -from idl.generators.cpp import CppGenerator +from idl.generators.bridge import BridgeGenerator from idl.generators import GeneratorStorage @@ -101,8 +101,8 @@ def add_test_cases(self, yaml_test_case_dict): def _create_generator(self, storage: GeneratorStorage, idl: Idl): if self.generator_name.lower() == 'java': return JavaGenerator(storage, idl) - if self.generator_name.lower() == 'cpp': - return CppGenerator(storage, idl) + if self.generator_name.lower() == 'bridge': + return BridgeGenerator(storage, idl) else: raise Exception("Unknown generator for testing: %s", self.generator_name.lower()) From c98d9d462aa0f0de851eca4dd799c74f4bb74154 Mon Sep 17 00:00:00 2001 From: Albert Chaulk Date: Fri, 30 Sep 2022 18:08:01 -0400 Subject: [PATCH 14/14] fix idl tests --- scripts/idl/tests/available_tests.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scripts/idl/tests/available_tests.yaml b/scripts/idl/tests/available_tests.yaml index 719f861db14fd9..3fb20e2a482b87 100644 --- a/scripts/idl/tests/available_tests.yaml +++ b/scripts/idl/tests/available_tests.yaml @@ -38,12 +38,22 @@ java: bridge: inputs/simple_attribute.matter: bridge/BridgeClustersImpl.h: outputs/simple_attribute/bridge/BridgeClustersImpl.h + bridge/BridgeGlobalStructs.h: outputs/simple_attribute/bridge/BridgeGlobalStructs.h + bridge/MyCluster.h: outputs/simple_attribute/bridge/MyCluster.h inputs/global_struct_attribute.matter: bridge/BridgeClustersImpl.h: outputs/global_struct_attribute/bridge/BridgeClustersImpl.h + bridge/BridgeGlobalStructs.h: outputs/global_struct_attribute/bridge/BridgeGlobalStructs.h + bridge/DemoCluster.h: outputs/global_struct_attribute/bridge/DemoCluster.h inputs/cluster_struct_attribute.matter: bridge/BridgeClustersImpl.h: outputs/cluster_struct_attribute/bridge/BridgeClustersImpl.h + bridge/BridgeGlobalStructs.h: outputs/cluster_struct_attribute/bridge/BridgeGlobalStructs.h + bridge/DemoCluster.h: outputs/cluster_struct_attribute/bridge/DemoCluster.h inputs/several_clusters.matter: bridge/BridgeClustersImpl.h: outputs/several_clusters/bridge/BridgeClustersImpl.h + bridge/BridgeGlobalStructs.h: outputs/several_clusters/bridge/BridgeGlobalStructs.h + bridge/First.h: outputs/several_clusters/bridge/First.h + bridge/Second.h: outputs/several_clusters/bridge/Second.h + bridge/Third.h: outputs/several_clusters/bridge/Third.h