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