Navigation

    Forum

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • intraHouse Site
    1. Home
    2. Alex_Jet
    3. Best
    A
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups

    Best posts made by Alex_Jet

    • Интеграция в iH считывателей ключей через MegaD

      К контроллеру MegaD можно подключить считыватели, имеющие интерфейс подключения 1-Wire/TouchMemory и Wiegand и протоколы обмена с ключами EM-Marine/Mifare. Для этого порт, к которому физически подключен считыватель необходимо сконфигурировать, подробнее тут.
      В плагине megad системы intraHouse необходимо создать запись в разделе "Расширения". Например для считывателя с интерфейсом 1-Wire/TouchMemory и протоколом обмена с ключами EM-Marine, подключенным к порту 35 контроллера:

      iH_MegaD_1-Wire_EM-Marine.png
      В поле "Входящее от контроллера MegaD" вписан URL, который приходит от контроллера при "срабатывании" считывателя. А в поле "Запустить сценарий" выбран сценарий, обрабатывающий данное сообщение от контроллера.
      Сценарий имеет следующий скрипт:

      const security = Device("ACTOR_SECURITY_SYS00"); //Системный индикатор (кнопки Взятия/Снятия)
      
      script({
        //Ключи Touch_Button
        key_aleksey: "123456789ABC",
        key_nadia: "123456789ABC",
        key_dima: "123456789ABC",
        
        start(param) {
          const obj = JSON.parse(param);
          
          //Постановка и снятие дома с охраны
          if(obj.pt == 35) {
            this.log("Активирован ключ с ID = " +obj.ib);
            let disarm = 0;
            
            if(obj.ib == this.key_aleksey) {
              disarm = 1;
              //Тут еще действия
            }
            else if(obj.ib == this.key_nadia) {
              disarm = 1;
              //Тут еще действия
            }
            else if(obj.ib == this.key_dima) {
              disarm = 1;
              //Тут еще действия
            }
            
            //При успешном считывании нужного ключа меняем состояние Security на противоположное
            if(disarm) {
              security.toggle();
              //Тут еще действия
            }
          }
        }
      });
      

      Как видно, в скрипте ключи прописаны как константы уровня скрипта (поэтому к ним нужно обращаться через this, где this - это сам скрипт) - key_aleksey: "123456789ABC". При запуске сценария ему как аргумент передается URL, полученный от контроллера, но преобразованный в JSON-строку с объектом. То есть из /mod_megad.php?pt=35&ib=123456789ABC получаем param = '{pt:35, ib:123456789ABC}'. В результате парсинга входящей строки JSON.parse(param) имеем:
      obj.pt - порт контроллера;
      obj.ib - идентификатор приложенного к считывателю ключа.
      Далее в скрипте идет проверка идентификатора ключа с прописанными константами (key_aleksey, key_nadia, key_dima). В случае истинности переменная disarm принимает истинное значение (disarm = 1), соответственно, актуатор security меняет свое состояние на противоположное. То есть при каждом считывании правильного ключа "охранный" актуатор будет включаться/выключаться по кругу.
      Переменная disarm введена в скрипт намеренно, поскольку в каждом операторе if при проверке соответствующего ключа можно вводить дополнительные условия срабатывания других систем. Так, например, у меня в каждом if вписана текстовая строка приветствия пользователя (this.string = "Алексей, я рада Вас видеть!"), которая в дальнейшем преобразуется в речь голосового помощника).
      Если не нужны индивидуальные операции для каждого ключа, можно прописать массив ключей и проверять поднесенный ключ таким образом:

      script({
        //Ключи Touch_Button
        key_array: ['11111','22222','33333'],
        
        start(param) {
          const obj = JSON.parse(param);
          
          //Проверка наличия ID ключа в массиве
          if( this.key_array.includes(obj.ib) ) {
            this.log("Активирован ключ с ID = " +obj.ib);
            //Выполняем действия
          }
        }
      });
      
      posted in intraHouse и MegaD
      A
      Alex_Jet
    • Интеграция в iH счетчиков через MegaD

      Главная особенность контроллера MegaD - это способность генерировать GET-запросы на сервер системы управления в случае изменения состояния входов контроллера (модули расширения MegaD-8I7O, MegaD-14-IN, MegaD-14-IOR, MegaD-16I-XT, моноблок MegaD-2561-24I14O-RTC). Ко входам IN можно подключить любые датчики, имеющие выход типа "сухой контакт" (при сработке датчика в нем замыкается/размыкается реле или уменьшает/увеличивает сопротивление активный элемент) - это выключатели, кнопки, герконы, датчики протечки, ИК-извещатели, пожарные извещатели, счетчики (типа "геркон"), датчик напряжения U-Sensor. В данной статье заострю внимание на интеграцию в систему intraHouse счетчиков потребления газа/электроэнергии/воды и прочие, имеющие выход типа "сухой контакт" или геркон.
      В частности распространенный и имеющий высокую надежность, а также внушительные габариты, счетчик газа BK-G4T можно интегрировать в систему, оснастив его родным модулем считывания - "IN-Z61". Однако, во-первых, он довольно дорого стоит для его "функциональности", во-вторых, его не просто приобрести ввиду отсутствия не только в розничной продаже, но и наличия в интернет-магазинах. Правда есть вариант намного дешевле и проще - это использование геркона типа "ИО-102-4" (такое решение на текущий момент работает 2 года без нареканий).
      iH_MegaD_Counter_IO-102-4.png

      От него нужно отрезать пластмассовую часть, которой он должен монтироваться на двери/рамы, и приклеить на обычный клей "Момент" в паз счетчика BK-G4T вот таким образом:
      Counter_Gaz_with_Gerkon.png

      Выход геркона подключаем к любому "стандартному" (не цифровому) входу контроллера MegaD. Конфигурируем порт следующим образом:
      iH_MegaD_Port_Settings.png
      После этого контроллер, при каждом срабатывании геркона, будет отправлять следующие GET-запросы на сервер intraHouse (можно посмотреть через раздел "Отладчик" соответствующего плагина megad):

      12.01 17:11:21.992 megad4: 192.168.11.24 => localhost:11024 HTTP GET /mod_megad.php?pt=7&cnt=15901&mdid=
      12.01 17:11:22.988 megad4: 192.168.11.24 => localhost:11024 HTTP GET /mod_megad.php?pt=7&m=2&cnt=15901&mdid=
      

      Первый запрос (/mod_megad.php?pt=7) - формируется сразу же после срабатывания геркона, а поскольку ось счетчика крутиться довольно медленно, то спустя ~1 секунду контроллер формирует второй запрос (/mod_megad.php?pt=7&m=2) - почему происходит так и для чего это сделано - читаем тут.
      Для отображения счетчика на мнемосхемах добавим новое устройство типа "Счетчик", в моем случае оно будет называться "Счетчик газа" и имеет ID "METER1_01". Чтобы получить дробную часть числа необходимо в свойствах устройства указать необходимое количество "Цифр после запятой". Для интеграции счетчика газа в iH в соответствующем плагине нужно:

      1. Добавить новый канал, привязав к нему ранее созданное устройство:
        iH_MegaD_Counter_Channel.png
        Запросы на сервер формируются самостоятельно, поэтому период опроса = 0 секунд, строку запроса оставляем без изменений. Самое главное - это ввести "Вес импульса счетчика". Поскольку при каждом срабатывании геркона у счетчика газа BK-G4T прибавляется одна сотая кубического метра газа (0.01), то вес импульса счетчика равен этому значению - 0.01.
      2. Добавить новое расширение для того, чтобы сервер знал на что ему нужно реагировать и что при этом делать:
        iH_MegaD_Counter_Extension.png
        В данном случае реагируем на запрос /mod_megad.php?pt=7&m=2 поскольку если будем реагировать на запрос /mod_megad.php?pt=7, то получится что за один проход состояние канала изменится два раза (в силу не идеальной реализации поиска расширений в плагине megad). При наличии вышеуказанного запроса изменяем состояние канала 7 (делаем "счет"): 7=CNT

      После проделанных действий в разделе "Отладчик" соответствующего плагина megad убеждаемся, что происходит правильный подсчет объемов:

      12.01 17:10:54.006 megad4: 192.168.11.24 => localhost:11024 HTTP GET /mod_megad.php?pt=7&cnt=15900&mdid=
      12.01 17:10:55.001 megad4: 192.168.11.24 => localhost:11024 HTTP GET /mod_megad.php?pt=7&m=2&cnt=15900&mdid=
      12.01 17:10:55.004 IH: get [ { id: '7', value: 6838.22 } ]
      set { METER1_01: { aval: 6838.22, err: 0 } }
      12.01 17:11:21.992 megad4: 192.168.11.24 => localhost:11024 HTTP GET /mod_megad.php?pt=7&cnt=15901&mdid=
      12.01 17:11:22.988 megad4: 192.168.11.24 => localhost:11024 HTTP GET /mod_megad.php?pt=7&m=2&cnt=15901&mdid=
      12.01 17:11:22.989 IH: get [ { id: '7', value: 6838.23 } ]
      set { METER1_01: { aval: 6838.23, err: 0 } }
      

      В данном случае, при каждом срабатывании геркона значение счетчика увеличивается на 0.01 м.куб. - с 6838.22 до 6838.23.
      Чтобы синхронизировать показания на счетчике с показаниями в системе необходимо вынести ранее созданное устройство "Счетчик газа" на мнемосхему, навести на устройство курсор и после долгого нажатия левой кнопки мыши откроется меню устройства - в текстовом поле необходимо ввести текущие показания счетчика и нажать кнопку справа.
      iH_MegaD_Device_Sinchronization.png

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

      В случае с другими счетчиками в канале плагина megad необходимо правильно указать "Вес импульса счетчика". Например, счетчик потребления электроэнергии имеет на выходе 2000 импульсов на 1 кВт*ч, значит чтобы получить единицы измерения в кВт*ч нужно указать "Вес импульса счетчика" - 0.0005 (2000 имп. * 0.0005 = 1 кВт*ч).

      posted in intraHouse и MegaD
      A
      Alex_Jet
    • Интеграция в iH входов типа Click Mode MegaD

      Входы контроллера MegaD-2561 имеют (подробнее - тут) несколько различных режимов:
      P - устройство реагирует только при замыкании контакта/выключателя (на сервер приходит GET-запрос вида - /megad.php?pt=0&cnt=1)
      R - устройство реагирует только при размыкании контакта/выключателя (на сервер приходит GET-запрос вида - /megad.php?pt=0&m=1&cnt=1)
      P&R - устройство реагирует как на замыкание, так и на размыкания контакта.
      С или Click mode - реагирует на:

      • Однократное нажатие на кнопку/выключатель (на сервер приходит GET-запрос вида - /megad.php?pt=0&click=1&cnt=1)
      • Двойное нажатие на кнопку/выключатель (на сервер приходит GET-запрос вида - /megad.php?pt=0&click=2&cnt=2)
      • Удержание кнопки/выключателя на время более 1 секунды (на сервер приходит GET-запрос вида - /megad.php?pt=0&m=2&cnt=3). То же для режима P.
      • Отпускание кнопки/выключателя после длительного нажатия (на сервер приходит GET-запрос вида - /megad.php?pt=0&m=1&cnt=3). То же для режима P&R.

      Таким образом, в режиме P&R есть 2 комбинации кнопки (нажатие и удержание), а в режиме C - 3 комбинации (одинарное нажатие, двойное нажатие и удержание), которые можно использовать для управления какими-либо устройствами.
      Разберем как можно интегрировать в iH вход контроллера в режиме "C" (Click mode). Есть несколько вариантов:

      1. Прямое управление устройствами (и входы, и выходы располагаются на одном и том же контроллере MegaD)
      Для этого необходимо перейти в раздел "Расширения" соответствующего плагина megad. И, например, для кнопки, подключенной ко входу 15 контроллера MegaD-2561 нужно прописать 3 "расширения":

      MegaD_Multi_Button_Variant-1.png

      Таким образом, плагин будет реагировать на одинарный клик кнопки (переключать выход 8), на двойной клик (переключать выход 7) и на удержание кнопки (выключать выход 7 и 8).

      2. Управление любыми устройствами с помощью сценария
      Другой вариант - это когда мы прописываем такие же расширения что и в первом варианте, но поля "Передать в ответ" и "Установить состояние канала" оставляем пустыми. При этом в поле "Запустить сценарий" выбираем нужный нам:

      MegaD_Multi_Button_Variant-2.png

      Таким образом, плагин будет реагировать на двойной клик кнопки и передавать в сценарий URL, полученный от контроллера, но преобразованный в JSON-строку с объектом. То есть из /mod_megad.php?pt=0&click=2 получаем param = '{pt:0, click:2}'. Сценарий управления устройствами при этом довольно прост:

      /** 
      * @name MegaD - управление устройствами 
      * @desc При возникновении событий от MegaD выполнить действия 
      * @version 4  
      */
      
      const lamp_table = Device("LAMP1_07");       //Обеденный стол
      
      script({
        start(param) {
          const obj = JSON.parse(param);
          
          //Освещение на разных контроллерах
          if(obj.pt == 0 && obj.click == 2) {
            lamp_table.toggle();
          }
        }
      });
      

      При запуске сценария в результате парсинга входящей строки JSON.parse(param) имеем объекты:
      obj.pt - порт контроллера;
      obj.click - параметр "клика".
      В случае с длительным нажатием или отпусканием кнопки также будем иметь объект obj.m. Более того, плагин также сообщает IP-адрес контроллера, с которого пришло сообщение, поэтому всегда будет иметь место и obj.ip!

      3. Продвинутое управление любыми устройствами с помощью сценария
      В задаче по выводу на дисплей с контроллером SSD1306 различной информации мне потребовалась "мультикнопка", которая будет:
      а. По однократному нажатию отображать температуру/влажность/СО2 в доме на дисплее по кругу
      б. По двукратному нажатию выводить на дисплей информацию о температуре на улице
      в. По удержанию кнопки - выключать дисплей
      Для этого я прописал в расширениях соответствующего плагина megad следующее:

      MegaD_Multi_Button_Variant-3.png

      Сделал устройство для кнопки на основе "Датчик универсальный бинарный" и привязал ее ко входу:

      MegaD_Multi_Button_Variant-3_Channel.png

      Сам сценарий срабатывает именно по изменению состояния кнопки:

      /** 
      * @name Обновление данных на OLED гостевой 
      * @desc При однократном нажатии кнопки OLED отображает параметры микроклимата данного помещения. При двойном нажатии кнопки
      *       OLED отображает уличную температуру. При удержании кнопки дисплей выключается. 
      * @version 4 
      */
      
      const button  = Device("BUTTON1_01");
      
      startOnChange(button);
      
      script({
          button_state: 0,  //Переменная параметров
        
          start() {
            let mode = button.value;  //Режим кнопки
            let param = 0;            //Переменная для выбора параметров
            
            //Перебор параметров при однократном нажатии кнопки
            if(mode == 1) {
              param = this.button_state + 1;
              if(param > 2) this.button_state = 0;
              else this.button_state = param;
            }
            //Двойное нажатие и удержание кнопки
            else {
              param = mode;
              this.button_state = 0;
            }
            
            //Перебор параметров для выполнения действий
            switch(param) {
              case 1: //Тут что-то делаем
                      break;
              case 2: //Тут что-то делаем
                      break;
              case 3: //Тут что-то делаем
                      break;
              case 4: //Тут что-то делаем
                      break;
              case 5: //Тут что-то делаем
                      break;
            }
            
            //Сброс состояния кнопки
            if(mode > 0) {
              this.startTimer("ButRst", 0.5, "ClearState");
            }
          },
          
          //Функция "обнуления" кнопки
          ClearState() {
            this.assign(button, "value", 0);
          },
      });
      

      Приведенный сценарий очень урезан (поскольку вывод разной информации на дисплей с контроллером SSD1306 - это тема другой статьи), однако и в таком виде он довольно не тривиальный! В нем введена переменная уровня сценария button_state - для "запоминания" предыдущего состояния кнопки. При этом в основной функции start введена локальная переменная mode (принимает значения 1, 4 и 5 - подробнее см. "Расширения") для "считывания" типа нажатия кнопки. Условный оператор if проверяет какой сейчас тип нажатия кнопки (mode):

      • если 1, то переменная param принимает значения 1->2->3; если param > 2, то он обнуляется и счет начинается снова 1->2->3;
      • иначе param принимает остальные значения - 4 или 5 в нашем случае.

      Важно! В конце функции состояние кнопки нужно обнулять, поскольку при однократном нажатии состояние кнопки будет всегда 1 и сценарий не будет запускаться по изменению состояния кнопки.
      В принципе можно сделать перебор однократным нажатием хоть 100 параметров! Для этого нужно в расширениях для click=2 прописать 8=101, а для m=2 - 8=102. А в самом сценарии изменить if(param > 2) на if(param > 100) и добавить соответствующие условия (1-100 и 101/102 - соответственно для click=2/m=2) в операторе switch.

      posted in intraHouse и MegaD
      A
      Alex_Jet
    • RE: Сценарии - новая версия API

      @homa, вот так все работает:

      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":""}
        ]);
      
      posted in Сценарии
      A
      Alex_Jet
    • RE: Вопросы по работе системы

      @Erik, этот баг давнишний. Обещали исправить. Я описывал, что если не получается в рабочих сценариях открыть отладчик, то надо открыть нижнее окно в обычных сценариях, а потом перейти в рабочие сценарии.

      posted in intraHouse V4 Cherry
      A
      Alex_Jet
    • RE: Плагин MegaD

      @amgstone, сервер кидает на Мегу свои запросы, а она ни на один не отвечает. Проверяйте сеть и почему MegaD недоступна с сервера.

      posted in Плагины
      A
      Alex_Jet
    • Интеграция в iH адресуемых RGB-лент на базе WS281X через MegaD

      Прошивка контроллера MegaD-2561 поддерживает управление адресуемыми RGB-драйверами серии WS281X. На этих микросхемах/драйверах делают не только адресуемые RGB-ленты, но и всякие RGB-PCB разных форм и размеров для встраивания куда либо - от DIY-устройств, до люстр бытового назначения. Причем микросхемы имеют всего лишь однопроводную шину данных! Поэтому к контроллеру MegaD-2561 теоретически можно подключить до 38 шт. RGB-лент или RGB-PCB, сделав из него подобие профессионального контроллера управления светом типа DMX.
      В данной статье расскажу как можно подключить к контроллеру ленту на базе RGB-драйверов WS2818. Примечательной особенностью данной ленты является ее питающее напряжение, составляющее 12В! Вообще лента на своем начале и конце имеет 4 шины: GND, BO/BI, DO/DI и 12V. Ленту/ленты можно запитать от отдельного мощного блока питания, но обязательное условие нормальной работы - это объединение GND блока питания ленты с блоком питания контроллера! К контроллеру можно подключить как контакт BO/BI, так и контакт DO/DI. Разница будет в...
      Итак, лента подключена к контроллеру, на блоки питания подано напряжение. Теперь нужно, а точнее НЕ нужно провести конфигурирование порта контроллера, то есть порт должен быть в состоянии NC. Подробнее о подключении лент на базе WS281X к контроллеру MegaD-2561 - тут.

      Применительно к системе intraHouse есть несколько вариантов управления лентами:

      1. Управление лентами с помощью устройства "Светильник RGB.
      Для этого создаем устройство, например, с ID "RGBLAMP1_01" с типом "Светильник RGB":
      MegaD_WS281X_ActorRGB.png
      В соответствующем плагине megad создаем канал и привязываем к нему ранее созданный светильник:
      MegaD_WS281X_Channel.png

      В канале плагина вписана команда управления /%pwd%/?pt=%adr%&ws=%value%&chip=151, где value - значение, получаемое от устройства, привязанного к данному каналу, chip - количество чипов в ленте (в моем 5 м экземпляре их именно 151 шт., то есть плотность ленты - 30 чипов на 1 м).

      Выносим созданный светильник RGB на нужную мнемосхему и теперь в веб-интерфейсе системы нажимаем на его иконку - лента должна засветиться каким-либо цветом (какой по умолчанию сохранен - не знаю). Чтобы изменить цвет свечения - нажимаем долго на иконку светильника и справа всплывает боковое меню устройства - в нем: RGB-ColorPicker позволяет выбрать либо предустановленный цвет или цвет любой градации, а нижний слайдер L позволяет либо уменьшить яркость ленты (в положении 0-50%) или увести яркость в белый цвет (50-100%). Чтобы выключить ленту, нужно нажать на иконку светильника еще раз. Выбранный цвет сохраняется и при новом включении будет такой же какой был при выключении.

      Кстати, если при настройке на иконке светильника RGB оставлены индикаторы, то в веб-интерфейсе на иконке сверху будет отображаться текущее значение массива (выключено - 0,0,0,0; включен красный цвет - 255,0,0,0), а внизу - значение по умолчанию (то, которое было выбрано, оно же будет установлено по команде "on").
      Для иконки светильника RGB @intrahouse сделал удачную картинку в SVG-формате - ищем тут в разделе "Электрика".

      Момент о китайских лентах: встречаются варианты не RGB, а GRB-ленты (проектировщики напутали в разводке)!!! Как итог - цвета green и red поменяны местами. Но в iH есть возможность устранить это:

      • нужно выбрать канал ленты в плагине megad и открыть его настройки;
      • перейти на вкладку "Обработка";
      • в поле "Формула расчета выходного значения для актуаторов" вписать:
      [ value[1],value[0],value[2] ]
      
      • если предполагается управлять лентой с помощью сценариев, то в поле "Формула расчета входного значения" нужно вписать:
      [ value[1],value[0],value[2] ]
      

      2. Управление лентой - с помощью сценария.
      В данном случае возможно сделать практически бесконечное количество вариантов работы RGB-ленты. Причем управление режимами происходит всего лишь с помощью одного актуатора. Для этого создаем актуатор, например, с ID "ACTORA_GARLAND1_01" и типом "Актуатор универсальный аналоговый". При этом для отображения в правом боковом меню устройства слайдера с диапазоном 1-10 (в нижеприведенном сценарии используется 10 вариантов управления лентой) делаем следующие настройки:
      MegaD_WS281X_ActorA.png

      Далее переходим в раздел "Сценарии" и создаем новый сценарий вот с таким кодом:

      /** 
      * @name Освещение - гирлянда из WS2818 
      * @desc Имитация работы гирлянды 
      * @version 4 
      */
      const sw = Device("ACTORA_GARLAND1_01"); 
      
      startOnChange(sw); 
      
      script({
          plugin: "megad1", //Константа названия плагина
          channel: 34,      //Константа номера канала плагина
          cmd: '000000',    //Константа команды
          chip: 151,        //Количество чипов в ленте WS2818
          period: 1,        //Период изменения цвета
          num: 3,
          i: 0,
          
          start() {
            this.ChangeStateSw();
          },
          
          ChangeStateSw() {
      
            //Остановка таймера для выхода из "цикла"
            this.stopTimer("T1");
            
            switch(sw.value) {
              case 0: this.cmd = '000000';
                      break;
              case 1: this.cmd = 'FF0000';
                      break;
              case 2: this.cmd = '00FF00';
                      break;
              case 3: this.cmd = '0000FF';
                      break;
              case 4: this.ChangeRed();
                      break;
              case 5: this.ChangeGreen();
                      break;
              case 6: this.ChangeBlue();
                      break;
              case 7: this.RandomColor();
                      break;
              case 8: this.num = 3; this.RandomPlay();
                      break;
              case 9: this.num = 6; this.RandomPlay();
                      break;
              case 10: this.num = 9; this.RandomPlay();
                      break;
            }
            
            if(sw.value < 4) {
              this.SendDataToWS2818(this.plugin, this.channel, this.cmd, this.chip);
              this.cmd = '';
              this.exit();
            }
          },
      
          ChangeRed() {
            this.addListener(sw, "ChangeStateSw");
            
            let color = this.i.toString(16);
            if(color.length == 1) color = '0' +color;
            this.cmd = color+ '0000';
            
            this.SendDataToWS2818(this.plugin, this.channel, this.cmd, this.chip);
            this.cmd = '';
            
            if(this.i >= 0 && this.i < 16) this.i += 1;
            else if(this.i >= 16 && this.i < 96) this.i += 8;
            else if(this.i >= 96 && this.i < 240) this.i += 16;
            else if(this.i >= 240) this.i = 0;
      
            this.startTimer("T1", this.period, "ChangeRed");
          },
      
          ChangeGreen() {
            this.addListener(sw, "ChangeStateSw");
            
            let color = this.i.toString(16);
            if(color.length == 1) color = '0' +color;
            this.cmd = '00' +color+ '00';
            
            this.SendDataToWS2818(this.plugin, this.channel, this.cmd, this.chip);
            this.cmd = '';
            
            if(this.i >= 0 && this.i < 16) this.i += 1;
            else if(this.i >= 16 && this.i < 96) this.i += 8;
            else if(this.i >= 96 && this.i < 240) this.i += 16;
            else if(this.i >= 240) this.i = 0;
      
            this.startTimer("T1", this.period, "ChangeGreen");
          },
          
          ChangeBlue() {
            this.addListener(sw, "ChangeStateSw");
            
            let color = this.i.toString(16);
            if(color.length == 1) color = '0' +color;
            this.cmd = '0000' +color;
            
            this.SendDataToWS2818(this.plugin, this.channel, this.cmd, this.chip);
            this.cmd = '';
            
            if(this.i >= 0 && this.i < 16) this.i += 1;
            else if(this.i >= 16 && this.i < 96) this.i += 8;
            else if(this.i >= 96 && this.i < 240) this.i += 16;
            else if(this.i >= 240) this.i = 0;
      
            this.startTimer("T1", this.period, "ChangeBlue");
          },
      
          
          RandomColor() {
            this.addListener(sw, "ChangeStateSw");
            
            let color = ["FF0000", "00FF00", "0000FF", "FFFFFF", "000000"];
            this.cmd = color[this.GetRandomInt(0, 5)] + color[this.GetRandomInt(0, 5)] + color[this.GetRandomInt(0, 5)];
            
            this.SendDataToWS2818(this.plugin, this.channel, this.cmd, this.chip);
            this.cmd = '';
            this.startTimer("T1", this.period, "RandomColor");
          },
          
          RandomPlay() {
            this.addListener(sw, "ChangeStateSw");
            
            let color;
            
            for (let i = 0; i < this.num; i++ ) {
              color = this.GetRandomInt(0,256).toString(16);
              if(color.length == 1) color = '0' +color;
              this.cmd += color;
            }
            
            this.SendDataToWS2818(this.plugin, this.channel, this.cmd, this.chip);
            this.cmd = '';
            this.startTimer("T1", this.period, "RandomPlay");
          },
          
          //Функция возвращает случайное целое число между min (включительно) и max (не включая max)
          GetRandomInt(min, max) {
            return Math.floor( Math.random() * (max - min)) + min;
          },
          
          //Функция формирования данных для ленты WS2818
          SendDataToWS2818(plugin, channel, cmd, chip) {
            this.pluginCommand({unit: plugin, command: '/sec/?pt=' +channel+ '&ws=' +cmd+ '&chip=' +chip});
          }
      });
      

      Для работы сценария в вашем конкретном случае нужно изменить константы уровня сценария на нужные (название плагина, канал контроллера, количество чипов ленты).

      Сценарий запускается когда изменяется состояние sw, то есть ранее созданного аналогового актуатора "ACTORA_GARLAND1_01". Актуатор можно включать/выключать, либо изменить состояние во включенном режиме с помощью слайдера в правом боковом меню устройства. Состояния запоминаются.
      0 - лента выключена (выполняется команда '000000');
      1 - лента светиться красным цветом (выполняется команда 'FF0000');
      2 - лента светиться зеленым цветом (выполняется команда '00FF00');
      3 - лента светиться голубым цветом (выполняется команда '0000FF');
      4 - лента плавно увеличивает яркость красного цвета (функция ChangeRed());
      5 - лента плавно увеличивает яркость зеленого цвета (функция ChangeGreen());
      6 - лента плавно увеличивает яркость голубого цвета (функция ChangeBlue());
      7 - лента по всей длине светиться цветом случайного выбора (функция RandomColor());
      8 - лента по всей длине на разных участках светиться цветом случайного выбора (функция RandomPlay() с параметром num=3);
      9 - более сложные цвета и сочетания чем в режиме 8 (функция RandomPlay() с параметром num=6);
      10 - еще более сложные цвета и сочетания чем в режиме 9 (функция RandomPlay() с параметром num=9).

      Во всех функция, чтобы не потерять управление лентой с помощью все того же аналогового актуатора, добавлен слушатель этого актуатора (this.addListener(sw, "ChangeStateSw")), иначе при входе в эти функции сценарий зациклится на их выполнении. Периодичность цвета установлена равной 1 секунде (определяется константой сценария "period").
      Функции ChangeRed(), ChangeGreen(), ChangeBlue() - довольно не простые, поскольку чтобы сделать плавное изменение цвета нужно иметь "цикл" с наибольшим количеством итераций, однако при уменьшении периода изменения цвета:

      1. Становится трудно переключать режимы работы ленты
      2. При сильном уменьшении периода можно вывести из строя саму систему intraHouse!

      Управление режимами работы RGB-ленты по расписанию.
      Чтобы управлять режимами по расписанию нужен сценарий, в который из расписания в назначенное время будет передаваться параметр, а этот параметр будет присваиваться значению актуатора, управляющего лентой. Код сценария простой:

      /** 
      * @name Освещение - управление гирляндой по расписанию 
      * @desc Включение вечером и чередование режимов 
      * @version 4  
      */
      
      const sw = Device("ACTORA_GARLAND1_01");
      
      script({
          start(param) {
            //Установка значения у аналогового актуатора гирлянды
            if(param !== undefined) sw.setValue(param);
            else this.exit();
          }
      });
      

      Теперь в расписании создадим новые записи:
      MegaD_WS281X_Change_Script.png

      Получится три сценария работы:

      • в 17.17 лента включиться зеленым цветом;
      • в 18.17 лента будет работать в режиме "радуга" (случайное изменение цвета по всей длине);
      • в 22.17 лента будет работать в режиме "гирлянда" (разные участки ленты будут светиться случайно выбранным цветом).

      MegaD_WS281X_Shedules.png

      Ну и в качестве закрепления - читателю нужно будет сделать запись в расписании для выключения ленты в нужное ему время)))

      posted in intraHouse и MegaD
      A
      Alex_Jet
    • RE: сообщение из сценария

      @alesle, вначале прочитайте про синтаксис сценариев - тут. Надеюсь, что после этого у Вас отпадет значительная часть вопросов. Также очень полезно знать систему команд - сам до сих пор пользуюсь этой страничкой).

      posted in Сценарии
      A
      Alex_Jet
    • RE: Голосовое управление IH

      Пользователь @div115 написал в Голосовое управление IH:

      у меня на физ. сервере живет IH, LMS и SqueezePlayer
      конечно хотелось бы перенаправить весь звук от апельсинки на сервер по сети, но пока не знаю как это сделать...

      Я думаю, что самой правильной концепцией является:

      1. Отдельный железный сервер УД + LMS +Media, к которому подключен только кабель Eth
      2. По всей квартире/дому разбросаны железки с подключеным Eth (на крайний случай Wi-Fi) и акустикой. На борту у железок - mdmTerminal2 и squeezelite.
        Поэтому ваш вариант перенести OPiZ в потолочное отверстие рядом с акустикой мне нравится намного больше. Сам хочу разработать плату для установки на нее OPiZ + микрофон с усилителем на TS472 + усилитель (хотя бы PAM8610) мощности + светодиодное кольцо на базе WS28xx, но пока руки не доходят...

      И да...я до конца не понял, но похоже у Вас связка LMS ->squeezelite не работает? Если так, то это проще простого! На клиентах ставим squeezelite и их находит LMS (в его настройках на закладке "Информация" есть раздел "Информация о плеере"). Собственно на главной странице LMS сверху справа будет выпадающий список из плееров)

      Passive-poe в реализации OPiZ очень плохой вариант... Лучше взять переходники для passive-poe и снимать хотя бы 12В, подавая сразу на усилитель (тот же PAM8610 - хорошая вещь!), а для OPiZ поставить step-down! - кушает она не мало и греется прилично!

      posted in intraHouse V4 Cherry
      A
      Alex_Jet
    • RE: Плагин CCTV

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

      В документации нет описания команды snap.
      Что за параметры "105","onSnap105" ?

      Это ID канала в плагине CCTV. Встаете на канал и открываете его свойства - вверху будет его ID. Пока этот функционал снэпшотов "ручной"...мультисценарий не организовать:( писал это в пожеланиях для версии 5.

      posted in Плагины
      A
      Alex_Jet
    • Интеграция в iH OLED-дисплея через MegaD

      В задаче Интеграция в iH входов типа Click Mode MegaD я описывал вариант использования "мультикнопки" для вывода различной информации на OLED-дисплей с контроллером SSD1306. Поскольку лишь недавно "допилил" сценарий работы с дисплеем, то сейчас хочу рассказать что же у меня вышло.
      Итак, "мультикнопка", висящая на входе MegaD, имеет три варианта нажатия:
      а. Однократное нажатие (click=1). Если дисплей был выключен (или был перезапуск iH, или перезапуск плагина megad, или сценарий был сохранен), то он включится и отобразит температуру внутри помещения. При втором нажатии кнопки отобразится значение влажности помещения, при третьем нажатии отобразиться значение СО2. Следующее нажатие снова отобразит температуру в помещении и так по кругу.
      б. Двукратное нажатие (click=2). На дисплее отобразится значение температуры на улице.
      в. Удержание кнопки (m=2). Дисплей выключится. Можно конечно было "навесить" что-то еще на этот вариант нажатия кнопки, но в нашей семье дисплей иногда мешает спать. Поэтому и решил его таким образом принудительно выключать.

      Кроме всего этого, сценарий запускается при изменении значения (value) датчиков и если в текущий момент времени на дисплее отображается соответствующий датчику параметр, то его значение обновляется на дисплее.

      /** 
      * @name Сервис - обновление данных на OLED
      * @desc При однократном нажатии кнопки OLED отображает параметры микроклимата данного помещения. При двойном нажатии кнопки - температуру на улице
      * @version 4  
      */
      
      const button  = Device("BUTTON1_01");
      const dt      = Device("STEMP1_01");
      const dh      = Device("SHUMIDITY1_01");
      const dco2    = Device("SENSORA1_01");
      const dt_s    = Device("STEMP4_01");
      
      startOnChange([button,dt,dh,dco2,dt_s]);
      
      script({
        plugin: "megad2", //Переменная названия плагина
        channel: 33,      //Переменная номера канала плагина
        param: 1,         //Переменная для выбора параметров
        button_state: 0,  //Переменная для подсчета одинарных нажатий кнопки
        oled_state: 0,    //Переменная состояния OLED (0 - выключен, 1 - включен)
        col: 0,           //Переменная для расчета № столбца для вывода текста
        time: 1,          //Переменная для вывода времени (0 - нет, 1 - есть)
        text: "",         //Переменная для отображения текста на OLED
        saved: "",        //Переменная для "запоминания" текста
        value: "",        //Переменная для отображения значения на OLED
        unit: "",         //Переменная для отображения ед.изм. на OLED
        
        start() {
          //Обновление данных по датчикам
          if(this.isChanged(dt, "value") && this.param == 1) {
            this.SendData1();
          }
          else if(this.isChanged(dh, "value") && this.param == 2) {
            this.SendData2();
          }
          else if(this.isChanged(dco2, "value") && this.param == 3) {
            this.SendData3();
          }
          else if(this.isChanged(dt_s, "value") && this.param == 4) {
            this.SendData4();
          }
          //Переключение режимов отображения кнопкой
          else if(this.isChanged(button, "value")) {
            let mode = button.value;  //Вариант нажатия кнопки
            
            //Одинарное нажатие кнопки всегда возвращает 1!
            if(mode == 1) {
              //Если OLED был выключен то отображаем первый параметр
              if(!this.oled_state) {
                this.param = mode;
                this.button_state = this.param;
              }
              //Перебираем параметры при каждом одинарном нажатии кнопки
              else {
                this.param = this.button_state + 1;
                if(this.param > 2) this.button_state = 0;
                else this.button_state = this.param;
              }
            }
            //Двойное нажатие кнопки возвращает 4, удержание - 5.
            else {
              this.param = mode;
              this.button_state = 0;
            }
            
            //Выводим информацию на OLED в соответствии с выбранным параметром
            switch(this.param) {
              case 1: this.SendData1();
                      break;
              case 2: this.SendData2();
                      break;
              case 3: this.SendData3();
                      break;
              case 4: this.SendData4();
                      break;
              case 5: this.SendData5();
                      break;
            }
            
            if(mode > 0) {
              this.startTimer("ButRst", 0.2, "ClearState");
            }
          }
        },
          
        SendData1() {
          let text = "Температура"
          let value = dt.value;
          let unit = "grad";
          this.DataToOLED(text, value, unit, this.time);
        },
        
        SendData2() {
          let text = "Влажность";
          let value = dh.value;
          let unit = "percent";
          this.DataToOLED(text, value, unit, this.time);
        },
        
        SendData3() {
          let text = "Уровень_СО2,_ppm";
          let value = dco2.value;
          let unit = "ppm";
          this.DataToOLED(text, value, unit, this.time);
        },
        
        SendData4() {
          let text = "На_улице";
          let value = dt_s.value;
          let unit = "grad";
          this.DataToOLED(text, value, unit, this.time);
        },
        
        SendData5() {
          this.TurnOffOLED();
        },
        
        //Функция форматирования данных и их отображения на OLED
        DataToOLED(text, value, unit, time) {
          let iconv = require("/opt/intrahouse-c/backend/node_modules/iconv-lite");
          let buf = iconv.encode(text, "cp866");
          this.text = buf.toString("latin1");
          
          //Центрирование заголовка
          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.value = 's+' +str;
          else if(str.length < 4) this.value = 'ss' +str;
          else if(str.length < 5) this.value = 's' +str;
          else this.value = str;
          
          //Выбор единицы измерения
          if(unit == "grad") this.unit = ":_";
          else if(unit == "percent") this.unit = "%";
          else if(unit == "ppm") this.unit = "s";
          
          //Вывод команд на дисплей
          if(this.saved != this.text) { //Если новый заголовок
            this.saved = this.text;     //то запоминаем его
            this.ClearOLED();           //очищаем первую строку
            //делаем паузу, выводим новый заголовок
            this.startTimer("T2", 0.05, "SendTextToOLED");
            //делаем паузу, выводим значение
            this.startTimer("T3", 0.2, "SendValueToOLED");
          }
          else {                        //Иначе обновляем значение
            this.SendValueToOLED();
          }
          if(time) {                    //Если есть вывод времени
            //то после отображения значения выводим его
            this.startTimer("T4", 0.4, "SendTimeToOLED");
          }
          if(!this.oled_state) {        //Если дисплей выключен
            //то включаем его после обновления параметра
            this.startTimer("T5", 0.4, "TurnOnOLED");
          }
        },
        
        ClearState() {
          this.assign(button, "value", 0);
        },
        
        ClearOLED() {
          this.pluginCommand({unit: this.plugin, command: '/sec/?pt=' +this.channel+ '&disp_cmd=1&row=0'});
        },
        
        ControlOLED(cmd) {
          this.pluginCommand({unit: this.plugin, command: '/sec/?cmd=' +this.channel+ ':' +cmd});
        },
        
        TurnOnOLED() {
          this.oled_state = 1;
          this.ControlOLED(this.oled_state);
        },
        
        TurnOffOLED() {
          this.oled_state = 0;
          this.ControlOLED(this.oled_state);
        },
        
        SendTextToOLED() {
          this.pluginCommand({unit: this.plugin, command: '/sec/?pt=' +this.channel+ '&text=' +this.text+ '&col=' +this.col+ '&row=0'});
        },
        
        SendValueToOLED() {
          this.pluginCommand({unit: this.plugin, command: '/sec/?pt=' +this.channel+ '&text=' +this.value+this.unit});
        },
        
        SendTimeToOLED() {
          //Запрос системного времени и форматирование единиц (для отображения 00...09)
          let time = new Date();
          let hours = time.getHours() < 10 ? "0" +time.getHours() : time.getHours();
          let minutes = time.getMinutes() < 10 ? "0" +time.getMinutes() : time.getMinutes();
          let seconds = time.getSeconds() < 10 ? "0" +time.getSeconds() : time.getSeconds();
          //Группировка единиц времени для передачи плагину
          let text = hours+ ':' +minutes+ ':' +seconds;
          this.pluginCommand({unit: this.plugin, command: '/sec/?pt=' +this.channel+ '&text=' +text+ '&col=45&row=6'});
        }
      });
      

      Код сценария получился довольно многострочным. Однако читатель, обладающий небольшим навыком JS-программирования сможет понять и разобраться со сценарием благодаря наличию комментариев и понятному названию функций. Непосредственно с дисплеем работают 5 функций - TurnOnOLED(), TurnOffOLED(), SendTextToOLED(), SendValueToOLED(), SendTimeToOLED(). Все они используют переменные уровня сценария (к которым нужно обращаться через "this"), поскольку обмен данными с дисплеем медленный и необходимо выдерживать паузы, запуская таймеры Т2-Т5, по истечению которых должны вызываться соответствующие функции (однако какой-либо аргумент в таком случае в функцию передать нет возможности):

      • для очистки первой строки, на которой по умолчанию выводится текст с наименованием параметра;
      • для вывода текста с наименованием параметра;
      • для вывода значения параметра крупным шрифтом ("нативный" шрифт MegaD);
      • для вывода времени обновления параметра.

      Кстати, при "игре" с выводом последнего возникли трудности отображения данных на дисплее. Итерационным методом понял, что надпись времени нужно выводить в 6-й строке (row=6), но когда попробовал вывести время в седьмой, то подопытный дисплей у меня нещадно заглючил! Вначале значение параметра (крупный шрифт) отображалось только на левой части дисплея (хотя все остальные строки - в полном объеме) и никакие переинициализации ("save" MegaD-2561 или php-скрипт) и даже долговременное снятие питания с дисплея не помогали! Каким-то чудом (с начало вывел время в row=1...6, потом снова в row=7) на некоторое время дисплей вновь заработал правильно, однако потом все строки дисплея сместились на половину строки и с этим я уже ничего не смог сделать.

      Сценарий обновлен 19.11.2020

      posted in intraHouse и MegaD
      A
      Alex_Jet
    • RE: Сценарии - новая версия API

      Готовлюсь к новому году) в проем гаражных ворот смонтировал 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 "пикселей". Как сделать уменьшающийся по яркости хвост огня и увеличить его скорость - это большой вопрос!!

      posted in Сценарии
      A
      Alex_Jet
    • RE: Голосовое управление IH

      @div115, раз на сервере стоит iH, то вероятно можно использовать голосовой плагин самого iH? А может все-таки к акустике подключить малинку/апельсинку?
      Вообще теоретически на это сервер можно установить mdmTerminal2 и в сценарии tts осуществлять через второй плагин. По крайней мере у меня несколько терминалов и я могу на любой вывести tts. А вот сервер УД у меня - только сервер, находящийся в темном черном углу. Даже LMS живет на другой железке.

      posted in intraHouse V4 Cherry
      A
      Alex_Jet
    • RE: Плагин MegaD

      @regabriel, если вы название канала указываете как 0 - 37, то они плагином парсятся в стандартном режиме - различаются состояния OFF=0 и ON=1.
      Если название канала задать типа "QWERTY", то стандартный парсинг не будет использоваться и по идее все что есть в body мы можем разбирать. Однако у меня сходу не получилось разобрать split-ом на Val и Cnt (OFF/1)...

      posted in Плагины
      A
      Alex_Jet
    • Преобразование входных данных с помощью плагина megad

      Плагин MegaD имеет широкие возможности для корректировки/расчета входных значений. Имеется как минимум две возможности:

      1. "Формула расчета входного значения" (в свойствах канала плагина переходим на вкладку "Обработка" и видим это поле)
      2. "Функция обработки значения" (в свойствах канала плагина на вкладке "Канал" включаем чек-боксом "Использовать функцию обработки при получении данных от контроллера" и ниже появляется поле "Функция обработки значения")

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

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

      Примеры использования "Формула расчета входного значения"
      1.1 Умножение, деление и смещение значения:

      value/10
      value*10
      value + 1.5 (есть баг, поэтому пишем Number(value)+1.5)
      value - 0.69 (есть баг, поэтому пишем Number(value)-0.69)
      

      1.2 В случае не RGB, а китайских GRB-лент для адекватной работы с ними:

      [ value[1],value[0],value[2] ]
      

      1.3 Расчет значения с аналогового датчика давления, подключенного к АЦП контроллера MegaD:

      ((value * 3.47/1024) - 0.5) * 2.8, где:
      3.47 - это реальное (нужно измерять) напряжение 3.3В на контроллере MegaD, которое используется в качестве опорного для АЦП.
      

      1.4 "Экзотические" формулы:

      ( ((840 - Number(value))/840) - 410 ) *100 - расчет значения влажности (в %) для аналогового датчика влажности почвы;
      100 - (Number(value) - 20)*100/85 - преобразование расстояния  в % для HC-SR04
      (value>=20 && value<= 105) ? Math.round(100 - (Number(value) - 20)*100/85) : (value <20 ? 100 : 0) - то же, с округлением в максимумах.
      

      Примеры использования "Функция обработки значения".
      По сути это JS-скрипт и он может вернуть значение или undefined. Входные параметры:
      val — значение c контроллера
      depo — объект, который хранит данные между вызовами функции. Внутри объекта можно создавать любые структуры.

      2.1 Накопление массива данных, откидывание "бракованных" (максимальное и минимальное значение) и усреднение оставшихся. Актуально для датчиков температуры/влажности/давления/освещенности и т.д., особенно которые участвуют в управлении какими-либо процессами.

      function (val, depo)
      {  var avr;
         
         if (!depo.res) depo.res = [];
         depo.res.push(val);
         
         //Нужны еще измерения, значение не возвращаем
         if (depo.res.length < 5) return;
         //Иначе сортируем и усредняем "средние" значения
         else{
            depo.res.sort();
            avr = ((depo.res[1] + depo.res[2] + depo.res[3]) / 3).toFixed(2);
         }
         
         depo.res = []; //Перед следующими измерениями сбрасываем массив
         return avr; //Возвращаем значение
      }
      

      2.2 То же, но с расчетом конечного значения. Актуально для датчиков, которые подключены к АЦП контроллера. В примере ниже - формула для аналогового датчика давления:

      function (val, depo)
      {  var result;
         var avr;
         
         if (!depo.res) depo.res = [];
         depo.res.push(val);
         
         //Нужны еще измерения, значение не возвращаем
         if (depo.res.length < 5) return;
         //Иначе сортируем и усредняем "средние" значения
         else{
            depo.res.sort();
            avr = ((depo.res[1] + depo.res[2] + depo.res[3]) / 3).toFixed(2);
         }
         
         result = (((avr * 3.47/1024) - 0.5) * 2.8).toFixed(2);
         
         depo.res = []; //Перед следующими измерениями сбрасываем массив
         return result; //Возвращаем значение
      }
      

      Чтобы накапливать данные и усреднять значения, я устанавливаю период опроса для большинства датчиков равный 60 секундам. Таким образом, данные накапливаются 5 минут и спустя это время устройству присваивается усредненное за последнюю пятиминутку значение. Оно же пишется в БД, соответственно, БД не "раздувается". Усредненное значение температуры очень актуально для системы отопления (сквозняки, ветер и прочие кратковременные факторы не приводят к резкому уменьшению температуры, соответственно система не замечает этого), усредненное значение влажности или уровня СО2 позволяет оставаться системе вентиляции и поддержания микроклимата в стабильном состоянии, то же справедливо для датчика освещенности, который является составляющим элементом системы освещения.

      posted in intraHouse и MegaD
      A
      Alex_Jet
    • RE: Голосовое управление IH

      Пользователь @div115 написал в Голосовое управление IH:

      по моей задумке, - на апельсин хочу повесить

      датчик движения,
      i2c датчики температуры/влажности, освещенности, СО2,
      микрофон,
      динамики с усилителем из колонок типа: http://microlab.com/ru/catalog/stereosistemyi/usb/md-122/ - кмк будет вполне бюджетно
      (исключение коридоры 1,2 этажей - там уже стоит потолочная акустика)
      возможно лед ленту W2812

      Не рекомендую делать такую солянку. Вообще OPiZ довольно не стабильная железка (у меня есть простая и Plus) и хоть она имеет gpio, но лучше их использовать для реализации полноценного mdmTerminal2 (управление режимами усилителя, управление кольцом из светодиодов WS28xx). Очень сильно греется и по хорошему ей надо тормозить CPU и занижать питание. В unix очень не удобно (ИМХО) работать с I2C и 1W датчиками.
      А датчики температуры/влажности/СО2, датчик движения и прочее лучше повесить на специализированные контроллеры! Я повсеместно использую MegaD-2561 (версия в моноблоке в последней ревизии - вообще улет!)

      Как указать какому плееру воспроизводить звук с конкретного MDMтерминала - я не знаю, буду благодарен если подскажете.

      Объясните по другому. Не понимаю вашу задачу! mdmTerminal2 - это железка "сама в себе", которую можно интегрировать в любой умный дом. У меня сейчас используется 3 терминала - в центре гостевой (по сути охватывает половину первого этажа), на втором этаже в спальне/кабинете и у сына в комнате. При этом благодаря LMS во всех вышеперечисленных комнатах сделан мультирум.

      posted in intraHouse V4 Cherry
      A
      Alex_Jet
    • RE: Плагин MegaD

      @regabriel, get-запрос улетает за считанные МИЛЛИСЕКУНДЫ! О чем вы говорите? У вас за 25 мс только один счет пролетает! Поставьте очередь запросов в плагине 1 мс, сделайте скрипт и попробуйте выявить ошибку. Думаю, ее просто не будет! И да - у вас промышленное производство по дозированию компонентов для изготовления каких-то продуктов?

      Формула расчета конечно работает. Правда при вычислении разности или сложении нужно записывать в виде - "Number(value)-0.69"

      Чтобы устройству записывать значение в cnt, то нужно применять "Функцию обработки значения" - в ней парсить значение в ключе cnt и возвращать его в систему. Правда у меня это сделать сходу не получилось. Может @intrapro поможет?

      posted in Плагины
      A
      Alex_Jet
    • RE: Воспроизведение медиафалов LMS на плеерах SqueezePlayer через IntraHouse

      Здравствуйте! Это конечно все хорошо, но все же это "костыль" к LMS. Хотя LMS - это скорее отличный мультирум!
      Посмотрите вот эту тему. mdmTerminal2 позволяет намного больше всего сделать. Причем плагин я "слепил" для iH (там правда много нужно чего причесать, но я не программист чтобы довести все хотелки до ума). Позволяет на всех разбросанных по дому Linux-устройствах (у меня на всех стоит squeezelite и mdmTerminal2) озвучивать любые события. А также отлично (в зависимости от микрофонной части) воспринимает речь и передает string на сервер. На сервере у меня есть большой!!! сценарий обрабатывающий все входящие стринги и в зависимости от них осуществляющий какие-либо действия (управление освещением, управление отоплением, вентиляцией, запрос состояния охранной системы, гаража, погреба, легкое общение с голосовым помощником как с одушевленным созданием...). Кроме этого, mdmTerminal2 имеет плагины "WiKi", "Скажи" и прочие. То есть, например, можно поинтересоваться у голосового помощника кто такой Наполеон, что такое Титаник и прочее. "Скажи" воспроизводит текст, который озвучен после слова "Скажи". Хотя удобнее сделать обработку на сервере строку "Позови всех кушать", на что отправить всем mdmTerminal2 фразу "Все приглашаются к столу на трапезу".

      posted in Задачи и варианты решения
      A
      Alex_Jet
    • RE: Голосовое управление IH

      Пользователь @div115 написал в Голосовое управление IH:

      MDM установленный на OPZ_1 получил запрос через микрофон OPZ_1 но голосовой ответ будет выведен на динамики OPZ_2 .

      Я такую задачу не решал, однако с помощью pulse audio такое сделать точно можно! То есть на локальном OPZ_1 в asound.conf надо прописать внешнюю звуковую карту в качестве pcm.playback. А с помощью pulse audio на OPZ_2 сделать сетевую звуковую карту.
      Но опять же - зачем? Какое применение?

      posted in intraHouse V4 Cherry
      A
      Alex_Jet
    • Сценарий для переключения чего-либо по расписанию и с помощью кнопок в веб-интерфейсе

      Задача: переключать режимы отопления "Эконом", "День", "Ночь" кнопками виджета "Режимы отопления", а также по расписанию. Вроде бы все просто, однако по расписанию отопление нужно переводить только в два режима - "День" (утром) и "Ночь" (вечером), а если пользователь принудительно установил режим "Эконом", то расписание не должно срабатывать!

      Вообще режимы отопления (3 режима) и вентиляции (5 режимов) у меня выбираются с помощью устройства "Переключатель", у которого можно сделать несколько позиций и конечно же визуализировать его на экране/мнемосхеме/виджете так как захочется. Вот только отдельные горизонтальные кнопки у меня не получилось сделать, только с вертикальным расположением:
      Сценарий_Переключения_Переключатели_Систем.png

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

      Сценарий, который обрабатывает нажатие кнопок изменения режима работы отопления и команды из расписания имеет следующий вид:

      /** 
      * @name Отопление - переключение режимов
      * @desc Параметр имеет вид {"type":"button/sсhedule", "value":"0...2"}
      * @version 4  
      */
      
      const mode = Device("SWITCH_HEATING");
      
      script({
        start(param) {
          if(param !== undefined) {
            const obj = this.ParseJSON(param);
            //Вывод в журнал для отладки
            //this.log("Тип - " +obj.type+ "; Значение = " +obj.value);
            
            //Если команда от кнопки виджета, то переключаем режим
            if(obj.type == "button") {
              mode.setValue(obj.value);
            }
            //Если команда от задания в расписании и режим День/Ночь, то переключаем режим
            else if(obj.type == "sсhedule" && mode.value > 0) {
              mode.setValue(obj.value);
            }
            //Иначе выходим (сохраняем режим "Эконом")
            else this.exit();
          }
          else this.exit();
        },
        
        //Функция парсинга входного параметра
        ParseJSON(param) {
            try {
              return JSON.parse(param);
            }
            catch (e) {
              let text = e instanceof SyntaxError;
              this.log("SyntaxError - " +text+ "; param - " +param);
            }
        }
      });
      

      Чтобы сценарий работал нужно в параметрах кнопок виджета выбрать "Запуск сценария", имя сценария (в моем случае - "Отопление - переключение режимов") и в качестве Команды/Дополнительного параметра вписать строку в формате JSON, например:

      1. {"type":"button", "value":"0"} - означает что команда на переключение отдается кнопкой со значением 0. В моем случае - это включение режима отопления "Эконом".
        Сценарий_Переключения_по_Кнопке.png

      2. {"type":"sсhedule", "value":"2"} - означает что команда на переключение отдается заданием из расписания со значением 2. В моем случае - это включение режима отопления "День"
        Сценарий_Переключения_по_Расписанию.png

      Собственно такую структуру управления - с помощью кнопок в веб-интерфейсе и заданий расписания iH - можно применить к любому устройству, соответственным образом переписав сценарий.

      posted in Решения пользователей
      A
      Alex_Jet