Страница 1 из 2

MAJORDOMO + VoIP

Добавлено: Пт июл 05, 2013 9:23 am
ksgroup
Имеется у меня на сервере IP АТС Asterisk. Разруливает входящие и исходящие звонки по пяти IP телефонам в доме. Решил я подружить умный дом с телефонией. И вот уже при каждом входящем звонке Алиса мне сообщает кто звонит. Понятное дело что для этого в линии должна присутствовать функция определения номера. В самом Asteriske в командах диалплана я указал вызов системной команды в которой номер звонящего передается в свойство CID объекта PHONE. В MJ создал объект PHONE со свойством CID и сценарий обрабатывающий изменение этого свойства.
Если тема интересна сообществу - опишу подробнее.

Теперь есть идея научить Алису в определенных ситуациях звонить по VoIP и сообщать нужную информацию. Для этого необходим софтфон умеющий получать команды из других программ. Кроме того этот софтфон должен работать в системе LINUX (так как у меня UBUNTU SERVER) да еще и без GUI. К сожалению на данный момент ничего такого не нашел. Возможно плохо искал. Если кто то из сообщества может подсказать какую то информацию по этому поводу буду очень рад. Возможно имеются какие то модули PHP (или других языков программирования) для работы с VoIP?

Re: MAJORDOMO + VoIP

Добавлено: Пт июл 05, 2013 11:36 am
sergejey
Отличная идея, подробности будут весьма кстати! В том числе по железу -- давно хочу организовать дома что-то вроде интеркомов с подключением телефонной сети, домофона и прочее.

Что касается "звонить" с Алисы -- а Asterisk не может прокручивать сценарии на каком-нибудь VoiceXML? Т.е. звонить сам по себе и чего-то говорить?

Re: MAJORDOMO + VoIP

Добавлено: Пт июл 05, 2013 3:08 pm
ksgroup
Да тут все просто. Создал класс 'TELEPHONIC'. В нем создал объект 'PHONE' и свойство 'CID'. Создал метод 'ring' в котором прописал код:

$this->setProperty('CID',$params['cid']);

Потом открыл объект 'PHONE' и его метод 'ring' настроил на вызов сценария "PhoneRing".

Сценарий "PhoneRing":

$cid = gg('PHONE.CID'); Получаем номер телефона из переменной.
$mes=''; Очищаем сообщение

if ($cid == '0441234567'){$mes = 'Дима звонит.';} ; Можно создать список телефонов которые Алиса будет называть по именам

//########################################################################
if ($mes == ''){
$kod = substr($cid,0,3);
$num1 = substr($cid,3,3);
$num2 = substr($cid,6,2);
$num3 = substr($cid,8,2);
$mes = 'Входящий вызов от абонента неизвесной сети с кодом '.substr($kod,0,1).' '.substr($kod,1,2).' и номером ';

if ($kod == '044'){$mes = 'Входящий вызов от абонента городской сети с номером ';}

if ($kod == '050'){$mes = 'Входящий вызов от абонента сети МТС с номером ';}
if ($kod == '095'){$mes = 'Входящий вызов от абонента сети МТС с номером ';}
if ($kod == '099'){$mes = 'Входящий вызов от абонента сети МТС с номером ';}

if ($kod == '066'){$mes = 'Входящий вызов от абонента сети ДЖИНС с номером ';}

if ($kod == '063'){$mes = 'Входящий вызов от абонента сети ЛАЙФ с номером ';}
if ($kod == '093'){$mes = 'Входящий вызов от абонента сети ЛАЙФ с номером ';}

if ($kod == '067'){$mes = 'Входящий вызов от абонента сети КИЕВСТАР с номером ';}
if ($kod == '096'){$mes = 'Входящий вызов от абонента сети КИЕВСТАР с номером ';}
if ($kod == '097'){$mes = 'Входящий вызов от абонента сети КИЕВСТАР с номером ';}
if ($kod == '098'){$mes = 'Входящий вызов от абонента сети КИЕВСТАР с номером ';}

if ($kod == '068'){$mes = 'Входящий вызов от абонента сети БИЛАЙН с номером ';}

if ($kod == '091'){$mes = 'Входящий вызов от абонента сети ЮТЕЛ с номером ';}

if ($kod == '092'){$mes = 'Входящий вызов от абонента сети ИНТЕРТЕЛЕКОМ с номером ';}

$mes = $mes.$num1.'-'.$num2.'-'.$num3;
}

