# OpenPrepPad - Pleasant Programmer

# OpenPrepPad

Posted: 2017-01-15 | More posts about hardware bluetooth

Smart electronics and IoT (Internet of Things) are all the rage these days. You have a lot of companies sprout up trying to make the next big thing, which also leads to a lot of failures big and small. Pebble, the maker of my smartwatch, got bought out by Fitbit recently. This left watch owners without any official support, but thankfully, community members stepped up to continue maintaining it.

Another casualty of the IoT boom was the Orange Chef Prep Pad. It’s a bluetooth connected weighing scale to make it easy to track your calories and carb/fat/protein intake. My dad bought it last year only to find out that the app was incredibly buggy. The search function doesn’t work which makes the whole thing practically useless. I also found out later that you can’t even download the app to use the scale anymore.

Note I just found out as I was writing this post that it may get supported by another company.

So the app is useless, but at least you can use it as a scale, right?

Nope. The device has no display whatsoever. The only controls on it are the on/off button and a green LED that isn’t even that useful at telling you whether it’s on or not. At this point, it’s just a giant paperweight.

## Reverse Engineering

Since I essentially had nothing to lose, I tried poking at the thing to figure out how it works. I didn’t really have experience with bluetooth besides trying to get my bluetooth mouse connected on Linux. The main thing I used then was `bluetoothctl` which is essentially a CLI for managing bluetooth devices so I started there.

I started up `bluetoothctl` and turned on the Prep Pad. And it showed up!

    [bluetooth]# power on
    [CHG] Controller ... Class: 0x00010c
    Changing power on succeeded
    [CHG] Controller ... Powered: yes
    [bluetooth]# scan on
    Discovery started
    [CHG] Device 1C:BA:8C:21:7C:BB RSSI: -51
    [CHG] Device 1C:BA:8C:21:7C:BB Name: CHSLEEV_00
    [CHG] Device 1C:BA:8C:21:7C:BB Alias: CHSLEEV_00

I then connected to it, which was surprisingly easy.

    [bluetooth]# connect 1C:BA:8C:21:7C:BB
    Attempting to connect to 1C:BA:8C:21:7C:BB
    [CHG] Device 1C:BA:8C:21:7C:BB Connected: yes
    [CHG] Device 1C:BA:8C:21:7C:BB Name: CH BTScale_00
    [CHG] Device 1C:BA:8C:21:7C:BB Alias: CH BTScale_00

Now normally, when you turn the device on, the green light flashes occasionally. Once I connected to it, the green light stayed on permanently. Clearly, I was making progress. A lot of services were also discovered but I had no idea what those things were at that point.

After a lot of poking around, I could check the general device information. You could get the hardware, software and firmware version. There’s also the device serial number which was nowhere on the actual physical device.

    [CHSLEEV_00]# select-attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0010/char0017
    [CH BTScale_00:/service0010/char0017]# attribute-info
    Characteristic - Firmware Revision String
    	UUID: 00002a26-0000-1000-8000-00805f9b34fb
    	Service: /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0010
    	Value: 0x31
    	Value: 0x2e
    	Value: 0x31
    	Value: 0x33
    	Value: 0x41
    	Value: 0x00
    	Flags: read
    [CH BTScale_00:/service0010/char0017]# read
    Attempting to read /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0010/char0017
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0010/char0017 Value: 0x31
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0010/char0017 Value: 0x2e
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0010/char0017 Value: 0x31
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0010/char0017 Value: 0x33
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0010/char0017 Value: 0x41
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0010/char0017 Value: 0x00
      31 2e 31 33 41 00                                1.13A.
    [CH BTScale_00:/service0010/char0017]#

There was also a service which contained Accel Enable, Accel Range, Accel X-Coordinate, Accel Y-Coordinate, and Accel Z-Coordinate. I guess it stands for accelerometer, which is probably what it uses to weigh things.

    [CHSLEEV_00]# select-attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char0024/desc0026
    [CH BTScale_00:/service0023/char0024/desc0026]# read
    Attempting to read /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char0024/desc0026
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char0024/desc0026 Value: 0x41
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char0024/desc0026 Value: 0x63
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char0024/desc0026 Value: 0x63
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char0024/desc0026 Value: 0x65
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char0024/desc0026 Value: 0x6c
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char0024/desc0026 Value: 0x20
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char0024/desc0026 Value: 0x45
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char0024/desc0026 Value: 0x6e
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char0024/desc0026 Value: 0x61
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char0024/desc0026 Value: 0x62
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char0024/desc0026 Value: 0x6c
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char0024/desc0026 Value: 0x65
      41 63 63 65 6c 20 45 6e 61 62 6c 65              Accel Enable

I couldn’t read from any of the Accel Coordinates. It kept saying permission denied. I could however, notify on them. But that didn’t yield anything as well. What I could read was Accel Enable, which was set to 00. I guess that means it was off. After writing 01 to Accel Enable, I found I could get values out of Accel X-Coordinate! Also, the green LED which was permanently on turned off.

    [CHSLEEV_00]# select-attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char0024
    [CH BTScale_00:/service0023/char0024]# write 01
    Attempting to write /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char0024
    [CH BTScale_00:/service0023/char0024]# select-attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char002a
    [CH BTScale_00:/service0023/char002a]# notify on
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char002a Notifying: yes
    Notify started
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char002a Value: 0x5b
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char002a Value: 0xa3
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char002a Value: 0x02
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char002a Value: 0x00
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char002a Value: 0x55
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char002a Value: 0xa3
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char002a Value: 0x02
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char002a Value: 0x00
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char002a Value: 0x59
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char002a Value: 0xa3
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char002a Value: 0x02
    [CHG] Attribute /org/bluez/hci0/dev_1C_BA_8C_21_7C_BB/service0023/char002a Value: 0x00

I tried pressing the scale down a few times, and the values changed accordingly. Now, I just had to figure out how to convert the values into grams. It looked like the values were 32-bit integers sent as 4 bytes. In the above example it would be `0x0002a35b`, `0x0002a355`, `0x0002a359` or 172891, 172855, 172899. The values also decrease as you exert more effort on the scale. So assuming you take the initial value as tare, you simply subtract any succeeding value from that tare and you get the “weight”.

The values I got didn’t seem to be in grams though. After weighing some things on an actual scale and comparing the values I got, I found I can just divide the values by 14 and get something in grams. That 14 is entirely a magic number though and I have no idea whether other Prep Pad’s would have the same constant.

## OpenPrepPad

With all that figured out, I went ahead and made a simple CLI application to interface with the Prep Pad. Ironically, node was the simplest thing I found that had nice bluetooth library support so that’s what I wrote it in. I also added most of the technical details in the README for that as well.

While this is all well and cool, I doubt the intersection of Linux users and people who got ripped off bought the Prep Pad is anyone besides me. In light of that, I’m in the process of making a React Native version of the app, but that’s still a work in progress. Who knows, if the new owners of Prep Pad are good, I might not even need to finish it.