<?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: Rob</title>
    <description>The latest articles on DEV Community by Rob (@robbm1).</description>
    <link>https://dev.to/robbm1</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%2F830374%2F5391096f-0796-4eb0-bcd1-862b727802fd.jpeg</url>
      <title>DEV Community: Rob</title>
      <link>https://dev.to/robbm1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/robbm1"/>
    <language>en</language>
    <item>
      <title>Using DutyCalls for IoT applications</title>
      <dc:creator>Rob</dc:creator>
      <pubDate>Tue, 26 Apr 2022 10:26:52 +0000</pubDate>
      <link>https://dev.to/robbm1/using-dutycalls-for-iot-applications-4f4e</link>
      <guid>https://dev.to/robbm1/using-dutycalls-for-iot-applications-4f4e</guid>
      <description>&lt;p&gt;Keeping track of the measurements of all your IoT devices is very useful and sometimes even necessary. This makes it possible to intervene before problems arise. In this blog we show how you can use DutyCalls, to provide insight into the measurements of all your devices. &lt;/p&gt;

&lt;p&gt;Although we use the Python programming language in this post to explain the technical aspects, it is also interesting for non-programmers. DutyCalls can be used in a lot of other contexts. So also in non-technical environments. For information about the DutyCalls platform, please visit: &lt;a href="https://dutycalls.me"&gt;https://dutycalls.me&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting started with DutyCalls
&lt;/h2&gt;

&lt;p&gt;Before we can start monitoring our devices, we must first create a DutyCalls account. Then we need to create a workspace and set it up. Creating the account as well as the workspace is completely free.&lt;/p&gt;

&lt;p&gt;For more information about setting up a workspace, consult the official DutyCalls &lt;a href="https://docs.dutycalls.me/getting-started/"&gt;documentation&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Collecting data from a device
&lt;/h2&gt;

&lt;p&gt;Now that the DutyCalls environment has been set up, it is important to collect the data that you want to send to DutyCalls. For this tutorial, we'll be using the weather station we created for a &lt;a href="https://siridb.com/blog/using-siridb-for-iot-applications/"&gt;previous blog post&lt;/a&gt;. This weather station consists of a Raspberry PI, a Sense HAT, a Python script for collecting measurements such as temperature/air pressure/humidity and a SiriDB database for storing the measurements. Check out our previous blog for more information about this.&lt;/p&gt;

&lt;p&gt;Now take the following Python variable as an example of the script's output:&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="c1"&gt;# This is the current relative humidity, expressed in
# percentage and rounded to 2 decimal places.
&lt;/span&gt;&lt;span class="n"&gt;humidity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;44.35&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Posting the data to DutyCalls
&lt;/h2&gt;

&lt;p&gt;How can this information be made easily visible and how can you be informed if something is wrong? For example, when the humidity in your home is too high or too low. We can do this by simply creating a &lt;em&gt;Ticket&lt;/em&gt; in DutyCalls. A &lt;em&gt;Ticket&lt;/em&gt; is an object in DutyCalls that represents an event. We need to assign a number of characteristics to this &lt;em&gt;Ticket&lt;/em&gt;, so that DutyCalls knows what to do with it.&lt;/p&gt;

&lt;p&gt;For example, we could compose a Python Dictionary with the following characteristics on the basis of the measurement just mentioned:&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="n"&gt;ticket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;Humidity&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;fine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;Current&lt;/span&gt; &lt;span class="n"&gt;humidity&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;humidity&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;percent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;severity&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The above dictionary is based on a default service. You might have to change it according to your own &lt;a href="https://docs.dutycalls.me/getting-started/add-service/#configuration"&gt;service mapping&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now to post this ‘ticket’ to DutyCalls we use the &lt;a href="https://pypi.org/project/dutycalls-sdk/"&gt;dutycalls-sdk&lt;/a&gt;. A Python library with which we can easily communicate with the DutyCalls API.&lt;/p&gt;

