Skip to content

Commit 301d071

Browse files
committed
Account for missing binary bits
This patch updates the telemetry parsing to account for missing binary bits in the packet.
1 parent 3dcceef commit 301d071

File tree

3 files changed

+73
-11
lines changed

3 files changed

+73
-11
lines changed

aprslib/parsing/telemetry.py

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,20 @@ def parse_telemetry_config(body):
8888
elif form == "BITS":
8989
# APRS spec says 23 chars, but real-world packets may be longer
9090
# Accept any reasonable length (up to 100 chars to be safe)
91+
# Some packets may be missing binary bits (just title)
9192
match = re.findall(r"^([01]{8}),(.{0,100})$", body.rstrip())
92-
if not match:
93-
raise ParseError("incorrect format of %s" % form)
94-
95-
bits, title = match[0]
96-
97-
parsed.update({
98-
't%s' % form: bits,
99-
'title': title.strip(' ')
93+
if match:
94+
bits, title = match[0]
95+
parsed.update({
96+
't%s' % form: bits,
97+
'title': title.strip(' ')
98+
})
99+
else:
100+
# No binary bits found - treat entire body as title
101+
# This handles malformed packets like "BITS.title" without bits
102+
parsed.update({
103+
't%s' % form: '00000000', # Default to all zeros
104+
'title': body.rstrip().strip(' ')
100105
})
101106

102107
return (body, parsed)
@@ -138,9 +143,45 @@ def parse_telemetry_report(body):
138143
while len(analog_strs) < 5:
139144
analog_strs.append('')
140145

141-
# Digital I/O field (may be missing)
142-
digital_field = parts[6] if len(parts) > 6 else '00000000'
143-
comment = parts[7] if len(parts) > 7 else ''
146+
# Digital I/O field (may be missing or in next position)
147+
digital_field = parts[6] if len(parts) > 6 else ''
148+
comment = ''
149+
150+
# If digital field is empty, check if next field could be digital I/O
151+
if not digital_field or digital_field.strip() == '':
152+
if len(parts) > 7:
153+
next_field = parts[7]
154+
# Check if next field starts with binary digits (could be digital I/O with concatenated comment)
155+
binary_match = re.match(r'^([01]+)', next_field)
156+
if binary_match:
157+
# Extract binary digits from start of next field
158+
binary_str = binary_match.group(1)
159+
# Use it as digital I/O if it's reasonable length (1-8 digits)
160+
if len(binary_str) <= 8:
161+
digital_field = binary_str
162+
# Rest of next_field and remaining parts are comment
163+
remaining = next_field[len(binary_str):].lstrip(',')
164+
remaining_parts = [remaining] if remaining else []
165+
if len(parts) > 8:
166+
remaining_parts.extend(parts[8:])
167+
comment = ','.join(remaining_parts) if remaining_parts else ''
168+
else:
169+
# Too long, use first 8 as digital I/O
170+
digital_field = binary_str[:8]
171+
remaining = binary_str[8:] + next_field[len(binary_str):]
172+
remaining_parts = [remaining] if remaining else []
173+
if len(parts) > 8:
174+
remaining_parts.extend(parts[8:])
175+
comment = ','.join(remaining_parts) if remaining_parts else ''
176+
else:
177+
# Next field is not binary, treat as comment
178+
digital_field = '00000000'
179+
comment = ','.join(parts[7:]) if len(parts) > 7 else ''
180+
else:
181+
# No more fields, use default
182+
digital_field = '00000000'
183+
else:
184+
comment = ','.join(parts[7:]) if len(parts) > 7 else ''
144185

145186
# Validate and parse sequence number (allow any positive integer)
146187
# APRS spec says 000-999, but real-world packets use larger numbers

tests/test_parse_telemetry.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,18 @@ def test_valid_telemetry_minimal_packet(self):
126126
# Digital I/O should default to all zeros
127127
self.assertEqual(result['telemetry']['bits'], '00000000')
128128

129+
def test_valid_telemetry_missing_digital_with_binary_in_next(self):
130+
"""Test telemetry packet with missing digital I/O field, binary digits in next position"""
131+
packet = "E25HML-13>APRS,TCPIP*,qAC,T2PERTH:T#075,039,,,000,000,,0000,ESP8266 Test WX DHT22 version"
132+
result = parse(packet)
133+
134+
self.assertEqual(result['format'], 'telemetry')
135+
self.assertEqual(result['telemetry']['seq'], 75)
136+
self.assertEqual(result['telemetry']['vals'], [39.0, 0.0, 0.0, 0.0, 0.0])
137+
# 0000 should be padded to 8 digits
138+
self.assertEqual(result['telemetry']['bits'], '00000000')
139+
self.assertEqual(result['comment'], 'ESP8266 Test WX DHT22 version')
140+
129141
def test_valid_telemetry_empty_analog_value(self):
130142
"""Test telemetry packet with empty analog value"""
131143
packet = "VU2IB-13>APRS,TCPIP*,qAC,T2DENMARK:T#126,250,057,000,040,,1011,Solar Power WX Station"

tests/test_parse_telemetry_config.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,15 @@ def test_parse_telemetry_config_eqns(self):
108108
self.assertIsInstance(result['tEQNS'], list)
109109
self.assertEqual(len(result['tEQNS']), 5)
110110

111+
def test_bits_without_binary_bits(self):
112+
"""Test BITS telemetry config without binary bits (malformed packet)"""
113+
packet = "E25HML-13>APRS,TCPIP*,qAC,T2PERTH::E25HML-13:BITS.ESP8266 Test WX DHT22 version"
114+
result = parse(packet)
115+
116+
self.assertEqual(result['format'], 'telemetry-message')
117+
self.assertEqual(result['tBITS'], '00000000') # Default to all zeros
118+
self.assertEqual(result['title'], 'ESP8266 Test WX DHT22 version')
119+
111120

112121
if __name__ == '__main__':
113122
unittest.main()

0 commit comments

Comments
 (0)