示例#1
0
        private T Write <T>(ModbusDevice device, ModbusFunctionCode functionCode, int zeroBasedOffset, Action <IMessageBufferWriter> writeAction, Func <IMessageBufferReader, T> readValueFunc)
        {
            var requestContext = new ModbusTransportContext()
            {
                TransactionIdentifier = GetTransactionIdentifier()
            };

            ModbusTransport.SendMessage(requestContext,
                                        (writer) =>
            {
                writer.Push(device.Address);
                writer.Push((byte)functionCode);
                writer.Push((byte)((zeroBasedOffset >> 8) & 0xFF));
                writer.Push((byte)((zeroBasedOffset >> 0) & 0xFF));
                writeAction(writer);
            });

            T returnedValue = default;

            var responseContext = ModbusTransport.ReceiveMessage(
                (reader) =>
            {
                if (reader.PushByteFromStream() != device.Address)
                {
                    throw new InvalidOperationException();
                }

                byte receivedFunctionCode = reader.PushByteFromStream();

                if (receivedFunctionCode == ((byte)functionCode | 0x80))
                {
                    var exceptionCode = (ModbusExceptionCode)reader.PushByteFromStream();
                    throw new ModbusException(exceptionCode);
                }

                if (receivedFunctionCode != (byte)functionCode)
                {
                    throw new InvalidOperationException();
                }

                if ((ushort)((reader.PushByteFromStream() << 8) + (reader.PushByteFromStream() << 0)) != zeroBasedOffset)
                {
                    throw new InvalidOperationException();
                }

                returnedValue = readValueFunc(reader);
            });

            if (requestContext.TransactionIdentifier != responseContext.TransactionIdentifier)
            {
                throw new InvalidOperationException();
            }

            return(returnedValue !);
        }
示例#2
0
        private void Read(ModbusDevice device, ModbusFunctionCode functionCode, int zeroBasedOffset, int count, Action <MessageBufferSpan> actionWithReturnedBuffer)
        {
            var requestContext = new ModbusTransportContext()
            {
                TransactionIdentifier = GetTransactionIdentifier()
            };

            ModbusTransport.SendMessage(requestContext,
                                        (writer) =>
            {
                writer.Push(device.Address);
                writer.Push((byte)functionCode);
                writer.Push((byte)((zeroBasedOffset >> 8) & 0xFF));
                writer.Push((byte)((zeroBasedOffset >> 0) & 0xFF));
                writer.Push((byte)((count >> 8) & 0xFF));
                writer.Push((byte)((count >> 0) & 0xFF));
            });

            MessageBufferSpan?receivedBuffer = null;

            var responseContext = ModbusTransport.ReceiveMessage(
                (reader) =>
            {
                if (reader.PushByteFromStream() != device.Address)
                {
                    throw new InvalidOperationException();
                }

                byte receivedFunctionCode = reader.PushByteFromStream();

                if (receivedFunctionCode == ((byte)functionCode | 0x80))
                {
                    var exceptionCode = (ModbusExceptionCode)reader.PushByteFromStream();
                    throw new ModbusException(exceptionCode);
                }

                if (receivedFunctionCode != (byte)functionCode)
                {
                    throw new InvalidOperationException();
                }

                var byteCount = reader.PushByteFromStream();

                reader.PushFromStream(byteCount);

                receivedBuffer = new MessageBufferSpan(reader.Buffer, (ushort)(reader.Buffer.Length - byteCount), byteCount);
            });

            if (responseContext.TransactionIdentifier != requestContext.TransactionIdentifier)
            {
                throw new InvalidOperationException();
            }

            actionWithReturnedBuffer(receivedBuffer !);
        }
示例#3
0
        public void HandleRequest(params ModbusDevice[] devices)
        {
            if (devices is null)
            {
                throw new ArgumentNullException(nameof(devices));
            }

            if (devices.Length == 0)
            {
                throw new ArgumentException();
            }

            MessageHandler?messageHandler = null;
            ModbusDevice?  device         = null;

            var requestContext = ModbusTransport.ReceiveMessage(reader =>
            {
                var deviceAddress = reader.PushByteFromStream();

                device = devices.FirstOrDefault(_ => _.Address == deviceAddress);

                if (device == null)
                {
                    throw new InvalidOperationException($"Received request for device with unknown address {deviceAddress}");
                }

                var functionCode = (ModbusFunctionCode)reader.PushByteFromStream();
                messageHandler   = functionCode switch
                {
                    ModbusFunctionCode.ReadDiscreteInputs => ReadDiscreteInputsHandler.Create(reader),
                    ModbusFunctionCode.ReadCoils => ReadCoilsHandler.Create(reader),
                    ModbusFunctionCode.ReadInputRegisters => ReadInputRegistersHandler.Create(reader),
                    ModbusFunctionCode.ReadHoldingRegisters => ReadHoldingRegistersHandler.Create(reader),

                    ModbusFunctionCode.WriteSingleCoil => WriteSingleCoilHandler.Create(reader),
                    ModbusFunctionCode.WriteSingleRegister => WriteSingleRegisterHandler.Create(reader),
                    ModbusFunctionCode.WriteMultipleCoils => WriteMultipleCoilsHandler.Create(reader),
                    ModbusFunctionCode.WriteMultipleRegisters => WriteMultipleRegistersHandler.Create(reader),

                    ModbusFunctionCode.ReadWriteMultipleRegisters => ReadWriteMultipleRegistersHandler.Create(reader),
                    _ => throw new NotSupportedException($"Function {functionCode} not supported"),
                };
            });

            if (messageHandler is WriteHandler writeHandler)
            {
                writeHandler.UpdateMemory(device !);
            }

            ModbusTransport.SendMessage(requestContext, writer =>
            {
                messageHandler !.WriteResponse(device !, writer);
            });