pylxpweb 0.1.0__py3-none-any.whl → 0.5.2__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.
- pylxpweb/__init__.py +47 -2
- pylxpweb/api_namespace.py +241 -0
- pylxpweb/cli/__init__.py +3 -0
- pylxpweb/cli/collect_device_data.py +874 -0
- pylxpweb/client.py +387 -26
- pylxpweb/constants/__init__.py +481 -0
- pylxpweb/constants/api.py +48 -0
- pylxpweb/constants/devices.py +98 -0
- pylxpweb/constants/locations.py +227 -0
- pylxpweb/{constants.py → constants/registers.py} +72 -238
- pylxpweb/constants/scaling.py +479 -0
- pylxpweb/devices/__init__.py +32 -0
- pylxpweb/devices/_firmware_update_mixin.py +504 -0
- pylxpweb/devices/_mid_runtime_properties.py +1427 -0
- pylxpweb/devices/base.py +122 -0
- pylxpweb/devices/battery.py +589 -0
- pylxpweb/devices/battery_bank.py +331 -0
- pylxpweb/devices/inverters/__init__.py +32 -0
- pylxpweb/devices/inverters/_features.py +378 -0
- pylxpweb/devices/inverters/_runtime_properties.py +596 -0
- pylxpweb/devices/inverters/base.py +2124 -0
- pylxpweb/devices/inverters/generic.py +192 -0
- pylxpweb/devices/inverters/hybrid.py +274 -0
- pylxpweb/devices/mid_device.py +183 -0
- pylxpweb/devices/models.py +126 -0
- pylxpweb/devices/parallel_group.py +364 -0
- pylxpweb/devices/station.py +908 -0
- pylxpweb/endpoints/control.py +980 -2
- pylxpweb/endpoints/devices.py +249 -16
- pylxpweb/endpoints/firmware.py +43 -10
- pylxpweb/endpoints/plants.py +15 -19
- pylxpweb/exceptions.py +4 -0
- pylxpweb/models.py +708 -41
- pylxpweb/transports/__init__.py +78 -0
- pylxpweb/transports/capabilities.py +101 -0
- pylxpweb/transports/data.py +501 -0
- pylxpweb/transports/exceptions.py +59 -0
- pylxpweb/transports/factory.py +119 -0
- pylxpweb/transports/http.py +329 -0
- pylxpweb/transports/modbus.py +617 -0
- pylxpweb/transports/protocol.py +217 -0
- {pylxpweb-0.1.0.dist-info → pylxpweb-0.5.2.dist-info}/METADATA +130 -85
- pylxpweb-0.5.2.dist-info/RECORD +52 -0
- {pylxpweb-0.1.0.dist-info → pylxpweb-0.5.2.dist-info}/WHEEL +1 -1
- pylxpweb-0.5.2.dist-info/entry_points.txt +3 -0
- pylxpweb-0.1.0.dist-info/RECORD +0 -19
|
@@ -0,0 +1,1427 @@
|
|
|
1
|
+
"""Runtime properties mixin for MIDDevice (GridBOSS).
|
|
2
|
+
|
|
3
|
+
This mixin provides properly-scaled property accessors for all GridBOSS
|
|
4
|
+
sensor data from the MID device runtime API. All properties return typed,
|
|
5
|
+
scaled values with graceful None handling.
|
|
6
|
+
|
|
7
|
+
Properties are organized by category:
|
|
8
|
+
- Voltage Properties (Grid, UPS, Generator - aggregate and per-phase)
|
|
9
|
+
- Current Properties (Grid, Load, Generator, UPS - per-phase)
|
|
10
|
+
- Power Properties (Grid, Load, Generator, UPS - per-phase and totals)
|
|
11
|
+
- Frequency Properties
|
|
12
|
+
- Smart Port Status
|
|
13
|
+
- System Status & Info
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from typing import TYPE_CHECKING
|
|
19
|
+
|
|
20
|
+
from pylxpweb.constants import scale_mid_frequency, scale_mid_voltage
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from pylxpweb.models import MidboxRuntime
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class MIDRuntimePropertiesMixin:
|
|
27
|
+
"""Mixin providing runtime property accessors for MID devices."""
|
|
28
|
+
|
|
29
|
+
_runtime: MidboxRuntime | None
|
|
30
|
+
|
|
31
|
+
# ===========================================
|
|
32
|
+
# Voltage Properties - Aggregate
|
|
33
|
+
# ===========================================
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def grid_voltage(self) -> float:
|
|
37
|
+
"""Get aggregate grid voltage in volts.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
Grid RMS voltage (÷10), or 0.0 if no data.
|
|
41
|
+
"""
|
|
42
|
+
if self._runtime is None:
|
|
43
|
+
return 0.0
|
|
44
|
+
|
|
45
|
+
return scale_mid_voltage(self._runtime.midboxData.gridRmsVolt)
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def ups_voltage(self) -> float:
|
|
49
|
+
"""Get aggregate UPS voltage in volts.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
UPS RMS voltage (÷10), or 0.0 if no data.
|
|
53
|
+
"""
|
|
54
|
+
if self._runtime is None:
|
|
55
|
+
return 0.0
|
|
56
|
+
|
|
57
|
+
return scale_mid_voltage(self._runtime.midboxData.upsRmsVolt)
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def generator_voltage(self) -> float:
|
|
61
|
+
"""Get aggregate generator voltage in volts.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
Generator RMS voltage (÷10), or 0.0 if no data.
|
|
65
|
+
"""
|
|
66
|
+
if self._runtime is None:
|
|
67
|
+
return 0.0
|
|
68
|
+
|
|
69
|
+
return scale_mid_voltage(self._runtime.midboxData.genRmsVolt)
|
|
70
|
+
|
|
71
|
+
# ===========================================
|
|
72
|
+
# Voltage Properties - Grid Per-Phase
|
|
73
|
+
# ===========================================
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def grid_l1_voltage(self) -> float:
|
|
77
|
+
"""Get grid L1 voltage in volts.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Grid L1 RMS voltage (÷10), or 0.0 if no data.
|
|
81
|
+
"""
|
|
82
|
+
if self._runtime is None:
|
|
83
|
+
return 0.0
|
|
84
|
+
|
|
85
|
+
return scale_mid_voltage(self._runtime.midboxData.gridL1RmsVolt)
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def grid_l2_voltage(self) -> float:
|
|
89
|
+
"""Get grid L2 voltage in volts.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Grid L2 RMS voltage (÷10), or 0.0 if no data.
|
|
93
|
+
"""
|
|
94
|
+
if self._runtime is None:
|
|
95
|
+
return 0.0
|
|
96
|
+
|
|
97
|
+
return scale_mid_voltage(self._runtime.midboxData.gridL2RmsVolt)
|
|
98
|
+
|
|
99
|
+
# ===========================================
|
|
100
|
+
# Voltage Properties - UPS Per-Phase
|
|
101
|
+
# ===========================================
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
def ups_l1_voltage(self) -> float:
|
|
105
|
+
"""Get UPS L1 voltage in volts.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
UPS L1 RMS voltage (÷10), or 0.0 if no data.
|
|
109
|
+
"""
|
|
110
|
+
if self._runtime is None:
|
|
111
|
+
return 0.0
|
|
112
|
+
|
|
113
|
+
return scale_mid_voltage(self._runtime.midboxData.upsL1RmsVolt)
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def ups_l2_voltage(self) -> float:
|
|
117
|
+
"""Get UPS L2 voltage in volts.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
UPS L2 RMS voltage (÷10), or 0.0 if no data.
|
|
121
|
+
"""
|
|
122
|
+
if self._runtime is None:
|
|
123
|
+
return 0.0
|
|
124
|
+
|
|
125
|
+
return scale_mid_voltage(self._runtime.midboxData.upsL2RmsVolt)
|
|
126
|
+
|
|
127
|
+
# ===========================================
|
|
128
|
+
# Voltage Properties - Generator Per-Phase
|
|
129
|
+
# ===========================================
|
|
130
|
+
|
|
131
|
+
@property
|
|
132
|
+
def generator_l1_voltage(self) -> float:
|
|
133
|
+
"""Get generator L1 voltage in volts.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Generator L1 RMS voltage (÷10), or 0.0 if no data.
|
|
137
|
+
"""
|
|
138
|
+
if self._runtime is None:
|
|
139
|
+
return 0.0
|
|
140
|
+
|
|
141
|
+
return scale_mid_voltage(self._runtime.midboxData.genL1RmsVolt)
|
|
142
|
+
|
|
143
|
+
@property
|
|
144
|
+
def generator_l2_voltage(self) -> float:
|
|
145
|
+
"""Get generator L2 voltage in volts.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
Generator L2 RMS voltage (÷10), or 0.0 if no data.
|
|
149
|
+
"""
|
|
150
|
+
if self._runtime is None:
|
|
151
|
+
return 0.0
|
|
152
|
+
|
|
153
|
+
return scale_mid_voltage(self._runtime.midboxData.genL2RmsVolt)
|
|
154
|
+
|
|
155
|
+
# ===========================================
|
|
156
|
+
# Current Properties - Grid
|
|
157
|
+
# ===========================================
|
|
158
|
+
|
|
159
|
+
@property
|
|
160
|
+
def grid_l1_current(self) -> float:
|
|
161
|
+
"""Get grid L1 current in amps.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
Grid L1 RMS current (÷100), or 0.0 if no data.
|
|
165
|
+
"""
|
|
166
|
+
if self._runtime is None:
|
|
167
|
+
return 0.0
|
|
168
|
+
return self._runtime.midboxData.gridL1RmsCurr / 100.0
|
|
169
|
+
|
|
170
|
+
@property
|
|
171
|
+
def grid_l2_current(self) -> float:
|
|
172
|
+
"""Get grid L2 current in amps.
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
Grid L2 RMS current (÷100), or 0.0 if no data.
|
|
176
|
+
"""
|
|
177
|
+
if self._runtime is None:
|
|
178
|
+
return 0.0
|
|
179
|
+
return self._runtime.midboxData.gridL2RmsCurr / 100.0
|
|
180
|
+
|
|
181
|
+
# ===========================================
|
|
182
|
+
# Current Properties - Load
|
|
183
|
+
# ===========================================
|
|
184
|
+
|
|
185
|
+
@property
|
|
186
|
+
def load_l1_current(self) -> float:
|
|
187
|
+
"""Get load L1 current in amps.
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
Load L1 RMS current (÷100), or 0.0 if no data.
|
|
191
|
+
"""
|
|
192
|
+
if self._runtime is None:
|
|
193
|
+
return 0.0
|
|
194
|
+
return self._runtime.midboxData.loadL1RmsCurr / 100.0
|
|
195
|
+
|
|
196
|
+
@property
|
|
197
|
+
def load_l2_current(self) -> float:
|
|
198
|
+
"""Get load L2 current in amps.
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
Load L2 RMS current (÷100), or 0.0 if no data.
|
|
202
|
+
"""
|
|
203
|
+
if self._runtime is None:
|
|
204
|
+
return 0.0
|
|
205
|
+
return self._runtime.midboxData.loadL2RmsCurr / 100.0
|
|
206
|
+
|
|
207
|
+
# ===========================================
|
|
208
|
+
# Current Properties - Generator
|
|
209
|
+
# ===========================================
|
|
210
|
+
|
|
211
|
+
@property
|
|
212
|
+
def generator_l1_current(self) -> float:
|
|
213
|
+
"""Get generator L1 current in amps.
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
Generator L1 RMS current (÷100), or 0.0 if no data.
|
|
217
|
+
"""
|
|
218
|
+
if self._runtime is None:
|
|
219
|
+
return 0.0
|
|
220
|
+
return self._runtime.midboxData.genL1RmsCurr / 100.0
|
|
221
|
+
|
|
222
|
+
@property
|
|
223
|
+
def generator_l2_current(self) -> float:
|
|
224
|
+
"""Get generator L2 current in amps.
|
|
225
|
+
|
|
226
|
+
Returns:
|
|
227
|
+
Generator L2 RMS current (÷100), or 0.0 if no data.
|
|
228
|
+
"""
|
|
229
|
+
if self._runtime is None:
|
|
230
|
+
return 0.0
|
|
231
|
+
return self._runtime.midboxData.genL2RmsCurr / 100.0
|
|
232
|
+
|
|
233
|
+
# ===========================================
|
|
234
|
+
# Current Properties - UPS
|
|
235
|
+
# ===========================================
|
|
236
|
+
|
|
237
|
+
@property
|
|
238
|
+
def ups_l1_current(self) -> float:
|
|
239
|
+
"""Get UPS L1 current in amps.
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
UPS L1 RMS current (÷100), or 0.0 if no data.
|
|
243
|
+
"""
|
|
244
|
+
if self._runtime is None:
|
|
245
|
+
return 0.0
|
|
246
|
+
return self._runtime.midboxData.upsL1RmsCurr / 100.0
|
|
247
|
+
|
|
248
|
+
@property
|
|
249
|
+
def ups_l2_current(self) -> float:
|
|
250
|
+
"""Get UPS L2 current in amps.
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
UPS L2 RMS current (÷100), or 0.0 if no data.
|
|
254
|
+
"""
|
|
255
|
+
if self._runtime is None:
|
|
256
|
+
return 0.0
|
|
257
|
+
return self._runtime.midboxData.upsL2RmsCurr / 100.0
|
|
258
|
+
|
|
259
|
+
# ===========================================
|
|
260
|
+
# Power Properties - Grid
|
|
261
|
+
# ===========================================
|
|
262
|
+
|
|
263
|
+
@property
|
|
264
|
+
def grid_l1_power(self) -> int:
|
|
265
|
+
"""Get grid L1 active power in watts.
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
Grid L1 power, or 0 if no data.
|
|
269
|
+
"""
|
|
270
|
+
if self._runtime is None:
|
|
271
|
+
return 0
|
|
272
|
+
return self._runtime.midboxData.gridL1ActivePower
|
|
273
|
+
|
|
274
|
+
@property
|
|
275
|
+
def grid_l2_power(self) -> int:
|
|
276
|
+
"""Get grid L2 active power in watts.
|
|
277
|
+
|
|
278
|
+
Returns:
|
|
279
|
+
Grid L2 power, or 0 if no data.
|
|
280
|
+
"""
|
|
281
|
+
if self._runtime is None:
|
|
282
|
+
return 0
|
|
283
|
+
return self._runtime.midboxData.gridL2ActivePower
|
|
284
|
+
|
|
285
|
+
@property
|
|
286
|
+
def grid_power(self) -> int:
|
|
287
|
+
"""Get total grid power in watts (L1 + L2).
|
|
288
|
+
|
|
289
|
+
Returns:
|
|
290
|
+
Total grid power, or 0 if no data.
|
|
291
|
+
"""
|
|
292
|
+
if self._runtime is None:
|
|
293
|
+
return 0
|
|
294
|
+
return (
|
|
295
|
+
self._runtime.midboxData.gridL1ActivePower + self._runtime.midboxData.gridL2ActivePower
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
# ===========================================
|
|
299
|
+
# Power Properties - Load
|
|
300
|
+
# ===========================================
|
|
301
|
+
|
|
302
|
+
@property
|
|
303
|
+
def load_l1_power(self) -> int:
|
|
304
|
+
"""Get load L1 active power in watts.
|
|
305
|
+
|
|
306
|
+
Returns:
|
|
307
|
+
Load L1 power, or 0 if no data.
|
|
308
|
+
"""
|
|
309
|
+
if self._runtime is None:
|
|
310
|
+
return 0
|
|
311
|
+
return self._runtime.midboxData.loadL1ActivePower
|
|
312
|
+
|
|
313
|
+
@property
|
|
314
|
+
def load_l2_power(self) -> int:
|
|
315
|
+
"""Get load L2 active power in watts.
|
|
316
|
+
|
|
317
|
+
Returns:
|
|
318
|
+
Load L2 power, or 0 if no data.
|
|
319
|
+
"""
|
|
320
|
+
if self._runtime is None:
|
|
321
|
+
return 0
|
|
322
|
+
return self._runtime.midboxData.loadL2ActivePower
|
|
323
|
+
|
|
324
|
+
@property
|
|
325
|
+
def load_power(self) -> int:
|
|
326
|
+
"""Get total load power in watts (L1 + L2).
|
|
327
|
+
|
|
328
|
+
Returns:
|
|
329
|
+
Total load power, or 0 if no data.
|
|
330
|
+
"""
|
|
331
|
+
if self._runtime is None:
|
|
332
|
+
return 0
|
|
333
|
+
return (
|
|
334
|
+
self._runtime.midboxData.loadL1ActivePower + self._runtime.midboxData.loadL2ActivePower
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
# ===========================================
|
|
338
|
+
# Power Properties - Generator
|
|
339
|
+
# ===========================================
|
|
340
|
+
|
|
341
|
+
@property
|
|
342
|
+
def generator_l1_power(self) -> int:
|
|
343
|
+
"""Get generator L1 active power in watts.
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
Generator L1 power, or 0 if no data.
|
|
347
|
+
"""
|
|
348
|
+
if self._runtime is None:
|
|
349
|
+
return 0
|
|
350
|
+
return self._runtime.midboxData.genL1ActivePower
|
|
351
|
+
|
|
352
|
+
@property
|
|
353
|
+
def generator_l2_power(self) -> int:
|
|
354
|
+
"""Get generator L2 active power in watts.
|
|
355
|
+
|
|
356
|
+
Returns:
|
|
357
|
+
Generator L2 power, or 0 if no data.
|
|
358
|
+
"""
|
|
359
|
+
if self._runtime is None:
|
|
360
|
+
return 0
|
|
361
|
+
return self._runtime.midboxData.genL2ActivePower
|
|
362
|
+
|
|
363
|
+
@property
|
|
364
|
+
def generator_power(self) -> int:
|
|
365
|
+
"""Get total generator power in watts (L1 + L2).
|
|
366
|
+
|
|
367
|
+
Returns:
|
|
368
|
+
Total generator power, or 0 if no data.
|
|
369
|
+
"""
|
|
370
|
+
if self._runtime is None:
|
|
371
|
+
return 0
|
|
372
|
+
return self._runtime.midboxData.genL1ActivePower + self._runtime.midboxData.genL2ActivePower
|
|
373
|
+
|
|
374
|
+
# ===========================================
|
|
375
|
+
# Power Properties - UPS
|
|
376
|
+
# ===========================================
|
|
377
|
+
|
|
378
|
+
@property
|
|
379
|
+
def ups_l1_power(self) -> int:
|
|
380
|
+
"""Get UPS L1 active power in watts.
|
|
381
|
+
|
|
382
|
+
Returns:
|
|
383
|
+
UPS L1 power, or 0 if no data.
|
|
384
|
+
"""
|
|
385
|
+
if self._runtime is None:
|
|
386
|
+
return 0
|
|
387
|
+
return self._runtime.midboxData.upsL1ActivePower
|
|
388
|
+
|
|
389
|
+
@property
|
|
390
|
+
def ups_l2_power(self) -> int:
|
|
391
|
+
"""Get UPS L2 active power in watts.
|
|
392
|
+
|
|
393
|
+
Returns:
|
|
394
|
+
UPS L2 power, or 0 if no data.
|
|
395
|
+
"""
|
|
396
|
+
if self._runtime is None:
|
|
397
|
+
return 0
|
|
398
|
+
return self._runtime.midboxData.upsL2ActivePower
|
|
399
|
+
|
|
400
|
+
@property
|
|
401
|
+
def ups_power(self) -> int:
|
|
402
|
+
"""Get total UPS power in watts (L1 + L2).
|
|
403
|
+
|
|
404
|
+
Returns:
|
|
405
|
+
Total UPS power, or 0 if no data.
|
|
406
|
+
"""
|
|
407
|
+
if self._runtime is None:
|
|
408
|
+
return 0
|
|
409
|
+
return self._runtime.midboxData.upsL1ActivePower + self._runtime.midboxData.upsL2ActivePower
|
|
410
|
+
|
|
411
|
+
# ===========================================
|
|
412
|
+
# Power Properties - Hybrid System
|
|
413
|
+
# ===========================================
|
|
414
|
+
|
|
415
|
+
@property
|
|
416
|
+
def hybrid_power(self) -> int:
|
|
417
|
+
"""Get hybrid system power in watts.
|
|
418
|
+
|
|
419
|
+
Returns:
|
|
420
|
+
Hybrid power (combined system power), or 0 if no data.
|
|
421
|
+
"""
|
|
422
|
+
if self._runtime is None:
|
|
423
|
+
return 0
|
|
424
|
+
return self._runtime.midboxData.hybridPower
|
|
425
|
+
|
|
426
|
+
# ===========================================
|
|
427
|
+
# Frequency Properties
|
|
428
|
+
# ===========================================
|
|
429
|
+
|
|
430
|
+
@property
|
|
431
|
+
def grid_frequency(self) -> float:
|
|
432
|
+
"""Get grid frequency in Hz.
|
|
433
|
+
|
|
434
|
+
Returns:
|
|
435
|
+
Grid frequency (÷100), or 0.0 if no data.
|
|
436
|
+
"""
|
|
437
|
+
if self._runtime is None:
|
|
438
|
+
return 0.0
|
|
439
|
+
|
|
440
|
+
return scale_mid_frequency(self._runtime.midboxData.gridFreq)
|
|
441
|
+
|
|
442
|
+
# ===========================================
|
|
443
|
+
# Smart Port Status
|
|
444
|
+
# ===========================================
|
|
445
|
+
|
|
446
|
+
@property
|
|
447
|
+
def smart_port1_status(self) -> int:
|
|
448
|
+
"""Get smart port 1 status.
|
|
449
|
+
|
|
450
|
+
Returns:
|
|
451
|
+
Port 1 status code, or 0 if no data.
|
|
452
|
+
"""
|
|
453
|
+
if self._runtime is None:
|
|
454
|
+
return 0
|
|
455
|
+
return self._runtime.midboxData.smartPort1Status
|
|
456
|
+
|
|
457
|
+
@property
|
|
458
|
+
def smart_port2_status(self) -> int:
|
|
459
|
+
"""Get smart port 2 status.
|
|
460
|
+
|
|
461
|
+
Returns:
|
|
462
|
+
Port 2 status code, or 0 if no data.
|
|
463
|
+
"""
|
|
464
|
+
if self._runtime is None:
|
|
465
|
+
return 0
|
|
466
|
+
return self._runtime.midboxData.smartPort2Status
|
|
467
|
+
|
|
468
|
+
@property
|
|
469
|
+
def smart_port3_status(self) -> int:
|
|
470
|
+
"""Get smart port 3 status.
|
|
471
|
+
|
|
472
|
+
Returns:
|
|
473
|
+
Port 3 status code, or 0 if no data.
|
|
474
|
+
"""
|
|
475
|
+
if self._runtime is None:
|
|
476
|
+
return 0
|
|
477
|
+
return self._runtime.midboxData.smartPort3Status
|
|
478
|
+
|
|
479
|
+
@property
|
|
480
|
+
def smart_port4_status(self) -> int:
|
|
481
|
+
"""Get smart port 4 status.
|
|
482
|
+
|
|
483
|
+
Returns:
|
|
484
|
+
Port 4 status code, or 0 if no data.
|
|
485
|
+
"""
|
|
486
|
+
if self._runtime is None:
|
|
487
|
+
return 0
|
|
488
|
+
return self._runtime.midboxData.smartPort4Status
|
|
489
|
+
|
|
490
|
+
# ===========================================
|
|
491
|
+
# System Status & Info
|
|
492
|
+
# ===========================================
|
|
493
|
+
|
|
494
|
+
@property
|
|
495
|
+
def status(self) -> int:
|
|
496
|
+
"""Get device status code.
|
|
497
|
+
|
|
498
|
+
Returns:
|
|
499
|
+
Status code, or 0 if no data.
|
|
500
|
+
"""
|
|
501
|
+
if self._runtime is None:
|
|
502
|
+
return 0
|
|
503
|
+
return self._runtime.midboxData.status
|
|
504
|
+
|
|
505
|
+
@property
|
|
506
|
+
def server_time(self) -> str:
|
|
507
|
+
"""Get server timestamp.
|
|
508
|
+
|
|
509
|
+
Returns:
|
|
510
|
+
Server time string, or empty string if no data.
|
|
511
|
+
"""
|
|
512
|
+
if self._runtime is None:
|
|
513
|
+
return ""
|
|
514
|
+
return self._runtime.midboxData.serverTime
|
|
515
|
+
|
|
516
|
+
@property
|
|
517
|
+
def device_time(self) -> str:
|
|
518
|
+
"""Get device timestamp.
|
|
519
|
+
|
|
520
|
+
Returns:
|
|
521
|
+
Device time string, or empty string if no data.
|
|
522
|
+
"""
|
|
523
|
+
if self._runtime is None:
|
|
524
|
+
return ""
|
|
525
|
+
return self._runtime.midboxData.deviceTime
|
|
526
|
+
|
|
527
|
+
@property
|
|
528
|
+
def firmware_version(self) -> str:
|
|
529
|
+
"""Get firmware version.
|
|
530
|
+
|
|
531
|
+
Returns:
|
|
532
|
+
Firmware version string, or empty string if no data.
|
|
533
|
+
"""
|
|
534
|
+
if self._runtime is None:
|
|
535
|
+
return ""
|
|
536
|
+
return self._runtime.fwCode
|
|
537
|
+
|
|
538
|
+
@property
|
|
539
|
+
def has_data(self) -> bool:
|
|
540
|
+
"""Check if device has runtime data.
|
|
541
|
+
|
|
542
|
+
Returns:
|
|
543
|
+
True if runtime data is available.
|
|
544
|
+
"""
|
|
545
|
+
return self._runtime is not None
|
|
546
|
+
|
|
547
|
+
# ===========================================
|
|
548
|
+
# Energy Properties - UPS
|
|
549
|
+
# ===========================================
|
|
550
|
+
|
|
551
|
+
@property
|
|
552
|
+
def e_ups_today_l1(self) -> float | None:
|
|
553
|
+
"""Get UPS L1 energy today in kWh.
|
|
554
|
+
|
|
555
|
+
Returns:
|
|
556
|
+
UPS L1 energy today (÷10), or None if not available.
|
|
557
|
+
"""
|
|
558
|
+
if self._runtime is None:
|
|
559
|
+
return None
|
|
560
|
+
val = self._runtime.midboxData.eUpsTodayL1
|
|
561
|
+
return val / 10.0 if val is not None else None
|
|
562
|
+
|
|
563
|
+
@property
|
|
564
|
+
def e_ups_today_l2(self) -> float | None:
|
|
565
|
+
"""Get UPS L2 energy today in kWh.
|
|
566
|
+
|
|
567
|
+
Returns:
|
|
568
|
+
UPS L2 energy today (÷10), or None if not available.
|
|
569
|
+
"""
|
|
570
|
+
if self._runtime is None:
|
|
571
|
+
return None
|
|
572
|
+
val = self._runtime.midboxData.eUpsTodayL2
|
|
573
|
+
return val / 10.0 if val is not None else None
|
|
574
|
+
|
|
575
|
+
@property
|
|
576
|
+
def e_ups_total_l1(self) -> float | None:
|
|
577
|
+
"""Get UPS L1 lifetime energy in kWh.
|
|
578
|
+
|
|
579
|
+
Returns:
|
|
580
|
+
UPS L1 lifetime energy (÷10), or None if not available.
|
|
581
|
+
"""
|
|
582
|
+
if self._runtime is None:
|
|
583
|
+
return None
|
|
584
|
+
val = self._runtime.midboxData.eUpsTotalL1
|
|
585
|
+
return val / 10.0 if val is not None else None
|
|
586
|
+
|
|
587
|
+
@property
|
|
588
|
+
def e_ups_total_l2(self) -> float | None:
|
|
589
|
+
"""Get UPS L2 lifetime energy in kWh.
|
|
590
|
+
|
|
591
|
+
Returns:
|
|
592
|
+
UPS L2 lifetime energy (÷10), or None if not available.
|
|
593
|
+
"""
|
|
594
|
+
if self._runtime is None:
|
|
595
|
+
return None
|
|
596
|
+
val = self._runtime.midboxData.eUpsTotalL2
|
|
597
|
+
return val / 10.0 if val is not None else None
|
|
598
|
+
|
|
599
|
+
# ===========================================
|
|
600
|
+
# Energy Properties - Grid Export
|
|
601
|
+
# ===========================================
|
|
602
|
+
|
|
603
|
+
@property
|
|
604
|
+
def e_to_grid_today_l1(self) -> float | None:
|
|
605
|
+
"""Get grid export L1 energy today in kWh.
|
|
606
|
+
|
|
607
|
+
Returns:
|
|
608
|
+
Grid export L1 energy today (÷10), or None if not available.
|
|
609
|
+
"""
|
|
610
|
+
if self._runtime is None:
|
|
611
|
+
return None
|
|
612
|
+
val = self._runtime.midboxData.eToGridTodayL1
|
|
613
|
+
return val / 10.0 if val is not None else None
|
|
614
|
+
|
|
615
|
+
@property
|
|
616
|
+
def e_to_grid_today_l2(self) -> float | None:
|
|
617
|
+
"""Get grid export L2 energy today in kWh.
|
|
618
|
+
|
|
619
|
+
Returns:
|
|
620
|
+
Grid export L2 energy today (÷10), or None if not available.
|
|
621
|
+
"""
|
|
622
|
+
if self._runtime is None:
|
|
623
|
+
return None
|
|
624
|
+
val = self._runtime.midboxData.eToGridTodayL2
|
|
625
|
+
return val / 10.0 if val is not None else None
|
|
626
|
+
|
|
627
|
+
@property
|
|
628
|
+
def e_to_grid_total_l1(self) -> float | None:
|
|
629
|
+
"""Get grid export L1 lifetime energy in kWh.
|
|
630
|
+
|
|
631
|
+
Returns:
|
|
632
|
+
Grid export L1 lifetime energy (÷10), or None if not available.
|
|
633
|
+
"""
|
|
634
|
+
if self._runtime is None:
|
|
635
|
+
return None
|
|
636
|
+
val = self._runtime.midboxData.eToGridTotalL1
|
|
637
|
+
return val / 10.0 if val is not None else None
|
|
638
|
+
|
|
639
|
+
@property
|
|
640
|
+
def e_to_grid_total_l2(self) -> float | None:
|
|
641
|
+
"""Get grid export L2 lifetime energy in kWh.
|
|
642
|
+
|
|
643
|
+
Returns:
|
|
644
|
+
Grid export L2 lifetime energy (÷10), or None if not available.
|
|
645
|
+
"""
|
|
646
|
+
if self._runtime is None:
|
|
647
|
+
return None
|
|
648
|
+
val = self._runtime.midboxData.eToGridTotalL2
|
|
649
|
+
return val / 10.0 if val is not None else None
|
|
650
|
+
|
|
651
|
+
# ===========================================
|
|
652
|
+
# Energy Properties - Grid Import
|
|
653
|
+
# ===========================================
|
|
654
|
+
|
|
655
|
+
@property
|
|
656
|
+
def e_to_user_today_l1(self) -> float | None:
|
|
657
|
+
"""Get grid import L1 energy today in kWh.
|
|
658
|
+
|
|
659
|
+
Returns:
|
|
660
|
+
Grid import L1 energy today (÷10), or None if not available.
|
|
661
|
+
"""
|
|
662
|
+
if self._runtime is None:
|
|
663
|
+
return None
|
|
664
|
+
val = self._runtime.midboxData.eToUserTodayL1
|
|
665
|
+
return val / 10.0 if val is not None else None
|
|
666
|
+
|
|
667
|
+
@property
|
|
668
|
+
def e_to_user_today_l2(self) -> float | None:
|
|
669
|
+
"""Get grid import L2 energy today in kWh.
|
|
670
|
+
|
|
671
|
+
Returns:
|
|
672
|
+
Grid import L2 energy today (÷10), or None if not available.
|
|
673
|
+
"""
|
|
674
|
+
if self._runtime is None:
|
|
675
|
+
return None
|
|
676
|
+
val = self._runtime.midboxData.eToUserTodayL2
|
|
677
|
+
return val / 10.0 if val is not None else None
|
|
678
|
+
|
|
679
|
+
@property
|
|
680
|
+
def e_to_user_total_l1(self) -> float | None:
|
|
681
|
+
"""Get grid import L1 lifetime energy in kWh.
|
|
682
|
+
|
|
683
|
+
Returns:
|
|
684
|
+
Grid import L1 lifetime energy (÷10), or None if not available.
|
|
685
|
+
"""
|
|
686
|
+
if self._runtime is None:
|
|
687
|
+
return None
|
|
688
|
+
val = self._runtime.midboxData.eToUserTotalL1
|
|
689
|
+
return val / 10.0 if val is not None else None
|
|
690
|
+
|
|
691
|
+
@property
|
|
692
|
+
def e_to_user_total_l2(self) -> float | None:
|
|
693
|
+
"""Get grid import L2 lifetime energy in kWh.
|
|
694
|
+
|
|
695
|
+
Returns:
|
|
696
|
+
Grid import L2 lifetime energy (÷10), or None if not available.
|
|
697
|
+
"""
|
|
698
|
+
if self._runtime is None:
|
|
699
|
+
return None
|
|
700
|
+
val = self._runtime.midboxData.eToUserTotalL2
|
|
701
|
+
return val / 10.0 if val is not None else None
|
|
702
|
+
|
|
703
|
+
# ===========================================
|
|
704
|
+
# Energy Properties - Load
|
|
705
|
+
# ===========================================
|
|
706
|
+
|
|
707
|
+
@property
|
|
708
|
+
def e_load_today_l1(self) -> float | None:
|
|
709
|
+
"""Get load L1 energy today in kWh.
|
|
710
|
+
|
|
711
|
+
Returns:
|
|
712
|
+
Load L1 energy today (÷10), or None if not available.
|
|
713
|
+
"""
|
|
714
|
+
if self._runtime is None:
|
|
715
|
+
return None
|
|
716
|
+
val = self._runtime.midboxData.eLoadTodayL1
|
|
717
|
+
return val / 10.0 if val is not None else None
|
|
718
|
+
|
|
719
|
+
@property
|
|
720
|
+
def e_load_today_l2(self) -> float | None:
|
|
721
|
+
"""Get load L2 energy today in kWh.
|
|
722
|
+
|
|
723
|
+
Returns:
|
|
724
|
+
Load L2 energy today (÷10), or None if not available.
|
|
725
|
+
"""
|
|
726
|
+
if self._runtime is None:
|
|
727
|
+
return None
|
|
728
|
+
val = self._runtime.midboxData.eLoadTodayL2
|
|
729
|
+
return val / 10.0 if val is not None else None
|
|
730
|
+
|
|
731
|
+
@property
|
|
732
|
+
def e_load_total_l1(self) -> float | None:
|
|
733
|
+
"""Get load L1 lifetime energy in kWh.
|
|
734
|
+
|
|
735
|
+
Returns:
|
|
736
|
+
Load L1 lifetime energy (÷10), or None if not available.
|
|
737
|
+
"""
|
|
738
|
+
if self._runtime is None:
|
|
739
|
+
return None
|
|
740
|
+
val = self._runtime.midboxData.eLoadTotalL1
|
|
741
|
+
return val / 10.0 if val is not None else None
|
|
742
|
+
|
|
743
|
+
@property
|
|
744
|
+
def e_load_total_l2(self) -> float | None:
|
|
745
|
+
"""Get load L2 lifetime energy in kWh.
|
|
746
|
+
|
|
747
|
+
Returns:
|
|
748
|
+
Load L2 lifetime energy (÷10), or None if not available.
|
|
749
|
+
"""
|
|
750
|
+
if self._runtime is None:
|
|
751
|
+
return None
|
|
752
|
+
val = self._runtime.midboxData.eLoadTotalL2
|
|
753
|
+
return val / 10.0 if val is not None else None
|
|
754
|
+
|
|
755
|
+
# ===========================================
|
|
756
|
+
# Energy Properties - AC Couple 1
|
|
757
|
+
# ===========================================
|
|
758
|
+
|
|
759
|
+
@property
|
|
760
|
+
def e_ac_couple1_today_l1(self) -> float | None:
|
|
761
|
+
"""Get AC Couple 1 L1 energy today in kWh.
|
|
762
|
+
|
|
763
|
+
Returns:
|
|
764
|
+
AC Couple 1 L1 energy today (÷10), or None if not available.
|
|
765
|
+
"""
|
|
766
|
+
if self._runtime is None:
|
|
767
|
+
return None
|
|
768
|
+
val = self._runtime.midboxData.eACcouple1TodayL1
|
|
769
|
+
return val / 10.0 if val is not None else None
|
|
770
|
+
|
|
771
|
+
@property
|
|
772
|
+
def e_ac_couple1_today_l2(self) -> float | None:
|
|
773
|
+
"""Get AC Couple 1 L2 energy today in kWh.
|
|
774
|
+
|
|
775
|
+
Returns:
|
|
776
|
+
AC Couple 1 L2 energy today (÷10), or None if not available.
|
|
777
|
+
"""
|
|
778
|
+
if self._runtime is None:
|
|
779
|
+
return None
|
|
780
|
+
val = self._runtime.midboxData.eACcouple1TodayL2
|
|
781
|
+
return val / 10.0 if val is not None else None
|
|
782
|
+
|
|
783
|
+
@property
|
|
784
|
+
def e_ac_couple1_total_l1(self) -> float | None:
|
|
785
|
+
"""Get AC Couple 1 L1 lifetime energy in kWh.
|
|
786
|
+
|
|
787
|
+
Returns:
|
|
788
|
+
AC Couple 1 L1 lifetime energy (÷10), or None if not available.
|
|
789
|
+
"""
|
|
790
|
+
if self._runtime is None:
|
|
791
|
+
return None
|
|
792
|
+
val = self._runtime.midboxData.eACcouple1TotalL1
|
|
793
|
+
return val / 10.0 if val is not None else None
|
|
794
|
+
|
|
795
|
+
@property
|
|
796
|
+
def e_ac_couple1_total_l2(self) -> float | None:
|
|
797
|
+
"""Get AC Couple 1 L2 lifetime energy in kWh.
|
|
798
|
+
|
|
799
|
+
Returns:
|
|
800
|
+
AC Couple 1 L2 lifetime energy (÷10), or None if not available.
|
|
801
|
+
"""
|
|
802
|
+
if self._runtime is None:
|
|
803
|
+
return None
|
|
804
|
+
val = self._runtime.midboxData.eACcouple1TotalL2
|
|
805
|
+
return val / 10.0 if val is not None else None
|
|
806
|
+
|
|
807
|
+
# ===========================================
|
|
808
|
+
# Energy Properties - AC Couple 2
|
|
809
|
+
# ===========================================
|
|
810
|
+
|
|
811
|
+
@property
|
|
812
|
+
def e_ac_couple2_today_l1(self) -> float | None:
|
|
813
|
+
"""Get AC Couple 2 L1 energy today in kWh.
|
|
814
|
+
|
|
815
|
+
Returns:
|
|
816
|
+
AC Couple 2 L1 energy today (÷10), or None if not available.
|
|
817
|
+
"""
|
|
818
|
+
if self._runtime is None:
|
|
819
|
+
return None
|
|
820
|
+
val = self._runtime.midboxData.eACcouple2TodayL1
|
|
821
|
+
return val / 10.0 if val is not None else None
|
|
822
|
+
|
|
823
|
+
@property
|
|
824
|
+
def e_ac_couple2_today_l2(self) -> float | None:
|
|
825
|
+
"""Get AC Couple 2 L2 energy today in kWh.
|
|
826
|
+
|
|
827
|
+
Returns:
|
|
828
|
+
AC Couple 2 L2 energy today (÷10), or None if not available.
|
|
829
|
+
"""
|
|
830
|
+
if self._runtime is None:
|
|
831
|
+
return None
|
|
832
|
+
val = self._runtime.midboxData.eACcouple2TodayL2
|
|
833
|
+
return val / 10.0 if val is not None else None
|
|
834
|
+
|
|
835
|
+
@property
|
|
836
|
+
def e_ac_couple2_total_l1(self) -> float | None:
|
|
837
|
+
"""Get AC Couple 2 L1 lifetime energy in kWh.
|
|
838
|
+
|
|
839
|
+
Returns:
|
|
840
|
+
AC Couple 2 L1 lifetime energy (÷10), or None if not available.
|
|
841
|
+
"""
|
|
842
|
+
if self._runtime is None:
|
|
843
|
+
return None
|
|
844
|
+
val = self._runtime.midboxData.eACcouple2TotalL1
|
|
845
|
+
return val / 10.0 if val is not None else None
|
|
846
|
+
|
|
847
|
+
@property
|
|
848
|
+
def e_ac_couple2_total_l2(self) -> float | None:
|
|
849
|
+
"""Get AC Couple 2 L2 lifetime energy in kWh.
|
|
850
|
+
|
|
851
|
+
Returns:
|
|
852
|
+
AC Couple 2 L2 lifetime energy (÷10), or None if not available.
|
|
853
|
+
"""
|
|
854
|
+
if self._runtime is None:
|
|
855
|
+
return None
|
|
856
|
+
val = self._runtime.midboxData.eACcouple2TotalL2
|
|
857
|
+
return val / 10.0 if val is not None else None
|
|
858
|
+
|
|
859
|
+
# ===========================================
|
|
860
|
+
# Energy Properties - AC Couple 3
|
|
861
|
+
# ===========================================
|
|
862
|
+
|
|
863
|
+
@property
|
|
864
|
+
def e_ac_couple3_today_l1(self) -> float | None:
|
|
865
|
+
"""Get AC Couple 3 L1 energy today in kWh.
|
|
866
|
+
|
|
867
|
+
Returns:
|
|
868
|
+
AC Couple 3 L1 energy today (÷10), or None if not available.
|
|
869
|
+
"""
|
|
870
|
+
if self._runtime is None:
|
|
871
|
+
return None
|
|
872
|
+
val = self._runtime.midboxData.eACcouple3TodayL1
|
|
873
|
+
return val / 10.0 if val is not None else None
|
|
874
|
+
|
|
875
|
+
@property
|
|
876
|
+
def e_ac_couple3_today_l2(self) -> float | None:
|
|
877
|
+
"""Get AC Couple 3 L2 energy today in kWh.
|
|
878
|
+
|
|
879
|
+
Returns:
|
|
880
|
+
AC Couple 3 L2 energy today (÷10), or None if not available.
|
|
881
|
+
"""
|
|
882
|
+
if self._runtime is None:
|
|
883
|
+
return None
|
|
884
|
+
val = self._runtime.midboxData.eACcouple3TodayL2
|
|
885
|
+
return val / 10.0 if val is not None else None
|
|
886
|
+
|
|
887
|
+
@property
|
|
888
|
+
def e_ac_couple3_total_l1(self) -> float | None:
|
|
889
|
+
"""Get AC Couple 3 L1 lifetime energy in kWh.
|
|
890
|
+
|
|
891
|
+
Returns:
|
|
892
|
+
AC Couple 3 L1 lifetime energy (÷10), or None if not available.
|
|
893
|
+
"""
|
|
894
|
+
if self._runtime is None:
|
|
895
|
+
return None
|
|
896
|
+
val = self._runtime.midboxData.eACcouple3TotalL1
|
|
897
|
+
return val / 10.0 if val is not None else None
|
|
898
|
+
|
|
899
|
+
@property
|
|
900
|
+
def e_ac_couple3_total_l2(self) -> float | None:
|
|
901
|
+
"""Get AC Couple 3 L2 lifetime energy in kWh.
|
|
902
|
+
|
|
903
|
+
Returns:
|
|
904
|
+
AC Couple 3 L2 lifetime energy (÷10), or None if not available.
|
|
905
|
+
"""
|
|
906
|
+
if self._runtime is None:
|
|
907
|
+
return None
|
|
908
|
+
val = self._runtime.midboxData.eACcouple3TotalL2
|
|
909
|
+
return val / 10.0 if val is not None else None
|
|
910
|
+
|
|
911
|
+
# ===========================================
|
|
912
|
+
# Energy Properties - AC Couple 4
|
|
913
|
+
# ===========================================
|
|
914
|
+
|
|
915
|
+
@property
|
|
916
|
+
def e_ac_couple4_today_l1(self) -> float | None:
|
|
917
|
+
"""Get AC Couple 4 L1 energy today in kWh.
|
|
918
|
+
|
|
919
|
+
Returns:
|
|
920
|
+
AC Couple 4 L1 energy today (÷10), or None if not available.
|
|
921
|
+
"""
|
|
922
|
+
if self._runtime is None:
|
|
923
|
+
return None
|
|
924
|
+
val = self._runtime.midboxData.eACcouple4TodayL1
|
|
925
|
+
return val / 10.0 if val is not None else None
|
|
926
|
+
|
|
927
|
+
@property
|
|
928
|
+
def e_ac_couple4_today_l2(self) -> float | None:
|
|
929
|
+
"""Get AC Couple 4 L2 energy today in kWh.
|
|
930
|
+
|
|
931
|
+
Returns:
|
|
932
|
+
AC Couple 4 L2 energy today (÷10), or None if not available.
|
|
933
|
+
"""
|
|
934
|
+
if self._runtime is None:
|
|
935
|
+
return None
|
|
936
|
+
val = self._runtime.midboxData.eACcouple4TodayL2
|
|
937
|
+
return val / 10.0 if val is not None else None
|
|
938
|
+
|
|
939
|
+
@property
|
|
940
|
+
def e_ac_couple4_total_l1(self) -> float | None:
|
|
941
|
+
"""Get AC Couple 4 L1 lifetime energy in kWh.
|
|
942
|
+
|
|
943
|
+
Returns:
|
|
944
|
+
AC Couple 4 L1 lifetime energy (÷10), or None if not available.
|
|
945
|
+
"""
|
|
946
|
+
if self._runtime is None:
|
|
947
|
+
return None
|
|
948
|
+
val = self._runtime.midboxData.eACcouple4TotalL1
|
|
949
|
+
return val / 10.0 if val is not None else None
|
|
950
|
+
|
|
951
|
+
@property
|
|
952
|
+
def e_ac_couple4_total_l2(self) -> float | None:
|
|
953
|
+
"""Get AC Couple 4 L2 lifetime energy in kWh.
|
|
954
|
+
|
|
955
|
+
Returns:
|
|
956
|
+
AC Couple 4 L2 lifetime energy (÷10), or None if not available.
|
|
957
|
+
"""
|
|
958
|
+
if self._runtime is None:
|
|
959
|
+
return None
|
|
960
|
+
val = self._runtime.midboxData.eACcouple4TotalL2
|
|
961
|
+
return val / 10.0 if val is not None else None
|
|
962
|
+
|
|
963
|
+
# ===========================================
|
|
964
|
+
# Energy Properties - Smart Load 1
|
|
965
|
+
# ===========================================
|
|
966
|
+
|
|
967
|
+
@property
|
|
968
|
+
def e_smart_load1_today_l1(self) -> float | None:
|
|
969
|
+
"""Get Smart Load 1 L1 energy today in kWh.
|
|
970
|
+
|
|
971
|
+
Returns:
|
|
972
|
+
Smart Load 1 L1 energy today (÷10), or None if not available.
|
|
973
|
+
"""
|
|
974
|
+
if self._runtime is None:
|
|
975
|
+
return None
|
|
976
|
+
val = self._runtime.midboxData.eSmartLoad1TodayL1
|
|
977
|
+
return val / 10.0 if val is not None else None
|
|
978
|
+
|
|
979
|
+
@property
|
|
980
|
+
def e_smart_load1_today_l2(self) -> float | None:
|
|
981
|
+
"""Get Smart Load 1 L2 energy today in kWh.
|
|
982
|
+
|
|
983
|
+
Returns:
|
|
984
|
+
Smart Load 1 L2 energy today (÷10), or None if not available.
|
|
985
|
+
"""
|
|
986
|
+
if self._runtime is None:
|
|
987
|
+
return None
|
|
988
|
+
val = self._runtime.midboxData.eSmartLoad1TodayL2
|
|
989
|
+
return val / 10.0 if val is not None else None
|
|
990
|
+
|
|
991
|
+
@property
|
|
992
|
+
def e_smart_load1_total_l1(self) -> float | None:
|
|
993
|
+
"""Get Smart Load 1 L1 lifetime energy in kWh.
|
|
994
|
+
|
|
995
|
+
Returns:
|
|
996
|
+
Smart Load 1 L1 lifetime energy (÷10), or None if not available.
|
|
997
|
+
"""
|
|
998
|
+
if self._runtime is None:
|
|
999
|
+
return None
|
|
1000
|
+
val = self._runtime.midboxData.eSmartLoad1TotalL1
|
|
1001
|
+
return val / 10.0 if val is not None else None
|
|
1002
|
+
|
|
1003
|
+
@property
|
|
1004
|
+
def e_smart_load1_total_l2(self) -> float | None:
|
|
1005
|
+
"""Get Smart Load 1 L2 lifetime energy in kWh.
|
|
1006
|
+
|
|
1007
|
+
Returns:
|
|
1008
|
+
Smart Load 1 L2 lifetime energy (÷10), or None if not available.
|
|
1009
|
+
"""
|
|
1010
|
+
if self._runtime is None:
|
|
1011
|
+
return None
|
|
1012
|
+
val = self._runtime.midboxData.eSmartLoad1TotalL2
|
|
1013
|
+
return val / 10.0 if val is not None else None
|
|
1014
|
+
|
|
1015
|
+
# ===========================================
|
|
1016
|
+
# Energy Properties - Smart Load 2
|
|
1017
|
+
# ===========================================
|
|
1018
|
+
|
|
1019
|
+
@property
|
|
1020
|
+
def e_smart_load2_today_l1(self) -> float | None:
|
|
1021
|
+
"""Get Smart Load 2 L1 energy today in kWh.
|
|
1022
|
+
|
|
1023
|
+
Returns:
|
|
1024
|
+
Smart Load 2 L1 energy today (÷10), or None if not available.
|
|
1025
|
+
"""
|
|
1026
|
+
if self._runtime is None:
|
|
1027
|
+
return None
|
|
1028
|
+
val = self._runtime.midboxData.eSmartLoad2TodayL1
|
|
1029
|
+
return val / 10.0 if val is not None else None
|
|
1030
|
+
|
|
1031
|
+
@property
|
|
1032
|
+
def e_smart_load2_today_l2(self) -> float | None:
|
|
1033
|
+
"""Get Smart Load 2 L2 energy today in kWh.
|
|
1034
|
+
|
|
1035
|
+
Returns:
|
|
1036
|
+
Smart Load 2 L2 energy today (÷10), or None if not available.
|
|
1037
|
+
"""
|
|
1038
|
+
if self._runtime is None:
|
|
1039
|
+
return None
|
|
1040
|
+
val = self._runtime.midboxData.eSmartLoad2TodayL2
|
|
1041
|
+
return val / 10.0 if val is not None else None
|
|
1042
|
+
|
|
1043
|
+
@property
|
|
1044
|
+
def e_smart_load2_total_l1(self) -> float | None:
|
|
1045
|
+
"""Get Smart Load 2 L1 lifetime energy in kWh.
|
|
1046
|
+
|
|
1047
|
+
Returns:
|
|
1048
|
+
Smart Load 2 L1 lifetime energy (÷10), or None if not available.
|
|
1049
|
+
"""
|
|
1050
|
+
if self._runtime is None:
|
|
1051
|
+
return None
|
|
1052
|
+
val = self._runtime.midboxData.eSmartLoad2TotalL1
|
|
1053
|
+
return val / 10.0 if val is not None else None
|
|
1054
|
+
|
|
1055
|
+
@property
|
|
1056
|
+
def e_smart_load2_total_l2(self) -> float | None:
|
|
1057
|
+
"""Get Smart Load 2 L2 lifetime energy in kWh.
|
|
1058
|
+
|
|
1059
|
+
Returns:
|
|
1060
|
+
Smart Load 2 L2 lifetime energy (÷10), or None if not available.
|
|
1061
|
+
"""
|
|
1062
|
+
if self._runtime is None:
|
|
1063
|
+
return None
|
|
1064
|
+
val = self._runtime.midboxData.eSmartLoad2TotalL2
|
|
1065
|
+
return val / 10.0 if val is not None else None
|
|
1066
|
+
|
|
1067
|
+
# ===========================================
|
|
1068
|
+
# Energy Properties - Smart Load 3
|
|
1069
|
+
# ===========================================
|
|
1070
|
+
|
|
1071
|
+
@property
|
|
1072
|
+
def e_smart_load3_today_l1(self) -> float | None:
|
|
1073
|
+
"""Get Smart Load 3 L1 energy today in kWh.
|
|
1074
|
+
|
|
1075
|
+
Returns:
|
|
1076
|
+
Smart Load 3 L1 energy today (÷10), or None if not available.
|
|
1077
|
+
"""
|
|
1078
|
+
if self._runtime is None:
|
|
1079
|
+
return None
|
|
1080
|
+
val = self._runtime.midboxData.eSmartLoad3TodayL1
|
|
1081
|
+
return val / 10.0 if val is not None else None
|
|
1082
|
+
|
|
1083
|
+
@property
|
|
1084
|
+
def e_smart_load3_today_l2(self) -> float | None:
|
|
1085
|
+
"""Get Smart Load 3 L2 energy today in kWh.
|
|
1086
|
+
|
|
1087
|
+
Returns:
|
|
1088
|
+
Smart Load 3 L2 energy today (÷10), or None if not available.
|
|
1089
|
+
"""
|
|
1090
|
+
if self._runtime is None:
|
|
1091
|
+
return None
|
|
1092
|
+
val = self._runtime.midboxData.eSmartLoad3TodayL2
|
|
1093
|
+
return val / 10.0 if val is not None else None
|
|
1094
|
+
|
|
1095
|
+
@property
|
|
1096
|
+
def e_smart_load3_total_l1(self) -> float | None:
|
|
1097
|
+
"""Get Smart Load 3 L1 lifetime energy in kWh.
|
|
1098
|
+
|
|
1099
|
+
Returns:
|
|
1100
|
+
Smart Load 3 L1 lifetime energy (÷10), or None if not available.
|
|
1101
|
+
"""
|
|
1102
|
+
if self._runtime is None:
|
|
1103
|
+
return None
|
|
1104
|
+
val = self._runtime.midboxData.eSmartLoad3TotalL1
|
|
1105
|
+
return val / 10.0 if val is not None else None
|
|
1106
|
+
|
|
1107
|
+
@property
|
|
1108
|
+
def e_smart_load3_total_l2(self) -> float | None:
|
|
1109
|
+
"""Get Smart Load 3 L2 lifetime energy in kWh.
|
|
1110
|
+
|
|
1111
|
+
Returns:
|
|
1112
|
+
Smart Load 3 L2 lifetime energy (÷10), or None if not available.
|
|
1113
|
+
"""
|
|
1114
|
+
if self._runtime is None:
|
|
1115
|
+
return None
|
|
1116
|
+
val = self._runtime.midboxData.eSmartLoad3TotalL2
|
|
1117
|
+
return val / 10.0 if val is not None else None
|
|
1118
|
+
|
|
1119
|
+
# ===========================================
|
|
1120
|
+
# Energy Properties - Smart Load 4
|
|
1121
|
+
# ===========================================
|
|
1122
|
+
|
|
1123
|
+
@property
|
|
1124
|
+
def e_smart_load4_today_l1(self) -> float | None:
|
|
1125
|
+
"""Get Smart Load 4 L1 energy today in kWh.
|
|
1126
|
+
|
|
1127
|
+
Returns:
|
|
1128
|
+
Smart Load 4 L1 energy today (÷10), or None if not available.
|
|
1129
|
+
"""
|
|
1130
|
+
if self._runtime is None:
|
|
1131
|
+
return None
|
|
1132
|
+
val = self._runtime.midboxData.eSmartLoad4TodayL1
|
|
1133
|
+
return val / 10.0 if val is not None else None
|
|
1134
|
+
|
|
1135
|
+
@property
|
|
1136
|
+
def e_smart_load4_today_l2(self) -> float | None:
|
|
1137
|
+
"""Get Smart Load 4 L2 energy today in kWh.
|
|
1138
|
+
|
|
1139
|
+
Returns:
|
|
1140
|
+
Smart Load 4 L2 energy today (÷10), or None if not available.
|
|
1141
|
+
"""
|
|
1142
|
+
if self._runtime is None:
|
|
1143
|
+
return None
|
|
1144
|
+
val = self._runtime.midboxData.eSmartLoad4TodayL2
|
|
1145
|
+
return val / 10.0 if val is not None else None
|
|
1146
|
+
|
|
1147
|
+
@property
|
|
1148
|
+
def e_smart_load4_total_l1(self) -> float | None:
|
|
1149
|
+
"""Get Smart Load 4 L1 lifetime energy in kWh.
|
|
1150
|
+
|
|
1151
|
+
Returns:
|
|
1152
|
+
Smart Load 4 L1 lifetime energy (÷10), or None if not available.
|
|
1153
|
+
"""
|
|
1154
|
+
if self._runtime is None:
|
|
1155
|
+
return None
|
|
1156
|
+
val = self._runtime.midboxData.eSmartLoad4TotalL1
|
|
1157
|
+
return val / 10.0 if val is not None else None
|
|
1158
|
+
|
|
1159
|
+
@property
|
|
1160
|
+
def e_smart_load4_total_l2(self) -> float | None:
|
|
1161
|
+
"""Get Smart Load 4 L2 lifetime energy in kWh.
|
|
1162
|
+
|
|
1163
|
+
Returns:
|
|
1164
|
+
Smart Load 4 L2 lifetime energy (÷10), or None if not available.
|
|
1165
|
+
"""
|
|
1166
|
+
if self._runtime is None:
|
|
1167
|
+
return None
|
|
1168
|
+
val = self._runtime.midboxData.eSmartLoad4TotalL2
|
|
1169
|
+
return val / 10.0 if val is not None else None
|
|
1170
|
+
|
|
1171
|
+
# ===========================================
|
|
1172
|
+
# Aggregate Energy Properties (L1 + L2)
|
|
1173
|
+
# ===========================================
|
|
1174
|
+
|
|
1175
|
+
def _sum_energy(self, l1: float | None, l2: float | None) -> float | None:
|
|
1176
|
+
"""Sum L1 and L2 energy values, returning None if both are None.
|
|
1177
|
+
|
|
1178
|
+
Args:
|
|
1179
|
+
l1: L1 phase energy value or None
|
|
1180
|
+
l2: L2 phase energy value or None
|
|
1181
|
+
|
|
1182
|
+
Returns:
|
|
1183
|
+
Sum of L1 + L2, treating None as 0, or None if both are None.
|
|
1184
|
+
"""
|
|
1185
|
+
if l1 is None and l2 is None:
|
|
1186
|
+
return None
|
|
1187
|
+
return (l1 or 0.0) + (l2 or 0.0)
|
|
1188
|
+
|
|
1189
|
+
# UPS Energy Aggregates
|
|
1190
|
+
|
|
1191
|
+
@property
|
|
1192
|
+
def e_ups_today(self) -> float | None:
|
|
1193
|
+
"""Get total UPS energy today in kWh (L1 + L2).
|
|
1194
|
+
|
|
1195
|
+
Returns:
|
|
1196
|
+
Total UPS energy today, or None if not available.
|
|
1197
|
+
"""
|
|
1198
|
+
return self._sum_energy(self.e_ups_today_l1, self.e_ups_today_l2)
|
|
1199
|
+
|
|
1200
|
+
@property
|
|
1201
|
+
def e_ups_total(self) -> float | None:
|
|
1202
|
+
"""Get total UPS lifetime energy in kWh (L1 + L2).
|
|
1203
|
+
|
|
1204
|
+
Returns:
|
|
1205
|
+
Total UPS lifetime energy, or None if not available.
|
|
1206
|
+
"""
|
|
1207
|
+
return self._sum_energy(self.e_ups_total_l1, self.e_ups_total_l2)
|
|
1208
|
+
|
|
1209
|
+
# Grid Export Energy Aggregates
|
|
1210
|
+
|
|
1211
|
+
@property
|
|
1212
|
+
def e_to_grid_today(self) -> float | None:
|
|
1213
|
+
"""Get total grid export energy today in kWh (L1 + L2).
|
|
1214
|
+
|
|
1215
|
+
Returns:
|
|
1216
|
+
Total grid export energy today, or None if not available.
|
|
1217
|
+
"""
|
|
1218
|
+
return self._sum_energy(self.e_to_grid_today_l1, self.e_to_grid_today_l2)
|
|
1219
|
+
|
|
1220
|
+
@property
|
|
1221
|
+
def e_to_grid_total(self) -> float | None:
|
|
1222
|
+
"""Get total grid export lifetime energy in kWh (L1 + L2).
|
|
1223
|
+
|
|
1224
|
+
Returns:
|
|
1225
|
+
Total grid export lifetime energy, or None if not available.
|
|
1226
|
+
"""
|
|
1227
|
+
return self._sum_energy(self.e_to_grid_total_l1, self.e_to_grid_total_l2)
|
|
1228
|
+
|
|
1229
|
+
# Grid Import Energy Aggregates
|
|
1230
|
+
|
|
1231
|
+
@property
|
|
1232
|
+
def e_to_user_today(self) -> float | None:
|
|
1233
|
+
"""Get total grid import energy today in kWh (L1 + L2).
|
|
1234
|
+
|
|
1235
|
+
Returns:
|
|
1236
|
+
Total grid import energy today, or None if not available.
|
|
1237
|
+
"""
|
|
1238
|
+
return self._sum_energy(self.e_to_user_today_l1, self.e_to_user_today_l2)
|
|
1239
|
+
|
|
1240
|
+
@property
|
|
1241
|
+
def e_to_user_total(self) -> float | None:
|
|
1242
|
+
"""Get total grid import lifetime energy in kWh (L1 + L2).
|
|
1243
|
+
|
|
1244
|
+
Returns:
|
|
1245
|
+
Total grid import lifetime energy, or None if not available.
|
|
1246
|
+
"""
|
|
1247
|
+
return self._sum_energy(self.e_to_user_total_l1, self.e_to_user_total_l2)
|
|
1248
|
+
|
|
1249
|
+
# Load Energy Aggregates
|
|
1250
|
+
|
|
1251
|
+
@property
|
|
1252
|
+
def e_load_today(self) -> float | None:
|
|
1253
|
+
"""Get total load energy today in kWh (L1 + L2).
|
|
1254
|
+
|
|
1255
|
+
Returns:
|
|
1256
|
+
Total load energy today, or None if not available.
|
|
1257
|
+
"""
|
|
1258
|
+
return self._sum_energy(self.e_load_today_l1, self.e_load_today_l2)
|
|
1259
|
+
|
|
1260
|
+
@property
|
|
1261
|
+
def e_load_total(self) -> float | None:
|
|
1262
|
+
"""Get total load lifetime energy in kWh (L1 + L2).
|
|
1263
|
+
|
|
1264
|
+
Returns:
|
|
1265
|
+
Total load lifetime energy, or None if not available.
|
|
1266
|
+
"""
|
|
1267
|
+
return self._sum_energy(self.e_load_total_l1, self.e_load_total_l2)
|
|
1268
|
+
|
|
1269
|
+
# AC Couple 1 Energy Aggregates
|
|
1270
|
+
|
|
1271
|
+
@property
|
|
1272
|
+
def e_ac_couple1_today(self) -> float | None:
|
|
1273
|
+
"""Get total AC Couple 1 energy today in kWh (L1 + L2).
|
|
1274
|
+
|
|
1275
|
+
Returns:
|
|
1276
|
+
Total AC Couple 1 energy today, or None if not available.
|
|
1277
|
+
"""
|
|
1278
|
+
return self._sum_energy(self.e_ac_couple1_today_l1, self.e_ac_couple1_today_l2)
|
|
1279
|
+
|
|
1280
|
+
@property
|
|
1281
|
+
def e_ac_couple1_total(self) -> float | None:
|
|
1282
|
+
"""Get total AC Couple 1 lifetime energy in kWh (L1 + L2).
|
|
1283
|
+
|
|
1284
|
+
Returns:
|
|
1285
|
+
Total AC Couple 1 lifetime energy, or None if not available.
|
|
1286
|
+
"""
|
|
1287
|
+
return self._sum_energy(self.e_ac_couple1_total_l1, self.e_ac_couple1_total_l2)
|
|
1288
|
+
|
|
1289
|
+
# AC Couple 2 Energy Aggregates
|
|
1290
|
+
|
|
1291
|
+
@property
|
|
1292
|
+
def e_ac_couple2_today(self) -> float | None:
|
|
1293
|
+
"""Get total AC Couple 2 energy today in kWh (L1 + L2).
|
|
1294
|
+
|
|
1295
|
+
Returns:
|
|
1296
|
+
Total AC Couple 2 energy today, or None if not available.
|
|
1297
|
+
"""
|
|
1298
|
+
return self._sum_energy(self.e_ac_couple2_today_l1, self.e_ac_couple2_today_l2)
|
|
1299
|
+
|
|
1300
|
+
@property
|
|
1301
|
+
def e_ac_couple2_total(self) -> float | None:
|
|
1302
|
+
"""Get total AC Couple 2 lifetime energy in kWh (L1 + L2).
|
|
1303
|
+
|
|
1304
|
+
Returns:
|
|
1305
|
+
Total AC Couple 2 lifetime energy, or None if not available.
|
|
1306
|
+
"""
|
|
1307
|
+
return self._sum_energy(self.e_ac_couple2_total_l1, self.e_ac_couple2_total_l2)
|
|
1308
|
+
|
|
1309
|
+
# AC Couple 3 Energy Aggregates
|
|
1310
|
+
|
|
1311
|
+
@property
|
|
1312
|
+
def e_ac_couple3_today(self) -> float | None:
|
|
1313
|
+
"""Get total AC Couple 3 energy today in kWh (L1 + L2).
|
|
1314
|
+
|
|
1315
|
+
Returns:
|
|
1316
|
+
Total AC Couple 3 energy today, or None if not available.
|
|
1317
|
+
"""
|
|
1318
|
+
return self._sum_energy(self.e_ac_couple3_today_l1, self.e_ac_couple3_today_l2)
|
|
1319
|
+
|
|
1320
|
+
@property
|
|
1321
|
+
def e_ac_couple3_total(self) -> float | None:
|
|
1322
|
+
"""Get total AC Couple 3 lifetime energy in kWh (L1 + L2).
|
|
1323
|
+
|
|
1324
|
+
Returns:
|
|
1325
|
+
Total AC Couple 3 lifetime energy, or None if not available.
|
|
1326
|
+
"""
|
|
1327
|
+
return self._sum_energy(self.e_ac_couple3_total_l1, self.e_ac_couple3_total_l2)
|
|
1328
|
+
|
|
1329
|
+
# AC Couple 4 Energy Aggregates
|
|
1330
|
+
|
|
1331
|
+
@property
|
|
1332
|
+
def e_ac_couple4_today(self) -> float | None:
|
|
1333
|
+
"""Get total AC Couple 4 energy today in kWh (L1 + L2).
|
|
1334
|
+
|
|
1335
|
+
Returns:
|
|
1336
|
+
Total AC Couple 4 energy today, or None if not available.
|
|
1337
|
+
"""
|
|
1338
|
+
return self._sum_energy(self.e_ac_couple4_today_l1, self.e_ac_couple4_today_l2)
|
|
1339
|
+
|
|
1340
|
+
@property
|
|
1341
|
+
def e_ac_couple4_total(self) -> float | None:
|
|
1342
|
+
"""Get total AC Couple 4 lifetime energy in kWh (L1 + L2).
|
|
1343
|
+
|
|
1344
|
+
Returns:
|
|
1345
|
+
Total AC Couple 4 lifetime energy, or None if not available.
|
|
1346
|
+
"""
|
|
1347
|
+
return self._sum_energy(self.e_ac_couple4_total_l1, self.e_ac_couple4_total_l2)
|
|
1348
|
+
|
|
1349
|
+
# Smart Load 1 Energy Aggregates
|
|
1350
|
+
|
|
1351
|
+
@property
|
|
1352
|
+
def e_smart_load1_today(self) -> float | None:
|
|
1353
|
+
"""Get total Smart Load 1 energy today in kWh (L1 + L2).
|
|
1354
|
+
|
|
1355
|
+
Returns:
|
|
1356
|
+
Total Smart Load 1 energy today, or None if not available.
|
|
1357
|
+
"""
|
|
1358
|
+
return self._sum_energy(self.e_smart_load1_today_l1, self.e_smart_load1_today_l2)
|
|
1359
|
+
|
|
1360
|
+
@property
|
|
1361
|
+
def e_smart_load1_total(self) -> float | None:
|
|
1362
|
+
"""Get total Smart Load 1 lifetime energy in kWh (L1 + L2).
|
|
1363
|
+
|
|
1364
|
+
Returns:
|
|
1365
|
+
Total Smart Load 1 lifetime energy, or None if not available.
|
|
1366
|
+
"""
|
|
1367
|
+
return self._sum_energy(self.e_smart_load1_total_l1, self.e_smart_load1_total_l2)
|
|
1368
|
+
|
|
1369
|
+
# Smart Load 2 Energy Aggregates
|
|
1370
|
+
|
|
1371
|
+
@property
|
|
1372
|
+
def e_smart_load2_today(self) -> float | None:
|
|
1373
|
+
"""Get total Smart Load 2 energy today in kWh (L1 + L2).
|
|
1374
|
+
|
|
1375
|
+
Returns:
|
|
1376
|
+
Total Smart Load 2 energy today, or None if not available.
|
|
1377
|
+
"""
|
|
1378
|
+
return self._sum_energy(self.e_smart_load2_today_l1, self.e_smart_load2_today_l2)
|
|
1379
|
+
|
|
1380
|
+
@property
|
|
1381
|
+
def e_smart_load2_total(self) -> float | None:
|
|
1382
|
+
"""Get total Smart Load 2 lifetime energy in kWh (L1 + L2).
|
|
1383
|
+
|
|
1384
|
+
Returns:
|
|
1385
|
+
Total Smart Load 2 lifetime energy, or None if not available.
|
|
1386
|
+
"""
|
|
1387
|
+
return self._sum_energy(self.e_smart_load2_total_l1, self.e_smart_load2_total_l2)
|
|
1388
|
+
|
|
1389
|
+
# Smart Load 3 Energy Aggregates
|
|
1390
|
+
|
|
1391
|
+
@property
|
|
1392
|
+
def e_smart_load3_today(self) -> float | None:
|
|
1393
|
+
"""Get total Smart Load 3 energy today in kWh (L1 + L2).
|
|
1394
|
+
|
|
1395
|
+
Returns:
|
|
1396
|
+
Total Smart Load 3 energy today, or None if not available.
|
|
1397
|
+
"""
|
|
1398
|
+
return self._sum_energy(self.e_smart_load3_today_l1, self.e_smart_load3_today_l2)
|
|
1399
|
+
|
|
1400
|
+
@property
|
|
1401
|
+
def e_smart_load3_total(self) -> float | None:
|
|
1402
|
+
"""Get total Smart Load 3 lifetime energy in kWh (L1 + L2).
|
|
1403
|
+
|
|
1404
|
+
Returns:
|
|
1405
|
+
Total Smart Load 3 lifetime energy, or None if not available.
|
|
1406
|
+
"""
|
|
1407
|
+
return self._sum_energy(self.e_smart_load3_total_l1, self.e_smart_load3_total_l2)
|
|
1408
|
+
|
|
1409
|
+
# Smart Load 4 Energy Aggregates
|
|
1410
|
+
|
|
1411
|
+
@property
|
|
1412
|
+
def e_smart_load4_today(self) -> float | None:
|
|
1413
|
+
"""Get total Smart Load 4 energy today in kWh (L1 + L2).
|
|
1414
|
+
|
|
1415
|
+
Returns:
|
|
1416
|
+
Total Smart Load 4 energy today, or None if not available.
|
|
1417
|
+
"""
|
|
1418
|
+
return self._sum_energy(self.e_smart_load4_today_l1, self.e_smart_load4_today_l2)
|
|
1419
|
+
|
|
1420
|
+
@property
|
|
1421
|
+
def e_smart_load4_total(self) -> float | None:
|
|
1422
|
+
"""Get total Smart Load 4 lifetime energy in kWh (L1 + L2).
|
|
1423
|
+
|
|
1424
|
+
Returns:
|
|
1425
|
+
Total Smart Load 4 lifetime energy, or None if not available.
|
|
1426
|
+
"""
|
|
1427
|
+
return self._sum_energy(self.e_smart_load4_total_l1, self.e_smart_load4_total_l2)
|