say($mes); Ну и собственно тут Алиса произносит подготовленное сообщение.
sg('PHONE.cid',''); Очищаем переменную.


В Asterisk-е в плане набра входящего вызова я вписал строку:
exten => s, 1, TrySystem(/usr/bin/php /var/majordomo/objects/index.php object:PHONE op:m m:ring cid:${CALLERID(number)})


По железу:
1.У меня на систему UBUNTU установлен Asterisk 1.8. На этой же машине установлен и MajorDoMo. Читал в сети что можно установить Asterisk на Raspberry Pi, но пока не пробовал.

2. VoIP шлюз SPA-3102. Он имеет 1 FXO - к которому подключена городская телефонная линия, и 1FXS - сюда у меня подключен аналоговый DECT телефон Panasonic.

3. 4 аппарата Dynamix IP Phone E210 установлены в комнатах и подключены витой парой к роутеру.

4. GSM шлюз сделан на базе модема Huawei E1550 и программного модуля Asterisk dongle.
Домофона к сожалению пока нет, но он планируется.

Re: MAJORDOMO + VoIP

Добавлено: Пт июл 05, 2013 10:20 pm
immortal
не понял зачем софтфон, когда проще звонить астериском используя call файлы предварительно их генерировать алисой.
только генерить надо не в папке outgoing, а в любой другой, а потом перемещать в outgoing

Re: MAJORDOMO + VoIP

Добавлено: Пт июл 05, 2013 10:31 pm
ksgroup
Да вся проблема в том что я Asterisk совершенно не знаю. Но спасибо за подсказку! Погуглю на тему call файлов.

Re: MAJORDOMO + VoIP

Добавлено: Пт дек 20, 2013 4:51 pm
Alien
Создание телефонного справочника для телефонов cisco 7940:
Создать сценарий createDxml и запускать его каждый час.
Код:

$xmlfile = "/var/www/asterisk/directory.xml"; // файл, на который указано в настройках телефона
$ufile = "/etc/asterisk/users.conf"; // конфигурационный файл asterisk.
$title = "Phonebook"; // Название меню
$prompt = "Select the User"; //Строка подписи

if (is_readable($ufile)) { //Проверяем конф на доступность
if ($conf = parse_ini_file ($ufile,true)) {
$dxf = fopen ($xmlfile, "w"); //Создаем xml файл телефонного справочника
fwrite ($dxf,"<CiscoIPPhoneDirectory>\n");
fwrite ($dxf,"<Title>$title</Title>\n");
fwrite ($dxf,"<Prompt>$prompt</Prompt>\n");
foreach ($conf as $array) { //Перебираем массив и добавляем все вхождения в xml
$name = $array["fullname"];
$num = $array["cid_number"];
if ($num) {
fwrite ($dxf,"<DirectoryEntry>\n");
fwrite ($dxf,"\t<Name>$name</Name>\n");
fwrite ($dxf,"\t<Telephone>$num</Telephone>\n");
fwrite ($dxf,"</DirectoryEntry>\n");
};
};
fwrite ($dxf,"</CiscoIPPhoneDirectory>\n");
};
};

fclose($dxf);

У такого способа есть два минуса.
Первый - безопасность. Для парсинга номеров нужно дать права на чтение /etc/asterisk/users.conf
всем пользователям, что не есть гуд. При желании злоумышленник вытянет заодно и пароли sip.
Решается просто - ложим этот скрипт в папку scripts. Называем его createDxml.php
Затем настраиваем cron на запуск каждый час от имени asterisk:
sudo crontab -e -u asterisk
В самом низу добавляем строку запуска каждый час:
0 * * * * /var/www/scripts/createDxml.php
После строки не забываем добавлять одну пустую - это знак крону что файл закончен.


Второй недостаток данного метода - ограничение телефона на 31 запись в xml.
Для дома может быть и достаточно, тогда можно оставить как есть.
Если телефонный справочник больше, то нужно организовать поиск.
В настройках телефона указываем путь не к directory.xml, а directory.php.
Создаем в /var/www/asterisk/directory.php
В файле нужно проставить IP-адрес сервера.
Код:

#!/usr/bin/php
<?php
$URLPHP="http://IP АДРЕС СЕРВЕРА/asterisk/directory.php";
$URLXML="http://IP АДРЕС СЕРВЕРА/asterisk/directory.xml";
$title = "Phonebook";
switch ($_GET[op]) {
case '':
echo "<CiscoIPPhoneInput>\n";
echo "<Title>$title</Title>\n";
echo "<Prompt>Please Enter User Last Name</Prompt>\n";
echo "<URL>$URLPHP?op=search</URL>\n";
echo "<InputItem>\n";
echo "<DisplayName>Last Name</DisplayName>\n";
echo "<QueryStringParam>lastname</QueryStringParam>\n";
echo "<DefaultValue />\n";
echo "<InputFlags>A</InputFlags>\n";
echo "</InputItem>\n";
echo "<InputItem>\n";
echo "<DisplayName>Number</DisplayName>\n";
echo "<QueryStringParam>number</QueryStringParam>\n";
echo "<DefaultValue />\n";
echo "<InputFlags>N</InputFlags>\n";
echo "</InputItem>\n";
echo "</CiscoIPPhoneInput>\n";
break;

case 'search':
$user = simplexml_load_file ($URLXML);
echo "<CiscoIPPhoneDirectory>\n";
echo "<Title>$title</Title>\n";
echo "<Prompt>Select the User</Prompt>\n";
foreach ($user->DirectoryEntry as $entry) {
if ($_GET[lastname]) {
if (preg_match("/".mb_strtolower($_GET[lastname])."/", mb_strtolower($entry->Name))) {
echo "<DirectoryEntry>\n";
echo "<Name>$entry->Name</Name>\n";
echo "<Telephone>$entry->Telephone</Telephone>\n";
echo "</DirectoryEntry>\n";
};
} else {
if (preg_match("/".$_GET[number]."/", $entry->Telephone)) {
echo "<DirectoryEntry>\n";
echo "<Name>$entry->Name</Name>\n";
echo "<Telephone>$entry->Telephone</Telephone>\n";
echo "</DirectoryEntry>\n";
};
};
};
echo "</CiscoIPPhoneDirectory>\n";
break;
}
?>

Re: MAJORDOMO + VoIP

Добавлено: Пт дек 27, 2013 4:50 pm
Alien
По call файлам можно в systemStates stateChanged добавить код для дозвона. Как пример Security.stateChanged

if (gg("Security.stateColor") == "red") {
$calltmp = "/var/spool/asterisk/tmp/security_red.call";
$calldir = "/var/spool/asterisk/outgoing/security_red.call";
$callnumber = "SIP/200"; //Указываем внутренний на который звонить. Или внешний через донгл: Dongle/dongle0/holdother:0505555555
$dirmessage = "/var/www/cached/voice/";
$message = (md5("Статус системы безопасности изменился на ".gg("Security.stateTitle").". ".implode(". ",gg("Security.stateDetails"))));
$callfile = fopen ($calltmp, "w");
fwrite ($callfile,"Channel: $callnumber\n");
fwrite ($callfile,"Callerid: 299\n");
fwrite ($callfile,"MaxRetries: 2\n");
fwrite ($callfile,"RetryTime: 60\n");
fwrite ($callfile,"WaitTime: 60\n");
fwrite ($callfile,"Context: majordomo\n");
fwrite ($callfile,"Extension: s\n");
fwrite ($callfile,"Priority: 1\n");
fwrite ($callfile,"Set: playfile=$dirmessage$message\n");
fwrite ($callfile,"Archive: Yes\n");
fclose($callfile);
copy ($calltmp,$calldir);
};
Астериск дозванивается по указанному номеру и сообщает статус и ошибку из голосового кеша Алисы.

Re: MAJORDOMO + VoIP

Добавлено: Пт дек 27, 2013 6:49 pm
ksgroup
Alien писал(а):По call файлам можно в systemStates stateChanged добавить код для дозвона. Как пример Security.stateChanged

