<?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: Oliver Thamm</title>
    <description>The latest articles on DEV Community by Oliver Thamm (@oliverxapixio).</description>
    <link>https://dev.to/oliverxapixio</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%2F459108%2F7cbb9495-cc18-4378-adfc-e17c30725686.jpg</url>
      <title>DEV Community: Oliver Thamm</title>
      <link>https://dev.to/oliverxapixio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/oliverxapixio"/>
    <language>en</language>
    <item>
      <title>How to build an office alarm system with Home IoT devices</title>
      <dc:creator>Oliver Thamm</dc:creator>
      <pubDate>Wed, 14 Oct 2020 15:11:17 +0000</pubDate>
      <link>https://dev.to/oliverxapixio/how-to-build-an-office-alarm-system-with-home-iot-devices-167d</link>
      <guid>https://dev.to/oliverxapixio/how-to-build-an-office-alarm-system-with-home-iot-devices-167d</guid>
      <description>&lt;h2&gt;
  
  
  Building a security system with alarm and notifications using Home IoT hardware
&lt;/h2&gt;

&lt;p&gt;Office security is a 100 billion dollar business. Trustworthy products and service providers come with a steep price tag. Specialised cloud-based solution providers come with the potential threat of misusing or selling your office’s IoT sensor data. Data privacy raises major concerns, since every supplier with access to data gets a full view of an office schedule—how employees behave and when the office is empty.&lt;/p&gt;

&lt;p&gt;Hiring a security service company offers a good alternative to this. The security company could install a closed IIoT system within your company WiFi. But such services are very expensive.&lt;/p&gt;

&lt;p&gt;A less pricey option is to use consumer market Home IoT devices and install it yourself. In this blog post, we show you how to make your own security system with just a bit of time and hacker spirit. Save a lot of money and no trust into an external security service company is required. We will show how to set up a text notification, play an alarm sound and change the color of a light to red when a motion sensor detects movement after 8pm.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LhZSpiXE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k04w5zpbl5ceknt0qb0t.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LhZSpiXE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k04w5zpbl5ceknt0qb0t.gif" alt="iiot office alarm system"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the Home IoT motion sensor with lights
&lt;/h2&gt;

&lt;p&gt;In Home IoT applications, motions sensors are often used to switch lights on only when they register movement within their range. In the right room this saves energy and money. The motion sensors keep associated lights switched off and switch them on only for a configurable timespan when they detect movement. If there is further movement around the sensor, the devices will remain switched on.&lt;/p&gt;

&lt;p&gt;Home applications for this type of setup are often found in garages or driveways. Rooms in which people sit and stay usually don’t benefit. Also, pets can create unwanted side effects when they trigger motion sensors. In a small office, usage patterns are different to a private home. In an office before and after a workday, movement should trigger an alarm. Plus, it’s the kind of thing an office manager would like to know about.&lt;/p&gt;

&lt;p&gt;For this post, we use the motion sensors of a global swedish furniture chain. Follow the basic setup as described by the vendor and our &lt;a href="https://dev.to/oliverxapixio/how-to-setup-a-local-api-for-home-iot-devices-in-your-office-using-wifi-3173"&gt;initial post&lt;/a&gt;. Screw open the back of the motion sensor device so you can see three buttons and put in batteries. Pair the motion sensor first with your hub device and then with the lights.&lt;/p&gt;

&lt;p&gt;Go into the manufacturer's mobile app and test your setup. Use the app to name your light, e.g “room-a”.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a service to report events and trigger an alarm
&lt;/h2&gt;

&lt;p&gt;To access and react to events sent by the motion sensor, find out the device’s communication protocol. If the device communicates using keep-alive connections, e.g. CoaP or MQTT, then observe it’s messages. Otherwise frequently request, or poll, the device’s state.&lt;/p&gt;

&lt;p&gt;The hardware we use works best when it does not directly observe the motion sensor but observes the associated light instead. That too is handled by drivers in &lt;a href="https://github.com/xapix-io/iiot_server"&gt;IIoT Server&lt;/a&gt;. In Xapix IIoT Server drivers for this are included and you only need to configure the devices in the file &lt;code&gt;./config/devices.yml&lt;/code&gt;. Additionally configure your speaker and put your desired alarm audio file, e.g. “alarm.wav”, into a new folder &lt;code&gt;./tmp/iiot_office/media/&lt;/code&gt;.&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;devices&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;home_office&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;main_tradfri_hub&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;model_class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TradfriHub&lt;/span&gt;
      &lt;span class="na"&gt;mac&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;XX:XX:XX:XX:XX:XX&lt;/span&gt;
      &lt;span class="na"&gt;devices&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;room_a_bulb&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;model_class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TradfriLedColorBulb&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;room-a&lt;/span&gt;
    &lt;span class="na"&gt;speaker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;model_class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Audio&lt;/span&gt;
      &lt;span class="na"&gt;installation_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;iiot_office&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One option to trigger alarms and send text notifications is to create your own local web server application. The web application needs to have an HTTP POST endpoint accepting JSON formatted data. In the code for the endpoint,put the decision logic for the alarm and notifications. Enter the endpoint’s URL as an environment variable named &lt;code&gt;EVENT_WEBHOOK_URL&lt;/code&gt; for IIoT server.&lt;/p&gt;

&lt;p&gt;A second option is to use our free Xapix Community Edition and it’s web UI to trigger data pipelines which change the light color, play an alarm sound and send text notifications.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/468129090" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;If interested, then &lt;a href="https://xapix.io/post/how-to-build-an-office-alarm-system-with-home-iot-devices?utm_source=dev-to&amp;amp;utm_medium=editorial&amp;amp;utm_campaign=home_automation_3"&gt;&lt;strong&gt;&amp;gt; CONTINUE READING &amp;lt;&lt;/strong&gt;&lt;/a&gt; the full version of this article on our Xapix blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join our Home IoT community
&lt;/h2&gt;

&lt;p&gt;We are working on follow-ups to this blog series to inspire you with new ideas about how to use the &lt;a href="https://github.com/xapix-io/iiot_server"&gt;Xapix IIoT Server&lt;/a&gt; once you have set it up. We would love to hear your ideas and collaborate!&lt;/p&gt;

