<?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: JhonLiu</title>
    <description>The latest articles on DEV Community by JhonLiu (@lsxredrain).</description>
    <link>https://dev.to/lsxredrain</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4072220%2F09724ca8-4133-4cdb-85b7-35c592d147e1.jpg</url>
      <title>DEV Community: JhonLiu</title>
      <link>https://dev.to/lsxredrain</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lsxredrain"/>
    <language>en</language>
    <item>
      <title>I Pointed My Industrial IoT Platform at My Dog — Here Is What Happened</title>
      <dc:creator>JhonLiu</dc:creator>
      <pubDate>Sat, 15 Aug 2026 01:42:00 +0000</pubDate>
      <link>https://dev.to/lsxredrain/i-pointed-my-industrial-iot-platform-at-my-dog-here-is-what-happened-5ac5</link>
      <guid>https://dev.to/lsxredrain/i-pointed-my-industrial-iot-platform-at-my-dog-here-is-what-happened-5ac5</guid>
      <description>&lt;h1&gt;
  
  
  I Pointed My Industrial IoT Platform at My Dog — Here's What Happened
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Dog Days Challenge Entry 🐶&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;My company builds industrial IoT infrastructure — 928 gateways monitoring oil wells, UAV testing lines producing 60 drones a day, maritime safety platforms with 99.9999% uptime.&lt;/p&gt;

&lt;p&gt;This weekend, I pointed that entire stack at a Golden Retriever.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;p&gt;Meet &lt;strong&gt;PawTrack&lt;/strong&gt; — a dog health monitoring demo built on DGIOT, our open-source industrial IoT platform:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Smart Collar (PawCollar-V2)
    │  MQTT · 2-second sampling
    ▼
DGIOT Platform (Erlang/OTP)
    │  300+ protocol adapters · Shadow devices · Rule engine
    ├── TDengine (time-series storage)
    ├── DLAS Ontology Engine (OWL reasoning)
    └── Dashboard (real-time vitals)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The collar streams four metrics every 2 seconds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Heart rate&lt;/strong&gt; (bpm)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Body temperature&lt;/strong&gt; (°C)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Activity level&lt;/strong&gt; (%)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Battery + RSSI&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Industrial IoT Makes Sense for Pets
&lt;/h2&gt;

&lt;p&gt;Here's the part that surprised me: &lt;strong&gt;a dog is just another telemetry source&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The industrial world has spent decades solving problems that pet tech startups are rediscovering:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Industrial Problem&lt;/th&gt;
&lt;th&gt;Pet Equivalent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Gateway goes offline in a remote oil field&lt;/td&gt;
&lt;td&gt;Dog runs out of Wi-Fi range&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sensor drift on a pressure gauge&lt;/td&gt;
&lt;td&gt;Collar temperature calibration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;False alarms flooding operators&lt;/td&gt;
&lt;td&gt;"Your dog is dying" notification at 3am&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;928 gateways to manage&lt;/td&gt;
&lt;td&gt;Multiple pets, multiple collars&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We already solved all of these for oil fields. A Golden Retriever is just a smaller, fluffier oil well.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Ontology Layer — Why It Matters
&lt;/h2&gt;

&lt;p&gt;The interesting part is our &lt;strong&gt;DLAS ontology engine&lt;/strong&gt;. Instead of hard-coded thresholds ("if temp &amp;gt; 39.5, alert"), we model &lt;em&gt;knowledge&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="n"&gt;GoldenRetriever&lt;/span&gt; &lt;span class="err"&gt;⊑&lt;/span&gt; &lt;span class="n"&gt;Dog&lt;/span&gt; &lt;span class="err"&gt;⊓&lt;/span&gt; &lt;span class="err"&gt;∃&lt;/span&gt;&lt;span class="n"&gt;hasRisk.HipDysplasia&lt;/span&gt;
&lt;span class="n"&gt;ActivityDrop&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dog&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="err"&gt;∧&lt;/span&gt; &lt;span class="n"&gt;BreedRisk&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dog&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;High&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;Alert&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;medium&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means the system &lt;em&gt;knows&lt;/em&gt; that a Golden Retriever's activity drop is more concerning than a Border Collie's — hip dysplasia is breed-specific. The ontology compiles to Erlang pattern matches, so reasoning happens at runtime speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Shadow Device
&lt;/h2&gt;

