Сценарии - новая версия API
-
Добрый день!
Не работает команда операционной системы
Вот сценарийconst mon = Device("POWER_MIRROR"); // Запускаем сценарий при изменении состояния выключателя зеркала startOnChange(mon); script({ start() { if (mon.isOff()) // Если он выключен this.execOS(`/home/pi/mirror_off.sh`); // Даем команду на выключение монитора else this.execOS(`/home/pi/mirror_on.sh`); // Иначе - на включение } });
В отладчике пишет
04.01 15:56:49.463 Trigger POWER_MIRROR
04.01 15:56:49.464 Started
04.01 15:56:49.465 execOS: /home/pi/mirror_off.sh
04.01 15:56:49.492 Stopped
04.01 15:56:49.522 execOS error: Error: Command failed: /home/pi/mirror_off.sh
No protocol specified
xset: unable to open display ":0.0"04.01 15:56:49.523 stdout:
04.01 15:56:49.524 stderr: No protocol specified
xset: unable to open display ":0.0"Хотя из терминала все прекрасно срабатывает. Может кто-то подсказать куда копать?
-
Подскажите как можно вывести среднюю температуру с 3 датчиков температури в сценарии? Хочу чтобы рекуператор менял уставку в зависимости от температуры в помещении.
-
@amgstone, ну а в чем проблема? Подтягиваете в сценарий своих 3 датчика температуры, в переменную заносите среднюю температуру от них и присваиваете 4-му датчику усредненное значение, по которому будет работать рекуператор.
-
@Alex_Jet от непонимаю как ето сделать в ih.
-
let avr = (t1.value + t2.value + t3.value)/3; //Закон усреднения показаний от трех датчиков this.assign(t_avr, "value", avr); //Присвоение аналоговому датчику значения
-
@Alex_Jet спасибо, все получилось))))
-
Может хто показать сценарий для счетчика многотарифного, чтобы визуализировал расход електроенергии по тарифам. Прошивка tasmota, wemos, pzem-004, mqtt.
-
Добрый день!
В коде моего сценария есть такая строка:
const pump = Device(“pumpRecirculation_4”, [
{"name":"timePumpOn", "note":" Время работы насоса после отключения света, сек ", "type":"number", "val":1800}]);Так вот, после первого срабатывания сценария в свойство timePumpOn прописалось значение 1800. Меняю в сценарии значение "val" на другое, сохраняю изменения, а в timePumpOn остается по прежнему 1800. Изменить его можно только из сценария командой setParam. Разве так и должно быть?
-
@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 последних строчек...