Сценарии - новая версия API
-
Участник @intrapro написал в Сценарии - новая версия API:
@Alex_Jet, Добрый день! @Erik прав - нужен актуатор, который можно переключать как угодно - интерактивно, сценарием, по расписанию...
Сценарий гирлянды запускается при включении этого актуатора.
Состояния в php скрипте меняются случайным образом, поэтому логика еще проще:
- Добавить слушателя для актуатора-триггера
- Генерировать строку цветов случайным образом
- Передать команду на MegaD
- Взвести таймер 1 сек
По таймеру - повторить пункты 1-3
При выключении триггера - завершить сценарийСпасибо за помощь. В принципе получилось примерно что хотел. Надо еще подумать как сделать более плавное и быстрое изменение уровня одного и того же цвета (главное не зациклить цикл... иначе iH перестанет откликаться), но в принципе все работоспособно! Для тех кто еще не юзал RGB ленты, подключенные к MegaD, через iH:
/** * @name Освещение - гирлянда из WS2818 * @desc Имитация работы гирлянды * @version 4 */ const sw = Device("ACTORA_GARLAND1_01"); startOnChange(sw); script({ plugin: "megad1", //Переменная названия плагина channel: 34, //Переменная номера канала плагина cmd: '000000', //Переменная команды chip: 151, //Количество чипов в ленте WS2818 num: 3, i: 0, start() { this.ChangeStateSw(); }, ChangeStateSw() { //Остановка таймера для выхода из "цикла" this.stopTimer("T1"); switch(sw.value) { case 0: this.cmd = '000000'; break; case 1: this.cmd = '00FF00'; break; case 2: this.cmd = 'FF0000'; break; case 3: this.cmd = '0000FF'; break; case 4: this.ChangeRed(); break; case 5: this.ChangeGreen(); break; case 6: this.ChangeBlue(); break; case 7: this.RandomColor(); break; case 8: this.num = 3; this.RandomPlay(); break; case 9: this.num = 6; this.RandomPlay(); break; case 10: this.num = 9; this.RandomPlay(); break; } if(sw.value < 4) { this.SendDataToWS2818(this.plugin, this.channel, this.cmd, this.chip); this.cmd = ''; this.exit(); } }, ChangeRed() { this.addListener(sw, "ChangeStateSw"); let color = this.i.toString(16); if(color.length == 1) color = '0' +color; this.cmd = '00' +color+ '00'; this.SendDataToWS2818(this.plugin, this.channel, this.cmd, this.chip); this.cmd = ''; if(this.i >= 0 && this.i < 16) this.i += 1; else if(this.i >= 16 && this.i < 96) this.i += 8; else if(this.i >= 96 && this.i < 240) this.i += 16; else if(this.i >= 240) this.i = 0; this.startTimer("T1", 1, "ChangeRed"); }, ChangeGreen() { this.addListener(sw, "ChangeStateSw"); let color = this.i.toString(16); if(color.length == 1) color = '0' +color; this.cmd = color+ '0000'; this.SendDataToWS2818(this.plugin, this.channel, this.cmd, this.chip); this.cmd = ''; if(this.i >= 0 && this.i < 16) this.i += 1; else if(this.i >= 16 && this.i < 96) this.i += 8; else if(this.i >= 96 && this.i < 240) this.i += 16; else if(this.i >= 240) this.i = 0; this.startTimer("T1", 1, "ChangeGreen"); }, ChangeBlue() { this.addListener(sw, "ChangeStateSw"); let color = this.i.toString(16); if(color.length == 1) color = '0' +color; this.cmd = '0000' +color; this.SendDataToWS2818(this.plugin, this.channel, this.cmd, this.chip); this.cmd = ''; if(this.i >= 0 && this.i < 16) this.i += 1; else if(this.i >= 16 && this.i < 96) this.i += 8; else if(this.i >= 96 && this.i < 240) this.i += 16; else if(this.i >= 240) this.i = 0; this.startTimer("T1", 1, "ChangeBlue"); }, RandomColor() { this.addListener(sw, "ChangeStateSw"); let color = ["FF0000", "00FF00", "0000FF", "FFFFFF", "000000"]; this.cmd = color[this.GetRandomInt(0, 5)] + color[this.GetRandomInt(0, 5)] + color[this.GetRandomInt(0, 5)]; this.SendDataToWS2818(this.plugin, this.channel, this.cmd, this.chip); this.cmd = ''; this.startTimer("T1", 1, "RandomColor"); }, RandomPlay() { this.addListener(sw, "ChangeStateSw"); let color; for (let i = 0; i < this.num; i++ ) { color = this.GetRandomInt(0,256).toString(16); if(color.length == 1) color = '0' +color; this.cmd += color; } this.SendDataToWS2818(this.plugin, this.channel, this.cmd, this.chip); this.cmd = ''; this.startTimer("T1", 1, "RandomPlay"); }, //Функция возвращает случайное целое число между min (включительно) и max (не включая max) GetRandomInt(min, max) { return Math.floor( Math.random() * (max - min)) + min; }, //Функция формирования данных для ленты WS2818 SendDataToWS2818(plugin, channel, cmd, chip) { this.pluginCommand({unit: plugin, command: '/sec/?pt=' +channel+ '&ws=' +cmd+ '&chip=' +chip}); } });
Управление лентой - с помощью аналогового актюатора, который имеет слайдер с диапазоном 1-10. Чтобы управлять по расписанию нужен сценарий, в который из расписания будем передавать параметр, а этот параметр будет присваиваться значению актюатора.
-
Добрый день! Можно ли использовать в мультисценариях помимо переменный устройств, постоянные? Делаю так:
В ошибке вижу:
Или все таки нужно добавлять это устройство ко всем в списке?
-
Участник @homa написал в Сценарии - новая версия API:
Добрый день! Можно ли использовать в мультисценариях помимо переменный устройств, постоянные? Делаю так:
Добрый день, нет, поле все равно будет доступно для выбора, даже если вы пропишите id, но ошибки не должно быть
-
Добрый день!
Сейчас движок сценариев распознает тип - обычный сценарий или мульти, анализируя именно описание устройств.
За счет этого легко можно превратить обычный сценарий в мультисценарий и обратно. Поэтому смешивать параметрические и реальные устройства в текущей версии не получится
-
Добрый день, есть проблема, передаю на одну megad одновременно два запроса, как сделать между запросами паузу. если я на одну мегу одновременно даю 2 запроса this.pluginCommand не обрабатывает 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: jalusi.on(); if(jalusi.id === "ACTOR7"){ this.pluginCommand({unit:'megad3', command:'/258/?cmd='+jalusi.getParam('point_open')+':1;p200;'+jalusi.getParam('point_open')+':0'}); } if(jalusi.id === "ACTOR8"){ //this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_open')+':1;p210;'+jalusi.getParam('point_open')+':0'}); } if(jalusi.id === "ACTOR9"){ //this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_open')+':1;p230;'+jalusi.getParam('point_open')+':0'}); } break; case 1: //this.pluginCommand({unit:'megad3', command:'/258/?cmd='+jalusi.getParam('point_open')+':0;'+jalusi.getParam('point_close')+':0'}); break; case 2: jalusi.off(); if(jalusi.id === "ACTOR7"){ this.pluginCommand({unit:'megad3', command:'/258/?cmd='+jalusi.getParam('point_close')+':1;p200;'+jalusi.getParam('point_close')+':0'}); } if(jalusi.id === "ACTOR8"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_close')+':1;p210;'+jalusi.getParam('point_close')+':0'}); } if(jalusi.id === "ACTOR9"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_close')+':1;p230;'+jalusi.getParam('point_close')+':0'}); } break; } this.log('Жалюзі статус : '+switch_1.value+' '+jalusi.id); }, onJalusi(){ //this.log(this.isChanged(jalusi)+' 38 line'); if(jalusi.isOn()){ //this.log('jalusi On'); if(jalusi.id === "ACTOR7"){ this.pluginCommand({unit:'megad3', command:'/258/?cmd='+jalusi.getParam('point_open')+':1;p200;'+jalusi.getParam('point_open')+':0'}); } if(jalusi.id === "ACTOR8"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_open')+':1;p210;'+jalusi.getParam('point_open')+':0'}); } if(jalusi.id === "ACTOR9"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_open')+':1;p230;'+jalusi.getParam('point_open')+':0'}); } }else{ //this.log('jalusi Off'); if(jalusi.id === "ACTOR7"){ this.pluginCommand({unit:'megad3', command:'/258/?cmd='+jalusi.getParam('point_close')+':1;p200;'+jalusi.getParam('point_close')+':0'}); } if(jalusi.id === "ACTOR8"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_close')+':1;p210;'+jalusi.getParam('point_close')+':0'}); } if(jalusi.id === "ACTOR9"){ this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_close')+':1;p230;'+jalusi.getParam('point_close')+':0'}); } } this.exit(); } });
-
А как у мультисценария отладчик запустить?
Есть мультисценарий включения света по датчику движения, там 4 комплекта устройств.
У трех комплектов все работает, а у одного нет.
Причем видно, что датчик движения срабатывает.Как сапортить в таком случае?
И пробный запуск мультисценария для выбранного комплекта устройств возможен ли?
-
@Erik Добрый день, передите в
рабочие сценарии
, выберите необходимый сценарий, откройте нижнюю панель, и запустите отладчик
-
Подскажите, как сделать строковую переменную, чтобы ее значение можно было менять скриптом и выводить в интерфейсе?
-
@Erik, немного кода. Я правильно понял задачу?
const dev1 = Device("_UNIT_voiceterminal1", [ {"name":"status", "note":"Состояние", "type":"string", "val":""} ]); script({ start(param) { //Скрипт запускается плагином с параметрами if(param !== undefined) { const obj = this.ParseJSON(param); //Вывод status на вкладку "Параметры" dev1 if(obj.status !== undefined) dev1.setParam("status", obj.status); } } })
Есть только 2 неудобства:
- Когда справа всплывает панель устройства, то всегда отображается вкладка с кнопкой Вкл./Выкл...
- Данные на вкладке "Параметры" не обновляются "он-лайн" - свежие данные можно посмотреть только повторно открыв всплывающую панель устройства.
-
@Alex_Jet
Мне время нужно на осознание. Я не "читаю с листа" скриптыЗадача простая - вывести в интерфейсе информацию о последнем открытии (какое окно/дверь и дата время) и о последнем движении (в каком помещении и дата/время).
Не в меню справа, а в виде надписи в графическом интерфейсе.
Если бы было устройство, типа аналогового актуатора, но принимающего не числовые значения, а текстовые - было бы просто.Или окно пуш-уведомлений для графического интерфейса сделать.
-
@Erik Аналоговый датчик может принять и отобразить строку в значении
-
@Erik, может быть для этих целей журнал использовать? В него легко писать:
this.log("Это ваш текст - " +this_is_var);
Единственный момент - в нем будут всякие служебные записи от плагинов push, telegram...
-
@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, для алерта можно настроить - требует он подтверждения или нет.
Если подтверждение не требуется - алерт уходит, если событие завершено.
Если требуется - будет висеть, пока оператор не подтвердит, также фиксируется, кто подтвердил. Да, цвет зависит от уровня - предупреждение или авария.
Переход на мнемосхему планируется сделать, пока не реализовано.Если сообщений несколько - при закрытии появляется предыдущее. Также общее количество алертов выводится в виде индикатора.
Для экрана настраивается - будут на нем выводиться алерты или нет.Сейчас механизм алертов завязан не на сценарии, а напрямую на изменение состояния устройств.
-
Коллеги, тут делал в расписании задание на групповое выключение и обратил внимание, что зоны не фильтруются в зависимости от уровня. Не проверил, но скорее и уровни не фильтруются в зависимости от системы.
ИМХО, логика должна быть такой:- Выбираем систему
- В уровнях отображаются только те, на которых есть устройства данной системы
- В зонах отображаются только те, которые есть на этом уровне
Если систему не выбираем, то отображаются все уровни.
Если не выбираем уровни, то отображаются все зоны.
И т.д.