<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>InfluxData Blog - David G. Simmons</title>
    <description>Posts by David G. Simmons on the InfluxData Blog</description>
    <link>https://www.influxdata.com/blog/author/davidgsimmons/</link>
    <language>en-us</language>
    <lastBuildDate>Fri, 28 Feb 2020 07:00:56 -0700</lastBuildDate>
    <pubDate>Fri, 28 Feb 2020 07:00:56 -0700</pubDate>
    <ttl>1800</ttl>
    <item>
      <title>Integrating Particle.io with InfluxDB Cloud</title>
      <description>&lt;p&gt;If you followed the &lt;a href="https://w2.influxdata.com/resources/particle-ioandinfluxdb/"&gt;tutorial&lt;/a&gt; I presented a couple of years ago about integrating &lt;a href="https://www.particle.io/"&gt;Particle.io&lt;/a&gt; with &lt;a href="https://w2.influxdata.com/products/influxdb-overview/"&gt;InfluxDB&lt;/a&gt; and were unhappy, or simply couldn’t get it working, have I got a treat for you! Integrating Particle.io with &lt;a href="https://cloud2.influxdata.com/login"&gt;InfluxDB Cloud&lt;/a&gt; is very straightforward and requires no outside services or customizations outside of what Particle Cloud already offers. Here are the steps to get it all working:&lt;/p&gt;
&lt;ol&gt;
 	&lt;li&gt;Go to your &lt;a href="https://console.particle.io/"&gt;Particle.io Console&lt;/a&gt; and click on the Integrations tab.&lt;/li&gt;
 	&lt;li&gt;Click on New Integration, and choose Webhook.&lt;/li&gt;
 	&lt;li&gt;Fill out the form! You need to know your event name, and it needs to be spelled exactly the same as it is in your on-device code!&lt;/li&gt;
 	&lt;li&gt;You'll then enter the URL of your &lt;a href="https://cloud2.influxdata.com"&gt;InfluxDB Cloud&lt;/a&gt; instance. It might be different depending on the region you signed up for, which can be found on Load Data &amp;gt; Client Libraries Page: &lt;code class="language-ini" style="font-style: inherit; font-weight: inherit;"&gt;https://&amp;lt;your region&amp;gt;.&amp;lt;aws or gcp&amp;gt;.cloud2.influxdata.com/api/v2/write?org=YOUR_ORG&amp;amp;bucket=YOUR_BUCKET&amp;amp;precision=s&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You will need to know the name of your Organization and Bucket as well, which you can grab from the InfluxDB Cloud management interface.&lt;/p&gt;

&lt;p&gt;&lt;img class="wp-image-243164 aligncenter" src="/images/legacy-uploads/influxdb-cloud-particle-edit-integration.png" alt="InfluxDB Cloud Particle - edit integration" width="1012" height="660" /&gt;&lt;/p&gt;

&lt;p&gt;Next you’ll want to choose ‘Custom Body’ as your request format, and then expand the ‘Advanced’ setting as well. In there, you will insert the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/Screen-Shot-2020-02-21-at-1.20.02-PM.png"&gt;&lt;img class="wp-image-243167 aligncenter" src="/images/legacy-uploads/influxdb-cloud-particle-integration-advanced-settings.png" alt="InfluxDB Cloud Particle integration advanced settings" width="1034" height="674" /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can set whatever tags, if any, that you’d like, and then use the &lt;a href="https://mustache.github.io/"&gt;‘mustache’ notation&lt;/a&gt; to reference the Event Name and the Event Value, which will be used as the value name and value in InfluxDB.&lt;/p&gt;

&lt;p&gt;Finally, you will need to add the Authorization Header exactly as below. The Authorization Header should have the value ‘Token long-token-string-from-InfluxDBCloud’ in it. This is the exact same header needed when accessing any of the &lt;a href="https://v2.docs.influxdata.com/v2.0/write-data/#example-api-write-request"&gt;InfluxDB Cloud APIs&lt;/a&gt;. You can then save your integration, and you’re all set.&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/Screen-Shot-2020-02-21-at-1.20.15-PM.png"&gt;&lt;img class="wp-image-243166 aligncenter" src="/images/legacy-uploads/influxdb-cloud-particle-integration-authorize.png" alt="InfluxDB Cloud Particle integration - authorize" width="1048" height="684" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you save your integration, you will see a page that tells you all the details of it:&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/Screen-Shot-2020-02-21-at-1.29.51-PM.png"&gt;&lt;img class="wp-image-243163 aligncenter" src="/images/legacy-uploads/influxdb-cloud-particle-save-integration.png" alt="InfluxDB Cloud Particle - save integration" width="1067" height="711" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And below that, it even gives you some sample on-device code that will trigger the integration:&lt;/p&gt;

&lt;p&gt;&lt;img class="wp-image-243168 aligncenter" src="/images/legacy-uploads/influxdb-cloud-particle-trigger-integration.png" alt="InfluxDB Cloud Particle - trigger integration" width="983" height="613" /&gt;&lt;/p&gt;

&lt;p&gt;And that’s it! So simple! Try it out and let us know what you think in our &lt;a href="https://w2.influxdata.com/slack"&gt;Community Slack&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Fri, 28 Feb 2020 07:00:56 -0700</pubDate>
      <link>https://www.influxdata.com/blog/integrating-particle-io-with-influxdb-cloud/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/integrating-particle-io-with-influxdb-cloud/</guid>
      <category>Use Cases</category>
      <category>Product</category>
      <category>Developer</category>
      <author>David G. Simmons (InfluxData)</author>
    </item>
    <item>
      <title>The World's Smallest InfluxDB Server</title>
      <description>&lt;p&gt;I’ve built a lot of &lt;a href="https://w2.influxdata.com/products/influxdb-overview/"&gt;InfluxDB&lt;/a&gt; servers in my time here, and I’ve built some pretty esoteric ones at that, but I think I’ve finally pulled off what can only be described as the World’s Smallest InfluxDB Server! Back in the summer of 2019, I saw a project on &lt;a href="https://www.crowdsupply.com/groboards/giant-board"&gt;CrowdSupply.com&lt;/a&gt; for something called the ‘Giant Board’. It looked really, really cool! A complete Single Board Computer (SBC) that ran Linux, all in a Feather form factor. I immediately backed it! Then, thinking about it for a second, I backed it &lt;em&gt;again&lt;/em&gt;! So I got 2 of these things. Total accident, I swear.&lt;/p&gt;

&lt;p&gt;Some specs. Here’s what the Giant Board actually is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Giant Board Specs&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
 	&lt;li&gt;&lt;strong&gt;Processor&lt;/strong&gt;: Microchip SAMA5D2 ARM® Cortex®-A5 Processor 500 MHz&lt;/li&gt;
 	&lt;li&gt;&lt;strong&gt;Memory&lt;/strong&gt;: 128 MB DDR2 RAM&lt;/li&gt;
 	&lt;li&gt;&lt;strong&gt;Storage&lt;/strong&gt;: microSD card&lt;/li&gt;
 	&lt;li&gt;&lt;strong&gt;Sensing&lt;/strong&gt;: 6 x 12-bit ADC with 3.3 V reference and external trigger&lt;/li&gt;
 	&lt;li&gt;&lt;strong&gt;Actuation&lt;/strong&gt;: 4 x 16-bit PWM with external trigger&lt;/li&gt;
 	&lt;li&gt;&lt;strong&gt;Connectivity&lt;/strong&gt;: 1 x I²C, 1 x SPI, 1 x UART, more with Flexcom&lt;/li&gt;
 	&lt;li&gt;&lt;strong&gt;Power&lt;/strong&gt;: via USB, with support for LiPo batteries&lt;/li&gt;
 	&lt;li&gt;&lt;strong&gt;Operating System&lt;/strong&gt;: mainline Linux kernel&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All in this tiny form-factor that I usually use for Microcontrollers!&lt;/p&gt;

&lt;p&gt;Well, a few weeks ago, they arrived! So, some unboxing pictures:&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/GiantBoard-in-package.jpg"&gt;&lt;img class="aligncenter wp-image-242723 size-large" src="/images/legacy-uploads/GiantBoard-in-package-768x1024.jpg" alt="GiantBoard in package" width="768" height="1024" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wait, the whole thing fits in that one little bag? Yes. Not only that — there are multiple parts in that bag! And I realize (now) that there’s no scale to that bag in the picture, but that’s a Mac Mouse next to it. I’d retake the picture, but I already threw the bags away!&lt;/p&gt;

&lt;p&gt;&lt;img class="aligncenter wp-image-242726 size-large" src="/images/legacy-uploads/IMG_6752-1-768x1024.png" alt="Giant Board Parts" width="768" height="1024" /&gt;&lt;/p&gt;

&lt;p&gt;That’s right: I ordered the WiFi Feather Wing add-on because, after all, what’s an IoT board — and especially what’s an InfluxDB server — without networking!&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/IMG_6754-1.png"&gt;&lt;img class="aligncenter size-large wp-image-242724" src="/images/legacy-uploads/IMG_6754-1-768x1024.png" alt="Giant Board with Feather wing" width="768" height="1024" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And just for scale, that’s a US Quarter in between them. So that’s going to be my server &lt;em&gt;and&lt;/em&gt; my network interface! For something called the ‘Giant Board’ it sure is small!&lt;/p&gt;