&lt;p&gt;Every physical device gets a digital twin — a &lt;code&gt;gen_statem&lt;/code&gt; process that mirrors its lifecycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;init → auth → online → {active, inactive, alert}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the collar drops offline, the shadow holds state and retries silently. The dashboard doesn't scream "DOG IS GONE" — it waits, because shadows absorb network chaos. This is the same mechanism that keeps oil field gateways calm during sandstorms.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Demo
&lt;/h2&gt;

&lt;p&gt;The live demo simulates the MQTT stream with real-time vitals, ontology inference, and the alert closed-loop (discover → confirm → handle → verify):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;dgiot/pets/wanCai/telemetry&lt;/span&gt;&lt;span class="w"&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="nl"&gt;"temp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;38.6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"hr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"activity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;62&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;dgiot/pets/wanCai/shadow&lt;/span&gt;&lt;span class="w"&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="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"battery"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;87&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"rssi"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;-62&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;Watch for the activity-drop alert — when activity falls below 35%, the ontology fires a hip dysplasia risk warning for the Golden Retriever, generates a work order, and closes the loop when activity recovers.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Real vs. What's Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Real&lt;/strong&gt;: DGIOT platform, DLAS ontology engine, shadow device architecture, MQTT pipeline, alert closed-loop — all production code from our industrial deployments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Demo&lt;/strong&gt;: The collar hardware (simulated), the dog (borrowed), the vitals (synthetic values).&lt;/p&gt;

&lt;p&gt;The point: the &lt;em&gt;platform&lt;/em&gt; is production-grade. Building pet monitoring on it took one afternoon, because the hard parts — protocol handling, shadow state, ontology reasoning — were already done for 300+ industrial use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Code
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Platform&lt;/strong&gt;: &lt;a href="https://github.com/dgiot/dgiot" rel="noopener noreferrer"&gt;github.com/dgiot/dgiot&lt;/a&gt; — Apache 2.0, 4.8K stars&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Demo&lt;/strong&gt;: Single HTML file simulating the MQTT stream&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Want to build your own? The platform deploys in 6 minutes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/dgiot/dgiot.git
&lt;span class="nb"&gt;cd &lt;/span&gt;dgiot &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;em&gt;Built for the Dev.to Dog Days Challenge. If your dog's activity drops below 35%, take them to the vet — the ontology says so.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>weekendchallenge</category>
      <category>dogs</category>
      <category>iot</category>
      <category>opensource</category>
    </item>
    <item>
      <title>🐾 Dog Days Pack: Three Zero-Dependency Dog Projects in One Weekend</title>
      <dc:creator>JhonLiu</dc:creator>
      <pubDate>Fri, 14 Aug 2026 23:30:21 +0000</pubDate>
      <link>https://dev.to/lsxredrain/dog-days-pack-three-zero-dependency-dog-projects-in-one-weekend-2g69</link>
      <guid>https://dev.to/lsxredrain/dog-days-pack-three-zero-dependency-dog-projects-in-one-weekend-2g69</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/weekend-2026-08-13"&gt;Weekend Challenge: Dog Days Edition&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Three small dog-themed projects, all built from scratch within the challenge window — each one is a &lt;strong&gt;single self-contained HTML file&lt;/strong&gt; with zero dependencies, zero build steps, and zero CDNs. Open the file (or the links below) and it just works, the way software for dogs should.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. 🎴 Paw Match — Dog Breed Memory Game&lt;/strong&gt;&lt;br&gt;