&lt;p&gt;Contact me on &lt;a href="https://twitter.com/xapix_io/status/1316392832496791553"&gt;Twitter&lt;/a&gt; if you would like to discuss this tutorial or if you have questions or feedback about the Xapix Community Edition. We look forward to hearing from you!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>python</category>
      <category>api</category>
      <category>iot</category>
    </item>
    <item>
      <title>How to detect data anomalies using a simulator and an IIoT factory model</title>
      <dc:creator>Oliver Thamm</dc:creator>
      <pubDate>Wed, 07 Oct 2020 09:56:55 +0000</pubDate>
      <link>https://dev.to/oliverxapixio/how-to-detect-data-anomalies-using-a-simulator-and-an-iiot-factory-model-5hdm</link>
      <guid>https://dev.to/oliverxapixio/how-to-detect-data-anomalies-using-a-simulator-and-an-iiot-factory-model-5hdm</guid>
      <description>&lt;h2&gt;
  
  
  Detecting data anomalies in a constant event stream of IIoT sensor data
&lt;/h2&gt;

&lt;p&gt;Manufacturing companies look for ways to automatically analyze recorded sensor data, detect errors and improve production processes. Anomaly detection in industrial sensor data is a challenge to many manufacturing companies, because there exists a large variety of sensor types and manufacturers on the IIoT market.&lt;/p&gt;

&lt;p&gt;Popular IIoT applications often require anomaly detection, such as asset monitoring and alerting, predictive maintenance for machines and safety and security on the factory floor.&lt;/p&gt;

&lt;p&gt;In this post, we show how to create a constant event stream of sensor data using our IIoT factory model, and how to manually add data anomalies. Record the event stream data and add the recordings to our simulator to replay them at will. Set up data pipelines to detect those data anomalies and respond to them by sending text notifications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hiYvwVxe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f7abirl51nel38wl8iow.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hiYvwVxe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f7abirl51nel38wl8iow.gif" alt="Manually add anomalies with IIoT factory model"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Producing a continuous stream of valid data with the camera-based product reader
&lt;/h2&gt;

&lt;p&gt;In a &lt;a href="https://www.xapix.io/post/explaining-iiot-and-event-streaming-projects-with-models"&gt;previous blog post&lt;/a&gt;, we explained how to build an IIoT conveyor belt model. We made a camera-based product-reader model that reads product data from QR code strips. We also showed how to flexibly create such QR codes from a JSON file with product data.&lt;/p&gt;

&lt;p&gt;In this post, we use the same method and add dimension measures as attributes “x_mm” and “y_mm” and values around 800.0 to the input data file. Vary each dimension measure by less than plus or minus 0.5 mm of tolerance and generate the QR codes. This is a sample of our product data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;                            
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"123456"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"variant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"x_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"800.21"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"y_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"799.85"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"123451"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"variant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"x_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"800.49"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"y_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"799.96"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&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="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Print the QR codes and glue them together to a strip long enough to wrap around the conveyor belt. Start the IIoT factory model and it produces a constant stream of product data including the dimension measures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manually adding data anomalies to the product data stream
&lt;/h2&gt;

&lt;p&gt;Again, use the QR code maker script to create and print product data encoded in QR codes. This time they shall contain data anomalies. Create a new JSON file and vary at least one dimension value per record by more than plus or minus 0.5 mm of tolerance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"123456"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"variant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"x_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"800.21"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"y_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"799.45"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"123451"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"variant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"x_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"800.51"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"y_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"799.96"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"123452"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"variant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"x_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"799.81"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"y_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"798.85"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"123457"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"variant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"red"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"x_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"801.22"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"y_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"800.35"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Generate the QR codes, print them and cut them out with scissors. Glue the QR codes to the back of coasters so we can throw them onto the conveyor belt of our IIoT factory model at will.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recording the event stream of IIoT sensor data for a simulator
&lt;/h2&gt;

&lt;p&gt;With the QR code strip and coasters with encoded product data in place, start the factory model and watch the event stream get printed to the monitor of your Raspberry Pi. Per default, the model will only produce valid product data as encoded on the QR code strip in an endless loop. Throw a coaster onto the conveyor belt and the model will add the respective data anomaly to the event stream. The factory model does not know what constitutes a data anomaly and will only report sensor data as measured.&lt;/p&gt;

&lt;p&gt;Run the IIoT factory model two times for five minutes each and record the data. The first time do nothing with the coasters and therefore record a flawless stream of valid product data. The second time, use the coasters to add a few data anomalies to the recorded event stream. The HTTP API of our Raspberry Pi provides POST endpoints to start and stop the recording. The response body of the stop endpoint contains the recorded data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EIJW1AOd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ipm29pzdzxnfqzyfsn9d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EIJW1AOd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ipm29pzdzxnfqzyfsn9d.png" alt="Recording IIoT factory model data via API"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Ruby Sinatra code for recording the event streams we added to the open source Xapix &lt;a href="https://github.com/xapix-io/iiot_server"&gt;IIoT Server&lt;/a&gt; looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="vg"&gt;$rec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;recording?&lt;/span&gt;
  &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="vg"&gt;$rec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;record_event!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'value'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'data'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'timestamp'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="vg"&gt;$rec&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;recording?&lt;/span&gt;
  &lt;span class="n"&gt;event&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="s1"&gt;'/start_rec'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'already recording'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;recording?&lt;/span&gt;
  &lt;span class="vg"&gt;$rec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;
&lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;StandardError&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
  &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;error: &lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;message&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="s1"&gt;'/stop_rec'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'not recording'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;recording?&lt;/span&gt;
  &lt;span class="n"&gt;res_payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$rec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;
  &lt;span class="vg"&gt;$rec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
  &lt;span class="n"&gt;res_payload&lt;/span&gt;
&lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;StandardError&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
  &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;error: &lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;message&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Make sure to call record_event! in your event endpoint&lt;/span&gt;
&lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="s1"&gt;'/event'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parse_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;record_event!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;#...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The recorded data returned by the HTTP API has lots of doubles. This is because the limited number of product data QR codes on the conveyor belt repeat in a loop. To get unique product IDs and to save the recorded data to a trace file in which each line holds the data record of a single event in JSON format, run a script on the data that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'json'&lt;/span&gt;                 

