matter-python-client 0.4.1a0.dev20260220__py3-none-any.whl
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.
- matter_python_client-0.4.1a0.dev20260220.dist-info/METADATA +20 -0
- matter_python_client-0.4.1a0.dev20260220.dist-info/RECORD +22 -0
- matter_python_client-0.4.1a0.dev20260220.dist-info/WHEEL +5 -0
- matter_python_client-0.4.1a0.dev20260220.dist-info/top_level.txt +1 -0
- matter_server/__init__.py +1 -0
- matter_server/client/__init__.py +5 -0
- matter_server/client/client.py +806 -0
- matter_server/client/connection.py +177 -0
- matter_server/client/exceptions.py +63 -0
- matter_server/client/models/__init__.py +1 -0
- matter_server/client/models/device_types.py +952 -0
- matter_server/client/models/node.py +414 -0
- matter_server/common/__init__.py +1 -0
- matter_server/common/const.py +8 -0
- matter_server/common/custom_clusters.py +1371 -0
- matter_server/common/errors.py +94 -0
- matter_server/common/helpers/__init__.py +0 -0
- matter_server/common/helpers/api.py +70 -0
- matter_server/common/helpers/json.py +48 -0
- matter_server/common/helpers/util.py +359 -0
- matter_server/common/models.py +273 -0
- matter_server/py.typed +0 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"""Models that are (serializeable) shared between server and client."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from datetime import datetime # noqa: TC003
|
|
8
|
+
from enum import Enum
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
# Enums and constants
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class EventType(Enum):
|
|
15
|
+
"""Enum with possible events sent from server to client."""
|
|
16
|
+
|
|
17
|
+
NODE_ADDED = "node_added"
|
|
18
|
+
NODE_UPDATED = "node_updated"
|
|
19
|
+
NODE_REMOVED = "node_removed"
|
|
20
|
+
NODE_EVENT = "node_event"
|
|
21
|
+
ATTRIBUTE_UPDATED = "attribute_updated"
|
|
22
|
+
SERVER_SHUTDOWN = "server_shutdown"
|
|
23
|
+
SERVER_INFO_UPDATED = "server_info_updated"
|
|
24
|
+
ENDPOINT_ADDED = "endpoint_added"
|
|
25
|
+
ENDPOINT_REMOVED = "endpoint_removed"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class APICommand(str, Enum):
|
|
29
|
+
"""Enum with all known API commands."""
|
|
30
|
+
|
|
31
|
+
START_LISTENING = "start_listening"
|
|
32
|
+
SERVER_DIAGNOSTICS = "diagnostics"
|
|
33
|
+
SERVER_INFO = "server_info"
|
|
34
|
+
GET_NODES = "get_nodes"
|
|
35
|
+
GET_NODE = "get_node"
|
|
36
|
+
COMMISSION_WITH_CODE = "commission_with_code"
|
|
37
|
+
COMMISSION_ON_NETWORK = "commission_on_network"
|
|
38
|
+
SET_WIFI_CREDENTIALS = "set_wifi_credentials"
|
|
39
|
+
SET_THREAD_DATASET = "set_thread_dataset"
|
|
40
|
+
OPEN_COMMISSIONING_WINDOW = "open_commissioning_window"
|
|
41
|
+
DISCOVER = "discover"
|
|
42
|
+
INTERVIEW_NODE = "interview_node"
|
|
43
|
+
DEVICE_COMMAND = "device_command"
|
|
44
|
+
REMOVE_NODE = "remove_node"
|
|
45
|
+
GET_VENDOR_NAMES = "get_vendor_names"
|
|
46
|
+
READ_ATTRIBUTE = "read_attribute"
|
|
47
|
+
WRITE_ATTRIBUTE = "write_attribute"
|
|
48
|
+
PING_NODE = "ping_node"
|
|
49
|
+
GET_NODE_IP_ADDRESSES = "get_node_ip_addresses"
|
|
50
|
+
IMPORT_TEST_NODE = "import_test_node"
|
|
51
|
+
CHECK_NODE_UPDATE = "check_node_update"
|
|
52
|
+
UPDATE_NODE = "update_node"
|
|
53
|
+
SET_DEFAULT_FABRIC_LABEL = "set_default_fabric_label"
|
|
54
|
+
SET_ACL_ENTRY = "set_acl_entry"
|
|
55
|
+
SET_NODE_BINDING = "set_node_binding"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
EventCallBackType = Callable[[EventType, Any], None]
|
|
59
|
+
|
|
60
|
+
# Generic model(s)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass
|
|
64
|
+
class VendorInfo:
|
|
65
|
+
"""Vendor info as received from the CSA."""
|
|
66
|
+
|
|
67
|
+
vendor_id: int
|
|
68
|
+
vendor_name: str
|
|
69
|
+
company_legal_name: str
|
|
70
|
+
company_preferred_name: str
|
|
71
|
+
vendor_landing_page_url: str
|
|
72
|
+
creator: str
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@dataclass
|
|
76
|
+
class MatterNodeData:
|
|
77
|
+
"""Matter node data as received from (and stored on) the server."""
|
|
78
|
+
|
|
79
|
+
node_id: int
|
|
80
|
+
date_commissioned: datetime
|
|
81
|
+
last_interview: datetime
|
|
82
|
+
interview_version: int
|
|
83
|
+
available: bool = False
|
|
84
|
+
is_bridge: bool = False
|
|
85
|
+
# attributes are stored in form of AttributePath: ENDPOINT/CLUSTER_ID/ATTRIBUTE_ID
|
|
86
|
+
attributes: dict[str, Any] = field(default_factory=dict)
|
|
87
|
+
# all attribute subscriptions we need to persist for this node,
|
|
88
|
+
# a set of tuples in format (endpoint_id, cluster_id, attribute_id)
|
|
89
|
+
# where each value can also be a None for wildcard
|
|
90
|
+
attribute_subscriptions: set[tuple[int | None, int | None, int | None]] = field(
|
|
91
|
+
default_factory=set
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@dataclass
|
|
96
|
+
class MatterNodeEvent:
|
|
97
|
+
"""Representation of a NodeEvent for a Matter node."""
|
|
98
|
+
|
|
99
|
+
node_id: int
|
|
100
|
+
endpoint_id: int
|
|
101
|
+
cluster_id: int
|
|
102
|
+
event_id: int
|
|
103
|
+
event_number: int
|
|
104
|
+
priority: int
|
|
105
|
+
timestamp: int
|
|
106
|
+
timestamp_type: int
|
|
107
|
+
data: dict[str, Any] | None
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@dataclass
|
|
111
|
+
class ServerDiagnostics:
|
|
112
|
+
"""Full dump of the server information and data."""
|
|
113
|
+
|
|
114
|
+
info: ServerInfoMessage
|
|
115
|
+
nodes: list[MatterNodeData]
|
|
116
|
+
events: list[dict]
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
NodePingResult = dict[str, bool]
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
# API message models
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@dataclass
|
|
126
|
+
class CommandMessage:
|
|
127
|
+
"""Model for a Message holding a command from server to client or client to server."""
|
|
128
|
+
|
|
129
|
+
message_id: str
|
|
130
|
+
command: str
|
|
131
|
+
args: dict[str, Any] | None = None
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@dataclass
|
|
135
|
+
class ResultMessageBase:
|
|
136
|
+
"""Base class for a result/response of a Command Message."""
|
|
137
|
+
|
|
138
|
+
message_id: str
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@dataclass
|
|
142
|
+
class SuccessResultMessage(ResultMessageBase):
|
|
143
|
+
"""Message sent when a Command has been successfully executed."""
|
|
144
|
+
|
|
145
|
+
result: Any
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@dataclass
|
|
149
|
+
class ErrorResultMessage(ResultMessageBase):
|
|
150
|
+
"""Message sent when a command did not execute successfully."""
|
|
151
|
+
|
|
152
|
+
error_code: int
|
|
153
|
+
details: str | None = None
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@dataclass
|
|
157
|
+
class EventMessage:
|
|
158
|
+
"""Message sent when server or client signals a (stateless) event."""
|
|
159
|
+
|
|
160
|
+
event: EventType
|
|
161
|
+
data: Any
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@dataclass
|
|
165
|
+
class ServerInfoMessage:
|
|
166
|
+
"""Message sent by the server with it's info when a client connects."""
|
|
167
|
+
|
|
168
|
+
fabric_id: int
|
|
169
|
+
compressed_fabric_id: int
|
|
170
|
+
schema_version: int
|
|
171
|
+
min_supported_schema_version: int
|
|
172
|
+
sdk_version: str
|
|
173
|
+
wifi_credentials_set: bool
|
|
174
|
+
thread_credentials_set: bool
|
|
175
|
+
bluetooth_enabled: bool
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
MessageType = (
|
|
179
|
+
CommandMessage
|
|
180
|
+
| EventMessage
|
|
181
|
+
| SuccessResultMessage
|
|
182
|
+
| ErrorResultMessage
|
|
183
|
+
| ServerInfoMessage
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
@dataclass
|
|
188
|
+
class CommissionableNodeData:
|
|
189
|
+
"""Object that is returned on the 'discover_commissionable_nodes' command."""
|
|
190
|
+
|
|
191
|
+
# pylint: disable=too-many-instance-attributes
|
|
192
|
+
|
|
193
|
+
instance_name: str | None = None
|
|
194
|
+
host_name: str | None = None
|
|
195
|
+
port: int | None = None
|
|
196
|
+
long_discriminator: int | None = None
|
|
197
|
+
vendor_id: int | None = None
|
|
198
|
+
product_id: int | None = None
|
|
199
|
+
commissioning_mode: int | None = None
|
|
200
|
+
device_type: int | None = None
|
|
201
|
+
device_name: str | None = None
|
|
202
|
+
pairing_instruction: str | None = None
|
|
203
|
+
pairing_hint: int | None = None
|
|
204
|
+
mrp_retry_interval_idle: int | None = None
|
|
205
|
+
mrp_retry_interval_active: int | None = None
|
|
206
|
+
supports_tcp: bool | None = None
|
|
207
|
+
addresses: list[str] | None = None
|
|
208
|
+
rotating_id: str | None = None
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
@dataclass
|
|
212
|
+
class CommissioningParameters:
|
|
213
|
+
"""Object that is returned on the 'open_commisisoning_window' command."""
|
|
214
|
+
|
|
215
|
+
setup_pin_code: int
|
|
216
|
+
setup_manual_code: str
|
|
217
|
+
setup_qr_code: str
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
class UpdateSource(Enum):
|
|
221
|
+
"""Enum with possible sources for a software update."""
|
|
222
|
+
|
|
223
|
+
MAIN_NET_DCL = "main-net-dcl"
|
|
224
|
+
TEST_NET_DCL = "test-net-dcl"
|
|
225
|
+
LOCAL = "local"
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
@dataclass
|
|
229
|
+
class MatterSoftwareVersion:
|
|
230
|
+
"""Representation of a Matter software version. Return by the check_node_update command.
|
|
231
|
+
|
|
232
|
+
This holds Matter software version information similar to what is available from the CSA DCL.
|
|
233
|
+
https://on.dcl.csa-iot.org/#/Query/ModelVersion.
|
|
234
|
+
"""
|
|
235
|
+
|
|
236
|
+
vid: int
|
|
237
|
+
pid: int
|
|
238
|
+
software_version: int
|
|
239
|
+
software_version_string: str
|
|
240
|
+
firmware_information: str | None
|
|
241
|
+
min_applicable_software_version: int
|
|
242
|
+
max_applicable_software_version: int
|
|
243
|
+
release_notes_url: str | None
|
|
244
|
+
update_source: UpdateSource
|
|
245
|
+
|
|
246
|
+
@classmethod
|
|
247
|
+
def from_dict(cls, data: dict) -> MatterSoftwareVersion:
|
|
248
|
+
"""Initialize from dict."""
|
|
249
|
+
return cls(
|
|
250
|
+
vid=data["vid"],
|
|
251
|
+
pid=data["pid"],
|
|
252
|
+
software_version=data["software_version"],
|
|
253
|
+
software_version_string=data["software_version_string"],
|
|
254
|
+
firmware_information=data["firmware_information"],
|
|
255
|
+
min_applicable_software_version=data["min_applicable_software_version"],
|
|
256
|
+
max_applicable_software_version=data["max_applicable_software_version"],
|
|
257
|
+
release_notes_url=data["release_notes_url"],
|
|
258
|
+
update_source=UpdateSource(data["update_source"]),
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
def as_dict(self) -> dict:
|
|
262
|
+
"""Return dict representation of the object."""
|
|
263
|
+
return {
|
|
264
|
+
"vid": self.vid,
|
|
265
|
+
"pid": self.pid,
|
|
266
|
+
"software_version": self.software_version,
|
|
267
|
+
"software_version_string": self.software_version_string,
|
|
268
|
+
"firmware_information": self.firmware_information,
|
|
269
|
+
"min_applicable_software_version": self.min_applicable_software_version,
|
|
270
|
+
"max_applicable_software_version": self.max_applicable_software_version,
|
|
271
|
+
"release_notes_url": self.release_notes_url,
|
|
272
|
+
"update_source": self.update_source.value,
|
|
273
|
+
}
|
matter_server/py.typed
ADDED
|
File without changes
|