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



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


Авторизуйтесь, чтобы ответить