using InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Accessors; using static InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Constants; using static InnovEnergy.Lib.Protocols.Modbus.Protocol.FunctionCode; namespace InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Replies; using UInt16s = IReadOnlyList; internal class ReadWriteRegistersResponseFrame : ModbusFrame { internal new const Int32 MinSize = 3; public MbByte ByteCount => Data.ByteAt(2); public MbWords RegistersRead => Data.WordsAt(3); public ReadWriteRegistersResponseFrame(Byte slave, UInt16s registersRead) : base(ExpectedSize(registersRead.Count)) { if (registersRead.Count > MaxRegs) throw new ArgumentOutOfRangeException($"Maximum number of registers ({MaxRegs}) exceeeded!", nameof(registersRead)); SlaveAddress .Set(slave); FunctionCode .Set(ReadWriteMultipleRegisters); ByteCount .Set(2 * registersRead.Count); RegistersRead.Set(registersRead); } internal static Int32 ExpectedSize(Int32 nRegisters) => MinSize + nRegisters * 2; private ReadWriteRegistersResponseFrame(Byte[] data) : this (new ArraySegment(data)) { } private ReadWriteRegistersResponseFrame(ArraySegment data) : base(data) { if (data.Count < MinSize) throw new ArgumentException($"Expecting an array of size {MinSize} or more", nameof(data)); AssertFunctionCode(ReadWriteMultipleRegisters); var expectedSize = ByteCount + MinSize; if (data.Count != expectedSize) throw new ArgumentException($"Expecting an array of size {expectedSize}", nameof(data)); if (ByteCount != RegistersRead.Count * 2) throw new ArgumentException(nameof(RegistersRead)); } public static ReadWriteRegistersResponseFrame Parse(Byte[] data) => new ReadWriteRegistersResponseFrame(data); public static ReadWriteRegistersResponseFrame Parse(ArraySegment data) => new ReadWriteRegistersResponseFrame(data); public static ReadWriteRegistersResponseFrame Parse(ModbusFrame frame) => new ReadWriteRegistersResponseFrame(frame.Data); }