&lt;p&gt;After a little soldering, I had it all put together and, with the addition of a MicroSD card, it booted up!&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/Screen-Shot-2020-02-11-at-9.04.12-AM.png"&gt;&lt;img class="aligncenter size-full wp-image-242727" src="/images/legacy-uploads/Screen-Shot-2020-02-11-at-9.04.12-AM.png" alt="Command line with login to the Giant Board" width="581" height="281" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Woah! This tiny little thing runs Debian Linux? Why yes, yes it does! So that makes &lt;a href="https://docs.influxdata.com/influxdb/v1.7/introduction/installation/"&gt;installing InfluxDB&lt;/a&gt; super simple since we already ship ARMv7 binaries for InfluxDB and all the rest of the &lt;a href="https://w2.influxdata.com/time-series-platform/"&gt;TICK Stack&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/Screen-Shot-2020-02-11-at-9.07.54-AM.png"&gt;&lt;img class="aligncenter size-full wp-image-242728" src="/images/legacy-uploads/Screen-Shot-2020-02-11-at-9.07.54-AM.png" alt="Terminal showing influxd running" width="602" height="425" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok, sure, it’s currently hammering this tiny CPU, but it is also running!&lt;/p&gt;

&lt;p&gt;&lt;img class="aligncenter wp-image-242729 size-full" src="/images/legacy-uploads/Kapture-2020-01-21-at-12.22.19-screenshot.jpg" alt="live shot of a dashboard on the Giant Board" width="1024" height="372" /&gt;&lt;/p&gt;

&lt;p&gt;And as you can see, the dashboard runs in &lt;a href="https://w2.influxdata.com/time-series-platform/chronograf/"&gt;Chronograf&lt;/a&gt; to give me a view into how the whole thing is running!&lt;/p&gt;

&lt;p&gt;Now, would I run this as a production system? Absolutely not! As you can see, it is using far too many system resources on such a small device. Would I run it as an edge collection and forwarding device? Quite possibly. Would I run it as an embedded &lt;a href="https://w2.influxdata.com/time-series-platform/telegraf/"&gt;Telegraf&lt;/a&gt; agent device? 100% absolutely. Especially since I can also do this with it:&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/IMG_6779.png"&gt;&lt;img class="aligncenter size-large wp-image-242730" src="/images/legacy-uploads/IMG_6779-768x1024.png" alt="Giant Board running on battery" width="768" height="1024" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s right, I can run it on a battery! A rechargeable LiPo battery at that (and the recharging circuitry is built in to the board!). And for completeness, I’ll provide a pin-out here so you can see what &lt;em&gt;else&lt;/em&gt; I can add to this thing — sensors, actuators, etc., — to make it both a data node and a sensor node:&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/giant-board-pin-out.png"&gt;&lt;img class="aligncenter size-large wp-image-242776" src="/images/legacy-uploads/giant-board-pin-out-1024x690.png" alt="" width="1024" height="690" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next I will build a version of InfluxDB 2.0 for ARMv7 and see if that runs either better or worse on this device, so watch this space to see what happens!&lt;/p&gt;
</description>
      <pubDate>Thu, 13 Feb 2020 11:19:10 -0700</pubDate>
      <link>https://www.influxdata.com/blog/the-worlds-smallest-influxdb-server/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/the-worlds-smallest-influxdb-server/</guid>
      <category>Product</category>
      <category>Use Cases</category>
      <category>Developer</category>
      <author>David G. Simmons (InfluxData)</author>
    </item>
    <item>
      <title>Using Flux to Get IoT Sensor Metadata from MySQL</title>
      <description>&lt;p&gt;If you’ve deployed an IoT solution, you’ve had to decide where, and how, to store all your data. At least from my perspective, the best and easiest place to store the sensor data is, of course, &lt;a href="https://w2.influxdata.com/products/influxdb-overview/"&gt;InfluxDB&lt;/a&gt;. My saying that can’t come as a surprise to you. But what about the &lt;em&gt;other&lt;/em&gt; data you need to store? The data &lt;em&gt;about&lt;/em&gt; the sensors? Things like the sensor manufacturer, the date it was placed into service, the customer ID, what kind of platform it’s running on. You know, all the sensor metadata.&lt;/p&gt;

&lt;p&gt;One solution, of course, is to simply add all that stuff as tags to your sensor data in InfluxDB and go on about your day. But do you &lt;em&gt;really&lt;/em&gt; want to store all your sensor data with each datapoint? Lots of things seem like a good idea at the time, but then rapidly devolve into a terrible idea when reality hits. Since most of this metadata doesn’t change often, and may also be associated with customer information, the best place for it is very likely in a traditional RDBMS. Most likely you already &lt;em&gt;have&lt;/em&gt; an RDBMS with customer data in it, so why not just continue to leverage that investment? As I’ve said repeatedly, this is &lt;strong&gt;not&lt;/strong&gt; the best place for your sensor data. So now you’ve got your IoT data in two different databases. How do you access it and merge it into one place where you can see it all?&lt;/p&gt;

&lt;h2&gt;Flux is the answer&lt;/h2&gt;

&lt;p&gt;Tell me you saw that coming. You had to have seen that coming. Ok, to be fair, you may have because, after all, how are you going to get your SQL-based data via &lt;a href="https://university.influxdata.com/courses/intro-to-basic-flux-elements-tutorial/"&gt;Flux&lt;/a&gt;? That’s the beauty of Flux: it’s extensible! So we now have an extension that allows you to read data from either MySQL, MariaDB or Postgres via Flux. When I heard that this &lt;a href="https://www.influxdata.com/glossary/sql/"&gt;SQL&lt;/a&gt; connector was ready to go, I just had to try it. I’ll show you what I built, and how.&lt;/p&gt;

&lt;h2&gt;Build a customer database&lt;/h2&gt;

&lt;p&gt;The first thing to do was build a MySQL database with some Customer Information. I created a new database called &lt;code class="language-markup"&gt;IoTMeta&lt;/code&gt; into which I put a table with some sensor metadata. I also added another table with customer information about those sensors.&lt;/p&gt;

&lt;p&gt;&lt;img class="aligncenter size-full wp-image-239188" src="/images/legacy-uploads/Screen-Shot-2019-11-14-at-11.38.33-AM.png" alt="2 tables of data" width="425" height="291" /&gt;&lt;/p&gt;

&lt;p&gt;Pretty basic tables, really. The &lt;code class="language-markup"&gt;Sensor_ID&lt;/code&gt; field I populated with data corresponding to the &lt;code class="language-markup"&gt;Sensor_id&lt;/code&gt; tag in my InfluxDB instance. I bet you can see where I’m going with this already. I added a bunch of data:&lt;/p&gt;

&lt;p&gt;&lt;img class="aligncenter size-full wp-image-239190" src="/images/legacy-uploads/Screen-Shot-2019-11-14-at-11.50.47-AM.png" alt="" width="1262" height="155" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class="aligncenter size-full wp-image-239189" src="/images/legacy-uploads/Screen-Shot-2019-11-14-at-11.48.38-AM.png" alt="" width="714" height="111" /&gt;&lt;/p&gt;

&lt;p&gt;So now my sensor metadata database has some information about each sensor I’m running here, as well as some ‘customer data’ about who owns the sensors. Now it’s time to pull this all into something useful.&lt;/p&gt;
&lt;h2&gt;Query the data with Flux&lt;/h2&gt;
&lt;p&gt;First, I built a query in Flux to get some of my sensor data, but I wasn’t actually interested in the sensor data itself. I was looking for an identifying Tag value: &lt;code class="language-markup"&gt;Sensor_id&lt;/code&gt;. This query will look a little strange, but it will make sense in the end, I promise.&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-javascript"&gt;temperature = from(bucket: "telegraf") 
  |&amp;gt; range(start: v.timeRangeStart, stop: v.timeRangeStop) 
  |&amp;gt; filter(fn: (r) =&amp;gt; r._measurement == "temperature" and (r._field == "temp_c")) 
  |&amp;gt; last() 
  |&amp;gt; map(fn: (r) =&amp;gt; { 
       return { query: r.Sensor_id } 
       }) |&amp;gt; tableFind(fn: (key) =&amp;gt; true) |&amp;gt; getRecord(idx: 0)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It returns a table of one row, and then pulls out the &lt;code class="language-markup"&gt;Sensor_id&lt;/code&gt; tag, and that’s where you’re probably saying “Whaaaat?” Remember: Flux returns everything in tables. What I need is essentially a scalar value out of that table. In this case, it’s a string value for the Tag in question. That’s how you do that.&lt;/p&gt;

&lt;p&gt;Next, I’m going to get the username and password for my MySQL database, which is conveniently stored in the InfluxDB Secrets Store.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markup"&gt;uname = secrets.get(key: "SQL_USER") 
pass = secrets.get(key: "SQL_PASSW")&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wait, how did I get those values into this Secrets Store anyway? Right, let’s back up a minute.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-markup"&gt;curl -XPATCH http://localhost:9999/api/v2/orgs/&amp;lt;org-id&amp;gt;/secrets -H 'Authorization: Token &amp;lt;token&amp;gt;' -H 'Content-type: application/json' --data '{ "SQL_USER": "&amp;lt;username&amp;gt;" }'&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One thing to note is that you get the &lt;code class="language-markup"&gt;&amp;lt;org-id&amp;gt;&lt;/code&gt; out of your URL. It’s &lt;strong&gt;not&lt;/strong&gt; the actual name of your organization in InfluxDB. Then you do the same thing for the &lt;code class="language-markup"&gt;SQL_PASSW&lt;/code&gt; secret. You can call them anything you want, really. &lt;a href="https://v2.docs.influxdata.com/v2.0/security/secrets/"&gt;Now you don’t have to put your username/password in plain text in your query&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next, I’m going to use all of that to build my SQL Query:&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-sql"&gt;sq = sql.from(
  driverName: "mysql",
  dataSourceName: "${uname}:${pass}@tcp(localhost:3306)/IoTMeta",
  query: "SELECT * FROM Sensor_data, Customer_Data WHERE  Sensor_data.Sensor_ID = ${"\""+temperature.query+"\"  AND Sensor_data.measurement = \"temperature\" AND Sensor_data.CustomerID = Customer_Data.Customer_ID"}" //"SELECT * FROM Sensor_data WHERE Sensor_ID = ${"\""+temperature.query+"\" AND measurement = \"temperature\""}" //q //  humidity.query //"SELECT * FROM Sensor_Data WHERE Sensor_ID = \"THPL001\""// humidity.query 
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You’ll see that I’m using the value from my first Flux query in the SQL query. Cool! You might also notice that I am performing a &lt;code&gt;join&lt;/code&gt; in that SQL query so that I can get data from &lt;em&gt;both&lt;/em&gt; tables in the database. How cool is that? Next, I’ll format the resulting table to have just the columns I want to display:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;fin = sq
|&amp;gt; map(fn: (r) =&amp;gt; ({Sensor_id: r.Sensor_ID, Owner: r._Sensor_owner, Manufacturer: r.Sensor_mfg, MCU_Class: r.MCU_class, MCU_Vendor: r.MCU_vendor, Customer: r.Customer, Address: r.Address, Phone: r.phone}))

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I’ve now got a table that contains all the metadata about my sensor, as well as all the customer contact data about that sensor. It’s time for some magic:&lt;/p&gt;

