blob: 515a7775700af6fcf2308be9c2a30df5cace1382 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- This is broken by doc revisioning.
-->
<link rel="shortcut icon" href="../../../img/favicon.ico">
<title>BLE-enabled Air Quality Sensor - Apache Mynewt</title>
<link href="../../../css/bootstrap-3.0.3.min.css" rel="stylesheet">
<link rel="stylesheet" href="../../../css/highlight.css">
<link href="../../../css/base.css" rel="stylesheet">
<link href="../../../css/custom.css" rel="stylesheet">
<link href="../../../css/v2.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
<script>
(function(i, s, o, g, r, a, m) {
i["GoogleAnalyticsObject"] = r;
(i[r] =
i[r] ||
function() {
(i[r].q = i[r].q || []).push(arguments);
}),
(i[r].l = 1 * new Date());
(a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m);
})(window, document, "script", "//www.google-analytics.com/analytics.js", "ga");
ga("create", "UA-72162311-1", "auto");
ga("send", "pageview");
</script>
</head>
<body class="BLE-enabled Air Quality Sensor">
<div class="container">
<div class="row v2-main-banner">
<a class="logo-cell" href="/">
<img class="logo" src="/img/logo.png">
</a>
<div class="tagline-cell">
<h4 class="tagline">An OS to build, deploy and securely manage billions of devices</h4>
</div>
<div class="news-cell">
<div class="well">
<h4>Latest News:</h4> <a href="/download">Apache Mynewt 1.11.0, Apache NimBLE 1.6.0 </a> released (September 7, 2023)
</div>
</div>
</div>
</div>
<nav id="navbar" class="navbar navbar-inverse affix-top" data-spy="affix" data-offset-top="150" role="navigation">
<div class="container">
<!-- Collapsed navigation -->
<div class="navbar-header">
<!-- Expander button -->
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<!-- Expanded navigation -->
<div class="navbar-collapse collapse">
<!-- Main navigation -->
<ul class="nav navbar-nav navbar-right">
<li
class=""
>
<a href="/"><i class="fa fa-home" style="font-size: larger;"></i></a>
</li>
<li
class="important"
>
<a href="/quick-start/">Quick Start</a>
</li>
<li
class=""
>
<a href="/about/">About</a>
</li>
<li
class=""
>
<a href="/talks/">Talks</a>
</li>
<li
class="active"
>
<a href="/documentation/">Documentation</a>
</li>
<li
class=""
>
<a href="/download/">Download</a>
</li>
<li
class=""
>
<a href="/community/">Community</a>
</li>
<li
class=""
>
<a href="/events/">Events</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-md-3 v2-sidebar sidebar-container"><div id="docSidebar" class="hidden-print" role="complementary">
<div class="top">
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../../../search.html" method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search documentation" />
</div>
</form>
</div>
</div>
<ul class="toc-nav">
<li class="doc-version"><select class="form-control" onchange="if (this.value) window.location.href=this.value">
<option value="/latest">
Version: master
</option>
<option value="/v1_11_0/" >
Version: 1.11.0
</option>
<option value="/v1_10_0/" >
Version: 1.10.0
</option>
<option value="/v1_9_0/" >
Version: 1.9.0
</option>
<option value="/v1_8_0/" >
Version: 1.8.0
</option>
<option value="/v1_7_0/" >
Version: 1.7.0
</option>
<option value="/v1_6_0/" >
Version: 1.6.0
</option>
<option value="/v1_5_0/" >
Version: 1.5.0
</option>
<option value="/v1_4_0/" >
Version: 1.4.0
</option>
<option value="/v1_3_0/os/introduction" selected="selected" >
Version: 1.3.0
</option>
<option value="/v1_2_0/os/introduction" >
Version: 1.2.0
</option>
<option value="/v1_1_0/os/introduction" >
Version: 1.1.0
</option>
<option value="/v1_0_0/os/introduction" >
Version: 1.0.0
</option>
<option value="/v0_9_0/os/introduction" >
Version: 0.9.0
</option>
</select></li>
<li ><a href="../../introduction/">Mynewt Documentation</a>
<ul>
<li ><a href="../../get_started/get_started/">Basic Setup</a>
</li>
<li >
<a href="../../get_started/vocabulary/">Concepts</a>
</li>
<li ><a href="../tutorials/">Tutorials</a>
<ul>
<li ><a href="../blinky/">Project Blinky</a>
</li>
<li ><a href="../repo/add_repos/">Work with repositories</a>
</li>
<li ><a href="../project-slinky/">Project Slinky for Remote Comms</a>
</li>
<li><a href="
../ble_bare_bones/
">Bluetooth Low Energy</a>
</li>
<li><a href="
../lora/lorawanapp/
">LoRa</a>
</li>
<li><a href="
../event_queue/
">OS Fundamentals</a>
</li>
<li><a href="
../add_newtmgr/
">Remote Device Management</a>
</li>
<li><a href="
../sensors/sensors/
">Sensors</a>
<ul>
<li ><a href="../sensors/sensors/">Sensor Framework</a>
</li>
<li><a href="
../air_quality_sensor/
">Air-quality Sensor project</a>
<ul>
<li >
<a href="../air_quality_sensor/">Basic Air Quality Sensor</a>
</li>
<li class="active">
<a href="./">BLE-enabled Air Quality Sensor</a>
</li>
</ul>
</li>
<li >
<a href="../nrf52_adc/">Add an Analog Sensor</a>
</li>
</ul>
</li>
<li><a href="
../segger_rtt/
">Tooling</a>
</li>
<li><a href="
../codesize/
">Other</a>
</li>
</ul>
</li>
<li ><a href="../../os_user_guide/">OS User Guide</a>
</li>
<li><a href="
../../../network/ble/ble_intro/
">BLE User Guide</a>
</li>
<li ><a href="../../../newt/newt_intro/">Newt Tool Guide</a>
</li>
<li ><a href="../../../newtmgr/overview/">Newt Manager Guide</a>
</li>
<li >
<a href="../../../known_issues/">Known Issues</a>
</li>
</ul>
</li>
<li><a href="
../../../newt/install/prev_releases/
">Appendix</a>
</li>
</ul>
</div></div>
<div class="col-md-9" role="main">
<div class="doc-header">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="/documentation/">Docs</a></li>
<li>&raquo; <a href="os/tutorials/air_quality_sensor/">Air-quality Sensor project</a></li>
<li>&raquo; Sensors</li>
<li>&raquo; <a href="os/tutorials/tutorials/">Tutorials</a></li>
<li>&raquo; <a href="os/introduction/">Mynewt Documentation</a></li>
<li>&raquo; BLE-enabled Air Quality Sensor</li>
<li class="wy-breadcrumbs-aside">
<a href="https://github.com/apache/mynewt-site/blob/master/docs/os/tutorials/air_quality_ble.md"
class="icon icon-github"> Edit on GitHub</a>
</li>
</ul>
</div>
</div>
<div class="alert alert-warning">
<p>
Version 1.3.0 is not the most recent version of the Apache Mynewt
documentation. Click <a href="/latest">here</a> to read the latest
version.
</p>
</div>
<h2 id="air-quality-sensor-project-via-bluetooth">Air quality sensor project via Bluetooth</h2>
<p>This is a follow-on project to the <a href="../air_quality_sensor/">Basic Air Quality Sensor</a> project; so it is
assumed that you have worked through that project and have your CO<sub>2</sub> sensor working properly with
your Arduino Primo board. </p>
<p>So let's get started making this thing Bluetooth enabled!</p>
<h3 id="add-bluetooth-gatt-services">Add Bluetooth GATT Services</h3>
<p>Since we already built the previous demo on the <a href="../bleprph/bleprph-app/">bluetooth peripheral</a> basic
app most of the bluetooth plumbing has already been taken care of for us. What's left is for us
to add the required GATT services for advertising the Carbon Dioxide sensor so that
other devices can get those values.</p>
<p>First, we'll define the GATT Services in <code>apps/air_quality/src/bleprph.h</code>.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #177500">/* Sensor Data */</span>
<span style="color: #177500">/* e761d2af-1c15-4fa7-af80-b5729002b340 */</span>
<span style="color: #A90D91">static</span> <span style="color: #A90D91">const</span> <span style="color: #000000">ble_uuid128_t</span> <span style="color: #000000">gatt_svr_svc_co2_uuid</span> <span style="color: #000000">=</span>
<span style="color: #000000">BLE_UUID128_INIT</span>(<span style="color: #1C01CE">0x40</span>, <span style="color: #1C01CE">0xb3</span>, <span style="color: #1C01CE">0x20</span>, <span style="color: #1C01CE">0x90</span>, <span style="color: #1C01CE">0x72</span>, <span style="color: #1C01CE">0xb5</span>, <span style="color: #1C01CE">0x80</span>, <span style="color: #1C01CE">0xaf</span>,
<span style="color: #1C01CE">0xa7</span>, <span style="color: #1C01CE">0x4f</span>, <span style="color: #1C01CE">0x15</span>, <span style="color: #1C01CE">0x1c</span>, <span style="color: #1C01CE">0xaf</span>, <span style="color: #1C01CE">0xd2</span>, <span style="color: #1C01CE">0x61</span>, <span style="color: #1C01CE">0xe7</span>);
<span style="color: #633820">#define CO2_SNS_TYPE 0xDEAD</span>
<span style="color: #633820">#define CO2_SNS_STRING &quot;SenseAir K30 CO2 Sensor&quot;</span>
<span style="color: #633820">#define CO2_SNS_VAL 0xBEAD</span>
<span style="color: #A90D91">uint16_t</span> <span style="color: #000000">gatt_co2_val</span>;
</code></pre></div>
<p>You can use any hex values you choose for the sensor type and sensor values, and you can
even forget the sensor type and sensor string definitions altogether but they make
the results look nice in our Bluetooth App for Mac OS X and iOS.</p>
<p>Next we'll add those services to <code>apps/air_quality/src/gatt_svr.c</code>.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #A90D91">static</span> <span style="color: #A90D91">int</span>
<span style="color: #000000">gatt_svr_sns_access</span>(<span style="color: #A90D91">uint16_t</span> <span style="color: #000000">conn_handle</span>, <span style="color: #A90D91">uint16_t</span> <span style="color: #000000">attr_handle</span>,
<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">ble_gatt_access_ctxt</span> <span style="color: #000000">*ctxt</span>,
<span style="color: #A90D91">void</span> <span style="color: #000000">*arg</span>);
<span style="color: #A90D91">static</span> <span style="color: #A90D91">uint16_t</span> <span style="color: #000000">gatt_co2_val_len</span>;
</code></pre></div>
<p>Make sure it is added as <em>primary</em> service.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #A90D91">static</span> <span style="color: #A90D91">const</span> <span style="color: #A90D91">struct</span> <span style="color: #3F6E75">ble_gatt_svc_def</span> <span style="color: #000000">gatt_svr_svcs</span>[] <span style="color: #000000">=</span> {
{
<span style="color: #177500">/*** Service: Security test. */</span>
.<span style="color: #000000">type</span> <span style="color: #000000">=</span> <span style="color: #000000">BLE_GATT_SVC_TYPE_PRIMARY</span>,
.<span style="color: #000000">uuid</span> <span style="color: #000000">=</span> <span style="color: #000000">&amp;gatt_svr_svc_sec_test_uuid</span>.<span style="color: #000000">u</span>,
.<span style="color: #000000">characteristics</span> <span style="color: #000000">=</span> (<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">ble_gatt_chr_def</span>[]) { {
<span style="color: #177500">/*** Characteristic: Random number generator. */</span>
.<span style="color: #000000">uuid</span> <span style="color: #000000">=</span> <span style="color: #000000">&amp;gatt_svr_chr_sec_test_rand_uuid</span>.<span style="color: #000000">u</span>,
.<span style="color: #000000">access_cb</span> <span style="color: #000000">=</span> <span style="color: #000000">gatt_svr_chr_access_sec_test</span>,
.<span style="color: #000000">flags</span> <span style="color: #000000">=</span> <span style="color: #000000">BLE_GATT_CHR_F_READ</span> <span style="color: #000000">|</span> <span style="color: #000000">BLE_GATT_CHR_F_READ_ENC</span>,
}, {
<span style="color: #177500">/*** Characteristic: Static value. */</span>
.<span style="color: #000000">uuid</span> <span style="color: #000000">=</span> <span style="color: #000000">&amp;gatt_svr_chr_sec_test_static_uuid</span>,.<span style="color: #000000">u</span>
.<span style="color: #000000">access_cb</span> <span style="color: #000000">=</span> <span style="color: #000000">gatt_svr_chr_access_sec_test</span>,
.<span style="color: #000000">flags</span> <span style="color: #000000">=</span> <span style="color: #000000">BLE_GATT_CHR_F_READ</span> <span style="color: #000000">|</span>
<span style="color: #000000">BLE_GATT_CHR_F_WRITE</span> <span style="color: #000000">|</span> <span style="color: #000000">BLE_GATT_CHR_F_WRITE_ENC</span>,
}, {
<span style="color: #1C01CE">0</span>, <span style="color: #177500">/* No more characteristics in this service. */</span>
} },
},
{
<span style="color: #177500">/*** CO2 Level Notification Service. */</span>
.<span style="color: #000000">type</span> <span style="color: #000000">=</span> <span style="color: #000000">BLE_GATT_SVC_TYPE_PRIMARY</span>,
.<span style="color: #000000">uuid</span> <span style="color: #000000">=</span> <span style="color: #000000">&amp;gatt_svr_svc_co2_uuid</span>.<span style="color: #000000">u</span>,
.<span style="color: #000000">characteristics</span> <span style="color: #000000">=</span> (<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">ble_gatt_chr_def</span>[]) { {
.<span style="color: #000000">uuid</span> <span style="color: #000000">=</span> <span style="color: #000000">BLE_UUID16_DECLARE</span>(<span style="color: #000000">CO2_SNS_TYPE</span>),
.<span style="color: #000000">access_cb</span> <span style="color: #000000">=</span> <span style="color: #000000">gatt_svr_sns_access</span>,
.<span style="color: #000000">flags</span> <span style="color: #000000">=</span> <span style="color: #000000">BLE_GATT_CHR_F_READ</span>,
}, {
.<span style="color: #000000">uuid</span> <span style="color: #000000">=</span> <span style="color: #000000">BLE_UUID16_DECLARE</span>(<span style="color: #000000">CO2_SNS_VAL</span>),
.<span style="color: #000000">access_cb</span> <span style="color: #000000">=</span> <span style="color: #000000">gatt_svr_sns_access</span>,
.<span style="color: #000000">flags</span> <span style="color: #000000">=</span> <span style="color: #000000">BLE_GATT_CHR_F_NOTIFY</span>,
}, {
<span style="color: #1C01CE">0</span>, <span style="color: #177500">/* No more characteristics in this service. */</span>
} },
},
{
<span style="color: #1C01CE">0</span>, <span style="color: #177500">/* No more services. */</span>
},
};
</code></pre></div>
<p>Next we need to tell the GATT Server how to handle requests for CO<sub>2</sub> readings :</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #000000">sstatic</span> <span style="color: #A90D91">int</span>
<span style="color: #000000">gatt_svr_sns_access</span>(<span style="color: #A90D91">uint16_t</span> <span style="color: #000000">conn_handle</span>, <span style="color: #A90D91">uint16_t</span> <span style="color: #000000">attr_handle</span>,
<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">ble_gatt_access_ctxt</span> <span style="color: #000000">*ctxt</span>,
<span style="color: #A90D91">void</span> <span style="color: #000000">*arg</span>)
{
<span style="color: #A90D91">uint16_t</span> <span style="color: #000000">uuid16</span>;
<span style="color: #A90D91">int</span> <span style="color: #000000">rc</span>;
<span style="color: #000000">uuid16</span> <span style="color: #000000">=</span> <span style="color: #000000">ble_uuid_u16</span>(<span style="color: #000000">ctxt-&gt;chr-&gt;uuid</span>);
<span style="color: #A90D91">switch</span> (<span style="color: #000000">uuid16</span>) {
<span style="color: #A90D91">case</span> <span style="color: #000000">CO2_SNS_TYPE</span>:
<span style="color: #000000">assert</span>(<span style="color: #000000">ctxt-&gt;op</span> <span style="color: #000000">==</span> <span style="color: #000000">BLE_GATT_ACCESS_OP_READ_CHR</span>);
<span style="color: #000000">rc</span> <span style="color: #000000">=</span> <span style="color: #000000">os_mbuf_append</span>(<span style="color: #000000">ctxt-&gt;om</span>, <span style="color: #000000">CO2_SNS_STRING</span>, <span style="color: #A90D91">sizeof</span> <span style="color: #000000">CO2_SNS_STRING</span>);
<span style="color: #000000">BLEPRPH_LOG</span>(<span style="color: #000000">INFO</span>, <span style="color: #C41A16">&quot;CO2 SENSOR TYPE READ: %s\n&quot;</span>, <span style="color: #000000">CO2_SNS_STRING</span>);
<span style="color: #A90D91">return</span> <span style="color: #000000">rc</span> <span style="color: #000000">==</span> <span style="color: #1C01CE">0</span> <span style="color: #000000">?</span> <span style="color: #1C01CE">0</span> <span style="color: #000000">:</span> <span style="color: #000000">BLE_ATT_ERR_INSUFFICIENT_RES</span>;
<span style="color: #A90D91">case</span> <span style="color: #000000">CO2_SNS_VAL</span>:
<span style="color: #A90D91">if</span> (<span style="color: #000000">ctxt-&gt;op</span> <span style="color: #000000">==</span> <span style="color: #000000">BLE_GATT_ACCESS_OP_WRITE_CHR</span>) {
<span style="color: #000000">rc</span> <span style="color: #000000">=</span> <span style="color: #000000">gatt_svr_chr_write</span>(<span style="color: #000000">ctxt-&gt;om</span>, <span style="color: #1C01CE">0</span>,
<span style="color: #A90D91">sizeof</span> <span style="color: #000000">gatt_co2_val</span>,
<span style="color: #000000">&amp;gatt_co2_val</span>,
<span style="color: #000000">&amp;gatt_co2_val_len</span>);
<span style="color: #A90D91">return</span> <span style="color: #000000">rc</span>;
} <span style="color: #A90D91">else</span> <span style="color: #A90D91">if</span> (<span style="color: #000000">ctxt-&gt;op</span> <span style="color: #000000">==</span> <span style="color: #000000">BLE_GATT_ACCESS_OP_READ_CHR</span>) {
<span style="color: #000000">rc</span> <span style="color: #000000">=</span> <span style="color: #000000">os_mbuf_append</span>(<span style="color: #000000">ctxt-&gt;om</span>, <span style="color: #000000">&amp;gatt_co2_val</span>,
<span style="color: #A90D91">sizeof</span> <span style="color: #000000">gatt_co2_val</span>);
<span style="color: #A90D91">return</span> <span style="color: #000000">rc</span> <span style="color: #000000">==</span> <span style="color: #1C01CE">0</span> <span style="color: #000000">?</span> <span style="color: #1C01CE">0</span> <span style="color: #000000">:</span> <span style="color: #000000">BLE_ATT_ERR_INSUFFICIENT_RES</span>;
}
<span style="color: #A90D91">default</span><span style="color: #000000">:</span>
<span style="color: #000000">assert</span>(<span style="color: #1C01CE">0</span>);
<span style="color: #A90D91">return</span> <span style="color: #000000">BLE_ATT_ERR_UNLIKELY</span>;
}
}
</code></pre></div>
<p>Now it's time to go into our <code>apps/air_quality/src/main.c</code> and change how we read CO<sub>2</sub> readings and
respond to requests. </p>
<p>We'll need a task handler with an event queue for the CO<sub>2</sub> readings -- they were handled by the shell task in the previous tutorial but now it needs to be replaced by a different handler as shown below.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #177500">/* CO2 Task settings */</span>
<span style="color: #633820">#define CO2_TASK_PRIO 5</span>
<span style="color: #633820">#define CO2_STACK_SIZE (OS_STACK_ALIGN(336))</span>
<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">os_eventq</span> <span style="color: #000000">co2_evq</span>;
<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">os_task</span> <span style="color: #000000">co2_task</span>;
<span style="color: #000000">bssnz_t</span> <span style="color: #000000">os_stack_t</span> <span style="color: #000000">co2_stack</span>[<span style="color: #000000">CO2_STACK_SIZE</span>];
</code></pre></div>
<p>And of course we'll need to go to our <code>main()</code> and do all the standard task and event setup we
normally do by adding the following. Again, remember to delete all the shell event queues and tasks.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #177500">/* Initialize sensor eventq */</span>
<span style="color: #000000">os_eventq_init</span>(<span style="color: #000000">&amp;co2_evq</span>);
<span style="color: #177500">/* Create the CO2 reader task. </span>
<span style="color: #177500"> * All sensor reading operations are performed in this task.</span>
<span style="color: #177500"> */</span>
<span style="color: #000000">os_task_init</span>(<span style="color: #000000">&amp;co2_task</span>, <span style="color: #C41A16">&quot;sensor&quot;</span>, <span style="color: #000000">co2_task_handler</span>,
<span style="color: #A90D91">NULL</span>, <span style="color: #000000">CO2_TASK_PRIO</span>, <span style="color: #000000">OS_WAIT_FOREVER</span>,
<span style="color: #000000">co2_stack</span>, <span style="color: #000000">CO2_STACK_SIZE</span>);
</code></pre></div>
<p>We'll also need to add a task handler -- since we initialized it above:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #177500">/**</span>
<span style="color: #177500"> * Event loop for the sensor task.</span>
<span style="color: #177500"> */</span>
<span style="color: #A90D91">static</span> <span style="color: #A90D91">void</span>
<span style="color: #000000">co2_task_handler</span>(<span style="color: #A90D91">void</span> <span style="color: #000000">*unused</span>)
{
<span style="color: #A90D91">while</span> (<span style="color: #1C01CE">1</span>) {
<span style="color: #000000">co2_read_event</span>();
<span style="color: #177500">/* Wait 2 second */</span>
<span style="color: #000000">os_time_delay</span>(<span style="color: #000000">OS_TICKS_PER_SEC</span> <span style="color: #000000">*</span> <span style="color: #1C01CE">2</span>);
}
}
</code></pre></div>
<p>And finally, we'll take care of that <code>co2_read_event()</code> function:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #A90D91">int</span>
<span style="color: #000000">co2_read_event</span>(<span style="color: #A90D91">void</span>)
{
<span style="color: #A90D91">int</span> <span style="color: #000000">value</span>;
<span style="color: #A90D91">enum</span> <span style="color: #000000">senseair_read_type</span> <span style="color: #000000">type</span> <span style="color: #000000">=</span> <span style="color: #000000">SENSEAIR_CO2</span>;
<span style="color: #A90D91">uint16_t</span> <span style="color: #000000">chr_val_handle</span>;
<span style="color: #A90D91">int</span> <span style="color: #000000">rc</span>;
<span style="color: #000000">value</span> <span style="color: #000000">=</span> <span style="color: #000000">senseair_read</span>(<span style="color: #000000">type</span>);
<span style="color: #A90D91">if</span> (<span style="color: #000000">value</span> <span style="color: #000000">&gt;=</span> <span style="color: #1C01CE">0</span>) {
<span style="color: #000000">console_printf</span>(<span style="color: #C41A16">&quot;Got %d\n&quot;</span>, <span style="color: #000000">value</span>);
} <span style="color: #A90D91">else</span> {
<span style="color: #000000">console_printf</span>(<span style="color: #C41A16">&quot;Error while reading: %d\n&quot;</span>, <span style="color: #000000">value</span>);
<span style="color: #A90D91">goto</span> <span style="color: #000000">err</span>;
}
<span style="color: #000000">gatt_co2_val</span> <span style="color: #000000">=</span> <span style="color: #000000">value</span>;
<span style="color: #000000">rc</span> <span style="color: #000000">=</span> <span style="color: #000000">ble_gatts_find_chr</span>(<span style="color: #000000">&amp;gatt_svr_svc_co2_uuid</span>.<span style="color: #000000">u</span>, <span style="color: #000000">BLE_UUID16_DECLARE</span>(<span style="color: #000000">CO2_SNS_VAL</span>), <span style="color: #A90D91">NULL</span>, <span style="color: #000000">&amp;chr_val_handle</span>);
<span style="color: #000000">assert</span>(<span style="color: #000000">rc</span> <span style="color: #000000">==</span> <span style="color: #1C01CE">0</span>);
<span style="color: #000000">ble_gatts_chr_updated</span>(<span style="color: #000000">chr_val_handle</span>);
<span style="color: #A90D91">return</span> (<span style="color: #1C01CE">0</span>);
<span style="color: #000000">err</span>:
<span style="color: #A90D91">return</span> (<span style="color: #000000">rc</span>);
}
</code></pre></div>
<p>You'll notice that it looks eeirily similar to a portion of the shell event we created
earlier. This one simply reads and updates the CO<sub>2</sub> value and sends that over BLE to any
connected clients instead. </p>
<p>We can now build, create-image and load the app onto our Arduino Primo board, and then
connect and see the updated values! The image below shows the results using MyNewt Sensor Reader,
a Mac OS X app developed for connecting to MyNewt devices over Bluetooth but you can also use LightBlue
or any other application that can connect to, and read, Bluetooth data.</p>
<p><img alt="MyNewt Sensor Reader" src="../pics/MyNewtSensorReader.jpg" /></p>
<p>Congratulations!!</p>
<div class="row">
<ul class="nav nav-pills" style="margin-bottom: 10px">
<li>
</li>
<li class="pull-right">
</li>
</ul>
</div>
<footer class="row">
<div class="col-xs-12">
<p class="copyright">Apache Mynewt is available under Apache License, version 2.0.</p>
</div>
<div class="col-xs-12">
<div class="logos">
<a href="https://www.apache.org/">
<img src="/img/asf_logo_wide_small.png" alt="Apache" title="Apache">
</a>
<p>
Copyright © 2015-2021 The Apache Software Foundation.<br>
<small class="footnote">
Apache Mynewt, Mynewt, Apache, the Apache feather logo, and the Apache Mynewt
project logo are either registered trademarks or trademarks of the Apache
Software Foundation in the United States and other countries.
</small>
</p>
<a href="">
<img src="https://www.countit.com/images/add_to_slack.png" alt="Slack Icon" title="Join our Slack Community" />
</a>
</div>
</div>
<a href="https://www.apache.org/licenses/">
<button class="button-footer-asf">
License
</button>
</a>
<a href="https://www.apache.org/foundation/sponsorship.html">
<button class="button-footer-asf">
Sponsorship
</button>
</a>
<a href="https://www.apache.org/foundation/thanks.html">
<button class="button-footer-asf">
Thanks
</button>
</a>
<a href="https://www.apache.org/security/">
<button class="button-footer-asf">
Security
</button>
</a>
<a href="https://apache.org/events/current-event">
<button class="button-footer-asf">
ASF Events
</button>
</a>
</footer>
</div>
</div>
</div>
<script src="../../../js/jquery-1.10.2.min.js"></script>
<script src="../../../js/bootstrap-3.0.3.min.js"></script>
<script src="../../../js/highlight.pack.js"></script>
<script src="../../../js/base.js"></script>
<script src="../../../js/custom.js"></script>
<script src="search/main.js"></script>
</body>
</html>