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 9381838d79410e..32c8d1fe1b3c0a 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 @@ -2919,6 +2919,47 @@ server cluster SmokeCoAlarm = 92 { command SelfTestRequest(): DefaultSuccess = 0; } +/** Attributes and commands for configuring the Dishwasher alarm. */ +server cluster DishwasherAlarm = 93 { + bitmap AlarmMap : BITMAP32 { + kInflowError = 0x1; + kDrainError = 0x2; + kDoorError = 0x4; + kTempTooLow = 0x8; + kTempTooHigh = 0x10; + kWaterLevelError = 0x20; + } + + info event Notify = 0 { + AlarmMap active = 0; + AlarmMap inactive = 1; + AlarmMap state = 2; + AlarmMap mask = 3; + } + + readonly attribute AlarmMap mask = 0; + readonly attribute AlarmMap latch = 1; + readonly attribute AlarmMap state = 2; + readonly attribute AlarmMap supported = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct ResetRequest { + AlarmMap alarms = 0; + } + + request struct ModifyEnabledAlarmsRequest { + AlarmMap mask = 0; + } + + command Reset(ResetRequest): DefaultSuccess = 0; + command ModifyEnabledAlarms(ModifyEnabledAlarmsRequest): DefaultSuccess = 1; +} + /** This cluster supports remotely monitoring and, where supported, changing the operational state of any device where a state machine is a part of the operation. */ server cluster OperationalState = 96 { enum ErrorStateEnum : ENUM8 { @@ -6676,6 +6717,20 @@ endpoint 1 { ram attribute clusterRevision default = 1; } + server cluster DishwasherAlarm { + emits event Notify; + ram attribute mask default = 1; + ram attribute latch default = 1; + ram attribute state default = 0; + ram attribute supported default = 15; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 1; + ram attribute clusterRevision default = 1; + } + server cluster OperationalState { emits event OperationalError; emits event OperationCompletion; 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 9e7e08f0f57a3e..365337854727ed 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 @@ -15739,6 +15739,245 @@ } ] }, + { + "name": "Dishwasher Alarm", + "code": 93, + "mfgCode": null, + "define": "DISHWASHER_ALARM_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Reset", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ModifyEnabledAlarms", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Dishwasher Alarm", + "code": 93, + "mfgCode": null, + "define": "DISHWASHER_ALARM_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Mask", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "AlarmMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Latch", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "AlarmMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "State", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "AlarmMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Supported", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "AlarmMap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "15", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EventList", + "code": 65530, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "Notify", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, { "name": "Operational State", "code": 96, diff --git a/examples/all-clusters-app/all-clusters-common/src/dishwasher-alarm-stub.cpp b/examples/all-clusters-app/all-clusters-common/src/dishwasher-alarm-stub.cpp new file mode 100644 index 00000000000000..58d393752c8bfd --- /dev/null +++ b/examples/all-clusters-app/all-clusters-common/src/dishwasher-alarm-stub.cpp @@ -0,0 +1,142 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include + +using namespace chip; + +namespace chip { +namespace app { +namespace Clusters { +namespace DishwasherAlarm { + +class DishwasherAlarmDelegate : public Delegate +{ +public: + /** + * @brief + * A notification that the Mask attribute will be changed. When this happens, some previously suppressed + * alarms may need to be enabled, and previously enabled alarms may need to be suppressed. + * @param[in] mask The new value of the Mask attribute. + * @return The cluster will do this update if ModifyEnabledAlarmsCallback() returns true. + * The cluster will not do this update if ModifyEnabledAlarmsCallback() returns false. + */ + bool ModifyEnabledAlarmsCallback(const BitMask mask) override; + + /** + * @brief + * A notification that resets active alarms (if possible) + * @param[in] alarms The value of reset alarms + * @return The cluster will reset active alarms if ResetAlarmsCallback() returns true. + * The cluster will not reset active alarms if ResetAlarmsCallback() returns false. + */ + bool ResetAlarmsCallback(const BitMask alarms) override; + + ~DishwasherAlarmDelegate() = default; +}; + +bool DishwasherAlarmDelegate::ModifyEnabledAlarmsCallback(const BitMask mask) +{ + // placeholder implementation + return true; +} + +bool DishwasherAlarmDelegate::ResetAlarmsCallback(const BitMask alarms) +{ + // placeholder implementation + return true; +} + +} // namespace DishwasherAlarm +} // namespace Clusters +} // namespace app +} // namespace chip + +/* + * An example to present device's endpointId + */ +static constexpr EndpointId kDemoEndpointId = 1; + +void MatterDishwasherAlarmServerInit() +{ + using namespace app::Clusters; + using namespace app::Clusters::DishwasherAlarm; + + static DishwasherAlarm::DishwasherAlarmDelegate delegate; + DishwasherAlarm::SetDefaultDelegate(kDemoEndpointId, &delegate); + + // Set Supported attribute = 0x2F = 47 + // Bit Name Value + // 0 InflowError 1 + // 1 DrainError 1 + // 2 DoorError 1 + // 3 TempTooLow 1 + // 4 TempTooHigh 0 + // 5 WaterLevelError 1 + BitMask supported; + supported.SetField(AlarmMap::kInflowError, 1); + supported.SetField(AlarmMap::kDrainError, 1); + supported.SetField(AlarmMap::kDoorError, 1); + supported.SetField(AlarmMap::kTempTooLow, 1); + supported.SetField(AlarmMap::kWaterLevelError, 1); + DishwasherAlarmServer::Instance().SetSupportedValue(kDemoEndpointId, supported); + + // Set Mask attribute = 0x2F = 47 + // Bit Name Value + // 0 InflowError 1 + // 1 DrainError 1 + // 2 DoorError 1 + // 3 TempTooLow 1 + // 4 TempTooHigh 0 + // 5 WaterLevelError 1 + BitMask mask; + mask.SetField(AlarmMap::kInflowError, 1); + mask.SetField(AlarmMap::kDrainError, 1); + mask.SetField(AlarmMap::kDoorError, 1); + mask.SetField(AlarmMap::kTempTooLow, 1); + mask.SetField(AlarmMap::kWaterLevelError, 1); + DishwasherAlarmServer::Instance().SetMaskValue(kDemoEndpointId, mask); + + // Set Latch attribute = 0x03 + // Bit Name Value + // 0 InflowError 1 + // 1 DrainError 1 + // 2 DoorError 0 + // 3 TempTooLow 0 + // 4 TempTooHigh 0 + // 5 WaterLevelError 0 + BitMask latch; + latch.SetField(AlarmMap::kInflowError, 1); + latch.SetField(AlarmMap::kDrainError, 1); + DishwasherAlarmServer::Instance().SetLatchValue(kDemoEndpointId, latch); + + // Set State attribute = 0x07 + // Bit Name Value + // 0 InflowError 1 + // 1 DrainError 1 + // 2 DoorError 1 + // 3 TempTooLow 0 + // 4 TempTooHigh 0 + // 5 WaterLevelError 0 + BitMask state; + state.SetField(AlarmMap::kInflowError, 1); + state.SetField(AlarmMap::kDrainError, 1); + state.SetField(AlarmMap::kDoorError, 1); + DishwasherAlarmServer::Instance().SetStateValue(kDemoEndpointId, state); +} diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt index 90ba706cfa8556..14015338230788 100644 --- a/examples/all-clusters-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt @@ -95,6 +95,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/resource-monitoring-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/temperature-control-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-synchronization-server" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/dishwasher-alarm-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/src" ) diff --git a/examples/all-clusters-app/linux/BUILD.gn b/examples/all-clusters-app/linux/BUILD.gn index bdaf4945e3ae4f..72cd65ba55bc9e 100644 --- a/examples/all-clusters-app/linux/BUILD.gn +++ b/examples/all-clusters-app/linux/BUILD.gn @@ -23,6 +23,7 @@ source_set("chip-all-clusters-common") { 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/dishwasher-alarm-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/dishwasher-mode.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/laundry-washer-mode.cpp", diff --git a/examples/all-clusters-app/linux/main-common.cpp b/examples/all-clusters-app/linux/main-common.cpp index 7894a781a6f278..0ebeff439e9dc2 100644 --- a/examples/all-clusters-app/linux/main-common.cpp +++ b/examples/all-clusters-app/linux/main-common.cpp @@ -61,6 +61,9 @@ app::Clusters::TemperatureControl::AppSupportedTemperatureLevelsDelegate sAppSup #ifdef EMBER_AF_PLUGIN_OPERATIONAL_STATE_SERVER extern void MatterOperationalStateServerInit(); #endif +#ifdef EMBER_AF_PLUGIN_DISHWASHER_ALARM_SERVER +extern void MatterDishwasherAlarmServerInit(); +#endif void OnIdentifyStart(::Identify *) { @@ -181,6 +184,10 @@ void ApplicationInit() #ifdef EMBER_AF_PLUGIN_OPERATIONAL_STATE_SERVER MatterOperationalStateServerInit(); #endif + +#ifdef EMBER_AF_PLUGIN_DISHWASHER_ALARM_SERVER + MatterDishwasherAlarmServerInit(); +#endif app::Clusters::TemperatureControl::SetInstance(&sAppSupportedTemperatureLevelsDelegate); } diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index 8eae0fcf8c0c6c..1724d1048a304c 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -270,6 +270,12 @@ template("chip_data_model") { "${_app_root}/clusters/${cluster}/${cluster}.h", "${_app_root}/clusters/${cluster}/operational-state-delegate.h", ] + } else if (cluster == "dishwasher-alarm-server") { + sources += [ + "${_app_root}/clusters/${cluster}/${cluster}.cpp", + "${_app_root}/clusters/${cluster}/${cluster}.h", + "${_app_root}/clusters/${cluster}/dishwasher-alarm-delegate.h", + ] } else if (cluster == "icd-management-server") { sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp" ] diff --git a/src/app/clusters/dishwasher-alarm-server/dishwasher-alarm-delegate.h b/src/app/clusters/dishwasher-alarm-server/dishwasher-alarm-delegate.h new file mode 100644 index 00000000000000..5f4e77242a49e7 --- /dev/null +++ b/src/app/clusters/dishwasher-alarm-server/dishwasher-alarm-delegate.h @@ -0,0 +1,69 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace DishwasherAlarm { + +/** @brief + * Defines methods for implementing application-specific logic for the DishwasherAlarm Cluster. + */ +class Delegate +{ +public: + /** + * @brief + * A notification that the Mask attribute will be changed. When this happens, some previously suppressed + * alarms may need to be enabled, and previously enabled alarms may need to be suppressed. + * @param[in] mask The new value of the Mask attribute. + * @return The cluster will do this update if ModifyEnabledAlarmsCallback() returns true. + * the cluster will not do this update if ModifyEnabledAlarmsCallback() returns false. + */ + virtual bool ModifyEnabledAlarmsCallback(const BitMask mask) = 0; + + /** + * @brief + * A notification that resets active alarms (if possible) + * @param[in] alarms The value of reset alarms + * @return The cluster will reset active alarms if ResetAlarmsCallback() returns true. + * The cluster will not reset active alarms if ResetAlarmsCallback() returns false. + */ + virtual bool ResetAlarmsCallback(const BitMask alarms) = 0; + + Delegate(EndpointId endpoint) : mEndpoint(endpoint) {} + + Delegate() = default; + + virtual ~Delegate() = default; + +protected: + EndpointId mEndpoint = 0; +}; + +} // namespace DishwasherAlarm +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/dishwasher-alarm-server/dishwasher-alarm-server.cpp b/src/app/clusters/dishwasher-alarm-server/dishwasher-alarm-server.cpp new file mode 100644 index 00000000000000..c0d167f2993ec6 --- /dev/null +++ b/src/app/clusters/dishwasher-alarm-server/dishwasher-alarm-server.cpp @@ -0,0 +1,398 @@ +/** + * + * 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 "dishwasher-alarm-server.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::DishwasherAlarm; +using namespace chip::app::Clusters::DishwasherAlarm::Attributes; +using namespace chip::DeviceLayer; +using chip::Protocols::InteractionModel::Status; +using namespace std; + +static constexpr size_t kDishwasherAlarmDelegateTableSize = + EMBER_AF_DISHWASHER_ALARM_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; + +static_assert(kDishwasherAlarmDelegateTableSize <= kEmberInvalidEndpointIndex, "Dishwasher Alarm Delegate table size error"); + +namespace chip { +namespace app { +namespace Clusters { +namespace DishwasherAlarm { + +Delegate * gDelegateTable[kDishwasherAlarmDelegateTableSize] = { nullptr }; + +Delegate * GetDelegate(EndpointId endpoint) +{ + uint16_t ep = emberAfGetClusterServerEndpointIndex(endpoint, DishwasherAlarm::Id, + EMBER_AF_DISHWASHER_ALARM_CLUSTER_SERVER_ENDPOINT_COUNT); + return (ep >= kDishwasherAlarmDelegateTableSize ? nullptr : gDelegateTable[ep]); +} + +void SetDefaultDelegate(EndpointId endpoint, Delegate * delegate) +{ + uint16_t ep = emberAfGetClusterServerEndpointIndex(endpoint, DishwasherAlarm::Id, + EMBER_AF_DISHWASHER_ALARM_CLUSTER_SERVER_ENDPOINT_COUNT); + // if endpoint is found + if (ep < kDishwasherAlarmDelegateTableSize) + { + gDelegateTable[ep] = delegate; + } +} + +} // namespace DishwasherAlarm +} // namespace Clusters +} // namespace app +} // namespace chip + +DishwasherAlarmServer DishwasherAlarmServer::instance; + +DishwasherAlarmServer & DishwasherAlarmServer::Instance() +{ + return instance; +} + +EmberAfStatus DishwasherAlarmServer::GetMaskValue(EndpointId endpoint, BitMask * mask) +{ + EmberAfStatus status = Attributes::Mask::Get(endpoint, mask); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: reading mask, err:0x%x", status); + return status; + } + return status; +} + +EmberAfStatus DishwasherAlarmServer::GetLatchValue(EndpointId endpoint, BitMask * latch) +{ + if (!HasResetFeature(endpoint)) + { + ChipLogProgress(Zcl, "Dishwasher Alarm feature: Unsupport Latch attribute"); + return EMBER_ZCL_STATUS_UNSUPPORTED_ATTRIBUTE; + } + + EmberAfStatus status = Attributes::Latch::Get(endpoint, latch); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: reading latch, err:0x%x", status); + return status; + } + return status; +} + +EmberAfStatus DishwasherAlarmServer::GetStateValue(EndpointId endpoint, BitMask * state) +{ + EmberAfStatus status = Attributes::State::Get(endpoint, state); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: get state, err:0x%x", status); + return status; + } + return status; +} + +EmberAfStatus DishwasherAlarmServer::GetSupportedValue(EndpointId endpoint, BitMask * supported) +{ + EmberAfStatus status = Attributes::Supported::Get(endpoint, supported); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: reading supported, err:0x%x", status); + } + return status; +} + +EmberAfStatus DishwasherAlarmServer::SetSupportedValue(EndpointId endpoint, const BitMask supported) +{ + EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; + ; + if ((status = Attributes::Supported::Set(endpoint, supported)) != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: writing supported, err:0x%x", status); + return status; + } + // Whenever there is change in Supported attribute, Latch should change accordingly (if possible). + BitMask latch; + if (GetLatchValue(endpoint, &latch) == EMBER_ZCL_STATUS_SUCCESS && !supported.HasAll(latch)) + { + latch = latch & supported; + status = SetLatchValue(endpoint, latch); + } + + // Whenever there is change in Supported attribute, Mask, State should change accordingly. + BitMask mask; + if ((status = GetMaskValue(endpoint, &mask)) != EMBER_ZCL_STATUS_SUCCESS) + { + return status; + } + + if (!supported.HasAll(mask)) + { + mask = supported & mask; + status = SetMaskValue(endpoint, mask); + } + return status; +} + +EmberAfStatus DishwasherAlarmServer::SetMaskValue(EndpointId endpoint, const BitMask mask) +{ + BitMask supported; + if (GetSupportedValue(endpoint, &supported) || !supported.HasAll(mask)) + { + ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: Mask is not supported"); + return EMBER_ZCL_STATUS_FAILURE; + } + + EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; + if ((status = Attributes::Mask::Set(endpoint, mask)) != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: writing mask, err:0x%x", status); + return status; + } + + // Whenever there is change in Mask, State should change accordingly. + BitMask state; + status = GetStateValue(endpoint, &state); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + return status; + } + + if (!mask.HasAll(state)) + { + state = mask & state; + status = SetStateValue(endpoint, state, true); + } + return status; +} + +EmberAfStatus DishwasherAlarmServer::SetLatchValue(EndpointId endpoint, const BitMask latch) +{ + if (!HasResetFeature(endpoint)) + { + ChipLogProgress(Zcl, "Dishwasher Alarm feature: Unsupport Latch attribute"); + return EMBER_ZCL_STATUS_UNSUPPORTED_ATTRIBUTE; + } + + BitMask supported; + if (GetSupportedValue(endpoint, &supported) || !supported.HasAll(latch)) + { + ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: Latch is not supported"); + return EMBER_ZCL_STATUS_FAILURE; + } + + EmberAfStatus status = Attributes::Latch::Set(endpoint, latch); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: writing latch, err:0x%x", status); + return status; + } + + return status; +} + +EmberAfStatus DishwasherAlarmServer::SetStateValue(EndpointId endpoint, const BitMask newState, bool ignoreLatchState) +{ + BitMask supported; + BitMask finalNewState; + finalNewState.Set(newState); + + if (GetSupportedValue(endpoint, &supported) || !supported.HasAll(finalNewState)) + { + ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: Alarm is not supported"); + return EMBER_ZCL_STATUS_FAILURE; + } + + BitMask mask; + if (GetMaskValue(endpoint, &mask) || !mask.HasAll(finalNewState)) + { + ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: Alarm is suppressed"); + return EMBER_ZCL_STATUS_FAILURE; + } + + EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; + BitMask currentState; + status = Attributes::State::Get(endpoint, ¤tState); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: reading state, err:0x%x", status); + return status; + } + + BitMask latch; + if (!ignoreLatchState && (GetLatchValue(endpoint, &latch) == EMBER_ZCL_STATUS_SUCCESS)) + { + // Restore bits that have their Latch bit set. + auto bitsToKeep = latch & currentState; + finalNewState.Set(bitsToKeep); + } + + // Store the new value of the State attribute. + status = Attributes::State::Set(endpoint, finalNewState); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: writing state, err:0x%x", status); + return status; + } + + // Generate Notify event. + BitMask becameActive; + becameActive.Set(finalNewState).Clear(currentState); + BitMask becameInactive; + becameInactive.Set(currentState).Clear(finalNewState); + + SendNotifyEvent(endpoint, becameActive, becameInactive, finalNewState, mask); + return status; +} + +EmberAfStatus DishwasherAlarmServer::ResetLatchedAlarms(EndpointId endpoint, const BitMask alarms) +{ + BitMask supported; + if (GetSupportedValue(endpoint, &supported) || !supported.HasAll(alarms)) + { + ChipLogProgress(Zcl, "Dishwasher Alarm: ERR: Alarm is not supported"); + return EMBER_ZCL_STATUS_FAILURE; + } + + BitMask state; + if (GetStateValue(endpoint, &state) != EMBER_ZCL_STATUS_SUCCESS) + { + return EMBER_ZCL_STATUS_FAILURE; + } + + state.Clear(alarms); + return SetStateValue(endpoint, state, true); +} + +bool DishwasherAlarmServer::HasResetFeature(EndpointId endpoint) +{ + uint32_t featureMap = 0; + if (Attributes::FeatureMap::Get(endpoint, &featureMap) != EMBER_ZCL_STATUS_SUCCESS) + { + return false; + } + + if (featureMap & 1) + { + return true; + } + return false; +} + +void DishwasherAlarmServer::SendNotifyEvent(EndpointId endpointId, BitMask becameActive, BitMask becameInactive, + BitMask newState, BitMask mask) +{ + Events::Notify::Type event{ .active = becameActive, .inactive = becameInactive, .state = newState, .mask = mask }; + EventNumber eventNumber; + CHIP_ERROR error = LogEvent(event, endpointId, eventNumber); + if (CHIP_NO_ERROR != error) + { + ChipLogError(Zcl, "[Notify] Unable to send notify event: %s [endpointId=%d]", error.AsString(), endpointId); + } +} + +static Status ModifyEnabledHandler(const app::ConcreteCommandPath & commandPath, const BitMask mask) +{ + EndpointId endpoint = commandPath.mEndpointId; + BitMask supported; + + if (DishwasherAlarmServer::Instance().GetSupportedValue(endpoint, &supported) != EMBER_ZCL_STATUS_SUCCESS) + { + return Status::Failure; + } + + // receives this command with a Mask that includes bits that are set for alarms which are not supported + if (!supported.HasAll(mask)) + { + return Status::InvalidCommand; + } + + // A server that is unable to enable a currently suppressed alarm, + // or is unable to suppress a currently enabled alarm SHALL respond + // with a status code of FAILURE + Delegate * delegate = DishwasherAlarm::GetDelegate(endpoint); + if (delegate && !(delegate->ModifyEnabledAlarmsCallback(mask))) + { + ChipLogProgress(Zcl, "Unable to modify enabled alarms"); + return Status::Failure; + } + // The cluster will do this update if delegate.ModifyEnabledAlarmsCallback() returns true. + if (DishwasherAlarmServer::Instance().SetMaskValue(endpoint, mask) != EMBER_ZCL_STATUS_SUCCESS) + { + return Status::Failure; + } + return Status::Success; +} + +static Status ResetHandler(const app::ConcreteCommandPath & commandPath, const BitMask alarms) +{ + EndpointId endpoint = commandPath.mEndpointId; + + if (!DishwasherAlarmServer::Instance().HasResetFeature(endpoint)) + { + ChipLogProgress(Zcl, "Dishwasher Alarm feature: Unsupport Reset Command"); + return app::ToInteractionModelStatus(EMBER_ZCL_STATUS_UNSUPPORTED_COMMAND); + } + + // A server that is unable to reset alarms SHALL respond with a status code of FAILURE + Delegate * delegate = DishwasherAlarm::GetDelegate(endpoint); + if (delegate && !(delegate->ResetAlarmsCallback(alarms))) + { + ChipLogProgress(Zcl, "Unable to reset alarms"); + return Status::Failure; + } + + // The cluster will do this update if delegate.ResetAlarmsCallback() returns true. + if (DishwasherAlarmServer::Instance().ResetLatchedAlarms(endpoint, alarms) != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "reset alarms fail"); + return Status::Failure; + } + return Status::Success; +} + +bool emberAfDishwasherAlarmClusterResetCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, + const Commands::Reset::DecodableType & commandData) +{ + auto & alarms = commandData.alarms; + + Status status = ResetHandler(commandPath, alarms); + commandObj->AddStatus(commandPath, status); + + return true; +} + +bool emberAfDishwasherAlarmClusterModifyEnabledAlarmsCallback(app::CommandHandler * commandObj, + const app::ConcreteCommandPath & commandPath, + const Commands::ModifyEnabledAlarms::DecodableType & commandData) +{ + auto & mask = commandData.mask; + Status status = ModifyEnabledHandler(commandPath, mask); + commandObj->AddStatus(commandPath, status); + + return true; +} diff --git a/src/app/clusters/dishwasher-alarm-server/dishwasher-alarm-server.h b/src/app/clusters/dishwasher-alarm-server/dishwasher-alarm-server.h new file mode 100644 index 00000000000000..d03662f29333fd --- /dev/null +++ b/src/app/clusters/dishwasher-alarm-server/dishwasher-alarm-server.h @@ -0,0 +1,89 @@ +/* + * + * 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. + */ + +#pragma once + +#include "dishwasher-alarm-delegate.h" +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace DishwasherAlarm { + +class DishwasherAlarmServer +{ +public: + static DishwasherAlarmServer & Instance(); + + EmberAfStatus GetMaskValue(EndpointId endpoint, BitMask * mask); + EmberAfStatus GetStateValue(EndpointId endpoint, BitMask * state); + EmberAfStatus GetLatchValue(EndpointId endpoint, BitMask * latch); + EmberAfStatus GetSupportedValue(EndpointId endpoint, BitMask * suppported); + + // Whenever there is change on Mask we should change State accordingly. + EmberAfStatus SetMaskValue(EndpointId endpoint, const BitMask mask); + EmberAfStatus SetLatchValue(EndpointId endpoint, const BitMask latch); + // A change in supported value will result in a corresponding change in mask and state. + EmberAfStatus SetSupportedValue(EndpointId endpoint, const BitMask supported); + + /** + * @brief Set the value of the State attribute + * This method sets the State attribute to the value in newState, if allowed by the Mask + * and Supported attributes. When the State attribute changes, a Notify event will be + * generated. + * @param[in] endpoint The endpoint corresponding to the Dishwasher Alarm cluster. + * @param[in] newState The desired new value for the State attribute. + * @param[in] ignoreLatchState If false, the Latch attribute will be honored and the + * method will not reset any bits in the State attribute which have their + * associated Latch bit set. If true, the Latch attribute is ignored and the value of + * the State attribute will be set to the value of the newState parameter while + * honoring the Mask and Supported attributes. + * The default value for the ignoreLatchState parameter is false. + */ + EmberAfStatus SetStateValue(EndpointId endpoint, const BitMask newState, bool ignoreLatchState = false); + + /** + * @brief Reset the value of latched alarms in the State attribute. + * When the State attribute changes a Notify event is generated. + * @param[in] endpoint The endpoint corresponding to the Dishwasher Alarm cluster. + * @param[in] alarms Each bit set to a 1 in this parameter corresponds to a bit in the + * State attribute will SHALL be reset to false. + */ + EmberAfStatus ResetLatchedAlarms(EndpointId endpoint, const BitMask alarms); + + // check whether the Alarm featureMap has enabled Reset feature. + bool HasResetFeature(EndpointId endpoint); + +private: + static DishwasherAlarmServer instance; + + void SendNotifyEvent(EndpointId endpointId, BitMask becameActive, BitMask becameInactive, + BitMask newState, BitMask mask); +}; + +void SetDefaultDelegate(EndpointId endpoint, Delegate * delegate); + +} // namespace DishwasherAlarm +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/tests/suites/TestDishwasherAlarm.yaml b/src/app/tests/suites/TestDishwasherAlarm.yaml new file mode 100644 index 00000000000000..94af3329610e73 --- /dev/null +++ b/src/app/tests/suites/TestDishwasherAlarm.yaml @@ -0,0 +1,190 @@ +# 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. + +name: Dishwasher Alarm Tests + +config: + nodeId: 0x12344321 + cluster: "Dishwasher Alarm" + endpoint: 1 + +tests: + - label: "Wait for the commissioned device to be retrieved" + cluster: "DelayCommands" + command: "WaitForCommissionee" + arguments: + values: + - name: "nodeId" + value: nodeId + #Init + #Support 10 1111 (47) (0x2F) + #Mask 10 1111 (47) (0x2F) + #Latch 00 0011 (3) (0x03) + #State 00 0111 (7) (0x07) + #FeatureMap 1 + - label: "Read Supported Attribute" + command: "readAttribute" + attribute: "Supported" + response: + value: 47 + + - label: "Read Mask Attribute" + command: "readAttribute" + attribute: "Mask" + response: + value: 47 + + - label: "Read Latch Attribute" + command: "readAttribute" + attribute: "Latch" + response: + value: 3 + + - label: "Read State Attribute" + command: "readAttribute" + attribute: "State" + response: + value: 7 + + - label: "Read feature map Attribute" + command: "readAttribute" + attribute: "FeatureMap" + response: + constraints: + type: bitmap32 + hasMasksSet: [0x1] + + #After Modify Enabled Alarm (Valid) + #Support 10 1111 (47) (0x2F) + #Mask 10 1001 (41) (0x29) + #Latch 00 0011 (3) (0x03) + #State 00 0001 (1) (0x01) + - label: "Modify enabled alarms Command" + command: "ModifyEnabledAlarms" + arguments: + values: + - name: "Mask" + value: 41 + + - label: "Read Mask Attribute" + command: "readAttribute" + attribute: "Mask" + response: + value: 41 + + - label: "Read Latch Attribute" + command: "readAttribute" + attribute: "Latch" + response: + value: 3 + + - label: "Read State Attribute" + command: "readAttribute" + attribute: "State" + response: + value: 1 + + #After Modify Enabled Alarm (Invalid, set for unknown alarms) + #Support 10 1111 (47) (0x2F) + #Mask 110 1001 (105) (0x69) + #Latch 00 0011 (3) (0x03) + #State 00 0001 (1) (0x01) + - label: "Modify enabled alarms Command" + command: "ModifyEnabledAlarms" + arguments: + values: + - name: "Mask" + value: 105 + response: + error: INVALID_COMMAND + + - label: "Read Mask Attribute" + command: "readAttribute" + attribute: "Mask" + response: + value: 41 + + - label: "Read Latch Attribute" + command: "readAttribute" + attribute: "Latch" + response: + value: 3 + + - label: "Read State Attribute" + command: "readAttribute" + attribute: "State" + response: + value: 1 + + #After Modify Enabled Alarm (Invalid, set for alarms which are not supported) + #Support 10 1111 (47) (0x2F) + #Mask 11 1011 (59) (0x3B) + #Latch 00 0011 (3) (0x03) + #State 00 0001 (1) (0x01) + - label: "Modify enabled alarms Command" + command: "ModifyEnabledAlarms" + arguments: + values: + - name: "Mask" + value: 59 + response: + error: INVALID_COMMAND + + - label: "Read Mask Attribute" + command: "readAttribute" + attribute: "Mask" + response: + value: 41 + + - label: "Read Latch Attribute" + command: "readAttribute" + attribute: "Latch" + response: + value: 3 + + - label: "Read State Attribute" + command: "readAttribute" + attribute: "State" + response: + value: 1 + + #After Reset alarms bit 0 + #Support 10 1111 (47) (0x2F) + #Mask 10 1001 (41) (0x29) + #Latch 00 0011 (3) (0x03) + #State 00 0000 (0) (0x00) + - label: "Reset Command" + command: "Reset" + arguments: + values: + - name: "Alarms" + value: 1 + + - label: "Read Mask Attribute" + command: "readAttribute" + attribute: "Mask" + response: + value: 41 + + - label: "Read Latch Attribute" + command: "readAttribute" + attribute: "Latch" + response: + value: 3 + + - label: "Read State Attribute" + command: "readAttribute" + attribute: "State" + response: + value: 0 diff --git a/src/app/tests/suites/ciTests.json b/src/app/tests/suites/ciTests.json index fbb8340a50c75b..377dd568b2aea0 100644 --- a/src/app/tests/suites/ciTests.json +++ b/src/app/tests/suites/ciTests.json @@ -270,7 +270,8 @@ "TestCommissionerNodeId", "TestTimeSynchronization", "TestOperationalState", - "TestRVCOperationalState" + "TestRVCOperationalState", + "TestDishwasherAlarm" ], "MultiAdmin": ["TestMultiAdmin"], "SoftwareDiagnostics": ["Test_TC_DGSW_1_1"], diff --git a/src/app/util/util.cpp b/src/app/util/util.cpp index 116ed030cd751c..dd2085a2a827cb 100644 --- a/src/app/util/util.cpp +++ b/src/app/util/util.cpp @@ -156,6 +156,7 @@ void MatterLaundryWasherModePluginServerInitCallback() {} void MatterRefrigeratorAndTemperatureControlledCabinetModePluginServerInitCallback() {} void MatterOperationalStatePluginServerInitCallback() {} void MatterRvcOperationalStatePluginServerInitCallback() {} +void MatterDishwasherAlarmPluginServerInitCallback() {} // **************************************** // Print out information about each cluster // **************************************** diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h index 2ede95292b00a3..ce0c3be66f3523 100644 --- a/zzz_generated/chip-tool/zap-generated/test/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h @@ -299,6 +299,7 @@ class TestList : public Command printf("TestTimeSynchronization\n"); printf("TestOperationalState\n"); printf("TestRVCOperationalState\n"); + printf("TestDishwasherAlarm\n"); printf("TestMultiAdmin\n"); printf("Test_TC_DGSW_1_1\n"); printf("TestSubscribe_OnOff\n"); @@ -96813,6 +96814,348 @@ class TestRVCOperationalStateSuite : public TestCommand } }; +class TestDishwasherAlarmSuite : public TestCommand +{ +public: + TestDishwasherAlarmSuite(CredentialIssuerCommands * credsIssuerConfig) : + TestCommand("TestDishwasherAlarm", 22, credsIssuerConfig) + { + AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); + AddArgument("cluster", &mCluster); + AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint); + AddArgument("timeout", 0, UINT16_MAX, &mTimeout); + } + + ~TestDishwasherAlarmSuite() {} + + chip::System::Clock::Timeout GetWaitDuration() const override + { + return chip::System::Clock::Seconds16(mTimeout.ValueOr(kTimeoutInSeconds)); + } + +private: + chip::Optional mNodeId; + chip::Optional mCluster; + chip::Optional mEndpoint; + chip::Optional mTimeout; + + chip::EndpointId GetEndpoint(chip::EndpointId endpoint) { return mEndpoint.HasValue() ? mEndpoint.Value() : endpoint; } + + // + // Tests methods + // + + void OnResponse(const chip::app::StatusIB & status, chip::TLV::TLVReader * data) override + { + bool shouldContinue = false; + + switch (mTestIndex - 1) + { + case 0: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 1: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::BitMask value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("supported", value, 47UL)); + } + break; + case 2: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::BitMask value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("mask", value, 47UL)); + } + break; + case 3: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::BitMask value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("latch", value, 3UL)); + } + break; + case 4: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::BitMask value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("state", value, 7UL)); + } + break; + case 5: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + uint32_t value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckConstraintType("value", "bitmap32", "bitmap32")); + VerifyOrReturn(CheckConstraintHasMasksSet("value", value, 1UL)); + } + break; + case 6: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 7: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::BitMask value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("mask", value, 41UL)); + } + break; + case 8: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::BitMask value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("latch", value, 3UL)); + } + break; + case 9: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::BitMask value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("state", value, 1UL)); + } + break; + case 10: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + break; + case 11: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::BitMask value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("mask", value, 41UL)); + } + break; + case 12: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::BitMask value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("latch", value, 3UL)); + } + break; + case 13: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::BitMask value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("state", value, 1UL)); + } + break; + case 14: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + break; + case 15: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::BitMask value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("mask", value, 41UL)); + } + break; + case 16: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::BitMask value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("latch", value, 3UL)); + } + break; + case 17: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::BitMask value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("state", value, 1UL)); + } + break; + case 18: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 19: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::BitMask value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("mask", value, 41UL)); + } + break; + case 20: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::BitMask value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("latch", value, 3UL)); + } + break; + case 21: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::BitMask value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("state", value, 0UL)); + } + break; + default: + LogErrorOnFailure(ContinueOnChipMainThread(CHIP_ERROR_INVALID_ARGUMENT)); + } + + if (shouldContinue) + { + ContinueOnChipMainThread(CHIP_NO_ERROR); + } + } + + CHIP_ERROR DoTestStep(uint16_t testIndex) override + { + using namespace chip::app::Clusters; + switch (testIndex) + { + case 0: { + LogStep(0, "Wait for the commissioned device to be retrieved"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForCommissionee::Type value; + value.nodeId = mNodeId.HasValue() ? mNodeId.Value() : 305414945ULL; + return WaitForCommissionee(kIdentityAlpha, value); + } + case 1: { + LogStep(1, "Read Supported Attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Attributes::Supported::Id, + true, chip::NullOptional); + } + case 2: { + LogStep(2, "Read Mask Attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Attributes::Mask::Id, true, + chip::NullOptional); + } + case 3: { + LogStep(3, "Read Latch Attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Attributes::Latch::Id, true, + chip::NullOptional); + } + case 4: { + LogStep(4, "Read State Attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Attributes::State::Id, true, + chip::NullOptional); + } + case 5: { + LogStep(5, "Read feature map Attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Attributes::FeatureMap::Id, + true, chip::NullOptional); + } + case 6: { + LogStep(6, "Modify enabled alarms Command"); + ListFreer listFreer; + chip::app::Clusters::DishwasherAlarm::Commands::ModifyEnabledAlarms::Type value; + value.mask = static_cast>(41UL); + return SendCommand(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, + DishwasherAlarm::Commands::ModifyEnabledAlarms::Id, value, chip::NullOptional + + ); + } + case 7: { + LogStep(7, "Read Mask Attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Attributes::Mask::Id, true, + chip::NullOptional); + } + case 8: { + LogStep(8, "Read Latch Attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Attributes::Latch::Id, true, + chip::NullOptional); + } + case 9: { + LogStep(9, "Read State Attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Attributes::State::Id, true, + chip::NullOptional); + } + case 10: { + LogStep(10, "Modify enabled alarms Command"); + ListFreer listFreer; + chip::app::Clusters::DishwasherAlarm::Commands::ModifyEnabledAlarms::Type value; + value.mask = static_cast>(105UL); + return SendCommand(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, + DishwasherAlarm::Commands::ModifyEnabledAlarms::Id, value, chip::NullOptional + + ); + } + case 11: { + LogStep(11, "Read Mask Attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Attributes::Mask::Id, true, + chip::NullOptional); + } + case 12: { + LogStep(12, "Read Latch Attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Attributes::Latch::Id, true, + chip::NullOptional); + } + case 13: { + LogStep(13, "Read State Attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Attributes::State::Id, true, + chip::NullOptional); + } + case 14: { + LogStep(14, "Modify enabled alarms Command"); + ListFreer listFreer; + chip::app::Clusters::DishwasherAlarm::Commands::ModifyEnabledAlarms::Type value; + value.mask = static_cast>(59UL); + return SendCommand(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, + DishwasherAlarm::Commands::ModifyEnabledAlarms::Id, value, chip::NullOptional + + ); + } + case 15: { + LogStep(15, "Read Mask Attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Attributes::Mask::Id, true, + chip::NullOptional); + } + case 16: { + LogStep(16, "Read Latch Attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Attributes::Latch::Id, true, + chip::NullOptional); + } + case 17: { + LogStep(17, "Read State Attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Attributes::State::Id, true, + chip::NullOptional); + } + case 18: { + LogStep(18, "Reset Command"); + ListFreer listFreer; + chip::app::Clusters::DishwasherAlarm::Commands::Reset::Type value; + value.alarms = static_cast>(1UL); + return SendCommand(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Commands::Reset::Id, value, + chip::NullOptional + + ); + } + case 19: { + LogStep(19, "Read Mask Attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Attributes::Mask::Id, true, + chip::NullOptional); + } + case 20: { + LogStep(20, "Read Latch Attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Attributes::Latch::Id, true, + chip::NullOptional); + } + case 21: { + LogStep(21, "Read State Attribute"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), DishwasherAlarm::Id, DishwasherAlarm::Attributes::State::Id, true, + chip::NullOptional); + } + } + return CHIP_NO_ERROR; + } +}; + class TestMultiAdminSuite : public TestCommand { public: @@ -144580,6 +144923,7 @@ void registerCommandsTests(Commands & commands, CredentialIssuerCommands * creds make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), diff --git a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h index 2dc568d1ef81d4..3d69b11871f7b8 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h @@ -266,6 +266,7 @@ class TestList : public Command { printf("TestTimeSynchronization\n"); printf("TestOperationalState\n"); printf("TestRVCOperationalState\n"); + printf("TestDishwasherAlarm\n"); printf("TestMultiAdmin\n"); printf("Test_TC_DGSW_1_1\n"); printf("TestSubscribe_OnOff\n"); @@ -143027,6 +143028,717 @@ class TestRVCOperationalState : public TestCommandBridge { } }; +class TestDishwasherAlarm : public TestCommandBridge { +public: + // NOLINTBEGIN(clang-analyzer-nullability.NullPassedToNonnull): Test constructor nullability not enforced + TestDishwasherAlarm() + : TestCommandBridge("TestDishwasherAlarm") + , mTestIndex(0) + { + AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); + AddArgument("cluster", &mCluster); + AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint); + AddArgument("timeout", 0, UINT16_MAX, &mTimeout); + } + // NOLINTEND(clang-analyzer-nullability.NullPassedToNonnull) + + ~TestDishwasherAlarm() {} + + /////////// TestCommand Interface ///////// + void NextTest() override + { + CHIP_ERROR err = CHIP_NO_ERROR; + + if (0 == mTestIndex) { + ChipLogProgress(chipTool, " **** Test Start: TestDishwasherAlarm\n"); + } + + if (mTestCount == mTestIndex) { + ChipLogProgress(chipTool, " **** Test Complete: TestDishwasherAlarm\n"); + SetCommandExitStatus(CHIP_NO_ERROR); + return; + } + + Wait(); + + // Ensure we increment mTestIndex before we start running the relevant + // command. That way if we lose the timeslice after we send the message + // but before our function call returns, we won't end up with an + // incorrect mTestIndex value observed when we get the response. + switch (mTestIndex++) { + case 0: + ChipLogProgress(chipTool, " ***** Test Step 0 : Wait for the commissioned device to be retrieved\n"); + err = TestWaitForTheCommissionedDeviceToBeRetrieved_0(); + break; + case 1: + ChipLogProgress(chipTool, " ***** Test Step 1 : Read Supported Attribute\n"); + err = TestReadSupportedAttribute_1(); + break; + case 2: + ChipLogProgress(chipTool, " ***** Test Step 2 : Read Mask Attribute\n"); + err = TestReadMaskAttribute_2(); + break; + case 3: + ChipLogProgress(chipTool, " ***** Test Step 3 : Read Latch Attribute\n"); + err = TestReadLatchAttribute_3(); + break; + case 4: + ChipLogProgress(chipTool, " ***** Test Step 4 : Read State Attribute\n"); + err = TestReadStateAttribute_4(); + break; + case 5: + ChipLogProgress(chipTool, " ***** Test Step 5 : Read feature map Attribute\n"); + err = TestReadFeatureMapAttribute_5(); + break; + case 6: + ChipLogProgress(chipTool, " ***** Test Step 6 : Modify enabled alarms Command\n"); + err = TestModifyEnabledAlarmsCommand_6(); + break; + case 7: + ChipLogProgress(chipTool, " ***** Test Step 7 : Read Mask Attribute\n"); + err = TestReadMaskAttribute_7(); + break; + case 8: + ChipLogProgress(chipTool, " ***** Test Step 8 : Read Latch Attribute\n"); + err = TestReadLatchAttribute_8(); + break; + case 9: + ChipLogProgress(chipTool, " ***** Test Step 9 : Read State Attribute\n"); + err = TestReadStateAttribute_9(); + break; + case 10: + ChipLogProgress(chipTool, " ***** Test Step 10 : Modify enabled alarms Command\n"); + err = TestModifyEnabledAlarmsCommand_10(); + break; + case 11: + ChipLogProgress(chipTool, " ***** Test Step 11 : Read Mask Attribute\n"); + err = TestReadMaskAttribute_11(); + break; + case 12: + ChipLogProgress(chipTool, " ***** Test Step 12 : Read Latch Attribute\n"); + err = TestReadLatchAttribute_12(); + break; + case 13: + ChipLogProgress(chipTool, " ***** Test Step 13 : Read State Attribute\n"); + err = TestReadStateAttribute_13(); + break; + case 14: + ChipLogProgress(chipTool, " ***** Test Step 14 : Modify enabled alarms Command\n"); + err = TestModifyEnabledAlarmsCommand_14(); + break; + case 15: + ChipLogProgress(chipTool, " ***** Test Step 15 : Read Mask Attribute\n"); + err = TestReadMaskAttribute_15(); + break; + case 16: + ChipLogProgress(chipTool, " ***** Test Step 16 : Read Latch Attribute\n"); + err = TestReadLatchAttribute_16(); + break; + case 17: + ChipLogProgress(chipTool, " ***** Test Step 17 : Read State Attribute\n"); + err = TestReadStateAttribute_17(); + break; + case 18: + ChipLogProgress(chipTool, " ***** Test Step 18 : Reset Command\n"); + err = TestResetCommand_18(); + break; + case 19: + ChipLogProgress(chipTool, " ***** Test Step 19 : Read Mask Attribute\n"); + err = TestReadMaskAttribute_19(); + break; + case 20: + ChipLogProgress(chipTool, " ***** Test Step 20 : Read Latch Attribute\n"); + err = TestReadLatchAttribute_20(); + break; + case 21: + ChipLogProgress(chipTool, " ***** Test Step 21 : Read State Attribute\n"); + err = TestReadStateAttribute_21(); + break; + } + + if (CHIP_NO_ERROR != err) { + ChipLogError(chipTool, " ***** Test Failure: %s\n", chip::ErrorStr(err)); + SetCommandExitStatus(err); + } + } + + void OnStatusUpdate(const chip::app::StatusIB & status) override + { + switch (mTestIndex - 1) { + case 0: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 1: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 2: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 3: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 4: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 5: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 6: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 7: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 8: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 9: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 10: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + break; + case 11: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 12: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 13: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 14: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_COMMAND)); + break; + case 15: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 16: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 17: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 18: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 19: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 20: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 21: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + } + + // Go on to the next test. + ContinueOnChipMainThread(CHIP_NO_ERROR); + } + + chip::System::Clock::Timeout GetWaitDuration() const override + { + return chip::System::Clock::Seconds16(mTimeout.ValueOr(kTimeoutInSeconds)); + } + +private: + std::atomic_uint16_t mTestIndex; + const uint16_t mTestCount = 22; + + chip::Optional mNodeId; + chip::Optional mCluster; + chip::Optional mEndpoint; + chip::Optional mTimeout; + + CHIP_ERROR TestWaitForTheCommissionedDeviceToBeRetrieved_0() + { + + chip::app::Clusters::DelayCommands::Commands::WaitForCommissionee::Type value; + value.nodeId = mNodeId.HasValue() ? mNodeId.Value() : 305414945ULL; + return WaitForCommissionee("alpha", value); + } + + CHIP_ERROR TestReadSupportedAttribute_1() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeSupportedWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read Supported Attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("Supported", actualValue, 47UL)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadMaskAttribute_2() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeMaskWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read Mask Attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("Mask", actualValue, 47UL)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadLatchAttribute_3() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeLatchWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read Latch Attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("Latch", actualValue, 3UL)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadStateAttribute_4() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeStateWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read State Attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("State", actualValue, 7UL)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadFeatureMapAttribute_5() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read feature map Attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + VerifyOrReturn(CheckConstraintType("featureMap", "bitmap32", "bitmap32")); + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestModifyEnabledAlarmsCommand_6() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + __auto_type * params = [[MTRDishwasherAlarmClusterModifyEnabledAlarmsParams alloc] init]; + params.mask = [NSNumber numberWithUnsignedInt:41UL]; + [cluster modifyEnabledAlarmsWithParams:params + completion:^(NSError * _Nullable err) { + NSLog(@"Modify enabled alarms Command Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadMaskAttribute_7() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeMaskWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read Mask Attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("Mask", actualValue, 41UL)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadLatchAttribute_8() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeLatchWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read Latch Attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("Latch", actualValue, 3UL)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadStateAttribute_9() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeStateWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read State Attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("State", actualValue, 1UL)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestModifyEnabledAlarmsCommand_10() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + __auto_type * params = [[MTRDishwasherAlarmClusterModifyEnabledAlarmsParams alloc] init]; + params.mask = [NSNumber numberWithUnsignedInt:105UL]; + [cluster + modifyEnabledAlarmsWithParams:params + completion:^(NSError * _Nullable err) { + NSLog(@"Modify enabled alarms Command Error: %@", err); + + VerifyOrReturn(CheckValue("status", + err ? ([err.domain isEqualToString:MTRInteractionErrorDomain] ? err.code + : EMBER_ZCL_STATUS_FAILURE) + : 0, + EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadMaskAttribute_11() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeMaskWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read Mask Attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("Mask", actualValue, 41UL)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadLatchAttribute_12() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeLatchWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read Latch Attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("Latch", actualValue, 3UL)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadStateAttribute_13() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeStateWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read State Attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("State", actualValue, 1UL)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestModifyEnabledAlarmsCommand_14() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + __auto_type * params = [[MTRDishwasherAlarmClusterModifyEnabledAlarmsParams alloc] init]; + params.mask = [NSNumber numberWithUnsignedInt:59UL]; + [cluster + modifyEnabledAlarmsWithParams:params + completion:^(NSError * _Nullable err) { + NSLog(@"Modify enabled alarms Command Error: %@", err); + + VerifyOrReturn(CheckValue("status", + err ? ([err.domain isEqualToString:MTRInteractionErrorDomain] ? err.code + : EMBER_ZCL_STATUS_FAILURE) + : 0, + EMBER_ZCL_STATUS_INVALID_COMMAND)); + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadMaskAttribute_15() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeMaskWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read Mask Attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("Mask", actualValue, 41UL)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadLatchAttribute_16() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeLatchWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read Latch Attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("Latch", actualValue, 3UL)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadStateAttribute_17() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeStateWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read State Attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("State", actualValue, 1UL)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestResetCommand_18() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + __auto_type * params = [[MTRDishwasherAlarmClusterResetParams alloc] init]; + params.alarms = [NSNumber numberWithUnsignedInt:1UL]; + [cluster resetWithParams:params + completion:^(NSError * _Nullable err) { + NSLog(@"Reset Command Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadMaskAttribute_19() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeMaskWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read Mask Attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("Mask", actualValue, 41UL)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadLatchAttribute_20() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeLatchWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read Latch Attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("Latch", actualValue, 3UL)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR TestReadStateAttribute_21() + { + + MTRBaseDevice * device = GetDevice("alpha"); + __auto_type * cluster = [[MTRBaseClusterDishwasherAlarm alloc] initWithDevice:device endpointID:@(1) queue:mCallbackQueue]; + VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE); + + [cluster readAttributeStateWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read State Attribute Error: %@", err); + + VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0)); + + { + id actualValue = value; + VerifyOrReturn(CheckValue("State", actualValue, 0UL)); + } + + NextTest(); + }]; + + return CHIP_NO_ERROR; + } +}; + class TestMultiAdmin : public TestCommandBridge { public: // NOLINTBEGIN(clang-analyzer-nullability.NullPassedToNonnull): Test constructor nullability not enforced @@ -173739,6 +174451,7 @@ void registerCommandsTests(Commands & commands) make_unique(), make_unique(), make_unique(), + make_unique(), make_unique(), make_unique(), make_unique(),