100 lines
3.8 KiB
C#
100 lines
3.8 KiB
C#
using System.Reflection;
|
|
using InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames;
|
|
using InnovEnergy.Lib.Protocols.Modbus.Reflection.Attributes;
|
|
using InnovEnergy.Lib.Utils;
|
|
using static System.Reflection.BindingFlags;
|
|
|
|
namespace InnovEnergy.Lib.Protocols.Modbus.Reflection;
|
|
|
|
using ModbusRegisters = IReadOnlyList<ModbusRegister>;
|
|
using ModbusBooleans = IReadOnlyList<ModbusBoolean>;
|
|
using UInt16s = IReadOnlyList<UInt16>;
|
|
using Booleans = IReadOnlyList<Boolean>;
|
|
|
|
internal static class Batches
|
|
{
|
|
|
|
internal static IEnumerable<ModbusRegister[]> GetModbusRegisterBatches<T>(this Object statusRecord) where T : ModbusRegisterAttribute
|
|
{
|
|
var modbusRegisters = from mi in statusRecord.GetDataMembers()
|
|
from a in mi.GetCustomAttributes<T>()
|
|
select new ModbusRegister(a, mi, statusRecord);
|
|
|
|
return modbusRegisters.SplitIntoFrameSizedBatches();
|
|
}
|
|
|
|
|
|
internal static IEnumerable<ModbusBoolean[]> GetModbusBooleanBatches<T>(this Object statusRecord) where T : ModbusBooleanAttribute
|
|
{
|
|
var modbusBooleans = from mi in statusRecord.GetDataMembers()
|
|
from a in mi.GetCustomAttributes<T>()
|
|
select new ModbusBoolean(a, mi, statusRecord);
|
|
|
|
return modbusBooleans.SplitIntoFrameSizedBatches();
|
|
}
|
|
|
|
|
|
private static IEnumerable<MemberInfo> GetDataMembers(this Object statusRecord)
|
|
{
|
|
const BindingFlags bindingFlags = Instance
|
|
| Public
|
|
| NonPublic
|
|
| FlattenHierarchy;
|
|
|
|
var type = statusRecord.GetType();
|
|
|
|
var fields = type.GetFields(bindingFlags);
|
|
var props = type.GetProperties(bindingFlags);
|
|
|
|
return fields.Concat<MemberInfo>(props);
|
|
}
|
|
|
|
|
|
private static IEnumerable<T[]> SplitIntoFrameSizedBatches<T>(this IEnumerable<T> members) where T : IAddress
|
|
{
|
|
return members
|
|
.OrderBy(m => m.Address)
|
|
.GroupWhile((a, b) => b.Address - a.Address > 1) // split when there is a gap between consecutive addresses
|
|
.SelectMany(g => g.Chunk(Constants.MaxRegs)); // group cannot be larger than Constants.MaxRegs
|
|
}
|
|
|
|
|
|
public static IEnumerable<UInt16> SetStatusRecordMembersFromRawModbusValues(this ModbusRegisters modbusBooleans, UInt16s rawRegisterValues)
|
|
{
|
|
foreach (var modbusBoolean in modbusBooleans)
|
|
{
|
|
var index = modbusBoolean.Address - modbusBooleans[0].Address;
|
|
var rawRegisterValue = rawRegisterValues[index];
|
|
modbusBoolean.SetStatusRecordMemberFromRawModbusValue(rawRegisterValue);
|
|
yield return modbusBoolean.Address;
|
|
}
|
|
}
|
|
|
|
|
|
public static UInt16[] GetRawModbusValuesFromControlRecord(this ModbusRegisters modbusBooleans)
|
|
{
|
|
return modbusBooleans
|
|
.Select(v => v.GetRawModbusValueFromControlRecord())
|
|
.ToArray(modbusBooleans.Count);
|
|
}
|
|
|
|
|
|
public static IEnumerable<UInt16> SetStatusRecordMembersFromRawModbusValues(this ModbusBooleans modbusBooleans, Booleans rawRegisterValues)
|
|
{
|
|
foreach (var modbusBoolean in modbusBooleans)
|
|
{
|
|
var index = modbusBoolean.Address - modbusBooleans[0].Address;
|
|
var rawRegisterValue = rawRegisterValues[index];
|
|
modbusBoolean.SetStatusRecordMemberFromRawModbusValue(rawRegisterValue);
|
|
yield return modbusBoolean.Address;
|
|
}
|
|
}
|
|
|
|
|
|
public static Boolean[] GetRawModbusValuesFromControlRecord(this ModbusBooleans modbusBooleans)
|
|
{
|
|
return modbusBooleans
|
|
.Select(v => v.GetRawModbusValueFromControlRecord())
|
|
.ToArray(modbusBooleans.Count);
|
|
}
|
|
} |