perl скрипт производящий голосовой обзвон (оповещение) через usb модем huawei e1550

от автора

В свое время, так как я много времени проводил в командировках, мной была приобретена замечательная игрушка — usb модем Huawei e1550. Но времена лихой молодости прошли, и необходимость в использовании данного девайса по прямому назначению отпала. Так он и пылился у меня на полке в течении нескольких лет. И пылился бы и дальше, но возникла задача сделать систему оповещения. Тут я и вспомнил про модем. Рассмотрев поставленную задачу — был вынужден отказаться от SMS оповещения в пользу голосового дозвона по причине невозможности получить уведомление о прочтении SMS. Решения на базе Asterisk показались мне несколько громоздкими, и почитав доку по модему я решил написать звонилку самостоятельно.

Причина публикации.

Несмотря на обилие статей по работе с USSD и SMS запросами, я не нашел ни одной реализации голосовых вызовов на скриптовых языках (таких как Perl, PHP, Node.js). Надеюсь данная статья будет для Вас хорошим подспорьем.

Среда разработки

операционная система: LinuxДистрибутив: openSuSe 12.3Ядро: 3.7.10-1.16-desktop #1 SMP PREEMPT Fri May 31 20:21:23 UTC 2013 (97c14ba) i686 i686 i386 GNU/LinuxЯзык программирования: Perlusb модем: Huawei e1550

Немного теории.

В большинстве дистрибутивов Linux, при подключении данного модема в /dev создаются 3 usb интерфейса. обычно это:/dev/ttyUSB0 — командный интерфейс модема/dev/ttyUSB1 — голосовой(при включенном голосовом режиме) интерфейс модема/dev/ttyUSB2 — командный интерфейс модема. Отличается от /dev/ttyUSB0 тем что с него можно читать не только ответы модема на команды, а также служебные сообщения. Такие как данные о качестве сигнала, вывод ^CEND и прочее.Для начала работы с модемом достаточно открыть как файл один из командных интерфейсов на чтение и запись. Чтобы отправить модему команду — нужно записать ее в открытый файл интерфейса.Чтобы получить ответ модема на данную команду — нужно прочесть его из открытого файла интерфейса.Команды которые можно подавать модему — это AT командыКоманды для модема Huawei e1550 и ответы которые на них можно получить описаны в его спецификации:HUAWEICDMADatacard ModemAT Command Interface SpecificationHUAWEICDMADatacard ModemAT Command Interface SpecificationДля того чтобы активировать голосовые функции модема нужно подать команду AT^CVOICE=0Голосовые функции будут активированы до тех пор пока не будут отключены командой AT^CVOICE=1Для того чтобы начать прием/передачу в модем аудио информации нужно при каждом звонке переключать режим работы аудио порта модема командой AT^DDSETEX=2Аудиоданные для передачи модему должны иметь формат:частота оцифровки: 8000 Герц.количество каналов: 1 (mono).бит на оцифровку: 16 unsigneg.Аудиоданные должны подаваться в аудио порт модема порциями по 320 байт каждые 0.02 секунды.По завершении вызова модем через 2-й командный интерфейс выдает информацию о вызове в виде сообщения CEND формат вывода ^CEND:call_index, duration, end_status, cc_cause где:call_index — уникальный идентификатор вызоваduration — длительность вызова в секундахend_status — код статуса устройства после завершения вызоваcc_cause — код причины завершения вызова

Итак. Начнем.

звонилка будет состоять из 3-х файлов:huawey_voice_call.pl — непосредственно сам скрипт голосового дозвона.list.01.pl — файл с данными абонентов.test.voice.raw — файл с голосовым сообщением записанным в нужном формате.также в конце статьи будут представлены 2 дополнительных файла:cc_cause.pl — содержит коды причин завершения вызова (cc_cause)end_status.pl — содержит коды статуса устройства после завершения вызова (end_status)рассмотрим huawey_voice_call.pl

