IVR меню для Умного Дома, удаленное управление без Internet (на примере MajorDoMo и FreeSWITCH)

от автора

Небольшое решение по организации нового способа удаленного контроля и управления и системы домашней автоматизации с помощью SIP телефонии (в частности IVR меню).
IVR (англ. Interactive Voice Response), интерактивное голосовое меню — система предварительно записанных голосовых сообщений, выполняющая функцию маршрутизации звонков внутри АТС с использованием информации, вводимой клиентом на клавиатуре телефона с помощью тонального набора.).
Управление не такое удобное, как управление посредством Web-интерфейса или приложениями, и несколько необычное. Однако это способ управления не зависит ни от работоспособности как отдельных сервисов (облачные решения, VPN/VPS, Telegram и т.д.), так и от наличия вообще доступа к Internet или самого «Умного Дома» или устройства для управления (обычно смартфона). Думаю, этот способ возможно рассматривать в случае необходимости при разного рода пропаданиях доступа к УД, как резервный.
Для решения использовался одноплатный компьютер Raspberry Pi 3b и VoIP GSM шлюз Yestar TG-01. Программная часть: система домашней автоматизации MajorDoMo и SIP сервер FreeSWITCH.

Постановка задачи

Начнем с постановки задачи: требуется, при отсутствии или используемого для удаленного управления сервиса УД или канала к Интернету, обеспечить удаленный контроль и управление работой «Умного дома» наиболее важных устройств.
Алгоритм работы: при отсутствии стандартного сервиса связи (или вообще доступа к Intertnet) для управления или контроля, осуществляем голосовой вызов в наш Умный Дом, через GSM сеть мобильного оператора, далее срабатывает IVR меню с голосовым приветствием и возможностью выбора действий. Упрощенный пример: при нажатии на клавиатуре смартфона цифры 1 – переходим в подменю контроля «Умного Дома», при нажатии цифры 2 — в подменю управления. В меню контроля при нажатии цифры 0 – узнаём состояние всей системы, при нажатии цифры 1 – состояние определенного устройства к примере реле, при нажатии 2 – другого устройства (какого либо датчика) и т.д., при нажатии * — выход на раздел выше.
В меню управления – при нажатии 1 включаем устройство (к примеру реле), при нажатии цифры 0 – выключаем, при нажатии * — выход на раздел выше.

Подготовка системы домашней автоматизации MajorDoMo к удаленному контролю и управлению через IVR меню.

Для записи и преобразования текстовой информации в голосовой файл я буду использовать синтезатор речи TTS (в комплекте с MajorDoMo установлен сервис RHVoice). Конфигурационный файл по умолчанию располагается в /usr/local/etc/RHVoice/RHVoice.conf или /etc/RHVoice/RHVoice.conf. Отредактировав файл, можем изменить голос, скорость и т.д.
Создадим директорию для голосовых звуков нашего Умного Дома, в которой будем записывать аудио файлы в формате *.wav:

sudo -u www-data mkdir /var/www/html/smathome_IVR_sounds

Первая задача – получить звуковой файл об общем состояние о системе домашней автоматизации.
По умолчанию в MajorDoMo имеется ряд встроенных сценариев. Посмотреть их можно, перейдя в Панель управления- Объекты – Сценарии.
Откроем сценарий reportStatus.
image
Он проверяет работу всей системы и её компонентов. К примеру, наличие или отсутствие доступа к сети Internet, сетевым устройствам, критичных аварий (авария датчика протечки, газа и прочее), наличие системных устройств и т.д.
Изменим (или создадим новый сценарий, полностью скопировав код существующего) и добавим строчку в самом конце кода, аудиофайл текстовой информации в аудиофайл.

shell_exec ('echo "'.$res.'" | RHVoice-test -p anna -o /var/www/html/smathome_IVR_sounds/IVR_report_status.wav'); 

Внизу страницы есть небольшая подсказка, как его можно запустить, обратим на это внимание, запуск по ссылке нам понадобится в дальнейшем: 192.168.1.128/objects/?script=reportStatus
Примеры ответа работы этого сценария (в первом варианте – когда всё работает, второй вариант – примеры с аварийными сообщениями от УД):

