Ejemplo n.º 1
0
        private bool IsException(ResponseBuffer buffer, ModbusRequest request, int timeout, out ModbusResponse responseMessage)
        {
            if ((Read(buffer, 1, timeout) & 0x80) == 0x80)
            {
                var codeValue = Read(buffer, 2, timeout);

                if (IsErrorCRC(buffer, 3, request, timeout))
                {
                    throw new ModbusCommException(ModbusCommErrorCode.ErrorCRC, buffer, request);
                }

                ModbusExceptionCode exceptionCode = ModbusExceptionCode.NotDefined;
                if (Enum.IsDefined(typeof(ModbusExceptionCode), codeValue))
                {
                    exceptionCode = (ModbusExceptionCode)codeValue;
                }

                responseMessage = new ModbusExceptionResponse(exceptionCode, request);
                return(true);
            }
            else
            {
                responseMessage = null;
                return(false);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Read Discrete Inputs from Server device (FC2).
        /// </summary>
        /// <param name="startingAddress">First discrete input to read</param>
        /// <param name="quantity">Number of discrete Inputs to read</param>
        /// <returns>Boolean Array which contains the discrete Inputs</returns>
        public Modbus.DiscreteInputs ReadDiscreteInputs(int startingAddress, int quantity)
        {
            Logger.Info($"FC2 (Read Discrete Inputs from StartingAddress: { startingAddress }, Quantity: { quantity }");

            if (this.modbusChannel == null)
            {
                Logger.Error("ConnectionException Throwed");
                throw new InvalidOperationException("No ModbusChannel initialized.");
            }

            if (startingAddress > 65535 || quantity > 2000)
            {
                Logger.Error("ArgumentException Throwed");
                throw new ArgumentException("Starting address must be 0 - 65535; quantity must be 0 - 2000");
            }

            var request = ModbusRequest.DiscriteInputRequest(startingAddress, quantity);

            var error = modbusChannel.SendReadCommand <DiscreteInputs>(request, out DiscreteInputs inputs);

            if (error != null)
            {
                throw ModbusException.FromProtocolException(error.ProtocolException);
            }

            return(inputs);
        }
Ejemplo n.º 3
0
        internal ModbusResponse Deserialize(ResponseBuffer buffer, ModbusRequest request, int timeout)
        {
            ModbusResponse result;

            try
            {
                result = DeserializeResponse(buffer, request, timeout);
            }
            catch (TimeoutException ex)
            {
                throw new ModbusCommException(ModbusCommErrorCode.ResponseTimeout, buffer, ex, request);
            }
            catch (ModbusCommException ex)
            {
                throw new ModbusCommException(ex.Code, buffer, ex.InnerException, request);
            }
            catch (Exception ex)
            {
                throw new ModbusCommException(buffer, ex, request);
            }

            if (result is ModbusCommErrorResponse commErrorResponse)
            {
                throw new ModbusCommException(commErrorResponse.ErrorCode, commErrorResponse.ReceivedBytes, commErrorResponse.Request);
            }

            return(result);
        }
Ejemplo n.º 4
0
        internal virtual ModbusResponse DeserializeResponse(ResponseBuffer buffer, ModbusRequest request, int timeout)
        {
            if (request is ModbusReadRequest readMessage)
            {
                switch (readMessage.ObjectType)
                {
                case ModbusObjectType.DiscreteInput:
                case ModbusObjectType.Coil:
                    return(DeserializeReadBooleanResponse(buffer, readMessage, timeout));

                case ModbusObjectType.InputRegister:
                case ModbusObjectType.HoldingRegister:
                    return(DeserializeReadRegisterResponse(buffer, readMessage, timeout));
                }
            }
            else if (request is ModbusWriteCoilRequest writeCoilMessage)
            {
                return(DeserializeWriteResponse(buffer, writeCoilMessage, timeout));
            }
            else if (request is ModbusWriteHoldingRegisterRequest writeHoldingRegisterMessage)
            {
                return(DeserializeWriteResponse(buffer, writeHoldingRegisterMessage, timeout));
            }

            throw new ArgumentOutOfRangeException(nameof(request));
        }
Ejemplo n.º 5
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);
        }
