Innovenergy_trunk/csharp/Lib/Protocols/Modbus/Clients/ModbusSlave.cs

159 lines
4.8 KiB
C#

using InnovEnergy.Lib.Protocols.Modbus.Reflection;
using InnovEnergy.Lib.Protocols.Modbus.Reflection.Attributes;
namespace InnovEnergy.Lib.Protocols.Modbus.Clients;
public class ModbusSlave<S, C> where S : notnull, new() where C : notnull
{
private readonly ModbusClient _ModbusClient;
public ModbusSlave(ModbusClient modbusClient) => _ModbusClient = modbusClient;
public S? Read()
{
try
{
return ReadInto(new S());
}
catch (Exception e)
{
return default; // TODO :stdErr
}
}
public Exception? Write(C controlRecord)
{
try
{
WriteHoldingRegisters(controlRecord);
WriteCoils(controlRecord);
}
catch (Exception e)
{
_ModbusClient.Connection.Close();
return e;
}
return default;
}
public S ReadInto(S statusRecord)
{
Int32 holdingRegisters;
Int32 coils;
Int32 inputRegisters;
Int32 discreteInputs;
try
{
holdingRegisters = ReadHoldingRegisters(statusRecord).Count(); // force enumeration!
inputRegisters = ReadInputRegisters(statusRecord).Count();
discreteInputs = ReadDiscreteInputs(statusRecord).Count();
coils = ReadCoils(statusRecord).Count();
}
catch (Exception e)
{
_ModbusClient.Connection.Close();
throw;
}
var nUpdated = holdingRegisters
+ inputRegisters
+ discreteInputs
+ coils;
if (nUpdated == 0)
throw new ArgumentException(nameof(statusRecord));
return statusRecord;
}
// returns an enumerable of read addresses
private IEnumerable<UInt16> ReadDiscreteInputs(Object statusRecord)
{
return from batch in statusRecord.GetModbusBooleanBatches<DiscreteInputAttribute>()
let received = _ModbusClient.ReadDiscreteInputs(batch[0].Address, (UInt16)batch.Length)
from address in batch.SetStatusRecordMembersFromRawModbusValues(received)
select address;
}
// returns an enumerable of read addresses
private IEnumerable<UInt16> ReadCoils(Object statusRecord)
{
return from batch in statusRecord.GetModbusBooleanBatches<CoilAttribute>()
let received = _ModbusClient.ReadCoils(batch[0].Address, (UInt16)batch.Length)
from address in batch.SetStatusRecordMembersFromRawModbusValues(received)
select address;
}
// returns an enumerable of read addresses
private IEnumerable<UInt16> ReadInputRegisters(Object statusRecord)
{
return from batch in statusRecord.GetModbusRegisterBatches<InputRegisterAttribute>()
let received = _ModbusClient.ReadInputRegisters(batch[0].Address, (UInt16)batch.Length)
from address in batch.SetStatusRecordMembersFromRawModbusValues(received)
select address;
}
// returns an enumerable of read addresses
private IEnumerable<UInt16> ReadHoldingRegisters(Object statusRecord)
{
return from batch in statusRecord.GetModbusRegisterBatches<HoldingRegisterAttribute>()
let received = _ModbusClient.ReadHoldingRegisters(batch[0].Address, (UInt16)batch.Length)
from address in batch.SetStatusRecordMembersFromRawModbusValues(received)
select address;
}
private Int32 WriteCoils(C controlRecord)
{
var nBatches = 0;
foreach (var batch in controlRecord.GetModbusBooleanBatches<CoilAttribute>())
{
var values = batch.GetRawModbusValuesFromControlRecord();
_ModbusClient.WriteCoils(batch[0].Address, values);
nBatches++;
}
return nBatches;
}
private Int32 WriteHoldingRegisters(C controlRecord)
{
var nBatches = 0;
foreach (var batch in controlRecord.GetModbusRegisterBatches<HoldingRegisterAttribute>())
{
var values = batch.GetRawModbusValuesFromControlRecord();
_ModbusClient.WriteRegisters(batch[0].Address, values);
nBatches++;
}
return nBatches;
}
}
public class ModbusSlave<T> : ModbusSlave<T, T> where T : notnull, new()
{
public ModbusSlave(ModbusClient modbusClient) : base(modbusClient)
{
}
}
public static class ModbusSlave
{
public static ModbusSlave<T> Slave<T>(this ModbusClient modbusClient) where T : notnull, new()
{
return new ModbusSlave<T>(modbusClient);
}
public static ModbusSlave<S,C> Slave<S,C>(this ModbusClient modbusClient) where S : notnull, new() where C : notnull
{
return new ModbusSlave<S, C>(modbusClient);
}
}