Сценарии - новая версия API
-
@homa
можно сделать присвоение в скрипте
Actuator.setValue(движение в коридоре ${new Date().toLocaleString()})???
Еще бы строку параметра мультисценарию.
Чтобы вместе с группой устройств можно было какой нибудь параметр назначить.
Например выбрать датчик движения в комнате и параметру дать значение "в комнате", чтобы он подставлялся в скрипт.
-
Если можно аналоговому актуатору присваивать строковое значение, то я выведу в интерфейсе надпись "последнее движение" а рядом поле со значением аналогового актуатора, которому при движении буду присваивать значение "в помещении", "дата", "время".
И оно будет всегда отображаться на экране безопасности.
-
@Erik, проверил - действительно работает:
const text = Device("PUSH_STATUS"); const dw = Device("SGERKON1_01"); script({ start() { let message = ""; if(dw.isOn()) { message = dw.name.replace("Датчик открытия окна","Окно")+ " - открыто: " +new Date().toLocaleString(); } else message = ""; text.setValue(message); } });
PUSH_STATUS - это устройство "Актуатор универсальный аналоговый". Соответственно если вместо первого вписать ActorA, а вместо второго SensorD, то будет мультисценарий. Только внутри сценария, вероятно (не знаю как у вас называются устройства), надо определять как называются датчики, чтобы им соответствующие подписи/значения присваивать. В принципе можно в name искать совпадение, например, так - if(dw.name.indexOf("окно") >= 0), то значит имя датчика связано с окном.
Вот только очистить полностью сообщение не получается - вместо пустого сообщения прописывается "0"...
Вообще я давно прошу разработчиков чтобы сделали Alert-виджет для всплывающих критичных сообщений! Причем такой, чтобы его форматирование можно было из сценария менять (цвет, размер текста, фон контейнера и т.д.).
-
@Erik
Можно выводить свойства устройства: https://ih-systems.com/ru/command_list/dev.zoneName - помещение,
dev.placeName - этаж,
dev.fullName - название + помещение (если есть) + этаж (если есть)Например
dev.setValue(`Зафиксировано движение ${new Date().toLocaleString()}. ${dev.zoneName} ${dev.placeName} `)
Можно еще в состоянии устройства прописать "Название состояния" и вывести его как dev.stateName (например, "Открыто окно", "Открыта дверь"
dev.setValue(`${dev.stateName} ${new Date().toLocaleString()}. ${dev.zoneName} ${dev.placeName} `)
-
@Alex_Jet
Всплывающие алерты есть в версии Scada. В пятой версии вероятно будет и в Pro
-
@intrapro, а можно привести примеры как они выглядят? Я вот себе представляю работу так - сообщение всплыло, если юзер нажал на него, то оно ушло, либо произошел переход на нужную мнемосхему. Если сообщений несколько, то текущее ушло, появилось предыдущее и т.д. При этом в зависимости от критичности сообщения имеют разный цвет текста/фон.
-
@Alex_Jet, для алерта можно настроить - требует он подтверждения или нет.
Если подтверждение не требуется - алерт уходит, если событие завершено.
Если требуется - будет висеть, пока оператор не подтвердит, также фиксируется, кто подтвердил. Да, цвет зависит от уровня - предупреждение или авария.
Переход на мнемосхему планируется сделать, пока не реализовано.Если сообщений несколько - при закрытии появляется предыдущее. Также общее количество алертов выводится в виде индикатора.
Для экрана настраивается - будут на нем выводиться алерты или нет.Сейчас механизм алертов завязан не на сценарии, а напрямую на изменение состояния устройств.
-
Коллеги, тут делал в расписании задание на групповое выключение и обратил внимание, что зоны не фильтруются в зависимости от уровня. Не проверил, но скорее и уровни не фильтруются в зависимости от системы.
ИМХО, логика должна быть такой:- Выбираем систему
- В уровнях отображаются только те, на которых есть устройства данной системы
- В зонах отображаются только те, которые есть на этом уровне
Если систему не выбираем, то отображаются все уровни.
Если не выбираем уровни, то отображаются все зоны.
И т.д.
-
@Alex_Jet
Вы правы, сейчас каждый параметр независим. Если фильтруется по зоне, то уровень в результирующем фильтре ни к чему. Короче, свобода творчества для пользователя
-
Коллеги, никак не разберусь в ситуации. Есть код:
Почему-то во время выполнения setparam переменная становится текстовой... как с этим бороться?
-
@homa заработало так:
не знаю насколько это верный путь
-
@homa, ноль получается в строку превращается?
Если работает, то путь верныйМожно при суммировании преобразовать аргументы :
this.sum = Number(pssrv.getParam("ps2srvvar_")) + Number(pssrv.getParam("ps1srvvar_"));
-
@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'); } });