Ejemplo n.º 6
0
        static void Main(string[] args)
        {
            RawTcp(); return;//

            byte[]        buffer = new byte[] { 0x01, 0x00, 0x13, 0x00, 0x13 };
            ModbusMessage mm     = ModbusRequest.ParseBuffer(buffer);

            return;

            //ReflectMyClasses();return;
            //TestMessage();return;
            ModbusTcpClient client = new ModbusTcpClient();

            Console.WriteLine($"Keep Alive          : {client.KeepAlive}");
            Console.WriteLine($"Receive Buffer Size : {client.ReceiveBufferSize = 1024}");
            Console.WriteLine($"Send Buffer Size    : {client.SendBufferSize = 1024}");
            Console.WriteLine($"Receive Timeout     : {client.ReceiveTimeout = 500}");
            Console.WriteLine($"Send Timeout        : {client.SendTimeout = 500}");
            Console.WriteLine($"No Delay            : {client.NoDelay}");
            Console.WriteLine($"Reuse Address       : {client.ReuseAddress = true}");
            client.Connect("localhost");
            bool running = true;

            Task.Run(() =>
            {
                try
                {
                    while (running && client.Connected)
                    {
                        int length = client.SendMessage(new WriteSingleRegisterRequest(9999, 1000));

                        Console.WriteLine($"{length} bytes sent");
                        Thread.Sleep(200);
                    }
                    if (client.Connected)
                    {
                        Console.WriteLine("Stopped");
                    }
                    else
                    {
                        Console.WriteLine("Disconnected");
                    }
                }
                catch (Exception x)
                {
                    Console.WriteLine($"Error: {x.Message}");
                    client = new ModbusTcpClient("localhost");
                }
            });

            Console.ReadLine();
            running = false;
            //new ArraySegment<byte>()
        }
Ejemplo n.º 7
0
        private ModbusRequest Get(ModbusResponse response)
        {
            ModbusRequest result = null;

            if (response != null)
            {
                lock (lockerRequestes)
                {
                    result = requestes.Find(x => x.MBAPHeader.TransactionId == response.MBAPHeader.TransactionId);
                    requestes.Remove(result);
                }
            }
            return(result);
        }
Ejemplo n.º 8
0
        internal ModbusError SendReadCommand <T>(ModbusRequest request, out T responseType) where T : class, IModbusResponse
        {
            byte[] data         = request.GetPDU();
            var    responseData = SendReadCommand(data);
            var    response     = new ModbusResponse(responseData);

            if (response.ExceptionCode > 0)
            {
                var err = new ModbusError(response.ExceptionCode);
                responseType = null;
                return(err);
            }
            else
            {
                responseType = (T)Activator.CreateInstance(typeof(T), response);
                return(null);
            }
        }
Ejemplo n.º 9
0
        internal override ModbusResponse DeserializeResponse(ResponseBuffer buffer, ModbusRequest request, int timeout)
        {
            var responseWaitHandle = this.responseWaitHandles[request.TransactionID] = new ResponseWaitHandle(buffer, request, timeout);

            Task.Run(() => RunReceive(buffer.Channel));

            responseWaitHandle.WaitOne(timeout);

            var result = responseWaitHandle.Response;

            if (result == null)
            {
                this.responseWaitHandles.Remove(request.TransactionID);
                return(new ModbusCommErrorResponse(ModbusCommErrorCode.ResponseTimeout, new byte[0], request));
            }

            return(result);
        }
