Skip to content
Open
Show file tree
Hide file tree
Changes from 60 commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
e7a22c9
Implement FanControl cluster with code-driven pattern
LyudmilaKostanyan Mar 3, 2026
1e04945
Add ZAP codegen integration and attribute handling
LyudmilaKostanyan Mar 18, 2026
036208e
Add OnOff cluster synchronization to FanControl
LyudmilaKostanyan Mar 21, 2026
d6bc6fc
Fix FanControl validation, settings preservation, and cleanup
LyudmilaKostanyan Mar 22, 2026
3a06875
Clean up Fan Control examples
LyudmilaKostanyan Mar 31, 2026
d4b3622
Couple delegate storage; drop codegen Get/Set wrappers
LyudmilaKostanyan Mar 31, 2026
f6c637b
Restyled by clang-format
restyled-commits Mar 31, 2026
d162f36
Use SetAttributeValue, VerifyOrReturn, and braced ifs in fan-control …
LyudmilaKostanyan Mar 31, 2026
31be437
Restyled by clang-format
restyled-commits Mar 31, 2026
8fcdc20
imgui_ui: depend on fan-control-server for fan_control window
LyudmilaKostanyan Apr 2, 2026
1185c50
Drop redundant IM checks in FanControlCluster
LyudmilaKostanyan Apr 6, 2026
9000a68
Move FanControl attributes from external to RAM/persist storage in ZAP
LyudmilaKostanyan Apr 6, 2026
422d59e
Restyled by prettier-json
restyled-commits Apr 6, 2026
3014287
Use generated accessors in FanControl CodegenIntegration
LyudmilaKostanyan Apr 6, 2026
27c5839
Clean up includes in FanControl cluster
LyudmilaKostanyan Apr 6, 2026
17f42e8
Drop redundant Startup/Shutdown overrides in FanControlCluster
LyudmilaKostanyan Apr 6, 2026
b65f183
Add FanMode persistence support to FanControl cluster
LyudmilaKostanyan Apr 6, 2026
1b0040f
Restyled by clang-format
restyled-commits Apr 6, 2026
4d96d2a
Use SetAttributeValue helper in FanControl cluster
LyudmilaKostanyan Apr 6, 2026
8412374
Notify delegate on attribute updates in decoupled cluster
LyudmilaKostanyan Apr 6, 2026
abde04a
Log SetFanMode errors in FanControl examples
LyudmilaKostanyan Apr 7, 2026
45f3dcd
Add OnFanStateChanged delegate callback to FanControl cluster
LyudmilaKostanyan Apr 7, 2026
6e3a8d8
Add syncOnOffDelegate parameter to SetFanMode to skip OnOff delegate …
LyudmilaKostanyan Apr 7, 2026
e85c01e
Merge branch 'master' into FanControl
LyudmilaKostanyan Apr 9, 2026
b2b85a4
Use VerifyOrReturn in SetFanModeToOff
LyudmilaKostanyan Apr 9, 2026
548fd69
Zap regen
LyudmilaKostanyan Apr 9, 2026
847e9ea
Use NullNullable
LyudmilaKostanyan Apr 9, 2026
7432009
Fix Auto current notify pairing, use mSpeedMax inline, delegate from …
LyudmilaKostanyan Apr 9, 2026
e9392eb
Simpler defaults, delegate wiring, and percent values
LyudmilaKostanyan Apr 9, 2026
c4d9917
Restyled by clang-format
restyled-commits Apr 9, 2026
4928d3e
Fix fan-control include path
LyudmilaKostanyan Apr 9, 2026
fd1f4e3
Add detailed comments for FanMode side effects
LyudmilaKostanyan Apr 13, 2026
8b1b152
Refactor FanControl delegate to use unified FanDriveState callback
LyudmilaKostanyan Apr 13, 2026
d86a554
Add documentation for FanControl SetOnOffState
LyudmilaKostanyan Apr 13, 2026
566d60f
Restyled by whitespace
restyled-commits Apr 13, 2026
9f2d363
Restyled by clang-format
restyled-commits Apr 13, 2026
9294ea6
Refactor Startup fan mode restoration
LyudmilaKostanyan Apr 13, 2026
bb1d18b
Refactor FanControl Step handling with early validation and nullable …
LyudmilaKostanyan Apr 13, 2026
8e5ee5f
Restyled by clang-format
restyled-commits Apr 13, 2026
62621bb
Merge branch 'master' into FanControl
LyudmilaKostanyan Apr 13, 2026
6c07537
Merge branch 'master' into FanControl
LyudmilaKostanyan Apr 13, 2026
3b197dc
Merge branch 'master' into FanControl
LyudmilaKostanyan Apr 13, 2026
90fa6f9
Merge branch 'master' into FanControl
LyudmilaKostanyan Apr 13, 2026
e18dccc
Add README.md
LyudmilaKostanyan Apr 13, 2026
d9723b2
Zap regen
LyudmilaKostanyan Apr 13, 2026
3303f39
Add fan device in all-devices-app
LyudmilaKostanyan Apr 20, 2026
aee2dc5
Merge branch 'master' into FanControl
LyudmilaKostanyan Apr 20, 2026
946d4dd
Zap regen
LyudmilaKostanyan Apr 20, 2026
4a3eb59
Restyled by whitespace
restyled-commits Apr 20, 2026
c0a4186
Restyled by clang-format
restyled-commits Apr 20, 2026
3ca5d59
Restyled by gn
restyled-commits Apr 20, 2026
316e5d2
Merge branch 'master' into FanControl
LyudmilaKostanyan Apr 20, 2026
96e8503
Wire fan device into ESP32 CMake and run TC_FAN tests against all-dev…
LyudmilaKostanyan Apr 20, 2026
f286ba6
Configure FanControl with SpeedMax and Step
LyudmilaKostanyan Apr 20, 2026
b484525
Set FanControl OnOff state on OnOff startup and changes
LyudmilaKostanyan Apr 21, 2026
51820c5
Merge branch 'master' into FanControl
LyudmilaKostanyan Apr 21, 2026
ee72891
Zap regen
LyudmilaKostanyan Apr 21, 2026
3f3abca
Implement FanControl Step command handler in LoggingFanDevice
LyudmilaKostanyan Apr 21, 2026
fa6889d
Restyled
LyudmilaKostanyan Apr 21, 2026
61fdc69
Fix FanControl Step command lowestOff default and LoggingFanDevice st…
LyudmilaKostanyan Apr 23, 2026
638078e
Fix FanControl to notify delegate once when setting percent/speed to …
LyudmilaKostanyan Apr 25, 2026
25a7fb9
Remove unused GroupsCluster accessor from FanDevice
LyudmilaKostanyan Apr 25, 2026
29c4170
Merge branch 'master' into FanControl
LyudmilaKostanyan Apr 25, 2026
e28962b
Remove unused GroupsCluster accessor from FanDevice
LyudmilaKostanyan Apr 25, 2026
271492e
Add Wind, Rock and AirflowDirection support to FanDevice
LyudmilaKostanyan Apr 27, 2026
759987b
Merge branch 'master' into FanControl
LyudmilaKostanyan Apr 27, 2026
c99f183
Restyle
LyudmilaKostanyan Apr 27, 2026
d399071
Fix fan OnOff state logic in all-devices-app
LyudmilaKostanyan Apr 27, 2026
09299a1
Fix fan OnOff state logic in all-devices-app
LyudmilaKostanyan Apr 27, 2026
2a15f03
Remove OnOffCluster accessor from FanDevice
LyudmilaKostanyan Apr 28, 2026
f218a4c
Align server with Fan Control cluster spec
LyudmilaKostanyan Apr 28, 2026
f89c94a
Fix FanControl to reject null PercentSetting/SpeedSetting outside Aut…
LyudmilaKostanyan Apr 28, 2026
bffd0fc
Return InvalidInState for unsupported FanMode instead of ConstraintError
LyudmilaKostanyan Apr 29, 2026
76627bd
Decouple server from OnOff
LyudmilaKostanyan Apr 29, 2026
bbc77cb
Add OnOffCluster support to FanDevice in all-devices-app
LyudmilaKostanyan Apr 29, 2026
7e50785
Add percent and speed setting methods to FanControlCluster; update Lo…
LyudmilaKostanyan Apr 29, 2026
1ec3dec
Add percent and speed setting methods to FanControlCluster; update Lo…
LyudmilaKostanyan Apr 29, 2026
1675d8e
Refine LoggingFanDevice state management logic to ensure proper handl…
LyudmilaKostanyan Apr 29, 2026
494ec89
Merge branch 'master' into FanControl
LyudmilaKostanyan Apr 29, 2026
bc57cbd
Restyled
LyudmilaKostanyan Apr 29, 2026
bb538ef
Merge branch 'master' into FanControl
LyudmilaKostanyan Apr 30, 2026
c5bed78
Refactor LoggingFanDevice to remove redundant speed setting logic in …
LyudmilaKostanyan Apr 30, 2026
c8f72c7
Refactor LoggingFanDevice to streamline fan state management by conso…
LyudmilaKostanyan Apr 30, 2026
c6760bf
Merge branch 'master' into FanControl
LyudmilaKostanyan Apr 30, 2026
55b637d
Change for trigger REPL test
LyudmilaKostanyan May 1, 2026
be01c7b
Merge branch 'master' into FanControl
LyudmilaKostanyan May 1, 2026
f873b0f
Merge branch 'master' into FanControl
LyudmilaKostanyan May 4, 2026
e619211
Align OnOff with fan settings. Add TODO for FanMode error code
LyudmilaKostanyan May 4, 2026
e696f9e
Refactor fan state handling in LoggingFanDevice
LyudmilaKostanyan May 4, 2026
7af5943
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 4, 2026
9714f8c
Remove second `soil-sensor` registration from `DeviceFactory`
LyudmilaKostanyan May 4, 2026
3ad74d9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 4, 2026
b0d50e4
Refactor AirPurifierManager to improve fan control logic
LyudmilaKostanyan May 4, 2026
6123807
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 4, 2026
7cf68d3
Refactor fan control logic in AirPurifierManager and related components
LyudmilaKostanyan May 4, 2026
7a8e971
Return comment
LyudmilaKostanyan May 4, 2026
611138d
Return nameing and remove useless casts
LyudmilaKostanyan May 4, 2026
d612b7e
Added comments to suppress lint warnings
LyudmilaKostanyan May 4, 2026
743eeb6
Refactor fan state handling in LoggingFanDevice
LyudmilaKostanyan May 4, 2026
e55a4a7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 4, 2026
15adca1
Keep fan currents at zero while On/Off is off
LyudmilaKostanyan May 5, 2026
4c1ed8a
Enhance LoggingFanDevice to handle On/Off state changes more robustly…
LyudmilaKostanyan May 5, 2026
30ff0ab
Match LoggingFanDevice::HandleStep to all-clusters fan-stub (null
LyudmilaKostanyan May 5, 2026
c766935
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 5, 2026
7c84965
Merge branch 'master' into FanControl
LyudmilaKostanyan May 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3155,7 +3155,7 @@ endpoint 1 {
callback attribute acceptedCommandList;
callback attribute attributeList;
ram attribute featureMap default = 63;
ram attribute clusterRevision default = 0x0006;
callback attribute clusterRevision;

handle command Step;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ class AirPurifierManager : public FanControl::Delegate, public DeviceManager::De
*/
Protocols::InteractionModel::Status HandleStep(FanControl::StepDirectionEnum aDirection, bool aWrap, bool aLowestOff) override;

/**
* @brief Sync the OnOff cluster when the fan turns on or off via FanControl.
*/
void OnFanStateChanged(bool isOn) override;
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Outdated

/**
* @brief Callback that thermostat manager calls when the heating state changes
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
*/

#include <air-purifier-manager.h>
#include <app/clusters/fan-control-server/CodegenIntegration.h>
#include <app/clusters/fan-control-server/FanControlCluster.h>
#include <lib/support/CodeUtils.h>

using namespace chip;
using namespace chip::app;
Expand Down Expand Up @@ -90,10 +93,12 @@ Status AirPurifierManager::HandleStep(FanControl::StepDirectionEnum aDirection,

VerifyOrReturnError(aDirection != FanControl::StepDirectionEnum::kUnknownEnumValue, Status::InvalidCommand);

uint8_t speedMax;
FanControl::Attributes::SpeedMax::Get(mEndpointId, &speedMax);
FanControlCluster * fc = FanControl::FindClusterOnEndpoint(mEndpointId);
VerifyOrReturnError(fc != nullptr, Status::UnsupportedEndpoint);
VerifyOrReturnError(fc->GetFeatureMap().Has(FanControl::Feature::kMultiSpeed), Status::Failure);

DataModel::Nullable<uint8_t> speedSetting = GetSpeedSetting();
uint8_t speedMax = fc->GetSpeedMax();
DataModel::Nullable<uint8_t> speedSetting = fc->GetSpeedSetting();

uint8_t newSpeedSetting = speedSetting.IsNull() ? 0 : speedSetting.Value();

Expand Down Expand Up @@ -149,7 +154,14 @@ Status AirPurifierManager::HandleStep(FanControl::StepDirectionEnum aDirection,
}
}

return FanControl::Attributes::SpeedSetting::Set(mEndpointId, newSpeedSetting);
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
return fc->SetSpeedSetting(DataModel::Nullable<uint8_t>(newSpeedSetting)).GetStatusCode().GetStatus();
}
Comment thread
LyudmilaKostanyan marked this conversation as resolved.

void AirPurifierManager::OnFanStateChanged(bool isOn)
{
ChipLogProgress(NotSpecified, "AirPurifierManager::OnFanStateChanged: %d", isOn);
OnOff::Attributes::OnOff::Set(mEndpointId, isOn);
mOnOffClusterOn = isOn;
}

void AirPurifierManager::HandleFanControlAttributeChange(AttributeId attributeId, uint8_t type, uint16_t size, uint8_t * value)
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Expand Down Expand Up @@ -201,61 +213,13 @@ void AirPurifierManager::HandleOnOff(AttributeId attributeId, uint8_t type, uint
return;
}
bool on = static_cast<bool>(*value);
uint8_t new_speed;
uint8_t new_percent;
if (on)
{
// If either of these come back as NULL, that should mean the fan is operating in auto mode.
// I have no idea what that means for this case, so I'll just set them to high because this
// is just an example.
// In theory these should always be NULL together or not at all, so hopefully
// the checks for only percent.IsNull() or only speed.IsNull() are more theoretical
// than practical.
DataModel::Nullable<Percent> percent = GetPercentSetting();
DataModel::Nullable<uint8_t> speed = GetSpeedSetting();
uint8_t speedMax = GetSpeedMax();
if (speedMax == 0)
{
ChipLogError(NotSpecified, "Out of bounds value for SpeedMax, setting to default (1)");
speedMax = 1;
}
if (percent.IsNull() && speed.IsNull())
{
// Operating in auto mode, set to 100
new_percent = 100;
new_speed = speedMax;
}
else if (percent.IsNull())
{
// This should never happen, but nonetheless, let's check and warn.
ChipLogError(NotSpecified,
"AirPurifierManager::HandleOnOff: PercentSetting is null when SpeedSetting is not. Setting PercentCurrent "
"from Speed");
new_speed = speed.Value();
new_percent = static_cast<uint8_t>(new_speed * 100u / speedMax);
}
else if (speed.IsNull())
{
// This should never happen, but nonetheless, let's check and warn.
ChipLogError(NotSpecified,
"AirPurifierManager::HandleOnOff: SpeedSetting is null when PercentSetting is not. Setting SpeedCurrent "
"from Percent");
new_percent = percent.Value();
new_speed = static_cast<uint8_t>(new_percent * speedMax / 100u);
}
else
{
new_percent = percent.Value();
new_speed = speed.Value();
}
}
else

FanControlCluster * fanCluster = FanControl::FindClusterOnEndpoint(mEndpointId);
if (fanCluster != nullptr)
{
new_percent = 0;
new_speed = 0;
fanCluster->SetOnOffState(on);
}
FanControl::Attributes::SpeedCurrent::Set(mEndpointId, new_speed);
FanControl::Attributes::PercentCurrent::Set(mEndpointId, new_percent);

mOnOffClusterOn = on;
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Outdated
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Outdated
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Outdated
}

