swift-desktopia: Smarten up your desk

In 2022, I bought my height-adjustable desk that I still use and enjoy every day. One feature that really sold me on it was the USB connection to the desk’s controller. I wanted the ability to integrate it into my smart home setup: moving it remotely, querying its current height, and building logic on top of that information.

It felt like a promise that I would be able to control it regardless of its vendor — and spoiler alert: that is exactly what happened.

Ergotopia themselves provide a desktop app for the Desktopia Pro X, however, it seems that development has not continued since the beginning of 2023. Since it is an Electron app, I was able to easily read the source and use that as a base to reverse engineer the protocol. I’ve had my desk smart-controlled since then but never got around to publishing the results.

Introducing swift-desktopia

Available now in version 1.0.0, swift-desktopia is a Swift library that allows you to control your Desktopia Pro X desk directly from your computer. I use this library in a small HTTP server on a Raspberry Pi Zero 2W to expose commands on the network, making my desk smart. This way, I can even control it using Siri.

There are a few commands that the desk understands:

  • Moving up or down
  • Moving to memory positions 1, 2, or 3
  • Saving the current height to memory position 1 and 2
  • Showing the current status on the desk controller display
  • Sending a heartbeat signal

The library can take care of sending the heartbeat signal for you. This means that the controller’s display will stay on the entire time. Personally, I perfer disabling this which in turn means that commands might have to be sent twice if the controller needs to wake up before.

Controlling the desk height was my main concern. Since the “move up” and “move down” commands only move it for an indeterminate height and have to be reissued to continue moving, dynamically setting a height is a bit tricky. While it is technically possible to dynamically target an exact height, doing so reliably would require a fairly involved control algorithm to avoid stuttering and overshooting. For now, I’ve intentionally kept this out of scope.

Instead, I recommend you stick to the preset memory positions. The controller will do the same as when you press the “1”, “2” or “3” buttons on the hardware, and move the desk to the preset position automatically for you.

Example usage

Please refer to the documentation on how to get started with swift-desktopia. The connection via USB is a serial connection, so you need to provide the serial port name to the library for now. You can also search automatically for a serial port with the vendor ID 1A86.

The following example shows how to connect to the desk and move it to a preset memory position.

1
2
3
4
5
6
import DesktopiaProX

let desk = Desk(port: "/dev/cu.usbserial-123", keepAlive: true)
try await desk.connect()

try await desk.send(command: .moveToMemoryPosition1)

After sending this command, the desk will move into memory position 1.

Reading events from the desk

The desk will also report its current height while it is moving. This also applies if the height is changed by using the control panel on the front of the desk.

You can read the events sent by the desk in an AsyncStream<Command>:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import DesktopiaProX

let desk = Desk(port: "/dev/cu.usbserial-123", keepAlive: true)
try await desk.connect()

let stream = try await desk.readCommands()

for await command in stream {
  switch command {
    case .desk(.heightInfo):
      // you can interpret the desk height yourself, if you like,
      // by reading from `command.data` here.
      // However, the library already parses the height commands for you,
      // giving you direct access to the height:
      print("Current height: \(await desk.height)")
  }
}

Documenting the protocol

The library is a very specific implementation of the protocol. I am not even sure, how many Desktopia Pro X owners there are out there that actually have the need to control their desk via a USB connection. It seems that the controller is still, even after years, the only one on the market that offers this type of smart connection.

I personally find this a shame and missed opportunity, since you could do so many things with it. Apart from Shortcuts and Siri, just think of Home Assistant and its vast ecosystem.

To enable further development and experimentation, I’m considering documenting the underlying protocol in an interchange format that can be reused across languages. One promising option is Kaitai Struct, which would make it much easier for others to build their own tooling on top of the desk’s protocol.

If that is something you’d be interested in, or if you’re already experimenting with similar hardware integrations, I’d love to hear from you or see what you build.