Skip to content
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 server #35892

Merged
merged 13 commits into from
Oct 25, 2024
Merged
4,029 changes: 1,877 additions & 2,152 deletions scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/endpoint_config.h

Large diffs are not rendered by default.

Large diffs are not rendered by default.

185 changes: 185 additions & 0 deletions src/app/clusters/chime-server/chime-server.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@

/*
*
andyg-apple marked this conversation as resolved.
Show resolved Hide resolved
* 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.EncodeList([this](const auto & encoder) -> CHIP_ERROR {
uint8_t index = 0;
CHIP_ERROR err = CHIP_NO_ERROR;

// runs through all the Chime sounds available one by one
do
{
Chime::Structs::ChimeSoundStruct::Type chimeSound;
andyg-apple marked this conversation as resolved.
Show resolved Hide resolved
if ((err = this->mDelegate.GetChimeSoundByIndex(index, chimeSound)) == CHIP_NO_ERROR)
andyg-apple marked this conversation as resolved.
Show resolved Hide resolved
{
ReturnErrorOnFailure(encoder.Encode(chimeSound));
index++;
}
} while (err == CHIP_NO_ERROR);

if (err == CHIP_ERROR_NOT_FOUND)
{
return CHIP_NO_ERROR;
}
return err;
});

case ActiveChimeID::Id:
return aEncoder.Encode(mDelegate.GetActiveChimeId());
andyg-apple marked this conversation as resolved.
Show resolved Hide resolved

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 ActiveChimeID::Id: {
uint8_t newValue;
ReturnErrorOnFailure(aDecoder.Decode(newValue));
ReturnErrorOnFailure(mDelegate.SetActiveChimeId(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::SetActiveChimeId(uint8_t soundId)
andyg-apple marked this conversation as resolved.
Show resolved Hide resolved
{
uint8_t currentSoundId = mDelegate.GetActiveChimeId();
bool activeIdChanged = !(currentSoundId == soundId);

VerifyOrReturnError(activeIdChanged, CHIP_NO_ERROR);
VerifyOrDie(mDelegate.SetActiveChimeId(soundId) == CHIP_NO_ERROR);
MatterReportingAttributeChangeCallback(GetEndpointId(), Chime::Id, ActiveChimeID::Id);

return CHIP_NO_ERROR;
}

CHIP_ERROR ChimeServer::SetEnabled(bool enabled)
andyg-apple marked this conversation as resolved.
Show resolved Hide resolved
{
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() {}
112 changes: 112 additions & 0 deletions src/app/clusters/chime-server/chime-server.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
*
* 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);
andyg-apple marked this conversation as resolved.
Show resolved Hide resolved
~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 SetActiveChimeId(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

/**
* Get the chime sounds.
* @param index The index of the chime sound to be returned. It is assumed that chime sounds are indexable from 0 and with no
* gaps.
* @param chimeSound A reference to receive the chime sound struct on success.
* @return Returns a CHIP_NO_ERROR if there was no error and the chime sound was returned successfully,
* CHIP_ERROR_NOT_FOUND if the index in beyond the list of available chime sounds.
*/
virtual CHIP_ERROR GetChimeSoundByIndex(uint8_t index, Chime::Structs::ChimeSoundStruct::Type & chimeSound) = 0;
virtual uint8_t GetActiveChimeId() = 0;
andyg-apple marked this conversation as resolved.
Show resolved Hide resolved
virtual bool GetEnabled() = 0;

// Set Attribute Methods
virtual CHIP_ERROR SetActiveChimeId(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;
andyg-apple marked this conversation as resolved.
Show resolved Hide resolved

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
1 change: 1 addition & 0 deletions src/app/common/templates/config-data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ CommandHandlerInterfaceOnlyClusters:
- RVC Operational State
- Sample MEI
- Microwave Oven Control
- Chime
- Energy EVSE
- Energy EVSE Mode
- Device Energy Management
Expand Down
1 change: 1 addition & 0 deletions src/app/zap-templates/zcl/zcl-with-test-extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@
"MaxPathsPerInvoke"
],
"Bridged Device Basic Information": ["ProductAppearance"],
"Chime": ["InstalledChimeSounds"],
andyg-apple marked this conversation as resolved.
Show resolved Hide resolved
"Descriptor": ["ClusterRevision", "FeatureMap"],
"Device Energy Management": [
"ESAType",
Expand Down
1 change: 1 addition & 0 deletions src/app/zap-templates/zcl/zcl.json
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@
"MaxPathsPerInvoke"
],
"Bridged Device Basic Information": ["ProductAppearance"],
"Chime": ["InstalledChimeSounds"],
andyg-apple marked this conversation as resolved.
Show resolved Hide resolved
"Descriptor": ["ClusterRevision", "FeatureMap"],
"Device Energy Management": [
"ESAType",
Expand Down
2 changes: 1 addition & 1 deletion src/app/zap_cluster_list.json
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@
"concentration-measurement-server"
],
"CHANNEL_CLUSTER": ["channel-server"],
"CHIME_CLUSTER": [],
"CHIME_CLUSTER": ["chime-server"],
"COLOR_CONTROL_CLUSTER": ["color-control-server"],
"COMMISSIONER_CONTROL_CLUSTER": ["commissioner-control-server"],
"COMMISSIONING_CLUSTER": [],
Expand Down
19 changes: 19 additions & 0 deletions src/controller/data_model/controller-clusters.zap
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading
Loading