&lt;span class="n"&gt;res_body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'[{ YOUR JSON RESPONSE }, ...]'&lt;/span&gt; 
&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"./iiot_factory_product_dimensions_regular.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; 
  &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res_body&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'value'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Run the factory model twice to get two trace files, one with anomalies and one without any. The trace files can have hundreds of records and look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"100001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"variant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"x_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"800.21"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"y_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"799.85"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1601371059.556218&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"100002"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"variant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"x_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"799.81"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"y_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"799.85"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1601371062.339446&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"100003"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"variant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"gray"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"x_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"800.11"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"y_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"800.05"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1601371065.3834803&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"100004"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"variant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"gray"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"x_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"800.33"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"y_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"799.65"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1601371067.9262557&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"100005"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"variant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"x_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"800.33"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"y_mm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"799.77"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;1601371070.470316&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Replaying multiple event streams of IIoT sensor data with a simulator
&lt;/h2&gt;

&lt;p&gt;We at Xapix added our two trace files to our simulator to replay the trace files on the simulator at will. In a previous blog post, we briefly explained how to build such a simulator yourself, in case you do not want to use ours.&lt;/p&gt;

&lt;p&gt;Replay the trace file without anomalies multiple times simultaneously to simulate a lot of regular data volume. Next, replay a single trace file containing an anomaly in the simulator. The anomaly is hard to detect in the regular data traffic and therefore a good test for anomaly detection software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anomaly detection data pipelines
&lt;/h2&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/464162939" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;You could either build by hand a software script with decision logic reporting the data anomalies if an incident is recorded on your own Kafka server. It would need to work well with your simulator.&lt;/p&gt;

&lt;p&gt;Or &lt;a href="https://www.xapix.io/post/how-to-detect-data-anomalies-using-a-simulator-and-an-iiot-factory-model?utm_source=dev-to&amp;amp;utm_medium=editorial&amp;amp;utm_campaign=IIoT_3"&gt;&lt;strong&gt;&amp;gt; CONTINUE READING &amp;lt;&lt;/strong&gt;&lt;/a&gt; the full version of the article on our Xapix blog and create a free &lt;a href="https://cloud.xapix.io/users/sign_up"&gt;Xapix Community Edition&lt;/a&gt; account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join our Home IoT community
&lt;/h2&gt;

&lt;p&gt;We are working on follow-ups to this blog series to inspire you with new ideas about how to use the &lt;a href="https://github.com/xapix-io/iiot_server"&gt;Xapix IIoT Server&lt;/a&gt; once you have set it up. We would love to hear your ideas and collaborate!&lt;/p&gt;

&lt;p&gt;Contact me on &lt;a href="https://twitter.com/xapix_io/status/1313779422558916608"&gt;Twitter&lt;/a&gt; if you would like to discuss this tutorial or if you have questions or feedback about the Xapix Community Edition. Or really anything else as well. We look forward to hearing from you!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>python</category>
      <category>raspberrypi</category>
      <category>iot</category>
    </item>
    <item>
      <title>Building an IIoT conveyor-belt model and incident simulation</title>
      <dc:creator>Oliver Thamm</dc:creator>
      <pubDate>Thu, 10 Sep 2020 18:24:43 +0000</pubDate>
      <link>https://dev.to/oliverxapixio/building-an-iiot-conveyor-belt-model-and-incident-simulation-596l</link>
      <guid>https://dev.to/oliverxapixio/building-an-iiot-conveyor-belt-model-and-incident-simulation-596l</guid>
      <description>&lt;h2&gt;
  
  
  Staging a critical machine incident that causes an emergency shutdown of the model
&lt;/h2&gt;

&lt;p&gt;To detect and immediately react to incidents is a classic use case for Industrial Internet of Things (IIoT) applications. Of course, you don’t want to mess with production machinery in a factory to develop your software application. Using a model and simulator to stage, record, and replay incidents provides flexibility to prototype, iterate, and test your software without touching actual factory machines. &lt;/p&gt;

&lt;p&gt;Simulating incidents requires a baseline data stream that represents normal operations of a machine. For example, a constant flow of product data. A singular event then interrupts such a constant stream. This might be something like sensor data of an incident.&lt;/p&gt;

&lt;p&gt;For the abstract IIoT factory model, we want to stage several scenarios with various product data and incident data. We want to flexibly develop software or data pipelines that react to sensor data that indicates incidents. And we want to see the results of such reactions to sensor data in the real world equipment of our model.&lt;/p&gt;

&lt;p&gt;In our &lt;a href="https://www.xapix.io/post/explaining-iiot-and-event-streaming-projects-with-models?utm_source=dev-to&amp;amp;utm_medium=editorial&amp;amp;utm_campaign=IIoT_2"&gt;previous blog post&lt;/a&gt;, we explained how to create a camera-based product-reader model reading QR code strips. We also showed how to flexibly create such QR codes from a JSON file with product data. &lt;/p&gt;

&lt;p&gt;In this blog post, we share how to create a physical conveyor-belt model and stage an incident that causes an emergency shutdown of the model.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/456618628" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Staging an incident with the product reader
&lt;/h2&gt;

&lt;p&gt;To prepare incident data, use the same method as for producing the QR code based product data stream you find in our &lt;a href="https://www.xapix.io/post/explaining-iiot-and-event-streaming-projects-with-models?utm_source=dev-to&amp;amp;utm_medium=editorial&amp;amp;utm_campaign=IIoT_2"&gt;previous post&lt;/a&gt;. Instead of strips with multiple product variants, we produce a strip with incident data compatible with our open source &lt;a href="https://github.com/xapix-io/iiot_server"&gt;IIoT Server&lt;/a&gt;. Our file in &lt;code&gt;./qr_data/&lt;/code&gt; is called “incidents.json” and looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"incident"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"FOREIGN_OBJECT"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"incident"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"PERSON_TOO_CLOSE"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"incident"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"FIRE_ON_BELT"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, run the script &lt;code&gt;ruby ./make_qr_strip.rb incidents&lt;/code&gt;, open the generated HTML page “./qr_strips/incidents.html” in a web browser, and print it. Cut out the QR codes and glue them to the back of a coaster. We recommend writing the type of incident on each coaster to recognize them later.&lt;/p&gt;