Все системы работают в штатном режиме.

Системная проблема: Тестовый замок двери не обновляется
Проблема связи: Нет доступа в Интернет.
Внимание! Сигнал тревоги от датчика: Протечка расположенный в комнате Кухня.

Сделаем ещё несколько сценариев, для контроля работы устройств УД назвав их Ivr_state_OpenClose01 и Ivr_state_rele01. В первом сценарии мы будем записывать аудио файл с информацией о состоянии датчика открытия/закрытия, во втором о состоянии управляемого реле.

Пример сценария состояния датчика

open=gg("Openclose01.status"); echo $open; if ($open==1) shell_exec ('echo "Тестовый датчик замка двери закрыт" | RHVoice-test -p anna -o /var/www/html/smathome_IVR_sounds/IVR_check_status_openclose01.wav'); else  shell_exec ('echo "Тестовый датчик замка двери открыт, не забудьте закрыть замок" | RHVoice-test -p anna -o /var/www/html/smathome_IVR_sounds/IVR_check_status_openclose01.wav');

Пример сценария состояния реле

$rele1=gg("Switch1.status"); echo $rele1; if ($rele1==0) shell_exec ('echo "Реле выключено" | RHVoice-test -p anna -o /var/www/html/smathome_IVR_sounds/IVR_state_rele01.wav'); else  shell_exec ('echo " Реле включено " | RHVoice-test -p anna -o /var/www/html/smathome_IVR_sounds/IVR_state_rele01.wav'); 

Точно так же, как в первом сценарии, при выполнении этих сценариев, создаются файлы IVR_check_status_openclose01.wav и IVR_state_rele01.wav, при последующих запусках сценария – файлы полностью перезаписываются. Запуск любого сценария в MajorDoMo возможен по ссылке.
Управление устройствами в MajorDoMo, тоже реализовано довольно просто: у каждого устройства есть методы и свойства, перейдя в Панель Управления – Объекты — Методы можем увидеть применяемые методы для конкретного устройства. Для удаленного управления наиболее часто используется простое включение / выключение объекта (методы turnOn, turnOff).
image

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

Установка сервера Freeswitch

Наиболее быстрый и простой способ установки – установка из репозитория. Подробная описание есть на сайте FS. Для установки требуется регистрация и Token из личного кабинета на сайте разработчика FreeSWITCH Signalware.
Ссылка на официальную документацию по установке FreeSWITCH на Raspberry Pi
Все действия выполняются от sudo.

Установка FreeSWITCH из репозитория

 sudo -i TOKEN=YOURSIGNALWIRETOKEN  apt-get update && apt-get install -y gnupg2 wget lsb-release apt-transport-https wget --http-user=signalwire --http-password=$TOKEN -O /usr/share/keyrings/signalwire-freeswitch-repo.gpg https://freeswitch.signalwire.com/repo/deb/rpi/debian-release/signalwire-freeswitch-repo.gpg  echo "machine freeswitch.signalwire.com login signalwire password $TOKEN" > /etc/apt/auth.conf chmod 600 /etc/apt/auth.conf  echo "deb [signed-by=/usr/share/keyrings/signalwire-freeswitch-repo.gpg] https://freeswitch.signalwire.com/repo/deb/rpi/debian-release/ `lsb_release -sc` main" > /etc/apt/sources.list.d/freeswitch.list echo "deb-src [signed-by=/usr/share/keyrings/signalwire-freeswitch-repo.gpg] https://freeswitch.signalwire.com/repo/deb/rpi/debian-release/ `lsb_release -sc` main" >> /etc/apt/sources.list.d/freeswitch.list apt-get update && apt-get install -y freeswitch-meta-all 

Также возможна сборка из исходных кодов (в этом случае Token можно не использовать), но процесс сборки более сложный и занимает несколько длительное время.

