lupyuen.org/articles/connect-stm32-blue-pill-to-esp8266-with-apache-mynewt.html

2366 lines
No EOL
183 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="/_static/css/banner-styles.css?v=bsmaklHF" />
<link rel="stylesheet" type="text/css" href="/_static/css/iconochive.css?v=qtvMKcIJ" />
<link rel="canonical" href="https://lupyuen.org/articles/connect-stm32-blue-pill-to-esp8266-with-apache-mynewt.html" />
<!-- End Wayback Rewrite JS Include -->
<title data-rh="true">Connect STM32 Blue Pill to ESP8266 with Apache Mynewt</title>
<meta data-rh="true" charset="utf-8" />
<meta data-rh="true" name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" />
<meta data-rh="true" name="theme-color" content="#000000" />
<meta data-rh="true" property="og:type" content="article" />
<meta data-rh="true" property="article:published_time" content="2019-07-25T18:17:36.155Z" />
<meta data-rh="true" name="title" content="Connect STM32 Blue Pill to ESP8266 with Apache Mynewt" />
<meta data-rh="true" property="og:title" content="Connect STM32 Blue Pill to ESP8266 with Apache Mynewt" />
<meta data-rh="true" property="twitter:title" content="Connect STM32 Blue Pill to ESP8266 with Apache Mynewt" />
<meta data-rh="true" name="description"
content="Send sensor data to a CoAP server and perform WiFi Geolocation with ESP8266" />
<meta data-rh="true" property="og:description"
content="Send sensor data to a CoAP server and perform WiFi Geolocation with ESP8266" />
<meta data-rh="true" property="twitter:description"
content="Send sensor data to a CoAP server and perform WiFi Geolocation with ESP8266" />
<meta data-rh="true" name="twitter:card" content="summary_large_image" />
<meta data-rh="true" name="twitter:creator" content="@MisterTechBlog" />
<meta data-rh="true" name="author" content="Lup Yuen Lee 李立源" />
<meta data-rh="true" name="robots" content="index,follow" />
<meta data-rh="true" name="referrer" content="unsafe-url" />
<meta data-rh="true" name="twitter:label1" value="Reading time" />
<meta data-rh="true" name="twitter:data1" value="29 min read" />
<meta property="og:image"
content="https://lupyuen.github.io/images/legacy2/h1.png">
<!-- Begin scripts/rustdoc-header.html: Header for Custom Markdown files processed by rustdoc, like chip8.md -->
<link rel="alternate" type="application/rss+xml" title="RSS Feed for lupyuen" href="/rss.xml" />
<link rel="stylesheet" type="text/css" href="../normalize.css">
<link rel="stylesheet" type="text/css" href="../rustdoc.css" id="mainThemeStyle">
<link rel="stylesheet" type="text/css" href="../light.css" id="themeStyle">
<link rel="stylesheet" type="text/css" href="../prism.css">
<script src="../storage.js"></script><noscript>
<link rel="stylesheet" href="../noscript.css"></noscript>
<link rel="shortcut icon" href="../favicon.ico">
<style type="text/css">
#crate-search {
background-image: url("../down-arrow.svg");
}
a {
color: #77d;
}
</style>
<!-- End scripts/rustdoc-header.html -->
</head>
<body>
<div id="root">
<div class="a b c">
<article>
<section class="cj ck cl cm ak cn ce n co"></section><span class="r"></span>
<div>
<div class="cp u cq cr cs ct"></div>
<section class="cu cv cw cx cy">
<div class="cz">
<div class="n p">
<div class="da db dc dd de df ag dg ah dh aj ak">
<div class="figure dj dk dl dm dn cz do dp paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h1.png" /></p>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<div>
<div id="8b15" class="ei ej ek bk el b em en eo ep eq er es">
<h1 class="el b em et ek">Connect STM32 Blue Pill to ESP8266 with Apache Mynewt</h1>
</div>
<div class="eu">
<div class="n ev ew ex ey">
<div class="o n">
<div><a rel="noopener"
href="https://lupyuen.github.io">
<div class="ds ez fa">
<div class="bs n fb o p cp fc fd fe ff fg ct"></div>
</div>
</a></div>
<div class="fi ak r">
<div class="n">
<div style="flex:1"><span class="bj b bk bl bm bn r ek q">
<div class="fj n o fk"><span class="bj fl fm bl dx fn fo fp fq fr ek"><a
class="at au av aw ax ay az ba bb bc fs bf bg bh bi" rel="noopener"
href="https://lupyuen.github.io">Lup
Yuen Lee 李立源</a></span>
</div>
</span></div>
</div><span class="bj b bk bl bm bn r bo bp"><span class="bj fl fm bl dx fn fo fp fq fr bo">
<div><a class="at au av aw ax ay az ba bb bc fs bf bg bh bi" rel="noopener"
href="https://lupyuen.github.io/articles/connect-stm32-blue-pill-to-esp8266-with-apache-mynewt">
20 Apr 2019</a> <!-- -->·
<!-- -->
<!-- -->29
<!-- --> min read
</div>
</span></span>
</div>
</div>
</div>
</div>
</div>
<p id="79ce" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The <a
href="https://en.wikipedia.org/wiki/ESP8266"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">ESP8266 WiFi
module</strong></a> is a brilliant invention… It connects your microcontroller to the WiFi network
(and the internet) through simple <code class="eb hk hl hm hn b">AT</code> commands. Since it <strong
class="gt hj">sends and receives network packets on your behalf</strong> (UDP and TCP), creating IoT
gadgets will be so easy!</p>
<p id="f693" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">But building an embedded
application with ESP8266 can be challenging… We cant really be sure<strong class="gt hj"> when an
</strong><code class="eb hk hl hm hn b"><strong class="gt hj">AT</strong></code><strong class="gt hj">
command will complete</strong>. Maybe the server was slow in responding. Or the WiFi connection has
dropped and the module needs to reconnect.</p>
<p id="8c35" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Today well learn to solve this
problem with <a href="https://mynewt.apache.org/"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">Apache
Mynewt</strong></a>, a real-time embedded operating system. Well create an IoT application for <a
href="http://wiki.stm32duino.com/index.php?title=Blue_Pill"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">STM32 Blue
Pill</strong></a><strong class="gt hj"> </strong>that<strong class="gt hj"> multitasks the ESP8266
module</strong> with a <strong class="gt hj">temperature sensor</strong>. So while were waiting for
an ESP8266 command to complete, the application can continue to process the sensor data at regular
intervals.</p>
<p id="3466" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Like in the real world, our IoT
application will transmit sensor data to an IoT server, via the <a
href="https://en.wikipedia.org/wiki/Constrained_Application_Protocol"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong
class="gt hj">CoAP</strong></a> protocol, over the ESP8266 WiFi connection. Well also dig deeper
into WiFi networking… <em class="ho">Is it possible to compute your location accurately based on the
data scanned by the ESP8266 module?</em></p>
<p id="995e" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Youll be amazed how easy it is
to do WiFi Geolocation with ESP8266, once we have our simple CoAP application running. The <strong
class="gt hj">accuracy of WiFi Geolocation</strong> will startle you!</p>
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib ic id ie if ig paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h2.png" /></p>
<figcaption><p><em>Top to bottom: STM32 Blue Pill, ST-Link V2 USB
Adapter (compatible), ESP8266 WiFi Module. Connect Blue Pill to ST-Link V2 as shown at lower right.
The two yellow jumpers on Blue Pill should be connected as shown.</em></p></figcaption>
</div>
<p id="b77c" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Heres what we need for the
tutorial…</p>
<p id="7850" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">1<strong class="gt hj">STM32
Blue Pill</strong></p>
<blockquote class="in io ip">
<p id="4ff0" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://gist.github.com/lupyuen/5c7804c15a45abebfd5f567f0ada6c02"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Where to buy</a></p>
</blockquote>
<p id="1c31" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2<strong class="gt hj">ST-Link
V2 USB Adapter</strong> <br />(or compatible)</p>
<blockquote class="in io ip">
<p id="4719" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://gist.github.com/lupyuen/5c7804c15a45abebfd5f567f0ada6c02"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Where to buy</a></p>
</blockquote>
<p id="b79a" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">3<strong class="gt hj">ESP8266
WiFi Module</strong></p>
<blockquote class="in io ip">
<p id="aa6f" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://gist.github.com/lupyuen/5c7804c15a45abebfd5f567f0ada6c02"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Where to buy</a></p>
</blockquote>
<p id="c8b8" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Connect Blue Pill to ESP8266 as
follows…</p>
<div class="figure hq hr hs ht hu cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="da db dc dd de df ag dg ah dh aj ak">
<div class="figure hq hr hs ht hu cz do dp paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h3.png" /></p>
<figcaption><p><em>Connecting Blue Pill to ESP8266. Fritzing
File: <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/esp8266.fzz"
class="at cg hf hg hh hi" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/esp8266.fzz</a>
</em></p></figcaption>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib ic id ie if ig paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h4.jpeg" /></p>
<figcaption><p><em>Supersized STM32 Blue Pill with ESP8266 module
plugged in</em></p></figcaption>
</div>
<p id="01af" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The tutorial also works with <a
href="https://detail.tmall.com/item.htm?id=568676838958"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">this Supersized STM32 Blue
Pill</a> with ESP8266 module plugged in.</p>
<p id="62fe" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://youtu.be/YrKXdxB77Oc"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Watch the video</a> to see our
application in action, installed on a real Blue Pill.</p>
<p id="2adb" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Click <code
class="eb hk hl hm hn b"><strong class="gt hj">CC</strong></code> to display the annotations.</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="da db dc dd de df ag dg ah dh aj ak">
<div class="figure hq hr hs ht hu cz">
<div class="ea r ds">
<div class="iw r"><iframe
src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FYrKXdxB77Oc%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DYrKXdxB77Oc&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FYrKXdxB77Oc%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube"
allowfullscreen="" frameborder="0" height="480" width="854"
title="Apache Mynewt Debug on STM32 Blue Pill" class="cp t u dw ak" scrolling="auto"></iframe>
</div>
</div>
<figcaption><p><em>Our application running on Blue Pill,
reading the temperature sensor and sending to our CoAP server</em></p></figcaption>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<div class="figure hq hr hs ht hu cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
<blockquote class="in io ip">
<p id="ec92" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><em class="bk">💎 </em>Sections
marked with a diamond are meant for advanced developers. If youre new to embedded programming, you
may skip these sections</p>
</blockquote>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="4d12" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">Application Overview</h1>
<p id="55bc" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he"><em class="ho">(If you havent
read my introductory tutorial on Mynewt, </em><a class="at cg hf hg hh hi" target="_blank"
rel="noopener"
href="https://lupyuen.github.io/articles/create-your-iot-gadget-with-apache-mynewt-and-stm32-blue-pill"><em
class="ho">check it out here</em></a><em class="ho">)</em></p>
<p id="3d54" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Heres the complete source code
for the IoT application, libraries and drivers used in this tutorial…</p>
<div class="dj dk dl dm dn jz"><a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor?source=post_page-----7edceb9e3b8d----------------------"
rel="noopener nofollow">
<section class="kc cl cm ak ce n ar kd ke kf kg kh ki kj kk kl km kn ko kp kq kr">
<div class="ks n co p kt ku">
<h2 class="bj ji kv bl ek">
<div class="dx ka fo fp kb fr">lupyuen/stm32bluepill-mynewt-sensor</div>
</h2>
</div>
<div class="ky r">
<div class="kz r la lb lc ky ld le lf"></div>
</div>
</section>
</a></div>
<p id="a885" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Lets peek at the top-level
functions in <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/master/apps/my_sensor_app/src" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">apps/my_sensor_app/src</a></code>
to understand how this application will <strong class="gt hj">read Blue Pills internal temperature
sensor</strong> and <strong class="gt hj">send the temperature data</strong> to a CoAP server…</p>
<p id="71a6" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">1⃣ At startup, our main program
<code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/main.c" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">main.c</strong></a></code>
delegates the <strong class="gt hj">reading of sensor data</strong> to <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/listen_sensor.c" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">listen_sensor.c</a></code>.
It also delegates the <strong class="gt hj">transmitting of sensor data</strong> to <code
class="eb hk hl hm hn b">send_coap.c</code>.</p>
<p id="36ed" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Mynewt understands the
dependencies between our drivers and libraries. It ensures that the drivers and libraries are
initialised in the correct sequence.</p>
<p id="f251" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2⃣ Sensor handler <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/listen_sensor.c" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">listen_sensor.c</strong></a></code>
instructs Mynewt to <strong class="gt hj">poll the internal temperature sensor</strong> and to<strong
class="gt hj"> </strong>call a<strong class="gt hj"> custom Listener Function</strong> that will
<strong class="gt hj">transmit the polled data</strong> (via <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/send_coap.c" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">send_coap.c</a></code>).
</p>
<p id="7b65" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">With Mynewt its easy to
configure a sensor to be polled at regular intervals. Mynewts Sensor Framework lets us define a
Listener Function that will be called after polling.</p>
<p id="5a05" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">3⃣ Network handler <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/send_coap.c" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">send_coap.c</strong></a></code>
starts <strong class="gt hj">ESP8266 WiFi</strong> networking and <strong class="gt hj">transmits the
temperature data</strong> to a CoAP server like thethings.io.</p>
<p id="d89c" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Well create a Mynewt driver for
ESP8266 that supports multitasking, with locking to prevent multiple commands from running
concurrently. Mynewt supports CoAP so well create a simple library to transmit sensor data as CoAP
messages.</p>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="5958" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">Closer View</h1>
<p id="4245" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he"><em class="ho">(Below is a list
of Mynewt APIs called by the above top-level functions. You may skip this section if you dont wish
to create your own Mynewt application.)</em></p>
<blockquote class="lg">
<div id="e7e5" class="lh li lj bk el b lk ll lm ln lo lp he">
<p class="el b lq lr bo"><a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/main.c"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">main.c</a> Poll Temperature
Sensor, Transmit Sensor Data</p>
</div>
</blockquote>
<div class="figure ls lt lu lv lw cz">
<p><script src="https://gist.github.com/lupyuen/c7c4072e693445e75ef97e31df99113d.js"></script></p>
</div>
<p id="0de0" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/main.c#L13-L47" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">main</strong></a><strong class="gt hj">()</strong></code>
is the overall program that starts ESP8266 WiFi networking and starts the polling of Blue Pills
internal temperature sensor. It calls the following functions…</p>
<p id="d854" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">1<code
class="eb hk hl hm hn b"><strong class="gt hj">sysinit()</strong></code> to initialise the drivers
and libraries. This includes the <code class="eb hk hl hm hn b">temp_stm32</code> driver for Blue
Pills Internal Temperature Sensor and the <code class="eb hk hl hm hn b">sensor_coap</code> library
for transmitting Sensor CoAP messages.</p>
<p id="d78d" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Mynewt auto-generates <code
class="eb hk hl hm hn b">sysinit()</code> during the application build and includes all the
initialisation functions for drivers and libraries. Here is a <a
href="https://gist.github.com/lupyuen/e6efd675c3f6fcb7d1470f2c17e6d1fb"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">sample </a><code
class="eb hk hl hm hn b"><a href="https://gist.github.com/lupyuen/e6efd675c3f6fcb7d1470f2c17e6d1fb" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">sysinit</a>()</code>.
The functions are called in sequence according to their Stage Numbers. Our custom drivers and
libraries are initialised last, from <strong class="gt hj">Stage 600 </strong>onwards.</p>
<p id="69bc" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2<code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/send_coap.c#L36-L54" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">start_network_task</strong></a><strong class="gt hj">()</strong></code>
to run the <strong class="gt hj">Network Task</strong> in the background. The Network Task starts
ESP8266 WiFi networking and registers the ESP8266 driver as the Transport Layer for transmitting CoAP
messages.</p>
<p id="f588" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">3<code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/listen_sensor.c#L46-L76" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">start_sensor_listener</strong></a><strong class="gt hj">()</strong></code>
to start polling the internal temperature sensor and to register the Listener Function that will
process the polled sensor data.</p>
<p id="c77f" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">After that the <code
class="eb hk hl hm hn b">main()</code> function loops forever, receiving Mynewt events and
processing them with <code
class="eb hk hl hm hn b"><a href="https://mynewt.apache.org/latest/os/core_os/event_queue/event_queue.html#c.os_eventq_run" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">os_eventq_run</strong></a><strong class="gt hj">()</strong></code>.
This is the standard Event Queue loop thats required for all Mynewt applications.</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="da db dc dd de df ag dg ah dh aj ak">
<div class="figure hq hr hs ht hu cz do dp paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<blockquote class="lg">
<div id="aabd" class="lh li lj bk el b lk ll lm ln lo lp he">
<p class="el b lq lr bo"><a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/listen_sensor.c"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">listen_sensor.c</a> Poll
Internal Temperature Sensor</p>
</div>
</blockquote>
<div class="figure ls lt lu lv lw cz">
<p><script src="https://gist.github.com/lupyuen/79d9e7d7d1e760ecb334a4c835410aec.js"></script></p>
</div>
<p id="bbdc" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/listen_sensor.c#L46-L76" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">start_sensor_listener</strong></a><strong class="gt hj">()</strong></code>
configures Mynewt to poll the internal temperature sensor every 10 seconds and to process the received
temperature data with our custom function. It calls the following functions, which are provided by
Mynewts Sensor Framework…</p>
<p id="3432" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">1<code
class="eb hk hl hm hn b"><a href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_mgr_api.html#c.sensor_set_poll_rate_ms" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">sensor_set_poll_rate_ms</strong></a><strong class="gt hj">()</strong></code>
to poll the internal temperature sensor every 10 seconds</p>
<p id="399d" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2<code
class="eb hk hl hm hn b"><a href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_mgr_api.html#c.sensor_mgr_find_next_bydevname" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">sensor_mgr_find_next_bydevname</strong></a><strong class="gt hj">()</strong></code>
to fetch the internal temperature sensor <code class="eb hk hl hm hn b">temp_stm32_0</code></p>
<p id="1dc2" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">3<code
class="eb hk hl hm hn b"><a href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_listener_api.html#c.sensor_register_listener" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">sensor_register_listener</strong></a><strong class="gt hj">()</strong></code>
to register a Listener Function <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/listen_sensor.c#L109-L153" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">read_temperature</a>()</code>
that will be called with the polled temperature data every 10 seconds. <code
class="eb hk hl hm hn b">read_temperature()</code> will transmit the temperature to the CoAP server.
</p>
<p id="9add" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">To learn more about Mynewts
Sensor Framework, check out <a class="at cg hf hg hh hi" target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/create-your-iot-gadget-with-apache-mynewt-and-stm32-blue-pill">the
previous tutorial</a>.</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="da db dc dd de df ag dg ah dh aj ak">
<div class="figure hq hr hs ht hu cz do dp paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<blockquote class="lg">
<div id="792c" class="lh li lj bk el b lk ll lm ln lo lp he">
<p class="el b lq lr bo"><a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/send_coap.c"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">send_coap.c</a> Start
ESP8266, Transmit Sensor Data</p>
</div>
</blockquote>
<div class="figure ls lt lu lv lw cz">
<p><script src="https://gist.github.com/lupyuen/24c8aee33bb527c8a5e949c2aa3392e7.js"></script></p>
</div>
<p id="5fa2" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/send_coap.c#L36-L54" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">start_network_task</strong></a><strong class="gt hj">()</strong></code>
starts the task that connects the ESP8266 to the WiFi network. It calls <code
class="eb hk hl hm hn b"><a href="https://mynewt.apache.org/latest/os/core_os/task/task.html#c.os_task_init" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">os_task_init</strong></a><strong class="gt hj">()</strong></code>
to start the <strong class="gt hj">Network Task</strong> in the background.</p>
<p id="5270" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Mynewt is a preemptive
multitasking operating system. Thats how we create tasks in Mynewt to run at different priorities.
Here we created a background task to start up ESP8266 (which may take some time) so that the Main Task
can proceed to run other functions.</p>
<p id="1e14" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">When the Network Task starts it
runs <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/send_coap.c#L55-L93" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">network_task_func</strong></a><strong class="gt hj">()</strong></code>...
</p>
<div class="figure hq hr hs ht hu cz">
<p><script src="https://gist.github.com/lupyuen/c1fe605004994a68efbcf06621f77fb8.js"></script></p>
</div>
<p id="07d3" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/send_coap.c#L55-L93" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">network_task_func</strong></a><strong class="gt hj">()</strong></code>
is the function in the Network Task that connects the ESP8266 module to the WiFi network and registers
the ESP8266 module as the Transport Layer for sending CoAP messages. It calls the following functions:
</p>
<p id="f86d" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">1<code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/hmac_prng/src/hmac_prng.c#L53-L59" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">hmac_prng_generate</strong></a><strong class="gt hj">()</strong></code>
to generate a random device ID, to assure privacy of the sensor data when viewed on a public website
</p>
<p id="ce3d" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2<code
class="eb hk hl hm hn b"><a href="https://github.com/apache/mynewt-core/blob/master/kernel/os/include/os/os_dev.h" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">os_dev_open</strong></a><strong class="gt hj">()</strong></code>
to lock the ESP8266 device for exclusive use</p>
<p id="8cca" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">3<code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/driver.cpp#L101-L118" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">esp8266_connect</strong></a><strong class="gt hj">()</strong></code>
to connect the ESP8266 to the WiFi router</p>
<p id="e4f1" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">4<code
class="eb hk hl hm hn b"><a href="https://github.com/apache/mynewt-core/blob/master/kernel/os/include/os/os_dev.h" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">os_dev_close</strong></a><strong class="gt hj">()</strong></code>
to unlock the ESP8266 device and allow other tasks to use it</p>
<p id="6764" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">5<code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/transport.cpp#L35-L70" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">esp8266_register_transport</strong></a><strong class="gt hj">()</strong></code>
to register the ESP8266 device as the Transport Layer for transmitting CoAP messages</p>
<p id="d18b" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">6<code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/geolocate.c#L35-L83" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">geolocate</strong></a><strong class="gt hj">()</strong></code>
(if <code class="eb hk hl hm hn b">WIFI_GEOLOCATION</code> is enabled) to compute latitude and
longitude based on WiFi Access Points scanned by ESP8266</p>
<p id="1420" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">7<code
class="eb hk hl hm hn b"><a href="https://mynewt.apache.org/latest/os/core_os/mbuf/mbuf.html#c.os_msys_num_free" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">os_msys_num_free</strong></a><strong class="gt hj">()</strong></code>
to show number of free <code class="eb hk hl hm hn b">mbufs</code> every 10 seconds. <code
class="eb hk hl hm hn b">mbufs</code> are RAM memory buffers used for composing and transmitting
CoAP messages. The number should remain constant after a while.</p>
<p id="9178" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">8<code
class="eb hk hl hm hn b"><a href="https://mynewt.apache.org/latest/os/core_os/time/os_time.html#c.os_time_delay" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">os_time_delay</strong></a><strong class="gt hj">()</strong></code>
to sleep for 10 seconds before calling <code
class="eb hk hl hm hn b"><a href="https://mynewt.apache.org/latest/os/core_os/mbuf/mbuf.html#c.os_msys_num_free" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">os_msys_num_free</a>() </code>again.
While sleeping, Mynewt will schedule other tasks to run.</p>
<p id="ead0" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Here we see how we open and lock
Mynewt drivers for exclusive access, to prevent other tasks from accessing the same interface.</p>
<p id="d615" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">In a multitasking environment
like Mynewt, its good to sleep occasionally (shown above) so that other tasks will have the chance to
run.</p>
<p id="936e" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Also in <code
class="eb hk hl hm hn b">send_coap.c</code> is <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/send_coap.c#L94-L112" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">send_sensor_data</strong></a><strong class="gt hj">(),</strong></code>
the function that transmits the temperature sensor data to the CoAP server. Well examine this
function in a while.</p>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="f29a" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">Download Source Code</h1>
<p id="1351" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he">Lets download the source code
with Visual Studio Code…</p>
<blockquote class="in io ip">
<p id="6f91" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://youtu.be/uevCLrzLANk"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Watch the video</a></p>
</blockquote>
<p id="6d1a" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">1⃣ Install <a
href="https://code.visualstudio.com/"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">Visual
Studio Code</strong></a> if you havent. Launch Visual Studio Code.</p>
<p id="2c2e" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2⃣ Click <code
class="eb hk hl hm hn b"><strong class="gt hj">View → Command Palette</strong></code></p>
<p id="b313" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">3⃣ Type <code
class="eb hk hl hm hn b"><strong class="gt hj">git clone</strong></code> then press Enter</p>
<p id="8ae7" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">4⃣ For <code
class="eb hk hl hm hn b"><strong class="gt hj">Repository URL</strong></code>, enter</p>
<p id="8197" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">https://github.com/lupyuen/stm32bluepill-mynewt-sensor</strong></a></code>
</p>
<p id="6d0b" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">5⃣ When prompted to <code
class="eb hk hl hm hn b"><strong class="gt hj">Select Repository Location</strong></code></p>
<p id="eba6" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><em class="ho">For Windows:</em>
Select your <code class="eb hk hl hm hn b"><strong class="gt hj">Local Disk C:</strong></code> drive
</p>
<p id="7bf0" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><em class="ho">For macOS:</em>
Select your <strong class="gt hj">Home folder</strong></p>
<p id="d840" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">(If you have previously
downloaded <code class="eb hk hl hm hn b">stm32bluepill-mynewt-sensor</code><strong class="gt hj">,
</strong>rename the old folder before downloading)</p>
<p id="8ea3" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The Mynewt Sensor Application
source code will be downloaded to <code
class="eb hk hl hm hn b"><strong class="gt hj">C:\stm32bluepill-mynewt-sensor</strong></code>
(Windows) or <code
class="eb hk hl hm hn b"><strong class="gt hj">$HOME/stm32bluepill-mynewt-sensor</strong></code>
(macOS)</p>
<p id="6522" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">6⃣ When prompted, click <code
class="eb hk hl hm hn b"><strong class="gt hj">Open Repository</strong></code> and <code
class="eb hk hl hm hn b"><strong class="gt hj">Open Workspace</strong></code></p>
<p id="50c1" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">If you have trouble with the
steps, check the screenshots under <em class="ho"></em><a class="at cg hf hg hh hi" target="_blank"
rel="noopener"
href="https://lupyuen.github.io/articles/create-your-iot-gadget-with-apache-mynewt-and-stm32-blue-pill"><em
class="ho">Install Visual Studio Code and the Mynewt Sensor Application</em></a><em
class="ho"></em></p>
<blockquote class="in io ip">
<p id="41e2" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://youtu.be/uevCLrzLANk"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Watch the video</a></p>
</blockquote>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="da db dc dd de df ag dg ah dh aj ak">
<div class="figure hq hr hs ht hu cz do dp paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h5.png" /></p>
<figcaption><p><em>Visual Studio Code with application source
code</em></p></figcaption>
</div>
</div>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="53a6" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">Configure WiFi Settings</h1>
<p id="cacc" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he">In Visual Studio Code, open the
configuration file <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/targets/bluepill_my_sensor/syscfg.yml" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">targets/bluepill_my_sensor/syscfg.yml</strong></a></code>.
Look for these lines:</p>
<pre
class="hq hr hs ht hu ma mb mc"><span id="dff9" class="md jh ek bk hn b fm me mf r mg"> # Connect to the WiFi access point with this SSID<br/> WIFI_SSID: &#x27;&quot;my_ssid&quot;&#x27;<br/> <br/> # Password for WiFi access point<br/> WIFI_PASSWORD: &#x27;&quot;my_password_is_secret&quot;&#x27;</span></pre>
<p id="fe4c" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The ESP8266 module will use these
settings to connect to your WiFi network. Fill in the SSID and password for your WiFi network. The
SSID and password values should always begin with <code class="eb hk hl hm hn b">&#x27;&quot;</code>
and end with <code class="eb hk hl hm hn b">&quot;&#x27;</code>.</p>
<p id="77b2" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">To enter the single-quote <code
class="eb hk hl hm hn b">&#x27;</code> character, use <code
class="eb hk hl hm hn b">&#x27;&#x27;</code></p>
<pre
class="hq hr hs ht hu ma mb mc"><span id="a3cd" class="md jh ek bk hn b fm me mf r mg"> # This becomes: My Home&#x27;s SSID<br/> WIFI_SSID: &#x27;&quot;My Home&#x27;&#x27;s SSID&quot;&#x27;</span></pre>
<p id="8e9e" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">To enter the double-quote <code
class="eb hk hl hm hn b">&quot;</code> character, use <code class="eb hk hl hm hn b">\&quot;</code>
</p>
<pre
class="hq hr hs ht hu ma mb mc"><span id="2c8c" class="md jh ek bk hn b fm me mf r mg"> # This becomes: My &quot;SSID&quot; goes here<br/> WIFI_SSID: &#x27;&quot;My \&quot;SSID\&quot; goes here&quot;&#x27;</span></pre>
<blockquote class="in io ip">
<p id="9984" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://youtu.be/Wk11fIZr_cM"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Watch the video</a></p>
</blockquote>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="dc9c" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">Build The Application</h1>
<p id="5292" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he">1⃣ Install Mynewt as instructed
in the last tutorial. Look for the sections <em class="ho"></em><a class="at cg hf hg hh hi"
target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/create-your-iot-gadget-with-apache-mynewt-and-stm32-blue-pill"><em
class="ho">Install Apache Mynewt for Windows</em></a><em class="ho"></em> or <em
class="ho"></em><a class="at cg hf hg hh hi" target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/create-your-iot-gadget-with-apache-mynewt-and-stm32-blue-pill"><em
class="ho">Install Apache Mynewt for macOS</em></a><em class="ho">”. </em>For Ubuntu Linux, <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor#install-apache-mynewt-for-ubuntu-linux"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">refer to these instructions</a>.
</p>
<blockquote class="in io ip">
<p id="e781" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://youtu.be/uevCLrzLANk?t=103"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Watch the video</a></p>
</blockquote>
<p id="5b3b" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2⃣ Restart Visual Studio Code
after installing Mynewt</p>
<blockquote class="in io ip">
<p id="8c5a" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://youtu.be/uevCLrzLANk?t=899"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Watch the video</a></p>
</blockquote>
<p id="8ac1" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">3⃣ Click <code
class="eb hk hl hm hn b"><strong class="gt hj">Terminal → Run Task → [1] Build bluepill_boot</strong></code>
</p>
<blockquote class="in io ip">
<p id="4861" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://youtu.be/LWJIAOFQBe0"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Watch the video</a></p>
</blockquote>
<p id="6279" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">4⃣ Click <code
class="eb hk hl hm hn b"><strong class="gt hj">Terminal → Run Task → [2] Build bluepill_my_sensor</strong></code>
</p>
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib ic id ie if ig paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h6.png" /></p>
<figcaption><p><em>Build warnings caused by type conversion
</em></p></figcaption>
</div>
<p id="be3e" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">You will encounter <code
class="eb hk hl hm hn b">invalid conversion</code> errors like this.</p>
<p id="fa0a" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The workaround: <a
href="https://gist.github.com/lupyuen/bbc2dae52a8fdac1e70a60757fed1467"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Follow the instructions here</a>
to edit 3 files in the Mynewt source code. Then build again.</p>
<blockquote class="in io ip">
<p id="7ba1" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://youtu.be/8naNVsLzlic"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Watch the video</a></p>
</blockquote>
<p id="a0bf" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">5⃣ Click <code
class="eb hk hl hm hn b"><strong class="gt hj">Terminal → Run Task → [3] Image bluepill_my_sensor</strong></code>
</p>
<blockquote class="in io ip">
<p id="bcd1" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://youtu.be/NU8CnHkOudM"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Watch the video</a></p>
</blockquote>
<p id="e361" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">6⃣ Connect your Blue Pill and
ST-Link V2 to the USB port</p>
<p id="708f" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">7⃣ Click <code
class="eb hk hl hm hn b"><strong class="gt hj">Terminal → Run Task → [4] Load bluepill_boot</strong></code>
</p>
<blockquote class="in io ip">
<p id="98c1" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://youtu.be/ndGlxmj4N6o"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Watch the video</a></p>
</blockquote>
<p id="f477" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">8⃣ Click <code
class="eb hk hl hm hn b"><strong class="gt hj">Terminal → Run Task → [5] Load bluepill_my_sensor</strong></code>
</p>
<blockquote class="in io ip">
<p id="cc25" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://youtu.be/5o4ff3fn-8Y"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Watch the video</a></p>
</blockquote>
<p id="cd5d" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">If you get stuck, refer to the
sections <em class="ho"></em><a class="at cg hf hg hh hi" target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/create-your-iot-gadget-with-apache-mynewt-and-stm32-blue-pill"><em
class="ho">Build Mynewt Bootloader and Application</em></a><em class="ho">”, “</em><a
class="at cg hf hg hh hi" target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/create-your-iot-gadget-with-apache-mynewt-and-stm32-blue-pill"><em
class="ho">Create Application Image</em></a><em class="ho"></em>and<em class="ho"></em><a
class="at cg hf hg hh hi" target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/create-your-iot-gadget-with-apache-mynewt-and-stm32-blue-pill"><em
class="ho">Flash Bootloader and Application to Blue Pill</em></a><em class="ho"></em></p>
<p id="225d" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The <code
class="eb hk hl hm hn b">Install Apache Mynewt</code> step installs a custom memory layout for Blue
Pill so that the bootloader and application both fit in 64 KB of ROM. <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/patch/README.md"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">More details here</a>.</p>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="49d8" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">Run The Application</h1>
<p id="92ed" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he">Were now ready to run the
application on Blue Pill to read the internal temperature sensor and send the data to the CoAP server…
</p>
<blockquote class="in io ip">
<p id="f423" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://youtu.be/YrKXdxB77Oc"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Watch the video</a></p>
</blockquote>
<p id="df64" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">1⃣ Click <code
class="eb hk hl hm hn b"><strong class="gt hj">Debug → Start Debugging</strong></code></p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="da db dc dd de df ag dg ah dh aj ak">
<div class="figure hq hr hs ht hu cz do dp paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib ic id ie if ig paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h7.png" /></p>
</div>
<p id="1911" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2⃣ Click <code
class="eb hk hl hm hn b"><strong class="gt hj">View → Output</strong></code></p>
<p id="99c7" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Select <code
class="eb hk hl hm hn b"><strong class="gt hj">Adapter Output</strong></code> to see the Blue Pill
log</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="da db dc dd de df ag dg ah dh aj ak">
<div class="figure hq hr hs ht hu cz do dp paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib ic id ie if ig paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h8.png" /></p>
</div>
<p id="e5e2" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">3⃣ The debugger pauses at the
line with <code class="eb hk hl hm hn b">LoopCopyDataInit</code></p>
<p id="a990" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Click <code
class="eb hk hl hm hn b"><strong class="gt hj">Continue</strong></code> or press <code
class="eb hk hl hm hn b"><strong class="gt hj">F5</strong></code></p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="da db dc dd de df ag dg ah dh aj ak">
<div class="figure hq hr hs ht hu cz do dp paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib ic id ie if ig paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h9.png" /></p>
</div>
<p id="ab15" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">4⃣ The debugger pauses next at
the <code class="eb hk hl hm hn b">main()</code> function.</p>
<p id="3988" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Click <code
class="eb hk hl hm hn b"><strong class="gt hj">Continue</strong></code> or press <code
class="eb hk hl hm hn b"><strong class="gt hj">F5</strong></code></p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="da db dc dd de df ag dg ah dh aj ak">
<div class="figure hq hr hs ht hu cz do dp paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib ic id ie if ig paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h10.png" /></p>
</div>
<p id="c3df" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">5⃣ Your Blue Pill log should
look like this:</p>
<p id="00d7" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b"><a href="https://gist.github.com/lupyuen/1006f1b2144b489c895f14a036dad8fb" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">https://gist.github.com/lupyuen/1006f1b2144b489c895f14a036dad8fb</a></code>
</p>
<blockquote class="in io ip">
<p id="8869" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://youtu.be/YrKXdxB77Oc"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Watch the video</a></p>
</blockquote>
<p id="8a88" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">To understand whats really
happening under the hood, lets study the Blue Pill log.</p>
<p id="b29f" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Well start by looking at the
commands sent to the ESP8266 module…</p>
<div class="figure hq hr hs ht hu cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="a343" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">ESP8266 Commands</h1>
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib ic id ie if ig paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h11.png" /></p>
<figcaption><p><em>Chatting with ESP8266… “AT” and “OK”
</em></p></figcaption>
</div>
<p id="ae0f" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Sending commands to ESP8266 is
like chatting… We say something (the command), we wait for the response, and we parse the response for
certain keywords (like “OK”) to decide how to proceed.</p>
<p id="e6e0" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">ESP8266 commands begin with <code
class="eb hk hl hm hn b">AT</code> and end with carriage return + line feed (<code
class="eb hk hl hm hn b">\r\n</code>). Like <code class="eb hk hl hm hn b">AT+RST</code> which is
the Reset command. You may check the entire list of AT commands in the <a
href="https://www.espressif.com/sites/default/files/documentation/4a-esp8266_at_instruction_set_en.pdf"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><em class="ho">ESP8266 AT
Instruction Set</em></a> reference. Also check out the examples in the <a
href="https://www.espressif.com/sites/default/files/documentation/4b-esp8266_at_command_examples_en.pdf"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><em class="ho">ESP8266 AT Command
Examples</em></a> doc.</p>
<p id="19dd" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Lets run through the ESP8266
commands in the <a
href="https://gist.github.com/lupyuen/1006f1b2144b489c895f14a036dad8fb"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">sample log</a></p>
<blockquote class="lg">
<div id="66c4" class="lh li lj bk el b lk ll lm ln lo lp he">
<p class="el b lq lr bo">ESP8266 Reset</p>
</div>
</blockquote>
<p id="cc37" class="gr gs ek bk gt b gu mq gw mr gy ms ha mt hc mu he">To understand the <a
href="https://gist.github.com/lupyuen/1006f1b2144b489c895f14a036dad8fb"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">sample log</a>, look out for these
markers:</p>
<p id="9110" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b">[</code> and <code class="eb hk hl hm hn b">]</code> mark the start and end
of each ESP8266 command<br /><code class="eb hk hl hm hn b">AT&gt;</code> flags the commands that we
sent to ESP8266<br /><code class="eb hk hl hm hn b">AT&lt;</code> shows the responses from
ESP8266<br /><code class="eb hk hl hm hn b">AT=</code> means that we have matched a keyword in the
response</p>
<p id="513a" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The first command is the Reset
command — we send <code class="eb hk hl hm hn b">AT+RST</code> to the ESP8266 to restart the module
and clear any WiFi connections. Heres the log for the Reset command…</p>
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib mv mw mx my ig">
<p><script src="https://gist.github.com/lupyuen/3864ad0861b962d4721e176a8768365a.js"></script></p>
</div>
<p id="38d4" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b">AT&gt; (newline) AT+RST</code> means that we sent the command <code
class="eb hk hl hm hn b">AT+RST</code> to the ESP8266 module.</p>
<p id="abd3" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">ESP8266 responded with an error
<code class="eb hk hl hm hn b">AT&lt; ERROR</code> caused by the newline that we sent. Its OK to
ignore this error. (The newline was sent to terminate any prior commands)</p>
<p id="23c0" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">To check that the command has
succeeded, the program waits for the keyword <code class="eb hk hl hm hn b">OK</code>. <code
class="eb hk hl hm hn b">AT= OK</code> means that the program has matched the <code
class="eb hk hl hm hn b">OK</code> response from ESP8266. Most commands return <code
class="eb hk hl hm hn b">OK</code> upon completion, but the Reset command is more complicated…</p>
<p id="6bc9" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">After ESP8266 has returned the
<code class="eb hk hl hm hn b">OK</code> response, it returns more text to show the progress of the
module restarting (including some garbled text). When the restart has completed, it returns a keyword
<code class="eb hk hl hm hn b">ready</code> which is matched by the program: <code
class="eb hk hl hm hn b">AT= ready</code>. So now we know that the Reset command has completed and
we may send the next command.</p>
<div class="figure hq hr hs ht hu cz">
<p><script src="https://gist.github.com/lupyuen/9875365613e498abf85025ce07604c04.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/Controller.cpp#L83-L108"
class="at cg hf hg hh hi" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/Controller.cpp#L83-L108</a>
</em></p></figcaption>
</div>
<p id="66fe" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Heres the <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/Controller.cpp#L83-L108" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">ESP8266::reset()</a></code>
function in <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/Controller.cpp#L83-L108" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">libs/esp8266/src/Controller.cpp</a></code>
that sends the Reset command and matches the response keywords. <code
class="eb hk hl hm hn b">send()</code> is called to send a command to ESP8266. <code
class="eb hk hl hm hn b">recv(keyword)</code> will wait until the keyword is found in the response
from ESP8266. If the keyword is not found within a few seconds, it fails with a timeout error and the
program stops.</p>
<blockquote class="lg">
<div id="1192" class="lh li lj bk el b lk ll lm ln lo lp he">
<p class="el b lq lr bo">ESP8266 Echo</p>
</div>
</blockquote>
<p id="2404" class="gr gs ek bk gt b gu mq gw mr gy ms ha mt hc mu he">ESP8266 is usually very chatty…
when you send a command like <code class="eb hk hl hm hn b">AT+RST</code>, it responds with the same
command <code class="eb hk hl hm hn b">AT+RST</code> before responding <code
class="eb hk hl hm hn b">OK</code>. Its like hearing an echo of yourself. To simplify the response
matching, we disable the echoing by sending the <code class="eb hk hl hm hn b">ATE0</code> command.
Heres the log…</p>
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib mv mw mx my ig">
<p><script src="https://gist.github.com/lupyuen/896fcf0f08cec47f036b7c5d73562a56.js"></script></p>
</div>
<p id="16d8" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The function <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/Controller.cpp#L47-L64" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">ESP8266::setEcho()</a></code>
sends the <code class="eb hk hl hm hn b">ATE0</code> command and waits for the <code
class="eb hk hl hm hn b">OK</code> keyword.</p>
<p id="f2ac" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The program sends three more
commands:</p>
<p id="1b90" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b">AT+CWMODE=3</code> Set the ESP8266 into WiFi Client mode (instead of WiFi
Access Point mode). This means that our ESP8266 will connect to an existing WiFi Access Point (a WiFi
router) to access the internet.</p>
<p id="504e" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b">AT+CIPMUX=1</code> Allow multiple TCP and UDP connections. In case we need
to connect to multiple servers</p>
<p id="d934" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b">AT+CWDHCP=1</code> Enable DHCP so that the ESP8266 will request an IP
address from the WiFi network</p>
<blockquote class="lg">
<div id="7684" class="lh li lj bk el b lk ll lm ln lo lp he">
<p class="el b lq lr bo">ESP8266 Connect</p>
</div>
</blockquote>
<p id="5e7e" class="gr gs ek bk gt b gu mq gw mr gy ms ha mt hc mu he">After disabling the command echo,
we connect the ESP8266 to our WiFi Access Point to get internet access…</p>
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib mv mw mx my ig">
<p><script src="https://gist.github.com/lupyuen/5aeacb1a4f7afb8413444d3b040ed40e.js"></script></p>
</div>
<p id="93fa" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b">AT+CWJAP=”ssid”,”password”</code> connects the ESP8266 to the WiFi router
using the SSID and password. To change the WiFi settings, edit <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/targets/bluepill_my_sensor/syscfg.yml" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">targets/bluepill_my_sensor/syscfg.yml</a></code>
</p>
<p id="6231" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b">AT+CIFSR</code> returns the WiFi connection details (IP and MAC addresses).
</p>
<p id="29a4" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">These commands are sent by <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/Controller.cpp#L121-L128" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">ESP8266::connect()</a></code>
and <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/Controller.cpp#L135-L144" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">ESP8266::getIPAddress()</a></code>
</p>
<div class="figure hq hr hs ht hu cz">
<p><script src="https://gist.github.com/lupyuen/5ed4ac2e0f34139bcb1f33bd601bbf9c.js"></script></p>
</div>
<p id="8047" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">If the connection to the WiFi
Access Point fails, well see a <code class="eb hk hl hm hn b">response mismatch</code> message
because the program has waited a while for the <code class="eb hk hl hm hn b">OK</code> response but
didnt see any. If you see this message, check the WiFi settings in <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/targets/bluepill_my_sensor/syscfg.yml" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">targets/bluepill_my_sensor/syscfg.yml</a></code>
</p>
<blockquote class="lg">
<div id="85fa" class="lh li lj bk el b lk ll lm ln lo lp he">
<p class="el b lq lr bo">ESP8266 Orchestration</p>
</div>
</blockquote>
<p id="6609" class="gr gs ek bk gt b gu mq gw mr gy ms ha mt hc mu he"><code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/Controller.cpp#L83-L108" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">ESP8266::reset()</a></code>,
<code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/Controller.cpp#L47-L64" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">setEcho()</a></code>
and <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/Controller.cpp#L121-L128" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">connect()</a></code>
are the functions that send the Reset, Echo and Connect commands to ESP8266… but for transmitting
sensor data over WiFi, its tedious to code our application to call each of these low-level functions.
So we have a high-level function, <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/driver.cpp#L101-L118" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">esp8266_connect()</a></code>,
that orchestrates (calls sequentially) the low-level functions to send the individual ESP8266
commands…</p>
<div class="figure hq hr hs ht hu cz">
<p><script src="https://gist.github.com/lupyuen/72b2f0c088397a982d5ac0821078c6c3.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/driver.cpp#L101-L118"
class="at cg hf hg hh hi" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/driver.cpp#L101-L118</a>
</em></p></figcaption>
</div>
<p id="7e91" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/driver.cpp#L101-L118" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">esp8266_connect()</a></code>
is the function that we should call in our application to restart the ESP8266 module and connect it to
the WiFi router, <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/send_coap.c#L69-L120"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">like this</a>.</p>
<blockquote class="lg">
<div id="3101" class="lh li lj bk el b lk ll lm ln lo lp he">
<p class="el b lq lr bo">ESP8266 Open</p>
</div>
</blockquote>
<p id="207d" class="gr gs ek bk gt b gu mq gw mr gy ms ha mt hc mu he">Before transmitting messages to
our server, we need to open the server connection by sending the command <code
class="eb hk hl hm hn b">AT+CIPSTART=0,”UDP”,”coap.thethings.io”,5683</code></p>
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib mv mw mx my ig">
<p><script src="https://gist.github.com/lupyuen/a21ca431c36529358b0f0107fb857bfc.js"></script></p>
</div>
<p id="de56" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">This opens a connection on socket
number <code class="eb hk hl hm hn b">0</code> of the ESP8266 module.</p>
<p id="0020" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The socket will be used to
transmit UDP packets to the server <code class="eb hk hl hm hn b">coap.thethings.io</code> at port
<code class="eb hk hl hm hn b">5683</code> (the standard port for CoAP).</p>
<p id="24a1" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">For this tutorial you may use my
paid-subscription account at thethings.io, since its too tedious to set up your own CoAP server. (Im
not sponsored by thethings.io) If you wish to use another server, edit the CoAP settings at <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/targets/bluepill_my_sensor/syscfg.yml" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">targets/bluepill_my_sensor/syscfg.yml</a></code>
</p>
<p id="a000" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Back to the Open command <code
class="eb hk hl hm hn b">AT+CIPSTART=0,...</code> How did we know that socket <code
class="eb hk hl hm hn b">0</code> was available? We call the function <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/driver.cpp#L150-L170" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">esp8266_socket_open()</a></code>
to allocate a socket. The function tracks which sockets are in use, assuming that we call <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/driver.cpp#L172-L180" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">esp8266_socket_close()</a></code>
to deallocate the socket.</p>
<p id="f799" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The Open command is sent by <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/Controller.cpp#L233-L244" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">ESP8266::open()</a></code>.
We call it <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/transport.cpp#L35-L70"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">like this</a> (look for <code
class="eb hk hl hm hn b">esp8266_socket_open()</code> and <code
class="eb hk hl hm hn b">esp8266_socket_connect()</code>).</p>
<blockquote class="lg">
<div id="f0d9" class="lh li lj bk el b lk ll lm ln lo lp he">
<p class="el b lq lr bo">ESP8266 Send</p>
</div>
</blockquote>
<p id="cdd9" class="gr gs ek bk gt b gu mq gw mr gy ms ha mt hc mu he">The final command for today: the
Send command.</p>
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib mv mw mx my ig">
<p><script src="https://gist.github.com/lupyuen/8cb3afa5b765948dca7970dd37aa2e01.js"></script></p>
</div>
<p id="b627" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b">AT+CIPSEND=0,177</code> prepares the ESP8266 to transmit <code
class="eb hk hl hm hn b">177</code> bytes of data to socket number <code
class="eb hk hl hm hn b">0</code> (which we have specified earlier to <code
class="eb hk hl hm hn b">AT+CIPSTART</code>).</p>
<p id="d11b" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Following this command, the
program sends 177 bytes of packet data to ESP8266. Be sure that we send exactly 177 bytes of data — if
we dont,<strong class="gt hj"> the ESP8266 module will not respond to commands until we power it off
and on again. </strong><em class="ho">(So if you think the ESP8266 is acting strange, just
power-cycle it)</em></p>
<p id="7325" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Since we have already opened
socket number <code class="eb hk hl hm hn b">0</code> to the UDP server at thethings.io, this command
transmits the 177 bytes as a single UDP packet to thethings.io. Which is sufficient in this tutorial
for sending sensor data via the CoAP protocol (based on UDP).</p>
<p id="debe" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The Send command is sent by <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/Controller.cpp#L246-L261" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">ESP8266::send()</a></code>.
We call it <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/transport.cpp#L90-L118"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">like this</a> (look for <code
class="eb hk hl hm hn b">esp8266_socket_send_mbuf()</code>, which transmits data stored as <code
class="eb hk hl hm hn b"><a href="https://mynewt.apache.org/latest/os/core_os/mbuf/mbuf.html" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">mbufs</a></code>).
</p>
<p id="0969" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">ESP8266 Reset, Echo, Connect,
Open and Send commands are all that we need in this tutorial for sending sensor data to the CoAP
server at thethings.io. <a
href="https://en.wikipedia.org/wiki/Constrained_Application_Protocol"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">CoAP is based on simple UDP
networking</a>, so its easy to implement on ESP8266 and constrained microcontrollers like Blue Pill
(unlike MQTT based on TCP).</p>
<p id="7202" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The ESP8266 driver is located at
<code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/master/libs/esp8266" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">libs/esp8266</a></code>.
Its based on the mbed community project <code
class="eb hk hl hm hn b"><a href="https://os.mbed.com/teams/ESP8266/code/esp8266-driver/" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">esp8266-driver</a></code>,
which I ported to Mynewt and added some performance enhancements meant for constrained platforms like
Blue Pill. Note that theres a bug in the <code
class="eb hk hl hm hn b"><a href="https://mynewt.apache.org/latest/os/modules/baselibc.html#https://www.freebsd.org/cgi/man.cgi" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">baselibc</a></code>
implementation of <code class="eb hk hl hm hn b">vsscanf()</code>. The corrected version is at <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/vsscanf.c" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">apps/my_sensor_app/src/vsscanf.c</a></code>
and it must be placed in the same folder as <code class="eb hk hl hm hn b">main.c</code>.</p>
<blockquote class="in io ip">
<p id="4cfe" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><em class="bk">💎 </em>Whats
in the 177 bytes of the UDP packet? Check the section “Advanced Topic: Whats Inside The CoAP
Message?”</p>
</blockquote>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="eab4" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">Read Temperature Sensor</h1>
<p id="78f5" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he"><a class="at cg hf hg hh hi"
target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/create-your-iot-gadget-with-apache-mynewt-and-stm32-blue-pill">In
the previous tutorial</a> we built a Mynewt application that read the BME280 Temperature Sensor. For
this tutorial, Ill save us the trouble of sourcing for an actual BME280… well just use Blue Pills
internal temperature sensor instead!</p>
<p id="ac6c" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Blue Pills internal temperature
sensor may be accessed via the <a
href="https://en.wikipedia.org/wiki/Analog-to-digital_converter"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Analogue-To-Digital Converter</a>
port ADC1, channel 16. Mynewt doesnt have an ADC driver for Blue Pill, so I ported a <a
href="https://github.com/apache/mynewt-core/tree/master/hw/drivers/adc/adc_stm32f4"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">similar driver for STM32F4</a> to
Blue Pill (STM32F1). The new driver is named <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/master/libs/adc_stm32f1" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">adc_stm32f1</strong></a></code>
and its located at <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/master/libs/adc_stm32f1" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">libs/adc_stm32f1</a></code>.
</p>
<p id="fe9a" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Remember in the previous tutorial
we called <code class="eb hk hl hm hn b">sensor_register_listener()</code> to register our custom
Listener Function named <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/listen_sensor.c#L52-L84" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">read_temperature()</a></code>?<strong
class="gt hj"> </strong>Mynewt will call <code
class="eb hk hl hm hn b">read_temperature()</code><strong class="gt hj"> </strong>with the
temperature value<strong class="gt hj"> </strong>after polling<strong class="gt hj"> </strong>the
BME280 sensor every 10 seconds.</p>
<p id="305a" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">To make the Listener Function
work with the internal temperature sensor, we need to create a <a
href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_driver.html"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">Mynewt
Sensor Device Driver</strong></a>. Which I have done: the driver is named <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/master/libs/temp_stm32" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">temp_stm32</strong></a></code>
and its located at <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/master/libs/temp_stm32" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">libs/temp_stm32</a></code>.
</p>
<div class="figure hq hr hs ht hu cz">
<p><script src="https://gist.github.com/lupyuen/af584f829ae6f986bb5dd4cc4160dc12.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/listen_sensor.c#L52-L84"
class="at cg hf hg hh hi" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/listen_sensor.c#L52-L84</a>
</em></p></figcaption>
</div>
<p id="13d9" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Thanks to <a
href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_framework.html"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Mynewts Sensor Framework</a>, the
same Listener Function <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/listen_sensor.c#L52-L84" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">read_temperature()</a></code>
works for both BME280 and the internal temperature sensor! Notice that the function now calls <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/send_coap.c#L122-L173" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">send_sensor_data</strong>()</a></code>
to transmit the temperature sensor value. Lets dig deeper into <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/send_coap.c#L122-L173" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">send_sensor_data()</a></code>
</p>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="d6e7" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">Send Sensor Data</h1>
<p id="39af" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he"><code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/send_coap.c#L122-L173" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">send_sensor_data(tmp)</a></code>
transmits the temperature sensor value <code class="eb hk hl hm hn b">tmp</code> to the CoAP server,
e.g. thethings.io. Mynewt has built-in support for CoAP — its part of the <a
href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_oic.html"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">Open
Interconnect Consortium (OIC)</strong> Sensor Library</a>. (<a
href="https://openconnectivity.org/developer/specifications"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">More details on OIC here</a>)</p>
<p id="14b3" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Mynewts OIC library doesnt
fully implement the <a
href="https://openconnectivity.org/specs/OCF_Cloud_Specification_v2.0.2.pdf"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">new OIC specification</a> for
transmitting sensor data to a server. So I created a library <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/master/libs/sensor_coap" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">sensor_coap</strong></a></code>
(located at <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/master/libs/sensor_coap" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">libs/sensor_coap</a></code>)
that fills in the missing features for composing and transmitting CoAP sensor data messages. Lets
check out how <code class="eb hk hl hm hn b">send_sensor_data()</code> calls the <code
class="eb hk hl hm hn b">sensor_coap</code> library…</p>
<div class="figure hq hr hs ht hu cz">
<p><script src="https://gist.github.com/lupyuen/b0484db303d3cd79679948049573d392.js"></script></p>
<figcaption><p><em>From <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/send_coap.c#L122-L173"
class="at cg hf hg hh hi" target="_blank"
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/send_coap.c#L122-L173</a>
</em></p></figcaption>
</div>
<p id="ac09" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">1<code
class="eb hk hl hm hn b">send_sensor_data()</code> calls <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/sensor_coap/src/sensor_coap.c#L40-L45" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">init_sensor_post()</strong></a></code>
(from the <code class="eb hk hl hm hn b">sensor_coap</code> library) to prepare a new CoAP sensor data
message</p>
<p id="7b13" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2<code
class="eb hk hl hm hn b">send_sensor_data()</code> then calls some <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/sensor_coap/include/sensor_coap/sensor_coap.h#L120-L180" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">CP_…()</strong></a></code><a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/sensor_coap/include/sensor_coap/sensor_coap.h#L120-L180"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"> macros</a> (also from <code
class="eb hk hl hm hn b">sensor_coap</code> library) to compose the payload of the CoAP message that
will contain the sensor data…</p>
<p id="b4a2" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/sensor_coap/include/sensor_coap/sensor_coap.h#L124-L129" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">CP_ROOT()</strong></a></code>
creates the top-level root for the CoAP payload</p>
<p id="8b40" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/sensor_coap/include/sensor_coap/sensor_coap.h#L131-L136" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">CP_ARRAY()</strong></a></code>
creates a child array in the payload, e.g. <code class="eb hk hl hm hn b">{ “values”:[ ] }</code></p>
<p id="cd12" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/sensor_coap/include/sensor_coap/sensor_coap.h#L173-L180" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">CP_ITEM_STR()</strong></a></code>
and <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/sensor_coap/include/sensor_coap/sensor_coap.h#L164-L171" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">CP_ITEM_FLOAT()</strong></a></code>
add string and floating-point values (with string keys) to the child array, e.g.</p>
<pre
class="hq hr hs ht hu ma mb mc"><span id="1a49" class="md jh ek bk hn b fm me mf r mg">{ “values”:[<br/> {“key”:”tmp”, “value”:28.7} <br/> ] }<!-- --> </span></pre>
<p id="838c" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">3⃣ Finally <code
class="eb hk hl hm hn b">send_sensor_data()</code> calls <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/sensor_coap/src/sensor_coap.c#L154-L159" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">do_sensor_post()</strong></a></code>
to transmit the CoAP message to the server, with sensor data in the payload.</p>
<p id="cfab" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Lets look at the encoding of the
CoAP payload…</p>
<blockquote class="in io ip">
<p id="1705" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><em class="bk">💎 </em>We can
use loops to encode complex payloads. See <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/geolocate.c#L135-L192" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">apps/my_sensor_app/src/geolocate.c</a></code>
</p>
</blockquote>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<p id="b236" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/master/libs/sensor_coap" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">sensor_coap</a></code>
library supports two formats for encoding the CoAP payload with the <code
class="eb hk hl hm hn b">CP…()</code> macros: <strong class="gt hj">JSON</strong> and <a
href="https://cbor.io/" class="at cg hf hg hh hi"
target="_blank" rel="noopener nofollow"><strong class="gt hj">CBOR</strong></a>, a binary,
compressed variant of JSON. CBOR encoding (but not JSON) is supported natively by <a
href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_oic.html"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Mynewts OIC library</a>, so I
added the JSON encoding to the <code class="eb hk hl hm hn b">sensor_coap</code> library (based on <a
href="https://mynewt.apache.org/latest/os/modules/json/json.html"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Mynewts low-level JSON
library</a>).</p>
<p id="5343" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">With JSON encoding, <code
class="eb hk hl hm hn b">send_sensor_data()</code> creates a CoAP payload like this…</p>
<div class="figure hq hr hs ht hu cz">
<p><script src="https://gist.github.com/lupyuen/08d8565dfac19771644575d242aeb7ef.js"></script></p>
</div>
<p id="553f" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">This CoAP JSON format works for
<a href="https://developers.thethings.io/docs/coap-protocol"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">transmitting sensor data to
thethings.io</a>. (CBOR is not supported by thethings.io today). If you didnt change the CoAP
settings in <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/targets/bluepill_my_sensor/syscfg.yml" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">syscfg.yml</a></code>,
the application will send your sensor data to my paid account at thethings.io.</p>
<p id="2c0d" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><em class="ho">For the purpose of
learning about transmitting sensor data over CoAP in this tutorial, Ill allow you to send sensor
data CoAP messages to my server.</em></p>
<p id="7c85" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Ill explain in a while how you
may view your sensor data through a special public website that I have created (connected to my
account at thethings.io). To protect your privacy, the website requires the randomly-generated device
ID thats shown in the CoAP payload above.</p>
<blockquote class="in io ip">
<p id="e621" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><em class="bk">💎 </em>To
select JSON or CBOR encoding, edit the settings in <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/targets/bluepill_my_sensor/syscfg.yml" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">targets/bluepill_my_sensor/syscfg.yml</a></code><br />For
JSON encoding (default): <code class="eb hk hl hm hn b">COAP_JSON_ENCODING: 1<br/></code>For CBOR
encoding: <code class="eb hk hl hm hn b">COAP_CBOR_ENCODING: 1</code></p>
</blockquote>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="fded" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">Send CoAP Message</h1>
<p id="08a7" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he">We saw earlier how <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/send_coap.c#L122-L173" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">send_sensor_data()</a></code>
transmits a CoAP sensor data message by calling <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/sensor_coap/src/sensor_coap.c#L154-L159" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">do_sensor_post()</a></code>
defined in the <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/master/libs/sensor_coap" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">sensor_coap</a></code>
library. You will be delighted to learn this: <code class="eb hk hl hm hn b">do_sensor_post()</code>
<em class="ho">doesnt actually send the CoAP message itself!</em></p>
<p id="a585" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Instead, <code
class="eb hk hl hm hn b">do_sensor_post()</code> forwards the message (via an <a
href="https://mynewt.apache.org/latest/tutorials/os_fundamentals/event_queue.html"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Event Queue</a>) to the <strong
class="gt hj">OIC Task</strong> running in the background, which will transmit the message. Why is
this a good thing? Because our sensors Listener Function <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/listen_sensor.c#L52-L84" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">read_temperature()</a></code>
<em class="ho">wont be stuck waiting for the CoAP message to be transmitted!</em></p>
<p id="6830" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The transmission will take place
in the background, so the Listener Function may happily crunch through the next set of sensor data and
prepare the new data for transmission. Thats the power of <a
href="https://mynewt.apache.org/latest/tutorials/os_fundamentals/tasks_lesson.html"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">multitasking in Mynewt</a>!</p>
<p id="5807" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">When you look back at the <a
href="https://gist.github.com/lupyuen/1006f1b2144b489c895f14a036dad8fb"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">sample log</a>, youll see these
events that triggered the sending of the CoAP message…</p>
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib mv mw mx my ig">
<p><script src="https://gist.github.com/lupyuen/4f715bdcf688aee65d4013095d58d57c.js"></script></p>
</div>
<p id="1615" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">1<code
class="eb hk hl hm hn b"><strong class="gt hj">ADC open ch 16</strong></code>: Mynewt Sensor
Framework prepares to read our internal temperature sensor <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/master/libs/temp_stm32" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">temp_stm32</a></code>,
since we have configured Mynewt to poll the sensor every 10 seconds. <code
class="eb hk hl hm hn b">temp_stm32</code> calls the ADC driver <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/master/libs/adc_stm32f1" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">adc_stm32f1</a></code>
to open port ADC1 channel 16, where the sensor may be accessed.</p>
<p id="3629" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2<code
class="eb hk hl hm hn b"><strong class="gt hj">STM read int temp sensor</strong></code>: <code
class="eb hk hl hm hn b">temp_stm32</code> <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/temp_stm32/src/temp_stm32.c#L142-L276"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">reads the internal temperature
sensor value</a> through the open ADC1 port. <code class="eb hk hl hm hn b">temp_stm32</code>
returns the temperature value <code class="eb hk hl hm hn b">29.86</code> to the Sensor Framework.</p>
<p id="92ef" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">3<code
class="eb hk hl hm hn b"><strong class="gt hj">TMP poll data tmp 29.86</strong></code>: The Sensor
Framework calls our Listener Function <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/listen_sensor.c#L52-L84" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">read_temperature()</a></code>
with the temperature value <code class="eb hk hl hm hn b">29.86</code>. <code
class="eb hk hl hm hn b">read_temperature()</code> takes this value and calls the <code
class="eb hk hl hm hn b">sensor_coap</code> library to compose the CoAP message and transmit it.</p>
<p id="0df7" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">4<code
class="eb hk hl hm hn b"><strong class="gt hj">CP&gt; payload size 105</strong></code>: The <code
class="eb hk hl hm hn b">sensor_coap</code> library <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/sensor_coap/src/sensor_coap.c#L57-L91"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">forwards the CoAP message to the
OIC Background Task</a> for transmission</p>
<p id="bdf9" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">5⃣ We see the <a
href="https://gist.github.com/lupyuen/08d8565dfac19771644575d242aeb7ef"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">JSON
payload</strong></a> that was composed by the <code class="eb hk hl hm hn b">sensor_coap</code>
library</p>
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib ic id ie if ig paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h12.png" /></p>
<figcaption><p><em>Real-time display of temperature sensor data,
transmitted by Blue Pill</em></p></figcaption>
</div>
<p id="0778" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">6⃣ When you run the application,
you will see the <code class="eb hk hl hm hn b">blue-pill-geolocate.appspot.com</code> <strong
class="gt hj">URL for viewing the sensor data</strong>, secured with the randomly-generated device
ID.</p>
<p id="5f29" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><strong class="gt hj">Ctrl-Click
the URL</strong> to view the live sensor data transmitted by your Blue Pill.</p>
<blockquote class="in io ip">
<p id="b54a" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://youtu.be/YrKXdxB77Oc?t=87"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Watch the video</a></p>
</blockquote>
<p id="b4d4" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The device ID changes when you
restart the application, <em class="ho">so always check the log for the updated URL.</em></p>
<p id="4313" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The sensor data display is
refreshed automatically every 10 seconds.</p>
<div class="figure hq hr hs ht hu cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
<p id="19b5" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The OIC Background Task receives
the forwarded CoAP message and transmits it by calling the <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/transport.cpp#L90-L118"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">function </a><code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/transport.cpp#L90-L118" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">oc_tx_ucast()</a></code>.
The function invokes the ESP8266 driver to send the message via UDP. <code
class="eb hk hl hm hn b">ESP send udp</code> marks the beginning of the ESP8266 Send command, which
we have covered earlier.</p>
<blockquote class="in io ip">
<p id="c3ae" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><em class="bk">💎 </em>To
conserve RAM and avoid dynamic memory allocation (which can become unpredictable), the Mynewt OIC
Library and our <code class="eb hk hl hm hn b">sensor_coap</code> library both use
network-optimised, preallocated <code
class="eb hk hl hm hn b"><a href="https://mynewt.apache.org/latest/os/core_os/mbuf/mbuf.html" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">mbuf</a></code><a
href="https://mynewt.apache.org/latest/os/core_os/mbuf/mbuf.html"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"> buffers</a> in RAM while
composing and transmitting messages.</p>
<p id="4c26" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he">The ESP8266 driver supports <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/driver.cpp#L205-L214"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">transmitting </a><code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/driver.cpp#L205-L214" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">mbuf</a></code><a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/driver.cpp#L205-L214"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"> messages</a>, so theres no
need to copy the data into into a flat array before transmission. Which saves RAM space and
processing time.</p>
</blockquote>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="ca6a" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">What is WiFi Geolocation?</h1>
<p id="2ebd" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he">Scary but true… Our mobile phones
are scanning all the WiFi Access Points in our homes and workplaces… <a
href="https://www.zdnet.com/article/how-google-and-everyone-else-gets-wi-fi-location-data/"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><em class="ho">And sending the
data to Google and Apple</em></a><em class="ho">!</em></p>
<p id="2fb2" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Thats why its possible today to
estimate your location (latitude and longitude) very accurately by transmitting to Google…</p>
<p id="356d" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">1⃣ A list of <strong
class="gt hj">WiFi Access Points</strong> visible at your location (just the unique MAC Addresses of
the Access Points) and</p>
<p id="35c7" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2<strong class="gt hj">WiFi
signal strength</strong> of each Access Point at your location. Technically its called the <strong
class="gt hj">Received Signal Strength Indication (RSSI)</strong></p>
<p id="c551" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">We call this <strong
class="gt hj">WiFi Geolocation</strong> — Google can compute your location when you give Google the
above information about the WiFi Access Points at your location.</p>
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib mv mw mx my ig">
<p><script src="https://gist.github.com/lupyuen/59b8c88647ced98b334943930d7f159f.js"></script></p>
<figcaption><p><em>Google WiFi Geolocation API Input</em></p></figcaption>
</div>
<p id="e44a" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Google offers a <a
href="https://developers.google.com/maps/documentation/geolocation/intro"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">paid WiFi Geolocation API</a> for
computing your location.</p>
<p id="9090" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">After subscribing to the service,
we transmit the MAC Addresses and Signal Strength of each WiFi Access Point to the API, as shown here.
</p>
<p id="2433" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Note that <strong
class="gt hj">we dont actually need to connect to any of these Access Points</strong>. They may be
secured, but all we need are their MAC Addresses, which are publicly accessible.</p>
<p id="2da0" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Within a second the API returns a
result like this…</p>
<pre
class="hq hr hs ht hu ma mb mc"><span id="695c" class="md jh ek bk hn b fm me mf r mg">{<br/> &quot;location&quot;: {<br/> &quot;lat&quot;: 1.273065699,<br/> &quot;lng&quot;: 103.8096223<br/> },<br/> &quot;accuracy&quot;: 40<br/>}</span></pre>
<p id="0160" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">which contains the computed
latitude <code class="eb hk hl hm hn b">1.273065699</code> and longitude <code
class="eb hk hl hm hn b">103.8096223</code>. The result also indicates that the actual location may
be up to <code class="eb hk hl hm hn b">40</code> metres away from the computed location. (We show
this by drawing a circle with radius 40, centered at the computed location.)</p>
<p id="0ece" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Lets ponder how WiFi Geolocation
may be used…</p>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="f91b" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">Why is WiFi Geolocation useful?
</h1>
<p id="8726" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he">1⃣ WiFi Geolocation works
<strong class="gt hj">indoors and outdoors</strong>. Often we connect a GPS Receiver to our
microcontroller to get the GPS location. GPS relies on satellite signals from the sky so it doesnt
work indoors. And GPS performs poorly in cloudy weather, also when there are tall buildings nearby
(the “<a href="https://en.wikipedia.org/wiki/Street_canyon"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Street Canyon</a>” effect).</p>
<p id="cbf6" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">WiFi Geolocation works as long as
there are known WiFi Access Points broadcasting at the location. Indoor, outdoor and maybe underground
too.</p>
<p id="09cd" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2⃣ WiFi Geolocation<strong
class="gt hj"> doesnt require any additional hardware</strong>… If we already have a WiFi module
like ESP8266. Well just call the ESP8266 Scan command to fetch the WiFi Access Points, and well
transmit the data to our server, which will call the Google WiFi Geolocation API. Its remarkably
similar to the way we process IoT sensor data!</p>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="0d68" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">Try WiFi Geolocation For
Yourself</h1>
<p id="b0fe" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he">To show you how well WiFi
Geolocation can compute your location, I have configured my paid account at thethings.io to call the
paid Google WiFi Geolocation API <em class="ho">when you send a list of WiFi Access Point MAC
Addresses and Signal Strength over CoAP</em>. (The exact same way we used earlier for sending sensor
data.)</p>
<p id="8508" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><em class="ho">For the purpose of
learning about WiFi Geolocation in this tutorial, Ill allow you to send Geolocation CoAP messages
to my server. I dont store any WiFi or geolocation data on my server, the data is discarded as soon
as the computation is complete.</em></p>
<p id="cfaa" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><strong
class="gt hj">Caution</strong>: The Access Point information is <strong class="gt hj">transmitted in
cleartext over CoAP UDP, without any encryption</strong>. Its theoretically possible for another
party to intercept the transmitted information and compute your location.</p>
<p id="6ebf" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><em class="ho">If you fully
understand and accept the consequences:</em> Proceed to enable WiFi Geolocation in your application:
Edit <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/targets/bluepill_my_sensor/syscfg.yml" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">targets/bluepill_my_sensor/syscfg.yml</a></code>
and uncomment this line (by removing the leading <code class="eb hk hl hm hn b">#</code>):</p>
<pre
class="hq hr hs ht hu ma mb mc"><span id="04ae" class="md jh ek bk hn b fm me mf r mg">WIFI_GEOLOCATION: 1 # Uncommented to enable WiFi Geolocation</span></pre>
<p id="e4cd" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Rebuild the application and run
it. View the log. The overall logic for geolocation is driven by the <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/geolocate.c#L35-L83" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">geolocate()</a></code><a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/geolocate.c#L35-L83"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"> function</a> thats called by the
Network Task at startup.</p>
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib mv mw mx my ig">
<p><script src="https://gist.github.com/lupyuen/5279031a07b8557ad7c11a142756e418.js"></script></p>
</div>
<p id="bc93" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">A new ESP8266 command appears in
the log: <code class="eb hk hl hm hn b">AT+CWLAP</code>. This is the command for ESP8266 to <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/esp8266/src/Controller.cpp#L204-L231"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">scan for nearby WiFi Access
Points</a>.</p>
<p id="eb38" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The program <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/geolocate.c#L44-L56"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">picks the first 3 Access
Points</a> returned by the command and <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/geolocate.c#L134-L191"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">composes a CoAP message</a>
containing…</p>
<p id="bdc4" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">1⃣ The random device ID: <code
class="eb hk hl hm hn b">device</code></p>
<p id="e0a1" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2⃣ The 3 MAC Addresses: <code
class="eb hk hl hm hn b">ssid0</code>, <code class="eb hk hl hm hn b">ssid1</code> and <code
class="eb hk hl hm hn b">ssid2</code></p>
<p id="cbc3" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">3⃣ The 3 values for Signal
Strength: <code class="eb hk hl hm hn b">rssi0</code>, <code class="eb hk hl hm hn b">rssi1</code> and
<code class="eb hk hl hm hn b">rssi2</code></p>
<p id="c243" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Then it <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/geolocate.c#L69-L82"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">transmits the CoAP message</a> to
the CoAP server for my thethings.io account.</p>
<div class="figure hq hr hs ht hu cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
<div class="figure ij cz eg hv cd hw hx hy hz ia ba ib ic id ie if ig paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h13.png" /></p>
</div>
<p id="ba84" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">When you run the application, you
will see a <code class="eb hk hl hm hn b">blue-pill-geolocate.appspot.com</code> URL for viewing your
computed geolocation thats secured with the randomly-generated device ID.</p>
<p id="e793" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><strong class="gt hj">Ctrl-Click
the URL </strong>to see your computed geolocation in the web browser (purple marker).</p>
<p id="4818" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">On the map there is a blue circle
at top right. <strong class="gt hj">Click the blue circle</strong> to see your actual location (blue
dot), as determined by your mobile device. Your actual location will not be transmitted to the server.
</p>
<p id="8389" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The device ID changes when you
restart the application, <em class="ho">so always check the log for the updated URL.</em></p>
<div class="figure hq hr hs ht hu cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
<blockquote class="in io ip">
<p id="d4c0" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><em class="bk">💎 </em>How did
I configure my account at thethings.io to call the Google WiFi Geolocation API? Check the section
“Advanced Topic: WiFi Geolocation with thethings.io and Google App Engine”</p>
</blockquote>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="da db dc dd de df ag dg ah dh aj ak">
<div class="figure hq hr hs ht hu cz">
<div class="ea r ds">
<div class="iv r"><iframe
src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FDNBk9hnPkTY%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DDNBk9hnPkTY&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FDNBk9hnPkTY%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube"
allowfullscreen="" frameborder="0" height="300" width="400"
title="WiFi Geolocation with STM32 Blue Pill, ESP8266 and Apache Mynewt" class="cp t u dw ak"
scrolling="auto"></iframe></div>
</div>
</div>
</div>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="d34d" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">Privacy Concerns</h1>
<p id="d1cb" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he">You can see for yourself — by
sending only 3 WiFi Access Points to the Google Geolocation API, its possible to <strong
class="gt hj">compute your location with high accuracy</strong>, perhaps within 10 metres of error.
</p>
<p id="24e6" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The ESP8266 has everything we
need to scan the WiFi access points and to transmit the WiFi data… <strong class="gt hj">Yet we see
ESP8266 appearing in some smart home gadgets</strong>. <em class="ho">Could these gadgets be
transmitting your location without your consent?</em></p>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="5a11" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">Whats Next?</h1>
<p id="3f3f" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he">Reflecting on my experience with
Mynewt… Its amazing that we were able to <strong class="gt hj">accomplish so much</strong> in this
tutorial with <strong class="gt hj">so little application code</strong>, thanks to the <strong
class="gt hj">excellent frameworks in Mynewt</strong>. Most of the code went into the drivers and
libraries. Please make full use of my open-source drivers and libraries to <strong class="gt hj">build
your IoT gadget in record time</strong>!</p>
<p id="5d87" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Apache Mynewt is an<strong
class="gt hj"> incredible achievement for open-source IoT embedded platforms</strong>. But its not
obvious to most people why certain Mynewt features (like the Sensor Framework) were designed that way.
So I have lined up a series of Mynewt tutorials to show you the fun and exciting <strong
class="gt hj">problems that Mynewt was designed to solve</strong></p>
<p id="1af0" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">1⃣ How I<strong class="gt hj">
configured thethings.io to receive sensor data</strong> over CoAP and <strong
class="gt hj">visualise the data with dashboards</strong></p>
<div class="dj dk dl dm dn jz"><a rel="noopener"
href="https://lupyuen.github.io/articles/build-your-iot-sensor-network-stm32-blue-pill-nrf24l01-esp8266-apache-mynewt-thethings-io">
<section class="kc cl cm ak ce n ar kd ke kf kg kh ki kj kk kl km kn ko kp kq kr">
<div class="ks n co p kt ku">
<h2 class="bj ji kv bl ek">
<div class="dx ka fo fp kb fr">Build Your IoT Sensor Network — STM32 Blue Pill + nRF24L01 +
ESP8266 + Apache Mynewt + thethings.io</div>
</h2>
</div>
<div class="ky r">
<div class="nb r la lb lc ky ld le lf"></div>
</div>
</section>
</a></div>
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib ic id ie if ig paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h14.jpeg" /></p>
<figcaption><p><em>Nordic Semiconductor nRF24L01. Porting soon to
Mynewt!</em></p></figcaption>
</div>
<p id="233b" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2⃣ How I built the<strong
class="gt hj"> Mynewt drivers</strong> <strong class="gt hj">for ESP8266 and Blue Pills internal
temperature sensor</strong>. Building drivers for Mynewt isnt hard, we just follow the conventions.
</p>
<p id="4942" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">3⃣ Ill be creating a Mynewt
driver to support <a
href="https://www.sparkfun.com/datasheets/Components/nRF24L01_prelim_prod_spec_1_2.pdf"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">Nordic
Semiconductor nRF24L01</strong></a>, a low-cost long-range wireless module operating on 2.4 GHz.
</p>
<p id="7155" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Why? To prove that its feasible
to create a <strong class="gt hj">Network -Agnostic IoT Application</strong> with Mynewt. Need to send
sensor data thru ESP8266 WiFi, nRF24L01, Zigbee, NB-IoT, LoRa or Sigfox or …? They are all supported
by the same IoT Application!</p>
<p id="d0d7" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><em class="ho">(Hint: Remember
that we created a CoAP Transport Layer for ESP8266 WiFi in this tutorial? We can do the same for any
network interface!)</em></p>
<div class="dj dk dl dm dn jz"><a rel="noopener"
href="https://lupyuen.github.io/articles/build-your-iot-sensor-network-stm32-blue-pill-nrf24l01-esp8266-apache-mynewt-thethings-io">
<section class="kc cl cm ak ce n ar kd ke kf kg kh ki kj kk kl km kn ko kp kq kr">
<div class="ks n co p kt ku">
<h2 class="bj ji kv bl ek">
<div class="dx ka fo fp kb fr">Build Your IoT Sensor Network — STM32 Blue Pill + nRF24L01 +
ESP8266 + Apache Mynewt + thethings.io</div>
</h2>
</div>
<div class="ky r">
<div class="nb r la lb lc ky ld le lf"></div>
</div>
</section>
</a></div>
<p id="ad3f" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">4⃣ Lastly Ill be writing about
this<a
href="https://detail.tmall.com/item.htm?id=568676838958"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj"> exciting
new evolution of the STM32 Blue Pill</strong></a>. <em class="ho">(</em><a
href="https://www.linkedin.com/feed/update/urn:li:activity:6525729591317893120"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><em class="ho">Check out this
update</em></a><em class="ho">)</em></p>
<div class="dj dk dl dm dn jz"><a rel="noopener"
href="https://lupyuen.github.io/articles/super-blue-pill-like-stm32-blue-pill-but-better">
<section class="kc cl cm ak ce n ar kd ke kf kg kh ki kj kk kl km kn ko kp kq kr">
<div class="ks n co p kt ku">
<h2 class="bj ji kv bl ek">
<div class="dx ka fo fp kb fr">Super Blue Pill — Like STM32 Blue Pill, But Better!</div>
</h2>
</div>
<div class="ky r">
<div class="nd r la lb lc ky ld le lf"></div>
</div>
</section>
</a></div>
<div class="figure hq hr hs ht hu cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h15.jpeg" /></p>
<figcaption><p><em>STM32 Blue Pills unnamed beefy twin brother.
Testing soon! <a
href="https://detail.tmall.com/item.htm?id=568676838958"
class="at cg hf hg hh hi" target="_blank"
rel="noopener nofollow">https://detail.tmall.com/item.htm?id=568676838958</a></em></p></figcaption>
</div>
<p id="5ccf" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">[UPDATE] I have ported the code
in this article to Rust for a safer, smarter coding experience…</p>
<div class="dj dk dl dm dn jz"><a rel="noopener"
href="https://lupyuen.github.io/articles/hosting-embedded-rust-apps-on-apache-mynewt-with-stm32-blue-pill">
<section class="kc cl cm ak ce n ar kd ke kf kg kh ki kj kk kl km kn ko kp kq kr">
<div class="ks n co p kt ku">
<h2 class="bj ji kv bl ek">
<div class="dx ka fo fp kb fr">Hosting Embedded Rust apps on Apache Mynewt with STM32 Blue
Pill</div>
</h2>
</div>
<div class="ky r">
<div class="ng r la lb lc ky ld le lf"></div>
</div>
</section>
</a></div>
<p id="1ee5" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">We have a new tutorial on
connecting Blue Pill to NB-IoT…</p>
<div class="dj dk dl dm dn jz"><a rel="noopener"
href="https://lupyuen.github.io/articles/connect-stm32-blue-pill-to-nb-iot-with-quectel-bc95-g-and-apache-mynewt">
<section class="kc cl cm ak ce n ar kd ke kf kg kh ki kj kk kl km kn ko kp kq kr">
<div class="ks n co p kt ku">
<h2 class="bj ji kv bl ek">
<div class="dx ka fo fp kb fr">Connect STM32 Blue Pill to NB-IoT with Quectel BC95-G and
Apache Mynewt</div>
</h2>
</div>
<div class="ky r">
<div class="nh r la lb lc ky ld le lf"></div>
</div>
</section>
</a></div>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<blockquote class="in io ip">
<p id="c062" class="gr gs ek ho gt b gu gv gw gx gy gz ha hb hc hd he"><em class="bk">💎 </em>The
following Advanced Topic sections are for advanced developers. If youre new to embedded
programming, you may stop here.</p>
</blockquote>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="f84a" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">💎 Advanced Topic: Improve the
Accuracy of WiFi Geolocation</h1>
<p id="799a" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he"><em class="ho">(Skip this section
if youre happy with the accuracy of the WiFi Geolocation)</em></p>
<p id="bbf6" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Since we are sending only 3 WiFi
Access Points to the Google WiFi Geolocation API, we ought to pick the Access Points that really
matter. Here are some tips to improve the accuracy…</p>
<p id="2888" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">1⃣ The program calls a <strong
class="gt hj">Filter Function</strong> <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/geolocate.c#L85-L110" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">filter_func()</strong></a></code>
to determine whether it should accept or reject an Access Point that has just been detected. <code
class="eb hk hl hm hn b">filter_func()</code> implements 2 types of checks…</p>
<p id="80bf" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2⃣ Reject an Access Point whose
<strong class="gt hj">MAC Address matches a pattern</strong>. If were connecting the ESP8266 to a
mobile hotspot, we should blacklist the hotspot from being selected as one of the 3 Access Points.
Because mobile hotspots dont have fixed locations and they are not useful for computing geolocation.
</p>
<p id="c4c0" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The matching of MAC Addresses is
done by <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/geolocate.c#L112-L121" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">mac_matches_pattern()</strong></a></code>.
</p>
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib mv mw mx my ig">
<p><script src="https://gist.github.com/lupyuen/f71558ca5ee1757e24c02b27985bb037.js"></script></p>
</div>
<p id="1a05" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The function matches each Access
Points MAC Address against a blacklist of patterns defined in the array <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/geolocate.c#L20-L26" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">skip_ssid</strong></a></code>.
</p>
<p id="c099" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">In this example, any MAC
Addresses matching the patterns <code class="eb hk hl hm hn b">fc:39:98:*:*:*</code> or <code
class="eb hk hl hm hn b">00:87:01:*:*:*</code> will be excluded, since such MAC Addresses belong to
Apple or Samsung mobile devices.</p>
<p id="6385" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">If you have a MAC Address that
should be excluded, add to <code class="eb hk hl hm hn b">skip_ssid</code> before <code
class="eb hk hl hm hn b">LAST_MAC_PATTERN</code>.</p>
<p id="8ebf" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">3⃣ Reject <strong
class="gt hj">similar</strong> <strong class="gt hj">MAC Addresses</strong>. If two Access Points
have MAC Addresses that differ in only 1 byte, e.g. <code
class="eb hk hl hm hn b">01:02:03:04:05:<strong class="gt hj">06</strong></code> and <code
class="eb hk hl hm hn b">01:02:03:04:05:<strong class="gt hj">ab</strong></code>, then both Access
Points most likely belong to the same WiFi Router with multiple network interfaces (like 2.4 GHz vs 5
GHz interfaces). When we select two MAC Addresses from the same WiFi Router for computing geolocation,
we are actually submitting redundant data that produces a geolocation that is less precise.</p>
<p id="0ccb" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The function <code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/apps/my_sensor_app/src/geolocate.c#L123-L129" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">similar_mac()</strong></a></code>
rejects any Access Point whose MAC Address is similar (they differ in only 1 byte) to any MAC Address
that has already been selected.</p>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="09f7" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">💎 Advanced Topic: WiFi
Geolocation with thethings.io and Google App Engine</h1>
<p id="4026" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he">If youre building an IoT System
to process and visualise sensor data, thethings.io has everything you need. To protect your IoT data,
only users of thethings.io will be able to view the dashboards.</p>
<p id="6acf" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">For this tutorial I decided to
make the data available for viewing by the public (as long as you have a valid device ID). So I added
one component to extend thethings.io: A web application hosted on Google Cloud App Engine thats
publicly accessible. Heres how thethings.io and the web application work together to execute
geolocation requests and display sensor data…</p>
<blockquote class="lg">
<div id="b537" class="lh li lj bk el b lk ll lm ln lo lp he">
<p class="el b lq lr bo">thethings.io</p>
</div>
</blockquote>
<div class="figure ls lt lu lv lw cz eg hv cd hw hx hy hz ia ba ib ic id ie if ig paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h16.png" /></p>
<figcaption><p><em>Cloud Code Trigger “<code
class="eb hk hl hm hn b">forward_geolocate&quot; and Cloud Code Function &quot;geolocate&quot; installed in my thethings.io account</code>
</em></p></figcaption>
</div>
<p id="ebf8" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">In my account at thethings.io, I
created a Cloud Code Trigger <code class="eb hk hl hm hn b">forward_geolocate</code> and a Cloud Code
Function <code class="eb hk hl hm hn b">geolocate</code>. The two components work together to execute
geolocation requests and forward sensor data to the web application…</p>
<p id="fa33" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">1<code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/thethingsio-wifi-geolocation/blob/master/forward_geolocate.js" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">forward_geolocate</strong></a></code>
is a Cloud Code Trigger thats called upon receiving sensor data through any channel (including the
CoAP server that were using in this tutorial). As we have seen earlier, our device transmits the
temperature data in this JSON format…</p>
<div class="figure hq hr hs ht hu cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
<pre
class="hq hr hs ht hu ma mb mc"><span id="30e2" class="md jh ek bk hn b fm me mf r mg">[ {&quot;key&quot;: &quot;device&quot;, &quot;value&quot;: &quot;01027f231f13739e8633f3b7da4e439f&quot; },<br/> {&quot;key&quot;: &quot;tmp&quot;, &quot;value&quot;: 28.95} ]</span></pre>
<p id="25ce" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b">forward_geolocate</code> transforms the JSON into…</p>
<pre
class="hq hr hs ht hu ma mb mc"><span id="2f6e" class="md jh ek bk hn b fm me mf r mg">{ &quot;device&quot;: &quot;01027f231f13739e8633f3b7da4e439f&quot;, &quot;tmp&quot;: 28.95 }</span></pre>
<p id="0a6f" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">It pushes the transformed JSON to
our web application at the URL <code class="eb hk hl hm hn b">/push</code> (described below). This
allows the sensor data to be viewed through the web server.</p>
<p id="8d9d" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">If the sensor data contains <code
class="eb hk hl hm hn b">ssid</code> and <code class="eb hk hl hm hn b">rssi</code> values, <code
class="eb hk hl hm hn b">forward_geolocate</code> doesnt push the data to the web application.
Instead, it forwards the data to the Cloud Code Function <code
class="eb hk hl hm hn b">geolocate</code>.</p>
<p id="1049" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2<code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/thethingsio-wifi-geolocation/blob/master/geolocate.js" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">geolocate</strong></a></code>
is a Cloud Code Function called by <code class="eb hk hl hm hn b">forward_geolocate</code> to perform
geolocation. The input contains 3 <code class="eb hk hl hm hn b">ssid</code> and 3 <code
class="eb hk hl hm hn b">rssi</code> values, representing the 3 WiFi Access Points scanned by the
ESP8266.</p>
<p id="13d6" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b">geolocate</code> calls the Google WiFi Geolocation API, passing the <code
class="eb hk hl hm hn b">ssid</code> and <code class="eb hk hl hm hn b">rssi</code> values. The
Geolocation API returns the computed latitude, longitude and accuracy. This information is passed by
<code class="eb hk hl hm hn b">geolocate</code> back to <code
class="eb hk hl hm hn b">forward_geolocate</code></p>
<p id="baf8" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">3⃣ When <code
class="eb hk hl hm hn b">forward_geolocate</code> receives the computed latitude, longitude and
accuracy, it composes a JSON like this…</p>
<pre
class="hq hr hs ht hu ma mb mc"><span id="24e9" class="md jh ek bk hn b fm me mf r mg">{ &quot;device&quot;: &quot;01027f231f13739e8633f3b7da4e439f&quot;, <br/> &quot;latitude&quot;: 1.274, &quot;longitude&quot;: 103.81, &quot;accuracy&quot;: 40.1 }</span></pre>
<p id="4c07" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">And pushes the JSON to our web
application at the URL <code class="eb hk hl hm hn b">/push</code> (described below). This allows the
computed geolocation to be viewed through the web server.</p>
<p id="86f1" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">More on the features that I have
implemented in thethings.io…</p>
<div class="dj dk dl dm dn jz"><a
href="https://github.com/lupyuen/thethingsio-wifi-geolocation?source=post_page-----7edceb9e3b8d----------------------"
rel="noopener nofollow">
<section class="kc cl cm ak ce n ar kd ke kf kg kh ki kj kk kl km kn ko kp kq kr">
<div class="ks n co p kt ku">
<h2 class="bj ji kv bl ek">
<div class="dx ka fo fp kb fr">lupyuen/thethingsio-wifi-geolocation</div>
</h2>
</div>
<div class="ky r">
<div class="nk r la lb lc ky ld le lf"></div>
</div>
</section>
</a></div>
<blockquote class="lg">
<div id="1e30" class="lh li lj bk el b lk ll lm ln lo lp he">
<p class="el b lq lr bo">Web Application</p>
</div>
</blockquote>
<p id="8fb4" class="gr gs ek bk gt b gu mq gw mr gy ms ha mt hc mu he">The web application was built
with Go, hosted on <a
href="https://cloud.google.com/appengine/docs/standard/go111/"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Google Cloud App Engine Standard
Environment</a>. The web application receives sensor and geolocation data from thethings.io and
renders the data. The data is visible only to users with a valid device ID.</p>
<p id="fd6b" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">1<code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/gcloud-wifi-geolocation/blob/master/main.go" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">main.go</strong></a></code>
is the server-side Go program that implements two functions at these URLs…</p>
<p id="b9e7" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b"><strong class="gt hj">/push</strong></code>: Receives a JSON document <code
class="eb hk hl hm hn b">POST</code>ed by <code class="eb hk hl hm hn b">forward_geolocate</code>
that contains one or more sensor values for a device:</p>
<pre
class="hq hr hs ht hu ma mb mc"><span id="6295" class="md jh ek bk hn b fm me mf r mg">{ &quot;device&quot;: &quot;01027f231f13739e8633f3b7da4e439f&quot;, &quot;tmp&quot;: 28.95 }</span><span id="4b41" class="md jh ek bk hn b fm nl nm nn no np mf r mg">{ &quot;device&quot;: &quot;01027f231f13739e8633f3b7da4e439f&quot;, <br/> &quot;latitude&quot;: 1.274, &quot;longitude&quot;: 103.81, &quot;accuracy&quot;: 40.1 }</span></pre>
<p id="7c28" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The program merges the sensor
values into the Device State and remembers the updated Device State in RAM:</p>
<pre
class="hq hr hs ht hu ma mb mc"><span id="51c6" class="md jh ek bk hn b fm me mf r mg">{ &quot;device&quot;: &quot;01027f231f13739e8633f3b7da4e439f&quot;, <br/> &quot;tmp&quot;: 28.95, <br/> &quot;latitude&quot;: 1.274, &quot;longitude&quot;: 103.81, &quot;accuracy&quot;: 40.1 }</span></pre>
<p id="f6d5" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The Device States in memory are
lost when the server is restarted automatically during an idle period with no requests.</p>
<p id="5d5c" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><code
class="eb hk hl hm hn b"><strong class="gt hj">/pull</strong></code>: Return the JSON Device State
for a device ID. Called by <code class="eb hk hl hm hn b">index.html</code>. The Device State contains
all sensor values for the device received so far:</p>
<pre
class="hq hr hs ht hu ma mb mc"><span id="bb81" class="md jh ek bk hn b fm me mf r mg">{ &quot;device&quot;: &quot;01027f231f13739e8633f3b7da4e439f&quot;, <br/> &quot;tmp&quot;: 28.95, <br/> &quot;latitude&quot;: 1.274, &quot;longitude&quot;: 103.81, &quot;accuracy&quot;: 40.1 }</span></pre>
<p id="22bf" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2<code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/gcloud-wifi-geolocation/blob/master/public/index.html" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"><strong class="gt hj">index.html</strong></a></code>
is a static HTML page with client-side JavaScript that renders the map using the <a
href="https://docs.mapbox.com/mapbox-gl-js/overview/"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Mapbox GL JavaScript API</a>.</p>
<p id="8beb" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The JavaScript polls the <code
class="eb hk hl hm hn b"><strong class="gt hj">/pull</strong></code> URL every 10 seconds via the
<code
class="eb hk hl hm hn b"><a href="https://developers.google.com/web/updates/2015/03/introduction-to-fetch?authuser=0" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">fetch</a></code><a
href="https://developers.google.com/web/updates/2015/03/introduction-to-fetch?authuser=0"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"> API</a>. When it detects any
changes to the sensor data (including location), it updates the map.</p>
<p id="ae42" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Check out the Go source code for
the web application here…</p>
<div class="dj dk dl dm dn jz"><a
href="https://github.com/lupyuen/gcloud-wifi-geolocation?source=post_page-----7edceb9e3b8d----------------------"
rel="noopener nofollow">
<section class="kc cl cm ak ce n ar kd ke kf kg kh ki kj kk kl km kn ko kp kq kr">
<div class="ks n co p kt ku">
<h2 class="bj ji kv bl ek">
<div class="dx ka fo fp kb fr">lupyuen/gcloud-wifi-geolocation</div>
</h2>
</div>
<div class="ky r">
<div class="nq r la lb lc ky ld le lf"></div>
</div>
</section>
</a></div>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="fc69" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">💎 Advanced Topic: Whats
Inside The CoAP Message?</h1>
<p id="e924" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he"><em class="ho">(Skip this section
if youre not interested in decoding CoAP messages)</em></p>
<p id="7563" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Earlier we saw the ESP8266 Send
command transmit this mysterious UDP packet containing 177 bytes to our server…</p>
<div class="figure hq hr hs ht hu cz">
<p><script src="https://gist.github.com/lupyuen/8cb3afa5b765948dca7970dd37aa2e01.js"></script></p>
</div>
<p id="2c25" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Thats a CoAP message, based on
UDP. The message data is displayed in two sections separated by a newline…</p>
<pre
class="hq hr hs ht hu ma mb mc"><span id="f8e5" class="md jh ek bk hn b fm me mf r mg">58 02 00 01 00 00 16 4a 27 2a e2 39 b2 76 32 06 74 68 69 6e 67 73 0d 1e 49 56 52 69 42 43 63 52 36 48 50 70 5f 43 63 5a 49 46 66 4f 5a 46 78 7a 5f 69 7a 6e 69 35 78 63 5f 4b 4f 2d 6b 67 53 41 32 59 38 11 32 51 32 ff</span><span id="a26c" class="md jh ek bk hn b fm nl nm nn no np mf r mg">7b 22 76 61 6c 75 65 73 22 3a 20 5b 7b 22 6b 65 79 22 3a 20 22 64 65 76 69 63 65 22 2c 22 76 61 6c 75 65 22 3a 20 22 36 63 30 31 33 30 37 63 30 63 32 34 62 39 37 31 66 30 34 62 32 34 39 62 37 31 36 34 36 36 30 30 22 7d 2c 7b 22 6b 65 79 22 3a 20 22 74 6d 70 22 2c 22 76 61 6c 75 65 22 3a 20 32 39 2e 38 36 7d 5d 7d</span></pre>
<p id="a328" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The top part contains the <strong
class="gt hj">CoAP message header</strong> (which always ends with <code
class="eb hk hl hm hn b">ff</code>) while the bottom part contains the <strong class="gt hj">CoAP
payload</strong> (notice that its all <a
href="https://en.wikipedia.org/wiki/ASCII"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">ASCII</a>!) To decode the entire
message, well use open-source <a
href="https://www.wireshark.org/"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Wireshark</a> (available for
Windows, macOS and Linux).</p>
<p id="2f4c" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">1⃣ Copy both parts of the
message and paste into a new text file, say <code class="eb hk hl hm hn b">coap.txt</code>. We may use
Visual Studio Code to create the file…</p>
<div class="figure hq hr hs ht hu cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h17.png" /></p>
<figcaption><p><em>Creating the CoAP message file with Visual
Studio Code</em></p></figcaption>
</div>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="da db dc dd de df ag dg ah dh aj ak">
<div class="figure hq hr hs ht hu cz do dp paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<p id="3483" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">2⃣ Install and launch Wireshark.
</p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="da db dc dd de df ag dg ah dh aj ak">
<div class="figure hq hr hs ht hu cz do dp paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<div class="figure hq hr hs ht hu cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h18.png" /></p>
</div>
<p id="bf80" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">3⃣ Click <code
class="eb hk hl hm hn b"><strong class="gt hj">File → Import From Hex Dump</strong></code></p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="da db dc dd de df ag dg ah dh aj ak">
<div class="figure hq hr hs ht hu cz do dp paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<div class="figure hq hr hs ht hu cz eg hv cd hw hx hy hz ia ba ib ic id ie if ig paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h19.png" /></p>
</div>
<p id="083b" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">4⃣ Click <code
class="eb hk hl hm hn b"><strong class="gt hj">Browse</strong></code> to select the text file that
we have created, e.g. <code class="eb hk hl hm hn b">coap.txt</code></p>
<p id="3806" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">For <code
class="eb hk hl hm hn b"><strong class="gt hj">Offsets</strong></code>, select <code
class="eb hk hl hm hn b"><strong class="gt hj">None</strong></code></p>
<p id="adba" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">For <code
class="eb hk hl hm hn b"><strong class="gt hj">Encapsulation Type</strong></code>, <br />select
<code class="eb hk hl hm hn b"><strong class="gt hj">Ethernet</strong></code></p>
<p id="1613" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Click <code
class="eb hk hl hm hn b"><strong class="gt hj">UDP</strong></code></p>
<p id="12ba" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Set <code
class="eb hk hl hm hn b"><strong class="gt hj">Source Port</strong></code> to <code
class="eb hk hl hm hn b"><strong class="gt hj">1</strong></code></p>
<p id="43e9" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Set <code
class="eb hk hl hm hn b"><strong class="gt hj">Destination Port</strong></code> to <code
class="eb hk hl hm hn b"><strong class="gt hj">5683</strong></code><br />(the CoAP port number, so
that Wireshark will recognise this as a CoAP message)</p>
<p id="4e12" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Click <code
class="eb hk hl hm hn b"><strong class="gt hj">Import</strong></code></p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="da db dc dd de df ag dg ah dh aj ak">
<div class="figure hq hr hs ht hu cz do dp paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<div class="figure hq hr hs ht hu cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h20.png" /></p>
</div>
<p id="e4d0" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">5⃣ Wireshark decodes and
displays the <strong class="gt hj">CoAP Header</strong> (which includes the URI) and the <strong
class="gt hj">CoAP Payload</strong></p>
</div>
</div>
<div class="cz">
<div class="n p">
<div class="da db dc dd de df ag dg ah dh aj ak">
<div class="figure hq hr hs ht hu cz do dp paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
</div>
</div>
</div>
</div>
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<p id="f55d" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The CoAP Payload contains <em
class="ho">exactly the same sensor data JSON that we have composed earlier, as shown in the
log!</em></p>
<div class="figure hq hr hs ht hu cz">
<p><script src="https://gist.github.com/lupyuen/08d8565dfac19771644575d242aeb7ef.js"></script></p>
</div>
<p id="4aa4" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Heres the log…</p>
<div class="figure hq hr hs ht hu cz">
<p><script src="https://gist.github.com/lupyuen/4f715bdcf688aee65d4013095d58d57c.js"></script></p>
</div>
<p id="5f17" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">Thats how we may decode and
troubleshoot CoAP messages generated by the application. Wireshark also works for CoAP Payloads
encoded in CBOR.</p>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="da1d" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">💎 Advanced Topic: Application
ROM Usage</h1>
<p id="5532" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he">Heres the detailed ROM memory
usage of the application in this tutorial (total 44 KB ROM). It was created using the <a
class="at cg hf hg hh hi" target="_blank" rel="noopener"
href="https://lupyuen.github.io/articles/stm32-blue-pill-analyse-and-optimise-your-ram-and-rom">memory
map spreadsheet that I described in an earlier article</a>. The full spreadsheet is <a
href="https://docs.google.com/spreadsheets/d/1Xn5fiV3OafsAETZOtuAbUTMm7Yswq8X72AsvKGAarD0/edit#gid=381366828&amp;fvid=1359565135"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">available here</a>.</p>
</div>
</div>
<div class="cz ak">
<div class="figure hq hr hs ht hu cz ak paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h21.png" /></p>
<figcaption><p><em>ROM usage of the application. From <a
href="https://docs.google.com/spreadsheets/d/1Xn5fiV3OafsAETZOtuAbUTMm7Yswq8X72AsvKGAarD0/edit#gid=381366828&amp;fvid=1359565135"
class="at cg hf hg hh hi" target="_blank"
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Xn5fiV3OafsAETZOtuAbUTMm7Yswq8X72AsvKGAarD0/edit#gid=381366828&amp;fvid=1359565135</a>
</em></p></figcaption>
</div>
</div>
</section>
<hr class="ix fl iy iz ja ik jb jc jd je jf" />
<section class="cu cv cw cx cy">
<div class="n p">
<div class="ac ae af ag ah eh aj ak">
<h1 id="6f33" class="jg jh ek bk bj ji jj jk jl jm jn jo jp jq jr js jt">💎 Advanced Topic: How Random
Is The Device ID?</h1>
<p id="f6e9" class="gr gs ek bk gt b gu ju gw jv gy jw ha jx hc jy he">The device ID was generated with
the open-source TinyCrypt librarys HMAC PRNG (pseudorandom number generator).</p>
<p id="1e7c" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he"><a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/hmac_prng/src/hmac_prng.c#L16-L51"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">Our </a><code
class="eb hk hl hm hn b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/hmac_prng/src/hmac_prng.c#L16-L51" class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">hmac_prng</a></code><a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/hmac_prng/src/hmac_prng.c#L16-L51"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow"> library</a> simply calls
TinyCrypt, passing an entropy seed to initialise the generator.</p>
<p id="1f7f" class="gr gs ek bk gt b gu gv gw gx gy gz ha hb hc hd he">The 32-bit entropy seed is
computed by <a
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/master/libs/temp_stm32/src/temp_stm32.c#L207-L276"
class="at cg hf hg hh hi" target="_blank" rel="noopener nofollow">aggregating 64 temperature samples
from Blue Pills internal temperature sensor</a>.</p>
<div class="figure hq hr hs ht hu cz cl cm paragraph-image">
<p><img src="https://lupyuen.github.io/images/legacy2/h22.png" /></p>
<figcaption><p><em>32-bit entropy seed for HMAC PRNG created with
Blue Pills internal temperature sensor</em></p></figcaption>
</div>
</div>
</div>
</section>
</div>
</article>
</div>
</div>
<ul>
<li>
<p><a href="https://github.com/sponsors/lupyuen">Sponsor me a coffee</a></p>
</li>
<li>
<p><a href="https://lupyuen.github.io">Check out my articles</a></p>
</li>
<li>
<p><a href="https://lupyuen.github.io/rss.xml">RSS Feed</a></p>
</li>
</ul>
</body>
</html>
<!--
FILE ARCHIVED ON 19:42:51 Dec 04, 2019 AND RETRIEVED FROM THE
INTERNET ARCHIVE ON 01:30:18 Feb 23, 2021.
JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE.
ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C.
SECTION 108(a)(3)).
-->
<!--
playback timings (ms):
exclusion.robots: 0.4
captures_list: 565.072
esindex: 0.011
CDXLines.iter: 22.339 (3)
PetaboxLoader3.resolve: 36.012
LoadShardBlock: 525.053 (3)
load_resource: 1552.272
exclusion.robots.policy: 0.383
PetaboxLoader3.datanode: 1930.262 (4)
RedisCDXSource: 14.071
-->