Ad Widget

Collapse

Модуль MODBUS и NaN

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • sysand
    Junior Member
    • May 2021
    • 13

    #1

    Модуль MODBUS и NaN

    Всем привет!

    Вопрос больше к разработчикам, т.к. сама суть проблемы ясна.

    Собственно по теме:
    Стоит Centos-8 и Zabbix-5.2.6.
    Имеется парк приборов ЭльметроВиЭР-104К (более 400 шт) с MODBUS/TCP на борту, к приборам подключены датчики,
    при обрыве или неисправности датчика в регистр данных записывается float значение NaN.
    Приборы нежненькие, очень не любят когда их часто спрашивают по TCP, ну раз в пару-тройку минут один запрос терпят,
    т.е. надо выдернуть диапазон из примерно 30 регистров типа float за один запрос и потом его разобрать по переменным с одного прибора,
    так вот создаем Data Item -> Type - Zabbix, Key -> modbus.get[tcp://IP_HERE,1,4,0,16,float,mbe] , и создаем подчиненные Data Items с предобработкой JSONPath -> $.[номер регистра],
    если в регистрах нет NaN, то всё прекрасно работает, а вот если появляется NaN, тогда вся схема ломается,
    т.е. требуется чтобы родительский Data Item возвращал JSON что-то типа [12.11,11.234,NaN,123,456], а он просто возвращает ошибку: Unable to create json: json: unsupported value: NaN.
    Прикрепляю картинки, на которых видно такое поведение.
    Еще глянул исходники модуля MODBUS и по ним видно, что это проблема находится в функции pack2Json (файл .../zabbix-5.2.6/src/go/plugins/modbus/endianness.go), там используется так называемый сериализатор jd, jerr := json.Marshal(arr)
    и как пишут в ИНЕТ вот он-то и неправильно понимает NaN, к сожалению на этом моя программистская компетенция заканчивается и я не знаю как это поправить.

    Кто, что подскажет?

    Заранее благодарен.

    Click image for larger version

Name:	Get-Registers-1-6.png
Views:	398
Size:	69.8 KB
ID:	425085
    Здесь читаем 6 float регистров
    Click image for larger version

Name:	One-Register-With-NaN.png
Views:	395
Size:	67.4 KB
ID:	425088
    Здесь читаем регистр с NaN (седьмой)
    Click image for larger version

Name:	Get-Registers-1-7-with-NaN.png
Views:	422
Size:	67.8 KB
ID:	425089
    Здесь читаем 7 float регистров
    седьмой с NaN



    Attached Files
  • AlexL
    Zabbix Certified Specialist
    Zabbix Certified Specialist
    • Aug 2019
    • 55

    #2
    Добрый День,
    Я завел задачу https://support.zabbix.com/browse/ZBX-19441.

    Comment

    • sysand
      Junior Member
      • May 2021
      • 13

      #3
      Originally posted by AlexL
      Добрый День,
      Я завел задачу https://support.zabbix.com/browse/ZBX-19441.
      Всем, привет!

      В общем я тут сделал маленький костылик, который решает одну маленькую проблему с NaN и сразу же вскрывает целый пласт проблем не только самого Zabbix, но и JSON и MySQL.
      Ноги растут скорее всего с MySQL, он не умеет хранить нечисловые float значения типа NaN, -Inf, +Inf, хотя Postgres, Oracle, SQLite умеют.
      Из-за этого Zabbix тоже неадекватно реагирует на такие значения сенсоров, при получении такого значения (NaN,-+Inf) элемент данных деактивируется и нет возможности на это повлиять,
      ну например просто откинуть нечисловое значение и продолжать собирать данные и строить графики.
      Варианты обхода есть , но на мой взгляд они кривоватые, можно создать два зависимых элемента данных, ловить там
      нечисловые значения float, в первом элементе заменять на какую-то константу в зависимости от условий, а во втором числовые значения занулять, а нечисловые мапить тоже каким-нибудь способом и уже оттуда строить графики и корреляции.
      И еще оказывается в соответствии с RFC7159 JSON тоже не умеет сериализовать/десериализовать нечисловые значения float, цитата
      Numeric values that cannot be represented in the grammar below (such as Infinity and NaN) are not permitted.
      Подведу черту, в модуле MODBUS для значений float и double, надо сделать опции замены нечисловых значений на константы, и причем различные для NaN, +Inf,-Inf

      Всем удачи!

      Так diff не заливается, прицеплю текстом.
      Code:
      *** endianness.go.orig 2021-03-29 16:21:28.000000000 +0700
      --- endianness.go 2021-05-25 19:59:54.870535025 +0700
      ***************
      *** 24,29 ****
      --- 24,30 ----
      "encoding/binary"
      "encoding/json"
      "fmt"
      + "strings"
      )
      
      // main data transformation
      ***************
      *** 92,97 ****
      --- 93,102 ----
      if p.RetType == Uint8 {
      arr = getArr16(p.RetType, p.RetCount, arr.([]byte))
      }
      +
      + if p.RetType == Float || p.RetType == Double {
      + return strings.ReplaceAll(strings.ReplaceAll(fmt.Sprintf( "%v", arr), " ", ","), "NaN", "\"NaN\""), nil
      + }
      
      jd, jerr := json.Marshal(arr)
      if jerr != nil {

      Comment

      • shkiper
        Senior Member
        • Mar 2016
        • 123

        #4
        у меня похожая ситуация, не знаю на сколько
        работаю с mqtt.get

        тоже счетчик - возвращает общее количество потребленного с момента включения, алгоритм получения данных такой:
        1-й итем - mqtt.get[{$IP},{$MQTT_TOPIC}]
        2-й итем - зависимый от первого, предобработка JSONPath
        3-й итем - last от 2-го (уже точно не помню зачем, это попытка обойти особенности jsonpath, может первая попытка решить проблему)
        4-й итем - delta за 5 минут от 3-го, и вот здесь иногда приходит ошибка (когда счетчик долго простаивает)
        и тогда все 5 мин выдают ошибку
        по 4-му итему считаются данные за час, смену , сутки (дельта по 4-му итему), и если расчет попадает на время когда есть эта ошибка (оно может быть несколько минут), то и за час и за сутки тоже пустота, причем я это заметил через несколько дней, потому что после запуска, система нормально работала день-два
        ошибку сейчас точно не приведу, потому что проблему давно решил
        поставил проверку на соотв. регулярке: ^[\s\S]{1,10} (т.е. проверка - возвращает строку или нет)
        если не соответствует то задать 0, проблема ушла - в периодах простоя начал проставляться ноль

        Comment

        Working...