Exemple #1
0
        /// <summary>
        /// Reads the specified number of values of type <typeparamref name="TRead"/> from and writes the provided array of type <typeparamref name="TWrite"/> to the holding registers. The write operation is performed before the read.
        /// </summary>
        /// <typeparam name="TRead">Determines the type of the returned data.</typeparam>
        /// <typeparam name="TWrite">Determines the type of the provided data.</typeparam>
        /// <param name="unitIdentifier">The unit identifier is used to communicate via devices such as bridges, routers and gateways that use a single IP address to support multiple independent Modbus end units. Thus, the unit identifier is the address of a remote slave connected on a serial line or on other buses. Use the default values 0x00 or 0xFF when communicating to a Modbus server that is directly connected to a TCP/IP network.</param>
        /// <param name="readStartingAddress">The holding register start address for the read operation.</param>
        /// <param name="readCount">The number of elements of type <typeparamref name="TRead"/> to read.</param>
        /// <param name="writeStartingAddress">The holding register start address for the write operation.</param>
        /// <param name="dataset">The data of type <typeparamref name="TWrite"/> to write to the server.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
        public async Task <Memory <TRead> > ReadWriteMultipleRegistersAsync <TRead, TWrite>(int unitIdentifier, int readStartingAddress, int readCount, int writeStartingAddress, TWrite[] dataset, CancellationToken cancellationToken = default) where TRead : unmanaged
            where TWrite : unmanaged
        {
            var unitIdentifier_converted       = this.ConvertUnitIdentifier(unitIdentifier);
            var readStartingAddress_converted  = this.ConvertUshort(readStartingAddress);
            var readCount_converted            = this.ConvertUshort(readCount);
            var writeStartingAddress_converted = this.ConvertUshort(writeStartingAddress);

            if (this.SwapBytes)
            {
                ModbusUtils.SwitchEndianness(dataset.AsSpan());
            }

            var readQuantity = this.ConvertSize <TRead>(readCount_converted);
            var byteData     = MemoryMarshal.Cast <TWrite, byte>(dataset).ToArray();

            var dataset2 = SpanExtensions.Cast <byte, TRead>(await this.ReadWriteMultipleRegistersAsync(unitIdentifier_converted, readStartingAddress_converted, readQuantity, writeStartingAddress_converted, byteData).ConfigureAwait(false));

            if (this.SwapBytes)
            {
                ModbusUtils.SwitchEndianness(dataset2);
            }

            return(dataset2);
        }
Exemple #2
0
        /// <summary>
        /// Reads the specified number of values of type <typeparamref name="TRead"/> from and writes the provided array of type <typeparamref name="TWrite"/> to the holding registers. The write operation is performed before the read.
        /// </summary>
        /// <typeparam name="TRead">Determines the type of the returned data.</typeparam>
        /// <typeparam name="TWrite">Determines the type of the provided data.</typeparam>
        /// <param name="unitIdentifier">The unit identifier is used to communicate via devices such as bridges, routers and gateways that use a single IP address to support multiple independent Modbus end units. Thus, the unit identifier is the address of a remote slave connected on a serial line or on other buses. Use the default values 0x00 or 0xFF when communicating to a Modbus server that is directly connected to a TCP/IP network.</param>
        /// <param name="readStartingAddress">The holding register start address for the read operation.</param>
        /// <param name="readCount">The number of elements of type <typeparamref name="TRead"/> to read.</param>
        /// <param name="writeStartingAddress">The holding register start address for the write operation.</param>
        /// <param name="dataset">The data of type <typeparamref name="TWrite"/> to write to the server.</param>
        public Span <TRead> ReadWriteMultipleRegisters <TRead, TWrite>(int unitIdentifier, int readStartingAddress, int readCount, int writeStartingAddress, TWrite[] dataset) where TRead : unmanaged
            where TWrite : unmanaged
        {
            var unitIdentifier_converted       = this.ConvertUnitIdentifier(unitIdentifier);
            var readStartingAddress_converted  = this.ConvertUshort(readStartingAddress);
            var readCount_converted            = this.ConvertUshort(readCount);
            var writeStartingAddress_converted = this.ConvertUshort(writeStartingAddress);

            if (this.SwapBytes)
            {
                ModbusUtils.SwitchEndianness(dataset.AsSpan());
            }

            var readQuantity = this.ConvertSize <TRead>(readCount_converted);
            var byteData     = MemoryMarshal.Cast <TWrite, byte>(dataset).ToArray();

            var dataset2 = MemoryMarshal.Cast <byte, TRead>(this.ReadWriteMultipleRegisters(unitIdentifier_converted, readStartingAddress_converted, readQuantity, writeStartingAddress_converted, byteData));

            if (this.SwapBytes)
            {
                ModbusUtils.SwitchEndianness(dataset2);
            }

            return(dataset2);
        }
        public static T SwitchEndianness <T>(T value) where T : unmanaged
        {
            Span <T> data = stackalloc T[] { value };

            ModbusUtils.SwitchEndianness(data);

            return(data[0]);
        }
