Skip to content

Latest commit

 

History

History
311 lines (238 loc) · 18.1 KB

README.md

File metadata and controls

311 lines (238 loc) · 18.1 KB

Документация для разработчиков

В данном файле описано все что нужно знать для разработки новых сценариев для WB с нуля.

Информация по другим аспектам работы со сценариями собрана тут:

  1. Пример добавления сценария
  2. Описание используемого стиля и окружения Обязательно использовать форматтер prettier, чтобы следить за форматом кода По желанию можно использовать линтер ESLint, чтобы подсвечивать ошибки
  3. Варианты установки и сборки сценариев

Общее о сценариях

Сценарии являются методом упрощения конфигурирования контроллера WB. Они позволяют настраивать работу частых юзкейсов через графический интерфейс без необходимости изучения написания скриптов.

Сценарии состоят из 4 составляющих

  1. Описание WEBUI в виде схемы json-editor: *.schema.json При необходимости изображения *.png

  2. Сохраненный конфиг из вебки в виде json структуры: *.conf

  3. Файл правил *.js Это точка входа в логику исполнения сценариев, он содержит:

    • Чтение конфигурации из файла
    • Логику парсинга и подготовки данных для инициализации (если она нужна)
    • Вызов методов которые инициализируют виртуальные устрйоства и правила
  4. Модуль *.mod.js Это опциональная единица для возможности использования из скриптов. Сюда можно перенести метод init и другую логику.

    ВАЖНО - если пишется модуль - то нужно стараться делать его так, чтобы он не занал что работает в сценариях: Он должен принимать общие структуры данных - например массивы входных и выходных контролов, но не объект самого сценария. Это нужно чтобы его можно было использовать вообще без сценариев, там где конфиг имеет другую структуру.

Ниже описывается процесс создания новых сценариев

Добавление нового сценария

