123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- <!DOCTYPE html>
- <html lang="en-us">
- <head>
- <meta charset="utf-8">
- <meta name="generator" content="Hugo 0.92.0" />
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <link rel="stylesheet" href="/assets/css/theme.css">
- <link rel="alternate" href="/rss.xml" type="application/rss+xml" title="Pleasant Programmer">
- <script type="text/javascript" src="//use.typekit.net/iwm5axp.js"></script>
- <script type="text/javascript">try{Typekit.load();}catch(e){}</script>
- <title>OpenPrepPad - Pleasant Programmer</title>
- </head>
- <body>
- <header id="header" role="banner">
- <div id="thomas">
- <img src="/assets/img/thomas.gif" alt="DJ THOMAS IN DA HAUS">
- <img src="/assets/img/thomas.png" alt="Pleasant Programmer">
- </div>
- <h1 class="site-title"><a href="/">Pleasant Programmer</a></h1>
- <nav id="menu" role="navigation">
- <ul>
- <li><a href="/pages/projects.html">projects</a></li>
- <li><a href="/posts.html">archives</a></li>
- <li><a href="/tags.html">tags</a></li>
- <li><a href="/rss.xml">rss</a></li>
- </ul>
- </nav>
- </header>
- <div id="container">
- <main id="content" role="main">
- <article itemscope itemtype="http://schema.org/BlogPosting">
- <h1 class="p-name entry-title" itemprop="headline name">
- <a href="/posts/openpreppad.html">OpenPrepPad</a></h1>
- <small>
- <span class="dateline">Posted: <time itemprop="datePublished" datetime="2017-01-15">2017-01-15</time></span>
- | More posts about
-
- <a class="tag p-category" href="/tags/hardware.html" rel="tag">
- hardware
- </a>
-
- <a class="tag p-category" href="/tags/bluetooth.html" rel="tag">
- bluetooth
- </a>
-
- </small>
- <div class="e-content entry-content" itemprop="entry-text">
- <p>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 <a href="http://rebble.io/">stepped up</a> to continue
- maintaining it.</p>
- <p>Another casualty of the IoT boom was the <a href="http://theorangechef.com/">Orange Chef</a> <a href="https://www.amazon.com/Orange-Chef-Smart-Scale-Silver/dp/B00KFW8L90">Prep Pad</a>. 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.</p>
- <p><strong>Note</strong> I just found out as I was writing this post that it <em>may</em> get supported
- by <a href="http://www.prnewswire.com/news-releases/perfect-company-acquires-orange-chefs-prep-pad-related-ip-continues-momentum-in-the-connected-kitchen-300383178.html">another company</a>.</p>
- <p>So the app is useless, but at least you can use it as a scale, right?</p>
- <p><img src="/galleries/openpreppad/preppad.jpg" alt="Prep Pad"></p>
- <p>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.</p>
- <h2 id="reverse-engineering">Reverse Engineering</h2>
- <p>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
- <code>bluetoothctl</code> which is essentially a CLI for managing bluetooth devices so I
- started there.</p>
- <p>I started up <code>bluetoothctl</code> and turned on the Prep Pad. And it showed up!</p>
- <div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">[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
- </code></pre></div><p>I then connected to it, which was surprisingly easy.</p>
- <div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">[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
- </code></pre></div><p>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.</p>
- <p>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.</p>
- <div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">[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]#
- </code></pre></div><p>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.</p>
- <div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">[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
- </code></pre></div><p>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 <em>could</em> 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.</p>
- <div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">[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
- </code></pre></div><p>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 <code>0x0002a35b</code>, <code>0x0002a355</code>, <code>0x0002a359</code> or 172891, 172855, 172899. The
- values also decrease as you exert more effort on the scale. So assuming you take
- the initial value as <em>tare</em>, you simply subtract any succeeding value from that
- <em>tare</em> and you get the “weight”.</p>
- <p>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.</p>
- <h2 id="openpreppad">OpenPrepPad</h2>
- <p>With all that figured out, I went ahead and made a <a href="https://github.com/thatsmydoing/openpreppad">simple CLI application</a>
- to interface with the Prep Pad. Ironically, node was the simplest thing I found
- that had <a href="https://github.com/sandeepmistry/noble">nice bluetooth library support</a> so that’s what I wrote it in. I
- also added most of the technical details in the README for that as well.</p>
- <p>While this is all well and cool, I doubt the intersection of Linux users and
- people who <!-- raw HTML omitted -->got ripped off<!-- raw HTML omitted --> 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.</p>
- </div>
- <aside class="postpromonav">
- <nav>
- <ul class="pager clearfix">
-
- <li class="previous">
- <a href="/posts/haproxy-charset.html" rel="prev" title="Haproxy Charset">← Previous post</a>
- </li>
-
-
- <li class="next">
- <a href="/posts/audventure.html" rel="next" title="Audventure">Next post →</a>
- </li>
-
- </ul>
- </nav>
- </aside>
- <section class="comments">
- <script
- data-isso="https://isso.pleasantprogrammer.com/"
- data-isso-require-author="true"
- data-isso-vote="false"
- src="https://isso.pleasantprogrammer.com/js/embed.min.js">
- </script>
- <section id="isso-thread"></section>
- </section>
- </article>
- </main>
- <footer id="footer" role="contentinfo">
- <p>
- <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/deed.en_US">
- <img alt="CC-BY-SA" style="border-width:0" src="https://licensebuttons.net/l/by-sa/3.0/80x15.png">
- </a> © 2022 Thomas Dy - Powered by <a href="http://gohugo.io">Hugo</a></p>
- </footer>
- </div>
- <script src="/assets/js/konami.js"></script>
- <script>
- var easter_egg = new Konami();
- easter_egg.code = function() {
- var el = document.getElementById('thomas');
- if(el.className == "whoa") {
- el.className = "";
- }
- else {
- el.className = "whoa";
- }
- document.body.scrollTop = document.documentElement.scrollTop = 0;
- }
- easter_egg.load();
- </script>
- </body>
- </html>
|