aioccl 2024.9.8__py3-none-any.whl → 2024.12__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.
- aioccl/__init__.py +1 -1
- aioccl/device.py +13 -5
- aioccl/sensor.py +441 -131
- aioccl/server.py +39 -40
- {aioccl-2024.9.8.dist-info → aioccl-2024.12.dist-info}/METADATA +3 -3
- aioccl-2024.12.dist-info/RECORD +9 -0
- {aioccl-2024.9.8.dist-info → aioccl-2024.12.dist-info}/WHEEL +1 -1
- aioccl-2024.9.8.dist-info/RECORD +0 -9
- {aioccl-2024.9.8.dist-info → aioccl-2024.12.dist-info}/LICENSE +0 -0
- {aioccl-2024.9.8.dist-info → aioccl-2024.12.dist-info}/top_level.txt +0 -0
aioccl/__init__.py
CHANGED
aioccl/device.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
"""
|
1
|
+
"""CCL device mapping."""
|
2
2
|
from __future__ import annotations
|
3
3
|
|
4
4
|
import logging
|
@@ -33,34 +33,42 @@ class CCLDevice:
|
|
33
33
|
|
34
34
|
@property
|
35
35
|
def passkey(self) -> str:
|
36
|
+
"""Return the passkey."""
|
36
37
|
return self._passkey
|
37
38
|
|
38
39
|
@property
|
39
40
|
def device_id(self) -> str | None:
|
41
|
+
"""Return the device ID."""
|
40
42
|
return self._mac_address.replace(":", "").lower()[-6:]
|
41
43
|
|
42
44
|
@property
|
43
45
|
def name(self) -> str | None:
|
46
|
+
"""Return the display name."""
|
44
47
|
return self._model + " - " + self.device_id
|
45
48
|
|
46
49
|
@property
|
47
50
|
def mac_address(self) -> str | None:
|
51
|
+
"""Return the MAC address."""
|
48
52
|
return self._mac_address
|
49
53
|
|
50
54
|
@property
|
51
55
|
def model(self) -> str | None:
|
56
|
+
"""Return the model."""
|
52
57
|
return self._model
|
53
58
|
|
54
59
|
@property
|
55
60
|
def fw_ver(self) -> str | None:
|
61
|
+
"""Return the firmware version."""
|
56
62
|
return self._fw_ver
|
57
63
|
|
58
64
|
@property
|
59
65
|
def binary_sensors(self) -> dict[str, CCLSensor] | None:
|
66
|
+
"""Store binary sensor data under this device."""
|
60
67
|
return self._binary_sensors
|
61
68
|
|
62
69
|
@property
|
63
70
|
def sensors(self) -> dict[str, CCLSensor] | None:
|
71
|
+
"""Store sensor data under this device."""
|
64
72
|
return self._sensors
|
65
73
|
|
66
74
|
def update_info(self, info: dict[str, None | str]) -> None:
|
@@ -73,12 +81,12 @@ class CCLDevice:
|
|
73
81
|
"""Add or update all sensor values."""
|
74
82
|
for key, value in sensors.items():
|
75
83
|
if CCL_SENSORS.get(key).binary:
|
76
|
-
if not
|
84
|
+
if key not in self._binary_sensors:
|
77
85
|
self._binary_sensors[key] = CCLSensor(key)
|
78
86
|
self._new_sensors.append(self._binary_sensors[key])
|
79
87
|
self._binary_sensors[key].value = value
|
80
88
|
else:
|
81
|
-
if not
|
89
|
+
if key not in self._sensors:
|
82
90
|
self._sensors[key] = CCLSensor(key)
|
83
91
|
self._new_sensors.append(self._sensors[key])
|
84
92
|
self._sensors[key].value = value
|
@@ -100,7 +108,7 @@ class CCLDevice:
|
|
100
108
|
try:
|
101
109
|
for callback in self._update_callbacks:
|
102
110
|
callback()
|
103
|
-
except Exception as err:
|
111
|
+
except Exception as err: # pylint: disable=broad-exception-caught
|
104
112
|
_LOGGER.warning("Error while publishing sensor updates: %s", err)
|
105
113
|
|
106
114
|
def register_new_binary_sensor_cb(self, callback: Callable[[], None]) -> None:
|
@@ -131,5 +139,5 @@ class CCLDevice:
|
|
131
139
|
for callback in self._new_sensor_callbacks:
|
132
140
|
callback(sensor)
|
133
141
|
self._new_sensors.remove(sensor)
|
134
|
-
except Exception as err:
|
142
|
+
except Exception as err: # pylint: disable=broad-exception-caught
|
135
143
|
_LOGGER.warning("Error while publishing new sensors: %s", err)
|
aioccl/sensor.py
CHANGED
@@ -1,42 +1,50 @@
|
|
1
|
+
"""CCL sensor mapping."""
|
2
|
+
|
1
3
|
from __future__ import annotations
|
2
4
|
|
3
5
|
from dataclasses import dataclass
|
4
6
|
import enum
|
5
|
-
|
7
|
+
|
6
8
|
|
7
9
|
class CCLSensor:
|
8
10
|
"""Class that represents a CCLSensor object in the aioCCL API."""
|
9
|
-
|
11
|
+
|
10
12
|
def __init__(self, key: str):
|
11
13
|
"""Initialize a CCL sensor."""
|
12
14
|
self._value: None | str | int | float = None
|
13
|
-
|
15
|
+
|
14
16
|
if key in CCL_SENSORS.keys():
|
15
17
|
self._key = key
|
16
|
-
|
18
|
+
|
17
19
|
@property
|
18
20
|
def key(self) -> str:
|
21
|
+
"""Key ID of the sensor."""
|
19
22
|
return self._key
|
20
|
-
|
23
|
+
|
21
24
|
@property
|
22
25
|
def name(self) -> str:
|
26
|
+
"""Display name of the sensor."""
|
23
27
|
return CCL_SENSORS[self._key].name
|
24
|
-
|
28
|
+
|
25
29
|
@property
|
26
30
|
def sensor_type(self) -> CCLSensorTypes:
|
31
|
+
"""Type of the sensor."""
|
27
32
|
return CCL_SENSORS[self._key].sensor_type
|
28
|
-
|
33
|
+
|
29
34
|
@property
|
30
35
|
def compartment(self) -> None | str:
|
36
|
+
"""Decide which compartment it belongs to."""
|
31
37
|
if CCL_SENSORS[self._key].compartment is not None:
|
32
38
|
return CCL_SENSORS[self._key].compartment.value
|
33
|
-
|
39
|
+
|
34
40
|
@property
|
35
41
|
def binary(self) -> bool:
|
42
|
+
"""Decide if the sensor is binary."""
|
36
43
|
return CCL_SENSORS[self._key].binary
|
37
44
|
|
38
45
|
@property
|
39
46
|
def value(self) -> None | str | int | float:
|
47
|
+
"""Return the intrinsic sensor value."""
|
40
48
|
if self.sensor_type.name in CCL_SENSOR_VALUES:
|
41
49
|
return CCL_SENSOR_VALUES[self.sensor_type.name].get(self._value)
|
42
50
|
elif self.sensor_type == CCLSensorTypes.BATTERY_BINARY:
|
@@ -46,19 +54,25 @@ class CCLSensor:
|
|
46
54
|
pass
|
47
55
|
else:
|
48
56
|
return self._value
|
49
|
-
|
57
|
+
|
50
58
|
@value.setter
|
51
59
|
def value(self, new_value):
|
52
60
|
self._value = new_value
|
53
61
|
|
62
|
+
|
54
63
|
@dataclass
|
55
64
|
class CCLSensorPreset:
|
65
|
+
"""Attributes of a CCL sensor."""
|
66
|
+
|
56
67
|
name: str
|
57
68
|
sensor_type: str
|
58
69
|
compartment: None | CCLDeviceCompartment = None
|
59
70
|
binary: bool = False
|
60
|
-
|
71
|
+
|
72
|
+
|
61
73
|
class CCLSensorTypes(enum.Enum):
|
74
|
+
"""List of CCL sensor types."""
|
75
|
+
|
62
76
|
PRESSURE = 1
|
63
77
|
TEMPERATURE = 2
|
64
78
|
HUMIDITY = 3
|
@@ -84,135 +98,431 @@ class CCLSensorTypes(enum.Enum):
|
|
84
98
|
LIGHTNING_DURATION = 23
|
85
99
|
LIGHTNING_FREQUENCY = 24
|
86
100
|
BATTERY_VOLTAGE = 25
|
87
|
-
|
101
|
+
|
102
|
+
|
88
103
|
class CCLDeviceCompartment(enum.Enum):
|
89
|
-
|
90
|
-
|
91
|
-
|
104
|
+
"""Grouping of CCL sensors."""
|
105
|
+
|
106
|
+
MAIN = "Console & Sensor Array"
|
107
|
+
OTHER = "Other Sensors"
|
108
|
+
STATUS = "Status"
|
109
|
+
|
92
110
|
|
93
111
|
CCL_SENSOR_VALUES: dict[str, dict[str, str]] = {
|
94
|
-
|
95
|
-
2:
|
96
|
-
3:
|
97
|
-
4:
|
112
|
+
"CH_SENSOR_TYPE": {
|
113
|
+
2: "thermo-hygro",
|
114
|
+
3: "pool",
|
115
|
+
4: "soil",
|
116
|
+
},
|
117
|
+
"LEAKAGE": {
|
118
|
+
0: "no_leak",
|
119
|
+
1: "leaking",
|
98
120
|
},
|
99
|
-
'LEAKAGE': {
|
100
|
-
0: 'no_leak',
|
101
|
-
1: 'leaking',
|
102
|
-
}
|
103
121
|
}
|
104
122
|
|
105
123
|
CCL_SENSORS: dict[str, CCLSensorPreset] = {
|
106
124
|
# Main Sensors 12-34
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
125
|
+
"abar": CCLSensorPreset(
|
126
|
+
"Air Pressure (Absolute)", CCLSensorTypes.PRESSURE, CCLDeviceCompartment.MAIN
|
127
|
+
),
|
128
|
+
"rbar": CCLSensorPreset(
|
129
|
+
"Air Pressure (Relative)", CCLSensorTypes.PRESSURE, CCLDeviceCompartment.MAIN
|
130
|
+
),
|
131
|
+
"t1dew": CCLSensorPreset(
|
132
|
+
"Index: Dew Point", CCLSensorTypes.TEMPERATURE, CCLDeviceCompartment.MAIN
|
133
|
+
),
|
134
|
+
"t1feels": CCLSensorPreset(
|
135
|
+
"Index: Feels Like", CCLSensorTypes.TEMPERATURE, CCLDeviceCompartment.MAIN
|
136
|
+
),
|
137
|
+
"t1heat": CCLSensorPreset(
|
138
|
+
"Index: Heat Index", CCLSensorTypes.TEMPERATURE, CCLDeviceCompartment.MAIN
|
139
|
+
),
|
140
|
+
"t1wbgt": CCLSensorPreset(
|
141
|
+
"Index: WBGT", CCLSensorTypes.TEMPERATURE, CCLDeviceCompartment.MAIN
|
142
|
+
),
|
143
|
+
"t1chill": CCLSensorPreset(
|
144
|
+
"Index: Wind Chill", CCLSensorTypes.TEMPERATURE, CCLDeviceCompartment.MAIN
|
145
|
+
),
|
146
|
+
"inhum": CCLSensorPreset(
|
147
|
+
"Indoor Humidity", CCLSensorTypes.HUMIDITY, CCLDeviceCompartment.MAIN
|
148
|
+
),
|
149
|
+
"intem": CCLSensorPreset(
|
150
|
+
"Indoor Temperature", CCLSensorTypes.TEMPERATURE, CCLDeviceCompartment.MAIN
|
151
|
+
),
|
152
|
+
"t1solrad": CCLSensorPreset(
|
153
|
+
"Light Intensity", CCLSensorTypes.RADIATION, CCLDeviceCompartment.MAIN
|
154
|
+
),
|
155
|
+
"t1hum": CCLSensorPreset(
|
156
|
+
"Outdoor Humidity", CCLSensorTypes.HUMIDITY, CCLDeviceCompartment.MAIN
|
157
|
+
),
|
158
|
+
"t1tem": CCLSensorPreset(
|
159
|
+
"Outdoor Temperature", CCLSensorTypes.TEMPERATURE, CCLDeviceCompartment.MAIN
|
160
|
+
),
|
161
|
+
"t1rainra": CCLSensorPreset(
|
162
|
+
"Rain Rate", CCLSensorTypes.RAIN_RATE, CCLDeviceCompartment.MAIN
|
163
|
+
),
|
164
|
+
"t1rainhr": CCLSensorPreset(
|
165
|
+
"Rainfall: Hourly ", CCLSensorTypes.RAINFALL, CCLDeviceCompartment.MAIN
|
166
|
+
),
|
167
|
+
"t1raindy": CCLSensorPreset(
|
168
|
+
"Rainfall: Daily", CCLSensorTypes.RAINFALL, CCLDeviceCompartment.MAIN
|
169
|
+
),
|
170
|
+
"t1rainwy": CCLSensorPreset(
|
171
|
+
"Rainfall: Weekly", CCLSensorTypes.RAINFALL, CCLDeviceCompartment.MAIN
|
172
|
+
),
|
173
|
+
"t1rainmth": CCLSensorPreset(
|
174
|
+
"Rainfall: Monthly", CCLSensorTypes.RAINFALL, CCLDeviceCompartment.MAIN
|
175
|
+
),
|
176
|
+
"t1rainyr": CCLSensorPreset(
|
177
|
+
"Rainfall: Yearly", CCLSensorTypes.RAINFALL, CCLDeviceCompartment.MAIN
|
178
|
+
),
|
179
|
+
"t1uvi": CCLSensorPreset("UV Index", CCLSensorTypes.UVI, CCLDeviceCompartment.MAIN),
|
180
|
+
"t1wdir": CCLSensorPreset(
|
181
|
+
"Wind Direction", CCLSensorTypes.WIND_DIRECITON, CCLDeviceCompartment.MAIN
|
182
|
+
),
|
183
|
+
"t1wgust": CCLSensorPreset(
|
184
|
+
"Wind Gust", CCLSensorTypes.WIND_SPEED, CCLDeviceCompartment.MAIN
|
185
|
+
),
|
186
|
+
"t1ws": CCLSensorPreset(
|
187
|
+
"Wind Speed", CCLSensorTypes.WIND_SPEED, CCLDeviceCompartment.MAIN
|
188
|
+
),
|
189
|
+
"t1ws10mav": CCLSensorPreset(
|
190
|
+
"Wind Speed (10 mins AVG.)",
|
191
|
+
CCLSensorTypes.WIND_SPEED,
|
192
|
+
CCLDeviceCompartment.MAIN,
|
193
|
+
),
|
130
194
|
# Additional Sensors 35-77
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
195
|
+
"t11co": CCLSensorPreset(
|
196
|
+
"Air Quality: CO", CCLSensorTypes.CO, CCLDeviceCompartment.OTHER
|
197
|
+
),
|
198
|
+
"t10co2": CCLSensorPreset(
|
199
|
+
"Air Quality: CO\u2082", CCLSensorTypes.CO2, CCLDeviceCompartment.OTHER
|
200
|
+
),
|
201
|
+
"t9hcho": CCLSensorPreset(
|
202
|
+
"Air Quality: HCHO", CCLSensorTypes.VOLATILE, CCLDeviceCompartment.OTHER
|
203
|
+
),
|
204
|
+
"t8pm10": CCLSensorPreset(
|
205
|
+
"Air Quality: PM10", CCLSensorTypes.PM10, CCLDeviceCompartment.OTHER
|
206
|
+
),
|
207
|
+
"t8pm10ai": CCLSensorPreset(
|
208
|
+
"Air Quality: PM10 AQI", CCLSensorTypes.AQI, CCLDeviceCompartment.OTHER
|
209
|
+
),
|
210
|
+
"t8pm25": CCLSensorPreset(
|
211
|
+
"Air Quality: PM2.5", CCLSensorTypes.PM25, CCLDeviceCompartment.OTHER
|
212
|
+
),
|
213
|
+
"t8pm25ai": CCLSensorPreset(
|
214
|
+
"Air Quality: PM2.5 AQI", CCLSensorTypes.AQI, CCLDeviceCompartment.OTHER
|
215
|
+
),
|
216
|
+
"t9voclv": CCLSensorPreset(
|
217
|
+
"Air Quality: VOC Level", CCLSensorTypes.VOC, CCLDeviceCompartment.OTHER
|
218
|
+
),
|
219
|
+
"t234c1tem": CCLSensorPreset(
|
220
|
+
"CH1 Temperature", CCLSensorTypes.TEMPERATURE, CCLDeviceCompartment.OTHER
|
221
|
+
),
|
222
|
+
"t234c1hum": CCLSensorPreset(
|
223
|
+
"CH1 Humidity", CCLSensorTypes.HUMIDITY, CCLDeviceCompartment.OTHER
|
224
|
+
),
|
225
|
+
"t234c1tp": CCLSensorPreset(
|
226
|
+
"CH1 Type", CCLSensorTypes.CH_SENSOR_TYPE, CCLDeviceCompartment.OTHER
|
227
|
+
),
|
228
|
+
"t234c2tem": CCLSensorPreset(
|
229
|
+
"CH2 Temperature", CCLSensorTypes.TEMPERATURE, CCLDeviceCompartment.OTHER
|
230
|
+
),
|
231
|
+
"t234c2hum": CCLSensorPreset(
|
232
|
+
"CH2 Humidity", CCLSensorTypes.HUMIDITY, CCLDeviceCompartment.OTHER
|
233
|
+
),
|
234
|
+
"t234c2tp": CCLSensorPreset(
|
235
|
+
"CH2 Type", CCLSensorTypes.CH_SENSOR_TYPE, CCLDeviceCompartment.OTHER
|
236
|
+
),
|
237
|
+
"t234c3tem": CCLSensorPreset(
|
238
|
+
"CH3 Temperature", CCLSensorTypes.TEMPERATURE, CCLDeviceCompartment.OTHER
|
239
|
+
),
|
240
|
+
"t234c3hum": CCLSensorPreset(
|
241
|
+
"CH3 Humidity", CCLSensorTypes.HUMIDITY, CCLDeviceCompartment.OTHER
|
242
|
+
),
|
243
|
+
"t234c3tp": CCLSensorPreset(
|
244
|
+
"CH3 Type", CCLSensorTypes.CH_SENSOR_TYPE, CCLDeviceCompartment.OTHER
|
245
|
+
),
|
246
|
+
"t234c4tem": CCLSensorPreset(
|
247
|
+
"CH4 Temperature", CCLSensorTypes.TEMPERATURE, CCLDeviceCompartment.OTHER
|
248
|
+
),
|
249
|
+
"t234c4hum": CCLSensorPreset(
|
250
|
+
"CH4 Humidity", CCLSensorTypes.HUMIDITY, CCLDeviceCompartment.OTHER
|
251
|
+
),
|
252
|
+
"t234c4tp": CCLSensorPreset(
|
253
|
+
"CH4 Type", CCLSensorTypes.CH_SENSOR_TYPE, CCLDeviceCompartment.OTHER
|
254
|
+
),
|
255
|
+
"t234c5tem": CCLSensorPreset(
|
256
|
+
"CH5 Temperature", CCLSensorTypes.TEMPERATURE, CCLDeviceCompartment.OTHER
|
257
|
+
),
|
258
|
+
"t234c5hum": CCLSensorPreset(
|
259
|
+
"CH5 Humidity", CCLSensorTypes.HUMIDITY, CCLDeviceCompartment.OTHER
|
260
|
+
),
|
261
|
+
"t234c5tp": CCLSensorPreset(
|
262
|
+
"CH5 Type", CCLSensorTypes.CH_SENSOR_TYPE, CCLDeviceCompartment.OTHER
|
263
|
+
),
|
264
|
+
"t234c6tem": CCLSensorPreset(
|
265
|
+
"CH6 Temperature", CCLSensorTypes.TEMPERATURE, CCLDeviceCompartment.OTHER
|
266
|
+
),
|
267
|
+
"t234c6hum": CCLSensorPreset(
|
268
|
+
"CH6 Humidity", CCLSensorTypes.HUMIDITY, CCLDeviceCompartment.OTHER
|
269
|
+
),
|
270
|
+
"t234c6tp": CCLSensorPreset(
|
271
|
+
"CH6 Type", CCLSensorTypes.CH_SENSOR_TYPE, CCLDeviceCompartment.OTHER
|
272
|
+
),
|
273
|
+
"t234c7tem": CCLSensorPreset(
|
274
|
+
"CH7 Temperature", CCLSensorTypes.TEMPERATURE, CCLDeviceCompartment.OTHER
|
275
|
+
),
|
276
|
+
"t234c7hum": CCLSensorPreset(
|
277
|
+
"CH7 Humidity", CCLSensorTypes.HUMIDITY, CCLDeviceCompartment.OTHER
|
278
|
+
),
|
279
|
+
"t234c7tp": CCLSensorPreset(
|
280
|
+
"CH7 Type", CCLSensorTypes.CH_SENSOR_TYPE, CCLDeviceCompartment.OTHER
|
281
|
+
),
|
282
|
+
"t6c1wls": CCLSensorPreset(
|
283
|
+
"Leakage CH1", CCLSensorTypes.LEAKAGE, CCLDeviceCompartment.OTHER
|
284
|
+
),
|
285
|
+
"t6c2wls": CCLSensorPreset(
|
286
|
+
"Leakage CH2", CCLSensorTypes.LEAKAGE, CCLDeviceCompartment.OTHER
|
287
|
+
),
|
288
|
+
"t6c3wls": CCLSensorPreset(
|
289
|
+
"Leakage CH3", CCLSensorTypes.LEAKAGE, CCLDeviceCompartment.OTHER
|
290
|
+
),
|
291
|
+
"t6c4wls": CCLSensorPreset(
|
292
|
+
"Leakage CH4", CCLSensorTypes.LEAKAGE, CCLDeviceCompartment.OTHER
|
293
|
+
),
|
294
|
+
"t6c5wls": CCLSensorPreset(
|
295
|
+
"Leakage CH5", CCLSensorTypes.LEAKAGE, CCLDeviceCompartment.OTHER
|
296
|
+
),
|
297
|
+
"t6c6wls": CCLSensorPreset(
|
298
|
+
"Leakage CH6", CCLSensorTypes.LEAKAGE, CCLDeviceCompartment.OTHER
|
299
|
+
),
|
300
|
+
"t6c7wls": CCLSensorPreset(
|
301
|
+
"Leakage CH7", CCLSensorTypes.LEAKAGE, CCLDeviceCompartment.OTHER
|
302
|
+
),
|
303
|
+
"t5lskm": CCLSensorPreset(
|
304
|
+
"Lightning Distance",
|
305
|
+
CCLSensorTypes.LIGHTNING_DISTANCE,
|
306
|
+
CCLDeviceCompartment.OTHER,
|
307
|
+
),
|
308
|
+
"t5lsf": CCLSensorPreset(
|
309
|
+
"Lightning: Past 60 mins Strikes",
|
310
|
+
CCLSensorTypes.LIGHTNING_FREQUENCY,
|
311
|
+
CCLDeviceCompartment.OTHER,
|
312
|
+
),
|
313
|
+
"t5ls30mtc": CCLSensorPreset(
|
314
|
+
"Lightning: Strikes in 30 mins",
|
315
|
+
CCLSensorTypes.LIGHTNING_FREQUENCY,
|
316
|
+
CCLDeviceCompartment.OTHER,
|
317
|
+
),
|
318
|
+
"t5ls5mtc": CCLSensorPreset(
|
319
|
+
"Lightning: Strikes in 5 mins",
|
320
|
+
CCLSensorTypes.LIGHTNING_FREQUENCY,
|
321
|
+
CCLDeviceCompartment.OTHER,
|
322
|
+
),
|
323
|
+
"t5ls1dtc": CCLSensorPreset(
|
324
|
+
"Lightning: Strikes in day",
|
325
|
+
CCLSensorTypes.LIGHTNING_FREQUENCY,
|
326
|
+
CCLDeviceCompartment.OTHER,
|
327
|
+
),
|
328
|
+
"t5ls1htc": CCLSensorPreset(
|
329
|
+
"Lightning: Strikes in hour",
|
330
|
+
CCLSensorTypes.LIGHTNING_FREQUENCY,
|
331
|
+
CCLDeviceCompartment.OTHER,
|
332
|
+
),
|
174
333
|
# Status 78-119
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
334
|
+
"t234c1bat": CCLSensorPreset(
|
335
|
+
"Battery: CH1", CCLSensorTypes.BATTERY_BINARY, CCLDeviceCompartment.STATUS, True
|
336
|
+
),
|
337
|
+
"t234c2bat": CCLSensorPreset(
|
338
|
+
"Battery: CH2", CCLSensorTypes.BATTERY_BINARY, CCLDeviceCompartment.STATUS, True
|
339
|
+
),
|
340
|
+
"t234c3bat": CCLSensorPreset(
|
341
|
+
"Battery: CH3", CCLSensorTypes.BATTERY_BINARY, CCLDeviceCompartment.STATUS, True
|
342
|
+
),
|
343
|
+
"t234c4bat": CCLSensorPreset(
|
344
|
+
"Battery: CH4", CCLSensorTypes.BATTERY_BINARY, CCLDeviceCompartment.STATUS, True
|
345
|
+
),
|
346
|
+
"t234c5bat": CCLSensorPreset(
|
347
|
+
"Battery: CH5", CCLSensorTypes.BATTERY_BINARY, CCLDeviceCompartment.STATUS, True
|
348
|
+
),
|
349
|
+
"t234c6bat": CCLSensorPreset(
|
350
|
+
"Battery: CH6", CCLSensorTypes.BATTERY_BINARY, CCLDeviceCompartment.STATUS, True
|
351
|
+
),
|
352
|
+
"t234c7bat": CCLSensorPreset(
|
353
|
+
"Battery: CH7", CCLSensorTypes.BATTERY_BINARY, CCLDeviceCompartment.STATUS, True
|
354
|
+
),
|
355
|
+
"t11bat": CCLSensorPreset(
|
356
|
+
"Battery Level: CO", CCLSensorTypes.BATTERY, CCLDeviceCompartment.STATUS
|
357
|
+
),
|
358
|
+
"t10bat": CCLSensorPreset(
|
359
|
+
"Battery Level: CO\u2082", CCLSensorTypes.BATTERY, CCLDeviceCompartment.STATUS
|
360
|
+
),
|
361
|
+
"inbat": CCLSensorPreset(
|
362
|
+
"Battery: Console",
|
363
|
+
CCLSensorTypes.BATTERY_BINARY,
|
364
|
+
CCLDeviceCompartment.STATUS,
|
365
|
+
True,
|
366
|
+
),
|
367
|
+
"t9bat": CCLSensorPreset(
|
368
|
+
"Battery Level: HCHO/VOC", CCLSensorTypes.BATTERY, CCLDeviceCompartment.STATUS
|
369
|
+
),
|
370
|
+
"t6c1bat": CCLSensorPreset(
|
371
|
+
"Battery: Leakage CH1",
|
372
|
+
CCLSensorTypes.BATTERY_BINARY,
|
373
|
+
CCLDeviceCompartment.STATUS,
|
374
|
+
True,
|
375
|
+
),
|
376
|
+
"t6c2bat": CCLSensorPreset(
|
377
|
+
"Battery: Leakage CH2",
|
378
|
+
CCLSensorTypes.BATTERY_BINARY,
|
379
|
+
CCLDeviceCompartment.STATUS,
|
380
|
+
True,
|
381
|
+
),
|
382
|
+
"t6c3bat": CCLSensorPreset(
|
383
|
+
"Battery: Leakage CH3",
|
384
|
+
CCLSensorTypes.BATTERY_BINARY,
|
385
|
+
CCLDeviceCompartment.STATUS,
|
386
|
+
True,
|
387
|
+
),
|
388
|
+
"t6c4bat": CCLSensorPreset(
|
389
|
+
"Battery: Leakage CH4",
|
390
|
+
CCLSensorTypes.BATTERY_BINARY,
|
391
|
+
CCLDeviceCompartment.STATUS,
|
392
|
+
True,
|
393
|
+
),
|
394
|
+
"t6c5bat": CCLSensorPreset(
|
395
|
+
"Battery: Leakage CH5",
|
396
|
+
CCLSensorTypes.BATTERY_BINARY,
|
397
|
+
CCLDeviceCompartment.STATUS,
|
398
|
+
True,
|
399
|
+
),
|
400
|
+
"t6c6bat": CCLSensorPreset(
|
401
|
+
"Battery: Leakage CH6",
|
402
|
+
CCLSensorTypes.BATTERY_BINARY,
|
403
|
+
CCLDeviceCompartment.STATUS,
|
404
|
+
True,
|
405
|
+
),
|
406
|
+
"t6c7bat": CCLSensorPreset(
|
407
|
+
"Battery: Leakage CH7",
|
408
|
+
CCLSensorTypes.BATTERY_BINARY,
|
409
|
+
CCLDeviceCompartment.STATUS,
|
410
|
+
True,
|
411
|
+
),
|
412
|
+
"t5lsbat": CCLSensorPreset(
|
413
|
+
"Battery: Lightning Sensor",
|
414
|
+
CCLSensorTypes.BATTERY_BINARY,
|
415
|
+
CCLDeviceCompartment.STATUS,
|
416
|
+
True,
|
417
|
+
),
|
418
|
+
"t1bat": CCLSensorPreset(
|
419
|
+
"Battery: Sensor Array",
|
420
|
+
CCLSensorTypes.BATTERY_BINARY,
|
421
|
+
CCLDeviceCompartment.STATUS,
|
422
|
+
True,
|
423
|
+
),
|
424
|
+
"t1batvt": CCLSensorPreset(
|
425
|
+
"Battery Voltage: Sensor Array",
|
426
|
+
CCLSensorTypes.BATTERY_VOLTAGE,
|
427
|
+
CCLDeviceCompartment.STATUS,
|
428
|
+
),
|
429
|
+
"t8bat": CCLSensorPreset(
|
430
|
+
"Battery Level: PM2.5/10", CCLSensorTypes.BATTERY, CCLDeviceCompartment.STATUS
|
431
|
+
),
|
432
|
+
"t234c1cn": CCLSensorPreset(
|
433
|
+
"Connection: CH1", CCLSensorTypes.CONNECTION, CCLDeviceCompartment.STATUS, True
|
434
|
+
),
|
435
|
+
"t234c2cn": CCLSensorPreset(
|
436
|
+
"Connection: CH2", CCLSensorTypes.CONNECTION, CCLDeviceCompartment.STATUS, True
|
437
|
+
),
|
438
|
+
"t234c3cn": CCLSensorPreset(
|
439
|
+
"Connection: CH3", CCLSensorTypes.CONNECTION, CCLDeviceCompartment.STATUS, True
|
440
|
+
),
|
441
|
+
"t234c4cn": CCLSensorPreset(
|
442
|
+
"Connection: CH4", CCLSensorTypes.CONNECTION, CCLDeviceCompartment.STATUS, True
|
443
|
+
),
|
444
|
+
"t234c5cn": CCLSensorPreset(
|
445
|
+
"Connection: CH5", CCLSensorTypes.CONNECTION, CCLDeviceCompartment.STATUS, True
|
446
|
+
),
|
447
|
+
"t234c6cn": CCLSensorPreset(
|
448
|
+
"Connection: CH6", CCLSensorTypes.CONNECTION, CCLDeviceCompartment.STATUS, True
|
449
|
+
),
|
450
|
+
"t234c7cn": CCLSensorPreset(
|
451
|
+
"Connection: CH7", CCLSensorTypes.CONNECTION, CCLDeviceCompartment.STATUS, True
|
452
|
+
),
|
453
|
+
"t6c1cn": CCLSensorPreset(
|
454
|
+
"Connection: Leakage CH1",
|
455
|
+
CCLSensorTypes.CONNECTION,
|
456
|
+
CCLDeviceCompartment.STATUS,
|
457
|
+
True,
|
458
|
+
),
|
459
|
+
"t6c2cn": CCLSensorPreset(
|
460
|
+
"Connection: Leakage CH2",
|
461
|
+
CCLSensorTypes.CONNECTION,
|
462
|
+
CCLDeviceCompartment.STATUS,
|
463
|
+
True,
|
464
|
+
),
|
465
|
+
"t6c3cn": CCLSensorPreset(
|
466
|
+
"Connection: Leakage CH3",
|
467
|
+
CCLSensorTypes.CONNECTION,
|
468
|
+
CCLDeviceCompartment.STATUS,
|
469
|
+
True,
|
470
|
+
),
|
471
|
+
"t6c4cn": CCLSensorPreset(
|
472
|
+
"Connection: Leakage CH4",
|
473
|
+
CCLSensorTypes.CONNECTION,
|
474
|
+
CCLDeviceCompartment.STATUS,
|
475
|
+
True,
|
476
|
+
),
|
477
|
+
"t6c5cn": CCLSensorPreset(
|
478
|
+
"Connection: Leakage CH5",
|
479
|
+
CCLSensorTypes.CONNECTION,
|
480
|
+
CCLDeviceCompartment.STATUS,
|
481
|
+
True,
|
482
|
+
),
|
483
|
+
"t6c6cn": CCLSensorPreset(
|
484
|
+
"Connection: Leakage CH6",
|
485
|
+
CCLSensorTypes.CONNECTION,
|
486
|
+
CCLDeviceCompartment.STATUS,
|
487
|
+
True,
|
488
|
+
),
|
489
|
+
"t6c7cn": CCLSensorPreset(
|
490
|
+
"Connection: Leakage CH7",
|
491
|
+
CCLSensorTypes.CONNECTION,
|
492
|
+
CCLDeviceCompartment.STATUS,
|
493
|
+
True,
|
494
|
+
),
|
495
|
+
"t5lscn": CCLSensorPreset(
|
496
|
+
"Connection: Lightning Sensor",
|
497
|
+
CCLSensorTypes.CONNECTION,
|
498
|
+
CCLDeviceCompartment.STATUS,
|
499
|
+
True,
|
500
|
+
),
|
501
|
+
"t11cn": CCLSensorPreset(
|
502
|
+
"Connection: CO", CCLSensorTypes.CONNECTION, CCLDeviceCompartment.STATUS, True
|
503
|
+
),
|
504
|
+
"t10cn": CCLSensorPreset(
|
505
|
+
"Connection: CO\u2082",
|
506
|
+
CCLSensorTypes.CONNECTION,
|
507
|
+
CCLDeviceCompartment.STATUS,
|
508
|
+
True,
|
509
|
+
),
|
510
|
+
"t9cn": CCLSensorPreset(
|
511
|
+
"Connection: HCHO/VOC",
|
512
|
+
CCLSensorTypes.CONNECTION,
|
513
|
+
CCLDeviceCompartment.STATUS,
|
514
|
+
True,
|
515
|
+
),
|
516
|
+
"t1cn": CCLSensorPreset(
|
517
|
+
"Connection: Sensor Array",
|
518
|
+
CCLSensorTypes.CONNECTION,
|
519
|
+
CCLDeviceCompartment.STATUS,
|
520
|
+
True,
|
521
|
+
),
|
522
|
+
"t8cn": CCLSensorPreset(
|
523
|
+
"Connection: PM2.5/10",
|
524
|
+
CCLSensorTypes.CONNECTION,
|
525
|
+
CCLDeviceCompartment.STATUS,
|
526
|
+
True,
|
527
|
+
),
|
218
528
|
}
|
aioccl/server.py
CHANGED
@@ -1,113 +1,112 @@
|
|
1
1
|
"""CCL API server and handler."""
|
2
|
+
|
2
3
|
from __future__ import annotations
|
3
4
|
|
4
|
-
import asyncio
|
5
5
|
import logging
|
6
6
|
|
7
7
|
from aiohttp import web
|
8
|
-
import aiohttp_cors
|
9
8
|
|
10
9
|
from .device import CCLDevice, CCL_DEVICE_INFO_TYPES
|
11
10
|
from .sensor import CCL_SENSORS
|
12
11
|
|
13
12
|
_LOGGER = logging.getLogger(__name__)
|
14
13
|
|
14
|
+
|
15
15
|
class CCLServer:
|
16
|
+
"""Represent a CCL server manager."""
|
17
|
+
|
16
18
|
LISTEN_PORT = 42373
|
17
|
-
|
19
|
+
|
18
20
|
devices: dict[str, CCLDevice] = {}
|
19
|
-
|
21
|
+
|
22
|
+
@staticmethod
|
20
23
|
def add_copy(device: CCLDevice) -> None:
|
21
24
|
"""Attach a device copy to the server."""
|
22
25
|
CCLServer.devices.setdefault(device.passkey, device)
|
23
26
|
_LOGGER.debug(CCLServer.devices)
|
24
27
|
|
25
|
-
#routes = web.RouteTableDef()
|
28
|
+
# routes = web.RouteTableDef()
|
26
29
|
|
30
|
+
@staticmethod
|
27
31
|
async def _handler(request: web.BaseRequest) -> web.Response:
|
28
32
|
"""Handle POST requests for data updating."""
|
33
|
+
|
29
34
|
class HandlerStorage:
|
35
|
+
"""Store data for a single request."""
|
36
|
+
|
30
37
|
body: dict[str, None | str | int | float]
|
31
38
|
info: dict[str, None | str]
|
32
39
|
sensors: dict[str, None | str | int | float]
|
33
|
-
|
40
|
+
|
34
41
|
_LOGGER.debug("Request received.")
|
35
|
-
|
42
|
+
|
36
43
|
# Resetting variables
|
37
44
|
_device: CCLDevice = None
|
38
45
|
|
39
46
|
HandlerStorage.body = {}
|
40
47
|
HandlerStorage.info = {}
|
41
48
|
HandlerStorage.sensors = {}
|
42
|
-
|
49
|
+
|
43
50
|
_status: None | int = None
|
44
51
|
_text: None | str = None
|
45
|
-
|
52
|
+
|
46
53
|
try:
|
47
|
-
for passkey in CCLServer.devices:
|
48
|
-
if passkey == request.match_info[
|
49
|
-
_device = CCLServer.devices[passkey]
|
54
|
+
for passkey, _device in CCLServer.devices.items():
|
55
|
+
if passkey == request.match_info["passkey"]:
|
50
56
|
break
|
51
57
|
assert _device, 404
|
52
|
-
|
53
|
-
assert request.content_type ==
|
58
|
+
|
59
|
+
assert request.content_type == "application/json", 400
|
54
60
|
assert 0 < request.content_length <= 5000, 400
|
55
|
-
|
61
|
+
|
56
62
|
HandlerStorage.body = await request.json()
|
57
63
|
_LOGGER.debug(HandlerStorage.body)
|
58
|
-
|
59
|
-
except Exception as err:
|
64
|
+
|
65
|
+
except Exception as err: # pylint: disable=broad-exception-caught
|
60
66
|
_status = err.args[0]
|
61
|
-
if _status == 400:
|
62
|
-
|
67
|
+
if _status == 400:
|
68
|
+
_text = "400 Bad Request"
|
69
|
+
elif _status == 404:
|
70
|
+
_text = "404 Not Found"
|
63
71
|
else:
|
64
72
|
_status = 500
|
65
73
|
_text = "500 Internal Server Error"
|
66
74
|
_LOGGER.debug("Request exception occured: %s", err)
|
67
|
-
|
75
|
+
return web.Response(status=_status, text=_text)
|
76
|
+
|
68
77
|
else:
|
69
78
|
for key, value in HandlerStorage.body.items():
|
70
79
|
if key in CCL_DEVICE_INFO_TYPES:
|
71
80
|
HandlerStorage.info.setdefault(key, value)
|
72
|
-
elif key in CCL_SENSORS
|
81
|
+
elif key in CCL_SENSORS:
|
73
82
|
HandlerStorage.sensors.setdefault(key, value)
|
74
|
-
|
83
|
+
|
75
84
|
_device.update_info(HandlerStorage.info)
|
76
85
|
_device.update_sensors(HandlerStorage.sensors)
|
77
86
|
_status = 200
|
78
87
|
_text = "200 OK"
|
79
88
|
_LOGGER.debug("Request processed.")
|
80
|
-
|
81
|
-
finally:
|
82
89
|
return web.Response(status=_status, text=_text)
|
83
90
|
|
84
91
|
app = web.Application()
|
92
|
+
|
93
|
+
app.add_routes([web.get('/{passkey}', _handler)])
|
85
94
|
|
86
|
-
|
87
|
-
|
88
|
-
resource = cors.add(app.router.add_resource("/{passkey}"))
|
89
|
-
route = cors.add(
|
90
|
-
resource.add_route("POST", _handler), {
|
91
|
-
"*": aiohttp_cors.ResourceOptions(
|
92
|
-
allow_credentials=True,
|
93
|
-
expose_headers="*",
|
94
|
-
allow_headers="*",
|
95
|
-
)
|
96
|
-
})
|
97
|
-
|
95
|
+
@staticmethod
|
98
96
|
async def run() -> None:
|
99
97
|
"""Try to run the API server in case none is available."""
|
100
98
|
try:
|
101
99
|
_LOGGER.debug("Trying to start the API server.")
|
102
|
-
runner = web.AppRunner(CCLServer.app)
|
103
|
-
await runner.setup()
|
104
|
-
site = web.TCPSite(runner, port=CCLServer.LISTEN_PORT)
|
100
|
+
CCLServer.runner = web.AppRunner(CCLServer.app)
|
101
|
+
await CCLServer.runner.setup()
|
102
|
+
site = web.TCPSite(CCLServer.runner, port=CCLServer.LISTEN_PORT)
|
105
103
|
await site.start()
|
106
|
-
except Exception as err:
|
104
|
+
except Exception as err: # pylint: disable=broad-exception-caught
|
107
105
|
_LOGGER.warning("Failed to run the API server: %s", err)
|
108
106
|
else:
|
109
107
|
_LOGGER.debug("Successfully started the API server.")
|
110
108
|
|
109
|
+
@staticmethod
|
111
110
|
async def stop() -> None:
|
112
111
|
"""Stop running the API server."""
|
113
112
|
await CCLServer.runner.cleanup()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: aioccl
|
3
|
-
Version: 2024.
|
3
|
+
Version: 2024.12
|
4
4
|
Summary: A Python library for CCL API server
|
5
5
|
Home-page: https://github.com/fkiscd/aioccl
|
6
6
|
Download-URL: https://github.com/fkiscd/aioccl
|
@@ -16,8 +16,8 @@ Classifier: Programming Language :: Python :: 3
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
17
17
|
Description-Content-Type: text/markdown
|
18
18
|
License-File: LICENSE
|
19
|
-
Requires-Dist: aiohttp
|
20
|
-
Requires-Dist:
|
19
|
+
Requires-Dist: aiohttp>3
|
20
|
+
Requires-Dist: aiohttp_cors>=0.7.0
|
21
21
|
|
22
22
|
# aioCCL
|
23
23
|
A Python library for CCL API server
|
@@ -0,0 +1,9 @@
|
|
1
|
+
aioccl/__init__.py,sha256=XnegKtbvHvUTwVuuWNLb4LB9ZuGGar0xrZYOqk7scyg,133
|
2
|
+
aioccl/device.py,sha256=AjTlcIFysxPg57InXE8BEnRethEpypZsu5wf3tW5wuk,5390
|
3
|
+
aioccl/sensor.py,sha256=tMv_ypqsDIxWdghHQv91PUTOt2kUJGygZmFnJtzOx0k,16905
|
4
|
+
aioccl/server.py,sha256=T9VY5gqdr-NcDbytH_8IkHDTUGKpDqAxyOJX3yy4L70,3588
|
5
|
+
aioccl-2024.12.dist-info/LICENSE,sha256=PBRsTHchx7o0TQ2R2ktEAfFmn1iNHTxcOP_xaeuSAuo,11349
|
6
|
+
aioccl-2024.12.dist-info/METADATA,sha256=udIKIXa6n6BstSdHv2WLTJF6CeSun_v2p3ibRNLVWEQ,766
|
7
|
+
aioccl-2024.12.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
8
|
+
aioccl-2024.12.dist-info/top_level.txt,sha256=-xIJfyfXTaW_EH7XCIHyxjSSSwjLmawa2qhsrHZH1vA,7
|
9
|
+
aioccl-2024.12.dist-info/RECORD,,
|
aioccl-2024.9.8.dist-info/RECORD
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
aioccl/__init__.py,sha256=iL1OC2F_rf3qkswi-bO8Y_uj2-lf284LCnyxwqdLUU8,137
|
2
|
-
aioccl/device.py,sha256=ALvK7qvGlG0duS1axPz7uQj85vHW1iyzezvX2bD2Zuc,4994
|
3
|
-
aioccl/sensor.py,sha256=jvff3BlaW_Rf7kwZ9neRu3cqINmyOFnjwZ7TrJ5msmI,14525
|
4
|
-
aioccl/server.py,sha256=-ZDii20CLqj4_jqVVqRMlnvg-CCtJiZjuMMDamem0DE,3717
|
5
|
-
aioccl-2024.9.8.dist-info/LICENSE,sha256=PBRsTHchx7o0TQ2R2ktEAfFmn1iNHTxcOP_xaeuSAuo,11349
|
6
|
-
aioccl-2024.9.8.dist-info/METADATA,sha256=dsdm4dLviWUx9b5UKOFhrhKSUTzuJIK4nRKLsCMxCHg,769
|
7
|
-
aioccl-2024.9.8.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
8
|
-
aioccl-2024.9.8.dist-info/top_level.txt,sha256=-xIJfyfXTaW_EH7XCIHyxjSSSwjLmawa2qhsrHZH1vA,7
|
9
|
-
aioccl-2024.9.8.dist-info/RECORD,,
|
File without changes
|
File without changes
|