def handleConn(connectionInformation): conn: socket.socket = connectionInformation[0] addr = connectionInformation[1] # print('Connected by', addr) # ensure all data is received try: header = messageType(conn.recv(4).decode()) except: # if invalid header is received, ignore the packet return if (header == messageType.camera): try: data = b"" while EOM not in data: data += conn.recv(4096) split = data.index(EOM) metaData = json.loads(data[:split]) data = data[split + len(EOM):] while len(data) < metaData["size"]: data += conn.recv(4096) # construct image GUI.cameraBuffer.put_nowait(imageDecoder.decode(metaData, data)) except: # if any error occurs, return without updating cams Logger.logError(print_exc()) return else: data = conn.recv(4096) while EOM not in data: data += conn.recv(4096) # decode data data = data.decode()[0:-len(EOM)] split = data.index(":") GUI.varData[data[0:split]] = data[split + 1:]
def startControllerServer(): Logger.log("Controller Server Started") while True: try: doServer() except ConnectionAbortedError: Logger.logError(format_exc()) time.sleep(2) continue
def subscribe(fn): # create wrapper function to manipulate wrapped fn if(not inspect.iscoroutinefunction(fn)): # ensure function has been defined as async def name(): ... (could add functionality for both but would add like 50 lines and its easy enough to write an asynchronous function that does not need to wait on anything :P) raise SubscriptionException("Cannot subscribe synchronous function to asynchronous event system") if not event_type in subscribers: # add subscribed event to subscription tracker subscribers[event_type] = [] if fn in subscribers[event_type]: # ensure no function is subscribed twice try: raise SubscriptionException("Cannot subscribe function twice") except SubscriptionException: Logger.logError(format_exc()) return fn subscribers[event_type].append(fn) # add function to subscribed event in tracker Logger.log(fn, "successfully subscribed to event " + event_type.__name__) # DEBUG log return fn
from tools import Logger from tools.network import Client, Server from gui import GUI from traceback import format_exc import cv2 # Debug Tools purgeLogs = True def initialize(): Logger.createNewLog(purgeLogs) # GUI already initialized on import resolution Client.startClient() Server.startServer() # ControllerClient.startControllerForwarding() Logger.log("DriverStation initialized") initialize() try: while True: # always update GUI (prevent OS from thinking program has stalled) GUI.rootWindow.update() GUI.updateWidgets() except: Logger.logError(format_exc()[0:-1]) finally: Logger.log("Shutting down")
def doServer(): # create new socket object with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) # bind our socket to our port s.listen() # listen for connections # outside loop to enable restarting the server while True: conn, addr = s.accept( ) # once connection available, accept it (THIS IS BLOCKING) try: with conn: # Start by getting controller information json (first packet received) # print("Connected to", addr) # print who we are connected with data: bytes = b"" while not data: data += conn.recv(4096) # if message post-curser not found, keep polling the socket if (EOM not in data): continue split = data.index(EOM) controllerInformation = data[:split] data = data[split + len(EOM):] controllerInformation = controllerInformation.decode() try: controllerInformation = json.loads( controllerInformation) except JSONDecodeError: # JSONDecode error here is FATAL, abort the connection (and retry connection) Logger.logError(format_exc()) s.close() raise ConnectionAbortedError # TODO: MAKE OBSOLETE # parse any events grabbed from socket at this time events: List[List] = [] while EOM in data: split = data.index(EOM) try: events.append( json.loads(data[:split].decode().replace( '\n', ''))) except JSONDecodeError: Logger.logError(format_exc()) data = data[split + len( EOM ):] # if we cut off data, leave cut off data in buffer # once we start getting data, get the first thing sent (our controller information) devices_json = controllerInformation devices = [] for device_json in devices_json: capabilities = {} for k, v in device_json['capabilities'].items( ): # parse capabilities json capabilities[int(k)] = [ x if not isinstance(x, list) else (x[0], evdev.AbsInfo(**x[1])) for x in v ] # create new EVDev device devices.append( evdev.UInput(capabilities, name=device_json['name'], vendor=device_json["vendor"], product=device_json["product"], version=device_json["version"])) Logger.log('Controller Device created') # while we are connected read controller data (and try not to miss any events) while True: # poll the socket start = time.time() while EOM not in data: # grab data until EOM character reached data += conn.recv(4096) if (not data and time.time() - start > 60 ): # 60 second timeout for controller server raise ConnectionResetError # parse data # deocde, remove EOM character, split events into list dataLST: List[str] = data.decode()[:len(data) - len(EOM)].split( '\n') for possibleEvent in dataLST: if (possibleEvent == '' ): # check if event is valid continue try: events.append( json.loads(possibleEvent.replace('\n', '')) ) # get rid of unwanted \n's if they exist except JSONDecodeError: # Error here is not FATAL, ignore the event and continue parsing events Logger.logError(format_exc()) continue # apply pending events for event in events: if (event == ''): continue # write events to applicable device devices[int(event[0])].write( int(event[1]), int(event[2]), int(event[3])) events = [] # connection was reset from other side (or maybe your network dropped) except ConnectionResetError: Logger.logError(format_exc()) time.sleep(1) # wait second before retrying connection continue