Сценарии - новая версия API
-
@intrapro да, ноль становится строкой) будем конвертировать в число) спасибо
-
@intrapro, а проблему когда остановленные сценарии (Рабочие сценарии) восстанавливаются после перезагрузки iH так и не победили???
-
подскажите как можно
this.pluginCommand({unit:'megad3', command:'/258/?cmd='+jalusi.getParam('point_open')+':1;p200;'+jalusi.getParam('point_open')+':0'});
как можно получить обратную связь, тоесть узнать статус канала после завершения паузы.
или нужно создать виртуальное устройство которое будет поддерживать управление 2 реле (каналы), каждый из которых изменяет статус на время работы мотора. У меня роллеты которые подключены к мегаД, на открытие и закрытые используется отдельные реле, срабатывают реле только когда жалюзи закрываются или открываются, в остальное время статус реле открытое (0).
-
@amgstone, у Вас просто не верное решение используется - вы передаете полную команду с сервера на MegaD. Но MegaD конечно это отрабатывает, правда есть оговорки по этому поводу. Однако сам сервер iH может выдержать любую паузу! Поэтому стоит сделать так:
//В основном цикле this.pluginCommand({unit:'megad3', command:'/258/?cmd='+jalusi.getParam('point_open')+':1'}); this.startTimer("T1", 0.200, "Stop_Jalusi"); //Функция остановки жалузи Stop_Jalusi() { this.pluginCommand({ unit:"megad3", command:{url:"/258/?cmd=" +jalusi.getParam('point_open')+":0", onResponse:[{id:"jalusi.getParam('point_open')",value:"OFF"}]} }); this.exit(); }
onResponse - это как раз callback сработки канала (когда на команду контроллер отвечает Done), в данном случае - MegaD. Не особо понимаю что за дополнительный параметр у Вас - jalusi.getParam('point_open'), но в данном случае именно он примет значение OFF принудительно когда канал MegaD будет выключен.
Вообще для включения/выключения устройств я в некоторых сценариях применяю такую связку:
//Включаем устройство, если оно выключено и ждем изменение его состояния if(this.device.isOff()) { this.device.on(); this.addListener(this.device, 'Function') } //Эта функция запускается когда произошло изменение состояния устройства Function() { //Тут что-то делаем this.exit(); //Принудительно выходим из сценария чтобы завершились слушатели }
-
@Alex_Jet спасибо, сегодня попробую а то эти ролокасети это предпоследний минингит.
-
подскажите как можно сделать очередь отправки команд на MegaD, не могу добится чтобы на одной меге отрабатывали сразу 2 команды, посылаю 2 команды 1 останавливается а 2 начинает отрабатывать
/** * @name Новый мультисценарий * @desc * @version 4 */ const switch_1 = Device("ActorE","Switch"); const jalusi = Device("ActorD","Actor",[ {"name":"point_open", "note":"Пін відкриття", "type":"number", "val":15}, {"name":"point_close", "note":"Пін закриття", "type":"number", "val":16} ]); startOnChange([switch_1,jalusi]); script({ start() { if(this.isChanged(switch_1)){ this.onSwitch(); } if(this.isChanged(jalusi)){ this.onJalusi(); } }, onSwitch(){ switch(switch_1.value){ case 0: if(jalusi.id === "ACTOR7"){ this.pluginCommand({unit:'megad3', command:'/258/?cmd='+jalusi.getParam('point_open')+':1' }); this.startTimer("T1", 20, "Stop_Jalusi_up"); } if(jalusi.id === "ACTOR8"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_open')+':1'}); this.startTimer("T1", 40, "Stop_Jalusi_up"); } if(jalusi.id === "ACTOR9"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_open')+':1'}); this.startTimer("T1", 60, "Stop_Jalusi_up"); } break; case 1: break; case 2: if(jalusi.id === "ACTOR7"){ this.pluginCommand({unit:'megad3', command:'/258/?cmd='+jalusi.getParam('point_close')+':1'}); this.startTimer("T1", 20, "Stop_Jalusi_down"); } if(jalusi.id === "ACTOR8"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_close')+':1'}); this.startTimer("T1", 40, "Stop_Jalusi_down"); } if(jalusi.id === "ACTOR9"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_close')+':1'}); this.startTimer("T1", 60, "Stop_Jalusi_down"); } break; } this.log('Жалюзі статус : '+switch_1.value+' '+jalusi.id); }, onJalusi(){ if(jalusi.isOn()){ if(jalusi.id === "ACTOR7"){ this.pluginCommand({unit:'megad3', command:'/258/?cmd='+jalusi.getParam('point_open')+':1'}); this.startTimer("T1", 20, "Stop_Jalusi_up"); } if(jalusi.id === "ACTOR8"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_open')+':1'}); this.startTimer("T1", 40, "Stop_Jalusi_up"); } if(jalusi.id === "ACTOR9"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_open')+':1'}); this.startTimer("T1", 60, "Stop_Jalusi_up"); } }else{ if(jalusi.id === "ACTOR7"){ this.pluginCommand({unit:'megad3', command:'/258/?cmd='+jalusi.getParam('point_close')+':1'}); this.startTimer("T1", 20, "Stop_Jalusi_down"); } if(jalusi.id === "ACTOR8"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_close')+':1'}); this.startTimer("T1", 40, "Stop_Jalusi_down"); } if(jalusi.id === "ACTOR9"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_close')+':1'}); this.startTimer("T1", 60, "Stop_Jalusi_down"); } } }, Stop_Jalusi_up() { if(jalusi.id === "ACTOR7"){ this.pluginCommand({unit:'megad3', command:'/258/?cmd='+jalusi.getParam('point_open')+':0', onResponse:[{id:"jalusi.getParam('point_open')",value:"ON"}]}); } if(jalusi.id === "ACTOR8"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_open')+':0', onResponse:[{id:"jalusi.getParam('point_open')",value:"ON"}]}); } if(jalusi.id === "ACTOR9"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_open')+':0', onResponse:[{id:"jalusi.getParam('point_open')",value:"ON"}]}); } }, Stop_Jalusi_down() { if(jalusi.id === "ACTOR7"){ this.pluginCommand({unit:'megad3', command:'/258/?cmd='+jalusi.getParam('point_close')+':0', onResponse:[{id:"jalusi.getParam('point_close')",value:"OFF"}]}); } if(jalusi.id === "ACTOR8"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_close')+':0', onResponse:[{id:"jalusi.getParam('point_close')",value:"OFF"}]}); } if(jalusi.id === "ACTOR9"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_close')+':0', onResponse:[{id:"jalusi.getParam('point_close')",value:"OFF"}]}); } } });
-
@amgstone, очередь отправки команд на контроллер формирует плагин, команды отправляются последовательно по мере поступления. У Вас не работает управление двумя одновременно?
Посмотрите, что происходит в отладчике плагина.
-
Если кому будет интересно сценарий для роллет:
/** * @name Новый мультисценарий * @desc * @version 4 */ const switch_1 = Device("ActorE","Switch"); const jalusi = Device("ActorD","Actor",[ {"name":"point_open", "note":"Пін відкриття", "type":"number", "val":15}, {"name":"point_close", "note":"Пін закриття", "type":"number", "val":16} ]); startOnChange([switch_1,jalusi]); script({ start() { if(this.isChanged(switch_1)){ this.onSwitch(); } if(this.isChanged(jalusi)){ if(switch_1.value===1){ this.onJalusi(); } } }, onSwitch(){ switch(switch_1.value){ case 0: if(jalusi.isOff()){ if(global.get('jalusi_work')){ global.set('jalusi_count',global.get('jalusi_count')+1); this.log('Жалюзі статус : jalusi_count : '+global.get('jalusi_count')); this.startTimer("T1"+global.get('jalusi_count'), global.get('jalusi_time'), "Start_Jalusi_up"); global.set('jalusi_time',(global.get('jalusi_time')+28)); }else{ global.set('jalusi_work',true); this.log('Жалюзі статус : '+jalusi.id); global.set('jalusi_count',1); global.set('jalusi_time',28); this.startTimer("T11", 0.100, "Start_Jalusi_up"); } } break; case 1: global.remove('jalusi_work'); global.remove('jalusi_count'); break; case 2: if(jalusi.isOn()){ if(global.get('jalusi_work')){ global.set('jalusi_count',global.get('jalusi_count')+1); this.log('Жалюзі статус : jalusi_count : '+global.get('jalusi_count')); this.startTimer("T1"+global.get('jalusi_count'), global.get('jalusi_time'), "Start_Jalusi_down"); global.set('jalusi_time',(global.get('jalusi_time')+28)); }else{ global.set('jalusi_work',true); this.log('Жалюзі статус : '+jalusi.id); global.set('jalusi_count',1); global.set('jalusi_time',28); this.startTimer("T11", 0.100, "Start_Jalusi_down"); } } break; } }, onJalusi(){ if(switch_1.value===1){ if(jalusi.isOn()){ if(global.get('jalusi_work')){ global.set('jalusi_count',global.get('jalusi_count')+1); this.log('Жалюзі статус : jalusi_count : '+global.get('jalusi_count')); this.startTimer("T1"+global.get('jalusi_count'), global.get('jalusi_time'), "Start_Jalusi_up"); global.set('jalusi_time',(global.get('jalusi_time')+28)); }else{ global.set('jalusi_work',true); this.log('Жалюзі статус : '+jalusi.id); global.set('jalusi_count',1); global.set('jalusi_time',28); this.startTimer("T11", 0.100, "Start_Jalusi_up"); } }else{ if(global.get('jalusi_work')){ global.set('jalusi_count',global.get('jalusi_count')+1); this.log('Жалюзі статус : jalusi_count : '+global.get('jalusi_count')); this.startTimer("T1"+global.get('jalusi_count'), global.get('jalusi_time'), "Start_Jalusi_down"); global.set('jalusi_time',(global.get('jalusi_time')+28)); }else{ global.set('jalusi_work',true); this.log('Жалюзі статус : '+jalusi.id); global.set('jalusi_count',1); global.set('jalusi_time',28); this.startTimer("T11", 0.100, "Start_Jalusi_down"); } } } }, Start_Jalusi_up(){ jalusi.on(); this.log('Жалюзі статус : Start_Jalusi_up '+jalusi.id); switch(jalusi.id){ case "ACTOR7": this.pluginCommand({unit:'megad3', command:'/258/?cmd='+jalusi.getParam('point_open')+':1;'}); break; case "ACTOR8": this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_open')+':1;'}); break; case "ACTOR9": this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_open')+':1;'}); break; } this.startTimer("T2", 25, "Stop_Jalusi_up"); }, Start_Jalusi_down(){ jalusi.off(); this.log('Жалюзі статус : Start_Jalusi_down '+jalusi.id); switch(jalusi.id){ case "ACTOR7": this.pluginCommand({unit:'megad3', command:'/258/?cmd='+jalusi.getParam('point_close')+':1;'}); break; case "ACTOR8": this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_close')+':1;'}); break; case "ACTOR9": this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_close')+':1;'}); break; } this.startTimer("T2", 25, "Stop_Jalusi_down"); }, Stop_Jalusi_up() { global.set('jalusi_count',global.get('jalusi_count')-1); this.log('Жалюзі статус : Stop_Jalusi_up '+jalusi.id+' jalusi_count : '+global.get('jalusi_count')); switch(jalusi.id){ case "ACTOR7": this.pluginCommand({unit:'megad3', command:'/258/?cmd='+jalusi.getParam('point_open')+':0;'}); break; case "ACTOR8": this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_open')+':0;'}); break; case "ACTOR9": this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_open')+':0;'}); break; } global.set('jalusi_work',false); if(global.get('jalusi_count')===0){ switch_1.setValue(1); } this.log('End Jalusi Up'); }, Stop_Jalusi_down() { global.set('jalusi_count',global.get('jalusi_count')-1); this.log('Жалюзі статус : Stop_Jalusi_down '+jalusi.id+' jalusi_count : '+global.get('jalusi_count')); switch(jalusi.id){ case "ACTOR7": this.pluginCommand({unit:'megad3', command:'/258/?cmd='+jalusi.getParam('point_close')+':0;'}); break; case "ACTOR8": this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_close')+':0;'}); break; case "ACTOR9": this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_close')+':0;'}); break; } global.set('jalusi_work',false); if(global.get('jalusi_count')===0){ switch_1.setValue(1); } this.log('End Jalusi Down'); } });
-
можно в блок схеме передать значение?
start() { mid.setValue([10011, 20]); // id 0 - 8, 10 - 13, 20 - 29, custom 10001 | vol 0 - standart, 10 - 100 } });
-
Подскажите как в блок схеме (http://joxi.ru/1A5JM43SDpdwbr) добавить возможность чтобы рас в сутку срабатывал вентилятор на определенное время даже если влажность не достигла заданой.
-
@amgstone
Отдельный скрипт и запуск его по расписанию.
-
Коллеги, переписываю сценарии под версию 4. И чтобы не сломать систему отопления) подскажите как правильно присваивать уставки температурным датчикам?
Сейчас это делается так - this.assign(dt, "defval", dt.nightTemp);
Сейчас нужно сделать вероятно dt.setpoint(dt.nightTemp)??? Или, скорее всего даже вот так: dt.setpoint( dt.getParam("ecoTemp") )???
-
@Alex_Jet
Совершенно верно, параметры в сценарии напрямую не доступны, нужно использовать getParam("имя параметра") / setParam("имя параметра", значение).Просто dt.setpoint - это значение уставки. Для уставки есть специальная команда setSetpoint (да, довольно коряво )
Другой вариант - любое свойство можно присвоить с помощью setParam.
Таким образом, есть два варианта:dt.setSetpoint( dt.getParam("nightTemp") )
или
dt.setParam( "setpoint", dt.getParam("nightTemp") )
-
Коллеги, у меня почему-то в связке с "Актуатор аналоговый универсальный" не работает слушатель..., точнее сценарий зависает. Имею такой код:
if(this.device.isOff()) { this.device.on(); this.addListener(this.device, 'TTStoVTdevOn'); }
В отладчике - вижу включение актуатора и все...после этого надо скрипт либо пересохранить, либо принудительно остановить. С "Актуатор дискретный универсальный" все работает как надо!
Если строчку this.addListener(this.device, 'TTStoVTdevOn'); закомментировать, то все работает.Идея состояла в том, что как только актуатор изменит свое состояние (включится), то сообщать об этом пользователю.
-
@Alex_Jet, покажите весь сценарий. Или хотя бы функции start и TTStoVTdevOn.
И что за устройство this.device? Меняется динамически внутри сценария?
-
@intrapro, если Вам сильно нужно...правда это получится то же самое что я разбираюсь в ваших кодах)))
/** * @name VoiceTerminal - управление устройствами * @desc При возникновении событий от голосового терминала выполнить действия * @version 4 */ //Константы для погоды const dt_s = Device("STEMP4_01"); const dh_s = Device("SHUMIDITY4_01"); //Константы для отопления const dt_supply = Device("ST_HEATING_SYS_01"); const dt_hydro = Device("ST_HEATING_SYS_03"); const dt_floor1 = Device("ST_HEATING1_02"); const dt_floor2 = Device("ST_HEATING2_02"); //Константы для вентиляции const sw_pvu= Device("SWITCH_PVU"); //Константы для охраны const guard = Device("ACTOR_SECURITY_SYS00"); //Константы для освещения const lamp_guest = Device("LAMP1_01"); const lamp_kitchen = Device("LAMP1_03"); const lamp_small_corridor = Device("LAMP1_05"); const lamp_washroom = Device("LAMP1_06"); const lamp_big_corridor = Device("LAMP1_08"); const lamp_lobby = Device("LAMP1_09"); const lamp_boiler_room = Device("LAMP1_11"); const lamp_laundry_room = Device("LAMP1_12"); const lamp_veranda = Device("LAMP4_01"); const lamp_porch = Device("LAMP4_02"); //Константы для других систем const garland_house = Device("ACTORA_GARLAND1_01"); script({ unit1: "voiceterminal1", unit2: "voiceterminal2", unit_com: "tts", string: "", //Вспомогательная переменная device: "", //Переменная для устройства terminal: "", //Переменная для имени терминала period: "", //Переменная для периода дня arr: [], hello: ["Доброе утро!","Добрый день!","Добрый вечер!","Доброй ночи!"], answerToYouarehere: ["Конечно я тут!","А где я должна быть?","Нет, я в кинотеатре","Странный вопрос","Да, гуляю по дому..."], answerToHey: ["Чем могу помочь?","Что мне сделать для вас?","Какую команду выполнить?"], answerToWhoareyou: ["Я обученный интеллект вашего дома","Я просто программа","Я черная коробочка со светодиодами","Я маленький сервер"], answerToWelldone: ["Спасибо, мне очень приятно!","Да, я такая!","Ой, как приятно!","Спасибо за благодарность!"], answerToFool: ["Извините меня, я не специально!","Я что-то не так сделала?","Я иногда не понимаю что вы хотите от меня!","Прошу понять меня и простить!"], answerToThanks: ["Не за что!","Пожалуйста!","Пожалуйста, я старалась!","Нет проблем!","Велл кам!","Wellcom!"], doIt: ["Сделала!","Без проблем!","Выполнила!","Хорошо!","Все сделано!"], doNotKnowCommand: ["Я не знаю такой команды","Я не поняла вас","Что-то меня сбило","Вероятно я не верно услышала команду"], start(param) { const obj = JSON.parse(param); this.terminal = obj.terminal; this.qry = obj.qry.toLowerCase(); this.rms = obj.rms_avg; //let message = []; //Для дебага входящих сообщений //this.log("### Receive message from - " +this.terminal+ ". Username - " +obj.username+ ". Qry - " +obj.qry+ ". RMS = " +obj.rms_avg); /* message.push(Date.now(), obj.terminal, obj.username, obj.qry.toLowerCase(), obj.rms_avg); this.arr.push(message); if(this.arr.length > 3) { //if(this.arr[1] - this.arr[0] < 100) { //} this.arr = []; } this.log(this.arr); this.log(this.arr.length); */ //Установка громкости терминала в зависимости от периода дня this.SetVolumeTerminal(); //Голосовой терминал VT1 if(this.terminal == "VT1" || this.terminal == "VT2") { //Обработка фраз для формирования интеллектуального образа помощника if( this.qry.indexOf("ты тут") >= 0 || this.qry.indexOf("ты здесь") >= 0 ) { let number = this.GetRandomInt(0, this.answerToYouarehere.length); let answer = this.answerToYouarehere[number]; if(obj.username == "aleksey") this.string = "Привет, Алексей! " +answer; else if(obj.username == "dima") this.string = "Привет, Дима! " +answer; else if(obj.username == "nadia") this.string = "Привет, Надежда! " +answer; else if(obj.username == "voiceterminal") this.string = "Да, но мои голосовые модели нужно усовершенствовать"; else this.string = "Привет, я вас не узнала. Вы кто?"; this.CommandToVoiceTerminal(); } else if( this.qry.indexOf("привет") >= 0 ) { this.unit_com = "ask"; let number = this.GetRandomInt(0, this.answerToHey.length); this.string = this.GetPeriodDay()+ " " +this.answerToHey[number]; this.CommandToVoiceTerminal(); this.unit_com = "tts"; } else if( this.qry.indexOf("человек") >= 0 || this.qry.indexOf("кто ты") >= 0 ) { let number = this.GetRandomInt(0, this.answerToWhoareyou.length); this.string = this.answerToWhoareyou[number]; this.CommandToVoiceTerminal(); } else if( this.qry.indexOf("умница") >= 0 || this.qry.indexOf("молодец") >= 0 ) { let number = this.GetRandomInt(0, this.answerToWelldone.length); this.string = this.answerToWelldone[number]; this.CommandToVoiceTerminal(); } else if( this.qry.indexOf("дура") >= 0 ) { let number = this.GetRandomInt(0, this.answerToFool.length); this.string = this.answerToFool[number]; this.CommandToVoiceTerminal(); } else if( this.qry.indexOf("спасибо") >= 0 ) { let number = this.GetRandomInt(0, this.answerToThanks.length); this.string = this.answerToThanks[number]; this.CommandToVoiceTerminal(); } else if( this.qry.indexOf("как дела") >= 0 ) { if(guard.value) this.string = "Дом под охраной! "; else this.string = "Дом снят с охраны! "; //Подсчет проникновений и озвучивание let disturbance = global.get('Counter_OpenWindow'); let disturbance_unit = this.FormLineEnd(disturbance, "проникновени", "n"); if(disturbance < 1 || disturbance === undefined) this.string += "Проникновений не было!"; else this.string += "Зафиксировано " +disturbance+ " " +disturbance_unit+ "!"; this.CommandToVoiceTerminal(); } //Обработка "время" и "времени" else if( this.qry.indexOf("сколько врем") >= 0 || this.qry.indexOf("какое врем") >= 0 ) { this.Time_Control(); } //Обработка "погода" else if( this.qry.indexOf("погода") >= 0 ) { this.Weather_Control(); } //Обработка "музык" else if( this.qry.indexOf("музык") >= 0 ) { if( this.qry.indexOf("включи") >= 0 || this.qry.indexOf("выключи") >= 0) /* this.unit_com = "get"; this.string = "mstate"; this.CommandToVoiceTerminal(); */ this.unit_com = "pause"; this.string = ""; this.CommandToVoiceTerminal(); //Подтверждение со случайным выбором варианта this.unit_com = "tts"; let number = this.GetRandomInt(0, this.doIt.length); this.string = this.doIt[number]; this.CommandToVoiceTerminal(); } //Обработка "температура" else if( this.qry.indexOf("температура") >= 0 ) { let dt = ""; if( this.qry.indexOf("газов") >= 0 ) dt = dt_supply; else if( this.qry.indexOf("гидро") >= 0 ) dt = dt_hydro; else if( this.qry.indexOf("перв") >= 0 ) dt = dt_floor1; else if( this.qry.indexOf("втор") >= 0 ) dt = dt_floor2; else { this.unit_com = "ask"; this.string = "Уточните какие показания вам нужны"; } if(dt !== "") { let temp = dt.value.toFixed(1); let temp_unit = this.FormLineEnd(temp, "градус", "m"); this.string = dt.name+ " равна " +temp+ " " +temp_unit; } this.CommandToVoiceTerminal(); this.unit_com = "tts"; } //Обработка "везде", "весь" и "все" (должен быть приоритет над свет/освещение и т.п.) else if( this.qry.indexOf("везде") >= 0 || this.qry.indexOf("веcь") >= 0 || this.qry.indexOf("вcе") >= 0 ) { if( this.qry.indexOf("свет") >= 0 || this.qry.indexOf("освещение") >= 0) this.Lamp_Control_All(); this.exit(); //if( this.qry.indexOf("электроприборы") >= 0 ) this.Energy_Control_All(); } //Обработка команды включения/выключения света else if( this.qry.indexOf("свет") >= 0 || this.qry.indexOf("освещение") >= 0 ) { this.Lamp_Control(); } //Обработка команды включения/выключения RGB-лент и гирлянд else if( this.qry.indexOf("ленту") >= 0 || this.qry.indexOf("гирлянду") >= 0 ) { this.Garland_Control(); } //Обработка "давай спать" else if( this.qry.indexOf("давай спать") >= 0 ) { let device = new Array(lamp_guest,lamp_kitchen,lamp_washroom,lamp_big_corridor,lamp_lobby,lamp_boiler_room,lamp_laundry_room); //Выключение всех включенных ламп for(i=0; i < 7; i++) { if(device[i].isOn()) device[i].off(); } //Включение ночного освещения if(lamp_small_corridor.isOff()) { lamp_small_corridor.on(); } //Включение ночной громкости this.TTStoVTallOK(); this.SetVolumeTerminal(50); } //Обработка "вентиляция" и "вентилятор" else if( this.qry.indexOf("вентиля") >= 0 || this.qry.indexOf("рекуператор") >= 0 ) { if( this.qry.indexOf("скорость 1") >= 0 ) sw_pvu.setValue(2); else if( this.qry.indexOf("скорость 2") >= 0 ) sw_pvu.setValue(3); else if( this.qry.indexOf("скорость 3") >= 0 ) sw_pvu.setValue(4); else if( this.qry.indexOf("включи") >= 0 ) sw_pvu.setValue(1); else if( this.qry.indexOf("выключи") >= 0 ) sw_pvu.setValue(0); this.string = "Выбран " +sw_pvu.name+ " - " +sw_pvu.stateName; this.CommandToVoiceTerminal(); } else { //Команда "слушать без ключевого слова" this.unit_com = "ask"; this.string = this.GetRandElementArr(this.doNotKnowCommand); this.CommandToVoiceTerminal(); //Переход в обычный режим (распознавание с ключевым словом) this.unit_com = "tts"; } } }, //Функция устанавливает нужную громкость в зависимости от периода дня SetVolumeTerminal(level) { let time = this.GetPeriodDay('digit'); if(this.period != time) { this.period = time; if(time == 0) level = 70; //Утро else if(time == 1) level = 100; //День else if(time == 2) level = 70; //Вечер else if(time == 3) level = 50; //Ночь } //Если уровень установлен, то даем команду на изменение громкости if(level !== undefined) { this.unit_com = "volume"; this.string = level; this.CommandToVoiceTerminal(); this.unit_com = "tts"; } }, //Функция возвращает текстовое (цифровое) значение периода дня GetPeriodDay(format) { let hello = new Array("Доброе утро!","Добрый день!","Добрый вечер!","Доброй ночи!"); let date = new Date(); let hour = date.getHours(); let period = 0; if(hour > 6 && hour < 10) period = 0; // Период 7-9 else if(hour > 9 && hour < 20) period = 1; // Период 10-19 else if(hour > 19 && hour < 23) period = 2; // Период 20-22 else period = 3; // Период 23-6 //format == 'digit' или '' if(format == 'digit') return period; else return hello[period]; }, //Функция возвращает случайное целое число между min (включительно) и max (не включая max) GetRandomInt(min, max) { return Math.floor( Math.random() * (max - min)) + min; }, //Функция получения случайного элемента из массива GetRandElementArr(array) { let number = this.GetRandomInt(0, array.length); return array[number]; }, //Функция формирования окончаний единиц измерений - если unit = "градус", то будет "градуса" и "градусов" FormLineEnd(val, unit, gender) { let part = 0; let string = ""; let val_abs = Math.abs(val); if(val_abs > 20) part = val_abs % 10; else part = val_abs; //gender = m|f|n if(gender == "m") { if(part == 1) string = unit; else if(part > 1 && part < 5) string = unit+ "а"; else string = unit+ "ов"; } else if(gender == "f") { if(part == 1) string = unit+ "а"; else if(part > 1 && part < 5) string = unit+ "ы"; else string = unit; } else if(gender == "n") { if(part == 1) string = unit+ "е"; else if(part > 1 && part < 5) string = unit+ "я"; else string = unit+ "й"; } return string; }, //Функция для поиска нужного текста в строке qry от терминала FindTextOfQRY(text) { if(this.qry.indexOf(text) >= 0) return true; else return false; }, //Функция передачи команды на терминал CommandToVoiceTerminal() { //if(this.rms) //this.pluginCommand({ unit:this.unit1, command:this.unit_com+ ":" +this.string }); this.pluginCommand({ unit:this.unit2, command:this.unit_com+ ":" +this.string }); }, //Функция оповещения о текущем времени Time_Control() { let date = new Date(); let hour = date.getHours(); let minute = date.getMinutes(); let hour_unit = this.FormLineEnd(hour, "час", "m"); let minute_unit = this.FormLineEnd(minute, "минут", "f"); this.string = "Сейчас " +hour+ " " +hour_unit+ " и " +minute+ " " +minute_unit; this.CommandToVoiceTerminal(); }, //Функция оповещения о текущей погоде за окном (запуск при наличии слов "погод") Weather_Control() { let temp = Math.round(dt_s.value); let hum = Math.round(dh_s.value); let temp_unit = this.FormLineEnd(temp, "градус", "m"); let hum_unit = this.FormLineEnd(hum, "процент", "m"); this.string = "Сейчас на улице " +temp+ " " +temp_unit+ " и влажность " +hum+ " " +hum_unit; this.CommandToVoiceTerminal(); }, //Функция управления освещением (запуск при наличии слов "свет" и "освещение") Lamp_Control() { //Поиск помещений по шаблону //switch() if( this.FindTextOfQRY("гост") ) this.device = lamp_guest; else if( this.FindTextOfQRY("кухн") ) this.device = lamp_kitchen; else if( this.FindTextOfQRY("мал") ) this.device = lamp_small_corridor; else if( this.FindTextOfQRY("сануз") ) this.device = lamp_washroom; else if( this.FindTextOfQRY("большо") ) this.device = lamp_big_corridor; else if( this.FindTextOfQRY("прихож") ) this.device = lamp_lobby; else if( this.FindTextOfQRY("котельн") ) this.device = lamp_boiler_room; else if( this.FindTextOfQRY("прачечн") ) this.device = lamp_laundry_room; else if( this.FindTextOfQRY("веранд") ) this.device = lamp_veranda; else if( this.FindTextOfQRY("крыльц") ) this.device = lamp_porch; else { this.TTStoVT("Уточните название помещения!"); this.device = ''; this.exit(); } //Поиск действия по шаблону if( this.qry.indexOf("включи") >= 0 ) { if(this.device.isOff()) { this.device.on(); this.addListener(this.device, 'TTStoVTdevOn') } else this.TTStoVTdevisOn(); } else if( this.qry.indexOf("выключи") >= 0 ) { if(this.device.isOn()) { this.device.off(); this.addListener(this.device, 'TTStoVTdevOff') } else this.TTStoVTdevisOff(); } else this.TTStoVT("Уточните действие!"); }, //Функция управления RGB-лентами (запуск при наличии слов "лент" и "гирлянд") Garland_Control() { //Поиск помещений по шаблону if( this.qry.indexOf("дом") >= 0 ) this.device = garland_house; else if( this.qry.indexOf("крыльцо") >= 0 ) this.device = garland_porch; else if( this.qry.indexOf("гараж") >= 0 ) this.device = garland_garage; else { this.TTStoVT("Уточните название помещения!"); this.device = ''; this.exit(); } //Поиск действия по шаблону if( this.qry.indexOf("включи") >= 0 ) { if(this.device.isOff()) { this.device.on(); //this.addListener(this.device, 'TTStoVTdevOn'); } else this.TTStoVTdevisOn(); } else if( this.qry.indexOf("выключи") >= 0 ) { if(this.device.isOn()) { this.device.off(); //this.addListener(this.device, 'TTStoVTdevOff'); } else this.TTStoVTdevisOff(); } else this.TTStoVT("Уточните действие!"); }, Lamp_Control_All() { let lighting = '1'; let one_floor = '1'; if( this.qry.indexOf("включи") >= 0 ) { this.doAll({place:'1,2,3,5', subs:lighting}, 'on'); } else if( this.qry.indexOf("выключи") >= 0 ) { this.doAll({place:'1,2,3,5', subs:lighting}, 'off'); } this.TTStoVTallComplete(); }, //Функция управления розетками (запуск при наличии слов "розетк" и "электричество") Socket_Control() { //Поиск помещений по шаблону if( this.FindTextOfQRY("гост") ) this.device = socket_guest; else if( this.qry.indexOf("кухн") >= 0 ) this.device = socket_kitchen; else if( this.qry.indexOf("сануз") >= 0 ) this.device = socket_washroom; else if( this.qry.indexOf("большо") >= 0 ) this.device = socket_big_corridor; else if( this.qry.indexOf("прачечн") >= 0 ) this.device = socket_laundry_room; else if( this.qry.indexOf("веранд") >= 0 ) this.device = socket_veranda; else if( this.qry.indexOf("крыльц") >= 0 ) this.device = socket_porch; else this.TTStoVT("Уточните название помещения!"); //Поиск действия по шаблону if( this.qry.indexOf("включи") >= 0 ) { if(this.device.isOff()) { this.device.on(); this.addListener(this.device, 'TTStoVTdevOn') } else this.TTStoVTdevisOn(); } else if( this.qry.indexOf("выключи") >= 0 ) { if(this.device.isOn()) { this.device.off(); this.addListener(this.device, 'TTStoVTdevOff') } else this.TTStoVTdevisOff(); } else this.TTStoVT("Уточните действие!"); }, TTStoVTdevOn() { this.string = this.device.name+ " включен"; this.CommandToVoiceTerminal(); this.exit(); }, TTStoVTdevOff() { this.string = this.device.name+ " выключен"; this.CommandToVoiceTerminal(); this.exit(); }, TTStoVTdevisOn() { this.string = this.device.name+ " уже был включен!"; this.CommandToVoiceTerminal(); this.exit(); }, TTStoVTdevisOff() { this.string = this.device.name+ " уже был выключен!"; this.CommandToVoiceTerminal(); this.exit(); }, TTStoVT(text) { this.string = text; this.CommandToVoiceTerminal(); }, TTStoVTWhatPlace() { this.string = "Уточните название помещения!"; this.CommandToVoiceTerminal(); }, TTStoVTallComplete() { let number = this.GetRandomInt(0, this.doIt.length); this.string = this.doIt[number]; this.CommandToVoiceTerminal(); }, TTStoVTallOK() { this.string = "Я готова"; this.CommandToVoiceTerminal(); } });
Устройство меняется динамически внутри сценария (см.функцию - Garland_Control()). В данном случае сделал функцию для включения/выключения RGB-лент, которые управляются актуатором аналоговым. В данном конкретном случае - const garland_house
При этом функция Lamp_Control() работает без нареканий. Поэтому сделал вывод что есть какая-то проблема с актуатором аналоговым.
-
@Alex_Jet, ОЧЕНЬ изобретательно и креативно
И вполне рабочая схема:
Сформировать команду на основе фразы -> передать команду -> установить слушателя для устройства.
А когда устройство переключится (сработает слушатель) - отрапортовать о выполнении.Единственное тонкое место здесь - если устройство по какой-то причине не ответит, то сценарий зависнет.
Потому что, устанавливая слушателя, мы оставляем сценарий запущенным. Он ждет события, и не выходит.
Обычно, параллельно со слушателями, целесообразно устанавливать таймер, чтобы сценарий все же завершился. Типа "не шмогла"Почему в конкретном случае не срабатывает - нужно смотреть. В скрипте garland_porch и garland_garage не определены. Но Вы говорите, что команда на включение уходит, то есть идете по ветке garland_house. Можно посмотреть параллельно в отладчике плагина - что приходит в ответ на команду.
Но таймер нужен в любом случае: если устанавливается слушатель - нужно предусмотреть и другой выход.
-
Участник @intrapro написал в Сценарии - новая версия API:
В скрипте garland_porch и garland_garage не определены. Но Вы говорите, что команда на включение уходит, то есть идете по ветке garland_house. Можно посмотреть параллельно в отладчике плагина - что приходит в ответ на команду.
Но таймер нужен в любом случае: если устанавливается слушатель - нужно предусмотреть и другой выход.Да, я иду по ветке garland_house (определение фраз очень точное!). В отладчике плагина megad - действительно не додумался посмотреть......и сейчас понял, что там нечего смотреть! Поскольку управление WS281x хоть и нативное, но одностороннее! Как итог - ответа от контроллера нет, а плагин ждет его. Хотя!!! Опять же - я управляю всего лишь актуатором и косвенно самой лентой. А актуатор в свою очередь завязан на сценарий управления и плагин megad тут не причем! То есть здесь нет отклика именно от актуатора. Мне кажется, что Вы сами можете воспроизвести такую ситуацию.
С таймером согласен - это "байпас" сценария, правда пока не могу придумать логику чтобы было все по взрослому (если завис слушатель, то сказать "Не смогла", а если не завис, то не говорить "Не смогла"...).
Сам сценарий еще далек от завершения...знаю как все оптимизировать, но пока не хватает времени. Особенно нет времени разобраться и сделать хороший плагин (двухсторонний обмен по соккету) и чтобы информацию с него можно было обрабатывать в сценарии. А так - уже очень привыкли всей семьей к голосовому управлению))
-
Участник @Alex_Jet написал в Сценарии - новая версия API:
То есть здесь нет отклика именно от актуатора.
Если у Вас актуатор виртуальный, то проверьте, что по команде переключается состояние актуатора.
С таймером согласен - это "байпас" сценария, правда пока не могу придумать логику чтобы было все по взрослому (если завис слушатель, то сказать "Не смогла", а если не завис, то не говорить "Не смогла"...).
Если не завис, то все OK, сценарий у Вас сразу выходит. То есть говорить ничего не придется.
Цель таймера - страховка слушателей. При добавлении слушателя просто всегда добавлять таймер (на время отклика*2, например) и по таймеру выходить.А так - уже очень привыкли всей семьей к голосовому управлению))
Да, к хорошему быстро привыкаешь :).
-
Участник @intrapro написал в Сценарии - новая версия API:
сли у Вас актуатор виртуальный, то проверьте, что по команде переключается состояние актуатора.
Так я это вижу как в отладчике сценария (ACTORA_GARLAND1_01 on), так и визуально (RGB-лента начинает работать). То же при выключении. Вы не пробовали сымитировать ситуацию?