import RPi.GPIO as GPIO from subprocess import call from time import time IR_PIN_INPUT = 15 def setup(): GPIO.setmode(GPIO.BOARD) # Numbers GPIOs by physical location GPIO.setup(IR_PIN_INPUT, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) def binary_aquire(pin, duration): # aquires data as quickly as possible t0 = time() results = [] while (time() - t0) < duration: results.append(GPIO.input(pin)) return results def on_ir_receive(pinNo, bouncetime=150): # when edge detect is called (which requires less CPU than constant # data acquisition), we acquire data as quickly as possible data = binary_aquire(pinNo, bouncetime/1000.0) if len(data) < bouncetime: return rate = len(data) / (bouncetime / 1000.0) pulses = [] i_break = 0 # detect run lengths using the acquisition rate to turn the times in to microseconds for i in range(1, len(data)): if (data[i] != data[i-1]) or (i == len(data)-1): pulses.append((data[i-1], int((i-i_break)/rate*1e6))) i_break = i # decode ( < 1 ms "1" pulse is a 1, > 1 ms "1" pulse is a 1, longer than 2 ms pulse is something else) # does not decode channel, which may be a piece of the information after the long 1 pulse in the middle outbin = "" for val, us in pulses: if val != 1: continue if outbin and us > 2000: break elif us < 1000: outbin += "0" elif 1000 < us < 2000: outbin += "1" try: return int(outbin, 2) except ValueError: # probably an empty code return None def run_command(mpc_command): call(["mpc", mpc_command]) def destroy(): GPIO.cleanup() codes = { "0x5ea110ef": "play", "0x5ea1906f": "stop", "0x2f50c837": "toggle", "0x5ea150af": "next", "0x5ea1d02f": "prev", } if __name__ == "__main__": setup() try: print("Starting IR Listener") while True: print("Waiting for signal") GPIO.wait_for_edge(IR_PIN_INPUT, GPIO.FALLING) code = on_ir_receive(IR_PIN_INPUT) if code and str(hex(code)) in codes: hex_code = str(hex(code)) print(f"{hex_code} -> {codes[hex_code]}") run_command(codes[hex_code]) else: pass print("Invalid code") except KeyboardInterrupt: print("interupt") pass except RuntimeError as e: # this gets thrown when control C gets pressed # because wait_for_edge doesn't properly pass this on print(f"runtime: {e}") pass print("Quitting") destroy()