Skip to content

Commit

Permalink
Added Chime Server
Browse files Browse the repository at this point in the history
  • Loading branch information
andyg-apple committed Oct 4, 2024
1 parent 965a377 commit 11509b3
Show file tree
Hide file tree
Showing 7 changed files with 326 additions and 1 deletion.
191 changes: 191 additions & 0 deletions src/app/clusters/chime-server/chime-server.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@

/*
*
* 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;
if ((err = this->mDelegate.GetChimeSoundByIndex(index, chimeSound)) == CHIP_NO_ERROR)
{
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());

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)
{
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)
{
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);
~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;
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;

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"],
"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"],
"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

0 comments on commit 11509b3

Please sign in to comment.