From fa6e5d82137564d946c0c8710af4cb8c808fbc52 Mon Sep 17 00:00:00 2001 From: Caleb Fontenot Date: Wed, 3 Jun 2020 12:18:51 -0500 Subject: [PATCH] Almost done, although there's a data send collision now --- Client.py | 51 ++++++++------------------ README.md | 8 +++-- Server.py | 106 +++++++++++++++++++++++++++++------------------------- 3 files changed, 78 insertions(+), 87 deletions(-) diff --git a/Client.py b/Client.py index d3c7846..0fc52b1 100644 --- a/Client.py +++ b/Client.py @@ -1,44 +1,23 @@ #!/usr/bin/python import socket import threading -#import pyxinput +import pyxinput from time import sleep import pickle # Define server ip and port ip = '192.168.122.1' port = 2222 -#Define globals -decodedServerData = "" -def recvData(ip, port): - global decodedServerData - # Connect to Server - client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - #client.setblocking(False) - client.connect((ip, port)) - while True: - from_server = client.recv(4096) - #Decode Sever message - decodedServerData = pickle.loads(from_server) - print("Raw Data:", decodedServerData) - MyVirtual.set_value(decodedServerData) -def virtualController(): - MyVirtual = pyxinput.vController() - #Set percent to false so values match the raw data from the server - # MyVirtual.percent = False - MyRead = pyxinput.rController(1) - print(MyRead.gamepad) -''' - while True: - #global decodedServerData - # Init virtual XInput Controller - - MyVirtual.set_value('AxisLy', 0) - -''' -# Execute all functions as threads -if __name__ == "__main__": - #Create Threads - t1 = threading.Thread(target=recvData, args=(ip, port)) - #t2 = threading.Thread(target=virtualController, args=()) -t1.start() -#t2.start() +# Create virtual controller +MyVirtual = pyxinput.vController() +# Connect to Server +client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +client.connect((ip, port)) +while True: + from_server = client.recv(8144) + #Decode Sever message + decodedServerData = pickle.loads(from_server) + print("Raw Data:", str(decodedServerData)) + # pyxinput will only accept values one at a time, so we need to apply the itme in the dictionary one by one + for event, state in decodedServerData.items(): + MyVirtual.set_value(event, state) + print('\''+event+'\''+',', state) diff --git a/README.md b/README.md index 1a4abbe..3aaed37 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ # pyInputStreaming Python Scripts to stream controller input from a Linux Host to a Windows 10 virtual machine - -lol +# Dependancies +On the server, the following libraries are required: +colored +inputs +On the Client: +PYXInput diff --git a/Server.py b/Server.py index be0e115..e55743e 100644 --- a/Server.py +++ b/Server.py @@ -14,53 +14,61 @@ print("Gamepads available:") print(devices.gamepads) #Define globals controllerData = "" -# Show device output, send it in var -#def printInput(): - #global controllerData -# Capture device input and send it via a web socket -#def inputCapture(ip, port): - #global controllerData -print("Waiting for connection...") -''' -with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: - s.bind((ip, port)) - s.listen(1) - #s.setblocking(False) - conn, addr = s.accept() - with conn: - print(colored('Connected by', 'red'), addr) -''' #Dictionary of of all possible values -controllerDataDict = {'AxisLx': 0, 'AxisLy': 0, 'AxisRx': 0, 'AxisRy': 0, 'BtnBack': 0, 'BtnStart': 0, 'BtnA': 0, 'BtnB': 0, 'BtnX': 0, 'BtnY': 0, 'BtnThumbL': 0, 'BtnThumbR': 0, 'BtnShoulderL': 0, 'BtnShoulderR': 0, 'Dpad': 0, 'TriggerL': 0, 'TriggerR,': 0} -# Convert "inputs" library data to our dict -print(controllerDataDict) - #Print value of AxisRx - #print(controllerDataDict['AxisRx']) -while True: - events = get_gamepad() - for event in events: - #controllerDataTuple = event.ev_type, event.code, event.state - controllerDataTuple = event.code, event.state - controllerData = controllerDataTuple - #print("controllerData is a", type(controllerData)) - print(controllerData) - -''' - #Pickle for transmittion - encodedControllerData = pickle.dumps(controllerDataDict) - print(encodedControllerData) - conn.send(encodedControllerData) - #Wait for ok signal from client before continuing... -''' - - - - - -# Execute all functions as threads -#if __name__ == "__main__": - #Create Threads - #t1 = threading.Thread(target=printInput, args=()) - #t2 = threading.Thread(target=inputCapture, args=(ip, port)) -#t1.start() -#t2.start() +controllerDataDict = {'AxisLx': 0, 'AxisLy': 0, 'AxisRx': 0, 'AxisRy': 0, 'BtnBack': 0, 'BtnStart': 0, 'BtnA': 0, 'BtnB': 0, 'BtnX': 0, 'BtnY': 0, 'BtnThumbL': 0, 'BtnThumbR': 0, 'BtnShoulderL': 0, 'BtnShoulderR': 0, 'Dpad': 0, 'TriggerL': 0, 'TriggerR': 0} +#Lookup table to convert values from the "inputs" library +lookup_table = {'ABS_X': 'AxisLx', 'ABS_Y': 'AxisLy', 'ABS_RX': 'AxisRx', 'ABS_RY': 'AxisRy', 'BTN_SELECT': 'BtnBack', 'BTN_START': 'BtnStart', 'BTN_SOUTH': 'BtnA', 'BTN_EAST': 'BtnB', 'BTN_NORTH': 'BtnX', 'BTN_WEST': 'BtnY', 'BTN_THUMBL': 'BtnThumbL', 'BTN_THUMBR': 'BtnThumbR', 'BTN_TL': 'BtnShoulderL', 'BTN_TR': 'BtnShoulderR', 'ABS_Z': 'TriggerL', 'ABS_RZ': 'TriggerR'} +print("Waiting for connection...") +def sendData(): + #Pickle for transmittion + encodedControllerData = pickle.dumps(controllerDataDict) + #print(encodedControllerData) + conn.send(encodedControllerData) +with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.bind((ip, port)) + s.listen(1) + #s.setblocking(False) + conn, addr = s.accept() + with conn: + print(colored('Connected by', 'red'), addr) + print(controllerDataDict) + while True: + events = get_gamepad() + for event in events: + #controllerDataTuple = event.ev_type, event.code, event.state + controllerDataTuple = event.code, event.state + controllerData = controllerDataTuple + #print("controllerData is a", type(controllerData)) + print(controllerData) + print(controllerDataDict) + #If event.code is SYN_REPORT, ignore it + if event.code == "SYN_REPORT": + continue + if event.code == "BTN_MODE": + print(colored('The home button is unimplemented on PYXinput, ignoring', 'red')) + continue + #Ugh, PYXinput and inputs handle the Dpad in the most annoying way possible + elif event.code == "ABS_HAT0X": + #if ABS_HAT0X is 0, then there is no input on the dpad + if event.state == 0: + controllerDataDict['Dpad'] = 0 #No input + if event.state == 1: + controllerDataDict['Dpad'] = 8 #Right + if event.state == -1: + controllerDataDict['Dpad'] = 4 #Left + sendData() + elif event.code == "ABS_HAT0Y": + #if ABS_HAT0Y is 0, then there is no input on the dpad + if event.state == 0: + controllerDataDict['Dpad'] = 0 #No input + if event.state == 1: + controllerDataDict['Dpad'] = 2 #Down + if event.state == -1: + controllerDataDict['Dpad'] = 1 #Up + sendData() + else: + # Add values to controllerDataDict + controllerDataDict[lookup_table[str(event.code)]] = event.state + sendData() +#Execute everything +controllerLoop()