Подключение Modbus TCP устройств через IoT Edge к IoT Hub. Урок 5.

В предыдущей статье подробно изложено подключение Modbus RTU устройства к конвертеру Modbus RTU <-> TCP.  Подключим конвертер Modbus TCP и, соответственно, устройство Modbus RTU к облаку IoT Hub.

Для начала воспользуемся статьей на сайте Microsoft по подключению modbus устройств. Поскольку объяснение в статье очень подробное, нет смысла дублировать.  Для моего оборудования настройки будут такими:

  • IP:  192.168.26.110
  • Address: 30001 + 1 (смещение) = 30002. Адресация Input Register начинается с 30001 адреса + смещение.
  • Port: 8899 — в документации Microsoft и на сайте github с исходниками модуля modbus нет упоминания о том, как указать порт и не сказано какой порт является дефолтным. Посмотрим как отреагирует модуль, если опустить этот параметр.
  • HwId — поправил название устройства, MAC адрес оставил из примера, не критично.
  • DisplayName — поправил на «Temp».

Результирующий JSON для вставки в properties.

 "properties.desired": {
      "PublishInterval": "2000",
      "SlaveConfigs": {
        "TermoSensor": {
          "SlaveConnection": "192.168.26.110",
          "HwId": "TermoSensor-0a:01:01:01:01:01",
          "Operations": {
            "Op01": {
              "PollingInterval": "1000",
              "UnitId": "1",
              "StartAddress": "30002",
              "Count": "1",
              "DisplayName": "Temp"
            }
        }
      }
    }
  }
}

После развертывания модуля получаем следующиий набор ошибок:

PS C:\WINDOWS\system32> iotedge logs modbus -f
IoT Hub module client initialized.
Desired property change:
{"PublishInterval":"2000","SlaveConfigs":{"TermoSensor":{"SlaveConnection":"192.168.26.110","HwId":"PowerMeter-0a:01:01:01:01:01","Operations":{"Op01":{"PollingInterval":"1000","UnitId":"1","StartAddress":"30002","Count":"1","DisplayName":"Temp"}}}},"$version":1}
Attempt to load configuration: {"PublishInterval":"2000","SlaveConfigs":{"TermoSensor":{"SlaveConnection":"192.168.26.110","HwId":"PowerMeter-0a:01:01:01:01:01","Operations":{"Op01":{"PollingInterval":"1000","UnitId":"1","StartAddress":"30002","Count":"1","DisplayName":"Temp"}}}},"$version":1}
Invalid TcpPort: , set to DefaultTcpPort: 502
Invalid RetryCount: , set to DefaultRetryCount: 10
Invalid RetryInterval: , set to DefaultRetryInterval: 50
Empty CorrelationId: , set to DefaultCorrelationId: DefaultCorrelationId
Connect Slave failed
Connection refused 192.168.26.110:502
Connection lost, reconnecting...

Итак:

  • Порт по умолчанию — 502.
  • Свойство для указания номера порта: TcpPort. О существовании этого параметра почему-то ничего не говорится в документации.
  • Параметры RetryCount и RetryInterval можно не задавать, они есть по умолчанию.

Откорректируем Module Identity Twin. Возможность редактировать Module Identity Twin  появляется только после того как модуль устройство развернуто на IoT Edge устройстве.

Добавляем в Module Identity Twin в desired строчку  «TcpPort»: «8899», сохраняем. В логах видим:

Desired property change:
{"PublishInterval":"2000","SlaveConfigs":{"TermoSensor":{"SlaveConnection":"192.168.26.110","TcpPort":"8899","HwId":"PowerMeter-0a:01:01:01:01:01","Operations":{"Op01":{"PollingInterval":"1000","UnitId":"1","StartAddress":"30002","Count":"1","DisplayName":"Temp"}}}},"$version":2}
Attempt to load configuration: {"PublishInterval":"2000","SlaveConfigs":{"TermoSensor":{"SlaveConnection":"192.168.26.110","TcpPort":"8899","HwId":"PowerMeter-0a:01:01:01:01:01","Operations":{"Op01":{"PollingInterval":"1000","UnitId":"1","StartAddress":"30002","Count":"1","DisplayName":"Temp"}}}},"$version":2}
Invalid RetryCount: , set to DefaultRetryCount: 10
Invalid RetryInterval: , set to DefaultRetryInterval: 50
Empty CorrelationId: , set to DefaultCorrelationId: DefaultCorrelationId
Saving reported properties: {"PublishInterval":2000,"SlaveConfigs":{"TermoSensor":{"Operations":{"Op01":{"PollingInterval":1000,"UnitId":1,"StartAddress":"30002","Count":1,"DisplayName":"Temp","CorrelationId":"DefaultCorrelationId"}},"SlaveConnection":"192.168.26.110","RetryCount":10,"RetryInterval":50,"TcpPort":8899,"HwId":"PowerMeter-0a:01:01:01:01:01","BaudRate":null,"StopBits":null,"DataBits":null,"Parity":null}}}
30002: 261

30002: 261

30002: 261

Соответственно, видим, что модуль корректно отрабатывает смену настроек в desired.  Появился введенный параметр «TcpPort»:»8899″ и он корректно отработал.