if (gg("Security.stateColor") == "red") {
$calltmp = "/var/spool/asterisk/tmp/security_red.call";
$calldir = "/var/spool/asterisk/outgoing/security_red.call";
$callnumber = "SIP/200"; //Указываем внутренний на который звонить. Или внешний через донгл: Dongle/dongle0/holdother:0505555555
$dirmessage = "/var/www/cached/voice/";
$message = (md5("Статус системы безопасности изменился на ".gg("Security.stateTitle").". ".implode(". ",gg("Security.stateDetails"))));
$callfile = fopen ($calltmp, "w");
fwrite ($callfile,"Channel: $callnumber\n");
fwrite ($callfile,"Callerid: 299\n");
fwrite ($callfile,"MaxRetries: 2\n");
fwrite ($callfile,"RetryTime: 60\n");
fwrite ($callfile,"WaitTime: 60\n");
fwrite ($callfile,"Context: majordomo\n");
fwrite ($callfile,"Extension: s\n");
fwrite ($callfile,"Priority: 1\n");
fwrite ($callfile,"Set: playfile=$dirmessage$message\n");
fwrite ($callfile,"Archive: Yes\n");
fclose($callfile);
copy ($calltmp,$calldir);
};
Астериск дозванивается по указанному номеру и сообщает статус и ошибку из голосового кеша Алисы.
А вот что при этом должно быть в контексте "majordomo" в экстеншне "s"?
Мне так и не удалось добиться проигрывания файла.

Re: MAJORDOMO + VoIP

Добавлено: Пт дек 27, 2013 8:53 pm
Alien
Ну, варианты по проигрыванию у меня были такие:
1. wav файл - астериск играет именно их. Звук я формирую фестивалем, как в примерах было, с нюансом битрейта в 8000:

echo "$1" | text2wave -F 8000 -o /var/www/cached/voice/"$2" -eval "(voice_msu_ru_nsh_clunits)"
aplay /var/www/cached/voice/"$2" > /dev/null 2>&1

2. Имя файла это хеш md5 от произносимой фразы, астериску расширение указывать не нужно. Если Алиса говорит через гугл, то нужно еще предварительно запустить mpg123 для перекодировки из mp3 в wav.

Вот контекст астериска для дозвона:
[majordomo]
exten => s,1,Answer
exten => s,n,Wait(1)
exten => s,n,Playback(${playfile})
exten => s,n,hangup

Ну а вообще нужно посмотреть что астериск в лог выдает: asterisk -rv.

Re: MAJORDOMO + VoIP

Добавлено: Сб дек 28, 2013 5:15 pm
ksgroup
Alien писал(а):Ну, варианты по проигрыванию у меня были такие:
1. wav файл - астериск играет именно их. Звук я формирую фестивалем, как в примерах было, с нюансом битрейта в 8000:

echo "$1" | text2wave -F 8000 -o /var/www/cached/voice/"$2" -eval "(voice_msu_ru_nsh_clunits)"
aplay /var/www/cached/voice/"$2" > /dev/null 2>&1

2. Имя файла это хеш md5 от произносимой фразы, астериску расширение указывать не нужно. Если Алиса говорит через гугл, то нужно еще предварительно запустить mpg123 для перекодировки из mp3 в wav.

Вот контекст астериска для дозвона:
[majordomo]
exten => s,1,Answer
exten => s,n,Wait(1)
exten => s,n,Playback(${playfile})
exten => s,n,hangup

Ну а вообще нужно посмотреть что астериск в лог выдает: asterisk -rv.
Вот теперь все заработало. Спасибо.

Вижу что у вас достаточно знаний об Астериске, поэтому хочу задать вопрос. Вот у меня есть несколько внутренних номеров в Астериксе, но парочку из них удаленные, которые подключены через интернет. Так уж сложилось что они подключены не всегда, а только тогда когда удаленный аппарат включен (ну есть такая необходимость что бы он был включен не всегда.) Очень хотелось бы как то из МДМ иметь возможность видеть в реальном времени включен ли удаленный SIP аппарат. К сожалению на удаленном конце динамические IP поэтому простым пингом тут не отделаться. Хотелось бы как то получать инфу от астериска о подключенных в данный момент аппаратах.