Skip to content

Commit 73ce1c0

Browse files
committed
Binding manager initial implementation
1 parent 64259a5 commit 73ce1c0

File tree

5 files changed

+368
-0
lines changed

5 files changed

+368
-0
lines changed

examples/oven-app/oven-app-common/oven-app.zap

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,112 @@
217217
}
218218
]
219219
},
220+
{
221+
"name": "Binding",
222+
"code": 30,
223+
"mfgCode": null,
224+
"define": "BINDING_CLUSTER",
225+
"side": "server",
226+
"enabled": 1,
227+
"attributes": [
228+
{
229+
"name": "Binding",
230+
"code": 0,
231+
"mfgCode": null,
232+
"side": "server",
233+
"type": "array",
234+
"included": 1,
235+
"storageOption": "External",
236+
"singleton": 0,
237+
"bounded": 0,
238+
"defaultValue": null,
239+
"reportable": 1,
240+
"minInterval": 1,
241+
"maxInterval": 65534,
242+
"reportableChange": 0
243+
},
244+
{
245+
"name": "GeneratedCommandList",
246+
"code": 65528,
247+
"mfgCode": null,
248+
"side": "server",
249+
"type": "array",
250+
"included": 1,
251+
"storageOption": "External",
252+
"singleton": 0,
253+
"bounded": 0,
254+
"defaultValue": null,
255+
"reportable": 1,
256+
"minInterval": 1,
257+
"maxInterval": 65534,
258+
"reportableChange": 0
259+
},
260+
{
261+
"name": "AcceptedCommandList",
262+
"code": 65529,
263+
"mfgCode": null,
264+
"side": "server",
265+
"type": "array",
266+
"included": 1,
267+
"storageOption": "External",
268+
"singleton": 0,
269+
"bounded": 0,
270+
"defaultValue": null,
271+
"reportable": 1,
272+
"minInterval": 1,
273+
"maxInterval": 65534,
274+
"reportableChange": 0
275+
},
276+
{
277+
"name": "AttributeList",
278+
"code": 65531,
279+
"mfgCode": null,
280+
"side": "server",
281+
"type": "array",
282+
"included": 1,
283+
"storageOption": "External",
284+
"singleton": 0,
285+
"bounded": 0,
286+
"defaultValue": null,
287+
"reportable": 1,
288+
"minInterval": 1,
289+
"maxInterval": 65534,
290+
"reportableChange": 0
291+
},
292+
{
293+
"name": "FeatureMap",
294+
"code": 65532,
295+
"mfgCode": null,
296+
"side": "server",
297+
"type": "bitmap32",
298+
"included": 1,
299+
"storageOption": "External",
300+
"singleton": 0,
301+
"bounded": 0,
302+
"defaultValue": null,
303+
"reportable": 1,
304+
"minInterval": 1,
305+
"maxInterval": 65534,
306+
"reportableChange": 0
307+
},
308+
{
309+
"name": "ClusterRevision",
310+
"code": 65533,
311+
"mfgCode": null,
312+
"side": "server",
313+
"type": "int16u",
314+
"included": 1,
315+
"storageOption": "External",
316+
"singleton": 0,
317+
"bounded": 0,
318+
"defaultValue": null,
319+
"reportable": 1,
320+
"minInterval": 1,
321+
"maxInterval": 65534,
322+
"reportableChange": 0
323+
}
324+
]
325+
},
220326
{
221327
"name": "Access Control",
222328
"code": 31,
@@ -5003,6 +5109,24 @@
50035109
"deviceTypeCode": 120,
50045110
"deviceTypeProfileId": 259,
50055111
"clusters": [
5112+
{
5113+
"name": "On/Off",
5114+
"code": 6,
5115+
"mfgCode": null,
5116+
"define": "ON_OFF_CLUSTER",
5117+
"side": "client",
5118+
"enabled": 1,
5119+
"commands": [
5120+
{
5121+
"name": "Off",
5122+
"code": 0,
5123+
"mfgCode": null,
5124+
"source": "client",
5125+
"isIncoming": 0,
5126+
"isEnabled": 1
5127+
}
5128+
]
5129+
},
50065130
{
50075131
"name": "On/Off",
50085132
"code": 6,
@@ -5272,6 +5396,120 @@
52725396
"reportableChange": 0
52735397
}
52745398
]
5399+
},
5400+
{
5401+
"name": "Binding",
5402+
"code": 30,
5403+
"mfgCode": null,
5404+
"define": "BINDING_CLUSTER",
5405+
"side": "server",
5406+
"enabled": 1,
5407+
"attributes": [
5408+
{
5409+
"name": "Binding",
5410+
"code": 0,
5411+
"mfgCode": null,
5412+
"side": "server",
5413+
"type": "array",
5414+
"included": 1,
5415+
"storageOption": "External",
5416+
"singleton": 0,
5417+
"bounded": 0,
5418+
"defaultValue": null,
5419+
"reportable": 1,
5420+
"minInterval": 1,
5421+
"maxInterval": 65534,
5422+
"reportableChange": 0
5423+
},
5424+
{
5425+
"name": "GeneratedCommandList",
5426+
"code": 65528,
5427+
"mfgCode": null,
5428+
"side": "server",
5429+
"type": "array",
5430+
"included": 1,
5431+
"storageOption": "External",
5432+
"singleton": 0,
5433+
"bounded": 0,
5434+
"defaultValue": null,
5435+
"reportable": 1,
5436+
"minInterval": 1,
5437+
"maxInterval": 65534,
5438+
"reportableChange": 0
5439+
},
5440+
{
5441+
"name": "AcceptedCommandList",
5442+
"code": 65529,
5443+
"mfgCode": null,
5444+
"side": "server",
5445+
"type": "array",
5446+
"included": 1,
5447+
"storageOption": "External",
5448+
"singleton": 0,
5449+
"bounded": 0,
5450+
"defaultValue": null,
5451+
"reportable": 1,
5452+
"minInterval": 1,
5453+
"maxInterval": 65534,
5454+
"reportableChange": 0
5455+
},
5456+
{
5457+
"name": "AttributeList",
5458+
"code": 65531,
5459+
"mfgCode": null,
5460+
"side": "server",
5461+
"type": "array",
5462+
"included": 1,
5463+
"storageOption": "External",
5464+
"singleton": 0,
5465+
"bounded": 0,
5466+
"defaultValue": null,
5467+
"reportable": 1,
5468+
"minInterval": 1,
5469+
"maxInterval": 65534,
5470+
"reportableChange": 0
5471+
},
5472+
{
5473+
"name": "FeatureMap",
5474+
"code": 65532,
5475+
"mfgCode": null,
5476+
"side": "server",
5477+
"type": "bitmap32",
5478+
"included": 1,
5479+
"storageOption": "External",
5480+
"singleton": 0,
5481+
"bounded": 0,
5482+
"defaultValue": null,
5483+
"reportable": 1,
5484+
"minInterval": 1,
5485+
"maxInterval": 65534,
5486+
"reportableChange": 0
5487+
},
5488+
{
5489+
"name": "ClusterRevision",
5490+
"code": 65533,
5491+
"mfgCode": null,
5492+
"side": "server",
5493+
"type": "int16u",
5494+
"included": 1,
5495+
"storageOption": "External",
5496+
"singleton": 0,
5497+
"bounded": 0,
5498+
"defaultValue": null,
5499+
"reportable": 1,
5500+
"minInterval": 1,
5501+
"maxInterval": 65534,
5502+
"reportableChange": 0
5503+
}
5504+
]
5505+
},
5506+
{
5507+
"name": "Fan Control",
5508+
"code": 514,
5509+
"mfgCode": null,
5510+
"define": "FAN_CONTROL_CLUSTER",
5511+
"side": "client",
5512+
"enabled": 1
52755513
}
52765514
]
52775515
},

