Skip to main content
deleted 555 characters in body; edited title
Source Link

Modbus TCP Gateway returns zero-filled packets instead of timeoutsuccessful '0' for disconnectednon-existent Slave IDs instead of Timeout. How to reliably detect offline devices?

I am writingdeveloping a C# application using the EasyModbusEasyModbus library to poll severalmultiple Modbus RTU devices connected viabehind a single Modbus TCP Gateway.

The Problem: Normally The application works perfectly when the devices are online or when the gateway itself is disconnected (it properly throws a timeout exception). However, ifI am facing a critical issue with non-existent or offline Slave IDs.

If I query a Slave ID that is physically disconnected or missingsimply doesn't exist on the RS485 bus, I expectthe gateway does not throw a TimeoutExceptiontimeout or a Modbus Exception. HoweverInstead, my specific Gateway handles missing slaves by returningit intercepts the timeout and returns a perfectly valid Modbus TCP packet filled entirely with zeros0s ([0, 0, 0...]). Therefore, the code doesn't fall intoor sometimes repeats the catch block and assumesdata from the device is online and reading 0previous active Slave ID).

My Partial Workaround: For devices where I read multiple registers Since 0 is a completely normal value for some of my point sensors (e.g., quantity = 15normal state = 0, alarm = 1), I addedcannot distinguish between a logic to check if all values are 0. If they are, I assume the device is offline, because"Healthy Sensor reading 0" and a real device will have at least one non-zero configuration or time register"Missing Sensor returning fake 0s".

The Core Issue: To bypass this hardware limitation, I have some "Point Sensors" whereimplemented a "Ping" logic in C#. If I only needread a 0 from a point sensor, I immediately try to read quantity = 1a clearly invalid register. The normal address (no-alarm) state of this register is 0e. Since I don't have the manual for these sensorsg., I don't know any specific static address (like Baudrate or Firmware Version9999) to "ping" and expect a non-zero response.

How can I reliably differentiate between "Sensor is online and normal (returns 0)" and "Sensor is offline (Gateway returns fake 0)" under these circumstances? Is there a Modbus-level trick or standard register to ping when manuals are missing?

Here is my simplified code:

using EasyModbus;
using System;

namespace MyApp.Modbus
{
    public class ModbusScanner
    {
        public void ScanDevice(string ip, int port, byte slaveId, int startAddress, int quantity)
        {
            ModbusClient modbusClient = new ModbusClient(ip, port)
            {
                UnitIdentifier = slaveId,
                ConnectionTimeout = 1500
            };

            try
            {
                modbusClient.Connect();
                
                // Gateway returns an array of 0s instead of throwing timeout ifIf Slavethe IDdevice is missing
                int[] registers =truly modbusClient.ReadHoldingRegisters(startAddressonline, quantity);

                if (quantity > 1)
                {
                    // Workaround for multi-register devices
                    bool allZero = true;
                    foreach (int val in registers)
                    {
                        if (val != 0) { allZero = false; break; }
                    }

                    if (allZero)
                    {
                 it responds with 02 Illegal Data Address Console.WriteLine($"Slave ID {slaveId}which isI offlinecatch (Gatewayand sentconsider fakeas 0s"Alive").");
                    }
                }
                else if (quantity == 1)
                {
                    // THE PROBLEM IS HERE:
                    // Single-register device.If Normalthe stategateway is 0. 
                    // How do I know if it's offline or just reading normal 0lying, withoutit knowingreturns a static register to ping?
                    int regValue = registers[0]; 
                }
            }
            catch (Exception ex)
            {
                // Thissuccessful catchread iswithout notany triggeredexception, byproving the gateway for missing slaves
                Console.WriteLine($"Network Failure: {ex.Message}");
            }
            finally
            {
               device ifis (modbusClient.Connected)actually modbusClientoffline.Disconnect();
            }
        }
    }
}

Here is a simplified version of my polling loop:

using System;
using System.Diagnostics;

