<?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: Sebastian</title>
    <description>The latest articles on DEV Community by Sebastian (@s_cordero_84).</description>
    <link>https://dev.to/s_cordero_84</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%2F4044783%2Fc2caa6e3-8643-4690-9a04-9a28be60044b.jpeg</url>
      <title>DEV Community: Sebastian</title>
      <link>https://dev.to/s_cordero_84</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/s_cordero_84"/>
    <language>en</language>
    <item>
      <title>I Replaced a 24/7 Alarm Watcher with 30 Lines of Python and a Telegram Bot</title>
      <dc:creator>Sebastian</dc:creator>
      <pubDate>Sat, 25 Jul 2026 06:19:49 +0000</pubDate>
      <link>https://dev.to/s_cordero_84/i-replaced-a-247-alarm-watcher-with-30-lines-of-python-and-a-telegram-bot-4o82</link>
      <guid>https://dev.to/s_cordero_84/i-replaced-a-247-alarm-watcher-with-30-lines-of-python-and-a-telegram-bot-4o82</guid>
      <description>&lt;p&gt;Before this, I had never built a notification system. I just had a PC, a free Telegram bot, and a simple problem: alarms were firing on the plant floor, and by the time someone noticed on a dashboard, the downtime clock had already been running for minutes.&lt;/p&gt;

&lt;p&gt;So I asked myself a dumb question: what if the alarm just... texted someone?&lt;/p&gt;

&lt;p&gt;Turns out, it's a lot easier than it sounds.&lt;/p&gt;

&lt;p&gt;Let me set the scene&lt;br&gt;
Industrial alarms are usually built to be seen, not heard. A light turns red on an HMI. A tag flips in a SCADA system. If nobody's staring at that screen at that exact moment, the alarm just sits there, quietly costing minutes.&lt;/p&gt;

&lt;p&gt;Meanwhile, everyone on a maintenance team already has a phone in their pocket.&lt;/p&gt;

&lt;p&gt;So instead of building (or paying for) a bigger dashboard, I built something dumber and faster: a Python script that watches tag states and pings a Telegram group the second something goes wrong — and logs everything so there's a report waiting at the end of the shift, no manual tally required.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fubau1hq5y1khc9dm136k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fubau1hq5y1khc9dm136k.png" alt=" " width="799" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No database server. No new dashboard software. No licenses.&lt;/p&gt;

&lt;p&gt;How it's wired together&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ PLC / data source ]
        |
        | tag values
        |
