From 0c176bea03bff0ece7b893373d3d9f6bb2ce9064 Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Sun, 14 Feb 2021 23:58:32 +0000 Subject: [PATCH] Add WIP controller support. --- build/requirements.txt | 1 + controllers/__init__.py | 0 controllers/controller.py | 24 ++++++++++++++++++++ controllers/mattchbox_usb.py | 43 ++++++++++++++++++++++++++++++++++++ server.py | 5 +++++ 5 files changed, 73 insertions(+) create mode 100644 controllers/__init__.py create mode 100644 controllers/controller.py create mode 100644 controllers/mattchbox_usb.py diff --git a/build/requirements.txt b/build/requirements.txt index 06596ef..a37cbd5 100644 --- a/build/requirements.txt +++ b/build/requirements.txt @@ -7,3 +7,4 @@ setproctitle pyttsx3 websockets typing_extensions +pyserial diff --git a/controllers/__init__.py b/controllers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/controllers/controller.py b/controllers/controller.py new file mode 100644 index 0000000..ad4be67 --- /dev/null +++ b/controllers/controller.py @@ -0,0 +1,24 @@ +from multiprocessing import Queue +from typing import Any, Callable, List + +# Main controller class. All implementations of controller support should inherit this. +class Controller(): + callbacks: List[Callable] = [] + player_to_q: List[Queue] + player_from_q: List[Queue] + + def __init__(self, player_to_q: List[Queue], player_from_q: List[Queue]): + self.receive() + return + + # Registers a function for the controller class to call to tell BAPSicle to do something. + def register_callback(self, callback: Callable): + self.callbacks.append(callback) + return + + # Loop etc in here to process the data from your controller and call the callbacks. + def receive(self): + return + + + diff --git a/controllers/mattchbox_usb.py b/controllers/mattchbox_usb.py new file mode 100644 index 0000000..e21b5d1 --- /dev/null +++ b/controllers/mattchbox_usb.py @@ -0,0 +1,43 @@ +from typing import List +from controllers.controller import Controller +from multiprocessing import Queue +import serial +import sys + +class MattchBox(Controller): + ser: serial.Serial + + def __init__(self, player_to_q: List[Queue], player_from_q: List[Queue]): + # connect to serial port + self.ser = serial.serial_for_url("/dev/cu.usbserial-310", do_not_open=True) + self.ser.baudrate = 2400 + + # TOOD: These need to be split in the player handler. + self.player_from_q = player_from_q + self.player_to_q = player_to_q + + try: + self.ser.open() + except serial.SerialException as e: + sys.stderr.write('Could not open serial port {}: {}\n'.format(self.ser.name, e)) + return + + self.receive() + + def receive(self): + while self.ser.is_open: + try: + line = int.from_bytes(self.ser.read(1), "big") # Endianness doesn't matter for 1 byte. + print("Controller got:", line) + if (line == 255): + print("Sending back KeepAlive") + self.ser.write(b'\xff') # Send 255 back. + elif (line in [1,3,5]): + self.player_to_q[int(line / 2)].put("PLAY") + elif (line in [2,4,6]): + self.player_to_q[int(line / 2)-1].put("STOP") + + except: + continue + + diff --git a/server.py b/server.py index 739f1f9..882db3e 100644 --- a/server.py +++ b/server.py @@ -13,6 +13,7 @@ October, November 2020 """ import asyncio +from controllers.mattchbox_usb import MattchBox import copy import multiprocessing import queue @@ -420,6 +421,10 @@ async def startServer(): websockets_server = multiprocessing.Process(target=WebsocketServer, args=(channel_to_q, channel_from_q, state)) websockets_server.start() + + controller_handler = multiprocessing.Process(target=MattchBox, args=(channel_to_q, channel_from_q)) + controller_handler.start() + if not isMacOS(): # Temporary RIP.