Exemple #4
0
        public static T SwitchEndianness <T>(T value) where T : unmanaged
        {
            var data = new T[] { value };

            ModbusUtils.SwitchEndianness(data.AsSpan());

            return(data[0]);
        }
        /// <summary>
        /// Writes the provided <paramref name="value"/> to the holding registers.
        /// </summary>
        /// <param name="unitIdentifier">The unit identifier is used to communicate via devices such as bridges, routers and gateways that use a single IP address to support multiple independent Modbus end units. Thus, the unit identifier is the address of a remote slave connected on a serial line or on other buses. Use the default values 0x00 or 0xFF when communicating to a Modbus server that is directly connected to a TCP/IP network.</param>
        /// <param name="registerAddress">The holding register address for the write operation.</param>
        /// <param name="value">The value to write to the server.</param>
        public void WriteSingleRegister(byte unitIdentifier, ushort registerAddress, ushort value)
        {
            if (this.SwapBytes)
            {
                value = ModbusUtils.SwitchEndianness(value);
            }

            this.WriteSingleRegister(unitIdentifier, registerAddress, MemoryMarshal.Cast <ushort, byte>(new[] { value }).ToArray());
        }
        /// <summary>
        /// Writes the provided array of type <typeparamref name="T"/> to the holding registers.
        /// </summary>
        /// <typeparam name="T">Determines the type of the provided data.</typeparam>
        /// <param name="unitIdentifier">The unit identifier is used to communicate via devices such as bridges, routers and gateways that use a single IP address to support multiple independent Modbus end units. Thus, the unit identifier is the address of a remote slave connected on a serial line or on other buses. Use the default values 0x00 or 0xFF when communicating to a Modbus server that is directly connected to a TCP/IP network.</param>
        /// <param name="startingAddress">The holding register start address for the write operation.</param>
        /// <param name="dataset">The data of type <typeparamref name="T"/> to write to the server.</param>
        public void WriteMultipleRegisters <T>(byte unitIdentifier, ushort startingAddress, T[] dataset) where T : unmanaged
        {
            if (this.SwapBytes)
            {
                ModbusUtils.SwitchEndianness(dataset.AsSpan());
            }

            this.WriteMultipleRegisters(unitIdentifier, startingAddress, MemoryMarshal.Cast <T, byte>(dataset).ToArray());
        }
        /// <summary>
        /// Reads the specified number of values of type <typeparamref name="T"/> from the input registers.
        /// </summary>
        /// <typeparam name="T">Determines the type of the returned data.</typeparam>
        /// <param name="unitIdentifier">The unit identifier is used to communicate via devices such as bridges, routers and gateways that use a single IP address to support multiple independent Modbus end units. Thus, the unit identifier is the address of a remote slave connected on a serial line or on other buses. Use the default values 0x00 or 0xFF when communicating to a Modbus server that is directly connected to a TCP/IP network.</param>
        /// <param name="startingAddress">The input register start address for the read operation.</param>
        /// <param name="count">The number of elements of type <typeparamref name="T"/> to read.</param>
        public Span <T> ReadInputRegisters <T>(byte unitIdentifier, ushort startingAddress, ushort count) where T : unmanaged
        {
            var dataset = MemoryMarshal.Cast <byte, T>(this.ReadInputRegisters(unitIdentifier, startingAddress, this.ConvertSize <T>(count)));

            if (this.SwapBytes)
            {
                ModbusUtils.SwitchEndianness(dataset);
            }

            return(dataset);
        }
Exemple #8
0
        /// <summary>
        /// Writes the provided <paramref name="value"/> to the holding registers.
        /// </summary>
        /// <param name="unitIdentifier">The unit identifier is used to communicate via devices such as bridges, routers and gateways that use a single IP address to support multiple independent Modbus end units. Thus, the unit identifier is the address of a remote slave connected on a serial line or on other buses. Use the default values 0x00 or 0xFF when communicating to a Modbus server that is directly connected to a TCP/IP network.</param>
        /// <param name="registerAddress">The holding register address for the write operation.</param>
        /// <param name="value">The value to write to the server.</param>
        public void WriteSingleRegister(int unitIdentifier, int registerAddress, ushort value)
        {
            var unitIdentifier_converted  = this.ConvertUnitIdentifier(unitIdentifier);
            var registerAddress_converted = this.ConvertUshort(registerAddress);

            if (this.SwapBytes)
            {
                value = ModbusUtils.SwitchEndianness(value);
            }

            this.WriteSingleRegister(unitIdentifier_converted, registerAddress_converted, MemoryMarshal.Cast <ushort, byte>(new[] { value }).ToArray());
        }
