Не получается подружить modbus_client (Debian) и WB-MGE v2

Добрый день. Имеется порядка 20 WB-MGE v2 к которым подключены релейные модули. Чтобы не настраивать каждый контроллер отдельно, возникло желение подключить к всему этому удовольствию Ansible. Проблема возникла когда попытался на Debian подключиться к контроллеру удаленно, используя modbus_client.

Подскажите, какую команду нужно для это использовать?

Добрый день. Насколько понимаю вам требуется Утилита «modbus_client» — Wiren Board

Виноват, не изложил как следует.

Стенд:

  • локальная сеть в ней находятся WB-MGE v2 (c подключенными к ней релейными модулями).
  • виртуальная машина в этой же сети, на которой стоит ОС Debian вместе с пакетом modbus_client.

Далее пытаюсь считать значения, чтобы получить хотябы что-то, для начала.

$ modbus_client --debug -mtcp -t0x03 -r0 -p502 10.2.1.94 -c3

Connecting to 10.2.1.94:502
[00][01][00][00][00][06][01][03][00][00][00][03]
Waiting for a confirmation...
ERROR Connection timed out: select
ERROR occured!

Если подключаться к котроллеру Wirenboard 6:

$ modbus_client --debug -mtcp -t0x03 -r128 -p502 10.2.1.80 -c3

Connecting to 10.2.1.80:502
[00][01][00][00][00][06][01][03][00][80][00][03]
Waiting for a confirmation...
<00><01><00><00><00><03><01><83><02>
ERROR Illegal data address
ERROR occured!

Если подлючаться, используя утилиту Modbus poll всё работает. Но там используется режим RTU over TCP как я понял.

Теперь вопрос, можно ли, и каким образом подключиться с помощью приложения modbus_client к WB-MGE v2 (modbus gateway) и через него настроить релейный модуль WB-MR6C v2 (slave id 119)?

Дополнительный тест: подключился к Wirenboard 6 по SSH, ввел стандартную команду:

$ modbus_client --debug -mtcp -t0x03 -r0 -p502 127.0.0.1 -c3

0x007f Connecting to 0.0.0.0
[00][01][00][00][00][06][01][03][00][00][00][03]
Waiting for a confirmation...
<00><01><00><00><00><03><01><83><02>
ERROR Illegal data address
ERROR occured!

Приветствую!
Это можно сделать через RTU over TCP, но не через MODBUS TCP.

Вам понадобится поднять виртуальный порт через socat:
https://wirenboard.com/wiki/WB_FAQ/modbus-modules-behind-gateway

Коллега имеет в виду - что если у вас шлюзы настроенs на Modbus over TCP то сначала надо отобразить сетевой порт в локальный.

Спасибо за ответы, я вас понял. Через несколько дней отпишусь о результатах.

Изучаю вашу систему, 2 блока (из 20) выдают следующую ошибку:

$ modbus_client --debug -mrtu -b9600 -pnone -s2 /dev/ttyRS485-12 -a79 -t0x05 -r0 0

Data to write: 0x00 0x00 0x00 0x00 0x00 0x00
Opening /dev/ttyRS485-12 at 9600 bauds (N, 8, 2)
[4F][0F][00][00][00][06][01][00][1A][EA]
Waiting for a confirmation...
<77><03><02><00><77><31><A9>
Request for slave 119 ignored (not 79)
ERROR occured!

Зашел в GW настройки понажимал один модуль починился.

Обратите внимание, пишете в устройство с адресом 4F , причем команда 0F А ответ получаете от 77, приччем на чтение холдинга (03) Такое впечателение что устройство опрашивает в этот момент кто-то еще.

Спасибо за ответы, ещё раз. Разобрался в теме, на сколько потребовалось.
Внедрил Infrastructure as Code для настройки релейных модулей. Ниже предлагаю вариант решения, может кому-нибудь поможет.


README
Структура реализованного решения.


В нашем случае потребовалось подкрутить настройки WB-MGE v2:



Далее, используя ссылки выше, собрал контейнер, заслал в него настройки:

$ docker run -it
-p 22:22
–env MODBUS_DEVICES=“:<Условный ID который будет использоваться в Ansible>”
–env MODBUS_EMAIL_ADMIN="admin@example.com"
–env MODBUS_CREDENTIAL=“login:ssh-rsa some_public_key”
h963z57/modbus_client-docker:main

