Navigation

    Forum

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

    div115

    @div115

    8
    Reputation
    29
    Posts
    4
    Profile views
    1
    Followers
    0
    Following
    Joined Last Online

    div115 Follow

    Best posts made by div115

    • RE: Плагин TextToSpeech

      привел в рабочее состояние text2speech

      Как оказалось, на сегодняшний момент Yandex полностью поменял API по сравнению с тем, под который написан плагин, по этому пришлось переписать немножко код (я качал и ковырял версию 0.0.4 с гитхаба).

      Для того что-бы получить доступ к фунциям Yandex SpeechKit пришлось:

      • зарегистрировать на себя облако создав платежный аккаунт,
      • получить IAM-токен
      • создать каталог в облаке (и запомнить его ID - он нам далее пригодится для синтеза звука)
      • в каталоге создать - Сервисный аккаунт
      • в сервисном аккаунте создать API-ключ - и запомнить его - он нам далее пригодится для синтеза звука.

      Итого: по результатам регистрации на Yandex должен быть API-ключ и ID каталога.

      Далее ковырял установленный плагин, заранее прошу прощения за корявый код, т.к. таких слов как js-node и CURL до текущей ситуации я не знал.
      Ковырял при помощи описания API от Yandex https://cloud.yandex.ru/docs/speechkit/tts/request + гуглил по синтаксису и функциям языков.

      По большому счету надо переписать в плагине одну библиотеку из модуля "yandex-speech" для этого идем в: /var/lib/intrahouse-c/plugins/text2speech/node_modules/yandex-speech/lib
      там есть файл: YandexTTS.js

      Содержимое YandexTTS.js после моего ковыряния:

      'use strict';
      
      var request = require('request');
      var fs = require('fs');
      
      
      var yandex_tts_url = 'https://tts.api.cloud.yandex.net/speech/v1/tts:synthesize';
      
      var YandexTTS = function (options, callback) {
        
      
      var headers = {'Authorization': 'Api-Key ' + options['developer_key']};
      
      var dataString = 'text='+  options['text'] +
          '&lang='+ options['lang'] +
          '&voice='+ options['speaker'] +
          '&emotion='+ options['emotions'] +
        //  '&speed=' + options['speed'] + '';
          '&speed=0.9' +
        //  '&folderId=' + options['folder_id'] + '';
       	'&folderId=b1g92u63tba34rg4c8sr';
      
      
      var request_options = {
          url: yandex_tts_url,
          method: 'POST',
          headers: headers,
          body: dataString
      };
         	var file = fs.createWriteStream(options['file']);
          	file.on('finish', callback);
      	request(request_options).pipe(file);
      };
      
      module.exports = YandexTTS;
      

      Если кто-то будет пользоваться исправленным кодом, в коде надо заменить слово b1****************sr на ранее полученный ID каталога и в параметрах плагина надо в поле токен прописать ранее полученный API-ключ и после этого перезапустить плагин.

      В параметры плагина text2speech, пытался добавить элементы: folderId и speed - но что-то у меня не получилось, - параметры в интерфейсе появились, данные там сохранялись, но вызвать их у меня не получилось.

      Далее, как выяснилось, в новом API SpeechKit в качестве ответа выдает файл в формате ogg (по умолчанию), или в RAW (надо дополнительно выбирать при передаче параметров) - который потом придется преобразовывать в какой-то другой формат. Сразу в формате wav SpeechKit не синтезирует. Поэтому пришлось доустановить в линуксе mplayer, т.к. тот что был у меня установлен по умолчанию файлы ogg не проигрывал.

      При вызове информатора, в тексте который необходимо озвучить можно расставлять ударения в словах вставляя перед ударной гласной 3 символа: %2B согласно документации Yandex вообще-то надо ставить символ "+" но у меня как-то не срослось с урл-кодированием передаваемого текста, и поэтому вместо "+" ставлю %2B

      В целом на текущий момент синтез звука в IH работает.

      И еще, изначально в text2speech не было голоса alena, - как по мне - так это самый приятный голос из синтезируемых. Его можно добавить поправив файл /var/lib/intrahouse-c/plugins/text2speech/text2speech.json добавив следующий код в параметре yandex_speaker:

      {
                "id": "alena",
                "name": "Alena"
              },
      

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

      posted in intraHouse V4 Cherry
      D
      div115
    • RE: Плагин HTTP-Client

      @div115
      проблема решена, как оказалась я неправильно установил систему IntraHouse

      IH ставил на Debian 10, по умолчанию в нем нет пакета sudo. И посмотрев что установка ругается в том числе на sudo я решил установить IH без команды sudo: "curl -sL https://git.io/fN1JN | bash -E -s ru"
      вместо "curl -sL https://git.io/fN1JN | sudo -E bash -s ru".

      С варнингами система поставилась и работала, + там точно работали планины МегаД, р2р, и уведомления на телефон. А с планином http получилась засада - после запуска он сразу же останавливался.

      Внимательно прочитав список поддерживаемых систем я на виртуалке поставил Ubuntu 18.04, на нее IH и плагин http. - все работало как надо.

      Так я решил что IH просто не поддерживает Debian 10. Потом на виртуалке я поставил Debian 9, в очередной раз обратив внимание на то что команда установки не запустилась ругаясь на sudo. Я установил IH как и раньше - без sudo. Грабли оказались те же - http плагин не работал. Тогда я до установил sudo и переустановил IH правильной коммандой - и счастье - http заработал.

      Далее на физическом сервере на котором работал IH на debian 10 я сделал бэкап проекта, доустановил sudo и переустановил IH правильной коммандой. Далее апгрейдил IH до последней версии и просто переключился с демо-проекта на рабочий проект что был раньше (оказывается во время переустановки он не удалился и даже не пришлось загружать бэкап). Теперь все работает как надо.

      posted in Плагины
      D
      div115
    • Как подружить WQTT и устройства IntraHouse уже привязанные к другим плагинам

      Просто добавить в канал плагина устройство уже привязанное к другому плагину (например к плагину Mega-D) просто так не получается, т.к. в поле "Устройство" его нет. Но все же сделать связку топика канала с таким устройством возможно.

      Для этого нужно создать такой мультисценарий (можно и простой сценарий но тогда придется писать похожий сценарий для каждого подключаемого устройства) с "ID сценария" например - [syncro_switch] и "Найменование" например - [переключатель]

      const lamp = Device("ActorD", "Устройство"); 
      
      script ({    
          start({topic, message}) {
        if (message == 1) lamp.on();
        else lamp.off();
          }
      });
      

      После сохранения скрипта надо перезапустить IntraHouse.

      далее во вкладке скрипта "Запуск для устройств" создаем новую запись и в графе "Устройство" добавляем то устройство которое хотим привязать к топику MQTT и сохраняем.
      Далее идем в плагин MQTT создаем новый канал. Там заполняем номер канала, выбираем тип канала DO-digital output, прописывем топик и сохраняем. После сохранения появляется поле "Запустить сценарий при получении" - в нем выбираем сценарий типа переключатель(Имя_нашего_устройства_которое_хотим_подключить). Далее еще раз сохраняем канал. Потом перезапускаем плагин MQTT и все должно работать.

      alt text

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

      posted in Задачи и варианты решения
      D
      div115
    • RE: Релиз IntraHouse V5

      @IntraVM
      И еще если можно, поправьте пожалуйста ссылку в Примерах проектов (v5) по ссылке проекта - Dream House реально скачивается проект - Metro

      posted in intraHouse V5
      D
      div115
    • RE: Как подружить WQTT и устройства IntraHouse уже привязанные к другим плагинам

      Пользователь @Erik написал в Как подружить WQTT и устройства IntraHouse уже привязанные к другим плагинам:

      В свойствах устройства на вкладке "дополнительно" можно поставить галочку "расшарить устройство". Это не оно?

      Да, - оно. Круто ! и без извращений

      posted in Задачи и варианты решения
      D
      div115
    • RE: Как подружить WQTT и устройства IntraHouse уже привязанные к другим плагинам

      @Erik
      хотя у меня так не работает - возможности выбрать в канале устройство занятое другим плагином все равно нет 😞

      но через скрипт - все работает

      posted in Задачи и варианты решения
      D
      div115

    Latest posts made by div115

    • RE: MQTT. Неверно считывает состояние.

      @gewer как вариант - при изменении состояний сохранять их в глобальных переменных, а при загрузке сервера - восстанавливать

      posted in intraHouse V4 Cherry
      D
      div115
    • RE: Время в строке состояния

      @laronov
      у меня в HTML контейнере так работает:

      <script type="text/javascript">  
      setInterval(function () {  
       date = new Date(),  
       h = date.getHours(),  
       m = date.getMinutes(),  
       s = date.getSeconds(),  
       h = (h < 10) ? '0' + h : h,  
       m = (m < 10) ? '0' + m : m,  
       s = (s < 10) ? '0' + s : s,  
       document.getElementById('time').innerHTML = h + ':' + m + ':' + s; 
       var now = new Date();
      var days = ["воскресенье", "понедельник", "вторник", "среда", "четверг", "пятница", "суббота"];
      var months = ["января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентрября", "октября", "ноября", "декабря"];
       document.getElementById('date').innerHTML = days[now.getDay()] + " - " + now.getDate() + " " + months[now.getMonth()] + " "  + now.getFullYear();  
      }, 1000);
      </script>
       <div align="center"><span style="color:#FFFFFF; font-weight: bold; font-size:30pt;  line-height: 1.1; background:#000000; padding:0px;"><span id="date">-- -- --</span></span><div>
       <div align="center"><span style="color:#FFFFFF; font-weight: bold; font-size:130pt; line-height: 0.65; background:#000000; padding:-10px;"><span id="time">00:00:00</span></span><div>
      
      
      posted in intraHouse V4 Cherry
      D
      div115
    • RE: Воспроизведение медиафалов LMS на плеерах SqueezePlayer через IntraHouse

      ок, спасибо за информацию, как похолодает и у меня будет больше времени пробующую попытку №2 разобраться с mdmTerminalом т.к. у меня дома 4шт PI Zero, 4шт PI One и 1 PI PC, есть куда все повесить.
      И еще можете скинуть ссылку на - микрофонный усилитель T472?

      posted in Задачи и варианты решения
      D
      div115
    • RE: Воспроизведение медиафалов LMS на плеерах SqueezePlayer через IntraHouse

      Добрый день, @Alex_Jet, да согласен, что скрипт - костыль но для меня пока это выход, тем более в ближайшее время все равно буду переходить на IntraHouse V5.
      С mdmTerminal2 я год тому назад пытался что-то сообразить, и вроде бы в той теме даже были мои комментарии. Но ключевой проблемой у меня тогда стало качество распознавания. Процент успешного распознавания был для меня не приемлемым. Тогда в качестве железа использовал 4х канальный микрофон от PS и OPI. Судя по всему я не смог сделать нормальные профили под snowboy, да и к тому времени проект snowboy помирал уже... И все закончилось покупкой Yandex колонки.
      А для воспроизведения звука mdmTerminal не подошел т.к. на кухне/столовой у меня планшет и большинство звуковых сообщений идет именно на него и коридорные колонки. А как я понял андройд подружить с mdmTerminalом проблематично.
      Но все же я считаю mdmTerminal перспективным вариантом и надеюсь что на V5 он будет как-то реализован.

      posted in Задачи и варианты решения
      D
      div115
    • RE: Как подружить WQTT и устройства IntraHouse уже привязанные к другим плагинам

      @Erik
      хотя у меня так не работает - возможности выбрать в канале устройство занятое другим плагином все равно нет 😞

      но через скрипт - все работает

      posted in Задачи и варианты решения
      D
      div115
    • RE: Как подружить WQTT и устройства IntraHouse уже привязанные к другим плагинам

      Пользователь @Erik написал в Как подружить WQTT и устройства IntraHouse уже привязанные к другим плагинам:

      В свойствах устройства на вкладке "дополнительно" можно поставить галочку "расшарить устройство". Это не оно?

      Да, - оно. Круто ! и без извращений

      posted in Задачи и варианты решения
      D
      div115
    • Как подружить WQTT и устройства IntraHouse уже привязанные к другим плагинам

      Просто добавить в канал плагина устройство уже привязанное к другому плагину (например к плагину Mega-D) просто так не получается, т.к. в поле "Устройство" его нет. Но все же сделать связку топика канала с таким устройством возможно.

      Для этого нужно создать такой мультисценарий (можно и простой сценарий но тогда придется писать похожий сценарий для каждого подключаемого устройства) с "ID сценария" например - [syncro_switch] и "Найменование" например - [переключатель]

      const lamp = Device("ActorD", "Устройство"); 
      
      script ({    
          start({topic, message}) {
        if (message == 1) lamp.on();
        else lamp.off();
          }
      });
      

      После сохранения скрипта надо перезапустить IntraHouse.

      далее во вкладке скрипта "Запуск для устройств" создаем новую запись и в графе "Устройство" добавляем то устройство которое хотим привязать к топику MQTT и сохраняем.
      Далее идем в плагин MQTT создаем новый канал. Там заполняем номер канала, выбираем тип канала DO-digital output, прописывем топик и сохраняем. После сохранения появляется поле "Запустить сценарий при получении" - в нем выбираем сценарий типа переключатель(Имя_нашего_устройства_которое_хотим_подключить). Далее еще раз сохраняем канал. Потом перезапускаем плагин MQTT и все должно работать.

      alt text

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

      posted in Задачи и варианты решения
      D
      div115
    • RE: Воспроизвести звук в браузере

      https://forum.ih-systems.com/topic/322/воспроизведение-медиафалов-lms-на-плеерах-squeezeplayer-через-intrahouse

      posted in Задачи и варианты решения
      D
      div115
    • Воспроизведение медиафалов LMS на плеерах SqueezePlayer через IntraHouse

      Давно возникла потребость озвучивать различные события в разных частях дома. Например в дальних частях дома и на втором этаже не слышно как открывается/закрывается входная дверь или позвать всех домашних к столу что-бы не кричать на весь дом. Или озвучить персональное сообщение в конкретной комнате.
      Частичным решением были потолочные динамики в коридорах первого и вторго этажей, кабеля которых шли на правый и левый канал звуковой карты компа на котором стоит IntraHouse. И воспроизведение сообщений происходило за счет проигрывания файлов локально на сервере IntraHouse. Но все же этого не хватало.

      После долгих поисков обнаружил что при помощи скриптов можно удаленно управлять плеерами Logitech Media Server(LMS) - нашел скрипт на pearl который делал как раз то что мне было нужно: https://www.domoticz.com/wiki/Logitech_Media_Server но, к сожалению, я так и не смог заставить этот скрипт заработать. А это было бы замечательным решением, т.к. на практически любой линукс или андройд можно поставить SqueezePlayer - клиент для LMS и воспроизводить медиафайлы как на каком-либо отдельном плеере так и синхронно на нескольких. В том числе таким образом можно организовать воспроизведение звука на клиентах где стоит IntraHouse Kiosk.

      Как оказалось из разбора того скрипта на pearl - LMS поддерживает протокол JSON-RPC, и плюс еще нашелся API JSON-RPC для LMS: https://gist.github.com/samtherussell/335bf9ba75363bd167d2470b8689d9f2

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

      скрипт: lms_alert_player.py

      #-*- coding: UTF-8 -*-
      from sys import argv
      import requests
      import json
      import time
      
      script, alert_file = argv  # запоминаем аргументы переданные из коммандной строки - в данном случае - файл для воспроизведения
      
      #script, alert_file, alert_volume = argv
      #print  alert_file
      #print alert_volume
      
      
      # объявляем переменные 
      lms_ip = '10.0.0.2:9000' # IP адрес и порт логитеч медиа плеера
      player_mac = {'hall': 'd8:cb:8a:9c:67:63', 'kitchen': 'ad:d4:61:6d:65:33', 'parlor': 'dd:bb:cc:dd:00:44'} # словарь потенциальных плееров
      # на которых надо будет озвучивать сообщение  ключ - произвольный псевдоним плеера, значение - мак адрес плеера
      
      online_players =  list() # список экземпляров класса плеер на базе 
      master_player_mac = ""   # переменная в которой будет содержаться мак адрес мастер-плеера
      
      """---------- процедура для упрощения вызова процедуры протокола JSONRPC --------------------------"""
      def callRPC(params):
          data =  {"jsonrpc":"2.0", "method": "slim.request", "params": params ,'id':1}
          httpResponse = requests.post("http://%s/jsonrpc.js" % lms_ip, data=json.dumps(data))
          return json.loads(httpResponse.text)
      
      """  Класс для получения и хранения свойств удаленного плеера   """
      class LMS_Player(object):
      
          def __init__(self, alias, mac):
             
              self.alias = alias
              self.mac = mac
      
              try:
      	  answer = callRPC([mac, ["status","-"] ])
      	  self.name = answer["result"]["player_name"]
                self.power = answer["result"]["power"]
      	  self.volume = answer["result"]["mixer volume"]
                self.repeat = answer["result"]["playlist repeat"]
                self.mode = answer["result"]["mode"]
       	except Exception as e: # в том случае если не получили ответ от плеера (например он сейчас физически выключен)
        	  pass
      	  self.name = ""
                self.power = -1
                self.volume = -1
                self.repeat = -1
                self.time  = 0
                self.mode  = ""
      
              try:
                self.time = answer["result"]["time"]
              except Exception as e: # в том случае если был включен такой режим плеера в которм нет свойства time 
                pass
                self.time  = 0
      
              try:
                answer = callRPC([mac, ['playlist', 'path', '?'] ])
      	  self.path = answer["result"]["_path"]
              except Exception as e:  # в том случае если не получили ответ от плеера (например он сейчас физически выключен)
                pass
                self.path = ""
      
          def print_properties(self): # процедура вывода свойств плеера. Использовалась в процессе отладки 
      	print "*******************************"
       	print "Alias: %s" % self.alias
       	print "MAC: %s" % self.mac
       	print "Name: %s" % self.name
       	print "Power: %s" % self.power
       	print "Volume: %s" % self.volume
       	print "Repeat: %s" % self.repeat
       	print "Time: %s" % self.time
       	print "Mode: %s" % self.mode
       	print "Path: %s" % self.path
      
      
      # создаем список экземпляров класса LMS_Player в соответсвии с ранее объявленным словарем потенциальных плееров 
      for i in player_mac.keys():
       online_players.append(LMS_Player(i, player_mac.get(i)));
      
      z = range(len(online_players)); z.reverse() # сортируем список экземпляров плееров в обратном порядке в другой список что-бы удобнее было удалять физически отключенные
      for i in z: 
       online_players[i].print_properties()
       if (online_players[i].power == - 1): online_players.pop(i); print "^^^^^^ this player was deleted from syncro-list ^^^^^^" # удаляем плееры от котрых не получили ответ
      
      
      # подготавливаем плееры к воспроизведению нашего сообщения
      for current_player in online_players:
      
        if (current_player.mode == "play"): callRPC([current_player.mac, ['pause']])
        callRPC([current_player.mac, ['power', '1']])  
      #  callRPC([current_player.mac, ['mixer', 'volume', alert_volume]])  # на тот случай если в будущем захочется принудительно выставлять громкость на плеерах
        callRPC([current_player.mac, ['playlist', 'repeat', '0']])
        callRPC([current_player.mac, ['playlist', 'clear']])
      
        if (master_player_mac == ""):  master_player_mac = current_player.mac;  continue # запоминаем мак адрес  первого попавшегося плеера
      
        callRPC([master_player_mac, ["sync", current_player.mac]])   # назначаем  тот первый попавшийся плеер мастером для синхрогруппы
      
      # воспроизводим наше сообщение
      callRPC([master_player_mac, ['playlist', 'clear']])
      callRPC([master_player_mac, ['playlist', 'add', alert_file]])
      callRPC([master_player_mac, ['play']])
      
      # ждем пока закончится воспроизведение файла нашего сообщения 
      while True:
         answer = callRPC([current_player.mac, ["status","-"]])
         time.sleep(0.5)
         if (answer["result"]["mode"] != 'play'):  break
      
      
      # восстанавливаем настройки каждого плеера
      
      for current_player in online_players:
         callRPC([current_player.mac, ['mixer', 'volume', current_player.volume]])
         callRPC([current_player.mac, ["sync","-"]])
         callRPC([current_player.mac, ['playlist', 'clear']])
         callRPC([current_player.mac, ['playlist', 'repeat', current_player.repeat]])
         callRPC([current_player.mac, ['playlist', 'add', current_player.path]])
         callRPC([current_player.mac, ['mode', current_player.mode]])
         callRPC([current_player.mac, ['time', current_player.time]])
         callRPC([current_player.mac, ['power', current_player.power]])
      
      

      Что бы скрипт заработал в нем прописываем мак-адреса и псевдонимы плееров на которых хотим воспроизводить сообщение. А так же IP адрес и порт LMS. При первом запуске скрипт может ругаться на неустановленные питоновские пакеты, в таком случае доустанавливаем необходимые пакеты при помощи установщика пакетов pip. Далее при запуске скрипта указываем в качестве аргумента путь и имя медиафайла который хотим воспроизвести, при этом тот путь о котором знает и LMS у меня это предопределенная папка "музыка". Для запуска скрипта из среды IntraHouse это выглядит вот так при условии что скрипт называется lms_alert_player.py и находится в папке /media/:

      this.execOS(`python /media/lms_alert_player.py /media/go_eat.wav`);
      
      posted in Задачи и варианты решения
      D
      div115
    • RE: Плагин MQTT

      @intrapro
      Спасибо, - то что нужно, а я уже собирался делать виртуальные дубли устройств и их явно привязывать к каналу.

      posted in Плагины
      D
      div115