Сценарии - новая версия API



  • @Lost, эта уставка оперативно! меняется из веб-интерфейса через "Параметры" устройства (всплывающее меню устройства при долгом клике мышью).



  • @Alex_Jet, это я уже понял. Получается в самом сценарии значение val задается только первый раз, а дальше менять его либо командами либо из веб?



  • @Lost, просто из веб. Ну или в случае различных уставок в течении суток, то из сценария.



  • Понятно. Спасибо!



  • Добрый вечер!
    Столкнулся с интересной ситуацией. В сценарии был запущен таймер:
    this.startTimer("T1", 0.5, "onTimerT1").
    И так получилось, что до момента его срабатывания произошло выполнение следующей команды:
    this.startTimer("T1", 55, "turnOff").
    И после отработки выдержки 0.5 сек (задавалась в первой команде) выполнилась функция turnOff. Хотелось бы узнать, тут все верно или есть "косячок"?



  • @Lost, наверное логично поскольку в обоих случаях таймеры называются одинаково!



  • @Alex_Jet, получается не очень логично. Исполняемая функция изменилась, а время работы таймера - нет. Как то половинчато получается.



  • @Lost, пробовали таймеры называть своими именами? Или хотя бы явно объявлять их в начале сценария?



  • @Alex_Jet, да, таймер объявлен в самом начале сценария: this.addTimer('T1');
    А что это меняет?



  • @Lost, смысл в том что JS-многопоточный! Вы запускаете T1 на 0,5 секунды и параллельно тот же T1 запускается на 55 секунд (по идее его сработка на 0,5 секунд должна отмениться). Не знаю как движок системы в этом случае себя должен вести, но по мне - случайным образом... поэтому если нужно взводить несколько таймеров, то называйте их по разному.



  • Добрый вечер!
    Заметил, что если после команды this.exit() есть еще какой либо код, то он вполне себе исполняется. Вот пример:
    start() {
    this.off();
    },
    off() {
    this.log('сценарий запущен');
    this.exit();
    this.log('1');
    this.log('2');
    this.log('3');
    this.log('4');
    this.log('5');
    this.log('6');
    this.log(6 + 10);
    }
    });
    Лог отладчика:
    07.02 20:01:55.351 Started
    07.02 20:01:55.352 log: сценарий запущен
    07.02 20:01:55.369 exit
    07.02 20:01:55.370 Stopped
    07.02 20:01:55.371 log: 1
    07.02 20:01:55.375 log: 2
    07.02 20:01:55.377 log: 3
    07.02 20:01:55.380 log: 4
    07.02 20:01:55.383 log: 5
    07.02 20:01:55.385 log: 6
    07.02 20:01:55.388 log: 16
    Разве так и должно быть? Ранее в этой теме писалось, что по этой команде все таймеры и слушатели сценария удаляются и сценарий станет не активным. Я так понимаю, что после this.exit() сценарий должен сразу завершиться..



  • @intrapro, в продолжении вот этого топика...
    Все работало хорошо при существующем startOnChange и check(). Перенес все настройки системы вентиляции в свойства sw_pvu и чтобы при любом "чихе" не происходило сработки системы добавил в check() и ValveControl() дополнительные условия this.isChanged().
    Однако в связи с определенными обстоятельствами понадобилось чтобы в зимних условиях установка отключалась когда tempOut < уставки1 и включалась снова при tempOut > уставка2, поэтому сделал функцию CheckTempOut(), которую запускает this.addListener(tempOut, "CheckTempOut") когда система вентиляции включиться. В таком случае сценарий всегда в работе и по сути ни startOnChange, ни check() не принимают участия в работе сценария. Пока установка выключена по температуре, клапаны вентиляции могут отключиться. Значит и для них нужны тоже слушатели. Столкнулся с тем что из CheckTempOut() не могу дернуть ValveControl() как раз из-за this.isChanged()... в итоге добавил новый "флаг" - start_pvu, если он установлен то ValveControl() запустится, иначе нет. Сценарий по моему получился очень сложным. Как профессионал подскажите - может можно было все сделать легче?

    //Переключатель работы ПВУ и настройка опций
    const sw_pvu      = Device("SWITCH_PVU", [
      {"name":"timeOpenValves", "note":"Время открытия клапанов, сек.:", "type":"number", "val":20},
      {"name":"timeCloseValves", "note":"Время закрытия клапанов, сек.:", "type":"number", "val":10},
      {"name":"startTimeWork", "note":"Время начала работы 'Full speed':", "type":"time", "val":0},
      {"name":"endTimeWork", "note":"Время окончания работы 'Full speed':", "type":"time", "val":0},
      {"name":"tempOutMin", "note":"Минимальная температура на выходе:", "type":"number", "val":1},
      {"name":"tempOutNorm", "note":"Нормальная температура на выходе:", "type":"number", "val":15},
      {"name":"logcb", "note":"Уведомление в журнале", "type":"cb", "val":1}
    ]);
    
    //Актуаторы включения скорости 1-3 у вентиляторов ПВУ
    const vent_s1     = Device("VENT_PVU1");
    const vent_s2     = Device("VENT_PVU2");
    const vent_s3     = Device("VENT_PVU3");
    
    //Клапаны системы вентиляции
    const valveIn     = Device("VALVE_AIR1");   //Клапан на входе ПВУ
    const valveOut    = Device("VALVE_AIR2");   //Клапан на выходе ПВУ
    const valve1F     = Device("VALVE_AIR3");   //Клапан первого этажа
    const valve2F     = Device("VALVE_AIR4");   //Клапан второго этажа
    const valveLD     = Device("VALVE_AIR5");   //Клапан прачечной
    
    //Датчики и нагреватель ПВУ
    const tempIn      = Device("STEMP_PVU1");   //Температура на входе ПВУ
    const tempOut     = Device("STEMP_PVU2");   //Температура на выходе ПВУ
    const tempAirFlow = Device("STEMP_PVU3");   //Температура на притоке ПВУ
    const heaterAir   = Device("PUMP5");        //Насос жидкостного нагревателя
    
    startOnChange([sw_pvu,valve1F,valve2F,valveLD]);
    
    script({
      state_pvu: 0,   //0-выключена, 1-выключена по температуре, 2-включена
      start_pvu: 0,   //Флаг запуска системы (после остановки по температуре)
      message: '',
      
        check() {
          let auto = valveIn.auto && valveOut.auto && (sw_pvu.value == 1);
          
          //Проверка основных условий
          return auto && ( this.isChanged(sw_pvu, "value") || this.isChanged(valve1F, "value") || this.isChanged(valve2F, "value") || this.isChanged(valveLD, "value") );
        },
      
        start() {
          this.ValveControl();
        	this.startTimer("Add_Listener", 5, "AddListener");
        },
        
        AddListener() {
          //this.addListener(sw_pvu, "OnSw");
          this.addListener(tempOut, "CheckTempOut");
        	this.addListener(valve1F, "ValveControl");
        	this.addListener(valve2F, "ValveControl");
        	this.addListener(valveLD, "ValveControl");
        },
        
        //Реализация автоматической работы системы вентиляции
        ValveControl() {
          //Если состояние системы "Выключено" или "Включено" и производится старт системы или изменено состояние расходных клапанов
          if(this.state_pvu != 1 && (this.start_pvu || this.isChanged(valve1F, "value") || this.isChanged(valve2F, "value") || this.isChanged(valveLD, "value"))) {
            
            //Включение системы если открыт хотя бы один клапан вентиляции
       	    if(this.SumOpenValves()) {
              //Если входной и выходной клапан закрыты, то включаем систему
              if(valveIn.isOff() || valveOut.isOff()) this.TurnOn();
              //Иначе управляем только скоростью
              else this.SpeedControl();
              this.SendMessage(2);
       	    }
       	    //Выключение системы если все клапаны закрыты
       	    else {
       	      this.TurnOff();
       	      this.SendMessage(0);
       	    }
          }
        },
        
        //Реализация защиты от перемерзания рекуператора
        CheckTempOut() {
          if(this.isChanged(tempOut, "value")) {
          
            //Определение уставок
            let ust_min = sw_pvu.getParam("tempOutMin");
            let ust_max = sw_pvu.getParam("tempOutNorm");
            
            //Если температура минимум и система включена
            if((tempOut.value <= ust_min) && this.state_pvu == 2) {
              this.start_pvu = 0;     //Флаг запуска системы обнулен
              this.TurnOffTemp();     //Отключение системы по температуре
              this.SendMessage(1);
            }
            //Если температура нормальная и система выключена по температуре
            else if((tempOut.value >= ust_max) && this.state_pvu == 1) {
              this.start_pvu = 1;     //Флаг запуска системы установлен
              this.state_pvu = 2;     //Состояние ПВУ - "Включена"
              this.ValveControl();
            }
          }
        },
        
        //Вывод информации о работе в журнал
        SendMessage(variant) {
          //Если установлен соответствующий чек-бокс
          if(sw_pvu.getParam("logcb")) {
            let message = "Вентиляция. ";
            
            if(variant === 0) {
              message += "Все клапаны закрыты, ПВУ выключена";
            }
            else if(variant == 1) {
              message += "ПВУ выключена из-за низкой температуры!";
            }
            else if(variant == 2) {
              if(this.SumOpenValves() == 1) message += "Открыт - ";
              else if(this.SumOpenValves() > 1) message += "Открыты - ";
              
              if(valve1F.value) message += "'" +valve1F.name+ "', ";
              if(valve2F.value) message += "'" +valve2F.name+ "', ";
              if(valveLD.value) message += "'" +valveLD.name+ "', ";
              
              if(!this.GetStatusTime()) message += "установлена скорость 1";
              else message += "установлена скорость " +this.SumOpenValves();
            }
            
            this.log(message);
          }
        },
        
        //Функция определения количества включенных клапанов
        SumOpenValves() {
          return valve1F.value + valve2F.value + valveLD.value;
        },
        
        //Функция контроля скорости вентиляторов
        SpeedControl() {
          if(!this.GetStatusTime()) this.Speed1();
          else this.SpeedChange();
        },
        
        //Функция изменения скорости вентиляторов
        SpeedChange() {
        	switch(this.SumOpenValves()) {
        	  case 1: this.Speed1();
        	          break;
          	case 2: this.Speed2();
        	          break;
          	case 3: this.Speed3();
        	          break;
      	  }
        },
        
        //Функция выключения системы
        TurnOff() {
          this.state_pvu = 0;   //Состояние ПВУ - "Выключена"
          this.ValvesOff();     //Закрытие клапанов с задержкой выключения вентиляторов
          this.startTimer("Close_Valves", sw_pvu.getParam("timeCloseValves"), "TurnOffVent");
        },
        
        //Функция выключения системы по тмпературе
        TurnOffTemp() {
          this.state_pvu = 1;   //Состояние ПВУ - "Выключена по температуре"
          this.ValvesOff();     //Закрытие клапанов с задержкой выключения вентиляторов
          this.startTimer("Close_Valves_ByTemp", sw_pvu.getParam("timeCloseValves"), "TurnOffVentByTemp");
        },
        
        //Функция включения системы
        TurnOn() {
          this.state_pvu = 2;   //Состояние ПВУ - "Включена"
          this.ValvesOn();      //Открытие клапанов с задержкой включения вентиляторов
          this.startTimer("Open_Valves", sw_pvu.getParam("timeOpenValves"), "SpeedControl");
        },
        
        //Функция получения статуса работы по времени
        GetStatusTime() {
          let date = new Date();
          let time = 3600*date.getHours() + 60*date.getMinutes() + date.getSeconds();
          let startTimeWork = sw_pvu.getParam("startTimeWork");
          let endTimeWork = sw_pvu.getParam("endTimeWork");
          
          if(time > startTimeWork && time < endTimeWork)
            return 1; //Текущее время совпадает с рабочим диапазоном времени
          else
            return 0; //Текущее время НЕ совпадает с рабочим диапазоном времени
        },
        
        ValvesOn() {
          valveIn.turnOnSaveAuto();
          valveOut.turnOnSaveAuto();
        },
        
        ValvesOff() {
          valveIn.turnOffSaveAuto();
          valveOut.turnOffSaveAuto();
        },
        
        Speed1() {
          vent_s2.off();
          vent_s3.off();
          vent_s1.on();
        },
        
        Speed2() {
          vent_s1.off();
          vent_s3.off();
          vent_s2.on();
        },
        
        Speed3() {
          vent_s1.off();
          vent_s2.off();
          vent_s3.on();
        },
        
        TurnOffVentByTemp() {
          vent_s1.off();
          vent_s2.off();
          vent_s3.off();
        },
        
        TurnOffVent() {
          vent_s1.off();
          vent_s2.off();
          vent_s3.off();
          this.exit();
        }
    });
    

    И да - очень долго не мог понять как правильно выйти из сценария чтобы завершилась работа всех слушателей. this.exit(), как понял останавливает и слушателей, и таймеры. Но главным образом смущал такой лог:

    18.02 17:57:17.536 listener on event VALVE_AIR5: ValveControl
    18.02 17:57:17.536 exec function ValveControl
    18.02 17:57:17.537 do VALVE_AIR1 aoff 
    18.02 17:57:17.538 do VALVE_AIR2 aoff 
    18.02 17:57:17.593 start timer Close_Valves for 10 sek
    18.02 17:57:17.594 log: Вентиляция. Все клапаны закрыты, ПВУ выключена
    18.02 17:57:27.608 Done timer Close_Valves
    18.02 17:57:27.609 exec function TurnOffVent
    18.02 17:57:27.609 do VENT_PVU1 off 
    18.02 17:57:27.611 do VENT_PVU2 off 
    18.02 17:57:27.620 do VENT_PVU3 off 
    18.02 17:57:27.622 exit
    18.02 17:57:27.623 Stopped
    18.02 17:57:48.262 isChanged(SWITCH_PVU,dval)=false Changed: {"VALVE_AIR5":{"auto":1}}
    18.02 17:57:48.263 isChanged(VALVE_AIR3,dval)=false Changed: {"VALVE_AIR5":{"auto":1}}
    18.02 17:57:48.263 isChanged(VALVE_AIR4,dval)=false Changed: {"VALVE_AIR5":{"auto":1}}
    18.02 17:57:48.263 isChanged(VALVE_AIR5,dval)=false Changed: {"VALVE_AIR5":{"auto":1}}
    18.02 17:57:48.264 Check(VALVE_AIR5) => false
    

    Вроде произошел exit, но все равно появились 5 последних строчек...



  • Здравствуйте! Можно ли сделать сценарий, чтобы он отображался в виде кнопки в боковом меню устройства!
    5073f31a-1ae7-4970-924a-ee4dbec841bf-image.png
    или
    b8a92964-43f2-448d-be18-961a695743bf-image.png
    Кнопка с ссылкой, при нажатии которой происходит переход по адресу в браузер.



  • @konia74 выбрать мнемосхему где хотите что бы она визуализировалась, нажать на "+", примитивы и выбрать кнопка, а потом на ету кнопку назначить выполнение сценария.



  • @amgstone Кнопка должна находится именно в боковом меню устройства, которое открывается после долгого нажатия на устройство. Чтобы было понятнее кратко опишу идею: устройство с прошивкой для ws2812 WLED имеет очень широкий функционал но реализовать его (кроме вкл/выкл и изменения цветов) в IH нет возможности и смысла. Поэтому хочу сделать дополнительную кнопку в боковом меню выключателя, по нажатию на которую будет переход в браузер на адрес ip устройства, где уже будут все настройки устройства 9c917862-0565-4ad6-8050-e445ee4bf940-image.png

    Проблема в написании сценария, я не знаком с языками программирования.



  • подскажите как в этом сценарии передавать на виртуальное устройство температуру каждых 5 минут а не при каджом изменении температуры?

    /** 
    * @name Середня температура будинку 
    * @desc  
    * @version 4 
    */
    const temp_bedroom = Device("STEMP1");
    const temp_korudor = Device("STEMP11"); 
    const temp_vana = Device("STEMP12");
    const temp_hall = Device("STEMP5"); 
    const temp_danulo = Device("STEMP6"); 
    const temp_sofija = Device("STEMP7"); 
    const temp_kamina = Device("STEMP8"); 
    const temp_kitchen = Device("STEMP9"); 
    const temp_house = Device("Stemp_house");
    
    startOnChange([temp_bedroom,temp_korudor,temp_vana,temp_hall,temp_danulo,temp_sofija,temp_kamina,temp_kitchen]); 
    
    script({
        start() {
         let temp_house_t= (temp_bedroom.value+temp_korudor.value+temp_vana.value+temp_hall.value+temp_danulo.value+temp_sofija.value+temp_kamina.value+temp_kitchen.value)/7;
         this.assign(temp_house, "value", temp_house_t.toFixed(2));
        } 
    });
    
    


  • @amgstone при первом изменении температуры вы можете запустить таймер и записать среднюю температуру через 5 минут, и снова вызвать таймер и так бесконечно. Или вызывать сценарий периодически в расписании, только удалите функцию StartOnChange.



  • Добрый вечер! Подскажите где найти сценарий Управление поливом, смотрел видео с версией Berry и там использовался такой сценарий, планирую использовать в версии Cherry на MegaD.



  • Такой сценарий создать просто. Вам нужно создать два сценария, которые включают и выключают полив и настроить вызов этих сценариев через расписание. Это если по простому, но у вас может свой алгоритм работы.



  • @goodspeed1986 спасибо, но чтобы его создать нужно оттолкнуться хотьб от маломальского похожего сценария, в котором я бы смог что-то менять и экспериментировать, так как мне это ещё сложно.


Log in to reply