A card-memory game where you flip cards to match dog breed pairs. Match a pair and a real breed fact pops up — did you know Dalmatians are born pure white and only develop spots after 3–4 weeks? Three difficulties (6/8/10 pairs), move counter, timer, star ratings, CSS 3D flip animations and confetti.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. 📓 Paw Log — Dog Training &amp;amp; Care Journal&lt;/strong&gt;&lt;br&gt;
A practical training log (the brief literally suggested this one 🎯). Log walks, feedings, training sessions, vet visits, baths and playtime. Everything persists in localStorage, with daily stats (walks today, training minutes, day streak), per-activity totals with progress bars, and JSON export/import backups.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. 🎨 Dog-o-matic — Generative Dog Art&lt;/strong&gt;&lt;br&gt;
A tiny procedural dog factory. Every click generates a unique dog face — head shape, ear type (flop/point/round/fold), coat color, chest blaze, Dalmatian spots, tongue, freckles — all random. It "identifies" the breed and always concludes the dog is a very good boy. Pure Canvas 2D, and you can save any dog as PNG or auto-breed a dozen in a row.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;All three run right in your browser — no install, no login:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🎴 &lt;strong&gt;Paw Match&lt;/strong&gt;: &lt;a href="http://dev.dgiotcloud.cn/dogdays/dog-memory.html" rel="noopener noreferrer"&gt;play it here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📓 &lt;strong&gt;Paw Log&lt;/strong&gt;: &lt;a href="http://dev.dgiotcloud.cn/dogdays/dog-training-log.html" rel="noopener noreferrer"&gt;use it here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎨 &lt;strong&gt;Dog-o-matic&lt;/strong&gt;: &lt;a href="http://dev.dgiotcloud.cn/dogdays/dog-gen-art.html" rel="noopener noreferrer"&gt;generate dogs here&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;The entire codebase is the demos themselves: each project is one self-contained HTML file — right-click → &lt;em&gt;View Source&lt;/em&gt; in any browser and you have the full code. No frameworks, no lockfiles, no node_modules to explain.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A GitHub repository with the full pack (plus this README) is being published and I'll link it here before submissions close.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The one-file constraint&lt;/strong&gt; was the fun part. I decided each project had to be a single HTML file that works over &lt;code&gt;file://&lt;/code&gt; — double-click and play, anywhere, even offline. That forced some genuinely nice engineering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Paw Match&lt;/strong&gt; uses CSS 3D transforms for the flip animation (&lt;code&gt;perspective&lt;/code&gt; + &lt;code&gt;rotateY&lt;/code&gt;), a tiny state machine for the flip/lock/match flow, and a hand-picked fact table of 10 real breed facts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paw Log&lt;/strong&gt; is a full CRUD app in ~130 lines of vanilla JS: a single localStorage JSON document, day-keyed aggregation for the "today" view, streak calculation walking back through calendar days, and JSON backup export/import for the "data stays on your machine" promise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dog-o-matic&lt;/strong&gt; draws every dog procedurally on a &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt;: a parameter object (coat, ear, head, muzzle, patches, spots, tongue, freckles) drives an ordered paint pass — ears behind the head, muzzle overlay, white blaze, then face details. The "breed guess" is a tiny rules engine over those parameters (&lt;code&gt;ears === 'round' → "Corgi (all loaf, no legs)"&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The whole pack is responsive, works on mobile, and was built in one weekend sitting — because that's the challenge.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Made for fun. No dogs were harmed (or trained) in the making. 🦴&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
    </item>
    <item>
      <title>Why We Built an Ontology Engine Instead of Another Rules System</title>
      <dc:creator>JhonLiu</dc:creator>
      <pubDate>Thu, 13 Aug 2026 19:11:50 +0000</pubDate>
      <link>https://dev.to/lsxredrain/why-we-built-an-ontology-engine-instead-of-another-rules-system-8nj</link>
      <guid>https://dev.to/lsxredrain/why-we-built-an-ontology-engine-instead-of-another-rules-system-8nj</guid>
      <description>&lt;h1&gt;
  
  
  Why We Built an Ontology Engine Instead of Another Rules System
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Every IoT platform has a rules engine. We built something different: a 252-entity OWL ontology that understands what equipment &lt;em&gt;is&lt;/em&gt;, not just what values it reports.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Problem with Rules
&lt;/h2&gt;

&lt;p&gt;Traditional industrial alarm systems work like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IF temperature &amp;gt; 80°C THEN alert
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works until it doesn't:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;False alarms&lt;/strong&gt;: A pump starting up briefly spikes to 82°C. Is it failing, or just warming up? The rule doesn't know.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rule explosion&lt;/strong&gt;: 100 equipment types × 20 parameters × 5 thresholds = 10,000 rules to maintain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No context&lt;/strong&gt;: "Pressure low" means different things for a water pump (cavitation) vs an oil well (depletion)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fragile thresholds&lt;/strong&gt;: Each plant tunes its own thresholds. Nothing transfers between sites.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At Daqing Oil Field, false alarm rates exceeded 20% with the old rules-based system. Operators learned to ignore alarms — which defeats the entire purpose.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Ontology Approach
&lt;/h2&gt;

