From 4d9380a4fafbaa281d6b23f7c2f9922a5c7918e1 Mon Sep 17 00:00:00 2001 From: Andrew Griffiths Date: Mon, 23 Sep 2024 14:27:29 +1200 Subject: [PATCH] Chime Cluster Definition and server code --- .github/workflows/tests.yaml | 1 + scripts/rules.matterlint | 1 + .../clusters/chime-server/chime-server.cpp | 169 ++++++++++++++++++ src/app/clusters/chime-server/chime-server.h | 111 ++++++++++++ src/app/common/templates/config-data.yaml | 1 + .../zcl/data-model/chip/chime-cluster.xml | 57 ++++++ .../zcl/zcl-with-test-extensions.json | 2 + src/app/zap-templates/zcl/zcl.json | 2 + src/app/zap_cluster_list.json | 1 + .../data_model/controller-clusters.zap | 19 ++ 10 files changed, 364 insertions(+) create mode 100644 src/app/clusters/chime-server/chime-server.cpp create mode 100644 src/app/clusters/chime-server/chime-server.h create mode 100644 src/app/zap-templates/zcl/data-model/chip/chime-cluster.xml diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index d14d188a2fb6e4..0b9fd6754afefc 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -112,6 +112,7 @@ jobs: src/app/zap-templates/zcl/data-model/chip/chip-ota.xml \ src/app/zap-templates/zcl/data-model/chip/chip-types.xml \ src/app/zap-templates/zcl/data-model/chip/channel-cluster.xml \ + src/app/zap-templates/zcl/data-model/chip/chime-cluster.xml \ src/app/zap-templates/zcl/data-model/chip/clusters-extensions.xml \ src/app/zap-templates/zcl/data-model/chip/color-control-cluster.xml \ src/app/zap-templates/zcl/data-model/chip/commissioner-control-cluster.xml \ diff --git a/scripts/rules.matterlint b/scripts/rules.matterlint index e7bd644249a13e..c1e2e48cde9498 100644 --- a/scripts/rules.matterlint +++ b/scripts/rules.matterlint @@ -15,6 +15,7 @@ load "../src/app/zap-templates/zcl/data-model/chip/boolean-state-cluster.xml"; load "../src/app/zap-templates/zcl/data-model/chip/actions-cluster.xml"; load "../src/app/zap-templates/zcl/data-model/chip/bridged-device-basic-information.xml"; load "../src/app/zap-templates/zcl/data-model/chip/channel-cluster.xml"; +load "../src/app/zap-templates/zcl/data-model/chip/chime-cluster.xml"; load "../src/app/zap-templates/zcl/data-model/chip/chip-ota.xml"; load "../src/app/zap-templates/zcl/data-model/chip/chip-types.xml"; load "../src/app/zap-templates/zcl/data-model/chip/clusters-extensions.xml"; diff --git a/src/app/clusters/chime-server/chime-server.cpp b/src/app/clusters/chime-server/chime-server.cpp new file mode 100644 index 00000000000000..aa560b9313631b --- /dev/null +++ b/src/app/clusters/chime-server/chime-server.cpp @@ -0,0 +1,169 @@ +/* + * + * Copyright (c) 2024 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. + */ + +/****************************************************************************' + * @file + * @brief Implementation for the Chime Server Cluster + ***************************************************************************/ + + +#include "chime-server.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::DataModel; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::Chime; +using namespace chip::app::Clusters::Chime::Attributes; +using chip::Protocols::InteractionModel::Status; + + +namespace chip { +namespace app { +namespace Clusters { + +ChimeServer::ChimeServer(EndpointId endpointId, ChimeDelegate & delegate) : + AttributeAccessInterface(MakeOptional(endpointId), Chime::Id), + CommandHandlerInterface(MakeOptional(endpointId), Chime::Id), mDelegate(delegate) +{ + mDelegate.SetChimeServer(this); +} + +ChimeServer::~ChimeServer() +{ + AttributeAccessInterfaceRegistry::Instance().Unregister(this); + CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); +} + + +CHIP_ERROR ChimeServer::Init() +{ + VerifyOrReturnError(AttributeAccessInterfaceRegistry::Instance().Register(this), CHIP_ERROR_INTERNAL); + ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(this)); + return CHIP_NO_ERROR; +} + +// AttributeAccessInterface +CHIP_ERROR ChimeServer::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) +{ + VerifyOrDie(aPath.mClusterId == Chime::Id); + + switch (aPath.mAttributeId) + { + case InstalledChimeSounds::Id: + return aEncoder.Encode(mDelegate.GetInstalledChimeSounds()); + + case ActiveChimeSoundId::Id: + return aEncoder.Encode(mDelegate.GetActiveChimeSoundId()); + + case Enabled::Id: + return aEncoder.Encode(mDelegate.GetEnabled()); + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR ChimeServer::Write(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder) +{ + VerifyOrDie(aPath.mClusterId == Chime::Id); + + switch (aPath.mAttributeId) + { + case ActiveChimeSoundId::Id: { + uint8_t newValue; + ReturnErrorOnFailure(aDecoder.Decode(newValue)); + ReturnErrorOnFailure(SetActiveChimeSoundId(newValue)); + return CHIP_NO_ERROR; + + } + case Enabled::Id: { + bool newValue; + ReturnErrorOnFailure(aDecoder.Decode(newValue)); + ReturnErrorOnFailure(mDelegate.SetEnabled(newValue)); + return CHIP_NO_ERROR; + } + + default: + // Unknown attribute + return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); + } + +} + +CHIP_ERROR ChimeServer::SetActiveChimeSoundId(uint8_t soundId) +{ + uint8_t currentSoundId = mDelegate.GetActiveChimeSoundId(); + bool activeSoundIdChanged = !(currentSoundId == soundId); + + VerifyOrReturnError(activeSoundIdChanged, CHIP_NO_ERROR); + VerifyOrDie(mDelegate.SetActiveChimeSoundId(soundId) == CHIP_NO_ERROR); + MatterReportingAttributeChangeCallback(GetEndpointId(), Chime::Id, ActiveChimeSoundId::Id); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR ChimeServer::SetEnabled(bool enabled) +{ + bool currentlyEnabled = mDelegate.GetEnabled(); + bool enableChanged = !(currentlyEnabled == enabled); + + VerifyOrReturnError(enableChanged, CHIP_NO_ERROR); + VerifyOrDie(mDelegate.SetEnabled(enabled) == CHIP_NO_ERROR); + MatterReportingAttributeChangeCallback(GetEndpointId(), Chime::Id, Enabled ::Id); + + return CHIP_NO_ERROR; +} + +void ChimeServer::InvokeCommand(HandlerContext & ctx) +{ + switch (ctx.mRequestPath.mCommandId) + { + case Commands::PlayChimeSound::Id: + CommandHandlerInterface::HandleCommand( + ctx, [this](HandlerContext & ctx, const auto & req) { HandlePlayChimeSound(ctx, req); }); + break; + } +} + +void ChimeServer::HandlePlayChimeSound(HandlerContext & ctx, const Commands::PlayChimeSound::DecodableType & req) +{ + + ChipLogDetail(Zcl, "Chime: PlayChimeSound"); + + // call the delegate to play the chime + Status status = mDelegate.playChimeSound(); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); +} + +} // namespace Clusters +} // namespace app +} // namespace chip + +/** @brief Chime Cluster Server Init + * + * Server Init + * + */ +void MatterChimePluginServerInitCallback(){} diff --git a/src/app/clusters/chime-server/chime-server.h b/src/app/clusters/chime-server/chime-server.h new file mode 100644 index 00000000000000..5a4f59e830a827 --- /dev/null +++ b/src/app/clusters/chime-server/chime-server.h @@ -0,0 +1,111 @@ +/* + * + * Copyright (c) 2024 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 +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { + +class ChimeDelegate; + + +class ChimeServer : private AttributeAccessInterface, private CommandHandlerInterface +{ +public: + + ChimeServer(EndpointId endpointId, ChimeDelegate & delegate); + ~ChimeServer(); + + CHIP_ERROR Init(); + +private: + ChimeDelegate & mDelegate; + + EndpointId GetEndpointId() { return AttributeAccessInterface::GetEndpointId().Value(); } + + // AttributeAccessInterface + CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; + CHIP_ERROR Write(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder) override; + CHIP_ERROR SetActiveChimeSoundId(uint8_t chimeSoundId); + CHIP_ERROR SetEnabled(bool enabled); + + // CommandHandlerInterface + void InvokeCommand(HandlerContext & ctx) override; + + void HandlePlayChimeSound(HandlerContext & ctx, const Chime::Commands::PlayChimeSound::DecodableType & req); + +}; + +/** @brief + * Defines methods for implementing application-specific logic for the Chime Cluster. + */ +class ChimeDelegate +{ +public: + ChimeDelegate() = default; + + virtual ~ChimeDelegate() = default; + + // Get Attribute Methods + virtual DataModel::List& GetInstalledChimeSounds() = 0; + virtual uint8_t GetActiveChimeSoundId() = 0; + virtual bool GetEnabled() = 0; + + + // Set Attribute Methods + virtual CHIP_ERROR SetActiveChimeSoundId(uint8_t chimeSoundId) = 0; + virtual CHIP_ERROR SetEnabled(bool enabled) = 0; + + // Commands + /** + * @brief Delegate should implement a handler to play the currently active chime sound. + * It should report Status::Success if successful and may + * return other Status codes if it fails + */ + virtual Protocols::InteractionModel::Status playChimeSound() = 0; + + + + +private: + friend class ChimeServer; + + ChimeServer * mChimeServer = nullptr; + + void SetChimeServer(ChimeServer * chimeServer) { mChimeServer = chimeServer; } + +protected: + ChimeServer * GetChimeServer() const { return mChimeServer; } +}; + +} // namespace Clusters +} // namespace app +} // namespace chip + diff --git a/src/app/common/templates/config-data.yaml b/src/app/common/templates/config-data.yaml index 61e7c45582268a..f5259748d9421c 100644 --- a/src/app/common/templates/config-data.yaml +++ b/src/app/common/templates/config-data.yaml @@ -36,6 +36,7 @@ CommandHandlerInterfaceOnlyClusters: - RVC Operational State - Sample MEI - Microwave Oven Control + - Chime - Energy EVSE - Energy EVSE Mode - Device Energy Management diff --git a/src/app/zap-templates/zcl/data-model/chip/chime-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/chime-cluster.xml new file mode 100644 index 00000000000000..057dd1cdb094e9 --- /dev/null +++ b/src/app/zap-templates/zcl/data-model/chip/chime-cluster.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + Chime + Camera + 0x0556 + CHIME_CLUSTER + Attributes and commands to configure and play Chime sounds + + + + + + InstalledChimeSounds + + + + ActiveChimeSoundId + + + + + Enabled + + + + + + Plays the currently active chime sound. + + + + + diff --git a/src/app/zap-templates/zcl/zcl-with-test-extensions.json b/src/app/zap-templates/zcl/zcl-with-test-extensions.json index bc1a29c4b4aa3b..d8ee20e47bbbcd 100644 --- a/src/app/zap-templates/zcl/zcl-with-test-extensions.json +++ b/src/app/zap-templates/zcl/zcl-with-test-extensions.json @@ -29,6 +29,7 @@ "bridged-device-basic-information.xml", "chip-ota.xml", "channel-cluster.xml", + "chime-cluster.xml", "clusters-extensions.xml", "color-control-cluster.xml", "commissioner-control-cluster.xml", @@ -191,6 +192,7 @@ "MaxPathsPerInvoke" ], "Bridged Device Basic Information": ["ProductAppearance"], + "Chime": ["ActiveChimeSoundId", "Enabled"], "Descriptor": ["ClusterRevision", "FeatureMap"], "Device Energy Management": [ "ESAType", diff --git a/src/app/zap-templates/zcl/zcl.json b/src/app/zap-templates/zcl/zcl.json index db4526e39cbbde..7096ca88ddbac6 100644 --- a/src/app/zap-templates/zcl/zcl.json +++ b/src/app/zap-templates/zcl/zcl.json @@ -24,6 +24,7 @@ "bridged-device-basic-information.xml", "chip-ota.xml", "channel-cluster.xml", + "chime-cluster.xml", "clusters-extensions.xml", "color-control-cluster.xml", "commissioner-control-cluster.xml", @@ -185,6 +186,7 @@ "MaxPathsPerInvoke" ], "Bridged Device Basic Information": ["ProductAppearance"], + "Chime": ["ActiveChimeSoundId", "Enabled"], "Descriptor": ["ClusterRevision", "FeatureMap"], "Device Energy Management": [ "ESAType", diff --git a/src/app/zap_cluster_list.json b/src/app/zap_cluster_list.json index a047340147ece5..f24bbd93f20f9f 100644 --- a/src/app/zap_cluster_list.json +++ b/src/app/zap_cluster_list.json @@ -165,6 +165,7 @@ "concentration-measurement-server" ], "CHANNEL_CLUSTER": ["channel-server"], + "CHIME_CLUSTER": ["chime-server"], "COLOR_CONTROL_CLUSTER": ["color-control-server"], "COMMISSIONER_CONTROL_CLUSTER": ["commissioner-control-server"], "COMMISSIONING_CLUSTER": [], diff --git a/src/controller/data_model/controller-clusters.zap b/src/controller/data_model/controller-clusters.zap index 1a1f8539267101..8c1eba99077039 100644 --- a/src/controller/data_model/controller-clusters.zap +++ b/src/controller/data_model/controller-clusters.zap @@ -2955,6 +2955,25 @@ } ] }, + { + "name": "Chime", + "code": 1366, + "mfgCode": null, + "define": "CHIME_CLUSTER", + "side": "client", + "enabled": 1, + "apiMaturity": "provisional", + "commands": [ + { + "name": "PlayChimeSound", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + } + ] + }, { "name": "Unit Testing", "code": 4294048773,