Expand All @@ -264,7 +228,10 @@ void AirPurifierManager::PercentSettingWriteCallback(uint8_t aNewPercentSetting)
ChipLogDetail(NotSpecified, "AirPurifierManager::PercentSettingWriteCallback: %d", static_cast<int>(aNewPercentSetting));
if (mOnOffClusterOn)
{
Status status = FanControl::Attributes::PercentCurrent::Set(mEndpointId, aNewPercentSetting);
FanControlCluster * c = FanControl::FindClusterOnEndpoint(mEndpointId);
Status status = c == nullptr
? Status::UnsupportedEndpoint
: c->SetPercentSetting(DataModel::Nullable<Percent>(aNewPercentSetting)).GetStatusCode().GetStatus();
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Outdated
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Outdated
if (status != Status::Success)
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Outdated
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
{
ChipLogError(NotSpecified,
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Expand All @@ -279,7 +246,10 @@ void AirPurifierManager::SpeedSettingWriteCallback(uint8_t aNewSpeedSetting)
ChipLogDetail(NotSpecified, "AirPurifierManager::SpeedSettingWriteCallback: %d", static_cast<int>(aNewSpeedSetting));
if (mOnOffClusterOn)
{
Status status = FanControl::Attributes::SpeedCurrent::Set(mEndpointId, aNewSpeedSetting);
FanControlCluster * c = FanControl::FindClusterOnEndpoint(mEndpointId);
Status status = c == nullptr
? Status::UnsupportedEndpoint
: c->SetSpeedSetting(DataModel::Nullable<uint8_t>(aNewSpeedSetting)).GetStatusCode().GetStatus();
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Outdated
if (status != Status::Success)
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Outdated
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
{
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
ChipLogError(NotSpecified, "AirPurifierManager::SpeedSettingWriteCallback: failed to set SpeedCurrent attribute: %d",
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Expand All @@ -288,21 +258,30 @@ void AirPurifierManager::SpeedSettingWriteCallback(uint8_t aNewSpeedSetting)
}
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Comment thread
LyudmilaKostanyan marked this conversation as resolved.

Comment thread
LyudmilaKostanyan marked this conversation as resolved.
// Determine if the speed change should also change the fan mode
FanControl::FanModeEnum fanMode;
if (aNewSpeedSetting == 0)
{
FanControl::Attributes::FanMode::Set(mEndpointId, FanControl::FanModeEnum::kOff);
fanMode = FanControl::FanModeEnum::kOff;
}
else if (aNewSpeedSetting <= FAN_MODE_LOW_UPPER_BOUND)
{
FanControl::Attributes::FanMode::Set(mEndpointId, FanControl::FanModeEnum::kLow);
fanMode = FanControl::FanModeEnum::kLow;
}
else if (aNewSpeedSetting <= FAN_MODE_MEDIUM_UPPER_BOUND)
{
FanControl::Attributes::FanMode::Set(mEndpointId, FanControl::FanModeEnum::kMedium);
fanMode = FanControl::FanModeEnum::kMedium;
}
else if (aNewSpeedSetting <= FAN_MODE_HIGH_UPPER_BOUND)
{
FanControl::Attributes::FanMode::Set(mEndpointId, FanControl::FanModeEnum::kHigh);
fanMode = FanControl::FanModeEnum::kHigh;
}
else
{
return;
}
if (FanControlCluster * c = FanControl::FindClusterOnEndpoint(mEndpointId); c != nullptr)
{
LogErrorOnFailure(c->SetFanMode(fanMode).GetUnderlyingError());
}
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
}
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Comment thread
LyudmilaKostanyan marked this conversation as resolved.

Expand Down Expand Up @@ -366,7 +345,8 @@ void AirPurifierManager::SetSpeedSetting(DataModel::Nullable<uint8_t> aNewSpeedS
return;
}

Status status = FanControl::Attributes::SpeedSetting::Set(mEndpointId, aNewSpeedSetting);
FanControlCluster * c = FanControl::FindClusterOnEndpoint(mEndpointId);
Status status = c == nullptr ? Status::UnsupportedEndpoint : c->SetSpeedSetting(aNewSpeedSetting).GetStatusCode().GetStatus();
if (status != Status::Success)
{
ChipLogError(NotSpecified, "AirPurifierManager::SetSpeedSetting: failed to set SpeedSetting attribute: %d",
Expand All @@ -377,39 +357,31 @@ void AirPurifierManager::SetSpeedSetting(DataModel::Nullable<uint8_t> aNewSpeedS
DataModel::Nullable<uint8_t> AirPurifierManager::GetSpeedSetting()
{
DataModel::Nullable<uint8_t> speedSetting;
Status status = FanControl::Attributes::SpeedSetting::Get(mEndpointId, speedSetting);

if (status != Status::Success)
FanControlCluster * c = FanControl::FindClusterOnEndpoint(mEndpointId);
if (c != nullptr && c->GetFeatureMap().Has(FanControl::Feature::kMultiSpeed))
{
ChipLogError(NotSpecified, "AirPurifierManager::GetSpeedSetting: failed to get SpeedSetting attribute: %d",
to_underlying(status));
speedSetting = c->GetSpeedSetting();
}

return speedSetting;
}

DataModel::Nullable<Percent> AirPurifierManager::GetPercentSetting()
{
DataModel::Nullable<Percent> percentSetting;
Status status = FanControl::Attributes::PercentSetting::Get(mEndpointId, percentSetting);

if (status != Status::Success)
if (FanControlCluster * c = FanControl::FindClusterOnEndpoint(mEndpointId); c != nullptr)
{
ChipLogError(NotSpecified, "AirPurifierManager::GetPercentSetting: failed to get PercentSetting attribute: %d",
to_underlying(status));
percentSetting = c->GetPercentSetting();
}

return percentSetting;
}

uint8_t AirPurifierManager::GetSpeedMax()
{
uint8_t speedMax = 1;
Status status = FanControl::Attributes::SpeedMax::Get(mEndpointId, &speedMax);
if (status != Status::Success)
if (FanControlCluster * c = FanControl::FindClusterOnEndpoint(mEndpointId);
c != nullptr && c->GetFeatureMap().Has(FanControl::Feature::kMultiSpeed))
{
ChipLogError(NotSpecified, "AirPurifierManager::GetPercentSetting: failed to get SpeedMax attribute: %d",
to_underlying(status));
speedMax = c->GetSpeedMax();
}
return speedMax;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8275,7 +8275,7 @@ endpoint 1 {
ram attribute windSetting default = 0x00;
ram attribute airflowDirection default = 0;
ram attribute featureMap default = 0x3F;
ram attribute clusterRevision default = 0x0006;
callback attribute clusterRevision;

handle command Step;
}
Expand Down
40 changes: 32 additions & 8 deletions examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/AttributeAccessInterface.h>
#include <app/AttributeAccessInterfaceRegistry.h>
#include <app/clusters/fan-control-server/CodegenIntegration.h>
#include <app/clusters/fan-control-server/FanControlCluster.h>
#include <app/clusters/fan-control-server/fan-control-server.h>
#include <app/util/attribute-storage.h>
#include <app/util/attribute-table.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>

Expand All @@ -44,6 +47,7 @@ class FanControlManager : public AttributeAccessInterface, public Delegate

CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;
Status HandleStep(StepDirectionEnum aDirection, bool aWrap, bool aLowestOff) override;
void OnFanStateChanged(bool isOn) override;

private:
CHIP_ERROR ReadPercentCurrent(AttributeValueEncoder & aEncoder);
Expand All @@ -56,7 +60,10 @@ CHIP_ERROR FanControlManager::ReadPercentCurrent(AttributeValueEncoder & aEncode
{
// Return PercentSetting attribute value for now
DataModel::Nullable<Percent> percentSetting;
PercentSetting::Get(mEndpoint, percentSetting);
if (FanControlCluster * c = FanControl::FindClusterOnEndpoint(mEndpoint); c != nullptr)
{
percentSetting = c->GetPercentSetting();
}
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Outdated
Percent ret = 0;
if (!percentSetting.IsNull())
{
Expand All @@ -70,7 +77,11 @@ CHIP_ERROR FanControlManager::ReadSpeedCurrent(AttributeValueEncoder & aEncoder)
{
// Return SpeedCurrent attribute value for now
DataModel::Nullable<uint8_t> speedSetting;
SpeedSetting::Get(mEndpoint, speedSetting);
if (FanControlCluster * c = FanControl::FindClusterOnEndpoint(mEndpoint);
c != nullptr && c->GetFeatureMap().Has(FanControl::Feature::kMultiSpeed))
{
speedSetting = c->GetSpeedSetting();
}
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Outdated
uint8_t ret = 0;
if (!speedSetting.IsNull())
{
Expand All @@ -80,20 +91,29 @@ CHIP_ERROR FanControlManager::ReadSpeedCurrent(AttributeValueEncoder & aEncoder)
return aEncoder.Encode(ret);
}

void FanControlManager::OnFanStateChanged(bool isOn)
{
ChipLogProgress(NotSpecified, "FanControlManager::OnFanStateChanged: %d", isOn);
OnOff::Attributes::OnOff::Set(mEndpoint, isOn);
}

Status FanControlManager::HandleStep(StepDirectionEnum aDirection, bool aWrap, bool aLowestOff)
{
ChipLogProgress(NotSpecified, "FanControlManager::HandleStep aDirection %d, aWrap %d, aLowestOff %d", to_underlying(aDirection),
aWrap, aLowestOff);

VerifyOrReturnError(aDirection != StepDirectionEnum::kUnknownEnumValue, Status::InvalidCommand);

uint8_t speedMax;
SpeedMax::Get(mEndpoint, &speedMax);

FanControlCluster * cluster = FanControl::FindClusterOnEndpoint(mEndpoint);
uint8_t speedMax = 0;
DataModel::Nullable<uint8_t> speedSetting;
SpeedSetting::Get(mEndpoint, speedSetting);
if (cluster != nullptr && cluster->GetFeatureMap().Has(FanControl::Feature::kMultiSpeed))
{
speedMax = cluster->GetSpeedMax();
speedSetting = cluster->GetSpeedSetting();
}

uint8_t newSpeedSetting = speedSetting.IsNull() ? 0 : speedSetting.Value();
uint8_t newSpeedSetting = speedSetting.ValueOr(0);

if (aDirection == StepDirectionEnum::kIncrease)
{
Expand Down Expand Up @@ -147,7 +167,11 @@ Status FanControlManager::HandleStep(StepDirectionEnum aDirection, bool aWrap, b
}
}

return SpeedSetting::Set(mEndpoint, newSpeedSetting);
if (cluster == nullptr)
{
return Status::UnsupportedEndpoint;
}
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
return cluster->SetSpeedSetting(DataModel::MakeNullable(newSpeedSetting)).GetStatusCode().GetStatus();
}

CHIP_ERROR FanControlManager::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9141,7 +9141,7 @@ endpoint 1 {
ram attribute windSetting default = 0x00;
ram attribute airflowDirection default = 0;
ram attribute featureMap default = 0x3F;
ram attribute clusterRevision default = 0x0006;
callback attribute clusterRevision;

handle command Step;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7049,7 +7049,7 @@ endpoint 1 {
ram attribute percentSetting default = 0x00;
ram attribute percentCurrent default = 0x00;
ram attribute featureMap default = 0;
ram attribute clusterRevision default = 0x0006;
callback attribute clusterRevision;
}

server cluster ThermostatUserInterfaceConfiguration {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ source_set("device-factory") {
"${chip_root}/examples/all-devices-app/all-devices-common/devices/boolean-state-sensor",
"${chip_root}/examples/all-devices-app/all-devices-common/devices/chime",
"${chip_root}/examples/all-devices-app/all-devices-common/devices/dimmable-light/impl:logging",
"${chip_root}/examples/all-devices-app/all-devices-common/devices/fan/impl:logging",
"${chip_root}/examples/all-devices-app/all-devices-common/devices/occupancy-sensor/impl:toggling",
"${chip_root}/examples/all-devices-app/all-devices-common/devices/on-off-light",
"${chip_root}/examples/all-devices-app/all-devices-common/devices/soil-sensor/impl:increasing",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <devices/boolean-state-sensor/BooleanStateSensorDevice.h>
#include <devices/chime/ChimeDevice.h>
#include <devices/dimmable-light/impl/LoggingDimmableLightDevice.h>
#include <devices/fan/impl/LoggingFanDevice.h>
#include <devices/occupancy-sensor/impl/TogglingOccupancySensorDevice.h>
#include <devices/on-off-light/LoggingOnOffLightDevice.h>
#include <devices/soil-sensor/impl/IncreasingMoistureSoilSensorDevice.h>
Expand Down Expand Up @@ -140,6 +141,14 @@ class DeviceFactory
LoggingSpeakerDevice::Context{ .timerDelegate = mContext->timerDelegate });
};
mRegistry["soil-sensor"] = []() { return std::make_unique<IncreasingMoistureSoilSensorDevice>(); };
mRegistry["fan"] = [this]() {
VerifyOrDie(mContext.has_value());
return std::make_unique<LoggingFanDevice>(LoggingFanDevice::Context{
.groupDataProvider = mContext->groupDataProvider,
.fabricTable = mContext->fabricTable,
.timerDelegate = mContext->timerDelegate,
});
Comment thread
LyudmilaKostanyan marked this conversation as resolved.
Outdated
};
}
};

Expand Down
Loading
Loading