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



  • Коллеги, вероятно где-то туплю. Переписал работающий сценарий, вынеся гистерезис в дополнительные параметры устройства чтобы можно было из вебки изменять все уставки. Однако система жалуется (co2_guest Device params: Unexpected token / in JSON at position 4), что в сценарии есть ошибка. Не могу понять в чем дело!

    const valve1F   = Device("VALVE_AIR3");     //Клапан первого этажа
    const hum_guest = Device("SHUMIDITY1_01", [ //Датчик влажности гостевой
      {"name":"hst", "note":"Гистерезис, %", "type":"number", "val":5}
      ]);
    const co2_guest = Device("SENSORA1_01", [   //Датчик CO2 гостевой
      {"name":"hst", "note":"Гистерезис, ppm", "type":"number", "val":100}
      ]);
    
    script({
        check() {
          return(   (hum_guest.value > hum_guest.setpoint + hum_guest.getParam("hst") || co2_guest.value > co2_guest.setpoint + co2_guest.getParam("hst"))&&(valve1F.isOff()) ||
                    (hum_guest.value < hum_guest.setpoint - hum_guest.getParam("hst") && co2_guest.value < co2_guest.setpoint - co2_guest.getParam("hst"))&&(valve1F.isOn()) );
        },
        
        start() {
          if(valve1F.isOff()) valve1F.on();
          else valve1F.off();
        }
    });
    


  • Пользователь @Alex_Jet написал в Сценарии - новая версия API:

    Коллеги, вероятно где-то туплю.

    Такое ощущение, что виновными оказались комментарии внутри []...

    Ну а что не так с этим???

    const sensor_hum  = Device("SensorA", "Датчик влажности", [
      {"name":"hst", "note":"Гистерезис (для управления), %", "type":"number", "val":"5"}
      ]);
    

    В ошибке - sensor_hum Device params: Unexpected end of JSON input



  • @Alex_Jet, да, Вы правы, проблема именно в комментариях.
    В декларативной части сценария (выше script) код не выполняется движком JS, а парсится системой.
    Массив дополнительных параметров рассматривается как единый JSON объект. А внутри JSON-а комментарии не разрешены 😞



  • @intrapro, а что не так тут:???

    const sensor_hum  = Device("SensorA", "Датчик влажности", [
      {"name":"hist", "note":"Гистерезис (для управления), %", "type":"number", "val":5}
      ]);
    

    В ошибке - Unexpected end of JSON input
    Я уже перепробовал кучу всего и не могу понять где есть загвоздка!!!
    Вот на такое же ведь не ругается!!!:

    const dt          = Device("SensorA", "Датчик температуры в зоне актюатора ТП", [
      {"name":"hist", "note":"Гистерезис включения/отключения актюатора, °C", "type":"number", "val":2}
      ]);
    


  • @Alex_Jet, скобочки в значениях ломают парсинг.
    Так будет работать:

     "note":"Гистерезис для управления, %"
    


  • @intrapro, вопрос на 100$))). Вопрос методом гугления отпал сам собой... Только если ответите по поводу оптимальности такого кода)
    В сценарий забил свойства своих камеры в виде литералов чтобы при постановке дома на охрану перебрать их в цикле и сформировать для каждой команду включения motion_detection. Получилось так:

      //Функция включения/выключения режима охраны у камер видеонаблюдения
          CamerasSecurity(md_state) {
            //Список IP камер
            const camera1 = {ip:"192.168.11.11", login:"admin", password:"admin"};
            const camera2 = {ip:"192.168.11.12", login:"admin", password:"admin"};
            let obj = Object.assign([], [camera1, camera2]);
            
            //Преобразование On/Off -> 0/1
            if(md_state == "On") md_state = 1;
            else if(md_state == "Off") md_state = 0;
            
            //Цикл для перебора всех камер
            for(var i = 0; i < obj.length; i++) {
              let command = "http://" +obj[i].login+ ":" +obj[i].password+ "@" +obj[i].ip;
              
              //enable = 0/1 (Disable/Enable Motion Detection of Zone 1: "name=1")
              command += "/web/cgi-bin/hi3510/param.cgi?cmd=setmdattr&-name=1&-enable=" +md_state;
              
              //Отправка команды плагину HTTP
              this.SendCommandToHTTP(command);
            }
          },
        }
    

    PS: А можно в сценарии каким-нибудь образом брать данные по камерам из плагина? И да - у плагина CCTV будет древовидная структура в 5-й версии iH?



  • Пользователь @Alex_Jet написал в Сценарии - новая версия API:

    Только если ответите по поводу оптимальности такого кода)

    Код на мой взгляд хороший, с литералами работа происходит быстро.
    Это всегда дилемма - универсальность или скорость/простота.

    Если по синтаксису - массив можно заполнить проще:

       const obj = []; // Объявляем пустой массив obj. push добавляет элементы-объекты
       obj.push({ip:"192.168.11.11", login:"admin", password:"admin"});
       obj.push({ip:"192.168.11.12", login:"admin", password:"admin"});
    

    А можно в сценарии каким-нибудь образом брать данные по камерам из плагина?

    Нет, в Cherry такой возможности нет

    И да - у плагина CCTV будет древовидная структура в 5-й версии iH?

    Да, в V5 деревья будут почти везде 🙂



  • Подскажите, как в сценарии написать условие: если у датчика движения за последних 60 секунд не было движения то что бы сработало другое устройство. Проблема у меня: стоят внешние ролокасеты, по закату солнца закрываются и если хто то есть на улице то они все равно закрываются, на улице стоит датчик движения и хочу его подключить к сценарию.

    /** 
    * @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();
          jalusi.setBlk(1);
          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;
            case "ACTOR10":
              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();
          jalusi.setBlk(1);
          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;
            case "ACTOR10":
              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;
            case "ACTOR10":
              this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_open')+':0;'});
            break;
          }
          global.set('jalusi_work',false);
          jalusi.setBlk(0);
          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;
            case "ACTOR10":
              this.pluginCommand({unit:'megad2', command:'/258/?cmd='+jalusi.getParam('point_close')+':0;'});
            break;
          }
          global.set('jalusi_work',false);
          jalusi.setBlk(0);
          if(global.get('jalusi_count')===0){
            switch_1.setValue(1);
          }
          this.log('End Jalusi Down');
        }
    });
    
    
    /** 
    * @name Жалюзі закрити 
    * @desc  
    * @version 4  
    */
    const mid = Device("ACTORA1");
    const jalusi_1 = Device("ACTOR7");
    const jalusi_2 = Device("ACTOR8");
    const jalusi_3 = Device("ACTOR9");
    const jalusi_4 = Device("ACTOR10");
    const switch_jalusi = Device("SWITCH_windows");
    
    script({
        start() {
            if(jalusi_1.isOn() || jalusi_2.isOn() || jalusi_3.isOn() || jalusi_4.isOn()){
              this.assign( switch_jalusi, "value", 2);
              mid.setValue([10016, 20]);
            }
        } 
    });
    
    


  • @amgstone, вроде как в сченарии для управления освещением по датчику движения тут было опубликовано уже. Вот модификация моя:

    const lamp = Device("ActorD", "Светильник", [
      {"name":"timeOff", "note":"Светильник горит без движения, мин", "type":"number", "val":1}
      ]);
    
            if(motion.isOn()) {
              lamp.turnOnSaveAuto();  // Если просто дать команду on - АВТО будет сброшен.
                                      // Сейчас мы хотим сохранить АВТО  
            }
            else {
              // движения нет - взводим таймер, чтобы отключить 
              this.startTimer("T1", lamp.getParam("timeOff")*60, "turnOff");       
            }
    
        // Функция, которая сработает, когда таймер досчитает (нет движения в течение
        // заданного времени) - отключаем и выходим
        turnOff() {
          lamp.turnOffSaveAuto();
          this.exit();
        }
    

    По вашей роллете нужно делать аналогично.



  • @Alex_Jet нет, у меня там не все так просто, за закрытие ролокасет отвечает switch, надо какое то условие, что когда срабатывает switch на закрытие ролокасет опрашивался датчик движение и запретил закрывать ролокасету (двери-actor), и когда движение небудет установленое время то закрить отрытую ролокасету.



  • @amgstone, ну вы же сами описываете свой алгоритм! Значит надо для switch сделать слушателя, который будет выполнять функцию, в которой будет проверяться состояние датчика движения и взводить соответствующий таймер.



  • @Алексей, во-первых, не понятно о чем вы говорите, во-вторых, может вы ошиблись форумом?



  • @intrapro, помогите свежим взглядом разобраться. Выявил, что почему-то иногда сценарий передает "не контроллируемые" данные - передачу громкости 58 и 100 единиц:
    Сам сценарий запускается по входящему от терминала:

    12.10 12:39:55.773 voiceterminal1: 192.168.11.51 => localhost:11051 HTTP GET /api/method/name.method?terminal=VT1&volume=58&uptime=92530&username=voiceterminal
    12.10 12:39:55.774 voiceterminal1: 192.168.11.51 <= localhost:11051 
    12.10 12:39:55.774 voiceterminal1: { type: 'startscene',
      id: 'VoiceTerminal_Status',
      arg: '{"terminal":"VT1","volume":"58","uptime":"92530","username":"voiceterminal"}' }
    12.10 12:39:55.776 IH: plugin command { unit: 'voiceterminal1', command: 'volume:58', type: 'command' }
    12.10 12:39:55.778 IH: startscene VoiceTerminal_Status
    12.10 12:39:55.779 voiceterminal1: send command to terminal - 'volume:58'
    12.10 12:39:55.779 voiceterminal1: connection by socket to the 192.168.11.51:7999 successfull!
    12.10 12:39:55.779 voiceterminal1: send data by socket - 'volume:58'
    12.10 12:39:55.780 voiceterminal1: connection by socket to the 192.168.11.51:7999 is end!
    12.10 12:39:55.833 voiceterminal1: 192.168.11.51 => localhost:11051 HTTP GET /api/method/name.method?terminal=VT1&volume=100&uptime=92530&username=voiceterminal
    12.10 12:39:55.834 voiceterminal1: 192.168.11.51 <= localhost:11051 
    12.10 12:39:55.834 voiceterminal1: { type: 'startscene',
      id: 'VoiceTerminal_Status',
      arg: '{"terminal":"VT1","volume":"100","uptime":"92530","username":"voiceterminal"}' }
    12.10 12:39:55.835 IH: plugin command { unit: 'voiceterminal1',
      command: 'volume:100',
      type: 'command' }
    12.10 12:39:55.838 IH: startscene VoiceTerminal_Status
    12.10 12:39:55.838 voiceterminal1: send command to terminal - 'volume:100'
    12.10 12:39:55.839 voiceterminal1: connection by socket to the 192.168.11.51:7999 successfull!
    12.10 12:39:55.839 voiceterminal1: send data by socket - 'volume:100'
    12.10 12:39:55.839 voiceterminal1: connection by socket to the 192.168.11.51:7999 is end!
    12.10 12:39:55.893 voiceterminal1: 192.168.11.51 => localhost:11051 HTTP GET /api/method/name.method?terminal=VT1&volume=58&uptime=92530&username=voiceterminal
    12.10 12:39:55.893 voiceterminal1: 192.168.11.51 <= localhost:11051 
    12.10 12:39:55.894 voiceterminal1: { type: 'startscene',
      id: 'VoiceTerminal_Status',
      arg: '{"terminal":"VT1","volume":"58","uptime":"92530","username":"voiceterminal"}' }
    12.10 12:39:55.895 IH: plugin command { unit: 'voiceterminal1', command: 'volume:58', type: 'command' }
    12.10 12:39:55.898 IH: startscene VoiceTerminal_Status
    12.10 12:39:55.898 voiceterminal1: send command to terminal - 'volume:58'
    12.10 12:39:55.899 voiceterminal1: connection by socket to the 192.168.11.51:7999 successfull!
    12.10 12:39:55.899 voiceterminal1: send data by socket - 'volume:58'
    12.10 12:39:55.899 voiceterminal1: connection by socket to the 192.168.11.51:7999 is end!
    12.10 12:39:55.950 voiceterminal1: 192.168.11.51 => localhost:11051 HTTP GET /api/method/name.method?terminal=VT1&volume=100&uptime=92530&username=voiceterminal
    12.10 12:39:55.950 voiceterminal1: 192.168.11.51 <= localhost:11051 
    12.10 12:39:55.951 voiceterminal1: { type: 'startscene',
      id: 'VoiceTerminal_Status',
      arg: '{"terminal":"VT1","volume":"100","uptime":"92530","username":"voiceterminal"}' }
    12.10 12:39:55.952 IH: plugin command { unit: 'voiceterminal1',
      command: 'volume:100',
      type: 'command' }
    12.10 12:39:55.955 IH: startscene VoiceTerminal_Status
    12.10 12:39:55.956 voiceterminal1: send command to terminal - 'volume:100'
    12.10 12:39:55.956 voiceterminal1: connection by socket to the 192.168.11.51:7999 successfull!
    12.10 12:39:55.957 voiceterminal1: send data by socket - 'volume:100'
    12.10 12:39:55.957 voiceterminal1: connection by socket to the 192.168.11.51:7999 is end!
    12.10 12:39:56.006 voiceterminal1: 192.168.11.51 => localhost:11051 HTTP GET /api/method/name.method?terminal=VT1&volume=58&uptime=92531&username=voiceterminal
    12.10 12:39:56.006 voiceterminal1: 192.168.11.51 <= localhost:11051 
    12.10 12:39:56.007 voiceterminal1: { type: 'startscene',
      id: 'VoiceTerminal_Status',
      arg: '{"terminal":"VT1","volume":"58","uptime":"92531","username":"voiceterminal"}' }
    12.10 12:39:56.008 IH: plugin command { unit: 'voiceterminal1', command: 'volume:58', type: 'command' }
    12.10 12:39:56.011 IH: startscene VoiceTerminal_Status
    12.10 12:39:56.012 voiceterminal1: send command to terminal - 'volume:58'
    12.10 12:39:56.012 voiceterminal1: connection by socket to the 192.168.11.51:7999 successfull!
    12.10 12:39:56.012 voiceterminal1: send data by socket - 'volume:58'
    12.10 12:39:56.012 voiceterminal1: connection by socket to the 192.168.11.51:7999 is end!
    12.10 12:39:56.044 voiceterminal1: 192.168.11.51 => localhost:11051 HTTP GET /api/method/name.method?terminal=VT1&volume=100&uptime=92531&username=voiceterminal
    12.10 12:39:56.044 voiceterminal1: 192.168.11.51 <= localhost:11051 
    12.10 12:39:56.045 voiceterminal1: { type: 'startscene',
      id: 'VoiceTerminal_Status',
      arg: '{"terminal":"VT1","volume":"100","uptime":"92531","username":"voiceterminal"}' }
    12.10 12:39:56.046 IH: plugin command { unit: 'voiceterminal1',
      command: 'volume:100',
      type: 'command' }
    12.10 12:39:56.048 IH: startscene VoiceTerminal_Status
    12.10 12:39:56.049 voiceterminal1: send command to terminal - 'volume:100'
    12.10 12:39:56.049 voiceterminal1: connection by socket to the 192.168.11.51:7999 successfull!
    12.10 12:39:56.049 voiceterminal1: send data by socket - 'volume:100'
    12.10 12:39:56.050 voiceterminal1: connection by socket to the 192.168.11.51:7999 is end!
    12.10 12:39:56.366 voiceterminal1: 192.168.11.51 => localhost:11051 HTTP GET /api/method/name.method?terminal=VT1&volume=58&uptime=92531&username=voiceterminal
    12.10 12:39:56.366 voiceterminal1: 192.168.11.51 <= localhost:11051 
    12.10 12:39:56.367 voiceterminal1: { type: 'startscene',
      id: 'VoiceTerminal_Status',
      arg: '{"terminal":"VT1","volume":"58","uptime":"92531","username":"voiceterminal"}' }
    12.10 12:39:56.368 IH: plugin command { unit: 'voiceterminal1', command: 'volume:58', type: 'command' }
    12.10 12:39:56.370 IH: startscene VoiceTerminal_Status
    12.10 12:39:56.371 voiceterminal1: send command to terminal - 'volume:58'
    12.10 12:39:56.371 voiceterminal1: connection by socket to the 192.168.11.51:7999 successfull!
    12.10 12:39:56.372 voiceterminal1: send data by socket - 'volume:58'
    12.10 12:39:56.372 voiceterminal1: connection by socket to the 192.168.11.51:7999 is end!
    12.10 12:39:56.403 voiceterminal1: 192.168.11.51 => localhost:11051 HTTP GET /api/method/name.method?terminal=VT1&volume=100&uptime=92531&username=voiceterminal
    12.10 12:39:56.403 voiceterminal1: 192.168.11.51 <= localhost:11051 
    12.10 12:39:56.403 voiceterminal1: { type: 'startscene',
      id: 'VoiceTerminal_Status',
      arg: '{"terminal":"VT1","volume":"100","uptime":"92531","username":"voiceterminal"}' }
    12.10 12:39:56.405 IH: plugin command { unit: 'voiceterminal1',
      command: 'volume:100',
      type: 'command' }
    12.10 12:39:56.408 IH: startscene VoiceTerminal_Status
    12.10 12:39:56.408 voiceterminal1: send command to terminal - 'volume:100'
    12.10 12:39:56.408 voiceterminal1: connection by socket to the 192.168.11.51:7999 successfull!
    12.10 12:39:56.409 voiceterminal1: send data by socket - 'volume:100'
    12.10 12:39:56.409 voiceterminal1: connection by socket to the 192.168.11.51:7999 is end!
    12.10 12:39:56.632 voiceterminal1: 192.168.11.51 => localhost:11051 HTTP GET /api/method/name.method?terminal=VT1&status=start_record&uptime=92531&username=voiceterminal
    12.10 12:39:56.632 voiceterminal1: 192.168.11.51 <= localhost:11051 
    12.10 12:39:56.633 voiceterminal1: { type: 'startscene',
      id: 'VoiceTerminal_Status',
      arg: '{"terminal":"VT1","status":"start_record","uptime":"92531","username":"voiceterminal"}' }
    12.10 12:39:56.636 IH: startscene VoiceTerminal_Status
    

    Сценарий создавался для того, чтобы:

    1. На вкладке параметры устройства отображать состояние терминала
    2. Со вкладки параемтры регулировать громкость терминала и плеера.
    const dev1 = Device("_UNIT_voiceterminal1", [
      {"name":"uptime", "note":"Времы работы", "type":"string", "val":""},
      {"name":"status", "note":"Состояние", "type":"string", "val":""},
      {"name":"updater", "note":"Обновления", "type":"string", "val":""},
      {"name":"set_volume", "note":"Громкость терминала", "type":"number", "val":50},
      {"name":"set_music_volume", "note":"Громкость плеера", "type":"number", "val":50},
      {"name":"last_update", "note":"Update", "type":"string", "val":""}
      ]);
    
    const dev2 = Device("_UNIT_voiceterminal2", [
      {"name":"uptime", "note":"Времы работы", "type":"string", "val":""},
      {"name":"status", "note":"Состояние", "type":"string", "val":""},
      {"name":"updater", "note":"Обновление", "type":"string", "val":""},
      {"name":"set_volume", "note":"Громкость терминала", "type":"number", "val":50},
      {"name":"set_music_volume", "note":"Громкость плеера", "type":"number", "val":50},
      {"name":"last_update", "note":"Last update", "type":"string", "val":""}
      ]);
    
    script({
      start(param) {
        let device = '';
    
        //Скрипт запускается плагином с параметрами
        if(param !== undefined) {
          
          const obj = this.ParseJSON(param);
          
          //Выбор устройства
          if(obj.terminal == "VT1") {
            device = dev1;
          }
          else if(obj.terminal == "VT2") {
            device = dev2;
          }
        
          //Конвертация времени из секунд в часы
          let days = Math.floor(obj.uptime/86400);
          let hours = Math.floor((obj.uptime % 86400)/3600);
          let minutes = Math.floor((obj.uptime % 3600)/60);
          let seconds = obj.uptime % 60;
          let time = days+ "d " +((hours < 10) ? "0" : "")+hours+ ":" +((minutes < 10) ? "0" : "")+minutes+ ":" +((seconds < 10) ? "0" : "")+seconds;
          
          //Обновление параметров устройства
          if(obj.uptime !== undefined)
          device.setParam("uptime", time);
          
          if(obj.status !== undefined)
          device.setParam("status", obj.status);
          
          if(obj.updater !== undefined)
          device.setParam("updater", obj.updater);
          
          if(obj.volume !== undefined)
          device.setParam("set_volume", obj.volume);
          
          if(obj.music_volume !== undefined)
          device.setParam("set_music_volume", obj.music_volume);
          
          device.setParam("last_update", this.GetDate());
        }
      },
      
      ParseJSON(param) {
          try {
            return JSON.parse(param);
          }
          catch (e) {
            let text = e instanceof SyntaxError;
            this.log("SyntaxError - " +text+ "; param - " +param);
          }
      },
      
      GetDate() {
        return new Date().toLocaleString('ru-RU');
      }
    });
    

    В отладчике сценария:

    12.10 12:39:37.115 Started
    12.10 12:39:37.116 do _UNIT_voiceterminal1 uptime 1d 01:41:52
    12.10 12:39:37.117 do _UNIT_voiceterminal1 set_volume 58
    12.10 12:39:37.121 do _UNIT_voiceterminal1 last_update 2020-10-12 12:39:37
    12.10 12:39:37.122 Stopped
    12.10 12:39:37.148 Started
    12.10 12:39:37.149 do _UNIT_voiceterminal1 uptime 1d 01:41:52
    12.10 12:39:37.150 do _UNIT_voiceterminal1 set_volume 100
    12.10 12:39:37.152 do _UNIT_voiceterminal1 last_update 2020-10-12 12:39:37
    12.10 12:39:37.153 Stopped
    12.10 12:39:37.427 Started
    12.10 12:39:37.428 do _UNIT_voiceterminal1 uptime 1d 01:41:52
    12.10 12:39:37.428 do _UNIT_voiceterminal1 set_volume 58
    12.10 12:39:37.432 do _UNIT_voiceterminal1 last_update 2020-10-12 12:39:37
    12.10 12:39:37.432 Stopped
    12.10 12:39:37.464 Started
    12.10 12:39:37.464 do _UNIT_voiceterminal1 uptime 1d 01:41:52
    12.10 12:39:37.465 do _UNIT_voiceterminal1 set_volume 100
    12.10 12:39:37.467 do _UNIT_voiceterminal1 last_update 2020-10-12 12:39:37
    12.10 12:39:37.468 Stopped
    12.10 12:39:37.676 Started
    12.10 12:39:37.676 do _UNIT_voiceterminal1 uptime 1d 01:41:52
    12.10 12:39:37.677 do _UNIT_voiceterminal1 status start_record
    12.10 12:39:37.680 do _UNIT_voiceterminal1 last_update 2020-10-12 12:39:37
    12.10 12:39:37.681 Stopped
    

    Хм...этот сценарий причем лишь косвенно. Отрабатывает другой - вот этот!!!

    const dev1 = Device("_UNIT_voiceterminal1");
    const dev2 = Device("_UNIT_voiceterminal2");
    
    startOnChange([dev1,dev2]);
    
    script({
      start() {
        let device = '';
        let flag_volume = 0;
        
        //Проверка с какого устройства поступила команда
        if(this.isChanged(dev1, "set_volume")) {
          device = dev1;
          flag_volume = 1;
        }
        else if(this.isChanged(dev2, "set_volume")) {
          device = dev2;
          flag_volume = 1;
        }
        else if(this.isChanged(dev1, "set_music_volume")) {
          device = dev1;
          flag_volume = 2;
        }
        else if(this.isChanged(dev2, "set_music_volume")) {
          device = dev2;
          flag_volume = 2;
        }
        
        //Установка громкости на нужном терминале
        if(flag_volume == 1) this.SetVolumeTerminal(device);
        else if(flag_volume == 2) this.SetVolumeMusic(device);
      },
      
      SetVolumeTerminal(device) {
        let unit = device.id.replace('_UNIT_', '');
        let command = device.getParam('set_volume');
        this.pluginCommand({unit: unit, command:"volume:" +command});
      },
      
      SetVolumeMusic(device) {
        let unit = device.id.replace('_UNIT_', '');
        let command = device.getParam('set_music_volume');
        this.pluginCommand({unit: unit, command:"mvolume:" +command});
      }
    });
    

    Его лог:

    12.10 12:52:43.246 Trigger _UNIT_voiceterminal1
    12.10 12:52:43.247 Started
    12.10 12:52:43.247 isChanged(_UNIT_voiceterminal1,set_volume)=true Changed: {"_UNIT_voiceterminal1":{"set_volume":"58"}}
    12.10 12:52:43.247 plugincCommand { unit: 'voiceterminal1', command: 'volume:58' }
    12.10 12:52:43.248 Stopped
    12.10 12:52:43.285 Trigger _UNIT_voiceterminal1
    12.10 12:52:43.285 Started
    12.10 12:52:43.286 isChanged(_UNIT_voiceterminal1,set_volume)=true Changed: {"_UNIT_voiceterminal1":{"set_volume":"100"}}
    12.10 12:52:43.286 plugincCommand { unit: 'voiceterminal1', command: 'volume:100' }
    12.10 12:52:43.287 Stopped
    12.10 12:52:43.602 Trigger _UNIT_voiceterminal1
    12.10 12:52:43.603 Started
    12.10 12:52:43.603 isChanged(_UNIT_voiceterminal1,set_volume)=true Changed: {"_UNIT_voiceterminal1":{"set_volume":"58"}}
    12.10 12:52:43.604 plugincCommand { unit: 'voiceterminal1', command: 'volume:58' }
    12.10 12:52:43.604 Stopped
    12.10 12:52:43.661 Trigger _UNIT_voiceterminal1
    12.10 12:52:43.661 Started
    12.10 12:52:43.662 isChanged(_UNIT_voiceterminal1,set_volume)=true Changed: {"_UNIT_voiceterminal1":{"set_volume":"100"}}
    12.10 12:52:43.662 plugincCommand { unit: 'voiceterminal1', command: 'volume:100' }
    12.10 12:52:43.663 Stopped
    12.10 12:52:43.698 Trigger _UNIT_voiceterminal1
    12.10 12:52:43.698 Started
    12.10 12:52:43.699 isChanged(_UNIT_voiceterminal1,set_volume)=true Changed: {"_UNIT_voiceterminal1":{"set_volume":"58"}}
    12.10 12:52:43.699 plugincCommand { unit: 'voiceterminal1', command: 'volume:58' }
    12.10 12:52:43.700 Stopped
    12.10 12:52:43.931 Trigger _UNIT_voiceterminal1
    

    Заблокировал сценарий - все пропало. Разблокировал сценарий - тоже все нормально. В какой-то момент что-то происходит, что на каждый "чих" голосового терминала последний сценарий шлет ему громкость 58 и 100 попеременно (вероятно эти значения были заданы на вкладке "Параметры").
    Пока не могу предположить почему так происходит...



  • Подсжите как сделать сценарий: обратный отсчет времени для замены фильтра воды.



  • @amgstone создал сценарий:

    /** 
    * @name Заміна фільтра води 
    * @desc  
    * @version 4 
    */
    const meter = Device("Meter","час заміни фільтра"); 
    
    script({
        start() {
        meter.setParam("aval",meter.getParam("aval")+1);
        if(meter.getParam("aval")===90){
        this.info('telegram', 'OWNER', 'Заміна фільтра води');
        this.info('pushnotification', 'OWNER', 'Заміна фільтра води'); 
        
        }
        } 
    });
    
    

    но в IH не смог создать дату, чтобы визуализировало дату когда надо заменить фильтр, возможно добавите устройство?



  • Готовлюсь к новому году) в проем гаражных ворот смонтировал RGB-ленту на базе WS2818. Хочется реализовать эффект бегущего огня с плавно изменяемой яркостью (вот пример - смотреть на 2:52-3:02). Я конечно понимаю, что iH - это не RGB-контроллер, но все же есть ли какая-то возможность сделать подобный эффект?? Сам сделал "длинный" бегущий огонь, но код очень топорный...

        TronEffect() {
          this.addListener(sw, "ChangeStateSw");
          
          let blue = 'FF00FF';
          let dark = '000000';
          let color = [blue+blue+blue+dark+dark+dark,dark+blue+blue+blue+dark+dark, dark+dark+blue+blue+blue+dark, dark+dark+dark+blue+blue+blue, blue+dark+dark+dark+blue+blue, blue+blue+dark+dark+dark+blue];
          
          if(++this.i > color.length-1) this.i = 0;
          this.cmd = color[this.i];
          
          this.SendDataToWS2818(this.plugin, this.channel, this.cmd, this.chip);
          
          this.startTimer("T1", this.period, "TronEffect");
        },
    

    Причем это просто бегущий огонь из 6 "пикселей". Как сделать уменьшающийся по яркости хвост огня и увеличить его скорость - это большой вопрос!!



  • @Alex_Jet Добрый день, судя по коду, огонь у вас бегает в переделах 6-ти пикселей ? какая длина ленты у вас ? есть фризы ?



  • @dev, огонь смещается по 6 пикселям. Но поскольку megad повторяет всю эту посылку N-количество раз (ключ "chip" - тут описание), то выглядит это вот так:
    видео. Лента состоит из двух логических запараллеленых кусков длиной 39 чипов)). Ну а вообще длина - 2,4+3+2,4 м. Что такое фризы?



  • Пользователь @intrapro написал в Сценарии - новая версия API:

    @homa, пока такой возможности нет 😞

    Подскажите, появилась возможность запуска сценария из сценария ?
    И есть ли возможность после перезагрузки системы возобновлять работу активных сценариев ?



  • Пользователь @fanagor написал в Сценарии - новая версия API:

    И есть ли возможность после перезагрузки системы возобновлять работу активных сценариев ?

    А так не получается - функция boot()?
    @intrahouse, @dev, я бы всякие такие возможности (startOnChange, check, boot и прочее) добавил бы на страницу "Система команд".


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