using InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Accessors; using InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Replies; using static InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Constants; using static InnovEnergy.Lib.Protocols.Modbus.Protocol.FunctionCode; namespace InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Commands; using UInt16s = IReadOnlyList; internal class ReadWriteRegistersCommandFrame : ModbusFrame { internal new const Int32 MinSize = 11; public MbWord ReadAddress => Data.WordAt(2); public MbWord NbToRead => Data.WordAt(4); public MbWord WriteAddress => Data.WordAt(6); public MbWord NbToWrite => Data.WordAt(8); public MbByte ByteCount => Data.ByteAt(10); public MbWords RegistersToWrite => Data.WordsAt(11); public Int32 ExpectedResponseSize => ReadWriteRegistersResponseFrame.ExpectedSize(NbToRead); public ReadWriteRegistersCommandFrame(Byte slave, UInt16 readAddress, UInt16 nbToRead, UInt16 writeAddress, UInt16s registersToWrite) : base(MinSize + registersToWrite.Count * 2) { if (nbToRead > MaxRegs) throw new ArgumentOutOfRangeException($"Maximum number of registers ({MaxRegs}) exceeeded!", nameof(nbToRead)); if (registersToWrite.Count > MaxRegs) throw new ArgumentOutOfRangeException($"Maximum number of registers ({MaxRegs}) exceeeded!", nameof(registersToWrite)); SlaveAddress .Set(slave); FunctionCode .Set(ReadWriteMultipleRegisters); ReadAddress .Set(readAddress); NbToRead .Set(nbToRead); WriteAddress .Set(writeAddress); NbToWrite .Set(registersToWrite.Count); ByteCount .Set(registersToWrite.Count * 2); RegistersToWrite.Set(registersToWrite); } private ReadWriteRegistersCommandFrame(ArraySegment data) : base(data) { if (data.Count < MinSize) throw new ArgumentOutOfRangeException($"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)); } public static ReadWriteRegistersCommandFrame Parse(ArraySegment data) { return new ReadWriteRegistersCommandFrame(data); } public ReadWriteRegistersResponseFrame VerifyResponse(ReadWriteRegistersResponseFrame response) { if (response.SlaveAddress != SlaveAddress) throw new UnexpectedResponseFieldException(nameof(response.SlaveAddress), SlaveAddress.ToString(), response.SlaveAddress); if (response.RegistersRead.Count != NbToRead) throw new UnexpectedResponseFieldException(nameof(response.RegistersRead), NbToRead.ToString(), response.RegistersRead.Count); return response; } }