&lt;p&gt;Put the incident-data coasters on your product data strip and watch the product-reader model read the incident data and print it to your screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RihqKyuf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k0bzaxuhkd7q2xqbwvxq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RihqKyuf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k0bzaxuhkd7q2xqbwvxq.gif" alt="Simulating an incident with the QR code reader"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to 3D-print the IIoT factory model’s conveyor belt rollers
&lt;/h2&gt;

&lt;p&gt;We want to send the warmest thank you to the etventure tech guild team for their great support on building the model’s hardware and sensors! This wouldn’t be possible without your help.&lt;/p&gt;

&lt;p&gt;Our factory model has a total of four 3D-printed rollers, each of which consists of two halves that screw together. One of these rollers propels the conveyor belt and has a special design. Instead of an even surface, this roller has a lot of grip and a gear attached, so the motor can propel it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VdH00zj3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8x1wthvro4mpgqch91mz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VdH00zj3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8x1wthvro4mpgqch91mz.png" alt="IIoT factory model conveyor belt rollers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Building the IIoT factory model is a work in progress, and we welcome you ideas for optimizations on our &lt;a href="http://bit.ly/discord-xapix"&gt;Discord channel&lt;/a&gt;. Find the current versions of our 3D models for &lt;a href="https://drive.google.com/drive/folders/1zaFz0kv7Y718SpSdSUdhBIl6pyaEznmv"&gt;download here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to laser cut the IIoT factory model frame
&lt;/h2&gt;

&lt;p&gt;Thanks to our friends at the etventure tech guild team, we are using a wooden laser cut frame for the model. If you have carpentry skills, you could build a similar frame, of course. &lt;/p&gt;

&lt;p&gt;Our IIoT-factory model frame has two side panels with a couple of notches for the 3D printed  rollers, the stabilizing bridges and the motor. The stabilizing bridges between the side panels are in a separate model file. Their current versions are all available for &lt;a href="https://drive.google.com/drive/folders/1IFp1qiRdNMg9SclNcTOfTneNpd3vCmdl"&gt;download here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yU1AcwfE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/eyamudzc6go33yghg75s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yU1AcwfE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/eyamudzc6go33yghg75s.png" alt="3D laser cut model of IIoT factory model frame"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to attach a stepper motor to the IIoT factory model frame
&lt;/h2&gt;

&lt;p&gt;Select a corner of your frame to place your stepper motor and mount it. Do not tighten the screws too much, since adjustments may be necessary after mounting the rollers. On the inner side of the panel, attach the small 3D printed cogwheel to the stepper motor.&lt;/p&gt;

&lt;p&gt;Pick the 3D printed roller with the attached gear, turn it so that the gear is in the corner of the motor and put it in the notch. Adjust the position of the motor so that the roller rests easy, but the motor’s small cogwheel still tightly fits into the roller’s gear.&lt;/p&gt;

&lt;p&gt;The stepper motor we use on our IIoT factory model is set up with the x-axis slot of an Arduino motor controller. The motor can only be started by supplying power via USB and stopped by pulling the USB plug. We added a startup sequence that slowly accelerates the motor up to a certain speed to optimize grip on the conveyor belt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VoCmIlSz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/plrzky4ybnag8bprjzpu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VoCmIlSz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/plrzky4ybnag8bprjzpu.png" alt="IIoT stepper motor on IIoT factory model"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cutting the conveyor belt of the IIoT factory model
&lt;/h2&gt;

&lt;p&gt;The ideal material for your conveyor belt is thin, light, flexible, and durable. Depending on the total size of your model, the length of your raw material could be important, too.&lt;/p&gt;

&lt;p&gt;For our IIoT factory, we used a 2m-long travel yoga mat. They are made of rubber—an ideal material— and are much thinner and lighter than regular yoga mats. We just cut it to the right length and glued the ends together to form a belt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assembling the IIoT factory model prototype
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r-Nl5Shz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rzkw5o17jfsa94dvdw5q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r-Nl5Shz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rzkw5o17jfsa94dvdw5q.png" alt="IIoT factory model explainer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s put together the components. Put up the wooden side panels stabilized with bridges. Put the conveyor belt correctly around the rollers and fit them into the notches. Make sure the one gear attached to a roller is in the corner where the motor is. Adjust the motor’s position so it’s cogwheel fits with the roller gear. Wire up the Arduino motor controller with the motor plug the motor’s USB power supply into a smart plug configured to work with &lt;a href="https://github.com/xapix-io/iiot_server"&gt;IIoT Server&lt;/a&gt;. Make sure initially your smart plug is switched off.&lt;/p&gt;

&lt;p&gt;Put your product-reader model on top of your IIoT-factory model and make sure the distance and angle of its camera enable it to read the QR code product data strips on the conveyor belt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the IIoT factory model and recording the sensor events for the simulator
&lt;/h2&gt;

&lt;p&gt;Once everything is assembled, put your product-data strip on the conveyor belt and keep an incident coaster in your hand to throw in at will. Start the conveyor belt by switching on the smart plug by sending an HTTP request to your local IIoT Server API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --location --request POST &amp;lt;YOUR_RASPBERRY_LOCAL_IP&amp;gt;:4567/device_cmd' \
--header 'Content-Type: application/json' \
--data-raw '{
    "device": "conveyor_belt_plug",
    "action": {
        "cmd": "plug_on"
    }
}'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Throw in your incident coaster and the event data should be printed to screen. As we do this we record a trace file that we can replay in the simulator later. It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"name":"product_id","value":"123456","data":{"variant":"2b","color":"green"},"timestamp":1598365799.4526498}
{"name":"product_id","value":"123452","data":{"variant":"2b","color":"green"},"timestamp":1598365804.0941744}
{"name":"product_id","value":"123458","data":{"variant":"2c","color":"gray"},"timestamp":1598365809.2619932}
{"name":"product_id","value":"123451","data":{"variant":"2b","color":"green"},"timestamp":1598365816.2038214}
{"name":"product_id","value":"123457","data":{"variant":"2d","color":"red"},"timestamp":1598365820.4342263}
{"name":"product_id","value":"123453","data":{"variant":"2b","color":"green"},"timestamp":1598365824.5778954}
{"name":"incident","value":"FIRE_ON_BELT", "timestamp":1598365826.5328884}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You could either build by hand a software script with decision logic sending the HTTP request to switch off your smart plug if an incident is recorded on your own Kafka server. It would need to work well with the simulator we suggested building in our initial post.&lt;/p&gt;

&lt;p&gt;Or &lt;strong&gt;&lt;a href="https://www.xapix.io/post/building-an-iiot-conveyor-belt-model-and-incident-simulation?utm_source=dev-to&amp;amp;utm_medium=editorial&amp;amp;utm_campaign=IIoT_2"&gt;&amp;gt; CONTINUE READING &amp;lt;&lt;/a&gt;&lt;/strong&gt; the full version of the article on our Xapix blog and create a free &lt;a href="https://cloud.xapix.io/users/sign_up"&gt;Xapix Community Edition&lt;/a&gt; account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join our Home IoT community
&lt;/h2&gt;

&lt;p&gt;We are working on follow-ups to this blog series and will post updates in our Discord community to inspire you with new ideas about how to use the Xapix IIoT Server once you have set it up. We would love to hear your ideas and collaborate! &lt;/p&gt;

&lt;p&gt;Contact us on our &lt;a href="http://bit.ly/discord-xapix"&gt;Discord community channel&lt;/a&gt; if you would like to discuss this tutorial or if you have questions or feedback about the Xapix Community Edition. Or really anything else as well. We look forward to hearing from you!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>python</category>
      <category>iot</category>
      <category>raspberrypi</category>
    </item>
    <item>
      <title>Automating office lights and plugs to save energy with Home IoT devices</title>
      <dc:creator>Oliver Thamm</dc:creator>
      <pubDate>Fri, 04 Sep 2020 09:02:38 +0000</pubDate>
      <link>https://dev.to/oliverxapixio/automating-office-lights-and-plugs-to-save-energy-with-home-iot-devices-363l</link>
      <guid>https://dev.to/oliverxapixio/automating-office-lights-and-plugs-to-save-energy-with-home-iot-devices-363l</guid>
      <description>&lt;h2&gt;
  
  
  Small offices can save 20% of electricity and help save the environment
&lt;/h2&gt;

&lt;p&gt;Automating light management using industrial internet of things (IIoT) devices in offices promises 20% energy savings and 100% environmental karma points. Large offices spend substantial amounts of money on service companies installing hardware and administration software. For small and medium sized offices, such investments will never pay off. &lt;/p&gt;

&lt;p&gt;Here is an example calculation for a typical small company in a western country. If your office is consuming 10,000 kWh per year at an electric power price of $0.25 per kWh, the energy bill is $2.500 per year. Results vary, but most IIoT providers promise a 20% electricity saving using effective light management. That’s $500 per year saved in this example.&lt;/p&gt;

&lt;p&gt;In this post we suggest DIY approaches to achieving the same results in small offices. All you need are some common Home IoT devices sold in consumer markets, the IIoT Server Open Source Software, and a little bit of hacker spirit. Invest half a day of work, have fun, save some money, and do something good for our planet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyv2zeo3b2v4q9d1tdquo.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyv2zeo3b2v4q9d1tdquo.gif" alt="Switch off office Home IoT lights"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ensure Home IoT lights and plugs are switched off at night
&lt;/h2&gt;

&lt;p&gt;Ensuring lights and other devices are switched off — not just in standby mode — at night is a simple way to save electricity and money. Offices are often empty over the weekend and for 12 to 14 hours per work day, for example between 7:00 p.m. and 9:00 a.m..&lt;/p&gt;

&lt;p&gt;By running a scheduled task each evening, it becomes easy to prevent lights, monitors and power chargers from running when no one is around. By running an additional scheduled task in the morning you can make sure the smart plugs are switched on for employee’s convenience.&lt;/p&gt;

&lt;p&gt;To run such scheduled tasks you need Home IoT devices that are connected and programmable via your local office WiFi. We suggest running our open source &lt;a href="https://github.com/xapix-io/iiot_server" rel="noopener noreferrer"&gt;IIoT Server&lt;/a&gt; software on a Raspberry Pi, as described in our &lt;a href="https://dev.to/oliverxapixio/how-to-setup-a-local-api-for-home-iot-devices-in-your-office-using-wifi-3173"&gt;introduction blog post&lt;/a&gt; to this series. The IIoT Server supports a growing number of Home IoT devices. In our setup, we use lights from a global Swedish furniture chain and the Tp Link HS100 power plugs. Whatever hardware you use, set it up as described by their vendors. Then install IIoT Server as an additional way to send commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Home IoT devices to receive commands from IIoT Server
&lt;/h2&gt;

&lt;p&gt;Set up your lights as described in our &lt;a href="https://dev.to/oliverxapixio/how-to-setup-a-local-api-for-home-iot-devices-in-your-office-using-wifi-3173"&gt;introduction blog post&lt;/a&gt;. We added a second light from the same manufacturer as a reading lamp. Connect the monitors and chargers on your desk with a multiplug socket and use a TP-Link HS100 smart plug as a gatekeeper to power supply.&lt;/p&gt;

&lt;p&gt;Configure your devices in IIoT Server in the ./config/devices.yml file. Ours looks like this:&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;devices&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;office&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                      
    &lt;span class="na"&gt;room_a_bulb&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;               
      &lt;span class="na"&gt;model_class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TradfriLedColorBulb&lt;/span&gt;
      &lt;span class="na"&gt;hub_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;65537&lt;/span&gt;            
    &lt;span class="na"&gt;room_a_lamp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;model_class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TradfriLedColorBulb&lt;/span&gt;
      &lt;span class="na"&gt;hub_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;65540&lt;/span&gt;
    &lt;span class="na"&gt;room_a_plug&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;model_class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Hs100&lt;/span&gt;       
      &lt;span class="na"&gt;ip&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;192.168.10.77&lt;/span&gt;       
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the IIoT Server by following the manual. Test your setup and switch on all your lights and plugs, for example by using cURL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --location --request POST 'localhost:4567/device_cmd' \
--header 'Content-Type: application/json' \
--data-raw '{
    "device": "room_a_lamp",
    "action": {
        "cmd": "bulb_on"
    }
}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One option to schedule the execution of your commands at a specific time is to use the crontab program on your Raspberry Pi. Create two software scripts making HTTP calls to your IIot Server, one to switch all lights and plugs off and another to switch on all plugs. Finally, set up your desired schedule for running these scripts in crontab.&lt;/p&gt;