*** Внимание! сборка и установка из репозитория – для архитектуры ARM (Raspberry Pi и других одноплатных компьютеров у меня осуществилась успешно на ОС на базе Debian 11. На Debian 10 и 12 — нормального результата мне не удалось добиться.

Пути к файлам при установке из репозитория и сборке из исходных кодов различаются. В этой публикации указаны пути при установке из репозитория.
После установки SIP сервера, требуется незначительная подстройка для работоспособности SIP сервера FreeSWITCH из «коробки». Резервные файлы конфигурации по умолчанию — /usr/share/freeswitch/conf/vanilla в директории conf также хранятся и несколько других конфигураций.
Файлы текущей конфигурации находятся в директории /etc/freeswitch/.
FreeSwitch имеет модульную структуру, подключаемые модули можно посмотреть в файле modules.conf.xml. Отредактируем этот файл, подключаем mod_xml_rpc, включающий поддержку WEB API, удалив символы комментария в этой строке с. Также подключаем голосовой модуль русского языка и отключаем английский.

sudo nano /etc/freeswitch/autoload_configs/modules.conf.xml

<!-- XML Interfaces --> <load module="mod_xml_rpc"/>   <!-- Say --> <!--    <load module="mod_say_en"/> --> <load module="mod_say_ru"/>

В файле настройки модуля xml_rpc.con.xml укажем свободный порт, на котором будет работать этот модуль. Порт по умолчанию 8080, часто бывает занят разными сервисами (у меня это сервис zigbee2mqtt, установим свободный, к примеру порт 9090, />, так же можно сменить пароль и пользователя по умолчанию ( указан freeswitch, works).

sudo nano /etc/freeswitch/autoload_configs/xml_rpc.conf.xml

Отредактируем файл c глобальными переменными SIP сервера: vars.xml

sudo nano /etc/freeswitch/vars.xml

Изменим пароль по умолчанию с 1234, к примеру на 1111 (устраняем задержку в 10 секунд при наборе номера), укажем правильную директорию для голосовых файлов, изменим профиль с external на internal, так же поменяем страну и международный код установленные по умолчанию. Приведём строки к следующему виду:

Изменения в файле профиля vars.xml

<X-PRE-PROCESS cmd="set" data="default_password=1111"/> <X-PRE-PROCESS cmd="set" data="sound_prefix=$${sounds_dir}/ru/RU/vika"/> <X-PRE-PROCESS cmd="set" data="use_profile=internal"/> <X-PRE-PROCESS cmd="set" data="default_areacode=375"/> <X-PRE-PROCESS cmd="set" data="default_country=BY"/>

Перейдём к файлу sip профилей. Я буду использовать профиль internal (внутренний). В секции gateways добавим возможность чтения *.xml файлов из директории internal (которую нужно будет потом создать) и выставим параметры ext-rtp-ip и ext-sip-ip. Заменим значение NAT сервера или на IP адрес нашего SIP сервера FreeSWITCH в локальной сети или используем функцию auto-nat. Откорректируем следующие строки:
sudo nano /etc/freeswitch/sip_profiles/internal.xml

Изменения в файле профиля internal.xml

 <gateways> <X-PRE-PROCESS cmd="include" data="internal/*.xml"/>   </gateways> ...    <param name="ext-rtp-ip" value="auto-nat"/>     <param name="ext-sip-ip" value="auto-nat"/> 

Создаём директорию для SIP профилей:

sudo -u freeswitch mkdir /etc/freeswitch/sip_profiles/internal 

Ещё исправим одну строку с указанием неправильной директории звуковых файлов (которые находятся /usr/share/freeswitch/lang/ru/ru.xml) в файле языковых настроек: приводя строку к виду:

sudo nano /etc/freeswitch/lang/ru/ru.xml  

 <language name="ru" sound-prefix="$${sounds_dir}/ru/RU/vika" tts-engine="cepstral" tts-voice="elena">

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

 sudo systemctl restart freeswitch.service 

Можно подключить SIP клиент (На ПК я обычно использую MicroSIP или PhonerLite, на смартфоне Linphone и MizuDroid) и произвести тестовые наборы основных функций АТС в локальной сети.
Выполнив тестовый набор на номер 5000 услышим IVR меню по умолчанию. «Добро пожаловать в Freeswitch будущее голосовой телефонии….»

Настройка IVR меню для Умного Дома

Сделаем своё голосовое меню IVR: по набору номера 5002 должны попасть в диалог со своим УД.
Создадим звуковые файлы для нашего IVR меню. Вариантов действий довольно много, можно использовать стандартные голосовые файлы FreesWitch, расположенные в директории /usr/share/freeswitch/lang/ru/ и из них собирать фразы (phrases), можно найти необходимые в Интернет, можно записать с помощью микрофона. Опять используем синтезатор речи TTS RHVoice, и по аналогии создания звуковых файлов в системе домашней автоматизации, создадим файлы для IVR меню.
Создадим директорию в домашней папке и запишем фразы в звуковые файлы:

Создание звуковых файлов для IVR меню

mkdir /home/pi/my_smarthome_ivr

echo "Привет. Что будем делать. Чтоб войти в меню контроля нажмите цифру один. Чтоб войти в меню управления нажмите цифру два. " | RHVoice-test -p anna -o /home/pi/my_smarthome_ivr/privet.wav
echo "Вы в меню контроля. Узнать общее состояние системы нажмите ноль. Узнать состояние реле нажмите цифру один. Узнать состояние датчика замка нажмите два" | RHVoice-test -p anna -o /home/pi/my_smarthome_ivr/control.wav
echo "Вы в меню управления. Включить реле – нажмите цифру один. Выключить реле нажмите цифру ноль " | RHVoice-test -p anna -o /home/pi/my_smarthome_ivr/management.wav
echo "Чтоб войти в меню управления нажмите цифру два " | RHVoice-test -p anna -o /home/pi/my_smarthome_ivr/dva.wav

Перейдём к диалплану (номерной план, dialplan) — формальное описание схемы маршрутизации и обработки телефонных звонков. Номерной план подробно описывает, что система должна делать со входящими и исходящими звонками: передавать их дальше, сохранять, отвечать на них самостоятельно и так далее. Основные настройки по умолчанию, находятся в общем файле default.xml однако будем для каждого направления создавать свой отдельный файл в директории /etc/freeswitch/dialplan/default/
В самом конце файла default.xml добавим строчку

<X-PRE-PROCESS cmd="include" data="default/*.xml"/>

Создадим следующий диалплан (назначим каждому номеру своё действие):
5002 – вход в общее IVR меню
Для контроля: 5010 – получение общего статуса системы, 5011 – получение статуса датчика, 5012 – получение статуса реле.
Для управления: выключить реле – 5020 включить — 5021.
Для номера 5002 создадим файл, который переадресовывает абонента для входа в главное IVR меню (запускает приложение IVR с названием my_smarthome_ivr).

Направление 5002 — запуск главного IVR меню

sudo -u freeswitch nano /etc/freeswitch/dialplan/default/my_smarthome_ivr.xml

 <extension name="my_smarthome_ivr">       <condition field="destination_number" expression="^5002$">         <action application="answer"/>         <action application="sleep" data="2000"/>         <action application="ivr" data="my_smarthome_ivr"/>       </condition>     </extension>

Создаём следующий xml файл для направления 5010 (получение общего статуса системы домашней автоматизации):

Направление 5010 — получение статуса системы

sudo -u freeswitch nano /etc/freeswitch/dialplan/default/ivr_report_status.xml

<extension name=" ivr_report_status.">       <condition field="destination_number" expression="^5010$"> <action application="system" data="curl  http://192.168.1.128/objects/?script=reportStatus"/> <action application="sleep" data="5000"/>         <action application="answer"/>         <action application="sleep" data="2000"/> <action application="playback" data="/var/www/html/smathome_IVR_sounds/IVR_report_status.wav"/> <action application="sleep" data="2000"/> <action application="transfer" data="5002"/> <!--        <action application="hangup"/> -->       </condition>     </extension>

Алгоритм следующий: при наборе номера 5010 отрабатывает скрипт, который создали в системе домашней автоматизации, для получения статуса системы, ждём его выполнения и формирования звукового файла, проигрывание статуса системы и возврат в главное IVR меню (переадресация на номер 5002). Закомментирована строка с действием отбоя (на случай если нам не нужно возвращаться в главное меню).
Таким же образом создадим и другие действия, как информирование о статусе элементов системы, так и управления устройствами. Для примеру приведу получение текущего состояния устройства и управление реле на выключение:

Примеры файлов диалплана для направлений 5012 (статус реле), 5020 (выключение реле)

sudo -u freeswitch nano /etc/freeswitch/dialplan/default/IVR_state_rele01.xml

<extension name="IVR_state_rele01"> <condition field="destination_number" expression="^5012$"> <action application="system" data="curl 'http://192.168.1.128/objects/?script=IVR_state_rele01'"/>         <action application="sleep" data="2000"/> <action application="playback" data="/var/www/html/smathome_IVR_sounds/IVR_state_rele01.wav"/> <action application="sleep" data="2000"/> <action application="transfer" data="5002"/> <!--        <action application="hangup"/> -->       </condition>
sudo -u freeswitch nano /etc/freeswitch/dialplan/default/ivr_rele01_turnOff

 <<extension name="ivr_rele01_turnOff">       <condition field="destination_number" expression="^5020$"> <action application="system" data="curl  'http://192.168.1.128/objects/?object=Switch1&op=m&m=turnOff'"/> <action application="sleep" data="2000"/>         <action application="answer"/> <action application="system" data="curl 'http://192.168.1.128/objects/?script=IVR_state_rele01'"/>         <action application="sleep" data="2000"/> <action application="playback" data="/var/www/html/smathome_IVR_sounds/IVR_state_rele01.wav"/> <action application="sleep" data="2000"/> <action application="transfer" data="5002"/> <!--        <action application="hangup"/> -->       </condition>     </extension> 

Перейдём сейчас к созданию главного IVR меню для Умного Дома.
Уже в директории для файлов IVR меню /etc/freeswitch/ivr_menus/ создаём файл с содержимым описывающим главное IVR меню:

Main IVR Menu

sudo nano /etc/freeswitch/ivr_menus/my_smarthome_ivr.xml

 <include>   <!-- my_smarthome_ivr setup -->   <!-- my_smarthome_ivr, Main Menu -->   <menu name="my_smarthome_ivr" greet-long="/home/pi/my_smarthome_ivr/privet.wav" greet-short=="/home/pi/my_smarthome_ivr/privet.wav"       invalid-sound="ivr/ivr-that_was_an_invalid_entry.wav"       exit-sound="voicemail/vm-goodbye.wav"       confirm-macro=""       confirm-key=""       tts-engine="flite"       tts-voice="rms"       confirm-attempts="3"       timeout="10000"       inter-digit-timeout="2000"       max-failures="3"       max-timeouts="3"       digit-len="4">      <!-- The following are the definitions for the digits the user dials -->     <!-- Digit 1 transfer caller to menu control -->     <entry action="menu-sub" digits="1" param="control_ivr_submenu"/>     <entry action="menu-sub" digits="2" param="management_ivr_submenu"/>     <entry action="menu-top" digits="9"/>          <!-- Repeat this menu -->   </menu>  <!-- Control IVR Sub Menu -->   <menu name="control_ivr_submenu"       greet-long="/home/pi/my_smarthome_ivr/control.wav"       greet-short="/home/pi/my_smarthome_ivr/control.wav"       invalid-sound="ivr/ivr-that_was_an_invalid_entry.wav"       exit-sound="voicemail/vm-goodbye.wav"       timeout="15000"       max-failures="3"       max-timeouts="3">  <entry action="menu-exec-app" digits="0" param="transfer 5010 XML default"/>    <!-- System status MajorDoMo -->     <entry action="menu-exec-app" digits="1" param="transfer 5011 XML default"/>    <!-- status OpenClose01 -->     <entry action="menu-exec-app" digits="2" param="transfer 5012 XML default"/>    <!-- status Switch_Rele -->     <entry action="menu-top" digits="9"/>          <!-- Repeat this menu -->     <entry action="menu-top" digits="*"/>           <!-- Return main menu --> </menu>  <!-- management IVR Sub Menu -->   <menu name="management_ivr_submenu"       greet-long="/home/pi/my_smarthome_ivr/management.wav"       greet-short="/home/pi/my_smarthome_ivr/management.wav"       invalid-sound="ivr/ivr-that_was_an_invalid_entry.wav"       exit-sound="voicemail/vm-goodbye.wav"       timeout="15000"       max-failures="3"       max-timeouts="3">      <entry action="menu-exec-app" digits="0" param="transfer 5020 XML default"/>    <!--  Rele1 TurnOff -->     <entry action="menu-exec-app" digits="1" param="transfer 5021 XML default"/>    <!-- Rele1 TurnOff -->     <entry action="menu-top" digits="9"/>          <!-- Repeat this menu -->     <entry action="menu-top" digits="*"/>           <!-- Return main menu -->    </menu> </include> 

В этом файле описаны действия для главного (Main menu IVR) и двух подменю контроля и управления.

Подключение FreeSWITCH и MajorDoMo к мобильной сети

Для стыковки локальной сети Умного Дома с мобильной сетью, я использовал VoIP GSM шлюз Yestar TG-01 (предназначенный для перевода голосового трафика между сетями традиционной телефонии и сетями передачи данных).
По умолчанию на шлюзе имеется 2 Sip аккаунта. Для примера буду использовать один из них с именем 20001 и паролем на подключение pincode20001, никаких настроек менять (кроме назначения IP адреса) в нём не пришлось.
Первым делом подкорректируем настройки ACL SIP сервера Freeswitch. Разрешим подключение не только IP телефонов, но и других устройств. Добавляем в секции gateway разрешение на подключение устройств (шлюзов) из своей локальной сети, по умолчанию подключение запрещено, сделано исключение для своей домашней сети:

<list name="domains" default="deny">  <node type="allow" cidr="192.168.1.0/24"/>

Создадим файл, который отвечают за входящую GSM шлюза с freeswitch сервером. В файле from_GSM.xml все входящие звонки, поступающие от шлюза запускают новое IVR меню.
sudo -u freeswitch nano /etc/freeswitch/dialplan/default/from_GSM.xml

содержимое файла диалплана from_GSM.xml

<include> <extension name="call from GSM"> <condition field="destination_number" expression="^20001$">  <action application="answer"/>  <action application="sleep" data="800"/> <action application="set" data="transfer_ringback=$${ru-ring}"/>  <action application="ivr" data="from_GSM_ivr"/>     </condition> </extension> </include> 

Далее создаём файл IVR меню, специально для внешних (с телефонной сети общего пользования вызовов ТСОП) вызовов.

Содержимое IVR меню для ТСОП

<include>   <!-- from_GSM_ivr.xml -->   <!-- from_GSM_ivr, Main Menu -->   <menu name="from_GSM_ivr" greet-long="ivr/ivr-please_state_your_name_and_reason_for_calling.wav" greet-short=="ivr/ivr-please_state_your_name_and_reason_for_calling.wav"       invalid-sound="ivr/ivr-that_was_an_invalid_entry.wav"       exit-sound="voicemail/vm-goodbye.wav"       confirm-macro=""       confirm-key=""       tts-engine="flite"       tts-voice="rms"       confirm-attempts="3"       timeout="10000"       inter-digit-timeout="2000"       max-failures="3"       max-timeouts="3"       digit-len="4">    <entry action="menu-exec-app" digits="/^(1234)$/" param="transfer 5002 XML default"/>  <!-- Check PIN and transfer to main IVR menu --> </menu> </include> 

В этом IVR есть всего одна строка действия — требуется ввод символов 1234 для входа в основное меню. Я установил небольшую защиту (заглушку) от доступа посторонних. Попав на мобильный номер GSM шлюза слышим «приветствие» — «Пожалуйста назовите ваше имя и цель вашего звонка». Файл в этом случае, я брал из стандартных звуковых файлов FreeSWITCH. Идёт 3 раза повтор этого сообщения и после отбой. Также даётся 3 попытки ввода символов.
Перегружаем сервис freeswitch:

 sudo systemctl restart freeswitch.service

Пробуем позвонить на номер GSM шлюза, вначале запускается IVR меню на вход (проверка PIN), при правильном наборе попадаем в главное IVR и далее можем управлять и контролировать устройствами своего «Умного Дома».

На этом все, большое спасибо что прочитали, если у вас есть вопросы и замечания буду рад ответить в комментариях.
В качестве основного средства управлением УД, этот способ неудобен, а вот в качестве резервного (особенно в текущих реалиях) вполне может кому-нибудь пригодится.


ссылка на оригинал статьи https://habr.com/ru/articles/847806/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *