Навигация

    Forum

    • Зарегистрироваться
    • Войти
    • Поиск
    • Категории
    • Последние
    • Метки
    • Популярные
    • intraHouse Site
    1. Главная
    2. intrapro
    I
    • Профиль
    • Подписки
    • Подписчики
    • Темы
    • Сообщения
    • Лучшие сообщения
    • Группы

    intrapro

    @intrapro

    administrators

    17
    Репутация
    776
    Сообщения
    37
    Просмотры профиля
    2
    Подписчики
    1
    Подписки
    Регистрация Последнее посещение

    intrapro Подписаться
    administrators

    Лучшие сообщения intrapro

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

      Участник @homa написал

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

      идея в том, чтобы изменять из разных сценариев одно свойство... выходит не выходит)

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

      написал в Сценарии
      I
      intrapro
    • RE: Подключение DHT22 на RASPBERRY PI 4 GPIO

      @alexeyalvl, если порядок меняться не будет, то можно сделать так:

      Для считывания температуры (первый элемент):

      let value;
      if (!error && stdout) {
           value = parseFloat( stdout.split(' ').shift().split('=').pop() );
      }
      

      Для считывания влажности (второй элемент):

      let value;
      if (!error && stdout) {
           value = parseFloat( stdout.split(' ').pop().split('=').pop() );
      }
      

      Что тут делается:

      • stdout.split(' ') - строка разбивается на элементы, разделенные пробелом:
        [ 'Temp=24.3*', 'Humidity=48.6%' ]
      • shift() - берется первый элемент
        'Temp=24.3*'
      • split('=') - этот элемент разбивается на элементы, разделенные знаком =
        [ 'Temp', '24.3*' ]
      • pop() - берется последний элемент, то есть число
        '24.3*'
      • Результат обрабатывается функцией parseFloat, результат - 24.3

      Второе значение обрабатывается аналогично, только на втором шаге берется не первый элемент - shift(), а последний - pop()

      написал в Примеры сниппетов
      I
      intrapro
    • RE: Плагин MegaD

      Участник @Alex_Jet написал в Плагин MegaD:

      @intrapro, подключил ленту WS2818 к контроллеру, в канале плагина вписал команду управления /%pwd%/?pt=%adr%&ws=%value%&chip=151. Все работает, однако братья китайцы где-то напутали и поменяли местами R и G... как итог лента не RGB, а GRB... стандартными средствами плагина можно выйти из положения?

      Попробуйте в канале на вкладке Обработка прописать:
      Формула расчета выходного значения для актуаторов: [ value[1],value[0],value[2] ]

      Ну и входное тоже нужно так же:
      Формула расчета входного значения: [ value[1],value[0],value[2] ]

      Еще момент по уровню яркости. Если установить какой-нибудь цвет, то слайдер L по умолчанию переходит в значение 50. Если его двигать в сторону 0, то яркость выбранного цвета уменьшается, однако если двигать к 100, то яркость увеличивается, но и цвет плывет причем на 100 получается просто белый цвет. Это явно не верный алгоритм.

      Это вопрос спорный. Сейчас нужно ориентироваться, что трушный цвет при L=50

      А еще поработать бы с самим устройством. По идее индикатор 1 - это RGB параметры, а индикатор 2 - это уровень яркости. Однако сейчас индикатор 2 отображает, например, "0,255,0", хотя при настройке устройства на мнемосхеме отображается уровень в виде "100". При нажатии на устройство - ничего не меняется - (картинки одинаковые), уровень остается тот же.

      Да, с индикаторами не очень 😞 Сейчас наверху выводится текущее значение массива, внизу должно быть дефолтное значение (для команды on) Cостояния on/off должны переключаться. Попробуйте нажать кнопку Выключить в боковом меню. Должны уйти нули, а устройство перейти в состояние выключено. Ну а картинку для активного состояния сами раскрасьте 🙂

      написал в Плагины
      I
      intrapro
    • RE: Свет по датчику движения с дополнительными условиями.

      Участник @Erik написал

      И еще вопрос.

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

      При условии if ((SAF.value === 0) && (sw.value === 0) && (lamp.value == 1)) проверить, что таймер запущен, и обнулить его (тот же самый таймер).

      Для этого нужно добавить внутрь сценария "слушателя событий"

      script({
          start() {
            if ((SAF.value === 0) && (sw.value === 0) && (lamp.value === 0)) {
               lamp.on();
               // взводим таймер, чтобы отключить 
               this.startTimer("T1", 180, "turnOff");       
              
              // Добавляем слушателей - следим за датчиком движения и светильником
              this.addListener(motion, "onMotion");
              this.addListener(lamp, "onLamp");
            }
          },
          
          onMotion() {
            // Если движение возобновилось - сбрасываем таймер
            if (motion.isOn() )  {
              this.stopTimer("T1");
            }  
             // Если движение прекратилось - взводим таймер (после повторных движений)
            if (motion.isOff() && this.timer.T1 == "off")  {
              this.startTimer("T1",  180, "turnOff");
            }  
          },
          
           onLamp() {
            // Светильник выключили другим способом - выходим
             if (lamp.isOff()) this.exit();
           },
           
          // Функция, которая сработает, когда таймер досчитает - отключаем и выходим
          turnOff() {
            lamp.off();
            this.exit(); // Здесь exit нужен, так как есть активные слушатели и сценарий сам не завершится
          }
      });
      

      Более подробно про механизм работы сценариев - https://ih-systems.com/ru/about-scenes/
      Если коротко:

      • Если внутри сценария просто последовательность действий, он отработает и сразу завершится (станет не активным). При следующем запуске он опять начнется со start(). Большая часть сценариев работает именно так и 99,9% времени находятся в неактивном состоянии.

      • Если сценарий взводит таймеры и/или устанавливает слушателя событий устройства, то он остается активным, следит за своими таймерами и устройствами «изнутри» и выполняет действия как реакцию на отслеживаемые события. Стартовое событие не работает, так как сценарий уже активен.. В рабочих сценариях в левом столбце у сценариев, активных в данный момент, стоит зеленая галочка.
        Чтобы завершить такой сценарий, нужно выполнить команду this.exit().
        При завершении сценария все его таймеры и слушатели удаляются. При следующем запуске опять выполнится start()

      написал в Сценарии
      I
      intrapro
    • RE: Вопросы по работе системы

      Пользователь @regabriel написал в Вопросы по работе системы:

      Здравствуйте. Не пойму ошибка или нет.
      Создаю устройство - виртуальный датчик температуры, чтобы в нем выводить среднюю температуру с нескольких других датчиков.
      Соответственно делаю мульти скриптик(так как таких средних будет несколько)
      в котором прописываю:

      const temp_room = Device("SensorA","Средняя температура комнаты"); 
      
      ....
      script({
          start() {
               temp_room.setValue(15);
      

      Так вот не работает x.setValue(15);
      Для "ActorA" работает.
      Это ошибка или так и должно быть?

      Добрый день. Да, все верно, датчику значение таким образом присвоить нельзя.
      Идея в том, что x.setValue задействует канал на запись, по которому значение записывается на железо. Датчик сам значение записать не может, его value только для чтения.
      Для реализации виртуального датчика есть команда this.assign( имя устр-ва, имя свойства, значение)

      this.assign(temp_room,"value",42);
      

      В настройках-> дополнительно ставлю метод определения состояния "вычисляется сценарием".

      Не совсем. У датчика есть value - значение и state - состояние, которое грубо говоря определяет картинку.
      Этот пункт относится к state, Вы же сценарием хотите присвоить value.
      Если нужно, чтобы средняя пересчитывалась динамически при изменении любого датчика, получится примерно так:

      const temp1 = Device("SensorA","Датчик 1"); 
      const temp2 = Device("SensorA","Датчик 2"); 
      const temp3 = Device("SensorA","Датчик 3"); 
      const temp4 = Device("SensorA","Датчик 4"); 
      const temp_room = Device("SensorA","Средняя температура комнаты"); 
      
      startOnChange([ temp1, temp2, temp3, temp4 ]); 
      
      script({
          start() {
              const average = (temp1.value+temp2.value+temp3.value+temp4.value)/4;
              this.assign(temp_room,"value", average);
        }
      })
      

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

      И второй вопрос: при создании устройства выбор - актуатор бинарный(т.е. 2 состояния)
      При этом в мультисценарии ActorD — дискретный актуатор.

      Дискретный актуатор - имеется в виду актуатор с конечным числом состояний.
      По умолчанию создается бинарный. Но можно расширить число состояний

      Можно ли сделать более 2 состояний у актуатора и датчика и как? Где посмотреть примеры или описания?

      Да, можно. Раздел Состояния устройств на странице https://ih-systems.com/ru/devices/

      По состояниям:

      • у дискретных датчиков и актуаторов обычно делают value=state,
        метод определения состояния "Стандартный"

      • у аналоговых можно использовать "Метод интервалов", то есть состояние расчитывается исходя из value, по нарастанию значения (более подробно см в док-и)

      метод определения состояния "вычисляется сценарием" после перехода на v4 не используется

      Также обратите внимание на 2 момента:

      1. Состояния должны нумероваться строго подряд, начиная с 0
      2. Если устройство уже стоит на мнемосхеме, после изменения числа состояний его нужно удалить и заново поставить. На мнемосхеме можно менять визуальное представление каждого состояния, причем каждое редактируется отдельно
      написал в intraHouse V4 Cherry
      I
      intrapro
    • RE: Плагин HTTP-Client

      @alesle пожалуйста 🙂
      Вот вариант еще короче

      data.onew_temp.find(item => item.name=="S6").t
      

      Современный javascript мощный и гибкий язык, особенно если использовать синтаксис ES6 (или ES2015, что одно и то же) , в данном случае стрелочные функции.
      Магия этих выражений раскрывается в 2 шага

      1. Массивы в JS имеют встроенные методы для поиска по заданному критерию, в частности filter, find

        • find - ищет первый элемент массива, возвращает найденный объект
        • filter - сюрприз 🙂 - фильтрует входной массив и возвращает все найденные элементы (learn.javascript.ru/array-methods)
      2. Методу нужно передать критерий отбора - функцию для обработки элемента массива.

        Если писать, используя синтаксис классических функций, то получится так:

         arr.filter( function (item) {
           return item.name == 'S6';  
        });
        

        Функция вызывается по очереди для каждого элемента массива (item), если возвращает true, то элемент берется в новый массив

        С введением в ES6 стрелочных функций все стало компактнее:

         function (item) {return item.name == 'S6';} 
        

        можно заменить на

         (item)  => item.name == 'S6' 
        

        Что произошло

      • убрали function
      • грубо говоря return заменили на =>
      • если входной аргумент ровно один - то и скобки можно не ставить

      Подробнее https://learn.javascript.ru/arrow-functions
      Получаем:

       arr.filter( item => item.name == 'S6' );
      

      Ну и надо иметь в виду, что возвращает метод массива.
      Если результат - массив, то берем свойство его первого элемента

      data.onew_temp.filter(item => item.name=="S6")[0].t
      

      Если результат - объект, то просто берем свойство t

      data.onew_temp.find(item => item.name=="S6").t
      
      написал в Плагины
      I
      intrapro
    • RE: Сценарии - новая версия API

      @Alex_Jet, Добрый день! @Erik прав - нужен актуатор, который можно переключать как угодно - интерактивно, сценарием, по расписанию...

      Сценарий гирлянды запускается при включении этого актуатора.

      Состояния в php скрипте меняются случайным образом, поэтому логика еще проще:

      1. Добавить слушателя для актуатора-триггера
      2. Генерировать строку цветов случайным образом
      3. Передать команду на MegaD
      4. Взвести таймер 1 сек

      По таймеру - повторить пункты 1-3
      При выключении триггера - завершить сценарий

      написал в Сценарии
      I
      intrapro
    • RE: Установка значений каналов через REST API

      Добрый день! В канал плагина установить данные через REST API не получится. Можно записать значение в свойство устройства минуя канал. Для этого нужно сгенерировать событие 'received:device:data'. Такое же событие генерируется при получении данных с плагина для привязанных к каналам устройств.
      Объект события: {<device1 ID>:{<prop1>:val1,...}, <device2 ID>:{<prop2>:val2,...} }
      Пример 1. Передается ID устройства, имя свойства и значение

      /**
       * Обработчик запроса REST API
       * /restapi/device/set?did=d0021&prop=setpoint&value=42
       *    => {d0021:{setpoint:42}}
       */
      module.exports = async (req, res, holder, debug) => { 
        try {
          const did =  req.query.did;
          const prop =  req.query.prop;
          const val =  req.query.value || 0;
          holder.emit('received:device:data', {[did]: {[prop]: val} });
          res.json({ res: 1});
        } catch (e) {
          res.json({ res: 0, message: e.message });
          debug(e.message)
        }
      };
      

      Пример 2. Передается dn (device name) устройства, по нему сначала нужно определить device ID

      /**
       * Обработчик запроса REST API
       * /restapi/device/set?dn=DT101&prop=setpoint&value=42
       *    => {d0021:{setpoint:42}}
       */
      module.exports = async (req, res, holder, debug) => { 
        try {
          const dn =  req.query.dn;
          const prop =  req.query.prop;
          const val =  req.query.value || 0;
          const dobj = holder.dnSet[dn];
          if (!dobj) throw {message:'Not found device '+dn};
          
          const did = dobj._id;
          holder.emit('received:device:data', {[did]: {[prop]: val} });
          res.json({ res: 1});
        } catch (e) {
          res.json({ res: 0, message: e.message });
          debug(e.message)
        }
      };
      

      Конечно, аналогично можно передать POST запрос с множеством значений

      написал в IntraSCADA V5
      I
      intrapro
    • RE: Плагин MegaD

      Пользователь @regabriel написал в Плагин MegaD:

      Здравствуйте. Разбираюсь с системой и возникает множество вопросов))

      1. Как настраивается в плагине в канале"Функция обработки значения"?
        в каком виде можно писать?
        Например датчик температуры, если он показывает меньше -40, либо ровно 0, либо больше 100 значит он неисправен, как это записать?

      Добрый день.
      Настройку интервала допустимых значений можно настроить прямо на устройстве (min-max) . Там же можно определить, что делать, если произошел выход из диапазона:

      • "Не принимать значение вне диапазона" - значение не будет присвоено
      • "Установить ошибку при выходе из диапазона"

      Можно эти флаги устанавливать независимо. Также можно контролировать поступление данных - "Установить ошибку если нет данных в течение (сек)"

      device_setting.png

      Функция обработки в канале используется, если нужна сложная предварительная обработка. Например, от контроллера получаем 5 значений, сортируем, откидываем минимальное и максимальное и вычисляем среднее. И именно вычисленное значение отдаем ядру системы.
      Пример такой функции для плагина MegaD приведен в описании плагина (в конце страницы):
      https://ih-systems.com/ru/product/plugin-megad/

      1. Где вообще можно посмотреть хорошее описание API по intraHouse? Например по работе с БД?

      Пользовательские SQL запросы к БД на уровне ядра в версии 4 не поддерживаются. Можно писать и читать из сценария с помощью функций this.dbread(), this.dbwrite().
      Если нужно напрямую работать с БД, есть возможность написать отдельный плагин. Документации на эту тему нет 😞 , но есть примеры реализации.

      1. Как проверять работу сложного скрипта? Как посмотреть результаты работы consol.log('') или использовать какие либо аналоги ?

      Для отладки скрипта есть "Отладчик" в нижнем окне сценария. Там выводится трассировка при выполнении команд, таймеров, проверки условий.
      Вместо console.log в скрипте используйте. this.log(''), сообщение будет выведено в этом же окне

      написал в Плагины
      I
      intrapro
    • RE: Сценарии - новая версия API

      @Alex_Jet
      Совершенно верно, параметры в сценарии напрямую не доступны, нужно использовать getParam("имя параметра") / setParam("имя параметра", значение).

      Просто dt.setpoint - это значение уставки. Для уставки есть специальная команда setSetpoint (да, довольно коряво 😞 )
      Другой вариант - любое свойство можно присвоить с помощью setParam.
      Таким образом, есть два варианта:

      dt.setSetpoint( dt.getParam("nightTemp") )
      

      или

      dt.setParam( "setpoint", dt.getParam("nightTemp") )
      
      написал в Сценарии
      I
      intrapro

    Недавние сообщения intrapro

    • RE: Пользовательский обработчик.

      Добрый день. Обработчики устройства работают в рамках одного устройства, не имеют доступ к другим устройствам.

      Кроме обработчиков устройства, в системе есть другие виды скриптов:
      Общие концепции - > Скрипты

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

      /**
       * @desc
       * @version 5
       */
      const m1 = Device("Meter_001");
      const m2 = Device("Meter_002");
      const m3 = Device("Meter_003");
      const script = {
        start() {
          m3.assign('P0', m1.P0+m2.P0); // В счетчике Meter_003.P0 будет сумма значений
        }
      };
      

      Немаловажный вопрос - в какой момент нужно пересчитывать значение.
      Можно запустить этот сценарий по расписанию (циклически - каждые 30 сек, или на границе минуты...)
      Если же нужно, чтобы при любом изменении значений m1 или m2 - в декларативную часть сценария нужно добавить startOnChange.
      Можно вызывать сценарий при любом изменении значений m1, m2: startOnChange([m1,m2]);
      Можно указать конкретные свойства: startOnChange([m1.P0,m2.P0])

      const m1 = Device("Meter_001");
      const m2 = Device("Meter_002");
      const m3 = Device("Meter_003");
      
      startOnChange([m1.P0,m2.P0]);
      
      const script = {
        start() {
          m3.assign('P0', m1.P0+m2.P0); // В счетчике Meter_003.P0 будет сумма значений
        }
      };
      
      написал в intraHouse V5
      I
      intrapro
    • RE: MQTT данные в массиве парсятся неверно? (v5)

      Пользователь @AV написал

      Но всё равно - не работает. Значение в виде текста или словаря приходят нормально, а если делаешь массив - в канал ничего не приходит.

      Упс, вы правы. В плагине MQTT поступление массива всегда интерпретируется как архив.
      Подумаем, как это исправить. Скорее всего, придется добавить параметр на уровне плагина.

      написал в Плагины
      I
      intrapro
    • RE: MQTT данные в массиве парсятся неверно? (v5)

      @AV, попробуйте в Формуле входного значения для канала 'aaa' прописать

      JSON.parse(value).find(item => item.n == "aaa").v
      

      соответственно для 'bbb'

      JSON.parse(value).find(item => item.n == "bbb").v
      
      написал в Плагины
      I
      intrapro
    • RE: Установка значений каналов через REST API

      Добрый день, Александр! Очень изобретательно 🙂
      Но теперь понимаю, что задача у вас - организовать через API управление (запись на железо).
      Конечно, система должна предоставить для этого прямой способ.

      В версии 5.9 это к сожалению не работает, сейчас выполняем унификацию API для разных скриптов системы (скрипты визуализации, сценарии, REST API).

      В 5.10 (релиз выйдет в начале следующей недели) можно будет выполнять команды устройства напрямую:

      const dev = holder.getDevice('VENT1');             
      dev.setValue('setpoint', 22);        
      dev.on();          
      
      
      написал в IntraSCADA V5
      I
      intrapro
    • RE: Установка значений каналов через REST API

      Добрый день! В канал плагина установить данные через REST API не получится. Можно записать значение в свойство устройства минуя канал. Для этого нужно сгенерировать событие 'received:device:data'. Такое же событие генерируется при получении данных с плагина для привязанных к каналам устройств.
      Объект события: {<device1 ID>:{<prop1>:val1,...}, <device2 ID>:{<prop2>:val2,...} }
      Пример 1. Передается ID устройства, имя свойства и значение

      /**
       * Обработчик запроса REST API
       * /restapi/device/set?did=d0021&prop=setpoint&value=42
       *    => {d0021:{setpoint:42}}
       */
      module.exports = async (req, res, holder, debug) => { 
        try {
          const did =  req.query.did;
          const prop =  req.query.prop;
          const val =  req.query.value || 0;
          holder.emit('received:device:data', {[did]: {[prop]: val} });
          res.json({ res: 1});
        } catch (e) {
          res.json({ res: 0, message: e.message });
          debug(e.message)
        }
      };
      

      Пример 2. Передается dn (device name) устройства, по нему сначала нужно определить device ID

      /**
       * Обработчик запроса REST API
       * /restapi/device/set?dn=DT101&prop=setpoint&value=42
       *    => {d0021:{setpoint:42}}
       */
      module.exports = async (req, res, holder, debug) => { 
        try {
          const dn =  req.query.dn;
          const prop =  req.query.prop;
          const val =  req.query.value || 0;
          const dobj = holder.dnSet[dn];
          if (!dobj) throw {message:'Not found device '+dn};
          
          const did = dobj._id;
          holder.emit('received:device:data', {[did]: {[prop]: val} });
          res.json({ res: 1});
        } catch (e) {
          res.json({ res: 0, message: e.message });
          debug(e.message)
        }
      };
      

      Конечно, аналогично можно передать POST запрос с множеством значений

      написал в IntraSCADA V5
      I
      intrapro
    • RE: Запись в журналы.

      Пользователь @aleks-zonov написал в Запись в журналы.:

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

      В версии Cherry журнал аварий можно настроить только на уровне устройства. События добавляются и удаляются автоматически при изменении состояний.

      написал в intraHouse V4 Cherry
      I
      intrapro
    • RE: Сценарий отопления

      Пользователь @zahar69 написал в Сценарий отопления:

      (/assets/uploads/files/1646117183718-3.jpg) 4.JPG

      У вас косая перед "?" лишняя во входящем сообщении:
      /megad.php/?pt=3&v=0

      С меги приходит /megad.php?pt=3&v=0

      написал в intraHouse V5
      I
      intrapro
    • RE: Релиз IntraHouse V5

      Пользователь @Lost написал в Релиз IntraHouse V5:

      Все вроде работает....
      По факту сценарий активен, а тут показано, что он остановился.

      Да, это вы верно заметили, здесь информация не совсем верно представлена.
      Показывает, сколько длится синхронная часть (последняя выполненная функция, грубо говоря). Контроль зацикливания

      написал в intraHouse V5
      I
      intrapro
    • RE: Релиз IntraHouse V5

      Пользователь @Lost написал в Релиз IntraHouse V5:

      И функция boot() похоже не работает. По крайней мере этот сценарий не запускается при перезагрузке сервера. Пока закоментарил.

      Вышла версия 5.8.12-beta. В ней работает функция boot(), синтаксис как в V4.
      Проблемы с таймерами также исправлены. Еще раз спасибо за баг-репорт 🙂

      написал в intraHouse V5
      I
      intrapro
    • RE: Релиз IntraHouse V5

      @Lost, спасибо за подробный анализ проблемы!
      Будем разбираться

      написал в intraHouse V5
      I
      intrapro