В связи с выходом крупного обновления 5.9.х, приглашаем вас принять участие в вебинаре 09.06.2022 в 15:00. Участвовать

Свет по датчику движения с дополнительными условиями.



  • Здравствуйте.

    Дополнительные условия следующие:

    1. Нужно, чтобы сценарий не срабатывал, если свет включен выключателем на стене (чтобы не отключался по таймеру)
    2. Чтобы сценарий не срабатывал, если включен режим охраны.
      На основе шаблона сделал сценарий.
    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)

    Не дает исправить на ==
    alt text

    Ну и спустя какое то время он выполняется. Только сразу после выключения почему-то нет.
    Поэтому не понятно, почему проверка в одном случае проходит, во втором нет.



  • Участник @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
    Заработало, спасибо.


Log in to reply