Ejemplo n.º 10
0
        private bool Add(ModbusRequest request)
        {
            bool result = false;

            if (request != null)
            {
                lock (lockerRequestes)
                {
                    if (requestes.Find(x => x.MBAPHeader.TransactionId == request.MBAPHeader.TransactionId) == null)
                    {
                        requestes.Add(request);
                        result = true;
                    }
                    else
                    {
                        throw new ArgumentException("Запрос с таким Id транзакции уже есть в списке запросов!");
                    }
                }
            }
            return(result);
        }
Ejemplo n.º 11
0
        private bool IsErrorLRC(ResponseBuffer buffer, int messageLength, ModbusRequest request, int timeout, out ModbusResponse responseMessage)
        {
            byte lrc = 0;

            foreach (var b in Read(buffer, 0, messageLength, timeout))
            {
                lrc += b;
            }

            lrc = (byte)(-lrc & 0xff);

            if (lrc != Read(buffer, messageLength, timeout))
            {
                responseMessage = new ModbusCommErrorResponse(ModbusCommErrorCode.ErrorLRC, buffer, request);
                return(true);
            }
            else
            {
                responseMessage = null;
                return(false);
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Read Coils from Server device (FC1).
        /// </summary>
        /// <param name="startingAddress">First coil to read</param>
        /// <param name="quantity">Numer of coils to read</param>
        /// <returns>Boolean Array which contains the coils</returns>
        public Coils ReadCoils(int startingAddress, int quantity)
        {
            Logger.Info("FC1 (Read Coils from Master device), StartingAddress: " + startingAddress + ", Quantity: " + quantity);

            if (modbusChannel == null)
            {
                throw new  InvalidOperationException("No ModbusChannel initialized.");
            }
            if (startingAddress > 65535 || quantity > 2000)
            {
                throw new ArgumentException("Starting address must be 0 - 65535; quantity must be 0 - 2000");
            }

            var request = new ModbusRequest(ModbusFunctions.ReadCoils, startingAddress, quantity);
            var error   = modbusChannel.SendReadCommand(request, out Coils coils);

            if (error != null)
            {
                throw ModbusException.FromProtocolException(error.ProtocolException);
            }

            return(coils);
        }
Ejemplo n.º 13
0
        internal override ModbusResponse DeserializeResponse(ResponseBuffer buffer, ModbusRequest request, int timeout)
        {
            ModbusResponse result = base.DeserializeResponse(buffer, request, timeout);

            while (result is ModbusCommErrorResponse responseCommErrorMessage &&
                   responseCommErrorMessage.ErrorCode != ModbusCommErrorCode.ResponseTimeout)
            {
                errorBuffer.Add(buffer[0]);
                buffer.RemoveAt(0);
                result = base.DeserializeResponse(buffer, request, timeout);
            }

            if (result is ModbusCommErrorResponse responseCommError)
            {
                result = new ModbusCommErrorResponse(responseCommError.ErrorCode, errorBuffer.Concat(responseCommError.ReceivedBytes), request);
            }
            else if (errorBuffer.Count > 0)
            {
                RaiseUnrecognized(buffer.Channel, errorBuffer.ToArray());
                errorBuffer.Clear();
            }

            return(result);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Read Holding Registers from Master device (FC3).
        /// </summary>
        /// <param name="startingAddress">First holding register to be read. Integer between 0 and 65535</param>
        /// <param name="quantity">Number of holding registers to be read. Integer between 0 and 125.</param>
        /// <returns>Int Array which contains the holding registers</returns>
        public HoldingRegisters ReadHoldingRegisters(int startingAddress, int quantity)
        {
            Logger.Info("FC3 Read Holding Registers from Master device), StartingAddress: " + startingAddress + ", Quantity: " + quantity);
            if (modbusChannel == null)
            {
                Logger.Error("ConnectionException Throwed");
                throw new InvalidOperationException("No ModbusChannel initialized.");
            }
            if (startingAddress > 65535 || quantity > 125)
            {
                Logger.Error("ArgumentException Throwed");
                throw new ArgumentException("Starting address must be 0 - 65535; quantity must be 0 - 125");
            }

            var request = new ModbusRequest(ModbusFunctions.ReadHoldingRegisters, startingAddress, quantity);
            var error   = modbusChannel.SendReadCommand(request, out HoldingRegisters holdingReg);

            if (error != null)
            {
                throw ModbusException.FromProtocolException(error.ProtocolException);
            }

            return(holdingReg);
        }
Ejemplo n.º 15
0
        private bool IsErrorCRC(ResponseBuffer buffer, int messageLength, ModbusRequest request, int timeout)
        {
            var crc = Read(buffer, messageLength, 2, timeout).ToArray();

            return(!CalculateCrc(buffer.Take(messageLength)).SequenceEqual(crc));
        }
Ejemplo n.º 16
0
        internal override ModbusRequest DeserializeRequest(RequestBuffer rawBuffer)
        {
            ModbusRequest result = null;

            while (!rawBuffer.Channel.IsDisposed)
            {
                if (errorBuffer.Count >= 256)
                {
                    RaiseUnrecognized(rawBuffer.Channel, errorBuffer.ToArray());
                    errorBuffer.Clear();
                }

                while (rawBuffer.Count < 17 && !rawBuffer.Channel.IsDisposed)
                {
                    rawBuffer.Read();
                }

                if (rawBuffer.Channel.IsDisposed)
                {
                    break;
                }

                int messageLength = 0;

                if (rawBuffer[0] == 0x3a)
                {
                    List <byte> buffer = new List <byte>();

                    for (int i = 0; i < 7; i++)
                    {
                        if (TryParseFromHex(rawBuffer, i * 2 + 1, out var byteValue))
                        {
                            buffer.Add(byteValue);
                        }
                        else
                        {
                            break;
                        }
                    }

                    if (buffer.Count < 7)
                    {
                        errorBuffer.AddRange(rawBuffer.Take((buffer.Count + 1) * 2 + 1));
                        rawBuffer.RemoveRange(0, (buffer.Count + 1) * 2 + 1);
                        continue;
                    }

                    var slaveAddress = buffer[0];

                    if (rawBuffer.ModbusSlave.IsValidSlaveAddress(slaveAddress, rawBuffer.Channel) &&
                        Enum.IsDefined(typeof(ModbusFunction), buffer[1]))
                    {
                        ModbusFunction function      = (ModbusFunction)buffer[1];
                        var            address       = ToUInt16(buffer, 2);
                        var            valueOrLength = ToUInt16(buffer, 4);

                        switch (function)
                        {
                        case ModbusFunction.ReadCoils:
                        case ModbusFunction.ReadDiscreteInputs:
                        case ModbusFunction.ReadHoldingRegisters:
                        case ModbusFunction.ReadInputRegisters:
                        case ModbusFunction.WriteSingleCoil:
                        case ModbusFunction.WriteSingleHoldingRegister:
                            if ((-buffer.Take(6).Sum(b => b) & 0xff) == buffer[6] &&
                                rawBuffer[15] == '\r' && rawBuffer[16] == '\n')
                            {
                                messageLength = 17;
                                switch (function)
                                {
                                case ModbusFunction.ReadCoils:
                                case ModbusFunction.ReadDiscreteInputs:
                                case ModbusFunction.ReadHoldingRegisters:
                                case ModbusFunction.ReadInputRegisters:
                                    result = new ModbusReadRequest(slaveAddress, (ModbusObjectType)(byte)function, address, valueOrLength);
                                    break;

                                case ModbusFunction.WriteSingleCoil:
                                    if (valueOrLength != 0xff00 && valueOrLength != 0)
                                    {
                                        result = new ModbusWriteCoilRequest(slaveAddress, address);
                                    }
                                    else
                                    {
                                        result = new ModbusWriteCoilRequest(slaveAddress, address, valueOrLength == 0xff00);
                                    }
                                    break;

                                case ModbusFunction.WriteSingleHoldingRegister:
                                    result = new ModbusWriteHoldingRegisterRequest(slaveAddress, address, valueOrLength);
                                    break;
                                }
                            }
                            break;

                        case ModbusFunction.WriteMultipleCoils:
                        case ModbusFunction.WriteMultipleHoldingRegisters:
                            var byteLength = buffer[6];
                            messageLength = byteLength * 2 + 19;

                            if (function == ModbusFunction.WriteMultipleCoils && byteLength == Math.Ceiling(valueOrLength / 8d) ||
                                function == ModbusFunction.WriteMultipleHoldingRegisters && byteLength == valueOrLength * 2)
                            {
                                while (rawBuffer.Count < messageLength && !rawBuffer.Channel.IsDisposed)
                                {
                                    rawBuffer.Read();
                                }

                                if (rawBuffer.Channel.IsDisposed)
                                {
                                    break;
                                }

                                for (int i = 0; i < byteLength + 1; i++)
                                {
                                    if (TryParseFromHex(rawBuffer, i * 2 + 15, out var byteValue))
                                    {
                                        buffer.Add(byteValue);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }

                                if (buffer.Count < 8 + byteLength)
                                {
                                    errorBuffer.AddRange(rawBuffer.Take((buffer.Count + 1) * 2 + 1));
                                    rawBuffer.RemoveRange(0, (buffer.Count + 1) * 2 + 1);
                                    continue;
                                }


                                if ((-buffer.Take(7 + byteLength).Sum(b => b) & 0xff) == buffer[6] &&
                                    rawBuffer[15] == '\r' && rawBuffer[16] == '\n')
                                {
                                    switch (function)
                                    {
                                    case ModbusFunction.WriteMultipleCoils:
                                        result = new ModbusWriteCoilRequest(slaveAddress, address, buffer.Skip(7).Take(byteLength).SelectMany(b => ByteToBooleanArray(b)).Take(valueOrLength).ToArray());
                                        break;

                                    case ModbusFunction.WriteMultipleHoldingRegisters:
                                        result = new ModbusWriteHoldingRegisterRequest(slaveAddress, address, buffer.Skip(7).Take(byteLength).ToArray());
                                        break;
                                    }
                                }
                            }
                            break;
                        }
                    }
                }

                if (result != null)
                {
                    if (errorBuffer.Count > 0)
                    {
                        RaiseUnrecognized(rawBuffer.Channel, errorBuffer.ToArray());
                        errorBuffer.Clear();
                    }
                    return(result);
                }
                else
                {
                    errorBuffer.Add(rawBuffer[0]);
                    rawBuffer.RemoveAt(0);
                    continue;
                }
            }
            return(null);
        }
Ejemplo n.º 17
0
        internal override ModbusRequest DeserializeRequest(RequestBuffer buffer)
        {
            ModbusRequest result = null;

            while (!buffer.Channel.IsDisposed)
            {
                if (errorBuffer.Count >= 256)
                {
                    RaiseUnrecognized(buffer.Channel, errorBuffer.ToArray());
                    errorBuffer.Clear();
                }

                while (buffer.Count < 8 && !buffer.Channel.IsDisposed)
                {
                    buffer.Read();
                }

                if (buffer.Channel.IsDisposed)
                {
                    break;
                }

                var slaveAddress  = buffer[0];
                int messageLength = 0;

                if (buffer.ModbusSlave.IsValidSlaveAddress(slaveAddress, buffer.Channel) &&
                    Enum.IsDefined(typeof(ModbusFunction), buffer[1]))
                {
                    ModbusFunction function      = (ModbusFunction)buffer[1];
                    var            address       = ToUInt16(buffer, 2);
                    var            valueOrLength = ToUInt16(buffer, 4);

                    switch (function)
                    {
                    case ModbusFunction.ReadCoils:
                    case ModbusFunction.ReadDiscreteInputs:
                    case ModbusFunction.ReadHoldingRegisters:
                    case ModbusFunction.ReadInputRegisters:
                    case ModbusFunction.WriteSingleCoil:
                    case ModbusFunction.WriteSingleHoldingRegister:
                        if (CalculateCrc(buffer.Take(6)).SequenceEqual(buffer.Skip(6).Take(2)))
                        {
                            messageLength = 8;
                            switch (function)
                            {
                            case ModbusFunction.ReadCoils:
                            case ModbusFunction.ReadDiscreteInputs:
                            case ModbusFunction.ReadHoldingRegisters:
                            case ModbusFunction.ReadInputRegisters:
                                result = new ModbusReadRequest(slaveAddress, (ModbusObjectType)(byte)function, address, valueOrLength);
                                break;

                            case ModbusFunction.WriteSingleCoil:
                                if (valueOrLength != 0xff00 && valueOrLength != 0)
                                {
                                    result = new ModbusWriteCoilRequest(slaveAddress, address);
                                }
                                else
                                {
                                    result = new ModbusWriteCoilRequest(slaveAddress, address, valueOrLength == 0xff00);
                                }
                                break;

                            case ModbusFunction.WriteSingleHoldingRegister:
                                result = new ModbusWriteHoldingRegisterRequest(slaveAddress, address, valueOrLength);
                                break;
                            }
                        }
                        break;

                    case ModbusFunction.WriteMultipleCoils:
                    case ModbusFunction.WriteMultipleHoldingRegisters:
                        if (buffer.Count < 7 && !buffer.Channel.IsDisposed)
                        {
                            buffer.Read();
                        }

                        if (buffer.Channel.IsDisposed)
                        {
                            break;
                        }

                        var byteLength = buffer[6];
                        messageLength = byteLength + 9;

                        if (function == ModbusFunction.WriteMultipleCoils && byteLength == Math.Ceiling(valueOrLength / 8d) ||
                            function == ModbusFunction.WriteMultipleHoldingRegisters && byteLength == valueOrLength * 2)
                        {
                            while (buffer.Count < messageLength && !buffer.Channel.IsDisposed)
                            {
                                buffer.Read();
                            }

                            if (buffer.Channel.IsDisposed)
                            {
                                break;
                            }

                            if (CalculateCrc(buffer.Take(byteLength + 7)).SequenceEqual(buffer.Skip(byteLength + 7).Take(2)))
                            {
                                switch (function)
                                {
                                case ModbusFunction.WriteMultipleCoils:
                                    result = new ModbusWriteCoilRequest(slaveAddress, address, buffer.Skip(7).Take(byteLength).SelectMany(b => ByteToBooleanArray(b)).Take(valueOrLength).ToArray());
                                    break;

                                case ModbusFunction.WriteMultipleHoldingRegisters:
                                    result = new ModbusWriteHoldingRegisterRequest(slaveAddress, address, buffer.Skip(7).Take(byteLength).ToArray());
                                    break;
                                }
                            }
                        }
                        break;
                    }
                }

                if (result != null)
                {
                    if (errorBuffer.Count > 0)
                    {
                        RaiseUnrecognized(buffer.Channel, errorBuffer.ToArray());
                        errorBuffer.Clear();
                    }
                    return(result);
                }
                else
                {
                    errorBuffer.Add(buffer[0]);
                    buffer.RemoveAt(0);
                    continue;
                }
            }
            return(null);
        }
Ejemplo n.º 18
0
 public ModbusCommErrorResponse(ModbusCommErrorCode errorCode, IEnumerable <byte> receivedMessage, ModbusRequest request) : base(request)
 {
     ErrorCode     = errorCode;
     ReceivedBytes = receivedMessage?.ToArray() ?? new byte[0];
 }
Ejemplo n.º 19
0
 public ResponseWaitHandle(ResponseBuffer buffer, ModbusRequest request, int timeout) : base(false, EventResetMode.ManualReset)
 {
     ResponseBuffer = buffer;
     Request        = request;
     Timeout        = timeout;
 }