&lt;p&gt;An ontology models the &lt;em&gt;structure&lt;/em&gt; of industrial equipment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="n"&gt;Pump&lt;/span&gt; &lt;span class="err"&gt;⊑&lt;/span&gt; &lt;span class="n"&gt;Equipment&lt;/span&gt; &lt;span class="err"&gt;⊓&lt;/span&gt; &lt;span class="err"&gt;∃&lt;/span&gt;&lt;span class="n"&gt;hasPart.Bearing&lt;/span&gt; &lt;span class="err"&gt;⊓&lt;/span&gt; &lt;span class="err"&gt;∃&lt;/span&gt;&lt;span class="n"&gt;measures.Pressure&lt;/span&gt;
&lt;span class="n"&gt;Bearing&lt;/span&gt; &lt;span class="err"&gt;⊑&lt;/span&gt; &lt;span class="n"&gt;Component&lt;/span&gt; &lt;span class="err"&gt;⊓&lt;/span&gt; &lt;span class="err"&gt;∃&lt;/span&gt;&lt;span class="n"&gt;hasFailureMode.Overheat&lt;/span&gt;
&lt;span class="n"&gt;Overheat&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;triggers&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Alert&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="err"&gt;∧&lt;/span&gt; &lt;span class="n"&gt;reduces&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RemainingLife&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When our platform reads a pressure value of 2.35 MPa, it doesn't just compare against a threshold. It knows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;This is a &lt;strong&gt;pump&lt;/strong&gt; (not a valve, not a compressor)&lt;/li&gt;
&lt;li&gt;The pump &lt;strong&gt;has a bearing&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Bearings &lt;strong&gt;fail by overheating&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Combined with vibration data, this pattern matches "bearing wear stage 2"&lt;/li&gt;
&lt;li&gt;The recommended action is "schedule maintenance within 14 days" — not "sound alarm now"&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The DLAS Architecture
&lt;/h2&gt;

&lt;p&gt;We formalized this as a four-layer stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATA     Parse (23 classes) · PostgreSQL · TDengine · EMQX
LOGIC    Ontology Engine · Model Registry · 3 ETS Tables
ACTION   Shadow (gen_statem) · MQTT · Rule Engine  
SECURITY JWT · RBAC · ACL/CLP · Audit Log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key innovation: &lt;strong&gt;the ontology compiles to Erlang pattern matches&lt;/strong&gt;. Each OWL axiom becomes native code. Reasoning happens at runtime speed — not query speed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erlang"&gt;&lt;code&gt;&lt;span class="c"&gt;% OWL: Overheat → triggers(Alert)
&lt;/span&gt;&lt;span class="nf"&gt;handle_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;#event&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;overheat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;Pid&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nv"&gt;State&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nn"&gt;ontology&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;class_of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Pid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
        &lt;span class="n"&gt;bearing&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;next_state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;schedule_maintenance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;State&lt;/span&gt;&lt;span class="p"&gt;)};&lt;/span&gt;
        &lt;span class="p"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;next_state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;State&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Shadow Devices: The State Machine Layer
&lt;/h2&gt;

