예제 #1
0
        /// <summary>
        /// Method to send a Modbus read request to a Modbus slave and returns the requested value(s)
        /// providing common communication setup and associated exception handling (logging).
        /// A TCP client is created and used to send the request to the Modbus TCP client.
        /// The following requests are supported:
        ///
        ///     Single Coil
        ///     Single Discrete Input
        ///     Single Holding Register
        ///     Single Input Register
        ///
        ///     Multiple Coils
        ///     Multiple Discrete Inputs
        ///     Multiple Holding Registers
        ///     Multiple Input Registers
        ///
        /// Additional datatypes (single values, value arrays and strings) with read
        /// only access (discrete inputs and input registers) and read / write access
        /// (coils and holding registers) are supported:
        ///
        ///     ASCII String    (multiple registers)
        ///     Hex String      (multiple registers)
        ///     Bool            (single coil)
        ///     Bits            (single register)
        ///     Short           (single register)
        ///     UShort          (single register)
        ///     Int32           (two registers)
        ///     UInt32          (two registers)
        ///     Float           (two registers)
        ///     Double          (four registers)
        ///     Long            (four registers)
        ///     ULong           (four registers)
        ///
        /// </summary>
        /// <param name="request">The <see cref="ModbusRequestData"/> data.</param>
        /// <param name="function">The function name.</param>
        /// <returns>A task returning an action method result.</returns>
        protected async Task <IActionResult> ModbusReadRequest(ModbusRequestData request, string function)
        {
            try
            {
                request.Master = _client.RtuMaster;

                if (_client.Connect())
                {
                    switch (function)
                    {
                    case "ReadCoilAsync":
                    {
                        bool[] values = await _client.ReadCoilsAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseData <bool>(request, values[0])));
                    }

                    case "ReadCoilsAsync":
                    {
                        bool[] values = await _client.ReadCoilsAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <bool>(request, values)));
                    }

                    case "ReadInputAsync":
                    {
                        bool[] values = await _client.ReadInputsAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseData <bool>(request, values[0])));
                    }

                    case "ReadInputsAsync":
                    {
                        bool[] values = await _client.ReadInputsAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <bool>(request, values)));
                    }

                    case "ReadHoldingRegisterAsync":
                    {
                        ushort[] values = await _client.ReadHoldingRegistersAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseData <ushort>(request, values[0])));
                    }

                    case "ReadHoldingRegistersAsync":
                    {
                        ushort[] values = await _client.ReadHoldingRegistersAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <ushort>(request, values)));
                    }

                    case "ReadInputRegisterAsync":
                    {
                        ushort[] values = await _client.ReadInputRegistersAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseData <ushort>(request, values[0])));
                    }

                    case "ReadInputRegistersAsync":
                    {
                        ushort[] values = await _client.ReadInputRegistersAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <ushort>(request, values)));
                    }

                    case "ReadOnlyStringAsync":
                    {
                        string value = await _client.ReadOnlyStringAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseStringData(request, value)));
                    }

                    case "ReadOnlyHexStringAsync":
                    {
                        string value = await _client.ReadOnlyHexStringAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseStringData(request, value)));
                    }

                    case "ReadOnlyBoolAsync":
                    {
                        bool value = await _client.ReadOnlyBoolAsync(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <bool>(request, value)));
                    }

                    case "ReadOnlyBitsAsync":
                    {
                        BitArray value = await _client.ReadOnlyBitsAsync(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseStringData(request, value.ToDigitString())));
                    }

                    case "ReadOnlyShortAsync":
                    {
                        short value = await _client.ReadOnlyShortAsync(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <short>(request, value)));
                    }

                    case "ReadOnlyUShortAsync":
                    {
                        ushort value = await _client.ReadOnlyUShortAsync(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <ushort>(request, value)));
                    }

                    case "ReadOnlyInt32Async":
                    {
                        int value = await _client.ReadOnlyInt32Async(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <int>(request, value)));
                    }

                    case "ReadOnlyUInt32Async":
                    {
                        uint value = await _client.ReadOnlyUInt32Async(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <uint>(request, value)));
                    }

                    case "ReadOnlyFloatAsync":
                    {
                        float value = await _client.ReadOnlyFloatAsync(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <float>(request, value)));
                    }

                    case "ReadOnlyDoubleAsync":
                    {
                        double value = await _client.ReadOnlyDoubleAsync(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <double>(request, value)));
                    }

                    case "ReadOnlyLongAsync":
                    {
                        long value = await _client.ReadOnlyLongAsync(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <long>(request, value)));
                    }

                    case "ReadOnlyULongAsync":
                    {
                        ulong value = await _client.ReadOnlyULongAsync(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <ulong>(request, value)));
                    }

                    case "ReadOnlyBoolArrayAsync":
                    {
                        bool[] values = await _client.ReadOnlyBoolArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <bool>(request, values)));
                    }

                    case "ReadOnlyBytesAsync":
                    {
                        byte[] values = await _client.ReadOnlyBytesAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <byte>(request, values)));
                    }

                    case "ReadOnlyShortArrayAsync":
                    {
                        short[] values = await _client.ReadOnlyShortArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <short>(request, values)));
                    }

                    case "ReadOnlyUShortArrayAsync":
                    {
                        ushort[] values = await _client.ReadOnlyUShortArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <ushort>(request, values)));
                    }

                    case "ReadOnlyInt32ArrayAsync":
                    {
                        int[] values = await _client.ReadOnlyInt32ArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <int>(request, values)));
                    }

                    case "ReadOnlyUInt32ArrayAsync":
                    {
                        uint[] values = await _client.ReadOnlyUInt32ArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <uint>(request, values)));
                    }

                    case "ReadOnlyFloatArrayAsync":
                    {
                        float[] values = await _client.ReadOnlyFloatArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <float>(request, values)));
                    }

                    case "ReadOnlyDoubleArrayAsync":
                    {
                        double[] values = await _client.ReadOnlyDoubleArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <double>(request, values)));
                    }

                    case "ReadOnlyLongArrayAsync":
                    {
                        long[] values = await _client.ReadOnlyLongArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <long>(request, values)));
                    }

                    case "ReadOnlyULongArrayAsync":
                    {
                        ulong[] values = await _client.ReadOnlyULongArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <ulong>(request, values)));
                    }

                    case "ReadStringAsync":
                    {
                        string value = await _client.ReadStringAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseStringData(request, value)));
                    }

                    case "ReadHexStringAsync":
                    {
                        string value = await _client.ReadHexStringAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseStringData(request, value)));
                    }

                    case "ReadBoolAsync":
                    {
                        bool value = await _client.ReadBoolAsync(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <bool>(request, value)));
                    }

                    case "ReadBitsAsync":
                    {
                        BitArray value = await _client.ReadBitsAsync(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseStringData(request, value.ToDigitString())));
                    }

                    case "ReadShortAsync":
                    {
                        short value = await _client.ReadShortAsync(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <short>(request, value)));
                    }

                    case "ReadUShortAsync":
                    {
                        ushort value = await _client.ReadUShortAsync(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <ushort>(request, value)));
                    }

                    case "ReadInt32Async":
                    {
                        int value = await _client.ReadInt32Async(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <int>(request, value)));
                    }

                    case "ReadUInt32Async":
                    {
                        uint value = await _client.ReadUInt32Async(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <uint>(request, value)));
                    }

                    case "ReadFloatAsync":
                    {
                        float value = await _client.ReadFloatAsync(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <float>(request, value)));
                    }

                    case "ReadDoubleAsync":
                    {
                        double value = await _client.ReadDoubleAsync(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <double>(request, value)));
                    }

                    case "ReadLongAsync":
                    {
                        long value = await _client.ReadLongAsync(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <long>(request, value)));
                    }

                    case "ReadULongAsync":
                    {
                        ulong value = await _client.ReadULongAsync(request.Slave.ID, request.Offset);

                        _logger.LogTrace($"{function}(): {value}");
                        return(Ok(new ModbusResponseData <ulong>(request, value)));
                    }

                    case "ReadBoolArrayAsync":
                    {
                        bool[] values = await _client.ReadBoolArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <bool>(request, values)));
                    }

                    case "ReadBytesAsync":
                    {
                        byte[] values = await _client.ReadBytesAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <byte>(request, values)));
                    }

                    case "ReadShortArrayAsync":
                    {
                        short[] values = await _client.ReadShortArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <short>(request, values)));
                    }

                    case "ReadUShortArrayAsync":
                    {
                        ushort[] values = await _client.ReadUShortArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <ushort>(request, values)));
                    }

                    case "ReadInt32ArrayAsync":
                    {
                        int[] values = await _client.ReadInt32ArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <int>(request, values)));
                    }

                    case "ReadUInt32ArrayAsync":
                    {
                        uint[] values = await _client.ReadUInt32ArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <uint>(request, values)));
                    }

                    case "ReadFloatArrayAsync":
                    {
                        float[] values = await _client.ReadFloatArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <float>(request, values)));
                    }

                    case "ReadDoubleArrayAsync":
                    {
                        double[] values = await _client.ReadDoubleArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <double>(request, values)));
                    }

                    case "ReadLongArrayAsync":
                    {
                        long[] values = await _client.ReadLongArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <long>(request, values)));
                    }

                    case "ReadULongArrayAsync":
                    {
                        ulong[] values = await _client.ReadULongArrayAsync(request.Slave.ID, request.Offset, request.Number);

                        _logger.LogTrace($"{function}(): {values}");
                        return(Ok(new ModbusResponseArrayData <ulong>(request, values)));
                    }

                    default:
                        _client.Disconnect();
                        _logger.LogError($"RTU master read request {function}() not supported.");
                        return(NotFound($"RTU master read request {function}() not supported."));
                    }
                }
                else
                {
                    _logger.LogError($"RTU master ({request.Master.SerialPort}) not open.");
                    return(NotFound("RTU master COM port not open."));
                }
            }
            catch (UnauthorizedAccessException uae)
            {
                _logger.LogError(uae, $"{function}() Unauthorized Access Exception.");
                return(NotFound($"Unauthorized Access Exception: {uae.Message}"));
            }
            catch (ArgumentOutOfRangeException are)
            {
                _logger.LogError(are, $"{function}() Argument out of Range Exception.");
                return(BadRequest($"Argument out of Range Exception: {are.Message}"));
            }
            catch (ArgumentException aex)
            {
                _logger.LogError(aex, $"{function}() Argument Exception.");
                return(BadRequest($"Argument Exception: {aex.Message}"));
            }
            catch (NModbus.SlaveException mse)
            {
                _logger.LogError(mse, $"{function}() Modbus SlaveException.");
                return(StatusCode(502, $"Modbus SlaveException: {mse.Message}"));
            }
            catch (System.IO.IOException ioe)
            {
                _logger.LogError(ioe, $"{function}() IO Exception.");
                return(StatusCode(500, $"IO Exception: {ioe.Message}"));
            }
            catch (TimeoutException tex)
            {
                _logger.LogError(tex, $"{function}() Timeout Exception.");
                return(StatusCode(500, $"Timeout Exception: {tex.Message}"));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"{function}() Exception.");
                return(StatusCode(500, $"Exception: {ex.Message}"));
            }
            finally
            {
                if (_client.Connected)
                {
                    _client.Disconnect();
                }
            }
        }