&lt;p&gt;&lt;img class="aligncenter size-full wp-image-239191" src="/images/legacy-uploads/Screen-Shot-2019-11-14-at-12.12.19-PM.png" alt="" width="1357" height="289" /&gt;&lt;/p&gt;

&lt;p&gt;What is this sorcery? I have a table that has all the metadata about the sensor, some customer data, &lt;strong&gt;and&lt;/strong&gt; the sensor readings too? Yep. I do. And here’s the really magic thing: Since you can get data from both SQL databases &lt;em&gt;and&lt;/em&gt; InfluxDB buckets, you can also join that data together into a single table.&lt;/p&gt;

&lt;p&gt;Here’s how I did that:&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-javascript"&gt;temp = from(bucket: "telegraf")
  |&amp;gt; range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |&amp;gt; filter(fn: (r) =&amp;gt; r._measurement == "temperature" and (r._field == "temp_c"))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Gets me a table of the sensor data. I already have a table of the metadata from SQL, so …&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-javascript"&gt;j1 = join(tables: {temp: temp, fin: fin}, on: ["Sensor_id"] )
|&amp;gt; map(fn: (r) =&amp;gt; ({_value: r._value, _time: r._time, Owner: r.Owner, Manufacturer: r.Manufacturer, MCU_Class: r.MCU_Class, MCU_Vendor: r.MCU_Vendor, Customer: r.Customer, Address: r.Address, Phone: r.phone}))
|&amp;gt; yield()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I just join those two tables on a common element (the &lt;code&gt;Sensor_id&lt;/code&gt; field) and I have a table that has everything in one place!&lt;/p&gt;

&lt;p&gt;There are any number of ways that you can use this ability to merge data from different sources. I’d love to hear how you would implement something like this to better understand your sensor deployments.&lt;/p&gt;

&lt;p&gt;I’ve done all this using the Alpha18 build of InfluxDB 2.0, which is what I run — actually I custom-build my version from the &lt;code&gt;master&lt;/code&gt; because I have some additions to Flux that I use, but that’s a whole other post. For this stuff, the Alpha builds of OSS InfluxDB 2.0 work just fine. You should absolutely give it a try!&lt;/p&gt;
</description>
      <pubDate>Thu, 05 Dec 2019 07:00:49 -0700</pubDate>
      <link>https://www.influxdata.com/blog/using-flux-to-get-iot-sensor-metadata-from-mysql/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/using-flux-to-get-iot-sensor-metadata-from-mysql/</guid>
      <category>Use Cases</category>
      <category>Developer</category>
      <category>Product</category>
      <author>David G. Simmons (InfluxData)</author>
    </item>
    <item>
      <title>Connecting The Things Network to InfluxDB</title>
      <description>&lt;p&gt;There are many ways to connect your sensors to the network in the IoT. For short-range connections, there is Bluetooth LE, or Zigbee, or 802.15.4, or ZWave. For longer distances (though still fairly short) there’s always WiFi. But when you need longer distances, sometimes &lt;strong&gt;very&lt;/strong&gt; long distances, there’s LoRaWAN. It’s a sub-gigahertz set of frequencies that are available for small bits of data. These are typically only a few bytes of data but can be sent over much longer distances — up to 2 km or more in some instances! They are very low-power, so they are great for remote-sensing applications.&lt;/p&gt;

&lt;p&gt;In order to test out some LoRaWAN data transmission, and see how hard it might be to get that data into InfluxDB, I decided to move one of my sensors, a temperature/humidity/pressure sensor, to The Things Network (TTN), a community-based LoRaWAN provider. I wasn’t sure how hard, or easy, this transition might be, but I was able to complete it in less than a day! So here’s how you can do it too.&lt;/p&gt;
&lt;h2&gt;The hardware&lt;/h2&gt;
&lt;p&gt;First of all, you will need to make sure that either you have a TTN Gateway yourself, or that there is one in your area. As you can see, there are a &lt;em&gt;lot&lt;/em&gt; of gateways available.&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/Screen-Shot-2019-10-09-at-12.08.22-PM.png"&gt;&lt;img class="aligncenter size-full wp-image-237570" src="/images/legacy-uploads/Screen-Shot-2019-10-09-at-12.08.22-PM.png" alt="" width="1011" height="526" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There wasn’t one close enough, so I put up my own (Tip: These are &lt;strong&gt;not&lt;/strong&gt; cheap to buy — mine cost me &amp;gt;$200) so you can see me on the map now:&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/Screen-Shot-2019-10-09-at-12.09.32-PM-1.png"&gt;&lt;img class="aligncenter size-full wp-image-237712" src="/images/legacy-uploads/Screen-Shot-2019-10-09-at-12.09.32-PM-1.png" alt="" width="1006" height="478" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are lots of tutorials on how to set up a gateway, so I’m not going to cover that here.&lt;/p&gt;

&lt;p&gt;Next, you’ll need a LoRA radio for your sensor. I happened to have an &lt;a href="https://www.adafruit.com/product/2772"&gt;Adafruit Feather M0&lt;/a&gt; board lying around (I have a lot of random pieces of hardware just ‘lying around’), so I got an &lt;a href="https://www.adafruit.com/product/3231"&gt;Adafruit LorRa Featherwing&lt;/a&gt; for it and put it on. Lastly, I used a &lt;a href="https://www.adafruit.com/product/2652"&gt;BME280 breakout board&lt;/a&gt; (again from Adafruit. They really ought to sponsor me!) to collect the data and I was ready to go.&lt;/p&gt;

&lt;p&gt;Wiring everything up takes a minute, so I’ll give you the details on how I wired mine. The first thing to note is that with the LoRaWAN Featherwing, you &lt;strong&gt;must&lt;/strong&gt; do additional soldering. You can see below how I had to solder jumpers in from &lt;code class="language-markup"&gt;IRQ&lt;/code&gt;, &lt;code class="language-markup"&gt;CS&lt;/code&gt;, &lt;code class="language-markup"&gt;RST&lt;/code&gt;, &lt;code class="language-markup"&gt;DIO1&lt;/code&gt; and &lt;code class="language-markup"&gt;DIO2&lt;/code&gt;. These then map to pins on the M0 Feather, which we will see in the software section. If you wire these jumpers up differently, you will need to adjust the pin settings in your software accordingly.&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/IMG_6122.png"&gt;&lt;img class="aligncenter size-full wp-image-237571" src="/images/legacy-uploads/IMG_6122.png" alt="" width="266" height="640" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also see some small red wires coming in from off-screen (I love this ceramic-coated wire, even if it is a pain to solder). Those come from the BME280 Breakout board and go to the I2C pins and the 3v/ground on the board to power the sensor. Once all that is wired up, it’s down to software!&lt;/p&gt;
&lt;h2&gt;The software&lt;/h2&gt;
&lt;p&gt;Software for this took me a minute to get working, but most of that had to do with the difference in &lt;em&gt;how&lt;/em&gt; you send data over LoRaWAN. I’m used to using BLE or WiFi, so the size of the data packets really doesn’t matter that much. With LoRaWAN, the size of the data packets reigns supreme.&lt;/p&gt;

