mirror of
https://github.com/lupyuen/lupyuen.github.io.git
synced 2025-01-13 10:18:33 +08:00
2366 lines
No EOL
183 KiB
HTML
2366 lines
No EOL
183 KiB
HTML
<!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 can’t 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 we’ll 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. We’ll 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 we’re 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. We’ll 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">You’ll 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">Here’s 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&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DYrKXdxB77Oc&image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FYrKXdxB77Oc%2Fhqdefault.jpg&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&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 you’re 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 haven’t
|
||
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">Here’s 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">Let’s 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 Pill’s 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 it’s easy to
|
||
configure a sensor to be polled at regular intervals. Mynewt’s 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">We’ll create a Mynewt driver for
|
||
ESP8266 that supports multitasking, with locking to prevent multiple commands from running
|
||
concurrently. Mynewt supports CoAP so we’ll 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 don’t 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 Pill’s
|
||
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
|
||
Pill’s 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 that’s 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
|
||
Mynewt’s 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 Mynewt’s
|
||
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. That’s 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, it’s 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. We’ll 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">Let’s 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 haven’t. 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: '"my_ssid"'<br/> <br/> # Password for WiFi access point<br/> WIFI_PASSWORD: '"my_password_is_secret"'</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">'"</code>
|
||
and end with <code class="eb hk hl hm hn b">"'</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">'</code> character, use <code
|
||
class="eb hk hl hm hn b">''</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's SSID<br/> WIFI_SSID: '"My Home''s SSID"'</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">"</code> character, use <code class="eb hk hl hm hn b">\"</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 "SSID" goes here<br/> WIFI_SSID: '"My \"SSID\" goes here"'</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">We’re 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 what’s really
|
||
happening under the hood, let’s 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">We’ll 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">Let’s 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></code> flags the commands that we
|
||
sent to ESP8266<br /><code class="eb hk hl hm hn b">AT<</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. Here’s 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> (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< ERROR</code> caused by the newline that we sent. It’s 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">Here’s 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>. It’s 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.
|
||
Here’s 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, we’ll 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
|
||
didn’t 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, it’s 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 it’s too tedious to set up your own CoAP server. (I’m
|
||
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 don’t,<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 it’s 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>.
|
||
It’s 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 there’s 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>What’s
|
||
in the 177 bytes of the UDP packet? Check the section “Advanced Topic: What’s 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, I’ll save us the trouble of sourcing for an actual BME280… we’ll just use Blue Pill’s
|
||
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 Pill’s 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 doesn’t 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 it’s 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 it’s 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">Mynewt’s 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. Let’s 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 — it’s 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">Mynewt’s OIC library doesn’t
|
||
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. Let’s
|
||
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">Let’s 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">Mynewt’s 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">Mynewt’s 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 didn’t 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, I’ll 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">I’ll 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 that’s 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">doesn’t 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 sensor’s 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">won’t 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. That’s 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>, you’ll 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> 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 there’s 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">That’s why it’s 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 it’s 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 don’t 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/> "location": {<br/> "lat": 1.273065699,<br/> "lng": 103.8096223<br/> },<br/> "accuracy": 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">Let’s 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 doesn’t
|
||
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"> doesn’t require any additional hardware</strong>… If we already have a WiFi module
|
||
like ESP8266. We’ll just call the ESP8266 Scan command to fetch the WiFi Access Points, and we’ll
|
||
transmit the data to our server, which will call the Google WiFi Geolocation API. It’s 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, I’ll allow you to send Geolocation CoAP messages
|
||
to my server. I don’t 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>. It’s 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> that’s 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 that’s 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&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DDNBk9hnPkTY&image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FDNBk9hnPkTY%2Fhqdefault.jpg&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&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, it’s 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">What’s 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… It’s 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 it’s 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 Pill’s internal
|
||
temperature sensor</strong>. Building drivers for Mynewt isn’t 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️⃣ I’ll 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 it’s 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 I’ll 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 Pill’s 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 you’re 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 you’re 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 we’re 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 don’t 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
|
||
Point’s 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 you’re 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 that’s
|
||
publicly accessible. Here’s 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" and Cloud Code Function "geolocate" 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 that’s called upon receiving sensor data through any channel (including the
|
||
CoAP server that we’re 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">[ {"key": "device", "value": "01027f231f13739e8633f3b7da4e439f" },<br/> {"key": "tmp", "value": 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">{ "device": "01027f231f13739e8633f3b7da4e439f", "tmp": 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> doesn’t 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">{ "device": "01027f231f13739e8633f3b7da4e439f", <br/> "latitude": 1.274, "longitude": 103.81, "accuracy": 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">{ "device": "01027f231f13739e8633f3b7da4e439f", "tmp": 28.95 }</span><span id="4b41" class="md jh ek bk hn b fm nl nm nn no np mf r mg">{ "device": "01027f231f13739e8633f3b7da4e439f", <br/> "latitude": 1.274, "longitude": 103.81, "accuracy": 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">{ "device": "01027f231f13739e8633f3b7da4e439f", <br/> "tmp": 28.95, <br/> "latitude": 1.274, "longitude": 103.81, "accuracy": 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">{ "device": "01027f231f13739e8633f3b7da4e439f", <br/> "tmp": 28.95, <br/> "latitude": 1.274, "longitude": 103.81, "accuracy": 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: What’s
|
||
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 you’re 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">That’s 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 it’s 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, we’ll 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">Here’s 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">That’s 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">Here’s 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&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&fvid=1359565135"
|
||
class="at cg hf hg hh hi" target="_blank"
|
||
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Xn5fiV3OafsAETZOtuAbUTMm7Yswq8X72AsvKGAarD0/edit#gid=381366828&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 library’s 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 Pill’s 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 Pill’s 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
|
||
--> |