&lt;p&gt;The use of this API does require credentials. To be specific, credentials from a DutyCalls &lt;em&gt;Service&lt;/em&gt;. For information on how to retrieve these credentials, see the DutyCalls &lt;a href="https://docs.dutycalls.me/rest-api/authentication/"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is how we authenticate with DutyCalls when using the Python 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;dutycalls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'abcdef123456'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'abcdef123456'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: You should replace these fake credentials with your own.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now all we have to do is post the dictionary named ‘ticket’ that we composed earlier!&lt;/p&gt;

&lt;p&gt;That can be done this way:&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="c1"&gt;# Create a new Ticket in DutyCalls.
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new_ticket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ticket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;Example&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Channel&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: You should replace ‘Example-Channel’ with the name of your own &lt;em&gt;Channel&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To confirm that everything went well, we check whether the newly created ticket is actually in our DutyCalls inbox. And as you can see below that is the case:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rGsWsXPV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kr428xrc8tbu3ro5lbvp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rGsWsXPV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kr428xrc8tbu3ro5lbvp.png" alt="Image description" width="880" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But what if the humidity is above a certain self-determined limit? You probably want to be notified immediately, as this can cause problems for both your health and your home. To achieve this, we're tweaking the DutyCalls related code of the script a bit:&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;dutycalls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;

&lt;span class="n"&gt;humidity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;44.35&lt;/span&gt;

&lt;span class="n"&gt;severity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;humidity&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;
&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;Humidity&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;too&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="err"&gt;!”&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;humidity&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;Humidity&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;fine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;

&lt;span class="n"&gt;ticket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;Current&lt;/span&gt; &lt;span class="n"&gt;humidity&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;humidity&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;percent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;severity&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;severity&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'abcdef123456'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'abcdef123456'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new_ticket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ticket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;Example&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Channel&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if the humidity is above 70% percent, we will receive an equivalent &lt;em&gt;Ticket&lt;/em&gt; to the one below in DutyCalls:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aOkbiVgf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hqs3utk7hoz0qdqzevc2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aOkbiVgf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hqs3utk7hoz0qdqzevc2.png" alt="Image description" width="880" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that the severity of the ticket is higher than the previous one and that an &lt;em&gt;Alert&lt;/em&gt; has also been raised. When an &lt;em&gt;Alert&lt;/em&gt; is raised in DutyCalls, the relevant user(s) will be notified about this. How the user is notified depends on the configuration in DutyCalls, but some of the methods are: push notifications (in browsers and in the mobile app), email, SMS and voice calls.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tips &amp;amp; tricks
&lt;/h2&gt;

&lt;p&gt;Below are a number of cool features of DutyCalls, which are definitely worth trying out when monitoring devices. &lt;/p&gt;

&lt;h3&gt;
  
  
  Integrations
&lt;/h3&gt;

&lt;p&gt;All kinds of applications are or can be integrated with DutyCalls. This way you can monitor your devices and use the great features of DutyCalls from within your current applications. Checkout the &lt;a href="https://docs.dutycalls.me/integrations/"&gt;documentation&lt;/a&gt;, to see how you can integrate your favorite application(s) with DutyCalls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alerts
&lt;/h3&gt;

&lt;p&gt;Would you like to determine yourself when users are notified of events? Make use of alerts. These can be configured globally per workspace or specifically per channel depending on the type of the alert. This way you can decide for yourself when alerts are raised. For more information about the types of alerts and how to configure them, visit the DutyCalls &lt;a href="https://docs.dutycalls.me/alerts/"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ignore rules
&lt;/h3&gt;

&lt;p&gt;Do you want tickets received by DutyCalls to be ignored when they meet certain conditions? Make use of “ignore rules”. These rules can be configured per channel. For more information about these rules, please visit the &lt;a href="https://docs.dutycalls.me/ignore-rules/"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Expectations
&lt;/h3&gt;

&lt;p&gt;Would you like to be notified when a certain ticket has not been received by DutyCalls? Make use of expectation rules. Expectation rules ensure that when a certain ticket is not received that is expected, an alert will be raised. These rules can be configured per channel. For more information about these rules, please visit the &lt;a href="https://docs.dutycalls.me/expectations/"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Actions
&lt;/h3&gt;

