@@ -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 )
@@ -137,10 +142,46 @@ def parse_telemetry_report(body):
137142 # Pad to 5 analog values if we have fewer
138143 while len (analog_strs ) < 5 :
139144 analog_strs .append ('' )
140-
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 ''
145+
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
@@ -156,7 +197,7 @@ def parse_telemetry_report(body):
156197 if not val_str or val_str .strip () == '' :
157198 analog_vals .append (0.0 )
158199 continue
159-
200+
160201 # Allow integers, decimals, and negative numbers
161202 if not re .match (r'^-?\d+\.?\d*$' , val_str ):
162203 raise ParseError ("telemetry analog value %d has invalid format" % (i + 1 ))
@@ -169,28 +210,36 @@ def parse_telemetry_report(body):
169210 # Validate digital I/O (must be binary digits, pad to 8 if shorter)
170211 # Some packets have comment concatenated without comma separator
171212 # Some packets have shorter binary strings (pad with leading zeros)
172- # Check if field is entirely binary digits
173- if re .match (r'^[01]+$' , digital_field ):
174- # Pure binary string (all 0s and 1s)
175- if len (digital_field ) < 8 :
213+ # Some packets have non-binary characters mixed in (extract leading binary digits)
214+ # Check if field starts with binary digits
215+ binary_match = re .match (r'^([01]+)' , digital_field )
216+ if binary_match :
217+ binary_str = binary_match .group (1 )
218+
219+ # If there are non-binary characters after binary digits, require at least 4 binary digits
220+ # This prevents false positives like "123" (1 binary + 2 non-binary)
221+ if len (binary_str ) < len (digital_field ):
222+ # Has non-binary characters following
223+ if len (binary_str ) < 4 :
224+ # Too few binary digits before non-binary - likely invalid
225+ raise ParseError ("telemetry digital I/O must be binary digits" )
226+
227+ # Extract leading binary digits
228+ if len (binary_str ) < 8 :
176229 # Pad shorter binary strings to 8 digits
177- digital_str = digital_field .zfill (8 )
178- elif len (digital_field ) == 8 :
179- digital_str = digital_field
230+ digital_str = binary_str .zfill (8 )
231+ elif len (binary_str ) == 8 :
232+ digital_str = binary_str
180233 else :
181234 # Longer than 8, use first 8
182- digital_str = digital_field [:8 ]
183- elif re .match (r'^[01]{8,}[^01]' , digital_field ):
184- # Starts with 8+ binary digits followed by non-binary (concatenated comment)
185- digital_str = digital_field [:8 ]
186- if not comment :
187- comment = digital_field [8 :]
188- elif re .match (r'^[01]{1,7}[^01]' , digital_field ):
189- # Starts with 1-7 binary digits followed by non-binary
190- # This is invalid - need at least 8 binary digits before comment
191- raise ParseError ("telemetry digital I/O must be binary digits" )
235+ digital_str = binary_str [:8 ]
236+
237+ # If there's non-binary content after the binary digits, treat as comment if no comment yet
238+ if len (binary_str ) < len (digital_field ) and not comment :
239+ remaining = digital_field [len (binary_str ):]
240+ comment = remaining
192241 else :
193- # No valid binary digits found or invalid format
242+ # No valid binary digits found - this is invalid
194243 raise ParseError ("telemetry digital I/O must be binary digits" )
195244
196245 parsed .update ({
0 commit comments