pylxpweb 0.1.0__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/py.typed ADDED
File without changes
pylxpweb/registers.py ADDED
@@ -0,0 +1,511 @@
1
+ """Register mapping constants for Luxpower/EG4 inverter devices.
2
+
3
+ This module contains the register addresses and block sizes discovered through
4
+ empirical testing. See docs/claude/REGISTER_MAPPING_ANALYSIS.md for details.
5
+
6
+ IMPORTANT: Multi-register parameters require reading the full block starting
7
+ from the original register, even if the data is in the last register(s).
8
+
9
+ Example:
10
+ # WRONG - Will fail
11
+ read_parameters(serial_num, start_register=134, point_number=1)
12
+
13
+ # CORRECT - Use REGISTER_BLOCKS
14
+ block = REGISTER_BLOCKS_18KPV[134]
15
+ read_parameters(
16
+ serial_num,
17
+ start_register=block['read_start'], # 126
18
+ point_number=block['read_size'] # 9
19
+ )
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ from typing import TypedDict
25
+
26
+
27
+ class RegisterBlock(TypedDict):
28
+ """Register block definition.
29
+
30
+ Attributes:
31
+ register: Actual register position where data is located
32
+ size: Number of registers containing data
33
+ read_start: Starting register for API read (may include leading empty registers)
34
+ read_size: Block size for API read (may be larger than size)
35
+ parameters: List of parameter names available in this block
36
+ """
37
+
38
+ register: int
39
+ size: int
40
+ read_start: int
41
+ read_size: int
42
+ parameters: list[str]
43
+
44
+
45
+ # 18KPV Register Blocks
46
+ # Total blocks: 26
47
+ # Register range: 0-268
48
+ # Unique parameters: 51
49
+ REGISTER_BLOCKS_18KPV: dict[int, RegisterBlock] = {
50
+ 0: {
51
+ "register": 0,
52
+ "size": 2,
53
+ "read_start": 0,
54
+ "read_size": 2,
55
+ "parameters": [
56
+ "HOLD_MODEL",
57
+ "HOLD_MODEL_batteryType",
58
+ "HOLD_MODEL_leadAcidType",
59
+ "HOLD_MODEL_lithiumType",
60
+ "HOLD_MODEL_measurement",
61
+ "HOLD_MODEL_meterBrand",
62
+ "HOLD_MODEL_meterType",
63
+ "HOLD_MODEL_powerRating",
64
+ "HOLD_MODEL_rule",
65
+ "HOLD_MODEL_ruleMask",
66
+ "HOLD_MODEL_usVersion",
67
+ "HOLD_MODEL_wirelessMeter",
68
+ "INPUT_BATTERY_VOLTAGE",
69
+ ],
70
+ },
71
+ 2: {
72
+ "register": 2,
73
+ "size": 5,
74
+ "read_start": 2,
75
+ "read_size": 5,
76
+ "parameters": ["HOLD_SERIAL_NUM"],
77
+ },
78
+ 7: {
79
+ "register": 7,
80
+ "size": 4,
81
+ "read_start": 7,
82
+ "read_size": 4,
83
+ "parameters": ["HOLD_FW_CODE"],
84
+ },
85
+ 12: {
86
+ "register": 12,
87
+ "size": 3,
88
+ "read_start": 11,
89
+ "read_size": 4,
90
+ "parameters": ["HOLD_TIME"],
91
+ },
92
+ 19: {
93
+ "register": 19,
94
+ "size": 1,
95
+ "read_start": 17,
96
+ "read_size": 3,
97
+ "parameters": ["BIT_DEVICE_TYPE_ODM", "BIT_MACHINE_TYPE", "HOLD_DEVICE_TYPE_CODE"],
98
+ },
99
+ 96: {
100
+ "register": 96,
101
+ "size": 1,
102
+ "read_start": 92,
103
+ "read_size": 5,
104
+ "parameters": ["HOLD_DELAY_TIME_FOR_QV_CURVE"],
105
+ },
106
+ 99: {
107
+ "register": 99,
108
+ "size": 1,
109
+ "read_start": 98,
110
+ "read_size": 2,
111
+ "parameters": ["HOLD_LEAD_ACID_CHARGE_VOLT_REF"],
112
+ },
113
+ 105: {
114
+ "register": 105,
115
+ "size": 1,
116
+ "read_start": 104,
117
+ "read_size": 2,
118
+ "parameters": ["HOLD_DISCHG_CUT_OFF_SOC_EOD"],
119
+ },
120
+ 112: {
121
+ "register": 112,
122
+ "size": 1,
123
+ "read_start": 111,
124
+ "read_size": 2,
125
+ "parameters": ["HOLD_SET_MASTER_OR_SLAVE"],
126
+ },
127
+ 115: {
128
+ "register": 115,
129
+ "size": 1,
130
+ "read_start": 114,
131
+ "read_size": 2,
132
+ "parameters": ["_12K_HOLD_OVF_DERATE_START_POINT"],
133
+ },
134
+ 118: {
135
+ "register": 118,
136
+ "size": 1,
137
+ "read_start": 117,
138
+ "read_size": 2,
139
+ "parameters": ["HOLD_VBAT_START_DERATING"],
140
+ },
141
+ 125: {
142
+ "register": 125,
143
+ "size": 1,
144
+ "read_start": 123,
145
+ "read_size": 3,
146
+ "parameters": ["HOLD_SOC_LOW_LIMIT_EPS_DISCHG"],
147
+ },
148
+ 134: {
149
+ "register": 134,
150
+ "size": 1,
151
+ "read_start": 126,
152
+ "read_size": 9,
153
+ "parameters": ["HOLD_UVF_DERATE_START_POINT"],
154
+ },
155
+ 136: {
156
+ "register": 136,
157
+ "size": 1,
158
+ "read_start": 135,
159
+ "read_size": 2,
160
+ "parameters": ["HOLD_OVF_DROOP_KOF"],
161
+ },
162
+ 144: {
163
+ "register": 144,
164
+ "size": 1,
165
+ "read_start": 138,
166
+ "read_size": 7,
167
+ "parameters": ["HOLD_FLOATING_VOLTAGE"],
168
+ },
169
+ 148: {
170
+ "register": 148,
171
+ "size": 1,
172
+ "read_start": 147,
173
+ "read_size": 2,
174
+ "parameters": ["HOLD_NOMINAL_BATTERY_VOLTAGE"],
175
+ },
176
+ 176: {
177
+ "register": 176,
178
+ "size": 1,
179
+ "read_start": 170,
180
+ "read_size": 7,
181
+ "parameters": ["HOLD_MAX_AC_INPUT_POWER"],
182
+ },
183
+ 181: {
184
+ "register": 181,
185
+ "size": 1,
186
+ "read_start": 180,
187
+ "read_size": 2,
188
+ "parameters": ["HOLD_VOLT_WATT_V1"],
189
+ },
190
+ 193: {
191
+ "register": 193,
192
+ "size": 1,
193
+ "read_start": 192,
194
+ "read_size": 2,
195
+ "parameters": ["HOLD_UVF_DROOP_KUF"],
196
+ },
197
+ 201: {
198
+ "register": 201,
199
+ "size": 1,
200
+ "read_start": 199,
201
+ "read_size": 3,
202
+ "parameters": ["_12K_HOLD_CHARGE_FIRST_VOLT"],
203
+ },
204
+ 226: {
205
+ "register": 226,
206
+ "size": 1,
207
+ "read_start": 225,
208
+ "read_size": 2,
209
+ "parameters": [
210
+ "BIT_AC_COUPLE_ON_EPS_PORT",
211
+ "FUNC_AC_COUPLE_DARK_START_EN",
212
+ "FUNC_AC_COUPLE_ON_EPS_PORT_EN",
213
+ "FUNC_GEN_CTRL",
214
+ "FUNC_GRID_CT_CONNECTION_EN",
215
+ "FUNC_MIDBOX_EN",
216
+ "FUNC_N_PE_CONNECT_INNER_EN",
217
+ "FUNC_PARALLEL_DATA_SYNC_EN",
218
+ "FUNC_RETAIN_SHUTDOWN",
219
+ "FUNC_RETAIN_STANDBY",
220
+ "FUNC_RUN_WITHOUT_GRID_12K",
221
+ ],
222
+ },
223
+ 232: {
224
+ "register": 232,
225
+ "size": 1,
226
+ "read_start": 231,
227
+ "read_size": 2,
228
+ "parameters": ["_12K_HOLD_GRID_PEAK_SHAVING_POWER_2"],
229
+ },
230
+ 237: {
231
+ "register": 237,
232
+ "size": 1,
233
+ "read_start": 234,
234
+ "read_size": 4,
235
+ "parameters": ["_12K_HOLD_GEN_COOL_DOWN_TIME"],
236
+ },
237
+ 244: {
238
+ "register": 244,
239
+ "size": 1,
240
+ "read_start": 241,
241
+ "read_size": 4,
242
+ "parameters": ["_12K_HOLD_BOOT_LOADER_VERSION"],
243
+ },
244
+ 256: {
245
+ "register": 256,
246
+ "size": 1,
247
+ "read_start": 255,
248
+ "read_size": 2,
249
+ "parameters": ["HOLD_GEN_START_HOUR_1", "HOLD_GEN_START_MINUTE_1"],
250
+ },
251
+ 268: {
252
+ "register": 268,
253
+ "size": 1,
254
+ "read_start": 261,
255
+ "read_size": 8,
256
+ "parameters": ["HOLD_EXPORT_LOCK_POWER"],
257
+ },
258
+ }
259
+
260
+
261
+ # GridBOSS Register Blocks
262
+ # Total blocks: 22
263
+ # Register range: 0-2101
264
+ # Unique parameters: 54
265
+ REGISTER_BLOCKS_GRIDBOSS: dict[int, RegisterBlock] = {
266
+ 0: {
267
+ "register": 0,
268
+ "size": 2,
269
+ "read_start": 0,
270
+ "read_size": 2,
271
+ "parameters": [
272
+ "HOLD_MODEL",
273
+ "HOLD_MODEL_batteryType",
274
+ "HOLD_MODEL_leadAcidType",
275
+ "HOLD_MODEL_lithiumType",
276
+ "HOLD_MODEL_measurement",
277
+ "HOLD_MODEL_meterBrand",
278
+ "HOLD_MODEL_meterType",
279
+ "HOLD_MODEL_powerRating",
280
+ "HOLD_MODEL_rule",
281
+ "HOLD_MODEL_ruleMask",
282
+ "HOLD_MODEL_usVersion",
283
+ "HOLD_MODEL_wirelessMeter",
284
+ ],
285
+ },
286
+ 2: {
287
+ "register": 2,
288
+ "size": 5,
289
+ "read_start": 2,
290
+ "read_size": 5,
291
+ "parameters": ["HOLD_SERIAL_NUM"],
292
+ },
293
+ 7: {
294
+ "register": 7,
295
+ "size": 4,
296
+ "read_start": 7,
297
+ "read_size": 4,
298
+ "parameters": ["HOLD_FW_CODE"],
299
+ },
300
+ 12: {
301
+ "register": 12,
302
+ "size": 3,
303
+ "read_start": 11,
304
+ "read_size": 4,
305
+ "parameters": ["HOLD_TIME"],
306
+ },
307
+ 19: {
308
+ "register": 19,
309
+ "size": 1,
310
+ "read_start": 17,
311
+ "read_size": 3,
312
+ "parameters": ["BIT_DEVICE_TYPE_ODM", "BIT_MACHINE_TYPE", "HOLD_DEVICE_TYPE_CODE"],
313
+ },
314
+ 99: {
315
+ "register": 99,
316
+ "size": 1,
317
+ "read_start": 92,
318
+ "read_size": 8,
319
+ "parameters": ["HOLD_LEAD_ACID_CHARGE_VOLT_REF"],
320
+ },
321
+ 105: {
322
+ "register": 105,
323
+ "size": 1,
324
+ "read_start": 104,
325
+ "read_size": 2,
326
+ "parameters": ["HOLD_DISCHG_CUT_OFF_SOC_EOD"],
327
+ },
328
+ 112: {
329
+ "register": 112,
330
+ "size": 1,
331
+ "read_start": 111,
332
+ "read_size": 2,
333
+ "parameters": ["HOLD_SET_MASTER_OR_SLAVE"],
334
+ },
335
+ 116: {
336
+ "register": 116,
337
+ "size": 1,
338
+ "read_start": 114,
339
+ "read_size": 3,
340
+ "parameters": ["HOLD_P_TO_USER_START_DISCHG"],
341
+ },
342
+ 118: {
343
+ "register": 118,
344
+ "size": 1,
345
+ "read_start": 117,
346
+ "read_size": 2,
347
+ "parameters": ["HOLD_VBAT_START_DERATING"],
348
+ },
349
+ 122: {
350
+ "register": 122,
351
+ "size": 1,
352
+ "read_start": 121,
353
+ "read_size": 2,
354
+ "parameters": ["HOLD_MAINTENANCE_COUNT"],
355
+ },
356
+ 125: {
357
+ "register": 125,
358
+ "size": 1,
359
+ "read_start": 123,
360
+ "read_size": 3,
361
+ "parameters": ["HOLD_SOC_LOW_LIMIT_EPS_DISCHG"],
362
+ },
363
+ 137: {
364
+ "register": 137,
365
+ "size": 1,
366
+ "read_start": 126,
367
+ "read_size": 12,
368
+ "parameters": ["HOLD_SPEC_LOAD_COMPENSATE"],
369
+ },
370
+ 144: {
371
+ "register": 144,
372
+ "size": 1,
373
+ "read_start": 138,
374
+ "read_size": 7,
375
+ "parameters": ["HOLD_FLOATING_VOLTAGE"],
376
+ },
377
+ 148: {
378
+ "register": 148,
379
+ "size": 1,
380
+ "read_start": 147,
381
+ "read_size": 2,
382
+ "parameters": ["HOLD_NOMINAL_BATTERY_VOLTAGE"],
383
+ },
384
+ 176: {
385
+ "register": 176,
386
+ "size": 1,
387
+ "read_start": 170,
388
+ "read_size": 7,
389
+ "parameters": ["HOLD_MAX_AC_INPUT_POWER"],
390
+ },
391
+ 194: {
392
+ "register": 194,
393
+ "size": 1,
394
+ "read_start": 180,
395
+ "read_size": 15,
396
+ "parameters": ["OFF_GRID_HOLD_GEN_CHG_START_VOLT"],
397
+ },
398
+ 204: {
399
+ "register": 204,
400
+ "size": 1,
401
+ "read_start": 199,
402
+ "read_size": 6,
403
+ "parameters": ["_12K_HOLD_LEAD_CAPACITY"],
404
+ },
405
+ 215: {
406
+ "register": 215,
407
+ "size": 1,
408
+ "read_start": 205,
409
+ "read_size": 11,
410
+ "parameters": [
411
+ "FUNC_LSP_OUTPUT_10_EN",
412
+ "FUNC_LSP_OUTPUT_11_EN",
413
+ "FUNC_LSP_OUTPUT_12_EN",
414
+ "FUNC_LSP_OUTPUT_1_EN",
415
+ "FUNC_LSP_OUTPUT_2_EN",
416
+ "FUNC_LSP_OUTPUT_3_EN",
417
+ "FUNC_LSP_OUTPUT_4_EN",
418
+ "FUNC_LSP_OUTPUT_5_EN",
419
+ "FUNC_LSP_OUTPUT_6_EN",
420
+ "FUNC_LSP_OUTPUT_7_EN",
421
+ "FUNC_LSP_OUTPUT_8_EN",
422
+ "FUNC_LSP_OUTPUT_9_EN",
423
+ ],
424
+ },
425
+ 224: {
426
+ "register": 224,
427
+ "size": 1,
428
+ "read_start": 222,
429
+ "read_size": 3,
430
+ "parameters": ["MIDBOX_HOLD_GEN_VOLT_SOC_ENABLE"],
431
+ },
432
+ 2099: {
433
+ "register": 2099,
434
+ "size": 1,
435
+ "read_start": 2033,
436
+ "read_size": 67,
437
+ "parameters": ["MIDBOX_HOLD_BUSBAR_PCS_RATING"],
438
+ },
439
+ 2101: {
440
+ "register": 2101,
441
+ "size": 1,
442
+ "read_start": 2100,
443
+ "read_size": 2,
444
+ "parameters": [
445
+ "BIT_MID_INSTALL_POSITION",
446
+ "BIT_SMART_LOAD_BASE_ON_1",
447
+ "BIT_SMART_LOAD_BASE_ON_2",
448
+ "BIT_SMART_LOAD_BASE_ON_3",
449
+ "BIT_SMART_LOAD_BASE_ON_4",
450
+ "BIT_SMART_LOAD_BASE_ON_TIME_SOC_VOLT_1",
451
+ "BIT_SMART_LOAD_BASE_ON_TIME_SOC_VOLT_2",
452
+ "BIT_SMART_LOAD_BASE_ON_TIME_SOC_VOLT_3",
453
+ "BIT_SMART_LOAD_BASE_ON_TIME_SOC_VOLT_4",
454
+ ],
455
+ },
456
+ }
457
+
458
+
459
+ # Known register ranges from web UI
460
+ KNOWN_RANGES_18KPV = [
461
+ (0, 127),
462
+ (127, 127),
463
+ (240, 127),
464
+ # (269, 6), # Parallel mode only
465
+ ]
466
+
467
+ KNOWN_RANGES_GRIDBOSS = [
468
+ (0, 127),
469
+ (127, 127),
470
+ (254, 127),
471
+ (2032, 127),
472
+ ]
473
+
474
+
475
+ def get_register_block(device_type: str, register: int) -> RegisterBlock | None:
476
+ """Get register block definition for a specific register.
477
+
478
+ Args:
479
+ device_type: Device type ("18KPV" or "GridBOSS")
480
+ register: Register number
481
+
482
+ Returns:
483
+ RegisterBlock if found, None otherwise
484
+ """
485
+ if device_type == "18KPV":
486
+ return REGISTER_BLOCKS_18KPV.get(register)
487
+ elif device_type == "GridBOSS":
488
+ return REGISTER_BLOCKS_GRIDBOSS.get(register)
489
+ return None
490
+
491
+
492
+ def get_all_parameters(device_type: str) -> set[str]:
493
+ """Get all unique parameter names for a device type.
494
+
495
+ Args:
496
+ device_type: Device type ("18KPV" or "GridBOSS")
497
+
498
+ Returns:
499
+ Set of parameter names
500
+ """
501
+ if device_type == "18KPV":
502
+ blocks = REGISTER_BLOCKS_18KPV.values()
503
+ elif device_type == "GridBOSS":
504
+ blocks = REGISTER_BLOCKS_GRIDBOSS.values()
505
+ else:
506
+ return set()
507
+
508
+ params = set()
509
+ for block in blocks:
510
+ params.update(block["parameters"])
511
+ return params