I purchased a Logitech/Saitek [PZ55 Flight Switch Panel](https://www.saitek.com/uk/prod-bak/switch.html) recently and set it up so I could control my computer: It can now do the following: * Start my gaming PC via Wake-On-Lan. * Open Task Manager. * Open explorer.exe. * Start Firefox, Discord, Steam, Spotify, Blender. * Start my favourite game. * Start a Chrome session with Special Business™ tabs already open. ## Switch Controller The switch is connected to a Raspberry Pi 4B which runs a Python script as a SystemD service. A prototype version of the script worked as follows: ```python import hid import requests vid = 0x06a3 pid = 0x0d67 with hid.Device(vid, pid) as h: while True: fip = h.read(3) print(fip[0]) if fip[0] == 4: x = requests.get('http://10.0.0.100:5120/') ``` Using the [`pyhidapi`](https://pypi.org/project/hid/) package, we open a connection to the PZ55 Flight Switch Panel and keep reading every time a new [USB HID event is emitted]({{< relref "/content/dev/2022-12-17-saitek-pz55.md" >}}). If a particular switch is set, it'll call out to an API endpoint on a local network web server. A more recent verison of the code uses a global state, so that flicking a switch either way will call out to the same endpoint, and also added a bunch of different endpoints. ## Receiving Webserver I set up a very basic C# ASP.NET web app, with a controller that listens for specific endpoints (the ones used by the switch). Depending on the endpoint selected, it calls out to [PSExec](https://learn.microsoft.com/en-us/sysinternals/downloads/psexec) and tells it to run that particular application. An example controller: ```c# public string Inquisitor() { ExecuteCommand.Run("PsExec.exe -d -i $(query session | select -skip 2 | %{$_.Split(' ',[System.StringSplitOptions]::RemoveEmptyEntries)} | select -skip 2)[0] explorer 'steam://rungameid/527430'"); return "Starting Inquisitor: Martyr."; } ``` In this case, `ExecuteCommand.Run()` is a helper function I've created that starts a process, runs a background PowerShell prompt, and then executes that command through it: ```c# public static void Run(string Command) { ProcessStartInfo ProcessInfo; Process Process; ProcessInfo = new ProcessStartInfo("powershell.exe", "/c " + Command); Process = Process.Start(ProcessInfo); } ``` That PowerShell command gets the current active sessions, finds the first user session, and then runs PSExec against it so that we can enable GUI applications remotely. It's not super complicated, it's very hacky, but it works and it's designed for use only on my home setup. *Do not do something like this in an official environment.* I used [NSSM](https://nssm.cc/) to install it as a Windows Service that logs on with my account when I start up the PC and gives it Administrator level permissions to allow it to start applications in my active desktop. ## Why? The modern personal computer usually consists of a keyboard with a bunch of buttons and a mouse or trackpad with a couple more. But computers used to be all about the switches. Take for examble, the venerable PDP-11/70 front panel below: ![The front panel of a PDP-11/70 computer with rows of blinkenlights, a key to switch it on or off, and a row of about 30 switches to handle the output and debugging of the machine. It's in a beautiful mauve, purple, and orange colour scheme.](/img/2022-12-23-switch-panel-pdp-11-70.jpg) But what if we added physical switches to personal computing? I love the idea of a console like the Serenity from [Firefly](https://www.imdb.com/title/tt0303461/): ![A handsome Malcolm Reynolds played by Nathan Fillion sitting at the control seat, behind him a dizzying array of switches and buttons and controls to pilot his spacecraft.](/img/2022-12-23-switch-panel-serenity-firefly.jpg) Or the complexity of aircraft control panels like the A-10C Warthog: ![The cockpit of an A-10C Warthog close air support plane, showing a joystick and an incredible number of dials, switches, buttons, and displays.](/img/2022-12-23-switch-panel-a10c.png) I know what I'm doing isn't super practical when all of the functionality is available in menus accessible via my keyboard or mouse, but I think [personal computing should be more personal]({{< relref "/content/personal/2022-12-24-personal-computing-should-be-personal.md" >}}), more fun, and I'm aiming to enable that for myself.