Fan Control Cluster updates for Fall 2023: TE1 (#26296)
* Updated fan-control-server with better support for feature checking, step command handler and checks around the supported attributes in the pre-callback
* Updated fan-control-cluster.xml for TE1 for fall release and regenerated the generated code
* Ensured status was always initialised before returning, added missing break in switch case
* Update optional parameters of Step command and matched spec naming. Improved checking on Auto feature when receiving smart mode.
* Added a stop-gap fan-stub.cpp so that the existing FanControl tests pass for TE1
* removed unused variable
* fixed return after else warning
* reordered files as per restyler
diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter
index 95e20cb..b087a5f 100644
--- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter
+++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter
@@ -3285,6 +3285,16 @@
/** An interface for controlling a fan in a heating/cooling system. */
server cluster FanControl = 514 {
+ enum AirflowDirectionEnum : ENUM8 {
+ kForward = 0;
+ kReverse = 1;
+ }
+
+ enum DirectionEnum : ENUM8 {
+ kIncrease = 0;
+ kDecrease = 1;
+ }
+
enum FanModeSequenceType : ENUM8 {
kOffLowMedHigh = 0;
kOffLowHigh = 1;
@@ -3309,6 +3319,8 @@
kAuto = 0x2;
kRocking = 0x4;
kWind = 0x8;
+ kStep = 0x10;
+ kAirflowDirection = 0x20;
}
bitmap RockSupportMask : BITMAP8 {
@@ -3338,12 +3350,21 @@
attribute bitmap8 rockSetting = 8;
readonly attribute bitmap8 windSupport = 9;
attribute bitmap8 windSetting = 10;
+ attribute AirflowDirectionEnum airflowDirection = 11;
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 StepRequest {
+ DirectionEnum direction = 0;
+ optional boolean wrap = 1;
+ optional boolean lowestOff = 2;
+ }
+
+ command Step(StepRequest): DefaultSuccess = 0;
}
/** An interface for configuring the user interface of a thermostat (which may be remote from the thermostat). */
@@ -5330,6 +5351,7 @@
ram attribute rockSetting default = 0x00;
ram attribute windSupport default = 0x00;
ram attribute windSetting default = 0x00;
+ ram attribute airflowDirection default = 0;
ram attribute featureMap default = 0x0F;
ram attribute clusterRevision default = 2;
}
diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap
index c872509..4cea978 100644
--- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap
+++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap
@@ -15716,7 +15716,17 @@
"mfgCode": null,
"define": "FAN_CONTROL_CLUSTER",
"side": "client",
- "enabled": 0
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "Step",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ]
},
{
"name": "Fan Control",
@@ -15903,6 +15913,22 @@
"reportableChange": 0
},
{
+ "name": "AirflowDirection",
+ "code": 11,
+ "mfgCode": null,
+ "side": "server",
+ "type": "AirflowDirectionEnum",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
"name": "GeneratedCommandList",
"code": 65528,
"mfgCode": null,
diff --git a/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp b/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp
new file mode 100644
index 0000000..4f70f80
--- /dev/null
+++ b/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp
@@ -0,0 +1,115 @@
+/*
+ *
+ * Copyright (c) 2023 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <app-common/zap-generated/attributes/Accessors.h>
+#include <app-common/zap-generated/cluster-objects.h>
+#include <app-common/zap-generated/ids/Attributes.h>
+#include <app-common/zap-generated/ids/Clusters.h>
+#include <app/AttributeAccessInterface.h>
+#include <app/util/attribute-storage.h>
+#include <lib/support/CodeUtils.h>
+#include <lib/support/logging/CHIPLogging.h>
+
+using namespace chip;
+using namespace chip::app;
+using namespace chip::app::Clusters;
+using namespace chip::app::Clusters::FanControl::Attributes;
+
+namespace {
+
+/*
+ * TODO: This is a stop-gap solution to allow the existing fan control cluster tests to run after changes to
+ * the cluster objects for TE1. This should be removed once #6496 is resolved as it will likely result in a
+ * FanControl delegate added to the SDK.
+ *
+ * FYI... The previous implementation of the FanControl cluster set the speedCurrent/percentCurrent when it received
+ * speedSetting/percentSetting. The new implementation of the FanControl cluster does not do this as this should
+ * really be done by the application.
+ */
+
+class FanAttrAccess : public AttributeAccessInterface
+{
+public:
+ // Register for the FanControl cluster on all endpoints.
+ FanAttrAccess() : AttributeAccessInterface(Optional<EndpointId>::Missing(), FanControl::Id) {}
+
+ CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;
+
+private:
+ CHIP_ERROR ReadPercentCurrent(EndpointId endpoint, AttributeValueEncoder & aEncoder);
+ CHIP_ERROR ReadSpeedCurrent(EndpointId endpoint, AttributeValueEncoder & aEncoder);
+};
+
+CHIP_ERROR FanAttrAccess::ReadPercentCurrent(EndpointId endpoint, AttributeValueEncoder & aEncoder)
+{
+ // Return PercentSetting attribute value for now
+ DataModel::Nullable<uint8_t> percentSetting;
+ PercentSetting::Get(endpoint, percentSetting);
+ uint8_t ret = 0;
+ if (!percentSetting.IsNull())
+ {
+ ret = percentSetting.Value();
+ }
+
+ return aEncoder.Encode(ret);
+}
+
+CHIP_ERROR FanAttrAccess::ReadSpeedCurrent(EndpointId endpoint, AttributeValueEncoder & aEncoder)
+{
+ // Return SpeedCurrent attribute value for now
+ DataModel::Nullable<uint8_t> speedSetting;
+ SpeedSetting::Get(endpoint, speedSetting);
+ uint8_t ret = 0;
+ if (!speedSetting.IsNull())
+ {
+ ret = speedSetting.Value();
+ }
+
+ return aEncoder.Encode(ret);
+}
+
+FanAttrAccess gAttrAccess;
+
+CHIP_ERROR FanAttrAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
+{
+ VerifyOrDie(aPath.mClusterId == FanControl::Id);
+
+ switch (aPath.mAttributeId)
+ {
+ case SpeedCurrent::Id:
+ return ReadSpeedCurrent(aPath.mEndpointId, aEncoder);
+ case PercentCurrent::Id:
+ return ReadPercentCurrent(aPath.mEndpointId, aEncoder);
+ default:
+ break;
+ }
+ return CHIP_NO_ERROR;
+}
+} // anonymous namespace
+
+void emberAfFanControlClusterInitCallback(EndpointId endpoint)
+{
+ uint32_t featureMap = 0;
+
+ featureMap |= to_underlying(FanControl::Feature::kMultiSpeed);
+ featureMap |= to_underlying(FanControl::Feature::kMultiSpeed);
+ featureMap |= to_underlying(FanControl::Feature::kAuto);
+
+ FeatureMap::Set(endpoint, featureMap);
+
+ registerAttributeAccessOverride(&gAttrAccess);
+}
diff --git a/examples/all-clusters-app/linux/BUILD.gn b/examples/all-clusters-app/linux/BUILD.gn
index 1b8ff71..402649c 100644
--- a/examples/all-clusters-app/linux/BUILD.gn
+++ b/examples/all-clusters-app/linux/BUILD.gn
@@ -23,6 +23,7 @@
sources = [
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp",
+ "${chip_root}/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp",
"AllClustersCommandDelegate.cpp",
"AppOptions.cpp",
diff --git a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter
index 1193a78..8281f56 100644
--- a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter
+++ b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter
@@ -2769,6 +2769,16 @@
/** An interface for controlling a fan in a heating/cooling system. */
server cluster FanControl = 514 {
+ enum AirflowDirectionEnum : ENUM8 {
+ kForward = 0;
+ kReverse = 1;
+ }
+
+ enum DirectionEnum : ENUM8 {
+ kIncrease = 0;
+ kDecrease = 1;
+ }
+
enum FanModeSequenceType : ENUM8 {
kOffLowMedHigh = 0;
kOffLowHigh = 1;
@@ -2793,6 +2803,8 @@
kAuto = 0x2;
kRocking = 0x4;
kWind = 0x8;
+ kStep = 0x10;
+ kAirflowDirection = 0x20;
}
bitmap RockSupportMask : BITMAP8 {
diff --git a/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter b/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter
index d897406..00a4d90 100644
--- a/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter
+++ b/examples/chef/devices/rootnode_fan_7N2TobIlOX.matter
@@ -1187,6 +1187,16 @@
/** An interface for controlling a fan in a heating/cooling system. */
server cluster FanControl = 514 {
+ enum AirflowDirectionEnum : ENUM8 {
+ kForward = 0;
+ kReverse = 1;
+ }
+
+ enum DirectionEnum : ENUM8 {
+ kIncrease = 0;
+ kDecrease = 1;
+ }
+
enum FanModeSequenceType : ENUM8 {
kOffLowMedHigh = 0;
kOffLowHigh = 1;
@@ -1211,6 +1221,8 @@
kAuto = 0x2;
kRocking = 0x4;
kWind = 0x8;
+ kStep = 0x10;
+ kAirflowDirection = 0x20;
}
bitmap RockSupportMask : BITMAP8 {
diff --git a/examples/chef/devices/rootnode_heatingcoolingunit_ncdGai1E5a.matter b/examples/chef/devices/rootnode_heatingcoolingunit_ncdGai1E5a.matter
index dce6707..14a6168 100644
--- a/examples/chef/devices/rootnode_heatingcoolingunit_ncdGai1E5a.matter
+++ b/examples/chef/devices/rootnode_heatingcoolingunit_ncdGai1E5a.matter
@@ -1500,6 +1500,16 @@
/** An interface for controlling a fan in a heating/cooling system. */
server cluster FanControl = 514 {
+ enum AirflowDirectionEnum : ENUM8 {
+ kForward = 0;
+ kReverse = 1;
+ }
+
+ enum DirectionEnum : ENUM8 {
+ kIncrease = 0;
+ kDecrease = 1;
+ }
+
enum FanModeSequenceType : ENUM8 {
kOffLowMedHigh = 0;
kOffLowHigh = 1;
@@ -1524,6 +1534,8 @@
kAuto = 0x2;
kRocking = 0x4;
kWind = 0x8;
+ kStep = 0x10;
+ kAirflowDirection = 0x20;
}
bitmap RockSupportMask : BITMAP8 {
diff --git a/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter b/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter
index 17d0226..a5a3b48 100644
--- a/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter
+++ b/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter
@@ -1309,6 +1309,16 @@
/** An interface for controlling a fan in a heating/cooling system. */
client cluster FanControl = 514 {
+ enum AirflowDirectionEnum : ENUM8 {
+ kForward = 0;
+ kReverse = 1;
+ }
+
+ enum DirectionEnum : ENUM8 {
+ kIncrease = 0;
+ kDecrease = 1;
+ }
+
enum FanModeSequenceType : ENUM8 {
kOffLowMedHigh = 0;
kOffLowHigh = 1;
@@ -1333,6 +1343,8 @@
kAuto = 0x2;
kRocking = 0x4;
kWind = 0x8;
+ kStep = 0x10;
+ kAirflowDirection = 0x20;
}
bitmap RockSupportMask : BITMAP8 {
@@ -1362,12 +1374,22 @@
attribute optional bitmap8 rockSetting = 8;
readonly attribute optional bitmap8 windSupport = 9;
attribute optional bitmap8 windSetting = 10;
+ attribute optional AirflowDirectionEnum airflowDirection = 11;
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 StepRequest {
+ DirectionEnum direction = 0;
+ optional boolean wrap = 1;
+ optional boolean lowestOff = 2;
+ }
+
+ /** The Step command speeds up or slows down the fan, in steps. */
+ command Step(StepRequest): DefaultSuccess = 0;
}
/** An interface for configuring the user interface of a thermostat (which may be remote from the thermostat). */
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 25b593b..c2c9c1c 100644
--- a/src/app/clusters/fan-control-server/fan-control-server.cpp
+++ b/src/app/clusters/fan-control-server/fan-control-server.cpp
@@ -28,7 +28,10 @@
#include <app-common/zap-generated/ids/Attributes.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/AttributeAccessInterface.h>
+#include <app/CommandHandler.h>
+#include <app/ConcreteCommandPath.h>
#include <app/util/attribute-storage.h>
+#include <app/util/error-mapping.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
@@ -57,6 +60,45 @@
return status;
}
+bool HasFeature(EndpointId endpoint, Feature feature)
+{
+ bool success;
+ uint32_t featureMap;
+ success = (Attributes::FeatureMap::Get(endpoint, &featureMap) == EMBER_ZCL_STATUS_SUCCESS);
+
+ return success ? ((featureMap & to_underlying(feature)) != 0) : false;
+}
+
+inline bool SupportsMultiSpeed(chip::EndpointId endpointId)
+{
+ return HasFeature(endpointId, Feature::kMultiSpeed);
+}
+
+inline bool SupportsAuto(chip::EndpointId endpointId)
+{
+ return HasFeature(endpointId, Feature::kAuto);
+}
+
+inline bool SupportsRocking(chip::EndpointId endpointId)
+{
+ return HasFeature(endpointId, Feature::kRocking);
+}
+
+inline bool SupportsWind(chip::EndpointId endpointId)
+{
+ return HasFeature(endpointId, Feature::kWind);
+}
+
+inline bool SupportsStep(chip::EndpointId endpointId)
+{
+ return HasFeature(endpointId, Feature::kStep);
+}
+
+inline bool SupportsAirflowDirection(chip::EndpointId endpointId)
+{
+ return HasFeature(endpointId, Feature::kAirflowDirection);
+}
+
} // anonymous namespace
// =============================================================================
@@ -73,37 +115,75 @@
switch (attributePath.mAttributeId)
{
- case SpeedSetting::Id:
- // Check if the SpeedSetting is null.
- if (NumericAttributeTraits<uint8_t>::IsNullValue(*value))
+ case FanMode::Id: {
+ if (*value == to_underlying(FanModeType::kOn))
{
+ FanMode::Set(attributePath.mEndpointId, FanModeType::kHigh);
+ res = Status::WriteIgnored;
+ }
+ else if (*value == to_underlying(FanModeType::kSmart))
+ {
+ FanModeSequenceType fanModeSequence;
+ EmberAfStatus status = FanModeSequence::Get(attributePath.mEndpointId, &fanModeSequence);
+ VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, Status::Failure);
- if (gWriteFromClusterLogic)
+ if (SupportsAuto(attributePath.mEndpointId) &&
+ ((fanModeSequence == FanModeSequenceType::kOffLowHighAuto) ||
+ (fanModeSequence == FanModeSequenceType::kOffLowMedHighAuto)))
{
- res = Status::Success;
- gWriteFromClusterLogic = false;
+ FanMode::Set(attributePath.mEndpointId, FanModeType::kAuto);
}
else
{
- res = Status::WriteIgnored;
+ FanMode::Set(attributePath.mEndpointId, FanModeType::kHigh);
+ }
+ res = Status::WriteIgnored;
+ }
+ else
+ {
+ res = Status::Success;
+ }
+ break;
+ }
+ case SpeedSetting::Id: {
+ if (SupportsMultiSpeed(attributePath.mEndpointId))
+ {
+ // Check if the SpeedSetting is null.
+ if (NumericAttributeTraits<uint8_t>::IsNullValue(*value))
+ {
+
+ if (gWriteFromClusterLogic)
+ {
+ res = Status::Success;
+ gWriteFromClusterLogic = false;
+ }
+ else
+ {
+ res = Status::WriteIgnored;
+ }
+ }
+ else
+ {
+ uint8_t speedMax;
+ EmberAfStatus status = SpeedMax::Get(attributePath.mEndpointId, &speedMax);
+ VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, Status::ConstraintError);
+
+ if (*value <= speedMax)
+ {
+ res = Status::Success;
+ }
+ else
+ {
+ res = Status::ConstraintError;
+ }
}
}
else
{
- uint8_t speedMax;
- EmberAfStatus status = SpeedMax::Get(attributePath.mEndpointId, &speedMax);
- VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, Status::ConstraintError);
-
- if (*value <= speedMax)
- {
- res = Status::Success;
- }
- else
- {
- res = Status::ConstraintError;
- }
+ res = Status::UnsupportedAttribute;
}
break;
+ }
case PercentSetting::Id: {
// Check if the PercentSetting is null.
if (NumericAttributeTraits<uint8_t>::IsNullValue(*value))
@@ -124,6 +204,59 @@
}
break;
}
+ case RockSetting::Id: {
+ if (SupportsRocking(attributePath.mEndpointId))
+ {
+ uint8_t rockSupport;
+ EmberAfStatus status = RockSupport::Get(attributePath.mEndpointId, &rockSupport);
+ VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, Status::ConstraintError);
+ if ((*value & rockSupport) == *value)
+ {
+ res = Status::Success;
+ }
+ else
+ {
+ res = Status::ConstraintError;
+ }
+ }
+ else
+ {
+ res = Status::UnsupportedAttribute;
+ }
+ break;
+ }
+ case WindSupport::Id: {
+ if (SupportsWind(attributePath.mEndpointId))
+ {
+ uint8_t windSupport;
+ EmberAfStatus status = WindSupport::Get(attributePath.mEndpointId, &windSupport);
+ VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, Status::ConstraintError);
+ if ((*value & windSupport) == *value)
+ {
+ res = Status::Success;
+ }
+ else
+ {
+ res = Status::ConstraintError;
+ }
+ }
+ else
+ {
+ res = Status::UnsupportedAttribute;
+ }
+ break;
+ }
+ case AirflowDirection::Id: {
+ if (SupportsAirflowDirection(attributePath.mEndpointId))
+ {
+ res = Status::Success;
+ }
+ else
+ {
+ res = Status::UnsupportedAttribute;
+ }
+ break;
+ }
default:
res = Status::Success;
break;
@@ -134,17 +267,6 @@
void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAttributePath & attributePath)
{
- bool multiSpeedSupported = false;
-
- {
- uint32_t ourFeatureMap;
- if (FeatureMap::Get(attributePath.mEndpointId, &ourFeatureMap) == EMBER_ZCL_STATUS_SUCCESS)
- {
- if (ourFeatureMap & to_underlying(Feature::kMultiSpeed))
- multiSpeedSupported = true;
- }
- }
-
switch (attributePath.mAttributeId)
{
case FanMode::Id: {
@@ -164,7 +286,7 @@
VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status,
ChipLogError(Zcl, "Failed to write PercentCurrent with error: 0x%02x", status));
- if (multiSpeedSupported)
+ if (SupportsMultiSpeed(attributePath.mEndpointId))
{
status = SpeedSetting::Set(attributePath.mEndpointId, 0);
VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status,
@@ -185,7 +307,7 @@
VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status,
ChipLogError(Zcl, "Failed to write PercentSetting with error: 0x%02x", status));
- if (multiSpeedSupported)
+ if (SupportsMultiSpeed(attributePath.mEndpointId))
{
gWriteFromClusterLogic = true;
status = SpeedSetting::SetNull(attributePath.mEndpointId);
@@ -208,7 +330,7 @@
ChipLogError(Zcl, "Failed to set FanMode to off with error: 0x%02x", status));
}
- if (multiSpeedSupported)
+ if (SupportsMultiSpeed(attributePath.mEndpointId))
{
// Adjust SpeedSetting from a percent value change for PercentSetting
// speed = ceil( SpeedMax * (percent * 0.01) )
@@ -231,53 +353,69 @@
VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status,
ChipLogError(Zcl, "Failed to set SpeedSetting with error: 0x%02x", status));
}
-
- status = SpeedCurrent::Set(attributePath.mEndpointId, speedSetting);
- VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status,
- ChipLogError(Zcl, "Failed to set SpeedCurrent with error: 0x%02x", status));
}
break;
}
case SpeedSetting::Id: {
- DataModel::Nullable<uint8_t> speedSetting;
- EmberAfStatus status = SpeedSetting::Get(attributePath.mEndpointId, speedSetting);
- VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status && !speedSetting.IsNull());
-
- // If SpeedSetting is set to 0, the server SHALL set the FanMode attribute value to Off.
- if (speedSetting.Value() == 0)
+ if (SupportsMultiSpeed(attributePath.mEndpointId))
{
- status = SetFanModeToOff(attributePath.mEndpointId);
+ DataModel::Nullable<uint8_t> speedSetting;
+ EmberAfStatus status = SpeedSetting::Get(attributePath.mEndpointId, speedSetting);
+ VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status && !speedSetting.IsNull());
+
+ // If SpeedSetting is set to 0, the server SHALL set the FanMode attribute value to Off.
+ if (speedSetting.Value() == 0)
+ {
+ status = SetFanModeToOff(attributePath.mEndpointId);
+ VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status,
+ ChipLogError(Zcl, "Failed to set FanMode to off with error: 0x%02x", status));
+ }
+
+ // Adjust PercentSetting from a speed value change for SpeedSetting
+ // percent = floor( speed/SpeedMax * 100 )
+ uint8_t speedMax;
+ status = SpeedMax::Get(attributePath.mEndpointId, &speedMax);
VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status,
- ChipLogError(Zcl, "Failed to set FanMode to off with error: 0x%02x", status));
- }
+ ChipLogError(Zcl, "Failed to get SpeedMax with error: 0x%02x", status));
- // Adjust PercentSetting from a speed value change for SpeedSetting
- // percent = floor( speed/SpeedMax * 100 )
- uint8_t speedMax;
- status = SpeedMax::Get(attributePath.mEndpointId, &speedMax);
- VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status, ChipLogError(Zcl, "Failed to get SpeedMax with error: 0x%02x", status));
-
- DataModel::Nullable<uint8_t> currentPercentSetting;
- status = PercentSetting::Get(attributePath.mEndpointId, currentPercentSetting);
- VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status,
- ChipLogError(Zcl, "Failed to get PercentSetting with error: 0x%02x", status));
-
- float speed = speedSetting.Value();
- uint8_t percentSetting = static_cast<uint8_t>(speed / speedMax * 100);
-
- if (currentPercentSetting.IsNull() || percentSetting != currentPercentSetting.Value())
- {
- status = PercentSetting::Set(attributePath.mEndpointId, percentSetting);
+ DataModel::Nullable<uint8_t> currentPercentSetting;
+ status = PercentSetting::Get(attributePath.mEndpointId, currentPercentSetting);
VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status,
- ChipLogError(Zcl, "Failed to set PercentSetting with error: 0x%02x", status));
- }
+ ChipLogError(Zcl, "Failed to get PercentSetting with error: 0x%02x", status));
- status = PercentCurrent::Set(attributePath.mEndpointId, percentSetting);
- VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status,
- ChipLogError(Zcl, "Failed to set PercentCurrent with error: 0x%02x", status));
+ float speed = speedSetting.Value();
+ uint8_t percentSetting = static_cast<uint8_t>(speed / speedMax * 100);
+
+ if (currentPercentSetting.IsNull() || percentSetting != currentPercentSetting.Value())
+ {
+ status = PercentSetting::Set(attributePath.mEndpointId, percentSetting);
+ VerifyOrReturn(EMBER_ZCL_STATUS_SUCCESS == status,
+ ChipLogError(Zcl, "Failed to set PercentSetting with error: 0x%02x", status));
+ }
+ }
break;
}
default:
break;
}
}
+
+bool emberAfFanControlClusterStepCallback(chip::app::CommandHandler * commandObj,
+ const chip::app::ConcreteCommandPath & commandPath,
+ const chip::app::Clusters::FanControl::Commands::Step::DecodableType & commandData)
+{
+ /*
+ * TODO: Clarification needed in spec issue #6496 - if this is tied to the SpeedSetting attribute, then
+ * the attribute can be updated here, if it is supposed to be implementation specific, then the command
+ * will have to be handed off to an application specific callback which will require some sort of delegate.
+ */
+
+ Protocols::InteractionModel::Status status = Status::Success;
+
+ if (!SupportsStep(commandPath.mEndpointId))
+ {
+ status = Status::UnsupportedCommand;
+ }
+ commandObj->AddStatus(commandPath, status);
+ return true;
+}
diff --git a/src/app/zap-templates/zcl/data-model/chip/fan-control-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/fan-control-cluster.xml
index ce9ef44..8460756 100644
--- a/src/app/zap-templates/zcl/data-model/chip/fan-control-cluster.xml
+++ b/src/app/zap-templates/zcl/data-model/chip/fan-control-cluster.xml
@@ -23,6 +23,8 @@
<field name="Auto" mask="0x02" />
<field name="Rocking" mask="0x04" />
<field name="Wind" mask="0x08" />
+ <field name="Step" mask="0x10" />
+ <field name="Airflow Direction" mask="0x20" />
</bitmap>
<enum name="FanModeType" type="ENUM8">
@@ -65,6 +67,18 @@
<field name="Natural Wind" mask="0x02" />
</bitmap>
+ <enum name="DirectionEnum" type="ENUM8">
+ <cluster code="0x0202"/>
+ <item name="Increase" value="0x00"/>
+ <item name="Decrease" value="0x01"/>
+ </enum>
+
+ <enum name="AirflowDirectionEnum" type="ENUM8">
+ <cluster code="0x0202"/>
+ <item name="Forward" value="0x00"/>
+ <item name="Reverse" value="0x01"/>
+ </enum>
+
<cluster>
<name>Fan Control</name>
<domain>HVAC</domain>
@@ -86,5 +100,14 @@
<attribute side="server" code="0x0008" define="ROCK_SETTING" type="BITMAP8" writable="true" default="0x00" optional="true">RockSetting</attribute>
<attribute side="server" code="0x0009" define="WIND_SUPPORT" type="BITMAP8" writable="false" default="0x00" optional="true">WindSupport</attribute>
<attribute side="server" code="0x000A" define="WIND_SETTING" type="BITMAP8" writable="true" default="0x00" optional="true">WindSetting</attribute>
+ <attribute side="server" code="0x000B" define="AIRFLOW_DIRECTION" type="AirflowDirectionEnum" writable="true" default="0" optional="true">AirflowDirection</attribute>
+
+ <command source="client" code="0x00" name="Step" optional="true">
+ <description>The Step command speeds up or slows down the fan, in steps.</description>
+ <arg name="Direction" type="DirectionEnum"/>
+ <arg name="Wrap" type="boolean" optional="true"/>
+ <arg name="LowestOff" type="boolean" optional="true"/>
+ </command>
+
</cluster>
</configurator>
diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter
index ed238fa..f8bf495 100644
--- a/src/controller/data_model/controller-clusters.matter
+++ b/src/controller/data_model/controller-clusters.matter
@@ -4519,6 +4519,16 @@
/** An interface for controlling a fan in a heating/cooling system. */
client cluster FanControl = 514 {
+ enum AirflowDirectionEnum : ENUM8 {
+ kForward = 0;
+ kReverse = 1;
+ }
+
+ enum DirectionEnum : ENUM8 {
+ kIncrease = 0;
+ kDecrease = 1;
+ }
+
enum FanModeSequenceType : ENUM8 {
kOffLowMedHigh = 0;
kOffLowHigh = 1;
@@ -4543,6 +4553,8 @@
kAuto = 0x2;
kRocking = 0x4;
kWind = 0x8;
+ kStep = 0x10;
+ kAirflowDirection = 0x20;
}
bitmap RockSupportMask : BITMAP8 {
@@ -4572,12 +4584,22 @@
attribute optional bitmap8 rockSetting = 8;
readonly attribute optional bitmap8 windSupport = 9;
attribute optional bitmap8 windSetting = 10;
+ attribute optional AirflowDirectionEnum airflowDirection = 11;
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 StepRequest {
+ DirectionEnum direction = 0;
+ optional boolean wrap = 1;
+ optional boolean lowestOff = 2;
+ }
+
+ /** The Step command speeds up or slows down the fan, in steps. */
+ command Step(StepRequest): DefaultSuccess = 0;
}
/** An interface for configuring the user interface of a thermostat (which may be remote from the thermostat). */
diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java
index 63b53c7..d558f16 100644
--- a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java
+++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java
@@ -9328,6 +9328,7 @@
RockSetting(8L),
WindSupport(9L),
WindSetting(10L),
+ AirflowDirection(11L),
GeneratedCommandList(65528L),
AcceptedCommandList(65529L),
EventList(65530L),
@@ -9373,7 +9374,8 @@
}
}
- public enum Command {;
+ public enum Command {
+ Step(0L),;
private final long id;
Command(long id) {
this.id = id;
@@ -9391,7 +9393,24 @@
}
throw new NoSuchFieldError();
}
- }@Override
+ }public enum StepCommandField {Direction(0),Wrap(1),LowestOff(2),;
+ private final int id;
+ StepCommandField(int id) {
+ this.id = id;
+ }
+
+ public int getID() {
+ return id;
+ }
+ public static StepCommandField value(int id) throws NoSuchFieldError {
+ for (StepCommandField field : StepCommandField.values()) {
+ if (field.getID() == id) {
+ return field;
+ }
+ }
+ throw new NoSuchFieldError();
+ }
+ }@Override
public String getAttributeName(long id) throws NoSuchFieldError {
return Attribute.value(id).toString();
}
diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java
index acf9c51..3678b7d 100644
--- a/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java
+++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java
@@ -10072,6 +10072,17 @@
readFanControlWindSettingCommandParams
);
result.put("readWindSettingAttribute", readFanControlWindSettingAttributeInteractionInfo);
+ Map<String, CommandParameterInfo> readFanControlAirflowDirectionCommandParams = new LinkedHashMap<String, CommandParameterInfo>();
+ InteractionInfo readFanControlAirflowDirectionAttributeInteractionInfo = new InteractionInfo(
+ (cluster, callback, commandArguments) -> {
+ ((ChipClusters.FanControlCluster) cluster).readAirflowDirectionAttribute(
+ (ChipClusters.IntegerAttributeCallback) callback
+ );
+ },
+ () -> new ClusterInfoMapping.DelegatedIntegerAttributeCallback(),
+ readFanControlAirflowDirectionCommandParams
+ );
+ result.put("readAirflowDirectionAttribute", readFanControlAirflowDirectionAttributeInteractionInfo);
Map<String, CommandParameterInfo> readFanControlGeneratedCommandListCommandParams = new LinkedHashMap<String, CommandParameterInfo>();
InteractionInfo readFanControlGeneratedCommandListAttributeInteractionInfo = new InteractionInfo(
(cluster, callback, commandArguments) -> {
diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterWriteMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterWriteMapping.java
index 508627d..4f517da 100644
--- a/src/controller/java/generated/java/chip/devicecontroller/ClusterWriteMapping.java
+++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterWriteMapping.java
@@ -2223,6 +2223,28 @@
writeFanControlWindSettingCommandParams
);
writeFanControlInteractionInfo.put("writeWindSettingAttribute", writeFanControlWindSettingAttributeInteractionInfo);
+ Map<String, CommandParameterInfo> writeFanControlAirflowDirectionCommandParams = new LinkedHashMap<String, CommandParameterInfo>();
+ CommandParameterInfo fanControlairflowDirectionCommandParameterInfo =
+ new CommandParameterInfo(
+ "value",
+ Integer.class,
+ Integer.class
+ );
+ writeFanControlAirflowDirectionCommandParams.put(
+ "value",
+ fanControlairflowDirectionCommandParameterInfo
+ );
+ InteractionInfo writeFanControlAirflowDirectionAttributeInteractionInfo = new InteractionInfo(
+ (cluster, callback, commandArguments) -> {
+ ((ChipClusters.FanControlCluster) cluster).writeAirflowDirectionAttribute(
+ (DefaultClusterCallback) callback,
+ (Integer) commandArguments.get("value")
+ );
+ },
+ () -> new ClusterInfoMapping.DelegatedDefaultClusterCallback(),
+ writeFanControlAirflowDirectionCommandParams
+ );
+ writeFanControlInteractionInfo.put("writeAirflowDirectionAttribute", writeFanControlAirflowDirectionAttributeInteractionInfo);
writeAttributeMap.put("fanControl", writeFanControlInteractionInfo);
Map<String, InteractionInfo> writeThermostatUserInterfaceConfigurationInteractionInfo = new LinkedHashMap<>();
Map<String, CommandParameterInfo> writeThermostatUserInterfaceConfigurationTemperatureDisplayModeCommandParams = new LinkedHashMap<String, CommandParameterInfo>();
diff --git a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp
index db04f23..bed47f6 100644
--- a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp
+++ b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp
@@ -19055,6 +19055,21 @@
cppValue, value);
return value;
}
+ case Attributes::AirflowDirection::Id: {
+ using TypeInfo = Attributes::AirflowDirection::TypeInfo;
+ TypeInfo::DecodableType cppValue;
+ *aError = app::DataModel::Decode(aReader, cppValue);
+ if (*aError != CHIP_NO_ERROR)
+ {
+ return nullptr;
+ }
+ jobject value;
+ std::string valueClassName = "java/lang/Integer";
+ std::string valueCtorSignature = "(I)V";
+ chip::JniReferences::GetInstance().CreateBoxedObject<uint8_t>(valueClassName.c_str(), valueCtorSignature.c_str(),
+ static_cast<uint8_t>(cppValue), value);
+ return value;
+ }
case Attributes::GeneratedCommandList::Id: {
using TypeInfo = Attributes::GeneratedCommandList::TypeInfo;
TypeInfo::DecodableType cppValue;
diff --git a/src/controller/java/zap-generated/CHIPClustersWrite-JNI.cpp b/src/controller/java/zap-generated/CHIPClustersWrite-JNI.cpp
index 3b922d4..14111e7 100644
--- a/src/controller/java/zap-generated/CHIPClustersWrite-JNI.cpp
+++ b/src/controller/java/zap-generated/CHIPClustersWrite-JNI.cpp
@@ -5722,6 +5722,58 @@
onFailure.release();
}
+JNI_METHOD(void, FanControlCluster, writeAirflowDirectionAttribute)
+(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jobject value, jobject timedWriteTimeoutMs)
+{
+ chip::DeviceLayer::StackLock lock;
+ ListFreer listFreer;
+ using TypeInfo = chip::app::Clusters::FanControl::Attributes::AirflowDirection::TypeInfo;
+ TypeInfo::Type cppValue;
+
+ std::vector<Platform::UniquePtr<JniByteArray>> cleanupByteArrays;
+ std::vector<Platform::UniquePtr<JniUtfString>> cleanupStrings;
+
+ cppValue =
+ static_cast<std::remove_reference_t<decltype(cppValue)>>(chip::JniReferences::GetInstance().IntegerToPrimitive(value));
+
+ std::unique_ptr<CHIPDefaultSuccessCallback, void (*)(CHIPDefaultSuccessCallback *)> onSuccess(
+ Platform::New<CHIPDefaultSuccessCallback>(callback), Platform::Delete<CHIPDefaultSuccessCallback>);
+ VerifyOrReturn(onSuccess.get() != nullptr,
+ chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(
+ env, callback, "Error creating native success callback", CHIP_ERROR_NO_MEMORY));
+
+ std::unique_ptr<CHIPDefaultFailureCallback, void (*)(CHIPDefaultFailureCallback *)> onFailure(
+ Platform::New<CHIPDefaultFailureCallback>(callback), Platform::Delete<CHIPDefaultFailureCallback>);
+ VerifyOrReturn(onFailure.get() != nullptr,
+ chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(
+ env, callback, "Error creating native failure callback", CHIP_ERROR_NO_MEMORY));
+
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ FanControlCluster * cppCluster = reinterpret_cast<FanControlCluster *>(clusterPtr);
+ VerifyOrReturn(cppCluster != nullptr,
+ chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(
+ env, callback, "Could not get native cluster", CHIP_ERROR_INCORRECT_STATE));
+
+ auto successFn = chip::Callback::Callback<CHIPDefaultWriteSuccessCallbackType>::FromCancelable(onSuccess->Cancel());
+ auto failureFn = chip::Callback::Callback<CHIPDefaultFailureCallbackType>::FromCancelable(onFailure->Cancel());
+
+ if (timedWriteTimeoutMs == nullptr)
+ {
+ err = cppCluster->WriteAttribute<TypeInfo>(cppValue, onSuccess->mContext, successFn->mCall, failureFn->mCall);
+ }
+ else
+ {
+ err = cppCluster->WriteAttribute<TypeInfo>(cppValue, onSuccess->mContext, successFn->mCall, failureFn->mCall,
+ chip::JniReferences::GetInstance().IntegerToPrimitive(timedWriteTimeoutMs));
+ }
+ VerifyOrReturn(
+ err == CHIP_NO_ERROR,
+ chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error writing attribute", err));
+
+ onSuccess.release();
+ onFailure.release();
+}
+
JNI_METHOD(void, ThermostatUserInterfaceConfigurationCluster, writeTemperatureDisplayModeAttribute)
(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jobject value, jobject timedWriteTimeoutMs)
{
diff --git a/src/controller/java/zap-generated/chip/devicecontroller/ChipClusters.java b/src/controller/java/zap-generated/chip/devicecontroller/ChipClusters.java
index afc88c2..d689415 100644
--- a/src/controller/java/zap-generated/chip/devicecontroller/ChipClusters.java
+++ b/src/controller/java/zap-generated/chip/devicecontroller/ChipClusters.java
@@ -22720,6 +22720,24 @@
subscribeWindSettingAttribute(chipClusterPtr, callback, minInterval, maxInterval);
}
+ public void readAirflowDirectionAttribute(IntegerAttributeCallback callback) {
+ readAirflowDirectionAttribute(chipClusterPtr, callback);
+ }
+
+ public void writeAirflowDirectionAttribute(DefaultClusterCallback callback, Integer value) {
+ writeAirflowDirectionAttribute(chipClusterPtr, callback, value, null);
+ }
+
+ public void writeAirflowDirectionAttribute(
+ DefaultClusterCallback callback, Integer value, int timedWriteTimeoutMs) {
+ writeAirflowDirectionAttribute(chipClusterPtr, callback, value, timedWriteTimeoutMs);
+ }
+
+ public void subscribeAirflowDirectionAttribute(
+ IntegerAttributeCallback callback, int minInterval, int maxInterval) {
+ subscribeAirflowDirectionAttribute(chipClusterPtr, callback, minInterval, maxInterval);
+ }
+
public void readGeneratedCommandListAttribute(GeneratedCommandListAttributeCallback callback) {
readGeneratedCommandListAttribute(chipClusterPtr, callback);
}
@@ -22882,6 +22900,18 @@
private native void subscribeWindSettingAttribute(
long chipClusterPtr, IntegerAttributeCallback callback, int minInterval, int maxInterval);
+ private native void readAirflowDirectionAttribute(
+ long chipClusterPtr, IntegerAttributeCallback callback);
+
+ private native void writeAirflowDirectionAttribute(
+ long chipClusterPtr,
+ DefaultClusterCallback callback,
+ Integer value,
+ @Nullable Integer timedWriteTimeoutMs);
+
+ private native void subscribeAirflowDirectionAttribute(
+ long chipClusterPtr, IntegerAttributeCallback callback, int minInterval, int maxInterval);
+
private native void readGeneratedCommandListAttribute(
long chipClusterPtr, GeneratedCommandListAttributeCallback callback);
diff --git a/src/controller/java/zap-generated/chip/devicecontroller/ChipIdLookup.java b/src/controller/java/zap-generated/chip/devicecontroller/ChipIdLookup.java
index f0281a9..7698da8 100644
--- a/src/controller/java/zap-generated/chip/devicecontroller/ChipIdLookup.java
+++ b/src/controller/java/zap-generated/chip/devicecontroller/ChipIdLookup.java
@@ -3297,6 +3297,9 @@
if (attributeId == 10L) {
return "WindSetting";
}
+ if (attributeId == 11L) {
+ return "AirflowDirection";
+ }
if (attributeId == 65528L) {
return "GeneratedCommandList";
}
diff --git a/src/controller/python/chip/clusters/CHIPClusters.py b/src/controller/python/chip/clusters/CHIPClusters.py
index 245a048..06c2590 100644
--- a/src/controller/python/chip/clusters/CHIPClusters.py
+++ b/src/controller/python/chip/clusters/CHIPClusters.py
@@ -7054,6 +7054,15 @@
"clusterName": "FanControl",
"clusterId": 0x00000202,
"commands": {
+ 0x00000000: {
+ "commandId": 0x00000000,
+ "commandName": "Step",
+ "args": {
+ "direction": "int",
+ "wrap": "bool",
+ "lowestOff": "bool",
+ },
+ },
},
"attributes": {
0x00000000: {
@@ -7128,6 +7137,13 @@
"reportable": True,
"writable": True,
},
+ 0x0000000B: {
+ "attributeName": "AirflowDirection",
+ "attributeId": 0x0000000B,
+ "type": "int",
+ "reportable": True,
+ "writable": True,
+ },
0x0000FFF8: {
"attributeName": "GeneratedCommandList",
"attributeId": 0x0000FFF8,
diff --git a/src/controller/python/chip/clusters/Objects.py b/src/controller/python/chip/clusters/Objects.py
index 0afd782..ae4d95e 100644
--- a/src/controller/python/chip/clusters/Objects.py
+++ b/src/controller/python/chip/clusters/Objects.py
@@ -24539,6 +24539,7 @@
ClusterObjectFieldDescriptor(Label="rockSetting", Tag=0x00000008, Type=typing.Optional[uint]),
ClusterObjectFieldDescriptor(Label="windSupport", Tag=0x00000009, Type=typing.Optional[uint]),
ClusterObjectFieldDescriptor(Label="windSetting", Tag=0x0000000A, Type=typing.Optional[uint]),
+ ClusterObjectFieldDescriptor(Label="airflowDirection", Tag=0x0000000B, Type=typing.Optional[FanControl.Enums.AirflowDirectionEnum]),
ClusterObjectFieldDescriptor(Label="generatedCommandList", Tag=0x0000FFF8, Type=typing.List[uint]),
ClusterObjectFieldDescriptor(Label="acceptedCommandList", Tag=0x0000FFF9, Type=typing.List[uint]),
ClusterObjectFieldDescriptor(Label="eventList", Tag=0x0000FFFA, Type=typing.List[uint]),
@@ -24558,6 +24559,7 @@
rockSetting: 'typing.Optional[uint]' = None
windSupport: 'typing.Optional[uint]' = None
windSetting: 'typing.Optional[uint]' = None
+ airflowDirection: 'typing.Optional[FanControl.Enums.AirflowDirectionEnum]' = None
generatedCommandList: 'typing.List[uint]' = None
acceptedCommandList: 'typing.List[uint]' = None
eventList: 'typing.List[uint]' = None
@@ -24566,6 +24568,24 @@
clusterRevision: 'uint' = None
class Enums:
+ class AirflowDirectionEnum(MatterIntEnum):
+ kForward = 0x00
+ kReverse = 0x01
+ # All received enum values that are not listed above will be mapped
+ # to kUnknownEnumValue. This is a helper enum value that should only
+ # be used by code to process how it handles receiving and unknown
+ # enum value. This specific should never be transmitted.
+ kUnknownEnumValue = 2,
+
+ class DirectionEnum(MatterIntEnum):
+ kIncrease = 0x00
+ kDecrease = 0x01
+ # All received enum values that are not listed above will be mapped
+ # to kUnknownEnumValue. This is a helper enum value that should only
+ # be used by code to process how it handles receiving and unknown
+ # enum value. This specific should never be transmitted.
+ kUnknownEnumValue = 2,
+
class FanModeSequenceType(MatterIntEnum):
kOffLowMedHigh = 0x00
kOffLowHigh = 0x01
@@ -24599,6 +24619,8 @@
kAuto = 0x2
kRocking = 0x4
kWind = 0x8
+ kStep = 0x10
+ kAirflowDirection = 0x20
class RockSupportMask(IntFlag):
kRockLeftRight = 0x1
@@ -24613,6 +24635,27 @@
kSleepWind = 0x1
kNaturalWind = 0x2
+ class Commands:
+ @dataclass
+ class Step(ClusterCommand):
+ cluster_id: typing.ClassVar[int] = 0x0202
+ command_id: typing.ClassVar[int] = 0x00000000
+ is_client: typing.ClassVar[bool] = True
+ response_type: typing.ClassVar[str] = None
+
+ @ChipUtility.classproperty
+ def descriptor(cls) -> ClusterObjectDescriptor:
+ return ClusterObjectDescriptor(
+ Fields=[
+ ClusterObjectFieldDescriptor(Label="direction", Tag=0, Type=FanControl.Enums.DirectionEnum),
+ ClusterObjectFieldDescriptor(Label="wrap", Tag=1, Type=typing.Optional[bool]),
+ ClusterObjectFieldDescriptor(Label="lowestOff", Tag=2, Type=typing.Optional[bool]),
+ ])
+
+ direction: 'FanControl.Enums.DirectionEnum' = 0
+ wrap: 'typing.Optional[bool]' = None
+ lowestOff: 'typing.Optional[bool]' = None
+
class Attributes:
@dataclass
class FanMode(ClusterAttributeDescriptor):
@@ -24791,6 +24834,22 @@
value: 'typing.Optional[uint]' = None
@dataclass
+ class AirflowDirection(ClusterAttributeDescriptor):
+ @ChipUtility.classproperty
+ def cluster_id(cls) -> int:
+ return 0x0202
+
+ @ChipUtility.classproperty
+ def attribute_id(cls) -> int:
+ return 0x0000000B
+
+ @ChipUtility.classproperty
+ def attribute_type(cls) -> ClusterObjectFieldDescriptor:
+ return ClusterObjectFieldDescriptor(Type=typing.Optional[FanControl.Enums.AirflowDirectionEnum])
+
+ value: 'typing.Optional[FanControl.Enums.AirflowDirectionEnum]' = None
+
+ @dataclass
class GeneratedCommandList(ClusterAttributeDescriptor):
@ChipUtility.classproperty
def cluster_id(cls) -> int:
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm
index 5dda77c..4e92c0b 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm
@@ -3081,6 +3081,9 @@
case Attributes::WindSetting::Id: {
return YES;
}
+ case Attributes::AirflowDirection::Id: {
+ return YES;
+ }
case Attributes::GeneratedCommandList::Id: {
return YES;
}
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm
index e65888c..9d6b660 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm
@@ -15082,6 +15082,17 @@
value = [NSNumber numberWithUnsignedChar:cppValue];
return value;
}
+ case Attributes::AirflowDirection::Id: {
+ using TypeInfo = Attributes::AirflowDirection::TypeInfo;
+ TypeInfo::DecodableType cppValue;
+ *aError = DataModel::Decode(aReader, cppValue);
+ if (*aError != CHIP_NO_ERROR) {
+ return nil;
+ }
+ NSNumber * _Nonnull value;
+ value = [NSNumber numberWithUnsignedChar:chip::to_underlying(cppValue)];
+ return value;
+ }
case Attributes::GeneratedCommandList::Id: {
using TypeInfo = Attributes::GeneratedCommandList::TypeInfo;
TypeInfo::DecodableType cppValue;
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h
index 204bbf8..a215e2e 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h
@@ -13584,6 +13584,13 @@
queue:(dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER
API_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4));
+/**
+ * Command Step
+ *
+ * The Step command speeds up or slows down the fan, in steps.
+ */
+- (void)stepWithParams:(MTRFanControlClusterStepParams *)params completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE;
+
- (void)readAttributeFanModeWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion
API_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4));
- (void)writeAttributeFanModeWithValue:(NSNumber * _Nonnull)value
@@ -13759,6 +13766,23 @@
completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion
API_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4));
+- (void)readAttributeAirflowDirectionWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion
+ MTR_NEWLY_AVAILABLE;
+- (void)writeAttributeAirflowDirectionWithValue:(NSNumber * _Nonnull)value
+ completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE;
+- (void)writeAttributeAirflowDirectionWithValue:(NSNumber * _Nonnull)value
+ params:(MTRWriteParams * _Nullable)params
+ completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE;
+- (void)subscribeAttributeAirflowDirectionWithParams:(MTRSubscribeParams *)params
+ subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished
+ reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler
+ MTR_NEWLY_AVAILABLE;
++ (void)readAttributeAirflowDirectionWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer
+ endpoint:(NSNumber *)endpoint
+ queue:(dispatch_queue_t)queue
+ completion:(void (^)(NSNumber * _Nullable value,
+ NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE;
+
- (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion
API_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4));
- (void)subscribeAttributeGeneratedCommandListWithParams:(MTRSubscribeParams *)params
@@ -32847,6 +32871,16 @@
= 0x2,
} API_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1));
+typedef NS_ENUM(uint8_t, MTRFanControlAirflowDirection) {
+ MTRFanControlAirflowDirectionForward MTR_NEWLY_AVAILABLE = 0x00,
+ MTRFanControlAirflowDirectionReverse MTR_NEWLY_AVAILABLE = 0x01,
+} MTR_NEWLY_AVAILABLE;
+
+typedef NS_ENUM(uint8_t, MTRFanControlDirection) {
+ MTRFanControlDirectionIncrease MTR_NEWLY_AVAILABLE = 0x00,
+ MTRFanControlDirectionDecrease MTR_NEWLY_AVAILABLE = 0x01,
+} MTR_NEWLY_AVAILABLE;
+
typedef NS_ENUM(uint8_t, MTRFanControlFanModeSequenceType) {
MTRFanControlFanModeSequenceTypeOffLowMedHigh API_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) = 0x00,
MTRFanControlFanModeSequenceTypeOffLowHigh API_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) = 0x01,
@@ -32871,6 +32905,8 @@
MTRFanControlFeatureAuto API_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) = 0x2,
MTRFanControlFeatureRocking API_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) = 0x4,
MTRFanControlFeatureWind API_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) = 0x8,
+ MTRFanControlFeatureStep MTR_NEWLY_AVAILABLE = 0x10,
+ MTRFanControlFeatureAirflowDirection MTR_NEWLY_AVAILABLE = 0x20,
} API_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1));
typedef NS_OPTIONS(uint8_t, MTRFanControlRockSupportMask) {
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm
index b9045be..62d1149 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm
@@ -76146,6 +76146,51 @@
return self;
}
+- (void)stepWithParams:(MTRFanControlClusterStepParams *)params completion:(MTRStatusCompletion)completion
+{
+ // Make a copy of params before we go async.
+ params = [params copy];
+ auto * bridge = new MTRCommandSuccessCallbackBridge(
+ self.callbackQueue,
+ ^(id _Nullable value, NSError * _Nullable error) {
+ completion(error);
+ },
+ ^(ExchangeManager & exchangeManager, const SessionHandle & session, CommandSuccessCallbackType successCb,
+ MTRErrorCallback failureCb, MTRCallbackBridgeBase * bridge) {
+ auto * typedBridge = static_cast<MTRCommandSuccessCallbackBridge *>(bridge);
+ Optional<uint16_t> timedInvokeTimeoutMs;
+ Optional<Timeout> invokeTimeout;
+ ListFreer listFreer;
+ FanControl::Commands::Step::Type request;
+ if (params != nil) {
+ if (params.timedInvokeTimeoutMs != nil) {
+ params.timedInvokeTimeoutMs = MTRClampedNumber(params.timedInvokeTimeoutMs, @(1), @(UINT16_MAX));
+ timedInvokeTimeoutMs.SetValue(params.timedInvokeTimeoutMs.unsignedShortValue);
+ }
+ if (params.serverSideProcessingTimeout != nil) {
+ // Clamp to a number of seconds that will not overflow 32-bit
+ // int when converted to ms.
+ auto * serverSideProcessingTimeout = MTRClampedNumber(params.serverSideProcessingTimeout, @(0), @(UINT16_MAX));
+ invokeTimeout.SetValue(Seconds16(serverSideProcessingTimeout.unsignedShortValue));
+ }
+ }
+ request.direction
+ = static_cast<std::remove_reference_t<decltype(request.direction)>>(params.direction.unsignedCharValue);
+ if (params.wrap != nil) {
+ auto & definedValue_0 = request.wrap.Emplace();
+ definedValue_0 = params.wrap.boolValue;
+ }
+ if (params.lowestOff != nil) {
+ auto & definedValue_0 = request.lowestOff.Emplace();
+ definedValue_0 = params.lowestOff.boolValue;
+ }
+
+ return MTRStartInvokeInteraction(typedBridge, request, exchangeManager, session, successCb, failureCb, self->_endpoint,
+ timedInvokeTimeoutMs, invokeTimeout);
+ });
+ std::move(*bridge).DispatchAction(self.device);
+}
+
- (void)readAttributeFanModeWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion
{
MTRReadParams * params = [[MTRReadParams alloc] init];
@@ -76852,6 +76897,87 @@
});
}
+- (void)readAttributeAirflowDirectionWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion
+{
+ MTRReadParams * params = [[MTRReadParams alloc] init];
+ using TypeInfo = FanControl::Attributes::AirflowDirection::TypeInfo;
+ return MTRReadAttribute<MTRFanControlClusterAirflowDirectionEnumAttributeCallbackBridge, NSNumber, TypeInfo::DecodableType>(
+ params, completion, self.callbackQueue, self.device, self->_endpoint, TypeInfo::GetClusterId(), TypeInfo::GetAttributeId());
+}
+
+- (void)writeAttributeAirflowDirectionWithValue:(NSNumber * _Nonnull)value completion:(MTRStatusCompletion)completion
+{
+ [self writeAttributeAirflowDirectionWithValue:(NSNumber * _Nonnull) value params:nil completion:completion];
+}
+- (void)writeAttributeAirflowDirectionWithValue:(NSNumber * _Nonnull)value
+ params:(MTRWriteParams * _Nullable)params
+ completion:(MTRStatusCompletion)completion
+{
+ // Make a copy of params before we go async.
+ params = [params copy];
+ value = [value copy];
+
+ auto * bridge = new MTRDefaultSuccessCallbackBridge(
+ self.callbackQueue,
+ ^(id _Nullable ignored, NSError * _Nullable error) {
+ completion(error);
+ },
+ ^(ExchangeManager & exchangeManager, const SessionHandle & session, DefaultSuccessCallbackType successCb,
+ MTRErrorCallback failureCb, MTRCallbackBridgeBase * bridge) {
+ chip::Optional<uint16_t> timedWriteTimeout;
+ if (params != nil) {
+ if (params.timedWriteTimeout != nil) {
+ timedWriteTimeout.SetValue(params.timedWriteTimeout.unsignedShortValue);
+ }
+ }
+
+ ListFreer listFreer;
+ using TypeInfo = FanControl::Attributes::AirflowDirection::TypeInfo;
+ TypeInfo::Type cppValue;
+ cppValue = static_cast<std::remove_reference_t<decltype(cppValue)>>(value.unsignedCharValue);
+
+ chip::Controller::ClusterBase cppCluster(exchangeManager, session, self->_endpoint);
+ return cppCluster.WriteAttribute<TypeInfo>(cppValue, bridge, successCb, failureCb, timedWriteTimeout);
+ });
+ std::move(*bridge).DispatchAction(self.device);
+}
+
+- (void)subscribeAttributeAirflowDirectionWithParams:(MTRSubscribeParams * _Nonnull)params
+ subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished
+ reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler
+{
+ using TypeInfo = FanControl::Attributes::AirflowDirection::TypeInfo;
+ MTRSubscribeAttribute<MTRFanControlClusterAirflowDirectionEnumAttributeCallbackSubscriptionBridge, NSNumber,
+ TypeInfo::DecodableType>(params, subscriptionEstablished, reportHandler, self.callbackQueue, self.device, self->_endpoint,
+ TypeInfo::GetClusterId(), TypeInfo::GetAttributeId());
+}
+
++ (void)readAttributeAirflowDirectionWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer
+ endpoint:(NSNumber *)endpoint
+ queue:(dispatch_queue_t)queue
+ completion:
+ (void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion
+{
+ auto * bridge = new MTRFanControlClusterAirflowDirectionEnumAttributeCallbackBridge(queue, completion);
+ std::move(*bridge).DispatchLocalAction(clusterStateCacheContainer.baseDevice,
+ ^(FanControlClusterAirflowDirectionEnumAttributeCallback successCb, MTRErrorCallback failureCb) {
+ if (clusterStateCacheContainer.cppClusterStateCache) {
+ chip::app::ConcreteAttributePath path;
+ using TypeInfo = FanControl::Attributes::AirflowDirection::TypeInfo;
+ path.mEndpointId = static_cast<chip::EndpointId>([endpoint unsignedShortValue]);
+ path.mClusterId = TypeInfo::GetClusterId();
+ path.mAttributeId = TypeInfo::GetAttributeId();
+ TypeInfo::DecodableType value;
+ CHIP_ERROR err = clusterStateCacheContainer.cppClusterStateCache->Get<TypeInfo>(path, value);
+ if (err == CHIP_NO_ERROR) {
+ successCb(bridge, value);
+ }
+ return err;
+ }
+ return CHIP_ERROR_NOT_FOUND;
+ });
+}
+
- (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion
{
MTRReadParams * params = [[MTRReadParams alloc] init];
@@ -77119,6 +77245,11 @@
@implementation MTRBaseClusterFanControl (Deprecated)
+- (void)stepWithParams:(MTRFanControlClusterStepParams *)params completionHandler:(MTRStatusCompletion)completionHandler
+{
+ [self stepWithParams:params completion:completionHandler];
+}
+
- (void)readAttributeFanModeWithCompletionHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completionHandler
{
[self readAttributeFanModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCallbackBridge.h b/src/darwin/Framework/CHIP/zap-generated/MTRCallbackBridge.h
index c9022d3..b294998 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRCallbackBridge.h
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRCallbackBridge.h
@@ -595,6 +595,13 @@
chip::app::Clusters::Thermostat::ThermostatSystemMode);
typedef void (*NullableThermostatClusterThermostatSystemModeAttributeCallback)(
void *, const chip::app::DataModel::Nullable<chip::app::Clusters::Thermostat::ThermostatSystemMode> &);
+typedef void (*FanControlClusterAirflowDirectionEnumAttributeCallback)(void *,
+ chip::app::Clusters::FanControl::AirflowDirectionEnum);
+typedef void (*NullableFanControlClusterAirflowDirectionEnumAttributeCallback)(
+ void *, const chip::app::DataModel::Nullable<chip::app::Clusters::FanControl::AirflowDirectionEnum> &);
+typedef void (*FanControlClusterDirectionEnumAttributeCallback)(void *, chip::app::Clusters::FanControl::DirectionEnum);
+typedef void (*NullableFanControlClusterDirectionEnumAttributeCallback)(
+ void *, const chip::app::DataModel::Nullable<chip::app::Clusters::FanControl::DirectionEnum> &);
typedef void (*FanControlClusterFanModeSequenceTypeAttributeCallback)(void *, chip::app::Clusters::FanControl::FanModeSequenceType);
typedef void (*NullableFanControlClusterFanModeSequenceTypeAttributeCallback)(
void *, const chip::app::DataModel::Nullable<chip::app::Clusters::FanControl::FanModeSequenceType> &);
@@ -31597,6 +31604,140 @@
MTRSubscriptionEstablishedHandler mEstablishedHandler;
};
+class MTRFanControlClusterAirflowDirectionEnumAttributeCallbackBridge
+ : public MTRCallbackBridge<FanControlClusterAirflowDirectionEnumAttributeCallback>
+{
+public:
+ MTRFanControlClusterAirflowDirectionEnumAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler) :
+ MTRCallbackBridge<FanControlClusterAirflowDirectionEnumAttributeCallback>(queue, handler, OnSuccessFn){};
+
+ MTRFanControlClusterAirflowDirectionEnumAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler,
+ MTRActionBlock action) :
+ MTRCallbackBridge<FanControlClusterAirflowDirectionEnumAttributeCallback>(queue, handler, action, OnSuccessFn){};
+
+ static void OnSuccessFn(void * context, chip::app::Clusters::FanControl::AirflowDirectionEnum value);
+};
+
+class MTRFanControlClusterAirflowDirectionEnumAttributeCallbackSubscriptionBridge
+ : public MTRFanControlClusterAirflowDirectionEnumAttributeCallbackBridge
+{
+public:
+ MTRFanControlClusterAirflowDirectionEnumAttributeCallbackSubscriptionBridge(
+ dispatch_queue_t queue, ResponseHandler handler, MTRActionBlock action,
+ MTRSubscriptionEstablishedHandler establishedHandler) :
+ MTRFanControlClusterAirflowDirectionEnumAttributeCallbackBridge(queue, handler, action),
+ mEstablishedHandler(establishedHandler)
+ {}
+
+ void OnSubscriptionEstablished();
+ using MTRFanControlClusterAirflowDirectionEnumAttributeCallbackBridge::KeepAliveOnCallback;
+ using MTRFanControlClusterAirflowDirectionEnumAttributeCallbackBridge::OnDone;
+
+private:
+ MTRSubscriptionEstablishedHandler mEstablishedHandler;
+};
+
+class MTRNullableFanControlClusterAirflowDirectionEnumAttributeCallbackBridge
+ : public MTRCallbackBridge<NullableFanControlClusterAirflowDirectionEnumAttributeCallback>
+{
+public:
+ MTRNullableFanControlClusterAirflowDirectionEnumAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler) :
+ MTRCallbackBridge<NullableFanControlClusterAirflowDirectionEnumAttributeCallback>(queue, handler, OnSuccessFn){};
+
+ MTRNullableFanControlClusterAirflowDirectionEnumAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler,
+ MTRActionBlock action) :
+ MTRCallbackBridge<NullableFanControlClusterAirflowDirectionEnumAttributeCallback>(queue, handler, action, OnSuccessFn){};
+
+ static void OnSuccessFn(void * context,
+ const chip::app::DataModel::Nullable<chip::app::Clusters::FanControl::AirflowDirectionEnum> & value);
+};
+
+class MTRNullableFanControlClusterAirflowDirectionEnumAttributeCallbackSubscriptionBridge
+ : public MTRNullableFanControlClusterAirflowDirectionEnumAttributeCallbackBridge
+{
+public:
+ MTRNullableFanControlClusterAirflowDirectionEnumAttributeCallbackSubscriptionBridge(
+ dispatch_queue_t queue, ResponseHandler handler, MTRActionBlock action,
+ MTRSubscriptionEstablishedHandler establishedHandler) :
+ MTRNullableFanControlClusterAirflowDirectionEnumAttributeCallbackBridge(queue, handler, action),
+ mEstablishedHandler(establishedHandler)
+ {}
+
+ void OnSubscriptionEstablished();
+ using MTRNullableFanControlClusterAirflowDirectionEnumAttributeCallbackBridge::KeepAliveOnCallback;
+ using MTRNullableFanControlClusterAirflowDirectionEnumAttributeCallbackBridge::OnDone;
+
+private:
+ MTRSubscriptionEstablishedHandler mEstablishedHandler;
+};
+
+class MTRFanControlClusterDirectionEnumAttributeCallbackBridge
+ : public MTRCallbackBridge<FanControlClusterDirectionEnumAttributeCallback>
+{
+public:
+ MTRFanControlClusterDirectionEnumAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler) :
+ MTRCallbackBridge<FanControlClusterDirectionEnumAttributeCallback>(queue, handler, OnSuccessFn){};
+
+ MTRFanControlClusterDirectionEnumAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler,
+ MTRActionBlock action) :
+ MTRCallbackBridge<FanControlClusterDirectionEnumAttributeCallback>(queue, handler, action, OnSuccessFn){};
+
+ static void OnSuccessFn(void * context, chip::app::Clusters::FanControl::DirectionEnum value);
+};
+
+class MTRFanControlClusterDirectionEnumAttributeCallbackSubscriptionBridge
+ : public MTRFanControlClusterDirectionEnumAttributeCallbackBridge
+{
+public:
+ MTRFanControlClusterDirectionEnumAttributeCallbackSubscriptionBridge(dispatch_queue_t queue, ResponseHandler handler,
+ MTRActionBlock action,
+ MTRSubscriptionEstablishedHandler establishedHandler) :
+ MTRFanControlClusterDirectionEnumAttributeCallbackBridge(queue, handler, action),
+ mEstablishedHandler(establishedHandler)
+ {}
+
+ void OnSubscriptionEstablished();
+ using MTRFanControlClusterDirectionEnumAttributeCallbackBridge::KeepAliveOnCallback;
+ using MTRFanControlClusterDirectionEnumAttributeCallbackBridge::OnDone;
+
+private:
+ MTRSubscriptionEstablishedHandler mEstablishedHandler;
+};
+
+class MTRNullableFanControlClusterDirectionEnumAttributeCallbackBridge
+ : public MTRCallbackBridge<NullableFanControlClusterDirectionEnumAttributeCallback>
+{
+public:
+ MTRNullableFanControlClusterDirectionEnumAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler) :
+ MTRCallbackBridge<NullableFanControlClusterDirectionEnumAttributeCallback>(queue, handler, OnSuccessFn){};
+
+ MTRNullableFanControlClusterDirectionEnumAttributeCallbackBridge(dispatch_queue_t queue, ResponseHandler handler,
+ MTRActionBlock action) :
+ MTRCallbackBridge<NullableFanControlClusterDirectionEnumAttributeCallback>(queue, handler, action, OnSuccessFn){};
+
+ static void OnSuccessFn(void * context,
+ const chip::app::DataModel::Nullable<chip::app::Clusters::FanControl::DirectionEnum> & value);
+};
+
+class MTRNullableFanControlClusterDirectionEnumAttributeCallbackSubscriptionBridge
+ : public MTRNullableFanControlClusterDirectionEnumAttributeCallbackBridge
+{
+public:
+ MTRNullableFanControlClusterDirectionEnumAttributeCallbackSubscriptionBridge(
+ dispatch_queue_t queue, ResponseHandler handler, MTRActionBlock action,
+ MTRSubscriptionEstablishedHandler establishedHandler) :
+ MTRNullableFanControlClusterDirectionEnumAttributeCallbackBridge(queue, handler, action),
+ mEstablishedHandler(establishedHandler)
+ {}
+
+ void OnSubscriptionEstablished();
+ using MTRNullableFanControlClusterDirectionEnumAttributeCallbackBridge::KeepAliveOnCallback;
+ using MTRNullableFanControlClusterDirectionEnumAttributeCallbackBridge::OnDone;
+
+private:
+ MTRSubscriptionEstablishedHandler mEstablishedHandler;
+};
+
class MTRFanControlClusterFanModeSequenceTypeAttributeCallbackBridge
: public MTRCallbackBridge<FanControlClusterFanModeSequenceTypeAttributeCallback>
{
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCallbackBridge.mm b/src/darwin/Framework/CHIP/zap-generated/MTRCallbackBridge.mm
index 1ab0b6f..fa6adc0 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRCallbackBridge.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRCallbackBridge.mm
@@ -29505,6 +29505,106 @@
}
}
+void MTRFanControlClusterAirflowDirectionEnumAttributeCallbackBridge::OnSuccessFn(
+ void * context, chip::app::Clusters::FanControl::AirflowDirectionEnum value)
+{
+ NSNumber * _Nonnull objCValue;
+ objCValue = [NSNumber numberWithUnsignedChar:chip::to_underlying(value)];
+ DispatchSuccess(context, objCValue);
+};
+
+void MTRFanControlClusterAirflowDirectionEnumAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished()
+{
+ if (!mQueue) {
+ return;
+ }
+
+ if (mEstablishedHandler != nil) {
+ dispatch_async(mQueue, mEstablishedHandler);
+ // On failure, mEstablishedHandler will be cleaned up by our destructor,
+ // but we can clean it up earlier on successful subscription
+ // establishment.
+ mEstablishedHandler = nil;
+ }
+}
+
+void MTRNullableFanControlClusterAirflowDirectionEnumAttributeCallbackBridge::OnSuccessFn(
+ void * context, const chip::app::DataModel::Nullable<chip::app::Clusters::FanControl::AirflowDirectionEnum> & value)
+{
+ NSNumber * _Nullable objCValue;
+ if (value.IsNull()) {
+ objCValue = nil;
+ } else {
+ objCValue = [NSNumber numberWithUnsignedChar:chip::to_underlying(value.Value())];
+ }
+ DispatchSuccess(context, objCValue);
+};
+
+void MTRNullableFanControlClusterAirflowDirectionEnumAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished()
+{
+ if (!mQueue) {
+ return;
+ }
+
+ if (mEstablishedHandler != nil) {
+ dispatch_async(mQueue, mEstablishedHandler);
+ // On failure, mEstablishedHandler will be cleaned up by our destructor,
+ // but we can clean it up earlier on successful subscription
+ // establishment.
+ mEstablishedHandler = nil;
+ }
+}
+
+void MTRFanControlClusterDirectionEnumAttributeCallbackBridge::OnSuccessFn(
+ void * context, chip::app::Clusters::FanControl::DirectionEnum value)
+{
+ NSNumber * _Nonnull objCValue;
+ objCValue = [NSNumber numberWithUnsignedChar:chip::to_underlying(value)];
+ DispatchSuccess(context, objCValue);
+};
+
+void MTRFanControlClusterDirectionEnumAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished()
+{
+ if (!mQueue) {
+ return;
+ }
+
+ if (mEstablishedHandler != nil) {
+ dispatch_async(mQueue, mEstablishedHandler);
+ // On failure, mEstablishedHandler will be cleaned up by our destructor,
+ // but we can clean it up earlier on successful subscription
+ // establishment.
+ mEstablishedHandler = nil;
+ }
+}
+
+void MTRNullableFanControlClusterDirectionEnumAttributeCallbackBridge::OnSuccessFn(
+ void * context, const chip::app::DataModel::Nullable<chip::app::Clusters::FanControl::DirectionEnum> & value)
+{
+ NSNumber * _Nullable objCValue;
+ if (value.IsNull()) {
+ objCValue = nil;
+ } else {
+ objCValue = [NSNumber numberWithUnsignedChar:chip::to_underlying(value.Value())];
+ }
+ DispatchSuccess(context, objCValue);
+};
+
+void MTRNullableFanControlClusterDirectionEnumAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished()
+{
+ if (!mQueue) {
+ return;
+ }
+
+ if (mEstablishedHandler != nil) {
+ dispatch_async(mQueue, mEstablishedHandler);
+ // On failure, mEstablishedHandler will be cleaned up by our destructor,
+ // but we can clean it up earlier on successful subscription
+ // establishment.
+ mEstablishedHandler = nil;
+ }
+}
+
void MTRFanControlClusterFanModeSequenceTypeAttributeCallbackBridge::OnSuccessFn(
void * context, chip::app::Clusters::FanControl::FanModeSequenceType value)
{
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h
index 60ef563..aa7ddfa 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h
@@ -5273,6 +5273,7 @@
= 0x00000009,
MTRAttributeIDTypeClusterFanControlAttributeWindSettingID API_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4))
= 0x0000000A,
+ MTRAttributeIDTypeClusterFanControlAttributeAirflowDirectionID MTR_NEWLY_AVAILABLE = 0x0000000B,
MTRAttributeIDTypeClusterFanControlAttributeGeneratedCommandListID API_AVAILABLE(
ios(16.4), macos(13.3), watchos(9.4), tvos(16.4))
= MTRAttributeIDTypeGlobalAttributeGeneratedCommandListID,
@@ -10474,6 +10475,11 @@
MTRCommandIDTypeClusterThermostatCommandClearWeeklyScheduleID API_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4))
= 0x00000003,
+ // Cluster FanControl deprecated command id names
+
+ // Cluster FanControl commands
+ MTRCommandIDTypeClusterFanControlCommandStepID MTR_NEWLY_AVAILABLE = 0x00000000,
+
// Cluster ColorControl deprecated command id names
MTRClusterColorControlCommandMoveToHueID MTR_DEPRECATED("Please use MTRCommandIDTypeClusterColorControlCommandMoveToHueID",
ios(16.1, 16.4), macos(13.0, 13.3), watchos(9.1, 9.4), tvos(16.1, 16.4))
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h
index f5a0b6a..277d4d1 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h
@@ -4761,6 +4761,11 @@
queue:(dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER
API_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4));
+- (void)stepWithParams:(MTRFanControlClusterStepParams *)params
+ expectedValues:(NSArray<NSDictionary<NSString *, id> *> * _Nullable)expectedDataValueDictionaries
+ expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs
+ completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE;
+
- (NSDictionary<NSString *, id> *)readAttributeFanModeWithParams:(MTRReadParams * _Nullable)params
API_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1));
- (void)writeAttributeFanModeWithValue:(NSDictionary<NSString *, id> *)dataValueDictionary
@@ -4836,6 +4841,13 @@
params:(MTRWriteParams * _Nullable)params
API_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1));
+- (NSDictionary<NSString *, id> *)readAttributeAirflowDirectionWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE;
+- (void)writeAttributeAirflowDirectionWithValue:(NSDictionary<NSString *, id> *)dataValueDictionary
+ expectedValueInterval:(NSNumber *)expectedValueIntervalMs MTR_NEWLY_AVAILABLE;
+- (void)writeAttributeAirflowDirectionWithValue:(NSDictionary<NSString *, id> *)dataValueDictionary
+ expectedValueInterval:(NSNumber *)expectedValueIntervalMs
+ params:(MTRWriteParams * _Nullable)params MTR_NEWLY_AVAILABLE;
+
- (NSDictionary<NSString *, id> *)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params
API_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1));
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm
index c20c801..37861d9 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm
@@ -21555,6 +21555,83 @@
return self;
}
+- (void)stepWithParams:(MTRFanControlClusterStepParams *)params
+ expectedValues:(NSArray<NSDictionary<NSString *, id> *> *)expectedValues
+ expectedValueInterval:(NSNumber *)expectedValueIntervalMs
+ completion:(MTRStatusCompletion)completion
+{
+ NSString * logPrefix =
+ [NSString stringWithFormat:@"MTRDevice command %u %u %u %u", self.device.deviceController.fabricIndex, _endpoint,
+ (unsigned int) MTRClusterIDTypeFanControlID, (unsigned int) MTRCommandIDTypeClusterFanControlCommandStepID];
+ // Make a copy of params before we go async.
+ params = [params copy];
+ NSNumber * timedInvokeTimeoutMsParam = params.timedInvokeTimeoutMs;
+ if (timedInvokeTimeoutMsParam) {
+ timedInvokeTimeoutMsParam = MTRClampedNumber(timedInvokeTimeoutMsParam, @(1), @(UINT16_MAX));
+ }
+ MTRAsyncCallbackQueueWorkItem * workItem = [[MTRAsyncCallbackQueueWorkItem alloc] initWithQueue:self.device.queue];
+ MTRAsyncCallbackReadyHandler readyHandler = ^(MTRDevice * device, NSUInteger retryCount) {
+ MTRClustersLogDequeue(logPrefix, self.device.asyncCallbackWorkQueue);
+ MTRBaseDevice * baseDevice = [[MTRBaseDevice alloc] initWithNodeID:self.device.nodeID
+ controller:self.device.deviceController];
+ auto * bridge = new MTRCommandSuccessCallbackBridge(
+ self.device.queue,
+ ^(id _Nullable value, NSError * _Nullable error) {
+ MTRClustersLogCompletion(logPrefix, value, error);
+ dispatch_async(self.callbackQueue, ^{
+ completion(error);
+ });
+ [workItem endWork];
+ },
+ ^(ExchangeManager & exchangeManager, const SessionHandle & session, CommandSuccessCallbackType successCb,
+ MTRErrorCallback failureCb, MTRCallbackBridgeBase * bridge) {
+ auto * typedBridge = static_cast<MTRCommandSuccessCallbackBridge *>(bridge);
+ Optional<uint16_t> timedInvokeTimeoutMs;
+ Optional<Timeout> invokeTimeout;
+ ListFreer listFreer;
+ FanControl::Commands::Step::Type request;
+ if (timedInvokeTimeoutMsParam != nil) {
+ timedInvokeTimeoutMs.SetValue(timedInvokeTimeoutMsParam.unsignedShortValue);
+ }
+ if (params != nil) {
+ if (params.serverSideProcessingTimeout != nil) {
+ // Clamp to a number of seconds that will not overflow 32-bit
+ // int when converted to ms.
+ auto * serverSideProcessingTimeout
+ = MTRClampedNumber(params.serverSideProcessingTimeout, @(0), @(UINT16_MAX));
+ invokeTimeout.SetValue(Seconds16(serverSideProcessingTimeout.unsignedShortValue));
+ }
+ }
+ request.direction
+ = static_cast<std::remove_reference_t<decltype(request.direction)>>(params.direction.unsignedCharValue);
+ if (params.wrap != nil) {
+ auto & definedValue_0 = request.wrap.Emplace();
+ definedValue_0 = params.wrap.boolValue;
+ }
+ if (params.lowestOff != nil) {
+ auto & definedValue_0 = request.lowestOff.Emplace();
+ definedValue_0 = params.lowestOff.boolValue;
+ }
+
+ return MTRStartInvokeInteraction(typedBridge, request, exchangeManager, session, successCb, failureCb,
+ self->_endpoint, timedInvokeTimeoutMs, invokeTimeout);
+ });
+ std::move(*bridge).DispatchAction(baseDevice);
+ };
+ workItem.readyHandler = readyHandler;
+ MTRClustersLogEnqueue(logPrefix, self.device.asyncCallbackWorkQueue);
+ [self.device.asyncCallbackWorkQueue enqueueWorkItem:workItem];
+
+ if (!expectedValueIntervalMs || ([expectedValueIntervalMs compare:@(0)] == NSOrderedAscending)) {
+ expectedValues = nil;
+ } else {
+ expectedValueIntervalMs = MTRClampedNumber(expectedValueIntervalMs, @(1), @(UINT32_MAX));
+ }
+ if (expectedValues) {
+ [self.device setExpectedValues:expectedValues expectedValueInterval:expectedValueIntervalMs];
+ }
+}
+
- (NSDictionary<NSString *, id> *)readAttributeFanModeWithParams:(MTRReadParams * _Nullable)params
{
return [self.device readAttributeWithEndpointID:@(_endpoint)
@@ -21757,6 +21834,33 @@
timedWriteTimeout:timedWriteTimeout];
}
+- (NSDictionary<NSString *, id> *)readAttributeAirflowDirectionWithParams:(MTRReadParams * _Nullable)params
+{
+ return [self.device readAttributeWithEndpointID:@(_endpoint)
+ clusterID:@(MTRClusterIDTypeFanControlID)
+ attributeID:@(MTRAttributeIDTypeClusterFanControlAttributeAirflowDirectionID)
+ params:params];
+}
+
+- (void)writeAttributeAirflowDirectionWithValue:(NSDictionary<NSString *, id> *)dataValueDictionary
+ expectedValueInterval:(NSNumber *)expectedValueIntervalMs
+{
+ [self writeAttributeAirflowDirectionWithValue:dataValueDictionary expectedValueInterval:expectedValueIntervalMs params:nil];
+}
+- (void)writeAttributeAirflowDirectionWithValue:(NSDictionary<NSString *, id> *)dataValueDictionary
+ expectedValueInterval:(NSNumber *)expectedValueIntervalMs
+ params:(MTRWriteParams * _Nullable)params
+{
+ NSNumber * timedWriteTimeout = params.timedWriteTimeout;
+
+ [self.device writeAttributeWithEndpointID:@(_endpoint)
+ clusterID:@(MTRClusterIDTypeFanControlID)
+ attributeID:@(MTRAttributeIDTypeClusterFanControlAttributeAirflowDirectionID)
+ value:dataValueDictionary
+ expectedValueInterval:expectedValueIntervalMs
+ timedWriteTimeout:timedWriteTimeout];
+}
+
- (NSDictionary<NSString *, id> *)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params
{
return [self.device readAttributeWithEndpointID:@(_endpoint)
@@ -21814,6 +21918,16 @@
return [self initWithDevice:device endpointID:@(endpoint) queue:queue];
}
+- (void)stepWithParams:(MTRFanControlClusterStepParams *)params
+ expectedValues:(NSArray<NSDictionary<NSString *, id> *> * _Nullable)expectedDataValueDictionaries
+ expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs
+ completionHandler:(MTRStatusCompletion)completionHandler
+{
+ [self stepWithParams:params
+ expectedValues:expectedDataValueDictionaries
+ expectedValueInterval:expectedValueIntervalMs
+ completion:completionHandler];
+}
@end
@implementation MTRClusterThermostatUserInterfaceConfiguration
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h
index 23a469f..24c4e75 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h
@@ -5995,6 +5995,40 @@
@property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout;
@end
+MTR_NEWLY_AVAILABLE
+@interface MTRFanControlClusterStepParams : NSObject <NSCopying>
+
+@property (nonatomic, copy) NSNumber * _Nonnull direction MTR_NEWLY_AVAILABLE;
+
+@property (nonatomic, copy) NSNumber * _Nullable wrap MTR_NEWLY_AVAILABLE;
+
+@property (nonatomic, copy) NSNumber * _Nullable lowestOff MTR_NEWLY_AVAILABLE;
+/**
+ * Controls whether the command is a timed command (using Timed Invoke).
+ *
+ * If nil (the default value), a regular invoke is done for commands that do
+ * not require a timed invoke and a timed invoke with some default timed request
+ * timeout is done for commands that require a timed invoke.
+ *
+ * If not nil, a timed invoke is done, with the provided value used as the timed
+ * request timeout. The value should be chosen small enough to provide the
+ * desired security properties but large enough that it will allow a round-trip
+ * from the sever to the client (for the status response and actual invoke
+ * request) within the timeout window.
+ *
+ */
+@property (nonatomic, copy, nullable) NSNumber * timedInvokeTimeoutMs;
+
+/**
+ * Controls how much time, in seconds, we will allow for the server to process the command.
+ *
+ * The command will then time out if that much time, plus an allowance for retransmits due to network failures, passes.
+ *
+ * If nil, the framework will try to select an appropriate timeout value itself.
+ */
+@property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout;
+@end
+
API_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1))
@interface MTRColorControlClusterMoveToHueParams : NSObject <NSCopying>
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm
index b3731db..54b2cca 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm
@@ -9099,6 +9099,43 @@
}
@end
+@implementation MTRFanControlClusterStepParams
+- (instancetype)init
+{
+ if (self = [super init]) {
+
+ _direction = @(0);
+
+ _wrap = nil;
+
+ _lowestOff = nil;
+ _timedInvokeTimeoutMs = nil;
+ _serverSideProcessingTimeout = nil;
+ }
+ return self;
+}
+
+- (id)copyWithZone:(NSZone * _Nullable)zone;
+{
+ auto other = [[MTRFanControlClusterStepParams alloc] init];
+
+ other.direction = self.direction;
+ other.wrap = self.wrap;
+ other.lowestOff = self.lowestOff;
+ other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs;
+ other.serverSideProcessingTimeout = self.serverSideProcessingTimeout;
+
+ return other;
+}
+
+- (NSString *)description
+{
+ NSString * descriptionString = [NSString stringWithFormat:@"<%@: direction:%@; wrap:%@; lowestOff:%@; >",
+ NSStringFromClass([self class]), _direction, _wrap, _lowestOff];
+ return descriptionString;
+}
+
+@end
@implementation MTRColorControlClusterMoveToHueParams
- (instancetype)init
{
diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp
index b403e7b..b305704 100644
--- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp
+++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp
@@ -16609,6 +16609,37 @@
} // namespace WindSetting
+namespace AirflowDirection {
+
+EmberAfStatus Get(chip::EndpointId endpoint, chip::app::Clusters::FanControl::AirflowDirectionEnum * value)
+{
+ using Traits = NumericAttributeTraits<chip::app::Clusters::FanControl::AirflowDirectionEnum>;
+ Traits::StorageType temp;
+ uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp);
+ EmberAfStatus status = emberAfReadAttribute(endpoint, Clusters::FanControl::Id, Id, readable, sizeof(temp));
+ VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, status);
+ if (!Traits::CanRepresentValue(/* isNullable = */ false, temp))
+ {
+ return EMBER_ZCL_STATUS_CONSTRAINT_ERROR;
+ }
+ *value = Traits::StorageToWorking(temp);
+ return status;
+}
+EmberAfStatus Set(chip::EndpointId endpoint, chip::app::Clusters::FanControl::AirflowDirectionEnum value)
+{
+ using Traits = NumericAttributeTraits<chip::app::Clusters::FanControl::AirflowDirectionEnum>;
+ if (!Traits::CanRepresentValue(/* isNullable = */ false, value))
+ {
+ return EMBER_ZCL_STATUS_CONSTRAINT_ERROR;
+ }
+ Traits::StorageType storageValue;
+ Traits::WorkingToStorage(value, storageValue);
+ uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue);
+ return emberAfWriteAttribute(endpoint, Clusters::FanControl::Id, Id, writable, ZCL_ENUM8_ATTRIBUTE_TYPE);
+}
+
+} // namespace AirflowDirection
+
namespace FeatureMap {
EmberAfStatus Get(chip::EndpointId endpoint, uint32_t * value)
diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h
index 94bf7b1..086820b 100644
--- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h
+++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h
@@ -2988,6 +2988,11 @@
EmberAfStatus Set(chip::EndpointId endpoint, uint8_t value);
} // namespace WindSetting
+namespace AirflowDirection {
+EmberAfStatus Get(chip::EndpointId endpoint, chip::app::Clusters::FanControl::AirflowDirectionEnum * value); // AirflowDirectionEnum
+EmberAfStatus Set(chip::EndpointId endpoint, chip::app::Clusters::FanControl::AirflowDirectionEnum value);
+} // namespace AirflowDirection
+
namespace FeatureMap {
EmberAfStatus Get(chip::EndpointId endpoint, uint32_t * value); // bitmap32
EmberAfStatus Set(chip::EndpointId endpoint, uint32_t value);
diff --git a/zzz_generated/app-common/app-common/zap-generated/callback.h b/zzz_generated/app-common/app-common/zap-generated/callback.h
index abe7249..0c2f241 100644
--- a/zzz_generated/app-common/app-common/zap-generated/callback.h
+++ b/zzz_generated/app-common/app-common/zap-generated/callback.h
@@ -11482,6 +11482,12 @@
chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath,
const chip::app::Clusters::Thermostat::Commands::ClearWeeklySchedule::DecodableType & commandData);
/**
+ * @brief Fan Control Cluster Step Command callback (from client)
+ */
+bool emberAfFanControlClusterStepCallback(chip::app::CommandHandler * commandObj,
+ const chip::app::ConcreteCommandPath & commandPath,
+ const chip::app::Clusters::FanControl::Commands::Step::DecodableType & commandData);
+/**
* @brief Color Control Cluster MoveToHue Command callback (from client)
*/
bool emberAfColorControlClusterMoveToHueCallback(
diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h b/zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h
index 07c3a13..5520652 100644
--- a/zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h
+++ b/zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h
@@ -2165,6 +2165,30 @@
}
}
+static auto __attribute__((unused)) EnsureKnownEnumValue(FanControl::AirflowDirectionEnum val)
+{
+ using EnumType = FanControl::AirflowDirectionEnum;
+ switch (val)
+ {
+ case EnumType::kForward:
+ case EnumType::kReverse:
+ return val;
+ default:
+ return static_cast<EnumType>(2);
+ }
+}
+static auto __attribute__((unused)) EnsureKnownEnumValue(FanControl::DirectionEnum val)
+{
+ using EnumType = FanControl::DirectionEnum;
+ switch (val)
+ {
+ case EnumType::kIncrease:
+ case EnumType::kDecrease:
+ return val;
+ default:
+ return static_cast<EnumType>(2);
+ }
+}
static auto __attribute__((unused)) EnsureKnownEnumValue(FanControl::FanModeSequenceType val)
{
using EnumType = FanControl::FanModeSequenceType;
diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h b/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h
index 8b37509..47bec8a 100644
--- a/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h
+++ b/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h
@@ -2849,6 +2849,30 @@
namespace FanControl {
+// Enum for AirflowDirectionEnum
+enum class AirflowDirectionEnum : uint8_t
+{
+ kForward = 0x00,
+ kReverse = 0x01,
+ // All received enum values that are not listed above will be mapped
+ // to kUnknownEnumValue. This is a helper enum value that should only
+ // be used by code to process how it handles receiving and unknown
+ // enum value. This specific should never be transmitted.
+ kUnknownEnumValue = 2,
+};
+
+// Enum for DirectionEnum
+enum class DirectionEnum : uint8_t
+{
+ kIncrease = 0x00,
+ kDecrease = 0x01,
+ // All received enum values that are not listed above will be mapped
+ // to kUnknownEnumValue. This is a helper enum value that should only
+ // be used by code to process how it handles receiving and unknown
+ // enum value. This specific should never be transmitted.
+ kUnknownEnumValue = 2,
+};
+
// Enum for FanModeSequenceType
enum class FanModeSequenceType : uint8_t
{
@@ -2885,10 +2909,12 @@
// Bitmap for Feature
enum class Feature : uint32_t
{
- kMultiSpeed = 0x1,
- kAuto = 0x2,
- kRocking = 0x4,
- kWind = 0x8,
+ kMultiSpeed = 0x1,
+ kAuto = 0x2,
+ kRocking = 0x4,
+ kWind = 0x8,
+ kStep = 0x10,
+ kAirflowDirection = 0x20,
};
// Bitmap for RockSupportMask
diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp
index eb2f49d..67f09f8 100644
--- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp
+++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp
@@ -16854,7 +16854,53 @@
} // namespace Thermostat
namespace FanControl {
-namespace Commands {} // namespace Commands
+namespace Commands {
+namespace Step {
+CHIP_ERROR Type::Encode(TLV::TLVWriter & writer, TLV::Tag tag) const
+{
+ TLV::TLVType outer;
+ ReturnErrorOnFailure(writer.StartContainer(tag, TLV::kTLVType_Structure, outer));
+ ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(Fields::kDirection), direction));
+ ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(Fields::kWrap), wrap));
+ ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(Fields::kLowestOff), lowestOff));
+ ReturnErrorOnFailure(writer.EndContainer(outer));
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ TLV::TLVType outer;
+ VerifyOrReturnError(TLV::kTLVType_Structure == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE);
+ ReturnErrorOnFailure(reader.EnterContainer(outer));
+ while ((err = reader.Next()) == CHIP_NO_ERROR)
+ {
+ if (!TLV::IsContextTag(reader.GetTag()))
+ {
+ continue;
+ }
+ switch (TLV::TagNumFromTag(reader.GetTag()))
+ {
+ case to_underlying(Fields::kDirection):
+ ReturnErrorOnFailure(DataModel::Decode(reader, direction));
+ break;
+ case to_underlying(Fields::kWrap):
+ ReturnErrorOnFailure(DataModel::Decode(reader, wrap));
+ break;
+ case to_underlying(Fields::kLowestOff):
+ ReturnErrorOnFailure(DataModel::Decode(reader, lowestOff));
+ break;
+ default:
+ break;
+ }
+ }
+
+ VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
+ ReturnErrorOnFailure(reader.ExitContainer(outer));
+ return CHIP_NO_ERROR;
+}
+} // namespace Step.
+} // namespace Commands
namespace Attributes {
CHIP_ERROR TypeInfo::DecodableType::Decode(TLV::TLVReader & reader, const ConcreteAttributePath & path)
@@ -16894,6 +16940,9 @@
case Attributes::WindSetting::TypeInfo::GetAttributeId():
ReturnErrorOnFailure(DataModel::Decode(reader, windSetting));
break;
+ case Attributes::AirflowDirection::TypeInfo::GetAttributeId():
+ ReturnErrorOnFailure(DataModel::Decode(reader, airflowDirection));
+ break;
case Attributes::GeneratedCommandList::TypeInfo::GetAttributeId():
ReturnErrorOnFailure(DataModel::Decode(reader, generatedCommandList));
break;
@@ -27229,6 +27278,13 @@
return false;
}
}
+ case Clusters::FanControl::Id: {
+ switch (aCommand)
+ {
+ default:
+ return false;
+ }
+ }
case Clusters::ColorControl::Id: {
switch (aCommand)
{
diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h
index d14b390..8b8c7fb 100644
--- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h
+++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h
@@ -22138,6 +22138,57 @@
} // namespace Thermostat
namespace FanControl {
+namespace Commands {
+// Forward-declarations so we can reference these later.
+
+namespace Step {
+struct Type;
+struct DecodableType;
+} // namespace Step
+
+} // namespace Commands
+
+namespace Commands {
+namespace Step {
+enum class Fields : uint8_t
+{
+ kDirection = 0,
+ kWrap = 1,
+ kLowestOff = 2,
+};
+
+struct Type
+{
+public:
+ // Use GetCommandId instead of commandId directly to avoid naming conflict with CommandIdentification in ExecutionOfACommand
+ static constexpr CommandId GetCommandId() { return Commands::Step::Id; }
+ static constexpr ClusterId GetClusterId() { return Clusters::FanControl::Id; }
+
+ DirectionEnum direction = static_cast<DirectionEnum>(0);
+ Optional<bool> wrap;
+ Optional<bool> lowestOff;
+
+ CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag) const;
+
+ using ResponseType = DataModel::NullObjectType;
+
+ static constexpr bool MustUseTimedInvoke() { return false; }
+};
+
+struct DecodableType
+{
+public:
+ static constexpr CommandId GetCommandId() { return Commands::Step::Id; }
+ static constexpr ClusterId GetClusterId() { return Clusters::FanControl::Id; }
+
+ DirectionEnum direction = static_cast<DirectionEnum>(0);
+ Optional<bool> wrap;
+ Optional<bool> lowestOff;
+ CHIP_ERROR Decode(TLV::TLVReader & reader);
+};
+}; // namespace Step
+} // namespace Commands
+
namespace Attributes {
namespace FanMode {
@@ -22272,6 +22323,18 @@
static constexpr bool MustUseTimedWrite() { return false; }
};
} // namespace WindSetting
+namespace AirflowDirection {
+struct TypeInfo
+{
+ using Type = chip::app::Clusters::FanControl::AirflowDirectionEnum;
+ using DecodableType = chip::app::Clusters::FanControl::AirflowDirectionEnum;
+ using DecodableArgType = chip::app::Clusters::FanControl::AirflowDirectionEnum;
+
+ static constexpr ClusterId GetClusterId() { return Clusters::FanControl::Id; }
+ static constexpr AttributeId GetAttributeId() { return Attributes::AirflowDirection::Id; }
+ static constexpr bool MustUseTimedWrite() { return false; }
+};
+} // namespace AirflowDirection
namespace GeneratedCommandList {
struct TypeInfo : public Clusters::Globals::Attributes::GeneratedCommandList::TypeInfo
{
@@ -22329,6 +22392,8 @@
Attributes::RockSetting::TypeInfo::DecodableType rockSetting = static_cast<uint8_t>(0);
Attributes::WindSupport::TypeInfo::DecodableType windSupport = static_cast<uint8_t>(0);
Attributes::WindSetting::TypeInfo::DecodableType windSetting = static_cast<uint8_t>(0);
+ Attributes::AirflowDirection::TypeInfo::DecodableType airflowDirection =
+ static_cast<chip::app::Clusters::FanControl::AirflowDirectionEnum>(0);
Attributes::GeneratedCommandList::TypeInfo::DecodableType generatedCommandList;
Attributes::AcceptedCommandList::TypeInfo::DecodableType acceptedCommandList;
Attributes::EventList::TypeInfo::DecodableType eventList;
diff --git a/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h b/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h
index 88b4d87..98137f4 100644
--- a/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h
+++ b/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h
@@ -4038,6 +4038,10 @@
static constexpr AttributeId Id = 0x0000000A;
} // namespace WindSetting
+namespace AirflowDirection {
+static constexpr AttributeId Id = 0x0000000B;
+} // namespace AirflowDirection
+
namespace GeneratedCommandList {
static constexpr AttributeId Id = Globals::Attributes::GeneratedCommandList::Id;
} // namespace GeneratedCommandList
diff --git a/zzz_generated/app-common/app-common/zap-generated/ids/Commands.h b/zzz_generated/app-common/app-common/zap-generated/ids/Commands.h
index 566f589..f164933 100644
--- a/zzz_generated/app-common/app-common/zap-generated/ids/Commands.h
+++ b/zzz_generated/app-common/app-common/zap-generated/ids/Commands.h
@@ -997,6 +997,16 @@
} // namespace Commands
} // namespace Thermostat
+namespace FanControl {
+namespace Commands {
+
+namespace Step {
+static constexpr CommandId Id = 0x00000000;
+} // namespace Step
+
+} // namespace Commands
+} // namespace FanControl
+
namespace ColorControl {
namespace Commands {
diff --git a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h
index e0387eb..01b4df4 100644
--- a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h
+++ b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h
@@ -6324,6 +6324,7 @@
| Cluster FanControl | 0x0202 |
|------------------------------------------------------------------------------|
| Commands: | |
+| * Step | 0x00 |
|------------------------------------------------------------------------------|
| Attributes: | |
| * FanMode | 0x0000 |
@@ -6337,6 +6338,7 @@
| * RockSetting | 0x0008 |
| * WindSupport | 0x0009 |
| * WindSetting | 0x000A |
+| * AirflowDirection | 0x000B |
| * GeneratedCommandList | 0xFFF8 |
| * AcceptedCommandList | 0xFFF9 |
| * EventList | 0xFFFA |
@@ -6347,6 +6349,38 @@
| Events: | |
\*----------------------------------------------------------------------------*/
+/*
+ * Command Step
+ */
+class FanControlStep : public ClusterCommand
+{
+public:
+ FanControlStep(CredentialIssuerCommands * credsIssuerConfig) : ClusterCommand("step", credsIssuerConfig)
+ {
+ AddArgument("Direction", 0, UINT8_MAX, &mRequest.direction);
+ AddArgument("Wrap", 0, 1, &mRequest.wrap);
+ AddArgument("LowestOff", 0, 1, &mRequest.lowestOff);
+ ClusterCommand::AddArguments();
+ }
+
+ CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds) override
+ {
+ ChipLogProgress(chipTool, "Sending cluster (0x00000202) command (0x00000000) on endpoint %u", endpointIds.at(0));
+
+ return ClusterCommand::SendCommand(device, endpointIds.at(0), 0x00000202, 0x00000000, mRequest);
+ }
+
+ CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex) override
+ {
+ ChipLogProgress(chipTool, "Sending cluster (0x00000202) command (0x00000000) on Group %u", groupId);
+
+ return ClusterCommand::SendGroupCommand(groupId, fabricIndex, 0x00000202, 0x00000000, mRequest);
+ }
+
+private:
+ chip::app::Clusters::FanControl::Commands::Step::Type mRequest;
+};
+
/*----------------------------------------------------------------------------*\
| Cluster ThermostatUserInterfaceConfiguration | 0x0204 |
|------------------------------------------------------------------------------|
@@ -16514,6 +16548,7 @@
// Commands
//
make_unique<ClusterCommand>(Id, credsIssuerConfig), //
+ make_unique<FanControlStep>(credsIssuerConfig), //
//
// Attributes
//
@@ -16529,6 +16564,7 @@
make_unique<ReadAttribute>(Id, "rock-setting", Attributes::RockSetting::Id, credsIssuerConfig), //
make_unique<ReadAttribute>(Id, "wind-support", Attributes::WindSupport::Id, credsIssuerConfig), //
make_unique<ReadAttribute>(Id, "wind-setting", Attributes::WindSetting::Id, credsIssuerConfig), //
+ make_unique<ReadAttribute>(Id, "airflow-direction", Attributes::AirflowDirection::Id, credsIssuerConfig), //
make_unique<ReadAttribute>(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), //
make_unique<ReadAttribute>(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), //
make_unique<ReadAttribute>(Id, "event-list", Attributes::EventList::Id, credsIssuerConfig), //
@@ -16558,6 +16594,9 @@
WriteCommandType::kForceWrite, credsIssuerConfig), //
make_unique<WriteAttribute<uint8_t>>(Id, "wind-setting", 0, UINT8_MAX, Attributes::WindSetting::Id,
WriteCommandType::kWrite, credsIssuerConfig), //
+ make_unique<WriteAttribute<chip::app::Clusters::FanControl::AirflowDirectionEnum>>(
+ Id, "airflow-direction", 0, UINT8_MAX, Attributes::AirflowDirection::Id, WriteCommandType::kWrite,
+ credsIssuerConfig), //
make_unique<WriteAttributeAsComplex<chip::app::DataModel::List<const chip::CommandId>>>(
Id, "generated-command-list", Attributes::GeneratedCommandList::Id, WriteCommandType::kForceWrite,
credsIssuerConfig), //
@@ -16583,6 +16622,7 @@
make_unique<SubscribeAttribute>(Id, "rock-setting", Attributes::RockSetting::Id, credsIssuerConfig), //
make_unique<SubscribeAttribute>(Id, "wind-support", Attributes::WindSupport::Id, credsIssuerConfig), //
make_unique<SubscribeAttribute>(Id, "wind-setting", Attributes::WindSetting::Id, credsIssuerConfig), //
+ make_unique<SubscribeAttribute>(Id, "airflow-direction", Attributes::AirflowDirection::Id, credsIssuerConfig), //
make_unique<SubscribeAttribute>(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), //
make_unique<SubscribeAttribute>(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), //
make_unique<SubscribeAttribute>(Id, "event-list", Attributes::EventList::Id, credsIssuerConfig), //
diff --git a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp
index a4d2745..dcb545d 100644
--- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp
+++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp
@@ -9744,6 +9744,11 @@
ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value));
return DataModelLogger::LogValue("WindSetting", 1, value);
}
+ case FanControl::Attributes::AirflowDirection::Id: {
+ chip::app::Clusters::FanControl::AirflowDirectionEnum value;
+ ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value));
+ return DataModelLogger::LogValue("AirflowDirection", 1, value);
+ }
case FanControl::Attributes::GeneratedCommandList::Id: {
chip::app::DataModel::DecodableList<chip::CommandId> value;
ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value));
diff --git a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h
index 65f4b62..5840ca5 100644
--- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h
+++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h
@@ -70204,6 +70204,7 @@
| Cluster FanControl | 0x0202 |
|------------------------------------------------------------------------------|
| Commands: | |
+| * Step | 0x00 |
|------------------------------------------------------------------------------|
| Attributes: | |
| * FanMode | 0x0000 |
@@ -70217,6 +70218,7 @@
| * RockSetting | 0x0008 |
| * WindSupport | 0x0009 |
| * WindSetting | 0x000A |
+| * AirflowDirection | 0x000B |
| * GeneratedCommandList | 0xFFF8 |
| * AcceptedCommandList | 0xFFF9 |
| * EventList | 0xFFFA |
@@ -70228,6 +70230,64 @@
\*----------------------------------------------------------------------------*/
/*
+ * Command Step
+ */
+class FanControlStep : public ClusterCommand {
+public:
+ FanControlStep()
+ : ClusterCommand("step")
+ {
+ AddArgument("Direction", 0, UINT8_MAX, &mRequest.direction);
+ AddArgument("Wrap", 0, 1, &mRequest.wrap);
+ AddArgument("LowestOff", 0, 1, &mRequest.lowestOff);
+ ClusterCommand::AddArguments();
+ }
+
+ CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
+ {
+ ChipLogProgress(chipTool, "Sending cluster (0x00000202) command (0x00000000) on endpoint %u", endpointId);
+
+ dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
+ __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
+ endpointID:@(endpointId)
+ queue:callbackQueue];
+ __auto_type * params = [[MTRFanControlClusterStepParams alloc] init];
+ params.timedInvokeTimeoutMs
+ = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
+ params.direction = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.direction)];
+ if (mRequest.wrap.HasValue()) {
+ params.wrap = [NSNumber numberWithBool:mRequest.wrap.Value()];
+ } else {
+ params.wrap = nil;
+ }
+ if (mRequest.lowestOff.HasValue()) {
+ params.lowestOff = [NSNumber numberWithBool:mRequest.lowestOff.Value()];
+ } else {
+ params.lowestOff = nil;
+ }
+ uint16_t repeatCount = mRepeatCount.ValueOr(1);
+ uint16_t __block responsesNeeded = repeatCount;
+ while (repeatCount--) {
+ [cluster stepWithParams:params
+ completion:^(NSError * _Nullable error) {
+ responsesNeeded--;
+ if (error != nil) {
+ mError = error;
+ LogNSError("Error", error);
+ }
+ if (responsesNeeded == 0) {
+ SetCommandExitStatus(mError);
+ }
+ }];
+ }
+ return CHIP_NO_ERROR;
+ }
+
+private:
+ chip::app::Clusters::FanControl::Commands::Step::Type mRequest;
+};
+
+/*
* Attribute FanMode
*/
class ReadFanControlFanMode : public ReadAttribute {
@@ -71238,6 +71298,116 @@
};
/*
+ * Attribute AirflowDirection
+ */
+class ReadFanControlAirflowDirection : public ReadAttribute {
+public:
+ ReadFanControlAirflowDirection()
+ : ReadAttribute("airflow-direction")
+ {
+ }
+
+ ~ReadFanControlAirflowDirection() {}
+
+ CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
+ {
+ ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x0000000B) on endpoint %u", endpointId);
+
+ dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
+ __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
+ endpointID:@(endpointId)
+ queue:callbackQueue];
+ [cluster readAttributeAirflowDirectionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
+ NSLog(@"FanControl.AirflowDirection response %@", [value description]);
+ if (error != nil) {
+ LogNSError("FanControl AirflowDirection read Error", error);
+ }
+ SetCommandExitStatus(error);
+ }];
+ return CHIP_NO_ERROR;
+ }
+};
+
+class WriteFanControlAirflowDirection : public WriteAttribute {
+public:
+ WriteFanControlAirflowDirection()
+ : WriteAttribute("airflow-direction")
+ {
+ AddArgument("attr-name", "airflow-direction");
+ AddArgument("attr-value", 0, UINT8_MAX, &mValue);
+ WriteAttribute::AddArguments();
+ }
+
+ ~WriteFanControlAirflowDirection() {}
+
+ CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
+ {
+ ChipLogProgress(chipTool, "Sending cluster (0x00000202) WriteAttribute (0x0000000B) on endpoint %u", endpointId);
+ dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
+ __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
+ endpointID:@(endpointId)
+ queue:callbackQueue];
+ __auto_type * params = [[MTRWriteParams alloc] init];
+ params.timedWriteTimeout
+ = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
+ params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
+ NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];
+
+ [cluster writeAttributeAirflowDirectionWithValue:value
+ params:params
+ completion:^(NSError * _Nullable error) {
+ if (error != nil) {
+ LogNSError("FanControl AirflowDirection write Error", error);
+ }
+ SetCommandExitStatus(error);
+ }];
+ return CHIP_NO_ERROR;
+ }
+
+private:
+ uint8_t mValue;
+};
+
+class SubscribeAttributeFanControlAirflowDirection : public SubscribeAttribute {
+public:
+ SubscribeAttributeFanControlAirflowDirection()
+ : SubscribeAttribute("airflow-direction")
+ {
+ }
+
+ ~SubscribeAttributeFanControlAirflowDirection() {}
+
+ CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
+ {
+ ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x0000000B) on endpoint %u", endpointId);
+ dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
+ __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
+ endpointID:@(endpointId)
+ queue:callbackQueue];
+ __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
+ if (mKeepSubscriptions.HasValue()) {
+ params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
+ }
+ if (mFabricFiltered.HasValue()) {
+ params.filterByFabric = mFabricFiltered.Value();
+ }
+ if (mAutoResubscribe.HasValue()) {
+ params.resubscribeAutomatically = mAutoResubscribe.Value();
+ }
+ [cluster subscribeAttributeAirflowDirectionWithParams:params
+ subscriptionEstablished:^() {
+ mSubscriptionEstablished = YES;
+ }
+ reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
+ NSLog(@"FanControl.AirflowDirection response %@", [value description]);
+ SetCommandExitStatus(error);
+ }];
+
+ return CHIP_NO_ERROR;
+ }
+};
+
+/*
* Attribute GeneratedCommandList
*/
class ReadFanControlGeneratedCommandList : public ReadAttribute {
@@ -162828,6 +162998,7 @@
commands_list clusterCommands = {
make_unique<ClusterCommand>(Id), //
+ make_unique<FanControlStep>(), //
make_unique<ReadAttribute>(Id), //
make_unique<ReadFanControlFanMode>(), //
make_unique<WriteAttribute>(Id), //
@@ -162859,6 +163030,9 @@
make_unique<ReadFanControlWindSetting>(), //
make_unique<WriteFanControlWindSetting>(), //
make_unique<SubscribeAttributeFanControlWindSetting>(), //
+ make_unique<ReadFanControlAirflowDirection>(), //
+ make_unique<WriteFanControlAirflowDirection>(), //
+ make_unique<SubscribeAttributeFanControlAirflowDirection>(), //
make_unique<ReadFanControlGeneratedCommandList>(), //
make_unique<SubscribeAttributeFanControlGeneratedCommandList>(), //
make_unique<ReadFanControlAcceptedCommandList>(), //