- PVSM.RU - https://www.pvsm.ru -
На какие вопросы вы найдёте ответы в этой статье:
На какие вопросы вы не найдёте ответов:
Все понимают механизм сервиса, аналогичного «Кто звонил?»: по недоступности звонок уходит на специальный номер, там его принимают, сообщают звонящему, что абонент недоступен, и отправляют абоненту СМС с информацией о звонке. В приёме звонка с Мультифона на Астериске никаких тонкостей нет.
register => 79xxxxxxxxx@multifon.ru:<password>:79xxxxxxxxx@sbc.megafon.ru/79xxxxxxxxx
Транк:
[multifon](!)
type=peer
insecure=port,invite
host=sbc.megafon.ru
fromdomain=multifon.ru
context=from_multifon
dtmfmode=inband
[multifon-in](multifon)
; Если мы ещё и звонить хотим
[multifon-out](multifon)
defaultuser=79xxxxxxxxx
fromuser=79xxxxxxxxx
secret=<password>
Первый вопрос, который встал передо мной в полный рост…
Самый простой путь, конечно же, купить человеческий HTTP API у какого-нибудь гейта и задёшево отправлять через него. Но во-первых, это неспротивно. А во-вторых, у меня на тарифе несколько сотен СМС включено в абонплату, и с телефона я их почти не отправляю.
Перепробовав все возможные варианты с MessageSend [1] (и через диалплан, и через АМИ, и через чёрта лысого), а также помурыжив SipSak [2], я сдался и попробовал скрипт для Yate [3].
О чудо! СМС через Мультифон отправляются.
Но Yate – слишком тяжеловесный движок, подумал я. Yate должен крутиться демоном и требует совершенно избыточной для этих задач конфигурации, подумал я. Поэтому, изучив перловый скрипт, я вычленил из него главное и вернулся к сипсаку. Главным оказался набор нестандартных заголовков (включая обязательного совершенно определённого юзер-агента, ага):
User-Agent: MCPC-MG-1-0-34-3490/2.0.0.5301
X-Movial-Content: sms/text
X-Movial-DeliveryReport: true
Content-Type: text/plain; charset=ISO-10646-UCS-2
Кстати, кастомный юзер-агент, насколько я понимаю, изначально полностью исключал возможность отправки через Астериск.
На первый взгляд, всё казалось просто. Но сообщения всё равно не уходили. Включив дебаг у сипсака, я понял, что эта скотина имеет набор предопределённых заголовков, которые тупо дублируются, если заданы в командной строке. Пришлось брать в руки напильник.
Обработав сипсак так, чтобы кастомные заголовки он считал приоритетными, а дубли отбрасывал, я добился наконец первого результата. Но моя радость была бы неполной, если бы сипсак корректно кодировал передаваемое сообщение. Расписывать всю эпопею вкостыливания в код, построенный на нуль-терминированных строках, UCS2-BE я не буду, сразу представлю на ваш суд результаты своих трудов: https://github.com/wolandtel/sipsak [4]. Сам процесс отправки СМС я обернул в удобный скрипт [5]. Для комплекта в последнем репозитории есть скрипт settings.sh, который упрощает настройку пароля и маршрутизации (SIP, GSM+SIP, GSM) на мультифоне.
Ну, вот, отправлять СМС мы умеем. Теперь можно настроить сам…
Здесь нам поможет AGI [6]. Скажу сразу, что от природной лени протокол AGI реализовывать я не стал, а лишь сделал в скрипте такую эмуляцию, которая позволяет выполнить задачу. А именно, скрипт должен дождаться от астериска ответа на команду STREAM FILE, чтобы проигрывание не закончилось раньше времени.
; autoresponder
exten => 79xxxxxxxxx,1,NoOp
same => n,AGI(notify.agi)
same => n,Set(MSG="Абонент умер. Когда воскреснет, может перезвонить. Но хотите ли Вы этого?")
same => n,Answer
; Params: speaker, emotion, robot
; speaker: [мужские]: zahar, ermil; [женские]: jane, omazh.
; emotion: good, neutral, evil, mixed.
; robot: true, false.
same => n,AGI(tts.agi,${MSG},ermil,neutral,true)
same => n,Hangup
Можно было, конечно, отправлять СМС из того же скрипта, которым проигрывается сообщение, но с точки зрения структуры приложения логично было их разнести.
#!/bin/bash
while read line; do
[ -z "$line" ] && break
num=$(echo $line | grep 'agi_callerid: ' | sed 's/agi_callerid: //')
[ -n "$num" ] && break
done < /dev/stdin
[ -z "$num" ] && exit 1
/usr/local/multifon/sms.sh 79xxxxxxxxx "Пропущенный вызов [$(date '+%Y-%m-%d %H:%M:%S')] с номера +$num"
Абсолютно никакого AGI, по факту. Просто делаем, что требуется, и закругляемся.
#!/bin/bash
text="$1"
speaker="$2"
emotion="$3"
robot="$4"
key=<yandex API key>
dir=/var/lib/asterisk/tts
url=https://tts.voicetech.yandex.net/generate
dbg=${0/.agi/.log}
fname="$dir/$(echo -n "$text-$speaker-$emotion-$robot" | md5sum | cut -d' ' -f1)"
wav="${fname}.wav"
echo -e "$@" > "$dbg"
while read line; do
echo $line >> "$dbg"
[ -z "$line" ] && break
done < /dev/stdin
[ -f "$wav" ] || /usr/bin/curl -s --data-urlencode "text=$text"
--data-urlencode format=wav
--data-urlencode lang=ru-RU
--data-urlencode "speaker=$speaker"
--data-urlencode "key=$key"
--data-urlencode "emotion=$emotion"
--data-urlencode "robot=$robot"
"$url" > "$wav" || exit 1
for f in al ul gsm; do
[ -f "${fname}.$f" ] || /usr/bin/sox "$wav" -r8k "${fname}.$f" || exit 2
done
echo -e "STREAM FILE $fname 0"
read line < /dev/stdin
echo $line >> "$dbg"
Здесь тоже нет AGI. Мы только дожидаемся ответа от Астериска командой read, чтобы не закрыться раньше, чем он проиграет сообщение. Прошу обратить внимание на параметр -r8k для сокса. Почему-то без параметров он неправильно выставляет рейт выходному файлу, и сообщение получается замедленным в два раза. Подробности самого Яндекс SpeechKit API и то, как получить ключ, есть в документации [7].
Основная часть на этом закончена. Но статья будет неполной без описания нюансов.
Очевидно, чтобы всё это завелось, потребуется отдельный номер с Мультифоном. Вы покупаете сим-карту и…? Простой и очевидный путь – вставить её в телефон, набрать необходимые запросы и начать использовать. Но мы не ищем лёгких путей. У меня с давних времён валяется пачка 3G-модемов (знаменитый E1550 и чуть менее знаменитые E150), но нет ни одного свободного телефона. А использовать свой для таких операций я не люблю: лишний раз выключать, вскрывать.
Итак, для получения и отправки СМС мы будем использовать давно и хорошо всем известный smstools [8]. Настройку я описывать не буду, ибо боян. Только автодекодинг не включайте. А то будет вам мусор вместо тела сообщения.
Итак, после приобретения сим-карты нужно сделать две вещи:
И если с приёмом СМС всё понятно, то USSD – не такая прозрачная вещь.
Перед тем, как продолжить, можете ознакомиться с репозиторием [10] дополнений к smstools, облегчающих работу с SMS и USSD. В разделе example репозитория есть перловый инструмент работы с USSD, который я использовал для понимания сути кодирования/декодирования символов в USSD. Авторство не указано, и ссылок нет потому, что я не помню, где его взял. Можно использовать его, но лично я не понимаю perl, а техномагию я не люблю. Поэтому, чтобы почувствовать контроль над ситуацией, я написал утилиты encode и decode. Как мне кажется, код на си куда проще для понимания, поэтому утилиты будут полезны тем, кто тоже захочет знаний.
Подозреваю, что если выставить другую кодировку командой AT+CSCS, проблема отпадёт сама собой, но мы же не ищем…
В остальном работа с USSD проста: модем регистрирует три девайса ttyUSB. Пишем в первый, читаем из последнего.
Для подключения личного кабинета достаточно просто отправить 105: ./ussd.sh '*105#' (подразумевается, что /dev/modem указывает на первый из ttyUSB модема). Дожидаемся СМС с паролем (удобнее всего это делать командой ls -lrt /var/spool/incoming), после чего смотрим ./viewsms <path>.
Мультифон подключается в два этапа: запустив cat /dev/ttyUSB2, отправляем *137#. Копируем ответ и выясняем, что там написано, с помощью decode. А приходит в ответ менюшка, где для подключения нужно выбрать пункт 1. Выполняем ./ussd 1 и получаем в СМС пароль.
На этом можно было бы и завершить, но так как мы имеем дело с бабуинами, стоит упомянуть про…
К сожалению, Мультифон не передаёт номер, переадресовавший звонок. Поэтому, если вы хотите подключить свой бонусный «Кто звонил?» друзьям/родным, придётся на каждого человека покупать отдельный номер под автоответчик. Ещё можно попробовать переадресацию с доп. набором (+79XXXXXXXXXpXX), но я не проверял. Если проверите, пишите.
А вот теперь – всё!
Автор: wolandtel
Источник [11]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/telefoniya/114245
Ссылки в тексте:
[1] MessageSend: http://www.voip-info.org/wiki/view/Asterisk+cmd+MessageSend
[2] SipSak: http://www.voip-info.org/wiki/view/Sipsak
[3] скрипт для Yate: https://github.com/vir/yate/wiki/Multifon-sms
[4] https://github.com/wolandtel/sipsak: https://github.com/wolandtel/sipsak
[5] удобный скрипт: https://github.com/wolandtel/multifon
[6] AGI: http://www.voip-info.org/wiki/view/Asterisk+AGI
[7] документации: https://tech.yandex.ru/speechkit/cloud/doc/dg/concepts/speechkit-dg-tts-docpage/
[8] smstools: http://smstools3.kekekasvi.com/
[9] веб-интерфейс: https://sm.megafon.ru/sm/
[10] репозиторием: https://github.com/wolandtel/smstools
[11] Источник: https://habrahabr.ru/post/278679/
Нажмите здесь для печати.