Сценарии в intraHouse Cherry
-
Скрипт рабочий. Скорее всего, значение не принимается, так как для датчика температуры установлен диапазон Min-Max и флаги:
-Не принимать значения вне диапазона
-Устанавливать ошибку при выходе из диапазона.
И диапазон не включает 0-10
Да, Вы были правы! Я снова с просьбами о помощи:)
1. Бьюсь со сценарием включения/отключения актюатора по аналоговому датчику температуры (эмулирую значения 24,8 и 25,2; уставка температуры 25, гистерезис 0,1). Не могу побороть проблему - при понижении температуры актюатор включается, а при повышении - не выключается! Скрипт:
/** * @name Актюатор ТП по датчику температуры * @desc Сценарий работает при включеном режиме АВТО у актюатора * При увеличении температуры выше целевого значения на величину гистерезиса актюатор включается, * при уменьшении температуры ниже целевого значения на величину гистерезиса - выключается. * В качестве целевого значения берется уставка с датчика температуры (dt.defval) * В качестве гистерезиса берется пользовательская настройка актюатора (act.hist) */ const act = Device("ActorD", "Актюатор ТП", [ {"name":"hist", "note":"Гистерезис включения/отключения актюатора, °C", "type":"number", "val":0.1} ]); const dt = Device("SensorA", "Датчик температуры"); const script = { check() { return act.auto && ( !act.dval&&(dt.aval <= dt.defval-act.hist) || act.dval&&(dt.aval >= dt.defval+act.hist) ); }, start() { if(!act.dval) { this.do(act, "on"); } else { this.do(act, "off"); } } };
Лог отладчика - почему во втором случае Check выдает false - я не понимаю!
24.09 11:51:37.416 S1(ACTOR_HEATING1_01,ST_HEATING1_01) Check(ST_HEATING1_01) => true 24.09 11:51:37.416 S1(ACTOR_HEATING1_01,ST_HEATING1_01) Started 24.09 11:51:37.417 S1(ACTOR_HEATING1_01,ST_HEATING1_01) do ACTOR_HEATING1_01 on 24.09 11:51:37.418 S1(ACTOR_HEATING1_01,ST_HEATING1_01) Stopped 24.09 11:51:47.394 S1(ACTOR_HEATING1_01,ST_HEATING1_01) Check(ST_HEATING1_01) => false
2. У меня актюаторы НО. Чтобы когнитивный диссонанс не устраивать в скриптах, я так понимаю, в соответствующих каналах плагина MegaD нужно активировать чек-бокс "Ивертировать выходное значение"?
3. Еще что заметил - этот скрипт отключает режим АВТО у актюатора! Как сделать чтобы режим АВТО не отключался скриптом (кроме установки в свойствах актюатора 00:00:00 для включения/отключения режима АВТО)?
4. И научите как же все-таки пользоваться логированием?
@Alex_Jet:Для отладки (и записи в журнал) можно использовать this.log():
Пока не разобрался как же использовать log. Что он будет логировать? - работу функций или в его тело нужно вставлять какие-то комментарии?
-
Лог отладчика - почему во втором случае Check выдает false - я не понимаю!
Еще что заметил - этот скрипт отключает режим АВТО у актюатора!
Check выдает false именно потому, что режим АВТО при операции on/off отключается.
Как сделать чтобы режим АВТО не отключался скриптом (кроме установки в свойствах актюатора 00:00:00 для включения/отключения режима АВТО)?
Нужно использовать команды aon/aoff (как в Berry)
this.do(act, "aon");
И научите как же все-таки пользоваться логированием?
Любая строка, сформированная по правилам JS, будет выведена в журнал пользователя и в отладчик тоже
this.log( "Температура "+dt.aval+". Уставка "+dt.defval);
-
Check выдает false именно потому, что режим АВТО при операции on/off отключается.
Я тоже так думал и поэтому вручную в настройках актюатора установил 00:00:00 чтобы АВТО режим не отключался!
В итоге с помощью логирования сейчас вот такую ерунду выяснил:
24.09 13:34:47.890 S1(ACTOR_HEATING1_01,ST_HEATING1_01) log: Act.auto - 1; Act.dval - 0; Dt.aval = 24.8; Porog = 24.9 24.09 13:34:47.895 S1(ACTOR_HEATING1_01,ST_HEATING1_01) Check(ST_HEATING1_01) => true 24.09 13:34:47.895 S1(ACTOR_HEATING1_01,ST_HEATING1_01) Started 24.09 13:34:47.896 S1(ACTOR_HEATING1_01,ST_HEATING1_01) do ACTOR_HEATING1_01 aon 24.09 13:34:47.897 S1(ACTOR_HEATING1_01,ST_HEATING1_01) Stopped 24.09 13:35:05.407 S1(ACTOR_HEATING1_01,ST_HEATING1_01) log: Act.auto - 1; Act.dval - 1; Dt.aval = 25.2; Porog = 25.000.1 24.09 13:35:05.412 S1(ACTOR_HEATING1_01,ST_HEATING1_01) Check(ST_HEATING1_01) => false
Почему во втором случае Porog (dt.defval + act.hist) = 25.000.1? Почему не суммируется?
-
Почему во втором случае Porog (dt.defval + act.hist) = 25.000.1? Почему не суммируется?
JavaScript, он такой. Исправим у себя преобразование типов параметров сценария, недоглядели
Вам же достаточно сделать Number(dt.defval)
Ну, вы наверное уже и сами догадались
-
Почему во втором случае Porog (dt.defval + act.hist) = 25.000.1? Почему не суммируется?
JavaScript, он такой. Исправим у себя преобразование типов параметров сценария, недоглядели
Вам же достаточно сделать Number(dt.defval)
Ну, вы наверное уже и сами догадались
У меня не такой огромный опыт в JS как у Вас. Поэтому для меня это было загадкой.
Да, теперь работает. Единственный вопрос еще: как правильнее и чем это грозит:
1. Проверка в check "короткого" условия return act.auto && dt.aval с последующей проверкой условий в start
2. Проверка в check "длинного" условия return act.auto && dt.aval ( !act.dval&&(dt.aval <= dt.defval - act.hist) || act.dval&&(dt.aval >= dt.defval + act.hist) )
PS: расскажите в теме про CCTV про видеоалерты - есть ли уже такая возможность? и как настраивать.
-
Единственный вопрос еще: как правильнее и чем это грозит:
1. Проверка в check "короткого" условия return act.auto && dt.aval с последующей проверкой условий в start
2. Проверка в check "длинного" условия return act.auto && dt.aval ( !act.dval&&(dt.aval <= dt.defval - act.hist) || act.dval&&(dt.aval >= dt.defval + act.hist) )
Да ничем не грозит, дело вкуса.
Второй вариант предпочтительнее, т к :
1. Меньше количество операций сравнения.
Условные выражения в JS работают до первого ложного условия - т е если act.auto=0 - больше ничего проверяться не будет в обоих вариантах, хотя на вид условие по 2 варианту длинное.
А если act.auto =1, то по 1 варианту сначала будет проверка dt.aval в check (Вам пришлось вставить, чтобы датчик был триггером), а потом будет проверка в start
2. Меньше будет зафиксировано запусков сценария.
По 1 варианту запуск будет фиксироваться при каждом изменении тем-ры, а если она у вас с десятыми (или даже с сотыми), то количество запусков быстро перевалит за 1000. А на фиксацию запуска сценария также тратятся ресурсы.
По 2 варианту запуск сценария означает, что выполняется регулирование.
Но работать будут оба варианта.
PS: расскажите в теме про CCTV про видеоалерты - есть ли уже такая возможность? и как настраивать.
Запланировано, но пока не реализовано
-
Да ничем не грозит, дело вкуса.
Ок, понятно. По актюаторам еще можно комментарий?
@Alex_Jet:2. У меня актюаторы НО. Чтобы когнитивный диссонанс не устраивать в скриптах, я так понимаю, в соответствующих каналах плагина MegaD нужно активировать чек-бокс "Ивертировать выходное значение"?
-
У меня актюаторы НО. Чтобы когнитивный диссонанс не устраивать в скриптах, я так понимаю, в соответствующих каналах плагина MegaD нужно активировать чек-бокс "Ивертировать выходное значение"?
Да, должно работать (примерно как было в Berry)
-
Можно еще проще - привязать бинарный актуатор, а интерактивные операции для него отключить
В принципе эта идея сработала. При поднесении нужного ключа к считывателю актуатор меняет свое состояние. Отталкиваясь от его состояния можно написать сценарий установки/снятия с охраны. Единственный неопределенный момент в том, что когда MegaD опрашиваем командой cmd=all, то канал, соответствующий считывателю находится в неопределенном состоянии (ранее писал, что не верно под неопределенным состоянием считать 0). Возникает вопрос - после перезагрузки MegaD в каком состоянии окажется привязанный к этому каналу актуатор (ну или сенсор, если добавите ему обработку toggle). Или все же это правильно - считать за 0/OFF неопределенное состояние порта?
Написал сценарий постановки дома на охрану. Button - это актюатор, который привязан ко входу MegaD, к которому подключен считыватель. Кроме этого, из этого устройства сделан индикатор постановки на охрану в строке состояния и две кнопки "Постановка/Снятие с охраны" (для одной в свойствах выбрано on, для другой - off). Lamp - это сигнальная лампа (загорается при постановке), Ring - это сирена.
const Button = DeviceT("ACTOR_SECURITY_SYS01"); const Lamp = Device("ACTOR_SECURITY_SYS02"); const Ring = Device("ACTOR_SECURITY_SYS03"); const script = { start() { this.log(Button.name+ "=" +Button.dval); if(Button.dval) { this.do(Lamp, "on"); //Включаем лампу this.do(Ring, "on"); //На секунду срабатывает сирена this.startTimer("T1", 0.1, "ringOff"); } else { this.do(Lamp, "off"); //Выключаем лампу this.do(Ring, "on"); //На секунду срабатывает сирена this.startTimer("T1", 0.1, "ringOff"); } }, // Функция, которая сработает, когда таймер досчитает - отключаем и выходим ringOff() { this.do(Ring, "off"); this.exit(); } };
Суть в том, что при сработке считывателя все работает хорошо (актюатор меняет свое состояние и скрипт все верно отрабатывает). А вот при нажатии кнопок работает не верно - нажимаю кнопку "Поставить на охрану" (on) индикатор охраны становится активным, но реле сигнальном лампы не срабатывает, а в отладчике скрипта видно, что актюатор почему-то не "встал":
27.10 23:52:44.905 Trigger ACTOR_SECURITY_SYS01 27.10 23:52:44.905 Started 27.10 23:52:44.906 log: Актуатор постановки на охрану=0 27.10 23:52:44.912 do ACTOR_SECURITY_SYS02 off 27.10 23:52:44.916 do ACTOR_SECURITY_SYS03 on 27.10 23:52:44.918 start timer T1 for 0.1 sek 27.10 23:52:45.026 Done timer T1 27.10 23:52:45.026 exec function ringOff 27.10 23:52:45.027 do ACTOR_SECURITY_SYS03 off 27.10 23:52:45.029 exit 27.10 23:52:45.029 Stopped
Не могу понять почему так происходит? Надо таймер взводить перед проверкой состояния актюатора?
Up1: методом итераций (сначало сделал таймер на 0,1 секунду с переходом в main), потом чтобы при повторном нажатии той же кнопки (когда взято под охрану, но еще раз нажимают кнопку "Взять под охрану") не срабатывала сирена решил проверять совпадает текущее значение актуатора с предыдущем, потом судя по логам работы решил убрать таймер. И получилось вот что:
const Button = DeviceT("ACTOR_SECURITY_SYS01"); //Актуатор постановки на охрану const Lamp = Device("ACTOR_SECURITY_SYS02"); //Сигнальная лампа const Ring = Device("ACTOR_SECURITY_SYS03"); //Сирена var Status; const script = { start() { //this.log(Button.name+ " = " +Button.dval); this.main(); Status = Button.dval; }, // Основная функция постановки на охрану main() { //this.log(Button.name+ " = " +Button.dval); //Если предыдущее состояние актуатора совпадает с текущим, то выходим. if(Status != Button.dval) { if(Button.dval) this.do(Lamp, "on"); //Включаем лампу else this.do(Lamp, "off"); //Выключаем лампу this.do(Ring, "on"); //Срабатывает сирена this.startTimer("T1", 0.1, "ringOff"); } }, // Функция отключения сирены с выходом из скрипта ringOff() { this.do(Ring, "off"); this.exit(); } };
Парадокс в том, что если исключить Status = Button.dval; или перенести до this.main(); то ничего не работает. А именно в такой последовательности - работает. Однако моя логика не понимает в чем суть…
-
Написал сценарий постановки дома на охрану. Button - это актюатор, который привязан ко входу MegaD, к которому подключен считыватель. Кроме этого, из этого устройства сделан индикатор постановки на охрану в строке состояния и две кнопки "Постановка/Снятие с охраны" (для одной в свойствах выбрано on, для другой - off)…..
А канал считывателя MegaD отрабатывается как toggle?
Думаю, проблема в том, что у вас устройство Button, с одной стороны - псевдоактуатор с привязкой к считывателю, с другой - его же вы используете как виртуальный актуатор для постановки/снятия. Но фактически у вас выход не переключается, поэтому состояние может не совпадать с ожидаемым.
Можете посмотреть журнал устройства (при длинном нажатии).
Если отключить Button от канала, то виртуальное устройство будет правильно отрабатывать кнопки по первому варианту.
Выход - создать отдельный виртуальный актуатор Постановка/Снятие (Guard, например).
Он выводится на индикацию, он переключается кнопками. По его событиям включается сигнальная лампа и вообще все, что нужно сделать при постановке (снятии). Его состояние вы можете учитывать в других сценариях (датчики, герконы на охране и т д, ну вы знаете
Дополнительно, как я понимаю, вы хотите реализовать Постановку (и Снятие?) при сработке считывателя. Т е это триггер, который должен переключить Guard . Так это и надо реализовать - отдельный сценарий, который просто переключает Guard по считывателю (по сути, как кнопка)
-
Написал сценарий постановки дома на охрану. Button - это актюатор, который привязан ко входу MegaD, к которому подключен считыватель. Кроме этого, из этого устройства сделан индикатор постановки на охрану в строке состояния и две кнопки "Постановка/Снятие с охраны" (для одной в свойствах выбрано on, для другой - off)…..
А канал считывателя MegaD отрабатывается как toggle?
Думаю, проблема в том, что у вас устройство Button, с одной стороны - псевдоактуатор с привязкой к считывателю, с другой - его же вы используете как виртуальный актуатор для постановки/снятия. Но фактически у вас выход не переключается, поэтому состояние может не совпадать с ожидаемым.
Можете посмотреть журнал устройства (при длинном нажатии).
Если отключить Button от канала, то виртуальное устройство будет правильно отрабатывать кнопки по первому варианту.
Выход - создать отдельный виртуальный актуатор Постановка/Снятие (Guard, например).
Он выводится на индикацию, он переключается кнопками. По его событиям включается сигнальная лампа и вообще все, что нужно сделать при постановке (снятии). Его состояние вы можете учитывать в других сценариях (датчики, герконы на охране и т д, ну вы знаете
Дополнительно, как я понимаю, вы хотите реализовать Постановку (и Снятие?) при сработке считывателя. Т е это триггер, который должен переключить Guard . Так это и надо реализовать - отдельный сценарий, который просто переключает Guard по считывателю (по сути, как кнопка)
Да, канал считывателя отрабатывается как toggle.
Вообще я замечал, что если актуатор привязан к каналу и канал недоступен (плагин не включен, MegaD недоступна), то при переключении актуатора в вебе его состояние не меняется. Тут же канал доступен, актуатор свое состояние в вебе меняет, а логическое состояние изменяется только после повторного нажатия кнопки. Парадокс в том, что мой последний скрипт работает так как задумано (и от устройств-кнопок и от считывателя), но при этом сам скрипт вообще не логичен…
По поводу дополнительного сценария - у меня сейчас уже порядка 30 различных скриптов, поэтому дополнительных плодить не хотел. И именно поэтому ранее вносил предложение - добавить в скриптах признак системы.
В общем попробую ваше предложение осуществить.
-
Сделал новый актуатор не привязанный к каналам, переделал скрипт - вечером посмотрю как работает со считывателем (с "виртуальным" актуатором, судя по отладчикам, проблем нет). Вопрос - чтобы состояние "виртуального" актуатора оставалось актуальным даже после выключения/включения сервера надо изменение его состояния записывать в БД? Или его последнее состояние храниться в json и даже после жесткого ребута будет актуальным?
PS: для входов состояние toggle будете определять?
-
Вопрос - чтобы состояние "виртуального" актуатора оставалось актуальным даже после выключения/включения сервера надо изменение его состояния записывать в БД? Или его последнее состояние храниться в json и даже после жесткого ребута будет актуальным?
Нет, в БД писать не надо. Да, будет сохраняться.
Гарантированный интервал сохранения на диск 10 сек (при жестком ребуте есть вероятность потери состояний, изменившихся за последние 10 сек)
PS: для входов состояние toggle будете определять?
Не совсем понятен вопрос. toggle - это операция. Состояние - результат выполнения, зависит от предыдущего состояния.
Поэтому для входов определять toggle считают неверным. Мы же реальное состояние с входа только получаем, повлиять на него не можем, но можем сильно запутаться
Для канала считывателя, если считаете, что вам удобнее toggle - определите его как выход
-
Для канала считывателя, если считаете, что вам удобнее toggle - определите его как выход
ОК, понятно. А как в скрипте сделать toggle для актуатора состояния сигнализации? То есть при любом изменении reader изменить состояние Button на противоположное? Что-то не могу догадаться…
-
А как в скрипте сделать toggle для актуатора состояния сигнализации? То есть при любом изменении reader изменить состояние Button на противоположное? Что-то не могу догадаться…
Вы же все уже сделали - канал привязали к актуатору Button c операцией toggle. Он сам меняет состояние по считывателю.
Что вам осталось сделать - по триггеру Button переключать Guard
-
Вы же все уже сделали - канал привязали к актуатору Button c операцией toggle. Он сам меняет состояние по считывателю.
Что вам осталось сделать - по триггеру Button переключать Guard
Извините. Я просто все немного переименовал. Button - это у меня виртуальный актуатор, который вынесен на веб-интерфейс в том числе в виде кнопок. А Reader - тот который привязан к каналу считывателя.
В одном скрипте у меня если изменяется состояние Button (кнопки на веб-морде), то я ставлю/снимаю сигнализацию.
В другом скрипте у меня должно быть по любому изменению Reader состояние Button меняться на противоположное - я не знаю как это сделать…догадался сам пока писал:
const script = { start() { //При успешном считывании Reader меняем состояние Button на противоположное this.assign(Button, "dval", !Button.dval); } };
-
Подскажите как сделать нечто подобное чтобы оно работало как задумано:
/** * @name Сообщение в Telegram о недоступности * @desc Уведомление пользователя по Telegram о недоступности оборудования */ //const Device1 = DeviceT("SENSOR0"); const script = { check() { let i; for(i = 0; i < 10; i++) { dev = Device("SENSOR" +i); if(!dev.dval) this.info("telegram", "OWNER", "Внимание! Недоступно устройство '" +dev.name+ "'"); else this.info("telegram", "OWNER", "Связь с устройством '" +dev.name+ "' восстановлена"); this.log(dev.name+ "=" +dev.dval); } }, start() { } };
Если подробнее, то не объявлять в виде констант 100500 устройств (как DeviceT или проверять "вручную" изменение каждого в check), а с помощью цикла в check проверить состояние каждого. Если добавится еще 10 устройств, то заменить в скрипте только одно значение.
-
Подскажите как сделать нечто подобное чтобы оно работало как задумано:
> /** > * @name Сообщение в Telegram о недоступности > * @desc Уведомление пользователя по Telegram о недоступности оборудования > */ > //const Device1 = DeviceT("SENSOR0"); > > const script = { > check() { > let i; > for(i = 0; i < 10; i++) { > dev = Device("SENSOR" +i); > if(!dev.dval) this.info("telegram", "OWNER", "Внимание! Недоступно устройство '" +dev.name+ "'"); > else this.info("telegram", "OWNER", "Связь с устройством '" +dev.name+ "' восстановлена"); > > this.log(dev.name+ "=" +dev.dval); > } > }, > > start() { > > } > }; >
Если подробнее, то не объявлять в виде констант 100500 устройств (как DeviceT или проверять "вручную" изменение каждого в check), а с помощью цикла в check проверить состояние каждого. Если добавится еще 10 устройств, то заменить в скрипте только одно значение.
Зато будете получать 100500 телеграм-сообщений - при каждой сработке любого устройства такой скрипт выдавал бы сообщение о каждом устройстве, это наверное все же не совсем то, о чем мечтается
Главная цель определения триггера - запуск сценария именно в тот момент, когда с устройством что-то происходит
Можно же один раз сделать один-единственный мультисценарий
/** * @name Сообщение в Telegram о недоступности * @desc Уведомление пользователя по Telegram о недоступности оборудования */ const dev = DeviceT("SensorD"); const script = { start() { if(!dev.dval) this.info("telegram", "OWNER", "Внимание! Недоступно устройство '" +dev.name+ "'"); else this.info("telegram", "OWNER", "Связь с устройством '" +dev.name+ "' восстановлена"); this.log(dev.name+ "=" +dev.dval); } };
И привязывать устройства через Запуск для сценария
-
Можно же один раз сделать один-единственный мультисценарий
Да, вы правы. Как-то я увлекся скриптами…забыв что можно сделать "мультисценарий".
А как убрать из журнала "отладочные" сообщения telegram??? Типа "telegram send: xxx". Ну или сделать как в Berry для GSM-шлюза было:
"SMS +799999 Сообщение отправлено: текст сообщения"
-
@Alexulik:
const script = {
start() {
const temp = 25;
this.assign(dt, "defval", temp);
Видимо так?
Да, все верно, можно так.
Этот сценарий можно привязать к кнопке либо запускать по расписанию.
Если хочется более универсального решения, можно добавить виртуальное устройство Режим (как было в Berry):
1. Добавить устройство с типом Переключатель, назовем его MODE
2. Этому устройству в нижней табличке Состояния сделать: 0 - День 1 - Ночь 2 - Эконом и соотв. картинки
3. Теперь это устройство можно вытащить на интерфейс. Шаблон представления - Переключатель состояния.
Плюс по сравнению с кнопками - отображение текущего состояния.
Его же можно вытащить в виде иконки как индикатор ( то что было в Berry)
4. Сделать сценарий, для которого MODE является триггером и в нем уже менять уставки.
Например, сделаем сценарий, который будет переключать уставки датчику. А сами уставки доступны через интерфейс пользователя.
/** * @name При изменении режима - изменить уставку * @desc * @version */ const mode = DeviceT("ActorE", "Переключатель режима"); const dt = Device("SensorA", "Датчик температуры", [ {"name":"dayTemp", "note": "Целевая днем, С", "type":"number", "val":23}, {"name":"nightTemp", "note": "Целевая ночью, С", "type":"number", "val":21}, {"name":"ecoTemp", "note": "Целевая в режиме эконом, С", "type":"number", "val":19} ]); const script = { start() { if (mode.dval == 0) this.assign(dt, "defval", dt.dayTemp); if (mode.dval == 1) this.assign(dt, "defval", dt.nightTemp); if (mode.dval == 2) this.assign(dt, "defval", dt.ecoTemp); } }
Сделать для нужных датчиков привязку - Запуск для сценария
А можно параметры уставки перенести в Переключатель - тогда для всех будет один температурный режим.
И масса других вариантов …
Естественно, MODE можно переключать сценарием по расписанию