<!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. 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&rsquo;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&rsquo;t work which makes the whole
thing practically useless. I also found out later that you can&rsquo;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&rsquo;t even that useful at telling you whether
it&rsquo;s on or not. At this point, it&rsquo;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&rsquo;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 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 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&rsquo;s also the device
serial 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-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 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&rsquo;t read from any of the Accel Coordinates. It kept saying permission
denied. I could however, notify on them. But that didn&rsquo;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 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 &ldquo;weight&rdquo;.</p>
<p>The values I got didn&rsquo;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&rsquo;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&rsquo;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&rsquo;m in the process of making a React Native version of the app,
but that&rsquo;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">&larr; Previous post</a>
				</li>
				
				
				<li class="next">
					<a href="/posts/audventure.html" rel="next" title="Audventure">Next post &rarr;</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> &copy; 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>