@matter-server/ws-controller 0.7.0-alpha.0-20260512-b404bea → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/controller/ControllerCommandHandler.d.ts +10 -0
- package/dist/esm/controller/ControllerCommandHandler.d.ts.map +1 -1
- package/dist/esm/controller/ControllerCommandHandler.js +93 -24
- package/dist/esm/controller/ControllerCommandHandler.js.map +1 -1
- package/dist/esm/controller/MatterController.d.ts +7 -2
- package/dist/esm/controller/MatterController.d.ts.map +1 -1
- package/dist/esm/controller/MatterController.js +46 -3
- package/dist/esm/controller/MatterController.js.map +1 -1
- package/dist/esm/controller/Nodes.d.ts +7 -61
- package/dist/esm/controller/Nodes.d.ts.map +1 -1
- package/dist/esm/controller/Nodes.js +13 -77
- package/dist/esm/controller/Nodes.js.map +1 -1
- package/dist/esm/controller/WebRtcCallbackBridge.d.ts +9 -0
- package/dist/esm/controller/WebRtcCallbackBridge.d.ts.map +1 -0
- package/dist/esm/controller/WebRtcCallbackBridge.js +75 -0
- package/dist/esm/controller/WebRtcCallbackBridge.js.map +6 -0
- package/dist/esm/controller/behaviors/WebRtcTransportRequestorServer.d.ts +35 -0
- package/dist/esm/controller/behaviors/WebRtcTransportRequestorServer.d.ts.map +1 -0
- package/dist/esm/controller/behaviors/WebRtcTransportRequestorServer.js +123 -0
- package/dist/esm/controller/behaviors/WebRtcTransportRequestorServer.js.map +6 -0
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +3 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/server/WebSocketControllerHandler.d.ts.map +1 -1
- package/dist/esm/server/WebSocketControllerHandler.js +17 -0
- package/dist/esm/server/WebSocketControllerHandler.js.map +1 -1
- package/package.json +22 -21
- package/src/controller/ControllerCommandHandler.ts +121 -42
- package/src/controller/MatterController.ts +54 -4
- package/src/controller/Nodes.ts +13 -78
- package/src/controller/WebRtcCallbackBridge.ts +79 -0
- package/src/controller/behaviors/WebRtcTransportRequestorServer.ts +149 -0
- package/src/index.ts +2 -1
- package/src/server/WebSocketControllerHandler.ts +24 -0
|
@@ -9,33 +9,21 @@ import { AttributeDataCache } from "./AttributeDataCache.js";
|
|
|
9
9
|
class Nodes {
|
|
10
10
|
#nodes = /* @__PURE__ */ new Map();
|
|
11
11
|
#attributeCache = new AttributeDataCache();
|
|
12
|
-
/**
|
|
13
|
-
#previousStates = /* @__PURE__ */ new Map();
|
|
14
|
-
/** Cached availability so serialization and event paths always agree */
|
|
12
|
+
/** Cached so serialization and event paths always agree on availability. */
|
|
15
13
|
#lastAvailability = /* @__PURE__ */ new Map();
|
|
16
14
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* (e.g., Home Assistant) can resolve node.endpoints[endpoint_id] in their callback.
|
|
15
|
+
* Buffered endpoint_added events. python-matter-server wire contract requires
|
|
16
|
+
* node_updated (carrying the new endpoint) to arrive before endpoint_added,
|
|
17
|
+
* so HA can resolve node.endpoints[endpoint_id] in its callback.
|
|
21
18
|
*/
|
|
22
19
|
#pendingEndpointAdds = /* @__PURE__ */ new Map();
|
|
23
|
-
/**
|
|
24
|
-
* Get the attribute cache instance.
|
|
25
|
-
*/
|
|
26
20
|
get attributeCache() {
|
|
27
21
|
return this.#attributeCache;
|
|
28
22
|
}
|
|
29
|
-
/**
|
|
30
|
-
* Get all node IDs.
|
|
31
|
-
*/
|
|
32
23
|
getIds() {
|
|
33
24
|
return Array.from(this.#nodes.keys());
|
|
34
25
|
}
|
|
35
|
-
/**
|
|
36
|
-
* Get a node by ID.
|
|
37
|
-
* @throws ServerError if node not found
|
|
38
|
-
*/
|
|
26
|
+
/** @throws ServerError if node not found */
|
|
39
27
|
get(nodeId) {
|
|
40
28
|
const node = this.#nodes.get(nodeId);
|
|
41
29
|
if (node === void 0) {
|
|
@@ -43,31 +31,18 @@ class Nodes {
|
|
|
43
31
|
}
|
|
44
32
|
return node;
|
|
45
33
|
}
|
|
46
|
-
/**
|
|
47
|
-
* Check if a node exists.
|
|
48
|
-
*/
|
|
49
34
|
has(nodeId) {
|
|
50
35
|
return this.#nodes.has(nodeId);
|
|
51
36
|
}
|
|
52
|
-
/**
|
|
53
|
-
* Add or update a node in storage.
|
|
54
|
-
*/
|
|
55
37
|
set(nodeId, node) {
|
|
56
38
|
this.#nodes.set(nodeId, node);
|
|
57
39
|
}
|
|
58
|
-
/**
|
|
59
|
-
* Remove a node from storage and clear its attribute cache and state tracking.
|
|
60
|
-
*/
|
|
61
40
|
delete(nodeId) {
|
|
62
41
|
this.#nodes.delete(nodeId);
|
|
63
42
|
this.#attributeCache.delete(nodeId);
|
|
64
|
-
this.#previousStates.delete(nodeId);
|
|
65
43
|
this.#lastAvailability.delete(nodeId);
|
|
66
44
|
this.#pendingEndpointAdds.delete(nodeId);
|
|
67
45
|
}
|
|
68
|
-
/**
|
|
69
|
-
* Buffer an endpoint_added until the next nodeStructureChanged for that node.
|
|
70
|
-
*/
|
|
71
46
|
queueEndpointAdded(nodeId, endpointId) {
|
|
72
47
|
let queue = this.#pendingEndpointAdds.get(nodeId);
|
|
73
48
|
if (queue === void 0) {
|
|
@@ -76,10 +51,7 @@ class Nodes {
|
|
|
76
51
|
}
|
|
77
52
|
queue.push(endpointId);
|
|
78
53
|
}
|
|
79
|
-
/**
|
|
80
|
-
* Take ownership of buffered endpoint additions for a node and clear the queue.
|
|
81
|
-
* Returned array is in insertion order; an empty array is returned if nothing is queued.
|
|
82
|
-
*/
|
|
54
|
+
/** Returns insertion-ordered queue; empty if nothing pending. */
|
|
83
55
|
drainPendingEndpointAdds(nodeId) {
|
|
84
56
|
const queue = this.#pendingEndpointAdds.get(nodeId);
|
|
85
57
|
if (queue === void 0 || queue.length === 0) {
|
|
@@ -88,68 +60,32 @@ class Nodes {
|
|
|
88
60
|
this.#pendingEndpointAdds.delete(nodeId);
|
|
89
61
|
return queue;
|
|
90
62
|
}
|
|
91
|
-
/**
|
|
92
|
-
* Initialize state tracking for a newly paired/discovered node.
|
|
93
|
-
* Sets previous state and initial availability so the first stateChanged event
|
|
94
|
-
* has a real previous state instead of undefined.
|
|
95
|
-
*/
|
|
96
63
|
seedState(nodeId, initialState) {
|
|
97
|
-
this.#previousStates.set(nodeId, initialState);
|
|
98
64
|
this.#lastAvailability.set(nodeId, initialState === NodeStates.Connected);
|
|
99
65
|
}
|
|
100
|
-
/**
|
|
101
|
-
|
|
102
|
-
* computes new availability, and updates both tracking maps atomically.
|
|
103
|
-
* Returns whether availability changed and the new value.
|
|
104
|
-
*/
|
|
105
|
-
processStateChange(nodeId, newState) {
|
|
106
|
-
const previousState = this.#previousStates.get(nodeId);
|
|
66
|
+
/** `debouncePending` = reconnect timer armed by caller; keeps non-Connected states available. */
|
|
67
|
+
processStateChange(nodeId, newState, debouncePending) {
|
|
107
68
|
const wasAvailable = this.#lastAvailability.get(nodeId) ?? false;
|
|
108
|
-
const available = this.isNodeAvailable(newState,
|
|
109
|
-
this.#previousStates.set(nodeId, newState);
|
|
69
|
+
const available = this.isNodeAvailable(newState, debouncePending);
|
|
110
70
|
this.#lastAvailability.set(nodeId, available);
|
|
111
71
|
if (wasAvailable !== available) {
|
|
112
72
|
return { availabilityChanged: true, available };
|
|
113
73
|
}
|
|
114
74
|
return { availabilityChanged: false };
|
|
115
75
|
}
|
|
116
|
-
/**
|
|
117
|
-
* Force a node to unavailable state. Used by reconnect timeout
|
|
118
|
-
* when debounce period expires without reconnection.
|
|
119
|
-
* Only updates #lastAvailability — #previousStates is left as-is because
|
|
120
|
-
* processStateChange() will overwrite it on the next real state transition.
|
|
121
|
-
* Returns true if the node was previously considered available.
|
|
122
|
-
*/
|
|
76
|
+
/** Returns true if the node was previously considered available. */
|
|
123
77
|
forceUnavailable(nodeId) {
|
|
124
78
|
const wasAvailable = this.#lastAvailability.get(nodeId) ?? false;
|
|
125
79
|
this.#lastAvailability.set(nodeId, false);
|
|
126
80
|
return wasAvailable;
|
|
127
81
|
}
|
|
128
|
-
|
|
129
|
-
* Determine if a node should be considered available based on its connection state.
|
|
130
|
-
* Uses debouncing logic similar to Python Matter Server:
|
|
131
|
-
* - Connected: available
|
|
132
|
-
* - Reconnecting when previously Connected: still available (debouncing)
|
|
133
|
-
* - WaitingForDeviceDiscovery or Disconnected: unavailable
|
|
134
|
-
*
|
|
135
|
-
* @param currentState Current connection state
|
|
136
|
-
* @param previousState Previous connection state (undefined if first state change)
|
|
137
|
-
* @returns true if node should be considered available
|
|
138
|
-
*/
|
|
139
|
-
isNodeAvailable(currentState, previousState) {
|
|
82
|
+
isNodeAvailable(currentState, debouncePending = false) {
|
|
140
83
|
if (currentState === NodeStates.Connected) {
|
|
141
84
|
return true;
|
|
142
85
|
}
|
|
143
|
-
|
|
144
|
-
return true;
|
|
145
|
-
}
|
|
146
|
-
return false;
|
|
86
|
+
return debouncePending;
|
|
147
87
|
}
|
|
148
|
-
/**
|
|
149
|
-
* Check if a node is available. Returns the cached availability value set by
|
|
150
|
-
* seedState/processStateChange/forceUnavailable, avoiding the race where
|
|
151
|
-
* recomputing from live state disagrees with the event path's determination.
|
|
152
|
-
*/
|
|
88
|
+
/** Returns the cached value, not a recomputation — avoids disagreement with the event path. */
|
|
153
89
|
isAvailable(nodeId) {
|
|
154
90
|
return this.#lastAvailability.get(nodeId) ?? false;
|
|
155
91
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/controller/Nodes.ts"],
|
|
4
|
-
"mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,SAAS,kBAA8B;AACvC,SAAS,mBAAmB;AAC5B,SAAS,0BAA0B;AAW5B,MAAM,MAAM;AAAA,EACf,SAAS,oBAAI,IAAwB;AAAA,EACrC,kBAAkB,IAAI,mBAAmB;AAAA;AAAA,EAEzC,
|
|
4
|
+
"mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,SAAS,kBAA8B;AACvC,SAAS,mBAAmB;AAC5B,SAAS,0BAA0B;AAW5B,MAAM,MAAM;AAAA,EACf,SAAS,oBAAI,IAAwB;AAAA,EACrC,kBAAkB,IAAI,mBAAmB;AAAA;AAAA,EAEzC,oBAAoB,oBAAI,IAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM7C,uBAAuB,oBAAI,IAA8B;AAAA,EAEzD,IAAI,iBAAqC;AACrC,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,SAAmB;AACf,WAAO,MAAM,KAAK,KAAK,OAAO,KAAK,CAAC;AAAA,EACxC;AAAA;AAAA,EAGA,IAAI,QAA4B;AAC5B,UAAM,OAAO,KAAK,OAAO,IAAI,MAAM;AACnC,QAAI,SAAS,QAAW;AACpB,YAAM,YAAY,cAAc,MAAM;AAAA,IAC1C;AACA,WAAO;AAAA,EACX;AAAA,EAEA,IAAI,QAAyB;AACzB,WAAO,KAAK,OAAO,IAAI,MAAM;AAAA,EACjC;AAAA,EAEA,IAAI,QAAgB,MAAwB;AACxC,SAAK,OAAO,IAAI,QAAQ,IAAI;AAAA,EAChC;AAAA,EAEA,OAAO,QAAsB;AACzB,SAAK,OAAO,OAAO,MAAM;AACzB,SAAK,gBAAgB,OAAO,MAAM;AAClC,SAAK,kBAAkB,OAAO,MAAM;AACpC,SAAK,qBAAqB,OAAO,MAAM;AAAA,EAC3C;AAAA,EAEA,mBAAmB,QAAgB,YAAkC;AACjE,QAAI,QAAQ,KAAK,qBAAqB,IAAI,MAAM;AAChD,QAAI,UAAU,QAAW;AACrB,cAAQ,CAAC;AACT,WAAK,qBAAqB,IAAI,QAAQ,KAAK;AAAA,IAC/C;AACA,UAAM,KAAK,UAAU;AAAA,EACzB;AAAA;AAAA,EAGA,yBAAyB,QAAkC;AACvD,UAAM,QAAQ,KAAK,qBAAqB,IAAI,MAAM;AAClD,QAAI,UAAU,UAAa,MAAM,WAAW,GAAG;AAC3C,aAAO,CAAC;AAAA,IACZ;AACA,SAAK,qBAAqB,OAAO,MAAM;AACvC,WAAO;AAAA,EACX;AAAA,EAEA,UAAU,QAAgB,cAAgC;AACtD,SAAK,kBAAkB,IAAI,QAAQ,iBAAiB,WAAW,SAAS;AAAA,EAC5E;AAAA;AAAA,EAGA,mBACI,QACA,UACA,iBACkF;AAClF,UAAM,eAAe,KAAK,kBAAkB,IAAI,MAAM,KAAK;AAC3D,UAAM,YAAY,KAAK,gBAAgB,UAAU,eAAe;AAEhE,SAAK,kBAAkB,IAAI,QAAQ,SAAS;AAE5C,QAAI,iBAAiB,WAAW;AAC5B,aAAO,EAAE,qBAAqB,MAAM,UAAU;AAAA,IAClD;AACA,WAAO,EAAE,qBAAqB,MAAM;AAAA,EACxC;AAAA;AAAA,EAGA,iBAAiB,QAAyB;AACtC,UAAM,eAAe,KAAK,kBAAkB,IAAI,MAAM,KAAK;AAC3D,SAAK,kBAAkB,IAAI,QAAQ,KAAK;AACxC,WAAO;AAAA,EACX;AAAA,EAEA,gBAAgB,cAA0B,kBAAkB,OAAgB;AACxE,QAAI,iBAAiB,WAAW,WAAW;AACvC,aAAO;AAAA,IACX;AACA,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,YAAY,QAAyB;AACjC,WAAO,KAAK,kBAAkB,IAAI,MAAM,KAAK;AAAA,EACjD;AACJ;",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025-2026 Open Home Foundation
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import type { WebRtcCallbackData } from "@matter-server/ws-client";
|
|
7
|
+
import type { WebRtcTransportRequestorServer } from "./behaviors/WebRtcTransportRequestorServer.js";
|
|
8
|
+
export declare function attachWebRtcCallbackBridge(events: WebRtcTransportRequestorServer.Events, emit: (data: WebRtcCallbackData) => void): void;
|
|
9
|
+
//# sourceMappingURL=WebRtcCallbackBridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebRtcCallbackBridge.d.ts","sourceRoot":"","sources":["../../../src/controller/WebRtcCallbackBridge.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,+CAA+C,CAAC;AAIpG,wBAAgB,0BAA0B,CACtC,MAAM,EAAE,8BAA8B,CAAC,MAAM,EAC7C,IAAI,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,GACzC,IAAI,CA+DN"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025-2026 Open Home Foundation
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { Logger } from "@matter/main";
|
|
7
|
+
const logger = Logger.get("WebRtcCallbackBridge");
|
|
8
|
+
function attachWebRtcCallbackBridge(events, emit) {
|
|
9
|
+
events.offer.on((session, request) => {
|
|
10
|
+
logger.info(
|
|
11
|
+
`offer from peer node=${session.peerNodeId} ep=${session.peerEndpointId} session=${session.id} sdpLen=${request.sdp.length}`
|
|
12
|
+
);
|
|
13
|
+
emit({
|
|
14
|
+
event_type: "offer",
|
|
15
|
+
webrtc_session_id: session.id,
|
|
16
|
+
node_id: session.peerNodeId,
|
|
17
|
+
endpoint_id: session.peerEndpointId,
|
|
18
|
+
fabric_index: session.fabricIndex,
|
|
19
|
+
data: {
|
|
20
|
+
sdp: request.sdp,
|
|
21
|
+
ice_servers: request.iceServers,
|
|
22
|
+
ice_transport_policy: request.iceTransportPolicy
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
events.answer.on((session, sdp) => {
|
|
27
|
+
logger.info(
|
|
28
|
+
`answer from peer node=${session.peerNodeId} ep=${session.peerEndpointId} session=${session.id} sdpLen=${sdp.length}`
|
|
29
|
+
);
|
|
30
|
+
emit({
|
|
31
|
+
event_type: "answer",
|
|
32
|
+
webrtc_session_id: session.id,
|
|
33
|
+
node_id: session.peerNodeId,
|
|
34
|
+
endpoint_id: session.peerEndpointId,
|
|
35
|
+
fabric_index: session.fabricIndex,
|
|
36
|
+
data: { sdp }
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
events.iceCandidates.on((session, candidates) => {
|
|
40
|
+
logger.info(
|
|
41
|
+
`ice_candidates from peer node=${session.peerNodeId} ep=${session.peerEndpointId} session=${session.id} count=${candidates.length}`
|
|
42
|
+
);
|
|
43
|
+
emit({
|
|
44
|
+
event_type: "ice_candidates",
|
|
45
|
+
webrtc_session_id: session.id,
|
|
46
|
+
node_id: session.peerNodeId,
|
|
47
|
+
endpoint_id: session.peerEndpointId,
|
|
48
|
+
fabric_index: session.fabricIndex,
|
|
49
|
+
data: {
|
|
50
|
+
ice_candidates: candidates.map((c) => ({
|
|
51
|
+
candidate: c.candidate,
|
|
52
|
+
sdpMid: c.sdpMid ?? null,
|
|
53
|
+
sdpMLineIndex: c.sdpmLineIndex ?? null
|
|
54
|
+
}))
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
events.end.on((session, reason) => {
|
|
59
|
+
logger.info(
|
|
60
|
+
`end from peer node=${session.peerNodeId} ep=${session.peerEndpointId} session=${session.id} reason=${reason}`
|
|
61
|
+
);
|
|
62
|
+
emit({
|
|
63
|
+
event_type: "end",
|
|
64
|
+
webrtc_session_id: session.id,
|
|
65
|
+
node_id: session.peerNodeId,
|
|
66
|
+
endpoint_id: session.peerEndpointId,
|
|
67
|
+
fabric_index: session.fabricIndex,
|
|
68
|
+
data: { reason }
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
export {
|
|
73
|
+
attachWebRtcCallbackBridge
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=WebRtcCallbackBridge.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/controller/WebRtcCallbackBridge.ts"],
|
|
4
|
+
"mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,SAAS,cAAc;AAGvB,MAAM,SAAS,OAAO,IAAI,sBAAsB;AAEzC,SAAS,2BACZ,QACA,MACI;AACJ,SAAO,MAAM,GAAG,CAAC,SAAS,YAAY;AAClC,WAAO;AAAA,MACH,wBAAwB,QAAQ,UAAU,OAAO,QAAQ,cAAc,YAAY,QAAQ,EAAE,WAAW,QAAQ,IAAI,MAAM;AAAA,IAC9H;AACA,SAAK;AAAA,MACD,YAAY;AAAA,MACZ,mBAAmB,QAAQ;AAAA,MAC3B,SAAS,QAAQ;AAAA,MACjB,aAAa,QAAQ;AAAA,MACrB,cAAc,QAAQ;AAAA,MACtB,MAAM;AAAA,QACF,KAAK,QAAQ;AAAA,QACb,aAAa,QAAQ;AAAA,QACrB,sBAAsB,QAAQ;AAAA,MAClC;AAAA,IACJ,CAAC;AAAA,EACL,CAAC;AACD,SAAO,OAAO,GAAG,CAAC,SAAS,QAAQ;AAC/B,WAAO;AAAA,MACH,yBAAyB,QAAQ,UAAU,OAAO,QAAQ,cAAc,YAAY,QAAQ,EAAE,WAAW,IAAI,MAAM;AAAA,IACvH;AACA,SAAK;AAAA,MACD,YAAY;AAAA,MACZ,mBAAmB,QAAQ;AAAA,MAC3B,SAAS,QAAQ;AAAA,MACjB,aAAa,QAAQ;AAAA,MACrB,cAAc,QAAQ;AAAA,MACtB,MAAM,EAAE,IAAI;AAAA,IAChB,CAAC;AAAA,EACL,CAAC;AACD,SAAO,cAAc,GAAG,CAAC,SAAS,eAAe;AAC7C,WAAO;AAAA,MACH,iCAAiC,QAAQ,UAAU,OAAO,QAAQ,cAAc,YAAY,QAAQ,EAAE,UAAU,WAAW,MAAM;AAAA,IACrI;AACA,SAAK;AAAA,MACD,YAAY;AAAA,MACZ,mBAAmB,QAAQ;AAAA,MAC3B,SAAS,QAAQ;AAAA,MACjB,aAAa,QAAQ;AAAA,MACrB,cAAc,QAAQ;AAAA,MACtB,MAAM;AAAA,QACF,gBAAgB,WAAW,IAAI,QAAM;AAAA,UACjC,WAAW,EAAE;AAAA,UACb,QAAQ,EAAE,UAAU;AAAA,UACpB,eAAe,EAAE,iBAAiB;AAAA,QACtC,EAAE;AAAA,MACN;AAAA,IACJ,CAAC;AAAA,EACL,CAAC;AACD,SAAO,IAAI,GAAG,CAAC,SAAS,WAAW;AAC/B,WAAO;AAAA,MACH,sBAAsB,QAAQ,UAAU,OAAO,QAAQ,cAAc,YAAY,QAAQ,EAAE,WAAW,MAAM;AAAA,IAChH;AACA,SAAK;AAAA,MACD,YAAY;AAAA,MACZ,mBAAmB,QAAQ;AAAA,MAC3B,SAAS,QAAQ;AAAA,MACjB,aAAa,QAAQ;AAAA,MACrB,cAAc,QAAQ;AAAA,MACtB,MAAM,EAAE,OAAO;AAAA,IACnB,CAAC;AAAA,EACL,CAAC;AACL;",
|
|
5
|
+
"names": []
|
|
6
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025-2026 Open Home Foundation
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { Observable } from "@matter/general";
|
|
7
|
+
import { WebRtcTransportRequestorBehavior } from "@matter/node/behaviors/web-rtc-transport-requestor";
|
|
8
|
+
import { WebRtcTransportDefinitions } from "@matter/types/clusters/web-rtc-transport-definitions";
|
|
9
|
+
import { WebRtcTransportRequestor } from "@matter/types/clusters/web-rtc-transport-requestor";
|
|
10
|
+
type WebRtcSession = WebRtcTransportDefinitions.WebRtcSession;
|
|
11
|
+
export declare class WebRtcTransportRequestorServer extends WebRtcTransportRequestorBehavior {
|
|
12
|
+
#private;
|
|
13
|
+
state: WebRtcTransportRequestorServer.State;
|
|
14
|
+
events: WebRtcTransportRequestorServer.Events;
|
|
15
|
+
upsertSession(session: WebRtcSession): void;
|
|
16
|
+
removeSession(id: number): void;
|
|
17
|
+
offer(request: WebRtcTransportRequestor.OfferRequest): Promise<void>;
|
|
18
|
+
answer(request: WebRtcTransportRequestor.AnswerRequest): Promise<void>;
|
|
19
|
+
iceCandidates(request: WebRtcTransportRequestor.IceCandidatesRequest): Promise<void>;
|
|
20
|
+
end(request: WebRtcTransportRequestor.EndRequest): Promise<void>;
|
|
21
|
+
initialize(): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export declare namespace WebRtcTransportRequestorServer {
|
|
24
|
+
class State extends WebRtcTransportRequestorBehavior.State {
|
|
25
|
+
currentSessions: WebRtcSession[];
|
|
26
|
+
}
|
|
27
|
+
class Events extends WebRtcTransportRequestorBehavior.Events {
|
|
28
|
+
offer: Observable<[session: WebRtcTransportDefinitions.WebRtcSession, args: WebRtcTransportRequestor.OfferRequest], void>;
|
|
29
|
+
answer: Observable<[session: WebRtcTransportDefinitions.WebRtcSession, sdp: string], void>;
|
|
30
|
+
iceCandidates: Observable<[session: WebRtcTransportDefinitions.WebRtcSession, candidates: WebRtcTransportDefinitions.IceCandidate[]], void>;
|
|
31
|
+
end: Observable<[session: WebRtcTransportDefinitions.WebRtcSession, reason: WebRtcTransportDefinitions.WebRtcEndReason], void>;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=WebRtcTransportRequestorServer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebRtcTransportRequestorServer.d.ts","sourceRoot":"","sources":["../../../../src/controller/behaviors/WebRtcTransportRequestorServer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAI7C,OAAO,EAAE,gCAAgC,EAAE,MAAM,oDAAoD,CAAC;AAItG,OAAO,EAAE,0BAA0B,EAAE,MAAM,sDAAsD,CAAC;AAClG,OAAO,EAAE,wBAAwB,EAAE,MAAM,oDAAoD,CAAC;AAE9F,KAAK,aAAa,GAAG,0BAA0B,CAAC,aAAa,CAAC;AAI9D,qBAAa,8BAA+B,SAAQ,gCAAgC;;IACxE,KAAK,EAAE,8BAA8B,CAAC,KAAK,CAAC;IAC5C,MAAM,EAAE,8BAA8B,CAAC,MAAM,CAAC;IAEtD,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAa1C;IAED,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAE9B;IAEc,KAAK,CAAC,OAAO,EAAE,wBAAwB,CAAC,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAIlF;IAEc,MAAM,CAAC,OAAO,EAAE,wBAAwB,CAAC,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAIpF;IAEc,aAAa,CAAC,OAAO,EAAE,wBAAwB,CAAC,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CASlG;IAEc,GAAG,CAAC,OAAO,EAAE,wBAAwB,CAAC,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAK9E;IAEc,UAAU,kBASxB;CAqDJ;AAED,yBAAiB,8BAA8B,CAAC,CAAC;IAC7C,MAAa,KAAM,SAAQ,gCAAgC,CAAC,KAAK;QACpD,eAAe,EAAE,aAAa,EAAE,CAA8B;KAC1E;IACD,MAAa,MAAO,SAAQ,gCAAgC,CAAC,MAAM;QAC/D,KAAK,qHAAuF;QAC5F,MAAM,qFAAuD;QAC7D,aAAa,+HAAiG;QAC9G,GAAG,4HAA8F;KACpG;CACJ"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025-2026 Open Home Foundation
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { Observable } from "@matter/general";
|
|
7
|
+
import { Logger, Node } from "@matter/main";
|
|
8
|
+
import { AccessControlServer } from "@matter/node/behaviors/access-control";
|
|
9
|
+
import { WebRtcTransportRequestorBehavior } from "@matter/node/behaviors/web-rtc-transport-requestor";
|
|
10
|
+
import { assertRemoteActor, FabricAuthority, NodeSession } from "@matter/protocol";
|
|
11
|
+
import { Status, StatusResponseError } from "@matter/types";
|
|
12
|
+
import { AccessControl } from "@matter/types/clusters/access-control";
|
|
13
|
+
import { WebRtcTransportRequestor } from "@matter/types/clusters/web-rtc-transport-requestor";
|
|
14
|
+
const logger = Logger.get("WebRtcTransportRequestorServer");
|
|
15
|
+
class WebRtcTransportRequestorServer extends WebRtcTransportRequestorBehavior {
|
|
16
|
+
upsertSession(session) {
|
|
17
|
+
const enriched = {
|
|
18
|
+
...session,
|
|
19
|
+
videoStreamId: session.videoStreams?.[0] ?? null,
|
|
20
|
+
audioStreamId: session.audioStreams?.[0] ?? null
|
|
21
|
+
};
|
|
22
|
+
const sessions = this.state.currentSessions;
|
|
23
|
+
const idx = sessions.findIndex((s) => s.id === session.id);
|
|
24
|
+
if (idx === -1) {
|
|
25
|
+
this.state.currentSessions = [...sessions, enriched];
|
|
26
|
+
} else {
|
|
27
|
+
this.state.currentSessions = sessions.map((s, i) => i === idx ? enriched : s);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
removeSession(id) {
|
|
31
|
+
this.state.currentSessions = this.state.currentSessions.filter((s) => s.id !== id);
|
|
32
|
+
}
|
|
33
|
+
async offer(request) {
|
|
34
|
+
logger.info(`incoming Offer webRtcSessionId=${request.webRtcSessionId} sdpLen=${request.sdp.length}`);
|
|
35
|
+
const session = this.#findSessionStrict(request.webRtcSessionId);
|
|
36
|
+
this.events.offer.emit(session, request);
|
|
37
|
+
}
|
|
38
|
+
async answer(request) {
|
|
39
|
+
logger.info(`incoming Answer webRtcSessionId=${request.webRtcSessionId} sdpLen=${request.sdp.length}`);
|
|
40
|
+
const session = this.#findSessionStrict(request.webRtcSessionId);
|
|
41
|
+
this.events.answer.emit(session, request.sdp);
|
|
42
|
+
}
|
|
43
|
+
async iceCandidates(request) {
|
|
44
|
+
logger.info(
|
|
45
|
+
`incoming ICECandidates webRtcSessionId=${request.webRtcSessionId} count=${request.iceCandidates.length}`
|
|
46
|
+
);
|
|
47
|
+
if (request.iceCandidates.length === 0) {
|
|
48
|
+
throw new StatusResponseError("ICE candidates list must not be empty", Status.InvalidCommand);
|
|
49
|
+
}
|
|
50
|
+
const session = this.#findSessionStrict(request.webRtcSessionId);
|
|
51
|
+
this.events.iceCandidates.emit(session, request.iceCandidates);
|
|
52
|
+
}
|
|
53
|
+
async end(request) {
|
|
54
|
+
logger.info(`incoming End webRtcSessionId=${request.webRtcSessionId} reason=${request.reason}`);
|
|
55
|
+
const session = this.#findSessionStrict(request.webRtcSessionId);
|
|
56
|
+
this.removeSession(request.webRtcSessionId);
|
|
57
|
+
this.events.end.emit(session, request.reason);
|
|
58
|
+
}
|
|
59
|
+
async initialize() {
|
|
60
|
+
const node = Node.forEndpoint(this.endpoint);
|
|
61
|
+
logger.info(
|
|
62
|
+
`initialized on endpoint=${this.endpoint.number} (id="${this.endpoint.id}") cluster=0x${WebRtcTransportRequestor.id.toString(16)}`
|
|
63
|
+
);
|
|
64
|
+
this.reactTo(node.lifecycle.online, this.#nodeOnline);
|
|
65
|
+
if (node.lifecycle.isOnline) {
|
|
66
|
+
await this.#nodeOnline();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async #nodeOnline() {
|
|
70
|
+
const fabricAuthority = this.env.get(FabricAuthority);
|
|
71
|
+
const ownFabric = fabricAuthority.fabrics[0];
|
|
72
|
+
if (!ownFabric) {
|
|
73
|
+
fabricAuthority.fabricAdded.once(() => void this.#nodeOnline());
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const node = Node.forEndpoint(this.endpoint);
|
|
77
|
+
await node.act((agent) => agent.load(AccessControlServer));
|
|
78
|
+
if (node.behaviors.has(AccessControlServer)) {
|
|
79
|
+
if (!node.stateOf(AccessControlServer).acl.some(
|
|
80
|
+
({ fabricIndex, privilege, authMode, subjects, targets }) => fabricIndex === ownFabric.fabricIndex && privilege === AccessControl.AccessControlEntryPrivilege.Operate && authMode === AccessControl.AccessControlEntryAuthMode.Case && subjects?.length === 0 && targets?.length === 1 && targets[0].endpoint === this.endpoint.number && targets[0].cluster === WebRtcTransportRequestor.id
|
|
81
|
+
)) {
|
|
82
|
+
const acl = [
|
|
83
|
+
...node.stateOf(AccessControlServer).acl,
|
|
84
|
+
{
|
|
85
|
+
fabricIndex: ownFabric.fabricIndex,
|
|
86
|
+
privilege: AccessControl.AccessControlEntryPrivilege.Operate,
|
|
87
|
+
authMode: AccessControl.AccessControlEntryAuthMode.Case,
|
|
88
|
+
subjects: [],
|
|
89
|
+
targets: [{ endpoint: this.endpoint.number, cluster: WebRtcTransportRequestor.id }]
|
|
90
|
+
}
|
|
91
|
+
];
|
|
92
|
+
await node.setStateOf(AccessControlServer, { acl });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
#findSessionStrict(id) {
|
|
97
|
+
assertRemoteActor(this.context);
|
|
98
|
+
NodeSession.assert(this.context.session);
|
|
99
|
+
const peer = this.context.session.peerAddress;
|
|
100
|
+
const session = this.state.currentSessions.find((s) => s.id === id);
|
|
101
|
+
if (session === void 0 || session.fabricIndex !== peer.fabricIndex || session.peerNodeId !== peer.nodeId) {
|
|
102
|
+
throw new StatusResponseError(`WebRTC session ${id} not found`, Status.NotFound);
|
|
103
|
+
}
|
|
104
|
+
return session;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
((WebRtcTransportRequestorServer2) => {
|
|
108
|
+
class State extends WebRtcTransportRequestorBehavior.State {
|
|
109
|
+
currentSessions = new Array();
|
|
110
|
+
}
|
|
111
|
+
WebRtcTransportRequestorServer2.State = State;
|
|
112
|
+
class Events extends WebRtcTransportRequestorBehavior.Events {
|
|
113
|
+
offer = Observable();
|
|
114
|
+
answer = Observable();
|
|
115
|
+
iceCandidates = Observable();
|
|
116
|
+
end = Observable();
|
|
117
|
+
}
|
|
118
|
+
WebRtcTransportRequestorServer2.Events = Events;
|
|
119
|
+
})(WebRtcTransportRequestorServer || (WebRtcTransportRequestorServer = {}));
|
|
120
|
+
export {
|
|
121
|
+
WebRtcTransportRequestorServer
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=WebRtcTransportRequestorServer.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/controller/behaviors/WebRtcTransportRequestorServer.ts"],
|
|
4
|
+
"mappings": "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",
|
|
5
|
+
"names": ["WebRtcTransportRequestorServer"]
|
|
6
|
+
}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
/**
|
|
7
7
|
* @matter-server/ws-controller - Matter controller Websocket library
|
|
8
8
|
*/
|
|
9
|
+
export * from "./controller/behaviors/WebRtcTransportRequestorServer.js";
|
|
9
10
|
export * from "./controller/ControllerCommandHandler.js";
|
|
10
11
|
export * from "./controller/LegacyDataInjector.js";
|
|
11
12
|
export * from "./controller/MatterController.js";
|
|
@@ -19,5 +20,5 @@ export * from "./types/CommandHandler.js";
|
|
|
19
20
|
export * from "./types/WebSocketMessageTypes.js";
|
|
20
21
|
export { formatNodeId } from "./util/formatNodeId.js";
|
|
21
22
|
export * from "./util/matterVersion.js";
|
|
22
|
-
export { Crypto, Environment, LogDestination, LogFormat, LogLevel, Logger } from "@matter/main";
|
|
23
|
+
export { Crypto, Environment, LogDestination, LogFormat, LogLevel, Logger, StorageService } from "@matter/main";
|
|
23
24
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AAGH,cAAc,0CAA0C,CAAC;AACzD,cAAc,oCAAoC,CAAC;AACnD,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AAGjD,cAAc,wBAAwB,CAAC;AAGvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wCAAwC,CAAC;AACvD,cAAc,sBAAsB,CAAC;AAGrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AAGjD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,cAAc,yBAAyB,CAAC;AAGxC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AAGH,cAAc,0DAA0D,CAAC;AACzE,cAAc,0CAA0C,CAAC;AACzD,cAAc,oCAAoC,CAAC;AACnD,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AAGjD,cAAc,wBAAwB,CAAC;AAGvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wCAAwC,CAAC;AACvD,cAAc,sBAAsB,CAAC;AAGrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AAGjD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,cAAc,yBAAyB,CAAC;AAGxC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/esm/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Copyright 2025-2026 Open Home Foundation
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
+
export * from "./controller/behaviors/WebRtcTransportRequestorServer.js";
|
|
6
7
|
export * from "./controller/ControllerCommandHandler.js";
|
|
7
8
|
export * from "./controller/LegacyDataInjector.js";
|
|
8
9
|
export * from "./controller/MatterController.js";
|
|
@@ -16,7 +17,7 @@ export * from "./types/CommandHandler.js";
|
|
|
16
17
|
export * from "./types/WebSocketMessageTypes.js";
|
|
17
18
|
import { formatNodeId } from "./util/formatNodeId.js";
|
|
18
19
|
export * from "./util/matterVersion.js";
|
|
19
|
-
import { Crypto, Environment, LogDestination, LogFormat, LogLevel, Logger } from "@matter/main";
|
|
20
|
+
import { Crypto, Environment, LogDestination, LogFormat, LogLevel, Logger, StorageService } from "@matter/main";
|
|
20
21
|
export {
|
|
21
22
|
Crypto,
|
|
22
23
|
Environment,
|
|
@@ -24,6 +25,7 @@ export {
|
|
|
24
25
|
LogFormat,
|
|
25
26
|
LogLevel,
|
|
26
27
|
Logger,
|
|
28
|
+
StorageService,
|
|
27
29
|
formatNodeId
|
|
28
30
|
};
|
|
29
31
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/index.ts"],
|
|
4
|
-
"mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAWA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,SAAS,oBAAoB;AAC7B,cAAc;AAGd,SAAS,QAAQ,aAAa,gBAAgB,WAAW,UAAU,
|
|
4
|
+
"mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAWA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,SAAS,oBAAoB;AAC7B,cAAc;AAGd,SAAS,QAAQ,aAAa,gBAAgB,WAAW,UAAU,QAAQ,sBAAsB;",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebSocketControllerHandler.d.ts","sourceRoot":"","sources":["../../../src/server/WebSocketControllerHandler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAoBH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAKrE,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAMH,eAAe,EAMlB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AA+BnD,yDAAyD;AACzD,qBAAa,0BAA2B,YAAW,gBAAgB;;
|
|
1
|
+
{"version":3,"file":"WebSocketControllerHandler.d.ts","sourceRoot":"","sources":["../../../src/server/WebSocketControllerHandler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAoBH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAKrE,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAMH,eAAe,EAMlB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AA+BnD,yDAAyD;AACzD,qBAAa,0BAA2B,YAAW,gBAAgB;;IAe/D,YAAY,UAAU,EAAE,gBAAgB,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,EAMrF;IAED;;;OAGG;IACH,MAAM;QAIE,OAAO;QACP,UAAU;MAEjB;IAoBD;;OAEG;IACH,eAAe,IAAI,eAAe,EAAE,CAEnC;IAED,gBAAgB,IAAI,IAAI,CAEvB;IAEK,QAAQ,CAAC,MAAM,EAAE,UAAU,iBAwOhC;IAED,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAgC1B;CAoyBJ"}
|
|
@@ -54,6 +54,7 @@ class WebSocketControllerHandler {
|
|
|
54
54
|
#wss;
|
|
55
55
|
#closed = false;
|
|
56
56
|
#shuttingDown = false;
|
|
57
|
+
#serverObservers = new ObserverGroup();
|
|
57
58
|
/** Circular buffer for recent node events (max 25) */
|
|
58
59
|
#eventHistory = [];
|
|
59
60
|
/** Track when each node was last interviewed (connected) - keyed by nodeId */
|
|
@@ -105,6 +106,9 @@ class WebSocketControllerHandler {
|
|
|
105
106
|
async register(server) {
|
|
106
107
|
logger.info(`Starting server: matter-server/${this.#serverVersion} (matter.js/${MATTER_VERSION})`);
|
|
107
108
|
const wss = this.#wss = new WebSocketServer({ server, path: "/ws" });
|
|
109
|
+
this.#serverObservers.on(this.#commandHandler.events.webRtcCallback, (data) => {
|
|
110
|
+
this.#broadcastEvent("webrtc_callback", data);
|
|
111
|
+
});
|
|
108
112
|
wss.on("connection", (ws) => {
|
|
109
113
|
if (this.#closed || this.#shuttingDown) {
|
|
110
114
|
try {
|
|
@@ -293,6 +297,7 @@ class WebSocketControllerHandler {
|
|
|
293
297
|
return Promise.resolve();
|
|
294
298
|
}
|
|
295
299
|
this.#closed = true;
|
|
300
|
+
this.#serverObservers.close();
|
|
296
301
|
const shutdownMessage = toBigIntAwareJson({ event: "server_shutdown", data: {} });
|
|
297
302
|
this.#wss.clients.forEach((client) => {
|
|
298
303
|
if (client.readyState === 1) {
|
|
@@ -359,6 +364,9 @@ class WebSocketControllerHandler {
|
|
|
359
364
|
case "device_command":
|
|
360
365
|
result = await this.#handleDeviceCommand(args);
|
|
361
366
|
break;
|
|
367
|
+
case "send_webrtc_provider_command":
|
|
368
|
+
result = await this.#handleSendWebRtcProviderCommand(args);
|
|
369
|
+
break;
|
|
362
370
|
case "write_attribute":
|
|
363
371
|
result = await this.#handleWriteAttribute(args);
|
|
364
372
|
break;
|
|
@@ -713,6 +721,15 @@ class WebSocketControllerHandler {
|
|
|
713
721
|
}
|
|
714
722
|
return cmdResult;
|
|
715
723
|
}
|
|
724
|
+
async #handleSendWebRtcProviderCommand(args) {
|
|
725
|
+
const { node_id, endpoint_id, command_name, payload } = args;
|
|
726
|
+
return this.#commandHandler.sendWebRtcProviderCommand({
|
|
727
|
+
nodeId: NodeId(node_id),
|
|
728
|
+
endpointId: EndpointNumber(endpoint_id),
|
|
729
|
+
commandName: command_name,
|
|
730
|
+
payload
|
|
731
|
+
});
|
|
732
|
+
}
|
|
716
733
|
async #handleInterviewNode(args) {
|
|
717
734
|
const { node_id } = args;
|
|
718
735
|
const nodeId = NodeId(node_id);
|