Сценарии в intraHouse Cherry



  • @zahar69:

    Совсем запутался в скобках. Где можно скачать учебник для чайников по скриптам? Я очень далек от этого. в Берри было проще. 😞

    Сценарии пишутся на Javascript, в сети полно руководств, думаю не обязательно читать целый учебник, достаточно освоить введение 🙂

    В данном случае одна скобка { лишняя и нет последней закрывающей }. И в команде do вместо actor д б RADIATOR1.

    Все остальное верно

    const STEMP1 = Device("SensorA","Датчик темп Лиза"); 
    const RADIATOR1 = Device("ActorD","Батарея Лиза"); 
    
    const script = {
    	check() {
    		return (STEMP1.aval < 25 && !RADIATOR1.dval) || (STEMP1.aval > 30 && RADIATOR1.dval); 
    	}, 
    	start() {
    		if (STEMP1.aval < 25 && !RADIATOR1.dval) { this.do(actor, 'on'); } // Здесь д б RADIATOR1
    		// { <= Вот эта скобка лишняя.
           		 else if (STEMP1.aval > 30 && RADIATOR1.dval) { this.do(RADIATOR1, 'off'); }
    	}
    } // Здесь нужна последняя закрывающая скобка для script
    
    
    

    Javascript в отличие от Питона не требователен к отступам, переносам строк и т.д.

    Но существует правило, что после каждой открывающей скобкой делается отступ (табуляция, два пробела, что угодно - но всегда одинаково)

    Где ставить открывающую скобку - ведутся споры и даже религиозные войны:) Это относится ко многим языкам, не только Javascript.

    Есть два основных варианта:

    1. Открывающая и закрывающая ставится на одной линии в отдельной строке

    	if (STEMP1.aval < 25 && !RADIATOR1.dval)
    	{ 
    		this.do(actor, 'on'); 
    	}
    
    
    

    2. Открывающая ставится в конце строки без переноса, зато закрывающая - в отдельной строке

    	if (STEMP1.aval < 25 && !RADIATOR1.dval) { 
    		this.do(actor, 'on'); 
    	}
    
    
    

    Из-за некоторых особенностей Javascript-a обычно используется второй способ.

    Но в сценариях можно использовать любой, если он кажется легче. Главное - всегда делать это одинаково, тогда не запутаешься 🙂

    И две хорошие новости:

    1. Если после if одна команда - {} можно не ставить совсем. Но лучше тогда все писать в одну строку

    	if (STEMP1.aval < 25 && !RADIATOR1.dval)  this.do(actor, 'on'); 
    
    
    

    2. Если условия одновременно не выполняются, else можно не писать.

    То есть скрипт можно написать так:

    const STEMP1 = Device("SensorA","Датчик темп Лиза"); 
    const RADIATOR1 = Device("ActorD","Батарея Лиза"); 
    
    const script = {
    	check() {
    		return (STEMP1.aval < 25 && !RADIATOR1.dval) || (STEMP1.aval > 30 && RADIATOR1.dval); 
    	}, 
    
    	start() {
    		if (STEMP1.aval < 25 && !RADIATOR1.dval) this.do(RADIATOR1, 'on'); 
           		if (STEMP1.aval > 30 && RADIATOR1.dval)  this.do(RADIATOR1, 'off'); 
    	}
    } 	
    
    
    

    И после редактирования сценария нужно его сохранить и возможно обновить страницу до ввода параметров.

    @zahar69:

    в Берри было проще. 😞

    Конечно, будет и интерактивный способ настройки простых сценариев. Хочется сделать гибко, но не громоздко.

    Примеры шаблонных сценариев тоже за нами. Выложим в ближайшие дни.



  • Выложили шаблоны сценариев https://intrahouse.ru/scenes-examples_ru/

    Их можно устанавливать двумя способами.

    1. Загрузить zip файл со сценарием https://intrahouse.ru/work-scenes_ru/

    2. Copy/Paste. Просто скопировать текст скрипта, добавить новый сценарий и вставить туда скопированный текст.

    Также как в Berry, остается только привязать устройства к сценарию. При этом, при желании, можно корректировать сценарий.

    Вариантов разных сценариев может быть много. Мы можем написать и опубликовать любые сценарии. Но желательно чтобы эти сценарии были востребованы и другими пользователями. Спрашивайте, обсуждайте функционал сценария, а мы реализуем.

    Это не исключает самостоятельного написания сценариев. Если кто-то поделится своим скриптом, очень хорошо.



  • Спасибо большое!

    Думаю, многим это будет интересно

    Чтобы еще больше облегчить жизнь тем, кто захочет загрузить Ваш сценарий, сохраняйте его в zip как файл с расширением .js, а не .txt. А еще проще - сохраняйте прямо в Project Manager в списке сценариев командой "Выгрузить в файл".

    Intrahouse_scenes.png

    Тогда командой "Загрузить из файла" сценарий сразу загрузится в проект.



  • А где задается заданная температура отопления?



  • @intrapro:

    Спасибо большое!

    Думаю, многим это будет интересно

    Чтобы еще больше облегчить жизнь тем, кто захочет загрузить Ваш сценарий, сохраняйте его в zip как файл с расширением .js, а не .txt. А еще проще - сохраняйте прямо в Project Manager в списке сценариев командой "Выгрузить в файл".

    Intrahouse_scenes.png

    Тогда командой "Загрузить из файла" сценарий сразу загрузится в проект.

    Перевыгрузил. Предыдущий пост тогда лучше удалить, чтобы никого не смущать.

    Управление светом
    отключить_весь_свет.zip
    управление_светом_с_дополнительного_выключателя.zip
    включение-выключение_дополнительного_освещения_с_основным.zip



  • Управление вытяжкой\замком
    открытие_электрозамка_на_время.zip
    управление_вытяжкой_по_влажности.zip
    автоматическое_отключение_вытяжки.zip



  • @zahar69:

    А где задается заданная температура отопления?

    В пользовательском интерфейсе при длинном нажатии на датчик температуры вызывается окно свойств датчика.

    Там слайдером можно менять уставку температуры.
    frm1011.jpg



  • А можно для необразованных разжевать - как шаблонный сценарий привязать к устройствам? В Berry было все тривиально…тут затрудняюсь.



  • @Alex_Jet:

    А можно для необразованных разжевать - как шаблонный сценарий привязать к устройствам? В Berry было все тривиально…тут затрудняюсь.

    Вся настройка сценариев - в разделе Сценарии. Если сам сценарий уже есть (скачан или написан), то заполняются строчки в табличке "Запуск для устройств". Конечно, сделать это можно только для мультисценариев (шаблонных в терминологии Berry)

    scenecall1.png
    Просто выбираются устройства из списка устройств подходящего класса

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

    Как результат все рабочие сценарии, включая только что добавленный, можно увидеть в списке Рабочие сценарии.

    Там есть информация об активных сценариях, времени последнего запуска и т д
    workscenes.png
    Если сценарий имеет триггеры, то он запускается по событиям этих триггеров (Сценарии по событию в Berry)

    Если триггеров нет - это интерактивные сценарии, их можно вызывать с кнопки, по расписанию и тд

    Наличие триггеров у сценария определяется неявно по функции check()

        check() {
            return ((lamp.auto == 1) && ((lamp.dval == 0) && (motion.dval == 1) || (lamp.dval > 0)));  
        },
    
    
    

    Все устройства, включенные в check, являются триггерами - в данном случае lamp и motion

    Если check возвращает true, то сценарий запускается (выполняется функция start) - примерно также как в Berry

    Интерактивный сценарий не должен иметь check, если его запустили - он должен сработать, нужные проверки выполняются уже внутри запущенного сценария.



  • Добрый день!

    @sergeyygr:

    Можно ли сделать так, что бы в процессе привязки датчика и устройства была строка для написания текста для отправки по e-mail с целью конкретного указания места, где сработал датчик. А то иметь на каждую группу устройств по индивидуальному сценарию не очень удобно.

    Да, предложение хорошее - вместе с набором устройств добавлять дополнительные параметры при настройке в PM. Подумаем над реализацией.

    Но в данном случае решение есть - можно в текст включить данные устройства в любой комбинации

    sensor.name - название датчика

    sensor.nameOf("place") - название уровня

    sensor.nameOf("room") - название зоны

    sensor.nameOf("subs") - название подсистемы

    sensor.getPlaceDesc() - уровень и зона вместе, разделяются символом /: "1 этаж/Котельная"

    Если уровня или зоны нет - выдается то что есть, без разделителя

    Например:

      this.info("email", "OWNER", "Тревога! "+ sensor.nameOf("place")+" "+sensor.nameOf("room")+". Сработал "+sensor.name)
    
    
    

    Сформирует сообщение: "Тревога! 1 этаж Холл. Сработал Датчик движения"

    Или

      this.info("email", "OWNER", actor2.nameOf("place") + ": Включена сирена! Движение "+ sensor.getPlaceDesc())
    
    
    

    Сформирует сообщение: "Гараж: Включена сирена! Движение 1 этаж/Коридор"



  • @intrapro:

    Добрый день!

    @sergeyygr:

    Можно ли сделать так, что бы в процессе привязки датчика и устройства была строка для написания текста для отправки по e-mail с целью конкретного указания места, где сработал датчик. А то иметь на каждую группу устройств по индивидуальному сценарию не очень удобно.

    Да, предложение хорошее - вместе с набором устройств добавлять дополнительные параметры при настройке в PM. Подумаем над реализацией.

    Но в данном случае решение есть - можно в текст включить данные устройства в любой комбинации

    sensor.name - название датчика

    sensor.nameOf("place") - название уровня

    sensor.nameOf("room") - название зоны

    sensor.nameOf("subs") - название подсистемы

    sensor.getPlaceDesc() - уровень и зона вместе, разделяются символом /: "1 этаж/Котельная"

    Если уровня или зоны нет - выдается то что есть, без разделителя

    Например:

    >   this.info("email", "OWNER", "Тревога! "+ sensor.nameOf("place")+" "+sensor.nameOf("room")+". Сработал "+sensor.name)
    > 
    > 
    

    Сформирует сообщение: "Тревога! 1 этаж Холл. Сработал Датчик движения"

    Или

    >   this.info("email", "OWNER", actor2.nameOf("place") + ": Включена сирена! Движение "+ sensor.getPlaceDesc())
    > 
    > 
    

    Сформирует сообщение: "Гараж: Включена сирена! Движение 1 этаж/Коридор"

    А нет никакой инструкции вцелом по работе с плагином email? Задумка отправлять в заданный день месяца показания счётчиков на емэйл в УК и себе, но не представляю как это реализовать.



  • Недоступен для скачивания сценарий "Управление батареями отопления по датчикам температуры"…

    Расскажите про добавление в сценарии пользовательских настроек. Например, делаю так:

    const heater = Device("ActorD", "Нагреватель", [
      {"name":"hist", "note":"Гистерезис включения/отключения актюатора, °C", "type":"number", "val":0.2}
      ]);
    
    

    Но какое значение может быть в type чтобы hist можно было менять с точностью 0,05 градуса, например.



  • @Alex_Jet:

    Недоступен для скачивания сценарий "Управление батареями отопления по датчикам температуры"…

    Проверим

    @Alex_Jet:

    Расскажите про добавление в сценарии пользовательских настроек. Например, делаю так:

    > const heater = Device("ActorD", "Нагреватель", [
    >   {"name":"hist", "note":"Гистерезис включения/отключения актюатора, °C", "type":"number", "val":0.2}
    >   ]);
    > 
    

    Но какое значение может быть в type чтобы hist можно было менять с точностью 0,05 градуса, например.

    Для "type":"number" в пользовательском интерфейсе можно ввести вручную любое число, в том числе с любым числом знаков после запятой.

    • и - использовать не обязательно. Планируем шаг для +- также сделать настаиваемыми из сценария, но пока этого нет 😞

    Другие варианты:

    "type":"cb" - checkbox,

    "type":"time" - настройка времени - часы, минуты, секунды



  • @sergeyygr:

    Добрый день всем!!!

    Реализовал в своем сценарии передачу сообщения на e-mail при работке датчика движения (this.info("email", "OWNER", "Тревога! "+ sensor.nameOf("place")+" "+sensor.nameOf("room")+". Сработал "+sensor.name)). Усложняем задачу!

    В контроллере MegaD-2561 реализована возможность передачи и приема SMS сообщений https://ab-log.ru/page.php?Cat=110&ID=195&q=sim800.

    Из темы:

    Входящее SMS-сообщение передается на сервер следующим образом.

    /script.php?sms_phone=+79000001234&sms_text=hello

    Сервер также может через контроллер отправлять произвольные сообщения. Для этого необходимо отправить запрос следующего вида.

    http://192.168.0.14/sec/?sms=Alarm!&phone=+79000000000

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

    Добрый день!

    Для этого есть функция сценария plugincommand(pluginID, obj), но пока плагин MegaD такую функцию не поддерживает 😞

    Добавим в ближайшее время.

    Также, конечно, очень интересная тема по приему входящих sms через MegaD.

    Планируем сделать модуль для обработки входящих сообщений (sms, telegram и др)



  • В скрипте требуется для работы оборудования только в ночное время сравнить текущее время с заданным пользователем. Как это записать? Я конечно понимаю что есть объект Date() c атрибутами getHours, getMinutes и можно условие записать как if( new Array(date.getHours(), date.getMinutes()) > new Array(21,00) ). Но проверка синтаксиса ругается на эту строчку в скрипте. Поэтому как это сделать в iH?



  • @Alex_Jet:

    В скрипте требуется для работы оборудования только в ночное время сравнить текущее время с заданным пользователем. Как это записать? Я конечно понимаю что есть объект Date() c атрибутами getHours, getMinutes и можно условие записать как if( new Array(date.getHours(), date.getMinutes()) > new Array(21,00) ). Но проверка синтаксиса ругается на эту строчку в скрипте. Поэтому как это сделать в iH?

    А для чего Array? Например, ночное время с 21 до 6.

    if ((new Date().getHours() > 21) || (new Date().getHours() < 6)) ....
    
    
    

    А лучше один раз считать, потом проверять

    let dt = new Date();
    if ((dt.getHours()>21) || (dt.getHours()<6))
    
    
    


  • @intrapro:

    @Alex_Jet:

    В скрипте требуется для работы оборудования только в ночное время сравнить текущее время с заданным пользователем. Как это записать? Я конечно понимаю что есть объект Date() c атрибутами getHours, getMinutes и можно условие записать как if( new Array(date.getHours(), date.getMinutes()) > new Array(21,00) ). Но проверка синтаксиса ругается на эту строчку в скрипте. Поэтому как это сделать в iH?

    А для чего Array? Например, ночное время с 21 до 6.

    > if ((new Date().getHours() > 21) || (new Date().getHours() < 6)) ....
    > 
    > 
    

    А лучше один раз считать, потом проверять

    > let dt = new Date();
    > if ((dt.getHours()>21) || (dt.getHours()<6))
    > 
    > 
    

    Array для того чтобы проверять часы и минуты. Иногда недостаточно только часов. У меня вот утром свет в 6.45 включается, а выключается в 7.20 когда уезжаю. Неужели проверка синтаксиса на Array ругается?



  • @Alex_Jet:

    if( new Array(date.getHours(), date.getMinutes()) > new Array(21,00) ). Но проверка синтаксиса ругается на эту строчку в скрипте. ….

    Иногда недостаточно только часов. У меня вот утром свет в 6.45 включается, а выключается в 7.20 когда уезжаю. Неужели проверка синтаксиса на Array ругается?

    Скрипт не понимает, что такое date.getHours()

    И в целом так не получится. В JS массивы так не сравнивают.

    Могу предложить такой однострочный вариант (некрасивый, но рабочий)

    if (new Date().getHours()*100+new Date().getMinutes() > 2100)
    
    
    


  • @intrapro:

    И в целом так не получится. В JS массивы так не сравнивают.

    Я не стал особо заморачиваться минимизацией кода и написал, надеюсь, понятную пользователям функцию. "Настройка" простая, использование проще некуда.

        getStatusTime() {
          let date = new Date();
          let time = new Array(date.getHours(), date.getMinutes());
          let timeMon = new Array(09,10); //Время начала работы
          let timeEve = new Array(21,30); //Время окончания работы
          if(time[0]*60 + time[1] >= timeMon[0]*60 + timeMon[1] && time[0]*60 + time[1] <= timeEve[0]*60 + timeEve[1])
            return 1; //Текущее время совпадает с рабочим диапазоном времени
          else
            return 0; //Текущее время НЕ совпадает с рабочим диапазоном времени
        },
    
    

    Применение:

                if(this.getStatusTime())
                this.speed1();
                else
                this.speed2();
    
    

    Вопросы:

    1. Какой синтаксис чтобы в таймере исполнять не функцию, а сделать действие по окончании счета?

    this.startTimer("T1", 20, "turnOffVent");
    
    

    2. Как в функции в таймер передать значение времени из переменной? Чего-то догадаться не могу:( отладки такой как в Chrome нет…



  • @Alex_Jet:

    1. Какой синтаксис чтобы в таймере исполнять не функцию, а сделать действие по окончании счета?

    Действие все равно нужно оборачивать в анонимную callback-функцию.

    Для удобства трассировки и контроля сценариев анонимные функции в сценариях не используются.

    @Alex_Jet:

    2. Как в функции в таймер передать значение времени из переменной?

    Нужно объявить переменные на уровне объекта - сценария.

    Дальше к ним обращение через this.

    Эти переменные сохраняют значение пока сервер не перезагружен (т е запуск-останов сценария не приводит к сбросу значений).

    Можно создавать сколько угодно переменных любых типов. В данном случае создаем три массива, первый - пустой.

    Для отладки (и записи в журнал) можно использовать this.log():

    const script = {
        curTime:[], 
        timeMon:[9,10],
        timeEve:[21,30],
    
        start() {
           let date = new Date();
           curTime[0] = date.getHours();
           curTime[1] = date.getMinutes());
           this.startTimer("T1", 20, "turnOffVent");
        },
    
        turnOffVent() {
             this.log('Current time='+this.curTime.join(':'));
        	 if(this.getStatusTime()) {
        	 ....
        	 }
        },
    
        getStatusTime() {
          return ((this.curTime[0]*60 + this.curTime[1] >= this.timeMon[0]*60 +this.timeMon[1]) 
             && (this.curTime[0]*60 + this.curTime[1] <= this.timeEve[0]*60 + this.timeEve[1])) ? 1 : 0;
        },
        ....
     }     
    
    
    

Log in to reply