[ Python script — polling loop ]
        |
        ├── detects state change (off → on, on → off)
        |
        ├── sends message ──► [ Telegram group ]
        |
        └── logs event ──► [ alarms_YYYY-MM-DD.json ]
                                  |
                                  └── end of shift ──► [ Shift report: top 5 + downtime ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 1 — Get the bot talking&lt;/strong&gt;&lt;br&gt;
Telegram bots are free and take two minutes to set up via &lt;a class="mentioned-user" href="https://dev.to/botfather"&gt;@botfather&lt;/a&gt;. Once you have a token, sending a message is one HTTP call:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy6a49nm7qpkv2mbt7q7g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy6a49nm7qpkv2mbt7q7g.png" alt=" " width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's the entire notification layer. One function, reused for every alert.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2 — Don't alert on values, alert on changes&lt;/strong&gt;&lt;br&gt;
My first instinct was to just check "is this tag true?" every second and fire a message. Bad idea — that spams the same alarm every second while it's active.&lt;/p&gt;

&lt;p&gt;The fix: track the previous state, and only fire when it changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffx913jn0vu8bzbv80m5f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffx913jn0vu8bzbv80m5f.png" alt=" " width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Output (in the Telegram chat):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🔴 ALARM: Tank1_Level triggered&lt;br&gt;
🟢 CLEARED: Tank1_Level back to normal&lt;br&gt;
Two lines of chat, zero minutes of someone staring at a screen to catch it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3 — Log everything, automatically&lt;/strong&gt;&lt;br&gt;
Every trigger and clear event gets appended to a JSON file for the day. No database setup, no schema — just a growing list of events with timestamps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F63udau0xtmo2dxl77gwo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F63udau0xtmo2dxl77gwo.png" alt=" " width="799" height="645"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4 — The part that actually saves time: the shift report&lt;/strong&gt;&lt;br&gt;
This is where it clicked for me. By shift end, that JSON file already has everything needed to answer the question every supervisor asks: "what actually happened today?"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fslg93ze6me9mw9lyv1qa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fslg93ze6me9mw9lyv1qa.png" alt=" " width="763" height="777"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft2qv6z8yabokw5jm4oht.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft2qv6z8yabokw5jm4oht.png" alt=" " width="771" height="143"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No spreadsheet. No handover notes scribbled on paper. Just python report.py at the end of the shift.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this actually matters&lt;/strong&gt;&lt;br&gt;
This isn't a groundbreaking piece of engineering — that's the point. The value isn't in complexity, it's in closing three gaps that most plants quietly live with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detection lag: alarms sitting unnoticed on a dashboard&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Notification friction: nobody wants another app, but everybody already has Telegram/WhatsApp on their phone&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reporting overhead: someone manually reconstructing "what broke today" from memory at shift change&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Three Python functions, one free API, and a JSON file closed all three.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where to go from here&lt;/strong&gt;&lt;br&gt;
If you want to build something similar:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start read-only. Just alert and log — don't touch write commands until you fully trust the polling logic.&lt;/li&gt;
&lt;li&gt;Batch alerts if things get noisy. If ten tags fire in the same second, group them into one message instead of flooding the chat.&lt;/li&gt;
&lt;li&gt;Outgrowing JSON? Swap the file for SQLite — same logic, just a different storage layer.&lt;/li&gt;
&lt;li&gt;Add more context to alerts. A tag name is fine, but a tag name + last known good value + how long it's been active is a lot more useful at 3 AM.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You don't need a SCADA overhaul to get real-time visibility. Sometimes it's just a bot, a loop, and a JSON file.&lt;/p&gt;

&lt;p&gt;Built something similar with Slack, WhatsApp, or email instead of Telegram? I'd love to compare notes — drop a comment below.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>**Reading PLC Tags with Python: pylogix + Rockwell Automation 🐍⚙️**</title>
      <dc:creator>Sebastian</dc:creator>
      <pubDate>Fri, 24 Jul 2026 04:29:36 +0000</pubDate>
      <link>https://dev.to/s_cordero_84/reading-plc-tags-with-python-pylogix-rockwell-automation--4mhe</link>
      <guid>https://dev.to/s_cordero_84/reading-plc-tags-with-python-pylogix-rockwell-automation--4mhe</guid>
      <description>&lt;p&gt;PLCs and Python don't usually hang out together. One's rigid, real-time, industrial. The other's flexible and everywhere. But put them together and things get interesting.&lt;/p&gt;

&lt;p&gt;Enter pylogix — a Python library that talks directly to Rockwell/Allen-Bradley PLCs over EtherNet/IP. No OPC server, no extra middleware. Just Python. 🙌&lt;/p&gt;

&lt;p&gt;Install it:&lt;/p&gt;

&lt;p&gt;bash&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;pylogix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Read a tag:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;python&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pylogix&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PLC&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;PLC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;192.168.1.10&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;comm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;comm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Motor1_Running&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TagName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Three lines and you're pulling live data off a PLC. 🔥&lt;/p&gt;

&lt;p&gt;Reading a few tags at once? Just pass a list:&lt;/p&gt;

&lt;p&gt;python&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Motor1_Running&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Motor1_Fault&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tank1_Level&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;PLC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;192.168.1.10&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;comm&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;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;comm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TagName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Writing? Possible, but be careful ⚠️ — only write tags you fully understand, never touch safety logic.&lt;/p&gt;

&lt;p&gt;Why bother? Because once you can read tag data in Python, you unlock stuff PLCs just aren't built for:&lt;/p&gt;

&lt;p&gt;🔔 Real-time alerts (email, Slack, even voice)&lt;br&gt;
📊 Dashboards&lt;br&gt;
🗄️ Logging to a database for trends&lt;br&gt;
☁️ Cloud integration&lt;br&gt;
A couple of real-talk tips:&lt;/p&gt;

&lt;p&gt;Don't poll every millisecond — 1 tag read/sec is usually plenty&lt;br&gt;
Handle disconnects, networks drop&lt;br&gt;
Never expose your PLC to the internet 🚫&lt;br&gt;
Python doesn't replace the PLC. It just gives it a voice. 🗣️&lt;/p&gt;

&lt;p&gt;Have you connected Python to a PLC before?&lt;br&gt;
What'd you use — Modbus, OPC UA, pycomm3? Drop it below 👇&lt;/p&gt;

&lt;h1&gt;
  
  
  python #plc #iot #automation #rockwellautomation #industry40 #manufacturing #tech
&lt;/h1&gt;

</description>
      <category>automation</category>
      <category>hardware</category>
      <category>iot</category>
      <category>python</category>
    </item>
  </channel>
</rss>
