Как уменьшить количество публикуемых топиков системными устройствами контроллера?

Добрый день.

выделенные топики публикуют сообщения как не в себя, причем значения, которые или вообще не меняются, или меняются очень нечасто

картинка

как заставить их отправлять только изменения или изменения с дельтой, и/или с заданной периодичностью?

Спасибо

Здравствуйте! Сегодня выходной день, поэтому сотрудники техподдержки ответят вам в рабочий день.
Пока что я, автоматический помощник, проанализировал ваш вопрос и постарался найти решение:

Судя по скриншоту, речь о системных топиках контроллера (например, hwmon/power_status/working on battery, battery/controls/Percentage, Voltage и т.п.), которые публикуются очень часто и «забивают» MQTT.

1. Общий принцип: публикация только при изменении

У стандартных системных драйверов Wiren Board (температура, питание, батарея и т.п.) обычно уже используется публикация «по изменению» плюс периодическая републикация с достаточно редким интервалом[1]. Сильно «дребезжать» они не должны, если данные реально не меняются.

Но есть нюанс:

  • некоторые параметры (например, состояния питания, батареи) опрашиваются с небольшим периодом (1–5 с) и публикуются каждый раз, даже при малой дельте;
  • для системных устройств нет штатного «tolerance»/«deadband» в конфиге, который можно просто подкрутить через UI.

Прямо на уровне уже опубликованных топиков сделать фильтр «отправлять только при изменении» нельзя — нужен либо:

  1. фильтрующий MQTT‑посредник, либо
  2. своя «виртуальная» прослойка в wb-rules.

2. Практическое решение через wb-rules

Идея:

  • не подписывать внешние системы на «сырой» топик контроллера,
  • а создать свои виртуальные контролы, куда правило будет пересылать значения только при изменении выше порога и/или с редкой периодичностью.

Пример скрипта wb-rules (для процента батареи; по аналогии для тока, напряжения и т.д.):

var lastBattery = null;
var lastSent = 0;
var MIN_DELTA = 1.0;      // минимальная дельта, %, чтобы послать обновление
var MIN_PERIOD = 300000;  // минимальный период, мс (здесь 5 минут)

defineVirtualDevice("filtered_battery", {
  title: "Filtered battery",
  cells: {
    Percentage: {
      type: "value",
      units: "%",
      initial: 0
    }
  }
});

defineRule("filter_battery_percentage", {
  whenChanged: "battery/controls/Percentage",
  then: function (newValue, devName, cellName) {
    var now = Date.now();
    var v = parseFloat(newValue);
    if (isNaN(v)) return;

    if (lastBattery === null) {
      lastBattery = v;
      lastSent = now;
      dev["filtered_battery"]["Percentage"] = v;
      return;
    }

    var delta = Math.abs(v - lastBattery);

    // Условие отправки: изменилась больше, чем на MIN_DELTA,
    // ИЛИ прошло больше MIN_PERIOD с прошлой отправки
    if (delta >= MIN_DELTA || (now - lastSent) >= MIN_PERIOD) {
      dev["filtered_battery"]["Percentage"] = v;
      lastBattery = v;
      lastSent = now;
    }
  }
});

Подписывать внешние системы (Home Assistant, Node-RED и т.д.) уже на топик:

/devices/filtered_battery/controls/Percentage

Аналогично можно сделать скрипты с разными MIN_DELTA и MIN_PERIOD для Current, Voltage, Charging, либо собрать всё в одно правило с несколькими переменными состояния.

3. Что ещё можно сделать на уровне брокера/клиента

Если проблема именно в сети/клиенте, а не в логике:

  • В некоторых MQTT‑клиентах есть опция «process only changed values» – можно реализовать аналогичный фильтр уже на стороне приёмника.
  • Если вы используете внешний брокер вместо встроенного Mosquitto, у части брокеров/плагинов есть поддержка «suppression of unchanged messages» или агрегации сообщений.

4. Имеет ли смысл «прикручивать» это к системным устройствам напрямую

На текущий момент в документации Wiren Board не описано штатной настройки порога изменения/частоты публикации именно для системных датчиков батареи и питания через UI или конфиги драйвера[1:1]. Поэтому рекомендованный путь — именно «виртуальное устройство + правило», как выше.

