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 a28f341209feea..9d332ab0d7509b 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 @@ -2350,6 +2350,29 @@ server cluster ModeSelect = 80 { command ChangeToMode(ChangeToModeRequest): DefaultSuccess = 0; } +/** Attributes and commands for configuring the Refrigerator alarm. */ +server cluster RefrigeratorAlarm = 87 { + bitmap AlarmMap : BITMAP32 { + kDoorOpen = 0x1; + } + + info event Notify = 0 { + AlarmMap active = 0; + AlarmMap inactive = 1; + AlarmMap state = 2; + AlarmMap mask = 3; + } + + readonly attribute AlarmMap mask = 0; + readonly attribute AlarmMap state = 2; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + /** Attributes for reporting air quality classification */ server cluster AirQuality = 91 { enum AirQualityEnum : ENUM8 { @@ -6133,6 +6156,18 @@ endpoint 1 { ram attribute manufacturerExtension default = 255; } + server cluster RefrigeratorAlarm { + emits event Notify; + ram attribute mask default = 1; + ram attribute state default = 0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + server cluster AirQuality { ram attribute airQuality default = 0; callback attribute generatedCommandList; 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 bbdf3a2c461b57..7136a62988b61c 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 @@ -13076,6 +13076,195 @@ } ] }, + { + "name": "Refrigerator Alarm", + "code": 87, + "mfgCode": null, + "define": "REFRIGERATOR_ALARM", + "side": "client", + "enabled": 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": "Refrigerator Alarm", + "code": 87, + "mfgCode": null, + "define": "REFRIGERATOR_ALARM", + "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": "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": "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": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "Notify", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, { "name": "Air Quality", "code": 91, diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt index ed62e67b6d26f7..e2311a75f51f76 100644 --- a/examples/all-clusters-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt @@ -71,6 +71,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread-network-diagnostics-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/channel-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/scenes-server" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/refrigerator-alarm-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/software-diagnostics-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/switch-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-diagnostics-server" diff --git a/src/app/clusters/refrigerator-alarm-server/refrigerator-alarm-server.cpp b/src/app/clusters/refrigerator-alarm-server/refrigerator-alarm-server.cpp new file mode 100644 index 00000000000000..719b144902776d --- /dev/null +++ b/src/app/clusters/refrigerator-alarm-server/refrigerator-alarm-server.cpp @@ -0,0 +1,157 @@ +/** + * + * 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 "refrigerator-alarm-server.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::RefrigeratorAlarm; +using namespace chip::app::Clusters::RefrigeratorAlarm::Attributes; +using namespace chip::DeviceLayer; +using chip::Protocols::InteractionModel::Status; + +using namespace std; +RefrigeratorAlarmServer RefrigeratorAlarmServer::instance; + +RefrigeratorAlarmServer & RefrigeratorAlarmServer::Instance() +{ + return instance; +} + +EmberAfStatus RefrigeratorAlarmServer::GetMaskValue(EndpointId endpoint, BitMask * mask) +{ + EmberAfStatus status = Attributes::Mask::Get(endpoint, mask); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Refrigerator Alarm: ERR: reading mask, err:0x%x", status); + return status; + } + + ChipLogProgress(Zcl, "Refrigerator Alarm: Mask ep%d value: %" PRIu32 "", endpoint, mask->Raw()); + + return status; +} + +EmberAfStatus RefrigeratorAlarmServer::GetStateValue(EndpointId endpoint, BitMask * state) +{ + EmberAfStatus status = Attributes::State::Get(endpoint, state); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Refrigerator Alarm: ERR: reading state, err:0x%x", status); + return status; + } + + ChipLogProgress(Zcl, "Refrigerator Alarm: State ep%d value: %" PRIu32 "", endpoint, state->Raw()); + + return status; +} + +EmberAfStatus RefrigeratorAlarmServer::SetMaskValue(EndpointId endpoint, const BitMask mask) +{ + EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; + status = Attributes::Mask::Set(endpoint, mask); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Refrigerator Alarm: ERR: writing mask, err:0x%x", status); + return status; + } + + ChipLogProgress(Zcl, "Refrigerator Alarm: Mask ep%d value: %" PRIu32 "", endpoint, mask.Raw()); + + // 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 (state != (mask & state)) + { + state = mask & state; + status = SetStateValue(endpoint, state); + } + return status; +} + +EmberAfStatus RefrigeratorAlarmServer::SetStateValue(EndpointId endpoint, BitMask newState) +{ + EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; + BitMask currentState; + + status = Attributes::State::Get(endpoint, ¤tState); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Refrigerator Alarm: ERR: reading state, err:0x%x", status); + return status; + } + + status = Attributes::State::Set(endpoint, newState); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogProgress(Zcl, "Refrigerator Alarm: ERR: writing state, err:0x%x", status); + return status; + } + + ChipLogProgress(Zcl, "Refrigerator Alarm: State ep%d value: %" PRIu32 "", endpoint, newState.Raw()); + + // Generate Notify event. + BitMask becameActive; + becameActive.Set(newState).Clear(currentState); + BitMask becameInactive; + becameInactive.Set(currentState).Clear(newState); + // This field SHALL be a copy of the Mask attribute when this event was generated. + BitMask mask; + + status = GetMaskValue(endpoint, &mask); + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + return status; + } + SendNotifyEvent(endpoint, becameActive, becameInactive, newState, mask); + + return status; +} + +void RefrigeratorAlarmServer::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); + } +} + +/********************************************************** + * Callbacks Implementation + *********************************************************/ + +void emberAfRefrigeratorAlarmClusterServerInitCallback(EndpointId endpoint) {} + +void MatterRefrigeratorAlarmPluginServerInitCallback() {} diff --git a/src/app/clusters/refrigerator-alarm-server/refrigerator-alarm-server.h b/src/app/clusters/refrigerator-alarm-server/refrigerator-alarm-server.h new file mode 100644 index 00000000000000..a165a6c62d0d15 --- /dev/null +++ b/src/app/clusters/refrigerator-alarm-server/refrigerator-alarm-server.h @@ -0,0 +1,50 @@ +/* + * + * 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 +#include +#include +#include +#include +#include + +class RefrigeratorAlarmServer +{ +public: + static RefrigeratorAlarmServer & Instance(); + + EmberAfStatus GetMaskValue(chip::EndpointId endpoint, chip::BitMask * mask); + EmberAfStatus GetStateValue(chip::EndpointId endpoint, chip::BitMask * state); + + // Whenever there is change on Mask we should change State accordingly. + EmberAfStatus SetMaskValue(chip::EndpointId endpoint, + const chip::BitMask mask); + + // When State changes we are generating Notify event. + EmberAfStatus SetStateValue(chip::EndpointId endpoint, + chip::BitMask newState); + +private: + static RefrigeratorAlarmServer instance; + + void SendNotifyEvent(chip::EndpointId endpointId, chip::BitMask becameActive, + chip::BitMask becameInactive, + chip::BitMask newState, + chip::BitMask mask); +}; diff --git a/src/app/zap_cluster_list.json b/src/app/zap_cluster_list.json index 7925bbf5ee5fd9..6975c5cfe70164 100644 --- a/src/app/zap_cluster_list.json +++ b/src/app/zap_cluster_list.json @@ -263,11 +263,10 @@ ], "PWM_CLUSTER": [], "RADON_CONCENTRATION_MEASUREMENT_CLUSTER": [], - "REFRIGERATOR_ALARM_CLUSTER": ["refrigerator-alarm-server"], + "REFRIGERATOR_ALARM": ["refrigerator-alarm-server"], "REFRIGERATOR_AND_TEMPERATURE_CONTROLLED_CABINET_MODE_CLUSTER": [ "mode-select-server" ], - "REFRIGERATOR_ALARM_CLUSTER": ["refrigerator-alarm-server"], "RELATIVE_HUMIDITY_MEASUREMENT_CLUSTER": [], "RVC_CLEAN_MODE_CLUSTER": ["mode-select-server"], "RVC_RUN_MODE_CLUSTER": ["mode-select-server"],