&lt;p&gt;Do you want DutyCalls to take immediate action after receiving a &lt;em&gt;Ticket&lt;/em&gt;? Make use of actions. These can be configured per channel per tag. For more information about actions and tags, please visit the &lt;a href="https://docs.dutycalls.me/actions/"&gt;documentation&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this post, you have seen that it is very easy to use DutyCalls for monitoring devices. All we had to do for this was collect relevant data from a device (humidity this case), compose a ticket based on this data and post the ticket to DutyCalls using the &lt;a href="https://github.com/transceptor-technology/python-dutycalls-sdk"&gt;Python Dutycalls SDK&lt;/a&gt;. In DutyCalls we could then see the collected data very clearly and we were notified when something was wrong.&lt;/p&gt;

&lt;p&gt;However, we have only shown a small part of the functionalities and benefits of DutyCalls in this post and we are much more curious about how you implement DutyCalls in your projects/work!&lt;/p&gt;

</description>
      <category>iot</category>
      <category>monitoring</category>
      <category>saas</category>
      <category>raspberrypi</category>
    </item>
    <item>
      <title>Using SiriDB for IoT applications</title>
      <dc:creator>Rob</dc:creator>
      <pubDate>Wed, 30 Mar 2022 10:45:28 +0000</pubDate>
      <link>https://dev.to/robbm1/using-siridb-for-iot-applications-6d6</link>
      <guid>https://dev.to/robbm1/using-siridb-for-iot-applications-6d6</guid>
      <description>&lt;p&gt;The Internet of Things has long been one of the most popular technology trends and for good reason. It offers many possibilities and advantages. This includes monitoring data, such as the temperature or air quality in a home. But this data must be stored somewhere for later use. Preferably by using a very efficient solution, because IoT devices often do not have a lot of computing power. An extremely suitable solution that can be used for this is SiriDB. A super fast and very robust time series database.&lt;/p&gt;

&lt;p&gt;In this post, we'll show you how to easily build a weather station that uses SiriDB as the database for all its measurements. For this weather station we use a Raspberry Pi (3 Model B) in combination with a Sense HAT.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Hardware&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Raspberry Pi&lt;/li&gt;
&lt;li&gt;Sense HAT&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Software&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You will need the &lt;a href="https://www.raspberrypi.org/downloads/"&gt;latest version of Raspberry Pi OS&lt;/a&gt;, which already includes the following software packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python 3&lt;/li&gt;
&lt;li&gt;Sense HAT for Python 3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If for any reason you need to install the Sense HAT package manually, execute the following command on your Raspberry Pi:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo apt-get install sense-hat&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Set up
&lt;/h2&gt;

&lt;p&gt;Now that our Raspberry Pi is ready to go, we need to follow a few steps to install SiriDB.&lt;/p&gt;

&lt;p&gt;First, install the required SiriDB dependencies:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo apt install libcleri-dev libpcre2-dev libuv1-dev libyajl-dev uuid-dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Download the source code of SiriDB:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ wget https://github.com/SiriDB/siridb-server/archive/refs/tags/2.0.46.zip&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Change the version in the URL to get the latest version of SiriDB.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now unzip the downloaded ZIP file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ unzip 2.0.46.zip&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After that, compile the source code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;siridb-server-2.0.46/Release/
&lt;span class="nv"&gt;$ &lt;/span&gt;make clean
&lt;span class="nv"&gt;$ &lt;/span&gt;make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then install SiriDB:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo make install&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Finally, install the &lt;a href="https://pypi.org/project/siridb-connector/"&gt;SiriDB Connector for Python&lt;/a&gt; with pip (recommended), which will be used in a later step:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ pip install siridb-connector&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;Great! SiriDB is now installed. But in order for SiriDB to start automatically on startup, the file below named &lt;code&gt;siridb-server.service&lt;/code&gt; needs to be added to the &lt;code&gt;/etc/systemd/system&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=SiriDB Server
After=network.target

