38
38
39
39
PLATFORMS = ["sensor" ]
40
40
41
+
41
42
def mask_map (d ):
42
43
for k , v in d .copy ().items ():
43
44
if isinstance (v , dict ):
@@ -52,6 +53,7 @@ def mask_map(d):
52
53
d [k ] = v
53
54
return d
54
55
56
+
55
57
async def async_setup (hass : HomeAssistant , config : dict ):
56
58
return True
57
59
@@ -62,7 +64,8 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry):
62
64
config_entry .data .get (CONF_SCAN_INTERVAL ,
63
65
DEFAULT_SCAN_INTERVAL )))
64
66
65
- _LOGGER .info (f"Starting TibberLocal with interval: { SCAN_INTERVAL } - ConfigEntry: { mask_map (dict (config_entry .as_dict ()))} " )
67
+ _LOGGER .info (
68
+ f"Starting TibberLocal with interval: { SCAN_INTERVAL } - ConfigEntry: { mask_map (dict (config_entry .as_dict ()))} " )
66
69
67
70
if DOMAIN not in hass .data :
68
71
value = "UNKOWN"
@@ -99,7 +102,8 @@ def __init__(self, hass: HomeAssistant, config_entry):
99
102
# initial configuration phase - so we read it from the config_entry.data ONLY!
100
103
com_mode = int (config_entry .data .get (CONF_MODE , MODE_3_SML_1_04 ))
101
104
102
- self .bridge = TibberLocalBridge (host = self ._host , pwd = the_pwd , websession = async_get_clientsession (hass ), node_num = node_num ,
105
+ self .bridge = TibberLocalBridge (host = self ._host , pwd = the_pwd , websession = async_get_clientsession (hass ),
106
+ node_num = node_num ,
103
107
com_mode = com_mode , options = {"ignore_parse_errors" : ignore_parse_errors })
104
108
self .name = config_entry .title
105
109
self ._config_entry = config_entry
@@ -204,7 +208,10 @@ def __init__(self, obis_src: list, do_log_output: bool):
204
208
_c = int (obis_src [3 ])
205
209
_d = int (obis_src [4 ])
206
210
_e = int (obis_src [5 ])
207
- _f = int (obis_src [6 ])
211
+ if obis_src [6 ] is not None and len (obis_src [6 ]) > 0 :
212
+ _f = int (obis_src [6 ])
213
+ else :
214
+ _f = 255
208
215
209
216
# self.obis_code = f'{_a}-{_b}:{_c}.{_d}.{_e}*{_f}'
210
217
# self.obis_short = f'{_c}.{_d}.{_e}'
@@ -224,9 +231,8 @@ def get_as_two_digit_hex(input: int) -> str:
224
231
225
232
226
233
class TibberLocalBridge :
227
-
228
234
ONLY_DIGITS : re .Pattern = re .compile ("^[0-9]+$" )
229
- PLAIN_TEXT_LINE : re .Pattern = re .compile ('(.*?)-(.*?):(.*?)\\ .(.*?)\\ .(.*?)\\ *(.*?)\\ ((.*?)\\ )' )
235
+ PLAIN_TEXT_LINE : re .Pattern = re .compile ('(.*?)-(.*?):(.*?)\\ .(.*?)\\ .(.*?)(?: \\ *(.*?)| )\\ ((.*?)\\ )' )
230
236
231
237
# _communication_mode 'MODE_3_SML_1_04' is the initial implemented mode (reading binary sml data)...
232
238
# 'all' other modes have to be implemented... also it could be, that the bridge does
@@ -263,7 +269,7 @@ async def detect_com_mode(self):
263
269
if self ._com_mode not in ENUM_IMPLEMENTATIONS :
264
270
raise ValueError (f"NOT IMPLEMENTED yet! - Mode: { self ._com_mode } " )
265
271
266
- async def _check_modes_internal (self , mode_1 :int , mode_2 :int ):
272
+ async def _check_modes_internal (self , mode_1 : int , mode_2 : int ):
267
273
_LOGGER .debug (f"detect_com_mode is { self ._com_mode } : will try to read { mode_1 } " )
268
274
await self .read_tibber_local (mode_1 , False , log_payload = True )
269
275
if len (self ._obis_values ) > 0 :
@@ -322,13 +328,13 @@ async def read_tibber_local(self, mode: int, retry: bool, log_payload: bool = Fa
322
328
except Exception as exec :
323
329
_LOGGER .warning (f"access to bridge failed with exception: { exec } " )
324
330
325
- def check_first_six_parts_for_digits (self , parts : list [str ]) -> bool :
331
+ def check_first_six_parts_for_digits_or_last_is_none (self , parts : list [str ]) -> bool :
326
332
return (self .ONLY_DIGITS .match (parts [1 ]) is not None and
327
333
self .ONLY_DIGITS .match (parts [2 ]) is not None and
328
334
self .ONLY_DIGITS .match (parts [3 ]) is not None and
329
335
self .ONLY_DIGITS .match (parts [4 ]) is not None and
330
336
self .ONLY_DIGITS .match (parts [5 ]) is not None and
331
- self .ONLY_DIGITS .match (parts [6 ]) is not None )
337
+ ( parts [ 6 ] is None or self .ONLY_DIGITS .match (parts [6 ]) is not None ) )
332
338
333
339
async def read_plaintext (self , plaintext : str , retry : bool , log_payload : bool ):
334
340
try :
@@ -347,7 +353,7 @@ async def read_plaintext(self, plaintext: str, retry: bool, log_payload: bool):
347
353
# obis pattern is 'a-b:c.d.e*f'
348
354
parts = re .split (self .PLAIN_TEXT_LINE , a_line )
349
355
if len (parts ) == 9 :
350
- if self .check_first_six_parts_for_digits (parts ):
356
+ if self .check_first_six_parts_for_digits_or_last_is_none (parts ):
351
357
int_obc = IntBasedObisCode (parts , not self .ignore_parse_errors )
352
358
value = parts [7 ]
353
359
unit = None
@@ -382,7 +388,7 @@ async def read_plaintext(self, plaintext: str, retry: bool, log_payload: bool):
382
388
elif len (parts [0 ]) > 0 and parts [0 ][0 ] != '/' :
383
389
if not self .ignore_parse_errors :
384
390
_LOGGER .debug (f"unknown entry: { parts [0 ]} (line: '{ a_line } ')" )
385
- #else:
391
+ # else:
386
392
# print('ignore '+ parts[0])
387
393
388
394
except Exception as e :
@@ -534,22 +540,26 @@ def attr0100020800ff_in_k(self) -> float:
534
540
@property
535
541
def attr0100100700ff (self ) -> float :
536
542
# search for SUM (0), POS (0), POS (255), NEG (0), ABS (0)
537
- return self ._get_value_internal (['0100100700ff' , '0100010700ff' , '01000107ffff' , '0100020700ff' , '01000f0700ff' ])
543
+ return self ._get_value_internal (
544
+ ['0100100700ff' , '0100010700ff' , '01000107ffff' , '0100020700ff' , '01000f0700ff' ])
538
545
539
546
@property
540
547
def attr0100240700ff (self ) -> float :
541
548
# search for SUM (0), POS (0), POS (255), NEG (0), ABS (0)
542
- return self ._get_value_internal (['0100240700ff' , '0100150700ff' , '01001507ffff' , '0100160700ff' , '0100230700ff' ])
549
+ return self ._get_value_internal (
550
+ ['0100240700ff' , '0100150700ff' , '01001507ffff' , '0100160700ff' , '0100230700ff' ])
543
551
544
552
@property
545
553
def attr0100380700ff (self ) -> float :
546
554
# search for SUM (0), POS (0), POS (255), NEG (0), ABS (0)
547
- return self ._get_value_internal (['0100380700ff' , '0100290700ff' , '01002907ffff' , '01002a0700ff' , '0100370700ff' ])
555
+ return self ._get_value_internal (
556
+ ['0100380700ff' , '0100290700ff' , '01002907ffff' , '01002a0700ff' , '0100370700ff' ])
548
557
549
558
@property
550
559
def attr01004c0700ff (self ) -> float :
551
560
# search for SUM (0), POS (0), POS (255), NEG (0), ABS (0)
552
- return self ._get_value_internal (['01004c0700ff' , '01003d0700ff' , '01003d07ffff' , '01003e0700ff' , '01004b0700ff' ])
561
+ return self ._get_value_internal (
562
+ ['01004c0700ff' , '01003d0700ff' , '01003d07ffff' , '01003e0700ff' , '01004b0700ff' ])
553
563
554
564
@property
555
565
def attr0100200700ff (self ) -> float :
0 commit comments