Exemple #1
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);
        }
Exemple #2
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);
        }