<blockquote><font color="#666666">#!/usr/bin/perl</font><br/>  <br/> <font color="#666666"># подключаем модуль Time::HiRes и импортируем</font><br/> <font color="#666666"># в текущее пространство имен функцию sleep</font><br/> <font color="#666666"># особенность данной функции - возможность указывать</font><br/> <font color="#666666"># задержку меньше секунды</font><br/> <font color="#000000">use</font> Time<font color="#339933">::</font><font color="#006600">HiRes</font> <font color="#000066">qw</font><font color="#009900">(</font><font color="#000066">sleep</font><font color="#009900">)</font><font color="#339933">;</font><br/>  <br/>  <br/>  <br/> <font color="#666666"># подключаем файл cc_cause.pl содержащий коды Disconnect cause codes</font><br/> <font color="#666666"># Данные коды отображают причину завершения вызова</font><br/> <font color="#666666"># В данном скрипте не используются, но для написания</font><br/> <font color="#666666"># полноценной звонилки необходимо анализировать данный</font><br/> <font color="#666666"># параметр в выводе ^CEND:call_index, duration, end_status, cc_cause</font><br/> <font color="#666666"># my %cc_cause = do 'cc_cause.pl'; </font><br/>  <br/> <font color="#666666"># подключаем файл end_status.pl содержащий коды Call endind cause codes</font><br/> <font color="#666666"># Данные коды отображают статус устройства после завершения вызова</font><br/> <font color="#666666"># В данном скрипте не используются, но для написания</font><br/> <font color="#666666"># полноценной звонилки необходимо анализировать данный</font><br/> <font color="#666666"># параметр в выводе ^CEND:call_index, duration, end_status, cc_cause</font><br/> <font color="#666666"># my %end_status = do 'end_status.pl';</font><br/>  <br/> <font color="#666666"># Для информации:</font><br/> <font color="#666666"># Сообщения типа CEND выдаются модемом при завершении вызова</font><br/> <font color="#666666"># и содержат в себе информацию о вызове, о причине завершения вызова</font><br/> <font color="#666666"># и о состоянии устройства.</font><br/> <font color="#666666"># формат вывода ^CEND:call_index, duration, end_status, cc_cause</font><br/> <font color="#666666"># где:</font><br/> <font color="#666666"># call_index - уникальный идентификатор вызова</font><br/> <font color="#666666"># duration - длительность вызова в секундах</font><br/> <font color="#666666"># end_status - код статуса устройства после завершения вызова</font><br/> <font color="#666666"># cc_cause - код причины завершения вызова</font><br/>  <br/> <font color="#666666"># при подключении модема к компьютеру с OS Linux</font><br/> <font color="#666666"># создаются 3 usb интерфейса для обмена данными с модемом</font><br/> <font color="#666666"># обычно это:</font><br/> <font color="#666666"># /dev/ttyUSB0 - командный интерфейс модема</font><br/> <font color="#666666"># /dev/ttyUSB1 - голосовой(при включенном голосовом режиме) интерфейс модема</font><br/> <font color="#666666"># /dev/ttyUSB2 - командный интерфейс модема. Отличается от /dev/ttyUSB0 тем</font><br/> <font color="#666666"># что с него можно читать не только ответы модема на команды, а также служебные</font><br/> <font color="#666666"># сообщения. Такие как данные о качестве сигнала, вывод ^CEND и прочее</font><br/>  <br/> <font color="#666666"># указываем порт для отсылки модему звука</font><br/> <font color="#0000ff">$VOICE_PORT</font> <font color="#339933">=</font> <font color="#ff0000">"/dev/ttyUSB4"</font><font color="#339933">;</font><br/>  <br/> <font color="#666666"># указываем порт для подачи модему команд</font><br/> <font color="#0000ff">$COMMAND_PORT</font> <font color="#339933">=</font> <font color="#ff0000">"/dev/ttyUSB5"</font><font color="#339933">;</font><br/>  <br/> <font color="#666666"># устанавливаем в:</font><br/> <font color="#666666"># 0 - чтобы отключить вывод отладочной информации</font><br/> <font color="#666666"># 1 - чтобы включить вывод отладочной информации</font><br/> <font color="#0000ff">$VERBOSE</font> <font color="#339933">=</font> <font color="#cc66cc">1</font><font color="#339933">;</font><br/>  <br/> <font color="#666666"># Открываем командный порт модема на чтение и запись</font><br/> <font color="#000066">open</font> <font color="#b1b100">my</font> <font color="#0000ff">$SENDPORT</font><font color="#339933">,</font> <font color="#ff0000">'+<'</font><font color="#339933">,</font> <font color="#0000ff">$COMMAND_PORT</font> <font color="#b1b100">or</font> <font color="#000066">die</font> <font color="#ff0000">"Can't open '$COMMAND_PORT': $!n"</font><font color="#339933">;</font><br/>  <br/> <font color="#666666"># Открываем голосовой  порт модема на чтение и запись</font><br/> <font color="#666666"># чтение аудиопотока из порта в данной программе не используется</font><br/> <font color="#666666"># но вам ничто не мешает превратить данный скрипт в автоответчик например</font><br/> <font color="#000066">open</font> <font color="#b1b100">my</font> <font color="#0000ff">$SENDPORT_WAV</font><font color="#339933">,</font> <font color="#ff0000">'+<'</font><font color="#339933">,</font> <font color="#0000ff">$VOICE_PORT</font> <font color="#b1b100">or</font> <font color="#000066">die</font> <font color="#ff0000">"Can't open '$VOICE_PORT': $!n"</font><font color="#339933">;</font><br/>  <br/>  <br/>  <br/> <font color="#666666"># подключаем файл list.01.pl содержащий данные об абонентах</font><br/> <font color="#b1b100">my</font> <font color="#0000ff">@user_list</font> <font color="#339933">=</font> <font color="#b1b100">do</font> <font color="#ff0000">'list.01.pl'</font><font color="#339933">;</font> <br/>  <br/>  <br/> <font color="#666666"># вызываем функцию обзвона, которой передаются 2 параметра:</font><br/> <font color="#666666"># 1-й - имя файла с голосовым сообщением</font><br/> <font color="#666666"># 2-й - массив с данными об абонентах</font><br/> call_list<font color="#009900">(</font><font color="#ff0000">"test.voice.raw"</font><font color="#339933">,</font> <font color="#0000ff">@user_list</font> <font color="#009900">)</font><font color="#339933">;</font><br/>  <br/> <font color="#666666"># по окончании обзвона закрываем все открытые файлы/порты</font><br/> exit_call<font color="#009900">(</font><font color="#009900">)</font><font color="#339933">;</font><br/>  <br/>  <br/>  <br/> <font color="#666666"># данная функция производит обзвон абонентов по списку</font><br/> <font color="#000000">sub</font> call_list<font color="#009900">{</font><br/>     <font color="#666666"># получаем имя файла с голосовым сообщением</font><br/>     <font color="#b1b100">my</font> <font color="#0000ff">$l_file</font> <font color="#339933">=</font> <font color="#000066">shift</font><font color="#339933">;</font><br/>  <br/>     <font color="#666666"># получаем ссылку на список с данными об абонентах</font><br/>     <font color="#b1b100">my</font> <font color="#0000ff">$l_list</font> <font color="#339933">=</font> <font color="#000066">shift</font><font color="#339933">;</font><br/>  <br/>     <font color="#666666"># загружаем данные из файла с голосовым сообщением</font><br/>     <font color="#b1b100">my</font> <font color="#0000ff">$l_voice</font> <font color="#339933">=</font> load_voice<font color="#009900">(</font><font color="#0000ff">$l_file</font><font color="#009900">)</font><font color="#339933">;</font><br/>  <br/>     <font color="#666666"># данный цикл пробегает по списку абонентов</font><br/>     <font color="#666666"># и пытается произвести дозвон</font><br/>     <font color="#b1b100">foreach</font> <font color="#0000ff">$l_info</font> <font color="#009900">(</font><font color="#339933">@</font><font color="#009900">{</font><font color="#0000ff">$l_list</font><font color="#009900">}</font><font color="#009900">)</font><font color="#009900">{</font><br/>  <br/> 	<font color="#666666"># вызываем функцию дозвона до абонента</font><br/> 	<font color="#b1b100">my</font> <font color="#0000ff">$l_msg</font> <font color="#339933">=</font> call_one<font color="#009900">(</font><font color="#0000ff">$l_info</font><font color="#339933">,</font><font color="#0000ff">$l_voice</font><font color="#009900">)</font><font color="#339933">;</font><br/>  <br/> 	<font color="#666666"># Выводим полученное сообщение</font><br/> 	<font color="#000066">print</font> <font color="#0000ff">$l_msg</font><font color="#339933">;</font><br/>  <br/> 	<font color="#666666"># прежде чем звонить следующему абоненту</font><br/> 	<font color="#666666"># ждем 3 секунды.</font><br/> 	<font color="#000066">sleep</font> <font color="#cc66cc">3</font><font color="#339933">;</font><br/>     <font color="#009900">}</font><br/> <font color="#009900">}</font><br/>  <br/>  <br/> <font color="#666666"># данная функция производит попытку вызова указаного номера</font><br/> <font color="#666666"># и в случае успеха - транслирует голосовое сообщение</font><br/> <font color="#000000">sub</font> call_one<font color="#009900">{</font><br/>  <br/>     <font color="#b1b100">my</font> <font color="#0000ff">$l_info</font> <font color="#339933">=</font> <font color="#000066">shift</font><font color="#339933">;</font>  <font color="#666666"># ХЭШ с данными текущего абонента</font><br/>     <font color="#b1b100">my</font> <font color="#0000ff">$l_bufer</font> <font color="#339933">=</font> <font color="#000066">shift</font><font color="#339933">;</font> <font color="#666666"># массив с 320 байтными кусками головового сообщения</font><br/>  <br/>     <font color="#666666"># данная команда включает в модеме голосовой режим</font><br/>     <font color="#666666"># один раз включив его можно удалить/заремарить</font><br/>     <font color="#666666"># эту команду. Модем запомнит состояние.</font><br/>     <font color="#666666">#at_send('AT^CVOICE=0'); </font><br/>  <br/>     <font color="#666666"># отдаем модему команду дозвониться до номера $l_info->{phone}</font><br/>     <font color="#666666"># и ожидать ответа от модема:</font><br/>     <font color="#666666"># OK - дозвон прошел успешно</font><br/>     <font color="#666666"># NO CARRIER - нет соединения с сотовой сетью</font><br/>     <font color="#b1b100">my</font> <font color="#0000ff">$l_rec</font> <font color="#339933">=</font> at_send<font color="#009900">(</font><font color="#ff0000">"ATD$l_info->{phone};"</font><font color="#339933">,</font><font color="#000066">qr</font><font color="#339933">/</font><font color="#009900">(</font>OK<font color="#339933">|</font>NO CARRIER<font color="#009900">)</font><font color="#339933">/</font><font color="#009900">)</font><font color="#339933">;</font><br/>     <font color="#666666"># в случае если дозвон не произошел - выходим из функции и возвращаем соответствующее сообщение</font><br/>     <font color="#000066">return</font> <font color="#ff0000">"Абонент $l_info->{name} [$l_info->{phone}] не оповещен. НЕТ СЕТИn"</font>  <font color="#b1b100">if</font>  <font color="#0000ff">$l_rec</font> <font color="#b1b100">eq</font> <font color="#ff0000">'NO CARRIER'</font><font color="#339933">;</font><br/>  <br/>     <font color="#666666"># ожидаем когда абонент поднимет трубку</font><br/>     <font color="#666666"># CONN:.... - абонент поднял трубку</font><br/>     <font color="#666666"># CEND:.... - абонент недоступен, занят или сбросил вызов</font><br/>     <font color="#0000ff">$l_rec</font> <font color="#339933">=</font> at_rec<font color="#009900">(</font><font color="#009966">qr/^(CONN:1,0|CEND:)/</font><font color="#009900">)</font><font color="#339933">;</font><br/>     <font color="#666666"># в случае если абонент не поднял трубку - выходим из функции и возвращаем соответствующее сообщение</font><br/>     <font color="#000066">return</font> <font color="#ff0000">"Абонент $l_info->{name} [$l_info->{phone}] не оповещен. НЕДОСТУПЕН или СБРОСИЛn"</font> <font color="#b1b100">if</font>  <font color="#0000ff">$l_rec</font> <font color="#b1b100">eq</font> <font color="#ff0000">'CEND:'</font><font color="#339933">;</font><br/>  <br/>     <font color="#666666"># переключаем модем в режим приема/передачи голоса</font><br/>     <font color="#666666"># OK - переключение прошло успешно</font><br/>     <font color="#666666"># ERROR - переключение не произведено</font><br/>     <font color="#666666"># CEND:.... - абонент недоступен, занят или сбросил вызов</font><br/>     <font color="#0000ff">$l_rec</font> <font color="#339933">=</font> at_send<font color="#009900">(</font><font color="#ff0000">'AT^DDSETEX=2'</font><font color="#339933">,</font><font color="#000066">qr</font><font color="#339933">/</font><font color="#009900">(</font>OK<font color="#339933">|</font>ERROR<font color="#339933">|</font>CEND<font color="#339933">:</font><font color="#009900">)</font><font color="#339933">/</font><font color="#009900">)</font><font color="#339933">;</font><br/>     <font color="#666666"># в случае если не удалось переключится в голосовой режим или абонент не поднял</font><br/>     <font color="#666666"># трубку - выходим из функции и возвращаем соответствующее сообщение</font><br/>     <font color="#000066">return</font> <font color="#ff0000">"Абонент $l_info->{name} [$l_info->{phone}] не оповещен. НЕДОСТУПЕН или СБРОСИЛn"</font> <font color="#b1b100">if</font>  <font color="#0000ff">$l_rec</font> <font color="#b1b100">ne</font> <font color="#ff0000">'OK'</font><font color="#339933">;</font><br/>  <br/>     <font color="#666666"># Если дошли до сюда - значит вызов установлен и абонент поднял трубку</font><br/>     <font color="#666666"># Звук модему должен передаваться порциями по 320 байт каждые 0.02 секунды</font><br/>  <br/>     <font color="#666666"># Устанавливаем служебную переменную $| в единицу это отключает буферизацию.</font><br/>     <font color="#666666"># Таким образом данные в звуковой порт будут отправляться незамедлительно.</font><br/>     <font color="#0000ff">$|</font><font color="#339933">=</font><font color="#cc66cc">1</font><font color="#339933">;</font><br/>  <br/>     <font color="#666666"># Цикл по буферу с 320 байтными кусками колосового сообщения</font><br/>     <font color="#b1b100">foreach</font> <font color="#b1b100">my</font> <font color="#0000ff">$c</font> <font color="#009900">(</font><font color="#339933">@</font><font color="#009900">{</font><font color="#0000ff">$l_bufer</font><font color="#009900">}</font><font color="#009900">)</font> <font color="#009900">{</font><br/> 	    <font color="#666666"># Запись очередного куска в голосовой порт модема</font><br/> 	    <font color="#000066">syswrite</font>  <font color="#0000ff">$SENDPORT_WAV</font><font color="#339933">,</font> <font color="#0000ff">$c</font><font color="#339933">,</font> <font color="#cc66cc">320</font><font color="#339933">;</font><br/>  <br/> 	    <font color="#666666"># Ожидаем 0.02 секунды перед тем как продолжить цикл</font><br/> 	    <font color="#000066">sleep</font><font color="#009900">(</font><font color="#cc66cc">0.02</font><font color="#009900">)</font><font color="#339933">;</font><br/>     <font color="#009900">}</font><br/>  <br/>     <font color="#666666"># Вешаем трубку.</font><br/>     at_send<font color="#009900">(</font><font color="#ff0000">'AT+CHUP'</font><font color="#009900">)</font><font color="#339933">;</font><br/>  <br/>     <font color="#666666"># Возвращаем сообщение об успешном оповещении.</font><br/>     <font color="#000066">return</font> <font color="#ff0000">"Абонент $l_info->{name} [$l_info->{phone}] УСПЕШНО ОПОВЕЩЕНn"</font><font color="#339933">;</font><br/> <font color="#009900">}</font><br/>  <br/> <font color="#666666"># данная функция загружает голосовое сообщение в массив кусками по 320 байт</font><br/> <font color="#666666"># принимает 1 параметр - имя файла</font><br/> <font color="#666666"># формат звуковых данных - pcm, моно, 8000 кГц, 16 бит, unsigned</font><br/> <font color="#000000">sub</font> load_voice<font color="#009900">{</font><br/>     <font color="#b1b100">my</font> <font color="#0000ff">$l_file_name</font> <font color="#339933">=</font> <font color="#000066">shift</font><font color="#339933">;</font><br/>     <font color="#b1b100">my</font> <font color="#0000ff">$l_fh</font> <font color="#339933">=</font> <font color="#000000">new</font> IO<font color="#339933">::</font><font color="#006600">File</font> <font color="#ff0000">"< $l_file_name"</font> <font color="#b1b100">or</font> <font color="#000066">die</font> <font color="#ff0000">"Cannot open $l_file_name : $!"</font><font color="#339933">;</font><br/>     <font color="#000066">binmode</font><font color="#009900">(</font><font color="#0000ff">$l_fh</font><font color="#009900">)</font><font color="#339933">;</font><br/>     <font color="#b1b100">my</font> <font color="#0000ff">@l_bufer</font> <font color="#339933">=</font> <font color="#009900">(</font><font color="#009900">)</font><font color="#339933">;</font><br/>     <font color="#b1b100">while</font> <font color="#009900">(</font><font color="#000066">read</font><font color="#009900">(</font><font color="#0000ff">$l_fh</font><font color="#339933">,</font><font color="#0000ff">$l_bufer</font><font color="#009900">[</font><font color="#0000ff">$i</font><font color="#009900">]</font><font color="#339933">,</font><font color="#cc66cc">320</font><font color="#009900">)</font><font color="#009900">)</font> <font color="#009900">{</font> <font color="#0000ff">$i</font><font color="#339933">++;</font> <font color="#009900">}</font><br/>     <font color="#000066">close</font> <font color="#0000ff">$l_fh</font><font color="#339933">;</font><br/>     <font color="#000066">return</font> <font color="#0000ff">@l_bufer</font><font color="#339933">;</font><br/> <font color="#009900">}</font><br/>  <br/>  <br/> <font color="#666666"># данная функция отправляет команду в командный порт модема</font><br/> <font color="#666666"># и ждет ответа указанного в регулярном выражении</font><br/> <font color="#666666"># принимает 2 параметра:</font><br/> <font color="#666666"># 1-й - команда</font><br/> <font color="#666666"># 2-й - регулярное выражение описывающее варианты ожидаемых ответов (по умолчанию OK)</font><br/> <font color="#000000">sub</font> at_send<font color="#009900">{</font><br/>     <font color="#b1b100">my</font> <font color="#0000ff">$l_cmd</font> <font color="#339933">=</font> <font color="#000066">shift</font><font color="#339933">;</font><br/>     <font color="#b1b100">my</font> <font color="#0000ff">$l_rx</font> <font color="#339933">=</font> <font color="#000066">shift</font> <font color="#339933">||</font> <font color="#009966">qr/(OK)/</font><font color="#339933">;</font><br/>     <font color="#000066">print</font> <font color="#0000ff">$SENDPORT</font> <font color="#ff0000">"$l_cmdr"</font><font color="#339933">;</font><br/>     <font color="#000066">print</font> <font color="#ff0000">"SEND: [$l_cmd]n"</font> <font color="#b1b100">if</font> <font color="#0000ff">$VERBOSE</font><font color="#339933">;</font><br/>     <font color="#000066">return</font> at_rec<font color="#009900">(</font><font color="#0000ff">$l_rx</font><font color="#009900">)</font><font color="#339933">;</font><br/> <font color="#009900">}</font><br/>  <br/>  <br/> <font color="#666666"># данная функция ждет от модема ответа указанного в регулярном выражении </font><br/> <font color="#666666"># принимает 1 параметра - регулярное выражение описывающее варианты ожидаемых ответов (по умолчанию OK)</font><br/> <font color="#000000">sub</font> at_rec<font color="#009900">{</font><br/>     <font color="#b1b100">my</font> <font color="#0000ff">$l_rx</font> <font color="#339933">=</font> <font color="#000066">shift</font> <font color="#339933">||</font> <font color="#009966">qr/OK/</font><font color="#339933">;</font><br/>     <font color="#b1b100">my</font> <font color="#0000ff">$recive</font><font color="#339933">=</font><font color="#ff0000">''</font><font color="#339933">;</font><br/>     <font color="#b1b100">while</font> <font color="#009900">(</font> <font color="#339933">!</font><font color="#009900">(</font><font color="#0000ff">$recive</font><font color="#339933">=~</font><font color="#0000ff">$l_rx</font><font color="#009900">)</font> <font color="#009900">)</font> <font color="#009900">{</font><br/> 	<font color="#0000ff">$recive</font><font color="#339933">=<</font><font color="#0000ff">$SENDPORT</font><font color="#339933">>;</font><br/> 	<font color="#0000ff">$recive</font><font color="#339933">=~</font><font color="#000066">s</font><font color="#339933">/</font><font color="#009900">[</font>nr<font color="#009900">]</font><font color="#339933">+//</font>msg<font color="#339933">;</font><br/> 	<font color="#000066">print</font> <font color="#ff0000">"RECIVE: [$recive]n"</font> <font color="#b1b100">if</font> <font color="#0000ff">$VERBOSE</font> <font color="#339933">&&</font> <font color="#0000ff">$recive</font><font color="#339933">;</font><br/>     <font color="#009900">}</font><br/>     <font color="#0000ff">$recive</font><font color="#339933">=~</font><font color="#0000ff">$l_rx</font><font color="#339933">;</font><br/>     <font color="#000066">print</font> <font color="#ff0000">"END RECIVE: [$recive] [$1] [$l_rx]n"</font> <font color="#b1b100">if</font> <font color="#0000ff">$VERBOSE</font><font color="#339933">;</font><br/>     <font color="#000066">return</font> <font color="#0000ff">$1</font><font color="#339933">;</font><br/> <font color="#009900">}</font><br/>  <br/>  <br/> <font color="#666666"># данная функция закрывает ранее открытые порты модема</font><br/> <font color="#000000">sub</font> exit_call<font color="#009900">{</font><br/>     <font color="#000066">print</font> <font color="#ff0000">"ОПОВЕЩЕНИЕ ОКОНЧЕНОn"</font><font color="#339933">;</font><br/>     <font color="#000066">close</font> <font color="#0000ff">$SENDPORT_WAV</font><font color="#339933">;</font><br/>     at_send<font color="#009900">(</font><font color="#ff0000">'AT+CHUP'</font><font color="#009900">)</font><font color="#339933">;</font><br/>     <font color="#000066">close</font> <font color="#0000ff">$SENDPORT</font><font color="#339933">;</font><br/> <font color="#009900">}</font><br/>  </blockquote> 

