Как запустить правило после старта контроллера?

Вроде избитая тема и много где поднималась, но внятного ответа до сих пор нет.

Допустим, мне нужно включить реле сразу после инициализации контроллера. Сделать это напрямую в скрипте я не могу, т. к. там нельзя работать с dev.,when: function () { return true } так же работает непредсказуемо. Что-то там городить с задержками и таймаутами так себе идея.

В общем, как мне узнать, что инициализация прошла без танцев и без бубна?

setTimeout на несколько секунд вперёд - вполне рабочее решение

Ок. Я так, конечно, сделаю, но предусмотрите, пожалуйста, в будущем какой-нибудь хук или триггер или жизненный цикл приложения, чтобы, первым запускался preInit.js, потом devInit.js, потом networkInit.js и т. д.

Добрый день!

А зачем?

Действительно, зачем разработчику знать, когда инициализирована нужная периферия? Пусть гадает на таймаутах. А если, вдруг, не угадает, ну перестанут все скрипты работать без внятной ошибки, что такого. Вы же когда к базе данных подключаетесь, тоже не проверяете, установилось ли соединение. Зачем, если можно подождать пару секунд и начать чтение. Зачем, вообще, придумали все эти колбеки, асинхронность и прочую ерунду. Индийские программисты давно сообразили, что setTimeout решает все проблемы.

А почему бы preInit.js не возводить флаг своей готовности, а зависящему от него модулю этот флаг не проверять?

А если нам нужно выполнить внутреннюю инициализацию до вызова каких-либо правил? Стандартный подход в этом случае - callback. По идее достаточно было бы одного, который бы вызывался движком после того, как все retained значения получены и уже можно обращаться к dev, но до того, как движок в первый раз вызовет правила.

А опишите, пожалуйста, целиком и подробно, что нужно добиться, и почему сейчас это не работает.

А с чем там случается проблема? wb-mqtt-serial ещё не начинает работать?

Вы хотите, чтобы это были какие-то системные файлы со строгим порядком запуска? Что должно быть у них внутри: ваш код, наш код, какой?

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

В моем случае, я точно знаю, что нельзя обращаться к dev сразу (в т. ч. when: function () { return true }), потому что из-за этого все скрипты перестанут работать после перезагрузки. Более того, я не знаю в какой момент с dev уже можно начать работать. И самое печальное, что я даже по таймауту не могу проверить, готов ли dev или нет (нет такого флага или я не знаю о нем).

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

Можно сделать колбек по аналогии с whenChange. Например, whenInit: “wb-gpio/relay-1”, что гораздо лучше, но не удобно, когда нужно подписаться на инициализацию кучи устройств.

Можно пойти дальше и дополнительно к предыдущему выделить из приложения его жизненный цикл, как это делается во фреймворках. Тут уже надо думать, на какие стадии разбивать и какие события должны составлять эти стадии. Как минимум, всегда будет стадия init или start, которая означает окончание инициализации устройств, modbus, mqtt. Т.е. тот уровень, когда пользователю доступна основная периферия. Эта стадия должна быть основной, на которой пользователи будут безопасно работать. Часто выделяют стадию конфигурации (config, preInit), которая идет вначале и где пользователь может читать конфиги, настраивать коннект к БД и т.п.

То что я предложил с файлами preInit.js, devInit.js, networkInit.js - всего лишь пример. Можно, сделать так, чтобы все пользовательские скрипты запускались после того как устройства (dev) гарантировано доступны. Но, при этом определить специальные файлы с системными именами, которые запускались бы в другое время. Например, весь пользовательский код из файла configure.js или preInit.js выполнялся бы самым первым (как собственно сейчас и выполняются все скрипты). Пока на этом можно остановиться.

P.S. Примеры из разных областей

Разумеется и у МК есть свои жизненные циклы, о чем вы точно знаете. Даже у Ардуино есть start и loop. И при этом колбеки устройств, конечно, тоже никто не отменял.

Я ошибся, когда согласился, что это решение плохое, но рабочее. Оно не рабочее! Действительно, при задержке в пару секунд, скрипты загружались и всё выглядело отлично. НО, значения в dev так и не устанавливались! Т. е. такой скрипт выведет в лог “Start!”, но порты так и останутся false и контакторы (в моем случае) не включатся никогда.

setTimeout(function() {
  log("Start!")
  dev['wb-gpio/A1_OUT'] = true;
  dev['wb-gpio/A2_OUT'] = true;
  dev['wb-gpio/A3_OUT'] = true;
}, 2000)

Опытным путем установил, что нужна задержка не менее 15 с. и я очень надеюсь, что это значение не изменится. Хорошо, что вовремя заметил, а не когда щит стоял на объекте.
Пожалуйста, сделайте что-нибудь с этим.

defineRule("1", {
  when: function () {
     return true;
  },
  then: function () {
     dev["wb-gpio"]["A1_OUT"] = true;
  }
});

попробуйте так. должно работать.

Не работает. Все правила виснут.

Я пробовал этот вариант, setTimeout, startTimer. В любом случае работает только задержка в 15 с.

Чтобы выход А1 был включен по-умолчанию нужно отредактировать файл /mnt/data/etc/wb-homa-gpio.conf так:

{
    "device_name" : "Discrete I/O",

    "channels" : [    
       {
         "gpio": 79,
         "name": "A1_OUT",
         "direction": "output",
         "inverted": false,
         "initial_state": true
       }
    ]
}
1 лайк