IoT

Modbus to MQTT: Retrofitting Legacy Industrial Machinery for Cloud Telemetry

Jul 5, 2026
4 min read
Modbus to MQTT Conversion

A staggering percentage of active machinery in manufacturing plants runs on Modbus, a protocol designed in 1979. While Modbus is incredibly reliable for local, closed-loop PLC networks, it is completely unsuited for cloud ingestion. It is unencrypted, uses a rigid polling mechanism, lacks metadata, and operates on bare register addresses. To feed industrial data into modern Analytics or Machine Learning models, you must retrofit legacy systems. This is the classic "Brownfield" problem of IIoT.

The standard solution is using an Edge Gateway to act as a protocol translator—reading Modbus registers at a deterministic frequency, parsing the raw integers into structured JSON, and publishing the data via MQTT (Message Queuing Telemetry Transport). This guide walks you through this exact implementation using Python.

Understanding the Modbus Register Map

Unlike MQTT, which uses descriptive topics (e.g., factory/pump/vibration), Modbus relies on numeric address lookup tables. You must know the register map of the target machine. Let's assume we are monitoring an industrial chiller with the following registers:

  • Register 30001 (Input Register): Temperature (°C), scaled by 10 (e.g., a value of 234 represents 23.4°C).
  • Register 30002 (Input Register): Pressure (PSI), scaled by 100.
  • Register 40001 (Holding Register): Compressor State (0 = Off, 1 = Idle, 2 = Running).

The Implementation Strategy

Our edge gateway script will do the following:

  1. Establish a connection to the Modbus TCP server (often a PLC or remote I/O module).
  2. Establish a secure connection to our central MQTT broker.
  3. Periodically poll the registers.
  4. Scale the raw values, attach timestamps and metadata, and encode the data into a JSON string.
  5. Publish the JSON message to an structured MQTT topic.

Python Implementation: The Protocol Translator

Below is a production-grade Python script using pymodbus (for Modbus communication) and paho-mqtt (for MQTT publishing).


import time
import json
import logging
from pymodbus.client import ModbusTcpClient
import paho.mqtt.client as mqtt

# Configure Logger
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("ModbusToMQTT")

# Configurations
MODBUS_IP = "192.168.1.150"
MODBUS_PORT = 502
MQTT_BROKER = "mqtt.enterprise.io"
MQTT_PORT = 8883  # MQTTS (TLS)
MQTT_TOPIC = "factory/site_alpha/chiller_01/telemetry"

# Initialize Clients
mb_client = ModbusTcpClient(MODBUS_IP, port=MODBUS_PORT)
mqtt_client = mqtt.Client(client_id="gateway_chiller_01", callback_api_version=mqtt.CallbackAPIVersion.VERSION2)

def connect_services():
    try:
        # Connect Modbus
        if not mb_client.connected:
            mb_client.connect()
            logger.info("Connected to Modbus TCP server")
        
        # Connect MQTT (Production systems must load SSL/TLS certs here)
        # mqtt_client.tls_set(ca_certs="ca.crt", certfile="client.crt", keyfile="client.key")
        mqtt_client.connect(MQTT_BROKER, MQTT_PORT, keepalive=60)
        logger.info("Connected to MQTT Broker")
    except Exception as e:
        logger.error(f"Connection failed: {e}")

def read_telemetry():
    # Read 2 input registers starting at address 0 (30001)
    input_reg = mb_client.read_input_registers(address=0, count=2)
    # Read 1 holding register starting at address 0 (40001)
    holding_reg = mb_client.read_holding_registers(address=0, count=1)
    
    if input_reg.isError() or holding_reg.isError():
        logger.warning("Error reading Modbus registers")
        return None
        
    # Parse and Scale Values
    raw_temp = input_reg.registers[0]
    raw_pressure = input_reg.registers[1]
    raw_state = holding_reg.registers[0]
    
    temperature = raw_temp / 10.0
    pressure = raw_pressure / 100.0
    
    state_map = {0: "Off", 1: "Idle", 2: "Running"}
    status = state_map.get(raw_state, "Unknown")
    
    payload = {
        "timestamp": int(time.time()),
        "metrics": {
            "temperature_c": temperature,
            "pressure_psi": pressure,
            "status": status
        },
        "metadata": {
            "device_id": "chiller_01",
            "location": "site_alpha_zone_3"
        }
    }
    return payload

def main():
    connect_services()
    while True:
        try:
            # Reconnect if connections dropped
            if not mb_client.connected:
                mb_client.connect()
            
            payload = read_telemetry()
            if payload:
                payload_str = json.dumps(payload)
                mqtt_client.publish(MQTT_TOPIC, payload_str, qos=1)
                logger.info(f"Published payload: {payload_str}")
                
        except Exception as e:
            logger.error(f"Error during cycle: {e}")
            
        time.sleep(5)  # Poll frequency (5 seconds)

if __name__ == "__main__":
    main()

Critical Design Considerations for Production

While the script above is a strong foundation, deploying this in a harsh industrial plant requires addressing two key issues:

  • Keep-Alives and Reconnection Logic: Modbus connections can drop due to electrical noise or network resets. Your script must detect connection loss and execute retries gracefully.
  • Buffer During Network Outages: If your connection to the cloud MQTT broker drops, you will lose data. Implement a local database buffer on the gateway to temporarily cache the readings until connection is restored. Read our guide on Resilient Store-and-Forward Buffering to learn how.

Conclusion

Retrofitting legacy machinery with a Python-based protocol translator is a cost-effective and powerful way to transform legacy hardware into cloud-ready nodes. By parsing register maps on the edge and communicating via structured, lightweight MQTT JSON, manufacturers gain instant visibility without replacing multi-million dollar capital assets.

AdaptNXT specializes in brownfield integrations, protocol translation, and custom edge gateway software development. Contact our IoT engineers to start connecting your factory today.

Category IoT
Share this article
Link copied to clipboard!

Want to Discuss Your Next Project?

Let's explore how our expertise can drive your business forward.

Get In Touch
Call
WhatsApp
Email