рассмотрим list.01.pl

<blockquote><font color="#666666"># Список абонентов.</font><br/> <font color="#666666"># Это массив хэш массивов в котором каждая запись содержит</font><br/> <font color="#666666"># данные о абоненте:</font><br/> <font color="#666666">#	phone - телефон абонента</font><br/> <font color="#666666">#	name  - ФИО абонента</font><br/> <font color="#666666"># Также возможно хранение и других данных об абоненте</font><br/> <font color="#009900">(</font><br/>     <font color="#009900">{</font> phone <font color="#339933">=></font> <font color="#ff0000">'+79111234567'</font><font color="#339933">,</font> name <font color="#339933">=></font> <font color="#ff0000">'Петров Петр Петрович'</font> <font color="#009900">}</font><font color="#339933">,</font><br/>     <font color="#009900">{</font> phone <font color="#339933">=></font> <font color="#ff0000">'+79117654321'</font><font color="#339933">,</font> name <font color="#339933">=></font> <font color="#ff0000">'Васильев Василий Васильевич'</font> <font color="#009900">}</font><br/> <font color="#009900">)</font><font color="#339933">;</font></blockquote> 

рассмотрим test.voice.rawДля создания данного файла использовался аудиоредактор Audacity как показано на картинках:imageimageimageimageimageТакже привожу дополнительные файлы cc_cause.pl и end_status.pl. Они не используются в представленной версии скрипта, но в случае доработки будут полезны.cc_cause.pl