&lt;p&gt;Every physical device has a digital twin — a gen_statem process that mirrors its lifecycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;init → auth → online → {normal, alarm, offline}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The shadow absorbs network chaos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gateway drops offline for 30 seconds? Shadow holds state, retries silently.&lt;/li&gt;
&lt;li&gt;Device sends contradictory readings? Shadow evaluates against the ontology before propagating.&lt;/li&gt;
&lt;li&gt;Firmware updates? Shadow freezes state, swaps, resumes — no downtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why we run 928 gateways with 99.9999% uptime on a 10-person team.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Rules-Based&lt;/th&gt;
&lt;th&gt;Ontology-Based&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;False alarm rate&lt;/td&gt;
&lt;td&gt;22%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.7%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rules to maintain&lt;/td&gt;
&lt;td&gt;10,000+&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;252 entities + 15 SWRL rules&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New equipment onboarding&lt;/td&gt;
&lt;td&gt;2 weeks&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;2 hours&lt;/strong&gt; (just describe the type)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-site transfer&lt;/td&gt;
&lt;td&gt;Manual re-tuning&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Automatic&lt;/strong&gt; (ontology is generic)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The false alarm reduction alone saved an estimated $2.3M in year one at Daqing.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Use Which
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Rules Engine&lt;/th&gt;
&lt;th&gt;Ontology Engine&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Simple thresholds&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Overkill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Complex equipment hierarchies&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-industry reuse&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Explainable decisions&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;td&gt;✅ (inference chain)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We still ship a rules engine. But for anything with mechanical structure — pumps, turbines, compressors, breakers — the ontology wins.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;The full platform is open source (Apache 2.0):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/dgiot/dgiot.git
&lt;span class="nb"&gt;cd &lt;/span&gt;dgiot &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ontology engine is in &lt;code&gt;apps/dgiot_ontology/&lt;/code&gt;. Docs at &lt;code&gt;docs/DGAIOT_ONTOLOGY.md&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Liu Shouxin is the founder of DGIOT. He's spent 20 years on industrial IoT, previously at EMQ and Huawei. The ontology approach came from his master's thesis at Zhejiang University — 22 years before it shipped in production.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>iot</category>
      <category>ontology</category>
      <category>erlang</category>
      <category>architecture</category>
    </item>
    <item>
      <title>How One Open-Source IoT Platform Unified China Largest Oil Field — 928 Gateways, 114K Sensors, 600x Faster</title>
      <dc:creator>JhonLiu</dc:creator>
      <pubDate>Tue, 11 Aug 2026 03:25:37 +0000</pubDate>
      <link>https://dev.to/lsxredrain/how-one-open-source-iot-platform-unified-china-largest-oil-field-928-gateways-114k-sensors-600x-2aib</link>
      <guid>https://dev.to/lsxredrain/how-one-open-source-iot-platform-unified-china-largest-oil-field-928-gateways-114k-sensors-600x-2aib</guid>
      <description>&lt;h1&gt;
  
  
  How One Open-Source IoT Platform Unified China's Largest Oil Field — 928 Gateways, 114K Sensors, 600× Faster
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Daqing Oil Field produces 30 million tons of crude annually. When they needed to modernize their sensor network, they chose an open-source platform built by a 10-person team. Here's the story.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Scale of the Problem
&lt;/h2&gt;

&lt;p&gt;Daqing Oil Field spans 6,000 square kilometers — roughly the size of Delaware. It has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;16 oil extraction plants&lt;/li&gt;
&lt;li&gt;928 industrial gateways (mostly Modbus RTU/TCP and a proprietary CNPC protocol called A11)&lt;/li&gt;
&lt;li&gt;114,809 sensor points measuring pressure, temperature, flow rate, vibration, and 20 other parameters&lt;/li&gt;
&lt;li&gt;30+ years of accumulated legacy equipment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When we first visited in 2020, the data infrastructure looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Field Operator checks gauge → writes value on clipboard
  → enters into Excel at end of shift
  → supervisor reviews next morning
  → alarm triggered 4 hours after anomaly occurred
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Collection frequency: &lt;strong&gt;every 10 minutes&lt;/strong&gt; on a good day. End-to-end latency: &lt;strong&gt;15-30 minutes&lt;/strong&gt;. False alarm rate: &lt;strong&gt;over 20%&lt;/strong&gt;. Storage: data older than &lt;strong&gt;10 days&lt;/strong&gt; was purged.&lt;/p&gt;

&lt;p&gt;An oil pump failure caught 4 hours late costs &lt;strong&gt;$50,000-200,000&lt;/strong&gt; in lost production.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Approach: Protocol-First
&lt;/h2&gt;

&lt;p&gt;We didn't try to replace the gateways. Instead, we built protocol adapters that spoke their language:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Siemens S7-1200 (Modbus TCP)  ──┐
ABB AC500 (Modbus RTU)         ──┤
A11 CNPC Gateways (proprietary) ──┼──→ DGIOT Unified Pipeline
OPC UA Servers (newer units)   ──┤
Manual Input (legacy gauges)   ──┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each protocol adapter is an Erlang gen_statem process. A single gateway's Modbus connection is one lightweight process consuming ~2KB of memory. 928 gateways = &amp;lt;2MB RAM for the entire protocol layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  The A11 Protocol Challenge
&lt;/h3&gt;