Добавим в desired операцию по считыванию поля влажности получаемого с адреса 300001 + 2.

            "Op02": {
              "PollingInterval": "1000",
              "UnitId": "1",
              "StartAddress": "30003",
              "Count": "1",
              "DisplayName": "Humidity"
            }

Финально properties.desired должен выглядеть так:

"properties.desired": {
    "PublishInterval": "2000",
      "SlaveConfigs": {
        "TermoSensor": {
          "SlaveConnection": "192.168.26.110",
          "HwId": "TermoSensor-0a:01:01:01:01:01",
          "TcpPort": "8899",         
          "Operations": {
            "Op01": {
              "PollingInterval": "5000",
              "UnitId": "1",
              "StartAddress": "30002",
              "Count": "1",
              "DisplayName": "Temp"
            },
            "Op02": {
              "PollingInterval": "5000",
              "UnitId": "1",
              "StartAddress": "30003",
              "Count": "1",
              "DisplayName": "Humidity"
           }
        }
     }
   }
}

Модуль получает информацию о смене desired property и выводит новые данные:

Desired property change:
{"PublishInterval":"2000","SlaveConfigs":{"TermoSensor":{"SlaveConnection":"192.168.26.110","HwId":"PowerMeter-0a:01:01:01:01:01","Operations":{"Op01":{"PollingInterval":"1000","UnitId":"1","StartAddress":"30002","Count":"1","DisplayName":"Temp"},"Op02":{"PollingInterval":"1000","UnitId":"1","StartAddress":"30003","Count":"1","DisplayName":"Humidity"}},"TcpPort":"8899"}},"$version":3}
Attempt to load configuration: {"PublishInterval":"2000","SlaveConfigs":{"TermoSensor":{"SlaveConnection":"192.168.26.110","HwId":"PowerMeter-0a:01:01:01:01:01","Operations":{"Op01":{"PollingInterval":"1000","UnitId":"1","StartAddress":"30002","Count":"1","DisplayName":"Temp"},"Op02":{"PollingInterval":"1000","UnitId":"1","StartAddress":"30003","Count":"1","DisplayName":"Humidity"}},"TcpPort":"8899"}},"$version":3}
Invalid RetryCount: , set to DefaultRetryCount: 10
Invalid RetryInterval: , set to DefaultRetryInterval: 50
Empty CorrelationId: , set to DefaultCorrelationId: DefaultCorrelationId
Empty CorrelationId: , set to DefaultCorrelationId: DefaultCorrelationId
Saving reported properties: {"PublishInterval":2000,"SlaveConfigs":{"TermoSensor":{"Operations":{"Op01":{"PollingInterval":1000,"UnitId":1,"StartAddress":"30002","Count":1,"DisplayName":"Temp","CorrelationId":"DefaultCorrelationId"},"Op02":{"PollingInterval":1000,"UnitId":1,"StartAddress":"30003","Count":1,"DisplayName":"Humidity","CorrelationId":"DefaultCorrelationId"}},"SlaveConnection":"192.168.26.110","RetryCount":10,"RetryInterval":50,"TcpPort":8899,"HwId":"PowerMeter-0a:01:01:01:01:01","BaudRate":null,"StopBits":null,"DataBits":null,"Parity":null}}}
30002: 262

30003: 303

30002: 262

30003: 303

После проверки стоит сразу изменить интервал опроса сенсора хотя-бы до 5000 мс, в противном случае за час в облако уйдет 3600 х 2= 7200 сообщений и 8000 сообщений бесплатного аккаунта быстро закончатся.

Не забывайте останавливать работу модуля,
когда отправка данных в IoT Hub не нужна! 

После того как IoT Hub получит 8000 сообщений, Microsoft заблокирует доступ к нему. Нельзя даже зайти на IoT Edge устройства, чтобы исправить настройки. Доступ появится на следующий день.

В исходниках модуля нашел описание параметров:

{
  "PublishInterval": "push interval in millisecond",
  "SlaveConfigs": {
    "Slave01": {
      "SlaveConnection": "ipv4 address or the serial port name to Modbus device",
      "TcpPort": "tcp port of Modbus connection, default is 502",
      "RetryCount": "the max retry attempt when socket receive buffer is empty, default is 10",
      "RetryInterval": "the wait interval in millisecond between each retry, default is 50",
      "HwId": "unique HW Id defined by user",
      "BaudRate": "baud rate of serial communication (Modbus RTU only)",
      "DataBits": "data bits of serial communication (Modbus RTU only)",
      "StopBits": "stop bits of serial communication (Modbus RTU only)",
      "Parity": "parity of serial communication (Modbus RTU only)",
      "FlowControl": "flow control of serial communication (Modbus RTU only)",
      "Operations": {
        "Op01": {
          "PollingInterval": "polling interval in millisecond",
          "UnitId": "unit id of Modbus device",
          "StartAddress": "starting address of read request",
          "Count": "unit count of read request",
          "DisplayName": "alternative name defined by user",
          "CorrelationId": "id used to group output message"
        }
      }
    }
  }
}

Ссылки

Для полноты информации можно почитать.

Spread the love
Запись опубликована в рубрике IT опыт, IT рецепты с метками , . Добавьте в закладки постоянную ссылку.