Random Project Time - RemJoy (P1)
So I wanted to stream games from PC to my phone using Moonlight but it turns out my phone doesn't support USB Joysticks via OTG. So to circumvent this problem I’m creating this. It sends data from a USB Joystick (Connected to an RPi) over WiFi to a PC and writes it to a virtual joystick device. Pretty simple, huh.
TL;DR: We convert a USB Joystick into a WiFi Joystick
Stuff Required
- A Raspberry Pi (Tested on: RPi 0W and RPi 3B+)
- A Windows PC (min. Windows 7)
- A USB Joystick (Or really any joystick that is accessible at
/dev/input/js*
on linux) - Basic knowledge of C++ (Optional)
Planning
I started by looking for a way to create a virtual Joystick device on Windows and I came across PPJoy. The project seemed to be inactive since 2011 but you never know it may still be compatible with newer versions of Windows but after messing around for a while I had to give up as I couldn't find a version of it that would work with Windows 10.. So I started looking for another solution and I did find one it's called vJoy and it looks like it was initially meant as a replacement for PPJoy so I started making a test program with it and I ended up making this..
Silky Smooth
If you'll ignore the incorrectly looped GIF then this is pretty nice so I couldn't help but include this in the application. You can use it with the -t
argument.
I have to decide what to use on the Server side for reading joystick input and I found this neat little library from drewnoakes called joystick. The name is pretty self explanatory and the library is basically a wrapper around /dev/input/js*
so it's pretty easy to use. This also means that any joystick that maps to /dev/input/js*
can be used with this which might even be a Bluetooth Joysticks so this application can technically convert BT Joysticks into WiFi Joysticks. Neat.
Now we can move on to the protocol which has to be used. There were only two options I could go with:
- TCP - Slower, Ensures delivery of every packet
- UDP - Faster, Packets may or may not be delivered
Initially I was thinking of using UDP because it is used for real-time applications such as music and video as there is no overhead from checking if the other side actually recieved the data. While missing packets in music/video may result in slight distortion in this case the stakes are much higher as here missing a packet means a move isn't played out that may be either pressing a button or moving a stick which can potentially change the outcome of an entire game. Consequently, I had to go with TCP.
Now, I needed to decide what network libraries to use. This was pretty easy as I just selected what was natively provided by the Operating System. That is WinSock2 incase of Windows and Unix TCP Sockets incase of Linux. There's not much more to go over in this category.
Next I was thinking how I'm going to encode the packets. At first I was thinking of a pretty lazy solution of just sending over all of the Joystick data every single second I calculated a single packet of this kind to be 59 bytes so it didn't seem like the a good idea now. So I thought of just sending a packet whenever a change was detected but on further thought it didn't seem like the best solution either so I thought of sending over just the changes in the state when a change was detected. I was pretty sure this was the best solution as a change descriptor packet can be 9 bytes max.
The sizes of the packet and when they're sent
Lastly, I needed to think of something to store settings in as manually inputting the IP of the server every single time is pretty annoying so I decided to use JSON here and create a pretty basic settings.json. I use nlohmann/json for parsing the JSON. I'll discuss the list of settings later.
Stack:
Client
- vJoy - Creating + using virtual Joystick devices
- WinSock2 - Using the TCP protocol for recieving data from the Server
- nlohmann/json - Reading parameters from settings.json
Server
- drewnoakes/joystick - Reading input from the Joystick
- Unix TCP Sockets - Using the TCP protocol for sending data to the Client
- nlohmann/json - Reading parameters from settings.json
Server and Client architecture
That's it for now. You'll have to wait for part 2 for the rest.
Thanks for reading! Clap Clap