[Service]
Environment="SIRIDB_HTTP_API_PORT=9020"
ExecStart=/usr/bin/siridb-server
StandardOutput=journal
LimitNOFILE=65535
TimeoutStartSec=10
TimeoutStopSec=300

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The environment variable &lt;code&gt;SIRIDB_HTTP_API_PORT&lt;/code&gt; must be added because if the HTTP API port is not set (or 0), the API service of SiriDB will not start. Checkout the &lt;a href="https://docs.siridb.net/getting_started/configuration/"&gt;documentation&lt;/a&gt; for more information about using environment variables with SiriDB.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we need to reload the daemon, to make the system aware of the newly added service:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo systemctl daemon-reload&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let’s enable our service so that it doesn’t get disabled when the Raspberry Pi restarts:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo systemctl enable siridb-server.service&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And now let's start our service:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo systemctl start siridb-server.service&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The SiriDB server is now running in the background. &lt;/p&gt;

&lt;p&gt;The only thing left to do in terms of configuration is to create a database in SiriDB. For this we use the &lt;a href="https://docs.siridb.net/connect/http_api/"&gt;SiriDB HTTP API&lt;/a&gt;. SiriDB has a default &lt;a href="https://docs.siridb.net/overview/service_account/"&gt;service account&lt;/a&gt; with the username &lt;code&gt;sa&lt;/code&gt; and password &lt;code&gt;siri&lt;/code&gt;, which we will use. For our tutorial we only need a second precision database. We also select a &lt;a href="https://docs.siridb.net/shards/"&gt;shard&lt;/a&gt; duration of 6 hours for this database because our measurement interval will be only a few seconds. Sometimes you may want to store one value per measurement per hour or even per day. In that case, your database will perform better by using a larger shard duration.&lt;/p&gt;

&lt;p&gt;Create the database on the SiriDB server running on port 9020 using cURL with basic authentication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="nt"&gt;--request&lt;/span&gt; POST &lt;span class="s1"&gt;'http://localhost:9020/new-database'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Basic c2E6c2lyaQ=='&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: text/plain'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--data-raw&lt;/span&gt; &lt;span class="s1"&gt;'{
    "dbname": "iot",
    "time_precision": "s",
    "buffer_size": 8192,
    "duration_num": "6h",
    "duration_log": "3d"
}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The value passed to the header parameter &lt;code&gt;Authorization&lt;/code&gt;, is the word Basic word followed by a space and a base64-encoded string &lt;code&gt;username:password&lt;/code&gt;. See the &lt;a href="https://docs.siridb.net/connect/http_api/#authentication"&gt;documentation&lt;/a&gt; for more information about authentication in SiriDB.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Collecting data
&lt;/h2&gt;

&lt;p&gt;To collect the data we use Python 3 together with the Sense HAT package.&lt;/p&gt;

&lt;p&gt;The Python script below called &lt;code&gt;sense.py&lt;/code&gt; contains the minimal code necessary to collect some key measurements using the Raspberry Pi Sense HAT and then write them to SiriDB:&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;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;sense_hat&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SenseHat&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;siridb.connector&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SiriDBClient&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;collect_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;siri&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="c1"&gt;# Start connecting to SiriDB.
&lt;/span&gt;    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;siri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Initialize the Raspberry Pi Sense HAT.
&lt;/span&gt;    &lt;span class="n"&gt;sense&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SenseHat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Make sure the script runs indefinitely.
&lt;/span&gt;        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

            &lt;span class="c1"&gt;# Get the current temperature and round it to 2 decimal places.
&lt;/span&gt;            &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sense&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_temperature&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Get the current humidity and round it to 2 decimal places.
&lt;/span&gt;            &lt;span class="n"&gt;humi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sense&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_humidity&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Get the current pressure and round it to 2 decimal places.
&lt;/span&gt;            &lt;span class="n"&gt;pres&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sense&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_pressure&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Show the current temperature on the Sense HAT.
&lt;/span&gt;            &lt;span class="n"&gt;sense&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'%s C'&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Get the current time in seconds since the Epoch.
&lt;/span&gt;            &lt;span class="n"&gt;ts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

            &lt;span class="c1"&gt;# Add the collected data to the SiriDB serie: "temperature".
&lt;/span&gt;            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;siri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&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="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;]]})&lt;/span&gt;

            &lt;span class="c1"&gt;# Add the collected data to the SiriDB serie: "humidity".
