Сценарии пользователей



  • @sergeyygr:

    Спасибо! Но надо только время, без даты.

    Тогда можно так:

    let dt = new Date(); 
    this.log('Время  '+dt.getHours()+":"+dt.getMinutes()+":"+dt.getSeconds() );
    
    
    

    Или так:

    let dt = new Date(); 
    this.log('Время  '+dt.toLocaleString().substr(10))
    
    


  • Задача - Если насос/котел/кран не менял свое состояние (не включался) больше некоторого времени, то включить его на 5 минут и затем выключить. Сам скрипт оказался не таким сложным. Но понадобилось время чтобы в json-конфигах сервера разыскать параметр устройства под названием "lastts" - это время последнего изменения состояния (ON/OFF/TOGGLE) устройства в мс. Параметры устройств нигде не опубликованы, о чем я сожалею. Однако если скрипт оставлять в таком виде, в котором я его привел, то нужно запускать его по расписанию в "cron". Может быть кто-нибудь подскажет - можно ли что-то сделать со StartOnChange или Listener - чтобы сценарий самостоятельно запускался каждую минуту/10 минут/час/день/неделю?

    /** 
    * @name Включение устройств на время 
    * @desc Если прошло больше времени с момента последнего включения чем задано в сценарии, то включаем устройство на некоторое время 
    * @version 4 
    */
    
    const dev = Device("PUMP1"); 
    
    script({
        start() {
          let TurnOnDur = 300;  //Длительность работы в секундах
          let timer = 4;        //Таймер отсчета в часах
          let nowtime = Date.now(); // Текущее время в мс
          let lasttime = dev.getParam('lastts'); //Время изменения состояния в мс
          let diftime = nowtime - lasttime; //Разница в мс
          let dif = diftime/(1000*60*60); //Разница в часах
          let hours = Math.floor(dif);
          let minutes = Math.round((dif-hours)*60);
    
          //this.log(nowtime+ " - " +lasttime+ " = " +diftime);
    
          if(dev.isOff() && dif > timer) {
            this.log(dev.name+ " last ON = " +((hours < 10) ? "0" : "")+hours+ ":" +((minutes < 10) ? "0" : "")+minutes+ " ago > " +timer+ " -> TurnOn by " +TurnOnDur/60+ "min");
            dev.on();
            this.startTimer("T1", TurnOnDur, "TurnOffDev");
          }
          else if(dev.isOn()) {
            this.log(dev.name+ " is ON ~ " +((hours < 10) ? "0" : "")+hours+ ":" +((minutes < 10) ? "0" : "")+minutes+ " -> exit");
          }
          else {
            this.log(dev.name+ " last ON = " +((hours < 10) ? "0" : "")+hours+ ":" +((minutes < 10) ? "0" : "")+minutes+ " ago < " +timer+ " -> exit");
          }
        },
    
        TurnOffDev() {
          dev.off();
          dev.setAuto('True');
        }
    });
    
    
    

    Если это будут читать разработчики iH, то ответьте на мои вопросы: тут и тут.



  • @Alex_Jet:

    Задача - Если насос/котел/кран не менял свое состояние (не включался) больше некоторого времени, то включить его на 5 минут и затем выключить. Сам скрипт оказался не таким сложным. Но понадобилось время чтобы в json-конфигах сервера разыскать параметр устройства под названием "lastts" - это время последнего изменения состояния (ON/OFF/TOGGLE) устройства в мс. Параметры устройств нигде не опубликованы, о чем я сожалею. Однако если скрипт оставлять в таком виде, в котором я его привел, то нужно запускать его по расписанию в "cron". Может быть кто-нибудь подскажет - можно ли что-то сделать со StartOnChange или Listener - чтобы сценарий самостоятельно запускался каждую минуту/10 минут/час/день/неделю?

    > /** 
    > * @name Включение устройств на время 
    > * @desc Если прошло больше времени с момента последнего включения чем задано в сценарии, то включаем устройство на некоторое время 
    > * @version 4 
    > */
    > 
    > const dev = Device("PUMP1"); 
    > 
    > script({
    >     start() {
    >       let TurnOnDur = 300;  //Длительность работы в секундах
    >       let timer = 4;        //Таймер отсчета в часах
    >       let nowtime = Date.now(); // Текущее время в мс
    >       let lasttime = dev.getParam('lastts'); //Время изменения состояния в мс
    >       let diftime = nowtime - lasttime; //Разница в мс
    >       let dif = diftime/(1000*60*60); //Разница в часах
    >       let hours = Math.floor(dif);
    >       let minutes = Math.round((dif-hours)*60);
    >       
    >       //this.log(nowtime+ " - " +lasttime+ " = " +diftime);
    >       
    >       if(dev.isOff() && dif > timer) {
    >         this.log(dev.name+ " last ON = " +((hours < 10) ? "0" : "")+hours+ ":" +((minutes < 10) ? "0" : "")+minutes+ " ago > " +timer+ " -> TurnOn by " +TurnOnDur/60+ "min");
    >         dev.on();
    >         this.startTimer("T1", TurnOnDur, "TurnOffDev");
    >       }
    >       else if(dev.isOn()) {
    >         this.log(dev.name+ " is ON ~ " +((hours < 10) ? "0" : "")+hours+ ":" +((minutes < 10) ? "0" : "")+minutes+ " -> exit");
    >       }
    >       else {
    >         this.log(dev.name+ " last ON = " +((hours < 10) ? "0" : "")+hours+ ":" +((minutes < 10) ? "0" : "")+minutes+ " ago < " +timer+ " -> exit");
    >       }
    >     },
    >     
    >     TurnOffDev() {
    >       dev.off();
    >       dev.setAuto('True');
    >     }
    > });
    > 
    > 
    

    Если это будут читать разработчики iH, то ответьте на мои вопросы: тут и тут.

    Это можно делать используя эмулятор сенсора. В настройках плагина задается период изменения, а сценарий выполняется по признаку startOnChange(sensor_name), либо это не чаще раза в день, то можно запускать сценарий в определенное время каждый день\день месяца\дни недели



  • @homa:

    Это можно делать используя эмулятор сенсора. В настройках плагина задается период изменения, а сценарий выполняется по признаку startOnChange(sensor_name), либо это не чаще раза в день, то можно запускать сценарий в определенное время каждый день\день месяца\дни недели

    Про этот "костыль" я слышал, но не хочется в системе такого уровня использовать подобные вещи. Должно работать либо на основе методов сценария, либо штатным образом, как это делается везде - методом запуска сценариев через cron.



  • @Alex_Jet:

    как это делается везде - методом запуска сценариев через cron.

    Через Cron? Лично для меня это и есть костыль



  • @Alex_Jet:

    Задача - Если насос/котел/кран не менял свое состояние (не включался) больше некоторого времени, то включить его на 5 минут и затем выключить. Сам скрипт оказался не таким сложным. Но понадобилось время чтобы в json-конфигах сервера разыскать параметр устройства под названием "lastts" - это время последнего изменения состояния (ON/OFF/TOGGLE) устройства в мс.

    Не совсем так. lastts - это временная метка не ИЗМЕНЕНИЯ состояния, а получения данных от железа (даже если изменений нет)

    Это время вы видите в меню устройства внизу

    Почему - см ответ в другой теме: https://frm.intrahouse.ru/viewtopic.php?f=18&t=5446&p=8867#p8867

    Для получения времени последнего изменения состояния (переключения) добавим новую функцию сценария в следующем релизе.

    @Alex_Jet:

    Параметры устройств нигде не опубликованы, о чем я сожалею.

    Да, вы правы. Добавим в документацию

    @Alex_Jet:

    Однако если скрипт оставлять в таком виде, в котором я его привел, то нужно запускать его по расписанию в "cron". Может быть кто-нибудь подскажет - можно ли что-то сделать со StartOnChange или Listener - чтобы сценарий самостоятельно запускался каждую минуту/10 минут/час/день/неделю?

    Нет, использовать cron мы не планируем.

    Добавим либо циклический запуск из расписания, либо правило для запуска прямо в сценарии. Эта задача включена в план.

    @Alex_Jet:

    Если это будут читать разработчики iH, то ответьте на мои вопросы:

    Постараемся не только ответить, но и реализовать. Но не все сразу 🙂



  • @intrahouse:

    @Alex_Jet:

    как это делается везде - методом запуска сценариев через cron.

    Через Cron? Лично для меня это и есть костыль

    Ну это образно выражаясь. Cron - это прерогатива ОС, хотя я в своей СУиМ на php/js очень даже успешно использовал этого демона. Я больше к тому, что в движке iH должен быть свой аналог cron.
    @intrapro:

    Постараемся не только ответить, но и реализовать. Но не все сразу 🙂

    А можно тогда комментарии по 1,2,3,4 вопросам, которые озвучивал в посте https://frm.intrahouse.ru/viewtopic.php?f=18&t=5446&start=110#p8771 другой темы?

    PS: я часто сталкиваюсь с тем, что разработчики получат майл/пост на форуме и примут решение действительно что-то реализовать. А спустя день/неделю/месяц выкатывают свое решение (прошивка/новая версия ПО и т.д.). В итоге в это время живешь в условиях "вакуума" - то ли не прочитали, то ли забили, то ли что-то делают? Поэтому стараюсь задавать конкретные вопросы, чтобы получить на них конкретные ответы/комментарии.



  • Господа, дайте примеров сценариев с переключателями, не могу сообразить, просто примеры. Будут ли в "блоках" переключатели?



  • @thunder_d:

    Господа, дайте примеров сценариев с переключателями, не могу сообразить, просто примеры. Будут ли в "блоках" переключатели?

    Конкретизируйте что Вам необходимо реализовать?



  • Нужен переключатель на 10 положений (режимов), чтобы переключал 10 сценариев. 😉



  • Участник @thunder_d написал в Сценарии пользователей:

    Нужен переключатель на 10 положений (режимов), чтобы переключал 10 сценариев. 😉

    Делаете аналоговый актуатор с 10 фиксированными состояниями, и выводите его в интерфейс в виде переключателя.
    А в ваши скрипты добавляете проверку состояния этого актуатора. Если значение нужное - скрипт выполняется.



  • Переключатель уже давно готовый , мне надо пример сценария и только



  • @thunder_d написал в Сценарии пользователей:

    Переключатель уже давно готовый , мне надо пример сценария и только

    Извините за задержку с ответом
    Пример для стандартного переключателя на 3 состояния: Авто - Старт-Стоп
    Используется конструкция JavaScript-а switch
    Каждый вариант - это отдельный case, который должен заканчиваться break

    /** 
    * @name Отработка команд переключателя 
    * @desc  
    * @version 4 
    */
    
    const sw = DeviceT("SWITCH1"); 
    const vent = Device("VENT1"); 
    
    startOnChange(sw);
    
    const script = {
        start() {
          switch (Number(sw.value)) {
    
            case 0: 
                vent.setParam('auto',1);
                this.log('Вентилятор переведен в Авто с переключателя');
                break;
    
             case 1: 
                vent.on();
                this.log('Вентилятор включен с переключателя');
                break; 
    
             case 2: 
                vent.off();
                break; 
    
             // case 3:  ...  все остальные состояния 
          } 
        } 
    };
    

    Если действий много, для каждого варианта можно сделать отдельную функцию:

    /** 
    * @name Переключатель - своя функция для каждого случая
    * @desc  
    * @version 4 
    */
    
    const sw = DeviceT("SWITCH1"); 
    const vent = Device("LAMP1"); 
    
    startOnChange(sw);
    
    const script = {
        start() {
          switch (Number(sw.value)) {
    
            case 0: 
                this.press0();
                break;
    
             case 1: 
                this.press1();
                break; 
    
             case 2: 
                this.press2();
                break; 
          } 
        },
        
        press0() {
          vent.setParam('auto',1);
        },
        
        press1() {
          vent.on();
        },
        
        press2() {
          vent.off();
        }
    };
    

    Обратите внимание, что вызывать функции нужно через this: this.press2();

    Сценарий из сценария вызывать на данный момент нельзя 😞



  • Сенкью вэри мачь. Буду разбираться.



  • Это сообщение удалено!


  • Подскажите, как работать со временем в сценариях? Очень простая задача - сделать будильник (включение/выключение), но время необходимо вводить/изменять в интерфейсе. Понятно, что это можно сделать и через расписание, но как-то тяжело объяснить пожилым людям как им настраивать и изменять расписание ☹
    Так же хотелось бы узнать, можно ли добавить в свойства устройств время? Не временной интервал, а именно время?



  • @gis
    Если с расписанием не хочется работать, то можно сделать например, так:

    /** 
    * @name Управление будильником 
    * @desc  
    * @version 4 
    */
    const clock = Device("alarmClock",  [{"name":"wakeUpTime", "note":"Время будильника", "type":"time", "val":0}]); 
    
    script({
        boot() {
          return true;
        },
        
        start() {
          // Вывести планируемое время при старте - только для отладки. Реально оно будет динамически пересчитываться
          this.log('Планируемое время: '+ this.showWakeUpTime());
            
          // Сразу проверить время, затем проверять каждые 30 сек
          this.manageClock();
          this.startTimer("T1", 30, "onTimer");
        },
        
        onTimer() {
          this.manageClock();
          this.startTimer("T1", 30, "onTimer");
        },
        
        manageClock() {
          const itsTimeToWakeUp = this.checkWakeUpTime();
          if (itsTimeToWakeUp) {
            
            this.log('Будильник: '+ this.showWakeUpTime());
            clock.on(); 
          } else if (clock.isOn()) {
            // В следующем цикле сбросить
            clock.off();
          }
        },
        
        calcWakeUpTime() {
           // К времени от полуночи прибавить временной интервал устройства. Умножить на 1000, так как дате нужны милисекунды  
           return new Date().setHours(0,0,0,0) + clock.getParam('wakeUpTime')*1000;
        },
        
        checkWakeUpTime() {
          // Будильник должен сработать, если текущее время попадает в 30 сек интервал
          return (clock.getParam('wakeUpTime') && Math.abs(Date.now() - this.calcWakeUpTime() ) < 30000);
        },
        
        showWakeUpTime() {
           return new Date(this.calcWakeUpTime()).toLocaleString();
        }
    });
    

    Здесь alarmClock - дискретный актуатор, для которого задаем время сработки будильника как параметр. Используется компонент типа "time", он дает количество секунд. Прибавляем к полуночи и получаем время.

    Сценарий запускается на старте сервера (boot - true) и постоянно активен. Постоянно взводит таймер и проверяет, не пришло ли время звонить. Точность будет зависеть от интервала таймера, здесь - 30 сек, можно сделать и чаще.
    Так как никакого другого события запуска кроме старта сервера нет, при первом запуске или после редактирования сценарий автоматически не запустится, его надо запустить вручную. Штатно он всегда должен быть активен, в Рабочих сценариях должна быть зеленая галочка.

    Дальше можно доработать сценарий с учетом дня недели - задать для каждого дня время или просто checkbox-ы - должен сработать или нет в конкретный день. Также можно использовать механизм auto или дополнительные флаги для включения - отключения функции.
    Для самого устройства (его ведь придется вынести на интерфейс, чтобы устанавливать время) вероятно нужно настроить Действие при нажатии - off или даже none.



  • Спасибо большое! Попробую реализовать.



  • Добрый вечер! Есть связка RPi4 + Mega (пока по USB). Подскажите, как работать с Serial для выдачи команды в канал от IHS к устройству, подключенному к Ардуино, и приема из канала ответа устройства, подключенного к Ардуино? Только по Modbus, или есть еще какие решения? Заранее спасибо!



  • Участник @kostinanton написал в Сценарии пользователей:

    Добрый вечер! Есть связка RPi4 + Mega (пока по USB). Подскажите, как работать с Serial для выдачи команды в канал от IHS к устройству, подключенному к Ардуино, и приема из канала ответа устройства, подключенного к Ардуино? Только по Modbus, или есть еще какие решения? Заранее спасибо!

    Только по Modbus. Других вариантов сейчас нет


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