Шлюз Modbus TCP возвращает успешный «0» для несуществующих идентификаторов подчиненного устройства вместо тайм-аута. КакC#

Место общения программистов C#
Anonymous
Шлюз Modbus TCP возвращает успешный «0» для несуществующих идентификаторов подчиненного устройства вместо тайм-аута. Как

Сообщение Anonymous »

Я разрабатываю приложение C# с использованием библиотеки EasyModbus для опроса нескольких устройств Modbus RTU, подключенных к одному шлюзу Modbus TCP.
Приложение отлично работает, когда устройства находятся в сети или когда сам шлюз отключен (оно правильно выдает исключение тайм-аута). Однако я столкнулся с критической проблемой, связанной с несуществующими или автономными идентификаторами подчиненных устройств.
Если я запрашиваю идентификатор подчиненного устройства, который физически отключен или просто не существует на шине RS485, шлюз не выдает тайм-аут или исключение Modbus. Вместо этого он перехватывает тайм-аут и возвращает совершенно действительный пакет Modbus, заполненный нулями (или иногда повторяет данные из предыдущего активного идентификатора подчиненного устройства).
Поскольку 0 является совершенно нормальным значением для некоторых из моих точечных датчиков (например, нормальное состояние = 0, сигнал тревоги = 1), я не могу отличить «Исправный датчик, показывающий 0» и «Отсутствующий датчик, возвращающий ложные 0».
Чтобы обойти Из-за этого аппаратного ограничения я реализовал логику «Ping» на C#. Если я читаю 0 с точечного датчика, я немедленно пытаюсь прочитать явно неверный адрес регистра (например, 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.

Вот упрощенная версия моего цикла опроса:
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();
}
}```

Вернуться в «C#»