Skip to content

Commit 11509b3

Browse files
committed
Added Chime Server
1 parent 965a377 commit 11509b3

File tree

7 files changed

+326
-1
lines changed

7 files changed

+326
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
2+
/*
3+
*
4+
* Copyright (c) 2024 Project CHIP Authors
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
/****************************************************************************'
20+
* @file
21+
* @brief Implementation for the Chime Server Cluster
22+
***************************************************************************/
23+
24+
25+
#include "chime-server.h"
26+
27+
#include <app/AttributeAccessInterfaceRegistry.h>
28+
#include <app/CommandHandlerInterfaceRegistry.h>
29+
#include <app/ConcreteAttributePath.h>
30+
#include <app/InteractionModelEngine.h>
31+
#include <app/util/attribute-storage.h>
32+
#include <app/util/util.h>
33+
#include <protocols/interaction_model/StatusCode.h>
34+
35+
using namespace chip;
36+
using namespace chip::app;
37+
using namespace chip::app::DataModel;
38+
using namespace chip::app::Clusters;
39+
using namespace chip::app::Clusters::Chime;
40+
using namespace chip::app::Clusters::Chime::Attributes;
41+
using chip::Protocols::InteractionModel::Status;
42+
43+
44+
namespace chip {
45+
namespace app {
46+
namespace Clusters {
47+
48+
ChimeServer::ChimeServer(EndpointId endpointId, ChimeDelegate & delegate) :
49+
AttributeAccessInterface(MakeOptional(endpointId), Chime::Id),
50+
CommandHandlerInterface(MakeOptional(endpointId), Chime::Id), mDelegate(delegate)
51+
{
52+
mDelegate.SetChimeServer(this);
53+
}
54+
55+
ChimeServer::~ChimeServer()
56+
{
57+
AttributeAccessInterfaceRegistry::Instance().Unregister(this);
58+
CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this);
59+
}
60+
61+
62+
CHIP_ERROR ChimeServer::Init()
63+
{
64+
VerifyOrReturnError(AttributeAccessInterfaceRegistry::Instance().Register(this), CHIP_ERROR_INTERNAL);
65+
ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(this));
66+
return CHIP_NO_ERROR;
67+
}
68+
69+
// AttributeAccessInterface
70+
CHIP_ERROR ChimeServer::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
71+
{
72+
VerifyOrDie(aPath.mClusterId == Chime::Id);
73+
74+
switch (aPath.mAttributeId)
75+
{
76+
case InstalledChimeSounds::Id:
77+
return aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR {
78+
79+
uint8_t index = 0;
80+
CHIP_ERROR err = CHIP_NO_ERROR;
81+
82+
// runs through all the Chime sounds available one by one
83+
do
84+
{
85+
Chime::Structs::ChimeSoundStruct::Type chimeSound;
86+
if ((err = this->mDelegate.GetChimeSoundByIndex(index, chimeSound)) == CHIP_NO_ERROR)
87+
{
88+
ReturnErrorOnFailure(encoder.Encode(chimeSound));
89+
index++;
90+
}
91+
} while (err == CHIP_NO_ERROR);
92+
93+
if (err == CHIP_ERROR_NOT_FOUND)
94+
{
95+
return CHIP_NO_ERROR;
96+
}
97+
return err;
98+
});
99+
100+
case ActiveChimeID::Id:
101+
return aEncoder.Encode(mDelegate.GetActiveChimeId());
102+
103+
case Enabled::Id:
104+
return aEncoder.Encode(mDelegate.GetEnabled());
105+
}
106+
107+
return CHIP_NO_ERROR;
108+
}
109+
110+
CHIP_ERROR ChimeServer::Write(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder)
111+
{
112+
VerifyOrDie(aPath.mClusterId == Chime::Id);
113+
114+
switch (aPath.mAttributeId)
115+
{
116+
case ActiveChimeID::Id: {
117+
uint8_t newValue;
118+
ReturnErrorOnFailure(aDecoder.Decode(newValue));
119+
ReturnErrorOnFailure(mDelegate.SetActiveChimeId(newValue));
120+
return CHIP_NO_ERROR;
121+
122+
}
123+
case Enabled::Id: {
124+
bool newValue;
125+
ReturnErrorOnFailure(aDecoder.Decode(newValue));
126+
ReturnErrorOnFailure(mDelegate.SetEnabled(newValue));
127+
return CHIP_NO_ERROR;
128+
}
129+
130+
default:
131+
// Unknown attribute
132+
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
133+
}
134+
135+
}
136+
137+
CHIP_ERROR ChimeServer::SetActiveChimeId(uint8_t soundId)
138+
{
139+
uint8_t currentSoundId = mDelegate.GetActiveChimeId();
140+
bool activeIdChanged = !(currentSoundId == soundId);
141+
142+
VerifyOrReturnError(activeIdChanged, CHIP_NO_ERROR);
143+
VerifyOrDie(mDelegate.SetActiveChimeId(soundId) == CHIP_NO_ERROR);
144+
MatterReportingAttributeChangeCallback(GetEndpointId(), Chime::Id, ActiveChimeID::Id);
145+
146+
return CHIP_NO_ERROR;
147+
}
148+
149+
CHIP_ERROR ChimeServer::SetEnabled(bool enabled)
150+
{
151+
bool currentlyEnabled = mDelegate.GetEnabled();
152+
bool enableChanged = !(currentlyEnabled == enabled);
153+
154+
VerifyOrReturnError(enableChanged, CHIP_NO_ERROR);
155+
VerifyOrDie(mDelegate.SetEnabled(enabled) == CHIP_NO_ERROR);
156+
MatterReportingAttributeChangeCallback(GetEndpointId(), Chime::Id, Enabled::Id);
157+
158+
return CHIP_NO_ERROR;
159+
}
160+
161+
void ChimeServer::InvokeCommand(HandlerContext & ctx)
162+
{
163+
switch (ctx.mRequestPath.mCommandId)
164+
{
165+
case Commands::PlayChimeSound::Id:
166+
CommandHandlerInterface::HandleCommand<Commands::PlayChimeSound::DecodableType>(
167+
ctx, [this](HandlerContext & ctx, const auto & req) { HandlePlayChimeSound(ctx, req); });
168+
break;
169+
}
170+
}
171+
172+
void ChimeServer::HandlePlayChimeSound(HandlerContext & ctx, const Commands::PlayChimeSound::DecodableType & req)
173+
{
174+
175+
ChipLogDetail(Zcl, "Chime: PlayChimeSound");
176+
177+
// call the delegate to play the chime
178+
Status status = mDelegate.playChimeSound();
179+
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
180+
}
181+
182+
} // namespace Clusters
183+
} // namespace app
184+
} // namespace chip
185+
186+
/** @brief Chime Cluster Server Init
187+
*
188+
* Server Init
189+
*
190+
*/
191+
void MatterChimePluginServerInitCallback(){}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
*
3+
* Copyright (c) 2024 Project CHIP Authors
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#pragma once
20+
21+
#include <app-common/zap-generated/cluster-objects.h>
22+
#include <app/AttributeAccessInterface.h>
23+
#include <app/CommandHandlerInterface.h>
24+
#include <app/ConcreteAttributePath.h>
25+
#include <app/InteractionModelEngine.h>
26+
#include <app/MessageDef/StatusIB.h>
27+
#include <app/reporting/reporting.h>
28+
#include <app/util/attribute-storage.h>
29+
#include <lib/core/CHIPError.h>
30+
#include <protocols/interaction_model/StatusCode.h>
31+
32+
namespace chip {
33+
namespace app {
34+
namespace Clusters {
35+
36+
class ChimeDelegate;
37+
38+
class ChimeServer : private AttributeAccessInterface, private CommandHandlerInterface
39+
{
40+
public:
41+
ChimeServer(EndpointId endpointId, ChimeDelegate & delegate);
42+
~ChimeServer();
43+
44+
CHIP_ERROR Init();
45+
46+
private:
47+
ChimeDelegate & mDelegate;
48+
49+
EndpointId GetEndpointId() { return AttributeAccessInterface::GetEndpointId().Value(); }
50+
51+
// AttributeAccessInterface
52+
CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;
53+
CHIP_ERROR Write(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder) override;
54+
CHIP_ERROR SetActiveChimeId(uint8_t chimeSoundId);
55+
CHIP_ERROR SetEnabled(bool enabled);
56+
57+
// CommandHandlerInterface
58+
void InvokeCommand(HandlerContext & ctx) override;
59+
60+
void HandlePlayChimeSound(HandlerContext & ctx, const Chime::Commands::PlayChimeSound::DecodableType & req);
61+
};
62+
63+
/** @brief
64+
* Defines methods for implementing application-specific logic for the Chime Cluster.
65+
*/
66+
class ChimeDelegate
67+
{
68+
public:
69+
ChimeDelegate() = default;
70+
71+
virtual ~ChimeDelegate() = default;
72+
73+
// Get Attribute Methods
74+
75+
/**
76+
* Get the chime sounds.
77+
* @param index The index of the chime sound to be returned. It is assumed that chime sounds are indexable from 0 and with no
78+
* gaps.
79+
* @param chimeSound A reference to receive the chime sound struct on success.
80+
* @return Returns a CHIP_NO_ERROR if there was no error and the chime sound was returned successfully,
81+
* CHIP_ERROR_NOT_FOUND if the index in beyond the list of available chime sounds.
82+
*/
83+
virtual CHIP_ERROR GetChimeSoundByIndex(uint8_t index, Chime::Structs::ChimeSoundStruct::Type & chimeSound) = 0;
84+
virtual uint8_t GetActiveChimeId() = 0;
85+
virtual bool GetEnabled() = 0;
86+
87+
// Set Attribute Methods
88+
virtual CHIP_ERROR SetActiveChimeId(uint8_t chimeSoundId) = 0;
89+
virtual CHIP_ERROR SetEnabled(bool enabled) = 0;
90+
91+
// Commands
92+
/**
93+
* @brief Delegate should implement a handler to play the currently active chime sound.
94+
* It should report Status::Success if successful and may
95+
* return other Status codes if it fails
96+
*/
97+
virtual Protocols::InteractionModel::Status playChimeSound() = 0;
98+
99+
private:
100+
friend class ChimeServer;
101+
102+
ChimeServer * mChimeServer = nullptr;
103+
104+
void SetChimeServer(ChimeServer * chimeServer) { mChimeServer = chimeServer; }
105+
106+
protected:
107+
ChimeServer * GetChimeServer() const { return mChimeServer; }
108+
};
109+
110+
} // namespace Clusters
111+
} // namespace app
112+
} // namespace chip