&lt;p&gt;A second option is to use our free &lt;a href="https://cloud.xapix.io/users/sign_up" rel="noopener noreferrer"&gt;Xapix Community Edition&lt;/a&gt; and it’s web UI to set up a scheduler and trigger pipelines that switch on and off your lights and plugs.&lt;/p&gt;

&lt;p&gt;If interested, then &lt;strong&gt;&lt;a href="https://xapix.io/post/automating-office-lights-and-plugs-to-save-energy-with-home-iot-devices?utm_source=dev-to&amp;amp;utm_medium=editorial&amp;amp;utm_campaign=home_automation_2" rel="noopener noreferrer"&gt;&amp;gt; CONTINUE READING &amp;lt;&lt;/a&gt;&lt;/strong&gt; the full version of this article on our Xapix blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join our Home IoT community
&lt;/h2&gt;

&lt;p&gt;We are working on follow-ups to this blog series and will post updates in our Discord community to inspire you with new ideas about how to use the Xapix IIoT Server once you have set it up. We would love to hear your ideas and collaborate! &lt;/p&gt;

&lt;p&gt;Contact us on our &lt;a href="http://bit.ly/discord-xapix" rel="noopener noreferrer"&gt;Discord community channel&lt;/a&gt; if you would like to discuss this tutorial or if you have questions or feedback about the Xapix Community Edition. Or really anything else as well. We look forward to hearing from you!&lt;/p&gt;

</description>
      <category>iot</category>
      <category>api</category>
      <category>ruby</category>
      <category>python</category>
    </item>
    <item>
      <title>How to setup a local API for Home IoT Devices in your office using WiFi</title>
      <dc:creator>Oliver Thamm</dc:creator>
      <pubDate>Thu, 03 Sep 2020 11:02:27 +0000</pubDate>
      <link>https://dev.to/oliverxapixio/how-to-setup-a-local-api-for-home-iot-devices-in-your-office-using-wifi-3173</link>
      <guid>https://dev.to/oliverxapixio/how-to-setup-a-local-api-for-home-iot-devices-in-your-office-using-wifi-3173</guid>
      <description>&lt;h2&gt;
  
  
  Small offices can profit from Home IoT devices made programmable with OSS
&lt;/h2&gt;

&lt;p&gt;If you are working in an office with up to eight rooms, you may find yourself overlooked by commercial IoT solutions promising the typical benefits, e.g. energy savings, security improvements, disaster detection and other facility management improvements.&lt;/p&gt;

&lt;p&gt;Luckily there are plenty of Home IoT product series on the market that you can use. Unfortunately, they are usually closed proprietary systems and don’t target specific office needs. At Xapix, we decided to open source our Industrial Internet of Things (IIoT) Server software that enables you to access common consumer-market Home IoT devices and develop custom office automation software against an HTTP API in your local office WiFi.&lt;/p&gt;

&lt;p&gt;If you’d like an even simpler solution, you can enable the IIoT Server’s bridge to the free Xapix Community Edition and use the ready-made Xapix data pipelines. &lt;/p&gt;

&lt;p&gt;This blog series explains how to save money, and improve security and convenience in small offices using consumer-market Home IoT devices. &lt;/p&gt;

&lt;h2&gt;
  
  
  Get started with a Home IoT test environment
&lt;/h2&gt;

&lt;p&gt;This post sets up the technical work for the rest of the series with just a little bit of hacker spirit. &lt;/p&gt;

&lt;p&gt;Most Home IoT device series are closed proprietary systems that often involve a gateway hub device and a vendor mobile app. We need a way to programmatically access the Home IoT devices, e.g. via an HTTP API, from within the local office WiFi as you do not want to expose it to the internet for security reasons.&lt;/p&gt;

&lt;p&gt;Within this post, we explain how to set up a local API to a Home IoT light bulb on your development computer using our freshly released Open Source project &lt;a href="https://github.com/xapix-io/iiot_server" rel="noopener noreferrer"&gt;IIoT Server&lt;/a&gt; and test your setup with a sample HTTP request via cURL or Postman.&lt;/p&gt;

&lt;p&gt;If you have a &lt;a href="https://cloud.xapix.io/users/sign_up" rel="noopener noreferrer"&gt;free Xapix Community Edition account&lt;/a&gt;, we can even take the test setup one step further and create a Xapix pipeline. You’ll be able to turn your light bulb on and off with your web browser or cURL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fuvtincq813fgh8j449y7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fuvtincq813fgh8j449y7.gif" alt="Switch on bulb using Postman"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will describe the setup process for a Mac computer and a light bulb, hub device, and dimmer of a globally operating swedish furniture chain. Feel free to use other hardware - the setup process is likely to be similar and we’d be happy to help if you want to reach out to us directly, e.g on our &lt;a href="http://bit.ly/discord-xapix" rel="noopener noreferrer"&gt;Discord community channel&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Send HTTP API requests to your Home IoT devices within your local WiFi
&lt;/h2&gt;

&lt;p&gt;Setting up the Home IoT devices as documented by the vendor is the first step. You can follow the instructions that the maker includes in the product. For our devices, we connect the hub device to the office router and power plug and then use the vendor mobile app to register the hub device with the app. &lt;/p&gt;

&lt;p&gt;Put batteries into the dimmer and register it with the vendor mobile app by putting the dimmer close to the hub and pressing the hub’s link button. Your hub device now manages your dimmer.&lt;/p&gt;

&lt;p&gt;To register your light bulb with the app, plug in your light bulb, hold the dimmer close to the bulb and press the dimmer’s link button. Your hub now manages the dimmer, the dimmer manages your light bulb and the vendor mobile app controls everything. With the app or dimmer you should be able to dim, turn on and turn off the light bulb. The app additionally will allow you to change light color.   &lt;/p&gt;

&lt;p&gt;To do the same with cURL, Postman or your favourite programming language’s HTTP library, go ahead and download and install the Xapix &lt;a href="https://github.com/xapix-io/iiot_server" rel="noopener noreferrer"&gt;IIoT Server&lt;/a&gt; and it’s dependency software libraries. Follow the setup instructions and install the necessary libraries. &lt;/p&gt;

