В связи с выходом крупного обновления 5.9.х, приглашаем вас принять участие в вебинаре 09.06.2022 в 15:00. Участвовать

Плагин Modbus



  • Подскажите: имеются исполнительные модули которые работают по протоколу Modbus RTU (RS-485). Можно ли работать с такими модулями с помощью плагина Modbus через преобразователь интерфейсов из RS-485 (Modbus) в Ethernet (IP)?

    Вот такой преобразователь - https://wirenboard.com/ru/product/WB-MGE/

    Был ли у кого подобный опыт работы с подобными преобразователями?



  • На следующей неделе будем закупать некоторое оборудование wiremboard.

    Доделаем плагин для Modbus для протокола modbus RTU и протестируем с этим преобразователем.



  • Спасибо! Буду ждать результат.



  • Есть ли результат по плагину modbus-rtu?

    Пытаюсь считать показания тепловычислителя: ТМК-Н130. Подсоединен через преобразователь интерфейсов Ethernet/RS-232. Всё что поступает через Ethernet отправляется на интерфейс RS-232 тепловычислителя. modpoll работает нормально:

    Пример опроса (Количество тепловой энергии Q1), считываем регистр хранения 30018 (целая часть) и 30020 (дробная часть).

    В регистрах счетчика данные хранятся в формате little-endian.

    e:\Ivan\Проекты\modbus\soft\modpoll.3.4\win32>modpoll -m enc -a 0 -c 1 -r 17 -t 3:int -1 -0 -i -f -p 45016 77.244.70.15

    e:\Ivan\Проекты\modbus\soft\modpoll.3.4\win32>modpoll -m enc -a 0 -c 1 -r 19 -t 3:float -1 -0 -i -f -p 45016 77.244.70.15

    С плагином modbus-tcp работать не хочет, лог выдает:

    8.06 19:36:36.138 IH: Run /var/lib/intrahouse-c/plugins/modbus/modbus.js modbus2
    28.06 19:36:36.609 modbus2: Plugin modbus2 has started.
    28.06 19:36:36.632 modbus2: Connecting options { port: 45016, host: '77.244.70.15' }
    28.06 19:36:36.697 modbus2: Connected to 77.244.70.15:45016
    28.06 19:36:36.699 modbus2: READ unitid=1 FC=3 address=30018 (0x7542) length=2
    28.06 19:36:36.906 modbus2: Network ERROR: ETIMEDOUT
    28.06 19:36:36.914 IH: Plugin exit with code 1
    28.06 19:36:36.914 IH: restart timer 5
    28.06 19:36:42.164 IH: Run /var/lib/intrahouse-c/plugins/modbus/modbus.js modbus2
    28.06 19:36:42.640 modbus2: Plugin modbus2 has started.
    28.06 19:36:42.662 modbus2: Connecting options { port: 45016, host: '77.244.70.15' }
    28.06 19:36:42.747 modbus2: Connected to 77.244.70.15:45016
    28.06 19:36:42.749 modbus2: READ unitid=1 FC=3 address=30018 (0x7542) length=2
    28.06 19:36:42.957 modbus2: Network ERROR: ETIMEDOUT
    28.06 19:36:42.964 IH: Plugin exit with code 1
    28.06 19:36:42.965 IH: restart timer 5
    
    

    В чем может быть проблема?



  • @gis:

    Есть ли результат по плагину modbus-rtu?

    Пытаюсь считать показания тепловычислителя: ТМК-Н130. Подсоединен через преобразователь интерфейсов Ethernet/RS-232. Всё что поступает через Ethernet отправляется на интерфейс RS-232 тепловычислителя. modpoll работает нормально:

    Пример опроса (Количество тепловой энергии Q1), считываем регистр хранения 30018 (целая часть) и 30020 (дробная часть).

    В регистрах счетчика данные хранятся в формате little-endian.

    e:\Ivan\Проекты\modbus\soft\modpoll.3.4\win32>modpoll -m enc -a 0 -c 1 -r 17 -t 3:int -1 -0 -i -f -p 45016 77.244.70.15

    e:\Ivan\Проекты\modbus\soft\modpoll.3.4\win32>modpoll -m enc -a 0 -c 1 -r 19 -t 3:float -1 -0 -i -f -p 45016 77.244.70.15

    С плагином modbus-tcp работать не хочет, лог выдает:

    В чем может быть проблема?

    Если это простой преобразователь интерфейса, то пакеты RTU передаются в TCP сокет без преобразования. То есть это не Modbus-TCP, а Modbus RTU over TCP

    Попробуйте скачать новый релиз плагина v0.0.9 с github: https://github.com/intrahouseio/intraHouse.plugin-Modbus/releases

    В нем добавлен этот транспорт. Не выкладываем для обновления, так как протестировано пока только на одном виде оборудования.



  • Скачал плагин v0.0.9 с github. Показания не считываются, выдает вот такой лог:

    01.07 07:32:51.201 modbus2: Plugin modbus2 has started.
    01.07 07:32:51.220 modbus2: config=[ { id: 'ch1',
        vartype: 'uint16',
        unit: 'modbus2',
        usek: false,
        ks: 100,
        ks0: 0,
        gr: false,
        pollp: true,
        desc: 'AI',
        chan: 'ch1',
        kh0: 0,
        address: '30018',
        fcr: '3',
        useactions: false,
        actions: [ [Object] ],
        kh: 100,
        unitid: 0,
        inv: false,
        inv_out: false,
        prop: '',
        op: '',
        value: '',
        calc_out: '',
        dn: 'T',
        calc: '',
        nofb: false } ]
    01.07 07:32:51.225 modbus2: polls=[ { length: 1,
        unitid: 0,
        desc: 'AI',
        fcr: '3',
        address: 30018,
        ref: [ [Object] ] } ]
    01.07 07:32:51.300 modbus2: Connected to 77.244.70.15:45016
    01.07 07:32:51.301 modbus2: sendNext item={ length: 1,
      unitid: 0,
      desc: 'AI',
      fcr: '3',
      address: 30018,
      ref: [ { id: 'ch1', vartype: 'uint16le', widx: 0 } ] }
    01.07 07:32:51.302 modbus2: READ unitid=0 FC=3 address=30018 (0x7542) length=1
    01.07 07:32:51.355 modbus2: ERROR: Error: Modbus exception 2
        at TelnetPort. <anonymous>(/var/lib/intrahouse-c/plugins/modbus/node_modules/modbus-serial/index.js:288:42)
        at emitOne (events.js:115:13)
        at TelnetPort.emit (events.js:210:7)
        at TelnetPort._emitData (/var/lib/intrahouse-c/plugins/modbus/node_modules/modbus-serial/ports/telnetport.js:154:10)
        at Socket.onData (/var/lib/intrahouse-c/plugins/modbus/node_modules/modbus-serial/ports/telnetport.js:100:22)
        at emitOne (events.js:115:13)
        at Socket.emit (events.js:210:7)
        at addChunk (_stream_readable.js:264:12)
        at readableAddChunk (_stream_readable.js:251:11)
        at Socket.Readable.push (_stream_readable.js:209:10)
    01.07 07:32:51.364 IH: Plugin exit with code 1
    01.07 07:32:51.365 IH: restart timer 5</anonymous>
    
    


  • @gis:

    Скачал плагин v0.0.9 с github. Показания не считываются, выдает вот такой лог:

    > 01.07 07:32:51.302 modbus2: READ unitid=0 FC=3 address=30018 (0x7542) length=1
    > 01.07 07:32:51.355 modbus2: ERROR: Error: Modbus exception 2
    > 
    > 
    

    Не указан Unit ID (адрес устройства на шине).

    Проверьте, пожалуйста, в настройке канала



  • Спасибо! Согласно инструкции на тепловычислитель, если используется подключение RS232 (а оно используется через преобразователь интерфейсов), то адрес устройства = 0. Я такой адрес и установил в настройках плагина. Следует ли использовать адрес устройства =1?



  • Поставил адрес устройства =1 Аналогичная картина:

    01.07 18:48:17.041 modbus2: sendNext item={ length: 1,
      unitid: 1,
      desc: 'AI',
      fcr: '3',
      address: 30018,
      ref: [ { id: 'ch1', vartype: 'uint16le', widx: 0 } ] }
    01.07 18:48:17.042 modbus2: READ unitid=1 FC=3 address=30018 (0x7542) length=1
    01.07 18:48:17.092 modbus2: ERROR: Error: Modbus exception 2
    
    

    Что означает ERROR: Error: Modbus exception 2



  • @gis:

    Поставил адрес устройства =1 Аналогичная картина:

    > 01.07 18:48:17.042 modbus2: READ unitid=1 FC=3 address=30018 (0x7542) length=1
    > 01.07 18:48:17.092 modbus2: ERROR: Error: Modbus exception 2
    > 
    

    Что означает ERROR: Error: Modbus exception 2

    Сейчас подключение у Вас произошло. 2 - это стандартная ошибка адресации уровня Modbus:

    Modbus exception 2 - Illegal Data Address. The data address received in the query is not an allowable address for the slave

    Попробуйте адресоваться внутри таблицы, как в modpoll - адрес 17



  • Похоже проблема с адресаций. Поставил 17 ошибок не выдает:

    1.07 22:52:17.171 modbus2: sendNext item={ length: 2,
      unitid: 0,
      desc: 'AI',
      fcr: '3',
      address: 17,
      ref: [ { id: 'ch1', vartype: 'int32le', widx: 0 } ] }
    01.07 22:52:17.172 modbus2: READ unitid=0 FC=3 address=17 (0x11) length=2
    01.07 22:52:17.220 IH: set {"T":{"aval":0,"err":0}}
    01.07 22:52:17.221 modbus2: {"type":"Buffer","data":[0,0,0,0]}
    01.07 22:52:17.721 modbus2: sendNext item={ length: 2,
      unitid: 0,
      desc: 'AI',
      fcr: '3',
      address: 17,
      ref: [ { id: 'ch1', vartype: 'int32le', widx: 0 } ] }
    01.07 22:52:17.723 modbus2: READ unitid=0 FC=3 address=17 (0x11) length=2
    01.07 22:52:17.770 IH: set {"T":{"aval":0,"err":0}}
    01.07 22:52:17.771 modbus2: {"type":"Buffer","data":[0,0,0,0]}
    
    

    Но значение =0

    modpoll при этом выдает значение 1160.



  • @gis:

    Похоже проблема с адресаций. Поставил 17 ошибок не выдает:

    Но значение =0

    modpoll при этом выдает значение 1160.

    Можно для эксперимента соседние адреса почитать.



  • Соседние адреса читал, результат аналогичный. Если это поможет - могу дать удаленный доступ к устройству и описание регистров от производителя. Отписал в личку.



  • Спасибо! Все заработало, регистры читаются, но остался один вопрос - количество тепловой энергии Q ( а также часть других показателей) храниться в двух регистрах, отдельно целая и дробная части. Как в introhouse объединить эти части в единое число?



  • @gis:

    Спасибо! Все заработало, регистры читаются, но остался один вопрос - количество тепловой энергии Q ( а также часть других показателей) храниться в двух регистрах, отдельно целая и дробная части. Как в introhouse объединить эти части в единое число?

    Самый простой вариант - сделать сценарий. Можно мультисценарий для всех таких случаев

    Вызывается, когда приходит дробное показание. Поскольку адрес у него больше, целая часть должна быть уже считана

    /** 
    * @name Сложить целое и дробное показания
    * @version 4 
    */
    const Q_int = Device("SensorA","Целое показание"); 
    const Q_dec = Device("SensorA","Дробное показание"); 
    const Q = Device("Meter","Счетчик"); 
    
    startOnChange(Q_dec); 
    
    script({
        start() {
           this.assign(Q, 'aval', Q_int.value+Q_dec.value);
        } 
    });
    
    

    Сами дробные значения можно не округлять, количество знаков после запятой выставить у счетчика

    Другой вариант - специализированный плагин для этого типа счетчиков.



  • Будет ли работать плагин Modbus в режиме RTU over TCP с преобразователем интерфейсов RS-485/RS-232 В ETHERNET С2000-ETHERNET фирмы Болид? Очень актуальное оборудование для связи систем охраны.

    Производитель заявляет поддержку UDP, ICMP (ping), ARP (хотя про настройку прибора в ICMP (ping) ни слова). Из руководства следует, что пакеты RS-485/RS-232 передаются в UDP протоколе, в том числе и modbus.
    C-2000.jpg



  • Вопрос к разработке: при подключении к серверу устройств через переходник Wirenboard (протокол rtu over tcp) плагин modbus версии 13 опрашивает регистры циклически. При отключении одного из устройств от линии modbus, либо отсутствии ответа по одному из регистров плагин встает и пишет разрыв соединения. Как обойти остановку плагина и сделать циклический опрос последующих устройств и их регистров с простым выводом в лог ошибки без остановки плагина? Какая команда в agent.js отвечает за переход в следующему каналу по списку?



  • @Viktor

    Можно сделать так: в функции this.modbusReadCommand стр 160 добавить после обработки ошибки продолжение опроса that.sendNext();

    this.modbusReadCommand(fcr, address, length)
          .then(res => {
            // Получили ответ - разбираем и передаем на сервер
            this.plugin.sendDataToServer(protocol.getDataFromResponse(res.buffer, ref));
    
            that.plugin.log(res.buffer, 2); // Это сырой буфер
    
            return sleep(this.plugin.params.polldelay || 1); // Интервал между запросами
          })
          .then(() => {
            that.sendNext();
          })
          .catch(e => {
            that.checkError(e);
            that.sendNext(); // ДОБАВИТЬ ЭТУ СТРОКУ
          });
    

    в функции checkError стр 269 закомментировать выход плагина

    checkError(e) {
        if (e.errno && networkErrors.includes(e.errno)) {
          this.plugin.log('Network ERROR: ' + e.errno, 0);
        } else {
          this.plugin.log('ERROR: ' + util.inspect(e), 0);
        }
        // TODO - проверить ошибку и не всегда выходить
        // this.stop();  ЭТО ЗАКОММЕНТИРОВАТЬ
        // process.exit(1);  ЭТО ЗАКОММЕНТИРОВАТЬ
      },
    


  • @intrapro Да, мы тоже так думали. Однако в таком виде он начинает выдавать бесконечную ошибку (на картинке). При чем нет даже паузЦикл.jpg



  • @Viktor
    Похоже при ошибке соединение закрывается
    Можно тогда при ошибке со своей стороны закрывать и заново делать connect. Попробуйте так - стр 151:

    read({ unitid, fcr, address, length, ref }) {
        let that = this;
    
        this.client.setID(unitid);
        this.plugin.log(
          'READ unitid=' + unitid + ' FC=' + fcr + ' address=' + this.showAddress(address), 1
        );
    
         this.modbusReadCommand(fcr, address, length)
         .then(res => {
           this.plugin.sendDataToServer(protocol.getDataFromResponse(res.buffer, ref));
           that.plugin.log(res.buffer, 2); 
           return sleep(this.plugin.params.polldelay || 1); 
         })
         .catch(e => {
           that.checkError(e);
           that.client.close();  // Закрыть 
           return sleep(that.plugin.params.polldelay || 1); // сделать задержку. Ее можно увеличить
         })
         .then(() => {
           if (!that.client.isOpen())  return that.connect();
         })
         .then(() => {
            that.sendNext();
         })
        .catch(e => {
              that.plugin.log(' REconnection error:' + JSON.stringify(e), 0);  
              that.stop();
              process.exit(1);
        }); 
      },
    

Log in to reply