После чего используя login:ssh_private_key с помощью ansible задаю настройки, ниже привожу пример простого скрипта, но нужно быть осторожным если релейных модулей много, при быстром включении может выбить свет - проверено.


- name: DANGE MASTER
  hosts: MODBUS_CLIENT
  become: true

  vars:
    OFFICE:
    # FLOOR_UNDEGROUND
      - {id: 12, slave: 119}
      - {id: 12, slave: 79}
      
    # FLOOR_ONE
      - {id: 1, slave: 34}
      - {id: 2, slave: 149}
      - {id: 3, slave: 169}
      - {id: 4, slave: 113}
      - {id: 4, slave: 59}
      - {id: 5, slave: 84}
      - {id: 5, slave: 21}

     # FLOOR_TWO
      - {id: 6,  slave: 168}
      - {id: 6,  slave: 74}
      - {id: 7,  slave: 153}
      - {id: 8,  slave: 62}
      - {id: 9,  slave: 116}
      - {id: 10, slave: 119}
      - {id: 10, slave: 90}
      - {id: 11, slave: 86}
      - {id: 11, slave: 107}
      - {id: 11, slave: 80}
      - {id: 11, slave: 90}
      - {id: 13, slave: 154}
    
# ================= Safe zone ======================
    COMMON_CONFIGURATION: false
    DEFAULT_VALUE:
      ACTION_AFTER_POWER_REBOOT: 1 #Last state 0 - offed


# ================= Danger zone ====================
    DANGEROUS_IS_MY_SECOND_NAME: false
    POWER_STATUS               : false

  tasks:

  - name: Common settings
    block:
    - name : Change defult state aster power off/on
      shell: bash -c "modbus_client --debug -mrtu -b9600 -pnone -s2 /dev/ttyRS485-{{ item.id }} -a{{ item.slave }} -t0x06 -r6 {{ DEFAULT_VALUE.ACTION_AFTER_POWER_REBOOT }}" >> /var/log/modbus/modbus_client.log
      with_items: "{{ OFFICE }}"

    - name : Change default type button
      shell: bash -c "modbus_client --debug -mrtu -b9600 -pnone -s2 /dev/ttyRS485-{{ item.id }} -a{{ item.slave }} -t0x10 -r9 -c 6 0 0 0 0 0 0" >> /var/log/modbus/modbus_client.log
      with_items: "{{ OFFICE }}"

    when : COMMON_CONFIGURATION is true

# =============== REALLY DENGEROUS ==================

  - name : Danger zone
    block:

    - name    : Set POWER_STATUS as 1
      set_fact:
        POWER_VALUE: 1
      when    : POWER_STATUS is true

    - name    : Set POWER_STATUS as 0
      set_fact:
        POWER_VALUE: 0
      when    : POWER_STATUS is false

    - name    : Set POWER_DELAY as 5
      set_fact:
        POWER_DELAY: 5
      when    : POWER_STATUS is true

    - name    : Set POWER_STATUS as 0
      set_fact:
        POWER_DELAY: 0
      when    : POWER_STATUS is false


    - name        : Poweroff 1 output
      shell       : bash -c "modbus_client --debug -mrtu -b9600 -pnone -s2 /dev/ttyRS485-{{ item.id }} -a{{ item.slave }} -t0x0F -r0 {{ POWER_VALUE }}" >> /var/log/modbus/modbus_client.log
      with_items  : "{{ OFFICE }}"
      loop_control:
         pause    : "{{ POWER_DELAY }}"
     
    - name     : pause for prevent power destroy
      pause    :
        seconds: 10
      when     : POWER_STATUS is true

    - name        : Poweroff 2 output
      shell       : bash -c "modbus_client --debug -mrtu -b9600 -pnone -s2 /dev/ttyRS485-{{ item.id }} -a{{ item.slave }} -t0x0F -r1 {{ POWER_VALUE }}" >> /var/log/modbus/modbus_client.log
      with_items  : "{{ OFFICE }}"
      loop_control:
         pause    : "{{ POWER_DELAY }}"
      
    - name     : pause for prevent power destroy
      pause    :
        seconds: 10
      when     :  POWER_STATUS is true
    
    - name        : Poweroff 3 output
      shell       : bash -c "modbus_client --debug -mrtu -b9600 -pnone -s2 /dev/ttyRS485-{{ item.id }} -a{{ item.slave }} -t0x0F -r2 {{ POWER_VALUE }}" >> /var/log/modbus/modbus_client.log
      with_items  : "{{ OFFICE }}"
      loop_control:
         pause    : "{{ POWER_DELAY }}"
      
    - name     : pause for prevent power destroy
      pause    :
        seconds: 10
      when     :  POWER_STATUS is true

    - name        : Poweroff 4 output
      shell       : bash -c "modbus_client --debug -mrtu -b9600 -pnone -s2 /dev/ttyRS485-{{ item.id }} -a{{ item.slave }} -t0x0F -r3 {{ POWER_VALUE }}" >> /var/log/modbus/modbus_client.log
      with_items  : "{{ OFFICE }}"
      loop_control:
         pause    : "{{ POWER_DELAY }}"

    - name     : pause for prevent power destroy
      pause    :
        seconds: 10
      when     :  POWER_STATUS is true

    - name        : Poweroff 5 output
      shell       : bash -c "modbus_client --debug -mrtu -b9600 -pnone -s2 /dev/ttyRS485-{{ item.id }} -a{{ item.slave }} -t0x0F -r4 {{ POWER_VALUE }}" >> /var/log/modbus/modbus_client.log
      with_items  : "{{ OFFICE }}"
      loop_control:
         pause    : "{{ POWER_DELAY }}"

    - name     : pause for prevent power destroy
      pause    :
        seconds: 10
      when     :  POWER_STATUS is true

    - name        : Poweroff 6 output
      shell       : bash -c "modbus_client --debug -mrtu -b9600 -pnone -s2 /dev/ttyRS485-{{ item.id }} -a{{ item.slave }} -t0x0F -r5 {{ POWER_VALUE }}" >> /var/log/modbus/modbus_client.log
      with_items  : "{{ OFFICE }}"
      loop_control:
         pause    : "{{ POWER_DELAY }}"

    when: DANGEROUS_IS_MY_SECOND_NAME is true

