qbusmqttapi 0.1.0__tar.gz

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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Qbus
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,38 @@
1
+ Metadata-Version: 2.1
2
+ Name: qbusmqttapi
3
+ Version: 0.1.0
4
+ Summary: MQTT API for Qbus Home Automation
5
+ Author-email: Koen Schockaert <iot@qbus.be>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2024 Qbus
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/Qbus-iot/qbusmqttapi
29
+ Keywords: qbus,mqtt,api
30
+ Classifier: License :: OSI Approved :: MIT License
31
+ Classifier: Programming Language :: Python
32
+ Classifier: Programming Language :: Python :: 3
33
+ Requires-Python: >=3.11
34
+ Description-Content-Type: text/markdown
35
+ License-File: LICENSE
36
+
37
+ # qbusmqttapi
38
+ Python MQTT API for Qbus Home Automation
@@ -0,0 +1,2 @@
1
+ # qbusmqttapi
2
+ Python MQTT API for Qbus Home Automation
@@ -0,0 +1,25 @@
1
+ # pyproject.toml
2
+
3
+ [build-system]
4
+ requires = ["setuptools>=61.0.0", "wheel"]
5
+ build-backend = "setuptools.build_meta"
6
+
7
+ [project]
8
+ name = "qbusmqttapi"
9
+ version = "0.1.0"
10
+ description = "MQTT API for Qbus Home Automation"
11
+ readme = "README.md"
12
+ authors = [{ name = "Koen Schockaert", email = "iot@qbus.be" }]
13
+ license = { file = "LICENSE" }
14
+ classifiers = [
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python",
17
+ "Programming Language :: Python :: 3",
18
+ ]
19
+ keywords = ["qbus", "mqtt", "api"]
20
+ dependencies = [
21
+ ]
22
+ requires-python = ">=3.11"
23
+
24
+ [project.urls]
25
+ Homepage = "https://github.com/Qbus-iot/qbusmqttapi"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+ """QBUS MQTT API."""
@@ -0,0 +1,250 @@
1
+ """QBUS Discovery."""
2
+ from __future__ import annotations
3
+
4
+ import json
5
+ import logging
6
+
7
+ _LOGGER = logging.getLogger(__name__)
8
+
9
+ KEY_DEVICES = "devices"
10
+
11
+ KEY_DEVICE_FUNCTIONBLOCKS = "functionBlocks"
12
+ KEY_DEVICE_ID = "id"
13
+ KEY_DEVICE_IP = "ip"
14
+ KEY_DEVICE_MAC = "mac"
15
+ KEY_DEVICE_NAME = "name"
16
+ KEY_DEVICE_SERIAL_NR = "serialNr"
17
+ KEY_DEVICE_TYPE = "type"
18
+
19
+ KEY_OUTPUT_ID = "id"
20
+ KEY_OUTPUT_TYPE = "type"
21
+ KEY_OUTPUT_NAME = "name"
22
+ KEY_OUTPUT_REF_ID = "ref_id"
23
+ KEY_OUTPUT_PROPERTIES = "properties"
24
+ KEY_OUTPUT_ACTIONS = "actions"
25
+
26
+ KEY_CONTROLLER_CONNECTABLE = "connectable"
27
+ KEY_CONTROLLER_CONNECTED = "connected"
28
+ KEY_CONTROLLER_ID = "id"
29
+ KEY_CONTROLLER_STATE_PROPERTIES = "properties"
30
+
31
+
32
+ class QbusMqttOutput:
33
+ """Class for parsing MQTT discovered outputs for Qbus Home Automation."""
34
+
35
+ def __init__(self, dict: dict) -> None:
36
+ """Initialize based on a json loaded dictionary."""
37
+ self._dict = dict
38
+
39
+ @property
40
+ def id(self) -> str:
41
+ """Return the id."""
42
+ return self._dict.get(KEY_OUTPUT_ID) or ""
43
+
44
+ @property
45
+ def type(self) -> str:
46
+ """Return the type."""
47
+ return self._dict.get(KEY_OUTPUT_TYPE) or ""
48
+
49
+ @property
50
+ def name(self) -> str:
51
+ """Return the name."""
52
+ return self._dict.get(KEY_OUTPUT_NAME) or ""
53
+
54
+ @property
55
+ def ref_id(self) -> str:
56
+ """Return the ref id."""
57
+ return self._dict.get(KEY_OUTPUT_REF_ID) or ""
58
+
59
+ @property
60
+ def properties(self) -> dict:
61
+ """Return the properties."""
62
+ return self._dict.get(KEY_OUTPUT_PROPERTIES) or {}
63
+
64
+ @property
65
+ def actions(self) -> dict:
66
+ """Return the actions."""
67
+ return self._dict.get(KEY_OUTPUT_ACTIONS) or {}
68
+
69
+ class QbusMqttDevice:
70
+ """Class for parsing MQTT discovered devices for Qbus Home Automation."""
71
+
72
+ def __init__(self, dict: dict) -> None:
73
+ self._dict = dict
74
+ self._outputs: list[QbusMqttOutput] = []
75
+ self._connection_state: bool
76
+
77
+ @property
78
+ def id(self) -> str:
79
+ """Return the id."""
80
+ return self._dict.get(KEY_DEVICE_ID) or ""
81
+
82
+ @property
83
+ def ip(self) -> str:
84
+ """Return the ip address."""
85
+ return self._dict.get(KEY_DEVICE_IP) or ""
86
+
87
+ @property
88
+ def mac(self) -> str:
89
+ """Return the ip address."""
90
+ return self._dict.get(KEY_DEVICE_MAC) or ""
91
+
92
+ @property
93
+ def name(self) -> str:
94
+ """Return the ip address."""
95
+ return self._dict.get(KEY_DEVICE_NAME) or ""
96
+
97
+ @property
98
+ def serial_number(self) -> str:
99
+ """Return the serial number."""
100
+ return self._dict.get(KEY_DEVICE_SERIAL_NR) or ""
101
+
102
+ @property
103
+ def type(self) -> str:
104
+ """Return the mac address."""
105
+ return self._dict.get(KEY_DEVICE_TYPE) or ""
106
+
107
+ @property
108
+ def outputs(self) -> list[QbusMqttOutput]:
109
+ """Return the outputs."""
110
+
111
+ outputs: list[QbusMqttOutput] = []
112
+
113
+ if self._dict.get(KEY_DEVICE_FUNCTIONBLOCKS):
114
+ outputs = [QbusMqttOutput(x) for x in self._dict[KEY_DEVICE_FUNCTIONBLOCKS]]
115
+
116
+ self._outputs = outputs
117
+ return self._outputs
118
+
119
+ class QbusMqttControllerStateProperties:
120
+ """MQTT representation a Qbus controller its state properties."""
121
+
122
+ def __init__(self, dict: dict) -> None:
123
+ """Initialize based on a json loaded dictionary."""
124
+ self._dict = dict
125
+
126
+ @property
127
+ def connectable(self) -> bool | None:
128
+ """Return True if the controller is connectable."""
129
+ return self._dict.get(KEY_CONTROLLER_CONNECTABLE, None)
130
+
131
+ @property
132
+ def connected(self) -> bool | None:
133
+ """Return True if the controller is connected."""
134
+ return self._dict.get(KEY_CONTROLLER_CONNECTED, None)
135
+
136
+ class QbusMqttControllerState:
137
+ """MQTT representation a Qbus controller state."""
138
+
139
+ def __init__(self, dict: dict) -> None:
140
+ """Initialize based on a json loaded dictionary."""
141
+ self._dict = dict
142
+ self._properties: QbusMqttControllerStateProperties | None = None
143
+
144
+ @property
145
+ def id(self) -> str | None:
146
+ """Return the id."""
147
+ return self._dict.get(KEY_CONTROLLER_ID)
148
+
149
+ @property
150
+ def properties(self) -> QbusMqttControllerStateProperties | None:
151
+ """Return the properties."""
152
+
153
+ if self._properties is not None:
154
+ return self._properties
155
+
156
+ properties: QbusMqttControllerStateProperties | None = None
157
+
158
+ if self._dict.get(KEY_CONTROLLER_STATE_PROPERTIES):
159
+ properties = QbusMqttControllerStateProperties(self._dict[KEY_CONTROLLER_STATE_PROPERTIES])
160
+
161
+ self._properties = properties
162
+
163
+ return self._properties
164
+
165
+ class QbusMqttOutputState:
166
+ """MQTT representation a Qbus output state."""
167
+
168
+ def __init__(self, dict: dict) -> None:
169
+ """Initialize based on a json loaded dictionary."""
170
+ self._dict = dict
171
+
172
+ @property
173
+ def id(self) -> str:
174
+ """Return the id."""
175
+ return self._dict.get(KEY_OUTPUT_ID) or ""
176
+
177
+ @property
178
+ def type(self) -> str:
179
+ """Return the type."""
180
+ return self._dict.get(KEY_OUTPUT_TYPE) or ""
181
+
182
+ @property
183
+ def properties(self) -> dict | None:
184
+ """Return the properties."""
185
+ return self._dict.get(KEY_OUTPUT_PROPERTIES)
186
+
187
+ class QbusDiscovery:
188
+ """Class for parsing MQTT discovery messages for Qbus Home Automation."""
189
+
190
+ def __init__(self, domain: str) -> None:
191
+ """Initialize."""
192
+ self._domain = domain
193
+ self._devices = list[QbusMqttDevice] = []
194
+ self._hub_id = ""
195
+ self._device_id = ""
196
+ self._device_type = ""
197
+ self._device_desc = ""
198
+ self._name = ""
199
+ self._owner_id = ""
200
+ self._data_topic = ""
201
+ self._command_topic = ""
202
+
203
+ async def parse_discovery(self, discovery_topic: str, payload: str | bytes) -> bool:
204
+ """Parse an MQTT discovery message and return True if successful."""
205
+ try:
206
+ json_data = json.loads(payload)
207
+ except ValueError:
208
+ _LOGGER.error(
209
+ "Invalid QBUS MQTT discovery payload on %s: %s",
210
+ discovery_topic,
211
+ payload,
212
+ )
213
+ return False
214
+
215
+ topic_elements = discovery_topic.split("/")
216
+ if not (
217
+ topic_elements[2].endswith("config")
218
+ ):
219
+ return False
220
+
221
+
222
+
223
+ # Discovery data must include the Qbus device type and name.
224
+ if (
225
+ KEY_DEVICES in json_data
226
+ ):
227
+ self._devices = json_data[KEY_DEVICES]
228
+ else:
229
+ _LOGGER.error(
230
+ "Incomplete MQTT discovery payload on %s: %s", discovery_topic, payload
231
+ )
232
+ return False
233
+
234
+ @property
235
+ def devices(self) -> list[QbusMqttDevice]:
236
+ """Return the devices."""
237
+
238
+ devices: list[QbusMqttDevice] = []
239
+
240
+ if self._dict.get("devices"):
241
+ devices = [QbusMqttDevice(x) for x in self._dict["devices"]]
242
+
243
+ self._devices = devices
244
+
245
+ return self._devices
246
+
247
+ def get_device(self, serial: str) -> QbusMqttDevice | None:
248
+ """Get the device by serial number."""
249
+ return next((x for x in self.devices if x.serial_number == serial), None)
250
+
@@ -0,0 +1,38 @@
1
+ Metadata-Version: 2.1
2
+ Name: qbusmqttapi
3
+ Version: 0.1.0
4
+ Summary: MQTT API for Qbus Home Automation
5
+ Author-email: Koen Schockaert <iot@qbus.be>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2024 Qbus
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/Qbus-iot/qbusmqttapi
29
+ Keywords: qbus,mqtt,api
30
+ Classifier: License :: OSI Approved :: MIT License
31
+ Classifier: Programming Language :: Python
32
+ Classifier: Programming Language :: Python :: 3
33
+ Requires-Python: >=3.11
34
+ Description-Content-Type: text/markdown
35
+ License-File: LICENSE
36
+
37
+ # qbusmqttapi
38
+ Python MQTT API for Qbus Home Automation
@@ -0,0 +1,10 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ setup.cfg
5
+ src/qbusmqttapi/__init__.py
6
+ src/qbusmqttapi/discovery.py
7
+ src/qbusmqttapi.egg-info/PKG-INFO
8
+ src/qbusmqttapi.egg-info/SOURCES.txt
9
+ src/qbusmqttapi.egg-info/dependency_links.txt
10
+ src/qbusmqttapi.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ qbusmqttapi