src/app/common/templates/config-data.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ CommandHandlerInterfaceOnlyClusters:
3636
- RVC Operational State
3737
- Sample MEI
3838
- Microwave Oven Control
39+
- Chime
3940
- Energy EVSE
4041
- Energy EVSE Mode
4142
- Device Energy Management

src/app/zap-templates/zcl/zcl-with-test-extensions.json

+1
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@
193193
"MaxPathsPerInvoke"
194194
],
195195
"Bridged Device Basic Information": ["ProductAppearance"],
196+
"Chime": ["InstalledChimeSounds"],
196197
"Descriptor": ["ClusterRevision", "FeatureMap"],
197198
"Device Energy Management": [
198199
"ESAType",

src/app/zap-templates/zcl/zcl.json

+1
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@
187187
"MaxPathsPerInvoke"
188188
],
189189
"Bridged Device Basic Information": ["ProductAppearance"],
190+
"Chime": ["InstalledChimeSounds"],
190191
"Descriptor": ["ClusterRevision", "FeatureMap"],
191192
"Device Energy Management": [
192193
"ESAType",

src/app/zap_cluster_list.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@
167167
"concentration-measurement-server"
168168
],
169169
"CHANNEL_CLUSTER": ["channel-server"],
170-
"CHIME_CLUSTER": [],
170+
"CHIME_CLUSTER": ["chime-server"],
171171
"COLOR_CONTROL_CLUSTER": ["color-control-server"],
172172
"COMMISSIONER_CONTROL_CLUSTER": ["commissioner-control-server"],
173173
"COMMISSIONING_CLUSTER": [],

src/controller/data_model/controller-clusters.zap

+19
Original file line numberDiff line numberDiff line change
@@ -2955,6 +2955,25 @@
29552955
}
29562956
]
29572957
},
2958+
{
2959+
"name": "Chime",
2960+
"code": 1366,
2961+
"mfgCode": null,
2962+
"define": "CHIME_CLUSTER",
2963+
"side": "client",
2964+
"enabled": 1,
2965+
"apiMaturity": "provisional",
2966+
"commands": [
2967+
{
2968+
"name": "PlayChimeSound",
2969+
"code": 0,
2970+
"mfgCode": null,
2971+
"source": "client",
2972+
"isIncoming": 0,
2973+
"isEnabled": 1
2974+
}
2975+
]
2976+
},
29582977
{
29592978
"name": "Unit Testing",
29602979
"code": 4294048773,

0 commit comments

Comments
 (0)