Exemple #9
0
        /// <summary>
        /// Writes the provided array of type <typeparamref name="T"/> to the holding registers.
        /// </summary>
        /// <typeparam name="T">Determines the type of the provided data.</typeparam>
        /// <param name="unitIdentifier">The unit identifier is used to communicate via devices such as bridges, routers and gateways that use a single IP address to support multiple independent Modbus end units. Thus, the unit identifier is the address of a remote slave connected on a serial line or on other buses. Use the default values 0x00 or 0xFF when communicating to a Modbus server that is directly connected to a TCP/IP network.</param>
        /// <param name="startingAddress">The holding register start address for the write operation.</param>
        /// <param name="dataset">The data of type <typeparamref name="T"/> to write to the server.</param>
        public void WriteMultipleRegisters <T>(int unitIdentifier, int startingAddress, T[] dataset) where T : unmanaged
        {
            var unitIdentifier_converted  = this.ConvertUnitIdentifier(unitIdentifier);
            var startingAddress_converted = this.ConvertUshort(startingAddress);

            if (this.SwapBytes)
            {
                ModbusUtils.SwitchEndianness(dataset.AsSpan());
            }

            this.WriteMultipleRegisters(unitIdentifier_converted, startingAddress_converted, MemoryMarshal.Cast <T, byte>(dataset).ToArray());
        }
Exemple #10
0
        /// <summary>
        /// Writes the provided <paramref name="value"/> to the holding registers.
        /// </summary>
        /// <param name="unitIdentifier">The unit identifier is used to communicate via devices such as bridges, routers and gateways that use a single IP address to support multiple independent Modbus end units. Thus, the unit identifier is the address of a remote slave connected on a serial line or on other buses. Use the default values 0x00 or 0xFF when communicating to a Modbus server that is directly connected to a TCP/IP network.</param>
        /// <param name="registerAddress">The holding register address for the write operation.</param>
        /// <param name="value">The value to write to the server.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
        public async Task WriteSingleRegisterAsync(int unitIdentifier, int registerAddress, ushort value, CancellationToken cancellationToken = default)
        {
            var unitIdentifier_converted  = this.ConvertUnitIdentifier(unitIdentifier);
            var registerAddress_converted = this.ConvertUshort(registerAddress);

            if (this.SwapBytes)
            {
                value = ModbusUtils.SwitchEndianness(value);
            }

            await this.WriteSingleRegisterAsync(unitIdentifier_converted, registerAddress_converted, MemoryMarshal.Cast <ushort, byte>(new[] { value }).ToArray()).ConfigureAwait(false);
        }
Exemple #11
0
        /// <summary>
        /// Writes the provided array of type <typeparamref name="T"/> to the holding registers.
        /// </summary>
        /// <typeparam name="T">Determines the type of the provided data.</typeparam>
        /// <param name="unitIdentifier">The unit identifier is used to communicate via devices such as bridges, routers and gateways that use a single IP address to support multiple independent Modbus end units. Thus, the unit identifier is the address of a remote slave connected on a serial line or on other buses. Use the default values 0x00 or 0xFF when communicating to a Modbus server that is directly connected to a TCP/IP network.</param>
        /// <param name="startingAddress">The holding register start address for the write operation.</param>
        /// <param name="dataset">The data of type <typeparamref name="T"/> to write to the server.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
        public async Task WriteMultipleRegistersAsync <T>(int unitIdentifier, int startingAddress, T[] dataset, CancellationToken cancellationToken = default) where T : unmanaged
        {
            var unitIdentifier_converted  = this.ConvertUnitIdentifier(unitIdentifier);
            var startingAddress_converted = this.ConvertUshort(startingAddress);

            if (this.SwapBytes)
            {
                ModbusUtils.SwitchEndianness(dataset.AsSpan());
            }

            await this.WriteMultipleRegistersAsync(unitIdentifier_converted, startingAddress_converted, MemoryMarshal.Cast <T, byte>(dataset).ToArray()).ConfigureAwait(false);
        }
        public static void SetBigEndian <T>(this Span <short> buffer, ushort address, T value)
            where T : unmanaged
        {
            var byteBuffer = MemoryMarshal
                             .AsBytes(buffer)
                             .Slice(address * 2);

            if (BitConverter.IsLittleEndian)
            {
                value = ModbusUtils.SwitchEndianness(value);
            }

            Unsafe.WriteUnaligned(ref byteBuffer.GetPinnableReference(), value);
        }
