<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Anton Karazeev</title>
    <description>The latest articles on DEV Community by Anton Karazeev (@akarazeev).</description>
    <link>https://dev.to/akarazeev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F257110%2F6dcb9901-cb2f-4dda-8613-957bffbccce6.jpg</url>
      <title>DEV Community: Anton Karazeev</title>
      <link>https://dev.to/akarazeev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/akarazeev"/>
    <language>en</language>
    <item>
      <title>Raspberry Pi, InfluxDB, Grafana, Docker</title>
      <dc:creator>Anton Karazeev</dc:creator>
      <pubDate>Thu, 15 Jun 2023 15:55:26 +0000</pubDate>
      <link>https://dev.to/akarazeev/raspberry-pi-influxdb-grafana-docker-4h2j</link>
      <guid>https://dev.to/akarazeev/raspberry-pi-influxdb-grafana-docker-4h2j</guid>
      <description>&lt;p&gt;This is going to be my first post here. And I decided to cover steps I've taken to implement the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Measure Raspberry Pi's CPU temperature,&lt;/li&gt;
&lt;li&gt;Log the data into InfluxDB,&lt;/li&gt;
&lt;li&gt;Monitor it using Grafana.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To set things up faster I'm going to use docker containers.&lt;/p&gt;

&lt;h3&gt;
  
  
  RPi's CPU temperature
&lt;/h3&gt;

&lt;p&gt;For that I decided to use Python script with installed &lt;code&gt;gpiozero&lt;/code&gt; library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;gpiozero&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CPUTemperature&lt;/span&gt;
&lt;span class="n"&gt;cpu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CPUTemperature&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Float value of e.g. &lt;code&gt;58.1&lt;/code&gt; will be stored in that variable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logging of the data into InfluxDB
&lt;/h3&gt;

&lt;p&gt;InfluxDB is an example of time series database. Previously I've never worked with one, so I decided to give it a try instead of Prometheus.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sRKlJhTw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ear4wxjykgqdj2yy9hwz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sRKlJhTw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ear4wxjykgqdj2yy9hwz.jpg" alt="Data Explorer inside InfluxDB" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What basically I need from the database is to store pushed values in it and later return them to be visualized in Grafana dashboard.&lt;/p&gt;

&lt;p&gt;In order to push values into database we are going to use following piece of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;influxdb_client&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;influxdb_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;influxdb_client.client.write_api&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SYNCHRONOUS&lt;/span&gt;

&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"INFLUXDB_BUCKET"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;org&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"INFLUXDB_ORG"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"INFLUXDB_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"INFLUXDB_URL"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;influx_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;influxdb_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InfluxDBClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;write_api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;influx_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write_api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;write_options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;SYNCHRONOUS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"measurement"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cpu"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"temperature"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;write_api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;token&lt;/code&gt; will be generated by InfluxDB after you finish setting up of account via web UI by providing &lt;code&gt;username&lt;/code&gt;, &lt;code&gt;password&lt;/code&gt;, &lt;code&gt;org&lt;/code&gt; and &lt;code&gt;bucket&lt;/code&gt;. More on that in a part about setting up of docker containers.&lt;/p&gt;

&lt;p&gt;This information can also be found on &lt;strong&gt;Get Started&lt;/strong&gt; page of InfluxDB by accessing e.g. &lt;code&gt;http://localhost:8086&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker containers
&lt;/h3&gt;

&lt;p&gt;Before we'll be able to log the values and get anything to visualize, we need to configure docker containers with relevant services. For that I'm going to use &lt;code&gt;docker-compose.yml&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Since I want to preserve all the logged data including dashboards on Grafana even when containers were removed, &lt;strong&gt;persistent volumes&lt;/strong&gt; are used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;influxdb_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;grafana_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And specified accordingly in services definition part:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;influxdb&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;influxdb&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8086:8086"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;influxdb_data:/var/lib/influxdb2&lt;/span&gt;

  &lt;span class="na"&gt;grafana&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;grafana/grafana&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3000:3000"&lt;/span&gt;
    &lt;span class="na"&gt;links&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;influxdb&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;grafana_data:/var/lib/grafana&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One can also notice that I specified &lt;code&gt;links&lt;/code&gt; property as well. This is to make things easier when referring from one container to another. E.g. when I'll be specifying URL of InfluxDB while setting up data source in Grafana, I'll simply put &lt;code&gt;http://influxdb:8086&lt;/code&gt;. Pretty neat, right?&lt;/p&gt;

&lt;p&gt;It was a bit tricky to get CPU temperature of a host machine (Raspberry Pi) from within the running docker container. &lt;a href="https://github.com/gpiozero/gpiozero/issues/891"&gt;This Issue&lt;/a&gt; on GitHub has helped me :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;monitor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;devices&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/dev/gpiomem:/dev/gpiomem&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Monitoring the data using Grafana
&lt;/h3&gt;

&lt;p&gt;Once everything else is set up we can head to Grafana web UI and create a new data source which is InfluxDB in our case.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--N-xL9VS3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2n52mdbckffq300so0ws.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N-xL9VS3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2n52mdbckffq300so0ws.jpg" alt="Configuring Data source in Grafana" width="800" height="1191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Provided screenshot will help to make it more quickly. Creating a dashboard won't be an issue too - you can write the query yourself or just copy the one provided by &lt;strong&gt;Script editor&lt;/strong&gt; inside &lt;strong&gt;Data Explorer&lt;/strong&gt; page in InfluxDB web UI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0HW9Pwrl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ws73to6z1k56ncssjyo4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0HW9Pwrl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ws73to6z1k56ncssjyo4.jpg" alt="Grafana dashboard" width="800" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Repository
&lt;/h3&gt;

&lt;p&gt;I put everything inside one repository on GitHub: &lt;a href="https://github.com/akarazeev/temp-monitor"&gt;https://github.com/akarazeev/temp-monitor&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Just download it on Raspberry Pi with &lt;code&gt;git clone https://github.com/akarazeev/temp-monitor&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Go inside &lt;code&gt;cd temp-monitor&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;And start the containers with &lt;code&gt;sudo docker compose -d&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The end!&lt;/p&gt;




&lt;p&gt;Header image was generated using Stable Diffusion with parameters &lt;code&gt;/dream prompt:header image for an article with title "raspberry pi, influxdb, grafana, docker"&lt;/code&gt;&lt;/p&gt;

</description>
      <category>raspberrypi</category>
      <category>grafana</category>
      <category>influxdb</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