&lt;/span&gt;            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;siri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s"&gt;'humidity'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;humi&lt;/span&gt;&lt;span class="p"&gt;]]})&lt;/span&gt;

            &lt;span class="c1"&gt;# Add the collected data to the SiriDB serie: "pressure".
&lt;/span&gt;            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;siri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s"&gt;'pressure'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pres&lt;/span&gt;&lt;span class="p"&gt;]]})&lt;/span&gt;

            &lt;span class="c1"&gt;# Wait 10 seconds before retrieving new measurements.
&lt;/span&gt;            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Close all SiriDB connections.
&lt;/span&gt;        &lt;span class="n"&gt;siri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize the SiriDB client.
&lt;/span&gt;&lt;span class="n"&gt;siri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SiriDBClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'iris'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# Default username
&lt;/span&gt;    &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'siri'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# Default password
&lt;/span&gt;    &lt;span class="n"&gt;dbname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'iot'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# The name of the database we created earlier
&lt;/span&gt;    &lt;span class="n"&gt;hostlist&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="s"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;  &lt;span class="c1"&gt;# Multiple connections are supported
&lt;/span&gt;    &lt;span class="n"&gt;keepalive&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt; 
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_event_loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_until_complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collect_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;siri&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the script    to your Raspberry Pi and start it with:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ python sense.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To verify that everything is working properly you should now see a message on your Sense Hat every 10 seconds:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---klPu8Ql--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zanjdil55zkzf81rk4os.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---klPu8Ql--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zanjdil55zkzf81rk4os.jpg" alt="Raspberry Pi weather station" width="880" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Our camera couldn't capture the message from the LED matrix well, but it does show the correct temperature. (Assuming you believe us of course 🙂)&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Visualization
&lt;/h2&gt;

&lt;p&gt;That was all! Some key measurements are now automatically collected every 10 seconds and written to SiriDB.&lt;/p&gt;

&lt;p&gt;However, it would be even more valuable if some insights could also be obtained from this data. This can be done using a visualization application such as Grafana, for which SiriDB has made a ready-to-use plugin: &lt;a href="https://github.com/SiriDB/grafana-siridb-http-datasource"&gt;grafana-siridb-http-datasource&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;How Grafana can be used in combination with SiriDB is explained &lt;a href="https://siridb.com/blog/update-example-grafana-using-siridb-http-api/"&gt;here&lt;/a&gt;. But below you can already see what the measured data would look like in this application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lsMpPv9e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5c6w20oqdq46n00pm4h8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lsMpPv9e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5c6w20oqdq46n00pm4h8.png" alt="Grafana dashboard" width="880" height="550"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this blog post we have shown step by step how easy and effective it is to deploy SiriDB for IoT applications. Now you have enough information to get started with SiriDB yourself!&lt;/p&gt;

&lt;p&gt;If you want to learn more about SiriDB, you can visit the official documentation page at &lt;a href="https://docs.siridb.net"&gt;https://docs.siridb.net&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>iot</category>
      <category>timeseries</category>
      <category>database</category>
      <category>opensource</category>
    </item>
    <item>
      <title>aiowmi - A Python WMI library</title>
      <dc:creator>Rob</dc:creator>
      <pubDate>Mon, 14 Mar 2022 08:05:38 +0000</pubDate>
      <link>https://dev.to/robbm1/aiowmi-a-python-wmi-library-3nm</link>
      <guid>https://dev.to/robbm1/aiowmi-a-python-wmi-library-3nm</guid>
      <description>&lt;p&gt;In need of a solution for WMI queries from a non-Microsoft operating system? Make use of &lt;a href="https://pypi.org/project/aiowmi/"&gt;aiowmi&lt;/a&gt;! A Python library for WMI, which we have made freely available as an &lt;a href="https://github.com/cesbit/aiowmi"&gt;open source project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Read the announcement below for more information or start using &lt;strong&gt;aiowmi&lt;/strong&gt; in all your projects right away!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cesbit.com/aiowmi"&gt;https://cesbit.com/aiowmi&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>wmi</category>
      <category>windows</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