examples/oven-app/silabs/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ silabs_executable("oven_app") {
109109
"src/AppSupportedTemperatureLevelsDelegate.cpp",
110110
"src/AppTask.cpp",
111111
"src/DataModelCallbacks.cpp",
112+
"src/OvenBindingHandler.cpp",
112113
"src/OvenManager.cpp",
113114
]
114115

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Oven Binding Handler - derived from light-switch-app BindingHandler
3+
*/
4+
#pragma once
5+
6+
#include <app-common/zap-generated/ids/Clusters.h>
7+
#include <app-common/zap-generated/ids/Commands.h>
8+
#include <lib/core/CHIPError.h>
9+
#include <lib/core/CHIPCallback.h>
10+
#include <app/util/basic-types.h>
11+
12+
struct OnOffBindingContext
13+
{
14+
chip::EndpointId localEndpointId;
15+
chip::CommandId commandId;
16+
};
17+
18+
// Initialize binding manager (schedules init work)
19+
CHIP_ERROR InitOvenBindingHandler();
20+
21+
// Notify that CookTop OnOff cluster changed using pre-filled context
22+
void CookTopOnOffBindingTrigger(OnOffBindingContext * context);
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* OvenBindingHandler.cpp
3+
* Simplified binding command propagation for CookTop OnOff changes.
4+
*/
5+
6+
#include "OvenBindingHandler.h"
7+
#include "AppConfig.h"
8+
#include <app/clusters/bindings/BindingManager.h>
9+
#include <app/server/Server.h>
10+
#include <controller/InvokeInteraction.h>
11+
#include <lib/support/CodeUtils.h>
12+
#include <platform/CHIPDeviceLayer.h>
13+
14+
using namespace chip;
15+
using namespace chip::app;
16+
using namespace chip::app::Clusters;
17+
18+
namespace {
19+
20+
void ProcessOnOffUnicast(CommandId commandId, const Binding::TableEntry & binding, Messaging::ExchangeManager * exchangeMgr,
21+
const SessionHandle & sessionHandle)
22+
{
23+
auto onSuccess = [](const ConcreteCommandPath &, const StatusIB &, const auto &) {
24+
ChipLogProgress(AppServer, "CookTop OnOff bound unicast command success");
25+
};
26+
auto onFailure = [](CHIP_ERROR error) { ChipLogError(AppServer, "CookTop OnOff bound unicast failed: %s", error.AsString()); };
27+
28+
switch (commandId)
29+
{
30+
case Clusters::OnOff::Commands::On::Id: {
31+
Clusters::OnOff::Commands::On::Type cmd;
32+
Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, cmd, onSuccess, onFailure);
33+
break;
34+
}
35+
case Clusters::OnOff::Commands::Off::Id: {
36+
Clusters::OnOff::Commands::Off::Type cmd;
37+
Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, cmd, onSuccess, onFailure);
38+
break;
39+
}
40+
default:
41+
break;
42+
}
43+
}
44+
45+
void BoundDeviceChangedHandler(const Binding::TableEntry & binding, OperationalDeviceProxy * peerDevice, void * context)
46+
{
47+
VerifyOrReturn(context != nullptr);
48+
auto * data = static_cast<OnOffBindingContext *>(context);
49+
50+
if (binding.clusterId != Clusters::OnOff::Id)
51+
{
52+
return; // Only propagate OnOff
53+
}
54+
55+
// Only handle unicast bindings - groups are not supported
56+
if (binding.type == Binding::MATTER_UNICAST_BINDING)
57+
{
58+
VerifyOrReturn(peerDevice != nullptr && peerDevice->ConnectionReady());
59+
ProcessOnOffUnicast(data->commandId, binding, peerDevice->GetExchangeManager(), peerDevice->GetSecureSession().Value());
60+
}
61+
}
62+
63+
void ContextReleaseHandler(void * context)
64+
{
65+
if (context)
66+
{
67+
Platform::Delete(static_cast<OnOffBindingContext *>(context));
68+
}
69+
}
70+
71+
void InitBindingMgrWork(intptr_t)
72+
{
73+
auto & server = Server::GetInstance();
74+
Binding::Manager::GetInstance().Init(
75+
{ &server.GetFabricTable(), server.GetCASESessionManager(), &server.GetPersistentStorage() });
76+
Binding::Manager::GetInstance().RegisterBoundDeviceChangedHandler(BoundDeviceChangedHandler);
77+
Binding::Manager::GetInstance().RegisterBoundDeviceContextReleaseHandler(ContextReleaseHandler);
78+
ChipLogProgress(AppServer, "Oven binding manager initialized");
79+
}
80+
81+
void TriggerBindingWork(intptr_t context)
82+
{
83+
auto * ctx = reinterpret_cast<OnOffBindingContext *>(context);
84+
VerifyOrReturn(ctx != nullptr, ChipLogError(AppServer, "TriggerBindingWork: null context"));
85+
86+
// Notify all OnOff bindings from the specified endpoint
87+
Binding::Manager::GetInstance().NotifyBoundClusterChanged(ctx->localEndpointId, Clusters::OnOff::Id, ctx);
88+
}
89+
90+
} // namespace
91+
92+
CHIP_ERROR InitOvenBindingHandler()
93+
{
94+
DeviceLayer::PlatformMgr().ScheduleWork(InitBindingMgrWork);
95+
return CHIP_NO_ERROR;
96+
}
97+
98+
void CookTopOnOffBindingTrigger(OnOffBindingContext * context)
99+
{
100+
VerifyOrReturn(context != nullptr, ChipLogError(AppServer, "CookTopOnOffBindingTrigger: null context"));
101+
DeviceLayer::PlatformMgr().ScheduleWork(TriggerBindingWork, reinterpret_cast<intptr_t>(context));
102+
}

0 commit comments

Comments
 (0)