Здесь показаны различия между двумя версиями данной страницы.
doc:1cajam:listening [2012/01/30 11:28] nb |
doc:1cajam:listening [2014/11/14 22:32] |
||
---|---|---|---|
Строка 1: | Строка 1: | ||
- | ====== Прослушивание событий передаваемых сервером Asterisk из 1С ====== | ||
- | |||
- | После инициализации и авторизации компонента на сервере Asterisk, между компонентом и сервером устанавливается HTTP соединение, по которому сервер телефонии передает информацию о текущем состоянии каналов, вызовов, а так же результат выполнения различных команд. Полученный ответы разбираются компонентом при помощи встроенного XML парсера и вызывают в сеансе 1С предприятия встроенную функцию *ВнешнееСобытие*. | ||
- | |||
- | <note tip>Вызов функции возникает при посылке внешним приложением сообщения, сформированного в специальном формате. Внешнее событие сначала обрабатывается всеми открытыми формами, имеющими обработчик этого события, а затем может быть обработано в процедуре модуля обычного приложения с именем ОбработкаВнешнегоСобытия. | ||
- | </note> | ||
- | |||
- | Таким образом все события компоненты можно обработать в любой открытой форме или в модуле обычного приложения. В качестве переменных используются 3 строковых параметра: | ||
- | * Источник - Источник внешнего события. | ||
- | * Событие - Наименование события. | ||
- | * Данные - Данные для события. | ||
- | |||
- | В параметр *Источник* всегда передается строка //MikoAjamEvent// которая позволяет однозначно идентифицировать события отправленные компонентой. | ||
- | В параметр *Событие* передается наименование [[kb:asterisk:events|события Asterisk]] или строки //Error//, //Exeption// свидетельствующие о возникновении нештатной ситуации, например разрыв связи с Asterisk. | ||
- | В параметр *Данные* передается XML строка содержащая весь пакет данных полученных от сервера Acterisk без каких либо модификаций или техническую информацию о ошибке в работе компонента. | ||
- | |||
- | Стандартный вид обработки внешнего события компоненты выглядит так: | ||
- | <code 1c> | ||
- | Процедура ВнешнееСобытие(Источник, Событие, Данные) | ||
- | |||
- | Если Источник="MikoAjamEvent" Тогда // проверим ответ от нашей ли компоненты? | ||
- | |||
- | Если Событие="Error" | ||
- | Возврат; // тут надо разбираться в причинах сбоя, иногда они штатные и требуют просто переподключения компоненты. | ||
- | КонецЕсли; | ||
- | |||
- | //ПРИМЕР ОТВЕТА | ||
- | Попытка | ||
- | Если Событие="Hangup" Тогда //Положили трубку | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" | ||
- | //<generic | ||
- | //event='Hangup' | ||
- | //privilege='call,all' | ||
- | //sequencenumber='53031' | ||
- | //file='channel.c' | ||
- | //line='1901' | ||
- | //func='ast_hangup' | ||
- | //channel='SIP/263-0000013c' | ||
- | //uniqueid='1322225501.546' | ||
- | //calleridnum='263' | ||
- | //calleridname='<unknown>' | ||
- | //cause='16' | ||
- | //cause_txt='Normal Clearing' | ||
- | ///> | ||
- | |||
- | ИначеЕсли Событие="Bridge" Тогда //2 абонента соеденились и разговаривают | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" исходящий звонок с 263 на 04 | ||
- | //<generic | ||
- | //event='Bridge' | ||
- | //privilege='call,all' | ||
- | //sequencenumber='56804' | ||
- | //file='channel.c' | ||
- | //line='5345' | ||
- | //func='manager_bridge_event' | ||
- | //bridgestate='Link' | ||
- | //bridgetype='core' | ||
- | //channel1='SIP/263-0000014b' | ||
- | //channel2='SIP/04-0000014c' | ||
- | //uniqueid1='1322226827.577' | ||
- | //uniqueid2='1322226827.578' | ||
- | //callerid1='263' | ||
- | //callerid2='04' | ||
- | ///> | ||
- | |||
- | //Пример ответа Входящий звонок с 79265557842 на мультифонтранк | ||
- | //<generic | ||
- | // event='Bridge' | ||
- | // privilege='call,all' | ||
- | // sequencenumber='67966' | ||
- | // file='channel.c' | ||
- | // line='5345' | ||
- | // func='manager_bridge_event' | ||
- | // bridgestate='Link' | ||
- | // bridgetype='core' | ||
- | // channel1='SIP/multifon-out-00000171' | ||
- | // channel2='SIP/263-00000172' | ||
- | // uniqueid1='1322297638.642' | ||
- | // uniqueid2='1322297638.643' | ||
- | // callerid1='79265557842' | ||
- | // callerid2='263' | ||
- | // /> | ||
- | |||
- | ИначеЕсли Событие="Unlink" Тогда | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" | ||
- | // <generic | ||
- | // event='Unlink' | ||
- | // privilege='call,all' | ||
- | // channel1='SIP/263-000000e0' | ||
- | // channel2='SIP/17-000000e1' | ||
- | // uniqueid1='1322828367.324' | ||
- | // uniqueid2='1322828367.325' | ||
- | // callerid1='263' | ||
- | // callerid2='17' | ||
- | // /> | ||
- | |||
- | ИначеЕсли Событие="Dial" Тогда //Входящий звонок до поднятия трубочки | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" при внешнем входящем звонке с номера 79265557842 на мультифон транк | ||
- | //<generic | ||
- | // event='Dial' | ||
- | // privilege='call,all' | ||
- | // sequencenumber='67955' | ||
- | // file='app_dial.c' | ||
- | // line='695' | ||
- | // func='senddialevent' | ||
- | // subevent='Begin' | ||
- | // channel='SIP/multifon-out-00000171' | ||
- | // destination='SIP/263-00000172' | ||
- | // calleridnum='79265557842' | ||
- | // calleridname='MIKOKONTRAGENT' | ||
- | // uniqueid='1322297638.642' | ||
- | // destuniqueid='1322297638.643' | ||
- | // dialstring='263' | ||
- | // /> | ||
- | |||
- | ИначеЕсли Событие="PeerStatus" Тогда | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" | ||
- | //<generic | ||
- | //event='PeerStatus' | ||
- | //privilege='system,all' | ||
- | //sequencenumber='56136' | ||
- | //file='chan_sip.c' | ||
- | //line='12937' | ||
- | //func='parse_register_contact' | ||
- | //channeltype='SIP' | ||
- | //peer='SIP/261' | ||
- | //peerstatus='Registered' | ||
- | //address='172.16.32.123' | ||
- | //port='51789' | ||
- | // /> | ||
- | |||
- | ИначеЕсли Событие="VarSet" Тогда | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" | ||
- | //<generic | ||
- | //event='VarSet' | ||
- | //privilege='dialplan,all' | ||
- | //sequencenumber='54665' | ||
- | //file='pbx.c' | ||
- | //line='9141' | ||
- | //func='pbx_builtin_setvar_helper' | ||
- | //channel='Local/79265557842@from-internal-74f9;2' | ||
- | //variable='MACRO_DEPTH' | ||
- | //value='1' | ||
- | //uniqueid='1322226019.562' | ||
- | // /> | ||
- | ИначеЕсли Событие="Newchannel" Тогда | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" Звоню с номера 263 на номер 17 | ||
- | //<generic | ||
- | // event='Newchannel' | ||
- | // privilege='call,all' | ||
- | // sequencenumber='83247' | ||
- | // file='channel.c' | ||
- | // line='978' | ||
- | // func='__ast_channel_alloc_ap' | ||
- | // channel='SIP/263-000001ca' | ||
- | // channelstate='0' | ||
- | // channelstatedesc='Down' | ||
- | // calleridnum='263' | ||
- | // calleridname='device' | ||
- | // accountcode='' | ||
- | // exten='17' | ||
- | // context='from-internal' | ||
- | // uniqueid='1322315915.748' /> | ||
- | // /> | ||
- | |||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" Звоню с номера 74997623634 на номер 229-30-42 оператора МАНГО | ||
- | //<generic | ||
- | //event='Newchannel' | ||
- | //privilege='call,all' | ||
- | //channel='SIP/mangotrunk-0000016b' | ||
- | //channelstate='0' | ||
- | //channelstatedesc='Down' | ||
- | //calleridnum='74997623634' | ||
- | //calleridname='74997623634' | ||
- | //accountcode='' | ||
- | //exten='info' | ||
- | //context='from-trunk-sip-mangotrunk' | ||
- | //uniqueid='1323941846.598' /> | ||
- | |||
- | ИначеЕсли Событие="Newstate" Тогда | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" | ||
- | //<generic | ||
- | //event='Newstate' | ||
- | //privilege='call,all' | ||
- | //sequencenumber='56419' | ||
- | //file='channel.c' | ||
- | //line='5082' | ||
- | //func='ast_setstate' | ||
- | //channel='SIP/17-0000014a' | ||
- | //channelstate='5' | ||
- | //channelstatedesc='Ringing' | ||
- | //calleridnum='17' | ||
- | //calleridname='' | ||
- | //uniqueid='1322226729.576' | ||
- | // /> | ||
- | |||
- | ИначеЕсли Событие="Newexten" Тогда | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" | ||
- | //<generic | ||
- | //event='Newexten' | ||
- | //privilege='dialplan,all' | ||
- | //sequencenumber='53042' | ||
- | //file='pbx.c' | ||
- | //line='3725' | ||
- | //func='pbx_extension_helper' | ||
- | //channel='SIP/263-0000013b' | ||
- | //context='from-internal' | ||
- | //extension='h' | ||
- | //priority='1' | ||
- | //application='Hangup' | ||
- | //appdata='' | ||
- | //uniqueid='1322225501.545' | ||
- | ///> | ||
- | ИначеЕсли Событие="NewCallerid" Тогда | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" | ||
- | //<generic | ||
- | //event='NewCallerid' | ||
- | //privilege='call,all' | ||
- | //sequencenumber='54753' | ||
- | //file='channel.c' | ||
- | //line='4727' | ||
- | //func='report_new_callerid' | ||
- | //channel='SIP/multifon-out-00000144' | ||
- | //calleridnum='79036288313' | ||
- | //calleridname='' | ||
- | //uniqueid='1322226019.564' | ||
- | //cid_callingpres='0 (Presentation Allowed, Not Screened)' | ||
- | // /> | ||
- | |||
- | ИначеЕсли Событие="Registry" Тогда | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" | ||
- | //<generic | ||
- | //event='Registry' | ||
- | //privilege='system,all' | ||
- | //sequencenumber='56138' | ||
- | //file='chan_sip.c' | ||
- | //line='18725' | ||
- | //func='handle_response_register' | ||
- | //channeltype='SIP' | ||
- | //domain='sbc.megafon.ru' | ||
- | //status='Registered' | ||
- | // /> | ||
- | ИначеЕсли Событие="ExtensionStatus" Тогда | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" | ||
- | //<generic | ||
- | //event='ExtensionStatus' | ||
- | //privilege='call,all' | ||
- | //sequencenumber='54947' | ||
- | //file='manager.c' | ||
- | //line='3518' | ||
- | //func='manager_state_cb' | ||
- | //exten='02' | ||
- | //context='ext-local' | ||
- | //hint='SIP/02' | ||
- | //status='0' | ||
- | // /> | ||
- | ИначеЕсли Событие="Cdr" Тогда | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" | ||
- | //<generic | ||
- | //event='Cdr' | ||
- | //privilege='cdr,all' | ||
- | //sequencenumber='53045' | ||
- | //file='cdr_manager.c' | ||
- | //line='189' | ||
- | //func='manager_log' | ||
- | //accountcode='' | ||
- | //source='263' | ||
- | //destination='263' | ||
- | //destinationcontext='from-internal' | ||
- | //callerid='"WORK Vasiliy Pupkin" <263>' | ||
- | //channel='SIP/263-0000013b' | ||
- | //destinationchannel='SIP/263-0000013c' | ||
- | //lastapplication='Dial' | ||
- | //lastdata='SIP/263,,tr' | ||
- | //starttime='2011-11-25 16:51:41' | ||
- | //answertime='' | ||
- | //endtime='2011-11-25 16:51:43' | ||
- | //duration='2' | ||
- | //billableseconds='0' | ||
- | //disposition='NO ANSWER' | ||
- | //amaflags='DOCUMENTATION' | ||
- | //uniqueid='1322225501.545' | ||
- | //userfield='' | ||
- | // /> | ||
- | ИначеЕсли Событие="SkypeBuddyStatus" Тогда | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" | ||
- | //<generic | ||
- | //event='SkypeBuddyStatus' | ||
- | //privilege='system,all' | ||
- | //sequencenumber='54952' | ||
- | //file='chan_skype.c' | ||
- | //line='3239' | ||
- | //func='buddy_state_change' | ||
- | //buddy='Skype/miko_team@boffart' | ||
- | //buddystatus='Online' | ||
- | // /> | ||
- | ИначеЕсли Событие="SkypeChatMessage" Тогда | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" | ||
- | //<generic | ||
- | //event='SkypeChatMessage' | ||
- | //privilege='system,all' | ||
- | //sequencenumber='56124' | ||
- | //file='chan_skype.c' | ||
- | //line='871' | ||
- | //func='new_chat_message' | ||
- | //to='miko_team' | ||
- | //from='jorikfon' | ||
- | //message='Privet Chuvak' | ||
- | // /> | ||
- | ИначеЕсли Событие="ReceiveFAX" Тогда | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" | ||
- | //<generic | ||
- | // event='ReceiveFAX' | ||
- | // privilege='call,all' | ||
- | // sequencenumber='508724' | ||
- | // file='res_fax.c' | ||
- | // line='1654' | ||
- | // func='receivefax_exec' | ||
- | // channel='SIP/mangotrunk-00000a37' | ||
- | // context='ext-fax' | ||
- | // exten='s' | ||
- | // callerid='A16551705P1' | ||
- | // remotestationid='(null)' | ||
- | // localstationid='(null)' | ||
- | // pagestransferred='0' | ||
- | // resolution='(null)' | ||
- | // transferrate='(null)' | ||
- | // filename='/var/spool/asterisk/fax/1322812029.3901.tif' | ||
- | // /> | ||
- | |||
- | ИначеЕсли Событие="SendFAX" Тогда | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" | ||
- | // <generic | ||
- | // event='SendFAX' | ||
- | // privilege='call,all' | ||
- | // sequencenumber='506205' | ||
- | // file='res_fax.c' | ||
- | // line='2155' | ||
- | // func='sendfax_exec' | ||
- | // channel='SIP/263-00000a31' | ||
- | // context='amidll' | ||
- | // exten='333' | ||
- | // callerid='263' | ||
- | // remotestationid='(null)' | ||
- | // localstationid='(null)' | ||
- | // pagestransferred='0' | ||
- | // resolution='(null)' | ||
- | // transferrate='(null)' | ||
- | // filename='/var/spool/asterisk/tmp/SIP-261-fax.tif' | ||
- | // /> | ||
- | ИначеЕсли Событие="RTPReceiverStat" Тогда | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" | ||
- | //<generic event='RTPReceiverStat' | ||
- | //privilege='reporting,all' | ||
- | //ssrc='0' | ||
- | //receivedpackets='0' | ||
- | //lostpackets='0' | ||
- | //jitter='0.0000' | ||
- | //transit='0.0000' | ||
- | //rrcount='0' /> | ||
- | ИначеЕсли Событие="RTPSenderStat" Тогда | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" | ||
- | //<generic | ||
- | //event='RTPSenderStat' | ||
- | //privilege='reporting,all' | ||
- | //ssrc='901146673' | ||
- | //sentpackets='0' | ||
- | //lostpackets='0' | ||
- | //jitter='0' | ||
- | //srcount='0' | ||
- | //rtt='0.000000' | ||
- | ///> | ||
- | ИначеЕсли Событие="ChannelUpdate" Тогда | ||
- | //ПРИМЕР ОТВЕТА В ПЕРЕМЕННОЙ "ДАННЫЕ" | ||
- | //<generic | ||
- | //event='ChannelUpdate' | ||
- | //privilege='system,all' | ||
- | //channel='SIP/261-00000164' | ||
- | //uniqueid='1323940821.591' | ||
- | //channeltype='SIP' | ||
- | //sipcallid='NvKuRBoMgAVDmxHbntsStBfN9DbmGvMH' | ||
- | //sipfullcontact='sip:261@192.168.1.122:49935;transport=TCP' | ||
- | ///> | ||
- | |||
- | КонецЕсли; // По виду события | ||
- | |||
- | КонецЕсли; | ||
- | |||
- | КонецПроцедуры | ||
- | </code> | ||
- | |||
- | | ||
- | В приведенном выше коде мы проиллюстрировали возможный вариант обработки внешних событий компонента. Данные переданные в параметр *Данные* представляют из себя XML структуру которую можно разобрать используя функцию ЧтениеXML языка 1С:Предрпиятие 8. | ||
- | |||
- | |||
- | Пример разбора ответа используя объект ЧтениеXML: | ||
- | <code 1c> | ||
- | ЧтениеXML = Новый ЧтениеXML; | ||
- | ЧтениеXML.УстановитьСтроку(Данные); | ||
- | CallerID1 = ЧтениеXML.ЗначениеАтрибута("Callerid1"); | ||
- | CallerID2 = ЧтениеXML.ЗначениеАтрибута("Callerid2"); | ||
- | Channel1 = ЧтениеXML.ЗначениеАтрибута("Channel1"); | ||
- | Channel2 = ЧтениеXML.ЗначениеАтрибута("Channel2"); | ||
- | UniqueID1 = ЧтениеXML.ЗначениеАтрибута("Uniqueid1"); | ||
- | UniqueID2 = ЧтениеXML.ЗначениеАтрибута("Uniqueid2"); | ||
- | |||
- | </code> | ||
- | | ||
- | | ||
- | <note important>Объект ЧтениеXML не доступен в режиме веб клиента, потому при использовании такого режима нужно обходиться другими способами разбора строк.</note> | ||
- | | ||
- | |||
- | Например при использовании WEB клиента Mozilla Firefox мы реализовали разбор ответа следующим образом: | ||
- | <code 1c> | ||
- | &НаКлиенте | ||
- | Процедура ВнешнееСобытие(Источник, Событие, Данные) | ||
- | |||
- | Если Источник="MikoAjamEvent" Тогда // проверим ответ от нашей ли компоненты? | ||
- | СтруктураПолей=РазобратьОтветАстериска(Данные); | ||
- | |||
- | CallerID1 = СтруктураПолей.Получить("callerid1"); | ||
- | CallerID2 = СтруктураПолей.Получить("callerid2"); | ||
- | channel1 = СтруктураПолей.Получить("channel1"); | ||
- | КонецЕсли; | ||
- | Конецпроцедуры; | ||
- | |||
- | &НаКлиенте | ||
- | // разбирает строку XML в соответсвие ключ - значение | ||
- | Функция РазобратьОтветАстериска(Данные) | ||
- | СимволДвоеточиеПробел="="; | ||
- | МассивПодстрок=РазложитьСтрокуВМассивПодстрок(Данные," "); | ||
- | |||
- | ПараметрыОтвета=Новый Соответствие; | ||
- | Для к=0 по МассивПодстрок.Количество()-1 Цикл | ||
- | СтрокаДляРазбора = СокрЛП(МассивПодстрок[к]); | ||
- | ПозицияРазделителя = Найти(СтрокаДляРазбора,СимволДвоеточиеПробел); | ||
- | ДлинаСтроки = СтрДлина(СтрокаДляРазбора); | ||
- | Если ПозицияРазделителя<>0 Тогда | ||
- | Параметр=Лев(СтрокаДляРазбора,ПозицияРазделителя-1); | ||
- | Значение=Прав(СтрокаДляРазбора,ДлинаСтроки-ПозицияРазделителя-1); | ||
- | Значение=Лев(Значение,СтрДлина(Значение)-1); | ||
- | ПараметрыОтвета.Вставить(Параметр,Значение); | ||
- | КонецЕсли; | ||
- | |||
- | КонецЦикла; | ||
- | Возврат ПараметрыОтвета; | ||
- | КонецФункции //РазобратьОтветАстериска | ||
- | |||
- | &НаКлиенте | ||
- | //Переданную строку, разбивает в массив | ||
- | Функция РазложитьСтрокуВМассивПодстрок(Знач Стр, Разделитель = ",") Экспорт | ||
- | |||
- | МассивСтрок = Новый Массив(); | ||
- | Если Разделитель = " " Тогда | ||
- | Стр = СокрЛП(Стр); | ||
- | Пока Истина Цикл | ||
- | Поз = Найти(Стр,Разделитель); | ||
- | Если Поз=0 Тогда | ||
- | МассивСтрок.Добавить(Стр); | ||
- | Возврат МассивСтрок; | ||
- | КонецЕсли; | ||
- | МассивСтрок.Добавить(Лев(Стр,Поз-1)); | ||
- | Стр = СокрЛ(Сред(Стр,Поз)); | ||
- | КонецЦикла; | ||
- | Иначе | ||
- | ДлинаРазделителя = СтрДлина(Разделитель); | ||
- | Пока Истина Цикл | ||
- | Поз = Найти(Стр,Разделитель); | ||
- | Если Поз=0 Тогда | ||
- | МассивСтрок.Добавить(Стр); | ||
- | Возврат МассивСтрок; | ||
- | КонецЕсли; | ||
- | МассивСтрок.Добавить(Лев(Стр,Поз-1)); | ||
- | Стр = Сред(Стр,Поз+ДлинаРазделителя); | ||
- | КонецЦикла; | ||
- | КонецЕсли; | ||
- | |||
- | КонецФункции // РазложитьСтрокуВМассивПодстрок | ||
- | |||
- | </code> | ||
- | |||
- | |||
- | ===== Полезные ссылки ===== | ||
- | * [[doc:1cajam|SDK: Компонента связи 1C и Asterisk]] | ||
- | * [[doc:1cajam:api|Описание функций реализованных в SDK: Компонента связи 1С и Asterisk]] | ||
- | * [[kb:asterisk:events|Asterisk Manager: Events]] | ||
- | |||