&lt;p&gt;The first thing you’ll want to do is install the right library for your Arduino. I used the &lt;a href="https://github.com/mcci-catena/arduino-lmic"&gt;MCCI LoRaWAN LMIC Library&lt;/a&gt;. It seemed the easiest for integrating with TTN. Some of the documentation on this library was a bit less than clear (at least for me) so I’ll give you the specifics of what I did to get this running on an M0 Feather. From there, I started with the &lt;code class="language-markup"&gt;ttn-otaa-feather-us915&lt;/code&gt; sample program. Now, to fill in the pieces. You’ll need to go to your TTN Console and create a new Application.&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/Screen-Shot-2019-10-09-at-1.19.29-PM.png"&gt;&lt;img class="aligncenter size-full wp-image-237572" src="/images/legacy-uploads/Screen-Shot-2019-10-09-at-1.19.29-PM.png" alt="" width="1072" height="683" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you’ve registered that application, you will need to get the Application EUIS (ID) to paste into your Arduino Sketch. It’s important to note that, by default, the TTN console gives you your EUIS with most significant bit first (big-endian) whereas the Arduino sketch expects it in little-endian. Luckily, the TTN console makes all of that easy:&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/AppEUI.gif"&gt;&lt;img class="aligncenter size-full wp-image-237573" src="/images/legacy-uploads/AppEUI.gif" alt="" width="1074" height="506" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it even makes copying it into a byte-array simple.&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;static const u1_t PROGMEM APPEUI[8] = { 0xB2, 0x38, 0x02, 0xD0, 0x7E, 0xD5, 0xB3, 0x70 };
void os_getArtEui (u1_t* buf) {
  memcpy_P(buf, APPEUI, 8);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, that’s the APP ID. Next you’ll do the same thing for your Device ID and your App Key. Click to register a new device, and you can get access to all the needed information from there:&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/Screen-Shot-2019-10-09-at-1.33.14-PM.png"&gt;&lt;img class="aligncenter size-full wp-image-237574" src="/images/legacy-uploads/Screen-Shot-2019-10-09-at-1.33.14-PM.png" alt="" width="1082" height="628" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;// This should also be in little endian format, see above.
static const u1_t PROGMEM DEVEUI[8] = { &amp;lt;insert Dev Key };
void os_getDevEui (u1_t* buf) {
  memcpy_P(buf, DEVEUI, 8);
}

// This key should be in big endian format (or, since it is not really a
// number but a block of memory, endianness does not really apply). In
// practice, a key taken from the TTN console can be copied as-is.
static const u1_t PROGMEM APPKEY[16] = { &amp;lt;insert Program Key };
void os_getDevKey (u1_t* buf) {
  memcpy_P(buf, APPKEY, 16);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And don’t worry about me publishing those IDs. I created that dummy application and device just for this blog post, and they are long-gone now. But as a reminder, never publish your IDs or keys like this.&lt;/p&gt;

&lt;p&gt;You will need to adjust this data buffer for your data, but here’s what I used: &lt;code class="language-markup"&gt;unsigned char mydata[11];&lt;/code&gt; Remember, I said that the data transmitted was intentionally kept &lt;em&gt;very&lt;/em&gt; low, so I’m packing a whole lot of data into this 11 bytes! We’ll see how I do that in a bit.&lt;/p&gt;

&lt;p&gt;Next comes the pins. Remember from the hardware section? If you wired your LoRaWAN feather exactly like mine, this should work for you.&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;#if defined(ARDUINO_SAMD_FEATHER_M0) || defined(ADAFRUIT_FEATHER_M0)
// Pin mapping for Adafruit Feather M0 LoRa, etc.
const lmic_pinmap lmic_pins = {
  .nss = 5,
  .rxtx = LMIC_UNUSED_PIN,
  .rst = 6,
  .dio = {9, 10, 11},
  .rxtx_rx_active = 0,
  .rssi_cal = 8,              // LBT cal for the Adafruit Feather M0 LoRa, in dB
  .spi_freq = 8000000,
};&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Those were a little hard to figure out, and in the sample code it leaves a couple of those &lt;code class="language-markup"&gt;dio&lt;/code&gt; pins as &lt;code class="language-markup"&gt;LMIC_UNUSED_PIN&lt;/code&gt; but mine wouldn’t work until I defined them all.&lt;/p&gt;

&lt;p&gt;For the rest of my code, I used some boiler-plate I have for the BME280:&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;Adafruit_BME280 bme;
double temperature = 0.00;
double pressure = 0.00;
double altitude = 0.00;
double humidity = 0.00;
bool bme_config = true;

// this goes in the setup() function:
int tryInit = 0;
  while (!bme.begin()) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    delay(3000);
    if (++tryInit &amp;gt; 9) {
      bme_config = false;
      break;
    }
  }

// a function to get readings:
void getReadings() {
  if (bme_config) {
    temperature = bme.readTemperature();
    pressure = bme.readPressure() / 100.0F;
    altitude = bme.readAltitude(SEALEVELPRESSURE_HPA);
    humidity = bme.readHumidity();
    Serial.print("Temp:     "); Serial.println(temperature);
    Serial.print("Humidity: "); Serial.println(humidity);
    Serial.print("Pressure: "); Serial.println(pressure);
    Serial.print("Altitude: "); Serial.println(altitude);
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, to get the data stuffed into 11 bytes! You’ll notice that in my boilerplate BME280 code I defined all the measurements as &lt;code class="language-markup"&gt;double&lt;/code&gt; which was fine for high-bandwidth applications, but it just won’t do for LoRaWAN. So I’m going to whittle them down to 2-bytes each (except the pressure measurement, which will stay at 4-bytes).&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;getReadings();
    uint16_t ft = (uint16_t)(temperature * 100);
    uint16_t fh = (uint16_t)(humidity * 100);
    uint32_t fp = (uint32_t)(pressure * 100);
    uint16_t fa = (uint16_t)(altitude * 100);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If I have readings like:&lt;/p&gt;
&lt;blockquote&gt;Temp: 25.04
Humidity: 54.60
Pressure: 1006.38
Altitude: 57.34&lt;/blockquote&gt;
&lt;p&gt;Then I’ll end up with:&lt;/p&gt;
&lt;blockquote&gt;Temp: 2502
Humidity: 5460
Pressure 100638
Altitude: 5734&lt;/blockquote&gt;
&lt;p&gt;All 16- and 32-bit integers. Now, to stuff them all into my data array:&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;mydata[0] = ft &amp;gt;&amp;gt; 8;
    mydata[1] = ft &amp;amp; 0xFF;
    mydata[2] = fh &amp;gt;&amp;gt; 8;
    mydata[3] = fh &amp;amp; 0xFF;
    mydata[4] = fp &amp;amp; 0xFF; 
    mydata[5] = (fp &amp;gt;&amp;gt; 8) &amp;amp; 0xFF;
    mydata[6] = (fp &amp;gt;&amp;gt; 16) &amp;amp; 0xFF;
    mydata[7] = (fp &amp;gt;&amp;gt; 24) &amp;amp; 0xFF;
    mydata[8] = fa &amp;gt;&amp;gt; 8;
    mydata[9] = fa &amp;amp; 0xFF;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you’re not familiar with bit-wise data manipulation, basically I’m just moving each byte of each number into a spot in my byte-array. Since the pressure number is a 4-byte value, I have to do extra shifting. I can then send that off to TTN via LoRaWAN and my data transmission is completed.&lt;/p&gt;

&lt;p&gt;Sadly though, we’re not done yet!. TTN will politely send all the data I send to it out to an MQTT broker for me so that I can subscribe to it and do with it as I please. (&lt;strong&gt;Spoiler alert:&lt;/strong&gt; I’m going to put it into InfluxDB!)&lt;/p&gt;
&lt;h2&gt;Getting the data&lt;/h2&gt;
&lt;p&gt;My data is now coming into TTN via LoRaWAN, and is being written out to an MQTT broker for me, but how do I get at it? Well, the first thing to do is subscribe! I use an app called MQTT Box on my Mac to subscribe to various MQTT brokers to see data from different inputs. It allows me to define multiple brokers, and to subscribe to any number of topics from those brokers to see my data. To subscribe to the broker you need 3 pieces of information: The name/address of the broker, the username and the password to connect. For those of us in the US, the address of the broker is &lt;code class="language-markup"&gt;us-west.thethings.network&lt;/code&gt; . For your username, you will use the name of your application. In the example above, we’d use &lt;code class="language-markup"&gt;my-temp-app&lt;/code&gt; as the username. For the password, you’ll go to your application on the TTN Console, and look for the &lt;code class="language-markup"&gt;Application Key&lt;/code&gt; at the bottom of the page. Copy/paste that in to the password field for the broker and you should connect.&lt;/p&gt;

&lt;p&gt;If I look at my data coming out to my MQTT broker, I immediately notice a problem: It’s just a random-looking string of characters. It’s actually not random at all — it’s your data buffer, base-64 encoded.&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;{ "app_id":"my-temp-app",
  "dev_id":"my-device",
  "hardware_serial":"009E9BA30C869232",
  "port":1,
  "counter":17,
  "payload_raw":"CdgVLRGJAQAWzg==",
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not super helpful. I did find a &lt;strong&gt;super&lt;/strong&gt; helpful website that would help me translate that into something more meaningful. Go &lt;a href="https://cryptii.com/pipes/base64-to-hex"&gt;Crypti.com&lt;/a&gt; and paste in your raw, base-64-encoded data, and it will … translate it to Hexadecimal. Hmm … still not what I want to see. It turns out, in order to get the data in a usable form, you have to go back to your TTN console and click on the &lt;code class="language-markup"&gt;Payload Formats&lt;/code&gt; tab. From here, we will decode the Hex into something we can actually use.&lt;/p&gt;

&lt;p&gt;Remember, we send an array of bytes. I pasted the base-64-encoded message into that website above, and got the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/Screen-Shot-2019-10-09-at-2.34.09-PM.png"&gt;&lt;img class="aligncenter size-full wp-image-237577" src="/images/legacy-uploads/Screen-Shot-2019-10-09-at-2.34.09-PM.png" alt="" width="1142" height="398" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It decoded it into a series of bytes. Cool! Now to decode those bytes! (We’re almost there, I promise!)&lt;/p&gt;

&lt;p&gt;On your TTN Consoles &lt;code&gt;Payload Formats&lt;/code&gt; tab, we will enter the following function (it’s javascript!)&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;function Decoder(bytes, port) {
  var decoded = {};

  var cInt = (bytes[0] &amp;lt;&amp;lt; 8) | bytes[1]; // temperature ºC
  var rem =(bytes[2] &amp;lt;&amp;lt; 8) | bytes[3]; // humidity %
  var pre = (bytes[4]) + // pressure is a 4-byte value
  ((bytes[5]) &amp;lt;&amp;lt; 8) 
      + ((bytes[6]) &amp;lt;&amp;lt; 16) 
  + ((bytes[7]) &amp;lt;&amp;lt; 24) ;
  var alt = (bytes[8] &amp;lt;&amp;lt; 8) + bytes[9];
  
  

  // Decode integer to float
  decoded.temp_c = cInt / 100;
  decoded.humidity = rem / 100;
  decoded.pressure = pre / 100;
  decoded.altitude = alt / 100;

  return decoded;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I’ll step through what we’re doing here. If we look back at the data buffer we sent, you’ll remember that the first 2 bytes were the temperature. So we strip off those 2 bytes and store those in a temperature variable. We strip off the next 2 and that’s our humidity. We then need to grab the 4 bytes of the pressure, and finally the last 2 bytes for the altitude. Finally, we decode those back into their original floating-point state, and we’re done! Now if we look at what’s coming out of our MQTT broker, we will see:&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;{ "app_id":"my-temp-app",
  "dev_id":"my-device",
  "hardware_serial":"009E9BA30C869232",
  "port":1,
  "counter":28,
  "payload_raw":"CeEVJg6JAQAW7A==",
  "payload_fields":{
      "altitude":58.68,
      "humidity":54.14,
      "pressure":1006.22,
      "temp_c":25.29
  },
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which is a proper JSON object, with our data in a usable form! Now for the final bit: getting it all into InfluxDB!&lt;/p&gt;
&lt;h2&gt;Getting it into InfluxDB&lt;/h2&gt;
&lt;p&gt;Luckily, this is the easiest part of the whole thing thanks to Telegraf! On your telegraf host, edit your &lt;code class="language-markup"&gt;telegraf.conf&lt;/code&gt; file. Look for the section entitled Read metrics from MQTT topic(s) and add the following:&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;[[inputs.mqtt_consumer]]
  servers = ["tcp://us-west.thethings.network:1883"]
  qos = 0
  connection_timeout = "30s"
  topics = [ "+/devices/+/up" ]
  client_id = "ttn"
  username = "APP_NAMEr"
  password = "APPKEY"
  data_format = "json"&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then restart telegraf, and, like magic, you should be getting data into InfluxDB! If I go look in my data explorer in Chronograf, I should see a new measurement called &lt;code class="language-markup"&gt;mqtt_consumer&lt;/code&gt; and in there … Whoa!! A lot of data fields! It turns out that TTN provides a bunch of additional data about how the device connected and sent its data, and that is all preserved by the Telegraf plugin.&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/data1-queery-1.jpg"&gt;&lt;img class="aligncenter size-full wp-image-237578" src="/images/legacy-uploads/data1-queery-1.jpg" alt="" width="1658" height="878" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your sensor data will have &lt;code class="language-markup"&gt;payload_fields_&lt;/code&gt; prepended to it. All the rest is data &lt;strong&gt;about&lt;/strong&gt; your data.&lt;/p&gt;

&lt;p&gt;As usual, the easiest part of almost any deployment I do is the InfluxDB part. Once I had the data coming out of the MQTT broker in the proper format, having it stored in InfluxDB took just a few lines of configuration. I can now build a dashboard of my temperature, humidity, pressure and altitude data in Chronograf.&lt;/p&gt;
</description>
      <pubDate>Thu, 10 Oct 2019 09:25:17 -0700</pubDate>
      <link>https://www.influxdata.com/blog/connecting-the-things-network-to-influxdb/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/connecting-the-things-network-to-influxdb/</guid>
      <category>Product</category>
      <category>Use Cases</category>
      <category>Developer</category>
      <author>David G. Simmons (InfluxData)</author>
    </item>
    <item>
      <title>Hiding Complexity with Custom Functions: Calculating Heat Index</title>
      <description>&lt;p&gt;Have you ever watched the local weather — or The Weather Channel — and heard them announce the temperature, and then the “Heat Index”? Or how hot it &lt;strong&gt;feels&lt;/strong&gt; outside? At least here in the United States, and especially in the South, it’s part of every weather broadcast in the summer. But have you ever wondered how they actually &lt;em&gt;calculate&lt;/em&gt; the Heat Index? Since I collect temperature and humidity data, I decided one day I’d go and figure it out. After all, how hard could it be really? Hint: never ask yourself that question!&lt;/p&gt;
&lt;h2&gt;The Heat Index calculation&lt;/h2&gt;
&lt;p&gt;As soon as I went looking for what I was sure was a simple calculation to convert a temperature and a humidity reading into a heat index (HI) I was sorry I’d headed down this road. I easily found a page where the National Oceanic and Atmospheric Administration (NOAA) lays out the formula. It’s something called the Rothfusz Regression equation, and it goes like this:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;HI = -42.379 + 2.04901523&lt;em&gt;T + 10.14333127&lt;/em&gt;RH - .22475541&lt;em&gt;T&lt;/em&gt;RH - .00683783&lt;em&gt;T&lt;/em&gt;T - .05481717&lt;em&gt;RH&lt;/em&gt;RH + .00122874&lt;em&gt;T&lt;/em&gt;T&lt;em&gt;RH + .00085282&lt;/em&gt;T&lt;em&gt;RH&lt;/em&gt;RH - .00000199&lt;em&gt;T&lt;/em&gt;T&lt;em&gt;RH&lt;/em&gt;RH&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Where &lt;strong&gt;T&lt;/strong&gt; is temperature and &lt;strong&gt;RH&lt;/strong&gt; is relative humidity. Simple, right? Not so fast! It turns out there are a bunch of caveats to that (simple) equation. For instance, if the relative humidity is less than 13% and the temperature is between 80ºF and 112ºF, then you have to adjust the heat index by subtracting the following &lt;strong&gt;Adjustment&lt;/strong&gt; from it:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;ADJUSTMENT = [(13-RH)/4]*SQRT{[17-ABS(T-95.)]/17}&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Ok, fine. But wait, there’s more! If the relative humidity is above 85%, and the temperature is between 80ºF and 112ºF, then you need to &lt;strong&gt;add&lt;/strong&gt; the following &lt;strong&gt;Adjustment&lt;/strong&gt; to it:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;ADJUSTMENT = [(RH-85)/10] * [(87-T)/5]&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Outstanding! We’re finally there … wait, no we’re not there yet. If the heat index is below 80ºF, then you don’t need to use that calculation to determine the heat index. You can use a more simple Steadman equation:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;HI = 0.5 * {T + 61.0 + [(T-68.0)&lt;em&gt;1.2] + (RH&lt;/em&gt;0.094)}&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;So first you calculate the heat index using that ‘simple’ equation – and, according to NOAA, you average that with the temperature reading. If that is less than 80ºF, you have your answer. If not, you need to proceed with the Rothfusz regression and add (or subtract) any adjustments, if required.&lt;/p&gt;

&lt;p&gt;See? Simple, really.&lt;/p&gt;
&lt;h2&gt;Doing it in Flux&lt;/h2&gt;
&lt;p&gt;Here’s where some complicated Flux comes into play. You see, my temperature and humidity readings are in different measurements, so first there’s the task of building the tables, and joining them (yay for the beauty of cross-measurement math in Flux!).&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;humidity = from(bucket: "telegraf")
  |&amp;gt; range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |&amp;gt; filter(fn: (r) =&amp;gt; r._measurement == "environment" and (r._field == "humidity"))
  |&amp;gt; aggregateWindow(every: 30s, fn: mean)
  |&amp;gt; fill(column: "_value", usePrevious: true)
  |&amp;gt; keep(columns: ["_value", "_time"])

temperature = from(bucket: "telegraf")
  |&amp;gt; range(start: v.timeRangeStart)
  |&amp;gt; filter(fn: (r) =&amp;gt; r._measurement == "temperature" and (r._field == "temp_f"))
  |&amp;gt; aggregateWindow(every: 30s, fn: mean)
  |&amp;gt; fill(column: "_value", usePrevious: true)
  |&amp;gt; keep(columns: ["_value", "_time"])
  |&amp;gt; yield(name: "Temperature")&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That gets me my 2 tables of values. (Side note: I yield the Temperature table so that my graph will show both the temperature and the heat index on the same graph.)&lt;/p&gt;

&lt;p&gt;Next, I join the 2 tables:&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;first_join = join(tables: {temperature: temperature, humidity: humidity}, on: ["_time"])
  |&amp;gt;map(fn: (r) =&amp;gt; ({temperature: r._value_temperature, humidity:r._value_humidity, _time: r._time}))
  |&amp;gt; keep(columns: ["_time", "humidity", "temperature"])&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So now I have a single table, aligned on time, with columns for &lt;code class="language-markup"&gt;temperature&lt;/code&gt; and &lt;code class="language-markup"&gt;humidity&lt;/code&gt;. All that’s left is to do the calculation:&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;|&amp;gt; map(fn: (r) =&amp;gt; ({t: r.temperature, h: r.humidity}))
  |&amp;gt; map(fn: (r) =&amp;gt; ({
     r with heatIndex:
        if ((0.5 * (r.t + 61.0 + ((r.t-68.0)*1.2) + (r.h*0.094)))/2.0) &amp;lt; 80.0 then (0.5 * (r.t + 61.0 + ((r.t - 68.0)*1.2) + (r.h*0.094)))
        else if ( r.h &amp;lt; 13.0 and r.t &amp;gt; 80.0) then ((-42.379 + 2.04901523*r.t + 10.14333127*r.h - .22475541*r.t*r.h - .00683783*r.t*r.h - .05481717*r.t*r.h + .00122874*r.t*r.t*r.h + .00085282*r.t*r.h*r.h - .00000199*r.t*r.t*r.h*r.h - (((13.0-r.h)/4.0)*math.sqrt(x: ((17.0-math.abs(x: (r.t-95.0))/17.0))))))
        else if r.h &amp;gt; 85.0 and r.t &amp;gt;= 80.0 and r.t &amp;lt;= 87.0 then ((-42.379 + 2.04901523*r.t + 10.14333127*r.h - .22475541*r.t*r.h - .00683783*r.t*r.h - .05481717*r.t*r.h + .00122874*r.t*r.t*r.h + .00085282*r.t*r.h*r.h - .00000199*r.t*r.t*r.h*r.h) + (( r.h-85.0 )/10.0) *((87.0-r.t)/5.0))
        else (-42.379 + 2.04901523*r.t + 10.14333127*r.h - .22475541*r.t*r.h - .00683783*r.t*r.h - .05481717*r.t*r.h + .00122874*r.t*r.t*r.h + .00085282*r.t*r.h*r.h - .00000199*r.t*r.t*r.h*r.h)
        })
  )
  |&amp;gt; map(fn: (r) =&amp;gt; ({_value: r.heatIndex, _time: r._time}))
  |&amp;gt; yield(name: "HeatIndex")&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I told you it was complicated Flux!&lt;/p&gt;

&lt;p&gt;But in the end, you can then have a graph that shows the actual temperature and the calculated Heat Index in the same table cell:&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/Screen-Shot-2019-08-22-at-9.14.44-AM.png"&gt;&lt;img class="aligncenter size-full wp-image-235712" src="/images/legacy-uploads/Screen-Shot-2019-08-22-at-9.14.44-AM.png" alt="" width="1689" height="460" /&gt;&lt;/a&gt;And that’s a pretty cool thing!&lt;/p&gt;
&lt;h2&gt;Next step&lt;/h2&gt;
&lt;p&gt;Since that’s a lot of complicated Flux. The next step is to pull that all into Flux functions so that you can simply call &lt;code class="language-markup"&gt;|&amp;gt; HeatIndex()&lt;/code&gt; on your table with &lt;code class="language-markup"&gt;temperature&lt;/code&gt; and &lt;code class="language-markup"&gt;humidity&lt;/code&gt; columns and get back the proper table with the resulting heat indexes all calculated for you. So I’m in the process of adding the &lt;code class="language-markup"&gt;HeatIndex()&lt;/code&gt; function to Flux so you can have pretty Flux when you calculate your heat indexes.&lt;/p&gt;

&lt;p&gt;I’m planning to add in the calculation for Ideal Gas Law (an easy one) and Wind Chill as well (another ugly one!) to this future package as well as converters from ºF to ºC as well, so if you have any other ideas for things that you would use for environmental calculations, please &lt;a href="https://twitter.com/intent/follow?screen_name=davidgsIoT"&gt;reach out&lt;/a&gt; and let me know!&lt;/p&gt;
</description>
      <pubDate>Fri, 23 Aug 2019 07:00:22 -0700</pubDate>
      <link>https://www.influxdata.com/blog/hiding-complexity-with-custom-functions-calculating-heat-index/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/hiding-complexity-with-custom-functions-calculating-heat-index/</guid>
      <category>Use Cases</category>
      <category>Developer</category>
      <category>Product</category>
      <author>David G. Simmons (InfluxData)</author>
    </item>
    <item>
      <title>How to Output Data from Flux to MQTT Natively</title>
      <description>&lt;h2&gt;Writing data from InfluxDB to MQTT using Flux&lt;/h2&gt;
&lt;p&gt;I started using the Open Source (OSS) version of InfluxDB v2.0 very early on in the Alpha releases. Even in the early releases, I was very enamored with the way things were shaping up. But as you know, I do a &lt;strong&gt;lot&lt;/strong&gt; of IoT builds, and use InfluxDB for all of it, so there were a few things I needed it to do that it just didn’t, yet.&lt;/p&gt;

&lt;p&gt;One of the things I have all my IoT Demos do is to write out alerts to an &lt;a href="https://www.influxdata.com/mqtt/"&gt;MQTT&lt;/a&gt; broker. I have other IoT Devices that read from that broker, and take actions based on what messages they receive. But InfluxDB 2.0 Alpha had no real output capabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There is an alerting framework that is coming to InfluxDB 2.0 very soon, but a) it wasn’t available then and b) I needed it now.&lt;/p&gt;

&lt;p&gt;What to do? Well, Flux is an extensible language, so I decided to extend the language to write to MQTT. First, it’s important to note that Flux has 2 language constructs for reading and writing data: &lt;code class="language-markup"&gt;from()&lt;/code&gt; and &lt;code class="language-markup"&gt;to()&lt;/code&gt;. If you’ve written any Flux at all, you’ll recognize the &lt;code class="language-markup"&gt;from()&lt;/code&gt; syntax as being how you get data back from InfluxDB. The &lt;code class="language-markup"&gt;to()&lt;/code&gt; business is a bit harder. Built into the language is the ability to write back to InfluxDB, using the &lt;code class="language-markup"&gt;to()&lt;/code&gt; syntax. I also found a &lt;code class="language-markup"&gt;to()&lt;/code&gt; extension for http that allows you to write the results of your Flux query out to an http end-point. At least I now had a starting place!&lt;/p&gt;
&lt;h2&gt;Adding MQTT to Flux&lt;/h2&gt;
&lt;p&gt;I began poking around in the Flux code to see how the http &lt;code class="language-markup"&gt;to()&lt;/code&gt; method was implemented and quickly saw that it would be almost trivial to use this same framework for MQTT, so I copied all the code fro the http &lt;code class="language-markup"&gt;to()&lt;/code&gt; output and began working to move it over to MQTT. As with all of these things, it was a little less ‘trivial’ than I at first thought, but after a few weeks of on-again off-again work, I had a working output to MQTT from Flux!&lt;/p&gt;

&lt;p&gt;First, I had to define what options the MQTT output would need, and I settled on a sort of default minimum set of options:&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;golang
type ToMQTTOpSpec struct {
    Broker string `json:"broker"`
    Name string `json:"name"`
    Topic string `json:"topic"`
    Message string `json:"message"`
    ClientID string `json:"clientid"`
    Username string `json:"username"`
    Password string `json:"password"`
    QoS int `json:"qos"`
    NameColumn string `json:"nameColumn"` // either name or name_column must be set, if none is set try to use the "_measurement" column.
    Timeout time.Duration `json:"timeout"` // default to something reasonable if zero
    NoKeepAlive bool `json:"noKeepAlive"`
    TimeColumn string `json:"timeColumn"`
    TagColumns []string `json:"tagColumns"`
    ValueColumns []string `json:"valueColumns"`
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course, not all of those are &lt;strong&gt;required&lt;/strong&gt;, but I’ll go through the ones that are.&lt;/p&gt;

&lt;p&gt;First, of course, you need to define a Broker. This is the URL of the MQTT broker that you want to use. In your URL your broker should be identified as either &lt;code class="language-markup"&gt;tcp&lt;/code&gt;, &lt;code class="language-markup"&gt;ws&lt;/code&gt; or &lt;code class="language-markup"&gt;tls&lt;/code&gt; so &lt;code class="language-markup"&gt;tcp://mqtt.mybroker.com:1883&lt;/code&gt; would be what it’s looking for. Most of the rest are, by and large, optional to a degree. &lt;strong&gt;If&lt;/strong&gt; you supply a &lt;code class="language-markup"&gt;Username&lt;/code&gt; then you &lt;strong&gt;must also&lt;/strong&gt; supply a password. You can’t have one without the other! Also, if you don’t supply a &lt;code class="language-markup"&gt;Topic&lt;/code&gt; then one will be created for you by stringing together all of the tags returned from your query. I’d advise giving a topic, as a topic of &lt;code class="language-markup"&gt;/tag1/tag_2/tag_3/...&lt;/code&gt; would be less than ideal in a lot of situations.&lt;/p&gt;
&lt;h2&gt;How to use this new thing?&lt;/h2&gt;
&lt;p&gt;I’m glad you asked! First, it’s not actually part of Flux just yet. I have submitted a PR, it has been accepted, but (as of this writing) has not been merged. If you want to build your own version of Flux in order to get your hands on this &lt;em&gt;now&lt;/em&gt; then you’ll need to pull the branch and build from source. See the &lt;a href="https://github.com/influxdata/flux/pull/1653"&gt;MQTT PR&lt;/a&gt; and go from there.&lt;/p&gt;

&lt;p&gt;Once you’ve done that, the Flux code to start writing to an MQTT broker is actually trivial! You’ll want to create a Task in the InfluxDB 2.0 UI, and then you can paste in the following code:&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;import "mqtt"
from(bucket: "telegraf")
    |&amp;gt; range(start: -task.every)
    |&amp;gt; filter(fn: (r) =&amp;gt;
        (r._measurement == "cpu"))
    |&amp;gt; filter(fn: (r) =&amp;gt;
        (r._field == "usage_system"))
    |&amp;gt; filter(fn: (r) =&amp;gt;
        (r.cpu == "cpu-total"))
    |&amp;gt; last()
    |&amp;gt; mqtt.to(
        broker: "tcp://davidgs.com:8883",
        topic: "cpu",
        clientid: "cpu-flux",
        valueColumns: ["_value"],
        tagColumns: ["cpu", "host"],
    )&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will write the last CPU &lt;code class="language-markup"&gt;usage_system&lt;/code&gt; value to your MQTT broker. Using the UI, you can decide how frequently you want this data written.&lt;/p&gt;
&lt;h2&gt;A few things to note&lt;/h2&gt;
&lt;p&gt;It’s important to realize that &lt;a href="https://w2.influxdata.com/blog/use-flux-to-group-shape-and-analyze-your-time-series-data/"&gt;Flux returns all of its data from queries as tables&lt;/a&gt;. The reason the above Task uses the &lt;code class="language-markup"&gt;last()&lt;/code&gt; function is to limit the returned value to a table with exactly one row. The MQTT &lt;code class="language-markup"&gt;to()&lt;/code&gt; function will write the whole table to the broker, as line-protocol. If your query returns a very large table, be prepared for your MQTT broker to get a very large table as the message payload.&lt;/p&gt;

&lt;p&gt;In addition, if your query returns multiple tables, the MQTT &lt;code class="language-markup"&gt;to()&lt;/code&gt; function will write one message &lt;strong&gt;per table&lt;/strong&gt; with each message containing an entire table. If this is not the behavior you want, you should think about how to craft your query such that it returns a single (preferably small) table as the results.&lt;/p&gt;

&lt;p&gt;You may also have noticed an optional field &lt;code class="language-markup"&gt;Message&lt;/code&gt; above. If what you’d like is to send a pre-defined message instead of a table of results, you can define the &lt;code class="language-markup"&gt;message&lt;/code&gt; parameter in your call to &lt;code class="language-markup"&gt;to()&lt;/code&gt; and that message will be sent.
So far, I’ve been using this for about 2 months with fantastic results! I’m able to control some IoT devices based on the readings from other IoT devices and it works great!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; The PR for this has now been merged into the master branch so it should be showing up in a release of Flux soon!&lt;/p&gt;
</description>
      <pubDate>Fri, 16 Aug 2019 07:00:58 -0700</pubDate>
      <link>https://www.influxdata.com/blog/how-to-output-data-from-flux-to-mqtt-natively/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/how-to-output-data-from-flux-to-mqtt-natively/</guid>
      <category>Use Cases</category>
      <category>Product</category>
      <author>David G. Simmons (InfluxData)</author>
    </item>
    <item>
      <title>Publishing Data to InfluxDB from Swift</title>
      <description>&lt;p&gt;I’ve been a very busy man. It was only a few days ago that I wrote about a new InfluxDB library for writing data from Arduino devices to InfluxDB v2 and here I am again, writing about a &lt;strong&gt;new&lt;/strong&gt; library for writing data to InfluxDB. This time, it’s in Swift. Now your native Apple apps can write data directly to InfluxDB v2.0 with ease.&lt;/p&gt;

&lt;p&gt;It’s a really simple library to use, and you can download the entire Xcode project for it from my &lt;a href="https://github.com/davidgs/InfluxData-Swift"&gt;GitHub&lt;/a&gt;. You can use it to write single data points to the DB, or to do bulk writes of any size. Here’s a quick tutorial on how to use it.&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-swift"&gt;let influxdb = InfluxData()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That gets you an instance of the &lt;code class="language-markup"&gt;InfluxData&lt;/code&gt; class. Once you have that, you’ll need to set some configuration parameters for it.&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-markup"&gt;influxdb.setConfig(server: "serverName", port: 9999, org: "myOrganization", bucket: "myBucket", token: "myToken")&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You will, of course, need to set all those values according to your InfluxDB v2.0 server’s settings. You can also set the time precision with&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-swift"&gt;let myPrecision = DataPrecision.ms // for Milliseconds, 'us' for microseconds, and 's' for seconds
influxdb.setPrecision(precision: myPrecision)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point, you’re ready to start collecting data and sending it to InfluxDB v2.0! For each data point you collect and want to store, you will create a new &lt;code class="language-markup"&gt;Influx&lt;/code&gt; object to hold the tags and data.&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-swift"&gt;let point: Influx = Influx(measurement: "myMeasurement")
point.addTag(name: "location", value: "home")
point.addTag(name: "server", value: "home-server")
if !point.addValue(name: "value", value: 100.01) {
    print("Unknown value type!\n)
}
if !point.addValue(name: "value", value: 55) {
    print("Unknown value type!\n)
}
if !point.addValue(name: "value", value: true) {
    print("Unknown value type!\n)
}
if !point.addValue(name: "value", value: "String Value" {
    print("Unknown value type!\n)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, it accepts Integers, floating point values, Booleans and strings. If it cannot determine the data type, it will return the Boolean &lt;code class="language-markup"&gt;false&lt;/code&gt; so it’s always a good idea to check the return value.&lt;/p&gt;

&lt;p&gt;For best performance, we recommend writing data in batches to InfluxDB, so you’ll need to prepare the data to go into a batch. This is easy to do with a call to&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-swift"&gt;influxdb.prepare(point: point)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And when it’s time to write the batch, just call&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-swift"&gt;if influxdb.writeBatch() {
    print("Batch written successfully!\n)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again, &lt;code class="language-markup"&gt;writeBatch()&lt;/code&gt; returns a Boolean on success or failure, so it’s a good idea to check those values.&lt;/p&gt;

&lt;p&gt;If you want to write each data point as it comes in, just take the data point you created above and call&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-swift"&gt;influxdb.writeSingle(dataPoint: point)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can write data to multiple measurements simultaneously as each data point is initialized with its measurement, and you can add as many tags and fields as you’d like.&lt;/p&gt;

&lt;p&gt;This is really the first pass at the InfluxDB v2.0 Swift library as I’ll be adding the ability to query, create buckets, and a lot of other features of the &lt;a href="https://docs.influxdata.com/flux/v0.12/introduction/getting-started/"&gt;Flux language&lt;/a&gt; to the library in the future, but since what most people want to do right away is write data to the database, I thought I’d get this out there.&lt;/p&gt;

&lt;p&gt;I hope this is helpful! I know it has been for me! You see, I have lately been just using my Mac laptop to grab data off of my Bluetooth CO2 sensor that I built. In order to do that, I built a small BLE application that connects to the sensor, subscribes to the data ID, and constantly writes the data to InfluxDB. Needless to say, I used this library and have been scraping this data and storing it happily.&lt;/p&gt;

&lt;p&gt;I’d love to hear what you plan to do with a Swift Library for 2.0 so be sure to &lt;a href="http://twitter.com/follow?user=davidgsIoT"&gt;follow me&lt;/a&gt; on twitter and let me know what you’re doing!&lt;/p&gt;
</description>
      <pubDate>Thu, 28 Mar 2019 13:32:26 -0700</pubDate>
      <link>https://www.influxdata.com/blog/publishing-data-to-influxdb-from-swift/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/publishing-data-to-influxdb-from-swift/</guid>
      <category>Product</category>
      <category>Use Cases</category>
      <category>Developer</category>
      <author>David G. Simmons (InfluxData)</author>
    </item>
    <item>
      <title>Writing Data from Arduino to InfluxDB v2</title>
      <description>&lt;p&gt;As InfluxData moves ever closer to releasing v2.0, it’s becoming increasingly important to be able to get data &lt;strong&gt;into&lt;/strong&gt; InfluxDBv2, of course. Makes sense, right? Since the vast majority (like, indistinguishable from 100%) of my data comes from IoT devices, I decided it was time to start making those devices InfluxDB v2-capable.&lt;/p&gt;

&lt;p&gt;I’m happy to say that the first step in that direction is now complete! One of my favorite sensors is a particulate matter sensor that measures the amount of &lt;strong&gt;very small&lt;/strong&gt; particulate in the air (from 2.5µM to 100µM in diameter). This stuff, it turns out, is really, &lt;em&gt;really&lt;/em&gt; bad for you. So knowing how much is in the air is a good idea. To that end, I ordered one of these sensors from Adafruit.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;It’s small and easy to hook up to pretty much anything since it just spews data out via UART. Since I have a giant pile of ESP8266 boards lying around (I typically order them by the dozens since they are so cheap and easy to deal with), I hooked it up to one of those. The code was simple, thanks to Adafruit providing it, and there was a handle InfluxDB library to write data with, but it only supported InfluxDB v1.x. The first thing I did (because I was in a hurry) was to grab the 1.x library and just re-write it for 2.x. This took me about 1/2 hour or less, and it worked great! (you can use that version &lt;a href="https://github.com/davidgs/ESP8266_Influx_DB_V2"&gt;here&lt;/a&gt; if you’d like). That really wasn’t the &lt;em&gt;right&lt;/em&gt; solution though. So today I went back and created a proper fork of the &lt;a href="https://github.com/tobiasschuerg/ESP8266_Influx_DB"&gt;original repository&lt;/a&gt;, and updated it to support either version 1.x or version 2.x of InfluxDB. I’ve of course submitted a proper Pull Request against the original library and hope that it will be accepted/merged soon.&lt;/p&gt;

&lt;p&gt;Let’s walk through what it takes to use this new library then. It’s dead simple, really. At least with Arduino, all you have to do is add the Library, then include it in your sketch:&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-javascript"&gt;#include &amp;lt;InfluxDb.h&amp;gt;
//#include &amp;lt;InfluxDataV2.h&amp;gt; // if you want to use the other library I built and that's in my GitHub 
#define INFLUXDB_HOST "myhost.com"
Influxdb influx(INFLUXDB_HOST);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That gets you started. Next, you’re going to need some specific information from your InfluxDB v2.0 (alpha still!) installation. Notably, you will need the &lt;code class="language-markup"&gt;organization&lt;/code&gt;, &lt;code class="language-markup"&gt;bucket&lt;/code&gt;, and &lt;code class="language-markup"&gt;token&lt;/code&gt; that are associated with your account. You can find these by pointing your web browser at your InfluxDB server, port 9999, entering your username and password, and going to the Configuration Page.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;You can then enter them into the Arduino Sketch:&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-javascript"&gt;influx.setBucket("myBucket");
influx.setVersion(2);
influx.setOrg("myOrg");
influx.setPort(9999);
influx.setToken("myToken");&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once you’ve done that, in your &lt;code class="language-markup"&gt;setup()&lt;/code&gt; function, you can start writing data to your v2.0 Influx server!&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-javascript"&gt;void loop() {
    loopCount++;
    InfluxData row("temperature");row.addTag("device", "alpha");
    row.addTag("sensor", "one");
    row.addTag("mode", "pwm");
    row.addValue("loopCount", loopCount);
    row.addValue("value", random(10, 40));
    influx.write(row);delay(5000);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See? I told you it was easy!&lt;/p&gt;
</description>
      <pubDate>Tue, 26 Mar 2019 09:01:46 -0700</pubDate>
      <link>https://www.influxdata.com/blog/writing-data-from-arduino-to-influxdb-v2/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/writing-data-from-arduino-to-influxdb-v2/</guid>
      <category>Product</category>
      <category>Use Cases</category>
      <category>Developer</category>
      <author>David G. Simmons (InfluxData)</author>
    </item>
    <item>
      <title>Practical Uses of Cross-Measurement Math in Flux</title>
      <description>&lt;p&gt;I’ve been spending a lot of time lately with the 2.0 Alpha releases and I’m here to tell you: some of the new things coming are really, really cool! Especially for IoT. The one I’ve been using lately has been the ability to do math across measurements, which is really a game-changer for IoT data in InfluxDB.&lt;/p&gt;

&lt;p&gt;Let’s look at why here for a minute. As you probably know, I’ve been building out a bunch of IoT sensors that stream data to various instances of InfluxDB. One of the main sensors I use is a SenseAir K-30 CO2 sensor. It’s a fabulously accurate sensor, though it’s not cheap. I’ve been using it for a year or so and it’s extremely reliable and accurate, but I was wondering about how the temperature and the pressure might affect the CO2 readings. What I found was, of course, these things do, in fact, matter.&lt;/p&gt;

&lt;p&gt;I read up on it &lt;a href="https://www.bapihvac.com/application-note/effects-of-temperature-and-barometric-pressure-on-co2-sensors-application-note/"&gt;here&lt;/a&gt;, but essentially the temperature and atmospheric pressure affect the amount of gas inside the measuring chamber, not the concentration, so one should compensate for that. It’s a fairly simple calculation to do using some reference values like absolute zero and the pressure at sea level.&lt;/p&gt;

&lt;p&gt;We’ll use the &lt;a href="https://en.wikipedia.org/wiki/Ideal_gas_law"&gt;Ideal Gas Law&lt;/a&gt; formula:&lt;/p&gt;
&lt;p style="text-align: center;"&gt;ppm CO2 corrected = ppm CO2 measured * ((Temp measured * Pressure Reference ) / (Pressure measured * Temp Reference))&lt;/p&gt;
&lt;p&gt;Great. Easy! Almost. I have a temperature/pressure sensor that stores values in an ‘environment’ measurement in my InfluxDB instance. My CO2 sensor stores its readings in a “k30_reader” measurement. If you’re not using Flux, you already see the problem here: These values live in different measurements, so I either can’t do this calculation or I have to do a fair amount of gymnastics to somehow rewrite all these values into a common measurement first. Neither is a really viable answer, is it?&lt;/p&gt;

&lt;p&gt;Enter Flux and cross-measurement maths! So let’s walk through how I accomplished this in Flux (with a &lt;em&gt;ton&lt;/em&gt; of help from fellow DevRel Anais, among others). A little refresher on how Flux returns values first. Let’s remember that when I submit a query in Flux, I get back a table of values. This becomes important as we walk through how the Flux query is built, so keep that in mind.&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-javascript"&gt;Tref = 298.15
Pref = 1013.25

Tmeas = from(bucket: "telegraf")
   |&amp;gt; range(start: v.timeRangeStart)
   |&amp;gt; filter(fn: (r) =&amp;gt; r._measurement == "environment" and (r._field == "temp_c"))
   |&amp;gt; fill(column: "_value", usePrevious: true)
   |&amp;gt; aggregateWindow(every: 30s, fn: mean)
   |&amp;gt; keep(columns: ["_value", "_time"])&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First I’ve defined my reference temperature and pressure values. The reference temperature is usually 25ºC, converted to Kelvin, and the reference Pressure is sea level. I then query values of the Measured Temperature Values and store it in a table called ‘Tmeas’. If I &lt;code class="language-markup"&gt;yield()&lt;/code&gt; on this table, I’ll see my temperature values:&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/Screen-Shot-2019-03-19-at-4.21.00-PM.png"&gt;&lt;img class="aligncenter size-large wp-image-224032" src="/images/legacy-uploads/Screen-Shot-2019-03-19-at-4.21.00-PM-1024x413.png" alt="" width="1024" height="413" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I then repeat this for the CO2 and Pressure values:&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-javascript"&gt;CO2meas = from(bucket: "telegraf")
   |&amp;gt; range(start: v.timeRangeStart)
   |&amp;gt; filter(fn: (r) =&amp;gt; r._measurement == "k30_reader" and (r._field == "co2"))
   |&amp;gt; fill(column: "_value", usePrevious: true)
   |&amp;gt; aggregateWindow(every: 30s, fn: mean)
   |&amp;gt; keep(columns: ["_value", "_time"])&lt;/code&gt;&lt;/pre&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-javascript"&gt;Pmeas = from(bucket: "telegraf")
   |&amp;gt; range(start: v.timeRangeStart)
   |&amp;gt; filter(fn: (r) =&amp;gt; r._measurement == "environment" and (r._field == "pressure"))
   |&amp;gt; fill(column: "_value", usePrevious: true)
   |&amp;gt; aggregateWindow(every: 30s, fn: mean)
   |&amp;gt; keep(columns: ["_value", "_time"])&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Great! I now have 3 tables with all the values I need to do my calculations. All I have to do now is pull them all together, and I’ll do that through a series of &lt;code class="language-markup"&gt;join()&lt;/code&gt; statements:&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-javascript"&gt;first_join = join(tables: {CO2meas: CO2meas, Tmeas: Tmeas}, on: ["_time"])
    |&amp;gt; fill(column: "_value_CO2meas", usePrevious: true)
    |&amp;gt;fill(column: "_value_CO2meas", value: 400.00)
    |&amp;gt; fill(column: "_value_Tmeas",usePrevious: true)
    |&amp;gt;fill(column: "_value_Tmeas", value: 20.0)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This first &lt;code class="language-markup"&gt;join()&lt;/code&gt; gets me a table that contains the CO2 and temperature values, so I’m part way there.&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-javascript"&gt;second_join = join(tables: {first_join: first_join, Pmeas: Pmeas}, on: ["_time"])
   |&amp;gt;fill(column: "_value", usePrevious: true)
   |&amp;gt;fill(column: "_value", value: 1013.25)
   |&amp;gt;map(fn: (r) =&amp;gt; ({_time: r._time, _Pmeas: r._value, _CO2meas:r._value_CO2meas, _Tmeas:r._value_Tmeas}))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This second &lt;code class="language-markup"&gt;join()&lt;/code&gt; gets me a table with all the measured values in it! You’d think I’d be done, but in order to do the final calculation, since I’m joining on &lt;code class="language-markup"&gt;time&lt;/code&gt;, I have to build a final table where I fill in the reference values for each row in the table.&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-javascript"&gt;final = second_join
    |&amp;gt;map(fn: (r) =&amp;gt; ({Pmeas: r._Pmeas, CO2meas:r._CO2meas, Tmeas:r._Tmeas, Pref: Pref, Tref: Tref, _time: r._time,}))
    |&amp;gt; keep(columns: ["_time", "CO2meas", "Pmeas", "Tmeas", "Pref", "Tref"])&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So now I can create a final table and calculate the compensated CO2 value, for each row (time).&lt;/p&gt;
&lt;pre class="line-numbers"&gt;&lt;code class="language-javascript"&gt;CO2corr = final
    |&amp;gt; map(fn: (r) =&amp;gt; ({"_time": r._time, "CO2-Measured": r.CO2meas, "CO2-Adjusted": r.CO2meas * (((r.Tmeas + 273.15) * r.Pref) / (r.Pmeas * r.Tref))}))
   |&amp;gt; yield()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since this is my final table, I call &lt;code class="language-markup"&gt;yield()&lt;/code&gt; at the end so that the values will get displayed.&lt;/p&gt;

&lt;p&gt;And now I have a graph that shows the raw, measured CO2 value and the compensated CO2 value! All done on-the-fly using Flux’s cross-measurement math!&lt;/p&gt;

&lt;p&gt;&lt;a href="/images/legacy-uploads/Screen-Shot-2019-03-18-at-3.56.28-PM.png"&gt;&lt;img class="aligncenter size-full wp-image-224033" src="/images/legacy-uploads/Screen-Shot-2019-03-18-at-3.56.28-PM.png" alt="" width="278" height="485" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve actually been wanting to do this sensor compensation for a &lt;strong&gt;long&lt;/strong&gt; time and I’m thrilled that I can now do it quickly and easily using Flux! So what will you do with cross-measurement math in Flux? Feel free to tweet me your ideas, solutions, etc. &lt;a href="https://twitter.com/davidgsIoT"&gt;@davidgsIoT&lt;/a&gt;!&lt;/p&gt;
</description>
      <pubDate>Fri, 22 Mar 2019 08:00:18 -0700</pubDate>
      <link>https://www.influxdata.com/blog/practical-uses-of-cross-measurement-math-in-flux/</link>
      <guid isPermaLink="true">https://www.influxdata.com/blog/practical-uses-of-cross-measurement-math-in-flux/</guid>
      <category>Product</category>
      <category>Use Cases</category>
      <category>Developer</category>
      <author>David G. Simmons (InfluxData)</author>
    </item>
  </channel>
</rss>
