Движок wb-rules: не создавать командные MQTT-подписки для read-only контролов

Коллеги!

Автор запроса ChatGPT 6 Astra Work Mode :slight_smile: но я присоединяюсь и полностью поддерживаю. Запрос возник из оптимизации работы большого проекта на wb-rules.


Просим уменьшить накладные расходы MQTT в штатном wbgo.so: не создавать командные подписки для виртуальных контролов, объявленных read-only.

Наблюдение: на выпущенном wb-rules 2.40.0-wb100 под QEMU двадцать виртуальных Timer-устройств с тремя read-only контролами каждое создают 60 командных подписок. Они сохраняются в покое, после запуска/отмены таймеров и после настоящей перезагрузки скрипта с повторным созданием объектов. Пример фильтра: /devices/timer_1_presence/controls/state/on.

По Wiren Board MQTT Conventions у read-only контрола нет командного топика /on:

При этом текущее значение и метаданные нужны интерфейсу, а правила должны по-прежнему изменять контрол локально. Лишние фильтры увеличивают работу сопоставления входящих сообщений даже при неподвижных таймерах.

Предлагаем:

  • При регистрации виртуального контрола подписываться на командный /on только для writable-контролов.
  • Сохранить публикацию значений/метаданных, локальные присваивания через dev и setValue, уведомления об изменениях.
  • Согласованно добавлять/удалять командную подписку при setReadonly, удалении, повторном создании контрола и перезагрузке скрипта.

Ожидаемый результат на этом стенде: 60 → 0 лишних командных подписок при сохранении всех 60 контролов, их значений и локальной работы таймеров. При удалении M подписок общий список уменьшается с R до R−M; ускорение процесса и UI следует измерить отдельно на одинаковом входящем потоке.

Проверить writable-команды, локальные обновления read-only контролов, оба направления изменения readonly и повторную загрузку без утечек подписок.

Это самостоятельное улучшение расхода ресурсов. Просим реализовать изменение в официальной сборке.

Добрый день.

Актуальная версия 3.0.0 и переход на нее будет в скором времени.

Вот тут не совсем понимаю про какие подписки вопрос. То есть - что сейчас работает не так как описано в документации?

Добрый день! Спасибо за уточнение по версии 3.0.0. Наши измерения относятся к wb-rules 2.40.0-wb100; на версии 3.0.0 мы их пока не повторяли.

Уточню предмет обращения. Это предложение уменьшить расход ресурсов при большом количестве виртуальных контролов. Мы не утверждаем, что контролы только для чтения неправильно отображаются в веб-интерфейсе или что нарушено документированное поведение правил.

Покажу смысл предложения на минимальном примере, без нашей прикладной логики. В файле /etc/wb-rules/readonly_example.js можно объявить одно виртуальное устройство с одним контролом:

defineVirtualDevice("readonly_example", {
    title: "Пример контрола только для чтения",
    cells: {
        state: {
            title: "Состояние",
            type: "text",
            value: "Ожидание",
            readonly: true
        }
    }
});

Здесь readonly: true означает, что контрол предназначен для чтения. Пользователь видит его состояние в веб-интерфейсе, а значение задаёт сам скрипт. Например, скрипт может выполнить:

dev["readonly_example/state"] = "Работа";

Движок правил изменит значение виртуального контрола и опубликует его в топике:

/devices/readonly_example/controls/state

Веб-интерфейс получает это значение и отображает «Работа». Публикация значения и метаданных контрола нужна и должна сохраниться.

Отдельный топик с окончанием /on служит для приёма команды на изменение значения:

/devices/readonly_example/controls/state/on

Вопрос именно о подписке самого wb-rules на такой топик. В нашей проверке версии 2.40.0-wb100 для контролов с признаком «только для чтения» были зарегистрированы такие подписки, хотя внешнее управление значением для них не требуется. Речь о списке подписок клиента, а не о наличии сообщений в этих топиках. Приведённый выше код поясняет назначение топиков; отдельное измерение именно этого упрощённого примера пока не проводилось.

В соглашениях Wiren Board о топиках MQTT признак readonly описан через отсутствие у контрола топика /on. Это объясняет, почему мы предлагаем исключить соответствующую подписку. При этом документация не устанавливает требования к внутреннему списку подписок клиента: само наличие такой подписки мы не выдаём за доказанное нарушение документации.

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

Для понимания масштаба: в отдельной проверке 20 виртуальных устройств с тремя контролами только для чтения каждое давали 60 подписок на топики с окончанием /on. На физическом контроллере в исследованной конфигурации было зарегистрировано 2 487 подписок; в двух профилях на распределение и сопоставление входящих сообщений приходилось 51,6 % и 54,1 % процессорного времени, учтённого этими профилями. Это характеристика общего механизма обработки сообщений, а не измеренный эффект именно этих 60 подписок.

Предлагаем при создании контрола только для чтения не добавлять подписку на его топик /on. При этом сохранить публикацию значений и метаданных, изменение значения из правил и срабатывание правил при его изменении. Если разрешить запись, соответствующая подписка должна появиться; при обратном переходе — удалиться. Удаление устройства и повторная загрузка скрипта также должны корректно обновлять список подписок.

Проверяемый результат для случая с 60 контролами: все 60 контролов остаются доступными для чтения и изменения из правил, а число их подписок на команды уменьшается с 60 до 0. Изменение загрузки процессора и задержки реакции необходимо измерять отдельно.

Если в версии 3.0.0 создание этих подписок уже изменено, подскажите, пожалуйста: тогда нужно проверить именно эту версию.

Нет, посмотрел - механизм остался тот же.
Запишу для разработчиков пожелание.

Андрей, спасибо за проверку версии 3.0.0 и за готовность передать пожелание разработчикам!