예제 #1
0
        public virtual void WriteMultipleRegisters()
        {
            ushort testAddress = 120;

            ushort[] testValues = new ushort[] { 10, 20, 30, 40, 50 };

            ushort[] originalValues = Master.ReadHoldingRegisters(SlaveAddress, testAddress, (ushort)testValues.Length);
            Master.WriteMultipleRegisters(SlaveAddress, testAddress, testValues);
            ushort[] newValues = Master.ReadHoldingRegisters(SlaveAddress, testAddress, (ushort)testValues.Length);
            Assert.AreEqual(testValues, newValues);
            Master.WriteMultipleRegisters(SlaveAddress, testAddress, originalValues);
        }
예제 #2
0
        /// <summary>
        /// Запись желаемых параметров в устройство.
        /// </summary>
        protected virtual void SettingsWrite()
        {
            if (settings != null && !init)
            {
                ushort[] values  = new ushort[aSettingsLength - aSettingsStart];
                bool     changes = false;
                values[aSettingsFlagsOffset] = FlagsWriteableWanted;
                changes |= (_flagsWriteable ^ FlagsWriteableWanted) != 0;

                // parameters
                foreach (var p in settings) // table
                {
                    if (p != null)
                    {
                        values[aSettingsParametersOffset + GetId(p)] = p.WantedValue;
                        //values[aSettingsParametersOffset + p.ID] = p.WantedValue;
                        changes |= p.RawValue != p.WantedValue; // несовпадение желаемого с действительным
                    }
                }

                if (changes) // весь пакет настроек
                {
                    ioDelay();
                    master.WriteMultipleRegisters(DeviceID, aSettingsStart, values);
                    return;
                }
            }

            // default
            //ioDelay();
            //master.WriteSingleRegister(DeviceID, aSettingsStart, wzoom);
        }
예제 #3
0
 public void WriteMultipleRegisters(ushort start, ushort[] values)
 {
     if (RTUConnected || TCPConnected)
     {
         lock (_Locker)
             _Master.WriteMultipleRegisters(1, start, values);
     }
 }
예제 #4
0
        private void MainWork()
        {
            var res = Master.ReadHoldingRegisters(1, 4008, 3);

            for (int i = 0; i < res.Length; i++)
            {
                res[i]++;
            }
            var id = (ushort)Thread.CurrentThread.ManagedThreadId;

            Master.WriteMultipleRegisters(1, 4008, new ushort[] { id, id, id, id });
        }
예제 #5
0
        public int writeMultiRegisters(ModbusRegisters regs)
        {
            if (master == null)
            {
                commsts = COMMSTS_UNKONOWN;
                return(RET_INITFAILURE);
            }

            if (tcpClient == null)
            {
                commsts = COMMSTS_PORTNOTOPEN;
                return(RET_INITFAILURE);
            }

            lock (locker)
            {
                try
                {
                    for (int i = 0; i < regs.numRegisters; i++)
                    {
                        regs.values[i] = regs.stReg[i].value;
                    }

                    master.WriteMultipleRegisters(regs.slaveid, regs.startAddress, regs.values);
                }
                catch (TimeoutException ex)
                {
                    //LogClass.GetInstance().WriteLogFile("WriteMultipleRegisters Timeout:" + port.WriteTimeout.ToString());
                    //MessageBox.Show("Serial Port Write Timeout:" + port.WriteTimeout.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    if (rtycnt++ < MAX_RETYR_COUNT)
                    {
                        return(RET_TIMEOUT);
                    }
                    else
                    {
                        commsts = COMMSTS_FAILURE;
                        return(RET_COMMERROR);
                    }
                }
                catch (Exception ex)
                {
                    LogClass.GetInstance().WriteExceptionLog(ex);
                    //MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    commsts = COMMSTS_FAILURE;
                    return(RET_FAILURE);
                }
            }
            rtycnt  = 0;
            commsts = COMMSTS_NORMAL;
            return(RET_OK);
        }
