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



  • Здравствуйте, уважаемые разработчики и форумчане! Поздравляю всех с наступившим Новым 2021 годом!
    Желаю всем творческих успехов.
    А теперь о проблеме. Пишу сценарий для управления новогодней гирляндой. У нее есть http API. При управлении используются данные из предыдущих ответов на запрос. Проблема в том, что не получается распарсить ответ и присвоить его разным переменным. Вот, собственно, сценарий

    /** 
    * @name twinkly_http 
    * @desc  
    * @version 4  
    */
    
    script({
        host: '192.168.144.68',
        port: 80,
        method: '',
        path: '',
        myObj: '',
    
        start() {
          // login
          this.path = '/xled/v1/login';
          this.method = 'POST';
          this.send_http();
    
          // verify
          
          // Действие
          
        },  
        
        send_http() {
          const http = require('http');
          const querystring = require('querystring');
          const postData = JSON.stringify({
            challenge: 'AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8='
          });
          this.log('postData: '+postData);
          
          var options = {
            hostname: this.host,
    	      port: this.port,
    	      path: this.path,
    	      method: this.method,
    	      headers: {
    	        'Host': '192.168.144.68',
    		      'Content-Type': 'application/json',
    		      'Content-Length': postData.length //Buffer.byteLength(postData)
    	      }
          };
    
          var req = http.request(options, (res) => {
    	      this.log('STATUS: '+res.statusCode);
    	      this.log('HEADERS:' +JSON.stringify(res.headers));
    	      res.setEncoding('utf8');
    	      res.on('data', (chunk) => this.myObj += chunk);
    
    	      res.on('end', () => {
    		      this.log('Data:' +this.myObj);
    		      const data = JSON.parse(this.myObj);
    		      this.log('Code:' +data);
    		      this.log(typeof this.myObj === 'string');
    		      this.log('No more data in response.');
    	      });
          });
    
          req.on('error', (e) => {
    	      this.log('problem with request: ' +e.message);
          });
    
          // write data to request body
          req.write(postData);
          req.end();
        }
    });
    

    А вот сообщение в отладчике

    03.01 13:15:08.970 Started
    03.01 13:15:08.971 log: postData: {"challenge":"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8="}
    03.01 13:15:08.994 Stopped
    03.01 13:15:09.013 log: STATUS: 200
    03.01 13:15:09.017 log: HEADERS:{"connection":"close","content-length":"155","content-type":"application/json"}
    03.01 13:15:09.021 log: Data:{"authentication_token":"4Be8Ix3sQBQ=","authentication_token_expires_in":14400,"challenge-response":"7ef99322220ff8a9c45aa1efa26ba01d2320aecc","code":1000}
    03.01 13:15:09.024 log: Code:[object Object]
    03.01 13:15:09.026 log: true
    03.01 13:15:09.028 log: No more data in response.

    Данные из строки Data не могу получить по отдельности. Перечитал разные доки, форумы. Ничего не получается. Что я делаю не так?



  • @int144, добрый день! Удачи в Новом году!!!

    Данные из строки Data не могу получить по отдельности.

    Если только в этом проблема, то здесь у вас уже все есть, нужно брать свойства data через точку:

    const data = JSON.parse(this.myObj); // из строки получился прекрасный объект, дальше присваиваете свойствам сценария или локально:

    this.authentication_token = data.authentication_token;
    const challenge-response = data.challenge-response;



  • @intrapro, спасибо за быстрый ответ.
    Заработало, хотя вроде пробовал так, но может не совсем так. Но!
    Значения выводятся в лог, только если я их присвоил в разделе res.on('end'..., а если я пытаюсь вывести в лог присвоенные значения из start после вызова this.send_http, то получаю пустые значения



  • @int144, все верно, start работает синхронно, он просто запускает запрос в this.send_http и идет дальше. Не ждет, когда придет ответ на запрос.

    03.01 13:15:08.994 Stopped - здесь start уже работу свою закончил

    Можно взвести таймер (на 1 сек или меньше, 0.1 даже достаточно). И в этой функции значения уже должны быть



  • @intrapro, а таймер взводить в start?



  • @int144, да



  • @intrapro, спасибо, буду пробовать



  • Добрый день!
    Не работает команда операционной системы
    Вот сценарий

    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.



  • @amgstone,

    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. Хотелось бы узнать, тут все верно или есть "косячок"?


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