| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 | <!DOCTYPE html><html lang="en-us"><head>	<meta charset="utf-8">	<meta name="generator" content="Hugo 0.69.2" />	<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 class="twitter">					<a href="http://twitter.com/pleasantprog">@pleasantprog</a>				</li>				<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. Youhave a lot of companies sprout up trying to make the next big thing, which alsoleads 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 officialsupport, but thankfully, community members <a href="http://rebble.io/">stepped up</a> to continuemaintaining 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 abluetooth connected weighing scale to make it easy to track your calories andcarb/fat/protein intake. My dad bought it last year only to find out that theapp was incredibly buggy. The search function doesn’t work which makes the wholething practically useless. I also found out later that you can’t even downloadthe 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 supportedby <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 theon/off button and a green LED that isn’t even that useful at telling you whetherit’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 figureout how it works. I didn’t really have experience with bluetooth besides tryingto 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 Istarted there.</p><p>I started up <code>bluetoothctl</code> and turned on the Prep Pad. And it showed up!</p><div class="highlight"><pre 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: 0x00010cChanging power on succeeded[CHG] Controller ... Powered: yes[bluetooth]# scan onDiscovery 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 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:BBAttempting 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 wasmaking progress. A lot of services were also discovered but I had no idea whatthose things were at that point.</p><p>After a lot of poking around, I could check the general device information. Youcould get the hardware, software and firmware version. There’s also the deviceserial number which was nowhere on the actual physical device.</p><div class="highlight"><pre 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-infoCharacteristic - 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]# readAttempting 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, AccelX-Coordinate, Accel Y-Coordinate, and Accel Z-Coordinate. I guess it stands foraccelerometer, which is probably what it uses to weigh things.</p><div class="highlight"><pre 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]# readAttempting 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 permissiondenied. 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 itwas off. After writing 01 to Accel Enable, I found I could get values out ofAccel X-Coordinate! Also, the green LED which was permanently on turned off.</p><div class="highlight"><pre 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 01Attempting 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: yesNotify 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 lookedlike the values were 32-bit integers sent as 4 bytes. In the above example itwould be <code>0x0002a35b</code>, <code>0x0002a355</code>, <code>0x0002a359</code> or 172891, 172855, 172899. Thevalues also decrease as you exert more effort on the scale. So assuming you takethe 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 thingson an actual scale and comparing the values I got, I found I can just divide thevalues by 14 and get something in grams. That 14 is entirely a magic numberthough 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 foundthat had <a href="https://github.com/sandeepmistry/noble">nice bluetooth library support</a> so that’s what I wrote it in. Ialso 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 andpeople who <!-- raw HTML omitted -->got ripped off<!-- raw HTML omitted --> bought the Prep Pad is anyone besides me. Inlight 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 Padare 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> © 2020 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>
 |