예제 #6
0
        /// <summary>
        /// Write a block of contiguous 32 bit holding registers.
        /// </summary>
        /// <param name="master">The Modbus master.</param>
        /// <param name="slaveAddress">Address of the device to write to.</param>
        /// <param name="startAddress">Address to begin writing values.</param>
        /// <param name="data">Values to write.</param>
        public static void WriteMultipleRegisters32(this ModbusMaster master, byte slaveAddress, ushort startAddress, uint[] data)
        {
            if (master == null)
            {
                throw new ArgumentNullException("master");
            }
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }

            if (data.Length == 0 || data.Length > 61)
            {
                throw new ArgumentException(String.Format(CultureInfo.InvariantCulture,
                                                          "The length of argument data must be between 1 and 61 inclusive."));
            }

            master.WriteMultipleRegisters(slaveAddress, startAddress, Convert(data).ToArray());
        }
예제 #7
0
    /// <summary>
    ///     Write a block of contiguous 32 bit holding registers.
    /// </summary>
    /// <param name="master">The Modbus master.</param>
    /// <param name="slaveAddress">Address of the device to write to.</param>
    /// <param name="startAddress">Address to begin writing values.</param>
    /// <param name="data">Values to write.</param>
    public static void WriteMultipleRegisters32(
        this ModbusMaster master,
        byte slaveAddress,
        ushort startAddress,
        uint[] data)
    {
        if (master == null)
        {
            throw new ArgumentNullException(nameof(master));
        }

        if (data == null)
        {
            throw new ArgumentNullException(nameof(data));
        }

        if (data.Length is 0 or > 61)
        {
            throw new ArgumentException("The length of argument data must be between 1 and 61 inclusive.");
        }

        master.WriteMultipleRegisters(slaveAddress, startAddress, Convert(data).ToArray());
    }