&lt;p&gt;The hardest part was A11 — a proprietary CNPC protocol with almost no documentation. We had to reverse-engineer it from packet captures and conversations with retired engineers. The protocol uses a unique 4-byte magic number (&lt;code&gt;0x6A6A5A5A&lt;/code&gt;) and variable-length frames with custom CRC. It took three weeks of on-site work, but once we cracked it, we could talk to 60% of Daqing's legacy gateways natively.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture in Production
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;928 Gateways
    │  Modbus RTU/TCP, A11 CNPC, OPC UA
    ↓
DGIOT Edge (Runs on existing gateway hardware)
    │  Protocol adaptation + stream computation + 7-day offline buffer
    ↓
MQTT Broker (EMQX) — 1M+ msg/sec
    │
    ├──→ TDengine (time-series, 10:1 compression, 652M data points)
    ├──→ Parse Server (device metadata, auth, tenant isolation)
    └──→ Stream Engine (15 algorithms, real-time alerting)
    │
    ↓
Vue 3 Dashboard (operator view, maintenance view, director view)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;th&gt;Improvement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Collection frequency&lt;/td&gt;
&lt;td&gt;10 min&lt;/td&gt;
&lt;td&gt;1 sec&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;600×&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;End-to-end latency&lt;/td&gt;
&lt;td&gt;15-30 min&lt;/td&gt;
&lt;td&gt;&amp;lt;3 sec&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;600×&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage retention&lt;/td&gt;
&lt;td&gt;10 days&lt;/td&gt;
&lt;td&gt;2 years&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;73×&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;False alarm rate&lt;/td&gt;
&lt;td&gt;22%&lt;/td&gt;
&lt;td&gt;4.7%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.7× better&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gateways managed&lt;/td&gt;
&lt;td&gt;1 per system&lt;/td&gt;
&lt;td&gt;928 unified&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Protocols supported&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;15 at Daqing, 300+ globally&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uptime&lt;/td&gt;
&lt;td&gt;~95%&lt;/td&gt;
&lt;td&gt;99.9999%&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  The Real Impact
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;$2.3 million saved in the first year&lt;/strong&gt; — not from license fees (DGIOT is free), but from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reduced downtime&lt;/strong&gt;: Pumps caught at first sign of bearing wear, not after failure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eliminated manual rounds&lt;/strong&gt;: Operators stopped driving 2 hours to check a gauge&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimized maintenance&lt;/strong&gt;: Predictive instead of scheduled — 40% fewer truck rolls&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Open Source Won
&lt;/h2&gt;

&lt;p&gt;Daqing initially wanted a commercial SCADA system. Three vendors quoted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vendor A: $1.2M license + $200K/year maintenance&lt;/li&gt;
&lt;li&gt;Vendor B: $850K + $180K/year&lt;/li&gt;
&lt;li&gt;Vendor C: $3M for a "full digital transformation"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All three required replacing the existing gateways — a $15M hardware project. DGIOT ran on the existing hardware. The software was free. The only cost was integration and training.&lt;/p&gt;

&lt;p&gt;When the project lead asked "What if your company goes out of business?", we pointed to the GitHub repo: "The code is Apache 2.0. It outlives us."&lt;/p&gt;