&lt;p&gt;One of the trickier steps is finding the IP address of your hub device within your local WiFi. You can best find it in your router’s administration UI. On a Mac you can also run &lt;code&gt;arp -a&lt;/code&gt; in a terminal window and look for the IP address associated with your hub device’s MAC address to be found on the back of the device.&lt;/p&gt;

&lt;p&gt;Once everything is configured, run the IIoT Server in a terminal window and next, to programmatically turn on your light bulb for the first time, run the cURL command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --location --request POST 'localhost:4567/device_cmd' \
--header 'Content-Type: application/json' \
--data-raw '{
    "device": "test_bulb",
    "action": {
        "cmd": "bulb_on"
    }
}’
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congratulations! You are now good to go ahead and develop your own custom applications for your local office’s IoT setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting ready to integrate cloud APIs and services with your Home IoT setup
&lt;/h2&gt;

&lt;p&gt;If you are interested in some easy paths to advanced tasks, especially when using web APIs and services, then we recommend trying our free &lt;a href="https://cloud.xapix.io/users/sign_in" rel="noopener noreferrer"&gt;Xapix Community Edition&lt;/a&gt; that seamlessly integrates with the IIoT Server when enabled. With Xapix, you can start by creating a basic data pipeline to test your setup and from that point onward, integrations with different APIs for solving your use-cases, e.g. weather forecast APIs or text notification APIs, will only be a few clicks away.&lt;/p&gt;

&lt;p&gt;If interested, then &lt;strong&gt;&lt;a href="https://www.xapix.io/post/how-to-set-up-a-local-api-for-home-iot-devices-in-your-office-using-wifi?utm_source=dev-to&amp;amp;utm_medium=editorial&amp;amp;utm_campaign=home_automation_1" rel="noopener noreferrer"&gt;&amp;gt; CONTINUE READING &amp;lt;&lt;/a&gt;&lt;/strong&gt; the full version of this article on our Xapix blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join our Home IoT community
&lt;/h2&gt;

&lt;p&gt;We are working on numerous follow-ups to this blog-series and will be posting updates regularly within our Discord community to help inspire you on how best to make use of the Xapix IIoT Server once you have set it up. We would love to hear your ideas too and collaborate on this fun project. &lt;/p&gt;

&lt;p&gt;Please contact us on our &lt;a href="http://bit.ly/discord-xapix" rel="noopener noreferrer"&gt;Discord community channel&lt;/a&gt; if you would like to discuss this tutorial or if you have questions or feedback about the Xapix Community Edition. Or really anything else as well. We look forward to hearing from you!&lt;/p&gt;

</description>
      <category>iot</category>
      <category>api</category>
      <category>python</category>
      <category>ruby</category>
    </item>
    <item>
      <title>Explaining IIoT and event streaming projects with models</title>
      <dc:creator>Oliver Thamm</dc:creator>
      <pubDate>Thu, 27 Aug 2020 15:01:31 +0000</pubDate>
      <link>https://dev.to/oliverxapixio/explaining-iiot-and-event-streaming-projects-with-models-25l6</link>
      <guid>https://dev.to/oliverxapixio/explaining-iiot-and-event-streaming-projects-with-models-25l6</guid>
      <description>&lt;h2&gt;
  
  
  How to build a hardware IIoT factory product reader and replay data using the simulator
&lt;/h2&gt;

&lt;p&gt;If you work in IT or on a developer team, you may find it hard to explain the benefits of data-heavy event streaming or industrial internet of things (IIoT) projects to external stakeholders. This is when a model or simulator comes in handy.&lt;/p&gt;

&lt;p&gt;Creating a model of the IIoT solution you're proposing can help you demonstrate how it works and why it's valuable. Enabling stakeholders to see your solution in action helps everyone better understand the technical solution — this is key to getting their support. The model needs to be functional at a moment’s notice — you never know when people will stop by! It also needs to be easily adjusted and look professional. &lt;/p&gt;

&lt;p&gt;In this post, we will start building such a factory IIoT model by building a product-reader sensor, which records data from various scenarios — such as a normal constant product flow, start-and-stop modes and different types of incidents. &lt;/p&gt;

&lt;p&gt;We want to send the warmest thank you to the etventure tech guild team for their great support on building the model’s hardware and sensors! This wouldn’t be possible without your help.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0D4DkJrg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/aexhzzjjszlqcpzjg1qb.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0D4DkJrg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/aexhzzjjszlqcpzjg1qb.jpeg" alt="etventure tech guild at work"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also share concepts and tips for developing a simulator software that replays the data streams at any point in time so programmers can use it for building their own prototypes. We already operate such a simulator software for vehicles – you can learn more in our ride hail blog post. &lt;/p&gt;

&lt;h2&gt;
  
  
  Concept for a product reader sensor in the IIoT factory model
&lt;/h2&gt;

&lt;p&gt;Factories have different types of product flows going in or out of their machines. To keep the factory model abstract and flexible enough to cover as many use cases as possible we use a paper strip with QR codes. Each QR code has JSON data with a specified format encoded but the product data content is fully flexible. This way when reading the QR codes we can simulate different types of products and incidents by just directly encoding them into QR.&lt;/p&gt;

&lt;p&gt;For the product data sensor we use a Raspberry Pi 4 with a camera module and a Python script scanning the QR codes. Additionally, the Raspberry Pi runs a software very similar to our open source IIoT Server. The changes we made allow it to record locally and also stream all sensor events and API command logs via VPN to a Kafka cluster we operate.&lt;/p&gt;

&lt;p&gt;We arrange our camera and Raspberry Pi so we can drag along the paperstrip with QR codes underneath the setup. The factory software records the events and at the same time streams them to our Kafka cluster in the cloud. The recorded events we store in a “trace file” to be replayed later by our factory simulator software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make paper strips with QR codes from JSON data
&lt;/h2&gt;

&lt;p&gt;We are using the following Ruby script to make HTML pages with SVG QR codes. Store the file locally on your computer as “./make_qr_strip.rb”.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'json'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rqrcode'&lt;/span&gt;              

