-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Chime Cluster Definition and server code #35729
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <app/AttributeAccessInterfaceRegistry.h> | ||
#include <app/CommandHandlerInterfaceRegistry.h> | ||
#include <app/ConcreteAttributePath.h> | ||
#include <app/InteractionModelEngine.h> | ||
#include <app/util/attribute-storage.h> | ||
#include <app/util/util.h> | ||
#include <protocols/interaction_model/StatusCode.h> | ||
|
||
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()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be better if the simple things that can be stored in the cluster were stored there, so we can mark things dirty properly on changes. |
||
|
||
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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, but the write path is not calling this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, that's an error |
||
{ | ||
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<Commands::PlayChimeSound::DecodableType>( | ||
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(){} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <app-common/zap-generated/cluster-objects.h> | ||
#include <app/AttributeAccessInterface.h> | ||
#include <app/CommandHandlerInterface.h> | ||
#include <app/ConcreteAttributePath.h> | ||
#include <app/InteractionModelEngine.h> | ||
#include <app/MessageDef/StatusIB.h> | ||
#include <app/reporting/reporting.h> | ||
#include <app/util/attribute-storage.h> | ||
#include <lib/core/CHIPError.h> | ||
#include <protocols/interaction_model/StatusCode.h> | ||
|
||
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<const Chime::Structs::ChimeSoundStruct::Type>& GetInstalledChimeSounds() = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the lifetime of the buffer backing that list? How does the delegate know to not deallocate it? Also, it it intentional that this implementation does not allow chunking the list? |
||
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 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
<?xml version="1.0"?> | ||
<!-- | ||
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. | ||
--> | ||
<configurator> | ||
<domain name="CHIP"/> | ||
|
||
<struct name="ChimeSoundStruct" apiMaturity="provisional"> | ||
<cluster code="0x0556"/> | ||
<item name="ChimeId" type="int8u"/> | ||
<item name="Name" type="char_string" max="48"/> | ||
</struct> | ||
|
||
<cluster apiMaturity="provisional"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where is the spec for this? I don't see it in the Matter appclusters spec on "master".... It's impossible to review this XML without the spec. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's in the Cameras branch |
||
<name>Chime</name> | ||
<domain>Camera</domain> | ||
<code>0x0556</code> | ||
<define>CHIME_CLUSTER</define> | ||
<description>Attributes and commands to configure and play Chime sounds</description> | ||
|
||
<!-- cluster revision --> | ||
<globalAttribute side="either" code="0xFFFD" value="1"/> | ||
|
||
<attribute side="server" code="0x0000" define="CHIME_INSTALLED_CHIME_SOUNDS" type="array" entryType="ChimeSoundStruct" min="1" max="255" writable="false" optional="false"> | ||
<description>InstalledChimeSounds</description> | ||
<access op="read" privilege="view"/> | ||
</attribute> | ||
<attribute side="server" code="0x0001" define="CHIME_ACTIVE_CHIME_SOUND_ID" type="int8u" default="0x00" optional="false"> | ||
<description>ActiveChimeSoundId</description> | ||
<access op="read" privilege="view"/> | ||
<access op="write" privilege="operate"/> | ||
</attribute> | ||
<attribute side="server" code="0x0002" define="CHIME_ENABLED" type="boolean" default="1" optional="false"> | ||
<description>Enabled</description> | ||
<access op="read" privilege="view"/> | ||
<access op="write" privilege="operate"/> | ||
</attribute> | ||
|
||
<command source="client" code="0x00" name="PlayChimeSound" optional="false"> | ||
<description>Plays the currently active chime sound.</description> | ||
<access op="invoke" privilege="operate"/> | ||
</command> | ||
|
||
</cluster> | ||
</configurator> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally, the implementation would be a separate PR from adding the XML.