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



  • @homa:

    ps

    извините, разобрался. работает с \n

    Это хорошо. 🙂 Но вписывать многострочное сообщение в одну строку все равно неудобно. Будет многострочное поле.



  • Еще вопрос… можно ли получить значение счетчика через конфигуратор блок-схем? Не получается его выбрать ни в одном из типов устройств



  • @homa:

    Еще вопрос… можно ли получить значение счетчика через конфигуратор блок-схем? Не получается его выбрать ни в одном из типов устройств

    А зачем? Отправлять показания можно из расписания.



  • @Alex_Jet:

    Все вышеописанное Вами, надо в статью/вики добавить.

    Спасибо. Добавили.



  • В новой версии перестали прицепляться сценарии в расписаниях. Новые сценарии не отображаются, старые, которые были удалены, отображаются. Кроме того в рабочих сценариях отображаются сценарии, которых уже нет и удалить их не получается.
    сценарии.JPG
    расписание.JPG



  • Проанализировали ситуацию.

    1.В список сценариев в расписание попадают только те сценарии, которые не имеют триггеров. Поэтому вы не видите в этом списке всех ваших сценариев.

    2.Нельзя редактировать сценарии в разделе "Рабочие сценарии". Наша ошибка. Не убрали эту возможность. :oops:

    Попробуйте перезагрузить систему. В списке рабочих сценариев "лишние" сценарии должны пропасть.

    Если проблема останется прошу выслать проект нам на support.



  • @intrahouse:

    Проанализировали ситуацию.

    1.В список сценариев в расписание попадают только те сценарии, которые не имеют триггеров. Поэтому вы не видите в этом списке всех ваших сценариев.

    2.Нельзя редактировать сценарии в разделе "Рабочие сценарии". Наша ошибка. Не убрали эту возможность. :oops:

    Попробуйте перезагрузить систему. В списке рабочих сценариев "лишние" сценарии должны пропасть.

    Если проблема останется прошу выслать проект нам на support.

    Перезагружать несколько раз пробовал, не помогло… Выслал проект.

    Просьба посмотреть также сценарии на JS4 и блок-схемах. Там вроде нет триггеров, но они не отображаются... Может я что-то не понимаю



  • Сценарии теперь видны из расписания и их можно запускать по времени, но при автоматическом вызове из расписания сценарий отрабатывает дважды. Если запустить сценарий вручную, то приходит одно сообщение в телеграмм, если сценарий срабатывает из расписания, то приходит два сообщения, причем это не дубль сообщения, а именно второй вызов сценария, т.к. значения датчиков в выводе различаются. Тоже самое при оповещении на почту



  • если создать сценарий-блоксхему с несколькими триггерами, то при изменении одного из триггеров уведомления происходят по всем триггерам. Это правильная работа или же нужно создать отдельный сценарий на каждый триггер?
    ping.JPG



  • подскажите как можно получить название состояния устройства? x.value возвращает №состояния, а хотелось бы получать именно название состояния

    Также предложение - для уведомления по email добавить возможность указания темы письма



  • @homa:

    подскажите как можно получить название состояния устройства?

    x.stateName

    В описании системы команд не было. Добавили https://ih-systems.com/ru/command_list/
    @homa:

    Также предложение - для уведомления по email добавить возможность указания темы письма

    Сделаем позже.
    @homa:

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

    Работает правильно.

    По идее в блок-схемах не хватает проверки isChanged() Добавим этот элемент в блок-схемы позже.

    В вашем примере я бы сделал мультисценарий и привязал к нужным устройствам

    Но можно и отдельными сценариями 😉
    @homa:

    Сценарии теперь видны из расписания и их можно запускать по времени, но при автоматическом вызове из расписания сценарий отрабатывает дважды

    Это баг. Исправим сегодня в новой версии.



  • Несколько вопросов по js:

    1. Как в callback передать параметры? В отладчике такая ошибка:

    29.12 09:26:38.091 Done timer T2
    29.12 09:26:38.091 exec function TurnOffOLED(megad5,30)
    29.12 09:26:38.092 Error function TurnOffOLED(megad5,30):sceneSet[name][func] is not a function
    
    

    Задача - после передачи данных на дисплей хочу чтобы он через 10 секунд выключился:

        DataToOLED(text, value, nameunit, channel) {
          this.TurnOnOLED(nameunit, channel);
    
          //Форматирование цифровых значений
          value = value.toFixed(1);
          let str = value.toString();
          if(str.length < 4 && value > 0) str = 's+' +str;
          else if(str.length < 4) str = 'ss' +str;
          else if(str.length < 5) str = 's' +str;
    
          //Вывод команд на дисплей
          this.pluginCommand({unit: nameunit, command: '/sec/?pt=' +channel+ '&text=' +text+ '&col=0&row=0'});
          this.pluginCommand({unit: nameunit, command: '/sec/?pt=' +channel+ '&text=' +str+ ':'});
    
          this.startTimer("T2", 10, "TurnOffOLED(" +nameunit+ "," +channel+ ")");
        },
    
    
    

    Сама функция выключения:

        TurnOffOLED(nameunit, channel) {
          this.pluginCommand({unit: nameunit, command: '/sec/?cmd=' +channel+ ':0'});
        }
    
    
    

    2. Первый раз столкнулся с задачей конвертировать строку из utf-8 в cp866…в js это сделать оказалось не тривиальной задачей 😞 . Люди на форумах так и пишут - делайте это в php... можете помочь?

    3. Придумал алгоритм отображения различных показаний на OLED-экране. Подскажите как при срабатывании кнопки в сценарии можно каждый раз увеличивать значение переменно? Пока сделал с помощью глобальной переменной:

          //Перебор параметров при каждом нажатии кнопки
          let value = global.get('Button_Guest') + 1;
          if(isNaN(value) || value > 2) global.set('Button_Guest', 0);
          global.set('Button_Guest', value);
    
    
    


  • @Alex_Jet:

    Несколько вопросов по js:

    Начнем с конца

    @Alex_Jet:

    3. Придумал алгоритм отображения различных показаний на OLED-экране. Подскажите как при срабатывании кнопки в сценарии можно каждый раз увеличивать значение переменно? Пока сделал с помощью глобальной переменной:

    Это можно сделать, объявив переменную сценария. Сценарий у нас - не набор функций, а объект, поэтому может иметь свойство - переменную, которая сохраняется между запусками: Объявить ее нужно прямо в объекте, а не в теле функции. Инициализация начальным значением происходит при загрузке сценария (старте сервера). Далее переменную можно использовать через this в любом месте сценария

    
    script({
       myVar:0,
       start() {
        if (this.myVar <10) this.myVar += 1;
       },
    
      clear() {
        this.myVar = 0;
      } 
    })
    
    
    

    @Alex_Jet:

    2. Первый раз столкнулся с задачей конвертировать строку из utf-8 в cp866…в js это сделать оказалось не тривиальной задачей 😞 . Люди на форумах так и пишут - делайте это в php... можете помочь?

    Для конвертирования строк есть готовые модули для node.js, которые можно загрузить через npm

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

    Но если очень хочется, то можно попробовать 🙂

    Есть библиотека iconv-lite, нужно ее установить в /opt/intrahouse-c/backend/

    Можно установить вручную, можно просто дописать в /opt/intrahouse-c/backend/package.json в раздел dependencies

    "iconv-lite": "^0.4.24",

    И перезагрузить сервер

    В папке /opt/intrahouse-c/backend/node_modules должна появиться папка iconv-lite

    В сценарии для кодирования написать:

    let buf = require("iconv-lite").encode("привет, это строка для кодирования", "cp866")

    Получили буфер байт, его надо включить в url как строку (здесь результат не гарантирован, но должно сработать)

    let text = buf.toString()

    @Alex_Jet:

    1. Как в callback передать параметры?

    В callback параметры не передаются, нужно использовать механизм п.1 - создайте переменные объекта и используйте их через this.



  • Спасибо за ответы! С переменной сценария все получилось.

    Еще вопрос по переменным. Хочу сделать мультисценарий, как в нем описать плагин, который хочу выбирать в "Запуск для устройств" чтобы использовать для вывода информации на OLED? В конечном счете надо чтобы его имя подставлялось в

    this.pluginCommand({unit: plugin, command: '/sec/?pt=' +channel+ '&disp_cmd=1&row=0'});
    
    

    А еще как сделать чтобы в "Запуск для устройств" можно было указать канал плагина?

    Идея такая - в мультисценарии выбираем кнопку, нужные датчики (4 шт.), плагин и номер канала, к которому подключен OLED. В комнатах где будет OLED на нем будут отображаться "свои" показания датчиков.

    Кстати, нашел пару опечаток:

    1. В отладчике пишет - "plugincCommand"

    2. При создании нового сценарий - "Новый сценарийТ"



  • @sergeyygr:

    Добрый день!

    Может я просто не до конца разобрался в инструкциях. У меня освещением на кухне управляет мультисценарий включения света по датчику движения с учетом аналогового датчика освещенности. Очень хочется сделать так, что бы начиная с 23.00 и до утра основной свет не включался, а включалась подсветка. Т.е. один сценарий прекратил работу, а с 23.00 начал работу другой. Подскажите пожалуйста как это сделать. Сценарий скачан отсюда https://ih-systems.com/ru/scenes-examples/.

    Можно сделать так.

    Сценарии освещения по датчику движения оставить как есть. Только они должны учитывать режим Auto.

    Плюс добавить два сценария включения/выключения режима Auto для этих двух светильников.

    Первый сценарий будет запускаться по расписанию в 23.00 Устанавливать "auto" для одного светильника и снимать "auto" для другого

    Второй наоборот, и запускается в 7.00

    Так как эти сценарии запускаются по расписанию, триггер в них не нужен

    В виде блок-схемы сценарий выглядит так:
    scen201.jpg

    Если есть желание, можно немного усовершенствовать. Если в момент переключения режима авто первый светильник был включен, можно его выключить и включить второй светильник:
    scen301.jpg



  • @Alex_Jet:

    Еще вопрос по переменным. Хочу сделать мультисценарий, как в нем описать плагин, который хочу выбирать в "Запуск для устройств" чтобы использовать для вывода информации на OLED? В конечном счете надо чтобы его имя подставлялось в

    > this.pluginCommand({unit: plugin, command: '/sec/?pt=' +channel+ '&disp_cmd=1&row=0'});
    > 
    

    А еще как сделать чтобы в "Запуск для устройств" можно было указать канал плагина?

    Идея такая - в мультисценарии выбираем кнопку, нужные датчики (4 шт.), плагин и номер канала, к которому подключен OLED. В комнатах где будет OLED на нем будут отображаться "свои" показания датчиков.

    Через "Запуск для устройств" так сделать не получится. Ну, или очень криво.

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

    На данный момент вижу только не универсальное решение: прямо в сценарии задать какую-то связь устройств и плагин+канал 😞

     let plugin;
     let channel;
     switch (button.id) {
      case 'BUTTON1':  plugin = 'megad1';  channel = 32; break;
      ....
     } 
    
    
    


  • @homa:

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

    Ошибка исправлена в версии 4.4.9



  • @intrapro:

    …можно просто дописать в /opt/intrahouse-c/backend/package.json в раздел dependencies

    "iconv-lite": "^0.4.24",

    И перезагрузить сервер

    В папке /opt/intrahouse-c/backend/node_modules должна появиться папка iconv-lite

    После перезагрузки iH папка появилась, но сценарий заработал только когда указал полный путь: let buf = require("/opt/intrahouse-c/backend/node_modules/iconv-lite").encode(text, "cp866");

    По сути верно, поскольку сами скрипты лежат тут: /var/lib/intrahouse-c/projects/"PROJECT_NAME"/scenes/script



  • @Alex_Jet:

    @intrapro:

    …можно просто дописать в /opt/intrahouse-c/backend/package.json в раздел dependencies

    "iconv-lite": "^0.4.24",

    И перезагрузить сервер

    В папке /opt/intrahouse-c/backend/node_modules должна появиться папка iconv-lite

    После перезагрузки iH папка появилась, но сценарий заработал только когда указал полный путь: let buf = require("/opt/intrahouse-c/backend/node_modules/iconv-lite").encode(text, "cp866");

    По сути верно, поскольку сами скрипты лежат тут: /var/lib/intrahouse-c/projects/"PROJECT_NAME"/scenes/script

    Добрый день, здорово что у Вас получилось 😉



  • @dev:

    Добрый день, здорово что у Вас получилось 😉

    Коллеги, с наступившим Новым Годом Вас!!!

    Я немного поторопился с выводами о работе iconv…сценарий при запуске не ругался и в отладчике что-то подобное cp866 выводилось. Однако на практике оказалось не все так радужно - на OLED ничего нет. Связываю это с большой скорострельностью node.js и его "параллельной работе". Да, кстати, при обновлении системы из dependencies исчезает дописанная строка с версией iconv-lite.

    Еще смысл такой, что функцию вывода данных на OLED пришлось наворотить таймерами...таймер для очистки первой строки дисплея, для вывода новой первой строки, для вывода значения параметра... иначе все не читабельно и с кучей артефактов:(

        DataToOLED(text, value, unit, plugin, channel) {
          let iconv = require("/opt/intrahouse-c/backend/node_modules/iconv-lite");
          let buf = iconv.encode(text, "cp866");
          this.text = buf.toString();
    
          //Центрирование параметра на OLED
          let length = this.text.length;
          let col = (128 - length*6)/2;
          this.col = col.toFixed(0);
    
          //Форматирование цифровых значений
          let str = ""; //Вспомогательная переменная
          if(value < 100) value = value.toFixed(1);
          str = value.toString();
          if(str.length < 4 && value > 0) this.str = 's+' +str;
          else if(str.length < 4) this.str = 'ss' +str;
          else if(str.length < 5) this.str = 's' +str;
    
          //Выбор единицы измерения
          if(unit == "grad") this.unit = ":";
          else if(unit == "percent") this.unit = "s"; //"%"
          else if(unit == "ppm") this.unit = "s"; //"p"
    
          //Вывод команд на дисплей
          this.ClearOLED(); //Очищаем первую строчку
          this.startTimer("T2", 0.3, "SendTextToOLED");
          this.startTimer("T3", 0.5, "SendValueToOLED");
          if(!this.oled_state) {  //Если дисплей выключен
            //то включаем его после обновления параметра
            this.startTimer("T4", 0.7, "TurnOnOLED");
          }
        },
    
    

    На php все гораздо легче и работает на порядок предсказуемо, никакие задержки не нужны:

    $my_temp = number_format($temp_bme280, 1); // Получаем значение из базы и форматируем его
    if ( strlen($my_temp) < 4 && $my_temp > 0 )
    $my_temp = "s+$my_temp";
    elseif (strlen($my_temp) < 4 )
    $my_temp = "ss$my_temp";
    elseif (strlen($my_temp) < 5 )
    $my_temp = "s$my_temp";
    
    $text = "Улица";
    $text = iconv("utf-8", "cp866", $text);
    $length = strlen($text);
    $col = (128 - $length*6)/2;
    $col = round($col);
    
    file_get_contents("http://192.168.11.25/sec/?pt=31&disp_cmd=1&row=0");
    file_get_contents("http://192.168.11.25/sec/?pt=31&text=" .$text. "&col=" .$col. "&row=0");
    file_get_contents("http://192.168.11.25/sec/?pt=31&text=$my_temp:");
    
    

Log in to reply