void IMODBUSResponseMessage.Initialize(byte[] frame, bool isExtendedUnitId, IMODBUSRequestMessage requestMessage) { base.Initialize(frame, isExtendedUnitId); var dataLength = isExtendedUnitId ? frame[3] : frame[2]; var readCoilRegistersRequest = requestMessage as ReadCoilRegistersRequest; if (readCoilRegistersRequest != null) { this.CoilRegisters = readCoilRegistersRequest.CoilRegisters; data = new byte[dataLength + 1]; if (isExtendedUnitId) { Buffer.BlockCopy(frame, 3, data, 0, dataLength + 1); } else { Buffer.BlockCopy(frame, 2, data, 0, dataLength + 1); } var coilValues = new BitArray(data); for (int i = 0; i < this.CoilRegisters.Count; i++) { ((IMODBUSRegisterData)this.CoilRegisters[i]).Data = BitConverter.GetBytes(coilValues[i + 8]); } } else { throw new FormatException("Unable to create response message (request message null)."); } }
void IMODBUSResponseMessage.Initialize(byte[] frame, bool isExtendedUnitId, IMODBUSRequestMessage requestMessage) { base.Initialize(frame, isExtendedUnitId); var dataLength = isExtendedUnitId ? 5 : 4; var writeBooleanRequest = requestMessage as WriteBooleanRequest; if (writeBooleanRequest != null) { data = new byte[dataLength]; if (isExtendedUnitId) { Buffer.BlockCopy(frame, 3, data, 0, dataLength); } else { Buffer.BlockCopy(frame, 2, data, 0, dataLength); } } else { throw new FormatException("Unable to create response message (request message null)."); } }
void IMODBUSResponseMessage.Initialize(byte[] frame, bool isExtendedUnitId, IMODBUSRequestMessage requestMessage) { base.Initialize(frame, isExtendedUnitId); var dataLength = isExtendedUnitId ? frame[3] : frame[2]; var readEventArchiveRequest = requestMessage as ReadEventArchiveRequest; if (readEventArchiveRequest != null) { data = new byte[dataLength + 1]; if (isExtendedUnitId) { Buffer.BlockCopy(frame, 3, data, 0, dataLength + 1); } else { Buffer.BlockCopy(frame, 2, data, 0, dataLength + 1); } this.EventArchiveRecords = new List <EventArchiveRecord>(); for (int i = 1; i < dataLength; i += 20) { var eventData = new byte[20]; Buffer.BlockCopy(data, i, eventData, 0, 20); this.EventArchiveRecords.Add(new EventArchiveRecord(readEventArchiveRequest.Index, eventData)); } } else { throw new FormatException("Unable to create response message (request message null)."); } }
void IMODBUSResponseMessage.Initialize(byte[] frame, bool isExtendedUnitId, IMODBUSRequestMessage requestMessage) { base.Initialize(frame, isExtendedUnitId); var dataLength = isExtendedUnitId ? frame[3] : frame[2]; var readHistoryArchiveRequest = requestMessage as ReadHistoryArchiveRequest; if (readHistoryArchiveRequest != null) { data = new byte[dataLength + 1]; if (isExtendedUnitId) { Buffer.BlockCopy(frame, 3, data, 0, dataLength + 1); } else { Buffer.BlockCopy(frame, 2, data, 0, dataLength + 1); } var historyData = new byte[dataLength]; Buffer.BlockCopy(data, 1, historyData, 0, dataLength); this.HistoryArchiveRecord = new HistoryArchiveRecord(readHistoryArchiveRequest.Index, historyData); } else { throw new FormatException("Unable to create response message (request message null)."); } }
void IMODBUSResponseMessage.Initialize(byte[] frame, bool isExtendedUnitId, IMODBUSRequestMessage requestMessage) { base.Initialize(frame, isExtendedUnitId); var writeFloatsRequest = requestMessage as WriteFloatsRequest; if (writeFloatsRequest != null) { data = new byte[4]; if (isExtendedUnitId) { Buffer.BlockCopy(frame, 3, data, 0, 4); } else { Buffer.BlockCopy(frame, 2, data, 0, 4); } this.isZeroBased = writeFloatsRequest.FloatRegisters[0].Address.IsZeroBased; } else { throw new FormatException("Unable to create response message (request message null)."); } }
void IMODBUSResponseMessage.Initialize(byte[] frame, bool isExtendedUnitId, IMODBUSRequestMessage requestMessage) { base.Initialize(frame, isExtendedUnitId); var dataLength = isExtendedUnitId ? frame[3] : frame[2]; var readStringRequest = requestMessage as ReadStringRequest; if (readStringRequest != null) { data = new byte[dataLength + 1]; if (isExtendedUnitId) { Buffer.BlockCopy(frame, 3, data, 0, dataLength + 1); } else { Buffer.BlockCopy(frame, 2, data, 0, dataLength + 1); } this.StringRegister = readStringRequest.StringRegister; var stringData = new byte[StringRegister.Length]; Buffer.BlockCopy(data, 1, stringData, 0, dataLength); this.StringRegister.Data = stringData; } else { throw new FormatException("Unable to create response message (request message null)."); } }
void IMODBUSResponseMessage.Initialize(byte[] frame, bool isExtendedUnitId, IMODBUSRequestMessage requestMessage) { base.Initialize(frame, isExtendedUnitId); if (frame.Length < (IsExtendedUnitId ? Device.MinimumFrameSizeWithExtendedUnitId : Device.MinimumFrameSize)) { throw new FormatException("Message frame does not contain enough bytes."); } ErrorCode = IsExtendedUnitId ? frame[3] : frame[2]; }
internal IMODBUSResponseMessage ReadResponse <TResponseMessage>(IMODBUSRequestMessage requestMessage) where TResponseMessage : IMODBUSResponseMessage, new() { var sequence = 0; var referenceHeader = requestMessage.IsExtendedUnitId ? BitConverter.GetBytes(requestMessage.UnitId).Concat(new byte[] { requestMessage.FunctionCode }) : new byte[] { Convert.ToByte(requestMessage.UnitId) }.Concat(new byte[] { requestMessage.FunctionCode }); var errorHeader = requestMessage.IsExtendedUnitId ? BitConverter.GetBytes(requestMessage.UnitId).Concat(new byte[] { Convert.ToByte(requestMessage.FunctionCode + 128) }) : new byte[] { Convert.ToByte(requestMessage.UnitId) }.Concat(new byte[] { Convert.ToByte(requestMessage.FunctionCode + 128) }); var header = Read(requestMessage.IsExtendedUnitId ? RESPONSE_HEADER_LENGTH_WITH_EXTENDED_UNIT_ID : RESPONSE_HEADER_LENGTH, sequence); while ((!header.SequenceEqual(referenceHeader)) && (!header.SequenceEqual(errorHeader))) { sequence++; var streamByte = Read(1, sequence)[0]; if (requestMessage.IsExtendedUnitId) { header = new byte[] { header[1], header[2], streamByte }; } else { header = new byte[] { header[1], streamByte }; } } var frameStart = header.Concat(Read(RESPONSE_DATA_START_LENGTH, sequence)).ToArray(); sequence++; var numberOfBytesToRead = ResponseBytesToRead(frameStart, requestMessage.IsExtendedUnitId); var frameEnd = Read(numberOfBytesToRead, sequence); sequence++; var frameBytes = frameStart.Concat(frameEnd).ToArray(); sequence++; var numberOfBytesAvailable = Channel.NumberOfBytesAvailable; while (numberOfBytesAvailable > 0) { sequence++; Read(numberOfBytesAvailable, (-1 * sequence)); Thread.Sleep(0); numberOfBytesAvailable = Channel.NumberOfBytesAvailable; } var responseMessage = CreateResponse <TResponseMessage>(frameBytes, requestMessage); if (!ChecksumsMatch(responseMessage, frameBytes)) { throw new IOException("Checksum Error"); } return(responseMessage); }
internal void ValidateResponse(IMODBUSRequestMessage request, IMODBUSResponseMessage response) { if (request.FunctionCode != response.FunctionCode) { throw new IOException(String.Format(CultureInfo.InvariantCulture, "Received response with unexpected function code. Expected {0}, received {1}.", request.FunctionCode, response.FunctionCode)); } if (request.UnitId != response.UnitId) { throw new IOException(String.Format(CultureInfo.InvariantCulture, "Response source unit does not match request. Expected {0}, received {1}.", response.UnitId, request.UnitId)); } request.ValidateResponse(response); }
void IMODBUSResponseMessage.Initialize(byte[] frame, bool isExtendedUnitId, IMODBUSRequestMessage requestMessage) { base.Initialize(frame, isExtendedUnitId); var dataLength = isExtendedUnitId ? frame[3] : frame[2]; var readShortsRequest = requestMessage as ReadShortsRequest; if (readShortsRequest != null) { this.ShortRegisters = readShortsRequest.ShortRegisters; data = new byte[dataLength + 1]; if (isExtendedUnitId) { Buffer.BlockCopy(frame, 3, data, 0, dataLength + 1); } else { Buffer.BlockCopy(frame, 2, data, 0, dataLength + 1); } var shortRegisters = new List <ShortRegister>(); for (int i = 1; i < data.Length; i += 2) { var shortData = new byte[] { data[i], data[i + 1] }; ((IMODBUSRegisterData)this.ShortRegisters[((i - 1) / 2)]).Data = shortData; } } else { throw new FormatException("Unable to create response message (request message null)."); } }
public static IMODBUSResponseMessage CreateMODBUSResponseMessage <TResponseMessage>(byte[] frame, bool isExtendedUnitId, IMODBUSRequestMessage requestMessage) where TResponseMessage : IMODBUSResponseMessage, new() { TResponseMessage responseMessage = new TResponseMessage(); responseMessage.Initialize(frame, isExtendedUnitId, requestMessage); return(responseMessage); }
internal virtual TResponseMessage UnicastMessage <TResponseMessage>(IMODBUSRequestMessage requestMessage) where TResponseMessage : IMODBUSResponseMessage, new() { if (TracingEnabled) { Trace.WriteLine(string.Format("Function {0} Request Started At: {1}", requestMessage.FunctionCode.ToString(), DateTime.Now.ToString("O"), "Transport")); } var lastException = (Exception)null; var transactionStopWatch = Stopwatch.StartNew(); IMODBUSResponseMessage response = default(TResponseMessage); int attempt = 0; bool success = false; lock (channelLock) { do { try { attempt++; if (RequestWriteDelayMilliseconds > 0) { if (TracingEnabled) { Trace.WriteLine(string.Format("Function {0} Request Write Delay: {1}ms", requestMessage.FunctionCode.ToString(), RequestWriteDelayMilliseconds.ToString("0.0")), "Transport"); } TimedThreadBlocker.Wait(RequestWriteDelayMilliseconds); } Write(requestMessage); if (ResponseReadDelayMilliseconds > 0) { if (TracingEnabled) { Trace.WriteLine(string.Format("Function {0} Request Read Delay: {1}", requestMessage.FunctionCode.ToString(), ResponseReadDelayMilliseconds.ToString("0.0")), "Transport"); } TimedThreadBlocker.Wait(RequestWriteDelayMilliseconds); } response = ReadResponse <TResponseMessage>(requestMessage); if (response is MODBUSErrorResponse) { throw new MODBUSSlaveException(response as MODBUSErrorResponse); } else { ValidateResponse(requestMessage, response); transactionStopWatch.Stop(); if (TracingEnabled) { Trace.WriteLine(string.Format("Function {0} Request Completed in: {1}ms", requestMessage.FunctionCode.ToString(), transactionStopWatch.Elapsed.TotalMilliseconds.ToString()), "Transport"); } return((TResponseMessage)response); } } catch (Exception e) { lastException = e; Trace.WriteLine(string.Format("Function {0} Request Error: {1}", requestMessage.FunctionCode.ToString(), e.Message), "Transport"); if (e is FormatException || e is NotImplementedException || e is TimeoutException || e is IOException) { if (attempt > NumberOfRetries) { goto Finish; } else { TimedThreadBlocker.Wait(WaitToRetryMilliseconds); } } else { throw; } } if (TracingEnabled) { Trace.WriteLine(string.Format("Function {0} Request Retry Number {1}", requestMessage.FunctionCode.ToString(), attempt.ToString()), "Transport"); } } while (!success && NumberOfRetries > attempt); } Finish: throw new TimeoutException("Device not responding to requests", lastException); }
internal virtual IMODBUSResponseMessage CreateResponse <TResponseMessage>(byte[] frame, IMODBUSRequestMessage requestMessage) where TResponseMessage : IMODBUSResponseMessage, new() { byte functionCode = (requestMessage.IsExtendedUnitId ? frame[2] : frame[1]); IMODBUSResponseMessage response; switch (functionCode) { case Device.ReadCoils: response = MODBUSMessageFactory.CreateMODBUSResponseMessage <ReadCoilRegistersResponse>(frame, requestMessage.IsExtendedUnitId, requestMessage); break; case Device.ReadDiscreteInputs: response = MODBUSMessageFactory.CreateMODBUSResponseMessage <ReadDiscreteInputRegistersResponse>(frame, requestMessage.IsExtendedUnitId, requestMessage); break; case Device.WriteSingleCoil: response = MODBUSMessageFactory.CreateMODBUSResponseMessage <WriteBooleanResponse>(frame, requestMessage.IsExtendedUnitId, requestMessage); break; case Device.ReadInputRegisters: response = MODBUSMessageFactory.CreateMODBUSResponseMessage <ReadInputRegistersResponse>(frame, requestMessage.IsExtendedUnitId, requestMessage); break; case Device.ReadHoldingRegisters: switch (requestMessage.DataType) { case Device.DataType.EventArchive: response = MODBUSMessageFactory.CreateMODBUSResponseMessage <ReadEventArchiveResponse>(frame, requestMessage.IsExtendedUnitId, requestMessage); break; case Device.DataType.HistoryArchive: response = MODBUSMessageFactory.CreateMODBUSResponseMessage <ReadHistoryArchiveResponse>(frame, requestMessage.IsExtendedUnitId, requestMessage); break; case Device.DataType.Short: response = MODBUSMessageFactory.CreateMODBUSResponseMessage <ReadShortsResponse>(frame, requestMessage.IsExtendedUnitId, requestMessage); break; case Device.DataType.Long: response = MODBUSMessageFactory.CreateMODBUSResponseMessage <ReadLongsResponse>(frame, requestMessage.IsExtendedUnitId, requestMessage); break; case Device.DataType.String: response = MODBUSMessageFactory.CreateMODBUSResponseMessage <ReadStringResponse>(frame, requestMessage.IsExtendedUnitId, requestMessage); break; case Device.DataType.Float: response = MODBUSMessageFactory.CreateMODBUSResponseMessage <ReadFloatsResponse>(frame, requestMessage.IsExtendedUnitId, requestMessage); break; default: response = MODBUSMessageFactory.CreateMODBUSResponseMessage <ReadHoldingRegistersResponse>(frame, requestMessage.IsExtendedUnitId, requestMessage); break; } break; case Device.WriteMultipleRegisters: response = MODBUSMessageFactory.CreateMODBUSResponseMessage <WriteFloatsResponse>(frame, requestMessage.IsExtendedUnitId, requestMessage); break; default: if (functionCode > Device.ExceptionOffset) { response = MODBUSMessageFactory.CreateMODBUSResponseMessage <MODBUSErrorResponse>(frame, requestMessage.IsExtendedUnitId); break; } else { throw new FormatException(string.Format("Unknown Function Code ({0}).", functionCode.ToString())); } } return(response); }