Skip to content

Commit 0592449

Browse files
committed
addes helpers
1 parent 211f709 commit 0592449

1 file changed

Lines changed: 109 additions & 4 deletions

File tree

sd_protocols/helpers.py

Lines changed: 109 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)