Сценарии - новая версия API



  • @homa
    можно сделать присвоение в скрипте
    Actuator.setValue(движение в коридоре ${new Date().toLocaleString()})

    ???

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



  • @Alex_Jet

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

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



  • @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-виджет для всплывающих критичных сообщений! Причем такой, чтобы его форматирование можно было из сценария менять (цвет, размер текста, фон контейнера и т.д.).

    Pop-Up_Message.PNG



  • @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, для алерта можно настроить - требует он подтверждения или нет.
    Если подтверждение не требуется - алерт уходит, если событие завершено.
    Если требуется - будет висеть, пока оператор не подтвердит, также фиксируется, кто подтвердил. Да, цвет зависит от уровня - предупреждение или авария.
    Переход на мнемосхему планируется сделать, пока не реализовано.

    Если сообщений несколько - при закрытии появляется предыдущее. Также общее количество алертов выводится в виде индикатора.
    Для экрана настраивается - будут на нем выводиться алерты или нет.

    Сейчас механизм алертов завязан не на сценарии, а напрямую на изменение состояния устройств.



  • Коллеги, тут делал в расписании задание на групповое выключение и обратил внимание, что зоны не фильтруются в зависимости от уровня. Не проверил, но скорее и уровни не фильтруются в зависимости от системы.
    ИМХО, логика должна быть такой:

    1. Выбираем систему
    2. В уровнях отображаются только те, на которых есть устройства данной системы
    3. В зонах отображаются только те, которые есть на этом уровне

    Если систему не выбираем, то отображаются все уровни.
    Если не выбираем уровни, то отображаются все зоны.
    И т.д.



  • @Alex_Jet
    Вы правы, сейчас каждый параметр независим. Если фильтруется по зоне, то уровень в результирующем фильтре ни к чему. Короче, свобода творчества для пользователя 🙂



  • Коллеги, никак не разберусь в ситуации. Есть код:
    6138662e-4200-4303-892d-a2029c205268-image.png
    5936b6b4-1c43-4268-9157-533ac5c9fd4d-image.png
    Почему-то во время выполнения setparam переменная становится текстовой... как с этим бороться?



  • @homa заработало так:
    02b03b70-a986-4823-84d2-d13656028d83-image.png
    не знаю насколько это верный путь



  • @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');
        }
    });
    

Авторизуйтесь, чтобы ответить