예제 #1
0
        internal override ModbusResponse DeserializeResponse(ResponseBuffer buffer, ModbusRequest request, int timeout)
        {
            ModbusResponse result = null;

            while (result == null ||
                   result is ModbusCommErrorResponse responseCommErrorMessage &&
                   responseCommErrorMessage.ErrorCode != ModbusCommErrorCode.ResponseTimeout)
            {
                if (buffer.Count > 0)
                {
                    errorBuffer.Add(buffer[0]);
                    buffer.RemoveAt(0);
                }

                buffer.Read(timeout);

                try
                {
                    while (buffer[0] != 0x3a)
                    {
                        errorBuffer.Add(buffer[0]);
                        buffer.RemoveAt(0);
                        buffer.Read(timeout);
                    }
                }
                catch
                {
                    return(new ModbusCommErrorResponse(ModbusCommErrorCode.ResponseAsciiStartError, errorBuffer.Concat(buffer), request));
                }

                result = base.DeserializeResponse(buffer, request, timeout);
            }

            if (result is ModbusCommErrorResponse responseCommError)
            {
                result = new ModbusCommErrorResponse(responseCommError.ErrorCode, errorBuffer.Concat(responseCommError.ReceivedBytes), request);
            }
            else
            {
                var asciiEnd = buffer.Read(2, timeout);
                if (!asciiEnd.SequenceEqual(new byte[] { 13, 10 }))
                {
                    return(new ModbusCommErrorResponse(ModbusCommErrorCode.ResponseAsciiEndError, buffer, request));
                }

                if (errorBuffer.Count > 0)
                {
                    RaiseUnrecognized(buffer.Channel, errorBuffer.ToArray());
                    errorBuffer.Clear();
                }
            }

            return(result);
        }
예제 #2
0
        internal virtual IEnumerable <byte> Read(ResponseBuffer buffer, int index, int count, int timeout)
        {
            if (index + count > buffer.Count)
            {
                buffer.Read((uint)(index + count - buffer.Count), timeout);
            }

            return(buffer.Skip(index).Take(count));
        }
예제 #3
0
        internal virtual byte Read(ResponseBuffer buffer, int index, int timeout)
        {
            if (index >= buffer.Count)
            {
                buffer.Read((uint)(index - buffer.Count + 1), timeout);
            }

            return(buffer[index]);
        }
예제 #4
0
        internal override byte Read(ResponseBuffer buffer, int index, int timeout)
        {
            if (index * 2 >= buffer.Count - 2)
            {
                buffer.Read((uint)(index * 2 - buffer.Count + 3), timeout);
            }

            return(byte.Parse(Encoding.ASCII.GetString(buffer.Skip(index * 2 + 1).Take(2).ToArray()), System.Globalization.NumberStyles.HexNumber, null));
        }
예제 #5
0
        internal override IEnumerable <byte> Read(ResponseBuffer buffer, int index, int count, int timeout)
        {
            if ((index + count) * 2 > buffer.Count - 1)
            {
                buffer.Read((uint)((index + count) * 2 - buffer.Count + 1), timeout);
            }

            var bytes = buffer.Skip(index * 2 + 1).Take(count * 2).ToArray();

            for (int i = 0; i < count; i++)
            {
                yield return(byte.Parse(Encoding.ASCII.GetString(bytes, i * 2, 2), System.Globalization.NumberStyles.HexNumber, null));
            }
        }
예제 #6
0
        private void RunReceive(ModbusChannel channel)
        {
            lock (responseWaitHandles)
            {
                if (!isReceiving)
                {
                    isReceiving = true;
                    try
                    {
                        var readBuffer = new ResponseBuffer(channel);

                        while (responseWaitHandles.Count > 0)
                        {
                            if (errorBuffer.Count >= 256)
                            {
                                RaiseUnrecognized(channel, errorBuffer.ToArray());
                                errorBuffer.Clear();
                            }

                            readBuffer.Read(2, 0);

                            ushort transactionID = (ushort)((readBuffer[0] << 8) | readBuffer[1]);
                            if (!responseWaitHandles.TryGetValue(transactionID, out var responseWaitHandle))
                            {
                                errorBuffer.AddRange(readBuffer);
                                readBuffer.Clear();
                                continue;
                            }

                            readBuffer.Read(2, responseWaitHandle.Timeout);
                            if (readBuffer[2] != 0 ||
                                readBuffer[3] != 0)
                            {
                                errorBuffer.AddRange(readBuffer);
                                readBuffer.Clear();

                                responseWaitHandle.Response = new ModbusCommErrorResponse(ModbusCommErrorCode.ModbusTcpSymbolError, errorBuffer, responseWaitHandle.Request);
                                continue;
                            }

                            var result = base.DeserializeResponse(readBuffer, responseWaitHandle.Request, responseWaitHandle.Timeout);

                            if (result is ModbusCommErrorResponse responseCommErrorMessage)
                            {
                                errorBuffer.AddRange(readBuffer.Take(4));
                                readBuffer.RemoveRange(0, 4);

                                responseWaitHandle.Response = result;
                                continue;
                            }

                            if (readBuffer.Count - 6 != (ushort)((readBuffer[4] << 8) | readBuffer[5]))
                            {
                                errorBuffer.AddRange(readBuffer.Take(4));
                                readBuffer.RemoveRange(0, 4);

                                responseWaitHandle.Response = new ModbusCommErrorResponse(ModbusCommErrorCode.ResponseTcpLengthDoNotMatch, readBuffer, responseWaitHandle.Request);
                                continue;
                            }


                            if (errorBuffer.Count > 0)
                            {
                                RaiseUnrecognized(channel, errorBuffer.ToArray());
                                errorBuffer.Clear();
                            }

                            responseWaitHandle.ResponseBuffer.AddRange(readBuffer);

                            readBuffer.Clear();
                            responseWaitHandle.Response = result;
                            responseWaitHandle.Set();
                            this.responseWaitHandles.Remove(transactionID);
                        }
                    }
                    catch
                    {
                    }
                    isReceiving = false;
                }
            }
        }