Кому интересно, ссылка на репозиторий.
Чуть подробнее о самом контейнере.

1 лайк

В восторге! Да, действительно большая работа.
То есть практически реализована часть функционала GitHub - wirenboard/wb-mqtt-serial: Wiren Board MQTT serial protocol driver
А не проще было поставить ту же Установка Rapid SCADA на контроллер Wiren Board — Wiren Board

Это не основная деятельность, основная деятельность DevOps. Нужны понятные и привычные инструменты. Также привык работать без GUI т.к. они сильно ограничивают возможнотсти, и конфигурации, как правило, нельзя хранить на GitHub (т.е. чтобы в любой момент по коммитам отследить как менялась структура).

Например, если завтра поставят ещё 10 единици оборудования, я возьму внесу 10 строк кода, запущу его на исполнение и они интегрируются в общую систему (5 мин времени, если не торопясь).
Если нужен будет мониторинг Grafana+prometheus (если мониторить по MQTT то ещё этот модуль - проверено) закроет вопрос, пока не знаю буду ли делать.
С помощью этих инструментов, например, можно в облаке поднять ВМ, с помощью VPN подключиться к объектам “рулить” и мониторить из одной точки. Без привязок к ПО.

WB-MGE v2 вроде не умеет в MQTT. А если данное ПО умеет работать с MGE то для меня это все равно сложно.

Протоколы IP, TCP, UDP, DHCP, DNS, HTTP, ARP, ICMP, Web socket

Никто же не запрещает комбинировать.

Резюмируя: Для меня было проще написать 1 раз масштабируемый код и по мере необходимотси добавлять 1-2 , коротенькие строчки. + если честно, я пока-что с опаской смотрю на отечественный софт. Не хотелось бы чтобы production “прилёг”. Есть несколько коммерческих проектов, отечественных, которые пришлось дебажить прежде чем запустить хотябы в тестовой среде.

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

Полностю согласен!

Ну, код у нас открыт, весь. Достадные баги бывают, да но ловятся (как правило) на тестинге.

Респект! Как админивший в свое время несколько кластеров 1С и Аксапты заявляю: импортный софт ничем не лучше. :wink:

Спорить не стану. Т.к. завтра могу изменить мнение и сделать по-вашему. С другой стороны, ваша продукция предоставляет возможность, не используя проприетарный софт, напрямую управлять устройствами как душе угодно, как мне кажется, упустить эту возможность - не совсем верно. Идей много, оборудование позволяет.
Если отойти от темы, продать навыки работы с международными инструментами проще.

За информацию спасибо!

1 лайк

Эта тема была автоматически закрыта через 7 дней после последнего ответа. В ней больше нельзя отвечать.