예제 #8
0
        private Dictionary <int, string> SendRequests(ModbusMaster master, MasterSettings masterSettings)
        {
            if (master == null)
            {
                return(null);
            }

            var results = new Dictionary <int, string>();

            foreach (var slave in masterSettings.SlaveSettings)
            {
                string hexResults = "";

                PackagesCounter.RequestedPackagesCount += 1;

                try
                {
                    if (masterSettings.IsLoggerEnabled)
                    {
                        Logger.WriteDebug($"Sent request to a slave: DeviceId = {slave.DeviceId}; SlaveAddress={slave.StartAddress}; NumberOfRegisters={slave.NumberOfRegisters}.");
                    }

                    switch (slave.ActionType)
                    {
                    case ActionTypes.Read:
                        var registers = master.ReadHoldingRegisters(slave.DeviceId, slave.StartAddress,
                                                                    slave.NumberOfRegisters);

                        if (registers == null || registers.Length == 0)
                        {
                            throw new EmptyResultException(
                                      $"Slave with address {slave.DeviceId} returned an empty result when reading {slave.NumberOfRegisters} registers starting with register number {slave.StartAddress}.");
                        }

                        PackagesCounter.RecievedPackagesCount += 1;
                        isConnectionLost = false;

                        var inputs = registers.ConvertToBitArray();

                        hexResults = inputs.ConvertToHex();

                        var startAddress = slave.StartAddress;

                        foreach (var type in slave.Types)
                        {
                            switch (type.Item2)
                            {
                            case ModbusDataType.SInt16:
                                // Берём из массива битов первые 16, чтобы сконвертировать их в знаковое 16-битное целое число.
                                var sInt16Part = inputs.Take(8 * type.Item1).ToArray();

                                // Обрезаем у массива эти первые 16 бит (16 бит = 2 байта).
                                inputs = inputs.Skip(8 * type.Item1).ToArray();

                                // Преобразуем массив битов в строку, состоящую из единиц и нулей.
                                var sInt16BinaryString = string.Join("", sInt16Part.Select(x => x ? 1 : 0));

                                // Конвертируем полученное двоичное число в знаковое 16-битное целое число.
                                var sInt16 = Convert.ToInt16(sInt16BinaryString, 2);

                                // Добавляем полученное число в список значений.
                                results.Add(startAddress, sInt16.ToString());

                                // Перемещаем указатель на следующий регистр (16 бит = 2 байта = 1 регистр)
                                startAddress += (ushort)(type.Item1 / 2);

                                break;

                            case ModbusDataType.UInt16:
                                // Берём из массива битов первые 16, чтобы сконвертировать их в беззнаковое 16-битное целое число.
                                var uInt16Part = inputs.Take(8 * type.Item1).ToArray();

                                // Обрезаем у массива эти первые 16 бит (16 бит = 2 байта).
                                inputs = inputs.Skip(8 * type.Item1).ToArray();

                                // Преобразуем массив битов в строку, состоящую из единиц и нулей.
                                var binaryString = uInt16Part.Select(x => x ? 1 : 0);

                                // Конвертируем полученное двоичное число в беззнаковое 16-битное целое число.
                                var uShort = Convert.ToUInt16(string.Join("", binaryString), 2);

                                // Добавляем полученное число в список значений.
                                results.Add(startAddress, uShort.ToString());

                                // Перемещаем указатель на следующий регистр (16 бит = 2 байта = 1 регистр)
                                startAddress += (ushort)(type.Item1 / 2);

                                break;

                            case ModbusDataType.SInt32:
                                // Берём из массива битов первые 32, чтобы сконвертировать их в знаковое 32-битное целое число.
                                var sInt32Part = inputs.Take(8 * type.Item1).ToArray();

                                // Обрезаем у массива эти первые 32 бит (32 бит = 4 байта).
                                inputs = inputs.Skip(8 * type.Item1).ToArray();

                                // Преобразуем массив битов в строку, состоящую из единиц и нулей.
                                var sInt32BinaryString = sInt32Part.Select(x => x ? 1 : 0);

                                // Конвертируем полученное двоичное число в знаковое 32-битное целое число.
                                var sInt32 = Convert.ToInt32(string.Join("", sInt32BinaryString), 2);

                                // Добавляем полученное число в список значений.
                                results.Add(startAddress, sInt32.ToString());

                                // Перемещаем указатель на следующий регистр (32 бита = 4 байта = 2 регистра)
                                startAddress += (ushort)(type.Item1 / 2);

                                break;

                            case ModbusDataType.UInt32:
                                // Берём из массива битов первые 32, чтобы сконвертировать их в беззнаковое 32-битное целое число.
                                var uInt32Part = inputs.Take(8 * type.Item1).ToArray();

                                // Обрезаем у массива эти первые 32 бит (32 бит = 4 байта).
                                inputs = inputs.Skip(8 * type.Item1).ToArray();

                                // Преобразуем массив битов в строку, состоящую из единиц и нулей.
                                var binaryUInt32String = uInt32Part.Select(x => x ? 1 : 0);

                                // Конвертируем полученное двоичное число в беззнаковое 32-битное целое число.
                                var uInt32 = Convert.ToUInt32(string.Join("", binaryUInt32String), 2);

                                // Добавляем полученное число в список значений.
                                results.Add(startAddress, uInt32.ToString());

                                // Перемещаем указатель на следующий регистр (32 бита = 4 байта = 2 регистра)
                                startAddress += (ushort)(type.Item1 / 2);

                                break;

                            case ModbusDataType.Hex:
                                // Берём из массива битов первые 32, чтобы сконвертировать их в беззнаковое 32-битное целое число.
                                var hexPart = inputs.Take(8 * type.Item1).ToArray();

                                // Обрезаем у массива эти первые 32 бит (32 бит = 4 байта).
                                inputs = inputs.Skip(8 * type.Item1).ToArray();

                                // Преобразуем массив битов в строку, состоящую из единиц и нулей.
                                var binaryHexString = hexPart.Select(x => x ? 1 : 0);

                                // Конвертируем полученное десятичное число в знаковое 32-битное целое число, после этого конвертируем число в 16-ричную систему счисления.
                                var hex = Convert.ToUInt32(string.Join("", binaryHexString), 2).ToString("X");

                                // Добавляем полученное число в список значений.
                                results.Add(startAddress, $"0x{hex}");

                                // Перемещаем указатель на следующий регистр (32 бита = 4 байта = 2 регистра)
                                startAddress += (ushort)(type.Item1 / 2);

                                break;

                            case ModbusDataType.UtcTimestamp:
                                // В данном случае мы должны считать целое число (тоже беззнаковое 32-битное) и преобразовать к дате.
                                // Берём из массива битов первые 32, чтобы сконвертировать их в знаковое 32-битное целое число.
                                var utcTimestampPart = inputs.Take(8 * type.Item1).ToArray();
                                inputs = inputs.Skip(8 * type.Item1).ToArray();

                                // Преобразуем массив битов в строку, состоящую из единиц и нулей.
                                var binaryUtcTimestampString = utcTimestampPart.Select(x => x ? 1 : 0);

                                // Конвертируем полученное двоичное число в беззнаковое 32-битное целое число.
                                var utcTimestamp = Convert.ToUInt32(string.Join("", binaryUtcTimestampString), 2);

                                // Добавляем полученное число в список значений.
                                results.Add(startAddress, new DateTime(1970, 1, 1).AddSeconds(utcTimestamp)
                                            .ToLocalTime()
                                            .ToString("yyyy.MM.dd HH:mm:ss"));

                                // Перемещаем указатель на следующий регистр (32 бита = 4 байта = 2 регистра)
                                startAddress += (ushort)(type.Item1 / 2);

                                break;

                            case ModbusDataType.String:
                                bool[] stringPart;

                                if (inputs.Length > 8 * type.Item1)
                                {
                                    stringPart = inputs.Take(8 * type.Item1).ToArray();
                                    inputs     = inputs.Skip(8 * type.Item1).ToArray();

                                    results.Add(startAddress, stringPart.ConvertToString());

                                    startAddress += (ushort)(type.Item1 / 2);
                                }
                                else
                                {
                                    stringPart = inputs;
                                    inputs     = new bool[0];

                                    results.Add(startAddress, stringPart.ConvertToString());

                                    startAddress += (ushort)(stringPart.Length / 16);
                                }

                                break;

                            default:
                                throw new ArgumentOutOfRangeException();
                            }
                        }

                        if (masterSettings.IsLoggerEnabled)
                        {
                            Logger.WriteDebug($"Recieved data from slave: DeviceId = {slave.DeviceId}; SlaveAddress={slave.StartAddress}; NumberOfRegisters={slave.NumberOfRegisters}; {hexResults}");
                        }

                        break;

                    case ActionTypes.Write:
                        var data = new ushort[] { Convert.ToUInt16(slave.Formula) };

                        master.WriteMultipleRegisters(slave.DeviceId, slave.StartAddress, data);

                        if (masterSettings.IsLoggerEnabled)
                        {
                            Logger.WriteDebug($"Sent data to slave: DeviceId = {slave.DeviceId}; SlaveAddress={slave.StartAddress}; {data}");
                        }

                        break;
                    }
                }
                catch (SlaveException slaveException)
                {
                    switch (slaveException.SlaveExceptionCode)
                    {
                    case 130:
                        if (!isConnectionLost)
                        {
                            Logger.Write(slaveException.Message);
                        }
                        isConnectionLost = true;
                        break;

                    default:
                        if (loggerEnabled)
                        {
                            Logger.Write(slaveException.Message);
                        }
                        else
                        {
                            throw slaveException;
                        }
                        break;
                    }
                }
                catch (Exception exception)
                {
                    if (loggerEnabled)
                    {
                        Logger.Write(exception.Message);
                    }
                    else
                    {
                        throw exception;
                    }
                }
            }

            return(results);
        }