From c555ad465ca4b030e4e3aaeafca0d69cde736c02 Mon Sep 17 00:00:00 2001 From: Dan Allan Date: Thu, 21 Jan 2021 05:33:01 -0500 Subject: [PATCH 1/8] Refactor methods into functions that can be shared. --- adafruit_irremote.py | 199 ++++++++++++++++++++++--------------------- 1 file changed, 102 insertions(+), 97 deletions(-) diff --git a/adafruit_irremote.py b/adafruit_irremote.py index 7e58f6d..4ec5fa8 100644 --- a/adafruit_irremote.py +++ b/adafruit_irremote.py @@ -51,9 +51,6 @@ """ -# Pretend self matter because we may add object level config later. -# pylint: disable=no-self-use - import array import time @@ -69,107 +66,115 @@ class IRNECRepeatException(Exception): """Exception when a NEC repeat is decoded""" -class GenericDecode: - """Generic decoding of infrared signals""" - - def bin_data(self, pulses): - """Compute bins of pulse lengths where pulses are +-25% of the average. - - :param list pulses: Input pulse lengths - """ - bins = [[pulses[0], 0]] - - for _, pulse in enumerate(pulses): - matchedbin = False - # print(pulse, end=": ") - for b, pulse_bin in enumerate(bins): - if pulse_bin[0] * 0.75 <= pulse <= pulse_bin[0] * 1.25: - # print("matches bin") - bins[b][0] = (pulse_bin[0] + pulse) // 2 # avg em - bins[b][1] += 1 # track it - matchedbin = True - break - if not matchedbin: - bins.append([pulse, 1]) - # print(bins) - return bins +def bin_data(pulses): + """Compute bins of pulse lengths where pulses are +-25% of the average. - def decode_bits(self, pulses): - """Decode the pulses into bits.""" - # pylint: disable=too-many-branches,too-many-statements - - # special exception for NEC repeat code! - if ( - (len(pulses) == 3) - and (8000 <= pulses[0] <= 10000) - and (2000 <= pulses[1] <= 3000) - and (450 <= pulses[2] <= 700) - ): - raise IRNECRepeatException() - - if len(pulses) < 10: - raise IRDecodeException("10 pulses minimum") - - # Ignore any header (evens start at 1), and any trailer. - if len(pulses) % 2 == 0: - pulses_end = -1 + :param list pulses: Input pulse lengths + """ + bins = [[pulses[0], 0]] + + for _, pulse in enumerate(pulses): + matchedbin = False + # print(pulse, end=": ") + for b, pulse_bin in enumerate(bins): + if pulse_bin[0] * 0.75 <= pulse <= pulse_bin[0] * 1.25: + # print("matches bin") + bins[b][0] = (pulse_bin[0] + pulse) // 2 # avg em + bins[b][1] += 1 # track it + matchedbin = True + break + if not matchedbin: + bins.append([pulse, 1]) + # print(bins) + return bins + + +def decode_bits(pulses): + """Decode the pulses into bits.""" + # pylint: disable=too-many-branches,too-many-statements + + # special exception for NEC repeat code! + if ( + (len(pulses) == 3) + and (8000 <= pulses[0] <= 10000) + and (2000 <= pulses[1] <= 3000) + and (450 <= pulses[2] <= 700) + ): + raise IRNECRepeatException() + + if len(pulses) < 10: + raise IRDecodeException("10 pulses minimum") + + # Ignore any header (evens start at 1), and any trailer. + if len(pulses) % 2 == 0: + pulses_end = -1 + else: + pulses_end = None + + evens = pulses[1:pulses_end:2] + odds = pulses[2:pulses_end:2] + + # bin both halves + even_bins = bin_data(evens) + odd_bins = bin_data(odds) + + outliers = [b[0] for b in (even_bins + odd_bins) if b[1] == 1] + even_bins = [b for b in even_bins if b[1] > 1] + odd_bins = [b for b in odd_bins if b[1] > 1] + + if not even_bins or not odd_bins: + raise IRDecodeException("Not enough data") + + if len(even_bins) == 1: + pulses = odds + pulse_bins = odd_bins + elif len(odd_bins) == 1: + pulses = evens + pulse_bins = even_bins + else: + raise IRDecodeException("Both even/odd pulses differ") + + if len(pulse_bins) == 1: + raise IRDecodeException("Pulses do not differ") + if len(pulse_bins) > 2: + raise IRDecodeException("Only mark & space handled") + + mark = min(pulse_bins[0][0], pulse_bins[1][0]) + space = max(pulse_bins[0][0], pulse_bins[1][0]) + + if outliers: + # skip outliers + pulses = [ + p for p in pulses if not (outliers[0] * 0.75) <= p <= (outliers[0] * 1.25) + ] + # convert marks/spaces to 0 and 1 + for i, pulse_length in enumerate(pulses): + if (space * 0.75) <= pulse_length <= (space * 1.25): + pulses[i] = False + elif (mark * 0.75) <= pulse_length <= (mark * 1.25): + pulses[i] = True else: - pulses_end = None + raise IRDecodeException("Pulses outside mark/space") - evens = pulses[1:pulses_end:2] - odds = pulses[2:pulses_end:2] + # convert bits to bytes! + output = [0] * ((len(pulses) + 7) // 8) + for i, pulse_length in enumerate(pulses): + output[i // 8] = output[i // 8] << 1 + if pulse_length: + output[i // 8] |= 1 + return output - # bin both halves - even_bins = self.bin_data(evens) - odd_bins = self.bin_data(odds) - outliers = [b[0] for b in (even_bins + odd_bins) if b[1] == 1] - even_bins = [b for b in even_bins if b[1] > 1] - odd_bins = [b for b in odd_bins if b[1] > 1] +class GenericDecode: + """Generic decoding of infrared signals""" - if not even_bins or not odd_bins: - raise IRDecodeException("Not enough data") + def bin_data(self, pulses): + "Wraps the top-level function bin_data for backward-compatibility." + return bin_data(pulses) - if len(even_bins) == 1: - pulses = odds - pulse_bins = odd_bins - elif len(odd_bins) == 1: - pulses = evens - pulse_bins = even_bins - else: - raise IRDecodeException("Both even/odd pulses differ") - - if len(pulse_bins) == 1: - raise IRDecodeException("Pulses do not differ") - if len(pulse_bins) > 2: - raise IRDecodeException("Only mark & space handled") - - mark = min(pulse_bins[0][0], pulse_bins[1][0]) - space = max(pulse_bins[0][0], pulse_bins[1][0]) - - if outliers: - # skip outliers - pulses = [ - p - for p in pulses - if not (outliers[0] * 0.75) <= p <= (outliers[0] * 1.25) - ] - # convert marks/spaces to 0 and 1 - for i, pulse_length in enumerate(pulses): - if (space * 0.75) <= pulse_length <= (space * 1.25): - pulses[i] = False - elif (mark * 0.75) <= pulse_length <= (mark * 1.25): - pulses[i] = True - else: - raise IRDecodeException("Pulses outside mark/space") - - # convert bits to bytes! - output = [0] * ((len(pulses) + 7) // 8) - for i, pulse_length in enumerate(pulses): - output[i // 8] = output[i // 8] << 1 - if pulse_length: - output[i // 8] |= 1 - return output + def decode_bits(self, pulses): + "Wraps the top-level function decode_bits for backward-compatibility." + return decode_bits(pulses) def _read_pulses_non_blocking( self, input_pulses, max_pulse=10000, pulse_window=0.10 From 10f17e1a9e1f588a3dd693f532ac5c237965ff03 Mon Sep 17 00:00:00 2001 From: Dan Allan Date: Thu, 21 Jan 2021 06:39:41 -0500 Subject: [PATCH 2/8] Implement NonblockinGenericDecoder and example. --- adafruit_irremote.py | 127 ++++++++++++++++++++++++++++--- examples/irremote_nonblocking.py | 33 ++++++++ 2 files changed, 150 insertions(+), 10 deletions(-) create mode 100644 examples/irremote_nonblocking.py diff --git a/adafruit_irremote.py b/adafruit_irremote.py index 4ec5fa8..74d4be5 100644 --- a/adafruit_irremote.py +++ b/adafruit_irremote.py @@ -93,6 +93,12 @@ def decode_bits(pulses): """Decode the pulses into bits.""" # pylint: disable=too-many-branches,too-many-statements + # TODO The name pulses is redefined several times below, so we'll stash the + # original in a separate variable for now. It might be worth refactoring to + # avoid redefining pulses, for the sake of readability. + input_pulses = pulses + pulses = list(pulses) # Copy to avoid mutating input. + # special exception for NEC repeat code! if ( (len(pulses) == 3) @@ -100,10 +106,10 @@ def decode_bits(pulses): and (2000 <= pulses[1] <= 3000) and (450 <= pulses[2] <= 700) ): - raise IRNECRepeatException() + return NECRepeatIRMessage(input_pulses) if len(pulses) < 10: - raise IRDecodeException("10 pulses minimum") + return UnparseableIRMessage(input_pulses, reason="Too short") # Ignore any header (evens start at 1), and any trailer. if len(pulses) % 2 == 0: @@ -123,7 +129,7 @@ def decode_bits(pulses): odd_bins = [b for b in odd_bins if b[1] > 1] if not even_bins or not odd_bins: - raise IRDecodeException("Not enough data") + return UnparseableIRMessage(input_pulses, reason="Not enough data") if len(even_bins) == 1: pulses = odds @@ -132,12 +138,12 @@ def decode_bits(pulses): pulses = evens pulse_bins = even_bins else: - raise IRDecodeException("Both even/odd pulses differ") + return UnparseableIRMessage(input_pulses, reason="Both even/odd pulses differ") if len(pulse_bins) == 1: - raise IRDecodeException("Pulses do not differ") + return UnparseableIRMessage(input_pulses, reason="Pulses do not differ") if len(pulse_bins) > 2: - raise IRDecodeException("Only mark & space handled") + return UnparseableIRMessage(input_pulses, reason="Only mark & space handled") mark = min(pulse_bins[0][0], pulse_bins[1][0]) space = max(pulse_bins[0][0], pulse_bins[1][0]) @@ -154,7 +160,9 @@ def decode_bits(pulses): elif (mark * 0.75) <= pulse_length <= (mark * 1.25): pulses[i] = True else: - raise IRDecodeException("Pulses outside mark/space") + return UnparseableIRMessage( + input_pulses, reason="Pulses outside mark/space" + ) # convert bits to bytes! output = [0] * ((len(pulses) + 7) // 8) @@ -162,7 +170,102 @@ def decode_bits(pulses): output[i // 8] = output[i // 8] << 1 if pulse_length: output[i // 8] |= 1 - return output + return IRMessage(input_pulses, code=output) + + +class BaseIRMessage: + "Contains the pulses that were parsed as one message." + + def __init__(self, pulses): + # Stash an immutable copy of pulses. + self.pulses = tuple(pulses) + + def __repr__(self): + return f"{self.__class__.__name__}({self.pulses})" + + +class IRMessage(BaseIRMessage): + """ + Message interpreted as bytes. + + >>> m.code # the output of interest (the parsed bytes) + >>> m.pulses # the original pulses + """ + + def __init__(self, pulses, *, code): + super().__init__(pulses) + self.code = code + + def __repr__(self): + return f"{self.__class__.__name__}" f"(pulses={self.pulses}, code={self.code})" + + +class UnparseableIRMessage(BaseIRMessage): + "Message that could not be interpreted." + + def __init__(self, pulses, *, reason): + super().__init__(pulses) + self.reason = reason + + def __repr__(self): + return ( + f"{self.__class__.__name__}" f"(pulses={self.pulses}, reason={self.reason})" + ) + + +class NECRepeatIRMessage(BaseIRMessage): + "Message interpreted as an NEC repeat code." + pass + + +class NonblockingGenericDecode: + """ + Decode pulses into bytes in a non-blocking fashion. + + :param ~pulseio.PulseIn input_pulses: Object to read pulses from + :param int max_pulse: Pulse duration to end a burst. Units are + microseconds. + + >>> pulses = PulseIn(...) + >>> decoder = NonblockingGenericDecoder(pulses) + >>> for message in decoder.read(): + ... if isinstace(message, IRMessage): + ... message.code # TA-DA! Do something with this in your application. + ... else: + ... # message is either NECRepeatIRMessage or + ... # UnparseableIRMessage. You may decide to ignore it, raise + ... # an error, or log the issue to a file. If you raise or log, + ... # it may be helpful to include message.pulses in the error message. + ... ... + """ + + def __init__(self, pulses, max_pulse=10_000): + self.pulses = pulses # PulseIn + self.max_pulse = max_pulse + self._unparsed_pulses = [] # internal buffer of partial messages + + def read(self): + """ + Consume all pulses from PulseIn. Yield decoded messages, if any. + + If a partial message is received, this does not block to wait for the + rest. It stashes the partial message, to be continued the next time it + is called. + """ + # Consume from PulseIn. + while self.pulses: + pulse = self.pulses.popleft() + self._unparsed_pulses.append(pulse) + if pulse > self.max_pulse: + # End of message! Decode it and yield a BaseIRMessage. + yield decode_bits(self._unparsed_pulses) + self._unparsed_pulses.clear() + # TODO Do we need to consume and throw away more pulses here? + # I'm unclear about the role that "pruning" plays in the + # original implementation in GenericDecode._read_pulses_non_blocking. + # When we reach here, we have consumed everything from PulseIn. + # If there are some pulses in self._unparsed_pulses, they represent + # partial messages. We'll finish them next time read() is called. class GenericDecode: @@ -174,7 +277,11 @@ def bin_data(self, pulses): def decode_bits(self, pulses): "Wraps the top-level function decode_bits for backward-compatibility." - return decode_bits(pulses) + result = decode_bits(pulses) + if isinstance(result, NECRepeatIRMessage): + raise IRNECRepeatException() + elif isinstance(result, UnparseableIRMessage): + raise IRDecodeException("10 pulses minimum") def _read_pulses_non_blocking( self, input_pulses, max_pulse=10000, pulse_window=0.10 @@ -214,7 +321,7 @@ def read_pulses( max_pulse=10000, blocking=True, pulse_window=0.10, - blocking_delay=0.10 + blocking_delay=0.10, ): """Read out a burst of pulses until pulses stop for a specified period (pulse_window), pruning pulses after a pulse longer than ``max_pulse``. diff --git a/examples/irremote_nonblocking.py b/examples/irremote_nonblocking.py new file mode 100644 index 0000000..ad4a0d8 --- /dev/null +++ b/examples/irremote_nonblocking.py @@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries +# SPDX-License-Identifier: MIT + +# Circuit Playground Express Demo Code +# Adjust the pulseio 'board.PIN' if using something else +import pulseio +import board +import adafruit_irremote +import time + +pulsein = pulseio.PulseIn(board.REMOTEIN, maxlen=120, idle_state=True) +decoder = adafruit_irremote.NonblockingGenericDecode(pulsein) + + +t0 = next_heartbeat = time.monotonic() + +while True: + for message in decoder.read(): + print(f"t={time.monotonic() - t0:.3} New Message") + print("Heard", len(message.pulses), "Pulses:", message.pulses) + if isinstance(message, adafruit_irremote.IRMessage): + print("Decoded:", message.code) + elif isinstance(message, adafruit_irremote.NECRepeatIRMessage): + print("NEC repeat!") + elif isinstance(message, adafruit_irremote.UnparseableIRMessage): + print("Failed to decode", message.reason) + print("----------------------------") + + # This heartbeat confirms that we are not blocked somewhere above. + t = time.monotonic() + if t > next_heartbeat: + print(f"t={time.monotonic() - t0:.3} Heartbeat") + next_heartbeat = t + 0.1 From 0f597ca7b60f2a29fd8bd05fd03f0ed63f6247b1 Mon Sep 17 00:00:00 2001 From: Dan Allan Date: Thu, 21 Jan 2021 09:06:06 -0500 Subject: [PATCH 3/8] Refactor to use namedtuple instead of custom classes. --- adafruit_irremote.py | 53 ++++++++------------------------------------ 1 file changed, 9 insertions(+), 44 deletions(-) diff --git a/adafruit_irremote.py b/adafruit_irremote.py index 74d4be5..425cd8d 100644 --- a/adafruit_irremote.py +++ b/adafruit_irremote.py @@ -50,8 +50,8 @@ https://github.com/adafruit/circuitpython/releases """ - import array +from collections import namedtuple import time __version__ = "0.0.0-auto.0" @@ -96,7 +96,7 @@ def decode_bits(pulses): # TODO The name pulses is redefined several times below, so we'll stash the # original in a separate variable for now. It might be worth refactoring to # avoid redefining pulses, for the sake of readability. - input_pulses = pulses + input_pulses = tuple(pulses) pulses = list(pulses) # Copy to avoid mutating input. # special exception for NEC repeat code! @@ -170,52 +170,17 @@ def decode_bits(pulses): output[i // 8] = output[i // 8] << 1 if pulse_length: output[i // 8] |= 1 - return IRMessage(input_pulses, code=output) - - -class BaseIRMessage: - "Contains the pulses that were parsed as one message." - - def __init__(self, pulses): - # Stash an immutable copy of pulses. - self.pulses = tuple(pulses) + return IRMessage(tuple(input_pulses), code=tuple(output)) - def __repr__(self): - return f"{self.__class__.__name__}({self.pulses})" +IRMessage = namedtuple("IRMessage", ("pulses", "code")) +"Pulses and the code they were parsed into" -class IRMessage(BaseIRMessage): - """ - Message interpreted as bytes. - - >>> m.code # the output of interest (the parsed bytes) - >>> m.pulses # the original pulses - """ - - def __init__(self, pulses, *, code): - super().__init__(pulses) - self.code = code - - def __repr__(self): - return f"{self.__class__.__name__}" f"(pulses={self.pulses}, code={self.code})" - - -class UnparseableIRMessage(BaseIRMessage): - "Message that could not be interpreted." - - def __init__(self, pulses, *, reason): - super().__init__(pulses) - self.reason = reason - - def __repr__(self): - return ( - f"{self.__class__.__name__}" f"(pulses={self.pulses}, reason={self.reason})" - ) - +UnparseableIRMessage = namedtuple("IRMessage", ("pulses", "reason")) +"Pulses and the reason that they could not be parsed into a code" -class NECRepeatIRMessage(BaseIRMessage): - "Message interpreted as an NEC repeat code." - pass +NECRepeatIRMessage = namedtuple("NECRepeatIRMessage", ("pulses",)) +"Pulses interpreted as an NEC repeat code" class NonblockingGenericDecode: From 48ca809dfb6379e031335eeb17cbca98fa5632e2 Mon Sep 17 00:00:00 2001 From: Dan Allan Date: Sat, 29 May 2021 20:53:28 -0400 Subject: [PATCH 4/8] Address pylint failures. --- .gitignore | 1 + adafruit_irremote.py | 48 ++++++++++++++++++++++++++++++++------------ 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 9647e71..53ebf19 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ bundles .eggs dist **/*.egg-info +*.swp diff --git a/adafruit_irremote.py b/adafruit_irremote.py index 425cd8d..d0b0953 100644 --- a/adafruit_irremote.py +++ b/adafruit_irremote.py @@ -109,7 +109,8 @@ def decode_bits(pulses): return NECRepeatIRMessage(input_pulses) if len(pulses) < 10: - return UnparseableIRMessage(input_pulses, reason="Too short") + msg = UnparseableIRMessage(input_pulses, reason="Too short") + raise FailedToDecode(msg) # Ignore any header (evens start at 1), and any trailer. if len(pulses) % 2 == 0: @@ -129,7 +130,8 @@ def decode_bits(pulses): odd_bins = [b for b in odd_bins if b[1] > 1] if not even_bins or not odd_bins: - return UnparseableIRMessage(input_pulses, reason="Not enough data") + msg = UnparseableIRMessage(input_pulses, reason="Not enough data") + raise FailedToDecode(msg) if len(even_bins) == 1: pulses = odds @@ -138,12 +140,15 @@ def decode_bits(pulses): pulses = evens pulse_bins = even_bins else: - return UnparseableIRMessage(input_pulses, reason="Both even/odd pulses differ") + msg = UnparseableIRMessage(input_pulses, reason="Both even/odd pulses differ") + raise FailedToDecode(msg) if len(pulse_bins) == 1: - return UnparseableIRMessage(input_pulses, reason="Pulses do not differ") + msg = UnparseableIRMessage(input_pulses, reason="Pulses do not differ") + raise FailedToDecode(msg) if len(pulse_bins) > 2: - return UnparseableIRMessage(input_pulses, reason="Only mark & space handled") + msg = UnparseableIRMessage(input_pulses, reason="Only mark & space handled") + raise FailedToDecode(msg) mark = min(pulse_bins[0][0], pulse_bins[1][0]) space = max(pulse_bins[0][0], pulse_bins[1][0]) @@ -160,9 +165,8 @@ def decode_bits(pulses): elif (mark * 0.75) <= pulse_length <= (mark * 1.25): pulses[i] = True else: - return UnparseableIRMessage( - input_pulses, reason="Pulses outside mark/space" - ) + msg = UnparseableIRMessage(input_pulses, reason="Pulses outside mark/space") + raise FailedToDecode(msg) # convert bits to bytes! output = [0] * ((len(pulses) + 7) // 8) @@ -183,6 +187,10 @@ def decode_bits(pulses): "Pulses interpreted as an NEC repeat code" +class FailedToDecode(Exception): + "Raised by decode_bits. Error argument is UnparseableIRMessage" + + class NonblockingGenericDecode: """ Decode pulses into bytes in a non-blocking fashion. @@ -223,7 +231,13 @@ def read(self): self._unparsed_pulses.append(pulse) if pulse > self.max_pulse: # End of message! Decode it and yield a BaseIRMessage. - yield decode_bits(self._unparsed_pulses) + try: + yield decode_bits(self._unparsed_pulses) + except FailedToDecode as err: + # If you want to debug failed decodes, this would be a good + # place to print/log or (re-)raise. + (unparseable_message,) = err.args + yield unparseable_message self._unparsed_pulses.clear() # TODO Do we need to consume and throw away more pulses here? # I'm unclear about the role that "pruning" plays in the @@ -236,21 +250,26 @@ def read(self): class GenericDecode: """Generic decoding of infrared signals""" - def bin_data(self, pulses): + # Note: pylint's complaint about the following three methods (no self-use) + # is absolutely correct, which is why the code was refactored, but we need + # this here for back-compat, hence we disable pylint for that specific + # complaint. + + def bin_data(self, pulses): # pylint: disable=R0201 "Wraps the top-level function bin_data for backward-compatibility." return bin_data(pulses) - def decode_bits(self, pulses): + def decode_bits(self, pulses): # pylint: disable=R0201 "Wraps the top-level function decode_bits for backward-compatibility." result = decode_bits(pulses) if isinstance(result, NECRepeatIRMessage): raise IRNECRepeatException() - elif isinstance(result, UnparseableIRMessage): + if isinstance(result, UnparseableIRMessage): raise IRDecodeException("10 pulses minimum") def _read_pulses_non_blocking( self, input_pulses, max_pulse=10000, pulse_window=0.10 - ): + ): # pylint: disable=R0201 """Read out a burst of pulses without blocking until pulses stop for a specified period (pulse_window), pruning pulses after a pulse longer than ``max_pulse``. @@ -258,6 +277,9 @@ def _read_pulses_non_blocking( :param int max_pulse: Pulse duration to end a burst :param float pulse_window: pulses are collected for this period of time """ + # Note: pylint's complaint (no self-use) is absolutely correct, which + # is why the code was refactored, but we need this here for + # back-compat, hence we disable pylint. received = None recent_count = 0 pruning = False From 96403ae3758beae168308783a4d342f0203b1119 Mon Sep 17 00:00:00 2001 From: Dan Allan Date: Sun, 30 May 2021 11:31:30 -0400 Subject: [PATCH 5/8] Fix import order. --- examples/irremote_nonblocking.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/irremote_nonblocking.py b/examples/irremote_nonblocking.py index ad4a0d8..048a0e3 100644 --- a/examples/irremote_nonblocking.py +++ b/examples/irremote_nonblocking.py @@ -3,11 +3,12 @@ # Circuit Playground Express Demo Code # Adjust the pulseio 'board.PIN' if using something else -import pulseio -import board -import adafruit_irremote import time +import adafruit_irremote +import board +import pulseio + pulsein = pulseio.PulseIn(board.REMOTEIN, maxlen=120, idle_state=True) decoder = adafruit_irremote.NonblockingGenericDecode(pulsein) From e7e66c5821c43c7856f8dc5955295e9d1cf21f35 Mon Sep 17 00:00:00 2001 From: Dan Allan Date: Sun, 30 May 2021 13:35:59 -0400 Subject: [PATCH 6/8] Tweak import order again. --- examples/irremote_nonblocking.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/irremote_nonblocking.py b/examples/irremote_nonblocking.py index 048a0e3..a126df7 100644 --- a/examples/irremote_nonblocking.py +++ b/examples/irremote_nonblocking.py @@ -5,10 +5,11 @@ # Adjust the pulseio 'board.PIN' if using something else import time -import adafruit_irremote import board import pulseio +import adafruit_irremote + pulsein = pulseio.PulseIn(board.REMOTEIN, maxlen=120, idle_state=True) decoder = adafruit_irremote.NonblockingGenericDecode(pulsein) From 701aeb176f61eac236d421fe379a2127ab21870d Mon Sep 17 00:00:00 2001 From: Dan Allan Date: Mon, 31 May 2021 09:18:37 -0400 Subject: [PATCH 7/8] Whitespace change to satisfy sphinx. --- adafruit_irremote.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/adafruit_irremote.py b/adafruit_irremote.py index d0b0953..7c3ccdd 100644 --- a/adafruit_irremote.py +++ b/adafruit_irremote.py @@ -196,8 +196,7 @@ class NonblockingGenericDecode: Decode pulses into bytes in a non-blocking fashion. :param ~pulseio.PulseIn input_pulses: Object to read pulses from - :param int max_pulse: Pulse duration to end a burst. Units are - microseconds. + :param int max_pulse: Pulse duration to end a burst. Units are microseconds. >>> pulses = PulseIn(...) >>> decoder = NonblockingGenericDecoder(pulses) From 8ab59cefd0bd3fde59f31a1dbae79455af692588 Mon Sep 17 00:00:00 2001 From: Dan Allan Date: Wed, 2 Jun 2021 11:18:02 -0400 Subject: [PATCH 8/8] Use pylint name instead of code for readability. --- adafruit_irremote.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/adafruit_irremote.py b/adafruit_irremote.py index 7c3ccdd..4900b6b 100644 --- a/adafruit_irremote.py +++ b/adafruit_irremote.py @@ -254,11 +254,11 @@ class GenericDecode: # this here for back-compat, hence we disable pylint for that specific # complaint. - def bin_data(self, pulses): # pylint: disable=R0201 + def bin_data(self, pulses): # pylint: disable=no-self-use "Wraps the top-level function bin_data for backward-compatibility." return bin_data(pulses) - def decode_bits(self, pulses): # pylint: disable=R0201 + def decode_bits(self, pulses): # pylint: disable=no-self-use "Wraps the top-level function decode_bits for backward-compatibility." result = decode_bits(pulses) if isinstance(result, NECRepeatIRMessage): @@ -268,7 +268,7 @@ def decode_bits(self, pulses): # pylint: disable=R0201 def _read_pulses_non_blocking( self, input_pulses, max_pulse=10000, pulse_window=0.10 - ): # pylint: disable=R0201 + ): # pylint: disable=no-self-use """Read out a burst of pulses without blocking until pulses stop for a specified period (pulse_window), pruning pulses after a pulse longer than ``max_pulse``.