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();
}
}```
0001 0000 0005 11 03 02 0000when the device behind it is offline? If that is the case I don't see any way for your program to tell the difference between this and a real 0 value. Can you share details of the "specific Gateway"?