<blockquote><font color="#666666"># коды disconnect cause (cc)</font><br/> <font color="#666666"># English http://www.eversoft.net/dcc.html</font><br/> <font color="#666666"># по Русски http://ru.wikipedia.org/wiki/Q.931</font><br/> <font color="#666666"># маны по huawei</font><br/> <font color="#666666"># HUAWEICDMADatacard ModemAT Command Interface Specification</font><br/> <font color="#666666"># "http://www.letswireless.com.cn/asp_bin/downfile/2009929121443234.pdf"</font><br/> <font color="#666666">#</font><br/> <font color="#666666"># HUAWEICDMADatacard ModemAT Command Interface Specification</font><br/> <font color="#666666"># "http://www.net139.com/UploadFile/menu/HUAWEI%20UMTS%20Datacard%20Modem%20AT%20Command%20Interface%20Specification_V2.3.pdf"</font><br/> <font color="#009900">(</font><br/> <font color="#ff0000">'1'</font>	<font color="#339933">=></font> <font color="#ff0000">'UNASSIGNED_CAUSE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'3'</font>	<font color="#339933">=></font> <font color="#ff0000">'NO_ROUTE_TO_DEST'</font><font color="#339933">,</font><br/> <font color="#ff0000">'6'</font>	<font color="#339933">=></font> <font color="#ff0000">'CHANNEL_UNACCEPTABLE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'8'</font>	<font color="#339933">=></font> <font color="#ff0000">'OPERATOR_DETERMINED_BARRING'</font><font color="#339933">,</font><br/> <font color="#ff0000">'16'</font>	<font color="#339933">=></font> <font color="#ff0000">'NORMAL_CALL_CLEARING'</font><font color="#339933">,</font><br/> <font color="#ff0000">'17'</font>	<font color="#339933">=></font> <font color="#ff0000">'USER_BUSY'</font><font color="#339933">,</font><br/> <font color="#ff0000">'18'</font>	<font color="#339933">=></font> <font color="#ff0000">'NO_USER_RESPONDING'</font><font color="#339933">,</font><br/> <font color="#ff0000">'19'</font>	<font color="#339933">=></font> <font color="#ff0000">'USER_ALERTING_NO_ANSWER'</font><font color="#339933">,</font><br/> <font color="#ff0000">'21'</font>	<font color="#339933">=></font> <font color="#ff0000">'CALL_REJECTED'</font><font color="#339933">,</font><br/> <font color="#ff0000">'22'</font>	<font color="#339933">=></font> <font color="#ff0000">'NUMBER_CHANGED'</font><font color="#339933">,</font><br/> <font color="#ff0000">'26'</font>	<font color="#339933">=></font> <font color="#ff0000">'NON_SELECTED_USER_CLEARING'</font><font color="#339933">,</font><br/> <font color="#ff0000">'27'</font>	<font color="#339933">=></font> <font color="#ff0000">'DESTINATION_OUT_OF_ORDER'</font><font color="#339933">,</font><br/> <font color="#ff0000">'28'</font>	<font color="#339933">=></font> <font color="#ff0000">'INVALID_NUMBER_FORMAT'</font><font color="#339933">,</font><br/> <font color="#ff0000">'29'</font>	<font color="#339933">=></font> <font color="#ff0000">'FACILITY_REJECTED'</font><font color="#339933">,</font><br/> <font color="#ff0000">'30'</font>	<font color="#339933">=></font> <font color="#ff0000">'RESPONSE_TO_STATUS_ENQUIRY'</font><font color="#339933">,</font><br/> <font color="#ff0000">'31'</font>	<font color="#339933">=></font> <font color="#ff0000">'NORMAL_UNSPECIFIED'</font><font color="#339933">,</font><br/> <font color="#ff0000">'34'</font>	<font color="#339933">=></font> <font color="#ff0000">'NO_CIRCUIT_CHANNEL_AVAILABLE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'38'</font>	<font color="#339933">=></font> <font color="#ff0000">'NETWORK_OUT_OF_ORDER'</font><font color="#339933">,</font><br/> <font color="#ff0000">'41'</font>	<font color="#339933">=></font> <font color="#ff0000">'TEMPORARY_FAILURE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'42'</font>	<font color="#339933">=></font> <font color="#ff0000">'SWITCHING_EQUIPMENT_CONGESTION'</font><font color="#339933">,</font><br/> <font color="#ff0000">'43'</font>	<font color="#339933">=></font> <font color="#ff0000">'ACCESS_INFORMATION_DISCARDED'</font><font color="#339933">,</font><br/> <font color="#ff0000">'44'</font>	<font color="#339933">=></font> <font color="#ff0000">'REQUESTED_CIRCUIT_CHANNEL_NOT_AVAILABLE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'47'</font>	<font color="#339933">=></font> <font color="#ff0000">'RESOURCES_UNAVAILABLE_UNSPECIFIED'</font><font color="#339933">,</font><br/> <font color="#ff0000">'49'</font>	<font color="#339933">=></font> <font color="#ff0000">'QUALITY_OF_SERVICE_UNAVAILABLE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'50'</font>	<font color="#339933">=></font> <font color="#ff0000">'REQUESTED_FACILITY_NOT_SUBSCRIBED'</font><font color="#339933">,</font><br/> <font color="#ff0000">'55'</font>	<font color="#339933">=></font> <font color="#ff0000">'INCOMING_CALL_BARRED_WITHIN_CUG'</font><font color="#339933">,</font><br/> <font color="#ff0000">'57'</font>	<font color="#339933">=></font> <font color="#ff0000">'BEARER_CAPABILITY_NOT_AUTHORISED'</font><font color="#339933">,</font><br/> <font color="#ff0000">'58'</font>	<font color="#339933">=></font> <font color="#ff0000">'BEARER_CAPABILITY_NOT_PRESENTLY_AVAILABLE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'63'</font>	<font color="#339933">=></font> <font color="#ff0000">'SERVICE_OR_OPTION_NOT_AVAILABLE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'65'</font>	<font color="#339933">=></font> <font color="#ff0000">'BEARER_SERVICE_NOT_IMPLEMENTED'</font><font color="#339933">,</font><br/> <font color="#ff0000">'68'</font>	<font color="#339933">=></font> <font color="#ff0000">'ACM_GEQ_ACMMAX'</font><font color="#339933">,</font><br/> <font color="#ff0000">'69'</font>	<font color="#339933">=></font> <font color="#ff0000">'REQUESTED_FACILITY_NOT_IMPLEMENTED'</font><font color="#339933">,</font><br/> <font color="#ff0000">'70'</font>	<font color="#339933">=></font> <font color="#ff0000">'ONLY_RESTRICTED_DIGITAL_INFO_BC_AVAILABLE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'79'</font>	<font color="#339933">=></font> <font color="#ff0000">'SERVICE_OR_OPTION_NOT_IMPLEMENTED'</font><font color="#339933">,</font><br/> <font color="#ff0000">'81'</font>	<font color="#339933">=></font> <font color="#ff0000">'INVALID_TRANSACTION_ID_VALUE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'87'</font>	<font color="#339933">=></font> <font color="#ff0000">'USER_NOT_MEMBER_OF_CUG'</font><font color="#339933">,</font><br/> <font color="#ff0000">'88'</font>	<font color="#339933">=></font> <font color="#ff0000">'INCOMPATIBLE_DESTINATION'</font><font color="#339933">,</font><br/> <font color="#ff0000">'91'</font>	<font color="#339933">=></font> <font color="#ff0000">'INVALID_TRANSIT_NETWORK_SELECTION'</font><font color="#339933">,</font><br/> <font color="#ff0000">'95'</font>	<font color="#339933">=></font> <font color="#ff0000">'SEMANTICALLY_INCORRECT_MESSAGE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'96'</font>	<font color="#339933">=></font> <font color="#ff0000">'INVALID_MANDATORY_INFORMATION'</font><font color="#339933">,</font><br/> <font color="#ff0000">'97'</font>	<font color="#339933">=></font> <font color="#ff0000">'MESSAGE_TYPE_NON_EXISTENT'</font><font color="#339933">,</font><br/> <font color="#ff0000">'98'</font>	<font color="#339933">=></font> <font color="#ff0000">'MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROT_STATE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'99'</font>	<font color="#339933">=></font> <font color="#ff0000">'IE_NON_EXISTENT_OR_NOT_IMPLEMENTED'</font><font color="#339933">,</font><br/> <font color="#ff0000">'100'</font>	<font color="#339933">=></font> <font color="#ff0000">'CONDITIONAL_IE_ERROR'</font><font color="#339933">,</font><br/> <font color="#ff0000">'101'</font>	<font color="#339933">=></font> <font color="#ff0000">'MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'102'</font>	<font color="#339933">=></font> <font color="#ff0000">'RECOVERY_ON_TIMER_EXPIRY'</font><font color="#339933">,</font><br/> <font color="#ff0000">'111'</font>	<font color="#339933">=></font> <font color="#ff0000">'PROTOCOL_ERROR_UNSPECIFIED'</font><font color="#339933">,</font><br/> <font color="#ff0000">'127'</font>	<font color="#339933">=></font> <font color="#ff0000">'INTERWORKING_UNSPECIFIED'</font><font color="#339933">,</font><br/> <font color="#ff0000">'160'</font>	<font color="#339933">=></font> <font color="#ff0000">'REJ_UNSPECIFIED'</font><font color="#339933">,</font><br/> <font color="#ff0000">'161'</font>	<font color="#339933">=></font> <font color="#ff0000">'AS_REJ_RR_REL_IND'</font><font color="#339933">,</font><br/> <font color="#ff0000">'162'</font>	<font color="#339933">=></font> <font color="#ff0000">'AS_REJ_RR_RANDOM_ACCESS_FAILURE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'163'</font>	<font color="#339933">=></font> <font color="#ff0000">'AS_REJ_RRC_REL_IND'</font><font color="#339933">,</font><br/> <font color="#ff0000">'164'</font>	<font color="#339933">=></font> <font color="#ff0000">'AS_REJ_RRC_CLOSE_SESSION_IND'</font><font color="#339933">,</font><br/> <font color="#ff0000">'165'</font>	<font color="#339933">=></font> <font color="#ff0000">'AS_REJ_RRC_OPEN_SESSION_FAILURE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'166'</font>	<font color="#339933">=></font> <font color="#ff0000">'AS_REJ_LOW_LEVEL_FAIL'</font><font color="#339933">,</font><br/> <font color="#ff0000">'167'</font>	<font color="#339933">=></font> <font color="#ff0000">'AS_REJ_LOW_LEVEL_FAIL_REDIAL_NOT_ALLOWD'</font><font color="#339933">,</font><br/> <font color="#ff0000">'168'</font>	<font color="#339933">=></font> <font color="#ff0000">'MM_REJ_INVALID_SIM'</font><font color="#339933">,</font><br/> <font color="#ff0000">'169'</font>	<font color="#339933">=></font> <font color="#ff0000">'MM_REJ_NO_SERVICE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'170'</font>	<font color="#339933">=></font> <font color="#ff0000">'MM_REJ_TIMER_T3230_EXP'</font><font color="#339933">,</font><br/> <font color="#ff0000">'171'</font>	<font color="#339933">=></font> <font color="#ff0000">'MM_REJ_NO_CELL_AVAILABLE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'172'</font>	<font color="#339933">=></font> <font color="#ff0000">'MM_REJ_WRONG_STATE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'173'</font>	<font color="#339933">=></font> <font color="#ff0000">'MM_REJ_ACCESS_CLASS_BLOCKED'</font><font color="#339933">,</font><br/> <font color="#ff0000">'174'</font>	<font color="#339933">=></font> <font color="#ff0000">'ABORT_MSG_RECEIVED'</font><font color="#339933">,</font><br/> <font color="#ff0000">'175'</font>	<font color="#339933">=></font> <font color="#ff0000">'OTHER_CAUSE'</font><font color="#339933">,</font><br/> <font color="#ff0000">'176'</font>	<font color="#339933">=></font> <font color="#ff0000">'CNM_REJ_TIMER_T303_EXP'</font><font color="#339933">,</font><br/> <font color="#ff0000">'177'</font>	<font color="#339933">=></font> <font color="#ff0000">'CNM_REJ_NO_RESOURCES'</font><font color="#339933">,</font><br/> <font color="#ff0000">'178'</font>	<font color="#339933">=></font> <font color="#ff0000">'CNM_MM_REL_PENDING'</font><font color="#339933">,</font><br/> <font color="#ff0000">'179'</font>	<font color="#339933">=></font> <font color="#ff0000">'CNM_INVALID_USER_DATA'</font><br/> <font color="#009900">)</font><font color="#339933">;</font><br/>  </blockquote> 

