# Uplift Desk Automation

## Message Syntax

### Transmit

A transmitted message has the following syntax.

```
0xF1, 0xF1, <cmd>, 0x00, <crc>, 0x7E

```

- `0xF1, 0xF1` indicates the message start
- `cmd` is one of: 
    - `0x01` - Up
    - `0x02` - Down
    - `0x03` - Save preset 1
    - `0x04` - Save preset 2
    - `0x05` - Recall preset 1
    - `0x06` - Recall preset 2
    - `0x07` - Sync
    - `0x25` - Save preset 3
    - `0x26` - Save preset 4
    - `0x27` - Recall preset 3
    - `0x28` - Recall preset 4
    - `0x2B` - Stop
- `crc` is the sum of the bytes at index 2 and 3.
- `0x7E` indicates the end of message.

### Receive

A received message has the following syntax.

```
0xF2, 0xF2, <cmd>, <len>, <data...>, 0x0F, <crc>, 0x7E

```

- `0xF2, 0xF2` indicates the message start
- `cmd` is one of: 
    - `0x01` - Height value
    - `0x25` - Preset 1 height
    - `0x26` - Preset 2 height
    - `0x27` - Preset 3 height
    - `0x28` - Preset 4 height
- `len` indicates how many messages will be sent next, excluding the CRC and EOT.
- `data` will contain the incoming data values, explained for height readings below.
- `0x0F` - Unknown
- `crc` will be the sum of bytes at index 2 up to the CRC.
- `0x7E` indicates the end of message.

#### Example: Received Height Reading

When a new height value comes in, the message will look something like this:

```
0xF2, 0xF2, 0x01, 0x03, 0x01, 0x1B, 0x0F, 0x2F, 0x7E

```

In this case, the desk was at 28.3". Here is how we can calculate that.

1. First off, the command is `0x01`, so we know we're about to receive height data.
2. The next byte tells us to listen for 3 data bytes.
3. The relevant data comes in as `0x01, 0x1B`. This will be converted to a height value later. (Unclear what `0x2F` does here)
4. Then, we add all of the previous bytes (other than the header) to verify the CRC is correct.  
    `0x01 + 0x03 + 0x01 + 0x1B + 0x0F = 0x2F`
5. The actual height is a two-byte word, so the first number needs to be bitshifted. In this example, we received `0x01, 0x1B`, so the height calculation looks like: `0x01 << 8 | 0x1B = 283`.
6. Divide the received value by 10 to convert to inches. The result is `283 / 10.0 = 28.3in`.

#### Preset Heights

A sync request will get a response with cmd `0x25`, `0x26`, `0x27`, `0x28`, then a regular `0x01` height. The 0x01 value is understood, but the preset height values are not yet understood. There is a two-word response, and the words change with the saved height value. The second word seems to be a decimal. I have not yet determined how to parse these into the stored heights.

Here is a table of example values. For heights that are the same, I would slightly adjust the table height and save again. The changed values suggest these are more specific than inches.

<table id="bkmrk-height-data%5B4%5D-data%5B"><thead><tr><th>Height</th><th>`data[4]`</th><th>`data[5]`</th></tr></thead><tbody><tr><td>25.3</td><td>20</td><td>5</td></tr><tr><td>25.3</td><td>20</td><td>8</td></tr><tr><td>25.3</td><td>20</td><td>11</td></tr><tr><td>25.3</td><td>20</td><td>54</td></tr><tr><td>28.3</td><td>25</td><td>62</td></tr><tr><td>28.3</td><td>25</td><td>67</td></tr><tr><td>28.3</td><td>25</td><td>82</td></tr><tr><td>38.?</td><td>42</td><td>207</td></tr><tr><td>39.9</td><td>45</td><td>153</td></tr><tr><td>39.9</td><td>45</td><td>156</td></tr><tr><td>40.0</td><td>45</td><td>168</td></tr><tr><td>42.4</td><td>50</td><td>7</td></tr><tr><td>42.8</td><td>50</td><td>188</td></tr><tr><td>42.9</td><td>50</td><td>231</td></tr><tr><td>43.0</td><td>51</td><td>8</td></tr><tr><td>43.1</td><td>51</td><td>27</td></tr><tr><td>43.2</td><td>51</td><td>104</td></tr><tr><td>50.8</td><td>64</td><td>161</td></tr></tbody></table>

## References

### Hardware

1. ["2ANKDJCP35NBLT Bluetooth Box by ZHEJIANG JIECANG LINEAR MOTION TECHNOLOGY CO., LTD"](https://fccid.io/2ANKDJCP35NBLT). (2018, January 25). FCC ID. Retrieved January 19, 2021.
2. [Jiecang Bluetooth Dongle Product Listing](https://en.jiecang.com/product/131.html). Retrieved January 19, 2021.

#### Images from /u/deadman96385

1. [https://imgur.com/a/MUbXwnM](https://imgur.com/a/MUbXwnM)
2. [https://i.imgur.com/DyMf3Ee.jpg](https://i.imgur.com/DyMf3Ee.jpg)
3. [https://i.imgur.com/KtsWpVQ.jpg](https://i.imgur.com/KtsWpVQ.jpg)
4. [https://i.imgur.com/BS62C1E.jpg](https://i.imgur.com/BS62C1E.jpg)
5. [https://i.imgur.com/woWoQMe.jpg](https://i.imgur.com/woWoQMe.jpg)
6. [https://i.imgur.com/Lta5Nab.jpg](https://i.imgur.com/Lta5Nab.jpg)

### Software

1. Justintout. (2020, April 16). GitHub - ["justintout/uplift-reconnect: A Flutter app to control Uplift desks with Uplift Connect BLE modules installed"](https://github.com/justintout/uplift-reconnect). GitHub. Retrieved January 19, 2021.
2. Deadman96385. (2020, March 6). ["uplift\_desk\_controller\_app/BluetoothHandler.java at a58bcadfb77ac993751758465f1cf20f71d6d8fd · deadman96385/uplift\_desk\_controller\_app"](https://github.com/deadman96385/uplift_desk_controller_app/blob/a58bcadfb77ac993751758465f1cf20f71d6d8fd/app/src/main/java/com/deadman/uplift/BluetoothHandler.java). GitHub. Retrieved January 23, 2021.
3. Phord. (2021, August 12). ["phord/Jarvis: Hacking the Jarvis standup desk from fully.com for home automation using an ESP8266 arduino interface"](https://github.com/phord/Jarvis). GitHub. Retrieved December 5, 2021.
4. Ramot, Y. (2015, February 4). ["UpLift Desk wifi link"](https://hackaday.io/project/4173-uplift-desk-wifi-link). Hackaday.io.
5. Horacek, L. (2019, April 14). ["Standing desk remote control"](https://hackaday.io/project/164931-standing-desk-remote-control). Hackaday.io.
6. Hunleth, F. (2019, January 18). ["Nerves At Home: Controlling a Desk"](https://embedded-elixir.com/post/2019-01-18-nerves-at-home-desk-controller/). Embedded Elixir. Retrieved January 2021.