&lt;p&gt;That closed the deal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons for Industrial IoT Founders
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Don't compete on features. Compete on protocols.&lt;/strong&gt; Every protocol you support removes a reason to say no.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open source is a trust mechanism for hardware companies.&lt;/strong&gt; They've been burned by vendor lock-in. Apache 2.0 is the ultimate guarantee.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Edge computing is non-negotiable.&lt;/strong&gt; Oil fields have terrible connectivity. Your platform must work offline for days.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The hard part isn't the tech — it's the protocol reverse-engineering.&lt;/strong&gt; Budget 2-4 weeks per proprietary protocol. It's worth it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pricing: free software, paid integration.&lt;/strong&gt; The software is open source. The 3-week on-site integration, training, and custom protocol work is what you charge for.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;DGIOT is open source (Apache 2.0) at &lt;a href="https://github.com/dgiot/dgiot" rel="noopener noreferrer"&gt;github.com/dgiot/dgiot&lt;/a&gt;. The Daqing deployment has been running in production since 2021.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Liu Shouxin is the founder of DGIOT. He previously architected IoT platforms at EMQ, Huawei, and TCL.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>iot</category>
      <category>opensource</category>
      <category>casestudy</category>
      <category>industrial</category>
    </item>
    <item>
      <title>How We Built an IoT Platform That Handles 30 Million Concurrent Connections — With a Team of 10</title>
      <dc:creator>JhonLiu</dc:creator>
      <pubDate>Tue, 11 Aug 2026 03:25:00 +0000</pubDate>
      <link>https://dev.to/lsxredrain/how-we-built-an-iot-platform-that-handles-30-million-concurrent-connections-with-a-team-of-10-2ni0</link>
      <guid>https://dev.to/lsxredrain/how-we-built-an-iot-platform-that-handles-30-million-concurrent-connections-with-a-team-of-10-2ni0</guid>
      <description>&lt;h1&gt;
  
  
  How We Built an IoT Platform That Handles 30 Million Concurrent Connections — With a Team of 10
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;DGIOT is an open-source industrial IoT platform. We run 928 gateways across 16 oil fields, process 652 million data points, and maintain 99.9999% uptime. Here's the architecture that makes it possible.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;In 2021, we got a call from Daqing Oil Field — China's largest oil producer. They had a problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;928 industrial gateways from different vendors&lt;/li&gt;
&lt;li&gt;114,809 sensor points speaking 15 different protocols&lt;/li&gt;
&lt;li&gt;Data collection every 10 minutes (they needed seconds)&lt;/li&gt;
&lt;li&gt;15-30 minute end-to-end latency (they needed &amp;lt;3 seconds)&lt;/li&gt;
&lt;li&gt;False alarm rate above 20%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The existing system was a patchwork of vendor-specific tools, each with its own database, UI, and authentication. Operators had to log into 8 different systems just to check if a pump was overheating.&lt;/p&gt;

&lt;p&gt;They asked: "Can you unify this?"&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Built
&lt;/h2&gt;

&lt;p&gt;DGIOT is an Erlang/OTP-based platform that acts as a universal translator for industrial protocols. Think of it as a Rosetta Stone for machines.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Modbus ─┐
OPC UA ─┤
MQTT  ──┼──→ Unified Pipeline ──→ TDengine ──→ Dashboard
IEC104 ─┤
A11   ──┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key insight: &lt;strong&gt;industrial protocols are just state machines&lt;/strong&gt;. Once you model each protocol as a gen_statem FSM in Erlang, you can handle hundreds of them concurrently with almost zero overhead.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture: DLAS
&lt;/h2&gt;

&lt;p&gt;We designed a four-layer architecture that separates concerns cleanly:&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 1: DATA — Ingestion
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Parse Server&lt;/strong&gt; (23 classes) handles device metadata, user auth, tenant isolation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TDengine&lt;/strong&gt; stores 652M time-series data points with 10:1 compression&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EMQX&lt;/strong&gt; handles MQTT message routing at 1M+ msg/sec&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mnesia/ETS&lt;/strong&gt; provides in-memory caching for hot data&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Layer 2: LOGIC — Ontology Engine
&lt;/h3&gt;

&lt;p&gt;This is our secret weapon. We built a 252-entity OWL ontology that models industrial equipment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="n"&gt;Pump&lt;/span&gt; &lt;span class="err"&gt;⊑&lt;/span&gt; &lt;span class="n"&gt;Equipment&lt;/span&gt; &lt;span class="err"&gt;⊓&lt;/span&gt; &lt;span class="err"&gt;∃&lt;/span&gt;&lt;span class="n"&gt;hasPart.Bearing&lt;/span&gt; &lt;span class="err"&gt;⊓&lt;/span&gt; &lt;span class="err"&gt;∃&lt;/span&gt;&lt;span class="n"&gt;measures.Pressure&lt;/span&gt;
&lt;span class="n"&gt;Bearing&lt;/span&gt; &lt;span class="err"&gt;⊑&lt;/span&gt; &lt;span class="n"&gt;Component&lt;/span&gt; &lt;span class="err"&gt;⊓&lt;/span&gt; &lt;span class="err"&gt;∃&lt;/span&gt;&lt;span class="n"&gt;hasFailureMode.Overheat&lt;/span&gt;
&lt;span class="n"&gt;Overheat&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;triggers&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Alert&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="err"&gt;∧&lt;/span&gt; &lt;span class="n"&gt;reduces&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RemainingLife&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These rules are compiled to Erlang pattern matches. When a pressure sensor reads 2.35 MPa, the platform doesn't just display a number — it knows that pump P-103's bearing is trending toward failure, cross-references the maintenance schedule, and generates a work order.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 3: ACTION — Shadow State Machines
&lt;/h3&gt;