end_status.pl

<blockquote><font color="#666666"># коды Call ending cause codes</font><br/> <font color="#666666"># маны по huawei</font><br/> <font color="#666666">#</font><br/> <font color="#666666"># HUAWEICDMADatacard ModemAT Command Interface Specification</font><br/> <font color="#666666"># "http://www.letswireless.com.cn/asp_bin/downfile/2009929121443234.pdf"</font><br/> <font color="#666666">#</font><br/> <font color="#666666"># HUAWEICDMADatacard ModemAT Command Interface Specification</font><br/> <font color="#666666"># "http://www.net139.com/UploadFile/menu/HUAWEI%20UMTS%20Datacard%20Modem%20AT%20Command%20Interface%20Specification_V2.3.pdf"</font><br/> <font color="#009900">(</font><br/> <font color="#ff0000">'0'</font>	<font color="#339933">=></font> <font color="#ff0000">'The board is offline.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'21'</font>	<font color="#339933">=></font> <font color="#ff0000">'Board is out of service.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'22'</font>	<font color="#339933">=></font> <font color="#ff0000">'Call is ended normally.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'23'</font>	<font color="#339933">=></font> <font color="#ff0000">'Call is interrupted by BS.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'24'</font>	<font color="#339933">=></font> <font color="#ff0000">'BS record is received during a call.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'25'</font>	<font color="#339933">=></font> <font color="#ff0000">'BS releases a call.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'26'</font>	<font color="#339933">=></font> <font color="#ff0000">'BS rejects the current SO service.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'27'</font>	<font color="#339933">=></font> <font color="#ff0000">'There is incoming BS call.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'28'</font>	<font color="#339933">=></font> <font color="#ff0000">'received alert stop from BS.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'29'</font>	<font color="#339933">=></font> <font color="#ff0000">'Call is ended normally by the client end.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'30'</font>	<font color="#339933">=></font> <font color="#ff0000">'received end activation — OTASP call.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'31'</font>	<font color="#339933">=></font> <font color="#ff0000">'MC ends call initiation or call.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'34'</font>	<font color="#339933">=></font> <font color="#ff0000">'RUIM is not available.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'99'</font>	<font color="#339933">=></font> <font color="#ff0000">'NDSS error.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'100'</font>	<font color="#339933">=></font> <font color="#ff0000">'rxd a reason from lower layer,look in cc_cause'</font><font color="#339933">,</font><br/> <font color="#ff0000">'101'</font>	<font color="#339933">=></font> <font color="#ff0000">'After a MS initiates a call, the network fails to respond.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'102'</font>	<font color="#339933">=></font> <font color="#ff0000">'MS rejects an incoming call.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'103'</font>	<font color="#339933">=></font> <font color="#ff0000">'A call is rejected during the put-through process.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'104'</font>	<font color="#339933">=></font> <font color="#ff0000">'The release is from the For details, check'</font><font color="#339933">,</font><br/> <font color="#ff0000">'105'</font>	<font color="#339933">=></font> <font color="#ff0000">'The phone fee is used up.'</font><font color="#339933">,</font><br/> <font color="#ff0000">'106'</font>	<font color="#339933">=></font> <font color="#ff0000">'The MS is out of the service'</font><br/> <font color="#009900">)</font><font color="#339933">;</font></blockquote> 
В завершение.

Данная версия скрипта голосового оповещения не претендует на полноту и правильность реализации, а является лишь демонстрацией, и для серьезного использования может быть и должна быть усовершенствована. Необходимо добавить более серьезную обработку состояний CEND, реализовать условия повторного дозвона до абонентов, если с первого раза не удалось оповестить. Также можно сделать web интерфейс включающий в себя планировщик задач, редактор списков абонентов, генерацию отчетов и многое другое.Я надеюсь что эта статья окажется востребованной и полезной для Вас, а также постараюсь и впредь выкладывать интересные и полезные статьи.

ссылка на оригинал статьи http://habrahabr.ru/post/192930/


Комментарии

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

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