Exemple #13
0
        /// <summary>
        /// Reads the specified number of values of type <typeparamref name="T"/> from the input registers.
        /// </summary>
        /// <typeparam name="T">Determines the type of the returned data.</typeparam>
        /// <param name="unitIdentifier">The unit identifier is used to communicate via devices such as bridges, routers and gateways that use a single IP address to support multiple independent Modbus end units. Thus, the unit identifier is the address of a remote slave connected on a serial line or on other buses. Use the default values 0x00 or 0xFF when communicating to a Modbus server that is directly connected to a TCP/IP network.</param>
        /// <param name="startingAddress">The input register start address for the read operation.</param>
        /// <param name="count">The number of elements of type <typeparamref name="T"/> to read.</param>
        public Span <T> ReadInputRegisters <T>(int unitIdentifier, int startingAddress, int count) where T : unmanaged
        {
            var unitIdentifier_converted  = this.ConvertUnitIdentifier(unitIdentifier);
            var startingAddress_converted = this.ConvertUshort(startingAddress);
            var count_converted           = this.ConvertUshort(count);

            var dataset = MemoryMarshal.Cast <byte, T>(
                this.ReadInputRegisters(unitIdentifier_converted, startingAddress_converted, this.ConvertSize <T>(count_converted)));

            if (this.SwapBytes)
            {
                ModbusUtils.SwitchEndianness(dataset);
            }

            return(dataset);
        }
        public static T GetBigEndian <T>(this Span <short> buffer, ushort address)
            where T : unmanaged
        {
            var byteBuffer = MemoryMarshal
                             .AsBytes(buffer)
                             .Slice(address * 2);

            var value = Unsafe.ReadUnaligned <T>(ref byteBuffer.GetPinnableReference());

            if (BitConverter.IsLittleEndian)
            {
                value = ModbusUtils.SwitchEndianness(value);
            }

            return(value);
        }
Exemple #15
0
        /// <summary>
        /// Reads the specified number of values of type <typeparamref name="T"/> from the holding registers.
        /// </summary>
        /// <typeparam name="T">Determines the type of the returned data.</typeparam>
        /// <param name="unitIdentifier">The unit identifier is used to communicate via devices such as bridges, routers and gateways that use a single IP address to support multiple independent Modbus end units. Thus, the unit identifier is the address of a remote slave connected on a serial line or on other buses. Use the default values 0x00 or 0xFF when communicating to a Modbus server that is directly connected to a TCP/IP network.</param>
        /// <param name="startingAddress">The holding register start address for the read operation.</param>
        /// <param name="count">The number of elements of type <typeparamref name="T"/> to read.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
        public async Task <Memory <T> > ReadHoldingRegistersAsync <T>(int unitIdentifier, int startingAddress, int count, CancellationToken cancellationToken = default) where T : unmanaged
        {
            var unitIdentifier_converted  = this.ConvertUnitIdentifier(unitIdentifier);
            var startingAddress_converted = this.ConvertUshort(startingAddress);
            var count_converted           = this.ConvertUshort(count);

            var dataset = SpanExtensions.Cast <byte, T>(await
                                                        this.ReadHoldingRegistersAsync(unitIdentifier_converted, startingAddress_converted, this.ConvertSize <T>(count_converted)).ConfigureAwait(false));

            if (this.SwapBytes)
            {
                ModbusUtils.SwitchEndianness(dataset);
            }

            return(dataset);
        }
Exemple #16
0
        public static void SetBigEndian <T>(this Span <short> buffer, int address, T value)
            where T : unmanaged
        {
            if (!(0 <= address && address <= ushort.MaxValue))
            {
                throw new Exception(ErrorMessage.Modbus_InvalidValueUShort);
            }

            var byteBuffer = MemoryMarshal
                             .AsBytes(buffer)
                             .Slice(address * 2);

            if (BitConverter.IsLittleEndian)
            {
                value = ModbusUtils.SwitchEndianness(value);
            }

            Unsafe.WriteUnaligned(ref byteBuffer.GetPinnableReference(), value);
        }
        public static T GetMidLittleEndian <T>(this Span <short> buffer, int address)
            where T : unmanaged
        {
            if (!(0 <= address && address <= ushort.MaxValue))
            {
                throw new Exception(ErrorMessage.Modbus_InvalidValueUShort);
            }

            var byteBuffer = MemoryMarshal
                             .AsBytes(buffer)
                             .Slice(address * 2);

            var value = Unsafe.ReadUnaligned <T>(ref byteBuffer.GetPinnableReference());

            value = ModbusUtils.ConvertBetweenLittleEndianAndMidLittleEndian(value);

            if (!BitConverter.IsLittleEndian)
            {
                value = ModbusUtils.SwitchEndianness(value);
            }

            return(value);
        }
Exemple #18
0
 public static void SwitchEndianness <T>(Memory <T> dataset) where T : unmanaged
 {
     ModbusUtils.SwitchEndianness(dataset.Span);
 }