<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Solutions &#8211; IoT Expert</title>
	<atom:link href="https://iotexpert.com/category/solutions/feed/" rel="self" type="application/rss+xml" />
	<link>https://iotexpert.com</link>
	<description>Engineering for the Internet of Things</description>
	<lastBuildDate>Mon, 21 Jun 2021 19:50:26 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://iotexpert.com/wp-content/uploads/2017/01/cropped-Avatar-32x32.jpg</url>
	<title>Solutions &#8211; IoT Expert</title>
	<link>https://iotexpert.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>AnyCloud WiFi Template + WiFi Helper Library (Part 3): A New Modus Toolbox Library</title>
		<link>https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-3-a-new-modus-toolbox-library/</link>
					<comments>https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-3-a-new-modus-toolbox-library/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 05 Jul 2021 14:02:02 +0000</pubDate>
				<category><![CDATA[AnyCloud]]></category>
		<category><![CDATA[Elkhorn Creek 3.0]]></category>
		<category><![CDATA[WIFI]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=11298</guid>

					<description><![CDATA[Summary Instructions to create a new Modus Toolbox / AnyCloud library including modifying your master middleware manifest and updating the dependencies.  The new library and dependencies will then be available in your library browser and new project creator. Story In the previous article we discussed the steps to turn on the WiFi chip in your [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>Instructions to create a new Modus Toolbox / AnyCloud library including modifying your master middleware manifest and updating the dependencies.  The new library and dependencies will then be available in your library browser and new project creator.</p>
<p><span><p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
</tr>
</thead>
<tbody>
<tr><td >(Part 1) Create Basic Project &amp; Add Cypress Logging Functionality</td>
</tr>

<tr><td >(Part 2) Create New Thread to manage WiFi using the Wireless Connection Manager</td>
</tr>

<tr><td >(Part 3) Create a New Middleware Library with WiFi helper functions</td>
</tr>

<tr><td >(Part 4) Add WiFi Scan</td>
</tr>

<tr><td >Add WiFi Connect</td>
</tr>

<tr><td >Add WiFi Disconnect</td>
</tr>

<tr><td >Add WiFi Ping</td>
</tr>

<tr><td >Add Gethostbyname</td>
</tr>

<tr><td >Add MDNS</td>
</tr>

<tr><td >Add Status</td>
</tr>

<tr><td >Add StartAP</td>
</tr>

<tr><td >Make a new template project (update manifest)</td>
</tr>
</tbody></table></div></p></span></p>
<h1>Story</h1>
<p>In the previous article we discussed the steps to turn on the WiFi chip in your project using the Wireless Connection Manager Anycloud (WCM) library.  When something happens with the WCM it will give you a callback to tell you what happened.  In my example code there were three printf&#8217;s that were commented out for the conditions:</p>
<ul>
<li>CY_WCM_EVENT_IP_CHANGED</li>
<li>CY_WCM_EVENT_STA_JOINED_SOFTAP</li>
<li>CY_WCM_EVENT_STA_LEFT_SOFTAP</li>
</ul>
<p>The question you might have is &#8220;What is the new Ip Address&#8221;&#8221; or &#8220;What is the MAC address of the Station which joined the SoftAp?&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">        case CY_WCM_EVENT_IP_CHANGED:           /**&lt; IP address change event. This event is notified after connection, re-connection, and IP address change due to DHCP renewal. */
 //               cy_wcm_get_ip_addr(wifi_network_mode, &amp;ip_addr, 1);
                printf("Station IP Address Changed: %s\n",wifi_ntoa(&amp;ip_addr));
        break;
        case CY_WCM_EVENT_STA_JOINED_SOFTAP:    /**&lt; An STA device connected to SoftAP. */
//            printf("STA Joined: %s\n",wifi_mac_to_string(event_data-&gt;sta_mac));
        break;
        case CY_WCM_EVENT_STA_LEFT_SOFTAP:      /**&lt; An STA device disconnected from SoftAP. */
//            printf("STA Left: %s\n",wifi_mac_to_string(event_data-&gt;sta_mac));
</pre>
<p>So I wrote &#8220;standard&#8221; functions to</p>
<ul>
<li>Convert an IP address structure to a string (like ntoa in Linux)</li>
<li>Convert a MAC address to a string</li>
</ul>
<p>I essentially got these from the code example where they were redundantly repeatedly repeated.  After tweaking them to suit my liking I wanted to put them in a library.</p>
<h1>Make the C-Library</h1>
<p>Follow these steps to make the c-library.  First, make a new directory in your project called &#8220;wifi_helper&#8221;.  You can do this in Visual Studio Code by pressing the folder button with the plus on it.</p>
<p><a href="https://iotexpert.com/?attachment_id=11306" rel="attachment wp-att-11306"><img fetchpriority="high" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-7.27.03-PM.png" alt="" width="974" height="192" class="alignnone size-full wp-image-11306" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-7.27.03-PM.png 974w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-7.27.03-PM-300x59.png 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-7.27.03-PM-768x151.png 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-7.27.03-PM-600x118.png 600w" sizes="(max-width: 974px) 100vw, 974px" /></a></p>
<p>Then create the files wifi_helper.h and wifi_helper.c</p>
<p><a href="https://iotexpert.com/?attachment_id=11307" rel="attachment wp-att-11307"><img decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-7.27.39-PM.png" alt="" width="956" height="414" class="alignnone size-large wp-image-11307" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-7.27.39-PM.png 956w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-7.27.39-PM-300x130.png 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-7.27.39-PM-768x333.png 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-7.27.39-PM-600x260.png 600w" sizes="(max-width: 956px) 100vw, 956px" /></a></p>
<p>In &#8220;wifi_helper.h&#8221; type in the public interface.  Specifically, that we want a function that takes a mac address returns a char*.  And another function that takes an IP address and returns a char*</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#pragma once

#include "cy_wcm.h"

char *wifi_mac_to_string(cy_wcm_mac_t mac);

char *wifi_ntoa(cy_wcm_ip_address_t *ip_addr);


</pre>
<p>All right Hassane&#8230; yes these functions need comments.  Notice that I allocated a static buffer inside of these two function.  That means that these functions are NOT NOT NOT thread safe.  However, personally I think that is fine as I think that it is unlikely that they would ever be called from multiple threads.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">#include "wifi_helper.h"
#include "cy_wcm.h"
#include &lt;stdio.h&gt;
#include "cy_utils.h"
#include "cy_log.h"

char *wifi_mac_to_string(cy_wcm_mac_t mac)
{
    static char _mac_string[] = "xx:xx:xx:xx:xx:xx";
    sprintf(_mac_string,"%02X:%02X:%02X:%02X:%02X:%02X",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
    return _mac_string; 
}


char *wifi_ntoa(cy_wcm_ip_address_t *ip_addr)
{
    static char _netchar[32];
    switch(ip_addr-&gt;version)
    {
        case CY_WCM_IP_VER_V4:
            sprintf(_netchar,"%d.%d.%d.%d", (uint8_t)ip_addr-&gt;ip.v4,
                (uint8_t)(ip_addr-&gt;ip.v4 &gt;&gt; 8), (uint8_t)(ip_addr-&gt;ip.v4 &gt;&gt; 16),
                (uint8_t)(ip_addr-&gt;ip.v4 &gt;&gt; 24));        break;
        case CY_WCM_IP_VER_V6:
            sprintf(_netchar,"%X:%X:%X:%X", (uint8_t)ip_addr-&gt;ip.v6[0],
                (uint8_t)(ip_addr-&gt;ip.v6[1]), (uint8_t)(ip_addr-&gt;ip.v6[2]),
                (uint8_t)(ip_addr-&gt;ip.v6[3]));
        break;
    }
    CY_ASSERT(buff[0] != 0); // SOMETHING should have happened
    return _netchar;
}

</pre>
<h1>Git Repository</h1>
<p>Now that I have the files I need in the library, I want to create a place on GitHub to hold the library.</p>
<p><a href="https://iotexpert.com/?attachment_id=11319" rel="attachment wp-att-11319"><img decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-7.07.31-AM-1024x916.jpg" alt="" width="1024" height="916" class="alignnone size-large wp-image-11319" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-7.07.31-AM-1024x916.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-7.07.31-AM-300x268.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-7.07.31-AM-768x687.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-7.07.31-AM-1536x1373.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-7.07.31-AM-600x536.jpg 600w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-7.07.31-AM.jpg 1908w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now we need to integrate the files into Git.  To do this you need to</p>
<ol>
<li>Initialize a new git repository (git init .)</li>
<li>Add a remote (git remote add origin git@github.com:iotexpert/wifi_helper.git)</li>
<li>Pull the remote files (README and LICENSE) with (git pull origin main)</li>
<li>Add the wifi_helper files (git add wifi_helper.*)</li>
<li>Commit the changes (git commit -m &#8220;added initial c files&#8221;)</li>
<li>Push them to the remote (git push -u origin main)</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">arh (master *+) wifi_helper $ pwd
/Users/arh/proj/elkhorncreek3/IoTExpertWiFiTemplate/wifi_helper
arh (master *+) wifi_helper $ git init .
Initialized empty Git repository in /Users/arh/proj/elkhorncreek3/IoTExpertWiFiTemplate/wifi_helper/.git/
arh (main #) wifi_helper $ git remote add origin git@github.com:iotexpert/wifi_helper.git
arh (main #) wifi_helper $ git pull origin main
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), 1.28 KiB | 436.00 KiB/s, done.
From iotexpert.github.com:iotexpert/wifi_helper
 * branch            main       -&gt; FETCH_HEAD
 * [new branch]      main       -&gt; origin/main
arh (main) wifi_helper $ git add wifi_helper.*
arh (main +) wifi_helper $ git commit -m "added initial c files"
[main f7d10b1] added initial c files
 2 files changed, 72 insertions(+)
 create mode 100644 wifi_helper.c
 create mode 100644 wifi_helper.h
arh (main) wifi_helper $ git push -u origin main
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 1.10 KiB | 1.10 MiB/s, done.
Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
To iotexpert.github.com:iotexpert/wifi_helper.git
   3a1ad32..f7d10b1  main -&gt; main
Branch 'main' set up to track remote branch 'main' from 'origin'.
arh (main) wifi_helper $ 
</pre>
<p>Now you will have something like this on GitHub.</p>
<p><a href="https://iotexpert.com/?attachment_id=11320" rel="attachment wp-att-11320"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-7.33.33-AM-1024x523.jpg" alt="" width="1024" height="523" class="alignnone size-large wp-image-11320" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-7.33.33-AM-1024x523.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-7.33.33-AM-300x153.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-7.33.33-AM-768x392.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-7.33.33-AM-1536x785.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-7.33.33-AM-2048x1046.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-7.33.33-AM-600x307.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Manifest Files</h1>
<p>I would like to be able to have my new library show up in the library browser.  But how?  When the library browser starts up it needs to discover:</p>
<ol>
<li>Board Support Packages</li>
<li>Template Projects</li>
<li>Middleware Code Libraries</li>
</ol>
<p>To do this, it reads a series of XML files called &#8220;manifests&#8221;.  These manifest files tell the library browser where to find the libraries.  If you have ever noticed the library browser (or the new project creator) it looks like this:</p>
<p><a href="https://iotexpert.com/?attachment_id=11321" rel="attachment wp-att-11321"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-8.24.40-AM-1024x461.jpg" alt="" width="1024" height="461" class="alignnone size-large wp-image-11321" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-8.24.40-AM-1024x461.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-8.24.40-AM-300x135.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-8.24.40-AM-768x346.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-8.24.40-AM-1536x692.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-8.24.40-AM-2048x922.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-8.24.40-AM-600x270.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The message &#8220;Processing super-manifest &#8230;&#8221; give you a hint to go to https://raw.githubusercontent.com/cypresssemiconductorco/mtb-super-manifest/v2.X/mtb-super-manifest-fv2.xml</p>
<p>Here it is.  Notice that the XML scheme says that this file is a &#8220;super-manifest&#8221;.  Then notice that there are sections:</p>
<ul>
<li>&lt;board-manifest-list&gt; these are BSPs</li>
<li>&lt;app-manifest-list&gt; these are template projects</li>
<li>&lt;middleware-manifest-list&gt; these are middleware code libraries</li>
</ul>
<pre class="EnlighterJSRAW" data-enlighter-language="xml">&lt;super-manifest&gt;
  &lt;board-manifest-list&gt;
    &lt;board-manifest&gt;
      &lt;uri&gt;https://github.com/cypresssemiconductorco/mtb-bsp-manifest/raw/v2.X/mtb-bsp-manifest.xml&lt;/uri&gt;
    &lt;/board-manifest&gt;
    &lt;board-manifest dependency-url="https://github.com/cypresssemiconductorco/mtb-bsp-manifest/raw/v2.X/mtb-bsp-dependencies-manifest.xml"&gt;
      &lt;uri&gt;https://github.com/cypresssemiconductorco/mtb-bsp-manifest/raw/v2.X/mtb-bsp-manifest-fv2.xml&lt;/uri&gt;
    &lt;/board-manifest&gt;
    &lt;board-manifest&gt;
      &lt;uri&gt;https://github.com/cypresssemiconductorco/mtb-bt-bsp-manifest/raw/v2.X/mtb-bt-bsp-manifest.xml&lt;/uri&gt;
    &lt;/board-manifest&gt;
    &lt;board-manifest dependency-url="https://github.com/cypresssemiconductorco/mtb-bt-bsp-manifest/raw/v2.X/mtb-bt-bsp-dependencies-manifest.xml"&gt;
      &lt;uri&gt;https://github.com/cypresssemiconductorco/mtb-bt-bsp-manifest/raw/v2.X/mtb-bt-bsp-manifest-fv2.xml&lt;/uri&gt;
    &lt;/board-manifest&gt;
  &lt;/board-manifest-list&gt;
  &lt;app-manifest-list&gt;
    &lt;app-manifest&gt;
      &lt;uri&gt;https://github.com/cypresssemiconductorco/mtb-ce-manifest/raw/v2.X/mtb-ce-manifest.xml&lt;/uri&gt;
    &lt;/app-manifest&gt;
    &lt;app-manifest&gt;
      &lt;uri&gt;https://github.com/cypresssemiconductorco/mtb-ce-manifest/raw/v2.X/mtb-ce-manifest-fv2.xml&lt;/uri&gt;
    &lt;/app-manifest&gt;
    &lt;app-manifest&gt;
      &lt;uri&gt;https://github.com/cypresssemiconductorco/mtb-bt-app-manifest/raw/v2.X/mtb-bt-app-manifest.xml&lt;/uri&gt;
    &lt;/app-manifest&gt;
    &lt;app-manifest&gt;
      &lt;uri&gt;https://github.com/cypresssemiconductorco/mtb-bt-app-manifest/raw/v2.X/mtb-bt-app-manifest-fv2.xml&lt;/uri&gt;
    &lt;/app-manifest&gt;
  &lt;/app-manifest-list&gt;
  &lt;middleware-manifest-list&gt;
    &lt;middleware-manifest&gt;
      &lt;uri&gt;https://github.com/cypresssemiconductorco/mtb-mw-manifest/raw/v2.X/mtb-mw-manifest.xml&lt;/uri&gt;
    &lt;/middleware-manifest&gt;
    &lt;middleware-manifest dependency-url="https://github.com/cypresssemiconductorco/mtb-mw-manifest/raw/v2.X/mtb-mw-dependencies-manifest.xml"&gt;
      &lt;uri&gt;https://github.com/cypresssemiconductorco/mtb-mw-manifest/raw/v2.X/mtb-mw-manifest-fv2.xml&lt;/uri&gt;
    &lt;/middleware-manifest&gt;
    &lt;middleware-manifest&gt;
      &lt;uri&gt;https://github.com/cypresssemiconductorco/mtb-bt-mw-manifest/raw/v2.X/mtb-bt-mw-manifest.xml&lt;/uri&gt;
    &lt;/middleware-manifest&gt;
    &lt;middleware-manifest dependency-url="https://github.com/cypresssemiconductorco/mtb-bt-mw-manifest/raw/v2.X/mtb-bt-mw-dependencies-manifest.xml"&gt;
      &lt;uri&gt;https://github.com/cypresssemiconductorco/mtb-bt-mw-manifest/raw/v2.X/mtb-bt-mw-manifest-fv2.xml&lt;/uri&gt;
    &lt;/middleware-manifest&gt;
    &lt;middleware-manifest&gt;
      &lt;uri&gt;https://github.com/cypresssemiconductorco/mtb-wifi-mw-manifest/raw/v2.X/mtb-wifi-mw-manifest.xml&lt;/uri&gt;
    &lt;/middleware-manifest&gt;
    &lt;middleware-manifest dependency-url="https://github.com/cypresssemiconductorco/mtb-wifi-mw-manifest/raw/v2.X/mtb-wifi-mw-dependencies-manifest.xml"&gt;
      &lt;uri&gt;https://github.com/cypresssemiconductorco/mtb-wifi-mw-manifest/raw/v2.X/mtb-wifi-mw-manifest-fv2.xml&lt;/uri&gt;
    &lt;/middleware-manifest&gt;
  &lt;/middleware-manifest-list&gt;
&lt;/super-manifest&gt;</pre>
<p>But you can&#8217;t modify this to add your own?  So what do you do now?  Cypress put in the capability for you to extend the system by creating a file called &#8220;~/.modustoolbox/manifest.loc&#8221;.  This file contains one or more URLs to super-manifest files (like the one above) where you can add whatever you want.</p>
<p>Here is the iotexpert manifest.loc</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">arh ~ $ cd ~/.modustoolbox/
arh .modustoolbox $ more manifest.loc
https://github.com/iotexpert/mtb2-iotexpert-manifests/raw/master/iotexpert-super-manifest.xml
arh .modustoolbox $</pre>
<p>This file points to a super manifest file in a GitHub repository.  Here is the repository:</p>
<p><a href="https://iotexpert.com/?attachment_id=11322" rel="attachment wp-att-11322"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-8.34.16-AM-1024x619.jpg" alt="" width="1024" height="619" class="alignnone size-large wp-image-11322" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-8.34.16-AM-1024x619.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-8.34.16-AM-300x181.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-8.34.16-AM-768x464.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-8.34.16-AM-1536x928.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-8.34.16-AM-2048x1237.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-17-at-8.34.16-AM-600x363.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Notice that it has</p>
<ul>
<li>iotexpert-super-manifest.xml &#8211; the top level iotexpert manifest</li>
<li>iotexpert-app-manifest.xml &#8211; my template projects</li>
<li>iotexpert-mw-manifest.xml &#8211; my middleware</li>
<li>manifest.loc &#8211; the file you need to put in your home directory</li>
<li>iotexpert-mw-dependencies.xml &#8211; a new file which I will talk about later</li>
</ul>
<p>And the super manifest file that looks like this:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="xml">&lt;super-manifest&gt;
  &lt;board-manifest-list&gt;
  &lt;/board-manifest-list&gt;
  
  &lt;app-manifest-list&gt;
    &lt;app-manifest&gt;
      &lt;uri&gt;https://github.com/iotexpert/mtb2-iotexpert-manifests/raw/master/iotexpert-app-manifest.xml&lt;/uri&gt;
      &lt;/app-manifest&gt;
   &lt;/app-manifest-list&gt;
  &lt;board-manifest-list&gt;
  &lt;/board-manifest-list&gt;
  &lt;middleware-manifest-list&gt;
    &lt;middleware-manifest dependency-url="https://github.com/iotexpert/mtb2-iotexpert-manifests/raw/master/iotexpert-mw-dependencies.xml"&gt;
      &lt;uri&gt;https://github.com/iotexpert/mtb2-iotexpert-manifests/raw/master/iotexpert-mw-manifest.xml&lt;/uri&gt;
    &lt;/middleware-manifest&gt;
  &lt;/middleware-manifest-list&gt;
&lt;/super-manifest&gt;</pre>
<p>To add the library we created above, I need to add the new middleware into my middleware manifest.  Modify the file &#8220;<span>iotexpert-mw-manifest.xml&#8221; to have the new middleware.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="xml">&lt;middleware&gt;
  &lt;name&gt;WiFi Helper Utilties&lt;/name&gt;
  &lt;id&gt;wifi_helper&lt;/id&gt;
  &lt;uri&gt;https://github.com/iotexpert/wifi_helper&lt;/uri&gt;
  &lt;desc&gt;A library WiFi Helper utilities (e.g. aton)&lt;/desc&gt;
  &lt;category&gt;IoT Expert&lt;/category&gt;
  &lt;req_capabilities&gt;psoc6&lt;/req_capabilities&gt;
  &lt;versions&gt;
    &lt;version flow_version="2.0"&gt;
      &lt;num&gt;main&lt;/num&gt;
      &lt;commit&gt;main&lt;/commit&gt;
      &lt;desc&gt;main&lt;/desc&gt;
    &lt;/version&gt;
  &lt;/versions&gt;
&lt;/middleware&gt;
</pre>
<p>If you recall I have the &#8220;wifi_helper&#8221; directory inside of my project.  Not what I want (because I want it to be pulled using the library browser).  So I move out my project directory.  Now, let&#8217;s test the whole thing by running the library browser.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">arh (master *+) IoTExpertWiFiTemplate $ pwd
/Users/arh/proj/elkhorncreek3/IoTExpertWiFiTemplate
arh (master *+) IoTExpertWiFiTemplate $ mv wifi_helper/ ~/proj/
arh (master *+) IoTExpertWiFiTemplate $ make modlibs
Tools Directory: /Applications/ModusToolbox/tools_2.3
CY8CKIT-062S2-43012.mk: ./libs/TARGET_CY8CKIT-062S2-43012/CY8CKIT-062S2-43012.mk
Launching library-manager</pre>
<p>Excellent the WiFI Helper utilities show up.</p>
<p><a href="https://iotexpert.com/?attachment_id=11309" rel="attachment wp-att-11309"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-7.46.08-AM-1024x792.jpg" alt="" width="1024" height="792" class="alignnone size-large wp-image-11309" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-7.46.08-AM-1024x792.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-7.46.08-AM-300x232.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-7.46.08-AM-768x594.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-7.46.08-AM-1536x1188.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-7.46.08-AM-2048x1584.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-7.46.08-AM-600x464.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>And when I run the &#8220;update&#8221; the files show up in the project.</p>
<p><a href="https://iotexpert.com/?attachment_id=11311" rel="attachment wp-att-11311"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-7.48.25-AM-330x1024.png" alt="" width="330" height="1024" class="alignnone size-large wp-image-11311" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-7.48.25-AM-330x1024.png 330w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-7.48.25-AM-97x300.png 97w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-7.48.25-AM-600x1864.png 600w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-7.48.25-AM.png 620w" sizes="auto, (max-width: 330px) 100vw, 330px" /></a></p>
<h1>Add Dependencies</h1>
<p>If you recall from the code I had this include:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "cy_wcm.h"</pre>
<p>That means that I am dependent on the library &#8220;<span>wifi-connection-manager&#8221;.  To make this work I create a new file called &#8220;iotexpert-mw-depenencies.xml&#8221;.  In that file I tell the system that &#8220;wifi_helper&#8221; is now dependent on &#8220;wcm&#8221;</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="xml">&lt;dependencies version="2.0"&gt;
  &lt;depender&gt;
    &lt;id&gt;wifi_helper&lt;/id&gt;
    &lt;versions&gt;
      &lt;version&gt;
        &lt;commit&gt;main&lt;/commit&gt;
        &lt;dependees&gt;
          &lt;dependee&gt;
            &lt;id&gt;wcm&lt;/id&gt;
            &lt;commit&gt;latest-v2.X&lt;/commit&gt;
          &lt;/dependee&gt;
        &lt;/dependees&gt;
      &lt;/version&gt;
    &lt;/versions&gt;
  &lt;/depender&gt;
&lt;/dependencies&gt;</pre>
<p>Once I have that file, I add that depencency file to my middleware manifest file.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="xml">  &lt;middleware-manifest-list&gt;
    &lt;middleware-manifest dependency-url="https://github.com/iotexpert/mtb2-iotexpert-manifests/raw/master/iotexpert-mw-dependencies.xml"&gt;
      &lt;uri&gt;https://github.com/iotexpert/mtb2-iotexpert-manifests/raw/master/iotexpert-mw-manifest.xml&lt;/uri&gt;
    &lt;/middleware-manifest&gt;
  &lt;/middleware-manifest-list&gt;
&lt;/super-manifest&gt;
</pre>
<p>Now when I start the library browser and add the &#8220;WiFi Help Utilities&#8221; it will automatically add the wireless connection manager (and all of the libraries that the wcm is dependent on.</p>
<p><a href="https://iotexpert.com/?attachment_id=11314" rel="attachment wp-att-11314"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-10.13.07-AM-1024x885.jpg" alt="" width="1024" height="885" class="alignnone size-large wp-image-11314" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-10.13.07-AM-1024x885.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-10.13.07-AM-300x259.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-10.13.07-AM-768x663.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-10.13.07-AM-1536x1327.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-10.13.07-AM-2048x1769.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-16-at-10.13.07-AM-600x518.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>In the next article I will add Scanning functionality to the WiFi Task.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-3-a-new-modus-toolbox-library/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AnyCloud WiFi Template + WiFi Helper Library (Part 1): Introduction</title>
		<link>https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/</link>
					<comments>https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/#comments</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 21 Jun 2021 09:40:58 +0000</pubDate>
				<category><![CDATA[AnyCloud]]></category>
		<category><![CDATA[Elkhorn Creek 3.0]]></category>
		<category><![CDATA[WIFI]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=11229</guid>

					<description><![CDATA[Summary The first article in a series that discusses building a new IoT project using Modus Toolbox and the AnyCloud SDK.  Specifically: The new-ish Error Logging library AnyCloud Wireless Connection Manager Creation of New Libraries and Template Projects Dual Role WiFi Access Point and Station using CYW43012 MDNS Story I am working on a new [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>The first article in a series that discusses building a new IoT project using Modus Toolbox and the AnyCloud SDK.  Specifically:</p>
<ol>
<li>The new-ish Error Logging library</li>
<li>AnyCloud Wireless Connection Manager</li>
<li>Creation of New Libraries and Template Projects</li>
<li>Dual Role WiFi Access Point and Station using CYW43012</li>
<li>MDNS</li>
</ol>
<h1>Story</h1>
<p>I am working on a new implementation of my Elkhorn Creek IoT monitoring system.  In some of the previous articles I discussed the usage of the Influx Database and Docker as a new cloud backend.  To make this whole thing better I wanted to replace the Raspberry Pi (current system) with a PSoC 6 MCU and a CYW43012 WiFi Chip.  In order to do this, I need to make the PSoC 6 talk to the Influx Database using the WiFi and the Influx DB WebAPI.  I started to build this from my IoT Expert template, but quickly realized that I should make a template project with WiFi.</p>
<p>In this series of article I teach you how to use the Wireless Connection Manager, make new libraries and make new template projects.  Here is the agenda:</p>
<p><span><p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
</tr>
</thead>
<tbody>
<tr><td >(Part 1) Create Basic Project &amp; Add Cypress Logging Functionality</td>
</tr>

<tr><td >(Part 2) Create New Thread to manage WiFi using the Wireless Connection Manager</td>
</tr>

<tr><td >(Part 3) Create a New Middleware Library with WiFi helper functions</td>
</tr>

<tr><td >(Part 4) Add WiFi Scan</td>
</tr>

<tr><td >Add WiFi Connect</td>
</tr>

<tr><td >Add WiFi Disconnect</td>
</tr>

<tr><td >Add WiFi Ping</td>
</tr>

<tr><td >Add Gethostbyname</td>
</tr>

<tr><td >Add MDNS</td>
</tr>

<tr><td >Add Status</td>
</tr>

<tr><td >Add StartAP</td>
</tr>

<tr><td >Make a new template project (update manifest)</td>
</tr>
</tbody></table></div></p></span></p>
<h1>Create Basic Project</h1>
<p>Today I happen to have a CY8CKIT-062S2-43012 on my desk.</p>
<p><a href="https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/img_0829/" rel="attachment wp-att-11327"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/IMG_0829-scaled-e1624096593430-1024x768.jpg" alt="" width="1024" height="768" class="alignnone wp-image-11327 size-large" srcset="https://iotexpert.com/wp-content/uploads/2021/06/IMG_0829-scaled-e1624096593430-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/06/IMG_0829-scaled-e1624096593430-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/06/IMG_0829-scaled-e1624096593430-768x576.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/06/IMG_0829-scaled-e1624096593430-1536x1152.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/06/IMG_0829-scaled-e1624096593430-2048x1536.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/06/IMG_0829-scaled-e1624096593430-600x450.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>So that looks like a good place to start.  Pick that development kit in from the new project creator.</p>
<p><a href="https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/screen-shot-2021-06-15-at-9-46-28-am/" rel="attachment wp-att-11264"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.46.28-AM-1024x710.jpg" alt="" width="1024" height="710" class="alignnone size-large wp-image-11264" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.46.28-AM-1024x710.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.46.28-AM-300x208.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.46.28-AM-768x532.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.46.28-AM-1536x1064.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.46.28-AM-2048x1419.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.46.28-AM-600x416.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>I want to start from my tried and true NT Shell, FreeRTOS Template.  If you use the filter window and type &#8220;iot&#8221; it will filter things down to just the IoT templates.  Notice that I selected that I want to get a &#8220;Microsoft Visual Studio Code&#8221; target workspace.</p>
<p><a href="https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/screen-shot-2021-06-15-at-9-49-07-am/" rel="attachment wp-att-11266"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.49.07-AM-1024x709.jpg" alt="" width="1024" height="709" class="alignnone size-large wp-image-11266" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.49.07-AM-1024x709.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.49.07-AM-300x208.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.49.07-AM-768x532.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.49.07-AM-1536x1064.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.49.07-AM-2048x1418.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.49.07-AM-600x416.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>After clicking create you will get a new project.</p>
<p><a href="https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/screen-shot-2021-06-15-at-9-49-42-am/" rel="attachment wp-att-11265"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.49.42-AM-1024x414.png" alt="" width="1024" height="414" class="alignnone size-large wp-image-11265" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.49.42-AM-1024x414.png 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.49.42-AM-300x121.png 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.49.42-AM-768x310.png 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.49.42-AM-1536x621.png 1536w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.49.42-AM-2048x827.png 2048w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.49.42-AM-600x242.png 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Something weird happened.  Well actually something bad happened.  When I start Visual Studio Code I get the message that I have multiple workspace files.  Why is that?</p>
<p><a href="https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/screen-shot-2021-06-19-at-6-04-57-am/" rel="attachment wp-att-11328"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-19-at-6.04.57-AM.png" alt="" width="958" height="302" class="alignnone size-full wp-image-11328" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-19-at-6.04.57-AM.png 958w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-19-at-6.04.57-AM-300x95.png 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-19-at-6.04.57-AM-768x242.png 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-19-at-6.04.57-AM-600x189.png 600w" sizes="auto, (max-width: 958px) 100vw, 958px" /></a></p>
<p>So I pick the first one.</p>
<p><a href="https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/screen-shot-2021-06-19-at-6-05-04-am/" rel="attachment wp-att-11329"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-19-at-6.05.04-AM-1024x201.png" alt="" width="1024" height="201" class="alignnone size-large wp-image-11329" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-19-at-6.05.04-AM-1024x201.png 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-19-at-6.05.04-AM-300x59.png 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-19-at-6.05.04-AM-768x151.png 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-19-at-6.05.04-AM-600x118.png 600w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-19-at-6.05.04-AM.png 1262w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now there is a problem.  In the Makefile for this project I find out that the &#8220;APPNAME&#8221; is MTBShellTemplate</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic"># Name of application (used to derive name of final linked file).
APPNAME=MTBShellTemplate</pre>
<p>By default when you run &#8220;make vscode&#8221; it will make a workspace file for you with the name &#8220;APPNAME.code-workspace&#8221;.  This has now created a problem for you.  Specifically, i<span style="font-size: 1rem;">f you regenerate the workspace by running &#8220;make vscode&#8221; you will update the WRONG file.  When the new project creator runs the &#8220;make vscode&#8221; it uses the name you entered on that form, not the one in the Makefile.</span></p>
<p>To fix this, edit he Makefile &amp; delete the old MTB&#8230;workspace.  Then re-run make vscode</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">APPNAME=IoTExpertWiFiTemplate</pre>
<p>I have been checking in the *.code-workspace file, but that may not be exactly the right thing to do.  I am not sure.  Oh well.  Here is what you screen should look like now that you have Visual Studio Code going.</p>
<p><a href="https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/screen-shot-2021-06-15-at-9-52-41-am/" rel="attachment wp-att-11270"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.52.41-AM-1024x757.jpg" alt="" width="1024" height="757" class="alignnone size-large wp-image-11270" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.52.41-AM-1024x757.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.52.41-AM-300x222.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.52.41-AM-768x568.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.52.41-AM-1536x1135.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.52.41-AM-2048x1514.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.52.41-AM-600x444.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>I always like to test things to make sure everything works before I start editing.  So, press the play button, then the green play button.</p>
<p><a href="https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/screen-shot-2021-06-15-at-9-56-50-am/" rel="attachment wp-att-11276"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.56.50-AM-1024x756.png" alt="" width="1024" height="756" class="alignnone size-large wp-image-11276" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.56.50-AM-1024x756.png 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.56.50-AM-300x222.png 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.56.50-AM-768x567.png 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.56.50-AM-600x443.png 600w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.56.50-AM.png 1056w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>It should build and program the development kit.</p>
<p><a href="https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/screen-shot-2021-06-15-at-9-53-36-am/" rel="attachment wp-att-11272"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.53.36-AM-1024x573.png" alt="" width="1024" height="573" class="alignnone size-large wp-image-11272" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.53.36-AM-1024x573.png 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.53.36-AM-300x168.png 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.53.36-AM-768x429.png 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.53.36-AM-1536x859.png 1536w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.53.36-AM-2048x1145.png 2048w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.53.36-AM-600x335.png 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Then stop at main.</p>
<p><a href="https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/screen-shot-2021-06-15-at-9-53-20-am/" rel="attachment wp-att-11271"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.53.20-AM-1024x759.jpg" alt="" width="1024" height="759" class="alignnone size-large wp-image-11271" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.53.20-AM-1024x759.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.53.20-AM-300x222.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.53.20-AM-768x569.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.53.20-AM-1536x1138.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.53.20-AM-2048x1518.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.53.20-AM-600x445.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Press play and your terminal should look something like this.  Notice that I typed &#8220;help&#8221; and &#8220;tasks&#8221;</p>
<p><a href="https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/screen-shot-2021-06-15-at-9-54-09-am/" rel="attachment wp-att-11274"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.54.09-AM-1024x807.png" alt="" width="1024" height="807" class="alignnone size-large wp-image-11274" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.54.09-AM-1024x807.png 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.54.09-AM-300x237.png 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.54.09-AM-768x606.png 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.54.09-AM-1536x1211.png 1536w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.54.09-AM-600x473.png 600w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-9.54.09-AM.png 1872w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Add the Cypress Logging Functionality</h1>
<p>Sometime recently the Software team added a logging capability.  This seems like a good time to try that that.  Start the library browser by running &#8220;make modlibs&#8221;.  Then enable the &#8220;connectivity-utilities&#8221;.  For some silly reason that is where the logging functions were added.</p>
<p><a href="https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/screen-shot-2021-06-15-at-10-06-50-am/" rel="attachment wp-att-11277"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.06.50-AM-1024x884.jpg" alt="" width="1024" height="884" class="alignnone size-large wp-image-11277" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.06.50-AM-1024x884.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.06.50-AM-300x259.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.06.50-AM-768x663.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.06.50-AM-1536x1325.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.06.50-AM-2048x1767.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.06.50-AM-600x518.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>If you look in the &#8220;mtb_shared&#8221; you will now the cy_log directory.</p>
<p><a href="https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/screen-shot-2021-06-15-at-10-08-39-am/" rel="attachment wp-att-11278"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.08.39-AM-537x1024.png" alt="" width="537" height="1024" class="alignnone size-large wp-image-11278" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.08.39-AM-537x1024.png 537w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.08.39-AM-157x300.png 157w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.08.39-AM-768x1464.png 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.08.39-AM-806x1536.png 806w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.08.39-AM-600x1144.png 600w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.08.39-AM.png 956w" sizes="auto, (max-width: 537px) 100vw, 537px" /></a></p>
<p>Then click on the &#8220;api_reference.html&#8221;</p>
<p><a href="https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/screen-shot-2021-06-15-at-10-09-08-am/" rel="attachment wp-att-11279"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.09.08-AM.png" alt="" width="922" height="1010" class="alignnone size-full wp-image-11279" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.09.08-AM.png 922w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.09.08-AM-274x300.png 274w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.09.08-AM-768x841.png 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.09.08-AM-600x657.png 600w" sizes="auto, (max-width: 922px) 100vw, 922px" /></a></p>
<p>And open it.</p>
<p><a href="https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/screen-shot-2021-06-15-at-10-10-11-am/" rel="attachment wp-att-11281"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.10.11-AM-1024x516.png" alt="" width="1024" height="516" class="alignnone size-large wp-image-11281" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.10.11-AM-1024x516.png 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.10.11-AM-300x151.png 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.10.11-AM-768x387.png 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.10.11-AM-1536x775.png 1536w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.10.11-AM-600x303.png 600w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.10.11-AM.png 1832w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Cool.  This gives you some insight into the capability.</p>
<p><a href="https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/screen-shot-2021-06-15-at-10-09-38-am/" rel="attachment wp-att-11280"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.09.38-AM-1024x600.jpg" alt="" width="1024" height="600" class="alignnone size-large wp-image-11280" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.09.38-AM-1024x600.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.09.38-AM-300x176.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.09.38-AM-768x450.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.09.38-AM-1536x900.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.09.38-AM-2048x1201.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.09.38-AM-600x352.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>A simple test will be to printout a &#8220;blink&#8221; message in sync with the default blinking led.  To do this, I modify the blink_task in main.c  Take the following actions</p>
<ol>
<li>Add the include &#8220;cy_log.h&#8221;</li>
<li>Add the initialization call &#8220;cy_log_init&#8221;</li>
<li>Printout a test message using &#8220;cy_log_msg&#8221;</li>
<li>Fix the stack</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">#include "cyhal.h"
#include "cybsp.h"
#include "cy_retarget_io.h"
#include &lt;stdio.h&gt;
#include "FreeRTOS.h"
#include "task.h"
#include "usrcmd.h"
#include "cy_log.h"

volatile int uxTopUsedPriority ;
TaskHandle_t blinkTaskHandle;


void blink_task(void *arg)
{
    cyhal_gpio_init(CYBSP_USER_LED,CYHAL_GPIO_DIR_OUTPUT,CYHAL_GPIO_DRIVE_STRONG,0);

    for(;;)
    {
        cy_log_msg(CYLF_DEF,CY_LOG_INFO,"Blink Info\n");
    	cyhal_gpio_toggle(CYBSP_USER_LED);
    	vTaskDelay(500);
    }
}


int main(void)
{
    uxTopUsedPriority = configMAX_PRIORITIES - 1 ; // enable OpenOCD Thread Debugging

    /* Initialize the device and board peripherals */
    cybsp_init() ;
    __enable_irq();

    cy_retarget_io_init(CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX, CY_RETARGET_IO_BAUDRATE);

    cy_log_init(CY_LOG_INFO,0,0);


    // Stack size in WORDs
    // Idle task = priority 0
    xTaskCreate(blink_task, "blinkTask", configMINIMAL_STACK_SIZE*2,0 /* args */ ,0 /* priority */, &amp;blinkTaskHandle);
    xTaskCreate(usrcmd_task, "usrcmd_task", configMINIMAL_STACK_SIZE*4,0 /* args */ ,0 /* priority */, 0);
    vTaskStartScheduler();
}</pre>
<p>When you run this, you will get the message repeatedly coming on the screen (probably gonna-want-a delete this before you go on)</p>
<p><a href="https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/screen-shot-2021-06-15-at-10-27-18-am/" rel="attachment wp-att-11282"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.27.18-AM-1024x799.png" alt="" width="1024" height="799" class="alignnone size-large wp-image-11282" srcset="https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.27.18-AM-1024x799.png 1024w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.27.18-AM-300x234.png 300w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.27.18-AM-768x599.png 768w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.27.18-AM-1536x1199.png 1536w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.27.18-AM-600x468.png 600w, https://iotexpert.com/wp-content/uploads/2021/06/Screen-Shot-2021-06-15-at-10.27.18-AM.png 1886w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now that we have a working project with logging, in the next article Ill add WiFi</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/anycloud-wifi-template-wifi-helper-library-part-1-introduction/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>The Creek 3.0: Docker &#038; InfluxDB</title>
		<link>https://iotexpert.com/the-creek-3-0-docker-influxdb/</link>
					<comments>https://iotexpert.com/the-creek-3-0-docker-influxdb/#comments</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 07 Jun 2021 12:00:10 +0000</pubDate>
				<category><![CDATA[Elkhorn Creek 3.0]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=11196</guid>

					<description><![CDATA[Summary Instructions for installing InfluxDB2 in a docker container and writing a Python program to insert data. Story I don&#8217;t really have a long complicated story about how I got here.  I just wanted to replace my Java, MySQL, Tomcat setup with something newer.  I wanted to do it without writing a bunch of code. [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>Instructions for installing InfluxDB2 in a docker container and writing a Python program to insert data.</p>
<h1>Story</h1>
<p>I don&#8217;t really have a long complicated story about how I got here.  I just wanted to replace my Java, MySQL, Tomcat setup with something newer.  I wanted to do it without writing a bunch of code.  It seemed like Docker + Influx + Telegraph + Grafana was a good answer.  In this article I install Influx DB on my new server using Docker.  Then I hookup my Creek data via a Python script.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-docker-telegraf-influx-grafana-part-1/arch-6/" rel="attachment wp-att-11194"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/arch-1-1024x307.png" alt="" width="1024" height="307" class="alignnone size-large wp-image-11194" srcset="https://iotexpert.com/wp-content/uploads/2021/05/arch-1-1024x307.png 1024w, https://iotexpert.com/wp-content/uploads/2021/05/arch-1-300x90.png 300w, https://iotexpert.com/wp-content/uploads/2021/05/arch-1-768x230.png 768w, https://iotexpert.com/wp-content/uploads/2021/05/arch-1-1536x460.png 1536w, https://iotexpert.com/wp-content/uploads/2021/05/arch-1-600x180.png 600w, https://iotexpert.com/wp-content/uploads/2021/05/arch-1.png 1652w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Docker &amp; InfluxDB</h1>
<p>I have become a huge believer in using Docker, I think it is remarkable what they did.  I also think that using docker-compose is the correct way to launch new docker containers so that you don&#8217;t loose the secret sauce on the command line when doing a &#8220;docker run&#8221;.  Let&#8217;s get this whole thing going by creating a new docker-compose.yaml file with the description of our new docker container.  It is pretty simple:</p>
<ol>
<li>Specify the influxdb image</li>
<li>Map port 8086 on the client and on the container</li>
<li>Specify the initial conditions for the Influxdb &#8211; these are nicely documented in the installation instructions <a href="https://docs.influxdata.com/influxdb/v2.0/get-started/?t=Docker" target="_blank" rel="noopener">here</a>.</li>
<li>Create a volume</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">version: "3.3"  # optional since v1.27.0
services:
  influxdb:
    image: influxdb
    ports:
      - "8086:8086"
    environment:
      - DOCKER_INFLUXDB_INIT_MODE=setup
      - DOCKER_INFLUXDB_INIT_USERNAME=root
      - DOCKER_INFLUXDB_INIT_PASSWORD=password
      - DOCKER_INFLUXDB_INIT_ORG=creekdata
      - DOCKER_INFLUXDB_INIT_BUCKET=creekdata
    volumes:
      - influxdb2:/var/lib/influxdb2

volumes:
  influxdb2:</pre>
<p>Once you have that file you can run &#8220;docker-compose up&#8221;&#8230; and wait &#8230; until everything gets pulled from the docker hub.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">arh@spiff:~/influx-telegraf-grafana$ docker-compose up
Creating network "influx-telegraf-grafana_default" with the default driver
Creating volume "influx-telegraf-grafana_influxdb2" with default driver
Pulling influxdb (influxdb:)...
latest: Pulling from library/influxdb
d960726af2be: Pull complete
e8d62473a22d: Pull complete
8962bc0fad55: Pull complete
3b26e21cfb07: Pull complete
f77b907603e3: Pull complete
2b137bdfa0c5: Pull complete
7e6fa243fc79: Pull complete
3e0cae572c4f: Pull complete
9a27f9435a76: Pull complete
Digest: sha256:090ba796c2e5c559b9acede14fc7c1394d633fb730046dd2f2ebf400acc22fc0
Status: Downloaded newer image for influxdb:latest
Creating influx-telegraf-grafana_influxdb_1 ... done
Attaching to influx-telegraf-grafana_influxdb_1
influxdb_1  | 2021-05-19T12:37:14.866162317Z	info	booting influxd server in the background	{"system": "docker"}
influxdb_1  | 2021-05-19T12:37:16.867909370Z	info	pinging influxd...	{"system": "docker"}
influxdb_1  | 2021-05-19T12:37:18.879390124Z	info	pinging influxd...	{"system": "docker"}
influxdb_1  | 2021-05-19T12:37:20.891280023Z	info	pinging influxd...	{"system": "docker"}
influxdb_1  | ts=2021-05-19T12:37:21.065674Z lvl=info msg="Welcome to InfluxDB" log_id=0UD9wCAG000 version=2.0.6 commit=4db98b4c9a build_date=2021-04-29T16:48:12Z
influxdb_1  | ts=2021-05-19T12:37:21.068517Z lvl=info msg="Resources opened" log_id=0UD9wCAG000 service=bolt path=/var/lib/influxdb2/influxd.bolt
influxdb_1  | ts=2021-05-19T12:37:21.069293Z lvl=info msg="Bringing up metadata migrations" log_id=0UD9wCAG000 service=migrations migration_count=15
influxdb_1  | ts=2021-05-19T12:37:21.132269Z lvl=info msg="Using data dir" log_id=0UD9wCAG000 service=storage-engine service=store path=/var/lib/influxdb2/engine/data
influxdb_1  | ts=2021-05-19T12:37:21.132313Z lvl=info msg="Compaction settings" log_id=0UD9wCAG000 service=storage-engine service=store max_concurrent_compactions=3 throughput_bytes_per_second=50331648 throughput_bytes_per_second_burst=50331648
influxdb_1  | ts=2021-05-19T12:37:21.132325Z lvl=info msg="Open store (start)" log_id=0UD9wCAG000 service=storage-engine service=store op_name=tsdb_open op_event=start
influxdb_1  | ts=2021-05-19T12:37:21.132383Z lvl=info msg="Open store (end)" log_id=0UD9wCAG000 service=storage-engine service=store op_name=tsdb_open op_event=end op_elapsed=0.059ms
influxdb_1  | ts=2021-05-19T12:37:21.132407Z lvl=info msg="Starting retention policy enforcement service" log_id=0UD9wCAG000 service=retention check_interval=30m
influxdb_1  | ts=2021-05-19T12:37:21.132428Z lvl=info msg="Starting precreation service" log_id=0UD9wCAG000 service=shard-precreation check_interval=10m advance_period=30m
influxdb_1  | ts=2021-05-19T12:37:21.132446Z lvl=info msg="Starting query controller" log_id=0UD9wCAG000 service=storage-reads concurrency_quota=1024 initial_memory_bytes_quota_per_query=9223372036854775807 memory_bytes_quota_per_query=9223372036854775807 max_memory_bytes=0 queue_size=1024
influxdb_1  | ts=2021-05-19T12:37:21.133391Z lvl=info msg="Configuring InfluxQL statement executor (zeros indicate unlimited)." log_id=0UD9wCAG000 max_select_point=0 max_select_series=0 max_select_buckets=0
influxdb_1  | ts=2021-05-19T12:37:21.434078Z lvl=info msg=Starting log_id=0UD9wCAG000 service=telemetry interval=8h
influxdb_1  | ts=2021-05-19T12:37:21.434165Z lvl=info msg=Listening log_id=0UD9wCAG000 service=tcp-listener transport=http addr=:9999 port=9999
influxdb_1  | 2021-05-19T12:37:22.905008706Z	info	pinging influxd...	{"system": "docker"}
influxdb_1  | 2021-05-19T12:37:22.920976742Z	info	got response from influxd, proceeding	{"system": "docker"}
influxdb_1  | Config default has been stored in /etc/influxdb2/influx-configs.
influxdb_1  | User	Organization	Bucket
influxdb_1  | root	creekdata	creekdata
influxdb_1  | 2021-05-19T12:37:23.043336133Z	info	Executing user-provided scripts	{"system": "docker", "script_dir": "/docker-entrypoint-initdb.d"}
influxdb_1  | 2021-05-19T12:37:23.044663106Z	info	initialization complete, shutting down background influxd	{"system": "docker"}
influxdb_1  | ts=2021-05-19T12:37:23.044900Z lvl=info msg="Terminating precreation service" log_id=0UD9wCAG000 service=shard-precreation
influxdb_1  | ts=2021-05-19T12:37:23.044906Z lvl=info msg=Stopping log_id=0UD9wCAG000 service=telemetry interval=8h
influxdb_1  | ts=2021-05-19T12:37:23.044920Z lvl=info msg=Stopping log_id=0UD9wCAG000 service=scraper
influxdb_1  | ts=2021-05-19T12:37:23.044970Z lvl=info msg=Stopping log_id=0UD9wCAG000 service=tcp-listener
influxdb_1  | ts=2021-05-19T12:37:23.545252Z lvl=info msg=Stopping log_id=0UD9wCAG000 service=task
influxdb_1  | ts=2021-05-19T12:37:23.545875Z lvl=info msg=Stopping log_id=0UD9wCAG000 service=nats
influxdb_1  | ts=2021-05-19T12:37:23.546765Z lvl=info msg=Stopping log_id=0UD9wCAG000 service=bolt
influxdb_1  | ts=2021-05-19T12:37:23.546883Z lvl=info msg=Stopping log_id=0UD9wCAG000 service=query
influxdb_1  | ts=2021-05-19T12:37:23.548747Z lvl=info msg=Stopping log_id=0UD9wCAG000 service=storage-engine
influxdb_1  | ts=2021-05-19T12:37:23.548788Z lvl=info msg="Closing retention policy enforcement service" log_id=0UD9wCAG000 service=retention
influxdb_1  | ts=2021-05-19T12:37:29.740107Z lvl=info msg="Welcome to InfluxDB" log_id=0UD9wj2l000 version=2.0.6 commit=4db98b4c9a build_date=2021-04-29T16:48:12Z
influxdb_1  | ts=2021-05-19T12:37:29.751816Z lvl=info msg="Resources opened" log_id=0UD9wj2l000 service=bolt path=/var/lib/influxdb2/influxd.bolt
influxdb_1  | ts=2021-05-19T12:37:29.756974Z lvl=info msg="Checking InfluxDB metadata for prior version." log_id=0UD9wj2l000 bolt_path=/var/lib/influxdb2/influxd.bolt
influxdb_1  | ts=2021-05-19T12:37:29.757053Z lvl=info msg="Using data dir" log_id=0UD9wj2l000 service=storage-engine service=store path=/var/lib/influxdb2/engine/data
influxdb_1  | ts=2021-05-19T12:37:29.757087Z lvl=info msg="Compaction settings" log_id=0UD9wj2l000 service=storage-engine service=store max_concurrent_compactions=3 throughput_bytes_per_second=50331648 throughput_bytes_per_second_burst=50331648
influxdb_1  | ts=2021-05-19T12:37:29.757099Z lvl=info msg="Open store (start)" log_id=0UD9wj2l000 service=storage-engine service=store op_name=tsdb_open op_event=start
influxdb_1  | ts=2021-05-19T12:37:29.757149Z lvl=info msg="Open store (end)" log_id=0UD9wj2l000 service=storage-engine service=store op_name=tsdb_open op_event=end op_elapsed=0.051ms
influxdb_1  | ts=2021-05-19T12:37:29.757182Z lvl=info msg="Starting retention policy enforcement service" log_id=0UD9wj2l000 service=retention check_interval=30m
influxdb_1  | ts=2021-05-19T12:37:29.757187Z lvl=info msg="Starting precreation service" log_id=0UD9wj2l000 service=shard-precreation check_interval=10m advance_period=30m
influxdb_1  | ts=2021-05-19T12:37:29.757205Z lvl=info msg="Starting query controller" log_id=0UD9wj2l000 service=storage-reads concurrency_quota=1024 initial_memory_bytes_quota_per_query=9223372036854775807 memory_bytes_quota_per_query=9223372036854775807 max_memory_bytes=0 queue_size=1024
influxdb_1  | ts=2021-05-19T12:37:29.758844Z lvl=info msg="Configuring InfluxQL statement executor (zeros indicate unlimited)." log_id=0UD9wj2l000 max_select_point=0 max_select_series=0 max_select_buckets=0
influxdb_1  | ts=2021-05-19T12:37:30.056855Z lvl=info msg=Listening log_id=0UD9wj2l000 service=tcp-listener transport=http addr=:8086 port=8086
influxdb_1  | ts=2021-05-19T12:37:30.056882Z lvl=info msg=Starting log_id=0UD9wj2l000 service=telemetry interval=8h
</pre>
<p>After everything is rolling you can open up a web browser and go to &#8220;http://localhost:8086&#8221; and you should see something like this:  (I will sort out the http vs https in a later post &#8211; because I don&#8217;t actually know how to fix it right now.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-docker-influxdb/screen-shot-2021-05-19-at-8-38-17-am/" rel="attachment wp-att-11198"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.38.17-AM-1024x770.png" alt="" width="1024" height="770" class="alignnone size-large wp-image-11198" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.38.17-AM-1024x770.png 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.38.17-AM-300x226.png 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.38.17-AM-768x578.png 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.38.17-AM-1536x1155.png 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.38.17-AM-2048x1540.png 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.38.17-AM-600x451.png 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Once you enter the account and password (that you configured in the docker-compose.yaml&#8221; you will see this screen and you are off to the races.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-docker-influxdb/screen-shot-2021-05-19-at-8-38-43-am/" rel="attachment wp-att-11199"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.38.43-AM-1024x768.jpg" alt="" width="1024" height="768" class="alignnone size-large wp-image-11199" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.38.43-AM-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.38.43-AM-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.38.43-AM-768x576.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.38.43-AM-1536x1151.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.38.43-AM-2048x1535.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.38.43-AM-600x450.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>InfluxDB Basics</h1>
<p>Before we go too much further lets talk about some of the basics of the Influx Database.  An Influx Database also called a &#8220;bucket&#8221; has the following built in columns:</p>
<ul>
<li>_timestamp: The time for the data point stored in epoch nanosecond format (how&#8217;s that for some precision)</li>
<li>_measurement: A text string name for the a group of related datapoints</li>
<li>_field: A text string key for the datapoint</li>
<li>_value: The value of the datapoint</li>
</ul>
<p>In addition you can add &#8220;ad-hoc&#8221; columns called &#8220;tags&#8221; which have a &#8220;key&#8221; and a &#8220;value&#8221;</p>
<div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Organization</th>
<th >A group of users and the related buckets, dashboards and tasks</th>
</tr>
</thead>
<tbody>
<tr><td >Bucket</td>
<td >A database</td>
</tr>

<tr><td >Timestamp</td>
<td >The time of the datapoint measured in epoch nanoseconds</td>
</tr>

<tr><td >Field</td>
<td >A field includes a field key stored in the _field column and a field value stored in the _value column.</td>
</tr>

<tr><td >Field Set</td>
<td >A field set is a collection of field key-value pairs associated with a timestamp.</td>
</tr>

<tr><td >Measurement</td>
<td >A measurement acts as a container for tags</td>
<td > fields</td>
<td > and timestamps. Use a measurement name that describes your data.</td>
</tr>

<tr><td >Tag</td>
<td >Key/Value pairs assigned to a datapoint.  They are used to index the datapoints (so searches are faster)</td>
</tr>
</tbody></table></div>
<p>Here is a snapshot of the data in my Creek Influx database.  You can see that I have two fields</p>
<ul>
<li>depth</li>
<li>temperature</li>
</ul>
<p>I am saving all of the datapoints in the &#8220;elkhorncreek&#8221; _measurement.  And there are no tags (but I have ideas for that in the future)</p>
<p><a href="https://iotexpert.com/the-creek-3-0-docker-influxdb/screen-shot-2021-05-22-at-9-14-19-am/" rel="attachment wp-att-11219"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-22-at-9.14.19-AM-1003x1024.png" alt="" width="1003" height="1024" class="alignnone size-large wp-image-11219" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-22-at-9.14.19-AM-1003x1024.png 1003w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-22-at-9.14.19-AM-294x300.png 294w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-22-at-9.14.19-AM-768x784.png 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-22-at-9.14.19-AM-600x612.png 600w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-22-at-9.14.19-AM.png 1058w" sizes="auto, (max-width: 1003px) 100vw, 1003px" /></a></p>
<h1>InfluxDB Line Protocol</h1>
<p>There are a number of different methods to insert data into the Influx DB.  Several of them rely on &#8220;<a href="https://docs.influxdata.com/influxdb/v2.0/reference/syntax/line-protocol/" target="_blank" rel="noopener">Line Protocol</a>&#8220;.  This is simply a text string formatted like this:</p>
<p><a href="https://iotexpert.com/the-creek-3-0-docker-influxdb/screen-shot-2021-05-22-at-9-26-51-am/" rel="attachment wp-att-11221"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-22-at-9.26.51-AM-1024x330.png" alt="" width="1024" height="330" class="alignnone size-large wp-image-11221" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-22-at-9.26.51-AM-1024x330.png 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-22-at-9.26.51-AM-300x97.png 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-22-at-9.26.51-AM-768x247.png 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-22-at-9.26.51-AM-1536x495.png 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-22-at-9.26.51-AM-600x193.png 600w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-22-at-9.26.51-AM.png 1744w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>For my purposes a text string like this will insert a new datapoint into the &#8220;elkhorncreek&#8221; measurement with a depth of 1.85 fee and a temperature of 19c (yes we are a mixed unit household)</p>
<ul>
<li>elkhorncreek depth=1.85,temperature=19.0</li>
</ul>
<h1>Python &amp; InfluxDB</h1>
<p>I know that I want to run a Python program on the Raspberry Pi which gets the sensor data via I2C and then writes it into the cloud using the InfluxAPI.  It turns out that when you log into you new Influx DB that there is a built in webpage which shows you exactly how to do this.  Click on &#8220;Data&#8221; then &#8220;sources&#8221; then &#8220;Python&#8221;</p>
<p><a href="https://iotexpert.com/the-creek-3-0-docker-influxdb/screen-shot-2021-05-19-at-8-50-20-am/" rel="attachment wp-att-11205"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.50.20-AM-1024x519.png" alt="" width="1024" height="519" class="alignnone size-large wp-image-11205" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.50.20-AM-1024x519.png 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.50.20-AM-300x152.png 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.50.20-AM-768x389.png 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.50.20-AM-1536x779.png 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.50.20-AM-2048x1039.png 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.50.20-AM-600x304.png 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>You will see a screen like this which has exactly the Python code you need (almost).</p>
<p><a href="https://iotexpert.com/the-creek-3-0-docker-influxdb/screen-shot-2021-05-19-at-8-51-18-am/" rel="attachment wp-att-11206"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.51.18-AM-1024x846.jpg" alt="" width="1024" height="846" class="alignnone size-large wp-image-11206" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.51.18-AM-1024x846.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.51.18-AM-300x248.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.51.18-AM-768x635.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.51.18-AM-1536x1270.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.51.18-AM-2048x1693.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.51.18-AM-600x496.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>To make this code work on your system you need to install the influxdb-client library by running &#8220;pip install influxdb-client&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">(venv) pi@iotexpertpi:~/influx-test $ pip install influxdb-client
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting influxdb-client
  Using cached https://files.pythonhosted.org/packages/6b/0e/5c5a9a2da144fae80b23dd9741175493d8dbeabd17d23e5aff27c92dbfd5/influxdb_client-1.17.0-py3-none-any.whl
Collecting urllib3&gt;=1.15.1 (from influxdb-client)
  Using cached https://files.pythonhosted.org/packages/09/c6/d3e3abe5b4f4f16cf0dfc9240ab7ce10c2baa0e268989a4e3ec19e90c84e/urllib3-1.26.4-py2.py3-none-any.whl
Collecting pytz&gt;=2019.1 (from influxdb-client)
  Using cached https://files.pythonhosted.org/packages/70/94/784178ca5dd892a98f113cdd923372024dc04b8d40abe77ca76b5fb90ca6/pytz-2021.1-py2.py3-none-any.whl
Collecting certifi&gt;=14.05.14 (from influxdb-client)
  Using cached https://files.pythonhosted.org/packages/5e/a0/5f06e1e1d463903cf0c0eebeb751791119ed7a4b3737fdc9a77f1cdfb51f/certifi-2020.12.5-py2.py3-none-any.whl
Collecting rx&gt;=3.0.1 (from influxdb-client)
  Using cached https://files.pythonhosted.org/packages/e2/a9/efeaeca4928a9a56d04d609b5730994d610c82cf4d9dd7aa173e6ef4233e/Rx-3.2.0-py3-none-any.whl
Collecting six&gt;=1.10 (from influxdb-client)
  Using cached https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl
Requirement already satisfied: setuptools&gt;=21.0.0 in ./venv/lib/python3.7/site-packages (from influxdb-client) (40.8.0)
Collecting python-dateutil&gt;=2.5.3 (from influxdb-client)
  Using cached https://files.pythonhosted.org/packages/d4/70/d60450c3dd48ef87586924207ae8907090de0b306af2bce5d134d78615cb/python_dateutil-2.8.1-py2.py3-none-any.whl
Installing collected packages: urllib3, pytz, certifi, rx, six, python-dateutil, influxdb-client
Successfully installed certifi-2020.12.5 influxdb-client-1.17.0 python-dateutil-2.8.1 pytz-2021.1 rx-3.2.0 six-1.16.0 urllib3-1.26.4
(venv) pi@iotexpertpi:~/influx-test $</pre>
<p>Now write a little bit of code.  If you remember from the previous post I run a cronjob that gets the data from the I2C.  It will then run this program to do the insert of the data into the Influxdb.  Notice that I get the depth and temperature from the command line.   The &#8220;token&#8221; is an API key which you must include with requests to identify you are having permission to write into the database (more on this later).  The &#8220;data&#8221; variable is just a string formatted in &#8220;Influx Line Protocol&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">import sys
from datetime import datetime
from influxdb_client import InfluxDBClient, Point, WritePrecision
from influxdb_client.client.write_api import SYNCHRONOUS

if len(sys.argv) != 3:
    sys.exit("Wrong number of arguments")

# You can generate a Token from the "Tokens Tab" in the UI
token = "UvZvrrnk8yXvlVm1yrMmH2ZE706dZ14kpqSoE2u0COnDdqmQFTmIWPMjk0U2tO_GqmjzCupi_EaYP65RP4bELQ=="
org = "creekdata"
bucket = "creekdata"

client = InfluxDBClient(url="http://linux.local:8086", token=token)

write_api = client.write_api(write_options=SYNCHRONOUS)

data = f"elkhorncreek depth={sys.argv[1]},temperature={sys.argv[2]}"
write_api.write(bucket, org, data)
#print(data)</pre>
<p>Now I update my getInsertData.sh shell script to run the Influx as well as the original MySQL insert.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">#!/bin/bash

cd ~/influxdb
source venv/bin/activate
vals=$(python getData.py)
#echo $vals
python insertMysql.py $vals
python insertInflux.py $vals</pre>
<h1>InfluxDB Data Explorer</h1>
<p>After a bit of time (for some inserts to happen) I go to the data explorer in the web interface.  You can see that I have a number of readings.  This is filtering for &#8220;depth&#8221;</p>
<p><a href="https://iotexpert.com/the-creek-3-0-docker-influxdb/screen-shot-2021-05-19-at-8-43-18-am/" rel="attachment wp-att-11202"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.43.18-AM-1024x768.jpg" alt="" width="1024" height="768" class="alignnone size-large wp-image-11202" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.43.18-AM-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.43.18-AM-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.43.18-AM-768x576.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.43.18-AM-1536x1152.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.43.18-AM-2048x1536.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.43.18-AM-600x450.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>This is filtering for &#8220;temperature&#8221;</p>
<p><a href="https://iotexpert.com/the-creek-3-0-docker-influxdb/screen-shot-2021-05-19-at-8-46-29-am/" rel="attachment wp-att-11203"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.46.29-AM-1024x429.jpg" alt="" width="1024" height="429" class="alignnone size-large wp-image-11203" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.46.29-AM-1024x429.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.46.29-AM-300x126.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.46.29-AM-768x322.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.46.29-AM-1536x644.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.46.29-AM-2048x858.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.46.29-AM-600x251.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Influx Tokens</h1>
<p>To interact with an instance of the InfluxDB you will need an API key, which they call a token.  Press the &#8220;data&#8221; icon on the left side of the screen.  Then click &#8220;Tokens&#8221;.  You will see the currently available tokens, in this case just the original token.  You can create more tokens by pressing the blue + generate Token icon.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-docker-influxdb/screen-shot-2021-05-19-at-8-39-06-am/" rel="attachment wp-att-11200"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.39.06-AM-1024x768.jpg" alt="" width="1024" height="768" class="alignnone size-large wp-image-11200" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.39.06-AM-1024x768.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.39.06-AM-300x225.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.39.06-AM-768x576.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.39.06-AM-1536x1152.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.39.06-AM-2048x1536.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.39.06-AM-600x450.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Clock on the token.  Then copy it to your clipboard.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-docker-influxdb/screen-shot-2021-05-19-at-8-39-17-am/" rel="attachment wp-att-11201"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.39.17-AM-1024x859.png" alt="" width="1024" height="859" class="alignnone size-large wp-image-11201" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.39.17-AM-1024x859.png 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.39.17-AM-300x252.png 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.39.17-AM-768x644.png 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.39.17-AM-1536x1288.png 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.39.17-AM-600x503.png 600w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-19-at-8.39.17-AM.png 1646w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/the-creek-3-0-docker-influxdb/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>The Creek 3.0: A Docker MySQL Diversion &#8211; Part 2.5</title>
		<link>https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2-5/</link>
					<comments>https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2-5/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 24 May 2021 12:00:40 +0000</pubDate>
				<category><![CDATA[Elkhorn Creek 3.0]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=11183</guid>

					<description><![CDATA[Summary A discussion of reading I2C data from a sensor and sending it to a MySQL instance in the cloud using Python. I was originally planning only one article on the MySQL part of this project.  But things got really out of control and I ended up splitting the article into two parts.  I jokingly [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>A discussion of reading I2C data from a sensor and sending it to a MySQL instance in the cloud using Python.</p>
<p>I was originally planning only one <a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/">article</a> on the MySQL part of this project.  But things got really out of control and I ended up splitting the article into two parts.  I jokingly called this article &#8220;Part 2.5&#8221;.  In today&#8217;s article I&#8217;ll take the steps to have Python and the libraries running on the Raspberry Pi to read data and send it to my new Docker MySQL Server.</p>
<p>Here is what the picture looks like:</p>
<p><a href="https://iotexpert.com/the-creek-3-0-docker-telegraf-influx-grafana-part-1/arch-5/" rel="attachment wp-att-11128"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/arch-1024x307.png" alt="" width="1024" height="307" class="alignnone size-large wp-image-11128" srcset="https://iotexpert.com/wp-content/uploads/2021/05/arch-1024x307.png 1024w, https://iotexpert.com/wp-content/uploads/2021/05/arch-300x90.png 300w, https://iotexpert.com/wp-content/uploads/2021/05/arch-768x230.png 768w, https://iotexpert.com/wp-content/uploads/2021/05/arch-1536x460.png 1536w, https://iotexpert.com/wp-content/uploads/2021/05/arch-600x180.png 600w, https://iotexpert.com/wp-content/uploads/2021/05/arch.png 1652w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Build the Python Environment w/smbus &amp; mysql-connector-python</h1>
<p>I typically like to build a Python virtual environment with the specific version of python and all of the required packages.  To do this you need to</p>
<ol>
<li>python3 -m venv venv</li>
<li>source venv/bin/activate</li>
<li>pip install smbus</li>
<li>pip install mysql-connector-python</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">pi@iotexpertpi:~ $ mkdir mysql-docker
pi@iotexpertpi:~ $ python3 -m venv venv
pi@iotexpertpi:~ $ source venv/bin/activate
(venv) pi@iotexpertpi:~ $ pip install smbus
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting smbus
  Using cached https://www.piwheels.org/simple/smbus/smbus-1.1.post2-cp37-cp37m-linux_armv6l.whl
Installing collected packages: smbus
Successfully installed smbus-1.1.post2
(venv) pi@iotexpertpi:~ $ pip install mysql-connector-python
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting mysql-connector-python
  Using cached https://files.pythonhosted.org/packages/2a/8a/428d6be58fab7106ab1cacfde3076162cd3621ef7fc6871da54da15d857d/mysql_connector_python-8.0.25-py2.py3-none-any.whl
Collecting protobuf&gt;=3.0.0 (from mysql-connector-python)
  Downloading https://files.pythonhosted.org/packages/6b/2c/62cee2a27a1c4c0189582330774ed6ac2bfc88cb223f04723620ee04d59d/protobuf-3.17.0-py2.py3-none-any.whl (173kB)
    100% |████████████████████████████████| 174kB 232kB/s 
Collecting six&gt;=1.9 (from protobuf&gt;=3.0.0-&gt;mysql-connector-python)
  Using cached https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl
Installing collected packages: six, protobuf, mysql-connector-python
Successfully installed mysql-connector-python-8.0.25 protobuf-3.17.0 six-1.16.0
(venv) pi@iotexpertpi:~</pre>
<p>Once that is done you can see that everything is copasetic by running &#8220;pip freeze&#8221; where you can see the mysql-connector-python and the smbus.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">(venv) pi@iotexpertpi:~ $ pip freeze
mysql-connector-python==8.0.25
pkg-resources==0.0.0
protobuf==3.17.0
six==1.16.0
smbus==1.1.post2</pre>
<h1>Python: Get Data SMBUS</h1>
<p>If you remember from the <a href="https://iotexpert.com/the-creek-psoc-4-creator-schematic-firmware/" target="_blank" rel="noopener">original design</a> that the PSoC 4 acts as a register file with the data from the temperature and pressure sensor.  It has 12 bytes of data as</p>
<ol>
<li>2-bytes formatted as a 16-bit unsigned ADC counts from the Pressure Sensor</li>
<li>2-bytes formatted as a 16-bit signed pressure in &#8220;centiTemp&#8221;</li>
<li>4-bytes float as the depth in Feet</li>
<li>4-bytes float as the temperature in Centigrade</li>
</ol>
<p>This program:</p>
<ol>
<li>Reads the I2c for 12-bytes</li>
<li>Converts it into an array</li>
<li>Prints out the values</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import struct
import sys
import smbus
from datetime import datetime
from influxdb_client import InfluxDBClient, Point, WritePrecision
from influxdb_client.client.write_api import SYNCHRONOUS


######################################################
#Read the data from the PSoC 4
######################################################
bus = smbus.SMBus(1)
address = 0x08

# The data structure in the PSOC 4 is:
# uint16_t pressureCount ; the adc-counts being read on the pressure sensor
# int16_t centiTemp ; the temperaure in 10ths of a degree C
# float depth ; four bytes float representing the depth in Feet
# float temperature ; four byte float representing the temperature in degrees C

numBytesInStruct = 12
block = bus.read_i2c_block_data(address, 0, numBytesInStruct)

# convert list of bytes returned from sensor into array of bytes
mybytes = bytearray(block)
# convert the byte array into
# H=Unsigned 16-bit int
# h=Signed 16-bit int
# f=Float 
# this function will return a tuple with pressureCount,centiTemp,depth,temperature
vals = struct.unpack_from('Hhff',mybytes,0)
# prints the tuple
depth = vals[2]
temperature = vals[3]
print(f"{depth} {temperature}")
</pre>
<h1>Python: MySQL</h1>
<p>I created a separate Python program to insert the data into the MySQL database.  This program does the following things</p>
<ol>
<li>Makes sure the command line arguments make sense</li>
<li>Makes a connection to the server</li>
<li>Creates the SQL statement</li>
<li>Runs the inserts</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import mysql.connector
import sys
from datetime import datetime


if len(sys.argv) != 3:
    sys.exit("Wrong number of arguments")

mydb = mysql.connector.connect(
    host="spiff.local",
    user="creek",
    password="donthackme",
    database="creekdata",
    auth_plugin='mysql_native_password')

now = datetime.now()
formatted_date = now.strftime('%Y-%m-%d %H:%M:%S')
sql = "insert into creekdata.creekdata (depth,temperature,created_at) values (%s,%s,%s)"
vals = (sys.argv[1],sys.argv[2],formatted_date)


mycursor = mydb.cursor()

mycursor.execute(sql, vals)

mydb.commit()</pre>
<h1>Shell Script &amp; Crontab</h1>
<p>I created a simple bash shell script to</p>
<ol>
<li>Activate the virtual enviroment</li>
<li>Run the get data python program</li>
<li>Run the insert program</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">#!/bin/bash

cd ~/influxdb
source venv/bin/activate
vals=$(python getData.py)
#echo $vals
python insertMysql.py $vals</pre>
<p>Finally, a cronjob to run the program every 5 minutes.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Edit this file to introduce tasks to be run by cron.
# 
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
# 
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').
# 
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
# 
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
# 
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
# 
# For more information see the manual pages of crontab(5) and cron(8)
# 
# m h  dom mon dow   command
0,5,10,20,25,30,35,40,45,50,55 * * * * /home/pi/influxdb/getInsertData.sh</pre>
<h1>Test with MySQL WorkBench</h1>
<p>Now when I load the data from the MySQL Workbench I can see the inserts are happening.  Kick ass.</p>
<p><a href="https://iotexpert.com/?attachment_id=11191" rel="attachment wp-att-11191"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-2.24.20-PM-1005x1024.jpg" alt="" width="1005" height="1024" class="alignnone size-large wp-image-11191" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-2.24.20-PM-1005x1024.jpg 1005w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-2.24.20-PM-294x300.jpg 294w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-2.24.20-PM-768x783.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-2.24.20-PM-1507x1536.jpg 1507w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-2.24.20-PM-600x611.jpg 600w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-2.24.20-PM.jpg 1682w" sizes="auto, (max-width: 1005px) 100vw, 1005px" /></a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2-5/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>The Creek 3.0: A Docker MySQL Diversion &#8211; Part 2</title>
		<link>https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/</link>
					<comments>https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Tue, 18 May 2021 11:35:02 +0000</pubDate>
				<category><![CDATA[Elkhorn Creek 3.0]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=11140</guid>

					<description><![CDATA[Summary A tutorial on running MySQL in an instance of Docker on Ubuntu Linux.  Then creating a Raspberry Pi Python interface from a sensor to insert data over the network to the new MySQL Server. Story As I said in the introduction, this whole process has been a bit chaotic.  So here we go.  The [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>A tutorial on running MySQL in an instance of Docker on Ubuntu Linux.  Then creating a Raspberry Pi Python interface from a sensor to insert data over the network to the new MySQL Server.</p>
<h1>Story</h1>
<p>As I said in the <a href="https://iotexpert.com/the-creek-3-0-docker-telegraf-influx-grafana-part-1/">introduction</a>, this whole process has been a bit chaotic.  So here we go.  The Raspberry Pi that runs the current creek system has been in my barn since at least 2013 running on the same SD Card and never backed up.  I suppose that it wouldn&#8217;t have really mattered if I lost the old flood data, but it would have been annoying.  Also, that Raspberry Pi is very slow running queries given the 2.2M records that now exist in the database.</p>
<p>To fix this I decided that I want to start by moving the MySQL server to a new computer that runs Docker.  Here is the original configuration (<a href="https://iotexpert.com/the-elkhorn-creek/">from the original article</a>)</p>
<p><a href="https://iotexpert.com/the-creek-server-software-architecture/backendserver-3/" rel="attachment wp-att-516"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2016/03/backendserver-3-1024x707.png" alt="" width="1024" height="707" class="alignnone size-large wp-image-516" srcset="https://iotexpert.com/wp-content/uploads/2016/03/backendserver-3-1024x707.png 1024w, https://iotexpert.com/wp-content/uploads/2016/03/backendserver-3-600x414.png 600w, https://iotexpert.com/wp-content/uploads/2016/03/backendserver-3-300x207.png 300w, https://iotexpert.com/wp-content/uploads/2016/03/backendserver-3.png 1449w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>When I set out to do in this article the plan was to move the MySQL Instance from the Raspberry Pi to a new Linux box.  Unfortunately while I was doing this, I broke the operating system on the Raspberry Pi and ended up having to rebuild the interface to the PSoC 4.  Here is what I ended up building:</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/rpidocker/" rel="attachment wp-att-11176"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/rpidocker-1024x439.png" alt="" width="1024" height="439" class="alignnone size-large wp-image-11176" srcset="https://iotexpert.com/wp-content/uploads/2021/05/rpidocker-1024x439.png 1024w, https://iotexpert.com/wp-content/uploads/2021/05/rpidocker-300x129.png 300w, https://iotexpert.com/wp-content/uploads/2021/05/rpidocker-768x330.png 768w, https://iotexpert.com/wp-content/uploads/2021/05/rpidocker-600x257.png 600w, https://iotexpert.com/wp-content/uploads/2021/05/rpidocker.png 1508w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>This article will walk you through the following steps.</p>
<ol>
<li>Build a new Linux machine &amp; Install Ubuntu Server</li>
<li>Install Docker &amp; MySQL</li>
<li>Migrate the Data from the original Raspberry Pi MySQL Database</li>
<li>Build the Python Environment (Part 2.5)</li>
<li>Python: Get Data SMBUS (Part 2.5)</li>
<li>Python: Insert MySQL (Part 2.5)</li>
<li>Shell Script &amp; Crontab (Part 2.5)</li>
<li>Test using MySQL WorkBench (Part 2.5)</li>
</ol>
<h1>Build a new Linux Box with Ubuntu Server</h1>
<p>I wanted to have a local to my lan server running MySQL.  My lab assistant suggested that I find something fairly inexpensive on ebay.  Here is what I bought:</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-7-13-51-am/" rel="attachment wp-att-11146"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-7.13.51-AM-1024x543.jpg" alt="" width="1024" height="543" class="alignnone size-large wp-image-11146" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-7.13.51-AM-1024x543.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-7.13.51-AM-300x159.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-7.13.51-AM-768x407.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-7.13.51-AM-1536x814.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-7.13.51-AM-2048x1086.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-7.13.51-AM-600x318.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>&nbsp;</p>
<p>And&#8230; for sure it needed an SSD.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-2-29-37-pm/" rel="attachment wp-att-11151"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-2.29.37-PM-1024x526.jpg" alt="" width="1024" height="526" class="alignnone size-large wp-image-11151" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-2.29.37-PM-1024x526.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-2.29.37-PM-300x154.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-2.29.37-PM-768x395.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-2.29.37-PM-1536x789.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-2.29.37-PM-2048x1052.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-2.29.37-PM-600x308.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Then I downloaded Ubuntu Server 20.04 from https://ubuntu.com/download/server</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-7-15-32-am/" rel="attachment wp-att-11147"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-7.15.32-AM-1024x489.jpg" alt="" width="1024" height="489" class="alignnone size-large wp-image-11147" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-7.15.32-AM-1024x489.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-7.15.32-AM-300x143.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-7.15.32-AM-768x367.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-7.15.32-AM-1536x733.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-7.15.32-AM-2048x977.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-7.15.32-AM-600x286.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>After the file was downloaded I created a bootable sdcard by running: dd if=ubuntu-20.04.2-live-server-amd64.iso of=/dev/rdisk4 bs=1m</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">arh Downloads $ sudo diskutil unmountDisk /dev/disk4
Unmount of all volumes on disk4 was successful
arh Downloads $ sudo dd if=ubuntu-20.04.2-live-server-amd64.iso of=/dev/rdisk4 bs=1m
1158+1 records in
1158+1 records out
1215168512 bytes transferred in 32.400378 secs (37504763 bytes/sec)
arh Downloads $ diskutil list /dev/disk4
/dev/disk4 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     Apple_partition_scheme                        *31.1 GB    disk4
   1:        Apple_partition_map ⁨⁩                        4.1 KB     disk4s1
   2:                  Apple_HFS ⁨⁩                        4.1 MB     disk4s2
</pre>
<p>After doing the installation (I dont have screen captures of that, but it is easy).  I installed the avahi daemon.  What is that?  Avahi is program that enables mDNS &#8211; a part of no configuration networking that helps you manage &#8220;names&#8221;.  Specifically in my case it will create a DNS-like name for this computer without having to actually configure the DNS.  That name is &#8220;linux.local&#8221;.</p>
<p>To install avahi run sudo apt install avahi-daemon</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">arh@spiff:~$ systemctl status avahi-daemon
● avahi-daemon.service - Avahi mDNS/DNS-SD Stack
     Loaded: loaded (/lib/systemd/system/avahi-daemon.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2021-05-01 14:20:40 UTC; 2 weeks 1 days ago
TriggeredBy: ● avahi-daemon.socket
   Main PID: 713 (avahi-daemon)
     Status: "avahi-daemon 0.7 starting up."
      Tasks: 2 (limit: 14105)
     Memory: 2.8M
     CGroup: /system.slice/avahi-daemon.service
             ├─713 avahi-daemon: running [spiff.local]
             └─757 avahi-daemon: chroot helper

May 11 11:26:26 spiff avahi-daemon[713]: Registering new address record for fe80::4409:73ff:fe08:4c75 on veth72ac3b7.*.
May 11 11:26:26 spiff avahi-daemon[713]: Joining mDNS multicast group on interface br-18a7431f8090.IPv6 with address fe80::42:beff:fe8c:e24.
May 11 11:26:26 spiff avahi-daemon[713]: New relevant interface br-18a7431f8090.IPv6 for mDNS.
May 11 11:26:26 spiff avahi-daemon[713]: Registering new address record for fe80::42:beff:fe8c:e24 on br-18a7431f8090.*.
May 11 11:26:43 spiff avahi-daemon[713]: Interface veth72ac3b7.IPv6 no longer relevant for mDNS.
May 11 11:26:43 spiff avahi-daemon[713]: Leaving mDNS multicast group on interface veth72ac3b7.IPv6 with address fe80::4409:73ff:fe08:4c75.
May 11 11:26:43 spiff avahi-daemon[713]: Withdrawing address record for fe80::4409:73ff:fe08:4c75 on veth72ac3b7.
May 11 11:26:48 spiff avahi-daemon[713]: Joining mDNS multicast group on interface veth5c71e0d.IPv6 with address fe80::4499:b0ff:feef:30fe.
May 11 11:26:48 spiff avahi-daemon[713]: New relevant interface veth5c71e0d.IPv6 for mDNS.
May 11 11:26:48 spiff avahi-daemon[713]: Registering new address record for fe80::4499:b0ff:feef:30fe on veth5c71e0d.*.
arh@spiff:~$ 
</pre>
<p>I also will be running MySQL in a Docker instance.  To install docker run: sudo apt install docker.io</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">arh@spiff:~$ systemctl status docker
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2021-05-01 14:20:42 UTC; 2 weeks 1 days ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 758 (dockerd)
      Tasks: 26
     Memory: 142.1M
     CGroup: /system.slice/docker.service
             ├─   758 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
             └─240639 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 3306 -container-ip 172.18.0.2 -container-port 3306

May 02 13:39:42 spiff dockerd[758]: time="2021-05-02T13:39:42.754047181Z" level=info msg="ignoring event" container=4d2e6a3c8c779e01676e4fd8f748aa4581c9469d92398ff274a3800c5d3e98a2 module&gt;
May 02 13:40:42 spiff dockerd[758]: time="2021-05-02T13:40:42.381681852Z" level=error msg="Error setting up exec command in container 4d2e6a3c8c77: Container 4d2e6a3c8c779e01676e4fd8f748a&gt;
May 02 13:40:42 spiff dockerd[758]: time="2021-05-02T13:40:42.760184585Z" level=warning msg="error locating sandbox id 5e4b44ba78eacdb974bfd773ffabf46526177f4ff135ace09b667c3e497b3468: sa&gt;
May 02 13:40:42 spiff dockerd[758]: time="2021-05-02T13:40:42.762228692Z" level=error msg="4d2e6a3c8c779e01676e4fd8f748aa4581c9469d92398ff274a3800c5d3e98a2 cleanup: failed to delete conta&gt;
May 02 13:40:42 spiff dockerd[758]: time="2021-05-02T13:40:42.764274310Z" level=error msg="restartmanger wait error: network c6593d532df7651e3a38572e609d42f69f0daba3ac36263933ca0ae43504cc&gt;
May 11 11:26:24 spiff dockerd[758]: time="2021-05-11T11:26:24.772660650Z" level=info msg="No non-localhost DNS nameservers are left in resolv.conf. Using default external servers: [namese&gt;
May 11 11:26:24 spiff dockerd[758]: time="2021-05-11T11:26:24.772680359Z" level=info msg="IPv6 enabled; Adding default IPv6 external servers: [nameserver 2001:4860:4860::8888 nameserver 2&gt;
May 11 11:26:42 spiff dockerd[758]: time="2021-05-11T11:26:42.994091472Z" level=info msg="ignoring event" container=bfd550cab791b061bbd4e26f3435165de7b3664373de9cbb80d2e78a0aff08e2 module&gt;
May 11 11:26:46 spiff dockerd[758]: time="2021-05-11T11:26:46.212688536Z" level=info msg="No non-localhost DNS nameservers are left in resolv.conf. Using default external servers: [namese&gt;
May 11 11:26:46 spiff dockerd[758]: time="2021-05-11T11:26:46.212708396Z" level=info msg="IPv6 enabled; Adding default IPv6 external servers: [nameserver 2001:4860:4860::8888 nameserver 2&gt;
arh@spiff:~$</pre>
<h1>Docker Training</h1>
<p>I knew that I wanted to try Docker, no kidding eh, but I didn&#8217;t know much of anything about it.  I am not really a &#8220;video&#8221; person for learning, but my son had talked me into trying a skill share class to learn how to edit video.  So, I thought that I would give it a try for Docker as well.  This class was OK but not great (like 2/5)  Here is a screenshot from the class:</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-3-41-49-pm/" rel="attachment wp-att-11154"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-3.41.49-PM-1024x786.jpg" alt="" width="1024" height="786" class="alignnone size-large wp-image-11154" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-3.41.49-PM-1024x786.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-3.41.49-PM-300x230.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-3.41.49-PM-768x590.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-3.41.49-PM-1536x1179.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-3.41.49-PM-2048x1572.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-3.41.49-PM-600x461.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>I also watched this class, which is excellent&#8230;. especially if you watch it at 1.5x speed.</p>
<div class="jupiterx-oembed"><iframe loading="lazy" title="Docker Tutorial for Beginners [FULL COURSE in 3 Hours]" width="500" height="281" src="https://www.youtube.com/embed/3c-iBn73dDE?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></div>
<h1>Docker Introduction</h1>
<p>There are four basic ideas which you need to understand Docker.</p>
<div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Concept</th>
<th >Description</th>
<th >Commands</th>
</tr>
</thead>
<tbody>
<tr><td >Image</td>
<td >A runnable binary template that can be instantiated into a container (like a class in object oriented programming)</td>
<td >docker image ls</td>
</tr>

<tr><td >Container</td>
<td >An VM-like instance of an image (like an object i.e. an instance of a class in object oriented programming).  This includes network port mapping, volumes,network etc.</td>
<td >docker ps -a</td>
</tr>

<tr><td >Volume</td>
<td >A directory or file map between the host operating system and the docker container.  For example a directory X on the host is mapped to the directory Y inside of the container</td>
<td >docker volume ls</td>
</tr>

<tr><td >Network</td>
<td >A synthetic network that is created by the docker daemon to map one or more containers together.  This includes a dhcp, dns, routing etc.</td>
<td >docker network ls</td>
</tr>
</tbody></table></div>
<h1>Docker Compose &amp; MySQL</h1>
<p>You can find new images at https://hub.docker.com.  In fact this is where I get everything that I need for mysql.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-18-at-6-57-59-am/" rel="attachment wp-att-11178"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-6.57.59-AM-1024x964.jpg" alt="" width="1024" height="964" class="alignnone size-large wp-image-11178" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-6.57.59-AM-1024x964.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-6.57.59-AM-300x282.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-6.57.59-AM-768x723.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-6.57.59-AM-1536x1445.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-6.57.59-AM-2048x1927.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-6.57.59-AM-600x565.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>If you look a little bit later down on the docker hub you will find the specific instruction for &#8220;running&#8221; a docker mysql image.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-18-at-7-00-52-am/" rel="attachment wp-att-11180"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-7.00.52-AM-1024x245.png" alt="" width="1024" height="245" class="alignnone size-large wp-image-11180" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-7.00.52-AM-1024x245.png 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-7.00.52-AM-300x72.png 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-7.00.52-AM-768x184.png 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-7.00.52-AM-1536x368.png 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-7.00.52-AM-2048x490.png 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-7.00.52-AM-600x144.png 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>These instructions will work.  However, there are two problems.</p>
<p>#1 by running it this way you will not expose the ip port 3306 from inside of the container to the outside work (on your computer or network).  This means you won&#8217;t be able to talk to the MySQL instance.  That is not very helpful</p>
<p>#2 all of the secret sauce you typed will be lost if you need to do that same command again.</p>
<p>The good news is that docker has a specific file format for saving this information called &#8220;docker-compose.yaml&#8221;.</p>
<p>My docker compose file looks like this.</p>
<ol>
<li>The image is &#8220;mysql&#8221; (use the official docker mysql image)</li>
<li>Map the MySQL port 3306 from inside the container to the outside</li>
<li>Make the root password &#8220;supersecret&#8221;</li>
<li>Create a database called &#8220;creekdata&#8221;</li>
<li>Create a user called &#8220;creek&#8221; with a password &#8220;asillypassword&#8221;</li>
<li>Map the mysql data inside of the container at /var/lib/mysql to an outside volume called &#8220;mysql&#8221;</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">arh@spiff:~/mysql$ more docker-compose.yaml
version: '3.1'

services:

  db:
    image: mysql
    restart: always
    ports:
      - 3306:3306
    environment:
      MYSQL_ROOT_PASSWORD: supersecret
      MYSQL_DATABASE: creekdata
      MYSQL_USER: creek
      MYSQL_PASSWORD: asillypassword
    volumes:
      - mysql:/var/lib/mysql
      
volumes:
  mysql:</pre>
<p>With this file I can create the container by running &#8220;docker-compose up&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">linux$ docker-compose up
Creating network "mysql_default" with the default driver
Creating volume "mysql_mysql" with default driver
Pulling db (mysql:latest)...
latest: Pulling from library/mysql
69692152171a: Pull complete
1651b0be3df3: Pull complete
951da7386bc8: Pull complete
0f86c95aa242: Pull complete
37ba2d8bd4fe: Pull complete
6d278bb05e94: Pull complete
497efbd93a3e: Pull complete
f7fddf10c2c2: Pull complete
16415d159dfb: Pull complete
0e530ffc6b73: Pull complete
b0a4a1a77178: Pull complete
cd90f92aa9ef: Pull complete
Digest: sha256:d50098d7fcb25b1fcb24e2d3247cae3fc55815d64fec640dc395840f8fa80969
Status: Downloaded newer image for mysql:latest
Creating mysql_db_1 ... 
Creating mysql_db_1 ... done
Attaching to mysql_db_1
db_1  | 2021-05-17 20:01:20+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.25-1debian10 started.
db_1  | 2021-05-17 20:01:20+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
db_1  | 2021-05-17 20:01:20+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.25-1debian10 started.
db_1  | 2021-05-17 20:01:20+00:00 [Note] [Entrypoint]: Initializing database files
db_1  | 2021-05-17T20:01:20.192621Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.25) initializing of server in progress as process 41
db_1  | 2021-05-17T20:01:20.196027Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
db_1  | 2021-05-17T20:01:20.770999Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
db_1  | 2021-05-17T20:01:21.809117Z 6 [Warning] [MY-010453] [Server] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.
db_1  | 2021-05-17 20:01:24+00:00 [Note] [Entrypoint]: Database files initialized
db_1  | 2021-05-17 20:01:24+00:00 [Note] [Entrypoint]: Starting temporary server
db_1  | 2021-05-17T20:01:24.396505Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.25) starting as process 86
db_1  | 2021-05-17T20:01:24.415784Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
db_1  | 2021-05-17T20:01:24.551463Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
db_1  | 2021-05-17T20:01:24.618191Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: /var/run/mysqld/mysqlx.sock
db_1  | 2021-05-17T20:01:24.726805Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
db_1  | 2021-05-17T20:01:24.726923Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
db_1  | 2021-05-17T20:01:24.728714Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
db_1  | 2021-05-17T20:01:24.738807Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.25'  socket: '/var/run/mysqld/mysqld.sock'  port: 0  MySQL Community Server - GPL.
db_1  | 2021-05-17 20:01:24+00:00 [Note] [Entrypoint]: Temporary server started.
db_1  | Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
db_1  | Warning: Unable to load '/usr/share/zoneinfo/leap-seconds.list' as time zone. Skipping it.
db_1  | Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
db_1  | Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
db_1  | 2021-05-17 20:01:25+00:00 [Note] [Entrypoint]: Creating database creekdata
db_1  | 2021-05-17 20:01:25+00:00 [Note] [Entrypoint]: Creating user creek
db_1  | 2021-05-17 20:01:25+00:00 [Note] [Entrypoint]: Giving user creek access to schema creekdata
db_1  | 
db_1  | 2021-05-17 20:01:25+00:00 [Note] [Entrypoint]: Stopping temporary server
db_1  | 2021-05-17T20:01:25.775184Z 13 [System] [MY-013172] [Server] Received SHUTDOWN from user root. Shutting down mysqld (Version: 8.0.25).
db_1  | 2021-05-17T20:01:27.490685Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.25)  MySQL Community Server - GPL.
db_1  | 2021-05-17 20:01:27+00:00 [Note] [Entrypoint]: Temporary server stopped
db_1  | 
db_1  | 2021-05-17 20:01:27+00:00 [Note] [Entrypoint]: MySQL init process done. Ready for start up.
db_1  | 
db_1  | 2021-05-17T20:01:27.988961Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.25) starting as process 1
db_1  | 2021-05-17T20:01:27.999715Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
db_1  | 2021-05-17T20:01:28.135399Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
db_1  | 2021-05-17T20:01:28.202245Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
db_1  | 2021-05-17T20:01:28.287968Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
db_1  | 2021-05-17T20:01:28.288087Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
db_1  | 2021-05-17T20:01:28.290206Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
db_1  | 2021-05-17T20:01:28.300867Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.25'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server - GPL.</pre>
<h1>Migrate the Data using MySQLWorkbench</h1>
<p>I have a BUNCH of data (2.2M rows or so) on the original Raspberry Pi.  I want this data in my newly created instance of MySQL.  To get it there I will use the MySQL Workbench migration wizard to move the data from the old to the new instance.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-18-at-7-16-55-am/" rel="attachment wp-att-11181"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-7.16.55-AM-1024x382.jpg" alt="" width="1024" height="382" class="alignnone size-large wp-image-11181" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-7.16.55-AM-1024x382.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-7.16.55-AM-300x112.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-7.16.55-AM-768x286.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-7.16.55-AM-1536x573.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-7.16.55-AM-600x224.jpg 600w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-18-at-7.16.55-AM.jpg 1572w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>It starts with these nice instructions.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-4-56-23-pm/" rel="attachment wp-att-11158"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.56.23-PM-1024x716.jpg" alt="" width="1024" height="716" class="alignnone size-large wp-image-11158" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.56.23-PM-1024x716.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.56.23-PM-300x210.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.56.23-PM-768x537.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.56.23-PM-1536x1073.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.56.23-PM-2048x1431.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.56.23-PM-600x419.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Then I specify the source (the original Raspberry Pi)</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-4-56-51-pm/" rel="attachment wp-att-11159"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.56.51-PM-1024x715.jpg" alt="" width="1024" height="715" class="alignnone size-large wp-image-11159" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.56.51-PM-1024x715.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.56.51-PM-300x209.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.56.51-PM-768x536.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.56.51-PM-1536x1072.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.56.51-PM-2048x1430.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.56.51-PM-600x419.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The target is specified next.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-4-57-11-pm/" rel="attachment wp-att-11160"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.11-PM-1024x718.jpg" alt="" width="1024" height="718" class="alignnone size-large wp-image-11160" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.11-PM-1024x718.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.11-PM-300x210.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.11-PM-768x538.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.11-PM-1536x1076.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.11-PM-2048x1435.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.11-PM-600x420.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>It then reads the database schema from the source and makes sure that it can talk to the target.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-4-57-34-pm/" rel="attachment wp-att-11161"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.34-PM-1024x722.jpg" alt="" width="1024" height="722" class="alignnone size-large wp-image-11161" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.34-PM-1024x722.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.34-PM-300x211.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.34-PM-768x541.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.34-PM-1536x1082.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.34-PM-600x423.jpg 600w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.34-PM.jpg 2032w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Then it asks me what I want to transfer.  There is only one database schema on the source, the &#8220;creekdata&#8221; database.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-4-57-44-pm/" rel="attachment wp-att-11162"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.44-PM-1024x715.jpg" alt="" width="1024" height="715" class="alignnone size-large wp-image-11162" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.44-PM-1024x715.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.44-PM-300x209.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.44-PM-768x536.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.44-PM-1536x1072.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.44-PM-2048x1429.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.44-PM-600x419.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Next it reads the source schema and reverse engineers the tables etc.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-4-57-55-pm/" rel="attachment wp-att-11163"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.55-PM-1024x722.jpg" alt="" width="1024" height="722" class="alignnone size-large wp-image-11163" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.55-PM-1024x722.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.55-PM-300x211.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.55-PM-768x541.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.55-PM-1536x1083.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.55-PM-600x423.jpg 600w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.57.55-PM.jpg 2046w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now it asks specifically what you want to transfer.  For my case there are two tables in the creekdata database.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-4-58-09-pm/" rel="attachment wp-att-11164"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.09-PM-1024x715.jpg" alt="" width="1024" height="715" class="alignnone size-large wp-image-11164" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.09-PM-1024x715.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.09-PM-300x209.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.09-PM-768x536.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.09-PM-1536x1072.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.09-PM-2048x1430.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.09-PM-600x419.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Then it generates the specific mysql commands required to recreate the schema</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-4-58-19-pm/" rel="attachment wp-att-11165"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.19-PM-1024x716.jpg" alt="" width="1024" height="716" class="alignnone size-large wp-image-11165" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.19-PM-1024x716.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.19-PM-300x210.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.19-PM-768x537.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.19-PM-1536x1074.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.19-PM-2048x1432.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.19-PM-600x419.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Gives the option of changing it.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-4-58-32-pm/" rel="attachment wp-att-11166"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.32-PM-1024x724.jpg" alt="" width="1024" height="724" class="alignnone size-large wp-image-11166" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.32-PM-1024x724.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.32-PM-300x212.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.32-PM-768x543.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.32-PM-1536x1086.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.32-PM-600x424.jpg 600w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.32-PM.jpg 2036w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now it asks you what method you want to use on the target.  I choose to have it do all of the work.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-4-58-44-pm/" rel="attachment wp-att-11167"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.44-PM-1024x718.jpg" alt="" width="1024" height="718" class="alignnone size-large wp-image-11167" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.44-PM-1024x718.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.44-PM-300x210.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.44-PM-768x539.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.44-PM-1536x1077.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.44-PM-600x421.jpg 600w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.44-PM.jpg 2042w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Then it creates the new database and tables.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-4-58-59-pm/" rel="attachment wp-att-11168"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.59-PM-1024x716.jpg" alt="" width="1024" height="716" class="alignnone size-large wp-image-11168" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.59-PM-1024x716.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.59-PM-300x210.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.59-PM-768x537.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.59-PM-1536x1074.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.59-PM-600x420.jpg 600w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.58.59-PM.jpg 2042w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>And you can see that it worked.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-4-59-08-pm/" rel="attachment wp-att-11169"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.59.08-PM-1024x720.jpg" alt="" width="1024" height="720" class="alignnone size-large wp-image-11169" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.59.08-PM-1024x720.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.59.08-PM-300x211.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.59.08-PM-768x540.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.59.08-PM-1536x1080.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.59.08-PM-2048x1440.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.59.08-PM-600x422.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Then it asks how I want to copy the data.  I tell it to do all of the work for me.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-4-59-17-pm/" rel="attachment wp-att-11170"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.59.17-PM-1024x715.jpg" alt="" width="1024" height="715" class="alignnone size-large wp-image-11170" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.59.17-PM-1024x715.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.59.17-PM-300x210.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.59.17-PM-768x536.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.59.17-PM-1536x1073.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.59.17-PM-2048x1430.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-4.59.17-PM-600x419.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Then it runs a bulk transfer of the data.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-5-04-36-pm/" rel="attachment wp-att-11171"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.04.36-PM-1024x718.jpg" alt="" width="1024" height="718" class="alignnone size-large wp-image-11171" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.04.36-PM-1024x718.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.04.36-PM-300x210.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.04.36-PM-768x538.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.04.36-PM-1536x1077.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.04.36-PM-600x421.jpg 600w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.04.36-PM.jpg 2040w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>And give me a final report that things worked.  Kick ass.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-5-04-46-pm/" rel="attachment wp-att-11172"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.04.46-PM-1024x711.jpg" alt="" width="1024" height="711" class="alignnone size-large wp-image-11172" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.04.46-PM-1024x711.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.04.46-PM-300x208.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.04.46-PM-768x533.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.04.46-PM-1536x1067.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.04.46-PM-2048x1422.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.04.46-PM-600x417.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>I can now make a connection to the new database.   And I see my old data back to 2013.</p>
<p><a href="https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/screen-shot-2021-05-17-at-5-05-30-pm/" rel="attachment wp-att-11173"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.05.30-PM-1024x700.jpg" alt="" width="1024" height="700" class="alignnone size-large wp-image-11173" srcset="https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.05.30-PM-1024x700.jpg 1024w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.05.30-PM-300x205.jpg 300w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.05.30-PM-768x525.jpg 768w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.05.30-PM-1536x1050.jpg 1536w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.05.30-PM-2048x1399.jpg 2048w, https://iotexpert.com/wp-content/uploads/2021/05/Screen-Shot-2021-05-17-at-5.05.30-PM-600x410.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>That is it for this article.  In the next article Ill do the Python Shell Script stuff to reconnect my data to the new MySql Server.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/the-creek-3-0-a-docker-mysql-diversion-part-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>The Creek 3.0: Docker Telegraf, Influx, Grafana &#8211; Part 1</title>
		<link>https://iotexpert.com/the-creek-3-0-docker-telegraf-influx-grafana-part-1/</link>
					<comments>https://iotexpert.com/the-creek-3-0-docker-telegraf-influx-grafana-part-1/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Tue, 11 May 2021 15:30:55 +0000</pubDate>
				<category><![CDATA[Elkhorn Creek 3.0]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=11126</guid>

					<description><![CDATA[Summary The architecture and first steps of a new IoT implementation using PSoC 6, CYW43012 WiFi, AnyCloud MQTT, Raspberry Pi, Python, Influx, Grafana, Telegraf and Docker.  Wow, sounds like a lot. The Story For quite some time, I have been wanting to replace my original Elkhorn Creek implementation because. &#8230; well &#8230;, it is old [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>The architecture and first steps of a new IoT implementation using PSoC 6, CYW43012 WiFi, AnyCloud MQTT, Raspberry Pi, Python, Influx, Grafana, Telegraf and Docker.  Wow, sounds like a lot.</p>
<h1>The Story</h1>
<p>For quite some time, I have been wanting to replace my original <a href="https://iotexpert.com/the-elkhorn-creek/">Elkhorn Creek</a> implementation because. &#8230; well &#8230;, it is old school and a bit tired.  I started an implementation which I called &#8220;<a href="https://iotexpert.com/the-creek-amazon-aws-iot-solution-architecture-2-0/">The Creek 2.0</a>&#8221; which used AWS IoT,  AWS Lambda, and MySQL.  I thought it was interesting to learn about all of the AWS stuff&#8230; but I never finished the user interface, nor did I replace the Raspberry Pi.  Also, this solution was going in the old school direction and I wanted to use more open source.</p>
<p>So, this time I am going to go all the way.  Here is the architecture:</p>
<p><a href="https://iotexpert.com/the-creek-3-0-docker-telegraf-influx-grafana-part-1/arch-6/" rel="attachment wp-att-11194"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2021/05/arch-1-1024x307.png" alt="" width="1024" height="307" class="alignnone size-large wp-image-11194" srcset="https://iotexpert.com/wp-content/uploads/2021/05/arch-1-1024x307.png 1024w, https://iotexpert.com/wp-content/uploads/2021/05/arch-1-300x90.png 300w, https://iotexpert.com/wp-content/uploads/2021/05/arch-1-768x230.png 768w, https://iotexpert.com/wp-content/uploads/2021/05/arch-1-1536x460.png 1536w, https://iotexpert.com/wp-content/uploads/2021/05/arch-1-600x180.png 600w, https://iotexpert.com/wp-content/uploads/2021/05/arch-1.png 1652w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>There are a bunch of things that I have never used including:</p>
<ol>
<li>Docker</li>
<li>Mosquito MQTT</li>
<li>Telegraf</li>
<li>Influx DB</li>
<li>Grafana</li>
</ol>
<p>Which is quite a bit of new stuff.  Almost every time I work on a series like this I do all of the work in advance of writing the first article.  That way I know how things are going to an end and what is going to go wrong.   This way I can fix them in advance of you guys having to suffer with me.  This time, well, not so much, so I am quite sure that there will be some drama.</p>
<p>To this point I have spend a bunch of time with:</p>
<ol>
<li>Learning Docker</li>
<li>Trying out Influx DB and Grafana</li>
<li>Making Telegraf work</li>
</ol>
<p>There are still some things which are a bit unknown, including:</p>
<ol>
<li>I don&#8217;t like the Telegraf implementation of the mqtt_consumer, which is going to require me to spend time learning &#8220;Go&#8221;</li>
<li>I don&#8217;t really know how to expose Grafana to the internet safely (is that going to be OK?)</li>
<li>I am considering writing a &#8220;Influx Client Library&#8221; for PSoC to skip the MQTT?</li>
<li>I am considering using &#8220;Influx Line Protocol&#8221; and not using MQTT</li>
</ol>
<p>So over the next few weeks we will see how things evolves.  I also decided to purchase a new Linux box for my house to run the system so I will talk about what I did there.</p>
<p>Alan</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/the-creek-3-0-docker-telegraf-influx-grafana-part-1/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AnyCloud Bluetooth Advertising Scanner (Part 10)</title>
		<link>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/</link>
					<comments>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 28 Dec 2020 13:00:47 +0000</pubDate>
				<category><![CDATA[4343W]]></category>
		<category><![CDATA[AnyCloud]]></category>
		<category><![CDATA[AnyCloud Advertising Scanner]]></category>
		<category><![CDATA[Bluetooth]]></category>
		<category><![CDATA[CY8CKIT-062-WiFi-BT]]></category>
		<category><![CDATA[CY8CKIT-062S2-43012]]></category>
		<category><![CDATA[CY8CPROTO-062-4343W]]></category>
		<category><![CDATA[ModusToolbox]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=10250</guid>

					<description><![CDATA[Summary We have finally reached the end of the AnyCloud Bluetooth Advertising Scanner.  In this article I will add the ability to sort the database.  In addition I will add the ability to purge a device.  And finally, truly finally, a bit of commentary. Story I originally built this program to help me learn about [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>We have finally reached the end of the AnyCloud Bluetooth Advertising Scanner.  In this article I will add the ability to sort the database.  In addition I will add the ability to purge a device.  And finally, truly finally, a bit of commentary.</p>
<h1>Story</h1>
<p>I originally built this program to help me learn about the AnyCloud Bluetooth SDK.  Well, originally I built this functionality to try to find and talk to a specific device (in an upcoming series).  The problem is that there are so many devices at my house that are blasting out so much data it is hard to see what I am looking for.  What I realized would help is add the ability to sort the devices from newest to oldest.  In addition I noticed that occasionally my database would fill up&#8230; and it would be nice to purge out old entries.  So that is what we are going to do.</p>
<p>There are</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
<th >Topic</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 1)</a></td>
<td >Introduction to AnyCloud Bluetooth Advertising</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 2)</a></td>
<td >Creating an AnyCloud Bluetooth project</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 3)</a></td>
<td >Adding Observing functionality to the project</td>
</tr>

<tr><td ><a class="row-title" href="https://iotexpert.com/anycloud-bluetooth-utilities-library/" aria-label="“AnyCloud Bluetooth Utilities Library” (Edit)" target="_blank" rel="noopener">AnyCloud Bluetooth Utilities Library</a></td>
<td >A set of APIs for enhancement of the AnyCloud Library</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 4)</a></td>
<td >Adding a command line to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 5)</a></td>
<td >Adding a history database to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 6)</a></td>
<td >Decoding advertising packets</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 7)</a></td>
<td >Adding recording commands to the command line</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/">AnyCloud Bluetooth Advertising Scanner (Part 8)</a></td>
<td >Adding filtering to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/">AnyCloud Bluetooth Advertising Scanner (Part 9)</a></td>
<td >Improve the print and add packet age</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/">AnyCloud Bluetooth Advertising Scanner (Part 10)</a></td>
<td >Sort the database</td>
</tr>
</tbody></table></div></p>
<p>All of the code can be found at git@github.com:iotexpert/AnyCloudBLEScanner.git and https://github.com/iotexpert/AnyCloudBLEScanner.git</p>
<p>There are git tags in place starting at part 5 so that you can look at just that version of the code.  "git tag" to list the tags.  And "git checkout part6" to look at the part 6 version of the code.</p>
<p>You can also create a new project with this is a template if you have the IoT Expert Manifest Files installed</p>
<h1>Fix the Database Data Structure</h1>
<p>You might remember that the database was built as an array of structures.  This mean that any moving around of the data would be a require a replacement of the whole structure.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static adb_adv_t adb_database[ADB_MAX_SIZE];</pre>
<p>To fix this problem I moved the database to a an array of pointers.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static adb_adv_t *adb_database[ADB_MAX_SIZE];</pre>
<p>To support this, when I see a new device I malloc a block of memory to hold the actual structure.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    // If it is NOT found &amp;&amp; you have room
    if(entry == -1)
    {
        adb_database[adb_db_count] = malloc(sizeof(adb_adv_t));</pre>
<p>Then I had to fix all of the references to the structure.  And there were a bunch (actually 43 of them).  But the replacement was pretty simple</p>
<p>adb_database[&#8230;].xxx is replaced by adb_database[&#8230;]-&gt; &#8230;. here are the three different cases</p>
<p>case 1: adb_database[adb_db_count].</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/screen-shot-2020-11-16-at-7-40-36-am/" rel="attachment wp-att-10254"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-7.40.36-AM.png" alt="" class="alignnone size-full wp-image-10254" width="834" height="126" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-7.40.36-AM.png 834w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-7.40.36-AM-300x45.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-7.40.36-AM-768x116.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-7.40.36-AM-600x91.png 600w" sizes="auto, (max-width: 834px) 100vw, 834px" /></a></p>
<p>case 2: adb_database[entry].</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/screen-shot-2020-11-16-at-7-32-54-am/" rel="attachment wp-att-10251"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-7.32.54-AM.png" alt="" class="alignnone size-full wp-image-10251" width="842" height="132" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-7.32.54-AM.png 842w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-7.32.54-AM-300x47.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-7.32.54-AM-768x120.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-7.32.54-AM-600x94.png 600w" sizes="auto, (max-width: 842px) 100vw, 842px" /></a></p>
<p>case 1: adb_database[i].</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/screen-shot-2020-11-16-at-7-33-23-am/" rel="attachment wp-att-10252"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-7.33.23-AM.png" alt="" class="alignnone size-full wp-image-10252" width="838" height="132" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-7.33.23-AM.png 838w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-7.33.23-AM-300x47.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-7.33.23-AM-768x121.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-7.33.23-AM-600x95.png 600w" sizes="auto, (max-width: 838px) 100vw, 838px" /></a></p>
<p>That was actually way less painful that I thought it was going to be.  Probably what would actually be best is a library of these data structures with an API that would not have changed when the key changed, but that I suppose, is for another day.</p>
<h1>Add Two New Commands</h1>
<p>Now I add the sort and purge commands to my command list.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef enum {
    ADB_ADD,
    ADB_PRINT_RAW,
    ADB_PRINT_DECODE,
    ADB_WATCH,
    ADB_ERASE,
    ADB_RECORD,
    ADB_FILTER,
    ADB_SORT,
    ADB_PURGE,
} adb_cmd_t;
</pre>
<h1>Create the Sort Functionality</h1>
<p>To sort, I will use the c-standard library function qsort.  It requires a function that compares two entries a/b and returns</p>
<ol>
<li>a negative number of a&lt;b</li>
<li>0 if a=b</li>
<li>a positive number if a&gt;b</li>
</ol>
<p>Here is the function.  Hey Hassane you like those pointers?</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static int adb_sort_cmpfunc(const void * a, const void * b) 
{
    adb_adv_t *p1 = *((adb_adv_t **)a);
    adb_adv_t *p2 = *((adb_adv_t **)b);
        
    return p2-&gt;lastSeen - p1-&gt;lastSeen;
}</pre>
<p>The sort is actually really simple now.  Just a call to sort (then I decided to print out the table)</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">                case ADB_SORT:
                    qsort(adb_database, adb_db_count, sizeof(adb_adv_t *), adb_sort_cmpfunc);
                    adb_db_print(ADB_PRINT_METHOD_BYTES,true,-1);
                break;</pre>
<p>Now instead of this&#8230;.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/screen-shot-2020-11-16-at-4-35-26-pm/" rel="attachment wp-att-10256"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-4.35.26-PM-1024x678.png" alt="" class="alignnone size-large wp-image-10256" width="1024" height="678" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-4.35.26-PM-1024x678.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-4.35.26-PM-300x199.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-4.35.26-PM-768x508.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-4.35.26-PM-1536x1017.png 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-4.35.26-PM-600x397.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-4.35.26-PM.png 1970w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>I get this&#8230;</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/screen-shot-2020-11-16-at-4-35-37-pm/" rel="attachment wp-att-10257"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-4.35.37-PM-1024x660.png" alt="" class="alignnone size-large wp-image-10257" width="1024" height="660" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-4.35.37-PM-1024x660.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-4.35.37-PM-300x193.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-4.35.37-PM-768x495.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-4.35.37-PM-1536x990.png 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-4.35.37-PM-600x387.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-16-at-4.35.37-PM.png 2042w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Create the Purge Functionality</h1>
<p>The purge function needs to do two things</p>
<ol>
<li>Free all of the memory from an entry</li>
<li>Move the pointers so that the &#8220;purged&#8221; entry is gone.</li>
</ol>
<p>First I erase all of the data in the linked list with the adb_eraseEntry function.</p>
<p>Then I free the head of the list</p>
<p>Then I free the actual structure</p>
<p>Then I move all of the pointers to squeeze the able.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_purgeEntry(int entry)
{

    adb_eraseEntry(entry);
    free(adb_database[entry]-&gt;list);
    free(adb_database[entry]-&gt;result);
    free(adb_database[entry]);
    adb_db_count -= 1;
    for(int i=entry;i&lt;adb_db_count;i++)
    {
        adb_database[i] = adb_database[i+1];
    }
}
</pre>
<p>And you need to add the actual command.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">                case ADB_PURGE:
                    if((int)msg.data0&lt;0 || (int)msg.data0&gt;=adb_db_count)
                    {
                        printf("Purge error %d\n",(int)msg.data0);
                        break;
                    }   
                    adb_purgeEntry((int)msg.data0);
                break;</pre>
<h1>The End &amp; Commentary</h1>
<p>I would like to add and maybe will one day:</p>
<ol>
<li>A connect function with a GATT browser</li>
<li>A smarter way to deal with the fact that device change addresses</li>
</ol>
<p>Finally a couple of comments about this</p>
<ol>
<li>You might notice that I don&#8217;t check very many possible errors.  I do this in the interest of simpler to read code.  This is a tradeoff that I make for &#8220;teaching&#8221; code.  I hope that you understand that if you want to do something like this in a real product that you need to be much more careful.</li>
<li>I don&#8217;t have unit testing.  This falls into the same category as the error checking.  Really this is a bad idea as code without unit testing is obsolete the second it comes out of your fingers.  But, it is easier to read.</li>
<li>I don&#8217;t have many comments.  This is something that my colleagues bitch about all of the time with me.  And I know that it must be a personality defect.</li>
<li>I use malloc/free all over the place.  This is a religious war.  You can make a static allocation scheme, but it would be really complicated in this case.  I personally think that the tradeoff of using a battle worn and tested malloc/free is totally worthwhile against the complexity of custom static memory allocation schemes.</li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AnyCloud Bluetooth Advertising Scanner (Part 9)</title>
		<link>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/</link>
					<comments>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 21 Dec 2020 13:00:28 +0000</pubDate>
				<category><![CDATA[AnyCloud]]></category>
		<category><![CDATA[AnyCloud Advertising Scanner]]></category>
		<category><![CDATA[Bluetooth]]></category>
		<category><![CDATA[CY8CKIT-062-WiFi-BT]]></category>
		<category><![CDATA[CY8CKIT-062S2-43012]]></category>
		<category><![CDATA[CY8CPROTO-062-4343W]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=10239</guid>

					<description><![CDATA[Summary In this series of articles I am building a Bluetooth Low Energy Scanner using the Cypress/Infineon AnyCloud SDK running on a PSoC 6 and CYW43xxx.  In Part 9, I will fix a memory leak, add packet age, and improve the printing. Story You might be starting to wonder if this series is ever going [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In this series of articles I am building a Bluetooth Low Energy Scanner using the Cypress/Infineon AnyCloud SDK running on a PSoC 6 and CYW43xxx.  In Part 9, I will fix a memory leak, add packet age, and improve the printing.</p>
<h1>Story</h1>
<p>You might be starting to wonder if this series is ever going to end.  Well, this article and one more.  That is it.</p>
<p>This morning as I was looking at the serial console window I noticed that I had hit the limit of device in the buffer,  OK.  But that it had also crashed, gone, bye bye, so long &#8230; the long dark road.  That needs fixing.</p>
<p>I also was curious when I looked at the output, how long ago I had seen the packets/devices.  So I decided that having &#8220;age&#8221; in the database made sense.</p>
<p>There are</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
<th >Topic</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 1)</a></td>
<td >Introduction to AnyCloud Bluetooth Advertising</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 2)</a></td>
<td >Creating an AnyCloud Bluetooth project</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 3)</a></td>
<td >Adding Observing functionality to the project</td>
</tr>

<tr><td ><a class="row-title" href="https://iotexpert.com/anycloud-bluetooth-utilities-library/" aria-label="“AnyCloud Bluetooth Utilities Library” (Edit)" target="_blank" rel="noopener">AnyCloud Bluetooth Utilities Library</a></td>
<td >A set of APIs for enhancement of the AnyCloud Library</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 4)</a></td>
<td >Adding a command line to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 5)</a></td>
<td >Adding a history database to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 6)</a></td>
<td >Decoding advertising packets</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 7)</a></td>
<td >Adding recording commands to the command line</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/">AnyCloud Bluetooth Advertising Scanner (Part 8)</a></td>
<td >Adding filtering to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/">AnyCloud Bluetooth Advertising Scanner (Part 9)</a></td>
<td >Improve the print and add packet age</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/">AnyCloud Bluetooth Advertising Scanner (Part 10)</a></td>
<td >Sort the database</td>
</tr>
</tbody></table></div></p>
<p>All of the code can be found at git@github.com:iotexpert/AnyCloudBLEScanner.git and https://github.com/iotexpert/AnyCloudBLEScanner.git</p>
<p>There are git tags in place starting at part 5 so that you can look at just that version of the code.  "git tag" to list the tags.  And "git checkout part6" to look at the part 6 version of the code.</p>
<p>You can also create a new project with this is a template if you have the IoT Expert Manifest Files installed</p>
<h1>Fix the Memory Leak</h1>
<p>I noticed that a while after I started getting the message &#8220;ADV Table Max Size&#8221; that things would crash.  But Why?  The answer is a memory leak &#8211; go figure. I originally thought when I get a new device I would just overwrite the last entry in the table.  But, when I overwrote the adb_database[adb_db_count]. record with a new scan_result and a new list, I left memory that was previously allocated, here is the code:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    if(entry == -1)
    {
        adb_database[adb_db_count].result = scan_result;
        adb_database[adb_db_count].listCount = 1;
        adb_database[adb_db_count].record = false;
        adb_database[adb_db_count].filter = true;
        adb_database[adb_db_count].numSeen = 1;

        adb_adv_data_t *current = malloc(sizeof(adb_adv_data_t));
        current-&gt;next = 0;
        current-&gt;data = data;
        current-&gt;count = 1;

        adb_database[adb_db_count].list = current;

        adb_db_count = adb_db_count + 1;
        if(adb_db_count == ADB_MAX_SIZE)
        {
            printf("ADV Table Max Size\n");
            adb_db_count = adb_db_count - 1;
        }
        else
        {    
            adb_db_print(ADB_PRINT_METHOD_BYTES,false,adb_db_count-1);
        }
    }</pre>
<p>A cheap fix is to just stop making new entries when the database runs out of room.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    // If there is a new entry and you ran out of space
    if(entry == -1 &amp;&amp; adb_db_count &gt;= ADB_MAX_SIZE)
    {
        free(scan_result);
        free(data);
        return;
    }</pre>
<h1>Add Age</h1>
<p>As I mentioned earlier I wanted to keep track of</p>
<ol>
<li>The last time I had seen a device</li>
<li>When I saw that specific advertising packet</li>
</ol>
<p>The FreeRTOS has a free running millisecond counter that starts a 0 and counts up to 2^32.  A really cheap way to keep track of time is just to use this counter. To do this the first step is add the time to the database.  Both in the device record and the packet record.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef struct {
    uint8_t *data;
    int count;
    TickType_t lastSeen;
    struct adb_adv_data_t *next;
} adb_adv_data_t;

typedef struct {
    wiced_bt_ble_scan_results_t *result;
    bool record;
    bool filter;
    int numSeen;
    int listCount;
    TickType_t lastSeen;
    adb_adv_data_t *list;
} adb_adv_t ;</pre>
<h1>Update the Printing</h1>
<p>I am going to make the output look like this with a new column representing the seconds since I heard the packet.  In the picture below you can see that I heard 00 at 0.0 seconds ago&#8230;  Then you can see that I had a recording of device 5 where I have a bunch of packets that I heard back into time.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/screen-shot-2020-11-15-at-12-28-23-pm/" rel="attachment wp-att-10244"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-15-at-12.28.23-PM-1024x326.png" alt="" class="alignnone size-large wp-image-10244" width="1024" height="326" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-15-at-12.28.23-PM-1024x326.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-15-at-12.28.23-PM-300x95.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-15-at-12.28.23-PM-768x244.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-15-at-12.28.23-PM-1536x488.png 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-15-at-12.28.23-PM-600x191.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-15-at-12.28.23-PM.png 1988w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>To do this I just add a time calculation like this:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_printEntry(adb_print_method_t method, int entry, adb_adv_data_t *adv_data)
{
    float time = ((float)xTaskGetTickCount() - (float)(adv_data-&gt;lastSeen))/1000;

    printf("%c%c%02d %05d %03d %6.1f ",adb_database[entry].watch?'W':' ',
    adb_database[entry].filter?'F':' ',
    entry,adb_database[entry].numSeen,adb_database[entry].listCount,
    time);
</pre>
<h1>Fix up the Add</h1>
<p>The next thing that I need to do is make the &#8220;add&#8221; function add the time.  The problem is that this function has gotten totally totally out of control.  It turns out that there are x different possibilities</p>
<ol>
<li>Ignore the packet (because the table is full)</li>
<li>Add a new device &amp; packet</li>
<li>Update the head of the list with a new packet</li>
<li>Insert a new packet at the head of the list</li>
<li>If you are filtering update a duplicated packet count</li>
</ol>
<p>The code for these branches all looked somewhat similar.  But, which branch to take depended on</p>
<ol>
<li>If you were &#8220;watching&#8221; that device</li>
<li>If you were &#8220;filtering&#8221; that device</li>
<li>If you were &#8220;recording&#8221;</li>
<li>If you had seen that packet before (aka it was found)</li>
</ol>
<p>I ended up making a truth table:</p>
<table width="496" cellspacing="0" cellpadding="0" border="0">
<colgroup>
<col width="87" span="4" />
<col width="148" /></colgroup>
<tbody>
<tr height="21">
<td style="text-align: center;" width="87" height="21"><strong>Watch</strong></td>
<td style="text-align: center;" width="87"><strong>Filter</strong></td>
<td style="text-align: center;" width="87"><strong>Recording</strong></td>
<td style="text-align: center;" width="87"><strong>Found</strong></td>
<td style="text-align: center;" width="148"><strong>Action</strong></td>
</tr>
<tr height="21">
<td style="text-align: center;" height="21" align="right">0</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;">update the head</td>
</tr>
<tr height="21">
<td style="text-align: center;" height="21" align="right">0</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;">update the head</td>
</tr>
<tr height="21">
<td style="text-align: center;" height="21" align="right">0</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;">update the head</td>
</tr>
<tr height="21">
<td style="text-align: center;" height="21" align="right">0</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;">update the head</td>
</tr>
<tr height="21">
<td style="text-align: center;" height="21" align="right">0</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;">update the head</td>
</tr>
<tr height="21">
<td style="text-align: center;" height="21" align="right">0</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;">update the head</td>
</tr>
<tr height="21">
<td style="text-align: center;" height="21" align="right">0</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;">update the head</td>
</tr>
<tr height="21">
<td style="text-align: center;" height="21" align="right">0</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;">update the head</td>
</tr>
<tr height="21">
<td style="text-align: center;" height="21" align="right">1</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;">update the head</td>
</tr>
<tr height="21">
<td style="text-align: center;" height="21" align="right">1</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;">update the head</td>
</tr>
<tr height="21">
<td style="text-align: center;" height="21" align="right">1</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;">insert at the head</td>
</tr>
<tr height="21">
<td style="text-align: center;" height="21" align="right">1</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;">insert at the head</td>
</tr>
<tr height="21">
<td style="text-align: center;" height="21" align="right">1</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;">update the head</td>
</tr>
<tr height="21">
<td style="text-align: center;" height="21" align="right">1</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;">update the found</td>
</tr>
<tr height="21">
<td style="text-align: center;" height="21" align="right">1</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;" align="right">0</td>
<td style="text-align: center;">insert at the head</td>
</tr>
<tr height="21">
<td style="text-align: center;" height="21" align="right">1</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;" align="right">1</td>
<td style="text-align: center;">update the found</td>
</tr>
</tbody>
</table>
<p>The case where you</p>
<ol>
<li>Had no room</li>
<li>Saw a new device</li>
</ol>
<p>Look like this:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_add(wiced_bt_ble_scan_results_t *scan_result,uint8_t *data)
{

    TickType_t timeSeen = xTaskGetTickCount();

    int entry = adb_db_find(&amp;scan_result-&gt;remote_bd_addr);

    // If there is a new entry and you ran out of space
    if(entry == -1 &amp;&amp; adb_db_count &gt;= ADB_MAX_SIZE)
    {
        free(scan_result);
        free(data);
        return;
    }
    
    // If it is NOT found &amp;&amp; you have room
    if(entry == -1)
    {
        adb_database[adb_db_count] = malloc(sizeof(adb_adv_t));
        adb_database[adb_db_count]-&gt;result = scan_result;
        adb_database[adb_db_count]-&gt;listCount = 1;
        adb_database[adb_db_count]-&gt;watch = false;
        adb_database[adb_db_count]-&gt;filter = true;
        adb_database[adb_db_count]-&gt;numSeen = 1;
        adb_database[adb_db_count]-&gt;lastSeen = timeSeen;

        adb_adv_data_t *current = malloc(sizeof(adb_adv_data_t));
        current-&gt;next = 0;
        current-&gt;data = data;
        current-&gt;numSeen = 1;
        current-&gt;lastSeen = timeSeen;

        adb_database[adb_db_count]-&gt;list = current;

        adb_db_count = adb_db_count + 1;    
        adb_db_print(ADB_PRINT_METHOD_BYTES,false,adb_db_count-1);

        return; 
    }</pre>
<p>At this point in the code you know that you have seen this device before.  If you are filtering you should look in the linked list to see if you can find the specific packet (lines 1-15).</p>
<p>If you look at the truth table above you will see three cases where you should insert at the head of this list.  Those cases are identified with the sprawling if on lines 17-21).  Once you identify that scenario you do the needful.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    adb_adv_data_t *updateItem=0; 

    if(adb_database[entry].filter) // if filtering is on.
    {
        int len = btutil_adv_len(data); // ARH maybe a bug here
        
        for(adb_adv_data_t *list = adb_database[entry].list;list;list = (adb_adv_data_t *)list-&gt;next)
        {
            if(memcmp(list-&gt;data,data,len) == 0) // Found the data
            {
                updateItem = list;
                break;
            }
        }
    }

    // insert at the head
    if( (adb_database[entry].watch &amp;&amp; !adb_database[entry].filter &amp;&amp; adb_recording &amp;&amp; !updateItem) ||
        (adb_database[entry].watch &amp;&amp; !adb_database[entry].filter &amp;&amp; adb_recording &amp;&amp; updateItem) ||
        (adb_database[entry].watch &amp;&amp; adb_database[entry].filter &amp;&amp; adb_recording &amp;&amp; !updateItem)
    )
    {
        adb_adv_data_t *updateItem = malloc(sizeof(adb_adv_data_t)); // make new data
        updateItem-&gt;next = (struct adb_adv_data_t *)adb_database[entry].list;
        updateItem-&gt;numSeen = 1;
        updateItem-&gt;data = data;
        updateItem-&gt;lastSeen = timeSeen;

        adb_database[entry].list = updateItem;
        adb_database[entry].numSeen += 1;
        adb_database[entry].lastSeen = timeSeen;
        adb_database[entry].listCount += 1;
        free(scan_result);
        
        adb_db_print(ADB_PRINT_METHOD_BYTES,false,entry);


        adb_recording_count += 1;
        if(adb_recording_count == ADB_RECORD_MAX)
        {
            adb_recording = false;
            printf("Recording buffer full\n");
        }
        return;
    }
</pre>
<p>The final case happens when you are just going to update a found packet.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    if(updateItem == 0)
        updateItem = adb_database[entry].list;


    adb_database[entry].numSeen += 1;
    adb_database[entry].lastSeen = timeSeen;

    updateItem-&gt;lastSeen = timeSeen;

    int len = btutil_adv_len(data); // ARH maybe a bug here
    if(memcmp(updateItem-&gt;data,data,len) == 0)
    {
        updateItem-&gt;numSeen += 1;
    }
    else
    {
        updateItem-&gt;numSeen = 1;   
    }

    free(updateItem-&gt;data);
    updateItem-&gt;data = data;
    free(scan_result);

}
</pre>
<p>In the next article I will add</p>
<ol>
<li>Sort</li>
<li>Purge</li>
</ol>
<p>Then I will call it  a day.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AnyCloud Bluetooth Advertising Scanner (Part 8)</title>
		<link>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/</link>
					<comments>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 14 Dec 2020 13:00:23 +0000</pubDate>
				<category><![CDATA[4343W]]></category>
		<category><![CDATA[AnyCloud]]></category>
		<category><![CDATA[AnyCloud Advertising Scanner]]></category>
		<category><![CDATA[CY8CKIT-062-WiFi-BT]]></category>
		<category><![CDATA[CY8CKIT-062S2-43012]]></category>
		<category><![CDATA[CY8CPROTO-062-4343W]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=10220</guid>

					<description><![CDATA[Summary In this series of articles I am building a Bluetooth Low Energy Scanner using the Cypress/Infineon AnyCloud SDK running on a PSoC 6 and CYW43xxx.  In Part 8 I will turn on the ability to filter duplicate advertising packets. Story In the previous article I added the ability to record advertising packets.  The problem [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In this series of articles I am building a Bluetooth Low Energy Scanner using the Cypress/Infineon AnyCloud SDK running on a PSoC 6 and CYW43xxx.  In Part 8 I will turn on the ability to filter duplicate advertising packets.</p>
<h1>Story</h1>
<p>In the previous article I added the ability to record advertising packets.  The problem is, of course, that many devices are blasting out advertising packets, which will quickly overwhelm you.  I suppose more importantly it will overwhelm the packet buffer.  Most of the device are just advertising their presence, so they send the same data over and over.  Some devices alternate between a small number of different advertising packets, e.g. an iBeacon then and Eddystone beacon.</p>
<p>The way that the filter will work is that I will update the &#8220;add&#8221; function to search through all of the packets that device has launched, then if I have seen the packet before (Ill use a memcmp) then I will just keep a count of how many times I have see that packet.</p>
<p>The other thing that needs to happen is for me to add a &#8220;filter&#8221; command so that I can turn on packet filtering on a device by device basis.</p>
<p>And I need to fix the printing to use the new filtered packet database.</p>
<p>There are</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
<th >Topic</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 1)</a></td>
<td >Introduction to AnyCloud Bluetooth Advertising</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 2)</a></td>
<td >Creating an AnyCloud Bluetooth project</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 3)</a></td>
<td >Adding Observing functionality to the project</td>
</tr>

<tr><td ><a class="row-title" href="https://iotexpert.com/anycloud-bluetooth-utilities-library/" aria-label="“AnyCloud Bluetooth Utilities Library” (Edit)" target="_blank" rel="noopener">AnyCloud Bluetooth Utilities Library</a></td>
<td >A set of APIs for enhancement of the AnyCloud Library</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 4)</a></td>
<td >Adding a command line to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 5)</a></td>
<td >Adding a history database to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 6)</a></td>
<td >Decoding advertising packets</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 7)</a></td>
<td >Adding recording commands to the command line</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/">AnyCloud Bluetooth Advertising Scanner (Part 8)</a></td>
<td >Adding filtering to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/">AnyCloud Bluetooth Advertising Scanner (Part 9)</a></td>
<td >Improve the print and add packet age</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/">AnyCloud Bluetooth Advertising Scanner (Part 10)</a></td>
<td >Sort the database</td>
</tr>
</tbody></table></div></p>
<p>All of the code can be found at git@github.com:iotexpert/AnyCloudBLEScanner.git and https://github.com/iotexpert/AnyCloudBLEScanner.git</p>
<p>There are git tags in place starting at part 5 so that you can look at just that version of the code.  "git tag" to list the tags.  And "git checkout part6" to look at the part 6 version of the code.</p>
<p>You can also create a new project with this is a template if you have the IoT Expert Manifest Files installed</p>
<h1>Update the Data Structures</h1>
<p>In order to do the filters, and keep track of the data I will add</p>
<ol>
<li>A &#8220;count&#8221; field to the packet data structure</li>
<li>A &#8220;filter&#8221; boolean field to the device data structure.</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef struct {
    uint8_t *data;
    int count;
    struct adb_adv_data_t *next;
} adb_adv_data_t;

typedef struct {
    wiced_bt_ble_scan_results_t *result;
    bool record;
    bool filter;
    int numSeen;
    int listCount;
    adb_adv_data_t *list;
} adb_adv_t ;</pre>
<h1>Update the Add Function</h1>
<p>In the function &#8220;static void adb_db_add(wiced_bt_ble_scan_results_t *scan_result,uint8_t *data)&#8221; which is called every time I see a new advertising packet I will need to handle four different cases:</p>
<ol>
<li>The first time you see a device</li>
<li>A device you have seen AND you are recording AND have the filtering turned on</li>
<li>A device you are recording but not filtering</li>
<li>A device you have seen, but are not recording or filter.</li>
</ol>
<p>In the first case, a device you haven&#8217;t seen before, you need to</p>
<ol>
<li>Automatically turn on the filtering</li>
<li>Initialize the counts to 1</li>
<li>Do the other initialization (as before)</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    // If it is NOT found
    if(entry == -1)
    {
        adb_database[adb_db_count].result = scan_result;
        adb_database[adb_db_count].listCount = 1;
        adb_database[adb_db_count].record = false;
        adb_database[adb_db_count].filter = true;
        adb_database[adb_db_count].numSeen = 1;

        adb_adv_data_t *current = malloc(sizeof(adb_adv_data_t));
        current-&gt;next = 0;
        current-&gt;data = data;
        current-&gt;count = 1;</pre>
<p>In the case where you have</p>
<ol>
<li>See the device before</li>
<li>You have room in the record buffer</li>
<li>And you are in record mode</li>
</ol>
<p>You will then decide if you are filtering.</p>
<p>Then you will iterate through all of the packets and compare the data to the data you just received.  If there is a match then you update the count, free the duplicate data and return.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    else if(adb_database[entry].record &amp;&amp; adb_recording_count&lt;ADB_RECORD_MAX &amp;&amp; adb_recording)
    {
        adb_database[entry].numSeen += 1;

        if(adb_database[entry].filter) // if filtering is on.
        {
            int len = btutil_adv_len(data); 
            for(adb_adv_data_t *list = adb_database[entry].list;list;list = (adb_adv_data_t *)list-&gt;next)
            {
                if(memcmp(list-&gt;data,data,len) == 0) // Found the data
                {
                    list-&gt;count += 1;
                    printf("Count = %d\n",list-&gt;count);
                    free(data);
                    free(scan_result);
                    return;
                }
            }
        }
</pre>
<p>If you have not see the data before, then you need to add it to the linked list.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">        adb_adv_data_t *current = malloc(sizeof(adb_adv_data_t));
        current-&gt;next = (struct adb_adv_data_t *)adb_database[entry].list;
        current-&gt;data = data;
        current-&gt;count = 1;</pre>
<p>If you are not recording and not filtering, just increment counts.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    else
    {
        adb_database[entry].numSeen += 1;
        adb_database[entry].list-&gt;count += 1;</pre>
<h1>Add a &#8220;filter&#8221; Command</h1>
<p>I want the ability for a user to &#8220;filter all&#8221; or &#8220;filter clear&#8221; or &#8220;filter #&#8221; &#8211; just like we did with watch.  So, add the #defines and new function to advDatabase.h</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#define ADB_FILTER_ALL -1
#define ADB_FILTER_CLEAR -2
void adb_filter(int entry);
</pre>
<p>Then add the new filter command in advDatabase.c</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef enum {
    ADB_ADD,
    ADB_PRINT_RAW,
    ADB_PRINT_DECODE,
    ADB_WATCH,
    ADB_ERASE,
    ADB_RECORD,
    ADB_FILTER,
} adb_cmd_t;</pre>
<p>I will use the adb_queueCmd function that I created in the last article.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">inline void adb_filter(int entry) { adb_queueCmd(ADB_FILTER,(void*)entry,(void *)0); }
</pre>
<p>The filter command has three cases</p>
<ol>
<li>All &#8211; turn the bool for all on</li>
<li>Clear &#8211; turn the bool for all off</li>
<li>Just a specific number &#8211; toggle that specific number</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_filter(int entry)
{
    if(entry == ADB_FILTER_ALL)
    {
        for(int i=0;i&lt;adb_db_count;i++)
        {
            adb_database[i].filter = true;
        }
        return;
    }

    if(entry == ADB_FILTER_CLEAR)
    {
        for(int i=0;i&lt;adb_db_count;i++)
        {
            adb_database[i].filter = false;
        }
        return;
    }

    if(entry &gt; adb_db_count-1 || entry &lt; ADB_WATCH_CLEAR)
    {
        printf("Record doesnt exist: %d\n",entry);
        return;      
    }
    adb_database[entry].filter = !adb_database[entry].filter; 

}
</pre>
<p>And you need to fix up the main command processor</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">                case ADB_FILTER:
                    adb_db_filter((int)msg.data0);
                break;</pre>
<p>Finally add the command to the usrcmd.c</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static int usrcmd_filter(int argc, char **argv)
{

    if(argc == 2 &amp;&amp; !strcmp(argv[1],"all"))
    {
        adb_filter(ADB_FILTER_ALL); // all
        return 0;
    }


    if(argc == 2 &amp;&amp; !strcmp(argv[1],"clear"))
    {
        adb_filter(ADB_FILTER_CLEAR);
        return 0;
    }

    if(argc == 2)
    {
        int i;
        sscanf(argv[1],"%d",&amp;i);
        adb_filter(i);
        return 0;
    }

    return 0;
}</pre>
<h1>Fix the Printing</h1>
<p>Now we nee to fix the printing.  I want to add an indicate of the filtering to the output.  Remember from the previous article I indicated &#8220;Watch&#8221; with a &#8220;*&#8221;.  When I looked at it, I decided that I should indicate filter with an &#8220;F&#8221; and watch with a &#8220;W&#8221;.  So I fix that.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">        printf("%c%c%02d %05d %03d MAC: ",adb_database[i].record?'W':' ',
            adb_database[i].filter?'F':' ',
            i,adb_database[i].numSeen,adb_database[i].listCount);
        btutil_printBDaddress(adb_database[i].result-&gt;remote_bd_addr);
        switch(method)
        {</pre>
<p>Then I test the &#8220;filter&#8221; command</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/screen-shot-2020-11-14-at-9-49-32-am/" rel="attachment wp-att-10235"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-9.49.32-AM-1024x622.jpg" alt="" class="alignnone size-large wp-image-10235" width="1024" height="622" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-9.49.32-AM-1024x622.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-9.49.32-AM-300x182.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-9.49.32-AM-768x466.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-9.49.32-AM-1536x933.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-9.49.32-AM-600x364.jpg 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-9.49.32-AM.jpg 2042w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Fix the Printing Part (2)</h1>
<p>As I noodled on how to change the printing I decide that it would be nice to sometimes print out only one packet e.g. no history and sometimes print them all out e.g. history.  So, I add a new parameter to the function called &#8220;history&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_print(adb_print_method_t method,bool history,int entry)
</pre>
<p>As I looked at the printing code, I decided that it would be better to have a new function to print only one entry.  I suppose that I could have left the code inline, but I thought that intent was clearer.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_printEntry(adb_print_method_t method, int entry, adb_adv_data_t *adv_data)
{
    printf("%c%c%02d %05d %03d MAC: ",adb_database[entry].record?'W':' ',
    adb_database[entry].filter?'F':' ',
    entry,adb_database[entry].numSeen,adb_database[entry].listCount);
    btutil_printBDaddress(adb_database[entry].result-&gt;remote_bd_addr);

    switch(method)
    {
    
    case ADB_PRINT_METHOD_BYTES:
        printf(" Data: ");
        btutil_adv_printPacketBytes(adv_data-&gt;data);
    break;

    case ADB_PRINT_METHOD_DECODE:
        printf("\n");
        btutil_adv_printPacketDecode(adv_data-&gt;data);
    break;
    } 
    printf("\n");

}
</pre>
<p>With the new function in place I now need to update the print function to call the new entry function.  Printing the history is just a matter of iterating through the linked list.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_print(adb_print_method_t method,bool history,int entry)
{
    int start,end;
 
    if(entry &lt; 0)
    {
        start = 0;
        end = adb_db_count;
    }
    else
    {
        start = entry;
        end = entry+1;
    }

    if(end&gt;adb_db_count)
        end = adb_db_count; 

    for(int i=start;i&lt;end;i++)
    {
        if(history) // then iterate through the linked list print all of the packets
        {
            for(adb_adv_data_t *list = adb_database[i].list;list;list = (adb_adv_data_t *)list-&gt;next)
            {
                adb_db_printEntry(method,i,list);    
            }
        }
        else // Just print the first packet in the list
            adb_db_printEntry(method,i,adb_database[i].list);
    }
}</pre>
<p>Now, I need to update all of the calls to adb_db_print to have the new history parameter.  First, I made the decision that when you &#8220;print&#8221; from the command line that you are interested in the history.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">                case ADB_PRINT_RAW:
                    adb_db_print(ADB_PRINT_METHOD_BYTES,true,(int)msg.data0);
                break;
                case ADB_PRINT_DECODE:
                    adb_db_print(ADB_PRINT_METHOD_DECODE,true,(int)msg.data0);
                break;</pre>
<p>But when you are printing out the packet for a new device don&#8217;t print out the history</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">            adb_db_print(ADB_PRINT_METHOD_BYTES,false,adb_db_count-1);
</pre>
<h1>Program and Test</h1>
<p>After I program my development kit, I start by typing &#8220;watch all&#8221;.  Very quickly, at my house, you can see that a bunch of devices are discovered.  You can see that all of these have a &#8220;W&#8221; (meaning that I am watching them) and an &#8220;F&#8221; meaning they are filtering out duplicates.  Then I type &#8220;record&#8221; to turn on recording. After a minute I turn off recording then do the print you can see below.</p>
<p>A couple of things to notice.</p>
<ol>
<li>Device #4 (which I highlighted) appears to be sending out a pattern of alternating packets.  See that I have heard 3335 packets yet there are only two in the buffer</li>
<li>You can see device 11 seems to be sending out 16 different packets.  Why?  I don&#8217;t know.</li>
</ol>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/screen-shot-2020-11-14-at-12-33-06-pm/" rel="attachment wp-att-10236"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.33.06-PM-1024x624.png" alt="" class="alignnone size-large wp-image-10236" width="1024" height="624" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.33.06-PM-1024x624.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.33.06-PM-300x183.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.33.06-PM-768x468.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.33.06-PM-1536x936.png 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.33.06-PM-600x366.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.33.06-PM.png 2032w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>But we can &#8220;decode 11&#8221; to try to figure it out.  You can see that it is advertising manufactures specific data with Apple&#8217;s UUID which I happen to know is 0x004C.  But why?  I don&#8217;t know.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/screen-shot-2020-11-14-at-12-37-51-pm/" rel="attachment wp-att-10237"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.37.51-PM-1024x807.jpg" alt="" class="alignnone size-large wp-image-10237" width="1024" height="807" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.37.51-PM-1024x807.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.37.51-PM-300x236.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.37.51-PM-768x605.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.37.51-PM-1536x1210.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.37.51-PM-600x473.jpg 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-12.37.51-PM.jpg 1554w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>I really want to move onto a new series of articles&#8230; but there are two functions which I will add to the program.  Stay tuned for what they do.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AnyCloud Bluetooth Advertising Scanner (Part 7)</title>
		<link>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/</link>
					<comments>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 07 Dec 2020 13:00:38 +0000</pubDate>
				<category><![CDATA[AnyCloud]]></category>
		<category><![CDATA[AnyCloud Advertising Scanner]]></category>
		<category><![CDATA[Bluetooth]]></category>
		<category><![CDATA[CY8CKIT-062-WiFi-BT]]></category>
		<category><![CDATA[CY8CKIT-062S2-43012]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=10218</guid>

					<description><![CDATA[Summary In this series of articles I am building a Bluetooth Low Energy Scanner using the Cypress/Infineon AnyCloud SDK running on a PSoC 6 and CYW43xxx.  In Part 7 I will add the ability to record BLE ADV packets. Story If you have been reading along, at this point we have built a BLE scanner [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In this series of articles I am building a Bluetooth Low Energy Scanner using the Cypress/Infineon AnyCloud SDK running on a PSoC 6 and CYW43xxx.  In Part 7 I will add the ability to record BLE ADV packets.</p>
<h1>Story</h1>
<p>If you have been reading along, at this point we have built a BLE scanner that can see Bluetooth devices that are advertising.  My scanner has a command line and you can print out the most recent data.  Even better, we built a decoder that allows you to better understand the data.</p>
<p>Now I want to add the ability to record more than one advertising packet per device.  To that end I will add three commands:</p>
<ul>
<li>watch &#8211; Mark a device as one that needs to have the advertising data recorded.  You can type &#8220;watch 12&#8221; or you can say &#8220;watch all&#8221; or you can say &#8220;watch clear&#8221;</li>
<li>record &#8211; Turn on recording of &#8220;watched&#8221; devices.  When you type record it will toggle the recording state between On and Off.</li>
<li>erase &#8211; clear the record buffer of all but the most recent packet.</li>
</ul>
<p>There are</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
<th >Topic</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 1)</a></td>
<td >Introduction to AnyCloud Bluetooth Advertising</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 2)</a></td>
<td >Creating an AnyCloud Bluetooth project</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 3)</a></td>
<td >Adding Observing functionality to the project</td>
</tr>

<tr><td ><a class="row-title" href="https://iotexpert.com/anycloud-bluetooth-utilities-library/" aria-label="“AnyCloud Bluetooth Utilities Library” (Edit)" target="_blank" rel="noopener">AnyCloud Bluetooth Utilities Library</a></td>
<td >A set of APIs for enhancement of the AnyCloud Library</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 4)</a></td>
<td >Adding a command line to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 5)</a></td>
<td >Adding a history database to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 6)</a></td>
<td >Decoding advertising packets</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 7)</a></td>
<td >Adding recording commands to the command line</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/">AnyCloud Bluetooth Advertising Scanner (Part 8)</a></td>
<td >Adding filtering to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/">AnyCloud Bluetooth Advertising Scanner (Part 9)</a></td>
<td >Improve the print and add packet age</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/">AnyCloud Bluetooth Advertising Scanner (Part 10)</a></td>
<td >Sort the database</td>
</tr>
</tbody></table></div></p>
<p>All of the code can be found at git@github.com:iotexpert/AnyCloudBLEScanner.git and https://github.com/iotexpert/AnyCloudBLEScanner.git</p>
<p>There are git tags in place starting at part 5 so that you can look at just that version of the code.  "git tag" to list the tags.  And "git checkout part6" to look at the part 6 version of the code.</p>
<p>You can also create a new project with this is a template if you have the IoT Expert Manifest Files installed</p>
<h1>Update the advDatabase Interface</h1>
<p>The first thing I realized as I went to add a new command was that I was typing the exact same code over and over for the public interface.  The code looked like this:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void adb_watch(int entry)
{
    adb_cmdMsg_t msg;
    msg.cmd = ADB_WATCH;
    msg.data0 = (void *)entry;
    xQueueSend(adb_cmdQueue,&amp;msg,0); // If the queue is full... oh well

}</pre>
<p>So I created this:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_queueCmd(adb_cmd_t cmd,void *data0, void *data1)
{
    adb_cmdMsg_t msg;
    msg.cmd = cmd;
    msg.data0 = data0;
    msg.data1 = data1;
    xQueueSend(adb_cmdQueue,&amp;msg,0); // If you loose an adv packet it is OK...
}</pre>
<p>Then did this to eliminate the duplication.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">inline void adb_addAdv(wiced_bt_ble_scan_results_t *scan_result,void *data) { adb_queueCmd(ADB_ADD,(void *)scan_result,(void *)data);}
inline void adb_print(int entry) { adb_queueCmd(ADB_PRINT_RAW,(void *)entry,(void *)0); }
inline void adb_decode(int entry) { adb_queueCmd(ADB_PRINT_DECODE,(void*)entry,(void *)0); }
</pre>
<h1>Redo the Database</h1>
<p>If you recall from previous posts, my advertising database was just</p>
<ol>
<li>An Array of structures</li>
<li>Each structure contained the mac address and&#8230;</li>
<li>A pointer to a malloc&#8217;d copy of the advertising data</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef struct {
    wiced_bt_ble_scan_results_t *result;
    uint8_t *data;
} adb_adv_t ;

#define ADB_MAX_SIZE (40)
adb_adv_t adb_database[ADB_MAX_SIZE];</pre>
<p>Here is a picture of the datastructure</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/db1/" rel="attachment wp-att-10226"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/db1.png" alt="" width="550" height="976" class="alignnone size-full wp-image-10226" srcset="https://iotexpert.com/wp-content/uploads/2020/11/db1.png 550w, https://iotexpert.com/wp-content/uploads/2020/11/db1-169x300.png 169w" sizes="auto, (max-width: 550px) 100vw, 550px" /></a></p>
<p>&nbsp;</p>
<p>Now what I want to do is make the &#8220;data&#8221; pointer to be a pointer to a linked list of data.  Here is the new definition.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef struct {
    uint8_t *data;
    struct adb_adv_data_t *next;
} adb_adv_data_t;

typedef struct {
    wiced_bt_ble_scan_results_t *result;
    int listCount;
    bool record;
    int numSeen;
    adb_adv_data_t *list;
} adb_adv_t ;</pre>
<p>The new data structure looks like this</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/newdb/" rel="attachment wp-att-10227"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/newdb-1024x863.png" alt="" width="1024" height="863" class="alignnone size-large wp-image-10227" srcset="https://iotexpert.com/wp-content/uploads/2020/11/newdb-1024x863.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/newdb-300x253.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/newdb-768x647.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/newdb-600x506.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/newdb.png 1158w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>I wanted to limit the number advertising packets that can be stored so I don&#8217;t run out of memory.  I am not actually sure how many can be stored, but I suppose a bunch as the chip has 1MB of RAM.  But, I pick 100 which seems like enough to start out with.  I create two variables</p>
<ol>
<li>A counter for the number of advertising packets that are currently saved</li>
<li>A recording state (are you saving or not)</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">#define ADB_RECORD_MAX (100)
static int adb_recording_count = 0;
static bool adb_recording = false;
</pre>
<h1>Update the Printing</h1>
<p>You probably noticed that I declared two new members of the adb_adv_t structure, specifically numSeen and listCount, which I would like to print out.   I also wanted a visual indication that I am &#8220;watching&#8221; a device.  The columns are now:</p>
<ol>
<li>A &#8220;*&#8221; to indicate that a device is being watched</li>
<li>The device #</li>
<li>The number of packets that I have seen in total from that device</li>
<li>The number of recorded packets for that device</li>
<li>The MAC address</li>
<li>The raw bytes</li>
</ol>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/screen-shot-2020-11-13-at-9-11-45-am/" rel="attachment wp-att-10228"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-13-at-9.11.45-AM-1024x355.png" alt="" width="1024" height="355" class="alignnone size-large wp-image-10228" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-13-at-9.11.45-AM-1024x355.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-13-at-9.11.45-AM-300x104.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-13-at-9.11.45-AM-768x266.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-13-at-9.11.45-AM-1536x533.png 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-13-at-9.11.45-AM-600x208.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-13-at-9.11.45-AM.png 1984w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>To do implement this a simple change is made to the print function:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">    for(int i=start;i&lt;end;i++)
    {
    
        printf("%s%02d %05d %03d MAC: ",adb_database[i].record?"*":" ",i,adb_database[i].numSeen,adb_database[i].listCount);
        btutil_printBDaddress(adb_database[i].result-&gt;remote_bd_addr);
        switch(method)
        {
        
        case ADB_PRINT_METHOD_BYTES:
            printf(" Data: ");
            btutil_adv_printPacketBytes(adb_database[i].list-&gt;data);
        break;

        case ADB_PRINT_METHOD_DECODE:
            printf("\n");
            btutil_adv_printPacketDecode(adb_database[i].list-&gt;data);
        break;
        } 
        printf("\n");
    }</pre>
<h1>Update the Add</h1>
<p>Now that we have all of the infrastructure in place we need to update the function that saves advertising data.  When an advertising packet comes in you have three situations to consider:</p>
<ol>
<li>You have never seen the device before</li>
<li>You have seen the device before and you are &#8220;watching&#8221; it</li>
<li>You have see the device but you are not watching it</li>
</ol>
<p>In the case where you have never seen the device you need to</p>
<ol>
<li>Save the scan result</li>
<li>Set the listCount to 1 (you only have one datapoint)</li>
<li>Turn off recording (start with the recording off)</li>
<li>Set the total numSeen to 1 as this is the first packet you have seen</li>
<li>Allocate some memory for the advertising linked list structure</li>
<li>Terminate the linked list</li>
<li>Save the advertising data</li>
<li>Increment the database count (up to the max)</li>
<li>Print out the packet you just saw</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    if(entry == -1)
    {
        adb_database[adb_db_count].result = scan_result;
        adb_database[adb_db_count].listCount = 1;
        adb_database[adb_db_count].record = false;
        adb_database[adb_db_count].numSeen = 1;

        adb_adv_data_t *current = malloc(sizeof(adb_adv_data_t));
        current-&gt;next = 0;
        current-&gt;data = data;

        adb_database[adb_db_count].list = current;

        adb_db_count = adb_db_count + 1;
        if(adb_db_count == ADB_MAX_SIZE)
        {
            printf("ADV Table Max Size\n");
            adb_db_count = adb_db_count - 1;
        }
        else
        {    
            adb_db_print(ADB_PRINT_METHOD_BYTES,adb_db_count-1);
        }
    }</pre>
<p>In the case where you have</p>
<ol>
<li>Seen the device before</li>
<li>You are recording that device</li>
<li>There is room left in the recording buffer</li>
</ol>
<p>Then you will</p>
<ol>
<li>Increment number seen</li>
<li>Create memory for the new entry in the linked list</li>
<li>Attach the tail of the linked list to your new entry (you will insert at the front of the list)</li>
<li>Save the data</li>
<li>Increment the number of saved entries</li>
<li>Insert your new packet at the head of the list</li>
<li>Printout the packet</li>
<li>Increment the record count (the total number of packets in the recording buffer)</li>
<li>Then potentially stop recording if you have gotten to the max size.</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    else if(adb_database[entry].record &amp;&amp; adb_recording_count&lt;ADB_RECORD_MAX &amp;&amp; adb_recording)
    {
        adb_database[entry].numSeen += 1;

        adb_adv_data_t *current = malloc(sizeof(adb_adv_data_t));
        current-&gt;next = (struct adb_adv_data_t *)adb_database[entry].list;
        current-&gt;data = data;
        adb_database[entry].listCount += 1;
        adb_database[entry].list = current;

        adb_db_print(ADB_PRINT_METHOD_BYTES,entry);

        adb_recording_count += 1;
        if(adb_recording_count == ADB_RECORD_MAX)
        {
            adb_recording = false;
            printf("Recording buffer full\n");
        }
    }</pre>
<p>In the case where you have seen the device before, but you are not recoding then you will</p>
<ol>
<li>Update the numSeen</li>
<li>Erase the old packet data</li>
<li>Save the new packet</li>
<li>Erase the &#8220;result&#8221; (you already have it saved)</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    else
    {
        adb_database[entry].numSeen += 1;
        free(adb_database[entry].list-&gt;data);
        adb_database[entry].list-&gt;data = data;
        free(scan_result);
    }</pre>
<h1>Add a Watch Command</h1>
<p>The watch function is pretty simple.  It just needs to either mark the &#8220;record&#8221; boolean as true or false.  When I decided to implement this function I decided to make positive numbers be the entry in the table.  But, I also wanted to be able to &#8220;watch all&#8221; and &#8220;watch clear&#8221;.  So, I used negative numbers for those two special meanings.  I used a #define in advDatabase.h to define those values.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">#define ADB_WATCH_ALL -1
#define ADB_WATCH_CLEAR -2</pre>
<p>The function is then pretty simple</p>
<ol>
<li>If it is watch all&#8230; then iterate through the database and turn them on</li>
<li>If it is watch clear &#8230; then iterate through the database and turn them off</li>
<li>Otherwise make sure that it is a legal number and toggle it.</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_watch(int entry)
{
    if(entry == ADB_WATCH_ALL)
    {
        for(int i=0;i&lt;adb_db_count;i++)
        {
            adb_database[i].record = true;
        }
        return;
    }

    if(entry == ADB_WATCH_CLEAR)
    {
        for(int i=0;i&lt;adb_db_count;i++)
        {
            adb_database[i].record = false;
        }
        return;
    }

    if(entry &gt; adb_db_count-1 || entry &lt; ADB_WATCH_CLEAR)
    {
        printf("Record doesnt exist: %d\n",entry);
        return;      
    }
    adb_database[entry].record = !adb_database[entry].record; 

}</pre>
<p>Once I have the infrastructure in place, I then add the watch command to usrcmd.c</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">static int usrcmd_watch(int argc, char **argv)
{

    if(argc == 2 &amp;&amp; !strcmp(argv[1],"all"))
    {
        adb_watch(ADB_WATCH_ALL); // all
        return 0;
    }


    if(argc == 2 &amp;&amp; !strcmp(argv[1],"clear"))
    {
        adb_watch(ADB_WATCH_CLEAR);
        return 0;
    }

    if(argc == 2)
    {
        int i;
        sscanf(argv[1],"%d",&amp;i);
        adb_watch(i);
        return 0;
    }

    return 0;
}</pre>
<h1>Add a Record Command</h1>
<p>The record command simply turns on the global bool to either true or false and prints out the number of spaces free in the record &#8220;buffer&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">                case ADB_RECORD:
                    adb_recording = !adb_recording;
                    printf("Record %s Buffer Entries Free=%d\n",adb_recording?"ON":"OFF",
                        ADB_RECORD_MAX-adb_recording_count);
                break;</pre>
<p>And the change to usrcmd.c is also simple.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">// record = toggles
static int usrcmd_record(int argc, char **argv)
{
    if(argc == 1)
    {
        adb_record(-1);
        return 0;
    }
    return 0;
}</pre>
<h1>Add an Erase Command</h1>
<p>The erase function is like &#8220;watch&#8221;, as I overload the &#8220;entry&#8221; to have an ALL which is setup in advDatabase.h</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">#define ADB_ERASE_ALL -1</pre>
<p>The erase is a bit more complicated than the watch.  When you receive a erase command you will either erase them all by iterating over the whole dates, or just erase one.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">                case ADB_ERASE:
                    if((int)msg.data0 == ADB_ERASE_ALL)
                    {
                        for(int i=0;i&lt;adb_db_count;i++)
                        {
                            adb_eraseEntry(i);
                        }
                    }
                    else
                        adb_eraseEntry((int)msg.data0);

                    printf("Record Buffer Free %d\n",ADB_RECORD_MAX-adb_recording_count);
                break;</pre>
<p>The individual eraseEntry function checks to make sure that you have a legal &#8220;entry&#8221;.  Then it follows the linked list &#8220;freeing&#8221; the data structures.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">static void adb_eraseEntry(int entry)
{
    if(entry &gt; adb_db_count-1 || entry&lt;0)
    {
        printf("Erase Entry Not Found %d\n",entry);
        return;
    }

    adb_adv_data_t *ptr;
    ptr = (adb_adv_data_t *)adb_database[entry].list-&gt;next;
    adb_database[entry].list-&gt;next = 0;
    while(ptr)
    {
        adb_adv_data_t *next;
        next = (adb_adv_data_t *)ptr-&gt;next;
        free(ptr-&gt;data);
        free(ptr);
        adb_database[entry].listCount -= 1;
        adb_recording_count -= 1;
        ptr = next;
    }
}
</pre>
<p>And, of course, you need to add the command to usrcmd.c</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">// erase
// erase #
static int usrcmd_erase(int argc, char **argv)
{
    if(argc &gt; 2)
    {
        return 0;
    }

    if(argc == 1)
    {
        adb_erase(ADB_ERASE_ALL);
        return 0;
    }

    int i;
    sscanf(argv[1],"%d",&amp;i);
    adb_erase(i);
    return 0;    

}</pre>
<p>Now when you build and program the kit you can turn on/off recording and erase and&#8230;.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/screen-shot-2020-11-14-at-7-30-37-am/" rel="attachment wp-att-10233"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-7.30.37-AM-1024x741.jpg" alt="" width="1024" height="741" class="alignnone size-large wp-image-10233" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-7.30.37-AM-1024x741.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-7.30.37-AM-300x217.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-7.30.37-AM-768x556.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-7.30.37-AM-1536x1112.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-7.30.37-AM-600x434.jpg 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-14-at-7.30.37-AM.jpg 1976w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>In the next post I will add</p>
<ol>
<li>Smarter printing</li>
<li>A &#8220;filter&#8221; to eliminate duplicate advertising packets</li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AnyCloud Bluetooth Advertising Scanner (Part 6)</title>
		<link>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/</link>
					<comments>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 30 Nov 2020 13:00:38 +0000</pubDate>
				<category><![CDATA[4343W]]></category>
		<category><![CDATA[AnyCloud]]></category>
		<category><![CDATA[AnyCloud Advertising Scanner]]></category>
		<category><![CDATA[Bluetooth]]></category>
		<category><![CDATA[CY8CKIT-062-WiFi-BT]]></category>
		<category><![CDATA[CY8CKIT-062S2-43012]]></category>
		<category><![CDATA[CY8CPROTO-062-4343W]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=10206</guid>

					<description><![CDATA[Summary In part 6 of this series I will update the AnyCloud BLE Advertising Scanner to decode advertising packets into a more human readable textual output Story We are now 6 (or maybe 7 depending on how you count) articles into this series and we are still looking at raw bytes.  I have gotten to [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In part 6 of this series I will update the AnyCloud BLE Advertising Scanner to decode advertising packets into a more human readable textual output</p>
<h1>Story</h1>
<p>We are now 6 (or maybe 7 depending on how you count) articles into this series and we are still looking at raw bytes.  I have gotten to where I am pretty good at understanding those bytes, but that is now way to roll.  You might remember from the <a href="https://iotexpert.com/anycloud-bluetooth-utilities-library/">article</a> on the IoT Expert Bluetooth Utility library that there were a some interesting functions defined in the header.  Here it is:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">wiced_bool_t btutil_isEddystone(uint8_t *data);
wiced_bool_t btutil_is_iBeacon(uint8_t *data);
wiced_bool_t btutil_isCypress(uint8_t *data);

int btutil_adv_len(uint8_t *packet);
void btutil_adv_printPacketDecode(uint8_t *packet);
void btutil_adv_printPacketBytes(uint8_t *packet);</pre>
<p>Lets transform our  project from part 6 to use these functions.  In this article I will</p>
<ul>
<li>Redo the print bytes (to be smarter) functionality and to use the built in function</li>
<li>Rework the logic for the &#8220;print&#8221; command implementation</li>
<li>Add a new command &#8220;decode&#8221; which will run the decode function</li>
</ul>
<p>There are</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
<th >Topic</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 1)</a></td>
<td >Introduction to AnyCloud Bluetooth Advertising</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 2)</a></td>
<td >Creating an AnyCloud Bluetooth project</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 3)</a></td>
<td >Adding Observing functionality to the project</td>
</tr>

<tr><td ><a class="row-title" href="https://iotexpert.com/anycloud-bluetooth-utilities-library/" aria-label="“AnyCloud Bluetooth Utilities Library” (Edit)" target="_blank" rel="noopener">AnyCloud Bluetooth Utilities Library</a></td>
<td >A set of APIs for enhancement of the AnyCloud Library</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 4)</a></td>
<td >Adding a command line to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 5)</a></td>
<td >Adding a history database to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 6)</a></td>
<td >Decoding advertising packets</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 7)</a></td>
<td >Adding recording commands to the command line</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/">AnyCloud Bluetooth Advertising Scanner (Part 8)</a></td>
<td >Adding filtering to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/">AnyCloud Bluetooth Advertising Scanner (Part 9)</a></td>
<td >Improve the print and add packet age</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/">AnyCloud Bluetooth Advertising Scanner (Part 10)</a></td>
<td >Sort the database</td>
</tr>
</tbody></table></div></p>
<p>All of the code can be found at git@github.com:iotexpert/AnyCloudBLEScanner.git and https://github.com/iotexpert/AnyCloudBLEScanner.git</p>
<p>There are git tags in place starting at part 5 so that you can look at just that version of the code.  "git tag" to list the tags.  And "git checkout part6" to look at the part 6 version of the code.</p>
<p>You can also create a new project with this is a template if you have the IoT Expert Manifest Files installed</p>
<h1>Replace two code blocks with function calls</h1>
<p>Do you remember this block of code?  It print&#8217;s out the 6-bytes of the Bluetooth Address.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    for(int i=0;i&lt;BD_ADDR_LEN;i++)
    {
        printf("%02X:",adb_database[entry].result-&gt;remote_bd_addr[i]);
    }
</pre>
<p>You might have noticed that this function already exists in the BT Utility Library.  Use it.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    btutil_printBDaddress(adb_database[entry].result-&gt;remote_bd_addr);</pre>
<p>Then you remember this block of code which iterates through and advertising packet and prints out the raw bytes?</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">// Print the RAW Data of the ADV Packet
    printf(" Data: ");
    int i=0;
    while(adb_database[entry].data[i])
    {
        for(int j=0;j&lt;adb_database[entry].data[i];j++)
        {
            printf("%02X ",adb_database[entry].data[i+1+j]);
        }
        i = i + adb_database[entry].data[i]+1;
    }
</pre>
<p>Well, it exists in the library as well.  Use it.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">btutil_adv_printPacketBytes(adb_database[entry].data);</pre>
<h1>Fix the &#8220;print&#8221; Command</h1>
<p>In the previous implementation I had two functions for &#8220;print&#8221;.  The first one printed one entry and the second one printed the whole table.  I decided that I didnt really like this logic, so I compressed those two functions into one function.  Specifically, it take a number &#8220;entry&#8221;.  If that number is -1 then it will print the whole table.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_printRawPacket(int entry)
{
    int start,end;
 
    if(entry &lt;= -1)
    {
        start = 0;
        end = adb_db_count;
    }
    else
    {
        start = entry;
        end = entry;
    }

    if(end&gt;adb_db_count)
        end = adb_db_count; 

    for(int i=start;i&lt;=end;i++)
    {
    
        printf("%02d MAC: ",i);
        btutil_printBDaddress(adb_database[i].result-&gt;remote_bd_addr);
        printf(" Data: ");
        btutil_adv_printPacketBytes(adb_database[i].data);

        printf("\n");
    }
}
</pre>
<h1>Add a new &#8220;decode&#8221; Command</h1>
<p>The next thing to do is to add a function to print out decoded packets (or the whole table).  So I wrote this:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_printDecodePacket(int entry)
{
    int start,end;
 
    if(entry == -1)
    {
        start = 0;
        end = adb_db_count;
    }
    else
    {
        start = entry;
        end = entry;
    }

    if(end&gt;adb_db_count)
        end = adb_db_count; 

    for(int i=start;i&lt;=end;i++)
    {

        printf("%02d MAC: ",i);
        btutil_printBDaddress(adb_database[i].result-&gt;remote_bd_addr);
        printf("\n");
        btutil_adv_printPacketDecode(adb_database[i].data);
        printf("\n");
    }
}</pre>
<p>After finishing that block of code, I realized I had implemented almost exactly the same functionality which two different functions.  So, I decided to redo this by doing this.  Notice that it take in a adb_print_method, in other words raw bytes or decoded packet.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef enum {
    ADB_PRINT_METHOD_BYTES,
    ADB_PRINT_METHOD_DECODE,
} adb_print_method_t;

static void adb_db_print(adb_print_method_t method,int entry)
{
    int start,end;
 
    if(entry &lt; 0)
    {
        start = 0;
        end = adb_db_count;
    }
    else
    {
        start = entry;
        end = entry;
    }

    if(end&gt;adb_db_count)
        end = adb_db_count; 

    for(int i=start;i&lt;=end;i++)
    {
    
        printf("%02d MAC: ",i);
        btutil_printBDaddress(adb_database[i].result-&gt;remote_bd_addr);
        switch(method)
        {
        
        case ADB_PRINT_METHOD_BYTES:
            printf(" Data: ");
            btutil_adv_printPacketBytes(adb_database[i].data);
        break;

        case ADB_PRINT_METHOD_DECODE:
            printf("\n");
            btutil_adv_printPacketDecode(adb_database[i].data);
        break;
        } 
        printf("\n");
    }
}
</pre>
<p>I don&#8217;t show it here, but after changing this I had to fix up the function calls in several places in the advDatabase.</p>
<h1>Add a new command to print decode packets</h1>
<p>Now that I have a new method to print packets, I add a command to the database to allow the user to call it:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef enum {
    ADB_ADD,
    ADB_PRINT_RAW,
    ADB_PRINT_DECODE,
} adb_cmd_t;
</pre>
<p>Then in the queue loop:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">switch(msg.cmd)
            {
                case ADB_ADD:
                    scan_result = (wiced_bt_ble_scan_results_t *)msg.data0;
                    data = (uint8_t *)msg.data1;
                    adb_db_add(scan_result,data);
                break;
                case ADB_PRINT_RAW:
                    adb_db_print(ADB_PRINT_METHOD_BYTES,(int)msg.data0);
                break;
                case ADB_PRINT_DECODE:
                    adb_db_print(ADB_PRINT_METHOD_DECODE,(int)msg.data0);
                break;
            }</pre>
<p>Then the actual function</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void adb_printDecode(int entry)
{
    adb_cmdMsg_t msg;
    msg.cmd = ADB_PRINT_DECODE;
    msg.data0 = (void *)entry;
    xQueueSend(adb_cmdQueue,&amp;msg,0); // If the queue is full... oh well
}</pre>
<p>Then add it to advDatabase.h</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void adb_printDecode(int entry);
</pre>
<p>Finally to the usercmd.c</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static int usrcmd_printDecode(int argc, char **argv)
{
    if(argc == 1)
    {
        adb_printDecode(-1);
    }

    if(argc == 2)
    {
        int val;
        sscanf(argv[1],"%d",&amp;val);
        adb_printDecode(val);
    }
    return 0;
}</pre>
<h1>Program and Test</h1>
<p>When I actually program the scanner you can see that I can print out 1 item.  OR I can decode one item.  Notice that one contains 3 fields</p>
<ul>
<li>flags</li>
<li>Tx Power Level</li>
<li>Manufacturers data.  Apparently an Apple something or the other</li>
</ul>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/screen-shot-2020-11-09-at-7-53-43-am/" rel="attachment wp-att-10211"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.53.43-AM-1024x219.png" alt="" class="alignnone size-large wp-image-10211" width="1024" height="219" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.53.43-AM-1024x219.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.53.43-AM-300x64.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.53.43-AM-768x164.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.53.43-AM-600x128.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.53.43-AM.png 1358w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>And I can print the whole table</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/screen-shot-2020-11-09-at-7-51-10-am/" rel="attachment wp-att-10213"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.10-AM-1024x629.jpg" alt="" class="alignnone size-large wp-image-10213" width="1024" height="629" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.10-AM-1024x629.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.10-AM-300x184.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.10-AM-768x472.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.10-AM-1536x944.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.10-AM-2048x1259.jpg 2048w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.10-AM-600x369.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Or decode the whole table.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/screen-shot-2020-11-09-at-7-51-33-am/" rel="attachment wp-att-10212"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.33-AM-1024x633.jpg" alt="" class="alignnone size-large wp-image-10212" width="1024" height="633" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.33-AM-1024x633.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.33-AM-300x185.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.33-AM-768x475.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.33-AM-1536x949.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.33-AM-2048x1266.jpg 2048w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-09-at-7.51.33-AM-600x371.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AnyCloud Bluetooth Advertising Scanner (Part 5)</title>
		<link>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/</link>
					<comments>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 23 Nov 2020 18:03:57 +0000</pubDate>
				<category><![CDATA[4343W]]></category>
		<category><![CDATA[AnyCloud]]></category>
		<category><![CDATA[AnyCloud Advertising Scanner]]></category>
		<category><![CDATA[Bluetooth]]></category>
		<category><![CDATA[CY8CKIT-062-WiFi-BT]]></category>
		<category><![CDATA[CY8CKIT-062S2-43012]]></category>
		<category><![CDATA[CY8CPROTO-062-4343W]]></category>
		<category><![CDATA[PSoC 6]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=10196</guid>

					<description><![CDATA[Summary In this article I will add a new task to the AnyCloud BLE Advertising Scanning application which will save the advertising data into a database. Story There is still a boatload of mostly unintelligible advertising data coming ripping onto our screen.  It is FINALLY time to start fixing that.  In this article I will [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In this article I will add a new task to the AnyCloud BLE Advertising Scanning application which will save the advertising data into a database.</p>
<h1>Story</h1>
<p>There is still a boatload of mostly unintelligible advertising data coming ripping onto our screen.  It is FINALLY time to start fixing that.  In this article I will create a new task called the advertising database task which will hold the history of advertising packets that I have seen.  I will update the Bluetooth Manager task to submit the advertising packets to a queue running in the advertising database task.</p>
<p>There are</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
<th >Topic</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 1)</a></td>
<td >Introduction to AnyCloud Bluetooth Advertising</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 2)</a></td>
<td >Creating an AnyCloud Bluetooth project</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 3)</a></td>
<td >Adding Observing functionality to the project</td>
</tr>

<tr><td ><a class="row-title" href="https://iotexpert.com/anycloud-bluetooth-utilities-library/" aria-label="“AnyCloud Bluetooth Utilities Library” (Edit)" target="_blank" rel="noopener">AnyCloud Bluetooth Utilities Library</a></td>
<td >A set of APIs for enhancement of the AnyCloud Library</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 4)</a></td>
<td >Adding a command line to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 5)</a></td>
<td >Adding a history database to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 6)</a></td>
<td >Decoding advertising packets</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 7)</a></td>
<td >Adding recording commands to the command line</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/">AnyCloud Bluetooth Advertising Scanner (Part 8)</a></td>
<td >Adding filtering to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/">AnyCloud Bluetooth Advertising Scanner (Part 9)</a></td>
<td >Improve the print and add packet age</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/">AnyCloud Bluetooth Advertising Scanner (Part 10)</a></td>
<td >Sort the database</td>
</tr>
</tbody></table></div></p>
<p>All of the code can be found at git@github.com:iotexpert/AnyCloudBLEScanner.git and https://github.com/iotexpert/AnyCloudBLEScanner.git</p>
<p>There are git tags in place starting at part 5 so that you can look at just that version of the code.  "git tag" to list the tags.  And "git checkout part6" to look at the part 6 version of the code.</p>
<p>You can also create a new project with this is a template if you have the IoT Expert Manifest Files installed</p>
<h1>Create an Advertising Data Database Task</h1>
<p>We need to create the file advertisingDatabase.h which will hold the task prototype (so that main can get going).</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#pragma once

void adb_task(void *arg);
</pre>
<p>Then create the advertisingDatabase.c to hold the actual database code.  It will start with the definition of messages which can be sent to the task.  For now just &#8220;ADB_ADD&#8221;.  To make things a little bit simpler these command can have two data elements (which I call data0 and data1).  Then the main part of the task just</p>
<ol>
<li>Creates the queue to manage the messages</li>
<li>Process the message until the end of time</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "FreeRTOS.h"
#include "queue.h"

static QueueHandle_t adb_cmdQueue;
typedef enum {
    ADB_ADD,
} adb_cmd_t;

typedef struct
{
    adb_cmd_t cmd;
    void *data0;
    void *data1;
} adb_cmdMsg_t;

void adb_task(void *arg)
{
    // setup the queue
    adb_cmdMsg_t msg;

    adb_cmdQueue = xQueueCreate(10,sizeof(adb_cmdMsg_t));
    
    while(1)
    {
        BaseType_t status = xQueueReceive(adb_cmdQueue,&amp;msg,portMAX_DELAY);
        if(status == pdTRUE) 
        {
            switch(msg.cmd)
            {
                case ADB_ADD:
                break;
            }

        }
    }
}
</pre>
<p>To start the task, you need to add it to main.c.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    xTaskCreate(adb_task,"adv database",configMINIMAL_STACK_SIZE*4,0,1,0);
</pre>
<p>When I build and program this, you can now see the new task.  Good that working.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">AnyCloud&gt; Unhandled Bluetooth Management Event: BTM_LOCAL_IDENTITY_KEYS_REQUEST_EVT
Started BT Stack Succesfully

AnyCloud&gt; tasks
Name          State Priority   Stack  Num
------------------------------------------
usrcmd_ta       X       0       228     5
IDLE            R       0       115     7
Tmr Svc         B       0       223     8
CYBT_HCI_       B       5       950     3
sleep_tas       B       6       221     1
CYBT_BT_T       B       4       1371    2
blinkTask       B       0       98      4
adv datab       B       1       479     6
‘B’ – Blocked
‘R’ – Ready
‘D’ – Deleted (waiting clean up)
‘S’ – Suspended, or Blocked without a timeout
Stack = bytes free at highwater
AnyCloud&gt;</pre>
<h1>Update the Advertising Database to Accept Submitted ADV Packets</h1>
<p>If you recall our original setup was to take advertising packets in the Bluetooth Manager thread and print out the data.  The first thing that we want to fix up is the ability of the advertising database task to accept advertising packets which are pushed to its command queue.   To prepare for this I create two local variables to hold the data.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void adb_task(void *arg)
{
    // setup the queue
    adb_cmdMsg_t msg;
    wiced_bt_ble_scan_results_t *scan_result;
    uint8_t *data;</pre>
<p>Then I update the ADB_ADD command.  My first, and really simple fix, is to grab the printing code from the Bluetooth Manager task.  Obviously this won&#8217;t be an improvement from the original program as far as the users goes, but it will verify that the tasks are working properly together.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">                case ADB_ADD:
                    // Print the MAC Address
                    scan_result = (wiced_bt_ble_scan_results_t *)msg.data0;
                    data = (uint8_t *)msg.data1;

                    printf("MAC: ");
                    for(int i=0;i&lt;BD_ADDR_LEN;i++)
                    {
                        printf("%02X:",scan_result-&gt;remote_bd_addr[i]);
                    }
                    // Print the RAW Data of the ADV Packet
                    printf(" Data: ");
                    int i=0;
                    while(data[i])
                    {
                        for(int j=0;j&lt;data[i];j++)
                        {
                            printf("%02X ",data[i+1+j]);
                        }
                        i = i + data[i]+1;
                    }
                    printf("\n");
    
                    free(msg.data0);
                    free(msg.data1);
                break;
</pre>
<p>Then I add a command to the advertisingDatabase.h which the Bluetooth Manager task can call to submit advertising packets</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void adb_addAdv(wiced_bt_ble_scan_results_t *scan_result,void *data);</pre>
<p>The actual command in advertisingDatabase.c just takes the advertising information, puts it in a command message, then submits it to the command queue.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void adb_addAdv(wiced_bt_ble_scan_results_t *scan_result,void *data)
{
    adb_cmdMsg_t msg;
    msg.cmd = ADB_ADD;
    msg.data0 = (void *)scan_result;
    msg.data1 = (void *)data;
    xQueueSend(adb_cmdQueue,&amp;msg,0); // If you loose an adv packet it is OK...
}
</pre>
<h1>Update the Bluetooth Manager to Submit Adv Packets</h1>
<p>Now I go and edit the bluetoothManager. c to submit packets rather than print them.  To do this I greatly simplify the callback.  There is one VERY important issue to deal with, which is one of those potential religious war issues.  Memory.</p>
<p>When you get the callback from the stack, it gives you POINTERS to data for the advertising packet that reside inside of buffers inside of the stack.  As soon as this callback returns this memory is purged.  To prevent this data from getting cleaned up by the stack I</p>
<ol>
<li>Malloc some memory for the wiced_bt_ble_scan_results</li>
<li>Malloc some memory for the advertising data</li>
<li>Make a copy of the data</li>
<li>Submit it to the Advertising Database</li>
</ol>
<p>I KNOW from the spec that the largest data packet is 31-bytes (actually it is 31-bytes + one more field with length 0).  So I know the maximum length is 32-bytes  This means that in many situations I will be copying GARBAGE into my buffer if the packet is less than 32 bytes long.  I think that this is simpler than calculating the length and then only copying that much data.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void btm_advCallback(wiced_bt_ble_scan_results_t *p_scan_result, uint8_t *p_adv_data)
{
    wiced_bt_ble_scan_results_t *scan_result = malloc(sizeof(wiced_bt_ble_scan_results_t));
    uint8_t *data = malloc(32);
   
    memcpy(data,p_adv_data,32);
    memcpy(scan_result,p_scan_result-&gt;remote_bd_addr,BD_ADDR_LEN);
    adb_addAdv(scan_result,data);
}
</pre>
<p>When I run this updated program I should get the same stream of data coming out on the serial port.  Sure enough the new thread is working.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/screen-shot-2020-11-07-at-10-23-16-am/" rel="attachment wp-att-10198"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-07-at-10.23.16-AM-1024x577.png" alt="" width="1024" height="577" class="alignnone size-large wp-image-10198" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-07-at-10.23.16-AM-1024x577.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-07-at-10.23.16-AM-300x169.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-07-at-10.23.16-AM-768x433.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-07-at-10.23.16-AM-1536x865.png 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-07-at-10.23.16-AM-600x338.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-07-at-10.23.16-AM.png 1868w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Create an Advertising Data Database</h1>
<p>Now, lets create an actual database.  To simplify things my database is just an array of structures.  One structure per bluetooth device.  The structure will contain a pointer to the information about the device it just saw and the actual raw data.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef struct {
    wiced_bt_ble_scan_results_t *result;
    uint8_t *data;
} adb_adv_t ;

#define ADB_MAX_SIZE (40)
adb_adv_t adb_database[ADB_MAX_SIZE];
int adb_db_count=0;
</pre>
<p>Then I will create several helper functions to work with the database</p>
<ol>
<li>Find devices in the database given a mac address</li>
<li>Print an entry in the database</li>
<li>Add entries to the database</li>
</ol>
<p>First, find an entry in the database.  This function will search through the database and compare the mac address against the mac address in the database.  When the memcmp ==0 meaning it found a match, it will return that entry.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">static int adb_db_find(wiced_bt_device_address_t *add)
{
    int rval=-1;
    for(int i=0;i&lt;adb_db_count;i++)
    {
        if(memcmp(add,&amp;adb_database[i].result-&gt;remote_bd_addr,BD_ADDR_LEN)==0)
        {
            rval = i;
            break;
        }
    }
    return rval;
}</pre>
<p>The print function will make sure that you asked for a legal entry (much must be greater than 0&#8230; and less than the max).  Then it will print out the mac address and the raw data.  In a future post I will add a smarter print out.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_printEntry(int entry)
{
    if(!(entry&gt;= 0 &amp;&amp; entry &lt;= adb_db_count))
    {
        printf("Illegal entry\n");
        return;
    }
    printf("%02d MAC: ",entry);

    for(int i=0;i&lt;BD_ADDR_LEN;i++)
    {
        printf("%02X:",adb_database[entry].result-&gt;remote_bd_addr[i]);
    }

    // Print the RAW Data of the ADV Packet
    printf(" Data: ");
    int i=0;
    while(adb_database[entry].data[i])
    {
        for(int j=0;j&lt;adb_database[entry].data[i];j++)
        {
            printf("%02X ",adb_database[entry].data[i+1+j]);
        }
        i = i + adb_database[entry].data[i]+1;
    }
    printf("\n");
}</pre>
<p>To add an entry to the database, first make sure that it isn&#8217;t already in the database.  Then when you are sure that it isn&#8217;t the database, you just add the pointers to your table.  You need to make sure and not go beyond the end of the table, and if you did, you will have effectively blown away the last entry in the table.  Oh well.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void adb_db_add(wiced_bt_ble_scan_results_t *scan_result,uint8_t *data)
{
 
    int entry = adb_db_find(&amp;scan_result-&gt;remote_bd_addr);
    if(entry == -1)
    {
        
        adb_database[adb_db_count].result = scan_result;
        adb_database[adb_db_count].data = data;
        adb_db_printEntry(adb_db_count);
        adb_db_count = adb_db_count + 1;
        if(adb_db_count == ADB_MAX_SIZE)
        {
            printf("ADV Table Max Size\n");
            adb_db_count = adb_db_count - 1;
        }
    }
    else
    {
        free(scan_result);
        free(data);
    }
}
</pre>
<h1>Add a Command to Print the Database</h1>
<p>Now we want to add the ability to print from the command line.  So add a new command message to the list of legal commands.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef enum {
    ADB_ADD,
    ADB_PRINT,
} adb_cmd_t;
</pre>
<p>Then create a new function to print.  If you send in a &#8220;-1&#8221; it will print the whole table.  Otherwise just print the individual entry.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">static void adb_printTable(int entry)
{
    if(entry == -1)
    {
        for(int i=0;i&lt;adb_db_count;i++)
        {
            adb_db_printEntry(i);
        }

    }
    else
    {
        adb_db_printEntry(entry);
    }
    

}</pre>
<p>Now edit usercmd.c to have the new command line.  Notice that I use &#8220;sscanf&#8221; which obviously has some issues.  Too bad.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">static int usrcmd_print(int argc, char **argv)
{

    if(argc == 1)
    {
        adb_print(-1); // Print whole table
    }

    if(argc == 2)
    {
        int val;
        sscanf(argv[1],"%d",&amp;val);
        adb_print(val);
    }

    return 0;
}</pre>
<p>When I program the project it immediately prints out a bunch of devices that are at my house.  Then you can see I run the &#8220;print&#8221; command which prints the table.  Finally P do a print 0 to just print the first entry.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/screen-shot-2020-11-08-at-9-34-13-am/" rel="attachment wp-att-10201"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-08-at-9.34.13-AM-1024x782.jpg" alt="" width="1024" height="782" class="alignnone size-large wp-image-10201" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-08-at-9.34.13-AM-1024x782.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-08-at-9.34.13-AM-300x229.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-08-at-9.34.13-AM-768x587.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-08-at-9.34.13-AM-1536x1173.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-08-at-9.34.13-AM-600x458.jpg 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-08-at-9.34.13-AM.jpg 1864w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>In the next article I will add smarter diagnostics to the advertising packets.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AnyCloud Bluetooth Advertising Scanner (Part 4)</title>
		<link>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/</link>
					<comments>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 16 Nov 2020 13:00:10 +0000</pubDate>
				<category><![CDATA[AnyCloud]]></category>
		<category><![CDATA[AnyCloud Advertising Scanner]]></category>
		<category><![CDATA[Bluetooth]]></category>
		<category><![CDATA[CY8CKIT-062-WiFi-BT]]></category>
		<category><![CDATA[CY8CKIT-062S2-43012]]></category>
		<category><![CDATA[CY8CPROTO-062-4343W]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=10185</guid>

					<description><![CDATA[Summary In this article I update the AnyCloud BLE advertising scanner to use the btutil library that was created in the previous post.  In addition, I add a command queue to the bluetoothManger and enable a new command to turn on and off scanning. Story If you have been following along until now, which I [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In this article I update the AnyCloud BLE advertising scanner to use the btutil library that was created in the <a href="https://iotexpert.com/anycloud-bluetooth-utilities-library/" target="_blank" rel="noopener noreferrer">previous post</a>.  In addition, I add a command queue to the bluetoothManger and enable a new command to turn on and off scanning.</p>
<h1>Story</h1>
<p>If you have been following along until now, which I imagine that you have if you are reading this,  you will have gotten a vomit of device data blasting out onto your serial console.  This isn&#8217;t very helpful.  So now what?  I am going to divide this problem into two parts</p>
<ol>
<li>Creating a new user command to turn on and off scanning (this article)</li>
<li>Creating a database to manage the data + a set of commands to dump it (next article)</li>
</ol>
<p>There are</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
<th >Topic</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 1)</a></td>
<td >Introduction to AnyCloud Bluetooth Advertising</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 2)</a></td>
<td >Creating an AnyCloud Bluetooth project</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 3)</a></td>
<td >Adding Observing functionality to the project</td>
</tr>

<tr><td ><a class="row-title" href="https://iotexpert.com/anycloud-bluetooth-utilities-library/" aria-label="“AnyCloud Bluetooth Utilities Library” (Edit)" target="_blank" rel="noopener">AnyCloud Bluetooth Utilities Library</a></td>
<td >A set of APIs for enhancement of the AnyCloud Library</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 4)</a></td>
<td >Adding a command line to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 5)</a></td>
<td >Adding a history database to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 6)</a></td>
<td >Decoding advertising packets</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 7)</a></td>
<td >Adding recording commands to the command line</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/">AnyCloud Bluetooth Advertising Scanner (Part 8)</a></td>
<td >Adding filtering to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/">AnyCloud Bluetooth Advertising Scanner (Part 9)</a></td>
<td >Improve the print and add packet age</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/">AnyCloud Bluetooth Advertising Scanner (Part 10)</a></td>
<td >Sort the database</td>
</tr>
</tbody></table></div></p>
<p>All of the code can be found at git@github.com:iotexpert/AnyCloudBLEScanner.git and https://github.com/iotexpert/AnyCloudBLEScanner.git</p>
<p>There are git tags in place starting at part 5 so that you can look at just that version of the code.  "git tag" to list the tags.  And "git checkout part6" to look at the part 6 version of the code.</p>
<p>You can also create a new project with this is a template if you have the IoT Expert Manifest Files installed</p>
<h1>Add the IoT Expert &#8220;btutil&#8221; Library</h1>
<p>Before we actually start all of the command queue stuff, lets move to the btutil library that I talked about in the previous post.  To do this, add the library using the library manager.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/screen-shot-2020-11-02-at-1-50-08-pm/" rel="attachment wp-att-10187"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-02-at-1.50.08-PM-1024x197.png" alt="" width="1024" height="197" class="alignnone size-large wp-image-10187" srcset="https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-02-at-1.50.08-PM-1024x197.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-02-at-1.50.08-PM-300x58.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-02-at-1.50.08-PM-768x148.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-02-at-1.50.08-PM-600x115.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/Screen-Shot-2020-11-02-at-1.50.08-PM.png 1072w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Then delete bt_platform_cfg_settings.h and <span>bt_platform_cfg_settings.c from your project.  Finally </span>Rebuild and make sure that everything still works.  That is it.</p>
<h1>Multithreading</h1>
<p>Id like to explain that there is now some danger.  That danger comes from the fact that we have multiple tasks which are all accessing data plus functions that are talking to each other ASYNCHRONOUSLY.  Specifically we have:</p>
<ol>
<li>The Bluetooth Stack task &#8211; running the Bluetooth stack and management callback</li>
<li>The Bluetooth Stack APIs &#8211; e.g. wiced_bt_ble_observe</li>
<li>The usrcmd task &#8211; which is interacting with the user on the serial port and talking to the other tasks</li>
<li>A timer_svc task &#8211; which runs software timers</li>
<li>The advertising data (which I will start saving in the next article)</li>
</ol>
<p>When faced with this situation what I typically like to do is provide thread safe public functions for each of the tasks.  Then any other task can call these functions and know that things are not going to get corrupted by a race condition.</p>
<p>To make the design thread safe, I typically like to put an RTOS Queue between the tasks.  These queues are a safe place to send and receive data in a &#8220;thread safe&#8221; way.  There are two basic design patterns that can be used</p>
<ol>
<li>Define a message structure (that gets pushed into the queue) and make it global (via a dot-h).  Define a queue handle and make it global (via a dot-h).  Then let any task build messages and push them into the queue to be received in the task that owns the queue.</li>
<li>Define the message structure and queue.  Then define functions which are global (via a dot-h) which know how to interact with the queue.</li>
</ol>
<p>I typically think that the 2nd method is better, so that is what I am going to do here.</p>
<ol>
<li>In BluetoothManager.h I will provide a function called &#8220;btm_cmdScan&#8221;</li>
<li>The usrcmd task will call the btm_cmdScan function which will</li>
<li>Create a btm_cmdMsg_t with the &#8220;scan&#8221; command and data of true/false</li>
<li>Then push it into the Bluetooth Manager Command Queue</li>
<li>Where a timer callback in the Bluetooth Manager Task will take it out of the queue</li>
<li>Figure out that it is a &#8220;scan&#8221; command</li>
<li>Then will either turn on or off scanning</li>
</ol>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/cmdmsg/" rel="attachment wp-att-10194"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/11/cmdMsg-1024x140.png" alt="" width="1024" height="140" class="alignnone size-large wp-image-10194" srcset="https://iotexpert.com/wp-content/uploads/2020/11/cmdMsg-1024x140.png 1024w, https://iotexpert.com/wp-content/uploads/2020/11/cmdMsg-300x41.png 300w, https://iotexpert.com/wp-content/uploads/2020/11/cmdMsg-768x105.png 768w, https://iotexpert.com/wp-content/uploads/2020/11/cmdMsg-600x82.png 600w, https://iotexpert.com/wp-content/uploads/2020/11/cmdMsg.png 1182w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<h1>Add a Queue to the Bluetooth Manager Thread</h1>
<p>So we need two things a message to push into a queue (just a structure) and we need a queue to push it into.  First the message which is just a structure with two elements.  The first element is a command and the second element is some data of type void.  The meaning of the void *data will be different based on the command.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef struct {
	btm_cmd_t cmd;
	void *data;
} btm_cmdMsg_t;</pre>
<p>But how about the command?  The command is just an enumerate list of commands which will now start with just one command.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef enum {
	BTM_SCAN,
} btm_cmd_t;
</pre>
<p>And know we need to define the queue.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "queue.h"
static QueueHandle_t btm_cmdQueue;</pre>
<p>Before you can use the queue you need to initialize it.  The best place to initialize this queue is in the management callback right after the stack gets going.  You can see that I tell FreeRTOS that there is a queue which can hold up to 10 commands.  I also tell it that each command is the sizeof the command message.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    switch (event)
    {
        case BTM_ENABLED_EVT:
            printf("Started BT Stack Succesfully\n");
            btm_cmdQueue = xQueueCreate(10,sizeof(btm_cmdMsg_t));</pre>
<p>Now we need to create a way for other tasks to create these command messages.  They will do this by calling a function which we will define in the bluetoothManager.h</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void btm_cmdScan(bool enable);
</pre>
<p>This function will live in bluetoothManager.c and it simply</p>
<ol>
<li>Creates a command</li>
<li>Set the actual command to scan</li>
<li>Sets the void* data to be enable &#8230; in other words start or stop scanning.  Remember that a void * can be anything.  See I cast a bool to a void *</li>
<li>Finally push the data into the command queue</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">void btm_cmdScan(bool enable)
{
    btm_cmdMsg_t msg;
    msg.cmd = BTM_SCAN;
    msg.data = (void *)enable;
  	xQueueSend(btm_cmdQueue, &amp;msg,0);
}</pre>
<h1>Add a Timer to Process the Queue</h1>
<p>So now we have a method to push items into the queue.  How do we get them out of the queue?  To do that I will use a Bluetooth Stack timer that will run every 50ms.</p>
<p>First, define the timer in bluetoothManager.c</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "wiced_timer.h"
static wiced_timer_ext_t btm_mgmtQueueTimer;
</pre>
<p>Then define a function which the timer will call.  This function will</p>
<ol>
<li>Try to get a message out of the queue</li>
<li>IF there is a message it will use a big switch to look at the possible messages</li>
<li>If the message is a scan</li>
<li>Then call the wiced function to either start &#8220;observing&#8221; or stop &#8220;observing&#8221;</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static void btm_processBluetoothAppQueue()
{
	btm_cmdMsg_t msg;

	 BaseType_t rval;

	 rval = xQueueReceive( btm_cmdQueue,&amp;msg,0);
	 if(rval == pdTRUE)
	 {
		 switch(msg.cmd)
		 {
		 case BTM_SCAN:
            wiced_bt_ble_observe((wiced_bool_t)msg.data,0,btm_advCallback);
			 break;
		 }
	 }
}</pre>
<p>The last thing you need to do is start the timer.  The best place to start the timer is in the management callback where you need to</p>
<ol>
<li>Create the timer</li>
<li>Tell it to start and run every 50ms</li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    switch (event)
    {
        case BTM_ENABLED_EVT:
            printf("Started BT Stack Succesfully\n");
            btm_cmdQueue = xQueueCreate(10,sizeof(btm_cmdMsg_t));
            wiced_init_timer_ext (&amp;btm_mgmtQueueTimer, btm_processBluetoothAppQueue,0, WICED_TRUE);
            wiced_start_timer_ext (&amp;btm_mgmtQueueTimer, 50);
        break;</pre>
<h1>A Potential Threading Bug</h1>
<p>When I did the implementation originally I created what I thought was a threading bug.  Specifically I used the FreeRTOS timer to process the queue.  In other words instead of using a wiced_timer_ext_t I used a TimerHandle_t.  So what?</p>
<p>The wiced_timer_ext_t is run INSIDE of the BluetoothStack task where the TimerHandle_t is run inside of the Timer_SVC task.</p>
<p>So what?  I was afraid that the call to wiced_bt_ble_obsere was NOT thread safe and needed to be called inside of the same task as the stack.</p>
<p>After some digging I found out that the Bluetooth Stack is threadsafe, so I worried for no reason.  Well, actually, you can never worry enough about making these kinds of threading bugs because they are viscously difficult to debug.</p>
<h1>Add a Scan Off &amp; On Command</h1>
<p>The last thing that you need to do is add an actual command to the usercmd task to call the bluetooth manager function to turn on and off scanning.</p>
<p>First, add a new prototype for your new command in usercmd.c.  Then add it to the list of legal commands.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static int usrcmd_scan(int argc, char **argv);


static const cmd_table_t cmdlist[] = {

.... deleted stuff

    { "scan","scan [on|off]", usrcmd_scan},

};
</pre>
<p>Then create the function to process the command line input and call the btm_scan function.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">static int usrcmd_scan(int argc, char **argv)
{

    if(argc != 2)
        return 0;

    if(strcmp(argv[1],"on") == 0)
    {
        btm_cmdScan(true);
    }
    else if(strcmp(argv[1],"off") == 0)
    {
        btm_cmdScan(false);

    }
    return 0;

}</pre>
<p>Now build it and run it.  You should still get adv packets barfing all over your screen.  But now you can turn on and off the scanning with &#8220;scan on&#8221; and &#8220;scan off&#8221;.  In the next article we will create a database to hold the scan packets.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AnyCloud Bluetooth Advertising Scanner (Part 3)</title>
		<link>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/</link>
					<comments>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 02 Nov 2020 13:00:18 +0000</pubDate>
				<category><![CDATA[AnyCloud]]></category>
		<category><![CDATA[AnyCloud Advertising Scanner]]></category>
		<category><![CDATA[Bluetooth]]></category>
		<category><![CDATA[CY8CKIT-062S2-43012]]></category>
		<category><![CDATA[ModusToolbox]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=10153</guid>

					<description><![CDATA[Summary In this article I discuss BLE &#8220;Observing&#8221; and add that functionality to my PSoC 6 &#8211; CYW43xxx AnyCloud BLE Adverting Scanner project. Story In part1 of this series I discussed the pieces parts required to get the AnyCloud Bluetooth Stack operating using the AnyCloud SDK running on a PSoC 6 with a CY43xxx combo. [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>In this article I discuss BLE &#8220;Observing&#8221; and add that functionality to my PSoC 6 &#8211; CYW43xxx AnyCloud BLE Adverting Scanner project.</p>
<h1>Story</h1>
<p>In <a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/">part1</a> of this series I discussed the pieces parts required to get the AnyCloud Bluetooth Stack operating using the AnyCloud SDK running on a PSoC 6 with a CY43xxx combo.  Then in <a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/">part 2</a> I built a project with those parts and started up the Bluetooth Host stack.  The project didn&#8217;t really do anything, actually nothing, so it wasn&#8217;t very interesting, but it was going.  In this article I will discuss BLE advertising scanning, how to configure it in the AnyCloud project and finally how to add it to the project.</p>
<p><span><p>There are</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
<th >Topic</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 1)</a></td>
<td >Introduction to AnyCloud Bluetooth Advertising</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 2)</a></td>
<td >Creating an AnyCloud Bluetooth project</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 3)</a></td>
<td >Adding Observing functionality to the project</td>
</tr>

<tr><td ><a class="row-title" href="https://iotexpert.com/anycloud-bluetooth-utilities-library/" aria-label="“AnyCloud Bluetooth Utilities Library” (Edit)" target="_blank" rel="noopener">AnyCloud Bluetooth Utilities Library</a></td>
<td >A set of APIs for enhancement of the AnyCloud Library</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 4)</a></td>
<td >Adding a command line to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 5)</a></td>
<td >Adding a history database to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 6)</a></td>
<td >Decoding advertising packets</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 7)</a></td>
<td >Adding recording commands to the command line</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/">AnyCloud Bluetooth Advertising Scanner (Part 8)</a></td>
<td >Adding filtering to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/">AnyCloud Bluetooth Advertising Scanner (Part 9)</a></td>
<td >Improve the print and add packet age</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/">AnyCloud Bluetooth Advertising Scanner (Part 10)</a></td>
<td >Sort the database</td>
</tr>
</tbody></table></div></p>
<p>All of the code can be found at git@github.com:iotexpert/AnyCloudBLEScanner.git and https://github.com/iotexpert/AnyCloudBLEScanner.git</p>
<p>There are git tags in place starting at part 5 so that you can look at just that version of the code.  "git tag" to list the tags.  And "git checkout part6" to look at the part 6 version of the code.</p>
<p>You can also create a new project with this is a template if you have the IoT Expert Manifest Files installed</p></span></p>
<h1>Explain BLE Advertising &#8211; Scanner/Observer</h1>
<p>You might recall that there are four roles that a BLE device can perform</p>
<ul>
<li>Peripheral &#8211; low power devices that broadcast advertisements, then accept a single connection</li>
<li>Central &#8211; devices like cell phones that connect to peripherals.  They may run multiple connections at a time.</li>
<li>Broadcaster &#8211; a nonconnectable peripheral that sends out advertisements</li>
<li>Observer &#8211; A central-like device that listens for broadcasters (or advertising peripherals)</li>
</ul>
<p>And you might remember that advertisements are short, up to 31-byte, packets of data that give information which can be used for one or more of:</p>
<ul>
<li>advertising the availability to connect</li>
<li>advertising services</li>
<li>advertising the name</li>
<li>advertising vendor specific information</li>
<li>advertising beacon data (like temperature or &#8230;)</li>
<li>advertising location</li>
</ul>
<p>And, if you forgot, BLE operates on 40 channels.  But to save power in peripherals, all of the advertising happens on channel 37, 38 and 39.  Specifically a peripheral or broadcaster will send out the advertising data on channel 37, then 38 then 39, then wait&#8230; then do it again.  But why one channel at a time?  Because BLE radio&#8217;s can be tuned to transmit and receive on only one channel at a time (a power saving and complexity reducing feature)</p>
<p>Inside of the Central/Observer it will listen on channel 37 for a &#8220;window&#8221; amount of time.  Then it will do nothing for an interval-window amount of time.  Then it will do that same thing on channel 28 then 39.  But why only one channel at a time?  Same reason as above, it saves power and simplifies the design.  Why not have the window and the interval be the same?  Once again, it saves power.</p>
<p>Here is a picture:</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/screen-shot-2020-10-17-at-9-18-17-am/" rel="attachment wp-att-10113"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-9.18.17-AM.png" alt="" width="726" height="346" class="alignnone size-full wp-image-10113" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-9.18.17-AM.png 726w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-9.18.17-AM-300x143.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-9.18.17-AM-600x286.png 600w" sizes="auto, (max-width: 726px) 100vw, 726px" /></a></p>
<p>But, what happens if you are not listening when the advertiser advertises?  You missed it.  Tough shit.  It turns out that setting the scan window and interval will greatly impact the probability that you hear advertisements.  And, you are more likely to hear advertisements because they are sent on three channels.  But it seems like it will never work.  Will it? &#8230; yes, of course, or they wouldn&#8217;t have done it that way <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<h1>BLE Advertising &#8211; The Advertiser Peripheral or Broadcaster</h1>
<p>So what exactly is inside of an advertising packet?  Volume 6 part B Section 2.3 of the bluetooth core spec describes the advertising protocol data unit (PDU)</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/screen-shot-2020-10-17-at-11-20-29-am/" rel="attachment wp-att-10114"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.20.29-AM.png" alt="" width="1012" height="460" class="alignnone size-full wp-image-10114" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.20.29-AM.png 1012w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.20.29-AM-300x136.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.20.29-AM-768x349.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.20.29-AM-600x273.png 600w" sizes="auto, (max-width: 1012px) 100vw, 1012px" /></a></p>
<p>But what is inside of the header?</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/screen-shot-2020-10-17-at-11-20-37-am/" rel="attachment wp-att-10115"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.20.37-AM.png" alt="" width="1000" height="216" class="alignnone size-large wp-image-10115" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.20.37-AM.png 1000w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.20.37-AM-300x65.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.20.37-AM-768x166.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.20.37-AM-600x130.png 600w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></a></p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/screen-shot-2020-10-17-at-11-20-53-am/" rel="attachment wp-att-10116"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.20.53-AM.png" alt="" width="944" height="292" class="alignnone size-large wp-image-10116" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.20.53-AM.png 944w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.20.53-AM-300x93.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.20.53-AM-768x238.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.20.53-AM-600x186.png 600w" sizes="auto, (max-width: 944px) 100vw, 944px" /></a></p>
<p>This leaves us with what is inside of the &#8220;payload&#8221;.  The answer is that the ADV_IND Payload Data Unit (PDU) contains an address of 6-bytes plus up to 31 bytes of data.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/screen-shot-2020-10-17-at-1-13-00-pm/" rel="attachment wp-att-10125"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-1.13.00-PM.png" alt="" width="430" height="180" class="alignnone size-full wp-image-10125" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-1.13.00-PM.png 430w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-1.13.00-PM-300x126.png 300w" sizes="auto, (max-width: 430px) 100vw, 430px" /></a></p>
<div class="page" title="Page 2873">
<div class="layoutArea">
<div class="column">
<p><span>The AdvA field shall contain the advertiser’s public or random device address as indicated by TxAdd.</span></p>
<p>The actual AdvData field is further broken up into &#8220;AD Structures&#8221; like this:</p>
</div>
</div>
</div>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/screen-shot-2020-10-17-at-11-21-59-am/" rel="attachment wp-att-10117"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.21.59-AM.png" alt="" width="962" height="524" class="alignnone size-large wp-image-10117" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.21.59-AM.png 962w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.21.59-AM-300x163.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.21.59-AM-768x418.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.21.59-AM-600x327.png 600w" sizes="auto, (max-width: 962px) 100vw, 962px" /></a></p>
<p>And what is the &#8220;AD Type&#8221;, well it is a one byte of one of the following:</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/screen-shot-2020-10-17-at-11-22-21-am/" rel="attachment wp-att-10118"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.22.21-AM.png" alt="" width="962" height="112" class="alignnone size-large wp-image-10118" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.22.21-AM.png 962w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.22.21-AM-300x35.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.22.21-AM-768x89.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.22.21-AM-600x70.png 600w" sizes="auto, (max-width: 962px) 100vw, 962px" /></a> <a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/screen-shot-2020-10-17-at-11-24-26-am/" rel="attachment wp-att-10119"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.24.26-AM.png" alt="" width="982" height="1002" class="alignnone size-large wp-image-10119" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.24.26-AM.png 982w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.24.26-AM-294x300.png 294w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.24.26-AM-768x784.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.24.26-AM-600x612.png 600w" sizes="auto, (max-width: 982px) 100vw, 982px" /></a></p>
<p>And then where do you find the assigned numbers for the field types?  In the &#8220;<a href="https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile/" target="_blank" rel="noopener noreferrer">Assigned Numbers and GAP</a>&#8220;.  Here is a clip from the spec.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/screen-shot-2020-10-17-at-11-26-02-am/" rel="attachment wp-att-10120"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.26.02-AM-1024x755.png" alt="" width="1024" height="755" class="alignnone size-large wp-image-10120" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.26.02-AM-1024x755.png 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.26.02-AM-300x221.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.26.02-AM-768x566.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.26.02-AM-1536x1132.png 1536w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.26.02-AM-600x442.png 600w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.26.02-AM.png 1910w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/screen-shot-2020-10-17-at-11-26-15-am/" rel="attachment wp-att-10121"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.26.15-AM-1024x150.png" alt="" width="1024" height="150" class="alignnone size-large wp-image-10121" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.26.15-AM-1024x150.png 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.26.15-AM-300x44.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.26.15-AM-768x112.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.26.15-AM-1536x224.png 1536w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.26.15-AM-600x88.png 600w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-17-at-11.26.15-AM.png 1916w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>And conveniently enough we enumerated them for you inside of the SDK header file wiced_bt_ble.h</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">/** Advertisement data types */
enum wiced_bt_ble_advert_type_e {
    BTM_BLE_ADVERT_TYPE_FLAG                        = 0x01,                 /**&lt; Advertisement flags */
    BTM_BLE_ADVERT_TYPE_16SRV_PARTIAL               = 0x02,                 /**&lt; List of supported services - 16 bit UUIDs (partial) */
    BTM_BLE_ADVERT_TYPE_16SRV_COMPLETE              = 0x03,                 /**&lt; List of supported services - 16 bit UUIDs (complete) */
    BTM_BLE_ADVERT_TYPE_32SRV_PARTIAL               = 0x04,                 /**&lt; List of supported services - 32 bit UUIDs (partial) */
    BTM_BLE_ADVERT_TYPE_32SRV_COMPLETE              = 0x05,                 /**&lt; List of supported services - 32 bit UUIDs (complete) */
    BTM_BLE_ADVERT_TYPE_128SRV_PARTIAL              = 0x06,                 /**&lt; List of supported services - 128 bit UUIDs (partial) */
    BTM_BLE_ADVERT_TYPE_128SRV_COMPLETE             = 0x07,                 /**&lt; List of supported services - 128 bit UUIDs (complete) */
    BTM_BLE_ADVERT_TYPE_NAME_SHORT                  = 0x08,                 /**&lt; Short name */
    BTM_BLE_ADVERT_TYPE_NAME_COMPLETE               = 0x09,                 /**&lt; Complete name */
    BTM_BLE_ADVERT_TYPE_TX_POWER                    = 0x0A,                 /**&lt; TX Power level  */
    BTM_BLE_ADVERT_TYPE_DEV_CLASS                   = 0x0D,                 /**&lt; Device Class */
    BTM_BLE_ADVERT_TYPE_SIMPLE_PAIRING_HASH_C       = 0x0E,                 /**&lt; Simple Pairing Hash C */
    BTM_BLE_ADVERT_TYPE_SIMPLE_PAIRING_RAND_C       = 0x0F,                 /**&lt; Simple Pairing Randomizer R */
    BTM_BLE_ADVERT_TYPE_SM_TK                       = 0x10,                 /**&lt; Security manager TK value */
    BTM_BLE_ADVERT_TYPE_SM_OOB_FLAG                 = 0x11,                 /**&lt; Security manager Out-of-Band data */
    BTM_BLE_ADVERT_TYPE_INTERVAL_RANGE              = 0x12,                 /**&lt; Slave connection interval range */
    BTM_BLE_ADVERT_TYPE_SOLICITATION_SRV_UUID       = 0x14,                 /**&lt; List of solicitated services - 16 bit UUIDs */
    BTM_BLE_ADVERT_TYPE_128SOLICITATION_SRV_UUID    = 0x15,                 /**&lt; List of solicitated services - 128 bit UUIDs */
    BTM_BLE_ADVERT_TYPE_SERVICE_DATA                = 0x16,                 /**&lt; Service data - 16 bit UUID */
    BTM_BLE_ADVERT_TYPE_PUBLIC_TARGET               = 0x17,                 /**&lt; Public target address */
    BTM_BLE_ADVERT_TYPE_RANDOM_TARGET               = 0x18,                 /**&lt; Random target address */
    BTM_BLE_ADVERT_TYPE_APPEARANCE                  = 0x19,                 /**&lt; Appearance */
    BTM_BLE_ADVERT_TYPE_ADVERT_INTERVAL             = 0x1a,                 /**&lt; Advertising interval */
    BTM_BLE_ADVERT_TYPE_LE_BD_ADDR                  = 0x1b,                 /**&lt; LE device bluetooth address */
    BTM_BLE_ADVERT_TYPE_LE_ROLE                     = 0x1c,                 /**&lt; LE role */
    BTM_BLE_ADVERT_TYPE_256SIMPLE_PAIRING_HASH      = 0x1d,                 /**&lt; Simple Pairing Hash C-256 */
    BTM_BLE_ADVERT_TYPE_256SIMPLE_PAIRING_RAND      = 0x1e,                 /**&lt; Simple Pairing Randomizer R-256 */
    BTM_BLE_ADVERT_TYPE_32SOLICITATION_SRV_UUID     = 0x1f,                 /**&lt; List of solicitated services - 32 bit UUIDs */
    BTM_BLE_ADVERT_TYPE_32SERVICE_DATA              = 0x20,                 /**&lt; Service data - 32 bit UUID */
    BTM_BLE_ADVERT_TYPE_128SERVICE_DATA             = 0x21,                 /**&lt; Service data - 128 bit UUID */
    BTM_BLE_ADVERT_TYPE_CONN_CONFIRM_VAL            = 0x22,                 /**&lt; LE Secure Connections Confirmation Value */
    BTM_BLE_ADVERT_TYPE_CONN_RAND_VAL               = 0x23,                 /**&lt; LE Secure Connections Random Value */
    BTM_BLE_ADVERT_TYPE_URI                         = 0x24,                 /**&lt; URI */
    BTM_BLE_ADVERT_TYPE_INDOOR_POS                  = 0x25,                 /**&lt; Indoor Positioning */
    BTM_BLE_ADVERT_TYPE_TRANS_DISCOVER_DATA         = 0x26,                 /**&lt; Transport Discovery Data */
    BTM_BLE_ADVERT_TYPE_SUPPORTED_FEATURES          = 0x27,                 /**&lt; LE Supported Features */
    BTM_BLE_ADVERT_TYPE_UPDATE_CH_MAP_IND           = 0x28,                 /**&lt; Channel Map Update Indication */
    BTM_BLE_ADVERT_TYPE_PB_ADV                      = 0x29,                 /**&lt; PB-ADV */
    BTM_BLE_ADVERT_TYPE_MESH_MSG                    = 0x2A,                 /**&lt; Mesh Message */
    BTM_BLE_ADVERT_TYPE_MESH_BEACON                 = 0x2B,                 /**&lt; Mesh Beacon */
    BTM_BLE_ADVERT_TYPE_PSRI                        = 0x2E,                 /**&lt; Generic Audio Provate Set Random Identifier */
    BTM_BLE_ADVERT_TYPE_3D_INFO_DATA                = 0x3D,                 /**&lt; 3D Information Data */
    BTM_BLE_ADVERT_TYPE_MANUFACTURER                = 0xFF                  /**&lt; Manufacturer data */
};
</pre>
<h1>How does scanning work in the AnyCloud Bluetooth Stack?</h1>
<p>To turn on observing/scanning you need to call the function:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">wiced_bt_dev_status_t wiced_bt_ble_observe (wiced_bool_t start, uint8_t duration, wiced_bt_ble_scan_result_cback_t *p_scan_result_cback);
</pre>
<p>Which will cause the host stack to tell the controller to start scanning for advertising packets.  It will set the scan window and scan interval the low duty scan settings from the bluetooth configuration structure&#8230; which we setup with the Bluetooth configurator.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" "> .low_duty_scan_interval          = CY_BT_LOW_DUTY_SCAN_INTERVAL,                              /**&lt; Low duty scan interval */
        .low_duty_scan_window            = CY_BT_LOW_DUTY_SCAN_WINDOW,                                /**&lt; Low duty scan window */
        .low_duty_scan_duration          = CY_BT_LOW_DUTY_SCAN_DURATION,                              /**&lt; Low duty scan duration in seconds (0 for infinite) */
</pre>
<p>When the controller hears an advertising packet, it will send the HCI advertising report to the Bluetooth host stack, which with then call you back.  Specifically it will call you back by calling the p_scan_result_cback&#8221; function.</p>
<p>You provide the callback function which has the prototype:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">typedef void (wiced_bt_ble_scan_result_cback_t) (wiced_bt_ble_scan_results_t *p_scan_result, uint8_t *p_adv_data);
</pre>
<p>which contains two parameters, p_scan_result which is a structure that has the mac address and some thing data plus the p_adv_data which has the raw bytes of the advertising packet.</p>
<h1>Add Observing to our Project</h1>
<p>OK.  Lets add this to our project by creating a callback function like this:</p>
<p>Lines 5-9: Just prints out the raw bytes of the MAC address of the remote device, the one advertising</p>
<p>To print out the raw advertising data you need to remember that it is formatted as</p>
<ol>
<li>A length (of all of the data of the field)</li>
<li>A type</li>
<li>The rest of the data</li>
</ol>
<p>When you find a field of length of 0 you know that you have reached the end of the data</p>
<p>On Lines 13-20: I print out one field at a time and the raw data</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">//
void obv_callback(wiced_bt_ble_scan_results_t *p_scan_result, uint8_t *p_adv_data)
{
    // Print the MAC Address
    printf("MAC: ");
    for(int i=0;i&lt;6;i++)
    {
        printf("%02X:",p_scan_result-&gt;remote_bd_addr[i]);
    }
    // Print the RAW Data of the ADV Packet
    printf(" Data: ");
    int i=0;
    while(p_adv_data[i])
    {
        for(int j=0;j&lt;p_adv_data[i];j++)
        {
            printf("%02X ",p_adv_data[i+1+j]);
        }
        i = i + p_adv_data[i]+1;
    }
    printf("\n");
    
}</pre>
<p>Then update the management callback to start the scanner after the stack is successfully started</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">    switch (event)
    {
        case BTM_ENABLED_EVT:

            if (WICED_BT_SUCCESS == p_event_data-&gt;enabled.status)
            {
                printf("Started BT Stack Succesfully\n");
                wiced_bt_ble_observe(WICED_TRUE,0,obv_callback);

            }</pre>
<h1>Program and Test</h1>
<p>Now when I run the program data comes blasting out of the screen because there are a boatload of ble devices in my house</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">AnyCloud&gt; Unhandled Bluetooth Management Event: 0x16
Started BT Stack Succesfully
MAC: 76:99:58:E8:8B:1F:Data: 01 1A 0A 0C FF 4C 00 10 06 13 1A 54 F7 5A 7A 
MAC: 9E:7B:EF:0B:74:20:Data: 01 06 16 F7 FD 01 0C C2 81 CE 0C 74 58 77 19 C8 E3 84 A3 42 50 98 00 00 00 00 03 
MAC: 6F:11:7C:FF:02:13:Data: 01 1A 0A 05 FF 4C 00 10 06 03 1E BA 24 58 3D 
MAC: 3F:64:BE:4E:29:0C:Data: 01 04 FF 00 4C 02 15 26 86 F3 9C BA DA 46 58 85 4A A6 2E 7E 5E 8B 8D 00 01 00 00 C9 
MAC: 47:4B:F1:53:2C:84:Data: 01 06 FF 4C 00 10 05 08 18 79 1E C2 
MAC: C8:69:CD:18:BC:E6:Data: 01 1A 0A 0C FF 4C 00 10 05 0C 14 17 BF E9 
MAC: 27:F6:6F:1E:7A:78:Data: 01 1A FF 4C 00 09 06 03 12 C0 A8 20 0D 
MAC: 6F:AE:84:F6:6A:9F:Data: 01 06 FF 4C 00 10 05 08 18 79 1E C2 
MAC: 3F:64:BE:4E:29:0C:Data: 01 04 FF 00 4C 02 15 26 86 F3 9C BA DA 46 58 85 4A A6 2E 7E 5E 8B 8D 00 01 00 00 C9 
MAC: 41:EE:B4:9C:5C:5F:Data: 01 1A 0A 07 FF 4C 00 10 06 33 1A 49 59 46 B4 
MAC: 9E:7B:EF:0B:74:20:Data: 01 06 16 F7 FD 01 0C C2 81 CE 0C 74 58 77 19 C8 E3 84 A3 42 50 98 00 00 00 00 03 
MAC: C8:EB:ED:C8:AC:1C:Data: 01 0A 03 66 66 19 D0 07 FF EE 03 1C AC C8 ED EB C8 
MAC: 76:99:58:E8:8B:1F:Data: 01 1A 0A 0C FF 4C 00 10 06 13 1A 54 F7 5A 7A</pre>
<p>In the next article Ill add some more smarts to manage the data to be easier to look at.</p>
<p>For your information here is all of the file bluetoothManager.c</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

#include "cybsp.h"

#include "FreeRTOS.h"

#include "bluetoothManager.h"
#include "wiced_bt_stack.h"
#include "wiced_bt_dev.h"
#include "wiced_bt_trace.h"

//
void obv_callback(wiced_bt_ble_scan_results_t *p_scan_result, uint8_t *p_adv_data)
{
    // Print the MAC Address
    printf("MAC: ");
    for(int i=0;i&lt;6;i++)
    {
        printf("%02X:",p_scan_result-&gt;remote_bd_addr[i]);
    }
    // Print the RAW Data of the ADV Packet
    printf(" Data: ");
    int i=0;
    while(p_adv_data[i])
    {
        for(int j=0;j&lt;p_adv_data[i];j++)
        {
            printf("%02X ",p_adv_data[i+1+j]);
        }
        i = i + p_adv_data[i]+1;
    }
    printf("\n");
    
}

/**************************************************************************************************
* Function Name: app_bt_management_callback()
***************************************************************************************************
* Summary:
*   This is a Bluetooth stack event handler function to receive management events from
*   the BLE stack and process as per the application.
*
* Parameters:
*   wiced_bt_management_evt_t event             : BLE event code of one byte length
*   wiced_bt_management_evt_data_t *p_event_data: Pointer to BLE management event structures
*
* Return:
*  wiced_result_t: Error code from WICED_RESULT_LIST or BT_RESULT_LIST
*
*************************************************************************************************/
wiced_result_t app_bt_management_callback(wiced_bt_management_evt_t event, wiced_bt_management_evt_data_t *p_event_data)
{
    wiced_result_t result = WICED_BT_SUCCESS;

    switch (event)
    {
        case BTM_ENABLED_EVT:

            if (WICED_BT_SUCCESS == p_event_data-&gt;enabled.status)
            {
                printf("Started BT Stack Succesfully\n");
                wiced_bt_ble_observe(WICED_TRUE,0,obv_callback);

            }
            else
            {
            	printf("Error enabling BTM_ENABLED_EVENT\n");
            }

            break;

        default:
            printf("Unhandled Bluetooth Management Event: 0x%x\n", event);
            break;
    }

    return result;
}
</pre>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AnyCloud Bluetooth Advertising Scanner (Part 2)</title>
		<link>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/</link>
					<comments>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/#respond</comments>
		
		<dc:creator><![CDATA[Alan Hawse]]></dc:creator>
		<pubDate>Mon, 26 Oct 2020 11:06:12 +0000</pubDate>
				<category><![CDATA[AnyCloud Advertising Scanner]]></category>
		<category><![CDATA[Bluetooth]]></category>
		<category><![CDATA[CY8CKIT-062-WiFi-BT]]></category>
		<category><![CDATA[CY8CKIT-062S2-43012]]></category>
		<category><![CDATA[ModusToolbox]]></category>
		<guid isPermaLink="false">https://iotexpert.com/?p=10131</guid>

					<description><![CDATA[Summary The second article in a series discussing the creation of a PSoC 6 + CYW43xxx Advertising Scanner using the AnyCloud SDK.  This article will use the learning from Part 1 to create a template project that starts the BLE stack. Story In the previous article I discussed the structure of the Cypress/Infineon Bluetooth Stack [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Summary</h1>
<p>The second article in a series discussing the creation of a PSoC 6 + CYW43xxx Advertising Scanner using the AnyCloud SDK.  This article will use the learning from <a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/">Part 1</a> to create a template project that starts the BLE stack.</p>
<h1>Story</h1>
<p>In the <a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/">previous article</a> I discussed the structure of the Cypress/Infineon Bluetooth Stack and its integration into AnyCloud.  A bunch of &#8220;theory&#8221;, well I say BS to that.  Let&#8217;s build something.</p>
<p>There are</p>
<p><div class="table-responsive"><table  style="width:95%; "  class="easy-table easy-table-default " border="1">
<thead>
<tr><th >Article</th>
<th >Topic</th>
</tr>
</thead>
<tbody>
<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 1)</a></td>
<td >Introduction to AnyCloud Bluetooth Advertising</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 2)</a></td>
<td >Creating an AnyCloud Bluetooth project</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-3/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 3)</a></td>
<td >Adding Observing functionality to the project</td>
</tr>

<tr><td ><a class="row-title" href="https://iotexpert.com/anycloud-bluetooth-utilities-library/" aria-label="“AnyCloud Bluetooth Utilities Library” (Edit)" target="_blank" rel="noopener">AnyCloud Bluetooth Utilities Library</a></td>
<td >A set of APIs for enhancement of the AnyCloud Library</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-4/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 4)</a></td>
<td >Adding a command line to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-5/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 5)</a></td>
<td >Adding a history database to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-6/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 6)</a></td>
<td >Decoding advertising packets</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-7/" target="_blank" rel="noopener">AnyCloud Bluetooth Advertising Scanner (Part 7)</a></td>
<td >Adding recording commands to the command line</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-8/">AnyCloud Bluetooth Advertising Scanner (Part 8)</a></td>
<td >Adding filtering to the scanner</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-9/">AnyCloud Bluetooth Advertising Scanner (Part 9)</a></td>
<td >Improve the print and add packet age</td>
</tr>

<tr><td ><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-10/">AnyCloud Bluetooth Advertising Scanner (Part 10)</a></td>
<td >Sort the database</td>
</tr>
</tbody></table></div></p>
<p>All of the code can be found at git@github.com:iotexpert/AnyCloudBLEScanner.git and https://github.com/iotexpert/AnyCloudBLEScanner.git</p>
<p>There are git tags in place starting at part 5 so that you can look at just that version of the code.  "git tag" to list the tags.  And "git checkout part6" to look at the part 6 version of the code.</p>
<p>You can also create a new project with this is a template if you have the IoT Expert Manifest Files installed</p>
<p>Recall from <a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-1/">Part 1</a> that you need three things to startup the Bluetooth Stack</p>
<ul>
<li>The Hardware Configuration Structure that matches : cybt_platform_config_t</li>
<li>The Bluetooth Stack Configuration Structure that matches : wiced_bt_cfg_settings_t</li>
<li>The Bluetooth Management Callback that matches : typedef wiced_result_t (wiced_bt_management_cback_t) (wiced_bt_management_evt_t event, wiced_bt_management_evt_data_t *p_event_data);</li>
</ul>
<p>Then you need to call</p>
<ul>
<li>The hardware initialization function : cybt_platform_config_init</li>
<li>The stack initialization function : wiced_bt_stack_init</li>
</ul>
<p>Ok let&#8217;s do this!</p>
<h1>Basic Project</h1>
<p>You can do all of these steps from the Eclipse IDE for ModusToolbox.  Or you can do it from the individual programs and the command line.  I like Visual Studio code, so this article will be done completely from the command line and individual configurators.</p>
<p>Run the new project creator from the start menu.  Start by creating a project for the development kit that you have, in my case the one currently plugged into my computer is the CY8CKIT-062S2-43012, so that is what I pick.  But, this project will work with any of the WiFI/BT combo chips attached to PSoC 6.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/screen-shot-2020-10-25-at-8-18-19-am/" rel="attachment wp-att-10143"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.18.19-AM-1024x613.jpg" alt="" width="1024" height="613" class="alignnone size-large wp-image-10143" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.18.19-AM-1024x613.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.18.19-AM-300x179.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.18.19-AM-768x459.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.18.19-AM-1536x919.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.18.19-AM-2048x1225.jpg 2048w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.18.19-AM-600x359.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>In previous articles I discussed the template that I use to get things going with FreeRTOS.  I won&#8217;t discuss that here, but I want FreeRTOS and the NTShell, so pick the IoT Expert FreeRTOS NTShell Template.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/screen-shot-2020-10-25-at-8-19-14-am/" rel="attachment wp-att-10144"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.19.14-AM-1024x612.jpg" alt="" width="1024" height="612" class="alignnone size-large wp-image-10144" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.19.14-AM-1024x612.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.19.14-AM-300x179.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.19.14-AM-768x459.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.19.14-AM-1536x918.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.19.14-AM-2048x1223.jpg 2048w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.19.14-AM-600x358.jpg 600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>After about a minute you should have a project.  I always like to build the project to make sure that everything is working before I get too far down the road of modifying anything.  Run &#8220;make -j build&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">arh (master) AnyCloudBLEScanner $ make -j build
Tools Directory: /Applications/ModusToolbox/tools_2.2
CY8CKIT-062S2-43012.mk: ../mtb_shared/TARGET_CY8CKIT-062S2-43012/latest-v2.X/CY8CKIT-062S2-43012.mk

Prebuild operations complete
Commencing build operations...

Tools Directory: /Applications/ModusToolbox/tools_2.2
CY8CKIT-062S2-43012.mk: ../mtb_shared/TARGET_CY8CKIT-062S2-43012/latest-v2.X/CY8CKIT-062S2-43012.mk

Initializing build: MTBShellTemplate Debug CY8CKIT-062S2-43012 GCC_ARM

Auto-discovery in progress...
-&gt; Found 205 .c file(s)
-&gt; Found 46 .S file(s)
-&gt; Found 23 .s file(s)
-&gt; Found 0 .cpp file(s)
-&gt; Found 0 .o file(s)
-&gt; Found 6 .a file(s)
-&gt; Found 503 .h file(s)
-&gt; Found 0 .hpp file(s)
-&gt; Found 0 resource file(s)
Applying filters...
Auto-discovery complete

Constructing build rules...
Build rules construction complete

==============================================================================
= Building application =
==============================================================================
Generating compilation database file...
-&gt; ./build/compile_commands.json
Compilation database file generation complete
Building 193 file(s)
    Compiling app file lowPower.c
    Compiling app file main.c
    Compiling app file usrcmd.c
    Compiling ext file startup_psoc6_02_cm4.S

..... a bunch of lines deleted

    Compiling ext file psoc6_01_cm0p_sleep.c
    Compiling ext file psoc6_02_cm0p_sleep.c
    Compiling ext file psoc6_03_cm0p_sleep.c
    Compiling ext file psoc6_04_cm0p_sleep.c
    Compiling ext file cy_retarget_io.c
    Linking output file MTBShellTemplate.elf
==============================================================================
= Build complete =
==============================================================================

Calculating memory consumption: CY8C624ABZI-S2D44 GCC_ARM -Og

   ---------------------------------------------------- 
  | Section Name         |  Address      |  Size       | 
   ---------------------------------------------------- 
  | .cy_m0p_image        |  0x10000000   |  6044       | 
  | .text                |  0x10002000   |  54876      | 
  | .ARM.exidx           |  0x1000f65c   |  8          | 
  | .copy.table          |  0x1000f664   |  24         | 
  | .zero.table          |  0x1000f67c   |  8          | 
  | .data                |  0x080022e0   |  1688       | 
  | .cy_sharedmem        |  0x08002978   |  8          | 
  | .noinit              |  0x08002980   |  148        | 
  | .bss                 |  0x08002a14   |  2136       | 
  | .heap                |  0x08003270   |  1029520    | 
   ---------------------------------------------------- 

  Total Internal Flash (Available)          2097152    
  Total Internal Flash (Utilized)           64812      

  Total Internal SRAM (Available)           1046528    
  Total Internal SRAM (Utilized with heap)  1033500    

</pre>
<p>Then to be sure it is working, program the development kit.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c" ">arh (master) AnyCloudBLEScanner $ make program
Tools Directory: /Applications/ModusToolbox/tools_2.2
CY8CKIT-062S2-43012.mk: ../mtb_shared/TARGET_CY8CKIT-062S2-43012/latest-v2.X/CY8CKIT-062S2-43012.mk

Prebuild operations complete
Commencing build operations...

Tools Directory: /Applications/ModusToolbox/tools_2.2
CY8CKIT-062S2-43012.mk: ../mtb_shared/TARGET_CY8CKIT-062S2-43012/latest-v2.X/CY8CKIT-062S2-43012.mk

Initializing build: MTBShellTemplate Debug CY8CKIT-062S2-43012 GCC_ARM

Auto-discovery in progress...
-&gt; Found 205 .c file(s)
-&gt; Found 46 .S file(s)
-&gt; Found 23 .s file(s)
-&gt; Found 0 .cpp file(s)
-&gt; Found 0 .o file(s)
-&gt; Found 6 .a file(s)
-&gt; Found 503 .h file(s)
-&gt; Found 0 .hpp file(s)
-&gt; Found 0 resource file(s)
Applying filters...
Auto-discovery complete

Constructing build rules...
Build rules construction complete

==============================================================================
= Building application =
==============================================================================
Generating compilation database file...
-&gt; ./build/compile_commands.json
Compilation database file generation complete
Building 193 file(s)
==============================================================================
= Build complete =
==============================================================================

Calculating memory consumption: CY8C624ABZI-S2D44 GCC_ARM -Og

   ---------------------------------------------------- 
  | Section Name         |  Address      |  Size       | 
   ---------------------------------------------------- 
  | .cy_m0p_image        |  0x10000000   |  6044       | 
  | .text                |  0x10002000   |  54876      | 
  | .ARM.exidx           |  0x1000f65c   |  8          | 
  | .copy.table          |  0x1000f664   |  24         | 
  | .zero.table          |  0x1000f67c   |  8          | 
  | .data                |  0x080022e0   |  1688       | 
  | .cy_sharedmem        |  0x08002978   |  8          | 
  | .noinit              |  0x08002980   |  148        | 
  | .bss                 |  0x08002a14   |  2136       | 
  | .heap                |  0x08003270   |  1029520    | 
   ---------------------------------------------------- 

  Total Internal Flash (Available)          2097152    
  Total Internal Flash (Utilized)           64812      

  Total Internal SRAM (Available)           1046528    
  Total Internal SRAM (Utilized with heap)  1033500    


Programming target device... 
Open On-Chip Debugger 0.10.0+dev-4.1.0.1058 (2020-08-11-03:45)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select &lt;transport&gt;'.
adapter speed: 2000 kHz
adapter srst delay: 25
adapter srst pulse_width: 25
** Auto-acquire enabled, use "set ENABLE_ACQUIRE 0" to disable
cortex_m reset_config sysresetreq
cortex_m reset_config sysresetreq
Info : Using CMSIS loader 'CY8C6xxA_SMIF' for bank 'psoc6_smif0_cm0' (footprint 14672 bytes)
Warn : SFlash programming allowed for regions: USER, TOC, KEY
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: FW Version = 2.0.0
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : KitProg3: FW version: 1.14.514
Info : KitProg3: Pipelined transfers disabled, please update the firmware
Info : VTarget = 3.215 V
Info : kitprog3: acquiring the device...
Info : clock speed 2000 kHz
Info : SWD DPIDR 0x6ba02477
Info : psoc6.cpu.cm0: hardware has 4 breakpoints, 2 watchpoints
***************************************
** Silicon: 0xE453, Family: 0x102, Rev.: 0x12 (A1)
** Detected Device: CY8C624ABZI-S2D44
** Detected Main Flash size, kb: 2048
** Flash Boot version: 3.1.0.378
** Chip Protection: NORMAL
***************************************
Info : psoc6.cpu.cm4: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for psoc6.cpu.cm0 on 3333
Info : Listening on port 3333 for gdb connections
Info : starting gdb server for psoc6.cpu.cm4 on 3334
Info : Listening on port 3334 for gdb connections
Info : SWD DPIDR 0x6ba02477
Info : kitprog3: acquiring the device...
psoc6.cpu.cm0 halted due to debug-request, current mode: Thread 
xPSR: 0x41000000 pc: 0x00000190 msp: 0x080ff800
** Device acquired successfully
** psoc6.cpu.cm4: Ran after reset and before halt...
psoc6.cpu.cm4 halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x0000012a msp: 0x080ff800
** Programming Started **
auto erase enabled
Info : Flash write discontinued at 0x1000179c, next section at 0x10002000
Info : Padding image section 0 at 0x1000179c with 100 bytes (bank write end alignment)
[100%] [################################] [ Erasing     ]
[100%] [################################] [ Programming ]
Info : Padding image section 1 at 0x1000fd24 with 220 bytes (bank write end alignment)
[100%] [################################] [ Erasing     ]
[100%] [################################] [ Programming ]
wrote 62976 bytes from file /Users/arh/mtw/AnyCloudBLEScanner/build/CY8CKIT-062S2-43012/Debug/MTBShellTemplate.hex in 2.069358s (29.719 KiB/s)
** Programming Finished **
** Verify Started **
verified 62656 bytes in 0.122208s (500.683 KiB/s)
** Verified OK **
** Resetting Target **
Info : SWD DPIDR 0x6ba02477
shutdown command invoked
Info : psoc6.dap: powering down debug domain...
  
arh (master) AnyCloudBLEScanner $</pre>
<p>When that is done, open up a terminal window and you should have a functioning base project.  Notice that I ran &#8220;help&#8221; and &#8220;tasks&#8221; from the command shell.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/screen-shot-2020-10-25-at-8-22-34-am/" rel="attachment wp-att-10145"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.22.34-AM-1024x700.png" alt="" width="1024" height="700" class="alignnone size-large wp-image-10145" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.22.34-AM-1024x700.png 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.22.34-AM-300x205.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.22.34-AM-768x525.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.22.34-AM-600x410.png 600w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.22.34-AM.png 1214w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Now that we have a basic project working, add the Bluetooth libraries.  Run the library manager by typing &#8220;make modlibs&#8221;.  Then select &#8220;bluetooth-freertos&#8221; and the library manager will automatically select the other libraries you need.  Press Update then Close.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/screen-shot-2020-10-25-at-8-27-00-am/" rel="attachment wp-att-10146"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.27.00-AM-1024x799.jpg" alt="" width="1024" height="799" class="alignnone size-large wp-image-10146" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.27.00-AM-1024x799.jpg 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.27.00-AM-300x234.jpg 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.27.00-AM-768x599.jpg 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.27.00-AM-1536x1199.jpg 1536w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.27.00-AM-600x468.jpg 600w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.27.00-AM.jpg 1668w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Next, run the bluetooth configurator by running &#8220;make config_bt&#8221;  This tool will help you make the bluetooth stack configuration structure.  When the configurator starts, press &#8220;New&#8221;</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/screen-shot-2020-10-25-at-8-34-00-am/" rel="attachment wp-att-10147"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.34.00-AM-1024x792.png" alt="" width="1024" height="792" class="alignnone size-large wp-image-10147" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.34.00-AM-1024x792.png 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.34.00-AM-300x232.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.34.00-AM-768x594.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.34.00-AM-1536x1187.png 1536w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.34.00-AM-600x464.png 600w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.34.00-AM.png 1568w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Then select our device (the PSoC 6 and the Combo chip)</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/screen-shot-2020-10-25-at-8-34-13-am/" rel="attachment wp-att-10148"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.34.13-AM.png" alt="" width="796" height="242" class="alignnone size-large wp-image-10148" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.34.13-AM.png 796w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.34.13-AM-300x91.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.34.13-AM-768x233.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.34.13-AM-600x182.png 600w" sizes="auto, (max-width: 796px) 100vw, 796px" /></a></p>
<p>Click on the &#8220;GAP Settings&#8221;.  Then press the Plus and add &#8220;Observer configuration&#8221;</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/screen-shot-2020-10-25-at-8-34-41-am/" rel="attachment wp-att-10149"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.34.41-AM.png" alt="" width="874" height="472" class="alignnone size-large wp-image-10149" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.34.41-AM.png 874w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.34.41-AM-300x162.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.34.41-AM-768x415.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.34.41-AM-600x324.png 600w" sizes="auto, (max-width: 874px) 100vw, 874px" /></a></p>
<p>Then setup the scan settings (more detail on these numbers in the next article)</p>
<ul>
<li>Low duty scan window (ms) = 60</li>
<li>Low duty scan interval (ms) = 60</li>
<li>Low duty scan timeout = deselected (meaning no timeout)</li>
</ul>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/screen-shot-2020-10-25-at-8-37-48-am/" rel="attachment wp-att-10150"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.37.48-AM-1024x931.png" alt="" width="1024" height="931" class="alignnone size-large wp-image-10150" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.37.48-AM-1024x931.png 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.37.48-AM-300x273.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.37.48-AM-768x698.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.37.48-AM-1536x1397.png 1536w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.37.48-AM-600x546.png 600w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.37.48-AM.png 1630w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Then save your configuration file.  Notice that I called it &#8220;btconfig&#8221;</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/screen-shot-2020-10-25-at-8-38-23-am/" rel="attachment wp-att-10151"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.38.23-AM.png" alt="" width="908" height="436" class="alignnone size-large wp-image-10151" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.38.23-AM.png 908w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.38.23-AM-300x144.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.38.23-AM-768x369.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.38.23-AM-600x288.png 600w" sizes="auto, (max-width: 908px) 100vw, 908px" /></a></p>
<p>When you are done you will have a directory called &#8220;GeneratedSource&#8221; inside of your project with the needed files.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/screen-shot-2020-10-25-at-8-38-57-am/" rel="attachment wp-att-10152"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.38.57-AM-1024x197.png" alt="" width="1024" height="197" class="alignnone size-large wp-image-10152" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.38.57-AM-1024x197.png 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.38.57-AM-300x58.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.38.57-AM-768x148.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.38.57-AM-600x116.png 600w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-8.38.57-AM.png 1266w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>The next step is to fix up the Makefile.  I like changing the name of the &#8220;App&#8221;.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c"># Name of application (used to derive name of final linked file).
APPNAME=AnyCloudBLEScanner</pre>
<p>Then you need the &#8220;FREERTOS WICED_BLE&#8221; components.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c"># Enable optional code that is ordinarily disabled by default.
#
# Available components depend on the specific targeted hardware and firmware
# in use. In general, if you have
#
#    COMPONENTS=foo bar
#
# ... then code in directories named COMPONENT_foo and COMPONENT_bar will be
# added to the build
#
COMPONENTS=FREERTOS WICED_BLE</pre>
<p>If you run make vscode it will update the workspace with all of the stuff needed for Visual Studio Code to be able to find all of the files.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">arh (master) AnyCloudBLEScanner $ make vscode
Tools Directory: /Applications/ModusToolbox/tools_2.2
CY8CKIT-062S2-43012.mk: ../mtb_shared/TARGET_CY8CKIT-062S2-43012/latest-v2.X/CY8CKIT-062S2-43012.mk

Prebuild operations complete
Commencing build operations...

Tools Directory: /Applications/ModusToolbox/tools_2.2
CY8CKIT-062S2-43012.mk: ../mtb_shared/TARGET_CY8CKIT-062S2-43012/latest-v2.X/CY8CKIT-062S2-43012.mk

Initializing build: MTBShellTemplate Debug CY8CKIT-062S2-43012 GCC_ARM

Auto-discovery in progress...
-&gt; Found 230 .c file(s)
-&gt; Found 46 .S file(s)
-&gt; Found 23 .s file(s)
-&gt; Found 0 .cpp file(s)
-&gt; Found 0 .o file(s)
-&gt; Found 22 .a file(s)
-&gt; Found 561 .h file(s)
-&gt; Found 0 .hpp file(s)
-&gt; Found 0 resource file(s)
Applying filters...
Auto-discovery complete

Constructing build rules...
Build rules construction complete

==============================================================================
= Generating IDE files =
==============================================================================

==============================================================================
= Building application =
==============================================================================
Generating compilation database file...
-&gt; ./build/compile_commands.json
Compilation database file generation complete

echo "The existing MTBShellTemplate.code-workspace file has been saved to .vscode/backup";
The existing MTBShellTemplate.code-workspace file has been saved to .vscode/backup
The existing c_cpp_properties.json file has been saved to .vscode/backup
The existing launch.json file has been saved to .vscode/backup
Modifying existing settings.json file. Check against the backup copy in .vscode/backup
The existing tasks.json file has been saved to .vscode/backup

Generated Visual Studio Code files: c_cpp_properties.json launch.json openocd.tcl settings.json tasks.json

J-Link users, please see the comments at the top of the launch.json
   file about setting the location of the gdb-server.

Instructions:
1. Review the modustoolbox.toolsPath property in .vscode/settings.json
2. Open VSCode
3. Install "C/C++" and "Cortex-Debug" extensions
4. File-&gt;Open Folder (Welcome page-&gt;Start-&gt;Open folder)
5. Select the app root directory and open
6. Builds: Terminal-&gt;Run Task
7. Debugging: "Bug icon" on the left-hand pane

  
arh (master) AnyCloudBLEScanner $</pre>
<p>Inside of Visual Studio Code, create a new file called &#8220;bt_platform_cfg_settings.h&#8221; and add:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "cybt_platform_config.h"
#include "cybsp.h"
#include "wiced_bt_stack.h"

extern const cybt_platform_config_t bt_platform_cfg_settings;</pre>
<p>Inside of Visual Studio Code, create a new file called &#8220;bt_platform_cfg_settings.c&#8221; and add:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "cybt_platform_config.h"
#include "cybsp.h"
#include "wiced_bt_stack.h"

const cybt_platform_config_t bt_platform_cfg_settings =
{
    .hci_config =
    {
        .hci_transport = CYBT_HCI_UART,

        .hci =
        {
            .hci_uart =
            {
                .uart_tx_pin = CYBSP_BT_UART_TX,
                .uart_rx_pin = CYBSP_BT_UART_RX,
                .uart_rts_pin = CYBSP_BT_UART_RTS,
                .uart_cts_pin = CYBSP_BT_UART_CTS,

                .baud_rate_for_fw_download = 115200,
                .baud_rate_for_feature     = 115200,

                .data_bits = 8,
                .stop_bits = 1,
                .parity = CYHAL_UART_PARITY_NONE,
                .flow_control = WICED_TRUE
            }
        }
    },

    .controller_config =
    {
        .bt_power_pin      = CYBSP_BT_POWER,
        .sleep_mode =
        {
            #if (bt_0_power_0_ENABLED == 1) /* BT Power control is enabled in the LPA */
            #if (CYCFG_BT_LP_ENABLED == 1) /* Low power is enabled in the LPA, use the LPA configuration */
            .sleep_mode_enabled = true,
            .device_wakeup_pin = CYCFG_BT_DEV_WAKE_GPIO,
            .host_wakeup_pin = CYCFG_BT_HOST_WAKE_GPIO,
            .device_wake_polarity = CYCFG_BT_DEV_WAKE_POLARITY,
            .host_wake_polarity = CYCFG_BT_HOST_WAKE_IRQ_EVENT
            #else /* Low power is disabled in the LPA, disable low power */
            .sleep_mode_enabled = false
            #endif
            #else /* BT Power control is disabled in the LPA – default to BSP low power configuration */
            .sleep_mode_enabled = true,
            .device_wakeup_pin = CYBSP_BT_DEVICE_WAKE,
            .host_wakeup_pin = CYBSP_BT_HOST_WAKE,
            .device_wake_polarity = CYBT_WAKE_ACTIVE_LOW,
            .host_wake_polarity = CYBT_WAKE_ACTIVE_LOW
            #endif
        }
    },

    .task_mem_pool_size    = 2048
};</pre>
<p>Inside of Visual Studio Code, create bluetoothManager.h.  Remember this is the Bluetooth Stack Management Callback</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#pragma once
#include "wiced_bt_stack.h"
#include "wiced_bt_dev.h"

wiced_result_t app_bt_management_callback(wiced_bt_management_evt_t event, wiced_bt_management_evt_data_t *p_event_data);
</pre>
<p>Inside of Visual Studio code, create bluetoothManager.c.  This function does a whole lotta nothin&#8230; except saying that things got started.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

#include "cybsp.h"

#include "FreeRTOS.h"

#include "bluetoothManager.h"
#include "wiced_bt_stack.h"
#include "wiced_bt_dev.h"
#include "wiced_bt_trace.h"


/**************************************************************************************************
* Function Name: app_bt_management_callback()
***************************************************************************************************
* Summary:
*   This is a Bluetooth stack event handler function to receive management events from
*   the BLE stack and process as per the application.
*
* Parameters:
*   wiced_bt_management_evt_t event             : BLE event code of one byte length
*   wiced_bt_management_evt_data_t *p_event_data: Pointer to BLE management event structures
*
* Return:
*  wiced_result_t: Error code from WICED_RESULT_LIST or BT_RESULT_LIST
*
*************************************************************************************************/
wiced_result_t app_bt_management_callback(wiced_bt_management_evt_t event, wiced_bt_management_evt_data_t *p_event_data)
{
    wiced_result_t result = WICED_BT_SUCCESS;

    switch (event)
    {
        case BTM_ENABLED_EVT:

            if (WICED_BT_SUCCESS == p_event_data-&gt;enabled.status)
            {
                printf("Started BT Stack Succesfully\n");
            }
            else
            {
            	printf("Error enabling BTM_ENABLED_EVENT\n");
            }

            break;

        default:
            printf("Unhandled Bluetooth Management Event: 0x%x\n", event);
            break;
    }

    return result;
}
</pre>
<p>Next, update main.c with the required includes.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">#include "bluetoothManager.h"
#include "cycfg_bt_settings.h"
#include "bt_platform_cfg_settings.h"</pre>
<p>Then update main.c to start the stack</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">    cybt_platform_config_init(&amp;bt_platform_cfg_settings);
    wiced_bt_stack_init (app_bt_management_callback, &amp;wiced_bt_cfg_settings);</pre>
<p>Now build and program it, remember &#8220;make -j build&#8221; and &#8220;make program&#8221;.  Look, we have a functioning stack with the two bluetooth thread running.</p>
<p><a href="https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/screen-shot-2020-10-25-at-10-53-51-am/" rel="attachment wp-att-10154"><img loading="lazy" decoding="async" src="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-10.53.51-AM-1024x699.png" alt="" width="1024" height="699" class="alignnone size-large wp-image-10154" srcset="https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-10.53.51-AM-1024x699.png 1024w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-10.53.51-AM-300x205.png 300w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-10.53.51-AM-768x524.png 768w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-10.53.51-AM-600x410.png 600w, https://iotexpert.com/wp-content/uploads/2020/10/Screen-Shot-2020-10-25-at-10.53.51-AM.png 1210w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></p>
<p>In the next article Ill finally get around to building the Bluetooth Scanner.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://iotexpert.com/anycloud-bluetooth-advertising-scanner-part-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