&lt;span class="n"&gt;data_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ARGV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"./qr_data/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;data_file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.json"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;qr_strip_html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="s1"&gt;'&amp;lt;div&amp;gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;  
    &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&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;qrcode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;RQRCode&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;QRCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="s1"&gt;'&amp;lt;svg&amp;gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;  &lt;span class="n"&gt;qrcode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_svg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="ss"&gt;offset: &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;             
        &lt;span class="ss"&gt;color: &lt;/span&gt;&lt;span class="s1"&gt;'000'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;shape_rendering: &lt;/span&gt;&lt;span class="s1"&gt;'crispEdges'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="ss"&gt;module_size: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;standalone: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;      
      &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;/svg&amp;gt;'&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;/div&amp;gt;'&lt;/span&gt;

&lt;span class="n"&gt;html_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;style type="text/css"&amp;gt;svg { margin: 20px; width: 300px; height: 300px; }&amp;lt;/style&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;qr_strip_html&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;/body&amp;gt;&amp;lt;html&amp;gt;'&lt;/span&gt; 
&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"./qr_strips/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;data_file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;html_page&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Create a directory “./qr_data/” to store your different JSON files containing product data for your various scenarios. In our case it is named “factory_intro_1.json”. Add columns and rows as desired. The format for each file is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;                            
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"123456"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"variant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"123451"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"variant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"123452"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"variant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"product_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"123457"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"variant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"red"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Create a directory “./qr_strips/” the script stores your strips in. Finally, run &lt;code&gt;ruby ./make_qr_strip.rb &amp;lt;YOUR QR_DATA_FILENAME&amp;gt;&lt;/code&gt; (e.g. &lt;code&gt;ruby ./make_qr_strip.rb factory_intro_1&lt;/code&gt;) and find your strip as an HTML file in folder “./qr_strips/”. Open the strip file in a browser and print it out.&lt;/p&gt;

&lt;p&gt;H2: Install your Raspberry Pi camera module and use it as a product reader sensor&lt;/p&gt;

&lt;p&gt;Turn off your Raspberry Pi 4 and plug your camera module into it’s camera slot. Start the Raspberry Pi and in your “Raspberry Pi Configuration” menu in tab “Interfaces” to enable the camera.&lt;/p&gt;

&lt;p&gt;To install our QR code reader script you need Python3 and pip3 installed. Next, install the following software libraries for video stream and image processing and QR code reading via &lt;code&gt;pip3 install opencv-python imutils pyzbar&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Store the following script locally, e.g. in a file “./product_reader.py” and start the QR code scanning product reader in a terminal with command &lt;code&gt;python3 ./product_reader.py&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;print_function&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pyzbar.pyzbar&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pyzbar&lt;/span&gt; 
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;cv2&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;picamera&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PiCamera&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;imutils.video&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;VideoStream&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;argparse&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;imutils&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;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sleep&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Start Video Stream"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;vs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VideoStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;usePiCamera&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;start&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;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;last_3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;json_type_header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'Content-Type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'application/json'&lt;/span&gt;&lt;span class="p"&gt;}&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="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;imutils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;qr_codes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pyzbar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;qr_code&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;qr_codes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;qr_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qr_code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;last_3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qr_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qr_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;# DO SOMETHING USEFUL
&lt;/span&gt;            &lt;span class="c1"&gt;# In our case a local HTTP request
&lt;/span&gt;            &lt;span class="c1"&gt;# print(resp.status_code)         
&lt;/span&gt;            &lt;span class="c1"&gt;# if resp.status_code == 400:     
&lt;/span&gt;                &lt;span class="c1"&gt;# print(resp.json())              
&lt;/span&gt;            &lt;span class="n"&gt;last_3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;last_3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qr_data&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;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Put the QR code in front of your camera and your running script should output the data encoded in your QR code. On our model we use this script to send the scanned product data to our IIoT factory server software which then will record the event and send the data to our Kafka cluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BdENPoaR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2h26o6t0w8kv1fwyi7n7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BdENPoaR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2h26o6t0w8kv1fwyi7n7.gif" alt="QR code product reader at work"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we do this we record a trace file that we can replay in the simulator later. It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"name":"product_id","value":"123456","data":{"variant":"2b","color":"green"},"timestamp":1598365799.4526498}
{"name":"product_id","value":"123452","data":{"variant":"2b","color":"green"},"timestamp":1598365804.0941744}
{"name":"product_id","value":"123458","data":{"variant":"2c","color":"gray"},"timestamp":1598365809.2619932}
{"name":"product_id","value":"123451","data":{"variant":"2b","color":"green"},"timestamp":1598365816.2038214}
{"name":"product_id","value":"123457","data":{"variant":"2d","color":"red"},"timestamp":1598365820.4342263}
{"name":"product_id","value":"123453","data":{"variant":"2b","color":"green"},"timestamp":1598365824.5778954}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, you have 2 options. Either you could build a simulator script yourself reading the trace file and all it’s events. For example, you could group all events of a certain time interval and then iterate over these event groups, stream them to your own Kafka cluster and pause for the time interval length in between.&lt;/p&gt;

&lt;p&gt;Or create a free &lt;a href="https://cloud.xapix.io/users/sign_up"&gt;Xapix Community Edition&lt;/a&gt; account and &lt;strong&gt;&lt;a href="https://xapix.io/post/explaining-iiot-and-event-streaming-projects-with-models?utm_source=dev-to&amp;amp;utm_medium=editorial&amp;amp;utm_campaign=IIoT"&gt;&amp;gt; CONTINUE READING &amp;lt;&lt;/a&gt;&lt;/strong&gt; the full version of the article on our Xapix blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join our IIoT community
&lt;/h2&gt;

&lt;p&gt;We are working on numerous follow-ups to this blog-series and will be posting updates regularly within our Discord community to help inspire you on building IIoT models and simulators. We would love to hear your ideas too and collaborate on this fun project. &lt;/p&gt;

&lt;p&gt;Please contact us on our &lt;a href="http://bit.ly/discord-xapix"&gt;Discord community channel&lt;/a&gt; if you would like to discuss this tutorial or if you have questions or feedback about the Xapix Community Edition. Or really anything else as well. We look forward to hearing from you.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>python</category>
      <category>iot</category>
      <category>raspberrypi</category>
    </item>
  </channel>
</rss>