Для добавления нового сценария нужно выполнить несколько шагов:

  1. Создать в папке scenarios подпапку с именем вашего сценария. Имя маленькими латинскими буквами через тире, например link-in-to-out Тут хранятся файлы относяшиеся к конкретному сценарию:

    • Модуль js *.mod.js
    • Скрипт init-*.js читающий конфиг и инициализирующий сценарий вашего типа на его основе.
    • Ридми для данного сценария README.md - здесь должен быть внешний вид и краткая инструкция по использованию
  2. Добавить описание схемы webui для вашего нового сценария в файл schema/scenarios.schema.json

  3. Файлы изображений для отображения схеме в формате png - положить рядом в папке schema/*.png

  4. Если требуется поменять конфиг wb-scenarios.conf чтобы он корректно открывался в соответствии с вашими изменениями в схеме. В данный момент конфиг поставляется пустым, поэтому этот пункт можно опустить.

Процесс разработки сценария

  1. Пуш первой версии
    1. Создать папку
    2. Создать ридми где описать общий смысл сценария
    3. Создать файл скрипта с шаблоном
    4. Запушить как первую пустую версию

Дальше есть несколько возможных подходов - выберете удобный вам, они в итоге приводят к одному результату, но разные начальные точки и разные первые PR.

Разделил все три варианта от самого легкого новичкам к более трудным внизу.

Удобно создавать сценарий начиная от схемы json. Этот подход позволяет сначала создать и увидеть примерный WEBUI и что важно - видишь генерируемый выходной конфиг который нужно парсить в скрипте инициализации.

Как следствие - быстро можно получить первый PR и сразу имеешь результат в виде константного конфиг файла от которого можно уже строить логику скриптов

  1. Модифицируем схему так как нужно для вашего сценария
  2. Смотрим то что получается на выходе в конфиге
  3. Пробрасываем в скрипт чтение конфига
  4. Пишем простой скрипт
  5. Выделяем логику инициализации в отдельный модуль

Профит - мы получили то что хотели идя от json схемы с переодическими коммитами и плавным утверждением PR

1. Добавляем новый сценарий в схему

1.1. В definitions добавляем описание

Раздел должен иметь уникальное название - в данном случае это "devicesControl" Далее идут стандартные описания раздела - титл и тд Далее идет раздел properties - этот раздел содержит свойства данного сценария

  1. В начале в любом сценарии должны всегда идти 4 стандартные поля
    • scenarioType
    • enable
    • name
    • id_prefix
  2. Далее нужно описать кастомные поля для управления новым сценарием Примеры можно посмотреть в готовых сценариях
  3. В конце идет required которое говорит какие поля должны быть заполнены перед сохранением
        "devicesControl": {
            "type": "object",
            "title": "Light control",
            "description":"Данный сценарий предоставляет возможность управления светом с выключателей <br><img src=\"images/scenarios-link-in-to-out.png\">",
            "_format": "grid",
            "properties": {
                "scenarioType": {
                    "type": "string",
                    "enum": ["devicesControl"],
                    "default": "devicesControl",
                    "options": {
                        "hidden": true
                    }
                },
                "enable": {
                    "type": "boolean",
                    "title": "Enable",
                    "default": true,
                    "_format": "checkbox",
                    "propertyOrder": 1,
                    "options": {
                        "grid_columns": 12
                    }
                },
                "name": {
                    "type": "string",
                    "title": "Scenario name",
                    "default": "Управление светом",
                    "minLength": 1,
                    "maxLength": 30,
                    "propertyOrder": 2,
                    "options": {
                        "grid_columns": 12
                    }
                },
                "id_prefix": {
                    "type": "string",
                    "title": "ID Prefix",
                    "description": "Одно слово на английском языке исключая: пробел, /, +, #. Длина до 15 символов.",
                    "_pattern_comment": "Запрещает пробелы, /, +, и #, а также ограничивает строку использованием только цифр, нижнего подчеркивания и английских букв",
                    "pattern": "^[0-9a-zA-Z_]+$",
                    "default": "light_control",
                    "minLength": 1,
                    "maxLength": 15,
                    "propertyOrder": 3,
                    "options": {
                        "grid_columns": 12
                    }
                },
                ... Тут вставить кастомные поля ...
            },
            "required": ["scenarioType", "enable", "name", "id_prefix"]
        }

1.2. Модифицировать oneOf

Добавить сверху

"oneOf": [
    { "$ref": "#/definitions/linkInToOut" },
    { "$ref": "#/definitions/devicesControl" }
],

1.3. Переводы

Внизу файла схемы нужно добавить переводы

2. Проверка

Проверить что все отображается как вы хотите

Сохранить конфиг и посмотреть что все сохранилось конкретно

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

Например:

  • Для enum - вконце исопльзовать ...Type, например behaviorType
  • Для числовых значений - ... value, например actionValue
  • Для строковых сложно предусмотреть возможности, но например - ...Name, Path и тд указывая на то что содержится в параметре. Не просто mqttTopic, а mqttTopicName - явно указывает на строковый тип

3. Скрипт инициализации

Скрипт является точкой входа для сценария, так как при перезапуске wb-rules именно с этого места начинается выполнение кода.

Данный скрипт должен открыть конфигурационный файл и инициализировать все найденные сценарии с определенным типом.

4. Модуль

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

Прототип функции должен выглядеть следующим образом

function init(deviceTitle, cfg) {}
  • deviceTitle - это отображаемое имя виртуального девайса который создается для управления сценарием. Данное имя только отображается для людей и не используется в MQTT на данный момент.
  • cfg - это объект содержащий все настройки конкретного сценария и на данный момент имеет только одно обязательное поле cfg.idPrefix которое используется для добавления индивидуальных данных в виде префикса к правилам и виртуальным девайсам

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

  • Что введённые пользователем устройства и топики существуют
  • Что тип выбранных пользователем топиков поддерживает выбранный тип события для аходных топиков или вид действия для выходных топиков

Другие варианты порядка разработки

Так же можно разрабатывать начиная с других элементов:

  • От модуля
  • От обычного скрипта

От модуля

Самый сложный и абстрактный путь самурая которому не нужны никакая опора под ногами для работы. Модуль сам по себе является опциональной единицей разделения фукнционала и не обязателен для работы сценариев. Сразу пишем модуль, интегрируем его в скрипт который считывает конфиг. Здесь мало переделок, много параллельной взаимосвязанной работы и видимый результат виден только в конце.

От скрипта инициализации

Удобно использовать новичкам в первый раз - когда не знаешь еше окружения и не работал с json-editor. Путь начинается от обычного скрипта wb-rules и заканчивается интеграцией решения в json-editor.

  1. Написание обычного скрипта На данном этапе нужно написать скрипт который статично выполнит то что вы хотите сделать без обработок ошибок - просто в лоб.

  2. Разделить этот скрипт вытащив либо переменные в webui, либо написав сначала модуль

  3. Дописать оставшуюся часть

Библиотека сценариев

При разработке сценариев были разработаны и используются стандартные фукнции и сущности которые могут помочь при разработке нового сценария.

Стандартный сценарий представляет из себя

  • Массив входных топиков которые отслеживаются
  • Специфичную логику преобразования для данного сценария
  • Массив выходных топиков которым нужно изменить состояние

Есть два варианта блоков которые имеют уже написанные способы обработки и прокидывания значений enum в код.

  1. Массив источников событий
    • Обработчик анализирующий причину события
  2. Девайсы для воздействия
    • Обработчик выставляющий нужные значения каждому выходному контролу в зависимости от выбранного типа поведения (поменять, выставить в выключенное состояине и тд)

У обоих типов есть свои предопределенные типы поведений которые может выбрать пользователь, либо определить разработчик.

Выбранные enum будут определять как данный контрол будет обрабатываться фукнцией setAll...

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