using InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Accessors; using InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Replies; using InnovEnergy.Lib.Utils; using static InnovEnergy.Lib.Protocols.Modbus.Protocol.FunctionCode; using static InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Constants; namespace InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Commands; using Booleans = IReadOnlyCollection; using MbFc = MbByte; public class WriteCoilsCommandFrame : ModbusFrame { private new const Int32 MinSize = 7; private MbWord WriteAddress => Data.WordAt(2); private MbWord NbOfCoils => Data.WordAt(4); private MbByte ByteCount => Data.ByteAt(6); private MbBits CoilsToWrite => Data.BitsAt(7); public WriteCoilsCommandFrame(Byte slave, UInt16 writeAddress, Booleans coils) : base(MinSize + NbBytes(coils)) { if (coils.Count > MaxCoils) throw new ArgumentOutOfRangeException($"Maximum number of Coils to write ({MaxCoils}) exceeded!", nameof(coils)); SlaveAddress.Set(slave); FunctionCode.Set(WriteMultipleCoils); WriteAddress.Set(writeAddress); NbOfCoils .Set(coils.Count); ByteCount .Set(NbBytes(coils)); CoilsToWrite.Set(coils); } private WriteCoilsCommandFrame(ArraySegment data) : base(data) { if (data.Count < MinSize) throw new ArgumentOutOfRangeException($"Expecting an array of size {MinSize} or more!", nameof(data)); AssertFunctionCode(WriteMultipleCoils); var expectedSize = ByteCount + MinSize; if (data.Count != expectedSize) throw new ArgumentException($"Expecting an array of size {expectedSize}", nameof(data)); if (ByteCount != CoilsToWrite.Count / 8) throw new ArgumentException(nameof(CoilsToWrite)); } public WriteCoilsResponseFrame VerifyResponse(WriteCoilsResponseFrame response) { if (response.SlaveAddress != SlaveAddress) throw new UnexpectedResponseFieldException(nameof(response.SlaveAddress), SlaveAddress.ToString(), response.SlaveAddress); if (response.NbWritten != NbOfCoils) throw new UnexpectedResponseFieldException(nameof(response.NbWritten), NbOfCoils, response.NbWritten); if (response.WriteAddress != WriteAddress) throw new UnexpectedResponseFieldException(nameof(response.WriteAddress), WriteAddress, response.WriteAddress); return response; } public static WriteCoilsCommandFrame Parse(ArraySegment data) { return new WriteCoilsCommandFrame(data); } private static Int32 NbBytes(Booleans coils) { return Math.Ceiling(coils.Count / 8.0).ConvertTo(); } }