@@ -109,7 +109,8 @@ def decode_bits(pulses):
109
109
return NECRepeatIRMessage (input_pulses )
110
110
111
111
if len (pulses ) < 10 :
112
- return UnparseableIRMessage (input_pulses , reason = "Too short" )
112
+ msg = UnparseableIRMessage (input_pulses , reason = "Too short" )
113
+ raise FailedToDecode (msg )
113
114
114
115
# Ignore any header (evens start at 1), and any trailer.
115
116
if len (pulses ) % 2 == 0 :
@@ -129,7 +130,8 @@ def decode_bits(pulses):
129
130
odd_bins = [b for b in odd_bins if b [1 ] > 1 ]
130
131
131
132
if not even_bins or not odd_bins :
132
- return UnparseableIRMessage (input_pulses , reason = "Not enough data" )
133
+ msg = UnparseableIRMessage (input_pulses , reason = "Not enough data" )
134
+ raise FailedToDecode (msg )
133
135
134
136
if len (even_bins ) == 1 :
135
137
pulses = odds
@@ -138,12 +140,15 @@ def decode_bits(pulses):
138
140
pulses = evens
139
141
pulse_bins = even_bins
140
142
else :
141
- return UnparseableIRMessage (input_pulses , reason = "Both even/odd pulses differ" )
143
+ msg = UnparseableIRMessage (input_pulses , reason = "Both even/odd pulses differ" )
144
+ raise FailedToDecode (msg )
142
145
143
146
if len (pulse_bins ) == 1 :
144
- return UnparseableIRMessage (input_pulses , reason = "Pulses do not differ" )
147
+ msg = UnparseableIRMessage (input_pulses , reason = "Pulses do not differ" )
148
+ raise FailedToDecode (msg )
145
149
if len (pulse_bins ) > 2 :
146
- return UnparseableIRMessage (input_pulses , reason = "Only mark & space handled" )
150
+ msg = UnparseableIRMessage (input_pulses , reason = "Only mark & space handled" )
151
+ raise FailedToDecode (msg )
147
152
148
153
mark = min (pulse_bins [0 ][0 ], pulse_bins [1 ][0 ])
149
154
space = max (pulse_bins [0 ][0 ], pulse_bins [1 ][0 ])
@@ -160,9 +165,8 @@ def decode_bits(pulses):
160
165
elif (mark * 0.75 ) <= pulse_length <= (mark * 1.25 ):
161
166
pulses [i ] = True
162
167
else :
163
- return UnparseableIRMessage (
164
- input_pulses , reason = "Pulses outside mark/space"
165
- )
168
+ msg = UnparseableIRMessage (input_pulses , reason = "Pulses outside mark/space" )
169
+ raise FailedToDecode (msg )
166
170
167
171
# convert bits to bytes!
168
172
output = [0 ] * ((len (pulses ) + 7 ) // 8 )
@@ -183,6 +187,10 @@ def decode_bits(pulses):
183
187
"Pulses interpreted as an NEC repeat code"
184
188
185
189
190
+ class FailedToDecode (Exception ):
191
+ "Raised by decode_bits. Error argument is UnparseableIRMessage"
192
+
193
+
186
194
class NonblockingGenericDecode :
187
195
"""
188
196
Decode pulses into bytes in a non-blocking fashion.
@@ -223,7 +231,13 @@ def read(self):
223
231
self ._unparsed_pulses .append (pulse )
224
232
if pulse > self .max_pulse :
225
233
# End of message! Decode it and yield a BaseIRMessage.
226
- yield decode_bits (self ._unparsed_pulses )
234
+ try :
235
+ yield decode_bits (self ._unparsed_pulses )
236
+ except FailedToDecode as err :
237
+ # If you want to debug failed decodes, this would be a good
238
+ # place to print/log or (re-)raise.
239
+ (unparseable_message ,) = err .args
240
+ yield unparseable_message
227
241
self ._unparsed_pulses .clear ()
228
242
# TODO Do we need to consume and throw away more pulses here?
229
243
# I'm unclear about the role that "pruning" plays in the
@@ -236,28 +250,36 @@ def read(self):
236
250
class GenericDecode :
237
251
"""Generic decoding of infrared signals"""
238
252
239
- def bin_data (self , pulses ):
253
+ # Note: pylint's complaint about the following three methods (no self-use)
254
+ # is absolutely correct, which is why the code was refactored, but we need
255
+ # this here for back-compat, hence we disable pylint for that specific
256
+ # complaint.
257
+
258
+ def bin_data (self , pulses ): # pylint: disable=R0201
240
259
"Wraps the top-level function bin_data for backward-compatibility."
241
260
return bin_data (pulses )
242
261
243
- def decode_bits (self , pulses ):
262
+ def decode_bits (self , pulses ): # pylint: disable=R0201
244
263
"Wraps the top-level function decode_bits for backward-compatibility."
245
264
result = decode_bits (pulses )
246
265
if isinstance (result , NECRepeatIRMessage ):
247
266
raise IRNECRepeatException ()
248
- elif isinstance (result , UnparseableIRMessage ):
267
+ if isinstance (result , UnparseableIRMessage ):
249
268
raise IRDecodeException ("10 pulses minimum" )
250
269
251
270
def _read_pulses_non_blocking (
252
271
self , input_pulses , max_pulse = 10000 , pulse_window = 0.10
253
- ):
272
+ ): # pylint: disable=R0201
254
273
"""Read out a burst of pulses without blocking until pulses stop for a specified
255
274
period (pulse_window), pruning pulses after a pulse longer than ``max_pulse``.
256
275
257
276
:param ~pulseio.PulseIn input_pulses: Object to read pulses from
258
277
:param int max_pulse: Pulse duration to end a burst
259
278
:param float pulse_window: pulses are collected for this period of time
260
279
"""
280
+ # Note: pylint's complaint (no self-use) is absolutely correct, which
281
+ # is why the code was refactored, but we need this here for
282
+ # back-compat, hence we disable pylint.
261
283
received = None
262
284
recent_count = 0
263
285
pruning = False
0 commit comments