&lt;p&gt;Every physical device has a "shadow" in software — a gen_statem process that mirrors its real-world state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erlang"&gt;&lt;code&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;    &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;online&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alarm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;offline&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Rules&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;MQTT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;alarm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;   &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;escalate&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;notify&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;acknowledge&lt;/span&gt;
&lt;span class="nf"&gt;offline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nf"&gt;retry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;alert&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The shadow absorbs network interruptions. If a gateway goes offline for 30 seconds, the shadow holds the last known state and retries. The dashboard never shows "disconnected" unless the device has been unreachable for 2+ minutes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 4: EDGE — iotStudio
&lt;/h3&gt;

&lt;p&gt;A Python + Vue 3 edge agent that runs on ARM gateways. It does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Protocol adaptation&lt;/strong&gt;: Modbus RTU → MQTT bridge&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stream computation&lt;/strong&gt;: Moving average, anomaly detection, deadband filtering — 15 algorithms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offline autonomy&lt;/strong&gt;: 7-day buffer if cloud connection drops&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OTA updates&lt;/strong&gt;: Rolling firmware deployment to 928 gateways&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Numbers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before DGIOT&lt;/th&gt;
&lt;th&gt;After DGIOT&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Collection frequency&lt;/td&gt;
&lt;td&gt;10 min&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;1 second&lt;/strong&gt; (600×)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;End-to-end latency&lt;/td&gt;
&lt;td&gt;15-30 min&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&amp;lt;3 seconds&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage retention&lt;/td&gt;
&lt;td&gt;10 days&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2 years&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;False alarm rate&lt;/td&gt;
&lt;td&gt;&amp;gt;20%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&amp;lt;5%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Concurrent connections&lt;/td&gt;
&lt;td&gt;~1,000&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;30M verified&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Protocols supported&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;300+&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Why Erlang?
&lt;/h2&gt;

&lt;p&gt;We get this question a lot. The answer is simple: &lt;strong&gt;Erlang was built for this&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Preemptive scheduling&lt;/strong&gt;: A slow Modbus device can't block a fast MQTT stream&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hot code reloading&lt;/strong&gt;: We deploy updates without shutting down 928 gateways&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Let-it-crash philosophy&lt;/strong&gt;: A failing protocol adapter restarts in milliseconds without affecting others&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in distribution&lt;/strong&gt;: Adding a new node to the cluster is one command&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same reasons WhatsApp used Erlang for 2 billion users. Industrial IoT has the same requirements: massive concurrency, high availability, and soft real-time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open Source
&lt;/h2&gt;

&lt;p&gt;DGIOT is Apache 2.0 licensed. Full source at &lt;a href="https://github.com/dgiot/dgiot" rel="noopener noreferrer"&gt;github.com/dgiot/dgiot&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We made this choice deliberately. Industrial IoT is too fragmented for any single company to solve. The only way to cover 300+ protocols is to let the community add them. Every new protocol adapter benefits everyone.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/dgiot/dgiot.git
&lt;span class="nb"&gt;cd &lt;/span&gt;dgiot &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;span class="c"&gt;# Open http://localhost:5080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Protocols are the moat.&lt;/strong&gt; Every new protocol adapter opens a new industry. We went from 3 to 300 in 4 years — each one brought new customers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ontology beats rules.&lt;/strong&gt; Hard-coded alarm thresholds break. An ontology that understands "pump→bearing→overheat" generalizes across equipment types.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open source is the distribution.&lt;/strong&gt; We don't have a sales team. Our customers find us through GitHub, then ask for enterprise support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Erlang is a competitive advantage.&lt;/strong&gt; In a world of Node.js and Python IoT platforms, Erlang's concurrency model lets us handle 100x the load with the same hardware.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Community &amp;gt; code.&lt;/strong&gt; The 70K developers in our community have built integrations we never would have thought of.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;Liu Shouxin is the founder of DGIOT, an open-source industrial IoT platform. He previously worked at EMQ, Huawei, and Kaspersky. He lives in Hangzhou and Dallas.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>iot</category>
      <category>erlang</category>
      <category>opensource</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
