From 900c55bb3f65397d9a32595c0069639109d960c5 Mon Sep 17 00:00:00 2001 From: Shreyas Balakrishna Bhandare Date: Wed, 26 Feb 2025 23:13:10 -0800 Subject: [PATCH 01/14] Add on-off command handlers for fan control --- .../chef/common/chef-fan-control-manager.cpp | 144 ++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/examples/chef/common/chef-fan-control-manager.cpp b/examples/chef/common/chef-fan-control-manager.cpp index 42555e8052bea0..2b20a9398ebce7 100644 --- a/examples/chef/common/chef-fan-control-manager.cpp +++ b/examples/chef/common/chef-fan-control-manager.cpp @@ -49,6 +49,11 @@ class ChefFanControlManager : public Delegate DataModel::Nullable GetSpeedSetting(); DataModel::Nullable GetPercentSetting(); +#ifdef MATTER_DM_PLUGIN_ON_OFF_SERVER + Status OnCommand(const app::ConcreteCommandPath & commandPath); + Status OffCommand(const app::ConcreteCommandPath & commandPath); +#endif + private: uint8_t mPercentCurrent = 0; uint8_t mSpeedCurrent = 0; @@ -329,6 +334,145 @@ void emberAfFanControlClusterInitCallback(EndpointId endpoint) mFanControlManager->Init(); } +#ifdef MATTER_DM_PLUGIN_ON_OFF_SERVER + +Status ChefFanControlManager::OnCommand(const app::ConcreteCommandPath & commandPath) +{ + ChipLogProgress(DeviceLayer, "ChefFanControlManager::OnCommand"); + + bool currentValue; + // read current on/off value + Status status = OnOff::Attributes::OnOff::Get(commandPath.mEndpointId, ¤tValue); + if (status != Status::Success) + { + ChipLogError(DeviceLayer, "ERR: reading on/off %x", to_underlying(status)); + return status; + } + + if (currentValue) // Already On. Nothing to do. + { + return Status::Success; + } + + OnOff::Attributes::OnOff::Set(true); + MatterReportingAttributeChangeCallback(commandPath.mEndpointId, OnOff::Id, OnOff::Attributes::OnOff::Id); + + FanControl::FanModeEnum fanMode; + FanControl::Attributes::FanMode::Get(commandPath.mEndpointId, fanMode); + + if (fanMode == FanControl::FanModeEnum::kOff) // Off mode implies Speed/Percent setting values are 0. + { + return Status::Success; + } + + DataModel::Nullable speedSetting(GetSpeedSetting()); + + if (!speedSetting.IsNull() && speedSetting.Value()) + { + status = FanControl::Attributes::SpeedCurrent::Set(commandPath.mEndpointId, speedSetting.Value()); + if (status != Status::Success) + { + ChipLogError(DeviceLayer, "Error setting SpeedCurrent: %d", to_underlying(status)); + return status; + } + MatterReportingAttributeChangeCallback(commandPath.mEndpointId, FanControl::Id, FanControl::Attributes::SpeedCurrent::Id); + } + + DataModel::Nullable percentSetting(GetPercentSetting()); + + if (!percentSetting.IsNull() && percentSetting.Value()) + { + status = FanControl::Attributes::PercentCurrent::Set(commandPath.mEndpointId, percentSetting.Value()); + if (status != Status::Success) + { + ChipLogError(DeviceLayer, "Error setting PercentCurrent: %d", to_underlying(status)); + return status; + } + MatterReportingAttributeChangeCallback(commandPath.mEndpointId, FanControl::Id, FanControl::Attributes::PercentCurrent::Id); + } + + return Status::Success; +} + +Status ChefFanControlManager::OffCommand(const app::ConcreteCommandPath & commandPath); +{ + ChipLogProgress(DeviceLayer, "ChefFanControlManager::OnCommand"); + + bool currentValue; + // read current on/off value + Status status = OnOff::Attributes::OnOff::Get(commandPath.mEndpointId, ¤tValue); + if (status != Status::Success) + { + ChipLogError(DeviceLayer, "ERR: reading on/off %x", to_underlying(status)); + return status; + } + + if (!currentValue) // Already Off. Nothing to do. + { + return Status::Success; + } + + OnOff::Attributes::OnOff::Set(false); + MatterReportingAttributeChangeCallback(commandPath.mEndpointId, OnOff::Id, OnOff::Attributes::OnOff::Id); + + FanControl::FanModeEnum fanMode; + FanControl::Attributes::FanMode::Get(commandPath.mEndpointId, fanMode); + + if (fanMode == FanControl::FanModeEnum::kOff) // Off mode implies Speed/Percent current values are 0. + { + return Status::Success; + } + + uint8_t speedCurrent; + status = SpeedCurrent::Get(commandPath.mEndpointId, &speedCurrent); + VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); + + if (speedCurrent) + { + status = FanControl::Attributes::SpeedCurrent::Set(commandPath.mEndpointId, 0); + if (status != Status::Success) + { + ChipLogError(DeviceLayer, "Error setting SpeedCurrent: %d", to_underlying(status)); + return status; + } + MatterReportingAttributeChangeCallback(commandPath.mEndpointId, FanControl::Id, FanControl::Attributes::SpeedCurrent::Id); + } + + uint8_t percentCurrent; + status = PercentCurrent::Get(commandPath.mEndpointId, &percentCurrent); + VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); + + if (percentCurrent) + { + status = FanControl::Attributes::PercentCurrent::Set(commandPath.mEndpointId, 0); + if (status != Status::Success) + { + ChipLogError(DeviceLayer, "Error setting PercentCurrent: %d", to_underlying(status)); + return status; + } + MatterReportingAttributeChangeCallback(commandPath.mEndpointId, FanControl::Id, FanControl::Attributes::PercentCurrent::Id); + } + + return Status::Success; +} + +bool emberAfOnOffClusterOnCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, + const Commands::On::DecodableType & commandData) +{ + Status status = mFanControlManager->OffCommand(commandPath); + commandObj->AddStatus(commandPath, status); + return true; +} + +bool emberAfOnOffClusterOffCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, + const Commands::Off::DecodableType & commandData) +{ + Status status = mFanControlManager->OffCommand(commandPath); + commandObj->AddStatus(commandPath, status); + return true; +} +#endif + void HandleFanControlAttributeChange(AttributeId attributeId, uint8_t type, uint16_t size, uint8_t * value) { mFanControlManager->HandleFanControlAttributeChange(attributeId, type, size, value); From 7ec32cb5b87648222c7f49d61541e7073fb12b02 Mon Sep 17 00:00:00 2001 From: Shreyas Balakrishna Bhandare Date: Wed, 26 Feb 2025 23:23:51 -0800 Subject: [PATCH 02/14] Disallow step when fan is Off --- examples/chef/common/chef-fan-control-manager.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/examples/chef/common/chef-fan-control-manager.cpp b/examples/chef/common/chef-fan-control-manager.cpp index 2b20a9398ebce7..f3a6956f9fae0e 100644 --- a/examples/chef/common/chef-fan-control-manager.cpp +++ b/examples/chef/common/chef-fan-control-manager.cpp @@ -88,6 +88,21 @@ static std::unique_ptr mFanControlManager; Status ChefFanControlManager::HandleStep(StepDirectionEnum aDirection, bool aWrap, bool aLowestOff) { + + bool fanIsOn; + // read current on/off value + Status status = OnOff::Attributes::OnOff::Get(mEndpoint, &fanIsOn); + if (status != Status::Success) + { + ChipLogError(DeviceLayer, "ERR: reading on/off %x", to_underlying(status)); + return status; + } + if (!fanIsOn) + { + ChipLogError(DeviceLayer, "Can't step when device is Off."); + return Status::InvalidAction; + } + ChipLogProgress(NotSpecified, "ChefFanControlManager::HandleStep aDirection %d, aWrap %d, aLowestOff %d", to_underlying(aDirection), aWrap, aLowestOff); From 020fe63b2a4550a4b3376bb6ee409866f2ab1c52 Mon Sep 17 00:00:00 2001 From: Shreyas Bhandare Date: Thu, 27 Feb 2025 07:29:20 +0000 Subject: [PATCH 03/14] Add On/Off cluster to fan device --- .../devices/rootnode_fan_7N2TobIlOX.matter | 85 +++++++++++ .../chef/devices/rootnode_fan_7N2TobIlOX.zap | 132 ++++++++++++++++++ 2 files changed, 217 insertions(+) diff --git a/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter b/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter index cd53027e6c92e6..abd44809f4819a 100644 --- a/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter +++ b/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter @@ -368,6 +368,78 @@ cluster Groups = 4 { fabric command access(invoke: manage) AddGroupIfIdentifying(AddGroupIfIdentifyingRequest): DefaultSuccess = 5; } +/** Attributes and commands for switching devices between 'On' and 'Off' states. */ +cluster OnOff = 6 { + revision 6; + + enum DelayedAllOffEffectVariantEnum : enum8 { + kDelayedOffFastFade = 0; + kNoFade = 1; + kDelayedOffSlowFade = 2; + } + + enum DyingLightEffectVariantEnum : enum8 { + kDyingLightFadeOff = 0; + } + + enum EffectIdentifierEnum : enum8 { + kDelayedAllOff = 0; + kDyingLight = 1; + } + + enum StartUpOnOffEnum : enum8 { + kOff = 0; + kOn = 1; + kToggle = 2; + } + + bitmap Feature : bitmap32 { + kLighting = 0x1; + kDeadFrontBehavior = 0x2; + kOffOnly = 0x4; + } + + bitmap OnOffControlBitmap : bitmap8 { + kAcceptOnlyWhenOn = 0x1; + } + + readonly attribute boolean onOff = 0; + readonly attribute optional boolean globalSceneControl = 16384; + attribute optional int16u onTime = 16385; + attribute optional int16u offWaitTime = 16386; + attribute access(write: manage) optional nullable StartUpOnOffEnum startUpOnOff = 16387; + 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 OffWithEffectRequest { + EffectIdentifierEnum effectIdentifier = 0; + enum8 effectVariant = 1; + } + + request struct OnWithTimedOffRequest { + OnOffControlBitmap onOffControl = 0; + int16u onTime = 1; + int16u offWaitTime = 2; + } + + /** On receipt of this command, a device SHALL enter its ‘Off’ state. This state is device dependent, but it is recommended that it is used for power off or similar functions. On receipt of the Off command, the OnTime attribute SHALL be set to 0. */ + command Off(): DefaultSuccess = 0; + /** On receipt of this command, a device SHALL enter its ‘On’ state. This state is device dependent, but it is recommended that it is used for power on or similar functions. On receipt of the On command, if the value of the OnTime attribute is equal to 0, the device SHALL set the OffWaitTime attribute to 0. */ + command On(): DefaultSuccess = 1; + /** On receipt of this command, if a device is in its ‘Off’ state it SHALL enter its ‘On’ state. Otherwise, if it is in its ‘On’ state it SHALL enter its ‘Off’ state. On receipt of the Toggle command, if the value of the OnOff attribute is equal to FALSE and if the value of the OnTime attribute is equal to 0, the device SHALL set the OffWaitTime attribute to 0. If the value of the OnOff attribute is equal to TRUE, the OnTime attribute SHALL be set to 0. */ + command Toggle(): DefaultSuccess = 2; + /** The OffWithEffect command allows devices to be turned off using enhanced ways of fading. */ + command OffWithEffect(OffWithEffectRequest): DefaultSuccess = 64; + /** The OnWithRecallGlobalScene command allows the recall of the settings when the device was turned off. */ + command OnWithRecallGlobalScene(): DefaultSuccess = 65; + /** The OnWithTimedOff command allows devices to be turned on for a specific duration with a guarded off duration so that SHOULD the device be subsequently switched off, further OnWithTimedOff commands, received during this time, are prevented from turning the devices back on. */ + command OnWithTimedOff(OnWithTimedOffRequest): DefaultSuccess = 66; +} + /** 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; @@ -1884,6 +1956,19 @@ endpoint 1 { handle command AddGroupIfIdentifying; } + server cluster OnOff { + ram attribute onOff default = 1; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 6; + + handle command Off; + handle command On; + handle command Toggle; + } + server cluster Descriptor { callback attribute deviceTypeList; callback attribute serverList; diff --git a/examples/chef/devices/rootnode_fan_7N2TobIlOX.zap b/examples/chef/devices/rootnode_fan_7N2TobIlOX.zap index 790dd1d52a5773..25af0d46c97777 100644 --- a/examples/chef/devices/rootnode_fan_7N2TobIlOX.zap +++ b/examples/chef/devices/rootnode_fan_7N2TobIlOX.zap @@ -2643,6 +2643,138 @@ } ] }, + { + "name": "On/Off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Off", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "On", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "Toggle", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "OnOff", + "code": 0, + "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": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "6", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, { "name": "Descriptor", "code": 29, From fecb12b7fc076a9a79264ce853dbba3164fd896c Mon Sep 17 00:00:00 2001 From: Shreyas Balakrishna Bhandare Date: Wed, 26 Feb 2025 23:38:28 -0800 Subject: [PATCH 04/14] Fix compilation bugs --- .../chef/common/chef-fan-control-manager.cpp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/chef/common/chef-fan-control-manager.cpp b/examples/chef/common/chef-fan-control-manager.cpp index f3a6956f9fae0e..eb86338f6467f8 100644 --- a/examples/chef/common/chef-fan-control-manager.cpp +++ b/examples/chef/common/chef-fan-control-manager.cpp @@ -91,11 +91,11 @@ Status ChefFanControlManager::HandleStep(StepDirectionEnum aDirection, bool aWra bool fanIsOn; // read current on/off value - Status status = OnOff::Attributes::OnOff::Get(mEndpoint, &fanIsOn); - if (status != Status::Success) + Status result = OnOff::Attributes::OnOff::Get(mEndpoint, &fanIsOn); + if (result != Status::Success) { - ChipLogError(DeviceLayer, "ERR: reading on/off %x", to_underlying(status)); - return status; + ChipLogError(DeviceLayer, "ERR: reading on/off %x", to_underlying(result)); + return result; } if (!fanIsOn) { @@ -369,11 +369,11 @@ Status ChefFanControlManager::OnCommand(const app::ConcreteCommandPath & command return Status::Success; } - OnOff::Attributes::OnOff::Set(true); + OnOff::Attributes::OnOff::Set(commandPath.mEndpointId, true); MatterReportingAttributeChangeCallback(commandPath.mEndpointId, OnOff::Id, OnOff::Attributes::OnOff::Id); FanControl::FanModeEnum fanMode; - FanControl::Attributes::FanMode::Get(commandPath.mEndpointId, fanMode); + FanControl::Attributes::FanMode::Get(commandPath.mEndpointId, &fanMode); if (fanMode == FanControl::FanModeEnum::kOff) // Off mode implies Speed/Percent setting values are 0. { @@ -409,7 +409,7 @@ Status ChefFanControlManager::OnCommand(const app::ConcreteCommandPath & command return Status::Success; } -Status ChefFanControlManager::OffCommand(const app::ConcreteCommandPath & commandPath); +Status ChefFanControlManager::OffCommand(const app::ConcreteCommandPath & commandPath) { ChipLogProgress(DeviceLayer, "ChefFanControlManager::OnCommand"); @@ -427,11 +427,11 @@ Status ChefFanControlManager::OffCommand(const app::ConcreteCommandPath & comman return Status::Success; } - OnOff::Attributes::OnOff::Set(false); + OnOff::Attributes::OnOff::Set(commandPath.mEndpointId, false); MatterReportingAttributeChangeCallback(commandPath.mEndpointId, OnOff::Id, OnOff::Attributes::OnOff::Id); FanControl::FanModeEnum fanMode; - FanControl::Attributes::FanMode::Get(commandPath.mEndpointId, fanMode); + FanControl::Attributes::FanMode::Get(commandPath.mEndpointId, &fanMode); if (fanMode == FanControl::FanModeEnum::kOff) // Off mode implies Speed/Percent current values are 0. { @@ -472,7 +472,7 @@ Status ChefFanControlManager::OffCommand(const app::ConcreteCommandPath & comman } bool emberAfOnOffClusterOnCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, - const Commands::On::DecodableType & commandData) + const OnOff::Commands::On::DecodableType & commandData) { Status status = mFanControlManager->OffCommand(commandPath); commandObj->AddStatus(commandPath, status); @@ -480,7 +480,7 @@ bool emberAfOnOffClusterOnCallback(app::CommandHandler * commandObj, const app:: } bool emberAfOnOffClusterOffCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, - const Commands::Off::DecodableType & commandData) + const OnOff::Commands::Off::DecodableType & commandData) { Status status = mFanControlManager->OffCommand(commandPath); commandObj->AddStatus(commandPath, status); From e31d970a7a37dc5bafe89d18dc5037bacf7deafc Mon Sep 17 00:00:00 2001 From: Shreyas Balakrishna Bhandare Date: Wed, 26 Feb 2025 23:42:32 -0800 Subject: [PATCH 05/14] Fix compilation bugs --- examples/chef/common/chef-fan-control-manager.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/chef/common/chef-fan-control-manager.cpp b/examples/chef/common/chef-fan-control-manager.cpp index eb86338f6467f8..04aed3d83cfb0d 100644 --- a/examples/chef/common/chef-fan-control-manager.cpp +++ b/examples/chef/common/chef-fan-control-manager.cpp @@ -50,8 +50,8 @@ class ChefFanControlManager : public Delegate DataModel::Nullable GetPercentSetting(); #ifdef MATTER_DM_PLUGIN_ON_OFF_SERVER - Status OnCommand(const app::ConcreteCommandPath & commandPath); - Status OffCommand(const app::ConcreteCommandPath & commandPath); + Protocols::InteractionModel::Status OnCommand(const app::ConcreteCommandPath & commandPath); + Protocols::InteractionModel::Status OffCommand(const app::ConcreteCommandPath & commandPath); #endif private: @@ -351,7 +351,7 @@ void emberAfFanControlClusterInitCallback(EndpointId endpoint) #ifdef MATTER_DM_PLUGIN_ON_OFF_SERVER -Status ChefFanControlManager::OnCommand(const app::ConcreteCommandPath & commandPath) +Protocols::InteractionModel::Status ChefFanControlManager::OnCommand(const app::ConcreteCommandPath & commandPath) { ChipLogProgress(DeviceLayer, "ChefFanControlManager::OnCommand"); @@ -409,9 +409,9 @@ Status ChefFanControlManager::OnCommand(const app::ConcreteCommandPath & command return Status::Success; } -Status ChefFanControlManager::OffCommand(const app::ConcreteCommandPath & commandPath) +Protocols::InteractionModel::Status ChefFanControlManager::OffCommand(const app::ConcreteCommandPath & commandPath) { - ChipLogProgress(DeviceLayer, "ChefFanControlManager::OnCommand"); + ChipLogProgress(DeviceLayer, "ChefFanControlManager::OffCommand"); bool currentValue; // read current on/off value From 6a5576fd32dabfa5bff7ffbd78acd46fae142be1 Mon Sep 17 00:00:00 2001 From: Shreyas Balakrishna Bhandare Date: Wed, 26 Feb 2025 23:45:18 -0800 Subject: [PATCH 06/14] Fix compilation bugs --- examples/chef/common/chef-fan-control-manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/chef/common/chef-fan-control-manager.cpp b/examples/chef/common/chef-fan-control-manager.cpp index 04aed3d83cfb0d..047c7be8cc4b5b 100644 --- a/examples/chef/common/chef-fan-control-manager.cpp +++ b/examples/chef/common/chef-fan-control-manager.cpp @@ -474,7 +474,7 @@ Protocols::InteractionModel::Status ChefFanControlManager::OffCommand(const app: bool emberAfOnOffClusterOnCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const OnOff::Commands::On::DecodableType & commandData) { - Status status = mFanControlManager->OffCommand(commandPath); + Status status = mFanControlManager->OnCommand(commandPath); commandObj->AddStatus(commandPath, status); return true; } From eb852e408f31dfaab7eee81736eacf9d864b9534 Mon Sep 17 00:00:00 2001 From: Shreyas Balakrishna Bhandare Date: Thu, 27 Feb 2025 13:47:28 -0800 Subject: [PATCH 07/14] Handle onOff event in MatterPostAttributeChangeCallback since emberAFCommandHandler callbacks are already defined --- .../chef/common/chef-fan-control-manager.cpp | 80 +++++-------------- .../chef/common/chef-fan-control-manager.h | 5 ++ examples/chef/common/stubs.cpp | 6 ++ 3 files changed, 30 insertions(+), 61 deletions(-) diff --git a/examples/chef/common/chef-fan-control-manager.cpp b/examples/chef/common/chef-fan-control-manager.cpp index 047c7be8cc4b5b..93b1f5b13f5554 100644 --- a/examples/chef/common/chef-fan-control-manager.cpp +++ b/examples/chef/common/chef-fan-control-manager.cpp @@ -351,29 +351,12 @@ void emberAfFanControlClusterInitCallback(EndpointId endpoint) #ifdef MATTER_DM_PLUGIN_ON_OFF_SERVER -Protocols::InteractionModel::Status ChefFanControlManager::OnCommand(const app::ConcreteCommandPath & commandPath) +Protocols::InteractionModel::Status ChefFanControlManager::OnCommand(EndpointId endpointId) { ChipLogProgress(DeviceLayer, "ChefFanControlManager::OnCommand"); - bool currentValue; - // read current on/off value - Status status = OnOff::Attributes::OnOff::Get(commandPath.mEndpointId, ¤tValue); - if (status != Status::Success) - { - ChipLogError(DeviceLayer, "ERR: reading on/off %x", to_underlying(status)); - return status; - } - - if (currentValue) // Already On. Nothing to do. - { - return Status::Success; - } - - OnOff::Attributes::OnOff::Set(commandPath.mEndpointId, true); - MatterReportingAttributeChangeCallback(commandPath.mEndpointId, OnOff::Id, OnOff::Attributes::OnOff::Id); - FanControl::FanModeEnum fanMode; - FanControl::Attributes::FanMode::Get(commandPath.mEndpointId, &fanMode); + FanControl::Attributes::FanMode::Get(endpointId, &fanMode); if (fanMode == FanControl::FanModeEnum::kOff) // Off mode implies Speed/Percent setting values are 0. { @@ -384,54 +367,37 @@ Protocols::InteractionModel::Status ChefFanControlManager::OnCommand(const app:: if (!speedSetting.IsNull() && speedSetting.Value()) { - status = FanControl::Attributes::SpeedCurrent::Set(commandPath.mEndpointId, speedSetting.Value()); + status = FanControl::Attributes::SpeedCurrent::Set(endpointId, speedSetting.Value()); if (status != Status::Success) { ChipLogError(DeviceLayer, "Error setting SpeedCurrent: %d", to_underlying(status)); return status; } - MatterReportingAttributeChangeCallback(commandPath.mEndpointId, FanControl::Id, FanControl::Attributes::SpeedCurrent::Id); + MatterReportingAttributeChangeCallback(endpointId, FanControl::Id, FanControl::Attributes::SpeedCurrent::Id); } DataModel::Nullable percentSetting(GetPercentSetting()); if (!percentSetting.IsNull() && percentSetting.Value()) { - status = FanControl::Attributes::PercentCurrent::Set(commandPath.mEndpointId, percentSetting.Value()); + status = FanControl::Attributes::PercentCurrent::Set(endpointId, percentSetting.Value()); if (status != Status::Success) { ChipLogError(DeviceLayer, "Error setting PercentCurrent: %d", to_underlying(status)); return status; } - MatterReportingAttributeChangeCallback(commandPath.mEndpointId, FanControl::Id, FanControl::Attributes::PercentCurrent::Id); + MatterReportingAttributeChangeCallback(endpointId, FanControl::Id, FanControl::Attributes::PercentCurrent::Id); } return Status::Success; } -Protocols::InteractionModel::Status ChefFanControlManager::OffCommand(const app::ConcreteCommandPath & commandPath) +Protocols::InteractionModel::Status ChefFanControlManager::OffCommand(EndpointId endpointId) { ChipLogProgress(DeviceLayer, "ChefFanControlManager::OffCommand"); - bool currentValue; - // read current on/off value - Status status = OnOff::Attributes::OnOff::Get(commandPath.mEndpointId, ¤tValue); - if (status != Status::Success) - { - ChipLogError(DeviceLayer, "ERR: reading on/off %x", to_underlying(status)); - return status; - } - - if (!currentValue) // Already Off. Nothing to do. - { - return Status::Success; - } - - OnOff::Attributes::OnOff::Set(commandPath.mEndpointId, false); - MatterReportingAttributeChangeCallback(commandPath.mEndpointId, OnOff::Id, OnOff::Attributes::OnOff::Id); - FanControl::FanModeEnum fanMode; - FanControl::Attributes::FanMode::Get(commandPath.mEndpointId, &fanMode); + FanControl::Attributes::FanMode::Get(endpointId, &fanMode); if (fanMode == FanControl::FanModeEnum::kOff) // Off mode implies Speed/Percent current values are 0. { @@ -439,52 +405,44 @@ Protocols::InteractionModel::Status ChefFanControlManager::OffCommand(const app: } uint8_t speedCurrent; - status = SpeedCurrent::Get(commandPath.mEndpointId, &speedCurrent); + status = SpeedCurrent::Get(endpointId, &speedCurrent); VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); if (speedCurrent) { - status = FanControl::Attributes::SpeedCurrent::Set(commandPath.mEndpointId, 0); + status = FanControl::Attributes::SpeedCurrent::Set(endpointId, 0); if (status != Status::Success) { ChipLogError(DeviceLayer, "Error setting SpeedCurrent: %d", to_underlying(status)); return status; } - MatterReportingAttributeChangeCallback(commandPath.mEndpointId, FanControl::Id, FanControl::Attributes::SpeedCurrent::Id); + MatterReportingAttributeChangeCallback(endpointId, FanControl::Id, FanControl::Attributes::SpeedCurrent::Id); } uint8_t percentCurrent; - status = PercentCurrent::Get(commandPath.mEndpointId, &percentCurrent); + status = PercentCurrent::Get(endpointId, &percentCurrent); VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); if (percentCurrent) { - status = FanControl::Attributes::PercentCurrent::Set(commandPath.mEndpointId, 0); + status = FanControl::Attributes::PercentCurrent::Set(endpointId, 0); if (status != Status::Success) { ChipLogError(DeviceLayer, "Error setting PercentCurrent: %d", to_underlying(status)); return status; } - MatterReportingAttributeChangeCallback(commandPath.mEndpointId, FanControl::Id, FanControl::Attributes::PercentCurrent::Id); + MatterReportingAttributeChangeCallback(endpointId, FanControl::Id, FanControl::Attributes::PercentCurrent::Id); } return Status::Success; } -bool emberAfOnOffClusterOnCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, - const OnOff::Commands::On::DecodableType & commandData) -{ - Status status = mFanControlManager->OnCommand(commandPath); - commandObj->AddStatus(commandPath, status); - return true; -} - -bool emberAfOnOffClusterOffCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, - const OnOff::Commands::Off::DecodableType & commandData) +void HandleOnOffAttributeChangeForFan(EndpointId endpointId, bool value) { - Status status = mFanControlManager->OffCommand(commandPath); - commandObj->AddStatus(commandPath, status); - return true; + if (value) + mFanControlManager->OnCommand(endpointId); + else + mFanControlManager->OffCommand(endpointId); } #endif diff --git a/examples/chef/common/chef-fan-control-manager.h b/examples/chef/common/chef-fan-control-manager.h index 36a90e6a886e92..139660c9029a1f 100644 --- a/examples/chef/common/chef-fan-control-manager.h +++ b/examples/chef/common/chef-fan-control-manager.h @@ -19,4 +19,9 @@ #ifdef MATTER_DM_PLUGIN_FAN_CONTROL_SERVER void HandleFanControlAttributeChange(AttributeId attributeId, uint8_t type, uint16_t size, uint8_t * value); + +#ifdef MATTER_DM_PLUGIN_ON_OFF_SERVER +void HandleOnOffAttributeChangeForFan(EndpointId endpointId, bool value); +#endif // MATTER_DM_PLUGIN_ON_OFF_SERVER + #endif diff --git a/examples/chef/common/stubs.cpp b/examples/chef/common/stubs.cpp index 16e9b1b8694c64..6657cbb23b46b0 100644 --- a/examples/chef/common/stubs.cpp +++ b/examples/chef/common/stubs.cpp @@ -261,6 +261,12 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & { HandleFanControlAttributeChange(attributeId, type, size, value); } +#ifdef MATTER_DM_PLUGIN_ON_OFF_SERVER + else if (clusterId == OnOff::Id) + { + HandleOnOffAttributeChangeForFan(attributePath.mEndpointId, bool(*value)); + } +#endif // MATTER_DM_PLUGIN_ON_OFF_SERVER #endif // MATTER_DM_PLUGIN_FAN_CONTROL_SERVER } From 0a3f2ea22c3fecafb124df272a61820123662449 Mon Sep 17 00:00:00 2001 From: Shreyas Balakrishna Bhandare Date: Thu, 27 Feb 2025 13:49:10 -0800 Subject: [PATCH 08/14] Fix compilation --- examples/chef/common/chef-fan-control-manager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/chef/common/chef-fan-control-manager.cpp b/examples/chef/common/chef-fan-control-manager.cpp index 93b1f5b13f5554..401cf729944d60 100644 --- a/examples/chef/common/chef-fan-control-manager.cpp +++ b/examples/chef/common/chef-fan-control-manager.cpp @@ -50,8 +50,8 @@ class ChefFanControlManager : public Delegate DataModel::Nullable GetPercentSetting(); #ifdef MATTER_DM_PLUGIN_ON_OFF_SERVER - Protocols::InteractionModel::Status OnCommand(const app::ConcreteCommandPath & commandPath); - Protocols::InteractionModel::Status OffCommand(const app::ConcreteCommandPath & commandPath); + Protocols::InteractionModel::Status OnCommand(EndpointId endpointId); + Protocols::InteractionModel::Status OffCommand(EndpointId endpointId); #endif private: From 9c35121cca77074156beebc9380ff71fc2fd3e70 Mon Sep 17 00:00:00 2001 From: Shreyas Balakrishna Bhandare Date: Thu, 27 Feb 2025 13:51:31 -0800 Subject: [PATCH 09/14] Fix compilation --- examples/chef/common/chef-fan-control-manager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/chef/common/chef-fan-control-manager.cpp b/examples/chef/common/chef-fan-control-manager.cpp index 401cf729944d60..b7db61e0df7db9 100644 --- a/examples/chef/common/chef-fan-control-manager.cpp +++ b/examples/chef/common/chef-fan-control-manager.cpp @@ -404,6 +404,8 @@ Protocols::InteractionModel::Status ChefFanControlManager::OffCommand(EndpointId return Status::Success; } + Status status; + uint8_t speedCurrent; status = SpeedCurrent::Get(endpointId, &speedCurrent); VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); From c23b9391ff63b27aa6db73308c1011d4865ee90c Mon Sep 17 00:00:00 2001 From: Shreyas Balakrishna Bhandare Date: Thu, 27 Feb 2025 13:52:43 -0800 Subject: [PATCH 10/14] Fix compilation --- examples/chef/common/chef-fan-control-manager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/chef/common/chef-fan-control-manager.cpp b/examples/chef/common/chef-fan-control-manager.cpp index b7db61e0df7db9..07bef32cb95c16 100644 --- a/examples/chef/common/chef-fan-control-manager.cpp +++ b/examples/chef/common/chef-fan-control-manager.cpp @@ -363,6 +363,8 @@ Protocols::InteractionModel::Status ChefFanControlManager::OnCommand(EndpointId return Status::Success; } + Status status; + DataModel::Nullable speedSetting(GetSpeedSetting()); if (!speedSetting.IsNull() && speedSetting.Value()) From 1a7c2f502ba6a54bbcf707bea893bc442afcbcaf Mon Sep 17 00:00:00 2001 From: Shreyas Balakrishna Bhandare Date: Thu, 27 Feb 2025 14:18:53 -0800 Subject: [PATCH 11/14] Fix unreachable code. --- examples/chef/common/stubs.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/examples/chef/common/stubs.cpp b/examples/chef/common/stubs.cpp index 6657cbb23b46b0..6b0b6a4e6dbc28 100644 --- a/examples/chef/common/stubs.cpp +++ b/examples/chef/common/stubs.cpp @@ -248,6 +248,11 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & { ChipLogProgress(Zcl, "OnOff attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u", ChipLogValueMEI(attributeId), type, *value, size); +#ifdef MATTER_DM_PLUGIN_FAN_CONTROL_SERVER // Handle OnOff for fan +#ifdef MATTER_DM_PLUGIN_ON_OFF_SERVER + HandleOnOffAttributeChangeForFan(attributePath.mEndpointId, bool(*value)); +#endif // MATTER_DM_PLUGIN_ON_OFF_SERVER +#endif // MATTER_DM_PLUGIN_FAN_CONTROL_SERVER } else if (clusterId == LevelControl::Id) { @@ -261,12 +266,6 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & { HandleFanControlAttributeChange(attributeId, type, size, value); } -#ifdef MATTER_DM_PLUGIN_ON_OFF_SERVER - else if (clusterId == OnOff::Id) - { - HandleOnOffAttributeChangeForFan(attributePath.mEndpointId, bool(*value)); - } -#endif // MATTER_DM_PLUGIN_ON_OFF_SERVER #endif // MATTER_DM_PLUGIN_FAN_CONTROL_SERVER } From c58f99313846255e51741e2b26ff01996fb7fe52 Mon Sep 17 00:00:00 2001 From: Shreyas Balakrishna Bhandare Date: Thu, 27 Feb 2025 15:27:47 -0800 Subject: [PATCH 12/14] Remove hard checks on on-off to prevent tests from breaking --- examples/chef/common/chef-fan-control-manager.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/examples/chef/common/chef-fan-control-manager.cpp b/examples/chef/common/chef-fan-control-manager.cpp index 07bef32cb95c16..1fb18218df65a6 100644 --- a/examples/chef/common/chef-fan-control-manager.cpp +++ b/examples/chef/common/chef-fan-control-manager.cpp @@ -88,21 +88,6 @@ static std::unique_ptr mFanControlManager; Status ChefFanControlManager::HandleStep(StepDirectionEnum aDirection, bool aWrap, bool aLowestOff) { - - bool fanIsOn; - // read current on/off value - Status result = OnOff::Attributes::OnOff::Get(mEndpoint, &fanIsOn); - if (result != Status::Success) - { - ChipLogError(DeviceLayer, "ERR: reading on/off %x", to_underlying(result)); - return result; - } - if (!fanIsOn) - { - ChipLogError(DeviceLayer, "Can't step when device is Off."); - return Status::InvalidAction; - } - ChipLogProgress(NotSpecified, "ChefFanControlManager::HandleStep aDirection %d, aWrap %d, aLowestOff %d", to_underlying(aDirection), aWrap, aLowestOff); From 8f36ad719e990fafbf669822d000a31f7c9a2db3 Mon Sep 17 00:00:00 2001 From: Shreyas Balakrishna Bhandare Date: Fri, 28 Feb 2025 16:14:20 -0800 Subject: [PATCH 13/14] On command should set Fan to HIGH --- .../chef/common/chef-fan-control-manager.cpp | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/examples/chef/common/chef-fan-control-manager.cpp b/examples/chef/common/chef-fan-control-manager.cpp index 1fb18218df65a6..b1c074102b62d5 100644 --- a/examples/chef/common/chef-fan-control-manager.cpp +++ b/examples/chef/common/chef-fan-control-manager.cpp @@ -48,11 +48,8 @@ class ChefFanControlManager : public Delegate Status HandleStep(StepDirectionEnum aDirection, bool aWrap, bool aLowestOff) override; DataModel::Nullable GetSpeedSetting(); DataModel::Nullable GetPercentSetting(); - -#ifdef MATTER_DM_PLUGIN_ON_OFF_SERVER Protocols::InteractionModel::Status OnCommand(EndpointId endpointId); Protocols::InteractionModel::Status OffCommand(EndpointId endpointId); -#endif private: uint8_t mPercentCurrent = 0; @@ -334,8 +331,6 @@ void emberAfFanControlClusterInitCallback(EndpointId endpoint) mFanControlManager->Init(); } -#ifdef MATTER_DM_PLUGIN_ON_OFF_SERVER - Protocols::InteractionModel::Status ChefFanControlManager::OnCommand(EndpointId endpointId) { ChipLogProgress(DeviceLayer, "ChefFanControlManager::OnCommand"); @@ -343,9 +338,39 @@ Protocols::InteractionModel::Status ChefFanControlManager::OnCommand(EndpointId FanControl::FanModeEnum fanMode; FanControl::Attributes::FanMode::Get(endpointId, &fanMode); - if (fanMode == FanControl::FanModeEnum::kOff) // Off mode implies Speed/Percent setting values are 0. + if (fanMode == FanControl::FanModeEnum::kOff) // Off mode implies Speed/Percent setting values are 0. Set fan to HIGH. { - return Status::Success; + uint8_t speedMax; + Status status = SpeedMax::Get(mEndpoint, &speedMax); + if (status == Status::Success) + { + status = FanControl::Attributes::SpeedSetting::Set(mEndpoint, speedMax); + if (status == Status::Success) + { + // Atribute change handler sets SpeedCurrent equal to SpeedSetting and updates FanMode. + MatterReportingAttributeChangeCallback(endpointId, FanControl::Id, FanControl::Attributes::SpeedSetting::Id); + } + else + { + ChipLogError(DeviceLayer, "Error setting SpeedSetting: %d", to_underlying(status)); + return status; // Speed is enabled since SpeedMax read was successful. So return failed status. + } + } + else + { + // Not returning error as speed is optional. + ChipLogError(DeviceLayer, "Error getting SpeedMax: %d", to_underlying(status)); + } + status = FanControl::Attributes::PercentSetting::Set(mEndpoint, 100); + if (status == Status::Success) + { + // Atribute change handler sets PercentCurrent equal to PercentSetting. + MatterReportingAttributeChangeCallback(endpointId, FanControl::Id, FanControl::Attributes::PercentSetting::Id); + } + else + { + return status; // Percent is mandatory. So return failed status. + } } Status status; @@ -395,9 +420,8 @@ Protocols::InteractionModel::Status ChefFanControlManager::OffCommand(EndpointId uint8_t speedCurrent; status = SpeedCurrent::Get(endpointId, &speedCurrent); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (speedCurrent) + if (status == Protocols::InteractionModel::Status::Success && speedCurrent) { status = FanControl::Attributes::SpeedCurrent::Set(endpointId, 0); if (status != Status::Success) @@ -433,7 +457,6 @@ void HandleOnOffAttributeChangeForFan(EndpointId endpointId, bool value) else mFanControlManager->OffCommand(endpointId); } -#endif void HandleFanControlAttributeChange(AttributeId attributeId, uint8_t type, uint16_t size, uint8_t * value) { From 02d4974826a6dd074dc86f8ae14c173f1f158a93 Mon Sep 17 00:00:00 2001 From: Shreyas Bhandare Date: Sat, 1 Mar 2025 00:52:13 +0000 Subject: [PATCH 14/14] Set default OnOff state to Off to match default fanMode --- examples/chef/devices/rootnode_fan_7N2TobIlOX.matter | 2 +- examples/chef/devices/rootnode_fan_7N2TobIlOX.zap | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter b/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter index abd44809f4819a..5b9637b5fadeae 100644 --- a/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter +++ b/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter @@ -1957,7 +1957,7 @@ endpoint 1 { } server cluster OnOff { - ram attribute onOff default = 1; + ram attribute onOff default = 0; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute attributeList; diff --git a/examples/chef/devices/rootnode_fan_7N2TobIlOX.zap b/examples/chef/devices/rootnode_fan_7N2TobIlOX.zap index 25af0d46c97777..2b071aff48fe58 100644 --- a/examples/chef/devices/rootnode_fan_7N2TobIlOX.zap +++ b/examples/chef/devices/rootnode_fan_7N2TobIlOX.zap @@ -2687,7 +2687,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2703,7 +2703,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2719,7 +2719,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2735,7 +2735,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534,