private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { var startTime = DateTime.Now; var lockObject = SourceChannel.LockObject; lock (lockObject) { var masterStopWatch = new Stopwatch(); var requestBytes = new byte[] { }; TimedThreadBlocker.Wait(requestDelay); requestBytes = new byte[SerialPort.BytesToRead]; if (requestBytes.Length > 0) { Read(ref requestBytes, 0, requestBytes.Length, 0); SourceChannel.Write(ref requestBytes, 0, requestBytes.Length); TimedThreadBlocker.Wait(responseDelay); masterStopWatch.Start(); var sequence = 0; while (SourceChannel.NumberOfBytesAvailable > 0 && responseTimeout > masterStopWatch.ElapsedMilliseconds) { var responseBytes = new byte[SourceChannel.NumberOfBytesAvailable]; SourceChannel.Read(ref responseBytes, 0, responseBytes.Length, sequence++); Write(ref responseBytes, 0, responseBytes.Length); } masterStopWatch.Stop(); } } }
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 TResponseMessage UnicastMessage <TResponseMessage>(IROCRequestMessage requestMessage) where TResponseMessage : IROCResponseMessage, new() { if (TracingEnabled) { Trace.WriteLine(string.Format("ROCMaster.Transport,WriteDelay,{0},{1}", requestMessage.OpCode.ToString(), DateTime.Now.ToString("O"), "Transport")); } var lastException = (Exception)null; var transactionStopWatch = Stopwatch.StartNew(); IROCResponseMessage responseMessage = default(TResponseMessage); int attempt = 0; bool success = false; object channelLock = Channel.LockObject; lock (channelLock) { do { try { attempt++; if (RequestWriteDelayMilliseconds > 0) { if (TracingEnabled) { Trace.WriteLine(string.Format("ROCMaster.Transport,WriteDelay,{0},{1}", requestMessage.OpCode.ToString(), RequestWriteDelayMilliseconds.ToString("0.0"))); } TimedThreadBlocker.Wait(RequestWriteDelayMilliseconds); } Write(requestMessage); if (ResponseReadDelayMilliseconds > 0) { if (TracingEnabled) { Trace.WriteLine(string.Format("ROCMaster.Transport,ReadDelay,{0},{1}", requestMessage.OpCode.ToString(), ResponseReadDelayMilliseconds.ToString("0.0"))); } TimedThreadBlocker.Wait(RequestWriteDelayMilliseconds); } responseMessage = ReadResponse <TResponseMessage>(requestMessage); if (responseMessage.OpCode == 255) { var opCode255Response = responseMessage as OpCode255Response; if (opCode255Response != null) { throw new OpCode255Exception(opCode255Response); } } else { ValidateResponse(requestMessage, responseMessage); transactionStopWatch.Stop(); if (TracingEnabled) { Trace.WriteLine(string.Format("ROCMaster.Transport,Read,{0},{1},{3},{4}", requestMessage.OpCode.ToString(), transactionStopWatch.Elapsed.TotalMilliseconds.ToString(), HexConverter.ToHexString(requestMessage.ProtocolDataUnit), HexConverter.ToHexString(responseMessage.ProtocolDataUnit), "")); } return((TResponseMessage)responseMessage); } } catch (Exception e) { lastException = e; Trace.WriteLine(string.Format("ROCMaster.Transport.Error,{0},{1}", requestMessage.OpCode.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("ROCMaster.Transport.Warning,Retry,{0},{1}", requestMessage.OpCode.ToString(), attempt.ToString())); } } while (!success && NumberOfRetries > attempt); } Finish: throw new TimeoutException("Device not responding to requests", lastException); }