From 355a2a63c260991156327f80d44a284b48530679 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Thu, 14 Nov 2024 09:44:34 -0800 Subject: [PATCH 01/27] Add timeout to excute a command (#36492) --- examples/fabric-sync/shell/BUILD.gn | 1 + .../fabric-sync/shell/CommandRegistry.cpp | 48 +++++++++++++++++++ examples/fabric-sync/shell/CommandRegistry.h | 11 ++++- 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 examples/fabric-sync/shell/CommandRegistry.cpp diff --git a/examples/fabric-sync/shell/BUILD.gn b/examples/fabric-sync/shell/BUILD.gn index b3726ee178f9e0..436f8b5160e66c 100644 --- a/examples/fabric-sync/shell/BUILD.gn +++ b/examples/fabric-sync/shell/BUILD.gn @@ -31,6 +31,7 @@ source_set("shell") { "AddBridgeCommand.h", "AddDeviceCommand.cpp", "AddDeviceCommand.h", + "CommandRegistry.cpp", "CommandRegistry.h", "RemoveBridgeCommand.cpp", "RemoveBridgeCommand.h", diff --git a/examples/fabric-sync/shell/CommandRegistry.cpp b/examples/fabric-sync/shell/CommandRegistry.cpp new file mode 100644 index 00000000000000..34c01357eafd57 --- /dev/null +++ b/examples/fabric-sync/shell/CommandRegistry.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 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 "CommandRegistry.h" + +#include + +using namespace ::chip; + +namespace commands { + +void CommandRegistry::SetActiveCommand(std::unique_ptr command, uint32_t timeoutSeconds) +{ + mActiveCommand = std::move(command); + + // Cancel any previous timer to avoid multiple timers running simultaneously + DeviceLayer::SystemLayer().CancelTimer(OnTimeout, this); + + // Start a new timer for the specified timeout + CHIP_ERROR err = DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(timeoutSeconds * 1000), OnTimeout, this); + if (err != CHIP_NO_ERROR) + { + ResetActiveCommand(); + } +} + +void CommandRegistry::ResetActiveCommand() +{ + DeviceLayer::SystemLayer().CancelTimer(OnTimeout, this); + mActiveCommand.reset(); +} + +} // namespace commands diff --git a/examples/fabric-sync/shell/CommandRegistry.h b/examples/fabric-sync/shell/CommandRegistry.h index ec53e17960d98c..0043c267a5104e 100644 --- a/examples/fabric-sync/shell/CommandRegistry.h +++ b/examples/fabric-sync/shell/CommandRegistry.h @@ -38,16 +38,23 @@ class CommandRegistry return instance; } - void SetActiveCommand(std::unique_ptr command) { mActiveCommand = std::move(command); } + void SetActiveCommand(std::unique_ptr command, uint32_t timeoutSeconds = 30); Command * GetActiveCommand() { return mActiveCommand.get(); } - void ResetActiveCommand() { mActiveCommand.reset(); } + void ResetActiveCommand(); bool IsCommandActive() const { return mActiveCommand != nullptr; } private: CommandRegistry() = default; + + static void OnTimeout(chip::System::Layer * layer, void * appState) + { + // Callback function to reset the command when the timer expires + static_cast(appState)->ResetActiveCommand(); + } + std::unique_ptr mActiveCommand; }; From 238493fc20e63edcbfbe2c4f6d8e1f5e004aa831 Mon Sep 17 00:00:00 2001 From: Hasty Granbery Date: Thu, 14 Nov 2024 10:51:06 -0800 Subject: [PATCH 02/27] [HVAC] Thermostat deadband handling (#35673) * [HVAC] Shift heating and cooling setpoints to preserve deadband, when possible * Minor function renames, fix incorrect setters * Populate deadband on setpointLimits when Auto is supported * [Thermostat] Add test for deadband handling * Restyled Python test * Fix int promotion errors on some platforms * Remove unused Python imports * Fix capitalization of structs, methods, fields, etc. * Silly C++ int promotion rules * [HVAC] Fix incorrect naming of TSTAT 2.3 test class * Fix errant quote in TC_TSTAT_2_3.py * Drop deadband fix test in favor of separate PR * Apply suggestions from code review Co-authored-by: Boris Zbarsky * Don't use three-arg setter for attributes * Rename deadband member * Add backwards-compatibility comment for return code substitution * Restyled --------- Co-authored-by: Boris Zbarsky --- .../thermostat-server/thermostat-server.cpp | 348 +++++++++++++++--- 1 file changed, 307 insertions(+), 41 deletions(-) diff --git a/src/app/clusters/thermostat-server/thermostat-server.cpp b/src/app/clusters/thermostat-server/thermostat-server.cpp index bda97c5cb1f22f..a1f0d27779571f 100644 --- a/src/app/clusters/thermostat-server/thermostat-server.cpp +++ b/src/app/clusters/thermostat-server/thermostat-server.cpp @@ -220,6 +220,292 @@ int16_t EnforceCoolingSetpointLimits(int16_t CoolingSetpoint, EndpointId endpoin return CoolingSetpoint; } +struct SetpointLimits +{ + bool autoSupported = false; + bool heatSupported = false; + bool coolSupported = false; + bool occupancySupported = false; + + int16_t absMinHeatSetpointLimit; + int16_t absMaxHeatSetpointLimit; + int16_t minHeatSetpointLimit; + int16_t maxHeatSetpointLimit; + int16_t absMinCoolSetpointLimit; + int16_t absMaxCoolSetpointLimit; + int16_t minCoolSetpointLimit; + int16_t maxCoolSetpointLimit; + int16_t deadBand = 0; + int16_t occupiedCoolingSetpoint; + int16_t occupiedHeatingSetpoint; + int16_t unoccupiedCoolingSetpoint; + int16_t unoccupiedHeatingSetpoint; +}; + +/** + * @brief Reads all the attributes for enforcing setpoint limits + * + * @param endpoint The endpoint for the server whose limits are being enforced + * @param setpointLimits The SetpointLimits to populate + * @return Success if the limits were read completely, otherwise an error code + */ +Status GetSetpointLimits(EndpointId endpoint, SetpointLimits & setpointLimits) +{ + uint32_t flags; + if (FeatureMap::Get(endpoint, &flags) != Status::Success) + { + ChipLogError(Zcl, "GetSetpointLimits: could not get feature flags"); + flags = FEATURE_MAP_DEFAULT; + } + + auto featureMap = BitMask(flags); + setpointLimits.autoSupported = featureMap.Has(Feature::kAutoMode); + setpointLimits.heatSupported = featureMap.Has(Feature::kHeating); + setpointLimits.coolSupported = featureMap.Has(Feature::kCooling); + setpointLimits.occupancySupported = featureMap.Has(Feature::kOccupancy); + + if (setpointLimits.autoSupported) + { + int8_t deadBand; + if (MinSetpointDeadBand::Get(endpoint, &deadBand) != Status::Success) + { + deadBand = kDefaultDeadBand; + } + setpointLimits.deadBand = static_cast(deadBand * 10); + } + + if (AbsMinCoolSetpointLimit::Get(endpoint, &setpointLimits.absMinCoolSetpointLimit) != Status::Success) + setpointLimits.absMinCoolSetpointLimit = kDefaultAbsMinCoolSetpointLimit; + + if (AbsMaxCoolSetpointLimit::Get(endpoint, &setpointLimits.absMaxCoolSetpointLimit) != Status::Success) + setpointLimits.absMaxCoolSetpointLimit = kDefaultAbsMaxCoolSetpointLimit; + + if (MinCoolSetpointLimit::Get(endpoint, &setpointLimits.minCoolSetpointLimit) != Status::Success) + setpointLimits.minCoolSetpointLimit = setpointLimits.absMinCoolSetpointLimit; + + if (MaxCoolSetpointLimit::Get(endpoint, &setpointLimits.maxCoolSetpointLimit) != Status::Success) + setpointLimits.maxCoolSetpointLimit = setpointLimits.absMaxCoolSetpointLimit; + + if (AbsMinHeatSetpointLimit::Get(endpoint, &setpointLimits.absMinHeatSetpointLimit) != Status::Success) + setpointLimits.absMinHeatSetpointLimit = kDefaultAbsMinHeatSetpointLimit; + + if (AbsMaxHeatSetpointLimit::Get(endpoint, &setpointLimits.absMaxHeatSetpointLimit) != Status::Success) + setpointLimits.absMaxHeatSetpointLimit = kDefaultAbsMaxHeatSetpointLimit; + + if (MinHeatSetpointLimit::Get(endpoint, &setpointLimits.minHeatSetpointLimit) != Status::Success) + setpointLimits.minHeatSetpointLimit = setpointLimits.absMinHeatSetpointLimit; + + if (MaxHeatSetpointLimit::Get(endpoint, &setpointLimits.maxHeatSetpointLimit) != Status::Success) + setpointLimits.maxHeatSetpointLimit = setpointLimits.absMaxHeatSetpointLimit; + + if (setpointLimits.coolSupported) + { + if (OccupiedCoolingSetpoint::Get(endpoint, &setpointLimits.occupiedCoolingSetpoint) != Status::Success) + { + // We're substituting the failure code here for backwards-compatibility reasons + ChipLogError(Zcl, "Error: Can not read Occupied Cooling Setpoint"); + return Status::Failure; + } + } + + if (setpointLimits.heatSupported) + { + if (OccupiedHeatingSetpoint::Get(endpoint, &setpointLimits.occupiedHeatingSetpoint) != Status::Success) + { + // We're substituting the failure code here for backwards-compatibility reasons + ChipLogError(Zcl, "Error: Can not read Occupied Heating Setpoint"); + return Status::Failure; + } + } + + if (setpointLimits.coolSupported && setpointLimits.occupancySupported) + { + if (UnoccupiedCoolingSetpoint::Get(endpoint, &setpointLimits.unoccupiedCoolingSetpoint) != Status::Success) + { + // We're substituting the failure code here for backwards-compatibility reasons + ChipLogError(Zcl, "Error: Can not read Unoccupied Cooling Setpoint"); + return Status::Failure; + } + } + + if (setpointLimits.heatSupported && setpointLimits.occupancySupported) + { + if (UnoccupiedHeatingSetpoint::Get(endpoint, &setpointLimits.unoccupiedHeatingSetpoint) != Status::Success) + { + // We're substituting the failure code here for backwards-compatibility reasons + ChipLogError(Zcl, "Error: Can not read Unoccupied Heating Setpoint"); + return Status::Failure; + } + } + return Status::Success; +} + +/** + * @brief Checks to see if it's possible to adjust the heating setpoint to preserve a given deadband + * if the cooling setpoint is changed + * + * @param autoSupported Whether or not the thermostat supports Auto mode + * @param newCoolingSetpoing The desired cooling setpoint + * @param minHeatingSetpoint The minimum allowed heating setpoint + * @param deadband The deadband to preserve + * @return Success if the deadband can be preserved, InvalidValue if it cannot + */ +Status CheckHeatingSetpointDeadband(bool autoSupported, int16_t newCoolingSetpoint, int16_t minHeatingSetpoint, int16_t deadband) +{ + if (!autoSupported) + { + return Status::Success; + } + int16_t maxValidHeatingSetpoint = static_cast(newCoolingSetpoint - deadband); + if (maxValidHeatingSetpoint < minHeatingSetpoint) + { + // If we need to adjust the heating setpoint to preserve the deadband, it will go below the min heat setpoint + return Status::InvalidValue; + } + // It's possible to adjust the heating setpoint, if needed + return Status::Success; +} + +/** + * @brief Checks to see if it's possible to adjust the cooling setpoint to preserve a given deadband + * if the heating setpoint is changed + * + * @param autoSupported Whether or not the thermostat supports Auto mode + * @param newHeatingSetpoint The desired heating setpoint + * @param maxCoolingSetpoint The maximum allowed cooling setpoint + * @param deadband The deadband to preserve + * @return Success if the deadband can be preserved, InvalidValue if it cannot + */ +Status CheckCoolingSetpointDeadband(bool autoSupported, int16_t newHeatingSetpoint, int16_t maxCoolingSetpoint, int16_t deadband) +{ + if (!autoSupported) + { + return Status::Success; + } + int16_t minValidCoolingSetpoint = static_cast(newHeatingSetpoint + deadband); + if (minValidCoolingSetpoint > maxCoolingSetpoint) + { + // If we need to adjust the cooling setpoint to preserve the deadband, it will go above the max cool setpoint + return Status::InvalidValue; + } + // It's possible to adjust the cooling setpoint, if needed + return Status::Success; +} + +typedef Status (*SetpointSetter)(EndpointId endpoint, int16_t value); + +/** + * @brief Attempts to ensure that a change to the heating setpoint maintains the deadband with the cooling setpoint + * by adjusting the cooling setpoint + * + * @param endpoint The endpoint on which the heating setpoint has been changed + * @param currentCoolingSetpoint The current cooling setpoint + * @param newHeatingSetpoint The newly adjusted heating setpoint + * @param maxCoolingSetpoint The maximum allowed cooling setpoint + * @param deadband The deadband to preserve + * @param setter A function for setting the cooling setpoint + */ +void EnsureCoolingSetpointDeadband(EndpointId endpoint, int16_t currentCoolingSetpoint, int16_t newHeatingSetpoint, + int16_t maxCoolingSetpoint, int16_t deadband, SetpointSetter setter) +{ + int16_t minValidCoolingSetpoint = static_cast(newHeatingSetpoint + deadband); + if (currentCoolingSetpoint >= minValidCoolingSetpoint) + { + // The current cooling setpoint doesn't violate the deadband + return; + } + if (minValidCoolingSetpoint > maxCoolingSetpoint) + { + // Adjusting the cool setpoint to preserve the deadband would violate the max cool setpoint + // This should have been caught in CheckCoolingSetpointDeadband, so log and exit + ChipLogError(Zcl, "Failed ensuring cooling setpoint deadband"); + return; + } + // Adjust the cool setpoint to preserve deadband + auto status = setter(endpoint, minValidCoolingSetpoint); + if (status != Status::Success) + { + ChipLogError(Zcl, "Error: EnsureCoolingSetpointDeadband failed!"); + } +} + +/** + * @brief Attempts to ensure that a change to the cooling setpoint maintains the deadband with the heating setpoint + * by adjusting the heating setpoint + * + * @param endpoint The endpoint on which the cooling setpoint has been changed + * @param currentHeatingSetpointThe current heating setpoint + * @param newCoolingSetpoint The newly adjusted cooling setpoint + * @param minHeatingSetpoint The minimum allowed cooling setpoint + * @param deadband The deadband to preserve + * @param setter A function for setting the heating setpoint + */ +void EnsureHeatingSetpointDeadband(EndpointId endpoint, int16_t currentHeatingSetpoint, int16_t newCoolingSetpoint, + int16_t minHeatingSetpoint, int16_t deadband, SetpointSetter setter) +{ + int16_t maxValidHeatingSetpoint = static_cast(newCoolingSetpoint - deadband); + if (currentHeatingSetpoint <= maxValidHeatingSetpoint) + { + // The current heating setpoint doesn't violate the deadband + return; + } + if (maxValidHeatingSetpoint < minHeatingSetpoint) + { + // Adjusting the heating setpoint to preserve the deadband would violate the min heating setpoint + // This should have been caught in CheckHeatingSetpointDeadband, so log and exit + ChipLogError(Zcl, "Failed ensuring heating setpoint deadband"); + return; + } + // Adjust the heating setpoint to preserve deadband + auto status = setter(endpoint, maxValidHeatingSetpoint); + if (status != Status::Success) + { + ChipLogError(Zcl, "Error: EnsureHeatingSetpointDeadband failed!"); + } +} + +/** + * @brief For thermostats that support auto, shift setpoints to maintain the current deadband + * Note: this assumes that the shift is possible; setpoint changes which prevent the deadband + * from being maintained due to the min/max limits for setpoints should be rejected by + * MatterThermostatClusterServerPreAttributeChangedCallback + * + * @param attributePath + */ +void EnsureDeadband(const ConcreteAttributePath & attributePath) +{ + auto endpoint = attributePath.mEndpointId; + SetpointLimits setpointLimits; + auto status = GetSetpointLimits(endpoint, setpointLimits); + if (status != Status::Success) + { + return; + } + if (!setpointLimits.autoSupported) + { + return; + } + switch (attributePath.mAttributeId) + { + case OccupiedHeatingSetpoint::Id: + EnsureCoolingSetpointDeadband(endpoint, setpointLimits.occupiedCoolingSetpoint, setpointLimits.occupiedHeatingSetpoint, + setpointLimits.maxCoolSetpointLimit, setpointLimits.deadBand, OccupiedCoolingSetpoint::Set); + break; + case OccupiedCoolingSetpoint::Id: + EnsureHeatingSetpointDeadband(endpoint, setpointLimits.occupiedHeatingSetpoint, setpointLimits.occupiedCoolingSetpoint, + setpointLimits.minHeatSetpointLimit, setpointLimits.deadBand, OccupiedHeatingSetpoint::Set); + break; + case UnoccupiedHeatingSetpoint::Id: + EnsureCoolingSetpointDeadband(endpoint, setpointLimits.unoccupiedCoolingSetpoint, setpointLimits.unoccupiedHeatingSetpoint, + setpointLimits.maxCoolSetpointLimit, setpointLimits.deadBand, UnoccupiedCoolingSetpoint::Set); + break; + case UnoccupiedCoolingSetpoint::Id: + EnsureHeatingSetpointDeadband(endpoint, setpointLimits.unoccupiedHeatingSetpoint, setpointLimits.unoccupiedCoolingSetpoint, + setpointLimits.minHeatSetpointLimit, setpointLimits.deadBand, UnoccupiedHeatingSetpoint::Set); + break; + } +} + Delegate * GetDelegate(EndpointId endpoint) { uint16_t ep = @@ -477,14 +763,9 @@ void MatterThermostatClusterServerAttributeChangedCallback(const ConcreteAttribu return; } - auto featureMap = BitMask(flags); - if (!featureMap.Has(Feature::kPresets)) - { - // This server does not support presets, so nothing to do - return; - } - - bool occupied = true; + auto featureMap = BitMask(flags); + bool supportsPresets = featureMap.Has(Feature::kPresets); + bool occupied = true; if (featureMap.Has(Feature::kOccupancy)) { BitMask occupancy; @@ -499,19 +780,20 @@ void MatterThermostatClusterServerAttributeChangedCallback(const ConcreteAttribu { case OccupiedHeatingSetpoint::Id: case OccupiedCoolingSetpoint::Id: - clearActivePreset = occupied; + clearActivePreset = supportsPresets && occupied; + EnsureDeadband(attributePath); break; case UnoccupiedHeatingSetpoint::Id: case UnoccupiedCoolingSetpoint::Id: - clearActivePreset = !occupied; + clearActivePreset = supportsPresets && !occupied; + EnsureDeadband(attributePath); break; } - if (!clearActivePreset) + if (clearActivePreset) { - return; + ChipLogProgress(Zcl, "Setting active preset to null"); + gThermostatAttrAccess.SetActivePreset(attributePath.mEndpointId, std::nullopt); } - ChipLogProgress(Zcl, "Setting active preset to null"); - gThermostatAttrAccess.SetActivePreset(attributePath.mEndpointId, std::nullopt); } } // namespace Thermostat @@ -535,15 +817,15 @@ void emberAfThermostatClusterServerInitCallback(chip::EndpointId endpoint) // or should this just be the responsibility of the thermostat application? } -Protocols::InteractionModel::Status -MatterThermostatClusterServerPreAttributeChangedCallback(const app::ConcreteAttributePath & attributePath, - EmberAfAttributeType attributeType, uint16_t size, uint8_t * value) +Status MatterThermostatClusterServerPreAttributeChangedCallback(const app::ConcreteAttributePath & attributePath, + EmberAfAttributeType attributeType, uint16_t size, uint8_t * value) { EndpointId endpoint = attributePath.mEndpointId; int16_t requested; // Limits will be needed for all checks // so we just get them all now + // TODO: use GetSetpointLimits to fetch this information int16_t AbsMinHeatSetpointLimit; int16_t AbsMaxHeatSetpointLimit; int16_t MinHeatSetpointLimit; @@ -649,12 +931,8 @@ MatterThermostatClusterServerPreAttributeChangedCallback(const app::ConcreteAttr if (requested < AbsMinHeatSetpointLimit || requested < MinHeatSetpointLimit || requested > AbsMaxHeatSetpointLimit || requested > MaxHeatSetpointLimit) return Status::InvalidValue; - if (AutoSupported) - { - if (requested > OccupiedCoolingSetpoint - DeadBandTemp) - return Status::InvalidValue; - } - return Status::Success; + return CheckCoolingSetpointDeadband(AutoSupported, requested, std::min(MaxCoolSetpointLimit, AbsMaxCoolSetpointLimit), + DeadBandTemp); } case OccupiedCoolingSetpoint::Id: { @@ -664,12 +942,8 @@ MatterThermostatClusterServerPreAttributeChangedCallback(const app::ConcreteAttr if (requested < AbsMinCoolSetpointLimit || requested < MinCoolSetpointLimit || requested > AbsMaxCoolSetpointLimit || requested > MaxCoolSetpointLimit) return Status::InvalidValue; - if (AutoSupported) - { - if (requested < OccupiedHeatingSetpoint + DeadBandTemp) - return Status::InvalidValue; - } - return Status::Success; + return CheckHeatingSetpointDeadband(AutoSupported, requested, std::max(MinHeatSetpointLimit, AbsMinHeatSetpointLimit), + DeadBandTemp); } case UnoccupiedHeatingSetpoint::Id: { @@ -679,12 +953,8 @@ MatterThermostatClusterServerPreAttributeChangedCallback(const app::ConcreteAttr if (requested < AbsMinHeatSetpointLimit || requested < MinHeatSetpointLimit || requested > AbsMaxHeatSetpointLimit || requested > MaxHeatSetpointLimit) return Status::InvalidValue; - if (AutoSupported) - { - if (requested > UnoccupiedCoolingSetpoint - DeadBandTemp) - return Status::InvalidValue; - } - return Status::Success; + return CheckCoolingSetpointDeadband(AutoSupported, requested, std::min(MaxCoolSetpointLimit, AbsMaxCoolSetpointLimit), + DeadBandTemp); } case UnoccupiedCoolingSetpoint::Id: { requested = static_cast(chip::Encoding::LittleEndian::Get16(value)); @@ -693,12 +963,8 @@ MatterThermostatClusterServerPreAttributeChangedCallback(const app::ConcreteAttr if (requested < AbsMinCoolSetpointLimit || requested < MinCoolSetpointLimit || requested > AbsMaxCoolSetpointLimit || requested > MaxCoolSetpointLimit) return Status::InvalidValue; - if (AutoSupported) - { - if (requested < UnoccupiedHeatingSetpoint + DeadBandTemp) - return Status::InvalidValue; - } - return Status::Success; + return CheckHeatingSetpointDeadband(AutoSupported, requested, std::max(MinHeatSetpointLimit, AbsMinHeatSetpointLimit), + DeadBandTemp); } case MinHeatSetpointLimit::Id: { From 73ff58ff14c91c590c679a40c9570e434dbdd88f Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Thu, 14 Nov 2024 11:19:38 -0800 Subject: [PATCH 03/27] [Fabric-Sync] Use Meyers' Singleton pattern for BridgedDeviceManager and DeviceManager (#36491) --- .../fabric-sync/admin/BridgeSubscription.cpp | 4 +-- .../fabric-sync/admin/CommissionerControl.cpp | 2 +- examples/fabric-sync/admin/DeviceManager.cpp | 3 --- examples/fabric-sync/admin/DeviceManager.h | 25 +++++-------------- .../admin/DeviceSynchronization.cpp | 8 +++--- examples/fabric-sync/admin/FabricAdmin.cpp | 4 +-- .../bridge/include/BridgedDeviceManager.h | 21 +++++----------- examples/fabric-sync/bridge/src/Bridge.cpp | 4 +-- .../src/BridgedAdministratorCommissioning.cpp | 2 +- .../src/BridgedDeviceBasicInformationImpl.cpp | 4 +-- .../bridge/src/BridgedDeviceManager.cpp | 3 --- .../fabric-sync/bridge/src/FabricBridge.cpp | 12 ++++----- .../fabric-sync/shell/AddBridgeCommand.cpp | 12 ++++----- .../fabric-sync/shell/AddDeviceCommand.cpp | 6 ++--- .../fabric-sync/shell/RemoveBridgeCommand.cpp | 6 ++--- .../fabric-sync/shell/RemoveDeviceCommand.cpp | 4 +-- 16 files changed, 46 insertions(+), 74 deletions(-) diff --git a/examples/fabric-sync/admin/BridgeSubscription.cpp b/examples/fabric-sync/admin/BridgeSubscription.cpp index e7052d7df08a96..1df9371ff74dff 100644 --- a/examples/fabric-sync/admin/BridgeSubscription.cpp +++ b/examples/fabric-sync/admin/BridgeSubscription.cpp @@ -80,7 +80,7 @@ void BridgeSubscription::OnAttributeData(const ConcreteDataAttributePath & path, return; } - DeviceMgr().HandleAttributeData(path, *data); + DeviceManager::Instance().HandleAttributeData(path, *data); } void BridgeSubscription::OnEventData(const app::EventHeader & eventHeader, TLV::TLVReader * data, const app::StatusIB * status) @@ -101,7 +101,7 @@ void BridgeSubscription::OnEventData(const app::EventHeader & eventHeader, TLV:: return; } - DeviceMgr().HandleEventData(eventHeader, *data); + DeviceManager::Instance().HandleEventData(eventHeader, *data); } void BridgeSubscription::OnError(CHIP_ERROR error) diff --git a/examples/fabric-sync/admin/CommissionerControl.cpp b/examples/fabric-sync/admin/CommissionerControl.cpp index 45c7bc02da69a5..a0c24eb956d5bb 100644 --- a/examples/fabric-sync/admin/CommissionerControl.cpp +++ b/examples/fabric-sync/admin/CommissionerControl.cpp @@ -84,7 +84,7 @@ void CommissionerControl::OnResponse(app::CommandSender * client, const app::Con if (data != nullptr) { - DeviceMgr().HandleCommandResponse(path, *data); + DeviceManager::Instance().HandleCommandResponse(path, *data); } } diff --git a/examples/fabric-sync/admin/DeviceManager.cpp b/examples/fabric-sync/admin/DeviceManager.cpp index 9848d2f68d2550..6dfdad1213bc68 100644 --- a/examples/fabric-sync/admin/DeviceManager.cpp +++ b/examples/fabric-sync/admin/DeviceManager.cpp @@ -36,9 +36,6 @@ constexpr EndpointId kAggregatorEndpointId = 1; } // namespace -// Define the static member -DeviceManager DeviceManager::sInstance; - LinuxCommissionableDataProvider sCommissionableDataProvider; void DeviceManager::Init() diff --git a/examples/fabric-sync/admin/DeviceManager.h b/examples/fabric-sync/admin/DeviceManager.h index b92154c1e6e008..e114a62748549a 100644 --- a/examples/fabric-sync/admin/DeviceManager.h +++ b/examples/fabric-sync/admin/DeviceManager.h @@ -54,6 +54,12 @@ class DeviceManager public: DeviceManager() = default; + static DeviceManager & Instance() + { + static DeviceManager instance; + return instance; + } + void Init(); chip::NodeId GetNextAvailableNodeId(); @@ -170,8 +176,6 @@ class DeviceManager SyncedDevice * FindDeviceByNode(chip::NodeId nodeId); private: - friend DeviceManager & DeviceMgr(); - void RequestCommissioningApproval(); void HandleReadSupportedDeviceCategories(chip::TLV::TLVReader & data); @@ -184,8 +188,6 @@ class DeviceManager void HandleReverseOpenCommissioningWindow(chip::TLV::TLVReader & data); - static DeviceManager sInstance; - chip::NodeId mLastUsedNodeId = 0; // The Node ID of the remote bridge used for Fabric-Sync @@ -201,19 +203,4 @@ class DeviceManager FabricSyncGetter mFabricSyncGetter; }; -/** - * Returns the public interface of the DeviceManager singleton object. - * - * Applications should use this to access features of the DeviceManager - * object. - */ -inline DeviceManager & DeviceMgr() -{ - if (!DeviceManager::sInstance.mInitialized) - { - DeviceManager::sInstance.Init(); - } - return DeviceManager::sInstance; -} - } // namespace admin diff --git a/examples/fabric-sync/admin/DeviceSynchronization.cpp b/examples/fabric-sync/admin/DeviceSynchronization.cpp index 2f36eb9cb03f69..05a4fa9db8f398 100644 --- a/examples/fabric-sync/admin/DeviceSynchronization.cpp +++ b/examples/fabric-sync/admin/DeviceSynchronization.cpp @@ -148,7 +148,7 @@ void DeviceSynchronizer::OnDone(app::ReadClient * apReadClient) { ChipLogProgress(NotSpecified, "Synchronization complete for NodeId:" ChipLogFormatX64, ChipLogValueX64(mNodeId)); - if (mState == State::ReceivedResponse && !DeviceMgr().IsCurrentBridgeDevice(mNodeId)) + if (mState == State::ReceivedResponse && !DeviceManager::Instance().IsCurrentBridgeDevice(mNodeId)) { GetUniqueId(); if (mState == State::GettingUid) @@ -229,15 +229,15 @@ void DeviceSynchronizer::GetUniqueId() // If we have a UniqueId we can return leaving state in ReceivedResponse. VerifyOrReturn(!mCurrentDeviceData.uniqueId.has_value(), ChipLogDetail(NotSpecified, "We already have UniqueId")); - auto * device = DeviceMgr().FindDeviceByNode(mNodeId); + auto * device = DeviceManager::Instance().FindDeviceByNode(mNodeId); // If there is no associated remote Fabric Sync Aggregator there is no other place for us to try // getting the UniqueId from and can return leaving the state in ReceivedResponse. VerifyOrReturn(device, ChipLogDetail(NotSpecified, "No remote Fabric Sync Aggregator to get UniqueId from")); // Because device is not-null we expect IsFabricSyncReady to be true. IsFabricSyncReady indicates we have a // connection to the remote Fabric Sync Aggregator. - VerifyOrDie(DeviceMgr().IsFabricSyncReady()); - auto remoteBridgeNodeId = DeviceMgr().GetRemoteBridgeNodeId(); + VerifyOrDie(DeviceManager::Instance().IsFabricSyncReady()); + auto remoteBridgeNodeId = DeviceManager::Instance().GetRemoteBridgeNodeId(); EndpointId remoteEndpointIdOfInterest = device->GetEndpointId(); ChipLogDetail(NotSpecified, "Attempting to get UniqueId from remote Fabric Sync Aggregator"); diff --git a/examples/fabric-sync/admin/FabricAdmin.cpp b/examples/fabric-sync/admin/FabricAdmin.cpp index a012ac9d8c9a95..65b5a5a8e8fc30 100644 --- a/examples/fabric-sync/admin/FabricAdmin.cpp +++ b/examples/fabric-sync/admin/FabricAdmin.cpp @@ -65,13 +65,13 @@ FabricAdmin::CommissionRemoteBridge(Controller::CommissioningWindowPasscodeParam if (err == CHIP_NO_ERROR) { - NodeId nodeId = DeviceMgr().GetNextAvailableNodeId(); + NodeId nodeId = DeviceManager::Instance().GetNextAvailableNodeId(); // After responding with RequestCommissioningApproval to the node where the client initiated the // RequestCommissioningApproval, you need to wait for it to open a commissioning window on its bridge. usleep(kCommissionPrepareTimeMs * 1000); - DeviceMgr().PairRemoteDevice(nodeId, code.c_str()); + DeviceManager::Instance().PairRemoteDevice(nodeId, code.c_str()); } else { diff --git a/examples/fabric-sync/bridge/include/BridgedDeviceManager.h b/examples/fabric-sync/bridge/include/BridgedDeviceManager.h index be6c6a41db262d..67efe74addb038 100644 --- a/examples/fabric-sync/bridge/include/BridgedDeviceManager.h +++ b/examples/fabric-sync/bridge/include/BridgedDeviceManager.h @@ -30,6 +30,12 @@ class BridgedDeviceManager public: BridgedDeviceManager() = default; + static BridgedDeviceManager & Instance() + { + static BridgedDeviceManager instance; + return instance; + } + /** * @brief Initializes the BridgedDeviceManager. * @@ -111,29 +117,14 @@ class BridgedDeviceManager BridgedDevice * GetDeviceByUniqueId(const std::string & id); private: - friend BridgedDeviceManager & BridgeDeviceMgr(); - /** * Creates a new unique ID that is not used by any other mDevice */ std::string GenerateUniqueId(); - static BridgedDeviceManager sInstance; - chip::EndpointId mCurrentEndpointId; chip::EndpointId mFirstDynamicEndpointId; std::unique_ptr mDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT + 1]; }; -/** - * Returns the public interface of the BridgedDeviceManager singleton object. - * - * Applications should use this to access features of the BridgedDeviceManager - * object. - */ -inline BridgedDeviceManager & BridgeDeviceMgr() -{ - return BridgedDeviceManager::sInstance; -} - } // namespace bridge diff --git a/examples/fabric-sync/bridge/src/Bridge.cpp b/examples/fabric-sync/bridge/src/Bridge.cpp index 02bda529caec01..3d0a4af56ff064 100644 --- a/examples/fabric-sync/bridge/src/Bridge.cpp +++ b/examples/fabric-sync/bridge/src/Bridge.cpp @@ -81,7 +81,7 @@ void BridgedDeviceInformationCommandHandler::InvokeCommand(HandlerContext & hand return; } - BridgedDevice * device = BridgeDeviceMgr().GetDevice(endpointId); + BridgedDevice * device = BridgedDeviceManager::Instance().GetDevice(endpointId); if (device == nullptr || !device->IsIcd()) { handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::Failure); @@ -125,7 +125,7 @@ CHIP_ERROR BridgeInit(FabricAdminDelegate * delegate) CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(&gBridgedDeviceInformationCommandHandler); AttributeAccessInterfaceRegistry::Instance().Register(&gBridgedDeviceBasicInformationAttributes); - BridgeDeviceMgr().Init(); + BridgedDeviceManager::Instance().Init(); FabricBridge::Instance().SetDelegate(delegate); ReturnErrorOnFailure(gBridgedAdministratorCommissioning.Init()); ReturnErrorOnFailure(CommissionerControlInit(delegate)); diff --git a/examples/fabric-sync/bridge/src/BridgedAdministratorCommissioning.cpp b/examples/fabric-sync/bridge/src/BridgedAdministratorCommissioning.cpp index 3299df75a9039e..6cfb5a5caaedd7 100644 --- a/examples/fabric-sync/bridge/src/BridgedAdministratorCommissioning.cpp +++ b/examples/fabric-sync/bridge/src/BridgedAdministratorCommissioning.cpp @@ -45,7 +45,7 @@ CHIP_ERROR BridgedAdministratorCommissioning::Read(const ConcreteReadAttributePa { VerifyOrDie(aPath.mClusterId == Clusters::AdministratorCommissioning::Id); EndpointId endpointId = aPath.mEndpointId; - BridgedDevice * device = BridgeDeviceMgr().GetDevice(endpointId); + BridgedDevice * device = BridgedDeviceManager::Instance().GetDevice(endpointId); if (!device) { diff --git a/examples/fabric-sync/bridge/src/BridgedDeviceBasicInformationImpl.cpp b/examples/fabric-sync/bridge/src/BridgedDeviceBasicInformationImpl.cpp index d021671c8bf1bd..3a03d8f84a81a0 100644 --- a/examples/fabric-sync/bridge/src/BridgedDeviceBasicInformationImpl.cpp +++ b/examples/fabric-sync/bridge/src/BridgedDeviceBasicInformationImpl.cpp @@ -36,7 +36,7 @@ CHIP_ERROR BridgedDeviceBasicInformationImpl::Read(const ConcreteReadAttributePa // Registration is done for the bridged device basic information only VerifyOrDie(path.mClusterId == app::Clusters::BridgedDeviceBasicInformation::Id); - BridgedDevice * dev = BridgeDeviceMgr().GetDevice(path.mEndpointId); + BridgedDevice * dev = BridgedDeviceManager::Instance().GetDevice(path.mEndpointId); VerifyOrReturnError(dev != nullptr, CHIP_ERROR_NOT_FOUND); switch (path.mAttributeId) @@ -93,7 +93,7 @@ CHIP_ERROR BridgedDeviceBasicInformationImpl::Write(const ConcreteDataAttributeP { VerifyOrDie(path.mClusterId == app::Clusters::BridgedDeviceBasicInformation::Id); - BridgedDevice * dev = BridgeDeviceMgr().GetDevice(path.mEndpointId); + BridgedDevice * dev = BridgedDeviceManager::Instance().GetDevice(path.mEndpointId); VerifyOrReturnError(dev != nullptr, CHIP_ERROR_NOT_FOUND); if (!dev->IsReachable()) diff --git a/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp b/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp index 62d423dc9a3ec7..0ead453572aa4f 100644 --- a/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp +++ b/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp @@ -175,9 +175,6 @@ const EmberAfDeviceType sBridgedDeviceTypes[] = { { DEVICE_TYPE_BRIDGED_NODE, DE } // namespace -// Define the static member -BridgedDeviceManager BridgedDeviceManager::sInstance; - void BridgedDeviceManager::Init() { mFirstDynamicEndpointId = static_cast( diff --git a/examples/fabric-sync/bridge/src/FabricBridge.cpp b/examples/fabric-sync/bridge/src/FabricBridge.cpp index d1c27d2409262d..aa856ccf129ccc 100644 --- a/examples/fabric-sync/bridge/src/FabricBridge.cpp +++ b/examples/fabric-sync/bridge/src/FabricBridge.cpp @@ -103,7 +103,7 @@ CHIP_ERROR FabricBridge::AddSynchronizedDevice(const SynchronizedDevice & data) device->SetIcd(data.isIcd.value_or(false)); // Add the device to the bridge manager with a parent endpoint - auto result = BridgeDeviceMgr().AddDeviceEndpoint(std::move(device), /* parentEndpointId= */ 1); + auto result = BridgedDeviceManager::Instance().AddDeviceEndpoint(std::move(device), /* parentEndpointId= */ 1); if (!result.has_value()) { ChipLogError(NotSpecified, "Failed to add device with Id=[%d:0x" ChipLogFormatX64 "]", data.id.GetFabricIndex(), @@ -112,7 +112,7 @@ CHIP_ERROR FabricBridge::AddSynchronizedDevice(const SynchronizedDevice & data) } // Retrieve and verify the added device by ScopedNodeId - BridgedDevice * addedDevice = BridgeDeviceMgr().GetDeviceByScopedNodeId(data.id); + BridgedDevice * addedDevice = BridgedDeviceManager::Instance().GetDeviceByScopedNodeId(data.id); VerifyOrDie(addedDevice); ChipLogProgress(NotSpecified, "Added device with Id=[%d:0x" ChipLogFormatX64 "]", data.id.GetFabricIndex(), @@ -137,7 +137,7 @@ CHIP_ERROR FabricBridge::RemoveSynchronizedDevice(ScopedNodeId scopedNodeId) ChipLogProgress(NotSpecified, "Received RemoveSynchronizedDevice: Id=[%d:" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(), ChipLogValueX64(scopedNodeId.GetNodeId())); - auto removedIdx = BridgeDeviceMgr().RemoveDeviceByScopedNodeId(scopedNodeId); + auto removedIdx = BridgedDeviceManager::Instance().RemoveDeviceByScopedNodeId(scopedNodeId); if (!removedIdx.has_value()) { ChipLogError(NotSpecified, "Failed to remove device with Id=[%d:0x" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(), @@ -153,7 +153,7 @@ CHIP_ERROR FabricBridge::ActiveChanged(ScopedNodeId scopedNodeId, uint32_t promi ChipLogProgress(NotSpecified, "Received ActiveChanged: Id=[%d:" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(), ChipLogValueX64(scopedNodeId.GetNodeId())); - auto * device = BridgeDeviceMgr().GetDeviceByScopedNodeId(scopedNodeId); + auto * device = BridgedDeviceManager::Instance().GetDeviceByScopedNodeId(scopedNodeId); if (device == nullptr) { ChipLogError(NotSpecified, "Could not find bridged device associated with Id=[%d:0x" ChipLogFormatX64 "]", @@ -170,7 +170,7 @@ CHIP_ERROR FabricBridge::AdminCommissioningAttributeChanged(const AdministratorC ChipLogProgress(NotSpecified, "Received CADMIN attribute change: Id=[%d:" ChipLogFormatX64 "]", data.id.GetFabricIndex(), ChipLogValueX64(data.id.GetNodeId())); - auto * device = BridgeDeviceMgr().GetDeviceByScopedNodeId(data.id); + auto * device = BridgedDeviceManager::Instance().GetDeviceByScopedNodeId(data.id); if (device == nullptr) { ChipLogError(NotSpecified, "Could not find bridged device associated with Id=[%d:0x" ChipLogFormatX64 "]", @@ -207,7 +207,7 @@ CHIP_ERROR FabricBridge::DeviceReachableChanged(ScopedNodeId scopedNodeId, bool ChipLogProgress(NotSpecified, "Received device reachable changed: Id=[%d:" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(), ChipLogValueX64(scopedNodeId.GetNodeId())); - auto * device = BridgeDeviceMgr().GetDeviceByScopedNodeId(scopedNodeId); + auto * device = BridgedDeviceManager::Instance().GetDeviceByScopedNodeId(scopedNodeId); if (device == nullptr) { ChipLogError(NotSpecified, "Could not find bridged device associated with Id=[%d:0x" ChipLogFormatX64 "]", diff --git a/examples/fabric-sync/shell/AddBridgeCommand.cpp b/examples/fabric-sync/shell/AddBridgeCommand.cpp index 4b70998dccd273..e6b9dd060351e6 100644 --- a/examples/fabric-sync/shell/AddBridgeCommand.cpp +++ b/examples/fabric-sync/shell/AddBridgeCommand.cpp @@ -48,13 +48,13 @@ void AddBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) if (err == CHIP_NO_ERROR) { - admin::DeviceMgr().SetRemoteBridgeNodeId(mBridgeNodeId); + admin::DeviceManager::Instance().SetRemoteBridgeNodeId(mBridgeNodeId); ChipLogProgress(NotSpecified, "Successfully paired bridge device: NodeId: " ChipLogFormatX64, ChipLogValueX64(mBridgeNodeId)); - admin::DeviceMgr().UpdateLastUsedNodeId(mBridgeNodeId); - admin::DeviceMgr().SubscribeRemoteFabricBridge(); + admin::DeviceManager::Instance().UpdateLastUsedNodeId(mBridgeNodeId); + admin::DeviceManager::Instance().SubscribeRemoteFabricBridge(); // After successful commissioning of the Commissionee, initiate Reverse Commissioning // via the Commissioner Control Cluster. However, we must first verify that the @@ -62,7 +62,7 @@ void AddBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) // // Note: The Fabric-Admin MUST NOT send the RequestCommissioningApproval command // if the remote Fabric-Bridge lacks Fabric Synchronization support. - DeviceLayer::SystemLayer().ScheduleLambda([]() { admin::DeviceMgr().ReadSupportedDeviceCategories(); }); + DeviceLayer::SystemLayer().ScheduleLambda([]() { admin::DeviceManager::Instance().ReadSupportedDeviceCategories(); }); } else { @@ -75,7 +75,7 @@ void AddBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) CHIP_ERROR AddBridgeCommand::RunCommand() { - if (admin::DeviceMgr().IsFabricSyncReady()) + if (admin::DeviceManager::Instance().IsFabricSyncReady()) { // print to console fprintf(stderr, "Remote Fabric Bridge has already been configured.\n"); @@ -87,7 +87,7 @@ CHIP_ERROR AddBridgeCommand::RunCommand() ChipLogProgress(NotSpecified, "Running AddBridgeCommand with Node ID: %lu, PIN Code: %u, Address: %s, Port: %u", mBridgeNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); - return admin::DeviceMgr().PairRemoteFabricBridge(mBridgeNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); + return admin::DeviceManager::Instance().PairRemoteFabricBridge(mBridgeNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); } } // namespace commands diff --git a/examples/fabric-sync/shell/AddDeviceCommand.cpp b/examples/fabric-sync/shell/AddDeviceCommand.cpp index a85de7695deb98..a79e4696caaf4e 100644 --- a/examples/fabric-sync/shell/AddDeviceCommand.cpp +++ b/examples/fabric-sync/shell/AddDeviceCommand.cpp @@ -51,7 +51,7 @@ void AddDeviceCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) { ChipLogProgress(NotSpecified, "Successfully paired device: NodeId: " ChipLogFormatX64, ChipLogValueX64(mNodeId)); - admin::DeviceMgr().UpdateLastUsedNodeId(mNodeId); + admin::DeviceManager::Instance().UpdateLastUsedNodeId(mNodeId); } else { @@ -64,7 +64,7 @@ void AddDeviceCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) CHIP_ERROR AddDeviceCommand::RunCommand() { - if (admin::DeviceMgr().IsCurrentBridgeDevice(mNodeId)) + if (admin::DeviceManager::Instance().IsCurrentBridgeDevice(mNodeId)) { // print to console fprintf(stderr, "The specified node ID has been reserved by the Fabric Bridge.\n"); @@ -76,7 +76,7 @@ CHIP_ERROR AddDeviceCommand::RunCommand() admin::PairingManager::Instance().SetPairingDelegate(this); - return admin::DeviceMgr().PairRemoteDevice(mNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); + return admin::DeviceManager::Instance().PairRemoteDevice(mNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); } } // namespace commands diff --git a/examples/fabric-sync/shell/RemoveBridgeCommand.cpp b/examples/fabric-sync/shell/RemoveBridgeCommand.cpp index 77bd76be33675a..9a33b0b11ba94e 100644 --- a/examples/fabric-sync/shell/RemoveBridgeCommand.cpp +++ b/examples/fabric-sync/shell/RemoveBridgeCommand.cpp @@ -35,7 +35,7 @@ void RemoveBridgeCommand::OnDeviceRemoved(NodeId deviceId, CHIP_ERROR err) if (err == CHIP_NO_ERROR) { - admin::DeviceMgr().SetRemoteBridgeNodeId(kUndefinedNodeId); + admin::DeviceManager::Instance().SetRemoteBridgeNodeId(kUndefinedNodeId); // print to console fprintf(stderr, "Successfully removed bridge device: NodeId: " ChipLogFormatX64 "\n", ChipLogValueX64(mBridgeNodeId)); @@ -51,7 +51,7 @@ void RemoveBridgeCommand::OnDeviceRemoved(NodeId deviceId, CHIP_ERROR err) CHIP_ERROR RemoveBridgeCommand::RunCommand() { - NodeId bridgeNodeId = admin::DeviceMgr().GetRemoteBridgeNodeId(); + NodeId bridgeNodeId = admin::DeviceManager::Instance().GetRemoteBridgeNodeId(); if (bridgeNodeId == kUndefinedNodeId) { @@ -66,7 +66,7 @@ CHIP_ERROR RemoveBridgeCommand::RunCommand() admin::PairingManager::Instance().SetPairingDelegate(this); - return admin::DeviceMgr().UnpairRemoteFabricBridge(); + return admin::DeviceManager::Instance().UnpairRemoteFabricBridge(); } } // namespace commands diff --git a/examples/fabric-sync/shell/RemoveDeviceCommand.cpp b/examples/fabric-sync/shell/RemoveDeviceCommand.cpp index 78440f854283aa..5e316658d5b303 100644 --- a/examples/fabric-sync/shell/RemoveDeviceCommand.cpp +++ b/examples/fabric-sync/shell/RemoveDeviceCommand.cpp @@ -52,7 +52,7 @@ void RemoveDeviceCommand::OnDeviceRemoved(NodeId deviceId, CHIP_ERROR err) CHIP_ERROR RemoveDeviceCommand::RunCommand() { - if (admin::DeviceMgr().IsCurrentBridgeDevice(mNodeId)) + if (admin::DeviceManager::Instance().IsCurrentBridgeDevice(mNodeId)) { // print to console fprintf(stderr, "The specified node ID has been reserved by the Fabric Bridge.\n"); @@ -63,7 +63,7 @@ CHIP_ERROR RemoveDeviceCommand::RunCommand() ChipLogProgress(NotSpecified, "Running RemoveDeviceCommand with Node ID: %lu", mNodeId); - return admin::DeviceMgr().UnpairRemoteDevice(mNodeId); + return admin::DeviceManager::Instance().UnpairRemoteDevice(mNodeId); } } // namespace commands From 1bdcb74643ad758a9b71f857ef9660e6d2d89c05 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas Date: Thu, 14 Nov 2024 23:49:58 +0100 Subject: [PATCH 04/27] [darwin] Update the NetworkFramework UDP implementation (#36418) * [Network.framework] Add chip_system_config_use_network_framework * [Network.framework] Update src/lib/core/CHIPConfig.h file to enable CHIP_CONFIG_IsPlatformPOSIXErrorNonCritical * [Network.framework] Update src/system/SystemConfig.h file to enable CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS * [Network.Framework] Update src/inet/InetInterface* files with some additional #ifdef for the network framework * [Network.Framework] Update src/inet/IPAddress* files with some additional #ifdef for the network framework * [Network.framework] Update src/inet/InetInterfaceImplDefault.cpp to enable the default implementation * [Network.framework] Update src/system to not use WakeEvent/Signal when using the network framework * [Network.framework] Convert UDPEndPointImplNetworkFramework.cpp to .mm with arc support * [chip-tool] Ensure each commissioner listen onto its own udc port since Network.framework won't allow SO_REUSEPORT * [Matter.framework][darwin-framework-tool] Add chip_system_config_use_network_framework flag support * Apply suggestions from code review --------- Co-authored-by: Boris Zbarsky --- .../chip-tool/commands/common/CHIPCommand.cpp | 5 + examples/darwin-framework-tool/BUILD.gn | 14 +- scripts/build/build_darwin_framework.py | 5 +- .../Framework/chip_xcode_build_connector.sh | 6 + src/inet/BUILD.gn | 9 +- src/inet/IPAddress-StringFuncts.cpp | 8 +- src/inet/IPAddress.h | 9 +- src/inet/InetInterface.cpp | 8 +- src/inet/InetInterface.h | 2 +- src/inet/InetInterfaceImpl.h | 2 +- src/inet/InetInterfaceImplDefault.cpp | 2 +- src/inet/UDPEndPointImplNetworkFramework.cpp | 533 -------------- src/inet/UDPEndPointImplNetworkFramework.h | 8 +- src/inet/UDPEndPointImplNetworkFramework.mm | 655 ++++++++++++++++++ src/inet/inet.gni | 7 + src/lib/core/CHIPConfig.h | 6 +- src/system/BUILD.gn | 2 +- src/system/SystemConfig.h | 2 +- src/system/SystemLayer.h | 8 +- src/system/SystemLayerImplSelect.cpp | 40 +- src/system/SystemLayerImplSelect.h | 2 +- src/system/system.gni | 16 +- 22 files changed, 763 insertions(+), 586 deletions(-) delete mode 100644 src/inet/UDPEndPointImplNetworkFramework.cpp create mode 100644 src/inet/UDPEndPointImplNetworkFramework.mm diff --git a/examples/chip-tool/commands/common/CHIPCommand.cpp b/examples/chip-tool/commands/common/CHIPCommand.cpp index 1c3df517bd89d0..4f14cb855e5af7 100644 --- a/examples/chip-tool/commands/common/CHIPCommand.cpp +++ b/examples/chip-tool/commands/common/CHIPCommand.cpp @@ -467,6 +467,11 @@ void CHIPCommand::ShutdownCommissioner(const CommissionerIdentity & key) CHIP_ERROR CHIPCommand::InitializeCommissioner(CommissionerIdentity & identity, chip::FabricId fabricId) { std::unique_ptr commissioner = std::make_unique(); +#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY + VerifyOrReturnError(chip::CanCastTo(CHIP_UDC_PORT + fabricId), CHIP_ERROR_INVALID_ARGUMENT); + uint16_t udcListenPort = static_cast(CHIP_UDC_PORT + fabricId); + commissioner->SetUdcListenPort(udcListenPort); +#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY chip::Controller::SetupParams commissionerParams; ReturnLogErrorOnFailure(mCredIssuerCmds->SetupDeviceAttestation(commissionerParams, sTrustStore, sRevocationDelegate)); diff --git a/examples/darwin-framework-tool/BUILD.gn b/examples/darwin-framework-tool/BUILD.gn index fbe1c4d6f82954..257431b2425aec 100644 --- a/examples/darwin-framework-tool/BUILD.gn +++ b/examples/darwin-framework-tool/BUILD.gn @@ -46,6 +46,9 @@ declare_args() { # Enable automatic leak checks before the application exits enable_leak_checking = !is_asan && target_os == "mac" + + # Use Network.framework instead of POSIX sockets + use_network_framework = false } sdk = "macosx" @@ -125,6 +128,12 @@ action("build-darwin-framework") { args += [ "--no-enable-encoding-sentinel-enum-values" ] } + if (defined(use_network_framework) && use_network_framework) { + args += [ "--use-network-framework" ] + } else { + args += [ "--no-use-network-framework" ] + } + output_name = "Matter.framework" outputs = [ "${root_out_dir}/macos_framework_output/Build/Products/${output_sdk_type}/${output_name}", @@ -277,10 +286,7 @@ executable("darwin-framework-tool") { "${root_out_dir}/macos_framework_output/Build/Intermediates.noindex/Matter.build/${output_sdk_type}/Matter.build/out/gen/include", ] - defines = [ - "CHIP_HAVE_CONFIG_H=1", - "CHIP_SYSTEM_CONFIG_USE_SOCKETS=1", - ] + defines = [ "CHIP_HAVE_CONFIG_H=1" ] frameworks += [ "CoreFoundation.framework", diff --git a/scripts/build/build_darwin_framework.py b/scripts/build/build_darwin_framework.py index d2d3665a1bcfd0..a048241ff1f396 100644 --- a/scripts/build/build_darwin_framework.py +++ b/scripts/build/build_darwin_framework.py @@ -91,7 +91,8 @@ def build_darwin_framework(args): 'CHIP_IS_ASAN': args.asan, 'CHIP_IS_BLE': args.ble, 'CHIP_IS_CLANG': args.clang, - 'CHIP_ENABLE_ENCODING_SENTINEL_ENUM_VALUES': args.enable_encoding_sentinel_enum_values + 'CHIP_ENABLE_ENCODING_SENTINEL_ENUM_VALUES': args.enable_encoding_sentinel_enum_values, + 'CHIP_USE_NETWORK_FRAMEWORK': args.use_network_framework } for option in options: command += ["{}={}".format(option, "YES" if options[option] else "NO")] @@ -176,6 +177,8 @@ def build_darwin_framework(args): parser.add_argument('--clang', action=argparse.BooleanOptionalAction) parser.add_argument('--enable-encoding-sentinel-enum-values', action=argparse.BooleanOptionalAction) parser.add_argument('--compdb', action=argparse.BooleanOptionalAction) + parser.add_argument('--use-network-framework', + action=argparse.BooleanOptionalAction) args = parser.parse_args() build_darwin_framework(args) diff --git a/src/darwin/Framework/chip_xcode_build_connector.sh b/src/darwin/Framework/chip_xcode_build_connector.sh index 0c08ab381b32f4..7e8e72d213d685 100755 --- a/src/darwin/Framework/chip_xcode_build_connector.sh +++ b/src/darwin/Framework/chip_xcode_build_connector.sh @@ -187,6 +187,12 @@ esac ) } +[[ $CHIP_USE_NETWORK_FRAMEWORK == YES ]] && { + args+=( + 'chip_system_config_use_network_framework=true' + ) +} + # search current (or $2) and its parent directories until # a name match is found, which is output on stdout find_in_ancestors() { diff --git a/src/inet/BUILD.gn b/src/inet/BUILD.gn index e30d417ffc0b39..ede5d383734566 100644 --- a/src/inet/BUILD.gn +++ b/src/inet/BUILD.gn @@ -158,11 +158,16 @@ static_library("inet") { "EndpointQueueFilter.h", "UDPEndPoint.cpp", "UDPEndPoint.h", - "UDPEndPointImpl${chip_system_config_inet}.cpp", "UDPEndPointImpl${chip_system_config_inet}.h", "UDPEndPointImpl.h", ] + if (chip_system_config_use_network_framework) { + sources += [ "UDPEndPointImpl${chip_system_config_inet}.mm" ] + } else { + sources += [ "UDPEndPointImpl${chip_system_config_inet}.cpp" ] + } + if (chip_system_config_inet == "Sockets") { # TODO: dependency on this one is not clear as it is only ever # enabled through CMakeLists.txt. Added here for completeness @@ -187,5 +192,7 @@ static_library("inet") { cflags = [ "-Wconversion" ] if (current_os == "nuttx") { cflags -= [ "-Wconversion" ] + } else if (chip_system_config_use_network_framework) { + cflags += [ "-fobjc-arc" ] } } diff --git a/src/inet/IPAddress-StringFuncts.cpp b/src/inet/IPAddress-StringFuncts.cpp index 7022b44a6aaf60..2a7ff008a3c552 100644 --- a/src/inet/IPAddress-StringFuncts.cpp +++ b/src/inet/IPAddress-StringFuncts.cpp @@ -32,7 +32,7 @@ #include #include -#if CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK +#if CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS #include #endif @@ -54,7 +54,7 @@ char * IPAddress::ToString(char * buf, uint32_t bufSize) const ip6_addr_t ip6_addr = ToIPv6(); ip6addr_ntoa_r(&ip6_addr, buf, (int) bufSize); } -#elif CHIP_SYSTEM_CONFIG_USE_SOCKETS +#elif CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK // socklen_t is sometimes signed, sometimes not, so the only safe way to do // this is to promote everything to an unsigned type that's known to be big // enough for everything, then cast back to uint32_t after taking the min. @@ -93,7 +93,7 @@ bool IPAddress::FromString(const char * str, IPAddress & output) ip4_addr_t ipv4Addr; if (!ip4addr_aton(str, &ipv4Addr)) return false; -#elif CHIP_SYSTEM_CONFIG_USE_SOCKETS +#elif CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK struct in_addr ipv4Addr; if (inet_pton(AF_INET, str, &ipv4Addr) < 1) return false; @@ -107,7 +107,7 @@ bool IPAddress::FromString(const char * str, IPAddress & output) ip6_addr_t ipv6Addr; if (!ip6addr_aton(str, &ipv6Addr)) return false; -#elif CHIP_SYSTEM_CONFIG_USE_SOCKETS +#elif CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK struct in6_addr ipv6Addr; if (inet_pton(AF_INET6, str, &ipv6Addr) < 1) return false; diff --git a/src/inet/IPAddress.h b/src/inet/IPAddress.h index 2b756ef5561b99..03a40394b5e80b 100644 --- a/src/inet/IPAddress.h +++ b/src/inet/IPAddress.h @@ -56,12 +56,9 @@ #include #endif // CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT -#if CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK +#if CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS #include #include -#endif // CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK - -#if CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS #include #endif // CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS @@ -110,7 +107,7 @@ enum class IPv6MulticastFlag : uint8_t }; using IPv6MulticastFlags = BitFlags; -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS +#if CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK /** * SockAddr should be used when calling any API that returns (by copying into * it) a sockaddr, because that will need enough storage that it can hold data @@ -139,7 +136,7 @@ union SockAddrWithoutStorage sockaddr_in in; sockaddr_in6 in6; }; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS +#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK /** * @brief Internet protocol address diff --git a/src/inet/InetInterface.cpp b/src/inet/InetInterface.cpp index af89de8cb96822..4595dfef449fe3 100644 --- a/src/inet/InetInterface.cpp +++ b/src/inet/InetInterface.cpp @@ -38,7 +38,7 @@ #include #endif // CHIP_SYSTEM_CONFIG_USE_LWIP -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS +#if (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS #include #include #include @@ -50,7 +50,7 @@ #include #include #include -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS +#endif // (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF #include @@ -434,7 +434,7 @@ CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) const #endif // CHIP_SYSTEM_CONFIG_USE_LWIP -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS +#if (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) const { @@ -788,7 +788,7 @@ CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) const return (found) ? CHIP_NO_ERROR : INET_ERROR_ADDRESS_NOT_FOUND; } -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS +#endif // (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF diff --git a/src/inet/InetInterface.h b/src/inet/InetInterface.h index 9603ba80c3ed05..82f3797a8dc769 100644 --- a/src/inet/InetInterface.h +++ b/src/inet/InetInterface.h @@ -85,7 +85,7 @@ class InterfaceId static constexpr size_t kMaxIfNameLength = 13; // Names are formatted as %c%c%d #endif // CHIP_SYSTEM_CONFIG_USE_LWIP -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS +#if (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS using PlatformType = unsigned int; static constexpr size_t kMaxIfNameLength = IF_NAMESIZE; #endif // CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS diff --git a/src/inet/InetInterfaceImpl.h b/src/inet/InetInterfaceImpl.h index 4d310c998c0107..00c29cff158e61 100644 --- a/src/inet/InetInterfaceImpl.h +++ b/src/inet/InetInterfaceImpl.h @@ -19,7 +19,7 @@ #include -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS +#if (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS #include namespace chip { diff --git a/src/inet/InetInterfaceImplDefault.cpp b/src/inet/InetInterfaceImplDefault.cpp index 461cbe1b0a3ace..91eafed8001cf7 100644 --- a/src/inet/InetInterfaceImplDefault.cpp +++ b/src/inet/InetInterfaceImplDefault.cpp @@ -16,7 +16,7 @@ */ #include -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS +#if (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS #include namespace chip { namespace Inet { diff --git a/src/inet/UDPEndPointImplNetworkFramework.cpp b/src/inet/UDPEndPointImplNetworkFramework.cpp deleted file mode 100644 index 35f6d135a0fc08..00000000000000 --- a/src/inet/UDPEndPointImplNetworkFramework.cpp +++ /dev/null @@ -1,533 +0,0 @@ -/* - * - * Copyright (c) 2020-2021 Project CHIP Authors - * Copyright (c) 2018 Google LLC. - * Copyright (c) 2013-2018 Nest Labs, Inc. - * - * 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 implements Inet::UDPEndPoint using Network Framework. - */ - -#define __APPLE_USE_RFC_3542 -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define INET_PORTSTRLEN 6 - -namespace chip { -namespace Inet { - -CHIP_ERROR UDPEndPointImplNetworkFramework::BindImpl(IPAddressType addressType, const IPAddress & address, uint16_t port, - InterfaceId intfId) -{ - nw_parameters_configure_protocol_block_t configure_tls; - nw_parameters_t parameters; - - if (intfId.IsPresent()) - { - return CHIP_ERROR_NOT_IMPLEMENTED; - } - - configure_tls = NW_PARAMETERS_DISABLE_PROTOCOL; - parameters = nw_parameters_create_secure_udp(configure_tls, NW_PARAMETERS_DEFAULT_CONFIGURATION); - VerifyOrReturnError(parameters != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - - ReturnErrorOnFailure(ConfigureProtocol(addressType, parameters)); - - nw_endpoint_t endpoint = nullptr; - CHIP_ERROR res = GetEndPoint(endpoint, addressType, address, port); - nw_parameters_set_local_endpoint(parameters, endpoint); - nw_release(endpoint); - ReturnErrorOnFailure(res); - - mDispatchQueue = dispatch_queue_create("inet_dispatch_global", DISPATCH_QUEUE_CONCURRENT); - VerifyOrReturnError(mDispatchQueue != nullptr, CHIP_ERROR_NO_MEMORY); - dispatch_retain(mDispatchQueue); - - mConnectionSemaphore = dispatch_semaphore_create(0); - VerifyOrReturnError(mConnectionSemaphore != nullptr, CHIP_ERROR_NO_MEMORY); - dispatch_retain(mConnectionSemaphore); - - mSendSemaphore = dispatch_semaphore_create(0); - VerifyOrReturnError(mSendSemaphore != nullptr, CHIP_ERROR_NO_MEMORY); - dispatch_retain(mSendSemaphore); - - mAddrType = addressType; - mConnection = nullptr; - mParameters = parameters; - - return CHIP_NO_ERROR; -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::BindInterfaceImpl(IPAddressType addrType, InterfaceId intfId) -{ - return INET_ERROR_UNKNOWN_INTERFACE; -} - -InterfaceId UDPEndPointImplNetworkFramework::GetBoundInterface() const -{ - return InterfaceId::Null(); -} - -uint16_t UDPEndPointImplNetworkFramework::GetBoundPort() const -{ - nw_endpoint_t endpoint = nw_parameters_copy_local_endpoint(mParameters); - return nw_endpoint_get_port(endpoint); -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::ListenImpl() -{ - return StartListener(); -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::SendMsgImpl(const IPPacketInfo * pktInfo, System::PacketBufferHandle && msg) -{ - dispatch_data_t content; - - // Ensure the destination address type is compatible with the endpoint address type. - VerifyOrReturnError(mAddrType == pktInfo->DestAddress.Type(), CHIP_ERROR_INVALID_ARGUMENT); - - // For now the entire message must fit within a single buffer. - VerifyOrReturnError(msg->Next() == nullptr, CHIP_ERROR_MESSAGE_TOO_LONG); - - ReturnErrorOnFailure(GetConnection(pktInfo)); - - // Send a message, and wait for it to be dispatched. - content = dispatch_data_create(msg->Start(), msg->DataLength(), mDispatchQueue, DISPATCH_DATA_DESTRUCTOR_DEFAULT); - - // If there is a current message pending and the state of the network connection change (e.g switch to a - // different network) the connection will enter a nw_connection_state_failed state and the completion handler - // will never be called. In such cases a signal is sent from the connection state change handler to release - // the semaphore. In this case the CHIP_ERROR will not update with the result of the completion handler. - // To make sure caller knows that sending a message has failed the following code consider there is an error - // _unless_ the completion handler says otherwise. - __block CHIP_ERROR res = CHIP_ERROR_UNEXPECTED_EVENT; - nw_connection_send(mConnection, content, NW_CONNECTION_DEFAULT_MESSAGE_CONTEXT, true, ^(nw_error_t error) { - if (error) - { - res = CHIP_ERROR_POSIX(nw_error_get_error_code(error)); - } - else - { - res = CHIP_NO_ERROR; - } - dispatch_semaphore_signal(mSendSemaphore); - }); - dispatch_release(content); - - dispatch_semaphore_wait(mSendSemaphore, DISPATCH_TIME_FOREVER); - - return res; -} - -void UDPEndPointImplNetworkFramework::CloseImpl() -{ - ReleaseAll(); -} - -void UDPEndPointImplNetworkFramework::ReleaseAll() -{ - - OnMessageReceived = nullptr; - OnReceiveError = nullptr; - - ReleaseConnection(); - ReleaseListener(); - - if (mParameters) - { - nw_release(mParameters); - mParameters = nullptr; - } - - if (mDispatchQueue) - { - dispatch_suspend(mDispatchQueue); - dispatch_release(mDispatchQueue); - mDispatchQueue = nullptr; - } - - if (mConnectionSemaphore) - { - dispatch_release(mConnectionSemaphore); - mConnectionSemaphore = nullptr; - } - - if (mListenerQueue) - { - dispatch_suspend(mListenerQueue); - dispatch_release(mListenerQueue); - mListenerQueue = nullptr; - } - - if (mListenerSemaphore) - { - dispatch_release(mListenerSemaphore); - mListenerSemaphore = nullptr; - } - - if (mSendSemaphore) - { - dispatch_release(mSendSemaphore); - mSendSemaphore = nullptr; - } -} - -void UDPEndPointImplNetworkFramework::Free() -{ - Close(); - Release(); -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::SetMulticastLoopback(IPVersion aIPVersion, bool aLoopback) -{ - return CHIP_ERROR_NOT_IMPLEMENTED; -} - -#if INET_CONFIG_ENABLE_IPV4 -CHIP_ERROR UDPEndPointImplNetworkFramework::IPv4JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, - bool join) -{ - return CHIP_ERROR_NOT_IMPLEMENTED; -} -#endif // INET_CONFIG_ENABLE_IPV4 - -CHIP_ERROR UDPEndPointImplNetworkFramework::IPv6JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, - bool join) -{ - return CHIP_ERROR_NOT_IMPLEMENTED; -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::ConfigureProtocol(IPAddressType aAddressType, const nw_parameters_t & aParameters) -{ - CHIP_ERROR res = CHIP_NO_ERROR; - - nw_protocol_stack_t protocolStack = nw_parameters_copy_default_protocol_stack(aParameters); - nw_protocol_options_t ipOptions = nw_protocol_stack_copy_internet_protocol(protocolStack); - - switch (aAddressType) - { - - case IPAddressType::kIPv6: - nw_ip_options_set_version(ipOptions, nw_ip_version_6); - break; - -#if INET_CONFIG_ENABLE_IPV4 - case IPAddressType::kIPv4: - nw_ip_options_set_version(ipOptions, nw_ip_version_4); - break; -#endif // INET_CONFIG_ENABLE_IPV4 - - default: - res = INET_ERROR_WRONG_ADDRESS_TYPE; - break; - } - nw_release(ipOptions); - nw_release(protocolStack); - - return res; -} - -void UDPEndPointImplNetworkFramework::GetPacketInfo(const nw_connection_t & aConnection, IPPacketInfo & aPacketInfo) -{ - nw_path_t path = nw_connection_copy_current_path(aConnection); - nw_endpoint_t dest_endpoint = nw_path_copy_effective_local_endpoint(path); - nw_endpoint_t src_endpoint = nw_path_copy_effective_remote_endpoint(path); - - aPacketInfo.Clear(); - aPacketInfo.SrcAddress = IPAddress::FromSockAddr(*nw_endpoint_get_address(src_endpoint)); - aPacketInfo.DestAddress = IPAddress::FromSockAddr(*nw_endpoint_get_address(dest_endpoint)); - aPacketInfo.SrcPort = nw_endpoint_get_port(src_endpoint); - aPacketInfo.DestPort = nw_endpoint_get_port(dest_endpoint); -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::GetEndPoint(nw_endpoint_t & aEndPoint, const IPAddressType aAddressType, - const IPAddress & aAddress, uint16_t aPort) -{ - char addrStr[INET6_ADDRSTRLEN]; - char portStr[INET_PORTSTRLEN]; - - // Note: aAddress.ToString will return the IPv6 Any address if the address type is Any, but that's not what - // we want if the locale endpoint is IPv4. - if (aAddressType == IPAddressType::kIPv4 && aAddress.Type() == IPAddressType::kAny) - { - const IPAddress anyAddr = IPAddress(aAddress.ToIPv4()); - anyAddr.ToString(addrStr, sizeof(addrStr)); - } - else - { - aAddress.ToString(addrStr, sizeof(addrStr)); - } - - snprintf(portStr, sizeof(portStr), "%u", aPort); - - aEndPoint = nw_endpoint_create_host(addrStr, portStr); - VerifyOrReturnError(aEndPoint != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - - return CHIP_NO_ERROR; -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::GetConnection(const IPPacketInfo * aPktInfo) -{ - VerifyOrReturnError(mParameters != nullptr, CHIP_ERROR_INCORRECT_STATE); - - nw_endpoint_t endpoint = nullptr; - nw_connection_t connection = nullptr; - - if (mConnection) - { - nw_path_t path = nw_connection_copy_current_path(mConnection); - nw_endpoint_t remote_endpoint = nw_path_copy_effective_remote_endpoint(path); - const IPAddress remote_address = IPAddress::FromSockAddr(*nw_endpoint_get_address(remote_endpoint)); - const uint16_t remote_port = nw_endpoint_get_port(remote_endpoint); - const bool isDifferentEndPoint = aPktInfo->DestPort != remote_port || aPktInfo->DestAddress != remote_address; - VerifyOrReturnError(isDifferentEndPoint, CHIP_NO_ERROR); - - ReturnErrorOnFailure(ReleaseConnection()); - } - - ReturnErrorOnFailure(GetEndPoint(endpoint, mAddrType, aPktInfo->DestAddress, aPktInfo->DestPort)); - - connection = nw_connection_create(endpoint, mParameters); - nw_release(endpoint); - - VerifyOrReturnError(connection != nullptr, CHIP_ERROR_INCORRECT_STATE); - - return StartConnection(connection); -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::StartListener() -{ - __block CHIP_ERROR res = CHIP_NO_ERROR; - nw_listener_t listener; - - VerifyOrReturnError(mListener == nullptr, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mListenerSemaphore == nullptr, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mListenerQueue == nullptr, CHIP_ERROR_INCORRECT_STATE); - - listener = nw_listener_create(mParameters); - VerifyOrReturnError(listener != nullptr, CHIP_ERROR_INCORRECT_STATE); - - mListenerSemaphore = dispatch_semaphore_create(0); - VerifyOrReturnError(mListenerSemaphore != nullptr, CHIP_ERROR_NO_MEMORY); - dispatch_retain(mListenerSemaphore); - - mListenerQueue = dispatch_queue_create("inet_dispatch_listener", DISPATCH_QUEUE_CONCURRENT); - VerifyOrReturnError(mListenerQueue != nullptr, CHIP_ERROR_NO_MEMORY); - dispatch_retain(mListenerQueue); - - nw_listener_set_queue(listener, mListenerQueue); - - nw_listener_set_new_connection_handler(listener, ^(nw_connection_t connection) { - ReleaseConnection(); - StartConnection(connection); - }); - - nw_listener_set_state_changed_handler(listener, ^(nw_listener_state_t state, nw_error_t error) { - switch (state) - { - - case nw_listener_state_invalid: - ChipLogDetail(Inet, "Listener: Invalid"); - res = CHIP_ERROR_INCORRECT_STATE; - nw_listener_cancel(listener); - break; - - case nw_listener_state_waiting: - ChipLogDetail(Inet, "Listener: Waiting"); - break; - - case nw_listener_state_failed: - ChipLogDetail(Inet, "Listener: Failed"); - res = CHIP_ERROR_POSIX(nw_error_get_error_code(error)); - break; - - case nw_listener_state_ready: - ChipLogDetail(Inet, "Listener: Ready"); - res = CHIP_NO_ERROR; - dispatch_semaphore_signal(mListenerSemaphore); - break; - - case nw_listener_state_cancelled: - ChipLogDetail(Inet, "Listener: Cancelled"); - if (res == CHIP_NO_ERROR) - { - res = CHIP_ERROR_CONNECTION_ABORTED; - } - - dispatch_semaphore_signal(mListenerSemaphore); - break; - } - }); - - nw_listener_start(listener); - dispatch_semaphore_wait(mListenerSemaphore, DISPATCH_TIME_FOREVER); - ReturnErrorOnFailure(res); - - mListener = listener; - nw_retain(mListener); - return res; -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::StartConnection(nw_connection_t & aConnection) -{ - __block CHIP_ERROR res = CHIP_NO_ERROR; - - nw_connection_set_queue(aConnection, mDispatchQueue); - - nw_connection_set_state_changed_handler(aConnection, ^(nw_connection_state_t state, nw_error_t error) { - switch (state) - { - - case nw_connection_state_invalid: - ChipLogDetail(Inet, "Connection: Invalid"); - res = CHIP_ERROR_INCORRECT_STATE; - nw_connection_cancel(aConnection); - break; - - case nw_connection_state_preparing: - ChipLogDetail(Inet, "Connection: Preparing"); - res = CHIP_ERROR_INCORRECT_STATE; - break; - - case nw_connection_state_waiting: - ChipLogDetail(Inet, "Connection: Waiting"); - nw_connection_cancel(aConnection); - break; - - case nw_connection_state_failed: - ChipLogDetail(Inet, "Connection: Failed"); - res = CHIP_ERROR_POSIX(nw_error_get_error_code(error)); - break; - - case nw_connection_state_ready: - ChipLogDetail(Inet, "Connection: Ready"); - res = CHIP_NO_ERROR; - dispatch_semaphore_signal(mConnectionSemaphore); - break; - - case nw_connection_state_cancelled: - ChipLogDetail(Inet, "Connection: Cancelled"); - if (res == CHIP_NO_ERROR) - { - res = CHIP_ERROR_CONNECTION_ABORTED; - } - - dispatch_semaphore_signal(mConnectionSemaphore); - break; - } - }); - - nw_connection_start(aConnection); - dispatch_semaphore_wait(mConnectionSemaphore, DISPATCH_TIME_FOREVER); - SuccessOrExit(res); - - mConnection = aConnection; - nw_retain(mConnection); - HandleDataReceived(mConnection); - - return res; -} - -void UDPEndPointImplNetworkFramework::HandleDataReceived(const nw_connection_t & aConnection) -{ - nw_connection_receive_completion_t handler = - ^(dispatch_data_t content, nw_content_context_t context, bool is_complete, nw_error_t receive_error) { - dispatch_block_t schedule_next_receive = ^{ - if (receive_error == nullptr) - { - HandleDataReceived(aConnection); - } - else if (OnReceiveError != nullptr) - { - nw_error_domain_t error_domain = nw_error_get_error_domain(receive_error); - errno = nw_error_get_error_code(receive_error); - if (!(error_domain == nw_error_domain_posix && errno == ECANCELED)) - { - CHIP_ERROR error = CHIP_ERROR_POSIX(errno); - IPPacketInfo packetInfo; - GetPacketInfo(aConnection, packetInfo); - dispatch_async(mDispatchQueue, ^{ - OnReceiveError((UDPEndPoint *) this, error, &packetInfo); - }); - } - } - }; - - if (content != nullptr && OnMessageReceived != nullptr) - { - size_t count = dispatch_data_get_size(content); - System::PacketBufferHandle * packetBuffer = System::PacketBufferHandle::New(count); - dispatch_data_apply(content, ^(dispatch_data_t data, size_t offset, const void * buffer, size_t size) { - memmove(packetBuffer->Start() + offset, buffer, size); - return true; - }); - packetBuffer->SetDataLength(count); - - IPPacketInfo packetInfo; - GetPacketInfo(aConnection, packetInfo); - dispatch_async(mDispatchQueue, ^{ - OnMessageReceived((UDPEndPoint *) this, packetBuffer, &packetInfo); - }); - } - - schedule_next_receive(); - }; - - nw_connection_receive_message(aConnection, handler); -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::ReleaseListener() -{ - VerifyOrReturnError(mListener, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mDispatchQueue, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mConnectionSemaphore, CHIP_ERROR_INCORRECT_STATE); - - nw_listener_cancel(mListener); - dispatch_semaphore_wait(mListenerSemaphore, DISPATCH_TIME_FOREVER); - nw_release(mListener); - mListener = nullptr; - - return CHIP_NO_ERROR; -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::ReleaseConnection() -{ - VerifyOrReturnError(mConnection, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mDispatchQueue, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mConnectionSemaphore, CHIP_ERROR_INCORRECT_STATE); - - nw_connection_cancel(mConnection); - dispatch_semaphore_wait(mConnectionSemaphore, DISPATCH_TIME_FOREVER); - nw_release(mConnection); - mConnection = nullptr; - - return CHIP_NO_ERROR; -} - -} // namespace Inet -} // namespace chip diff --git a/src/inet/UDPEndPointImplNetworkFramework.h b/src/inet/UDPEndPointImplNetworkFramework.h index 55c5ef181212e4..0e8f7dda68ebcb 100644 --- a/src/inet/UDPEndPointImplNetworkFramework.h +++ b/src/inet/UDPEndPointImplNetworkFramework.h @@ -56,14 +56,16 @@ class UDPEndPointImplNetworkFramework : public UDPEndPoint, public EndPointState dispatch_queue_t mListenerQueue; nw_connection_t mConnection; dispatch_semaphore_t mConnectionSemaphore; - dispatch_queue_t mDispatchQueue; + dispatch_queue_t mConnectionQueue; dispatch_semaphore_t mSendSemaphore; + dispatch_queue_t mSystemQueue; CHIP_ERROR ConfigureProtocol(IPAddressType aAddressType, const nw_parameters_t & aParameters); CHIP_ERROR StartListener(); CHIP_ERROR GetConnection(const IPPacketInfo * aPktInfo); - CHIP_ERROR GetEndPoint(nw_endpoint_t & aEndpoint, const IPAddressType aAddressType, const IPAddress & aAddress, uint16_t aPort); - CHIP_ERROR StartConnection(nw_connection_t & aConnection); + nw_endpoint_t GetEndPoint(const IPAddressType aAddressType, const IPAddress & aAddress, uint16_t aPort, + InterfaceId interfaceIndex = InterfaceId::Null()); + CHIP_ERROR StartConnection(nw_connection_t aConnection); void GetPacketInfo(const nw_connection_t & aConnection, IPPacketInfo & aPacketInfo); void HandleDataReceived(const nw_connection_t & aConnection); CHIP_ERROR ReleaseListener(); diff --git a/src/inet/UDPEndPointImplNetworkFramework.mm b/src/inet/UDPEndPointImplNetworkFramework.mm new file mode 100644 index 00000000000000..070048538c6f50 --- /dev/null +++ b/src/inet/UDPEndPointImplNetworkFramework.mm @@ -0,0 +1,655 @@ +/* + * + * Copyright (c) 2020-2024 Project CHIP Authors + * Copyright (c) 2018 Google LLC. + * Copyright (c) 2013-2018 Nest Labs, Inc. + * + * 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 implements Inet::UDPEndPoint using Network Framework. + */ + +#if !__has_feature(objc_arc) +#error This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). +#endif + +#include +#include + +#include + +#define INET_PORTSTRLEN 6 + +#define NETWORK_FRAMEWORK_DEBUG 0 + +namespace { +#if !NETWORK_FRAMEWORK_DEBUG +void DebugPrintListenerState(nw_listener_state_t state) {}; +void DebugPrintConnectionState(nw_connection_state_t state) {}; +void DebugPrintConnection(const nw_connection_t aConnection) {}; +#else +constexpr const char * kNilConnection = "The connection is nil."; +constexpr const char * kNilPath = "The connection path is nil."; +constexpr const char * kNilPathSourceEndPoint = "The connection path source endpoint is nil."; +constexpr const char * kNilPathDestinationEndPoint = "The connection path destination endpoint is nil."; +constexpr const char * kPathStatusInvalid = "This path is not valid."; +constexpr const char * kPathStatusUnsatisfied = "The path is not available for use."; +constexpr const char * kPathStatusSatisfied = "The path is available to establish connections and send data."; +constexpr const char * kPathStatusSatisfiable = "The path is not currently available, but establishing a new connection may activate the path."; + +constexpr const char * kListenerStateInvalid = "Listener: Invalid"; +constexpr const char * kListenerStateWaiting = "Listener: Waiting"; +constexpr const char * kListenerStateFailed = "Listener: Failed"; +constexpr const char * kListenerStateReady = "Listener: Ready"; +constexpr const char * kListenerStateCancelled = "Listener: Cancelled"; + +constexpr const char * kConnectionStateInvalid = "Connection: Invalid"; +constexpr const char * kConnectionStateWaiting = "Connection: Waiting"; +constexpr const char * kConnectionStatePreparing = "Connection: Preparing"; +constexpr const char * kConnectionStateFailed = "Connection: Failed"; +constexpr const char * kConnectionStateReady = "Connection: Ready"; +constexpr const char * kConnectionStateCancelled = "Connection: Cancelled"; + +void DebugPrintConnectionState(nw_connection_state_t state) +{ + const char * str = nullptr; + + switch (state) { + case nw_connection_state_invalid: + str = kConnectionStateInvalid; + break; + case nw_connection_state_preparing: + str = kConnectionStatePreparing; + break; + case nw_connection_state_waiting: + str = kConnectionStateWaiting; + break; + case nw_connection_state_failed: + str = kConnectionStateFailed; + break; + case nw_connection_state_ready: + str = kConnectionStateReady; + break; + case nw_connection_state_cancelled: + str = kConnectionStateCancelled; + break; + default: + chipDie(); + } + + ChipLogDetail(Inet, "%s", str); +} + +void DebugPrintListenerState(nw_listener_state_t state) +{ + const char * str = nullptr; + + switch (state) { + case nw_listener_state_invalid: + str = kListenerStateInvalid; + break; + case nw_listener_state_waiting: + str = kListenerStateWaiting; + break; + case nw_listener_state_failed: + str = kListenerStateFailed; + break; + case nw_listener_state_ready: + str = kListenerStateReady; + break; + case nw_listener_state_cancelled: + str = kListenerStateCancelled; + break; + default: + chipDie(); + } + + ChipLogDetail(Inet, "%s", str); +} + +void DebugPrintConnectionPathStatus(nw_path_t path) +{ + const char * str = nullptr; + + __auto_type status = nw_path_get_status(path); + switch (status) { + case nw_path_status_invalid: + str = kPathStatusInvalid; + break; + case nw_path_status_unsatisfied: + str = kPathStatusUnsatisfied; + break; + case nw_path_status_satisfied: + str = kPathStatusSatisfied; + break; + case nw_path_status_satisfiable: + str = kPathStatusSatisfiable; + break; + default: + chipDie(); + } + + ChipLogError(Inet, "%s", str); +} + +void DebugPrintConnection(const nw_connection_t aConnection) +{ + VerifyOrReturn(nil != aConnection, ChipLogError(Inet, "%s", kNilConnection)); + + __auto_type path = nw_connection_copy_current_path(aConnection); + VerifyOrReturn(nil != path, ChipLogError(Inet, "%s", kNilPath)); + DebugPrintConnectionPathStatus(path); + + __auto_type srcEndPoint = nw_path_copy_effective_local_endpoint(path); + VerifyOrReturn(nil != srcEndPoint, ChipLogError(Inet, "%s", kNilPathSourceEndPoint)); + + __auto_type dstEndPoint = nw_path_copy_effective_remote_endpoint(path); + VerifyOrReturn(nil != dstEndPoint, ChipLogError(Inet, "%s", kNilPathDestinationEndPoint)); + + const __auto_type * srcAddress = nw_endpoint_copy_address_string(srcEndPoint); + const __auto_type srcPort = nw_endpoint_get_port(srcEndPoint); + const __auto_type * dstAddress = nw_endpoint_copy_address_string(dstEndPoint); + const __auto_type dstPort = nw_endpoint_get_port(dstEndPoint); + + ChipLogError(Inet, "Connection source: %s:%u destination: %s:%u", srcAddress, srcPort, dstAddress, dstPort); +} +#endif +} + +namespace chip { +namespace Inet { + + CHIP_ERROR UDPEndPointImplNetworkFramework::BindImpl(IPAddressType addressType, const IPAddress & address, uint16_t port, + InterfaceId intfId) + { +#if NETWORK_FRAMEWORK_DEBUG + ChipLogError(Inet, "%s (%p)", __func__, this); +#endif + + VerifyOrReturnError(!intfId.IsPresent(), CHIP_ERROR_NOT_IMPLEMENTED); + + __auto_type configure_tls = NW_PARAMETERS_DISABLE_PROTOCOL; + __auto_type parameters = nw_parameters_create_secure_udp(configure_tls, NW_PARAMETERS_DEFAULT_CONFIGURATION); + VerifyOrReturnError(nullptr != parameters, CHIP_ERROR_INVALID_ARGUMENT); + + // Note: The ConfigureProtocol function uses nw_ip_options_set_version to set the IP version for this endpoint. + // + // This works as expected when the IPAddress is specified. However, when using a wildcard address (chip::Inet::IPAddressType::kAny) + // for an IPv6 socket, the specified IP version (nw_ip_version_6) may be ignored, allowing both IPv4 and IPv6 connections. + ReturnErrorOnFailure(ConfigureProtocol(addressType, parameters)); + + // Note: Network.framework does not provide an API to set the SO_REUSEPORT socket option. + // This limitation is not an issue when the port is set to 0, as the platform will choose a random port. + // + // However, when both INET_CONFIG_ENABLE_IPV4 and CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY are enabled, + // the system attempts to create two endpoints—one over IPv6 and another over IPv4—both using the same port + // specified by CHIP_UDC_PORT. + // + // This results in a binding failure due to "Address already in use" since both IPv4 and IPv6 endpoints + // try to use the same port. + // + // A potential solution would be to define separate ports for IPv4 and IPv6 (e.g., CHIP_UDC_PORT_IPv4 and CHIP_UDC_PORT_IPv6). + // For now, as a workaround, we set the port to 0 for IPv4 when a specific port is needed, allowing the platform to + // auto-assign an available port and avoid the conflict. + if (IPAddressType::kIPv4 == addressType && port != 0) { + port = 0; + } + + __auto_type endpoint = GetEndPoint(addressType, address, port); + VerifyOrReturnError(nullptr != endpoint, CHIP_ERROR_INTERNAL); + nw_parameters_set_local_endpoint(parameters, endpoint); + + mConnectionQueue = dispatch_queue_create("inet_dispatch_global", DISPATCH_QUEUE_SERIAL); + VerifyOrReturnError(nullptr != mConnectionQueue, CHIP_ERROR_NO_MEMORY); + + mConnectionSemaphore = dispatch_semaphore_create(0); + VerifyOrReturnError(nullptr != mConnectionSemaphore, CHIP_ERROR_NO_MEMORY); + + mSendSemaphore = dispatch_semaphore_create(0); + VerifyOrReturnError(nullptr != mSendSemaphore, CHIP_ERROR_NO_MEMORY); + + mSystemQueue = static_cast(GetSystemLayer()).GetDispatchQueue(); + mAddrType = addressType; + mConnection = nullptr; + mParameters = parameters; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::BindInterfaceImpl(IPAddressType addrType, InterfaceId intfId) + { + return INET_ERROR_UNKNOWN_INTERFACE; + } + + InterfaceId UDPEndPointImplNetworkFramework::GetBoundInterface() const + { + return InterfaceId::Null(); + } + + uint16_t UDPEndPointImplNetworkFramework::GetBoundPort() const + { + __auto_type endpoint = nw_parameters_copy_local_endpoint(mParameters); + return nw_endpoint_get_port(endpoint); + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::ListenImpl() + { + return StartListener(); + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::SendMsgImpl(const IPPacketInfo * pktInfo, System::PacketBufferHandle && msg) + { +#if NETWORK_FRAMEWORK_DEBUG + ChipLogError(Inet, "%s (%p)", __func__, this); +#endif + + // Ensure we have an actual message to send. + VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_INVALID_ARGUMENT); + + // Ensure the destination address type is compatible with the endpoint address type. + VerifyOrReturnError(mAddrType == pktInfo->DestAddress.Type(), CHIP_ERROR_INVALID_ARGUMENT); + + // For now the entire message must fit within a single buffer. + VerifyOrReturnError(msg->Next() == nullptr, CHIP_ERROR_MESSAGE_TOO_LONG); + + ReturnErrorOnFailure(GetConnection(pktInfo)); + + // Send a message, and wait for it to be dispatched. + __auto_type content = dispatch_data_create(msg->Start(), msg->DataLength(), mSystemQueue, DISPATCH_DATA_DESTRUCTOR_DEFAULT); + + // If there is a current message pending and the state of the network connection changes (e.g switch to a + // different network) the connection will enter a nw_connection_state_failed state and the completion handler + // will never be called. In such cases a signal is sent from the connection state change handler to release + // the semaphore. In this case the CHIP_ERROR will not update with the result of the completion handler. + // To make sure our caller knows that sending a message has failed the following code assumes there is an error + // _unless_ the completion handler says otherwise. + __block CHIP_ERROR err = CHIP_ERROR_UNEXPECTED_EVENT; + nw_connection_send(mConnection, content, NW_CONNECTION_DEFAULT_MESSAGE_CONTEXT, true, ^(nw_error_t error) { + if (error) { + err = CHIP_ERROR_POSIX(nw_error_get_error_code(error)); + } else { + err = CHIP_NO_ERROR; + } + dispatch_semaphore_signal(mSendSemaphore); + }); + + dispatch_semaphore_wait(mSendSemaphore, DISPATCH_TIME_FOREVER); + + return err; + } + + void UDPEndPointImplNetworkFramework::CloseImpl() + { + ReleaseAll(); + } + + void UDPEndPointImplNetworkFramework::ReleaseAll() + { + + OnMessageReceived = nullptr; + OnReceiveError = nullptr; + + ReleaseConnection(); + ReleaseListener(); + + mParameters = nullptr; + + mConnectionQueue = nullptr; + mConnectionSemaphore = nullptr; + + mListenerQueue = nullptr; + mListenerSemaphore = nullptr; + + mSendSemaphore = nullptr; + } + + void UDPEndPointImplNetworkFramework::Free() + { + Close(); + Release(); + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::SetMulticastLoopback(IPVersion aIPVersion, bool aLoopback) + { + return CHIP_ERROR_NOT_IMPLEMENTED; + } + +#if INET_CONFIG_ENABLE_IPV4 + CHIP_ERROR UDPEndPointImplNetworkFramework::IPv4JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, + bool join) + { + return CHIP_ERROR_NOT_IMPLEMENTED; + } +#endif // INET_CONFIG_ENABLE_IPV4 + + CHIP_ERROR UDPEndPointImplNetworkFramework::IPv6JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, + bool join) + { + return CHIP_ERROR_NOT_IMPLEMENTED; + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::ConfigureProtocol(IPAddressType aAddressType, const nw_parameters_t & aParameters) + { + CHIP_ERROR err = CHIP_NO_ERROR; + + __auto_type protocolStack = nw_parameters_copy_default_protocol_stack(aParameters); + __auto_type ipOptions = nw_protocol_stack_copy_internet_protocol(protocolStack); + + switch (aAddressType) { + + case IPAddressType::kIPv6: + nw_ip_options_set_version(ipOptions, nw_ip_version_6); + break; + +#if INET_CONFIG_ENABLE_IPV4 + case IPAddressType::kIPv4: + nw_ip_options_set_version(ipOptions, nw_ip_version_4); + break; +#endif // INET_CONFIG_ENABLE_IPV4 + + default: + err = INET_ERROR_WRONG_ADDRESS_TYPE; + break; + } + + return err; + } + + void UDPEndPointImplNetworkFramework::GetPacketInfo(const nw_connection_t & aConnection, IPPacketInfo & aPacketInfo) + { + nw_path_t path = nw_connection_copy_current_path(aConnection); + nw_endpoint_t dest_endpoint = nw_path_copy_effective_local_endpoint(path); + nw_endpoint_t src_endpoint = nw_path_copy_effective_remote_endpoint(path); + + aPacketInfo.Clear(); + + // TODO Handle return value of IPAddress::GetIPAddressFromSockAdd + const auto * srcAddress = nw_endpoint_get_address(src_endpoint); + IPAddress::GetIPAddressFromSockAddr(*srcAddress, aPacketInfo.SrcAddress); + + // TODO Handle return value of IPAddress::GetIPAddressFromSockAdd + const auto * dstAddress = nw_endpoint_get_address(dest_endpoint); + IPAddress::GetIPAddressFromSockAddr(*dstAddress, aPacketInfo.DestAddress); + + aPacketInfo.SrcPort = nw_endpoint_get_port(src_endpoint); + aPacketInfo.DestPort = nw_endpoint_get_port(dest_endpoint); + +#if NETWORK_FRAMEWORK_DEBUG + char srcAddrStr[IPAddress::kMaxStringLength + 1 /*null terminator */]; + char dstAddrStr[IPAddress::kMaxStringLength + 1 /*null terminator */]; + aPacketInfo.SrcAddress.ToString(srcAddrStr); + aPacketInfo.DestAddress.ToString(dstAddrStr); + ChipLogError(Inet, "Packet received from %s to %s", srcAddrStr, dstAddrStr); +#endif + } + + nw_endpoint_t UDPEndPointImplNetworkFramework::GetEndPoint(const IPAddressType aAddressType, + const IPAddress & aAddress, uint16_t aPort, InterfaceId interfaceIndex) + { + char addrStr[IPAddress::kMaxStringLength + 1 /*%*/ + InterfaceId::kMaxIfNameLength + 1 /*null terminator */]; + char portStr[INET_PORTSTRLEN]; + + // Note: aAddress.ToString will return the IPv6 Any address if the address type is Any, but that's not what + // we want if the local endpoint is IPv4. +#if INET_CONFIG_ENABLE_IPV4 + if (aAddressType == IPAddressType::kIPv4 && aAddress.Type() == IPAddressType::kAny) { + const IPAddress anyAddr = IPAddress(aAddress.ToIPv4()); + anyAddr.ToString(addrStr); + } else +#endif // INET_CONFIG_ENABLE_IPV4 + { + aAddress.ToString(addrStr); + if (interfaceIndex != InterfaceId::Null()) { + char interface[InterfaceId::kMaxIfNameLength + 1] = {}; // +1 to prepend '%' + interface[0] = '%'; + interface[1] = 0; + CHIP_ERROR err = interfaceIndex.GetInterfaceName(interface + 1, sizeof(interface) - 1); + if (err != CHIP_NO_ERROR) { + Platform::CopyString(interface, sizeof(interface), "%(err)"); + } + strncat(addrStr, interface, sizeof(addrStr) - strlen(addrStr) - 1); + } + } + + snprintf(portStr, sizeof(portStr), "%u", aPort); + + char * target = addrStr; + +#if NETWORK_FRAMEWORK_DEBUG + ChipLogError(Inet, "Create endpoint for ip(%s) port(%s)", target, portStr); +#endif + return nw_endpoint_create_host(target, portStr); + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::GetConnection(const IPPacketInfo * aPktInfo) + { + VerifyOrReturnError(nullptr != mParameters, CHIP_ERROR_INCORRECT_STATE); + + if (mConnection) { + __auto_type path = nw_connection_copy_current_path(mConnection); + __auto_type remote_endpoint = nw_path_copy_effective_remote_endpoint(path); + // TODO Handle return value of IPAddress::GetIPAddressFromSockAdd + IPAddress remote_address; + IPAddress::GetIPAddressFromSockAddr(*nw_endpoint_get_address(remote_endpoint), remote_address); + + const uint16_t remote_port = nw_endpoint_get_port(remote_endpoint); + const bool isDifferentEndPoint = aPktInfo->DestPort != remote_port || aPktInfo->DestAddress != remote_address; + // Return without doing anything if we are not changing our endpoint. + VerifyOrReturnError(isDifferentEndPoint, CHIP_NO_ERROR); + + ReturnErrorOnFailure(ReleaseConnection()); + } + + __auto_type endpoint = GetEndPoint(mAddrType, aPktInfo->DestAddress, aPktInfo->DestPort, aPktInfo->Interface); + VerifyOrReturnError(nullptr != endpoint, CHIP_ERROR_INCORRECT_STATE); + + __auto_type connection = nw_connection_create(endpoint, mParameters); + VerifyOrReturnError(nullptr != connection, CHIP_ERROR_INCORRECT_STATE); + + return StartConnection(connection); + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::StartListener() + { + VerifyOrReturnError(nullptr == mListener, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(nullptr == mListenerSemaphore, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(nullptr == mListenerQueue, CHIP_ERROR_INCORRECT_STATE); + + __auto_type listener = nw_listener_create(mParameters); + VerifyOrReturnError(nullptr != listener, CHIP_ERROR_INCORRECT_STATE); + + mListenerSemaphore = dispatch_semaphore_create(0); + VerifyOrReturnError(nullptr != mListenerSemaphore, CHIP_ERROR_NO_MEMORY); + + mListenerQueue = dispatch_queue_create("inet_dispatch_listener", DISPATCH_QUEUE_CONCURRENT); + VerifyOrReturnError(nullptr != mListenerQueue, CHIP_ERROR_NO_MEMORY); + + nw_listener_set_queue(listener, mListenerQueue); + + nw_listener_set_new_connection_handler(listener, ^(nw_connection_t connection) { + ReleaseConnection(); + StartConnection(connection); + }); + + __block CHIP_ERROR err = CHIP_NO_ERROR; + nw_listener_set_state_changed_handler(listener, ^(nw_listener_state_t state, nw_error_t error) { + DebugPrintListenerState(state); + + switch (state) { + case nw_listener_state_invalid: + err = CHIP_ERROR_INCORRECT_STATE; + nw_listener_cancel(listener); + break; + + case nw_listener_state_waiting: + // Nothing to do. + break; + + case nw_listener_state_failed: + err = CHIP_ERROR_POSIX(nw_error_get_error_code(error)); + ChipLogError(Inet, "Error: %s", chip::ErrorStr(err)); + break; + + case nw_listener_state_ready: + err = CHIP_NO_ERROR; + dispatch_semaphore_signal(mListenerSemaphore); + break; + + case nw_listener_state_cancelled: + if (err == CHIP_NO_ERROR) { + err = CHIP_ERROR_CONNECTION_ABORTED; + } + + dispatch_semaphore_signal(mListenerSemaphore); + break; + } + }); + + nw_listener_start(listener); + dispatch_semaphore_wait(mListenerSemaphore, DISPATCH_TIME_FOREVER); + + if (CHIP_NO_ERROR == err) { + mListener = listener; + } + + return err; + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::StartConnection(nw_connection_t aConnection) + { + __block CHIP_ERROR err = CHIP_NO_ERROR; + + nw_connection_set_queue(aConnection, mConnectionQueue); + + nw_connection_set_state_changed_handler(aConnection, ^(nw_connection_state_t state, nw_error_t error) { + DebugPrintConnectionState(state); + + switch (state) { + case nw_connection_state_invalid: + err = CHIP_ERROR_INCORRECT_STATE; + nw_connection_cancel(aConnection); + break; + + case nw_connection_state_preparing: + err = CHIP_ERROR_INCORRECT_STATE; + break; + + case nw_connection_state_waiting: + nw_connection_cancel(aConnection); + break; + + case nw_connection_state_failed: + err = CHIP_ERROR_POSIX(nw_error_get_error_code(error)); + break; + + case nw_connection_state_ready: + err = CHIP_NO_ERROR; + dispatch_semaphore_signal(mConnectionSemaphore); + break; + + case nw_connection_state_cancelled: + if (err == CHIP_NO_ERROR) { + err = CHIP_ERROR_CONNECTION_ABORTED; + } + + dispatch_semaphore_signal(mConnectionSemaphore); + break; + } + }); + + nw_connection_start(aConnection); + dispatch_semaphore_wait(mConnectionSemaphore, DISPATCH_TIME_FOREVER); + + if (CHIP_NO_ERROR == err) { + DebugPrintConnection(aConnection); + + mConnection = aConnection; + HandleDataReceived(mConnection); + } + return err; + } + + void UDPEndPointImplNetworkFramework::HandleDataReceived(const nw_connection_t & aConnection) + { + nw_connection_receive_completion_t handler = ^(dispatch_data_t content, nw_content_context_t context, bool is_complete, nw_error_t receive_error) { + dispatch_block_t schedule_next_receive = ^{ + if (receive_error == nullptr) { + HandleDataReceived(aConnection); + } else if (OnReceiveError != nullptr) { + __auto_type error_domain = nw_error_get_error_domain(receive_error); + errno = nw_error_get_error_code(receive_error); + if (!(error_domain == nw_error_domain_posix && errno == ECANCELED)) { + CHIP_ERROR error = CHIP_ERROR_POSIX(errno); + IPPacketInfo packetInfo; + GetPacketInfo(aConnection, packetInfo); + dispatch_async(mSystemQueue, ^{ + OnReceiveError((UDPEndPoint *) this, error, &packetInfo); + }); + } + } + }; + + if (content != nullptr && OnMessageReceived != nullptr) { + size_t count = dispatch_data_get_size(content); + auto packetBufferHandle = System::PacketBufferHandle::New(count); + auto * packetBuffer = std::move(packetBufferHandle).UnsafeRelease(); + dispatch_data_apply(content, ^(dispatch_data_t data, size_t offset, const void * buffer, size_t size) { + memmove(packetBuffer->Start() + offset, buffer, size); + return true; + }); + packetBuffer->SetDataLength(count); + + IPPacketInfo packetInfo; + GetPacketInfo(aConnection, packetInfo); + dispatch_async(mSystemQueue, ^{ + auto handle = System::PacketBufferHandle::Adopt(packetBuffer); + OnMessageReceived((UDPEndPoint *) this, std::move(handle), &packetInfo); + }); + } + + schedule_next_receive(); + }; + + nw_connection_receive_message(aConnection, handler); + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::ReleaseListener() + { + VerifyOrReturnError(nullptr != mListener, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(nullptr != mConnectionQueue, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(nullptr != mConnectionSemaphore, CHIP_ERROR_INCORRECT_STATE); + + nw_listener_cancel(mListener); + dispatch_semaphore_wait(mListenerSemaphore, DISPATCH_TIME_FOREVER); + mListener = nullptr; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::ReleaseConnection() + { + VerifyOrReturnError(nullptr != mConnection, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(nullptr != mConnectionQueue, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(nullptr != mConnectionSemaphore, CHIP_ERROR_INCORRECT_STATE); + + nw_connection_cancel(mConnection); + dispatch_semaphore_wait(mConnectionSemaphore, DISPATCH_TIME_FOREVER); + mConnection = nullptr; + + return CHIP_NO_ERROR; + } + +} // namespace Inet +} // namespace chip diff --git a/src/inet/inet.gni b/src/inet/inet.gni index 1c19551da374c6..ea66c3df3f11ef 100644 --- a/src/inet/inet.gni +++ b/src/inet/inet.gni @@ -26,11 +26,18 @@ declare_args() { # Enable TCP endpoint. chip_inet_config_enable_tcp_endpoint = true + # TODO: Set to false when using Network.framework until a Network.framework TCP endpoint backend is implemented. + if (chip_system_config_use_network_framework) { + chip_inet_config_enable_tcp_endpoint = false + } + # Inet implementation type. if (chip_system_config_use_open_thread_inet_endpoints) { chip_system_config_inet = "OpenThread" } else if (chip_system_config_use_lwip) { chip_system_config_inet = "LwIP" + } else if (chip_system_config_use_network_framework) { + chip_system_config_inet = "NetworkFramework" } else { chip_system_config_inet = "Sockets" } diff --git a/src/lib/core/CHIPConfig.h b/src/lib/core/CHIPConfig.h index fca3472826a310..a775d2b58fc23f 100644 --- a/src/lib/core/CHIPConfig.h +++ b/src/lib/core/CHIPConfig.h @@ -618,13 +618,13 @@ #define _CHIP_CONFIG_IsPlatformLwIPErrorNonCritical(CODE) 0 #endif // !CHIP_SYSTEM_CONFIG_USE_LWIP -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS +#if CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK #define _CHIP_CONFIG_IsPlatformPOSIXErrorNonCritical(CODE) \ ((CODE) == CHIP_ERROR_POSIX(EHOSTUNREACH) || (CODE) == CHIP_ERROR_POSIX(ENETUNREACH) || \ (CODE) == CHIP_ERROR_POSIX(EADDRNOTAVAIL) || (CODE) == CHIP_ERROR_POSIX(EPIPE)) -#else // !CHIP_SYSTEM_CONFIG_USE_SOCKETS +#else // !(CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) #define _CHIP_CONFIG_IsPlatformPOSIXErrorNonCritical(CODE) 0 -#endif // !CHIP_SYSTEM_CONFIG_USE_SOCKETS +#endif // !(CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) #define CHIP_CONFIG_IsPlatformErrorNonCritical(CODE) \ (_CHIP_CONFIG_IsPlatformPOSIXErrorNonCritical(CODE) || _CHIP_CONFIG_IsPlatformLwIPErrorNonCritical(CODE)) diff --git a/src/system/BUILD.gn b/src/system/BUILD.gn index a8d15cf83f4223..3de5ea84be11f5 100644 --- a/src/system/BUILD.gn +++ b/src/system/BUILD.gn @@ -99,7 +99,7 @@ buildconfig_header("system_buildconfig") { "CHIP_SYSTEM_CONFIG_USE_LWIP=${chip_system_config_use_lwip}", "CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT=${chip_system_config_use_open_thread_inet_endpoints}", "CHIP_SYSTEM_CONFIG_USE_SOCKETS=${chip_system_config_use_sockets}", - "CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK=false", + "CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK=${chip_system_config_use_network_framework}", "CHIP_SYSTEM_CONFIG_POSIX_LOCKING=${chip_system_config_posix_locking}", "CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING=${chip_system_config_freertos_locking}", "CHIP_SYSTEM_CONFIG_MBED_LOCKING=${chip_system_config_mbed_locking}", diff --git a/src/system/SystemConfig.h b/src/system/SystemConfig.h index 58339df4be1e47..2fe0823922467e 100644 --- a/src/system/SystemConfig.h +++ b/src/system/SystemConfig.h @@ -768,7 +768,7 @@ struct LwIPEvent; * Defaults to enabled on platforms that use sockets other than Zephyr sockets. */ #ifndef CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && !CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKETS +#if (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && !CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKETS #define CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS 1 #else #define CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS 0 diff --git a/src/system/SystemLayer.h b/src/system/SystemLayer.h index 75878ce6a81f50..9314ccd5609786 100644 --- a/src/system/SystemLayer.h +++ b/src/system/SystemLayer.h @@ -40,10 +40,10 @@ #include #include -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS +#if CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK #include #include -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS +#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_USE_NETWORK_FRAMEWORK #if CHIP_SYSTEM_CONFIG_USE_DISPATCH #include @@ -235,7 +235,7 @@ class LayerFreeRTOS : public Layer #endif // CHIP_SYSTEM_CONFIG_USE_LWIP -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS +#if CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK class LayerSockets : public Layer { @@ -356,7 +356,7 @@ class LayerSocketsLoop : public LayerSockets decltype(EventLoopHandler::mState) & LoopHandlerState(EventLoopHandler & handler) { return handler.mState; } }; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS +#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK } // namespace System } // namespace chip diff --git a/src/system/SystemLayerImplSelect.cpp b/src/system/SystemLayerImplSelect.cpp index fe025a5765e659..52354f99d82ff0 100644 --- a/src/system/SystemLayerImplSelect.cpp +++ b/src/system/SystemLayerImplSelect.cpp @@ -67,10 +67,10 @@ CHIP_ERROR LayerImplSelect::Init() mHandleSelectThread = PTHREAD_NULL; #endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING -#if !CHIP_SYSTEM_CONFIG_USE_LIBEV +#if !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK // Create an event to allow an arbitrary thread to wake the thread in the select loop. ReturnErrorOnFailure(mWakeEvent.Open(*this)); -#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV +#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK VerifyOrReturnError(mLayerState.SetInitialized(), CHIP_ERROR_INCORRECT_STATE); return CHIP_NO_ERROR; @@ -116,9 +116,9 @@ void LayerImplSelect::Shutdown() mTimerPool.ReleaseAll(); #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH/LIBEV -#if !CHIP_SYSTEM_CONFIG_USE_LIBEV +#if !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK mWakeEvent.Close(*this); -#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV +#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK mLayerState.ResetFromShuttingDown(); // Return to uninitialized state to permit re-initialization. } @@ -127,6 +127,8 @@ void LayerImplSelect::Signal() { #if CHIP_SYSTEM_CONFIG_USE_LIBEV ChipLogError(DeviceLayer, "Signal() should not be called in CHIP_SYSTEM_CONFIG_USE_LIBEV builds (might be ok in tests)"); +#elif CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK + ChipLogError(DeviceLayer, "Signal() should not be called in CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK builds"); #else /* * Wake up the I/O thread by writing a single byte to the wake pipe. @@ -151,7 +153,7 @@ void LayerImplSelect::Signal() ChipLogError(chipSystemLayer, "System wake event notify failed: %" CHIP_ERROR_FORMAT, status.Format()); } -#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV +#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK } CHIP_ERROR LayerImplSelect::StartTimer(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) @@ -188,6 +190,9 @@ CHIP_ERROR LayerImplSelect::StartTimer(Clock::Timeout delay, TimerCompleteCallba dispatch_resume(timerSource); return CHIP_NO_ERROR; } +#if CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK + return CHIP_ERROR_INTERNAL; +#endif // CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK #elif CHIP_SYSTEM_CONFIG_USE_LIBEV VerifyOrDie(mLibEvLoopP != nullptr); ev_timer_init(&timer->mLibEvTimer, &LayerImplSelect::HandleLibEvTimer, 1, 0); @@ -205,15 +210,18 @@ CHIP_ERROR LayerImplSelect::StartTimer(Clock::Timeout delay, TimerCompleteCallba ev_timer_start(mLibEvLoopP, &timer->mLibEvTimer); return CHIP_NO_ERROR; #endif -#if !CHIP_SYSTEM_CONFIG_USE_LIBEV - // Note: dispatch based implementation needs this as fallback, but not LIBEV (and dead code is not allowed with -Werror) +#if !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK + // Note: The dispatch-based implementation (using sockets but not Network.framework) requires this as a fallback + // for testing purposes. However, it is not needed for LIBEV or when using Network.framework (which lacks a testing + // configuration). Since dead code is also not allowed with -Werror, we need to ifdef this code out + // in those configurations. if (mTimerList.Add(timer) == timer) { // The new timer is the earliest, so the time until the next event has probably changed. Signal(); } return CHIP_NO_ERROR; -#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV +#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK } CHIP_ERROR LayerImplSelect::ExtendTimerTo(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) @@ -290,8 +298,8 @@ void LayerImplSelect::CancelTimer(TimerCompleteCallback onComplete, void * appSt #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH/LIBEV mTimerPool.Release(timer); -#if !CHIP_SYSTEM_CONFIG_USE_LIBEV - // LIBEV has no I/O wakeup thread, so must not call Signal() +#if !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK + // Neither LIBEV nor CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK builds include an I/O wakeup thread, so must not call Signal(). Signal(); #endif } @@ -311,6 +319,9 @@ CHIP_ERROR LayerImplSelect::ScheduleWork(TimerCompleteCallback onComplete, void }); return CHIP_NO_ERROR; } +#if CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK + return CHIP_ERROR_INTERNAL; +#endif // CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK #elif CHIP_SYSTEM_CONFIG_USE_LIBEV // schedule as timer with no delay, but do NOT cancel previous timers with same onComplete/appState! TimerList::Node * timer = mTimerPool.Create(*this, SystemClock().GetMonotonicTimestamp(), onComplete, appState); @@ -324,8 +335,11 @@ CHIP_ERROR LayerImplSelect::ScheduleWork(TimerCompleteCallback onComplete, void ev_timer_start(mLibEvLoopP, &timer->mLibEvTimer); return CHIP_NO_ERROR; #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH/LIBEV -#if !CHIP_SYSTEM_CONFIG_USE_LIBEV - // Note: dispatch based implementation needs this as fallback, but not LIBEV (and dead code is not allowed with -Werror) +#if !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK + // Note: The dispatch-based implementation (using sockets but not Network.framework) requires this as a fallback + // for testing purposes. However, it is not needed for LIBEV or when using Network.framework (which lacks a testing + // configuration). Since dead code is also not allowed with -Werror, we need to ifdef this code out + // in those configurations. // Ideally we would not use a timer here at all, but if we try to just // ScheduleLambda the lambda needs to capture the following: // 1) onComplete @@ -360,7 +374,7 @@ CHIP_ERROR LayerImplSelect::ScheduleWork(TimerCompleteCallback onComplete, void Signal(); } return CHIP_NO_ERROR; -#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV +#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK } CHIP_ERROR LayerImplSelect::StartWatchingSocket(int fd, SocketWatchToken * tokenOut) diff --git a/src/system/SystemLayerImplSelect.h b/src/system/SystemLayerImplSelect.h index ce34ece0115b9b..d2f8c880ee50da 100644 --- a/src/system/SystemLayerImplSelect.h +++ b/src/system/SystemLayerImplSelect.h @@ -158,7 +158,7 @@ class LayerImplSelect : public LayerSocketsLoop int mSelectResult; ObjectLifeCycle mLayerState; -#if !CHIP_SYSTEM_CONFIG_USE_LIBEV +#if !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK WakeEvent mWakeEvent; #endif diff --git a/src/system/system.gni b/src/system/system.gni index 61cd52fa320245..e58f32914695b6 100644 --- a/src/system/system.gni +++ b/src/system/system.gni @@ -20,8 +20,8 @@ declare_args() { # Use the lwIP library. chip_system_config_use_lwip = chip_with_lwip && current_os == "freertos" - # Use BSD/POSIX socket API. - chip_system_config_use_sockets = current_os != "freertos" + # Use Network.framework API + chip_system_config_use_network_framework = false # Mutex implementation: posix, freertos, none. chip_system_config_locking = "" @@ -36,13 +36,21 @@ declare_args() { chip_system_config_use_open_thread_inet_endpoints = false } +declare_args() { + # Use BSD/POSIX socket API. + chip_system_config_use_sockets = + current_os != "freertos" && !chip_system_config_use_network_framework +} + declare_args() { # do not use libev by default chip_system_config_use_libev = false # use the dispatch library on darwin targets - chip_system_config_use_dispatch = chip_system_config_use_sockets && - (current_os == "mac" || current_os == "ios") + chip_system_config_use_dispatch = + (chip_system_config_use_sockets || + chip_system_config_use_network_framework) && + (current_os == "mac" || current_os == "ios") } declare_args() { From b8898ab793578b5bfc53578ba0df519fd22cca60 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 14 Nov 2024 18:26:07 -0500 Subject: [PATCH 05/27] Move more of the MTRAttributeValueWaiter logic into the waiter. (#36416) * Move more of the MTRAttributeValueWaiter logic into the waiter. This logic should not live in MTRDevice. * Address review comments. --- .../Framework/CHIP/MTRAttributeValueWaiter.mm | 77 +++++++++++++++---- .../CHIP/MTRAttributeValueWaiter_Internal.h | 10 ++- src/darwin/Framework/CHIP/MTRDevice.mm | 63 ++++----------- .../Framework/CHIP/MTRDevice_Internal.h | 2 +- 4 files changed, 87 insertions(+), 65 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRAttributeValueWaiter.mm b/src/darwin/Framework/CHIP/MTRAttributeValueWaiter.mm index 10d0b9f8e1393d..930bbd790cd299 100644 --- a/src/darwin/Framework/CHIP/MTRAttributeValueWaiter.mm +++ b/src/darwin/Framework/CHIP/MTRAttributeValueWaiter.mm @@ -15,12 +15,15 @@ */ #import +#import #import #import "MTRAttributeValueWaiter_Internal.h" #import "MTRDevice_Internal.h" +#import "MTRError_Internal.h" #import "MTRLogging_Internal.h" +#import "MTRUnfairLock.h" @implementation MTRAwaitedAttributeState - (instancetype)initWithValue:(MTRDeviceDataValueDictionary)value @@ -40,10 +43,14 @@ @interface MTRAttributeValueWaiter () // Protected by the MTRDevice's lock. @property (nonatomic, readwrite, retain) dispatch_queue_t queue; @property (nonatomic, readwrite, copy, nullable) MTRStatusCompletion completion; +@property (nonatomic, retain, readwrite, nullable) dispatch_source_t expirationTimer; @property (nonatomic, readonly, retain) MTRDevice * device; @end -@implementation MTRAttributeValueWaiter +@implementation MTRAttributeValueWaiter { + // Protects queue/completion and expirationTimer. + os_unfair_lock _lock; +} - (instancetype)initWithDevice:(MTRDevice *)device values:(NSDictionary *)values queue:(dispatch_queue_t)queue completion:(MTRStatusCompletion)completion { @@ -58,6 +65,7 @@ - (instancetype)initWithDevice:(MTRDevice *)device values:(NSDictionary(timeout * static_cast(NSEC_PER_SEC))), DISPATCH_TIME_FOREVER, + // Allow .5 seconds of leeway; should be plenty, in practice. + static_cast(0.5 * static_cast(NSEC_PER_SEC))); + + mtr_weakify(self); + dispatch_source_set_event_handler(timerSource, ^{ + dispatch_source_cancel(timerSource); + mtr_strongify(self); + if (self != nil) { + [self.device _forgetAttributeWaiter:self]; + [self _notifyWithError:[MTRError errorForCHIPErrorCode:CHIP_ERROR_TIMEOUT]]; + } + }); + + { + std::lock_guard lock(_lock); + self.expirationTimer = timerSource; + } + + dispatch_resume(timerSource); +} + - (NSString *)description { return [NSString stringWithFormat:@"<%@: %@>", NSStringFromClass(self.class), self.UUID]; diff --git a/src/darwin/Framework/CHIP/MTRAttributeValueWaiter_Internal.h b/src/darwin/Framework/CHIP/MTRAttributeValueWaiter_Internal.h index 8d4a7999691a0d..a23af1d06da1e8 100644 --- a/src/darwin/Framework/CHIP/MTRAttributeValueWaiter_Internal.h +++ b/src/darwin/Framework/CHIP/MTRAttributeValueWaiter_Internal.h @@ -37,7 +37,6 @@ MTR_DIRECT_MEMBERS @interface MTRAttributeValueWaiter () @property (nonatomic, readonly) BOOL allValuesSatisfied; -@property (nonatomic, retain, readwrite, nullable) dispatch_source_t expirationTimer; - (instancetype)initWithDevice:(MTRDevice *)device values:(NSDictionary *)values queue:(dispatch_queue_t)queue completion:(MTRStatusCompletion)completion; @@ -46,6 +45,15 @@ MTR_DIRECT_MEMBERS - (void)_notifyWithError:(NSError * _Nullable)error; +// Starts the timer for our timeout, using the device's queue as the dispatch +// queuue for the timer firing. +- (void)_startTimerWithTimeout:(NSTimeInterval)timeout; + +// Cancels the waiter without trying to remove it from the MTRDevice's +// collection of waiters (unlike "cancel", which does that removal). This is +// exposed so that MTRDevice can do it when invalidating. +- (void)_notifyCancellation; + @end NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRDevice.mm b/src/darwin/Framework/CHIP/MTRDevice.mm index 7c6414d2a1d9c0..7f273e26f03399 100644 --- a/src/darwin/Framework/CHIP/MTRDevice.mm +++ b/src/darwin/Framework/CHIP/MTRDevice.mm @@ -753,7 +753,6 @@ - (MTRAttributeValueWaiter *)waitForAttributeValues:(NSDictionary * currentValues = [self readAttributePaths:requestPaths]; - std::lock_guard lock(_lock); auto * attributeWaiter = [[MTRAttributeValueWaiter alloc] initWithDevice:self values:values queue:queue completion:completion]; for (MTRDeviceResponseValueDictionary currentValue in currentValues) { @@ -764,37 +763,23 @@ - (MTRAttributeValueWaiter *)waitForAttributeValues:(NSDictionary(timeout * static_cast(NSEC_PER_SEC))), DISPATCH_TIME_FOREVER, - // Allow .5 seconds of leeway; should be plenty, in practice. - static_cast(0.5 * static_cast(NSEC_PER_SEC))); - - mtr_weakify(attributeWaiter); - mtr_weakify(self); - dispatch_source_set_event_handler(timerSource, ^{ - dispatch_source_cancel(timerSource); - mtr_strongify(self); - mtr_strongify(attributeWaiter); - if (self != nil && attributeWaiter != nil) { - [self _attributeWaitTimedOut:attributeWaiter]; - } - }); - - dispatch_resume(timerSource); + [attributeWaiter _startTimerWithTimeout:timeout]; return attributeWaiter; } @@ -814,35 +799,15 @@ - (void)_attributeValue:(MTRDeviceDataValueDictionary)value reportedForPath:(MTR } for (MTRAttributeValueWaiter * attributeValueWaiter in satisfiedWaiters) { - [self _notifyAttributeValueWaiter:attributeValueWaiter withError:nil]; + [self.attributeValueWaiters removeObject:attributeValueWaiter]; + [attributeValueWaiter _notifyWithError:nil]; } } -- (void)_attributeWaitTimedOut:(MTRAttributeValueWaiter *)attributeValueWaiter +- (void)_forgetAttributeWaiter:(MTRAttributeValueWaiter *)attributeValueWaiter { std::lock_guard lock(_lock); - [self _notifyAttributeValueWaiter:attributeValueWaiter withError:[MTRError errorForCHIPErrorCode:CHIP_ERROR_TIMEOUT]]; -} - -- (void)_attributeWaitCanceled:(MTRAttributeValueWaiter *)attributeValueWaiter -{ - std::lock_guard lock(_lock); - [self _doAttributeWaitCanceled:attributeValueWaiter]; -} - -- (void)_doAttributeWaitCanceled:(MTRAttributeValueWaiter *)attributeValueWaiter -{ - os_unfair_lock_assert_owner(&_lock); - - [self _notifyAttributeValueWaiter:attributeValueWaiter withError:[MTRError errorForCHIPErrorCode:CHIP_ERROR_CANCELLED]]; -} - -- (void)_notifyAttributeValueWaiter:(MTRAttributeValueWaiter *)attributeValueWaiter withError:(NSError * _Nullable)error -{ - os_unfair_lock_assert_owner(&_lock); - [self.attributeValueWaiters removeObject:attributeValueWaiter]; - [attributeValueWaiter _notifyWithError:error]; } - (void)_cancelAllAttributeValueWaiters @@ -852,7 +817,7 @@ - (void)_cancelAllAttributeValueWaiters auto * attributeValueWaiters = self.attributeValueWaiters; self.attributeValueWaiters = nil; for (MTRAttributeValueWaiter * attributeValueWaiter in attributeValueWaiters) { - [self _doAttributeWaitCanceled:attributeValueWaiter]; + [attributeValueWaiter _notifyCancellation]; } } diff --git a/src/darwin/Framework/CHIP/MTRDevice_Internal.h b/src/darwin/Framework/CHIP/MTRDevice_Internal.h index ccd9dbebc8f609..8db681d4802e60 100644 --- a/src/darwin/Framework/CHIP/MTRDevice_Internal.h +++ b/src/darwin/Framework/CHIP/MTRDevice_Internal.h @@ -176,7 +176,7 @@ MTR_DIRECT_MEMBERS // expected value for the relevant attribute. - (void)_attributeValue:(MTRDeviceDataValueDictionary)value reportedForPath:(MTRAttributePath *)path; -- (void)_attributeWaitCanceled:(MTRAttributeValueWaiter *)attributeValueWaiter; +- (void)_forgetAttributeWaiter:(MTRAttributeValueWaiter *)attributeValueWaiter; @end From e09abaec3147a9a1b6024d5a1853ec6dd135c8e3 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Thu, 14 Nov 2024 19:12:07 -0800 Subject: [PATCH 06/27] Do not use reverse commissioning to pair test server (#36490) --- src/python_testing/TC_MCORE_FS_1_3.py | 95 ++++++++++----------------- 1 file changed, 35 insertions(+), 60 deletions(-) diff --git a/src/python_testing/TC_MCORE_FS_1_3.py b/src/python_testing/TC_MCORE_FS_1_3.py index 2ac1556199a0c7..4b732a1b3a8995 100644 --- a/src/python_testing/TC_MCORE_FS_1_3.py +++ b/src/python_testing/TC_MCORE_FS_1_3.py @@ -34,7 +34,7 @@ # --commissioning-method on-network # --discriminator 1234 # --passcode 20202021 -# --string-arg th_server_no_uid_app_path:${LIGHTING_APP_NO_UNIQUE_ID} +# --string-arg th_server_no_uid_app_path:${LIGHTING_APP_NO_UNIQUE_ID} dut_fsa_stdin_pipe:dut-fsa-stdin # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # factory-reset: true @@ -81,6 +81,13 @@ def setup_class(self): self.storage = tempfile.TemporaryDirectory(prefix=self.__class__.__name__) logging.info("Temporary storage directory: %s", self.storage.name) + if self.is_pics_sdk_ci_only: + # Get the named pipe path for the DUT_FSA app input from the user params. + dut_fsa_stdin_pipe = self.user_params.get("dut_fsa_stdin_pipe") + if not dut_fsa_stdin_pipe: + asserts.fail("CI setup requires --string-arg dut_fsa_stdin_pipe:") + self.dut_fsa_stdin = open(dut_fsa_stdin_pipe, "w") + self.th_server_port = 5544 self.th_server_discriminator = random.randint(0, 4095) self.th_server_passcode = 20202021 @@ -111,60 +118,6 @@ def steps_TC_MCORE_FS_1_3(self) -> list[TestStep]: "TH verifies a value is visible for the UniqueID from the DUT_FSA's Bridged Device Basic Information Cluster."), ] - async def commission_via_commissioner_control(self, controller_node_id: int, device_node_id: int, endpoint_id: int): - """Commission device_node_id to controller_node_id using CommissionerControl cluster.""" - - request_id = random.randint(0, 0xFFFFFFFFFFFFFFFF) - - vendor_id = await self.read_single_attribute_check_success( - node_id=device_node_id, - cluster=Clusters.BasicInformation, - attribute=Clusters.BasicInformation.Attributes.VendorID, - ) - - product_id = await self.read_single_attribute_check_success( - node_id=device_node_id, - cluster=Clusters.BasicInformation, - attribute=Clusters.BasicInformation.Attributes.ProductID, - ) - - await self.send_single_cmd( - node_id=controller_node_id, - endpoint=endpoint_id, - cmd=Clusters.CommissionerControl.Commands.RequestCommissioningApproval( - requestID=request_id, - vendorID=vendor_id, - productID=product_id, - ), - ) - - if not self.is_pics_sdk_ci_only: - self.wait_for_user_input("Approve Commissioning Approval Request on DUT using manufacturer specified mechanism") - - resp = await self.send_single_cmd( - node_id=controller_node_id, - endpoint=endpoint_id, - cmd=Clusters.CommissionerControl.Commands.CommissionNode( - requestID=request_id, - responseTimeoutSeconds=30, - ), - ) - - asserts.assert_equal(type(resp), Clusters.CommissionerControl.Commands.ReverseOpenCommissioningWindow, - "Incorrect response type") - - await self.send_single_cmd( - node_id=device_node_id, - cmd=Clusters.AdministratorCommissioning.Commands.OpenCommissioningWindow( - commissioningTimeout=3*60, - PAKEPasscodeVerifier=resp.PAKEPasscodeVerifier, - discriminator=resp.discriminator, - iterations=resp.iterations, - salt=resp.salt, - ), - timedRequestTimeoutMs=5000, - ) - @async_test_body async def test_TC_MCORE_FS_1_3(self): @@ -218,13 +171,35 @@ async def test_TC_MCORE_FS_1_3(self): asserts.assert_not_equal(aggregator_endpoint, 0, "Invalid aggregator endpoint. Cannot proceed with commissioning.") - await self.commission_via_commissioner_control( - controller_node_id=self.dut_node_id, - device_node_id=th_server_th_node_id, - endpoint_id=aggregator_endpoint) + # Open commissioning window on TH_SERVER_NO_UID. + discriminator = random.randint(0, 4095) + params = await self.default_controller.OpenCommissioningWindow( + nodeid=th_server_th_node_id, + option=self.default_controller.CommissioningWindowPasscode.kTokenWithRandomPin, + discriminator=discriminator, + iteration=10000, + timeout=600) + + # Commissioning TH_SERVER_NO_UID to DUT_FSA fabric. + if not self.is_pics_sdk_ci_only: + self.wait_for_user_input( + f"Commission TH_SERVER_NO_UID on DUT using manufacturer specified mechanism.\n" + f"Use the following parameters:\n" + f"- discriminator: {discriminator}\n" + f"- setupPinCode: {params.setupPinCode}\n" + f"- setupQRCode: {params.setupQRCode}\n" + f"- setupManualCode: {params.setupManualCode}\n" + f"If using FabricSync Admin, you may type:\n" + f">>> pairing onnetwork {params.setupPinCode}") + else: + self.dut_fsa_stdin.write( + f"pairing onnetwork 10 {params.setupPinCode}\n") + self.dut_fsa_stdin.flush() + # Wait for the commissioning to complete. + await asyncio.sleep(5) # Wait for the device to appear on the DUT_FSA_BRIDGE. - await asyncio.sleep(2 if self.is_pics_sdk_ci_only else 30) + await asyncio.sleep(1) # Get the list of endpoints on the DUT_FSA_BRIDGE after adding the TH_SERVER_NO_UID. dut_fsa_bridge_endpoints_new = set(await self.read_single_attribute_check_success( From 57489d1a4df3c58f99c5ef1cd8ba6256ff31cab6 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Thu, 14 Nov 2024 19:13:09 -0800 Subject: [PATCH 07/27] [Fabric-Sync] Port sync-device command from fabric-admin (#36507) --- examples/fabric-sync/admin/DeviceManager.cpp | 72 +++++++++++ examples/fabric-sync/admin/DeviceManager.h | 38 ++++++ examples/fabric-sync/admin/FabricAdmin.cpp | 21 ++++ examples/fabric-sync/admin/FabricAdmin.h | 3 + .../bridge/include/FabricAdminDelegate.h | 12 ++ examples/fabric-sync/shell/BUILD.gn | 2 + examples/fabric-sync/shell/ShellCommands.cpp | 38 +++++- .../fabric-sync/shell/SyncDeviceCommand.cpp | 112 ++++++++++++++++++ .../fabric-sync/shell/SyncDeviceCommand.h | 39 ++++++ 9 files changed, 335 insertions(+), 2 deletions(-) create mode 100644 examples/fabric-sync/shell/SyncDeviceCommand.cpp create mode 100644 examples/fabric-sync/shell/SyncDeviceCommand.h diff --git a/examples/fabric-sync/admin/DeviceManager.cpp b/examples/fabric-sync/admin/DeviceManager.cpp index 6dfdad1213bc68..69aa0a583f7273 100644 --- a/examples/fabric-sync/admin/DeviceManager.cpp +++ b/examples/fabric-sync/admin/DeviceManager.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -33,6 +34,9 @@ namespace admin { namespace { constexpr EndpointId kAggregatorEndpointId = 1; +constexpr uint16_t kWindowTimeout = 300; +constexpr uint16_t kIteration = 1000; +constexpr uint16_t kMaxDiscriminatorLength = 4095; } // namespace @@ -75,6 +79,13 @@ void DeviceManager::SetRemoteBridgeNodeId(chip::NodeId nodeId) } } +void DeviceManager::AddSyncedDevice(const SyncedDevice & device) +{ + mSyncedDevices.insert(device); + ChipLogProgress(NotSpecified, "Added synced device: NodeId:" ChipLogFormatX64 ", EndpointId %u", + ChipLogValueX64(device.GetNodeId()), device.GetEndpointId()); +} + SyncedDevice * DeviceManager::FindDeviceByEndpoint(EndpointId endpointId) { for (auto & device : mSyncedDevices) @@ -99,6 +110,27 @@ SyncedDevice * DeviceManager::FindDeviceByNode(NodeId nodeId) return nullptr; } +void DeviceManager::RemoveSyncedDevice(chip::ScopedNodeId scopedNodeId) +{ + NodeId nodeId = scopedNodeId.GetNodeId(); + + if (bridge::FabricBridge::Instance().RemoveSynchronizedDevice(scopedNodeId) != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to remove Node ID:" ChipLogFormatX64, ChipLogValueX64(nodeId)); + } + + SyncedDevice * device = FindDeviceByNode(nodeId); + if (device == nullptr) + { + ChipLogProgress(NotSpecified, "No device found with NodeId:" ChipLogFormatX64, ChipLogValueX64(nodeId)); + return; + } + + mSyncedDevices.erase(*device); + ChipLogProgress(NotSpecified, "Removed synced device: NodeId:" ChipLogFormatX64 ", EndpointId %u", + ChipLogValueX64(device->GetNodeId()), device->GetEndpointId()); +} + void DeviceManager::OpenLocalBridgeCommissioningWindow(uint32_t iterations, uint16_t commissioningTimeoutSec, uint16_t discriminator, const ByteSpan & salt, const ByteSpan & verifier) { @@ -132,6 +164,46 @@ void DeviceManager::OpenLocalBridgeCommissioningWindow(uint32_t iterations, uint } } +void DeviceManager::OpenDeviceCommissioningWindow(ScopedNodeId scopedNodeId, uint32_t iterations, uint16_t commissioningTimeoutSec, + uint16_t discriminator, const ByteSpan & salt, const ByteSpan & verifier) +{ + // PairingManager isn't currently capable of OpenCommissioningWindow on a device of a fabric that it doesn't have + // the controller for. Currently no implementation need this functionality, but should they need it they will hit + // the verify or die below and it will be the responsiblity of whoever requires that functionality to implement. + VerifyOrDie(PairingManager::Instance().CurrentCommissioner().GetFabricIndex() == scopedNodeId.GetFabricIndex()); + ChipLogProgress(NotSpecified, "Opening commissioning window for Node ID: " ChipLogFormatX64, + ChipLogValueX64(scopedNodeId.GetNodeId())); + + // Open the commissioning window of a device within its own fabric. + CHIP_ERROR err = PairingManager::Instance().OpenCommissioningWindow( + scopedNodeId.GetNodeId(), kRootEndpointId, commissioningTimeoutSec, iterations, discriminator, salt, verifier); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to open commissioning window: %s", ErrorStr(err)); + } +} + +void DeviceManager::OpenRemoteDeviceCommissioningWindow(EndpointId remoteEndpointId) +{ + // Open the commissioning window of a device from another fabric via its fabric bridge. + // This method constructs and sends a command to open the commissioning window for a device + // that is part of a different fabric, accessed through a fabric bridge. + + // Use random discriminator to have less chance of collision. + uint16_t discriminator = + Crypto::GetRandU16() % (kMaxDiscriminatorLength + 1); // Include the upper limit kMaxDiscriminatorLength + + ByteSpan emptySalt; + ByteSpan emptyVerifier; + + CHIP_ERROR err = PairingManager::Instance().OpenCommissioningWindow(mRemoteBridgeNodeId, remoteEndpointId, kWindowTimeout, + kIteration, discriminator, emptySalt, emptyVerifier); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to open commissioning window: %s", ErrorStr(err)); + } +} + CHIP_ERROR DeviceManager::PairRemoteFabricBridge(NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp, uint16_t deviceRemotePort) { diff --git a/examples/fabric-sync/admin/DeviceManager.h b/examples/fabric-sync/admin/DeviceManager.h index e114a62748549a..9afb1eec7d033f 100644 --- a/examples/fabric-sync/admin/DeviceManager.h +++ b/examples/fabric-sync/admin/DeviceManager.h @@ -72,6 +72,10 @@ class DeviceManager bool IsFabricSyncReady() const { return mRemoteBridgeNodeId != chip::kUndefinedNodeId; } + void AddSyncedDevice(const SyncedDevice & device); + + void RemoveSyncedDevice(chip::ScopedNodeId scopedNodeId); + /** * @brief Determines whether a given nodeId corresponds to the remote bridge device. * @@ -97,6 +101,40 @@ class DeviceManager void OpenLocalBridgeCommissioningWindow(uint32_t iterations, uint16_t commissioningTimeoutSec, uint16_t discriminator, const chip::ByteSpan & salt, const chip::ByteSpan & verifier); + /** + * @brief Open the commissioning window for a specific device within its own fabric. + * + * This function initiates the process to open the commissioning window for a device identified by the given node ID. + * + * @param scopedNodeId The scoped node ID of the device that should open the commissioning window. + * @param iterations The number of PBKDF (Password-Based Key Derivation Function) iterations to use + * for deriving the PAKE (Password Authenticated Key Exchange) verifier. + * @param commissioningTimeoutSec The time in seconds before the commissioning window closes. This value determines + * how long the commissioning window remains open for incoming connections. + * @param discriminator The device-specific discriminator, determined during commissioning, which helps + * to uniquely identify the device among others. + * @param salt The salt used in the cryptographic operations for commissioning. + * @param verifier The PAKE verifier used to authenticate the commissioning process. + * + */ + void OpenDeviceCommissioningWindow(chip::ScopedNodeId scopedNodeId, uint32_t iterations, uint16_t commissioningTimeoutSec, + uint16_t discriminator, const chip::ByteSpan & salt, const chip::ByteSpan & verifier); + + /** + * @brief Open the commissioning window of a device from another fabric via its fabric bridge. + * + * This function initiates the process to open the commissioning window for a device that belongs to another + * fabric, accessed through a fabric bridge. + * + * @param remoteEndpointId The endpoint ID of the remote device that should open the commissioning window. + * This endpoint is associated with the device in the other fabric, accessed via the + * fabric bridge. + * + * @note This function is used when the device to be commissioned is part of a different fabric and must be + * accessed through an intermediary fabric bridge. + */ + void OpenRemoteDeviceCommissioningWindow(chip::EndpointId remoteEndpointId); + /** * @brief Pair a remote fabric bridge with a given node ID. * diff --git a/examples/fabric-sync/admin/FabricAdmin.cpp b/examples/fabric-sync/admin/FabricAdmin.cpp index 65b5a5a8e8fc30..4e170ce78db043 100644 --- a/examples/fabric-sync/admin/FabricAdmin.cpp +++ b/examples/fabric-sync/admin/FabricAdmin.cpp @@ -38,6 +38,27 @@ FabricAdmin & FabricAdmin::Instance() return sInstance; } +CHIP_ERROR FabricAdmin::OpenCommissioningWindow(Controller::CommissioningWindowVerifierParams params, FabricIndex fabricIndex) +{ + ScopedNodeId scopedNodeId(params.GetNodeId(), fabricIndex); + uint32_t iterations = params.GetIteration(); + uint16_t discriminator = params.GetDiscriminator(); + uint16_t commissioningTimeoutSec = static_cast(params.GetTimeout().count()); + + // Log request details for debugging purposes + ChipLogProgress(NotSpecified, + "Received OpenCommissioningWindow request: NodeId " ChipLogFormatX64 + ", Timeout: %u, Iterations: %u, Discriminator: %u", + ChipLogValueX64(scopedNodeId.GetNodeId()), commissioningTimeoutSec, iterations, discriminator); + + // Open the device commissioning window with provided salt and verifier data + DeviceManager::Instance().OpenDeviceCommissioningWindow(scopedNodeId, iterations, commissioningTimeoutSec, discriminator, + ByteSpan(params.GetSalt().data(), params.GetSalt().size()), + ByteSpan(params.GetVerifier().data(), params.GetVerifier().size())); + + return CHIP_NO_ERROR; +} + CHIP_ERROR FabricAdmin::CommissionRemoteBridge(Controller::CommissioningWindowPasscodeParams params, VendorId vendorId, uint16_t productId) { diff --git a/examples/fabric-sync/admin/FabricAdmin.h b/examples/fabric-sync/admin/FabricAdmin.h index 1219e594fa8c5f..bec98dc4140183 100644 --- a/examples/fabric-sync/admin/FabricAdmin.h +++ b/examples/fabric-sync/admin/FabricAdmin.h @@ -42,6 +42,9 @@ class FabricAdmin final : public bridge::FabricAdminDelegate public: static FabricAdmin & Instance(); + CHIP_ERROR OpenCommissioningWindow(chip::Controller::CommissioningWindowVerifierParams params, + chip::FabricIndex fabricIndex) override; + CHIP_ERROR CommissionRemoteBridge(chip::Controller::CommissioningWindowPasscodeParams params, chip::VendorId vendorId, uint16_t productId) override; diff --git a/examples/fabric-sync/bridge/include/FabricAdminDelegate.h b/examples/fabric-sync/bridge/include/FabricAdminDelegate.h index 8b67ffd5b29ed7..1637c5294fb7a7 100644 --- a/examples/fabric-sync/bridge/include/FabricAdminDelegate.h +++ b/examples/fabric-sync/bridge/include/FabricAdminDelegate.h @@ -30,6 +30,18 @@ class FabricAdminDelegate public: virtual ~FabricAdminDelegate() = default; + /** + * Opens a commissioning window for a specified node using pre-computed PAKE passcode verifier. + * + * @param params Params for opening the commissioning window using verifier. + * @return CHIP_ERROR An error code indicating the success or failure of the operation. + * - CHIP_NO_ERROR: The RPC command was successfully sent. + * - CHIP_ERROR_BUSY: Another commissioning window is currently in progress. + * - CHIP_ERROR_INTERNAL: An internal error occurred. + */ + virtual CHIP_ERROR OpenCommissioningWindow(chip::Controller::CommissioningWindowVerifierParams params, + chip::FabricIndex fabricIndex) = 0; + /** * Reverse commission a bridge using the specified parameters. * diff --git a/examples/fabric-sync/shell/BUILD.gn b/examples/fabric-sync/shell/BUILD.gn index 436f8b5160e66c..3aa56122254a4a 100644 --- a/examples/fabric-sync/shell/BUILD.gn +++ b/examples/fabric-sync/shell/BUILD.gn @@ -39,6 +39,8 @@ source_set("shell") { "RemoveDeviceCommand.h", "ShellCommands.cpp", "ShellCommands.h", + "SyncDeviceCommand.cpp", + "SyncDeviceCommand.h", ] deps = [ diff --git a/examples/fabric-sync/shell/ShellCommands.cpp b/examples/fabric-sync/shell/ShellCommands.cpp index 3bab442aa5fc47..4923823481635a 100644 --- a/examples/fabric-sync/shell/ShellCommands.cpp +++ b/examples/fabric-sync/shell/ShellCommands.cpp @@ -19,6 +19,7 @@ #include "AddDeviceCommand.h" #include "RemoveBridgeCommand.h" #include "RemoveDeviceCommand.h" +#include "SyncDeviceCommand.h" #include #include @@ -129,11 +130,11 @@ static CHIP_ERROR HandleAddDeviceCommand(int argc, char ** argv) // Parse arguments chip::NodeId nodeId = static_cast(strtoull(argv[1], nullptr, 10)); - uint32_t setupPINCode = static_cast(strtoul(argv[2], nullptr, 10)); + uint32_t payload = static_cast(strtoul(argv[2], nullptr, 10)); const char * remoteAddr = argv[3]; uint16_t remotePort = static_cast(strtoul(argv[4], nullptr, 10)); - auto command = std::make_unique(nodeId, setupPINCode, remoteAddr, remotePort); + auto command = std::make_unique(nodeId, payload, remoteAddr, remotePort); CHIP_ERROR result = command->RunCommand(); if (result == CHIP_NO_ERROR) @@ -173,6 +174,35 @@ static CHIP_ERROR HandleRemoveDeviceCommand(int argc, char ** argv) return result; } +static CHIP_ERROR HandleSyncDeviceCommand(int argc, char ** argv) +{ + if (argc != 2) + { + fprintf(stderr, "Invalid arguments. Usage: app sync-device\n"); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + // Check if there is already an active command + if (commands::CommandRegistry::Instance().IsCommandActive()) + { + fprintf(stderr, "Another command is currently active. Please wait until it completes.\n"); + return CHIP_ERROR_BUSY; + } + + // Parse arguments + chip::EndpointId endpointId = static_cast(strtoul(argv[1], nullptr, 10)); + + auto command = std::make_unique(endpointId); + + CHIP_ERROR result = command->RunCommand(); + if (result == CHIP_NO_ERROR) + { + commands::CommandRegistry::Instance().SetActiveCommand(std::move(command)); + } + + return result; +} + static CHIP_ERROR AppPlatformHandler(int argc, char ** argv) { CHIP_ERROR error = CHIP_NO_ERROR; @@ -201,6 +231,10 @@ static CHIP_ERROR AppPlatformHandler(int argc, char ** argv) { return HandleRemoveDeviceCommand(argc, argv); } + else if (strcmp(argv[0], "sync-device") == 0) + { + return HandleSyncDeviceCommand(argc, argv); + } else { return CHIP_ERROR_INVALID_ARGUMENT; diff --git a/examples/fabric-sync/shell/SyncDeviceCommand.cpp b/examples/fabric-sync/shell/SyncDeviceCommand.cpp new file mode 100644 index 00000000000000..871c8d68feedb7 --- /dev/null +++ b/examples/fabric-sync/shell/SyncDeviceCommand.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2024 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 "SyncDeviceCommand.h" + +#include +#include +#include + +using namespace ::chip; + +namespace { + +// Constants +constexpr uint32_t kCommissionPrepareTimeMs = 500; + +} // namespace + +namespace commands { + +SyncDeviceCommand::SyncDeviceCommand(EndpointId remoteEndpointId) : mRemoteEndpointId(remoteEndpointId) {} + +void SyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_ERROR err, SetupPayload payload) +{ + ChipLogProgress(NotSpecified, "FabricSyncDeviceCommand::OnCommissioningWindowOpened"); + + if (err == CHIP_NO_ERROR) + { + char payloadBuffer[admin::kMaxManualCodeLength + 1]; + MutableCharSpan manualCode(payloadBuffer); + CHIP_ERROR error = ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(manualCode); + if (error == CHIP_NO_ERROR) + { + NodeId nodeId = admin::DeviceManager::Instance().GetNextAvailableNodeId(); + + admin::PairingManager::Instance().SetPairingDelegate(this); + mAssignedNodeId = nodeId; + + usleep(kCommissionPrepareTimeMs * 1000); + + admin::DeviceManager::Instance().PairRemoteDevice(nodeId, payloadBuffer); + } + else + { + ChipLogError(NotSpecified, "Unable to generate manual code for setup payload: %" CHIP_ERROR_FORMAT, error.Format()); + } + } + else + { + ChipLogError(NotSpecified, + "Failed to open synced device (0x:" ChipLogFormatX64 ") commissioning window: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + } +} + +void SyncDeviceCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) +{ + if (mAssignedNodeId != deviceId) + { + // Ignore if the deviceId does not match the mAssignedNodeId. + // This scenario should not occur because no other device should be commissioned during the fabric sync process. + return; + } + + if (err == CHIP_NO_ERROR) + { + admin::DeviceManager::Instance().AddSyncedDevice(admin::SyncedDevice(mAssignedNodeId, mRemoteEndpointId)); + } + else + { + ChipLogError(NotSpecified, "Failed to pair synced device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + } + + CommandRegistry::Instance().ResetActiveCommand(); +} + +CHIP_ERROR SyncDeviceCommand::RunCommand() +{ + if (!admin::DeviceManager::Instance().IsFabricSyncReady()) + { + // print to console + Shell::streamer_t * sout = Shell::streamer_get(); + Shell::streamer_printf(sout, "Remote Fabric Bridge has already been configured.\n"); + + return CHIP_ERROR_INCORRECT_STATE; + } + + ChipLogProgress(NotSpecified, "Running SyncDeviceCommand with EndpointId: %u", mRemoteEndpointId); + + admin::PairingManager::Instance().SetOpenCommissioningWindowDelegate(this); + admin::DeviceManager::Instance().OpenRemoteDeviceCommissioningWindow(mRemoteEndpointId); + + return CHIP_NO_ERROR; +} + +} // namespace commands diff --git a/examples/fabric-sync/shell/SyncDeviceCommand.h b/examples/fabric-sync/shell/SyncDeviceCommand.h new file mode 100644 index 00000000000000..270f57d8893f03 --- /dev/null +++ b/examples/fabric-sync/shell/SyncDeviceCommand.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 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 + +namespace commands { + +class SyncDeviceCommand : public Command, public admin::CommissioningWindowDelegate, public admin::PairingDelegate +{ +public: + SyncDeviceCommand(chip::EndpointId remoteEndpointId); + void OnCommissioningWindowOpened(chip::NodeId deviceId, CHIP_ERROR status, chip::SetupPayload payload) override; + void OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR err) override; + CHIP_ERROR RunCommand() override; + +private: + chip::EndpointId mRemoteEndpointId = chip::kInvalidEndpointId; + chip::NodeId mAssignedNodeId = chip::kUndefinedNodeId; +}; + +} // namespace commands From c0dbaaffd0a93bdf73942b91aadff9b263c4567e Mon Sep 17 00:00:00 2001 From: Sergio Soares Date: Fri, 15 Nov 2024 07:30:54 -0500 Subject: [PATCH 08/27] fan_control_server: Fix circular callback issue (#36489) * fan_control_server: Fix circular callback issue This PR fixes a circular callback bug in fan control server using flags when updating SpeedSetting and PercentSetting. Before this change, a PercentSetting write to 25% would end up circling back to 30% as shown: ``` [MatterTest] 11-12 19:16:40.792 INFO @@@ WRITE PercentSetting to 25 [MatterTest] 11-12 19:16:40.801 INFO @@@ ATTRIB: EP1/FanControl/SpeedSetting: 3 [MatterTest] 11-12 19:16:40.802 INFO @@@ ATTRIB: EP1/FanControl/SpeedCurrent: 3 [MatterTest] 11-12 19:16:40.802 INFO @@@ ATTRIB: EP1/FanControl/PercentSetting: 30 [MatterTest] 11-12 19:16:40.802 INFO @@@ ATTRIB: EP1/FanControl/PercentCurrent: 30 ``` Now it behaves as expected: ``` [MatterTest] 11-13 18:54:27.961 INFO @@@ WRITE PercentSetting to 25 [MatterTest] 11-13 18:54:27.970 INFO @@@ ATTRIB: EP1/FanControl/SpeedSetting: 3 [MatterTest] 11-13 18:54:27.970 INFO @@@ ATTRIB: EP1/FanControl/SpeedCurrent: 3 [MatterTest] 11-13 18:54:27.970 INFO @@@ ATTRIB: EP1/FanControl/PercentSetting: 25 [MatterTest] 11-13 18:54:27.971 INFO @@@ ATTRIB: EP1/FanControl/PercentCurrent: 25 ``` Co-authored-by: lpbeliveau-silabs * Addressed review suggestions --------- Co-authored-by: lpbeliveau-silabs --- .../fan-control-server/fan-control-server.cpp | 65 +++++++++---------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/src/app/clusters/fan-control-server/fan-control-server.cpp b/src/app/clusters/fan-control-server/fan-control-server.cpp index 46f4c6d7c0bb70..7ece1a1b575a24 100644 --- a/src/app/clusters/fan-control-server/fan-control-server.cpp +++ b/src/app/clusters/fan-control-server/fan-control-server.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -85,6 +86,10 @@ namespace { // Indicates if the write operation is from the cluster server itself bool gWriteFromClusterLogic = false; +// Avoid circular callback calls when adjusting SpeedSetting and PercentSetting together. +ScopedChangeOnly gSpeedWriteInProgress(false); +ScopedChangeOnly gPercentWriteInProgress(false); + Status SetFanModeToOff(EndpointId endpointId) { FanModeEnum currentFanMode; @@ -185,6 +190,10 @@ MatterFanControlClusterServerPreAttributeChangedCallback(const ConcreteAttribute break; } case SpeedSetting::Id: { + if (gSpeedWriteInProgress) + { + return Status::WriteIgnored; + } if (SupportsMultiSpeed(attributePath.mEndpointId)) { // Check if the SpeedSetting is null. @@ -224,6 +233,10 @@ MatterFanControlClusterServerPreAttributeChangedCallback(const ConcreteAttribute break; } case PercentSetting::Id: { + if (gPercentWriteInProgress) + { + return Status::WriteIgnored; + } // Check if the PercentSetting is null. if (NumericAttributeTraits::IsNullValue(*value)) { @@ -362,12 +375,18 @@ void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAt DataModel::Nullable percentSetting; Status status = PercentSetting::Get(attributePath.mEndpointId, percentSetting); VerifyOrReturn(Status::Success == status && !percentSetting.IsNull()); + uint8_t speedMax; + status = SpeedMax::Get(attributePath.mEndpointId, &speedMax); + VerifyOrReturn(Status::Success == status, + ChipLogError(Zcl, "Failed to get SpeedMax with error: 0x%02x", to_underlying(status))); + // Avoid circular callback calls + ScopedChange PercentWriteInProgress(gPercentWriteInProgress, true); // If PercentSetting is set to 0, the server SHALL set the FanMode attribute value to Off. if (percentSetting.Value() == 0) { status = SetFanModeToOff(attributePath.mEndpointId); - VerifyOrReturn(Status::Success == status, + VerifyOrReturn(status == Status::Success, ChipLogError(Zcl, "Failed to set FanMode to off with error: 0x%02x", to_underlying(status))); } @@ -375,26 +394,13 @@ void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAt { // Adjust SpeedSetting from a percent value change for PercentSetting // speed = ceil( SpeedMax * (percent * 0.01) ) - uint8_t speedMax; - status = SpeedMax::Get(attributePath.mEndpointId, &speedMax); - VerifyOrReturn(Status::Success == status, - ChipLogError(Zcl, "Failed to get SpeedMax with error: 0x%02x", to_underlying(status))); - - DataModel::Nullable currentSpeedSetting; - status = SpeedSetting::Get(attributePath.mEndpointId, currentSpeedSetting); - VerifyOrReturn(Status::Success == status, - ChipLogError(Zcl, "Failed to get SpeedSetting with error: 0x%02x", to_underlying(status))); - uint16_t percent = percentSetting.Value(); // Plus 99 then integer divide by 100 instead of multiplying 0.01 to avoid floating point precision error uint8_t speedSetting = static_cast((speedMax * percent + 99) / 100); - if (currentSpeedSetting.IsNull() || speedSetting != currentSpeedSetting.Value()) - { - status = SpeedSetting::Set(attributePath.mEndpointId, speedSetting); - VerifyOrReturn(Status::Success == status, - ChipLogError(Zcl, "Failed to set SpeedSetting with error: 0x%02x", to_underlying(status))); - } + status = SpeedSetting::Set(attributePath.mEndpointId, speedSetting); + VerifyOrDo(Status::Success == status, + ChipLogError(Zcl, "Failed to set SpeedSetting with error: 0x%02x", to_underlying(status))); } break; } @@ -404,7 +410,13 @@ void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAt DataModel::Nullable speedSetting; Status status = SpeedSetting::Get(attributePath.mEndpointId, speedSetting); VerifyOrReturn(Status::Success == status && !speedSetting.IsNull()); + uint8_t speedMax; + status = SpeedMax::Get(attributePath.mEndpointId, &speedMax); + VerifyOrReturn(Status::Success == status, + ChipLogError(Zcl, "Failed to get SpeedMax with error: 0x%02x", to_underlying(status))); + // Avoid circular callback calls + ScopedChange SpeedWriteInProgress(gSpeedWriteInProgress, true); // If SpeedSetting is set to 0, the server SHALL set the FanMode attribute value to Off. if (speedSetting.Value() == 0) { @@ -415,25 +427,12 @@ void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAt // Adjust PercentSetting from a speed value change for SpeedSetting // percent = floor( speed/SpeedMax * 100 ) - uint8_t speedMax; - status = SpeedMax::Get(attributePath.mEndpointId, &speedMax); - VerifyOrReturn(Status::Success == status, - ChipLogError(Zcl, "Failed to get SpeedMax with error: 0x%02x", to_underlying(status))); - - DataModel::Nullable currentPercentSetting; - status = PercentSetting::Get(attributePath.mEndpointId, currentPercentSetting); - VerifyOrReturn(Status::Success == status, - ChipLogError(Zcl, "Failed to get PercentSetting with error: 0x%02x", to_underlying(status))); - float speed = speedSetting.Value(); Percent percentSetting = static_cast(speed / speedMax * 100); - if (currentPercentSetting.IsNull() || percentSetting != currentPercentSetting.Value()) - { - status = PercentSetting::Set(attributePath.mEndpointId, percentSetting); - VerifyOrReturn(Status::Success == status, - ChipLogError(Zcl, "Failed to set PercentSetting with error: 0x%02x", to_underlying(status))); - } + status = PercentSetting::Set(attributePath.mEndpointId, percentSetting); + VerifyOrDo(Status::Success == status, + ChipLogError(Zcl, "Failed to set PercentSetting with error: 0x%02x", to_underlying(status))); } break; } From 503c9d0b10051c4412d48479070bd572add51cad Mon Sep 17 00:00:00 2001 From: Alex Tsitsiura Date: Fri, 15 Nov 2024 14:36:07 +0200 Subject: [PATCH 09/27] [Telink] fix stack sizes to avoid 90% usage (#36485) * [Telink] Add temporarry THREAD_ANALYZER to check stack sizes during crash * [Telink] fix configs * [Telink] Increase OpenThread stack (98% usage during OTA) * [Telink] Set INFO as default MCUboot log level * [Telink] define CHIP_TASK_STACK_SIZE from one place * [Telink] Add thread-analyzer as target build * [Telink] decrise BOOT_MAX_IMG_SECTORS * [Telink] temporary enable THREAD_ANALYZER by default * [Telink] Increase stack sizes to avoid 90+% usage * [Telink] increase more * [Telink] set THREAD_ANALYZER=n by default --- config/telink/app/bootloader.conf | 5 ++-- config/telink/chip-module/Kconfig | 1 + config/telink/chip-module/Kconfig.defaults | 25 ++++++++++++++----- scripts/build/build/targets.py | 1 + scripts/build/builders/telink.py | 5 ++++ .../build/testdata/all_targets_linux_x64.txt | 2 +- 6 files changed, 30 insertions(+), 9 deletions(-) diff --git a/config/telink/app/bootloader.conf b/config/telink/app/bootloader.conf index 52937e1649e9af..0ffacc8c0b052b 100644 --- a/config/telink/app/bootloader.conf +++ b/config/telink/app/bootloader.conf @@ -30,7 +30,8 @@ CONFIG_BOOT_SWAP_USING_SCRATCH=n CONFIG_BOOT_VALIDATE_SLOT0=y # Maximum number of image sectors supported by the bootloader. -CONFIG_BOOT_MAX_IMG_SECTORS=4096 +# Maximum signed image size: 512 * 4096 = 2M Bytes +CONFIG_BOOT_MAX_IMG_SECTORS=512 # Sets log level for modules which don't specify it explicitly. # When set to 0 it means log will not be activated for those modules. @@ -40,4 +41,4 @@ CONFIG_BOOT_MAX_IMG_SECTORS=4096 # - 2 WARNING, default to write LOG_LEVEL_WRN # - 3 INFO, default to write LOG_LEVEL_INFO # - 4 DEBUG, default to write LOG_LEVEL_DBG -CONFIG_LOG_DEFAULT_LEVEL=1 +CONFIG_LOG_DEFAULT_LEVEL=3 diff --git a/config/telink/chip-module/Kconfig b/config/telink/chip-module/Kconfig index ee87af2bbe9731..b06c7c855922d8 100644 --- a/config/telink/chip-module/Kconfig +++ b/config/telink/chip-module/Kconfig @@ -246,6 +246,7 @@ config CHIP_ENABLE_POWER_ON_FACTORY_RESET config CHIP_TASK_STACK_SIZE int + default 4864 if PM default 8192 config CHIP_USE_MARS_SENSOR diff --git a/config/telink/chip-module/Kconfig.defaults b/config/telink/chip-module/Kconfig.defaults index d28d77d6cffd32..bb722e8a3ab8bc 100644 --- a/config/telink/chip-module/Kconfig.defaults +++ b/config/telink/chip-module/Kconfig.defaults @@ -71,7 +71,7 @@ config IDLE_STACK_SIZE default 512 if PM config ISR_STACK_SIZE - default 502 if PM + default 576 if PM config SYSTEM_WORKQUEUE_STACK_SIZE default 616 if PM @@ -154,7 +154,7 @@ config BT_DEVICE_NAME_GATT_WRITABLE default n config B9X_BLE_CTRL_THREAD_STACK_SIZE - default 576 + default 648 config B9X_BLE_CTRL_MASTER_MAX_NUM default 0 @@ -261,10 +261,10 @@ config CHIP_ENABLE_ICD_SUPPORT default y if CHIP_THREAD_DEVICE_ROLE_SLEEPY_END_DEVICE config OPENTHREAD_THREAD_STACK_SIZE - default 2178 if PM + default 2400 if PM config OPENTHREAD_RADIO_WORKQUEUE_STACK_SIZE - default 361 if PM + default 432 if PM default 608 config OPENTHREAD_SLAAC @@ -366,6 +366,9 @@ config CHIP_WIFI_CONNECTION_RECOVERY_JITTER a random jitter interval is added to it to avoid periodicity. The random jitter is selected within range [-JITTER; +JITTER]. +config NET_MGMT_EVENT_STACK_SIZE + default 1128 + endif # CHIP_WIFI config CHIP_ENABLE_PAIRING_AUTOSTART @@ -448,7 +451,17 @@ config PWM_SHELL config OPENTHREAD_SHELL default n -config CHIP_TASK_STACK_SIZE - default 4864 if PM +# Thread analyzer +config THREAD_ANALYZER + default n + select THREAD_ANALYZER_AUTO + +config THREAD_ANALYZER_AUTO_INTERVAL + default 5 + depends on THREAD_ANALYZER_AUTO + +config THREAD_ANALYZER_LOG_LEVEL + default 3 # info + depends on THREAD_ANALYZER endif diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index b36824bc481583..0f80756ec49208 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -801,6 +801,7 @@ def BuildTelinkTarget(): target.AppendModifier('mars', mars_board_config=True) target.AppendModifier('usb', usb_board_config=True) target.AppendModifier('compress-lzma', compress_lzma_config=True) + target.AppendModifier('thread-analyzer', thread_analyzer_config=True) return target diff --git a/scripts/build/builders/telink.py b/scripts/build/builders/telink.py index 644f4cdc08e23a..a4943007161f53 100644 --- a/scripts/build/builders/telink.py +++ b/scripts/build/builders/telink.py @@ -155,6 +155,7 @@ def __init__(self, mars_board_config: bool = False, usb_board_config: bool = False, compress_lzma_config: bool = False, + thread_analyzer_config: bool = False, ): super(TelinkBuilder, self).__init__(root, runner) self.app = app @@ -168,6 +169,7 @@ def __init__(self, self.mars_board_config = mars_board_config self.usb_board_config = usb_board_config self.compress_lzma_config = compress_lzma_config + self.thread_analyzer_config = thread_analyzer_config def get_cmd_prefixes(self): if not self._runner.dry_run: @@ -215,6 +217,9 @@ def generate(self): if self.compress_lzma_config: flags.append("-DCONFIG_COMPRESS_LZMA=y") + if self.thread_analyzer_config: + flags.append("-DCONFIG_THREAD_ANALYZER=y") + if self.options.pregen_dir: flags.append(f"-DCHIP_CODEGEN_PREGEN_DIR={shlex.quote(self.options.pregen_dir)}") diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt index f34f42b55e0584..c473de1aa1d814 100644 --- a/scripts/build/testdata/all_targets_linux_x64.txt +++ b/scripts/build/testdata/all_targets_linux_x64.txt @@ -22,5 +22,5 @@ nuttx-x64-light qpg-qpg6105-{lock,light,shell,persistent-storage,light-switch,thermostat}[-updateimage] stm32-stm32wb5mm-dk-light tizen-arm-{all-clusters,chip-tool,light,tests}[-no-ble][-no-thread][-no-wifi][-asan][-ubsan][-coverage][-with-ui] -telink-{tlsr9118bdk40d,tlsr9518adk80d,tlsr9528a,tlsr9528a_retention,tlsr9258a,tlsr9258a_retention}-{air-quality-sensor,all-clusters,all-clusters-minimal,bridge,contact-sensor,light,light-switch,lock,ota-requestor,pump,pump-controller,shell,smoke-co-alarm,temperature-measurement,thermostat,window-covering}[-ota][-dfu][-shell][-rpc][-factory-data][-4mb][-mars][-usb][-compress-lzma] +telink-{tlsr9118bdk40d,tlsr9518adk80d,tlsr9528a,tlsr9528a_retention,tlsr9258a,tlsr9258a_retention}-{air-quality-sensor,all-clusters,all-clusters-minimal,bridge,contact-sensor,light,light-switch,lock,ota-requestor,pump,pump-controller,shell,smoke-co-alarm,temperature-measurement,thermostat,window-covering}[-ota][-dfu][-shell][-rpc][-factory-data][-4mb][-mars][-usb][-compress-lzma][-thread-analyzer] openiotsdk-{shell,lock}[-mbedtls][-psa] From e019c0f3dc7e8a974d70ef02ce723075b379dcb0 Mon Sep 17 00:00:00 2001 From: dinabenamar <108664279+dinabenamar@users.noreply.github.com> Date: Fri, 15 Nov 2024 14:58:28 +0100 Subject: [PATCH 10/27] [NXP][platform][common] Remove unrequired config defines to use default values instead (#36497) Signed-off-by: Dina Benamar --- src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h b/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h index 1cdb0644590362..5d8825bc8a6e6d 100644 --- a/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h +++ b/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h @@ -38,9 +38,6 @@ #define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING CONFIG_CHIP_DEVICE_SOFTWARE_VERSION_STRING #define CHIP_DEVICE_CONFIG_TEST_MANUFACTURING_DATE CONFIG_CHIP_DEVICE_MANUFACTURING_DATE #define CHIP_DEVICE_CONFIG_DEVICE_TYPE CONFIG_CHIP_DEVICE_TYPE -#define CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT CONFIG_CHIP_DEVICE_SPAKE2_IT -#define CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT CONFIG_CHIP_DEVICE_SPAKE2_SALT -#define CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER CONFIG_CHIP_DEVICE_SPAKE2_TEST_VERIFIER #if !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR CONFIG_CHIP_DEVICE_DISCRIMINATOR From 9c505b3888b702f2b62a0a068e4efde8959bbe82 Mon Sep 17 00:00:00 2001 From: Mihai Ignat <50373067+mihai-ignat@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:17:28 +0200 Subject: [PATCH 11/27] [nxp][examples][rt1060] Update WiFi credentials setting in RT1060 readme (#36496) --- examples/all-clusters-app/nxp/rt/rt1060/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/all-clusters-app/nxp/rt/rt1060/README.md b/examples/all-clusters-app/nxp/rt/rt1060/README.md index 96822ff6eb2453..3ddcbd7c853f9d 100644 --- a/examples/all-clusters-app/nxp/rt/rt1060/README.md +++ b/examples/all-clusters-app/nxp/rt/rt1060/README.md @@ -310,7 +310,7 @@ user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt106 build-time which will enable the device to join the Wi-Fi AP at startup): ``` -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ gn gen --args="chip_enable_wifi=true iwx12_transceiver=true evkname=\"evkcmimxrt1060\" chip_config_network_layer_ble=false tcp_download=true wifi_ssid=\"your_wifi_ssid\" wifi_password=\"your_wifi_password\"" out/debug +user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ export ssid_name= && export ssid_password= && gn gen --args="chip_enable_wifi=true iwx12_transceiver=true evkname=\"evkcmimxrt1060\" chip_config_network_layer_ble=false wifi_auto_connect_at_boot=true wifi_auto_connect_at_boot_ssid=\"${ssid_name}\" wifi_auto_connect_at_boot_password=\"${ssid_password}\"" out/debug user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ ninja -C out/debug ``` @@ -400,7 +400,7 @@ user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt106 - Build Matter with Border Router configuration with onnetwork commissioning: ``` -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ gn gen --args="chip_enable_wifi=true w8801_transceiver=true nxp_enable_matter_cli=true chip_config_network_layer_ble=false wifi_auto_connect_at_boot=true wifi_auto_connect_at_boot_ssid=\"your_wifi_ssid\" wifi_auto_connect_at_boot_password=\"your_wifi_password\" chip_enable_openthread=true k32w0_transceiver=true k32w0_transceiver_bin_path=\"/path/to/ot-rcp/ot-rcp-ble-hci-bb-k32w061.elf.bin.h\"" out/debug +user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ export ssid_name= && export ssid_password= && gn gen --args="chip_enable_wifi=true w8801_transceiver=true nxp_enable_matter_cli=true chip_config_network_layer_ble=false wifi_auto_connect_at_boot=true wifi_auto_connect_at_boot_ssid=\"${ssid_name}\" wifi_auto_connect_at_boot_password=\"${ssid_password}\" chip_enable_openthread=true k32w0_transceiver=true k32w0_transceiver_bin_path=\"/path/to/ot-rcp/ot-rcp-ble-hci-bb-k32w061.elf.bin.h\"" out/debug user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ ninja -C out/debug ``` From 144269a2ed0f6d40fb06423b019d875b1e23d0d9 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Fri, 15 Nov 2024 10:25:21 -0500 Subject: [PATCH 12/27] Add missing #include for size_t (#36474) --- src/lib/support/FunctionTraits.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/support/FunctionTraits.h b/src/lib/support/FunctionTraits.h index 17853a50af8c28..17f02e983a4592 100644 --- a/src/lib/support/FunctionTraits.h +++ b/src/lib/support/FunctionTraits.h @@ -17,6 +17,7 @@ #pragma once +#include #include namespace chip { From 636abc30bad1f7fe11fab5270346f5091f0511d8 Mon Sep 17 00:00:00 2001 From: Erwin Pan Date: Fri, 15 Nov 2024 15:25:40 +0000 Subject: [PATCH 13/27] [Chef] add Multi-sensor (#36469) * Chef add multi sensor * Fix compilation issues * Remove Groups cluster,fix by TC_DeviceConformance.py --- ...ualitysensor_powersource_367e7cea91.matter | 3142 ++++++ ...irqualitysensor_powersource_367e7cea91.zap | 9272 +++++++++++++++++ 2 files changed, 12414 insertions(+) create mode 100644 examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.matter create mode 100644 examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.zap diff --git a/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.matter b/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.matter new file mode 100644 index 00000000000000..27c88b4fb8435e --- /dev/null +++ b/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.matter @@ -0,0 +1,3142 @@ +// This IDL was generated automatically by ZAP. +// It is for view/code review purposes only. + +enum AreaTypeTag : enum8 { + kAisle = 0; + kAttic = 1; + kBackDoor = 2; + kBackYard = 3; + kBalcony = 4; + kBallroom = 5; + kBathroom = 6; + kBedroom = 7; + kBorder = 8; + kBoxroom = 9; + kBreakfastRoom = 10; + kCarport = 11; + kCellar = 12; + kCloakroom = 13; + kCloset = 14; + kConservatory = 15; + kCorridor = 16; + kCraftRoom = 17; + kCupboard = 18; + kDeck = 19; + kDen = 20; + kDining = 21; + kDrawingRoom = 22; + kDressingRoom = 23; + kDriveway = 24; + kElevator = 25; + kEnsuite = 26; + kEntrance = 27; + kEntryway = 28; + kFamilyRoom = 29; + kFoyer = 30; + kFrontDoor = 31; + kFrontYard = 32; + kGameRoom = 33; + kGarage = 34; + kGarageDoor = 35; + kGarden = 36; + kGardenDoor = 37; + kGuestBathroom = 38; + kGuestBedroom = 39; + kGuestRestroom = 40; + kGuestRoom = 41; + kGym = 42; + kHallway = 43; + kHearthRoom = 44; + kKidsRoom = 45; + kKidsBedroom = 46; + kKitchen = 47; + kLarder = 48; + kLaundryRoom = 49; + kLawn = 50; + kLibrary = 51; + kLivingRoom = 52; + kLounge = 53; + kMediaTVRoom = 54; + kMudRoom = 55; + kMusicRoom = 56; + kNursery = 57; + kOffice = 58; + kOutdoorKitchen = 59; + kOutside = 60; + kPantry = 61; + kParkingLot = 62; + kParlor = 63; + kPatio = 64; + kPlayRoom = 65; + kPoolRoom = 66; + kPorch = 67; + kPrimaryBathroom = 68; + kPrimaryBedroom = 69; + kRamp = 70; + kReceptionRoom = 71; + kRecreationRoom = 72; + kRestroom = 73; + kRoof = 74; + kSauna = 75; + kScullery = 76; + kSewingRoom = 77; + kShed = 78; + kSideDoor = 79; + kSideYard = 80; + kSittingRoom = 81; + kSnug = 82; + kSpa = 83; + kStaircase = 84; + kSteamRoom = 85; + kStorageRoom = 86; + kStudio = 87; + kStudy = 88; + kSunRoom = 89; + kSwimmingPool = 90; + kTerrace = 91; + kUtilityRoom = 92; + kWard = 93; + kWorkshop = 94; +} + +enum AtomicRequestTypeEnum : enum8 { + kBeginWrite = 0; + kCommitWrite = 1; + kRollbackWrite = 2; +} + +enum FloorSurfaceTag : enum8 { + kCarpet = 0; + kCeramic = 1; + kConcrete = 2; + kCork = 3; + kDeepCarpet = 4; + kDirt = 5; + kEngineeredWood = 6; + kGlass = 7; + kGrass = 8; + kHardwood = 9; + kLaminate = 10; + kLinoleum = 11; + kMat = 12; + kMetal = 13; + kPlastic = 14; + kPolishedConcrete = 15; + kRubber = 16; + kRug = 17; + kSand = 18; + kStone = 19; + kTatami = 20; + kTerrazzo = 21; + kTile = 22; + kVinyl = 23; +} + +enum LandmarkTag : enum8 { + kAirConditioner = 0; + kAirPurifier = 1; + kBackDoor = 2; + kBarStool = 3; + kBathMat = 4; + kBathtub = 5; + kBed = 6; + kBookshelf = 7; + kChair = 8; + kChristmasTree = 9; + kCoatRack = 10; + kCoffeeTable = 11; + kCookingRange = 12; + kCouch = 13; + kCountertop = 14; + kCradle = 15; + kCrib = 16; + kDesk = 17; + kDiningTable = 18; + kDishwasher = 19; + kDoor = 20; + kDresser = 21; + kLaundryDryer = 22; + kFan = 23; + kFireplace = 24; + kFreezer = 25; + kFrontDoor = 26; + kHighChair = 27; + kKitchenIsland = 28; + kLamp = 29; + kLitterBox = 30; + kMirror = 31; + kNightstand = 32; + kOven = 33; + kPetBed = 34; + kPetBowl = 35; + kPetCrate = 36; + kRefrigerator = 37; + kScratchingPost = 38; + kShoeRack = 39; + kShower = 40; + kSideDoor = 41; + kSink = 42; + kSofa = 43; + kStove = 44; + kTable = 45; + kToilet = 46; + kTrashCan = 47; + kLaundryWasher = 48; + kWindow = 49; + kWineCooler = 50; +} + +enum PositionTag : enum8 { + kLeft = 0; + kRight = 1; + kTop = 2; + kBottom = 3; + kMiddle = 4; + kRow = 5; + kColumn = 6; +} + +enum RelativePositionTag : enum8 { + kUnder = 0; + kNextTo = 1; + kAround = 2; + kOn = 3; + kAbove = 4; + kFrontOf = 5; + kBehind = 6; +} + +enum TestGlobalEnum : enum8 { + kSomeValue = 0; + kSomeOtherValue = 1; + kFinalValue = 2; +} + +enum ThreeLevelAutoEnum : enum8 { + kLow = 0; + kMedium = 1; + kHigh = 2; + kAutomatic = 3; +} + +bitmap TestGlobalBitmap : bitmap32 { + kFirstBit = 0x1; + kSecondBit = 0x2; +} + +struct TestGlobalStruct { + char_string<128> name = 0; + nullable TestGlobalBitmap myBitmap = 1; + optional nullable TestGlobalEnum myEnum = 2; +} + +struct LocationDescriptorStruct { + char_string<128> locationName = 0; + nullable int16s floorNumber = 1; + nullable AreaTypeTag areaType = 2; +} + +struct AtomicAttributeStatusStruct { + attrib_id attributeID = 0; + status statusCode = 1; +} + +/** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ +cluster Identify = 3 { + revision 4; + + enum EffectIdentifierEnum : enum8 { + kBlink = 0; + kBreathe = 1; + kOkay = 2; + kChannelChange = 11; + kFinishEffect = 254; + kStopEffect = 255; + } + + enum EffectVariantEnum : enum8 { + kDefault = 0; + } + + enum IdentifyTypeEnum : enum8 { + kNone = 0; + kLightOutput = 1; + kVisibleIndicator = 2; + kAudibleBeep = 3; + kDisplay = 4; + kActuator = 5; + } + + attribute int16u identifyTime = 0; + readonly attribute IdentifyTypeEnum identifyType = 1; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + 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 { + EffectIdentifierEnum effectIdentifier = 0; + EffectVariantEnum effectVariant = 1; + } + + /** Command description for Identify */ + command access(invoke: manage) Identify(IdentifyRequest): DefaultSuccess = 0; + /** Command description for TriggerEffect */ + command access(invoke: manage) TriggerEffect(TriggerEffectRequest): DefaultSuccess = 64; +} + +/** The Descriptor Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for describing a node, its endpoints and clusters. */ +cluster Descriptor = 29 { + revision 2; + + bitmap Feature : bitmap32 { + kTagList = 0x1; + } + + struct DeviceTypeStruct { + devtype_id deviceType = 0; + int16u revision = 1; + } + + struct SemanticTagStruct { + nullable vendor_id mfgCode = 0; + enum8 namespaceID = 1; + enum8 tag = 2; + optional nullable char_string label = 3; + } + + readonly attribute DeviceTypeStruct deviceTypeList[] = 0; + readonly attribute cluster_id serverList[] = 1; + readonly attribute cluster_id clientList[] = 2; + readonly attribute endpoint_no partsList[] = 3; + readonly attribute optional SemanticTagStruct tagList[] = 4; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** The Binding Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for supporting the binding table. */ +cluster Binding = 30 { + revision 1; // NOTE: Default/not specifically set + + fabric_scoped 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 access(write: manage) TargetStruct binding[] = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** The Access Control Cluster exposes a data model view of a + Node's Access Control List (ACL), which codifies the rules used to manage + and enforce Access Control for the Node's endpoints and their associated + cluster instances. */ +cluster AccessControl = 31 { + revision 2; + + enum AccessControlEntryAuthModeEnum : enum8 { + kPASE = 1; + kCASE = 2; + kGroup = 3; + } + + enum AccessControlEntryPrivilegeEnum : enum8 { + kView = 1; + kProxyView = 2; + kOperate = 3; + kManage = 4; + kAdminister = 5; + } + + enum AccessRestrictionTypeEnum : enum8 { + kAttributeAccessForbidden = 0; + kAttributeWriteForbidden = 1; + kCommandForbidden = 2; + kEventForbidden = 3; + } + + enum ChangeTypeEnum : enum8 { + kChanged = 0; + kAdded = 1; + kRemoved = 2; + } + + bitmap Feature : bitmap32 { + kExtension = 0x1; + kManagedDevice = 0x2; + } + + struct AccessRestrictionStruct { + AccessRestrictionTypeEnum type = 0; + nullable int32u id = 1; + } + + struct CommissioningAccessRestrictionEntryStruct { + endpoint_no endpoint = 0; + cluster_id cluster = 1; + AccessRestrictionStruct restrictions[] = 2; + } + + fabric_scoped struct AccessRestrictionEntryStruct { + fabric_sensitive endpoint_no endpoint = 0; + fabric_sensitive cluster_id cluster = 1; + fabric_sensitive AccessRestrictionStruct restrictions[] = 2; + fabric_idx fabricIndex = 254; + } + + struct AccessControlTargetStruct { + nullable cluster_id cluster = 0; + nullable endpoint_no endpoint = 1; + nullable devtype_id deviceType = 2; + } + + fabric_scoped struct AccessControlEntryStruct { + fabric_sensitive AccessControlEntryPrivilegeEnum privilege = 1; + fabric_sensitive AccessControlEntryAuthModeEnum authMode = 2; + nullable fabric_sensitive int64u subjects[] = 3; + nullable fabric_sensitive AccessControlTargetStruct targets[] = 4; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct AccessControlExtensionStruct { + fabric_sensitive octet_string<128> data = 1; + fabric_idx fabricIndex = 254; + } + + fabric_sensitive info event access(read: administer) AccessControlEntryChanged = 0 { + nullable node_id adminNodeID = 1; + nullable int16u adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable AccessControlEntryStruct latestValue = 4; + fabric_idx fabricIndex = 254; + } + + fabric_sensitive info event access(read: administer) AccessControlExtensionChanged = 1 { + nullable node_id adminNodeID = 1; + nullable int16u adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable AccessControlExtensionStruct latestValue = 4; + fabric_idx fabricIndex = 254; + } + + fabric_sensitive info event access(read: administer) FabricRestrictionReviewUpdate = 2 { + int64u token = 0; + optional long_char_string instruction = 1; + optional long_char_string ARLRequestFlowUrl = 2; + fabric_idx fabricIndex = 254; + } + + attribute access(read: administer, write: administer) AccessControlEntryStruct acl[] = 0; + attribute access(read: administer, write: administer) optional AccessControlExtensionStruct extension[] = 1; + readonly attribute int16u subjectsPerAccessControlEntry = 2; + readonly attribute int16u targetsPerAccessControlEntry = 3; + readonly attribute int16u accessControlEntriesPerFabric = 4; + readonly attribute optional CommissioningAccessRestrictionEntryStruct commissioningARL[] = 5; + readonly attribute optional AccessRestrictionEntryStruct arl[] = 6; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct ReviewFabricRestrictionsRequest { + CommissioningAccessRestrictionEntryStruct arl[] = 0; + } + + response struct ReviewFabricRestrictionsResponse = 1 { + int64u token = 0; + } + + /** This command signals to the service associated with the device vendor that the fabric administrator would like a review of the current restrictions on the accessing fabric. */ + fabric command access(invoke: administer) ReviewFabricRestrictions(ReviewFabricRestrictionsRequest): ReviewFabricRestrictionsResponse = 0; +} + +/** This cluster provides attributes and events for determining basic information about Nodes, which supports both + Commissioning and operational determination of Node characteristics, such as Vendor ID, Product ID and serial number, + which apply to the whole Node. Also allows setting user device information such as location. */ +cluster BasicInformation = 40 { + revision 3; + + enum ColorEnum : enum8 { + kBlack = 0; + kNavy = 1; + kGreen = 2; + kTeal = 3; + kMaroon = 4; + kPurple = 5; + kOlive = 6; + kGray = 7; + kBlue = 8; + kLime = 9; + kAqua = 10; + kRed = 11; + kFuchsia = 12; + kYellow = 13; + kWhite = 14; + kNickel = 15; + kChrome = 16; + kBrass = 17; + kCopper = 18; + kSilver = 19; + kGold = 20; + } + + enum ProductFinishEnum : enum8 { + kOther = 0; + kMatte = 1; + kSatin = 2; + kPolished = 3; + kRugged = 4; + kFabric = 5; + } + + struct CapabilityMinimaStruct { + int16u caseSessionsPerFabric = 0; + int16u subscriptionsPerFabric = 1; + } + + struct ProductAppearanceStruct { + ProductFinishEnum finish = 0; + nullable ColorEnum primaryColor = 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 optional char_string<16> manufacturingDate = 11; + readonly attribute optional char_string<32> partNumber = 12; + readonly attribute optional long_char_string<256> productURL = 13; + readonly attribute optional char_string<64> productLabel = 14; + readonly attribute optional char_string<32> serialNumber = 15; + attribute access(write: manage) optional boolean localConfigDisabled = 16; + readonly attribute optional boolean reachable = 17; + readonly attribute char_string<32> uniqueID = 18; + readonly attribute CapabilityMinimaStruct capabilityMinima = 19; + readonly attribute optional ProductAppearanceStruct productAppearance = 20; + readonly attribute int32u specificationVersion = 21; + readonly attribute int16u maxPathsPerInvoke = 22; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + command MfgSpecificPing(): DefaultSuccess = 0; +} + +/** Nodes should be expected to be deployed to any and all regions of the world. These global regions + may have differing common languages, units of measurements, and numerical formatting + standards. As such, Nodes that visually or audibly convey information need a mechanism by which + they can be configured to use a user’s preferred language, units, etc */ +cluster LocalizationConfiguration = 43 { + revision 1; // NOTE: Default/not specifically set + + attribute access(write: manage) 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 event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** This cluster is used to describe the configuration and capabilities of a physical power source that provides power to the Node. */ +cluster PowerSource = 47 { + revision 1; // NOTE: Default/not specifically set + + enum BatApprovedChemistryEnum : enum16 { + kUnspecified = 0; + kAlkaline = 1; + kLithiumCarbonFluoride = 2; + kLithiumChromiumOxide = 3; + kLithiumCopperOxide = 4; + kLithiumIronDisulfide = 5; + kLithiumManganeseDioxide = 6; + kLithiumThionylChloride = 7; + kMagnesium = 8; + kMercuryOxide = 9; + kNickelOxyhydride = 10; + kSilverOxide = 11; + kZincAir = 12; + kZincCarbon = 13; + kZincChloride = 14; + kZincManganeseDioxide = 15; + kLeadAcid = 16; + kLithiumCobaltOxide = 17; + kLithiumIon = 18; + kLithiumIonPolymer = 19; + kLithiumIronPhosphate = 20; + kLithiumSulfur = 21; + kLithiumTitanate = 22; + kNickelCadmium = 23; + kNickelHydrogen = 24; + kNickelIron = 25; + kNickelMetalHydride = 26; + kNickelZinc = 27; + kSilverZinc = 28; + kSodiumIon = 29; + kSodiumSulfur = 30; + kZincBromide = 31; + kZincCerium = 32; + } + + enum BatChargeFaultEnum : enum8 { + kUnspecified = 0; + kAmbientTooHot = 1; + kAmbientTooCold = 2; + kBatteryTooHot = 3; + kBatteryTooCold = 4; + kBatteryAbsent = 5; + kBatteryOverVoltage = 6; + kBatteryUnderVoltage = 7; + kChargerOverVoltage = 8; + kChargerUnderVoltage = 9; + kSafetyTimeout = 10; + } + + enum BatChargeLevelEnum : enum8 { + kOK = 0; + kWarning = 1; + kCritical = 2; + } + + enum BatChargeStateEnum : enum8 { + kUnknown = 0; + kIsCharging = 1; + kIsAtFullCharge = 2; + kIsNotCharging = 3; + } + + enum BatCommonDesignationEnum : enum16 { + kUnspecified = 0; + kAAA = 1; + kAA = 2; + kC = 3; + kD = 4; + k4v5 = 5; + k6v0 = 6; + k9v0 = 7; + k12AA = 8; + kAAAA = 9; + kA = 10; + kB = 11; + kF = 12; + kN = 13; + kNo6 = 14; + kSubC = 15; + kA23 = 16; + kA27 = 17; + kBA5800 = 18; + kDuplex = 19; + k4SR44 = 20; + k523 = 21; + k531 = 22; + k15v0 = 23; + k22v5 = 24; + k30v0 = 25; + k45v0 = 26; + k67v5 = 27; + kJ = 28; + kCR123A = 29; + kCR2 = 30; + k2CR5 = 31; + kCRP2 = 32; + kCRV3 = 33; + kSR41 = 34; + kSR43 = 35; + kSR44 = 36; + kSR45 = 37; + kSR48 = 38; + kSR54 = 39; + kSR55 = 40; + kSR57 = 41; + kSR58 = 42; + kSR59 = 43; + kSR60 = 44; + kSR63 = 45; + kSR64 = 46; + kSR65 = 47; + kSR66 = 48; + kSR67 = 49; + kSR68 = 50; + kSR69 = 51; + kSR516 = 52; + kSR731 = 53; + kSR712 = 54; + kLR932 = 55; + kA5 = 56; + kA10 = 57; + kA13 = 58; + kA312 = 59; + kA675 = 60; + kAC41E = 61; + k10180 = 62; + k10280 = 63; + k10440 = 64; + k14250 = 65; + k14430 = 66; + k14500 = 67; + k14650 = 68; + k15270 = 69; + k16340 = 70; + kRCR123A = 71; + k17500 = 72; + k17670 = 73; + k18350 = 74; + k18500 = 75; + k18650 = 76; + k19670 = 77; + k25500 = 78; + k26650 = 79; + k32600 = 80; + } + + enum BatFaultEnum : enum8 { + kUnspecified = 0; + kOverTemp = 1; + kUnderTemp = 2; + } + + enum BatReplaceabilityEnum : enum8 { + kUnspecified = 0; + kNotReplaceable = 1; + kUserReplaceable = 2; + kFactoryReplaceable = 3; + } + + enum PowerSourceStatusEnum : enum8 { + kUnspecified = 0; + kActive = 1; + kStandby = 2; + kUnavailable = 3; + } + + enum WiredCurrentTypeEnum : enum8 { + kAC = 0; + kDC = 1; + } + + enum WiredFaultEnum : enum8 { + kUnspecified = 0; + kOverVoltage = 1; + kUnderVoltage = 2; + } + + bitmap Feature : bitmap32 { + kWired = 0x1; + kBattery = 0x2; + kRechargeable = 0x4; + kReplaceable = 0x8; + } + + struct BatChargeFaultChangeType { + BatChargeFaultEnum current[] = 0; + BatChargeFaultEnum previous[] = 1; + } + + struct BatFaultChangeType { + BatFaultEnum current[] = 0; + BatFaultEnum previous[] = 1; + } + + struct WiredFaultChangeType { + WiredFaultEnum current[] = 0; + WiredFaultEnum previous[] = 1; + } + + info event WiredFaultChange = 0 { + WiredFaultEnum current[] = 0; + WiredFaultEnum previous[] = 1; + } + + info event BatFaultChange = 1 { + BatFaultEnum current[] = 0; + BatFaultEnum previous[] = 1; + } + + info event BatChargeFaultChange = 2 { + BatChargeFaultEnum current[] = 0; + BatChargeFaultEnum previous[] = 1; + } + + readonly attribute PowerSourceStatusEnum status = 0; + readonly attribute int8u order = 1; + readonly attribute char_string<60> description = 2; + readonly attribute optional nullable int32u wiredAssessedInputVoltage = 3; + readonly attribute optional nullable int16u wiredAssessedInputFrequency = 4; + readonly attribute optional WiredCurrentTypeEnum wiredCurrentType = 5; + readonly attribute optional nullable int32u wiredAssessedCurrent = 6; + readonly attribute optional int32u wiredNominalVoltage = 7; + readonly attribute optional int32u wiredMaximumCurrent = 8; + readonly attribute optional boolean wiredPresent = 9; + readonly attribute optional WiredFaultEnum activeWiredFaults[] = 10; + readonly attribute optional nullable int32u batVoltage = 11; + readonly attribute optional nullable int8u batPercentRemaining = 12; + readonly attribute optional nullable int32u batTimeRemaining = 13; + readonly attribute optional BatChargeLevelEnum batChargeLevel = 14; + readonly attribute optional boolean batReplacementNeeded = 15; + readonly attribute optional BatReplaceabilityEnum batReplaceability = 16; + readonly attribute optional boolean batPresent = 17; + readonly attribute optional BatFaultEnum activeBatFaults[] = 18; + readonly attribute optional char_string<60> batReplacementDescription = 19; + readonly attribute optional BatCommonDesignationEnum batCommonDesignation = 20; + readonly attribute optional char_string<20> batANSIDesignation = 21; + readonly attribute optional char_string<20> batIECDesignation = 22; + readonly attribute optional BatApprovedChemistryEnum batApprovedChemistry = 23; + readonly attribute optional int32u batCapacity = 24; + readonly attribute optional int8u batQuantity = 25; + readonly attribute optional BatChargeStateEnum batChargeState = 26; + readonly attribute optional nullable int32u batTimeToFullCharge = 27; + readonly attribute optional boolean batFunctionalWhileCharging = 28; + readonly attribute optional nullable int32u batChargingCurrent = 29; + readonly attribute optional BatChargeFaultEnum activeBatChargeFaults[] = 30; + readonly attribute endpoint_no endpointList[] = 31; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** This cluster is used to manage global aspects of the Commissioning flow. */ +cluster GeneralCommissioning = 48 { + revision 1; // NOTE: Default/not specifically set + + enum CommissioningErrorEnum : enum8 { + kOK = 0; + kValueOutsideRange = 1; + kInvalidAuthentication = 2; + kNoFailSafe = 3; + kBusyWithOtherAdmin = 4; + kRequiredTCNotAccepted = 5; + kTCAcknowledgementsNotReceived = 6; + kTCMinVersionNotMet = 7; + } + + enum RegulatoryLocationTypeEnum : enum8 { + kIndoor = 0; + kOutdoor = 1; + kIndoorOutdoor = 2; + } + + bitmap Feature : bitmap32 { + kTermsAndConditions = 0x1; + } + + struct BasicCommissioningInfo { + int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; + } + + attribute access(write: administer) int64u breadcrumb = 0; + readonly attribute BasicCommissioningInfo basicCommissioningInfo = 1; + readonly attribute RegulatoryLocationTypeEnum regulatoryConfig = 2; + readonly attribute RegulatoryLocationTypeEnum locationCapability = 3; + readonly attribute boolean supportsConcurrentConnection = 4; + provisional readonly attribute access(read: administer) optional int16u TCAcceptedVersion = 5; + provisional readonly attribute access(read: administer) optional int16u TCMinRequiredVersion = 6; + provisional readonly attribute access(read: administer) optional bitmap16 TCAcknowledgements = 7; + provisional readonly attribute access(read: administer) optional boolean TCAcknowledgementsRequired = 8; + provisional readonly attribute access(read: administer) optional int32u TCUpdateDeadline = 9; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + 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; + } + + response struct ArmFailSafeResponse = 1 { + CommissioningErrorEnum errorCode = 0; + char_string<128> debugText = 1; + } + + request struct SetRegulatoryConfigRequest { + RegulatoryLocationTypeEnum newRegulatoryConfig = 0; + char_string<2> countryCode = 1; + int64u breadcrumb = 2; + } + + response struct SetRegulatoryConfigResponse = 3 { + CommissioningErrorEnum errorCode = 0; + char_string debugText = 1; + } + + response struct CommissioningCompleteResponse = 5 { + CommissioningErrorEnum errorCode = 0; + char_string debugText = 1; + } + + request struct SetTCAcknowledgementsRequest { + int16u TCVersion = 0; + bitmap16 TCUserResponse = 1; + } + + response struct SetTCAcknowledgementsResponse = 7 { + CommissioningErrorEnum errorCode = 0; + } + + /** Arm the persistent fail-safe timer with an expiry time of now + ExpiryLengthSeconds using device clock */ + command access(invoke: administer) ArmFailSafe(ArmFailSafeRequest): ArmFailSafeResponse = 0; + /** Set the regulatory configuration to be used during commissioning */ + command access(invoke: administer) SetRegulatoryConfig(SetRegulatoryConfigRequest): SetRegulatoryConfigResponse = 2; + /** Signals the Server that the Client has successfully completed all steps of Commissioning/Recofiguration needed during fail-safe period. */ + fabric command access(invoke: administer) CommissioningComplete(): CommissioningCompleteResponse = 4; + /** This command sets the user acknowledgements received in the Enhanced Setup Flow Terms and Conditions into the node. */ + command access(invoke: administer) SetTCAcknowledgements(SetTCAcknowledgementsRequest): SetTCAcknowledgementsResponse = 6; +} + +/** Functionality to configure, enable, disable network credentials and access on a Matter device. */ +cluster NetworkCommissioning = 49 { + revision 1; // NOTE: Default/not specifically set + + enum NetworkCommissioningStatusEnum : 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 WiFiBandEnum : enum8 { + k2G4 = 0; + k3G65 = 1; + k5G = 2; + k6G = 3; + k60G = 4; + k1G = 5; + } + + bitmap Feature : bitmap32 { + kWiFiNetworkInterface = 0x1; + kThreadNetworkInterface = 0x2; + kEthernetNetworkInterface = 0x4; + kPerDeviceCredentials = 0x8; + } + + bitmap ThreadCapabilitiesBitmap : bitmap16 { + kIsBorderRouterCapable = 0x1; + kIsRouterCapable = 0x2; + kIsSleepyEndDeviceCapable = 0x4; + kIsFullThreadDevice = 0x8; + kIsSynchronizedSleepyEndDeviceCapable = 0x10; + } + + bitmap WiFiSecurityBitmap : bitmap8 { + kUnencrypted = 0x1; + kWEP = 0x2; + kWPAPersonal = 0x4; + kWPA2Personal = 0x8; + kWPA3Personal = 0x10; + kWPA3MatterPDC = 0x20; + } + + struct NetworkInfoStruct { + octet_string<32> networkID = 0; + boolean connected = 1; + optional nullable octet_string<20> networkIdentifier = 2; + optional nullable octet_string<20> clientIdentifier = 3; + } + + struct ThreadInterfaceScanResultStruct { + 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; + } + + struct WiFiInterfaceScanResultStruct { + WiFiSecurityBitmap security = 0; + octet_string<32> ssid = 1; + octet_string<6> bssid = 2; + int16u channel = 3; + WiFiBandEnum wiFiBand = 4; + int8s rssi = 5; + } + + readonly attribute access(read: administer) int8u maxNetworks = 0; + readonly attribute access(read: administer) NetworkInfoStruct networks[] = 1; + readonly attribute optional int8u scanMaxTimeSeconds = 2; + readonly attribute optional int8u connectMaxTimeSeconds = 3; + attribute access(write: administer) boolean interfaceEnabled = 4; + readonly attribute access(read: administer) nullable NetworkCommissioningStatusEnum lastNetworkingStatus = 5; + readonly attribute access(read: administer) nullable octet_string<32> lastNetworkID = 6; + readonly attribute access(read: administer) nullable int32s lastConnectErrorValue = 7; + provisional readonly attribute optional WiFiBandEnum supportedWiFiBands[] = 8; + provisional readonly attribute optional ThreadCapabilitiesBitmap supportedThreadFeatures = 9; + provisional readonly attribute optional int16u threadVersion = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct ScanNetworksRequest { + optional nullable octet_string<32> ssid = 0; + optional int64u breadcrumb = 1; + } + + response struct ScanNetworksResponse = 1 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional char_string debugText = 1; + optional WiFiInterfaceScanResultStruct wiFiScanResults[] = 2; + optional ThreadInterfaceScanResultStruct threadScanResults[] = 3; + } + + request struct AddOrUpdateWiFiNetworkRequest { + octet_string<32> ssid = 0; + octet_string<64> credentials = 1; + optional int64u breadcrumb = 2; + optional octet_string<140> networkIdentity = 3; + optional octet_string<20> clientIdentifier = 4; + optional octet_string<32> possessionNonce = 5; + } + + request struct AddOrUpdateThreadNetworkRequest { + octet_string<254> operationalDataset = 0; + optional int64u breadcrumb = 1; + } + + request struct RemoveNetworkRequest { + octet_string<32> networkID = 0; + optional int64u breadcrumb = 1; + } + + response struct NetworkConfigResponse = 5 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional char_string<512> debugText = 1; + optional int8u networkIndex = 2; + optional octet_string<140> clientIdentity = 3; + optional octet_string<64> possessionSignature = 4; + } + + request struct ConnectNetworkRequest { + octet_string<32> networkID = 0; + optional int64u breadcrumb = 1; + } + + response struct ConnectNetworkResponse = 7 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional char_string debugText = 1; + nullable int32s errorValue = 2; + } + + request struct ReorderNetworkRequest { + octet_string<32> networkID = 0; + int8u networkIndex = 1; + optional int64u breadcrumb = 2; + } + + request struct QueryIdentityRequest { + octet_string<20> keyIdentifier = 0; + optional octet_string<32> possessionNonce = 1; + } + + response struct QueryIdentityResponse = 10 { + octet_string<140> identity = 0; + optional octet_string<64> possessionSignature = 1; + } + + /** Detemine the set of networks the device sees as available. */ + command access(invoke: administer) ScanNetworks(ScanNetworksRequest): ScanNetworksResponse = 0; + /** Add or update the credentials for a given Wi-Fi network. */ + command access(invoke: administer) AddOrUpdateWiFiNetwork(AddOrUpdateWiFiNetworkRequest): NetworkConfigResponse = 2; + /** Add or update the credentials for a given Thread network. */ + command access(invoke: administer) AddOrUpdateThreadNetwork(AddOrUpdateThreadNetworkRequest): NetworkConfigResponse = 3; + /** Remove the definition of a given network (including its credentials). */ + command access(invoke: administer) RemoveNetwork(RemoveNetworkRequest): NetworkConfigResponse = 4; + /** Connect to the specified network, using previously-defined credentials. */ + command access(invoke: administer) ConnectNetwork(ConnectNetworkRequest): ConnectNetworkResponse = 6; + /** Modify the order in which networks will be presented in the Networks attribute. */ + command access(invoke: administer) ReorderNetwork(ReorderNetworkRequest): NetworkConfigResponse = 8; + /** Retrieve details about and optionally proof of possession of a network client identity. */ + command access(invoke: administer) QueryIdentity(QueryIdentityRequest): QueryIdentityResponse = 9; +} + +/** The cluster provides commands for retrieving unstructured diagnostic logs from a Node that may be used to aid in diagnostics. */ +cluster DiagnosticLogs = 50 { + revision 1; // NOTE: Default/not specifically set + + enum IntentEnum : enum8 { + kEndUserSupport = 0; + kNetworkDiag = 1; + kCrashLogs = 2; + } + + enum StatusEnum : enum8 { + kSuccess = 0; + kExhausted = 1; + kNoLogs = 2; + kBusy = 3; + kDenied = 4; + } + + enum TransferProtocolEnum : enum8 { + kResponsePayload = 0; + kBDX = 1; + } + + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct RetrieveLogsRequestRequest { + IntentEnum intent = 0; + TransferProtocolEnum requestedProtocol = 1; + optional char_string<32> transferFileDesignator = 2; + } + + response struct RetrieveLogsResponse = 1 { + StatusEnum status = 0; + long_octet_string logContent = 1; + optional epoch_us UTCTimeStamp = 2; + optional systime_us timeSinceBoot = 3; + } + + /** Retrieving diagnostic logs from a Node */ + command RetrieveLogsRequest(RetrieveLogsRequestRequest): RetrieveLogsResponse = 0; +} + +/** The General Diagnostics Cluster, along with other diagnostics clusters, provide a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems. */ +cluster GeneralDiagnostics = 51 { + revision 2; + + enum BootReasonEnum : enum8 { + kUnspecified = 0; + kPowerOnReboot = 1; + kBrownOutReset = 2; + kSoftwareWatchdogReset = 3; + kHardwareWatchdogReset = 4; + kSoftwareUpdateCompleted = 5; + kSoftwareReset = 6; + } + + enum HardwareFaultEnum : enum8 { + kUnspecified = 0; + kRadio = 1; + kSensor = 2; + kResettableOverTemp = 3; + kNonResettableOverTemp = 4; + kPowerSource = 5; + kVisualDisplayFault = 6; + kAudioOutputFault = 7; + kUserInterfaceFault = 8; + kNonVolatileMemoryError = 9; + kTamperDetected = 10; + } + + enum InterfaceTypeEnum : enum8 { + kUnspecified = 0; + kWiFi = 1; + kEthernet = 2; + kCellular = 3; + kThread = 4; + } + + enum NetworkFaultEnum : enum8 { + kUnspecified = 0; + kHardwareFailure = 1; + kNetworkJammed = 2; + kConnectionFailed = 3; + } + + enum RadioFaultEnum : enum8 { + kUnspecified = 0; + kWiFiFault = 1; + kCellularFault = 2; + kThreadFault = 3; + kNFCFault = 4; + kBLEFault = 5; + kEthernetFault = 6; + } + + bitmap Feature : bitmap32 { + kDataModelTest = 0x1; + } + + struct NetworkInterface { + 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; + InterfaceTypeEnum type = 7; + } + + critical event HardwareFaultChange = 0 { + HardwareFaultEnum current[] = 0; + HardwareFaultEnum previous[] = 1; + } + + critical event RadioFaultChange = 1 { + RadioFaultEnum current[] = 0; + RadioFaultEnum previous[] = 1; + } + + critical event NetworkFaultChange = 2 { + NetworkFaultEnum current[] = 0; + NetworkFaultEnum previous[] = 1; + } + + critical event BootReason = 3 { + BootReasonEnum bootReason = 0; + } + + readonly attribute NetworkInterface networkInterfaces[] = 0; + readonly attribute int16u rebootCount = 1; + readonly attribute optional int64u upTime = 2; + readonly attribute optional int32u totalOperationalHours = 3; + readonly attribute optional BootReasonEnum bootReason = 4; + readonly attribute optional HardwareFaultEnum activeHardwareFaults[] = 5; + readonly attribute optional RadioFaultEnum activeRadioFaults[] = 6; + readonly attribute optional NetworkFaultEnum activeNetworkFaults[] = 7; + readonly attribute boolean testEventTriggersEnabled = 8; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct TestEventTriggerRequest { + octet_string<16> enableKey = 0; + int64u eventTrigger = 1; + } + + response struct TimeSnapshotResponse = 2 { + systime_ms systemTimeMs = 0; + nullable posix_ms posixTimeMs = 1; + } + + request struct PayloadTestRequestRequest { + octet_string<16> enableKey = 0; + int8u value = 1; + int16u count = 2; + } + + response struct PayloadTestResponse = 4 { + octet_string payload = 0; + } + + /** Provide a means for certification tests to trigger some test-plan-specific events */ + command access(invoke: manage) TestEventTrigger(TestEventTriggerRequest): DefaultSuccess = 0; + /** Take a snapshot of system time and epoch time. */ + command TimeSnapshot(): TimeSnapshotResponse = 1; + /** Request a variable length payload response. */ + command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; +} + +/** The Software Diagnostics Cluster provides a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems. */ +cluster SoftwareDiagnostics = 52 { + revision 1; // NOTE: Default/not specifically set + + bitmap Feature : bitmap32 { + kWatermarks = 0x1; + } + + struct ThreadMetricsStruct { + 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 optional ThreadMetricsStruct threadMetrics[] = 0; + readonly attribute optional int64u currentHeapFree = 1; + readonly attribute optional int64u currentHeapUsed = 2; + readonly attribute optional int64u currentHeapHighWatermark = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + /** Reception of this command SHALL reset the values: The StackFreeMinimum field of the ThreadMetrics attribute, CurrentHeapHighWaterMark attribute. */ + command access(invoke: manage) ResetWatermarks(): DefaultSuccess = 0; +} + +/** Commands to trigger a Node to allow a new Administrator to commission it. */ +cluster AdministratorCommissioning = 60 { + revision 1; // NOTE: Default/not specifically set + + enum CommissioningWindowStatusEnum : enum8 { + kWindowNotOpen = 0; + kEnhancedWindowOpen = 1; + kBasicWindowOpen = 2; + } + + enum StatusCode : enum8 { + kBusy = 2; + kPAKEParameterError = 3; + kWindowNotOpen = 4; + } + + bitmap Feature : bitmap32 { + kBasic = 0x1; + } + + readonly attribute CommissioningWindowStatusEnum windowStatus = 0; + readonly attribute nullable fabric_idx adminFabricIndex = 1; + readonly attribute nullable vendor_id adminVendorId = 2; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct OpenCommissioningWindowRequest { + int16u commissioningTimeout = 0; + octet_string PAKEPasscodeVerifier = 1; + int16u discriminator = 2; + int32u iterations = 3; + octet_string<32> salt = 4; + } + + request struct OpenBasicCommissioningWindowRequest { + int16u commissioningTimeout = 0; + } + + /** This command is used by a current Administrator to instruct a Node to go into commissioning mode using enhanced commissioning method. */ + timed command access(invoke: administer) OpenCommissioningWindow(OpenCommissioningWindowRequest): DefaultSuccess = 0; + /** This command is used by a current Administrator to instruct a Node to go into commissioning mode using basic commissioning method, if the node supports it. */ + timed command access(invoke: administer) OpenBasicCommissioningWindow(OpenBasicCommissioningWindowRequest): DefaultSuccess = 1; + /** This command is used by a current Administrator to instruct a Node to revoke any active Open Commissioning Window or Open Basic Commissioning Window command. */ + timed command access(invoke: administer) RevokeCommissioning(): DefaultSuccess = 2; +} + +/** This cluster is used to add or remove Operational Credentials on a Commissionee or Node, as well as manage the associated Fabrics. */ +cluster OperationalCredentials = 62 { + revision 1; // NOTE: Default/not specifically set + + enum CertificateChainTypeEnum : enum8 { + kDACCertificate = 1; + kPAICertificate = 2; + } + + enum NodeOperationalCertStatusEnum : enum8 { + kOK = 0; + kInvalidPublicKey = 1; + kInvalidNodeOpId = 2; + kInvalidNOC = 3; + kMissingCsr = 4; + kTableFull = 5; + kInvalidAdminSubject = 6; + kFabricConflict = 9; + kLabelConflict = 10; + kInvalidFabricIndex = 11; + } + + fabric_scoped struct FabricDescriptorStruct { + 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; + } + + fabric_scoped struct NOCStruct { + fabric_sensitive octet_string noc = 1; + nullable fabric_sensitive octet_string icac = 2; + fabric_idx fabricIndex = 254; + } + + readonly attribute access(read: administer) NOCStruct NOCs[] = 0; + readonly attribute FabricDescriptorStruct 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 event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct AttestationRequestRequest { + octet_string<32> attestationNonce = 0; + } + + response struct AttestationResponse = 1 { + octet_string<900> attestationElements = 0; + octet_string<64> attestationSignature = 1; + } + + request struct CertificateChainRequestRequest { + CertificateChainTypeEnum certificateType = 0; + } + + response struct CertificateChainResponse = 3 { + octet_string<600> certificate = 0; + } + + request struct CSRRequestRequest { + octet_string<32> CSRNonce = 0; + optional boolean isForUpdateNOC = 1; + } + + response struct CSRResponse = 5 { + octet_string NOCSRElements = 0; + octet_string attestationSignature = 1; + } + + request struct AddNOCRequest { + octet_string<400> NOCValue = 0; + optional octet_string<400> ICACValue = 1; + octet_string<16> IPKValue = 2; + int64u caseAdminSubject = 3; + vendor_id adminVendorId = 4; + } + + request struct UpdateNOCRequest { + octet_string NOCValue = 0; + optional octet_string ICACValue = 1; + } + + response struct NOCResponse = 8 { + NodeOperationalCertStatusEnum statusCode = 0; + optional fabric_idx fabricIndex = 1; + optional char_string<128> debugText = 2; + } + + request struct UpdateFabricLabelRequest { + char_string<32> label = 0; + } + + request struct RemoveFabricRequest { + fabric_idx fabricIndex = 0; + } + + request struct AddTrustedRootCertificateRequest { + octet_string rootCACertificate = 0; + } + + /** Sender is requesting attestation information from the receiver. */ + command access(invoke: administer) AttestationRequest(AttestationRequestRequest): AttestationResponse = 0; + /** Sender is requesting a device attestation certificate from the receiver. */ + command access(invoke: administer) CertificateChainRequest(CertificateChainRequestRequest): CertificateChainResponse = 2; + /** Sender is requesting a certificate signing request (CSR) from the receiver. */ + command access(invoke: administer) CSRRequest(CSRRequestRequest): CSRResponse = 4; + /** Sender is requesting to add the new node operational certificates. */ + command access(invoke: administer) AddNOC(AddNOCRequest): NOCResponse = 6; + /** Sender is requesting to update the node operational certificates. */ + fabric command access(invoke: administer) UpdateNOC(UpdateNOCRequest): NOCResponse = 7; + /** This command SHALL be used by an Administrative Node to set the user-visible Label field for a given Fabric, as reflected by entries in the Fabrics attribute. */ + fabric command access(invoke: administer) UpdateFabricLabel(UpdateFabricLabelRequest): NOCResponse = 9; + /** This command is used by Administrative Nodes to remove a given fabric index and delete all associated fabric-scoped data. */ + command access(invoke: administer) RemoveFabric(RemoveFabricRequest): NOCResponse = 10; + /** This command SHALL add a Trusted Root CA Certificate, provided as its CHIP Certificate representation. */ + command access(invoke: administer) AddTrustedRootCertificate(AddTrustedRootCertificateRequest): DefaultSuccess = 11; +} + +/** The Group Key Management Cluster is the mechanism by which group keys are managed. */ +cluster GroupKeyManagement = 63 { + revision 1; // NOTE: Default/not specifically set + + enum GroupKeySecurityPolicyEnum : enum8 { + kTrustFirst = 0; + kCacheAndSync = 1; + } + + bitmap Feature : bitmap32 { + kCacheAndSync = 0x1; + } + + fabric_scoped struct GroupInfoMapStruct { + group_id groupId = 1; + endpoint_no endpoints[] = 2; + optional char_string<16> groupName = 3; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct GroupKeyMapStruct { + group_id groupId = 1; + int16u groupKeySetID = 2; + fabric_idx fabricIndex = 254; + } + + struct GroupKeySetStruct { + int16u groupKeySetID = 0; + GroupKeySecurityPolicyEnum 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 event_id eventList[] = 65530; + 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; + } + + response struct KeySetReadResponse = 2 { + GroupKeySetStruct groupKeySet = 0; + } + + request struct KeySetRemoveRequest { + int16u groupKeySetID = 0; + } + + response struct KeySetReadAllIndicesResponse = 5 { + int16u groupKeySetIDs[] = 0; + } + + /** Write a new set of keys for the given key set id. */ + fabric command access(invoke: administer) KeySetWrite(KeySetWriteRequest): DefaultSuccess = 0; + /** Read the keys for a given key set id. */ + fabric command access(invoke: administer) KeySetRead(KeySetReadRequest): KeySetReadResponse = 1; + /** Revoke a Root Key from a Group */ + fabric command access(invoke: administer) KeySetRemove(KeySetRemoveRequest): DefaultSuccess = 3; + /** Return the list of Group Key Sets associated with the accessing fabric */ + fabric command access(invoke: administer) KeySetReadAllIndices(): KeySetReadAllIndicesResponse = 4; +} + +/** The Fixed Label Cluster provides a feature for the device to tag an endpoint with zero or more read only +labels. */ +cluster FixedLabel = 64 { + revision 1; // NOTE: Default/not specifically set + + struct LabelStruct { + char_string<16> label = 0; + char_string<16> value = 1; + } + + readonly attribute LabelStruct labelList[] = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** This cluster provides an interface to a boolean state called StateValue. */ +cluster BooleanState = 69 { + revision 1; + + info event StateChange = 0 { + boolean stateValue = 0; + } + + readonly attribute boolean stateValue = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting air quality classification */ +cluster AirQuality = 91 { + revision 1; // NOTE: Default/not specifically set + + enum AirQualityEnum : enum8 { + kUnknown = 0; + kGood = 1; + kFair = 2; + kModerate = 3; + kPoor = 4; + kVeryPoor = 5; + kExtremelyPoor = 6; + } + + bitmap Feature : bitmap32 { + kFair = 0x1; + kModerate = 0x2; + kVeryPoor = 0x4; + kExtremelyPoor = 0x8; + } + + readonly attribute AirQualityEnum airQuality = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes and commands for configuring the measurement of illuminance, and reporting illuminance measurements. */ +cluster IlluminanceMeasurement = 1024 { + revision 3; + + enum LightSensorTypeEnum : enum8 { + kPhotodiode = 0; + kCMOS = 1; + } + + readonly attribute nullable int16u measuredValue = 0; + readonly attribute nullable int16u minMeasuredValue = 1; + readonly attribute nullable int16u maxMeasuredValue = 2; + readonly attribute optional int16u tolerance = 3; + readonly attribute optional nullable LightSensorTypeEnum lightSensorType = 4; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes and commands for configuring the measurement of temperature, and reporting temperature measurements. */ +cluster TemperatureMeasurement = 1026 { + revision 1; // NOTE: Default/not specifically set + + readonly attribute nullable temperature measuredValue = 0; + readonly attribute nullable temperature minMeasuredValue = 1; + readonly attribute nullable temperature maxMeasuredValue = 2; + readonly attribute optional int16u tolerance = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes and commands for configuring the measurement of pressure, and reporting pressure measurements. */ +cluster PressureMeasurement = 1027 { + revision 3; + + bitmap Feature : bitmap32 { + kExtended = 0x1; + } + + readonly attribute nullable int16s measuredValue = 0; + readonly attribute nullable int16s minMeasuredValue = 1; + readonly attribute nullable int16s maxMeasuredValue = 2; + readonly attribute optional int16u tolerance = 3; + readonly attribute optional nullable int16s scaledValue = 16; + readonly attribute optional nullable int16s minScaledValue = 17; + readonly attribute optional nullable int16s maxScaledValue = 18; + readonly attribute optional int16u scaledTolerance = 19; + readonly attribute optional int8s scale = 20; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes and commands for configuring the measurement of flow, and reporting flow measurements. */ +cluster FlowMeasurement = 1028 { + revision 1; // NOTE: Default/not specifically set + + readonly attribute nullable int16u measuredValue = 0; + readonly attribute nullable int16u minMeasuredValue = 1; + readonly attribute nullable int16u maxMeasuredValue = 2; + readonly attribute optional int16u tolerance = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes and commands for configuring the measurement of relative humidity, and reporting relative humidity measurements. */ +cluster RelativeHumidityMeasurement = 1029 { + revision 3; + + readonly attribute nullable int16u measuredValue = 0; + readonly attribute nullable int16u minMeasuredValue = 1; + readonly attribute nullable int16u maxMeasuredValue = 2; + readonly attribute optional int16u tolerance = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** The server cluster provides an interface to occupancy sensing functionality based on one or more sensing modalities, including configuration and provision of notifications of occupancy status. */ +cluster OccupancySensing = 1030 { + revision 5; + + enum OccupancySensorTypeEnum : enum8 { + kPIR = 0; + kUltrasonic = 1; + kPIRAndUltrasonic = 2; + kPhysicalContact = 3; + } + + bitmap Feature : bitmap32 { + kOther = 0x1; + kPassiveInfrared = 0x2; + kUltrasonic = 0x4; + kPhysicalContact = 0x8; + kActiveInfrared = 0x10; + kRadar = 0x20; + kRFSensing = 0x40; + kVision = 0x80; + } + + bitmap OccupancyBitmap : bitmap8 { + kOccupied = 0x1; + } + + bitmap OccupancySensorTypeBitmap : bitmap8 { + kPIR = 0x1; + kUltrasonic = 0x2; + kPhysicalContact = 0x4; + } + + struct HoldTimeLimitsStruct { + int16u holdTimeMin = 0; + int16u holdTimeMax = 1; + int16u holdTimeDefault = 2; + } + + info event OccupancyChanged = 0 { + OccupancyBitmap occupancy = 0; + } + + readonly attribute OccupancyBitmap occupancy = 0; + readonly attribute OccupancySensorTypeEnum occupancySensorType = 1; + readonly attribute OccupancySensorTypeBitmap occupancySensorTypeBitmap = 2; + attribute access(write: manage) optional int16u holdTime = 3; + readonly attribute optional HoldTimeLimitsStruct holdTimeLimits = 4; + attribute access(write: manage) optional int16u PIROccupiedToUnoccupiedDelay = 16; + attribute access(write: manage) optional int16u PIRUnoccupiedToOccupiedDelay = 17; + attribute access(write: manage) optional int8u PIRUnoccupiedToOccupiedThreshold = 18; + attribute access(write: manage) optional int16u ultrasonicOccupiedToUnoccupiedDelay = 32; + attribute access(write: manage) optional int16u ultrasonicUnoccupiedToOccupiedDelay = 33; + attribute access(write: manage) optional int8u ultrasonicUnoccupiedToOccupiedThreshold = 34; + attribute access(write: manage) optional int16u physicalContactOccupiedToUnoccupiedDelay = 48; + attribute access(write: manage) optional int16u physicalContactUnoccupiedToOccupiedDelay = 49; + attribute access(write: manage) optional int8u physicalContactUnoccupiedToOccupiedThreshold = 50; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting carbon monoxide concentration measurements */ +cluster CarbonMonoxideConcentrationMeasurement = 1036 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting carbon dioxide concentration measurements */ +cluster CarbonDioxideConcentrationMeasurement = 1037 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting nitrogen dioxide concentration measurements */ +cluster NitrogenDioxideConcentrationMeasurement = 1043 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting ozone concentration measurements */ +cluster OzoneConcentrationMeasurement = 1045 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting PM2.5 concentration measurements */ +cluster Pm25ConcentrationMeasurement = 1066 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting formaldehyde concentration measurements */ +cluster FormaldehydeConcentrationMeasurement = 1067 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting PM1 concentration measurements */ +cluster Pm1ConcentrationMeasurement = 1068 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting PM10 concentration measurements */ +cluster Pm10ConcentrationMeasurement = 1069 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting total volatile organic compounds concentration measurements */ +cluster TotalVolatileOrganicCompoundsConcentrationMeasurement = 1070 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting radon concentration measurements */ +cluster RadonConcentrationMeasurement = 1071 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +endpoint 0 { + device type ma_rootdevice = 22, version 1; + + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster AccessControl { + emits event AccessControlEntryChanged; + emits event AccessControlExtensionChanged; + callback attribute acl; + callback attribute extension; + callback attribute subjectsPerAccessControlEntry; + callback attribute targetsPerAccessControlEntry; + callback attribute accessControlEntriesPerFabric; + callback attribute attributeList; + ram attribute featureMap default = 1; + callback attribute clusterRevision; + } + + server cluster BasicInformation { + emits event StartUp; + emits event ShutDown; + emits event Leave; + callback attribute dataModelRevision; + callback attribute vendorName; + callback attribute vendorID; + callback attribute productName; + callback attribute productID; + persist attribute nodeLabel; + callback attribute location; + callback attribute hardwareVersion; + callback attribute hardwareVersionString; + callback attribute softwareVersion; + callback attribute softwareVersionString; + callback attribute manufacturingDate; + callback attribute partNumber; + callback attribute productURL; + callback attribute productLabel; + callback attribute serialNumber; + persist attribute localConfigDisabled default = 0; + callback attribute uniqueID; + callback attribute capabilityMinima; + callback attribute specificationVersion; + callback attribute maxPathsPerInvoke; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 3; + } + + server cluster LocalizationConfiguration { + ram attribute activeLocale; + callback attribute supportedLocales; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster GeneralCommissioning { + ram attribute breadcrumb default = 0x0000000000000000; + callback attribute basicCommissioningInfo; + callback attribute regulatoryConfig; + callback attribute locationCapability; + callback attribute supportsConcurrentConnection; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 2; + + handle command ArmFailSafe; + handle command ArmFailSafeResponse; + handle command SetRegulatoryConfig; + handle command SetRegulatoryConfigResponse; + handle command CommissioningComplete; + handle command CommissioningCompleteResponse; + } + + 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; + ram attribute featureMap default = 1; + ram attribute clusterRevision default = 0x0001; + + handle command ScanNetworks; + handle command ScanNetworksResponse; + handle command AddOrUpdateWiFiNetwork; + handle command AddOrUpdateThreadNetwork; + handle command RemoveNetwork; + handle command NetworkConfigResponse; + handle command ConnectNetwork; + handle command ConnectNetworkResponse; + handle command ReorderNetwork; + } + + server cluster DiagnosticLogs { + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command RetrieveLogsRequest; + handle command RetrieveLogsResponse; + } + + server cluster GeneralDiagnostics { + emits event BootReason; + callback attribute networkInterfaces; + callback attribute rebootCount; + callback attribute upTime; + callback attribute totalOperationalHours; + callback attribute bootReason; + callback attribute activeHardwareFaults; + callback attribute activeRadioFaults; + callback attribute activeNetworkFaults; + callback attribute testEventTriggersEnabled default = false; + callback attribute featureMap; + callback attribute clusterRevision; + + handle command TestEventTrigger; + handle command TimeSnapshot; + handle command TimeSnapshotResponse; + } + + server cluster SoftwareDiagnostics { + callback attribute threadMetrics; + callback attribute currentHeapFree; + callback attribute currentHeapUsed; + callback attribute currentHeapHighWatermark; + callback attribute featureMap; + ram attribute clusterRevision default = 0x0001; + + handle command ResetWatermarks; + } + + server cluster AdministratorCommissioning { + callback attribute windowStatus; + callback attribute adminFabricIndex; + callback attribute adminVendorId; + ram attribute featureMap default = 1; + ram attribute clusterRevision default = 0x0001; + + handle command OpenCommissioningWindow; + handle command OpenBasicCommissioningWindow; + handle command RevokeCommissioning; + } + + server cluster OperationalCredentials { + callback attribute NOCs; + callback attribute fabrics; + callback attribute supportedFabrics; + callback attribute commissionedFabrics; + callback attribute trustedRootCertificates; + callback attribute currentFabricIndex; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 0x0001; + + handle command AttestationRequest; + handle command AttestationResponse; + handle command CertificateChainRequest; + handle command CertificateChainResponse; + handle command CSRRequest; + handle command CSRResponse; + handle command AddNOC; + handle command UpdateNOC; + handle command NOCResponse; + handle command UpdateFabricLabel; + handle command RemoveFabric; + handle command AddTrustedRootCertificate; + } + + server cluster GroupKeyManagement { + callback attribute groupKeyMap; + callback attribute groupTable; + callback attribute maxGroupsPerFabric; + callback attribute maxGroupKeysPerFabric; + callback attribute featureMap; + callback attribute clusterRevision; + + handle command KeySetWrite; + handle command KeySetRead; + handle command KeySetReadResponse; + handle command KeySetRemove; + handle command KeySetReadAllIndices; + handle command KeySetReadAllIndicesResponse; + } + + server cluster FixedLabel { + callback attribute labelList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } +} +endpoint 1 { + device type ma_contactsensor = 21, version 1; + + binding cluster Binding; + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 5; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster BooleanState { + ram attribute stateValue default = 0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } +} +endpoint 2 { + device type ma_lightsensor = 262, version 1; + + binding cluster Binding; + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 5; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster IlluminanceMeasurement { + ram attribute measuredValue default = 0xC351; + ram attribute minMeasuredValue default = 1; + ram attribute maxMeasuredValue default = 0xfffe; + ram attribute lightSensorType default = 1; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 3; + } +} +endpoint 3 { + device type ma_occupancysensor = 263, version 4; + + binding cluster Binding; + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 5; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster OccupancySensing { + ram attribute occupancy default = 0; + ram attribute occupancySensorType default = 0; + ram attribute occupancySensorTypeBitmap default = 0x1; + callback attribute holdTime; + callback attribute holdTimeLimits; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 5; + } +} +endpoint 4 { + device type ma_tempsensor = 770, version 1; + + binding cluster Binding; + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 5; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster TemperatureMeasurement { + ram attribute measuredValue default = 2350; + ram attribute minMeasuredValue default = -27315; + ram attribute maxMeasuredValue default = 32767; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 4; + } +} +endpoint 5 { + device type ma_pressuresensor = 773, version 1; + + binding cluster Binding; + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 5; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster PressureMeasurement { + ram attribute measuredValue default = 0xA; + ram attribute minMeasuredValue default = 1; + ram attribute maxMeasuredValue default = 32767; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 3; + } +} +endpoint 6 { + device type ma_flowsensor = 774, version 1; + + binding cluster Binding; + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 5; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster FlowMeasurement { + ram attribute measuredValue default = 0xA; + ram attribute minMeasuredValue default = 0x1; + ram attribute maxMeasuredValue default = 0xFFF; + ram attribute tolerance default = 8; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 3; + } +} +endpoint 7 { + device type ma_humiditysensor = 775, version 1; + + binding cluster Binding; + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 5; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster RelativeHumidityMeasurement { + ram attribute measuredValue default = 0x11d0; + ram attribute minMeasuredValue default = 0x1; + ram attribute maxMeasuredValue default = 0x2710; + ram attribute tolerance default = 8; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 3; + } +} +endpoint 8 { + device type ma_air_quality_sensor = 44, version 1; + + binding cluster Binding; + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x00; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 5; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster AirQuality { + callback attribute airQuality; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster CarbonMonoxideConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster CarbonDioxideConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster NitrogenDioxideConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster OzoneConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster Pm25ConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster FormaldehydeConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster Pm1ConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster Pm10ConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster TotalVolatileOrganicCompoundsConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster RadonConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } +} +endpoint 9 { + device type ma_powersource = 17, version 1; + + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster PowerSource { + ram attribute status default = 1; + persist attribute order default = 1; + ram attribute description default = "Battery"; + ram attribute batVoltage default = 2590; + ram attribute batPercentRemaining default = 98; + ram attribute batTimeRemaining default = 52560000; + ram attribute batChargeLevel default = 0; + ram attribute batReplacementNeeded default = 0; + ram attribute batReplaceability default = 2; + ram attribute batPresent default = 1; + ram attribute batReplacementDescription default = "2x AA/LR6 Alkaline"; + ram attribute batCommonDesignation default = 2; + ram attribute batApprovedChemistry default = 1; + ram attribute batQuantity; + callback attribute endpointList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0x0A; + ram attribute clusterRevision default = 1; + } +} + + diff --git a/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.zap b/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.zap new file mode 100644 index 00000000000000..05d1c22eb23062 --- /dev/null +++ b/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.zap @@ -0,0 +1,9272 @@ +{ + "fileFormat": 2, + "featureLevel": 104, + "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", + "category": "matter", + "version": "chip-v1" + } + ], + "endpointTypes": [ + { + "id": 1, + "name": "MA-rootdevice", + "deviceTypeRef": { + "code": 22, + "profileId": 259, + "label": "MA-rootdevice", + "name": "MA-rootdevice", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 22, + "profileId": 259, + "label": "MA-rootdevice", + "name": "MA-rootdevice", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 22 + ], + "deviceTypeName": "MA-rootdevice", + "deviceTypeCode": 22, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": "1", + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "AccessControlEntryChanged", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "AccessControlExtensionChanged", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Basic Information", + "code": 40, + "mfgCode": null, + "define": "BASIC_INFORMATION_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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": "UniqueID", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CapabilityMinima", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "CapabilityMinimaStruct", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SpecificationVersion", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxPathsPerInvoke", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "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": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "StartUp", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "ShutDown", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "Leave", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "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": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "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": null, + "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": null, + "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": null, + "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": null, + "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": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ArmFailSafe", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ArmFailSafeResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "SetRegulatoryConfig", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "SetRegulatoryConfigResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "CommissioningComplete", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "CommissioningCompleteResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 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": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RegulatoryConfig", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationTypeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LocationCapability", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationTypeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ScanNetworks", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ScanNetworksResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "AddOrUpdateWiFiNetwork", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "AddOrUpdateThreadNetwork", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RemoveNetwork", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "NetworkConfigResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ConnectNetwork", + "code": 6, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ConnectNetworkResponse", + "code": 7, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ReorderNetwork", + "code": 8, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 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": null, + "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": "NetworkCommissioningStatusEnum", + "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": "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": "0x0001", + "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", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RetrieveLogsResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "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": "server", + "enabled": 1, + "commands": [ + { + "name": "TestEventTrigger", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TimeSnapshot", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TimeSnapshotResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "NetworkInterfaces", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BootReason", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "BootReasonEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "BootReason", + "code": 3, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Software Diagnostics", + "code": 52, + "mfgCode": null, + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ResetWatermarks", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "ThreadMetrics", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": "0x0001", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Administrator Commissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "WindowStatus", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "CommissioningWindowStatusEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminVendorId", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": "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": "0x0001", + "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": "AttestationRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "AttestationResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "CertificateChainRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "CertificateChainResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "CSRRequest", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "CSRResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "AddNOC", + "code": 6, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "UpdateNOC", + "code": 7, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "NOCResponse", + "code": 8, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "UpdateFabricLabel", + "code": 9, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RemoveFabric", + "code": 10, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "AddTrustedRootCertificate", + "code": 11, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "NOCs", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": "0x0001", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "KeySetWrite", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetRead", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "KeySetRemove", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadAllIndices", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadAllIndicesResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "GroupKeyMap", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "LabelList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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 + } + ] + } + ] + }, + { + "id": 2, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 21, + "profileId": 259, + "label": "MA-contactsensor", + "name": "MA-contactsensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 21, + "profileId": 259, + "label": "MA-contactsensor", + "name": "MA-contactsensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 21 + ], + "deviceTypeName": "MA-contactsensor", + "deviceTypeCode": 21, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "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": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "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": null, + "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": null, + "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": null, + "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": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 1 + }, + { + "name": "Boolean State", + "code": 69, + "mfgCode": null, + "define": "BOOLEAN_STATE_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "StateValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "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": null, + "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": null, + "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": null, + "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 + } + ] + } + ] + }, + { + "id": 3, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 262, + "profileId": 259, + "label": "MA-lightsensor", + "name": "MA-lightsensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 262, + "profileId": 259, + "label": "MA-lightsensor", + "name": "MA-lightsensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 262 + ], + "deviceTypeName": "MA-lightsensor", + "deviceTypeCode": 262, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "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": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "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": null, + "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": null, + "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": null, + "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": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 1 + }, + { + "name": "Illuminance Measurement", + "code": 1024, + "mfgCode": null, + "define": "ILLUMINANCE_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xC351", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "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": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xfffe", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LightSensorType", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "LightSensorTypeEnum", + "included": 1, + "storageOption": "RAM", + "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": null, + "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": null, + "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": null, + "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": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 4, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 263, + "profileId": 259, + "label": "MA-occupancysensor", + "name": "MA-occupancysensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 263, + "profileId": 259, + "label": "MA-occupancysensor", + "name": "MA-occupancysensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 4 + ], + "deviceIdentifiers": [ + 263 + ], + "deviceTypeName": "MA-occupancysensor", + "deviceTypeCode": 263, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "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": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "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": null, + "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": null, + "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": null, + "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": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 1 + }, + { + "name": "Occupancy Sensing", + "code": 1030, + "mfgCode": null, + "define": "OCCUPANCY_SENSING_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Occupancy", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "OccupancyBitmap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OccupancySensorType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "OccupancySensorTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OccupancySensorTypeBitmap", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "OccupancySensorTypeBitmap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "HoldTime", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "HoldTimeLimits", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "HoldTimeLimitsStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 5, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 770, + "profileId": 259, + "label": "MA-tempsensor", + "name": "MA-tempsensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 770, + "profileId": 259, + "label": "MA-tempsensor", + "name": "MA-tempsensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 770 + ], + "deviceTypeName": "MA-tempsensor", + "deviceTypeCode": 770, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "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": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "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": null, + "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": null, + "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": null, + "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": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 1 + }, + { + "name": "Temperature Measurement", + "code": 1026, + "mfgCode": null, + "define": "TEMPERATURE_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "temperature", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2350", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "temperature", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "-27315", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "temperature", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "32767", + "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": null, + "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": null, + "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": null, + "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": "4", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 6, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 773, + "profileId": 259, + "label": "MA-pressuresensor", + "name": "MA-pressuresensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 773, + "profileId": 259, + "label": "MA-pressuresensor", + "name": "MA-pressuresensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 773 + ], + "deviceTypeName": "MA-pressuresensor", + "deviceTypeCode": 773, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "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": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "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": null, + "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": null, + "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": null, + "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": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 1 + }, + { + "name": "Pressure Measurement", + "code": 1027, + "mfgCode": null, + "define": "PRESSURE_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xA", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "32767", + "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": null, + "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": null, + "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": null, + "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": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 7, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 774, + "profileId": 259, + "label": "MA-flowsensor", + "name": "MA-flowsensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 774, + "profileId": 259, + "label": "MA-flowsensor", + "name": "MA-flowsensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 774 + ], + "deviceTypeName": "MA-flowsensor", + "deviceTypeCode": 774, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "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": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "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": null, + "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": null, + "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": null, + "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": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 1 + }, + { + "name": "Flow Measurement", + "code": 1028, + "mfgCode": null, + "define": "FLOW_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xA", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFF", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "8", + "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": null, + "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": null, + "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": null, + "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": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 8, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 775, + "profileId": 259, + "label": "MA-humiditysensor", + "name": "MA-humiditysensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 775, + "profileId": 259, + "label": "MA-humiditysensor", + "name": "MA-humiditysensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 775 + ], + "deviceTypeName": "MA-humiditysensor", + "deviceTypeCode": 775, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "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": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "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": null, + "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": null, + "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": null, + "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": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 1 + }, + { + "name": "Relative Humidity Measurement", + "code": 1029, + "mfgCode": null, + "define": "RELATIVE_HUMIDITY_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x11d0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x2710", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "8", + "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": null, + "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": null, + "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": null, + "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": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 9, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 44, + "profileId": 259, + "label": "MA-air-quality-sensor", + "name": "MA-air-quality-sensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 44, + "profileId": 259, + "label": "MA-air-quality-sensor", + "name": "MA-air-quality-sensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 44 + ], + "deviceTypeName": "MA-air-quality-sensor", + "deviceTypeCode": 44, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "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": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "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": null, + "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": null, + "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": null, + "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": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 1 + }, + { + "name": "Air Quality", + "code": 91, + "mfgCode": null, + "define": "AIR_QUALITY_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "AirQuality", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "AirQualityEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": "Carbon Monoxide Concentration Measurement", + "code": 1036, + "mfgCode": null, + "define": "CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Carbon Dioxide Concentration Measurement", + "code": 1037, + "mfgCode": null, + "define": "CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Nitrogen Dioxide Concentration Measurement", + "code": 1043, + "mfgCode": null, + "define": "NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Ozone Concentration Measurement", + "code": 1045, + "mfgCode": null, + "define": "OZONE_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "PM2.5 Concentration Measurement", + "code": 1066, + "mfgCode": null, + "define": "PM2_5_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Formaldehyde Concentration Measurement", + "code": 1067, + "mfgCode": null, + "define": "FORMALDEHYDE_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "PM1 Concentration Measurement", + "code": 1068, + "mfgCode": null, + "define": "PM1_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "PM10 Concentration Measurement", + "code": 1069, + "mfgCode": null, + "define": "PM10_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Total Volatile Organic Compounds Concentration Measurement", + "code": 1070, + "mfgCode": null, + "define": "TVOC_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Radon Concentration Measurement", + "code": 1071, + "mfgCode": null, + "define": "RADON_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 10, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 17, + "profileId": 259, + "label": "MA-powersource", + "name": "MA-powersource", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 17, + "profileId": 259, + "label": "MA-powersource", + "name": "MA-powersource", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 17 + ], + "deviceTypeName": "MA-powersource", + "deviceTypeCode": 17, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": null, + "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": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Power Source", + "code": 47, + "mfgCode": null, + "define": "POWER_SOURCE_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Status", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "PowerSourceStatusEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Order", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Description", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "Battery", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatVoltage", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2590", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatPercentRemaining", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "98", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatTimeRemaining", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "52560000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatChargeLevel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "BatChargeLevelEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplacementNeeded", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplaceability", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "BatReplaceabilityEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatPresent", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplacementDescription", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2x AA/LR6 Alkaline", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatCommonDesignation", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "BatCommonDesignationEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatApprovedChemistry", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "BatApprovedChemistryEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatQuantity", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EndpointList", + "code": 31, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "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": null, + "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": null, + "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": null, + "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": "0x0A", + "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 + } + ] + } + ] + } + ], + "endpoints": [ + { + "endpointTypeName": "MA-rootdevice", + "endpointTypeIndex": 0, + "profileId": 259, + "endpointId": 0, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 1, + "profileId": 259, + "endpointId": 1, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 2, + "profileId": 259, + "endpointId": 2, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 3, + "profileId": 259, + "endpointId": 3, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 4, + "profileId": 259, + "endpointId": 4, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 5, + "profileId": 259, + "endpointId": 5, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 6, + "profileId": 259, + "endpointId": 6, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 7, + "profileId": 259, + "endpointId": 7, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 8, + "profileId": 259, + "endpointId": 8, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 9, + "profileId": 259, + "endpointId": 9, + "networkId": 0, + "parentEndpointIdentifier": null + } + ] +} \ No newline at end of file From be06550ff895afe52bd55f72607b2dfae0f59225 Mon Sep 17 00:00:00 2001 From: PeterC1965 <101805108+PeterC1965@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:26:05 +0000 Subject: [PATCH 14/27] FIX TC_EEVSE_2_3 test fail when run in EST timezone (#36500) * Ensure calculation of target_time_delta in compute_expected_target_time_as_epoch_s is done fully in UTC * Restyled by autopep8 --------- Co-authored-by: Restyled.io --- src/python_testing/TC_EEVSE_2_3.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/python_testing/TC_EEVSE_2_3.py b/src/python_testing/TC_EEVSE_2_3.py index eb4e43d0b50105..54c5baa1a7ddff 100644 --- a/src/python_testing/TC_EEVSE_2_3.py +++ b/src/python_testing/TC_EEVSE_2_3.py @@ -194,8 +194,10 @@ def compute_expected_target_time_as_epoch_s(self, minutes_past_midnight): f"{int(minutes_past_midnight/60)}:{int(minutes_past_midnight%60)}" f" Expected target_time = {target_time}") - target_time_delta = target_time - \ - datetime(2000, 1, 1, 0, 0, 0, 0).astimezone(timezone.utc) + matter_base_time = datetime(2000, 1, 1, 0, 0, 0, 0, tzinfo=timezone.utc) + + target_time_delta = target_time - matter_base_time + expected_target_time_epoch_s = int(target_time_delta.total_seconds()) return expected_target_time_epoch_s From a6253abcf7b33c3150400ea2d31c3a494d8008b7 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 15 Nov 2024 12:27:31 -0500 Subject: [PATCH 15/27] Improve detection of "historical" events in Matter.framework. (#36506) We were marking events as "historical" if there were any attributes in the same report that have the C quality. This had a few problems: * Some devices randomly report C-quality attributes, for various reasons. * Some attributes stop having the C quality in favor of Q, in some cases, so this is not very forward-compatible. The fix is to remove this C-quality check altogether. At that point we have the following situations: 1. We're setting up a new subscription and getting our initial priming report. This case will still have _receivingPrimingReport set, and will cause any events reported as part of priming to be marked "historical". 2. We are getting a "priming" report from a server-side subscription resumption after the server timed out on a subscription. If this happens before the max-interval elapses, we will see this as a normal report on our subscription, but with all attributes and events the server knows about included. In this case, we mark ourselves as being in a "priming report" if we get an event that has an event number we have already seen, so that we mark any not-seen-before events in that report as "historical", since we don't know how long ago they are from. 3. We are getting a normal incremental report, and will not mark any such events as "historical". Since we are now keeping track of last-received event numbers, we can also use those for our subscriptions and can filter out any events that have an event number no greater than our last-observed one. --- .../Framework/CHIP/MTRDevice_Concrete.mm | 76 +++++++++++++++---- .../Framework/CHIPTests/MTRDeviceTests.m | 74 +++++++++++++++++- 2 files changed, 135 insertions(+), 15 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm index 9169507634a88b..35cfbcf7d8ceb1 100644 --- a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm +++ b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm @@ -219,7 +219,23 @@ @interface MTRDevice_Concrete () @property (nonatomic, readonly) os_unfair_lock timeSyncLock; @property (nonatomic) NSMutableArray *> * unreportedEvents; + +// The highest event number we have observed, if there was one at all. +@property (nonatomic, readwrite, nullable) NSNumber * highestObservedEventNumber; + +// receivingReport is true if we are receving a subscription report. In +// particular, this will be false if we're just getting an attribute value from +// a read-through. @property (nonatomic) BOOL receivingReport; + +// receivingPrimingReport is true if this subscription report is part of us +// establishing a new subscription to the device. When this is true, it is +// _not_ guaranteed that any particular set of attributes will be reported +// (e.g. everything could be filtered out by our DataVersion filters). +// Conversely, when this is false that tells us nothing about attributes _not_ +// being reported: a device could randomly decide to rev all data versions and +// report all attributes at any point in time, for example due to performing +// subscription resumption. @property (nonatomic) BOOL receivingPrimingReport; // TODO: instead of all the BOOL properties that are some facet of the state, move to internal state machine that has (at least): @@ -390,6 +406,7 @@ - (instancetype)initWithNodeID:(NSNumber *)nodeID controller:(MTRDeviceControlle } _clusterDataToPersist = nil; _persistedClusters = [NSMutableSet set]; + _highestObservedEventNumber = nil; // If there is a data store, make sure we have an observer to monitor system clock changes, so // NSDate-based write coalescing could be reset and not get into a bad state. @@ -1954,11 +1971,14 @@ - (void)_injectEventReport:(NSArray *)eventRep return; } - // [_deviceController asyncDispatchToMatterQueue:^{ // TODO: This wasn't used previously, not sure why, so keeping it here for thought, but preserving existing behavior + [self _injectPossiblyInvalidEventReport:eventReport]; +} + +- (void)_injectPossiblyInvalidEventReport:(NSArray *)eventReport +{ dispatch_async(self.queue, ^{ [self _handleEventReport:eventReport]; }); - // } errorHandler: nil]; } // END DRAGON: This is used by the XPC Server to inject attribute reports @@ -1966,7 +1986,9 @@ - (void)_injectEventReport:(NSArray *)eventRep #ifdef DEBUG - (void)unitTestInjectEventReport:(NSArray *> *)eventReport { - [self _injectEventReport:eventReport]; + // Don't validate incoming event reports for unit tests, because we want to + // allow incoming event reports without an MTREventIsHistoricalKey. + [self _injectPossiblyInvalidEventReport:eventReport]; } - (void)unitTestInjectAttributeReport:(NSArray *> *)attributeReport fromSubscription:(BOOL)isFromSubscription @@ -2102,11 +2124,33 @@ - (void)_handleEventReport:(NSArray *> *)eventRepor } } - NSMutableDictionary * eventToReturn = eventDict.mutableCopy; - if (_receivingPrimingReport) { - eventToReturn[MTREventIsHistoricalKey] = @(YES); + auto * eventNumber = MTR_SAFE_CAST(eventDict[MTREventNumberKey], NSNumber); + if (!eventNumber) { + MTR_LOG_ERROR("%@ Event %@ missing event number", self, eventDict); + continue; + } + + if (!self.highestObservedEventNumber || + [self.highestObservedEventNumber compare:eventNumber] == NSOrderedAscending) { + // This is an event we have not seen before. + self.highestObservedEventNumber = eventNumber; } else { - eventToReturn[MTREventIsHistoricalKey] = @(NO); + // We have seen this event already; just filter it out. But also, we must be getting + // some sort of priming report if we are getting events we have seen before. + if (_receivingReport) { + _receivingPrimingReport = YES; + } + continue; + } + + NSMutableDictionary * eventToReturn = eventDict.mutableCopy; + // If MTREventIsHistoricalKey is already present, do not mess with the value. + if (eventToReturn[MTREventIsHistoricalKey] == nil) { + if (_receivingPrimingReport) { + eventToReturn[MTREventIsHistoricalKey] = @(YES); + } else { + eventToReturn[MTREventIsHistoricalKey] = @(NO); + } } [reportToReturn addObject:eventToReturn]; @@ -2558,8 +2602,15 @@ - (void)_setupSubscriptionWithReason:(NSString *)reason // Set up a cluster state cache. We just want this for the logic it has for // tracking data versions and event numbers so we minimize the amount of data we // request on resubscribes, so tell it not to store data. + Optional highestObservedEventNumber; + { + std::lock_guard lock(self->_lock); + if (self.highestObservedEventNumber) { + highestObservedEventNumber = MakeOptional(self.highestObservedEventNumber.unsignedLongLongValue); + } + } auto clusterStateCache = std::make_unique(*callback.get(), - /* highestReceivedEventNumber = */ NullOptional, + highestObservedEventNumber, /* cacheData = */ false); auto readClient = std::make_unique(InteractionModelEngine::GetInstance(), exchangeManager, clusterStateCache->GetBufferedCallback(), ReadClient::InteractionType::Subscribe); @@ -2609,6 +2660,10 @@ - (void)_setupSubscriptionWithReason:(NSString *)reason attributePath.release(); eventPath.release(); + // NOTE: We don't set the event number field in readParams, and just let + // the ReadClient get the min event number information from the cluster + // state cache. + // TODO: Change from local filter list generation to rehydrating ClusterStateCache to take advantage of existing filter list sorting algorithm // SendAutoResubscribeRequest cleans up the params, even on failure. @@ -3587,11 +3642,6 @@ - (NSArray *)_getAttributesToReportWithReportedValues:(NSArray *> * eventReport) { eventReportsReceived += eventReport.count; @@ -1489,6 +1490,7 @@ - (void)test017_TestMTRDeviceBasics if (!reportEnded) { NSNumber * reportIsHistorical = eventDict[MTREventIsHistoricalKey]; XCTAssertTrue(reportIsHistorical.boolValue); + lastObservedEventNumber = eventDict[MTREventNumberKey]; } else { if (!gotOneNonPrimingEvent) { NSNumber * reportIsHistorical = eventDict[MTREventIsHistoricalKey]; @@ -1509,7 +1511,7 @@ - (void)test017_TestMTRDeviceBasics MTREventTimestampDateKey : [NSDate date], MTREventIsHistoricalKey : @(NO), MTREventPriorityKey : @(MTREventPriorityInfo), - MTREventNumberKey : @(1), // Doesn't matter, in practice + MTREventNumberKey : @(lastObservedEventNumber.unsignedLongLongValue + 1), MTRDataKey : @ { MTRTypeKey : MTRStructureValueType, MTRValueKey : @[], @@ -3899,6 +3901,70 @@ - (void)test034_TestMTRDeviceHistoricalEvents // Must have gotten some events (at least StartUp!) XCTAssertTrue(eventReportsReceived > 0); + + // Now try doing some event injection. + __block uint64_t eventNumber = 0x1000000; // Should't have that many events on the device yet! + __block uint64_t firstNewEventNumber = eventNumber; + __auto_type createEventReport = ^{ + return @{ + MTREventPathKey : [MTREventPath eventPathWithEndpointID:@(1) clusterID:@(1) eventID:@(1)], + MTREventTimeTypeKey : @(MTREventTimeTypeTimestampDate), + MTREventTimestampDateKey : [NSDate date], + MTREventPriorityKey : @(MTREventPriorityInfo), + MTREventNumberKey : @(eventNumber++), + MTRDataKey : @ { + MTRTypeKey : MTRStructureValueType, + MTRValueKey : @[], + }, + }; + }; + + eventReportsReceived = 0; + const int eventReportsToInject = 5; + __block XCTestExpectation * eventReportsFinishedExpectation = [self expectationWithDescription:@"Injecting some new event reports"]; + __block int historicalEvents = 0; + __block int eventReportsToExpect = eventReportsToInject; + + delegate.onEventDataReceived = ^(NSArray *> * eventReport) { + eventReportsReceived += eventReport.count; + for (NSDictionary * eventDict in eventReport) { + NSNumber * reportIsHistorical = eventDict[MTREventIsHistoricalKey]; + NSNumber * eventNumber = eventDict[MTREventNumberKey]; + XCTAssertEqual(reportIsHistorical.boolValue, eventNumber.unsignedLongLongValue < firstNewEventNumber, + @"eventNumber: %@, firstNewEventNumber: %llu", eventNumber, firstNewEventNumber); + historicalEvents += reportIsHistorical.boolValue; + } + + if (eventReportsReceived >= eventReportsToExpect) { + [eventReportsFinishedExpectation fulfill]; + } + }; + + for (int i = 0; i < eventReportsToInject; ++i) { + [device unitTestInjectEventReport:@[ createEventReport() ]]; + } + + [self waitForExpectations:@[ eventReportsFinishedExpectation ] timeout:kTimeoutInSeconds]; + XCTAssertEqual(historicalEvents, 0); + + // Now inject some mix of historical and non-historical events. Since this + // includes events with old event numbers, those should get filtered out + // from reporting. + const uint64_t expectedHistoricalEvents = 2; + firstNewEventNumber = eventNumber; + eventNumber -= expectedHistoricalEvents; + eventReportsReceived = 0; + historicalEvents = 0; + // Events with already-observed event numbers do not get reported. + eventReportsToExpect = eventReportsToInject - expectedHistoricalEvents; + eventReportsFinishedExpectation = [self expectationWithDescription:@"Injecting a mix of old and new reports"]; + + for (int i = 0; i < eventReportsToInject; ++i) { + [device unitTestInjectEventReport:@[ createEventReport() ]]; + } + + [self waitForExpectations:@[ eventReportsFinishedExpectation ] timeout:kTimeoutInSeconds]; + XCTAssertEqual(historicalEvents, 0); } - (void)test035_TestMTRDeviceSubscriptionNotEstablishedOverXPC @@ -4266,13 +4332,17 @@ - (void)test037_MTRDeviceMultipleDelegatesGetReports - (NSDictionary *)_testEventResponseValueWithEndpointID:(NSNumber *)endpointID clusterID:(NSNumber *)clusterID eventID:(NSNumber *)eventID { + // Pick a large event number, so that in practice these event reports will + // all have larger event numbers than anything that might have been observed + // before. + static uint64_t eventNumber = 0x100000000llu; return @{ MTREventPathKey : [MTREventPath eventPathWithEndpointID:endpointID clusterID:clusterID eventID:eventID], MTREventTimeTypeKey : @(MTREventTimeTypeTimestampDate), MTREventTimestampDateKey : [NSDate date], MTREventIsHistoricalKey : @(NO), MTREventPriorityKey : @(MTREventPriorityInfo), - MTREventNumberKey : @(1), // Doesn't matter, in practice + MTREventNumberKey : @(eventNumber++), // Empty payload. MTRDataKey : @ { MTRTypeKey : MTRStructureValueType, From 3efd3d6654dd75b3867f4f412279c82d5b91f207 Mon Sep 17 00:00:00 2001 From: Vatsal Ghelani <152916324+vatsalghelani-csa@users.noreply.github.com> Date: Fri, 15 Nov 2024 12:36:17 -0500 Subject: [PATCH 16/27] Added the data_model_xmls.gni within matter testing infrastructure for data model python packaging (#36499) * Added data models gni file and consumed it using via BUILD.gn * Update build_python.sh with chip testing wheel modifications * Restyled by gn --------- Co-authored-by: Restyled.io --- scripts/build_python.sh | 2 +- .../matter_testing_infrastructure/BUILD.gn | 37 +- .../data_model_xmls.gni | 564 ++++++++++++++++++ .../pyproject.toml | 17 - .../matter_testing_infrastructure/setup.cfg | 21 - .../matter_testing_infrastructure/setup.py | 17 - 6 files changed, 594 insertions(+), 64 deletions(-) create mode 100644 src/python_testing/matter_testing_infrastructure/data_model_xmls.gni delete mode 100644 src/python_testing/matter_testing_infrastructure/pyproject.toml delete mode 100644 src/python_testing/matter_testing_infrastructure/setup.cfg delete mode 100644 src/python_testing/matter_testing_infrastructure/setup.py diff --git a/scripts/build_python.sh b/scripts/build_python.sh index 7f03815f3fe7e3..649aeeeec19357 100755 --- a/scripts/build_python.sh +++ b/scripts/build_python.sh @@ -182,7 +182,7 @@ ninja -C "$OUTPUT_ROOT" python_wheels WHEEL=("$OUTPUT_ROOT"/controller/python/chip*.whl) # Add the matter_testing_infrastructure wheel -WHEEL+=("$OUTPUT_ROOT"/python/obj/src/python_testing/matter_testing_infrastructure/chip-testing._build_wheel/chip_testing-*.whl) +WHEEL+=("$OUTPUT_ROOT"/obj/src/python_testing/matter_testing_infrastructure/chip-testing._build_wheel/chip_testing*.whl) if [ "$install_pytest_requirements" = "yes" ]; then # Add the matter_yamltests_distribution wheel diff --git a/src/python_testing/matter_testing_infrastructure/BUILD.gn b/src/python_testing/matter_testing_infrastructure/BUILD.gn index 19c7aee68defd9..64e27b47bb0a5d 100644 --- a/src/python_testing/matter_testing_infrastructure/BUILD.gn +++ b/src/python_testing/matter_testing_infrastructure/BUILD.gn @@ -14,16 +14,21 @@ import("//build_overrides/build.gni") import("//build_overrides/chip.gni") - import("//build_overrides/pigweed.gni") +import("//src/python_testing/matter_testing_infrastructure/data_model_xmls.gni") import("$dir_pw_build/python.gni") +import("$dir_pw_build/python_dist.gni") -pw_python_package("chip-testing") { - setup = [ - "setup.py", - "setup.cfg", - "pyproject.toml", - ] +pw_python_package("chip-testing-module") { + generate_setup = { + metadata = { + name = "chip-testing-module" + version = "1.4.0" + author = "Project CHIP Authors" + license_expression = "Apache-2.0" # Consistent license format + url = "https://github.com/project-chip/connectedhomeip" + } + } inputs = [ "env_test.yaml" ] @@ -41,9 +46,25 @@ pw_python_package("chip-testing") { "chip/testing/taglist_and_topology_test.py", "chip/testing/tasks.py", ] - tests = [ "chip/testing/test_metadata.py", "chip/testing/test_tasks.py", ] } + +pw_python_distribution("chip-testing") { + packages = [ ":chip-testing-module" ] + + generate_setup_cfg = { + name = "chip-testing" + version = "1.4.0" + include_default_pyproject_file = true + include_extra_files_in_package_data = true + } + + # Use the imported data_model_XMLS directly + extra_files = [] + foreach(file, data_model_XMLS) { + extra_files += [ "${file} > chip/testing/${file}" ] + } +} diff --git a/src/python_testing/matter_testing_infrastructure/data_model_xmls.gni b/src/python_testing/matter_testing_infrastructure/data_model_xmls.gni new file mode 100644 index 00000000000000..066537816a5c9a --- /dev/null +++ b/src/python_testing/matter_testing_infrastructure/data_model_xmls.gni @@ -0,0 +1,564 @@ +# Copyright (c) 2024 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") + +data_model_XMLS = [ + "${chip_root}/data_model/1.3/clusters/ACL-Cluster.xml", + "${chip_root}/data_model/1.3/clusters/AccountLogin.xml", + "${chip_root}/data_model/1.3/clusters/AdminCommissioningCluster.xml", + "${chip_root}/data_model/1.3/clusters/AirQuality.xml", + "${chip_root}/data_model/1.3/clusters/AlarmBase.xml", + "${chip_root}/data_model/1.3/clusters/ApplicationBasic.xml", + "${chip_root}/data_model/1.3/clusters/ApplicationLauncher.xml", + "${chip_root}/data_model/1.3/clusters/AudioOutput.xml", + "${chip_root}/data_model/1.3/clusters/BallastConfiguration.xml", + "${chip_root}/data_model/1.3/clusters/BasicInformationCluster.xml", + "${chip_root}/data_model/1.3/clusters/Binding-Cluster.xml", + "${chip_root}/data_model/1.3/clusters/BooleanState.xml", + "${chip_root}/data_model/1.3/clusters/BooleanStateConfiguration.xml", + "${chip_root}/data_model/1.3/clusters/Channel.xml", + "${chip_root}/data_model/1.3/clusters/ColorControl.xml", + "${chip_root}/data_model/1.3/clusters/ConcentrationMeasurement.xml", + "${chip_root}/data_model/1.3/clusters/ContentAppObserver.xml", + "${chip_root}/data_model/1.3/clusters/ContentControl.xml", + "${chip_root}/data_model/1.3/clusters/ContentLauncher.xml", + "${chip_root}/data_model/1.3/clusters/Descriptor-Cluster.xml", + "${chip_root}/data_model/1.3/clusters/DeviceEnergyManagement.xml", + "${chip_root}/data_model/1.3/clusters/DiagnosticLogsCluster.xml", + "${chip_root}/data_model/1.3/clusters/DiagnosticsEthernet.xml", + "${chip_root}/data_model/1.3/clusters/DiagnosticsGeneral.xml", + "${chip_root}/data_model/1.3/clusters/DiagnosticsSoftware.xml", + "${chip_root}/data_model/1.3/clusters/DiagnosticsThread.xml", + "${chip_root}/data_model/1.3/clusters/DiagnosticsWiFi.xml", + "${chip_root}/data_model/1.3/clusters/DishwasherAlarm.xml", + "${chip_root}/data_model/1.3/clusters/DoorLock.xml", + "${chip_root}/data_model/1.3/clusters/ElectricalEnergyMeasurement.xml", + "${chip_root}/data_model/1.3/clusters/ElectricalPowerMeasurement.xml", + "${chip_root}/data_model/1.3/clusters/EnergyEVSE.xml", + "${chip_root}/data_model/1.3/clusters/EnergyPreference.xml", + "${chip_root}/data_model/1.3/clusters/FanControl.xml", + "${chip_root}/data_model/1.3/clusters/FlowMeasurement.xml", + "${chip_root}/data_model/1.3/clusters/GeneralCommissioningCluster.xml", + "${chip_root}/data_model/1.3/clusters/Group-Key-Management-Cluster.xml", + "${chip_root}/data_model/1.3/clusters/Groups.xml", + "${chip_root}/data_model/1.3/clusters/ICDManagement.xml", + "${chip_root}/data_model/1.3/clusters/Identify.xml", + "${chip_root}/data_model/1.3/clusters/IlluminanceMeasurement.xml", + "${chip_root}/data_model/1.3/clusters/KeypadInput.xml", + "${chip_root}/data_model/1.3/clusters/Label-Cluster-FixedLabelCluster.xml", + "${chip_root}/data_model/1.3/clusters/Label-Cluster-LabelCluster.xml", + "${chip_root}/data_model/1.3/clusters/Label-Cluster-UserLabelCluster.xml", + "${chip_root}/data_model/1.3/clusters/LaundryDryerControls.xml", + "${chip_root}/data_model/1.3/clusters/LaundryWasherControls.xml", + "${chip_root}/data_model/1.3/clusters/LevelControl.xml", + "${chip_root}/data_model/1.3/clusters/LocalizationConfiguration.xml", + "${chip_root}/data_model/1.3/clusters/LocalizationTimeFormat.xml", + "${chip_root}/data_model/1.3/clusters/LocalizationUnit.xml", + "${chip_root}/data_model/1.3/clusters/LowPower.xml", + "${chip_root}/data_model/1.3/clusters/MediaInput.xml", + "${chip_root}/data_model/1.3/clusters/MediaPlayback.xml", + "${chip_root}/data_model/1.3/clusters/Messages.xml", + "${chip_root}/data_model/1.3/clusters/MicrowaveOvenControl.xml", + "${chip_root}/data_model/1.3/clusters/ModeBase.xml", + "${chip_root}/data_model/1.3/clusters/ModeSelect.xml", + "${chip_root}/data_model/1.3/clusters/Mode_DeviceEnergyManagement.xml", + "${chip_root}/data_model/1.3/clusters/Mode_Dishwasher.xml", + "${chip_root}/data_model/1.3/clusters/Mode_EVSE.xml", + "${chip_root}/data_model/1.3/clusters/Mode_LaundryWasher.xml", + "${chip_root}/data_model/1.3/clusters/Mode_MicrowaveOven.xml", + "${chip_root}/data_model/1.3/clusters/Mode_Oven.xml", + "${chip_root}/data_model/1.3/clusters/Mode_RVCClean.xml", + "${chip_root}/data_model/1.3/clusters/Mode_RVCRun.xml", + "${chip_root}/data_model/1.3/clusters/Mode_Refrigerator.xml", + "${chip_root}/data_model/1.3/clusters/NetworkCommissioningCluster.xml", + "${chip_root}/data_model/1.3/clusters/OTAProvider.xml", + "${chip_root}/data_model/1.3/clusters/OTARequestor.xml", + "${chip_root}/data_model/1.3/clusters/OccupancySensing.xml", + "${chip_root}/data_model/1.3/clusters/OnOff.xml", + "${chip_root}/data_model/1.3/clusters/OperationalCredentialCluster.xml", + "${chip_root}/data_model/1.3/clusters/OperationalState.xml", + "${chip_root}/data_model/1.3/clusters/OperationalState_Oven.xml", + "${chip_root}/data_model/1.3/clusters/OperationalState_RVC.xml", + "${chip_root}/data_model/1.3/clusters/PowerSourceCluster.xml", + "${chip_root}/data_model/1.3/clusters/PowerSourceConfigurationCluster.xml", + "${chip_root}/data_model/1.3/clusters/PowerTopology.xml", + "${chip_root}/data_model/1.3/clusters/PressureMeasurement.xml", + "${chip_root}/data_model/1.3/clusters/ProxyConfiguration-Cluster.xml", + "${chip_root}/data_model/1.3/clusters/ProxyDiscovery-Cluster.xml", + "${chip_root}/data_model/1.3/clusters/PumpConfigurationControl.xml", + "${chip_root}/data_model/1.3/clusters/RefrigeratorAlarm.xml", + "${chip_root}/data_model/1.3/clusters/ResourceMonitoring.xml", + "${chip_root}/data_model/1.3/clusters/Scenes.xml", + "${chip_root}/data_model/1.3/clusters/SmokeCOAlarm.xml", + "${chip_root}/data_model/1.3/clusters/Switch.xml", + "${chip_root}/data_model/1.3/clusters/TargetNavigator.xml", + "${chip_root}/data_model/1.3/clusters/TemperatureControl.xml", + "${chip_root}/data_model/1.3/clusters/TemperatureMeasurement.xml", + "${chip_root}/data_model/1.3/clusters/Thermostat.xml", + "${chip_root}/data_model/1.3/clusters/ThermostatUserInterfaceConfiguration.xml", + "${chip_root}/data_model/1.3/clusters/TimeSync.xml", + "${chip_root}/data_model/1.3/clusters/ValidProxies-Cluster.xml", + "${chip_root}/data_model/1.3/clusters/ValveConfigurationControl.xml", + "${chip_root}/data_model/1.3/clusters/WakeOnLAN.xml", + "${chip_root}/data_model/1.3/clusters/WaterContentMeasurement.xml", + "${chip_root}/data_model/1.3/clusters/WindowCovering.xml", + "${chip_root}/data_model/1.3/clusters/bridge-clusters-ActionsCluster.xml", + "${chip_root}/data_model/1.3/clusters/bridge-clusters-BridgedDeviceBasicInformationCluster.xml", + "${chip_root}/data_model/1.3/clusters/cluster_ids.json", + "${chip_root}/data_model/1.3/device_types/Aggregator.xml", + "${chip_root}/data_model/1.3/device_types/AirPurifier.xml", + "${chip_root}/data_model/1.3/device_types/AirQualitySensor.xml", + "${chip_root}/data_model/1.3/device_types/BaseDeviceType.xml", + "${chip_root}/data_model/1.3/device_types/BasicVideoPlayer.xml", + "${chip_root}/data_model/1.3/device_types/BridgedNode.xml", + "${chip_root}/data_model/1.3/device_types/CastingVideoClient.xml", + "${chip_root}/data_model/1.3/device_types/CastingVideoPlayer.xml", + "${chip_root}/data_model/1.3/device_types/ColorDimmerSwitch.xml", + "${chip_root}/data_model/1.3/device_types/ColorTemperatureLight.xml", + "${chip_root}/data_model/1.3/device_types/ContactSensor.xml", + "${chip_root}/data_model/1.3/device_types/ContentApp.xml", + "${chip_root}/data_model/1.3/device_types/ControlBridge.xml", + "${chip_root}/data_model/1.3/device_types/CookSurface.xml", + "${chip_root}/data_model/1.3/device_types/Cooktop.xml", + "${chip_root}/data_model/1.3/device_types/DeviceEnergyManagement.xml", + "${chip_root}/data_model/1.3/device_types/DimmableLight.xml", + "${chip_root}/data_model/1.3/device_types/DimmablePlug-InUnit.xml", + "${chip_root}/data_model/1.3/device_types/DimmerSwitch.xml", + "${chip_root}/data_model/1.3/device_types/Dishwasher.xml", + "${chip_root}/data_model/1.3/device_types/DoorLock.xml", + "${chip_root}/data_model/1.3/device_types/DoorLockController.xml", + "${chip_root}/data_model/1.3/device_types/EVSE.xml", + "${chip_root}/data_model/1.3/device_types/ElectricalSensor.xml", + "${chip_root}/data_model/1.3/device_types/ExtendedColorLight.xml", + "${chip_root}/data_model/1.3/device_types/ExtractorHood.xml", + "${chip_root}/data_model/1.3/device_types/Fan.xml", + "${chip_root}/data_model/1.3/device_types/FlowSensor.xml", + "${chip_root}/data_model/1.3/device_types/GenericSwitch.xml", + "${chip_root}/data_model/1.3/device_types/HumiditySensor.xml", + "${chip_root}/data_model/1.3/device_types/LaundryDryer.xml", + "${chip_root}/data_model/1.3/device_types/LaundryWasher.xml", + "${chip_root}/data_model/1.3/device_types/LightSensor.xml", + "${chip_root}/data_model/1.3/device_types/MicrowaveOven.xml", + "${chip_root}/data_model/1.3/device_types/ModeSelectDeviceType.xml", + "${chip_root}/data_model/1.3/device_types/OccupancySensor.xml", + "${chip_root}/data_model/1.3/device_types/OnOffLight.xml", + "${chip_root}/data_model/1.3/device_types/OnOffLightSwitch.xml", + "${chip_root}/data_model/1.3/device_types/OnOffPlug-inUnit.xml", + "${chip_root}/data_model/1.3/device_types/OnOffSensor.xml", + "${chip_root}/data_model/1.3/device_types/OtaProvider.xml", + "${chip_root}/data_model/1.3/device_types/OtaRequestor.xml", + "${chip_root}/data_model/1.3/device_types/Oven.xml", + "${chip_root}/data_model/1.3/device_types/PowerSource.xml", + "${chip_root}/data_model/1.3/device_types/PressureSensor.xml", + "${chip_root}/data_model/1.3/device_types/Pump.xml", + "${chip_root}/data_model/1.3/device_types/PumpController.xml", + "${chip_root}/data_model/1.3/device_types/RainSensor.xml", + "${chip_root}/data_model/1.3/device_types/Refrigerator.xml", + "${chip_root}/data_model/1.3/device_types/RoboticVacuumCleaner.xml", + "${chip_root}/data_model/1.3/device_types/RoomAirConditioner.xml", + "${chip_root}/data_model/1.3/device_types/RootNodeDeviceType.xml", + "${chip_root}/data_model/1.3/device_types/SmokeCOAlarm.xml", + "${chip_root}/data_model/1.3/device_types/Speaker.xml", + "${chip_root}/data_model/1.3/device_types/TemperatureControlledCabinet.xml", + "${chip_root}/data_model/1.3/device_types/TemperatureSensor.xml", + "${chip_root}/data_model/1.3/device_types/Thermostat.xml", + "${chip_root}/data_model/1.3/device_types/VideoRemoteControl.xml", + "${chip_root}/data_model/1.3/device_types/WaterFreezeDetector.xml", + "${chip_root}/data_model/1.3/device_types/WaterLeakDetector.xml", + "${chip_root}/data_model/1.3/device_types/WaterValve.xml", + "${chip_root}/data_model/1.3/device_types/WindowCovering.xml", + "${chip_root}/data_model/1.3/device_types/WindowCoveringController.xml", + "${chip_root}/data_model/1.4/clusters/ACL-Cluster.xml", + "${chip_root}/data_model/1.4/clusters/AccountLogin.xml", + "${chip_root}/data_model/1.4/clusters/AdminCommissioningCluster.xml", + "${chip_root}/data_model/1.4/clusters/AirQuality.xml", + "${chip_root}/data_model/1.4/clusters/AlarmBase.xml", + "${chip_root}/data_model/1.4/clusters/ApplicationBasic.xml", + "${chip_root}/data_model/1.4/clusters/ApplicationLauncher.xml", + "${chip_root}/data_model/1.4/clusters/AudioOutput.xml", + "${chip_root}/data_model/1.4/clusters/BallastConfiguration.xml", + "${chip_root}/data_model/1.4/clusters/BasicInformationCluster.xml", + "${chip_root}/data_model/1.4/clusters/Binding-Cluster.xml", + "${chip_root}/data_model/1.4/clusters/BooleanState.xml", + "${chip_root}/data_model/1.4/clusters/BooleanStateConfiguration.xml", + "${chip_root}/data_model/1.4/clusters/Channel.xml", + "${chip_root}/data_model/1.4/clusters/ColorControl.xml", + "${chip_root}/data_model/1.4/clusters/CommissionerControlCluster.xml", + "${chip_root}/data_model/1.4/clusters/ConcentrationMeasurement.xml", + "${chip_root}/data_model/1.4/clusters/ContentAppObserver.xml", + "${chip_root}/data_model/1.4/clusters/ContentControl.xml", + "${chip_root}/data_model/1.4/clusters/ContentLauncher.xml", + "${chip_root}/data_model/1.4/clusters/Descriptor-Cluster.xml", + "${chip_root}/data_model/1.4/clusters/DeviceEnergyManagement.xml", + "${chip_root}/data_model/1.4/clusters/DiagnosticLogsCluster.xml", + "${chip_root}/data_model/1.4/clusters/DiagnosticsEthernet.xml", + "${chip_root}/data_model/1.4/clusters/DiagnosticsGeneral.xml", + "${chip_root}/data_model/1.4/clusters/DiagnosticsSoftware.xml", + "${chip_root}/data_model/1.4/clusters/DiagnosticsThread.xml", + "${chip_root}/data_model/1.4/clusters/DiagnosticsWiFi.xml", + "${chip_root}/data_model/1.4/clusters/DishwasherAlarm.xml", + "${chip_root}/data_model/1.4/clusters/DoorLock.xml", + "${chip_root}/data_model/1.4/clusters/EcosystemInformationCluster.xml", + "${chip_root}/data_model/1.4/clusters/ElectricalEnergyMeasurement.xml", + "${chip_root}/data_model/1.4/clusters/ElectricalPowerMeasurement.xml", + "${chip_root}/data_model/1.4/clusters/EnergyEVSE.xml", + "${chip_root}/data_model/1.4/clusters/EnergyPreference.xml", + "${chip_root}/data_model/1.4/clusters/FanControl.xml", + "${chip_root}/data_model/1.4/clusters/FlowMeasurement.xml", + "${chip_root}/data_model/1.4/clusters/GeneralCommissioningCluster.xml", + "${chip_root}/data_model/1.4/clusters/Group-Key-Management-Cluster.xml", + "${chip_root}/data_model/1.4/clusters/Groups.xml", + "${chip_root}/data_model/1.4/clusters/ICDManagement.xml", + "${chip_root}/data_model/1.4/clusters/Identify.xml", + "${chip_root}/data_model/1.4/clusters/IlluminanceMeasurement.xml", + "${chip_root}/data_model/1.4/clusters/JointFabricDatastoreCluster.xml", + "${chip_root}/data_model/1.4/clusters/JointFabricPKICluster.xml", + "${chip_root}/data_model/1.4/clusters/KeypadInput.xml", + "${chip_root}/data_model/1.4/clusters/Label-Cluster-FixedLabelCluster.xml", + "${chip_root}/data_model/1.4/clusters/Label-Cluster-LabelCluster.xml", + "${chip_root}/data_model/1.4/clusters/Label-Cluster-UserLabelCluster.xml", + "${chip_root}/data_model/1.4/clusters/LaundryDryerControls.xml", + "${chip_root}/data_model/1.4/clusters/LaundryWasherControls.xml", + "${chip_root}/data_model/1.4/clusters/LevelControl.xml", + "${chip_root}/data_model/1.4/clusters/LocalizationConfiguration.xml", + "${chip_root}/data_model/1.4/clusters/LocalizationTimeFormat.xml", + "${chip_root}/data_model/1.4/clusters/LocalizationUnit.xml", + "${chip_root}/data_model/1.4/clusters/LowPower.xml", + "${chip_root}/data_model/1.4/clusters/MediaInput.xml", + "${chip_root}/data_model/1.4/clusters/MediaPlayback.xml", + "${chip_root}/data_model/1.4/clusters/Messages.xml", + "${chip_root}/data_model/1.4/clusters/MicrowaveOvenControl.xml", + "${chip_root}/data_model/1.4/clusters/ModeBase.xml", + "${chip_root}/data_model/1.4/clusters/ModeSelect.xml", + "${chip_root}/data_model/1.4/clusters/Mode_DeviceEnergyManagement.xml", + "${chip_root}/data_model/1.4/clusters/Mode_Dishwasher.xml", + "${chip_root}/data_model/1.4/clusters/Mode_EVSE.xml", + "${chip_root}/data_model/1.4/clusters/Mode_LaundryWasher.xml", + "${chip_root}/data_model/1.4/clusters/Mode_MicrowaveOven.xml", + "${chip_root}/data_model/1.4/clusters/Mode_Oven.xml", + "${chip_root}/data_model/1.4/clusters/Mode_RVCClean.xml", + "${chip_root}/data_model/1.4/clusters/Mode_RVCRun.xml", + "${chip_root}/data_model/1.4/clusters/Mode_Refrigerator.xml", + "${chip_root}/data_model/1.4/clusters/Mode_WaterHeater.xml", + "${chip_root}/data_model/1.4/clusters/NetworkCommissioningCluster.xml", + "${chip_root}/data_model/1.4/clusters/OTAProvider.xml", + "${chip_root}/data_model/1.4/clusters/OTARequestor.xml", + "${chip_root}/data_model/1.4/clusters/OccupancySensing.xml", + "${chip_root}/data_model/1.4/clusters/OnOff.xml", + "${chip_root}/data_model/1.4/clusters/OperationalCredentialCluster.xml", + "${chip_root}/data_model/1.4/clusters/OperationalState.xml", + "${chip_root}/data_model/1.4/clusters/OperationalState_Oven.xml", + "${chip_root}/data_model/1.4/clusters/OperationalState_RVC.xml", + "${chip_root}/data_model/1.4/clusters/PowerSourceCluster.xml", + "${chip_root}/data_model/1.4/clusters/PowerSourceConfigurationCluster.xml", + "${chip_root}/data_model/1.4/clusters/PowerTopology.xml", + "${chip_root}/data_model/1.4/clusters/PressureMeasurement.xml", + "${chip_root}/data_model/1.4/clusters/ProxyConfiguration-Cluster.xml", + "${chip_root}/data_model/1.4/clusters/ProxyDiscovery-Cluster.xml", + "${chip_root}/data_model/1.4/clusters/PumpConfigurationControl.xml", + "${chip_root}/data_model/1.4/clusters/RefrigeratorAlarm.xml", + "${chip_root}/data_model/1.4/clusters/ResourceMonitoring.xml", + "${chip_root}/data_model/1.4/clusters/Scenes.xml", + "${chip_root}/data_model/1.4/clusters/ServiceArea.xml", + "${chip_root}/data_model/1.4/clusters/SmokeCOAlarm.xml", + "${chip_root}/data_model/1.4/clusters/Switch.xml", + "${chip_root}/data_model/1.4/clusters/TargetNavigator.xml", + "${chip_root}/data_model/1.4/clusters/TemperatureControl.xml", + "${chip_root}/data_model/1.4/clusters/TemperatureMeasurement.xml", + "${chip_root}/data_model/1.4/clusters/Thermostat.xml", + "${chip_root}/data_model/1.4/clusters/ThermostatUserInterfaceConfiguration.xml", + "${chip_root}/data_model/1.4/clusters/ThreadBorderRouterManagement.xml", + "${chip_root}/data_model/1.4/clusters/ThreadNetworkDirectory.xml", + "${chip_root}/data_model/1.4/clusters/TimeSync.xml", + "${chip_root}/data_model/1.4/clusters/ValidProxies-Cluster.xml", + "${chip_root}/data_model/1.4/clusters/ValveConfigurationControl.xml", + "${chip_root}/data_model/1.4/clusters/WakeOnLAN.xml", + "${chip_root}/data_model/1.4/clusters/WaterContentMeasurement.xml", + "${chip_root}/data_model/1.4/clusters/WaterHeaterManagement.xml", + "${chip_root}/data_model/1.4/clusters/WiFiNetworkManagement.xml", + "${chip_root}/data_model/1.4/clusters/WindowCovering.xml", + "${chip_root}/data_model/1.4/clusters/bridge-clusters-ActionsCluster.xml", + "${chip_root}/data_model/1.4/clusters/bridge-clusters-BridgedDeviceBasicInformationCluster.xml", + "${chip_root}/data_model/1.4/clusters/cluster_ids.json", + "${chip_root}/data_model/1.4/device_types/Aggregator.xml", + "${chip_root}/data_model/1.4/device_types/AirPurifier.xml", + "${chip_root}/data_model/1.4/device_types/AirQualitySensor.xml", + "${chip_root}/data_model/1.4/device_types/BaseDeviceType.xml", + "${chip_root}/data_model/1.4/device_types/BasicVideoPlayer.xml", + "${chip_root}/data_model/1.4/device_types/BatteryStorage.xml", + "${chip_root}/data_model/1.4/device_types/BridgedNode.xml", + "${chip_root}/data_model/1.4/device_types/CastingVideoClient.xml", + "${chip_root}/data_model/1.4/device_types/CastingVideoPlayer.xml", + "${chip_root}/data_model/1.4/device_types/ColorDimmerSwitch.xml", + "${chip_root}/data_model/1.4/device_types/ColorTemperatureLight.xml", + "${chip_root}/data_model/1.4/device_types/ContactSensor.xml", + "${chip_root}/data_model/1.4/device_types/ContentApp.xml", + "${chip_root}/data_model/1.4/device_types/ControlBridge.xml", + "${chip_root}/data_model/1.4/device_types/CookSurface.xml", + "${chip_root}/data_model/1.4/device_types/Cooktop.xml", + "${chip_root}/data_model/1.4/device_types/DeviceEnergyManagement.xml", + "${chip_root}/data_model/1.4/device_types/DimmableLight.xml", + "${chip_root}/data_model/1.4/device_types/DimmablePlug-InUnit.xml", + "${chip_root}/data_model/1.4/device_types/DimmerSwitch.xml", + "${chip_root}/data_model/1.4/device_types/Dishwasher.xml", + "${chip_root}/data_model/1.4/device_types/DoorLock.xml", + "${chip_root}/data_model/1.4/device_types/DoorLockController.xml", + "${chip_root}/data_model/1.4/device_types/EVSE.xml", + "${chip_root}/data_model/1.4/device_types/ElectricalSensor.xml", + "${chip_root}/data_model/1.4/device_types/ExtendedColorLight.xml", + "${chip_root}/data_model/1.4/device_types/ExtractorHood.xml", + "${chip_root}/data_model/1.4/device_types/Fan.xml", + "${chip_root}/data_model/1.4/device_types/FlowSensor.xml", + "${chip_root}/data_model/1.4/device_types/GenericSwitch.xml", + "${chip_root}/data_model/1.4/device_types/HeatPump.xml", + "${chip_root}/data_model/1.4/device_types/HumiditySensor.xml", + "${chip_root}/data_model/1.4/device_types/JointFabricAdmin.xml", + "${chip_root}/data_model/1.4/device_types/LaundryDryer.xml", + "${chip_root}/data_model/1.4/device_types/LaundryWasher.xml", + "${chip_root}/data_model/1.4/device_types/LightSensor.xml", + "${chip_root}/data_model/1.4/device_types/MicrowaveOven.xml", + "${chip_root}/data_model/1.4/device_types/ModeSelectDeviceType.xml", + "${chip_root}/data_model/1.4/device_types/MountedDimmableLoadControl.xml", + "${chip_root}/data_model/1.4/device_types/MountedOnOffControl.xml", + "${chip_root}/data_model/1.4/device_types/NetworkInfraIntro.xml", + "${chip_root}/data_model/1.4/device_types/NetworkInfraManager.xml", + "${chip_root}/data_model/1.4/device_types/OccupancySensor.xml", + "${chip_root}/data_model/1.4/device_types/OnOffLight.xml", + "${chip_root}/data_model/1.4/device_types/OnOffLightSwitch.xml", + "${chip_root}/data_model/1.4/device_types/OnOffPlug-inUnit.xml", + "${chip_root}/data_model/1.4/device_types/OnOffSensor.xml", + "${chip_root}/data_model/1.4/device_types/OtaProvider.xml", + "${chip_root}/data_model/1.4/device_types/OtaRequestor.xml", + "${chip_root}/data_model/1.4/device_types/Oven.xml", + "${chip_root}/data_model/1.4/device_types/PowerSource.xml", + "${chip_root}/data_model/1.4/device_types/PressureSensor.xml", + "${chip_root}/data_model/1.4/device_types/Pump.xml", + "${chip_root}/data_model/1.4/device_types/PumpController.xml", + "${chip_root}/data_model/1.4/device_types/RainSensor.xml", + "${chip_root}/data_model/1.4/device_types/Refrigerator.xml", + "${chip_root}/data_model/1.4/device_types/RoboticVacuumCleaner.xml", + "${chip_root}/data_model/1.4/device_types/RoomAirConditioner.xml", + "${chip_root}/data_model/1.4/device_types/RootNodeDeviceType.xml", + "${chip_root}/data_model/1.4/device_types/SecondaryNetworkInterface.xml", + "${chip_root}/data_model/1.4/device_types/SmokeCOAlarm.xml", + "${chip_root}/data_model/1.4/device_types/SolarPower.xml", + "${chip_root}/data_model/1.4/device_types/Speaker.xml", + "${chip_root}/data_model/1.4/device_types/TemperatureControlledCabinet.xml", + "${chip_root}/data_model/1.4/device_types/TemperatureSensor.xml", + "${chip_root}/data_model/1.4/device_types/Thermostat.xml", + "${chip_root}/data_model/1.4/device_types/ThreadBorderRouter.xml", + "${chip_root}/data_model/1.4/device_types/VideoRemoteControl.xml", + "${chip_root}/data_model/1.4/device_types/WaterFreezeDetector.xml", + "${chip_root}/data_model/1.4/device_types/WaterHeater.xml", + "${chip_root}/data_model/1.4/device_types/WaterLeakDetector.xml", + "${chip_root}/data_model/1.4/device_types/WaterValve.xml", + "${chip_root}/data_model/1.4/device_types/WindowCovering.xml", + "${chip_root}/data_model/1.4/device_types/WindowCoveringController.xml", + "${chip_root}/data_model/master/clusters/ACL-Cluster.xml", + "${chip_root}/data_model/master/clusters/AccountLogin.xml", + "${chip_root}/data_model/master/clusters/AdminCommissioningCluster.xml", + "${chip_root}/data_model/master/clusters/AirQuality.xml", + "${chip_root}/data_model/master/clusters/AlarmBase.xml", + "${chip_root}/data_model/master/clusters/ApplicationBasic.xml", + "${chip_root}/data_model/master/clusters/ApplicationLauncher.xml", + "${chip_root}/data_model/master/clusters/AudioOutput.xml", + "${chip_root}/data_model/master/clusters/BallastConfiguration.xml", + "${chip_root}/data_model/master/clusters/BasicInformationCluster.xml", + "${chip_root}/data_model/master/clusters/Binding-Cluster.xml", + "${chip_root}/data_model/master/clusters/BooleanState.xml", + "${chip_root}/data_model/master/clusters/BooleanStateConfiguration.xml", + "${chip_root}/data_model/master/clusters/Channel.xml", + "${chip_root}/data_model/master/clusters/ColorControl.xml", + "${chip_root}/data_model/master/clusters/CommissionerControlCluster.xml", + "${chip_root}/data_model/master/clusters/ConcentrationMeasurement.xml", + "${chip_root}/data_model/master/clusters/ContentAppObserver.xml", + "${chip_root}/data_model/master/clusters/ContentControl.xml", + "${chip_root}/data_model/master/clusters/ContentLauncher.xml", + "${chip_root}/data_model/master/clusters/DemandResponseLoadControl.xml", + "${chip_root}/data_model/master/clusters/Descriptor-Cluster.xml", + "${chip_root}/data_model/master/clusters/DeviceEnergyManagement.xml", + "${chip_root}/data_model/master/clusters/DiagnosticLogsCluster.xml", + "${chip_root}/data_model/master/clusters/DiagnosticsEthernet.xml", + "${chip_root}/data_model/master/clusters/DiagnosticsGeneral.xml", + "${chip_root}/data_model/master/clusters/DiagnosticsSoftware.xml", + "${chip_root}/data_model/master/clusters/DiagnosticsThread.xml", + "${chip_root}/data_model/master/clusters/DiagnosticsWiFi.xml", + "${chip_root}/data_model/master/clusters/DishwasherAlarm.xml", + "${chip_root}/data_model/master/clusters/DoorLock.xml", + "${chip_root}/data_model/master/clusters/ElectricalEnergyMeasurement.xml", + "${chip_root}/data_model/master/clusters/ElectricalPowerMeasurement.xml", + "${chip_root}/data_model/master/clusters/EnergyCalendar.xml", + "${chip_root}/data_model/master/clusters/EnergyEVSE.xml", + "${chip_root}/data_model/master/clusters/EnergyPreference.xml", + "${chip_root}/data_model/master/clusters/EnergyPrice.xml", + "${chip_root}/data_model/master/clusters/FanControl.xml", + "${chip_root}/data_model/master/clusters/FlowMeasurement.xml", + "${chip_root}/data_model/master/clusters/GeneralCommissioningCluster.xml", + "${chip_root}/data_model/master/clusters/Group-Key-Management-Cluster.xml", + "${chip_root}/data_model/master/clusters/Groups.xml", + "${chip_root}/data_model/master/clusters/Humidistat.xml", + "${chip_root}/data_model/master/clusters/ICDManagement.xml", + "${chip_root}/data_model/master/clusters/Identify.xml", + "${chip_root}/data_model/master/clusters/IlluminanceMeasurement.xml", + "${chip_root}/data_model/master/clusters/JointFabricDatastoreCluster.xml", + "${chip_root}/data_model/master/clusters/JointFabricPKICluster.xml", + "${chip_root}/data_model/master/clusters/KeypadInput.xml", + "${chip_root}/data_model/master/clusters/Label-Cluster-FixedLabelCluster.xml", + "${chip_root}/data_model/master/clusters/Label-Cluster-LabelCluster.xml", + "${chip_root}/data_model/master/clusters/Label-Cluster-UserLabelCluster.xml", + "${chip_root}/data_model/master/clusters/LaundryDryerControls.xml", + "${chip_root}/data_model/master/clusters/LaundryWasherControls.xml", + "${chip_root}/data_model/master/clusters/LevelControl.xml", + "${chip_root}/data_model/master/clusters/LocalizationConfiguration.xml", + "${chip_root}/data_model/master/clusters/LocalizationTimeFormat.xml", + "${chip_root}/data_model/master/clusters/LocalizationUnit.xml", + "${chip_root}/data_model/master/clusters/LowPower.xml", + "${chip_root}/data_model/master/clusters/MediaInput.xml", + "${chip_root}/data_model/master/clusters/MediaPlayback.xml", + "${chip_root}/data_model/master/clusters/Messages.xml", + "${chip_root}/data_model/master/clusters/MeterIdentification.xml", + "${chip_root}/data_model/master/clusters/MicrowaveOvenControl.xml", + "${chip_root}/data_model/master/clusters/ModeBase.xml", + "${chip_root}/data_model/master/clusters/ModeSelect.xml", + "${chip_root}/data_model/master/clusters/Mode_DeviceEnergyManagement.xml", + "${chip_root}/data_model/master/clusters/Mode_Dishwasher.xml", + "${chip_root}/data_model/master/clusters/Mode_EVSE.xml", + "${chip_root}/data_model/master/clusters/Mode_LaundryWasher.xml", + "${chip_root}/data_model/master/clusters/Mode_MicrowaveOven.xml", + "${chip_root}/data_model/master/clusters/Mode_Oven.xml", + "${chip_root}/data_model/master/clusters/Mode_RVCClean.xml", + "${chip_root}/data_model/master/clusters/Mode_RVCRun.xml", + "${chip_root}/data_model/master/clusters/Mode_Refrigerator.xml", + "${chip_root}/data_model/master/clusters/Mode_WaterHeater.xml", + "${chip_root}/data_model/master/clusters/NetworkCommissioningCluster.xml", + "${chip_root}/data_model/master/clusters/NetworkIdentityManagement.xml", + "${chip_root}/data_model/master/clusters/OTAProvider.xml", + "${chip_root}/data_model/master/clusters/OTARequestor.xml", + "${chip_root}/data_model/master/clusters/OccupancySensing.xml", + "${chip_root}/data_model/master/clusters/OnOff.xml", + "${chip_root}/data_model/master/clusters/OperationalCredentialCluster.xml", + "${chip_root}/data_model/master/clusters/OperationalState.xml", + "${chip_root}/data_model/master/clusters/OperationalState_Oven.xml", + "${chip_root}/data_model/master/clusters/OperationalState_RVC.xml", + "${chip_root}/data_model/master/clusters/PowerSourceCluster.xml", + "${chip_root}/data_model/master/clusters/PowerSourceConfigurationCluster.xml", + "${chip_root}/data_model/master/clusters/PowerTopology.xml", + "${chip_root}/data_model/master/clusters/PressureMeasurement.xml", + "${chip_root}/data_model/master/clusters/ProxyConfiguration-Cluster.xml", + "${chip_root}/data_model/master/clusters/ProxyDiscovery-Cluster.xml", + "${chip_root}/data_model/master/clusters/PumpConfigurationControl.xml", + "${chip_root}/data_model/master/clusters/RefrigeratorAlarm.xml", + "${chip_root}/data_model/master/clusters/ResourceMonitoring.xml", + "${chip_root}/data_model/master/clusters/Scenes.xml", + "${chip_root}/data_model/master/clusters/ServiceArea.xml", + "${chip_root}/data_model/master/clusters/SmokeCOAlarm.xml", + "${chip_root}/data_model/master/clusters/Switch.xml", + "${chip_root}/data_model/master/clusters/TargetNavigator.xml", + "${chip_root}/data_model/master/clusters/TemperatureControl.xml", + "${chip_root}/data_model/master/clusters/TemperatureMeasurement.xml", + "${chip_root}/data_model/master/clusters/Thermostat.xml", + "${chip_root}/data_model/master/clusters/ThermostatUserInterfaceConfiguration.xml", + "${chip_root}/data_model/master/clusters/ThreadBorderRouterManagement.xml", + "${chip_root}/data_model/master/clusters/ThreadNetworkDirectory.xml", + "${chip_root}/data_model/master/clusters/TimeSync.xml", + "${chip_root}/data_model/master/clusters/ValidProxies-Cluster.xml", + "${chip_root}/data_model/master/clusters/ValveConfigurationControl.xml", + "${chip_root}/data_model/master/clusters/WakeOnLAN.xml", + "${chip_root}/data_model/master/clusters/WaterContentMeasurement.xml", + "${chip_root}/data_model/master/clusters/WaterHeaterManagement.xml", + "${chip_root}/data_model/master/clusters/WiFiNetworkManagement.xml", + "${chip_root}/data_model/master/clusters/WindowCovering.xml", + "${chip_root}/data_model/master/clusters/bridge-clusters-ActionsCluster.xml", + "${chip_root}/data_model/master/clusters/bridge-clusters-BridgedDeviceBasicInformationCluster.xml", + "${chip_root}/data_model/master/clusters/bridge-clusters-EcosystemInformationCluster.xml", + "${chip_root}/data_model/master/clusters/cluster_ids.json", + "${chip_root}/data_model/master/device_types/Aggregator.xml", + "${chip_root}/data_model/master/device_types/AirPurifier.xml", + "${chip_root}/data_model/master/device_types/AirQualitySensor.xml", + "${chip_root}/data_model/master/device_types/BaseDeviceType.xml", + "${chip_root}/data_model/master/device_types/BasicVideoPlayer.xml", + "${chip_root}/data_model/master/device_types/BatteryStorage.xml", + "${chip_root}/data_model/master/device_types/BridgedNode.xml", + "${chip_root}/data_model/master/device_types/CastingVideoClient.xml", + "${chip_root}/data_model/master/device_types/CastingVideoPlayer.xml", + "${chip_root}/data_model/master/device_types/ColorDimmerSwitch.xml", + "${chip_root}/data_model/master/device_types/ColorTemperatureLight.xml", + "${chip_root}/data_model/master/device_types/ContactSensor.xml", + "${chip_root}/data_model/master/device_types/ContentApp.xml", + "${chip_root}/data_model/master/device_types/ControlBridge.xml", + "${chip_root}/data_model/master/device_types/CookSurface.xml", + "${chip_root}/data_model/master/device_types/Cooktop.xml", + "${chip_root}/data_model/master/device_types/DeviceEnergyManagement.xml", + "${chip_root}/data_model/master/device_types/DimmableLight.xml", + "${chip_root}/data_model/master/device_types/DimmablePlug-InUnit.xml", + "${chip_root}/data_model/master/device_types/DimmerSwitch.xml", + "${chip_root}/data_model/master/device_types/Dishwasher.xml", + "${chip_root}/data_model/master/device_types/DoorLock.xml", + "${chip_root}/data_model/master/device_types/DoorLockController.xml", + "${chip_root}/data_model/master/device_types/EVSE.xml", + "${chip_root}/data_model/master/device_types/ElectricalSensor.xml", + "${chip_root}/data_model/master/device_types/EnergyTariff.xml", + "${chip_root}/data_model/master/device_types/EnergyTariffCalendar.xml", + "${chip_root}/data_model/master/device_types/ExtendedColorLight.xml", + "${chip_root}/data_model/master/device_types/ExtractorHood.xml", + "${chip_root}/data_model/master/device_types/Fan.xml", + "${chip_root}/data_model/master/device_types/FlowSensor.xml", + "${chip_root}/data_model/master/device_types/GenericSwitch.xml", + "${chip_root}/data_model/master/device_types/HeatPump.xml", + "${chip_root}/data_model/master/device_types/HumidifierDehumidifier.xml", + "${chip_root}/data_model/master/device_types/HumiditySensor.xml", + "${chip_root}/data_model/master/device_types/JointFabricAdmin.xml", + "${chip_root}/data_model/master/device_types/LaundryDryer.xml", + "${chip_root}/data_model/master/device_types/LaundryWasher.xml", + "${chip_root}/data_model/master/device_types/LightSensor.xml", + "${chip_root}/data_model/master/device_types/MicrowaveOven.xml", + "${chip_root}/data_model/master/device_types/ModeSelectDeviceType.xml", + "${chip_root}/data_model/master/device_types/MountedDimmableLoadControl.xml", + "${chip_root}/data_model/master/device_types/MountedOnOffControl.xml", + "${chip_root}/data_model/master/device_types/NetworkInfraIntro.xml", + "${chip_root}/data_model/master/device_types/NetworkInfraManager.xml", + "${chip_root}/data_model/master/device_types/OccupancySensor.xml", + "${chip_root}/data_model/master/device_types/OnOffLight.xml", + "${chip_root}/data_model/master/device_types/OnOffLightSwitch.xml", + "${chip_root}/data_model/master/device_types/OnOffPlug-inUnit.xml", + "${chip_root}/data_model/master/device_types/OnOffSensor.xml", + "${chip_root}/data_model/master/device_types/OtaProvider.xml", + "${chip_root}/data_model/master/device_types/OtaRequestor.xml", + "${chip_root}/data_model/master/device_types/Oven.xml", + "${chip_root}/data_model/master/device_types/PowerSource.xml", + "${chip_root}/data_model/master/device_types/PressureSensor.xml", + "${chip_root}/data_model/master/device_types/Pump.xml", + "${chip_root}/data_model/master/device_types/PumpController.xml", + "${chip_root}/data_model/master/device_types/RainSensor.xml", + "${chip_root}/data_model/master/device_types/Refrigerator.xml", + "${chip_root}/data_model/master/device_types/RoboticVacuumCleaner.xml", + "${chip_root}/data_model/master/device_types/RoomAirConditioner.xml", + "${chip_root}/data_model/master/device_types/RootNodeDeviceType.xml", + "${chip_root}/data_model/master/device_types/SecondaryNetworkInterface.xml", + "${chip_root}/data_model/master/device_types/SmokeCOAlarm.xml", + "${chip_root}/data_model/master/device_types/SolarPower.xml", + "${chip_root}/data_model/master/device_types/Speaker.xml", + "${chip_root}/data_model/master/device_types/TemperatureControlledCabinet.xml", + "${chip_root}/data_model/master/device_types/TemperatureSensor.xml", + "${chip_root}/data_model/master/device_types/Thermostat.xml", + "${chip_root}/data_model/master/device_types/ThreadBorderRouter.xml", + "${chip_root}/data_model/master/device_types/VideoRemoteControl.xml", + "${chip_root}/data_model/master/device_types/WaterFreezeDetector.xml", + "${chip_root}/data_model/master/device_types/WaterHeater.xml", + "${chip_root}/data_model/master/device_types/WaterLeakDetector.xml", + "${chip_root}/data_model/master/device_types/WaterValve.xml", + "${chip_root}/data_model/master/device_types/WindowCovering.xml", + "${chip_root}/data_model/master/device_types/WindowCoveringController.xml", +] diff --git a/src/python_testing/matter_testing_infrastructure/pyproject.toml b/src/python_testing/matter_testing_infrastructure/pyproject.toml deleted file mode 100644 index f62115ec75168a..00000000000000 --- a/src/python_testing/matter_testing_infrastructure/pyproject.toml +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2024 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. - -[build-system] -requires = ['setuptools', 'wheel'] -build-backend = 'setuptools.build_meta' diff --git a/src/python_testing/matter_testing_infrastructure/setup.cfg b/src/python_testing/matter_testing_infrastructure/setup.cfg deleted file mode 100644 index 862236aa038746..00000000000000 --- a/src/python_testing/matter_testing_infrastructure/setup.cfg +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2024 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. - -[metadata] -name = chip-testing -version = 1.0.0 -author = Project CHIP Authors -license-expression = Apache-2.0 -description = Various helpers associated with the python_testing scripts -url = https://github.com/project-chip/connectedhomeip diff --git a/src/python_testing/matter_testing_infrastructure/setup.py b/src/python_testing/matter_testing_infrastructure/setup.py deleted file mode 100644 index ab0a7f39adca20..00000000000000 --- a/src/python_testing/matter_testing_infrastructure/setup.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2024 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 setuptools # type: ignore - -setuptools.setup() # Package definition in setup.cfg From d73c821f1f592717e41e1e2efd9751ee6877ed9e Mon Sep 17 00:00:00 2001 From: BoB13-Matter Date: Sat, 16 Nov 2024 02:37:08 +0900 Subject: [PATCH 17/27] Fix crash in NamedPipeCommands.cpp caused by stack-buffer-underflow (#36465) * Fix stack-buffer-underflow in NamedPipeCommands.cpp * Update NamedPipeCommands.cpp --- examples/platform/linux/NamedPipeCommands.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/platform/linux/NamedPipeCommands.cpp b/examples/platform/linux/NamedPipeCommands.cpp index c77165e9000cf8..e07ea242f0faae 100644 --- a/examples/platform/linux/NamedPipeCommands.cpp +++ b/examples/platform/linux/NamedPipeCommands.cpp @@ -81,12 +81,15 @@ void * NamedPipeCommands::EventCommandListenerTask(void * arg) break; } - ssize_t readBytes = read(fd, readbuf, kChipEventCmdBufSize); - readbuf[readBytes - 1] = '\0'; - ChipLogProgress(NotSpecified, "Received payload: \"%s\"", readbuf); + ssize_t readBytes = read(fd, readbuf, kChipEventCmdBufSize); + if (readBytes > 0) + { + readbuf[readBytes - 1] = '\0'; + ChipLogProgress(NotSpecified, "Received payload: \"%s\"", readbuf); - // Process the received command request from event fifo - self->mDelegate->OnEventCommandReceived(readbuf); + // Process the received command request from event fifo + self->mDelegate->OnEventCommandReceived(readbuf); + } close(fd); } From b155ce16d2b7226c8801b63fa305f96f87017cac Mon Sep 17 00:00:00 2001 From: cdj <45139296+DejinChen@users.noreply.github.com> Date: Sat, 16 Nov 2024 01:37:35 +0800 Subject: [PATCH 18/27] ESP32: Fix compile error for esp32h2 and add config for dynamic server (#36432) * ESP32: Fix compile error for esp32h2 and add config for dynamic server * add esp_wifi_lib if wifi enabled --- config/esp32/components/chip/CMakeLists.txt | 10 ++++++++-- config/esp32/components/chip/Kconfig | 7 +++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt index f3e919d3b6b9db..40f5c0cea2936d 100644 --- a/config/esp32/components/chip/CMakeLists.txt +++ b/config/esp32/components/chip/CMakeLists.txt @@ -310,6 +310,10 @@ if (CONFIG_ENABLE_ESP_INSIGHTS_TRACE) target_include_directories(${COMPONENT_LIB} INTERFACE "${CHIP_ROOT}/src/tracing/esp32_trace/include") endif() +if (CONFIG_CHIP_DEVICE_ENABLE_DYNAMIC_SERVER) + chip_gn_arg_append("chip_build_controller_dynamic_server" "true") +endif() + set(args_gn_input "${CMAKE_CURRENT_BINARY_DIR}/args.gn.in") file(GENERATE OUTPUT "${args_gn_input}" CONTENT "${chip_gn_args}") @@ -508,9 +512,11 @@ endif() idf_component_get_property(lwip_lib lwip COMPONENT_LIB) list(APPEND chip_libraries $) +if ("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.3" OR CONFIG_ESP32_WIFI_ENABLED) + idf_component_get_property(esp_wifi_lib esp_wifi COMPONENT_LIB) + list(APPEND chip_libraries $) +endif() -idf_component_get_property(esp_wifi_lib esp_wifi COMPONENT_LIB) -list(APPEND chip_libraries $) if (CONFIG_ESP32_WIFI_ENABLED) idf_component_get_property(esp_wifi_dir esp_wifi COMPONENT_DIR) if (CONFIG_IDF_TARGET_ESP32C2) diff --git a/config/esp32/components/chip/Kconfig b/config/esp32/components/chip/Kconfig index 83d3f1c893261d..2d8127900eed69 100644 --- a/config/esp32/components/chip/Kconfig +++ b/config/esp32/components/chip/Kconfig @@ -193,6 +193,13 @@ menu "CHIP Core" help Specifies the maximum number of group key sets supported per fabric. + config CHIP_DEVICE_ENABLE_DYNAMIC_SERVER + bool "Enable dynamic server" + default n + help + Enable dynamic server to handle a different interaction model dispatch. + Can be implied when users do not want to use the same server clusters. + endmenu # "General Options" menu "Networking Options" From 4c53f7d488d5e29fb732dedda1705a777f5f1508 Mon Sep 17 00:00:00 2001 From: Marius Tache <102153746+marius-alex-tache@users.noreply.github.com> Date: Fri, 15 Nov 2024 19:38:33 +0200 Subject: [PATCH 19/27] [script] Add core.symlinks=true to submodules init (#36498) On Windows, symlinks in submodules are detected as simple text files. Adding this option to the git submodule command correctly detects the symlinks. Signed-off-by: marius-alex-tache --- scripts/checkout_submodules.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/checkout_submodules.py b/scripts/checkout_submodules.py index 4d527148c7d9b0..78b51435eb64c1 100755 --- a/scripts/checkout_submodules.py +++ b/scripts/checkout_submodules.py @@ -113,7 +113,8 @@ def checkout_modules(modules: list, shallow: bool, force: bool, recursive: bool, names = ', '.join([module.name for module in modules]) logging.info(f'Checking out: {names}') - cmd = ['git', '-C', CHIP_ROOT, 'submodule', '--quiet', 'update', '--init'] + cmd = ['git', '-c', 'core.symlinks=true', '-C', CHIP_ROOT] + cmd += ['submodule', '--quiet', 'update', '--init'] cmd += ['--depth', '1'] if shallow else [] cmd += ['--force'] if force else [] cmd += ['--recursive'] if recursive else [] From e6bbe667d61f278b83fbe985227592fcce0aa77b Mon Sep 17 00:00:00 2001 From: Kiel Oleson Date: Fri, 15 Nov 2024 09:39:33 -0800 Subject: [PATCH 20/27] [Darwin] add API to get public key without leaks (with fixes) (#36340) * Initial checkin * Fixing review feedback * Adding braces * Restyled by clang-format * Fixing build * Restyled by clang-format * Fixing annotations * Update src/darwin/Framework/CHIP/MTRKeypair.h Co-authored-by: Boris Zbarsky * separate statements involving _mPublicKey to make compiler happy * use `CFAutorelease` on CoreFoundation typed public key copies * fix indent * implement `copyPublicKey` for `MTRTestKeys`; add TODO note about optional method calls * remove comment it's a test; this is the best we can do with an optional protocol method * consistent formatting for `copyPublicKey` calls * reformat `copyPublicKey` in `MTRTestKeys` remove comment - not this method's job to worry about other implementation's potential side-effects * Update src/darwin/Framework/CHIP/MTRKeypair.h Co-authored-by: Boris Zbarsky * re-add `publicKey` in `CHIPToolKeypair` check compatibility in CI before going back and removing * use `copyPublicKey` in more places * dedupe public key cache population for CHIPToolKeypair * Restyled by clang-format * try manually releasing pubkey in test * leakfix: MTRP256KeypairBridge * leakfix: `MTRCertificateTests.testGenerateCSR` * remove unnecessary plain `publicKey` implementation * temporarily do the inelegant patch on CFAutorelease * fix another remaining `publicKey` instance * Restyled by clang-format * fix `publicKey` deprecation, marking for future release --------- Co-authored-by: Justin Wood Co-authored-by: Restyled.io Co-authored-by: Boris Zbarsky --- .../commands/common/CHIPCommandBridge.mm | 9 ++- .../commands/common/CHIPToolKeypair.h | 2 +- .../commands/common/CHIPToolKeypair.mm | 10 ++- src/darwin/Framework/CHIP/MTRCertificates.mm | 19 ++++- .../CHIP/MTRDeviceControllerFactory.mm | 19 ++++- src/darwin/Framework/CHIP/MTRKeypair.h | 14 ++-- .../Framework/CHIP/MTRP256KeypairBridge.mm | 12 +++- .../Framework/CHIPTests/MTRCertificateTests.m | 71 ++++++++++++++----- .../CHIPTests/MTRCertificateValidityTests.m | 5 +- .../CHIPTests/MTRControllerAdvertisingTests.m | 5 +- .../Framework/CHIPTests/MTRControllerTests.m | 59 +++++++++++---- .../Framework/CHIPTests/MTRFabricInfoTests.m | 5 +- .../CHIPTests/MTRPerControllerStorageTests.m | 7 +- .../CHIPTests/TestHelpers/MTRTestKeys.m | 6 ++ 14 files changed, 199 insertions(+), 44 deletions(-) diff --git a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm index 69071d4c423776..6b9dfcec29be9e 100644 --- a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm +++ b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm @@ -172,10 +172,17 @@ NSError * error; __auto_type * operationalKeypair = [certificateIssuer issueOperationalKeypairWithControllerStorage:controllerStorage error:&error]; + SecKeyRef publicKey = [operationalKeypair copyPublicKey]; + __auto_type * operational = [certificateIssuer issueOperationalCertificateForNodeID:nodeId fabricID:fabricId - publicKey:operationalKeypair.publicKey + publicKey:publicKey error:&error]; + + if (publicKey != NULL) { + CFAutorelease(publicKey); + } + VerifyOrReturnError(nil == error, MTRErrorToCHIPErrorCode(error), ChipLogError(chipTool, "Can not issue an operational certificate: %@", error)); __auto_type * controllerStorageQueue = dispatch_queue_create("com.chip.storage", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); diff --git a/examples/darwin-framework-tool/commands/common/CHIPToolKeypair.h b/examples/darwin-framework-tool/commands/common/CHIPToolKeypair.h index f0ee3f8db6092b..58be7f2ac4b041 100644 --- a/examples/darwin-framework-tool/commands/common/CHIPToolKeypair.h +++ b/examples/darwin-framework-tool/commands/common/CHIPToolKeypair.h @@ -22,7 +22,7 @@ @interface CHIPToolKeypair : NSObject - (BOOL)initialize; - (NSData *)signMessageECDSA_RAW:(NSData *)message; -- (SecKeyRef)publicKey; +- (SecKeyRef)copyPublicKey; - (CHIP_ERROR)Serialize:(chip::Crypto::P256SerializedKeypair &)output; - (CHIP_ERROR)Deserialize:(chip::Crypto::P256SerializedKeypair &)input; - (CHIP_ERROR)createOrLoadKeys:(id)storage; diff --git a/examples/darwin-framework-tool/commands/common/CHIPToolKeypair.mm b/examples/darwin-framework-tool/commands/common/CHIPToolKeypair.mm index ce0ef5819b6ac1..a09975d68da41f 100644 --- a/examples/darwin-framework-tool/commands/common/CHIPToolKeypair.mm +++ b/examples/darwin-framework-tool/commands/common/CHIPToolKeypair.mm @@ -65,7 +65,7 @@ - (NSData *)signMessageECDSA_RAW:(NSData *)message return out_signature; } -- (SecKeyRef)publicKey +- (SecKeyRef)copyPublicKey { if (_mPublicKey == nil) { chip::Crypto::P256PublicKey publicKey = _mKeyPair.Pubkey(); @@ -79,7 +79,13 @@ - (SecKeyRef)publicKey }; _mPublicKey = SecKeyCreateWithData((__bridge CFDataRef) publicKeyNSData, (__bridge CFDictionaryRef) attributes, nullptr); } - return _mPublicKey; + + if (_mPublicKey) { + CFRetain(_mPublicKey); + return _mPublicKey; + } + + return NULL; } - (CHIP_ERROR)Deserialize:(chip::Crypto::P256SerializedKeypair &)input diff --git a/src/darwin/Framework/CHIP/MTRCertificates.mm b/src/darwin/Framework/CHIP/MTRCertificates.mm index b153cf4442b373..7dcec96cba695b 100644 --- a/src/darwin/Framework/CHIP/MTRCertificates.mm +++ b/src/darwin/Framework/CHIP/MTRCertificates.mm @@ -152,7 +152,24 @@ + (MTRCertificateDERBytes _Nullable)createOperationalCertificate:(id + (BOOL)keypair:(id)keypair matchesCertificate:(NSData *)certificate { P256PublicKey keypairPubKey; - CHIP_ERROR err = MTRP256KeypairBridge::MatterPubKeyFromSecKeyRef(keypair.publicKey, &keypairPubKey); + SecKeyRef publicKey = NULL; + + if ([keypair respondsToSelector:@selector(copyPublicKey)]) { + publicKey = [keypair copyPublicKey]; + } else { + publicKey = [keypair publicKey]; + if (publicKey) { + CFRetain(publicKey); + } + } + + CHIP_ERROR err = MTRP256KeypairBridge::MatterPubKeyFromSecKeyRef(publicKey, &keypairPubKey); + + if (publicKey != NULL) { + CFRelease(publicKey); + publicKey = NULL; + } + if (err != CHIP_NO_ERROR) { MTR_LOG_ERROR("Can't extract public key from keypair: %s", ErrorStr(err)); return NO; diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm index 9de51431bfe4f8..e287ef0446593f 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm @@ -819,7 +819,24 @@ - (BOOL)findMatchingFabric:(FabricTable &)fabricTable } else { // No root certificate means the nocSigner is using the root keys, because // consumers must provide a root certificate whenever an ICA is used. - CHIP_ERROR err = MTRP256KeypairBridge::MatterPubKeyFromSecKeyRef(params.nocSigner.publicKey, &pubKey); + SecKeyRef publicKey = NULL; + + if ([params.nocSigner respondsToSelector:@selector(copyPublicKey)]) { + publicKey = [params.nocSigner copyPublicKey]; + } else { + publicKey = [params.nocSigner publicKey]; + if (publicKey) { + CFRetain(publicKey); + } + } + + CHIP_ERROR err = MTRP256KeypairBridge::MatterPubKeyFromSecKeyRef(publicKey, &pubKey); + + if (publicKey != NULL) { + CFRelease(publicKey); + publicKey = NULL; + } + if (err != CHIP_NO_ERROR) { MTR_LOG_ERROR("Can't extract public key from MTRKeypair: %s", ErrorStr(err)); return NO; diff --git a/src/darwin/Framework/CHIP/MTRKeypair.h b/src/darwin/Framework/CHIP/MTRKeypair.h index a4e4521b2864a6..bf664e13aa6385 100644 --- a/src/darwin/Framework/CHIP/MTRKeypair.h +++ b/src/darwin/Framework/CHIP/MTRKeypair.h @@ -16,6 +16,7 @@ */ #import +#import #import NS_ASSUME_NONNULL_BEGIN @@ -31,13 +32,18 @@ NS_ASSUME_NONNULL_BEGIN * framework APIs. */ @protocol MTRKeypair -@required + +@optional /** - * @brief Return public key for the keypair. + * @brief Returns a copy of the public key for the keypair. */ -- (SecKeyRef)publicKey; +- (SecKeyRef)copyPublicKey MTR_NEWLY_AVAILABLE; + +/** + * @brief Returns public key for the keypair without adding a reference. DEPRECATED - please use copyPublicKey, otherwise this will leak. + */ +- (SecKeyRef)publicKey MTR_NEWLY_DEPRECATED("Please implement copyPublicKey, this will leak otherwise"); -@optional /** * @brief A function to sign a message using ECDSA * diff --git a/src/darwin/Framework/CHIP/MTRP256KeypairBridge.mm b/src/darwin/Framework/CHIP/MTRP256KeypairBridge.mm index d253baa8dbf95c..03a396e27dffe5 100644 --- a/src/darwin/Framework/CHIP/MTRP256KeypairBridge.mm +++ b/src/darwin/Framework/CHIP/MTRP256KeypairBridge.mm @@ -132,7 +132,17 @@ return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; } -CHIP_ERROR MTRP256KeypairBridge::setPubkey() { return MatterPubKeyFromSecKeyRef([mKeypair publicKey], &mPubkey); } +CHIP_ERROR MTRP256KeypairBridge::setPubkey() +{ + if ([mKeypair respondsToSelector:@selector(copyPublicKey)]) { + SecKeyRef publicKey = [mKeypair copyPublicKey]; + auto copyResult = MatterPubKeyFromSecKeyRef(publicKey, &mPubkey); + CFRelease(publicKey); + return copyResult; + } else { + return MatterPubKeyFromSecKeyRef([mKeypair publicKey], &mPubkey); + } +} CHIP_ERROR MTRP256KeypairBridge::MatterPubKeyFromSecKeyRef(SecKeyRef pubkeyRef, P256PublicKey * matterPubKey) { diff --git a/src/darwin/Framework/CHIPTests/MTRCertificateTests.m b/src/darwin/Framework/CHIPTests/MTRCertificateTests.m index fb6cfb9ecb7e67..d822028b5c8227 100644 --- a/src/darwin/Framework/CHIPTests/MTRCertificateTests.m +++ b/src/darwin/Framework/CHIPTests/MTRCertificateTests.m @@ -127,9 +127,13 @@ - (void)testGenerateIntermediateCert __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = [intermediateKeys copyPublicKey]; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); + __auto_type * intermediateCert = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:rootCert - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil error:nil]; @@ -155,13 +159,16 @@ - (void)testGenerateIntermediateCertWithValidityPeriod __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = intermediateKeys.copyPublicKey; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * startDate = [MTRCertificateTests startDateWithTimeIntervalSinceNow:300]; __auto_type * validityPeriod = [[NSDateInterval alloc] initWithStartDate:startDate duration:400]; __auto_type * intermediateCert = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:rootCert - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil validityPeriod:validityPeriod @@ -192,13 +199,16 @@ - (void)testGenerateIntermediateCertWithInfiniteValidity __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = intermediateKeys.copyPublicKey; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * startDate = [MTRCertificateTests startDateWithTimeIntervalSinceNow:300]; __auto_type * validityPeriod = [[NSDateInterval alloc] initWithStartDate:startDate endDate:[NSDate distantFuture]]; __auto_type * intermediateCert = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:rootCert - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil validityPeriod:validityPeriod @@ -229,6 +239,9 @@ - (void)testGenerateOperationalCertNoIntermediate __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * cats = [[NSMutableSet alloc] initWithCapacity:3]; // High bits are identifier, low bits are version. @@ -238,7 +251,7 @@ - (void)testGenerateOperationalCertNoIntermediate __auto_type * operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:cats @@ -265,6 +278,9 @@ - (void)testGenerateOperationalCertNoIntermediateWithValidityPeriod __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * cats = [[NSMutableSet alloc] initWithCapacity:3]; // High bits are identifier, low bits are version. @@ -277,7 +293,7 @@ - (void)testGenerateOperationalCertNoIntermediateWithValidityPeriod __auto_type * operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:cats @@ -309,6 +325,9 @@ - (void)testGenerateOperationalCertNoIntermediateWithInfiniteValidity __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * cats = [[NSMutableSet alloc] initWithCapacity:3]; // High bits are identifier, low bits are version. @@ -321,7 +340,7 @@ - (void)testGenerateOperationalCertNoIntermediateWithInfiniteValidity __auto_type * operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:cats @@ -353,10 +372,13 @@ - (void)testGenerateOperationalCertWithIntermediate __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = [intermediateKeys copyPublicKey]; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * intermediateCert = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:rootCert - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil error:nil]; @@ -364,10 +386,13 @@ - (void)testGenerateOperationalCertWithIntermediate __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * operationalCert = [MTRCertificates createOperationalCertificate:intermediateKeys signingCertificate:intermediateCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:nil @@ -394,6 +419,9 @@ - (void)testGenerateOperationalCertErrorCases __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * longCats = [[NSMutableSet alloc] initWithCapacity:4]; [longCats addObject:@0x00010001]; @@ -415,7 +443,7 @@ - (void)testGenerateOperationalCertErrorCases // Check basic case works __auto_type * operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:nil @@ -425,7 +453,7 @@ - (void)testGenerateOperationalCertErrorCases // CATs too long operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:longCats @@ -435,7 +463,7 @@ - (void)testGenerateOperationalCertErrorCases // Multiple CATs with the same identifier but different versions operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:catsWithSameIdentifier @@ -445,7 +473,7 @@ - (void)testGenerateOperationalCertErrorCases // CAT with invalid version operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:catsWithInvalidVersion @@ -455,7 +483,7 @@ - (void)testGenerateOperationalCertErrorCases // Signing key mismatch operationalCert = [MTRCertificates createOperationalCertificate:operationalKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:nil @@ -465,7 +493,7 @@ - (void)testGenerateOperationalCertErrorCases // Invalid fabric id operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@0 nodeID:@1 caseAuthenticatedTags:nil @@ -475,7 +503,7 @@ - (void)testGenerateOperationalCertErrorCases // Undefined node id operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@0 caseAuthenticatedTags:nil @@ -485,7 +513,7 @@ - (void)testGenerateOperationalCertErrorCases // Non-operational node id operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@(0xFFFFFFFFFFFFFFFFLLU) caseAuthenticatedTags:nil @@ -504,7 +532,16 @@ - (void)testGenerateCSR __auto_type * publicKey = [MTRCertificates publicKeyFromCSR:csr error:nil]; XCTAssertNotNil(publicKey); - SecKeyRef originalKeyRef = [testKeys publicKey]; + SecKeyRef originalKeyRef; + if ([testKeys respondsToSelector:@selector(copyPublicKey)]) { + originalKeyRef = [testKeys copyPublicKey]; + if (originalKeyRef != NULL) { + CFAutorelease(originalKeyRef); + } + } else { + originalKeyRef = [testKeys publicKey]; + } + XCTAssertTrue(originalKeyRef != NULL); NSData * originalPublicKey = (__bridge_transfer NSData *) SecKeyCopyExternalRepresentation(originalKeyRef, nil); diff --git a/src/darwin/Framework/CHIPTests/MTRCertificateValidityTests.m b/src/darwin/Framework/CHIPTests/MTRCertificateValidityTests.m index ecc593e8432045..719be071063fbe 100644 --- a/src/darwin/Framework/CHIPTests/MTRCertificateValidityTests.m +++ b/src/darwin/Framework/CHIPTests/MTRCertificateValidityTests.m @@ -259,10 +259,13 @@ - (void)initStack:(MTRTestCertificateIssuer *)certificateIssuer __auto_type * controllerOperationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(controllerOperationalKeys); + __auto_type * controllerPublicKey = controllerOperationalKeys.copyPublicKey; + XCTAssert(controllerPublicKey != NULL); + CFAutorelease(controllerPublicKey); __auto_type * controllerOperationalCert = [certificateIssuer issueOperationalCertificateForNode:@(kControllerId) - operationalPublicKey:controllerOperationalKeys.publicKey]; + operationalPublicKey:controllerPublicKey]; XCTAssertNotNil(controllerOperationalCert); __auto_type * params = [[MTRDeviceControllerStartupParams alloc] initWithIPK:certificateIssuer.rootKey.ipk diff --git a/src/darwin/Framework/CHIPTests/MTRControllerAdvertisingTests.m b/src/darwin/Framework/CHIPTests/MTRControllerAdvertisingTests.m index 4092a38b56f84e..bee6ee90df3524 100644 --- a/src/darwin/Framework/CHIPTests/MTRControllerAdvertisingTests.m +++ b/src/darwin/Framework/CHIPTests/MTRControllerAdvertisingTests.m @@ -164,10 +164,13 @@ - (nullable MTRDeviceController *)startControllerWithRootKeys:(MTRTestKeys *)roo __auto_type * root = [MTRCertificates createRootCertificate:rootKeys issuerID:@(1) fabricID:nil error:error]; XCTAssertNil(*error); XCTAssertNotNil(root); + __auto_type * publicKey = operationalKeys.copyPublicKey; + XCTAssert(publicKey != NULL); + CFAutorelease(publicKey); __auto_type * operational = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:root - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:publicKey fabricID:fabricID nodeID:nodeID caseAuthenticatedTags:nil diff --git a/src/darwin/Framework/CHIPTests/MTRControllerTests.m b/src/darwin/Framework/CHIPTests/MTRControllerTests.m index 436a0df230e3d9..afd755f8e5e757 100644 --- a/src/darwin/Framework/CHIPTests/MTRControllerTests.m +++ b/src/darwin/Framework/CHIPTests/MTRControllerTests.m @@ -620,10 +620,13 @@ - (void)testControllerSignerKeyWithIntermediate __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = [intermediateKeys copyPublicKey]; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * intermediate = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil error:nil]; @@ -860,10 +863,12 @@ - (void)testControllerRotateToICA __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = intermediateKeys.copyPublicKey; + CFAutorelease(intermediatePublicKey); __auto_type * intermediate = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil error:nil]; @@ -922,10 +927,13 @@ - (void)testControllerRotateFromICA __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = [intermediateKeys copyPublicKey]; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * intermediate = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil error:nil]; @@ -986,10 +994,13 @@ - (void)testControllerRotateICA __auto_type * intermediateKeys1 = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys1); + __auto_type * intermediate1PublicKey = [intermediateKeys1 copyPublicKey]; + XCTAssert(intermediate1PublicKey != NULL); + CFAutorelease(intermediate1PublicKey); __auto_type * intermediate1 = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys1.publicKey + intermediatePublicKey:intermediate1PublicKey issuerID:nil fabricID:nil error:nil]; @@ -997,10 +1008,13 @@ - (void)testControllerRotateICA __auto_type * intermediateKeys2 = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys2); + __auto_type * intermediate2PublicKey = [intermediateKeys2 copyPublicKey]; + XCTAssert(intermediate2PublicKey != NULL); + CFAutorelease(intermediate2PublicKey); __auto_type * intermediate2 = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys2.publicKey + intermediatePublicKey:intermediate2PublicKey issuerID:nil fabricID:nil error:nil]; @@ -1061,10 +1075,13 @@ - (void)testControllerICAWithoutRoot __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = [intermediateKeys copyPublicKey]; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * intermediate = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil error:nil]; @@ -1104,10 +1121,13 @@ - (void)testControllerProvideFullCertChain __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = [intermediateKeys copyPublicKey]; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * intermediate = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil error:nil]; @@ -1115,10 +1135,13 @@ - (void)testControllerProvideFullCertChain __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * operational = [MTRCertificates createOperationalCertificate:intermediateKeys signingCertificate:intermediate - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@123 nodeID:@456 caseAuthenticatedTags:nil @@ -1179,10 +1202,13 @@ - (void)testControllerProvideCertChainNoICA __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * operational = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:root - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@123 nodeID:@456 caseAuthenticatedTags:nil @@ -1229,10 +1255,13 @@ - (void)testControllerCertChainFabricMismatchRoot __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * operational = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:root - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@123 nodeID:@456 caseAuthenticatedTags:nil @@ -1273,10 +1302,13 @@ - (void)testControllerCertChainFabricMismatchIntermediate __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = [intermediateKeys copyPublicKey]; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * intermediate = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:@111 error:nil]; @@ -1284,10 +1316,13 @@ - (void)testControllerCertChainFabricMismatchIntermediate __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * operational = [MTRCertificates createOperationalCertificate:intermediateKeys signingCertificate:intermediate - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@123 nodeID:@456 caseAuthenticatedTags:nil diff --git a/src/darwin/Framework/CHIPTests/MTRFabricInfoTests.m b/src/darwin/Framework/CHIPTests/MTRFabricInfoTests.m index a98067098688b5..acdc0ea45ff572 100644 --- a/src/darwin/Framework/CHIPTests/MTRFabricInfoTests.m +++ b/src/darwin/Framework/CHIPTests/MTRFabricInfoTests.m @@ -157,10 +157,13 @@ - (void)testFabricInfoTwoFabrics __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = intermediateKeys.copyPublicKey; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * intermediate = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil error:nil]; diff --git a/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m b/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m index 1ead4692a2b335..3d91a64712e32f 100644 --- a/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m +++ b/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m @@ -403,13 +403,18 @@ - (nullable MTRDeviceController *)startControllerWithRootKeys:(MTRTestKeys *)roo XCTAssertNil(*error); XCTAssertNotNil(root); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + __auto_type * operational = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:root - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:fabricID nodeID:nodeID caseAuthenticatedTags:caseAuthenticatedTags error:error]; + CFRelease(operationalPublicKey); + XCTAssertNil(*error); XCTAssertNotNil(operational); diff --git a/src/darwin/Framework/CHIPTests/TestHelpers/MTRTestKeys.m b/src/darwin/Framework/CHIPTests/TestHelpers/MTRTestKeys.m index e6a74f25bdeccf..090593a41babfb 100644 --- a/src/darwin/Framework/CHIPTests/TestHelpers/MTRTestKeys.m +++ b/src/darwin/Framework/CHIPTests/TestHelpers/MTRTestKeys.m @@ -31,6 +31,12 @@ - (NSData *)publicKeyData return (__bridge_transfer NSData *) SecKeyCopyExternalRepresentation([self publicKey], nil); } +- (SecKeyRef)copyPublicKey +{ + CFRetain(_publicKey); + return _publicKey; +} + - (instancetype)init { if (!(self = [super init])) { From 412271bcd8665810677aab39fe181385e065b7eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damian=20Kr=C3=B3lik?= <66667989+Damian-Nordic@users.noreply.github.com> Date: Fri, 15 Nov 2024 20:10:50 +0100 Subject: [PATCH 21/27] [nrfconnect] Fix all-clusters-app settings size (#36501) After switching to building with sysbuild, the source of the settings partition size has changed from the DTS to the partition manager. Make sure the settings partition is 32kB even when building all-clusters-apps without DFU support. Signed-off-by: Damian Krolik --- examples/all-clusters-app/nrfconnect/prj.conf | 3 +++ examples/all-clusters-minimal-app/nrfconnect/prj.conf | 3 +++ 2 files changed, 6 insertions(+) diff --git a/examples/all-clusters-app/nrfconnect/prj.conf b/examples/all-clusters-app/nrfconnect/prj.conf index 5917c3a9c7a17e..075fdd8e9d8d19 100644 --- a/examples/all-clusters-app/nrfconnect/prj.conf +++ b/examples/all-clusters-app/nrfconnect/prj.conf @@ -54,3 +54,6 @@ CONFIG_CHIP_QSPI_NOR=n # Enable the Read Client for binding purposes CONFIG_CHIP_ENABLE_READ_CLIENT=y + +# Increase the settings partition +CONFIG_PM_PARTITION_SIZE_SETTINGS_STORAGE=0x8000 diff --git a/examples/all-clusters-minimal-app/nrfconnect/prj.conf b/examples/all-clusters-minimal-app/nrfconnect/prj.conf index 58dae15804fe81..9e738ba64d1431 100644 --- a/examples/all-clusters-minimal-app/nrfconnect/prj.conf +++ b/examples/all-clusters-minimal-app/nrfconnect/prj.conf @@ -55,3 +55,6 @@ CONFIG_CHIP_QSPI_NOR=n # Enable Factory Data feature CONFIG_CHIP_FACTORY_DATA=y CONFIG_CHIP_FACTORY_DATA_BUILD=y + +# Increase the settings partition +CONFIG_PM_PARTITION_SIZE_SETTINGS_STORAGE=0x8000 From cda1c4d94edfb40871e623dcd5747a1306a618ee Mon Sep 17 00:00:00 2001 From: Kiel Oleson Date: Fri, 15 Nov 2024 12:20:14 -0800 Subject: [PATCH 22/27] Darwin XPC: allow `NSDate` typed objects in `internalProperties` dictionary (#36514) --- src/darwin/Framework/CHIP/MTRDevice_XPC.mm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRDevice_XPC.mm b/src/darwin/Framework/CHIP/MTRDevice_XPC.mm index b5006336029d21..d5356320b24d4c 100644 --- a/src/darwin/Framework/CHIP/MTRDevice_XPC.mm +++ b/src/darwin/Framework/CHIP/MTRDevice_XPC.mm @@ -258,7 +258,8 @@ - (oneway void)deviceConfigurationChanged:(NSNumber *)nodeID - (BOOL)_internalState:(NSDictionary *)dictionary hasValidValuesForKeys:(const NSArray *)keys valueRequired:(BOOL)required { - // All the keys are NSNumber-valued. + // At one point, all keys were NSNumber valued; now there are also NSDates. + // TODO: Create a mapping between keys and their expected types and use that in the type check below. for (NSString * key in keys) { id value = dictionary[key]; if (!value) { @@ -269,7 +270,7 @@ - (BOOL)_internalState:(NSDictionary *)dictionary hasValidValuesForKeys:(const N continue; } - if (!MTR_SAFE_CAST(value, NSNumber)) { + if (!MTR_SAFE_CAST(value, NSNumber) && !MTR_SAFE_CAST(value, NSDate)) { MTR_LOG_ERROR("%@ device:internalStateUpdated: handed state with invalid value for \"%@\": %@", self, key, value); return NO; } From f47f2fe99082b8b75d2dc73595f1479e0cf24d7f Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Fri, 15 Nov 2024 15:36:49 -0800 Subject: [PATCH 23/27] [Fabric-Sync] Fix failing to pair sync device (#36510) * Fix failing to pair sync device * Address review comments * Address review commment --- examples/fabric-sync/admin/DeviceManager.cpp | 5 +- examples/fabric-sync/admin/PairingManager.cpp | 5 ++ examples/fabric-sync/bridge/src/Bridge.cpp | 79 +++++++++++++++++++ 3 files changed, 87 insertions(+), 2 deletions(-) diff --git a/examples/fabric-sync/admin/DeviceManager.cpp b/examples/fabric-sync/admin/DeviceManager.cpp index 69aa0a583f7273..f9685295e48ad2 100644 --- a/examples/fabric-sync/admin/DeviceManager.cpp +++ b/examples/fabric-sync/admin/DeviceManager.cpp @@ -450,13 +450,14 @@ void DeviceManager::HandleAttributePartsListUpdate(TLV::TLVReader & data) for (const auto & endpoint : addedEndpoints) { // print to console - fprintf(stderr, "A new device is added on Endpoint: %u\n", endpoint); + fprintf(stderr, "A new endpoint %u is added on the remote bridge\n", endpoint); } // Process removed endpoints for (const auto & endpoint : removedEndpoints) { - ChipLogProgress(NotSpecified, "Endpoint removed: %u", endpoint); + // print to console + fprintf(stderr, "Endpoint %u removed from the remote bridge\n", endpoint); SyncedDevice * device = FindDeviceByEndpoint(endpoint); diff --git a/examples/fabric-sync/admin/PairingManager.cpp b/examples/fabric-sync/admin/PairingManager.cpp index ba360051a27b84..954680fe176187 100644 --- a/examples/fabric-sync/admin/PairingManager.cpp +++ b/examples/fabric-sync/admin/PairingManager.cpp @@ -467,6 +467,11 @@ void PairingManager::OnCurrentFabricRemove(void * context, NodeId nodeId, CHIP_E self->mPairingDelegate->OnDeviceRemoved(nodeId, err); self->SetPairingDelegate(nullptr); } + + FabricIndex fabricIndex = self->CurrentCommissioner().GetFabricIndex(); + app::InteractionModelEngine::GetInstance()->ShutdownSubscriptions(fabricIndex, nodeId); + ScopedNodeId scopedNodeId(nodeId, fabricIndex); + DeviceManager::Instance().RemoveSyncedDevice(scopedNodeId); } else { diff --git a/examples/fabric-sync/bridge/src/Bridge.cpp b/examples/fabric-sync/bridge/src/Bridge.cpp index 3d0a4af56ff064..770509957b99a5 100644 --- a/examples/fabric-sync/bridge/src/Bridge.cpp +++ b/examples/fabric-sync/bridge/src/Bridge.cpp @@ -45,6 +45,83 @@ namespace bridge { namespace { +class AdministratorCommissioningCommandHandler : public CommandHandlerInterface +{ +public: + // Register for the AdministratorCommissioning cluster on all endpoints. + AdministratorCommissioningCommandHandler() : + CommandHandlerInterface(Optional::Missing(), AdministratorCommissioning::Id) + {} + + void InvokeCommand(HandlerContext & handlerContext) override; +}; + +void AdministratorCommissioningCommandHandler::InvokeCommand(HandlerContext & handlerContext) +{ + using Protocols::InteractionModel::Status; + + EndpointId endpointId = handlerContext.mRequestPath.mEndpointId; + + if (handlerContext.mRequestPath.mCommandId != AdministratorCommissioning::Commands::OpenCommissioningWindow::Id || + endpointId == kRootEndpointId) + { + // Proceed with default handling in Administrator Commissioning Server + return; + } + + ChipLogProgress(NotSpecified, "Received command to open commissioning window on Endpoint: %d", endpointId); + + handlerContext.SetCommandHandled(); + + AdministratorCommissioning::Commands::OpenCommissioningWindow::DecodableType commandData; + if (DataModel::Decode(handlerContext.mPayload, commandData) != CHIP_NO_ERROR) + { + handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::InvalidCommand); + return; + } + + Status status = Status::Failure; + BridgedDevice * device = BridgedDeviceManager::Instance().GetDevice(endpointId); + FabricAdminDelegate * adminDelegate = FabricBridge::Instance().GetDelegate(); + + if (!device) + { + ChipLogError(NotSpecified, "Commissioning window failed to open: device is null"); + return; + } + + if (!adminDelegate) + { + ChipLogError(NotSpecified, "Commissioning window failed to open: adminDelegate is null"); + return; + } + + auto nodeId = device->GetScopedNodeId().GetNodeId(); + auto fabricIndex = device->GetScopedNodeId().GetFabricIndex(); + + Controller::CommissioningWindowVerifierParams params; + params.SetNodeId(nodeId) + .SetTimeout(commandData.commissioningTimeout) + .SetDiscriminator(commandData.discriminator) + .SetIteration(commandData.iterations) + .SetSalt(commandData.salt) + .SetVerifier(commandData.PAKEPasscodeVerifier); + + CHIP_ERROR err = adminDelegate->OpenCommissioningWindow(params, fabricIndex); + + if (err == CHIP_NO_ERROR) + { + ChipLogProgress(NotSpecified, "Commissioning window is now open"); + status = Status::Success; + } + else + { + ChipLogError(NotSpecified, "Failed to open commissioning window. Error: %" CHIP_ERROR_FORMAT, err.Format()); + } + + handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status); +} + class BridgedDeviceInformationCommandHandler : public CommandHandlerInterface { public: @@ -115,6 +192,7 @@ void BridgedDeviceInformationCommandHandler::InvokeCommand(HandlerContext & hand BridgedAdministratorCommissioning gBridgedAdministratorCommissioning; BridgedDeviceBasicInformationImpl gBridgedDeviceBasicInformationAttributes; +AdministratorCommissioningCommandHandler gAdministratorCommissioningCommandHandler; BridgedDeviceInformationCommandHandler gBridgedDeviceInformationCommandHandler; } // namespace @@ -122,6 +200,7 @@ BridgedDeviceInformationCommandHandler gBridgedDeviceInformationCommandHandler; CHIP_ERROR BridgeInit(FabricAdminDelegate * delegate) { MatterEcosystemInformationPluginServerInitCallback(); + CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(&gAdministratorCommissioningCommandHandler); CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(&gBridgedDeviceInformationCommandHandler); AttributeAccessInterfaceRegistry::Instance().Register(&gBridgedDeviceBasicInformationAttributes); From b258171cfca7ac466dfacd48ac833a8c1698a099 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Fri, 15 Nov 2024 15:37:04 -0800 Subject: [PATCH 24/27] [Fabric-Admin] Set remote bridge after reverse pair the bridge device (#36451) * [Fabric-Admin] Set remote bridge after reverse pair the bridge devide * Add remote bridge to local bridge after pairing * Set the reverse commissioning flag * Do not add device as a bridged device after reverse pairing * Fix compare error * Address review comments --- .../fabric-sync/FabricSyncCommand.cpp | 3 +- .../device_manager/DeviceManager.cpp | 48 +++++++++++-------- .../device_manager/DeviceManager.h | 21 ++++---- .../device_manager/DeviceSynchronization.cpp | 8 +++- .../device_manager/PairingManager.cpp | 12 ++--- examples/fabric-admin/rpc/RpcServer.cpp | 38 +++++++++++++-- 6 files changed, 90 insertions(+), 40 deletions(-) diff --git a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp index 315bf2f3711f35..e8296fa478d95d 100644 --- a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp +++ b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp @@ -57,6 +57,7 @@ void FabricSyncAddBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_E DeviceManager::Instance().UpdateLastUsedNodeId(mBridgeNodeId); DeviceManager::Instance().SubscribeRemoteFabricBridge(); + DeviceManager::Instance().InitCommissionerControl(); if (DeviceManager::Instance().IsLocalBridgeReady()) { @@ -284,7 +285,7 @@ void FabricSyncDeviceCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERRO if (err == CHIP_NO_ERROR) { - DeviceManager::Instance().AddSyncedDevice(Device(mAssignedNodeId, mRemoteEndpointId)); + DeviceManager::Instance().AddSyncedDevice(SyncedDevice(mAssignedNodeId, mRemoteEndpointId)); } else { diff --git a/examples/fabric-admin/device_manager/DeviceManager.cpp b/examples/fabric-admin/device_manager/DeviceManager.cpp index 9f40f92a87c411..7e40a8196555ea 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.cpp +++ b/examples/fabric-admin/device_manager/DeviceManager.cpp @@ -72,39 +72,35 @@ void DeviceManager::UpdateLastUsedNodeId(NodeId nodeId) void DeviceManager::SetRemoteBridgeNodeId(chip::NodeId nodeId) { mRemoteBridgeNodeId = nodeId; - - if (mRemoteBridgeNodeId != kUndefinedNodeId) - { - mCommissionerControl.Init(PairingManager::Instance().CurrentCommissioner(), mRemoteBridgeNodeId, kAggregatorEndpointId); - } + ChipLogProgress(NotSpecified, "Set remote bridge NodeId:" ChipLogFormatX64, ChipLogValueX64(mRemoteBridgeNodeId)); } -void DeviceManager::AddSyncedDevice(const Device & device) +void DeviceManager::AddSyncedDevice(const SyncedDevice & device) { mSyncedDevices.insert(device); ChipLogProgress(NotSpecified, "Added synced device: NodeId:" ChipLogFormatX64 ", EndpointId %u", ChipLogValueX64(device.GetNodeId()), device.GetEndpointId()); } -Device * DeviceManager::FindDeviceByEndpoint(EndpointId endpointId) +SyncedDevice * DeviceManager::FindDeviceByEndpoint(EndpointId endpointId) { for (auto & device : mSyncedDevices) { if (device.GetEndpointId() == endpointId) { - return const_cast(&device); + return const_cast(&device); } } return nullptr; } -Device * DeviceManager::FindDeviceByNode(NodeId nodeId) +SyncedDevice * DeviceManager::FindDeviceByNode(NodeId nodeId) { for (auto & device : mSyncedDevices) { if (device.GetNodeId() == nodeId) { - return const_cast(&device); + return const_cast(&device); } } return nullptr; @@ -116,8 +112,8 @@ void DeviceManager::RemoveSyncedDevice(chip::ScopedNodeId scopedNodeId) RemoveSynchronizedDevice(scopedNodeId); #endif - NodeId nodeId = scopedNodeId.GetNodeId(); - Device * device = FindDeviceByNode(nodeId); + NodeId nodeId = scopedNodeId.GetNodeId(); + SyncedDevice * device = FindDeviceByNode(nodeId); if (device == nullptr) { ChipLogProgress(NotSpecified, "No device found with NodeId:" ChipLogFormatX64, ChipLogValueX64(nodeId)); @@ -129,6 +125,18 @@ void DeviceManager::RemoveSyncedDevice(chip::ScopedNodeId scopedNodeId) ChipLogValueX64(device->GetNodeId()), device->GetEndpointId()); } +void DeviceManager::InitCommissionerControl() +{ + if (mRemoteBridgeNodeId != kUndefinedNodeId) + { + mCommissionerControl.Init(PairingManager::Instance().CurrentCommissioner(), mRemoteBridgeNodeId, kAggregatorEndpointId); + } + else + { + ChipLogError(NotSpecified, "Failed to initialize the Commissioner Control delegate"); + } +} + void DeviceManager::OpenDeviceCommissioningWindow(ScopedNodeId scopedNodeId, uint32_t iterations, uint16_t commissioningTimeoutSec, uint16_t discriminator, const ByteSpan & salt, const ByteSpan & verifier) { @@ -212,10 +220,10 @@ void DeviceManager::UnpairLocalFabricBridge() void DeviceManager::SubscribeRemoteFabricBridge() { - ChipLogProgress(NotSpecified, "Start subscription to the remote bridge.") + ChipLogProgress(NotSpecified, "Start subscription to the remote bridge."); - CHIP_ERROR error = mBridgeSubscriber.StartSubscription(PairingManager::Instance().CurrentCommissioner(), - mRemoteBridgeNodeId, kAggregatorEndpointId); + CHIP_ERROR error = mBridgeSubscriber.StartSubscription(PairingManager::Instance().CurrentCommissioner(), mRemoteBridgeNodeId, + kAggregatorEndpointId); if (error != CHIP_NO_ERROR) { @@ -354,7 +362,7 @@ void DeviceManager::HandleAttributePartsListUpdate(TLV::TLVReader & data) std::vector removedEndpoints; // Note: We're using vectors and manual searches instead of set operations - // because we need to work with the Device objects in mSyncedDevices, + // because we need to work with the SyncedDevice objects in mSyncedDevices, // not just their EndpointIds. This approach allows us to access the full // Device information when processing changes. @@ -381,15 +389,16 @@ void DeviceManager::HandleAttributePartsListUpdate(TLV::TLVReader & data) for (const auto & endpoint : addedEndpoints) { // print to console - fprintf(stderr, "A new device is added on Endpoint: %u\n", endpoint); + fprintf(stderr, "A new endpoint %u is added on the remote bridge\n", endpoint); } // Process removed endpoints for (const auto & endpoint : removedEndpoints) { - ChipLogProgress(NotSpecified, "Endpoint removed: %u", endpoint); + // print to console + fprintf(stderr, "Endpoint %u removed from the remote bridge\n", endpoint); - Device * device = FindDeviceByEndpoint(endpoint); + SyncedDevice * device = FindDeviceByEndpoint(endpoint); if (device == nullptr) { @@ -467,6 +476,7 @@ void DeviceManager::HandleCommandResponse(const app::ConcreteCommandPath & path, if (path.mClusterId == app::Clusters::CommissionerControl::Id && path.mCommandId == app::Clusters::CommissionerControl::Commands::ReverseOpenCommissioningWindow::Id) { + VerifyOrDie(path.mEndpointId == kAggregatorEndpointId); HandleReverseOpenCommissioningWindow(data); } } diff --git a/examples/fabric-admin/device_manager/DeviceManager.h b/examples/fabric-admin/device_manager/DeviceManager.h index 594fcfc5745703..8c273ee53d3af7 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.h +++ b/examples/fabric-admin/device_manager/DeviceManager.h @@ -32,15 +32,15 @@ constexpr uint32_t kDefaultSetupPinCode = 20202021; constexpr uint16_t kDefaultLocalBridgePort = 5540; constexpr uint16_t kResponseTimeoutSeconds = 30; -class Device +class SyncedDevice { public: - Device(chip::NodeId nodeId, chip::EndpointId endpointId) : mNodeId(nodeId), mEndpointId(endpointId) {} + SyncedDevice(chip::NodeId nodeId, chip::EndpointId endpointId) : mNodeId(nodeId), mEndpointId(endpointId) {} chip::NodeId GetNodeId() const { return mNodeId; } chip::EndpointId GetEndpointId() const { return mEndpointId; } - bool operator<(const Device & other) const + bool operator<(const SyncedDevice & other) const { return mNodeId < other.mNodeId || (mNodeId == other.mNodeId && mEndpointId < other.mEndpointId); } @@ -81,10 +81,15 @@ class DeviceManager bool IsLocalBridgeReady() const { return mLocalBridgeNodeId != chip::kUndefinedNodeId; } - void AddSyncedDevice(const Device & device); + void AddSyncedDevice(const SyncedDevice & device); void RemoveSyncedDevice(chip::ScopedNodeId scopedNodeId); + /** + * @brief Initializes the CommissionerControl for fabric sync setup process. + */ + void InitCommissionerControl(); + /** * @brief Determines whether a given nodeId corresponds to the "current bridge device," either local or remote. * @@ -177,8 +182,8 @@ class DeviceManager void HandleCommandResponse(const chip::app::ConcreteCommandPath & path, chip::TLV::TLVReader & data); - Device * FindDeviceByEndpoint(chip::EndpointId endpointId); - Device * FindDeviceByNode(chip::NodeId nodeId); + SyncedDevice * FindDeviceByEndpoint(chip::EndpointId endpointId); + SyncedDevice * FindDeviceByNode(chip::NodeId nodeId); private: void RequestCommissioningApproval(); @@ -193,8 +198,6 @@ class DeviceManager void HandleReverseOpenCommissioningWindow(chip::TLV::TLVReader & data); - static DeviceManager sInstance; - chip::NodeId mLastUsedNodeId = 0; // The Node ID of the remote bridge used for Fabric-Sync @@ -207,7 +210,7 @@ class DeviceManager // This represents the bridge within its own ecosystem. chip::NodeId mLocalBridgeNodeId = chip::kUndefinedNodeId; - std::set mSyncedDevices; + std::set mSyncedDevices; bool mInitialized = false; uint64_t mRequestId = 0; diff --git a/examples/fabric-admin/device_manager/DeviceSynchronization.cpp b/examples/fabric-admin/device_manager/DeviceSynchronization.cpp index 092c2505d19d73..9274b98d4a0d52 100644 --- a/examples/fabric-admin/device_manager/DeviceSynchronization.cpp +++ b/examples/fabric-admin/device_manager/DeviceSynchronization.cpp @@ -142,13 +142,16 @@ void DeviceSynchronizer::OnReportEnd() void DeviceSynchronizer::OnDone(app::ReadClient * apReadClient) { + ChipLogProgress(NotSpecified, "Synchronization complete for NodeId:" ChipLogFormatX64, ChipLogValueX64(mNodeId)); + #if defined(PW_RPC_ENABLED) if (mState == State::ReceivedResponse && !DeviceManager::Instance().IsCurrentBridgeDevice(mNodeId)) { GetUniqueId(); if (mState == State::GettingUid) { - // GetUniqueId was successful and we rely on callback to call SynchronizationCompleteAddDevice. + ChipLogProgress(NotSpecified, + "GetUniqueId was successful and we rely on callback to call SynchronizationCompleteAddDevice."); return; } SynchronizationCompleteAddDevice(); @@ -206,6 +209,8 @@ void DeviceSynchronizer::StartDeviceSynchronization(Controller::DeviceController mNodeId = nodeId; + ChipLogProgress(NotSpecified, "Start device synchronization for NodeId:" ChipLogFormatX64, ChipLogValueX64(mNodeId)); + #if defined(PW_RPC_ENABLED) mCurrentDeviceData = chip_rpc_SynchronizedDevice_init_default; mCurrentDeviceData.has_id = true; @@ -272,6 +277,7 @@ void DeviceSynchronizer::GetUniqueId() void DeviceSynchronizer::SynchronizationCompleteAddDevice() { VerifyOrDie(mState == State::ReceivedResponse || mState == State::GettingUid); + ChipLogProgress(NotSpecified, "Synchronization complete and add device"); #if defined(PW_RPC_ENABLED) AddSynchronizedDevice(mCurrentDeviceData); diff --git a/examples/fabric-admin/device_manager/PairingManager.cpp b/examples/fabric-admin/device_manager/PairingManager.cpp index 8474d78f023343..8d985ac553f010 100644 --- a/examples/fabric-admin/device_manager/PairingManager.cpp +++ b/examples/fabric-admin/device_manager/PairingManager.cpp @@ -285,6 +285,12 @@ void PairingManager::OnPairingDeleted(CHIP_ERROR err) void PairingManager::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err) { + if (mPairingDelegate) + { + mPairingDelegate->OnCommissioningComplete(nodeId, err); + SetPairingDelegate(nullptr); + } + if (err == CHIP_NO_ERROR) { // print to console @@ -308,12 +314,6 @@ void PairingManager::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err) } ChipLogProgress(NotSpecified, "Device commissioning Failure: %s", ErrorStr(err)); } - - if (mPairingDelegate) - { - mPairingDelegate->OnCommissioningComplete(nodeId, err); - SetPairingDelegate(nullptr); - } } void PairingManager::OnReadCommissioningInfo(const Controller::ReadCommissioningInfo & info) diff --git a/examples/fabric-admin/rpc/RpcServer.cpp b/examples/fabric-admin/rpc/RpcServer.cpp index 05fb9492248131..f59a2729dbfa84 100644 --- a/examples/fabric-admin/rpc/RpcServer.cpp +++ b/examples/fabric-admin/rpc/RpcServer.cpp @@ -55,7 +55,7 @@ struct ScopedNodeIdHasher } }; -class FabricAdmin final : public rpc::FabricAdmin, public IcdManager::Delegate +class FabricAdmin final : public rpc::FabricAdmin, public admin::PairingDelegate, public IcdManager::Delegate { public: void OnCheckInCompleted(const app::ICDClientInfo & clientInfo) override @@ -96,6 +96,33 @@ class FabricAdmin final : public rpc::FabricAdmin, public IcdManager::Delegate } } + void OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) override + { + if (mNodeId != deviceId) + { + ChipLogError(NotSpecified, + "Tried to pair a non-bridge device (0x:" ChipLogFormatX64 ") with result: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + return; + } + else + { + ChipLogProgress(NotSpecified, "Reverse commission succeeded for NodeId:" ChipLogFormatX64, ChipLogValueX64(mNodeId)); + } + + if (err == CHIP_NO_ERROR) + { + DeviceManager::Instance().SetRemoteBridgeNodeId(deviceId); + } + else + { + ChipLogError(NotSpecified, "Failed to pair bridge device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + } + + mNodeId = kUndefinedNodeId; + } + pw::Status OpenCommissioningWindow(const chip_rpc_DeviceCommissioningWindowInfo & request, chip_rpc_OperationStatus & response) override { @@ -146,13 +173,14 @@ class FabricAdmin final : public rpc::FabricAdmin, public IcdManager::Delegate if (error == CHIP_NO_ERROR) { - NodeId nodeId = DeviceManager::Instance().GetNextAvailableNodeId(); + mNodeId = DeviceManager::Instance().GetNextAvailableNodeId(); + ; // After responding with RequestCommissioningApproval to the node where the client initiated the // RequestCommissioningApproval, you need to wait for it to open a commissioning window on its bridge. usleep(kCommissionPrepareTimeMs * 1000); - - DeviceManager::Instance().PairRemoteDevice(nodeId, code.c_str()); + PairingManager::Instance().SetPairingDelegate(this); + DeviceManager::Instance().PairRemoteDevice(mNodeId, code.c_str()); } else { @@ -224,6 +252,8 @@ class FabricAdmin final : public rpc::FabricAdmin, public IcdManager::Delegate Platform::Delete(data); } + NodeId mNodeId = chip::kUndefinedNodeId; + // Modifications to mPendingCheckIn should be done on the MatterEventLoop thread // otherwise we would need a mutex protecting this data to prevent race as this // data is accessible by both RPC thread and Matter eventloop. From 18425eb9dbaaf3feaf0bbf718a4e25062d3e4bde Mon Sep 17 00:00:00 2001 From: Sergio Soares Date: Fri, 15 Nov 2024 20:04:59 -0500 Subject: [PATCH 25/27] fan-control-server: Fix FanMode circular callback issue (#36515) Similar to what was done for Speed and Percent, this PR fixes a bug where a FanMode could result in a circular callback. For example, setting the FanMode to kAuto, could trigger this issue. --- .../fan-control-server/fan-control-server.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/app/clusters/fan-control-server/fan-control-server.cpp b/src/app/clusters/fan-control-server/fan-control-server.cpp index 7ece1a1b575a24..2c30c9c6cdfa70 100644 --- a/src/app/clusters/fan-control-server/fan-control-server.cpp +++ b/src/app/clusters/fan-control-server/fan-control-server.cpp @@ -89,6 +89,7 @@ bool gWriteFromClusterLogic = false; // Avoid circular callback calls when adjusting SpeedSetting and PercentSetting together. ScopedChangeOnly gSpeedWriteInProgress(false); ScopedChangeOnly gPercentWriteInProgress(false); +ScopedChangeOnly gFanModeWriteInProgress(false); Status SetFanModeToOff(EndpointId endpointId) { @@ -160,12 +161,16 @@ MatterFanControlClusterServerPreAttributeChangedCallback(const ConcreteAttribute switch (attributePath.mAttributeId) { case FanMode::Id: { + if (gFanModeWriteInProgress) + { + return Status::WriteIgnored; + } if (*value == to_underlying(FanModeEnum::kOn)) { FanMode::Set(attributePath.mEndpointId, FanModeEnum::kHigh); - res = Status::WriteIgnored; + return Status::WriteIgnored; } - else if (*value == to_underlying(FanModeEnum::kSmart)) + if (*value == to_underlying(FanModeEnum::kSmart)) { FanModeSequenceEnum fanModeSequence; Status status = FanModeSequence::Get(attributePath.mEndpointId, &fanModeSequence); @@ -328,6 +333,9 @@ void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAt Status status = FanMode::Get(attributePath.mEndpointId, &mode); VerifyOrReturn(Status::Success == status); + // Avoid circular callback calls + ScopedChange FanModeWriteInProgress(gFanModeWriteInProgress, true); + // Setting the FanMode value to Off SHALL set the values of PercentSetting, PercentCurrent, // SpeedSetting, SpeedCurrent attributes to 0 (zero). if (mode == FanModeEnum::kOff) From 61e288a1968f359a57ebd40b60197976ebec46f7 Mon Sep 17 00:00:00 2001 From: Sergio Soares Date: Fri, 15 Nov 2024 21:50:23 -0500 Subject: [PATCH 26/27] chef-fan-control: Remove unnecessary circular callback checks (#36517) * chef-fan-control: Remove unnecessary checks With the recent circular callback bugfixes done in the cluster code in pull/36515 and pull/36489, we can now safely remove unnecessary checks that prevented the circular callbacks in the app side. * remove unused includes/imports. --- .../chef/common/chef-fan-control-manager.cpp | 35 ++++--------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/examples/chef/common/chef-fan-control-manager.cpp b/examples/chef/common/chef-fan-control-manager.cpp index 7c2aec389e08a4..42555e8052bea0 100644 --- a/examples/chef/common/chef-fan-control-manager.cpp +++ b/examples/chef/common/chef-fan-control-manager.cpp @@ -207,11 +207,6 @@ FanControl::FanModeEnum ChefFanControlManager::SpeedToFanMode(uint8_t speed) void ChefFanControlManager::SetPercentCurrent(uint8_t aNewPercentCurrent) { - if (aNewPercentCurrent == mPercentCurrent) - { - return; - } - ChipLogDetail(NotSpecified, "ChefFanControlManager::SetPercentCurrent: %d", aNewPercentCurrent); mPercentCurrent = aNewPercentCurrent; Status status = FanControl::Attributes::PercentCurrent::Set(mEndpoint, mPercentCurrent); @@ -224,12 +219,6 @@ void ChefFanControlManager::SetPercentCurrent(uint8_t aNewPercentCurrent) void ChefFanControlManager::SetSpeedCurrent(uint8_t aNewSpeedCurrent) { - if (aNewSpeedCurrent == mSpeedCurrent) - { - return; - } - - ChipLogDetail(NotSpecified, "ChefFanControlManager::SetSpeedCurrent: %d", aNewSpeedCurrent); mSpeedCurrent = aNewSpeedCurrent; Status status = FanControl::Attributes::SpeedCurrent::Set(mEndpoint, aNewSpeedCurrent); if (status != Status::Success) @@ -245,11 +234,8 @@ void ChefFanControlManager::FanModeWriteCallback(FanControl::FanModeEnum aNewFan switch (aNewFanMode) { case FanControl::FanModeEnum::kOff: { - if (mSpeedCurrent != 0) - { - DataModel::Nullable speedSetting(0); - SetSpeedSetting(speedSetting); - } + DataModel::Nullable speedSetting(0); + SetSpeedSetting(speedSetting); break; } case FanControl::FanModeEnum::kLow: { @@ -291,20 +277,11 @@ void ChefFanControlManager::FanModeWriteCallback(FanControl::FanModeEnum aNewFan void ChefFanControlManager::SetSpeedSetting(DataModel::Nullable aNewSpeedSetting) { - if (aNewSpeedSetting.IsNull()) - { - ChipLogError(NotSpecified, "ChefFanControlManager::SetSpeedSetting: null value is invalid"); - return; - } - - if (aNewSpeedSetting.Value() != mSpeedCurrent) + Status status = FanControl::Attributes::SpeedSetting::Set(mEndpoint, aNewSpeedSetting); + if (status != Status::Success) { - Status status = FanControl::Attributes::SpeedSetting::Set(mEndpoint, aNewSpeedSetting); - if (status != Status::Success) - { - ChipLogError(NotSpecified, "ChefFanControlManager::SetSpeedSetting: failed to set SpeedSetting attribute: %d", - to_underlying(status)); - } + ChipLogError(NotSpecified, "ChefFanControlManager::SetSpeedSetting: failed to set SpeedSetting attribute: %d", + to_underlying(status)); } } From 10a518b8c60702a32767530cd86ec60e0041bbc8 Mon Sep 17 00:00:00 2001 From: Alex Tsitsiura Date: Mon, 18 Nov 2024 16:20:05 +0200 Subject: [PATCH 27/27] [Telink] Update Docker image (Zephyr update) (#36530) * [Telink] Update Docker image (Zephyr update) * [Telink] Update Docker image (Zephyr update) --- integrations/docker/images/base/chip-build/version | 2 +- integrations/docker/images/stage-2/chip-build-telink/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/integrations/docker/images/base/chip-build/version b/integrations/docker/images/base/chip-build/version index 2546ff1921d2dc..6df5517b7ead14 100644 --- a/integrations/docker/images/base/chip-build/version +++ b/integrations/docker/images/base/chip-build/version @@ -1 +1 @@ -91 : [Ameba] Update matter timers and add more examples +92 : [Telink] Update Docker image (Zephyr update) diff --git a/integrations/docker/images/stage-2/chip-build-telink/Dockerfile b/integrations/docker/images/stage-2/chip-build-telink/Dockerfile index 2b84323d445955..b286bb8a74888b 100644 --- a/integrations/docker/images/stage-2/chip-build-telink/Dockerfile +++ b/integrations/docker/images/stage-2/chip-build-telink/Dockerfile @@ -18,7 +18,7 @@ RUN set -x \ && : # last line # Setup Zephyr -ARG ZEPHYR_REVISION=f762f1a1027284e63e338e6d83deeade62f355b0 +ARG ZEPHYR_REVISION=d88a47760dd4c7e57dfcc83e7c5856a9cea88fc1 WORKDIR /opt/telink/zephyrproject RUN set -x \ && python3 -m pip install --break-system-packages -U --no-cache-dir west \