public void PollSensors()
{
    ModbusClient modbusClient = new ModbusClient("192.168.1.100", 502)
    {
        ConnectionTimeout = 1500
    };

    try
    {
        modbusClient.Connect();
        
        // Let's say Slave ID 5 is currently disconnected
        modbusClient.UnitIdentifier = 5; 

        // Read 1 register starting from address 0
        int[] registers = modbusClient.ReadHoldingRegisters(0, 1);

        if (registers.Length > 0 && registers[0] == 0)
        {
            try
            {
                // PING TEST: Try reading an invalid address to force an exception
                modbusClient.ReadHoldingRegisters(9999, 1);
                
                // If we reach here, the gateway swallowed the error. The device is offline.
                throw new Exception("Gateway returned fake 0. Device is actually offline.");
            }
            catch (EasyModbus.Exceptions.ModbusException)
            {
                // Device threw "02 Illegal Address". It is physically online and healthy.
                Debug.WriteLine("Sensor is online.");
            }
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine($"Network Failure: {ex.Message}");
    }
    finally
    {
        if (modbusClient.Connected) modbusClient.Disconnect();
    }
}```

Modbus TCP Gateway returns zero-filled packets instead of timeout for disconnected Slave IDs. How to reliably detect offline devices?

I am writing a C# application using the EasyModbus library to poll several Modbus RTU devices connected via a Modbus TCP Gateway.

The Problem: Normally, if a Slave ID is disconnected or missing, I expect a TimeoutException or a Modbus Exception. However, my specific Gateway handles missing slaves by returning a perfectly valid Modbus TCP packet filled entirely with zeros ([0, 0, 0...]). Therefore, the code doesn't fall into the catch block and assumes the device is online and reading 0.

My Partial Workaround: For devices where I read multiple registers (e.g., quantity = 15), I added a logic to check if all values are 0. If they are, I assume the device is offline, because a real device will have at least one non-zero configuration or time register.

The Core Issue: I have some "Point Sensors" where I only need to read quantity = 1 register. The normal (no-alarm) state of this register is 0. Since I don't have the manual for these sensors, I don't know any specific static address (like Baudrate or Firmware Version) to "ping" and expect a non-zero response.

How can I reliably differentiate between "Sensor is online and normal (returns 0)" and "Sensor is offline (Gateway returns fake 0)" under these circumstances? Is there a Modbus-level trick or standard register to ping when manuals are missing?

Here is my simplified code:

using EasyModbus;
using System;

namespace MyApp.Modbus
{
    public class ModbusScanner
    {
        public void ScanDevice(string ip, int port, byte slaveId, int startAddress, int quantity)
        {
            ModbusClient modbusClient = new ModbusClient(ip, port)
            {
                UnitIdentifier = slaveId,
                ConnectionTimeout = 1500
            };

            try
            {
                modbusClient.Connect();
                
                // Gateway returns an array of 0s instead of throwing timeout if Slave ID is missing
                int[] registers = modbusClient.ReadHoldingRegisters(startAddress, quantity);

                if (quantity > 1)
                {
                    // Workaround for multi-register devices
                    bool allZero = true;
                    foreach (int val in registers)
                    {
                        if (val != 0) { allZero = false; break; }
                    }

                    if (allZero)
                    {
                        Console.WriteLine($"Slave ID {slaveId} is offline (Gateway sent fake 0s).");
                    }
                }
                else if (quantity == 1)
                {
                    // THE PROBLEM IS HERE:
                    // Single-register device. Normal state is 0. 
                    // How do I know if it's offline or just reading normal 0 without knowing a static register to ping?
                    int regValue = registers[0]; 
                }
            }
            catch (Exception ex)
            {
                // This catch is not triggered by the gateway for missing slaves
                Console.WriteLine($"Network Failure: {ex.Message}");
            }
            finally
            {
                if (modbusClient.Connected) modbusClient.Disconnect();
            }
        }
    }
}

Modbus TCP Gateway returns successful '0' for non-existent Slave IDs instead of Timeout. How to reliably detect offline devices?

I am developing a C# application using the EasyModbus library to poll multiple Modbus RTU devices connected behind a single Modbus TCP Gateway.

The application works perfectly when the devices are online or when the gateway itself is disconnected (it properly throws a timeout exception). However, I am facing a critical issue with non-existent or offline Slave IDs.

If I query a Slave ID that is physically disconnected or simply doesn't exist on the RS485 bus, the gateway does not throw a timeout or a Modbus Exception. Instead, it intercepts the timeout and returns a perfectly valid Modbus packet filled with 0s (or sometimes repeats the data from the previous active Slave ID).

Since 0 is a completely normal value for some of my point sensors (e.g., normal state = 0, alarm = 1), I cannot distinguish between a "Healthy Sensor reading 0" and a "Missing Sensor returning fake 0s".

To bypass this hardware limitation, I implemented a "Ping" logic in C#. If I read a 0 from a point sensor, I immediately try to read a clearly invalid register address (e.g., 9999).

If the device is truly online, it responds with 02 Illegal Data Address (which I catch and consider as "Alive").

If the gateway is lying, it returns a successful read without any exception, proving the device is actually offline.

Here is a simplified version of my polling loop:

using System;
using System.Diagnostics;

public void PollSensors()
{
    ModbusClient modbusClient = new ModbusClient("192.168.1.100", 502)
    {
        ConnectionTimeout = 1500
    };

    try
    {
        modbusClient.Connect();
        
        // Let's say Slave ID 5 is currently disconnected
        modbusClient.UnitIdentifier = 5; 

        // Read 1 register starting from address 0
        int[] registers = modbusClient.ReadHoldingRegisters(0, 1);

        if (registers.Length > 0 && registers[0] == 0)
        {
            try
            {
                // PING TEST: Try reading an invalid address to force an exception
                modbusClient.ReadHoldingRegisters(9999, 1);
                
                // If we reach here, the gateway swallowed the error. The device is offline.
                throw new Exception("Gateway returned fake 0. Device is actually offline.");
            }
            catch (EasyModbus.Exceptions.ModbusException)
            {
                // Device threw "02 Illegal Address". It is physically online and healthy.
                Debug.WriteLine("Sensor is online.");
            }
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine($"Network Failure: {ex.Message}");
    }
    finally
    {
        if (modbusClient.Connected) modbusClient.Disconnect();
    }
}```
edited tags
Link
Clemens
  • 129.2k
  • 13
  • 164
  • 296
Source Link

Modbus TCP Gateway returns zero-filled packets instead of timeout for disconnected Slave IDs. How to reliably detect offline devices?

I am writing a C# application using the EasyModbus library to poll several Modbus RTU devices connected via a Modbus TCP Gateway.

The Problem: Normally, if a Slave ID is disconnected or missing, I expect a TimeoutException or a Modbus Exception. However, my specific Gateway handles missing slaves by returning a perfectly valid Modbus TCP packet filled entirely with zeros ([0, 0, 0...]). Therefore, the code doesn't fall into the catch block and assumes the device is online and reading 0.

My Partial Workaround: For devices where I read multiple registers (e.g., quantity = 15), I added a logic to check if all values are 0. If they are, I assume the device is offline, because a real device will have at least one non-zero configuration or time register.

The Core Issue: I have some "Point Sensors" where I only need to read quantity = 1 register. The normal (no-alarm) state of this register is 0. Since I don't have the manual for these sensors, I don't know any specific static address (like Baudrate or Firmware Version) to "ping" and expect a non-zero response.

How can I reliably differentiate between "Sensor is online and normal (returns 0)" and "Sensor is offline (Gateway returns fake 0)" under these circumstances? Is there a Modbus-level trick or standard register to ping when manuals are missing?

Here is my simplified code:

using EasyModbus;
using System;

namespace MyApp.Modbus
{
    public class ModbusScanner
    {
        public void ScanDevice(string ip, int port, byte slaveId, int startAddress, int quantity)
        {
            ModbusClient modbusClient = new ModbusClient(ip, port)
            {
                UnitIdentifier = slaveId,
                ConnectionTimeout = 1500
            };

            try
            {
                modbusClient.Connect();
                
                // Gateway returns an array of 0s instead of throwing timeout if Slave ID is missing
                int[] registers = modbusClient.ReadHoldingRegisters(startAddress, quantity);

                if (quantity > 1)
                {
                    // Workaround for multi-register devices
                    bool allZero = true;
                    foreach (int val in registers)
                    {
                        if (val != 0) { allZero = false; break; }
                    }

                    if (allZero)
                    {
                        Console.WriteLine($"Slave ID {slaveId} is offline (Gateway sent fake 0s).");
                    }
                }
                else if (quantity == 1)
                {
                    // THE PROBLEM IS HERE:
                    // Single-register device. Normal state is 0. 
                    // How do I know if it's offline or just reading normal 0 without knowing a static register to ping?
                    int regValue = registers[0]; 
                }
            }
            catch (Exception ex)
            {
                // This catch is not triggered by the gateway for missing slaves
                Console.WriteLine($"Network Failure: {ex.Message}");
            }
            finally
            {
                if (modbusClient.Connected) modbusClient.Disconnect();
            }
        }
    }
}