Если напишете:

  • модель контроллера (WB6/WB7/WB8),
  • версии wb-mqtt-confed, wb-rules и прошивки,

инженеры в будни смогут дополнительно подсказать, нет ли в вашей версии уже каких‑то скрытых опций по системным устройствам.


Примечание: Я — искусственный интеллект, а не человек. В моих ответах могут быть неточности.


  1. Общая логика публикации и виртуальных устройств описана в документации Wiren Board по MQTT и wb-rules: Движок правил wb-rules — Wiren Board ↩︎ ↩︎

Добрый день.

Раз в секунду:

Jan 26 06:25:53 /devices/power_status/controls/working on battery 0
Jan 26 06:25:54 /devices/power_status/controls/working on battery 0
Jan 26 06:25:55 /devices/power_status/controls/working on battery 0
Jan 26 06:25:56 /devices/power_status/controls/working on battery 0
Jan 26 06:25:57 /devices/power_status/controls/working on battery 0
Jan 26 06:25:58 /devices/power_status/controls/working on battery 0
Jan 26 06:25:59 /devices/power_status/controls/working on battery 0
Jan 26 06:26:00 /devices/power_status/controls/working on battery 0

Публикуются скриптом, да. А чем эта публикация мешает?

увеличивает нагрузку и уменьшает заявленное ограничение в 100 топиков в секунду.

патаюсь хоть как-то снизить нагрузку на cpu, устройств очень много, соответствеено и публикаций тоже

Зачем раз в секунду отправлять неизменившееся значение?

Вот не совсем понятно - что за ограничение в сотню топиков?

А чем нагружен?

Обычно это не создает нагрузки, совсем.
Но - можете, конечно, отключить публикацию. Или уменьшить частоту.

Вот не совсем понятно - что за ограничение в сотню топиков?

тут

я так понимаю, это написали по итогу вот этого топика и в связи с жалобами на зависание wb-rules с ошибкой “MQTT token wait timeout”. Я с этой ошибкой столкнулся на двух контроллерах с большим количеством устройств.
Похоже ошибку пофиксили, но исправление пока есть только в testing. Из-за этой проблемы пришлось на testing ветку переползать. Но все равно периодически перестают работать сценарии.
возможно я где-то сильно накосячил в коде js, он для меня в новинку. буду признателен, если поможете с этим разобраться

А чем нагружен?

на одном контроллере 25шт MET3E, подключенных через 6шт WB-MGE + несколько реле + несколько блоков протечки
на другом порядка 180 устройств - реле, диммера, mcm8, датчики температуры, подключенных через n-ое количество WB-MGE

Но - можете, конечно, отключить публикацию. Или уменьшить частоту.

к сожалению, именно для этих параметров (в 1 посте) не нашел как. возможно где-то лежит информация на видном месте, но от меня ускользает )

Конечно, попробую. Давайте способ воспроизвести.

На контроллере /usr/share/wb-rules-system/rules/power_status.js

Давайте способ воспроизвести.

к сожалению, пока не получается достоверно воспроизвести/отловить ((

На контроллере /usr/share/wb-rules-system/rules/power_status.js

охх, я тут наломаю дров, не буду ничего менять

а можно офтоп?
вот в этом куске кода функция, которая используется в whenChanged, она же boolean возвращает. По идее тут просто when тогда должен быть. Как этот механизм тут работает? Для whenChanged ведь нужно название топика, т.е по сути или string, или array of string

        defineRule('_system_wb5_track_power_status', {
          whenChanged: [
            function () {
              // get power status
              // we don't expect the voltage to go up and down
              //  around the threshold, so no hysteresis here
              return (
                dev['wb-gpio/BATTERY_PRESENT'] &&
                !dev['wb-gpio/BATTERY_CHARGING'] &&
                dev['wb-adc/Vin'] < 5.0
              );
            },
          ],
          then: function (newValue, devName, cellName) {
            dev['power_status/working on battery'] = newValue;
          },
        });

Можно и (любой) объект использовать, в общем.

что значение dev (или их массива) что функции вычисляется при просмотре правил.
И да, тут When было б уместнее - но так как правило системное то в случае изменения обработки wheenChanged - будет переписано.

1 лайк