This needs reorganising, and adding things like osc-listening for configuration and preset-changing. Essentially, for each tourbox message, a preset will associate it to a sequence of Osc messages to designated hosts and ports (with a default set). Then there will be e.g. a receiver that takes in osc messages and generates keypresses. ```python #!/usr/bin/env python import serial # python -m pip install pyserial import time from pythonosc import udp_client # python -m pip install python-osc import random import time import sys import os import platform import socket def get_ip(): # workaround since reaper doesn't receive packets if sent to localhost rather than 192.168.0.x s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.settimeout(0) try: # doesn't even have to be reachable s.connect(('10.254.254.254', 1)) IP = s.getsockname()[0] except Exception: IP = '127.0.0.1' finally: s.close() return IP port = os.getenv("port",os.getenv("PORT",9000)) try: port = int(port) except ValueError: print(f"Port '{port}' must be an integer") exit(1) host = os.getenv("host",os.getenv("HOST",get_ip())) print(f"{host=} {port=}") # xxd /dev/ttyACM3 def main(): global client client = udp_client.SimpleUDPClient(host,port) com_port = os.getenv("com_port",None) if com_port is None: if platform.system() == "Linux": com_port = "/dev/ttyACM0" elif platform.system() == "Darwin": com_port = "weird" elif "cygwin" in platform.system().lower(): com_port = "/dev/ttyS4" elif platform.system() == "Windows": com_port = "COM5:" else: print(f"Don't support {platform.system()}") exit(2) with serial.Serial(com_port,19200) as ser: try: while True: x = ser.read() y = ord(x) print(f"{y:02x}") handle(y) except KeyboardInterrupt: print(f"Ctrl-c") exit() def button(n,dirn): if dirn == 0: action(f"button_{n:02x}") def rotary(n,dirn): if dirn > 0: return action('rotary_{n:02x}_{dirn}') def action(x,args=[]): print(x,args) client.send_message(f"tour/{x}",args) knobs = { 0x04: "knob", 0x0f: "dial", 0x09: "vdial" } dpad = { 0x10: "up", 0x11: "down", 0x12: "left", 0x13: "right" } def handle(x): print(f"{x=}") dirn = x >> 7 x &= 0x7F kdirn = x >> 4 x &= 0x3f if x in knobs: if dirn > 0: return action(f"{knobs[x]}/"+("cw" if kdirn > 0 else "ccw")) elif x in dpad: if dirn > 0: return action(f"dpad/{dpad[x]}") else: if dirn > 0: return action(f"button/{x:02x}") if __name__ == "__main__": main() ```