Свет по датчику движения с дополнительными условиями.
-
Здравствуйте.
Дополнительные условия следующие:
- Нужно, чтобы сценарий не срабатывал, если свет включен выключателем на стене (чтобы не отключался по таймеру)
- Чтобы сценарий не срабатывал, если включен режим охраны.
На основе шаблона сделал сценарий.
const lamp = Device("ActorD", "Светильник"); const sw = Device("SensorD", "Выключатель"); const motion = Device("SensorD", "Датчик движения"); const SAF = Device("ActorD","Охрана"); // Запустим сценарий при сработке датчика движения, если светильник не горит, режим охраны отключен, выключатель выключен. startOnChange([motion], motion.isOn() && lamp.isOff() && sw.isOFF() && SAF.isOFF()); script ({ start() { lamp.on(); // взводим таймер, чтобы отключить this.startTimer("T1", 180, "turnOff"); }, // Функция, которая сработает, когда таймер досчитает - отключаем и выходим turnOff() { lamp.off(); // this.exit(); Эту команду можно не ставить, сценарий и сам завершится } });
Сценарий не запустился ни разу. Хотя датчик присутствия срабатывает. Пи уменьшении количества условий он начинает иногда срабатывать.
ПОменял скрипт на следующий
const lamp = Device("ActorD", "Светильник"); const sw = Device("SensorD", "Выключатель"); const motion = Device("SensorD", "Датчик движения"); const SAF = Device("ActorD","Охрана"); // Запустим сценарий при сработке датчика движения, если светильник не горит, режим охраны отключен, выключатель выключен. startOnChange([motion], motion.isOn()); script ({ start() { if ((SAF.value === 0) && (sw.value === 0) && (lamp.value === 0)) { lamp.on(); // взводим таймер, чтобы отключить this.startTimer("T1", 180, "turnOff"); } }, // Функция, которая сработает, когда таймер досчитает - отключаем и выходим turnOff() { lamp.off(); // this.exit(); Эту команду можно не ставить, сценарий и сам завершится } });
Скрипт запускается, но.
Запустить второй раз сразу после выключения света по таймеру не получается.
Второй рах скрипт срабатывает только через какое-то время, которое мне определить не удалось.
Датчик движения срабатывает, а свет не включается, если он только что выключился.Что может влиять? К факту выключения света привязат скрипт включения ветнилятора на 2 минуты.
Может быть из-за него?const lamp = Device("ActorD", "Светильник"); const vent = Device("ActorD","Вентилятор"); // Запустим сценарий при сработке датчика движения, если светильник не горит, режим охраны отключен, выключатель выключен. startOnChange([lamp], lamp.isOff() && vent.isOff()); script ({ start() { vent.on(); // взводим таймер, чтобы отключить this.startTimer("T1", 120, "turnOff"); }, // Функция, которая сработает, когда таймер досчитает - отключаем и выходим turnOff() { vent.off(); // this.exit(); Эту команду можно не ставить, сценарий и сам завершится } });
Таймеры в скриптах по разному обозвать? Если таймеры - у меня это мультисценарии. Все равно будет другой набор устройств с тем же названием таймера, который попытается запуститься одновременно (свет в туалете и свет в ванной, например).
Или с состоянием ламп.исОфф задержки?
Куда смотреть?
-
И еще вопрос.
Как при включенном по датчику движения свете по повторному срабатыванию датчика движения обнулять таймер?
При условии if ((SAF.value === 0) && (sw.value === 0) && (lamp.value == 1)) проверить, что таймер запущен, и обнулить его (тот же самый таймер).
-
@Erik Добрый день
На основе шаблона сделал сценарий.
... startOnChange([motion], motion.isOn() && lamp.isOff() && sw.isOFF() && SAF.isOFF());
Сценарий не запустился ни разу. Хотя датчик присутствия срабатывает. При уменьшении количества условий он начинает иногда срабатывать.
Это условие не работает, так как синтаксис sw.isOFF() не опознается. Большие/малые буквы в JavaScript очень важны!! Должно быть sw.isOff()
ПОменял скрипт на следующий
startOnChange([motion], motion.isOn()); script ({ start() { if ((SAF.value === 0) && (sw.value === 0) && (lamp.value === 0)) { lamp.on(); // взводим таймер, чтобы отключить this.startTimer("T1", 180, "turnOff"); } }, // Функция, которая сработает, когда таймер досчитает - отключаем и выходим turnOff() { lamp.off(); // this.exit(); Эту команду можно не ставить, сценарий и сам завершится } });
Скрипт запускается, но.
Запустить второй раз сразу после выключения света по таймеру не получается.
Второй рах скрипт срабатывает только через какое-то время, которое мне определить не удалось.
Датчик движения срабатывает, а свет не включается, если он только что выключился.Что может влиять? К факту выключения света привязат скрипт включения ветнилятора на 2 минуты.
Может быть из-за него?
Таймеры в скриптах по разному обозвать? ...Нет, связи между экземплярами сценария даже по одному мультисценарию никакой нет. У вас сценарии управляют разными устройствами, то есть полностью независимы.
Скорее не проходит проверка условия со строгим равенством
Замените условие на один из трех вариантов (любой)if (SAF.isOff() && sw.isOff() && lamp.isOff()) { // ИЛИ if (!SAF.value && !sw.value && !lamp.value) { // ИЛИ if ((SAF.value == 0) && (sw.value == 0) && (lamp.value == 0)) {
-
Участник @intrapro написал в Свет по датчику движения с дополнительными условиями.:
lamp.value == 0)
Не дает исправить на ==
Ну и спустя какое то время он выполняется. Только сразу после выключения почему-то нет.
Поэтому не понятно, почему проверка в одном случае проходит, во втором нет.
-
Участник @Erik написал
И еще вопрос.
Как при включенном по датчику движения свете по повторному срабатыванию датчика движения обнулять таймер?
При условии if ((SAF.value === 0) && (sw.value === 0) && (lamp.value == 1)) проверить, что таймер запущен, и обнулить его (тот же самый таймер).
Для этого нужно добавить внутрь сценария "слушателя событий"
script({ start() { if ((SAF.value === 0) && (sw.value === 0) && (lamp.value === 0)) { lamp.on(); // взводим таймер, чтобы отключить this.startTimer("T1", 180, "turnOff"); // Добавляем слушателей - следим за датчиком движения и светильником this.addListener(motion, "onMotion"); this.addListener(lamp, "onLamp"); } }, onMotion() { // Если движение возобновилось - сбрасываем таймер if (motion.isOn() ) { this.stopTimer("T1"); } // Если движение прекратилось - взводим таймер (после повторных движений) if (motion.isOff() && this.timer.T1 == "off") { this.startTimer("T1", 180, "turnOff"); } }, onLamp() { // Светильник выключили другим способом - выходим if (lamp.isOff()) this.exit(); }, // Функция, которая сработает, когда таймер досчитает - отключаем и выходим turnOff() { lamp.off(); this.exit(); // Здесь exit нужен, так как есть активные слушатели и сценарий сам не завершится } });
Более подробно про механизм работы сценариев - https://ih-systems.com/ru/about-scenes/
Если коротко:-
Если внутри сценария просто последовательность действий, он отработает и сразу завершится (станет не активным). При следующем запуске он опять начнется со start(). Большая часть сценариев работает именно так и 99,9% времени находятся в неактивном состоянии.
-
Если сценарий взводит таймеры и/или устанавливает слушателя событий устройства, то он остается активным, следит за своими таймерами и устройствами «изнутри» и выполняет действия как реакцию на отслеживаемые события. Стартовое событие не работает, так как сценарий уже активен.. В рабочих сценариях в левом столбце у сценариев, активных в данный момент, стоит зеленая галочка.
Чтобы завершить такой сценарий, нужно выполнить команду this.exit().
При завершении сценария все его таймеры и слушатели удаляются. При следующем запуске опять выполнится start()
-
-
@Erik Это warning, можете его игнорировать, если вы все же остановились на этом варианте Строгое равенство предполагает ноль как число. Возможно в каком-то случае ноль приходит как строка или булево значение.
-
Участник @intrapro написал в Свет по датчику движения с дополнительными условиями.:
@Erik Это warning, можете его игнорировать, если вы все же остановились на этом варианте Строгое равенство предполагает ноль как число. Возможно в каком-то случае ноль приходит как строка или булево значение.
Почему потом срабатывает то? кто его трансформирует из строки в число?
-
@Erik Вы можете посмотреть в отладчике сценария и добавить логирование:
start() { this.log(`SAF=${SAF.value} sw=${sw.value} lamp=${lamp.value}`); // используется обратная кавычка! if ((SAF.value === 0) && (sw.value === 0) && (lamp.value === 0)) { lamp.on(); ..... } else { this.log('Условия не выполнены'); } },
Собственно, для того чтобы не возникало таких вопросов существуют функции isOff() и isOn()
-
Участник @intrapro написал в [Свет по датчику движения с дополнительными условиями.]
Для этого нужно добавить внутрь сценария "слушателя событий"
Спасибо огромное!
Добавил еще слушатель на выключатель. Если включить выключатель, все таймеры выключатся, и отключения не произойдет.
/** * @name Свет в комнате по движению * @desc * @version 4 */ const Lamp = Device("ActorD", "Светильник"); const Sw = Device("SensorD", "Выключатель"); const Motion = Device("SensorD", "Датчик движения"); const SAF = Device("ActorD","Охрана"); // Запустим сценарий при сработке датчика движения, если светильник не горит, режим охраны отключен, выключатель выключен. startOnChange([Motion], Motion.isOn() && Lamp.isOff() && Sw.isOff() && SAF.isOff()); script({ start() { Lamp.on(); // взводим таймер, чтобы отключить this.startTimer("T1", 180, "turnOff"); // Добавляем слушателей - следим за датчиком движения и светильником this.addListener(Motion, "onMotion"); this.addListener(Lamp, "onLamp"); this.addListener(Sw, "onSw"); }, onMotion() { // Если движение возобновилось - сбрасываем таймер if (Motion.isOn() ) { this.stopTimer("T1"); } // Если движение прекратилось - взводим таймер (после повторных движений) if (Motion.isOff() && this.timer.T1 == "off") { this.startTimer("T1", 180, "turnOff"); } }, onLamp() { // Светильник выключили другим способом - выходим if (Lamp.isOff()) this.exit(); }, onSw() { // Светильник выключили другим способом - выходим if (Sw.isOn() ) { this.stopTimer("T1"); this.exit(); } }, // Функция, которая сработает, когда таймер досчитает - отключаем и выходим turnOff() { Lamp.off(); this.exit(); // Здесь exit нужен, так как есть активные слушатели и сценарий сам не завершится } });
-
Есть вопрос со сценарием.
Был такой сценарий.
/** * @name Свет в комнате по движению * @desc * @version 4 */ const Lamp = Device("ActorD", "Светильник"); const Sw = Device("SensorD", "Выключатель"); const Motion = Device("SensorD", "Датчик движения"); const SAF = Device("ActorD","Охрана"); // Запустим сценарий при сработке датчика движения, если светильник не горит, режим охраны отключен, выключатель выключен. startOnChange([Motion], Motion.isOn() && Lamp.isOff() && Sw.isOff() && SAF.isOff()); script({ start() { Lamp.on(); // взводим таймер, чтобы отключить this.startTimer("T1", 180, "turnOff"); // Добавляем слушателей - следим за датчиком движения и светильником this.addListener(Motion, "onMotion"); this.addListener(Lamp, "onLamp"); this.addListener(Sw, "onSw"); }, onMotion() { // Если движение возобновилось - сбрасываем таймер if (Motion.isOn() ) { this.stopTimer("T1"); } // Если движение прекратилось - взводим таймер (после повторных движений) if (Motion.isOff() && this.timer.T1 == "off") { this.startTimer("T1", 180, "turnOff"); } }, onLamp() { // Светильник выключили другим способом - выходим if (Lamp.isOff()) this.exit(); }, onSw() { // Светильник выключили другим способом - выходим if (Sw.isOn() ) { this.stopTimer("T1"); this.exit(); } }, // Функция, которая сработает, когда таймер досчитает - отключаем и выходим turnOff() { Lamp.off(); this.exit(); // Здесь exit нужен, так как есть активные слушатели и сценарий сам не завершится } });
Все работало.
Добавил одну строку - вывод сообщения о последнем движении./** * @name Свет в комнате по движению * @desc * @version 4 */ const Lamp = Device("ActorD", "Светильник"); const Sw = Device("SensorD", "Выключатель"); const Motion = Device("SensorD", "Датчик движения"); const SAF = Device("ActorD","Охрана"); const Last = Device("ActorA","Последнее движение"); // Запустим сценарий при сработке датчика движения, если светильник не горит, режим охраны отключен, выключатель выключен. startOnChange([Motion], Motion.isOn() && Lamp.isOff() && Sw.isOff() && SAF.isOff()); script({ start() { Lamp.on(); Last.setValue(`Последнее движение ${new Date().toLocaleString()}. ${motion.zoneName}`); // взводим таймер, чтобы отключить this.startTimer("T1", 180, "turnOff"); // Добавляем слушателей - следим за датчиком движения и светильником this.addListener(Motion, "onMotion"); this.addListener(Lamp, "onLamp"); this.addListener(Sw, "onSw"); }, onMotion() { // Если движение возобновилось - сбрасываем таймер if (Motion.isOn() ) { this.stopTimer("T1"); } // Если движение прекратилось - взводим таймер (после повторных движений) if (Motion.isOff() && this.timer.T1 == "off") { this.startTimer("T1", 180, "turnOff"); } }, onLamp() { // Светильник выключили другим способом - выходим if (Lamp.isOff()) this.exit(); }, onSw() { // Светильник выключили другим способом - выходим if (Sw.isOn() ) { this.stopTimer("T1"); this.exit(); } }, // Функция, которая сработает, когда таймер досчитает - отключаем и выходим turnOff() { Lamp.off(); this.exit(); // Здесь exit нужен, так как есть активные слушатели и сценарий сам не завершится } });
В результате свет загорается, сообщение выводится, но больше свет не выключается.
Похоже, что после присвоения значения актуатору "последнее движение" скрипт останавливается.Что не так?
В отладчике это
59 Now is NOT active. 22.12 18:38:42.431 S59(,LAMP13,SENSOR6,SMOTION5,ACTOR1,ACTORA79) Check(SMOTION5) => true 22.12 18:38:42.433 S59(,LAMP13,SENSOR6,SMOTION5,ACTOR1,ACTORA79) Started 22.12 18:38:42.434 S59(,LAMP13,SENSOR6,SMOTION5,ACTOR1,ACTORA79) do LAMP13 on 22.12 18:38:42.437 S59(,LAMP13,SENSOR6,SMOTION5,ACTOR1,ACTORA79) Stopped 22.12 18:38:57.433 S59(,LAMP13,SENSOR6,SMOTION5,ACTOR1,ACTORA79) Check(SMOTION5) => false
Слушатели не запустились.
-
Участник @Erik написал в Свет по датчику движения с дополнительными условиями.:
Похоже, что после присвоения значения актуатору "последнее движение" скрипт останавливается.
В Рабочих сценариях должна быть ошибка типа: "motion is not defined", так как название устройства Motion должно быть с большой буквы.
Так должно работать:Last.setValue(`Последнее движение ${new Date().toLocaleString()}. ${Motion.zoneName}`);
-
@intrapro
Заработало, спасибо.