@@ -140,13 +140,26 @@ def length_in_range(self, protocol_id, message_length):
140140
141141 # Check minimum length
142142 min_len = self .check_property (protocol_id , 'length_min' , - 1 )
143- if message_length < min_len :
143+ if min_len is not None :
144+ try :
145+ min_len = int (min_len )
146+ except (ValueError , TypeError ):
147+ # Log warning? For now, treat as no limit or skip check?
148+ # Assuming data integrity, but let's be safe.
149+ pass
150+
151+ if min_len != - 1 and message_length < min_len :
144152 return (0 , 'message is too short' )
145153
146154 # Check maximum length
147155 max_len = self .get_property (protocol_id , 'length_max' )
148- if max_len is not None and message_length > max_len :
149- return (0 , 'message is too long' )
156+ if max_len is not None :
157+ try :
158+ max_len = int (max_len )
159+ if message_length > max_len :
160+ return (0 , 'message is too long' )
161+ except (ValueError , TypeError ):
162+ pass
150163
151164 return (1 , '' )
152165
@@ -170,4 +183,96 @@ def hex_to_bin_str(self, hex_string):
170183 padded_length = ((len (bin_string ) + 3 ) // 4 ) * 4
171184 return bin_string .zfill (padded_length )
172185 except ValueError :
173- return None
186+ return None
187+
188+ def lfsr_digest16 (self , bytes_count , gen , key , raw_data ):
189+ """
190+ Calculates 16-bit LFSR digest.
191+
192+ Args:
193+ bytes_count: Number of bytes to process
194+ gen: Generator polynomial
195+ key: Initial key
196+ raw_data: Hex string of data
197+
198+ Returns:
199+ int: Calculated LFSR value
200+ """
201+ if len (raw_data ) < bytes_count * 2 :
202+ return 0
203+
204+ lfsr = 0
205+ for k in range (bytes_count ):
206+ try :
207+ data = int (raw_data [k * 2 : k * 2 + 2 ], 16 )
208+ except ValueError :
209+ return 0
210+
211+ for i in range (7 , - 1 , - 1 ):
212+ if (data >> i ) & 0x01 :
213+ lfsr ^= key
214+
215+ if key & 0x01 :
216+ key = (key >> 1 ) ^ gen
217+ else :
218+ key = (key >> 1 )
219+ return lfsr
220+
221+ def ConvBresser_lightning (self , msg_data , msg_type = 'MN' ):
222+ """
223+ Process Bresser Lightning protocol data.
224+
225+ Args:
226+ msg_data: Dictionary with 'data' (hex string)
227+ msg_type: 'MN'
228+
229+ Returns:
230+ List containing decoded message dict or empty list on error.
231+ """
232+ hex_data = msg_data .get ('data' )
233+ if not hex_data :
234+ return []
235+
236+ hex_length = len (hex_data )
237+ if hex_length < 20 :
238+ self ._logging ("ConvBresser_lightning, hexData is too short" , 3 )
239+ return []
240+
241+ hex_data_xor_a = ""
242+ for i in range (hex_length ):
243+ try :
244+ xor = int (hex_data [i ], 16 ) ^ 0xA
245+ hex_data_xor_a += f"{ xor :X} "
246+ except ValueError :
247+ return []
248+
249+ self ._logging (f"ConvBresser_lightning, msg={ hex_data } " , 5 )
250+ self ._logging (f"ConvBresser_lightning, xor={ hex_data_xor_a } " , 5 )
251+
252+ # LFSR-16 gen 8810 key abf9 final xor 899e
253+ # Substr(hexDataXorA, 4, 16) means starting from index 4, take 16 chars (8 bytes)
254+ checksum = self .lfsr_digest16 (8 , 0x8810 , 0xABF9 , hex_data_xor_a [4 :20 ])
255+
256+ try :
257+ # substr(hexDataXorA, 0, 4) -> first 2 bytes (4 hex chars)
258+ first_2_bytes_xor = int (hex_data_xor_a [0 :4 ], 16 )
259+ except ValueError :
260+ return []
261+
262+ checksum_calc = checksum ^ first_2_bytes_xor
263+ checksum_calc_hex = f"{ checksum_calc :04X} "
264+
265+ self ._logging (f"ConvBresser_lightning, checksumCalc:0x{ checksum_calc_hex } , must be 0x899E" , 5 )
266+
267+ if checksum_calc_hex != '899E' :
268+ self ._logging (f"ConvBresser_lightning, checksumCalc:0x{ checksum_calc_hex } != checksum:0x899E" , 3 )
269+ return []
270+
271+ # Return first 20 chars (10 bytes)
272+ payload = hex_data_xor_a [:20 ]
273+
274+ return [{
275+ "protocol_id" : msg_data .get ('protocol_id' ),
276+ "payload" : payload ,
277+ "meta" : {}
278+ }]
0 commit comments