Сценарии - новая версия API
-
У меня проблема, которую я не могу осознать.
Мультисценарий
script({ start(step) { step = Number(step); let newvalue = step; ActUst.setValue(newvalue); } });
И кнопка с дополнительным параметром, запускающим суенарий.
Если дополнительный параметр положительный - все работает.
Если отрицательный - нет.
Отладчик скрипта пишет, что значение актуатору присвоено, а в устройствах оно не меняется.Актуатор по модбасу присоединен к параметру контроллера "температура антизамерзания". Этот параметр содержит значение температуры на улице, ниже которой насос в контуре станет постоянно включенным. Если выше включается/выключается по необходимости, если ниже - всегда гоняет жижу, чтобы не замерзла. Такая функция.
Соответственно, значение может быть от -25 до +5.
Но на 0 и выше скриптом назначается, а на любое отрицательное - нет.Решил сделать другой мультисценарий.
Просто строкуActUst.setValue(-25)
Ошибок нет. Но этот сценарий не отображается в меню "параметры" у кнопки. Перезагрузка IH не помогла.
Если назначаю отрицательное значение напрямую на контроллере - они считываются по модбас, и отображаются в IH. Наоборот - только положительные.
Что за магия?
-
Если управлять этим же скриптом актуатором, не подключенным к модбас, все работает.
-
@Erik, добрый день
Возможно, назначается не тот тип переменной при записи по modbus отрицательных чисел. Посмотрите в отладчике плагина в момент передачи команды на запись. Там должны быть сообщения:Command ..... received. Data: .... // Потом WRITE: unitId =..., FC = 6, address =....
-
вот успешное
29.02 13:49:06.536 IH: command [ { dn: 'ACTORA84', prop: 'set', val: 5 } ] 29.02 13:49:06.538 IH: send { type: 'act', data: [ { chan: 'T.Antizam.Ku', id: 'T.Antizam.Ku', vartype: 'int16', usek: false, ks: 100, ks0: 0, gr: false, pollp: true, value: 50, desc: 'AO', kh0: 0, address: '1321', fcr: '3', useactions: false, kh: 100, nofb: false, unitid: 1, calc_outfn: [Function: anonymous], command: 'set' } ] } 29.02 13:49:06.542 modbus1: Command to send: [ { chan: 'T.Antizam.Ku', id: 'T.Antizam.Ku', vartype: 'int16be', usek: false, ks: 100, ks0: 0, gr: false, pollp: true, value: 50, desc: 'AO', kh0: 0, address: 1321, fcr: '3', useactions: false, kh: 100, nofb: false, unitid: 1, command: 'set' }, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71 ] 29.02 13:49:06.557 modbus1: WRITE: unitId = 1, FC = 6, address = 1321 (0x529), value = 50 29.02 13:49:06.558 modbus1: writeSingleRegister: address = 1321 (0x529), value = 50 29.02 13:49:06.559 modbus1: Write result: { address: 1321, value: 50 }
а вот ошибки
29.02 13:49:08.683 IH: command [ { dn: 'ACTORA84', prop: 'set', val: -20 } ] 29.02 13:49:08.684 IH: send { type: 'act', data: [ { chan: 'T.Antizam.Ku', id: 'T.Antizam.Ku', vartype: 'int16', usek: false, ks: 100, ks0: 0, gr: false, pollp: true, value: -200, desc: 'AO', kh0: 0, address: '1321', fcr: '3', useactions: false, kh: 100, nofb: false, unitid: 1, calc_outfn: [Function: anonymous], command: 'set' } ] } 29.02 13:49:08.687 modbus1: Command to send: [ { chan: 'T.Antizam.Ku', id: 'T.Antizam.Ku', vartype: 'int16be', usek: false, ks: 100, ks0: 0, gr: false, pollp: true, value: -200, desc: 'AO', kh0: 0, address: 1321, fcr: '3', useactions: false, kh: 100, nofb: false, unitid: 1, command: 'set' }, 64, 65, 66, 67, 68, 69, 70, 71 ] 29.02 13:49:08.839 modbus1: WRITE: unitId = 1, FC = 6, address = 1321 (0x529), value = -200 29.02 13:49:08.839 modbus1: writeSingleRegister: address = 1321 (0x529), value = -200 29.02 13:49:08.841 modbus1: ERROR: TypeError: "value" argument is out of bounds at checkInt (buffer.js:1176:11) at Buffer.writeUInt16BE (buffer.js:1245:5) at ModbusRTU.writeFC6 (/var/lib/intrahouse-c/plugins/modbus/node_modules/modbus-serial/index.js:607:9) at /var/lib/intrahouse-c/plugins/modbus/node_modules/modbus-serial/apis/promise.js:48:31 at new Promise (<anonymous>) at ModbusRTU.converted [as writeRegister] (/var/lib/intrahouse-c/plugins/modbus/node_modules/modbus-serial/apis/promise.js:39:27) at Object.modbusWriteCommand (/var/lib/intrahouse-c/plugins/modbus/app.js:345:36) at Object.write (/var/lib/intrahouse-c/plugins/modbus/app.js:302:28) at Object.sendNext (/var/lib/intrahouse-c/plugins/modbus/app.js:379:18) at Object.read (/var/lib/intrahouse-c/plugins/modbus/app.js:248:18) 29.02 13:49:08.842 modbus1: Write result: undefined
-
@Erik
Спасибо за тестирование, действительно, есть проблема с записью отрицательных целых значений в библиотеке modbus-serial.
В новой версии библиотеки эта проблема исправлена. Проверим у себя и на следующей неделе выпустим новый релиз плагина
-
Это сообщение удалено!
-
Есть ли возможность сделать сценарий, стартующий при загрузке IH ( некий аналог RunOnce) ? Иногда бывает нужно "привести в порядок" контролируемые устройства после внезапной перезагрузки сервера.
-
@alesle Да, такая возможность есть.
Нужно в сценарий включить функцию boot, которая должна вернуть результат true, чтобы сценарий запустился при старте сервера. Выполнение, как обычно, начнется с функции start().
Если не будет триггеров (startOnChange), то сценарий больше запускаться не будетboot() { return true; // Всегда запускать при старте сервера }, start() { // Здесь скрипт, который нужно выполнить }
Эта возможность не документирована. Возможно, синтаксис изменится при доработке API сценариев.
-
Можно ли обьявить модуль (функцию), который будет доступен из всех сценариев?
-
Подскажите. Такая ситуация: есть внешние ролокасеты, при закате солнца они автоматически закрываются по сценарию, есть датчик движения на улице. Проблема: как в сценарии указать что бы actor (ролокасета) не опускалось если было движение за последных 30 минут для примера, что бы не остатся ночевать на заднем дворе)))).
-
3 скрипта. 1 доп актуатор.
- По датчику движения присвоить значение 1 доп актуатору на 30 минут.
- ПО изменении доп актуатора (при изменении с 1 на 0) проверить время, если закат закрыть ролокассеты.
- По таймеру Когда закат - проверить, что доп актуатор не 1, и закрыть ролокассету.
-
@Erik а кусочек сценария можно? Такого раньше не делал)))
-
@alesle Пока такой возможности нет
-
в следующей версии не планируете?
-
@intrapro, кстати да! Такая возможность очень нужна! У меня 100500 сценариев и в них просто копипастом вставляю одни и те же функции. По идее можно ведь как-то хотя бы вручную сделать библиотеку функций и подключать ее в сценариях?
-
-
@intrahouse, в связи с этим добавил новый пункт в теме по развитию версии 5)). Вообще мне ваши программисты в какой-то задаче уже подсказывали как подключать внешние библиотеки. Сейчас нет возможности найти эту задачу.
-
Пользователь @amgstone написал в Сценарии - новая версия API:
@Erik а кусочек сценария можно? Такого раньше не делал)))
Первый такой
/** * @name признак движения * @desc * @version 4 */ const Actor = Device("ActorA", "Признак движения"); const Motion = Device("SensorD", "Датчик движения"); // Запустим сценарий при сработке датчика движения, startOnChange([Motion], Motion.isOn()); script({ start() { Actor.on(); // взводим таймер, чтобы отключить this.startTimer("T1", 3600, "turnOff"); // Добавляем слушатель - следим за датчиком движения this.addListener(Motion, "onMotion"); }, onMotion() { // Если движение возобновилось - сбрасываем таймер if (Motion.isOn() ) { this.stopTimer("T1"); } // Если движение прекратилось - взводим таймер (после повторных движений) if (Motion.isOff() && this.timer.T1 == "off") { this.startTimer("T1", 3600, "turnOff"); } }, // Функция, которая сработает, когда таймер досчитает - отключаем признак движения и выходим turnOff() { Actor.off(); this.exit(); // Здесь exit нужен, так как есть активные слушатели и сценарий сам не завершится } });
Второй такой (запускаем на закате)
/** * @name признак движения * @desc * @version 4 */ const Actor = Device("ActorA", "Признак движения"); const Rol = Device("ActorA", "Ролкассета"); script({ start() { if (Actor.isOff()) { //пишите тут то, что хотите сделать с Rol) Rol.on(); this.exit(); }, if (Actor.isOn()) { // взводим таймер, чтобы отключить this.startTimer("T1", 3600, "turnOff"); // Добавляем слушатель - следим за признаком движения this.addListener(Actor, "onActor"); }, onActor() { // Если признак движения отключился, закрываем Ролкассету if (Actor.isOff()) { Rol.on(); this.exit(); } }, // Функция, которая сработает, когда таймер досчитает - закрываем Ролкассету и выходим turnOff() { Rol.on(); this.exit(); } } });
-
Подскажите, пожалуйста.
Есть датчик универсальный аналоговый. Привязан к датчику CO2 T6703. У датчика определены состояния: до 400, до 600, до 800, до 1000 и более 1000. Для каждого состояния меняется цвет иконки. На мнемосхеме все работает прекрасно- отображаются значения, меняется цвет иконки. Вопрос в другом. Решил сделать сценарий, отслеживающий изменение состояния. В системе команд есть функция x.isChanged (имя свойства). Но конструкция
startOnChanged(sens, sens.isChanged('state'));
не работает. В ошибках рабочего сценария пишет, что функция не определена. Если убрать условие отслеживания состояния, то сценарий отрабатывает по изменению значения каждую минуту. Хотел сократить число запусков. Подскажите, что не так
-
@int144 Вы все верно сделали, но в v4 сценариев мы по техническим причинам убрали device.isChanged(prop), заменив его на this.isChanged(device, prop,value)
То есть эту возможность в startOnChange сейчас применить нельзя.
Можно проверить уже внутри start:// Проверить, что сценарий запустился из-за изменения состояния if (this.isChanged(sens, 'state')) { .... } // Можно проверить, что переключился в определенное состояние if (this.isChanged(sens, 'state', 1)) { ... }
Извините за неточности в документации