Bot TutorialsGrok BotChatGPTClaudeGeminiCopilotPerplexityMore botsGuidesArticlesPapersIndustrialSearch

Read Modbus TCP data with a bot, read-only

Modbus TCP has no authentication, so safety comes from the network: the bot box can reach a device only through a filter that permits read function codes. Practice against a simulator first.

1. Get the register map from the manual

Never let the bot guess addresses. Put the vendor register map in a CSV the bot can cite: name,address,type,scale,units,lo_alarm,hi_alarm. Note whether the manual numbers are 0-based or 1-based (40001 style); this is the most common Modbus mistake.

2. Enforce read-only on the wire

Permit only function codes 01-04 (read coils, discrete inputs, holding registers, input registers) from the bot box to the device, via an industrial firewall or Modbus-aware gateway. Drop 05, 06, 15, 16, 22, 23 and everything else.

3. Poll with Python (pymodbus)

Install pymodbus from your offline wheel cache. This script only reads and writes CSV:

import csv, time, datetime
from pymodbus.client import ModbusTcpClient

MAP = list(csv.DictReader(open("regmap.csv")))  # name,address,scale,units,lo_alarm,hi_alarm
c = ModbusTcpClient("10.20.30.40", port=502, timeout=3)
c.connect()
with open("readings.csv", "a", newline="") as f:
    w = csv.writer(f)
    for r in MAP:
        rr = c.read_holding_registers(int(r["address"]), count=1, device_id=1)
        # pymodbus < 3.10 uses slave=1 instead of device_id=1
        if rr.isError():
            w.writerow([datetime.datetime.now().isoformat(), r["name"], "ERROR", ""]); continue
        val = rr.registers[0] * float(r["scale"])
        w.writerow([datetime.datetime.now().isoformat(), r["name"], val, r["units"]])
c.close()

The script contains no write calls. Keep it that way and review any change to it like a PLC change.

4. Let the local model explain, with citations

Send a slice of readings plus the register map to your local model:

Here are the last 60 minutes of readings (CSV) and the register map (CSV).
1. List any value outside lo_alarm/hi_alarm, with tag name and timestamp.
2. Describe trends in plain English. Cite tag names for every statement.
3. Do not recommend control actions. If something looks unsafe, say "notify operator" and why.

Bad: "Is pump 3 OK? Fix it if not."

Good: "Summarize P3_DISCH_PSI and P3_AMPS for the last hour against their alarm limits. Cite timestamps."

5. Poll gently

Old PLCs and serial gateways can be overwhelmed. Start at one read every few seconds per device, batch contiguous registers, and confirm with the controls engineer that comms load is acceptable.

Questions

Why not just let the bot write a register?

Modbus has no authentication or per-user permissions. Any client that can write can change the process. Writes stay with qualified people and validated tools.

0-based or 1-based addresses?

Protocol addresses are 0-based; many manuals list 1-based "40001" numbers. Holding register 40001 is usually protocol address 0. Confirm against a known value.

Where these facts come from

Checked Oct 29, 2026. Tutorials are educational. Follow your site's safety procedures, management-of-change process and the equipment maker's manual. Never test against live production equipment without authorization.

Industrial control with bots: all lessons → Next: 5. Read OPC UA tags securely with a bot →

Related: 1. Ground rules: what a bot may and may not do in OT2. Run a local LLM on an air-gapped Linux box3. Sneakernet: move models and updates across the gap safely4. Read Modbus TCP data with a bot (read-only)5. Read OPC UA tags securely with a bot6. Bot-written shift reports and alarm summaries7. Audit logs that a bot cannot rewrite8. Human-in-the-loop: approval gates before anything movesCan AI control a PLC?Run AI offline on LinuxGuidesScripts & templates