Инструменты пользователя

Инструменты сайта


doc:1cajam:listening

Прослушивание событий, передаваемых сервером Asterisk из 1С

После инициализации и авторизации компонента на сервере Asterisk между компонентом и сервером устанавливается HTTP соединение, по которому сервер телефонии передает информацию о текущем состоянии каналов, вызовов, а так же результат выполнения различных команд. Полученные ответы разбираются компонентом при помощи встроенного XML парсера и вызывают в сеансе 1С:Предприятия встроенную функцию *ВнешнееСобытие*.

Вызов функции возникает при посылке внешним приложением сообщения, сформированного в специальном формате. Внешнее событие сначала обрабатывается всеми открытыми формами, имеющими обработчик этого события, а затем может быть обработано в процедуре модуля обычного приложения с именем ОбработкаВнешнегоСобытия.

Таким образом, все события компонента можно обработать в любой открытой форме или в модуле обычного приложения. В качестве переменных используются 3 строковых параметра:

  • Источник - Источник внешнего события.
  • Событие - Наименование события.
  • Данные - Данные для события.

В параметр *Источник* всегда передается строка MikoAjamEvent которая позволяет однозначно идентифицировать события отправленные компонентой. В параметр *Событие* передается наименование события Asterisk или строки Error, Exeption, свидетельствующие о возникновении нештатной ситуации, например разрыв связи с Asterisk. В параметр *Данные* передается XML строка, содержащая весь пакет данных, полученных от сервера Acterisk без каких либо модификаций или техническую информацию о ошибке в работе компонента.

Стандартный вид обработки внешнего события компоненты выглядит так:

Процедура ВнешнееСобытие(Источник, Событие, Данные)
 
	Если Источник="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='&lt;unknown&gt;' 
				//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='&quot;WORK Vasiliy Pupkin&quot; &lt;263&gt;' 
				//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'
				///>
 
			КонецЕсли; // По виду события
 
	КонецЕсли; 
 
КонецПроцедуры

В приведенном выше коде мы проиллюстрировали возможный вариант обработки внешних событий компонента. Данные, переданные в параметр *Данные*, представляют из себя XML структуру, которую можно разобрать, используя функцию ЧтениеXML языка 1С:Предприятие 8.

Пример разбора ответа используя объект ЧтениеXML:

        ЧтениеXML = Новый ЧтениеXML;
	ЧтениеXML.УстановитьСтроку(Данные);
        CallerID1	=    ЧтениеXML.ЗначениеАтрибута("Callerid1");
	CallerID2	=    ЧтениеXML.ЗначениеАтрибута("Callerid2");
	Channel1	=    ЧтениеXML.ЗначениеАтрибута("Channel1");
	Channel2	=    ЧтениеXML.ЗначениеАтрибута("Channel2");
	UniqueID1	=    ЧтениеXML.ЗначениеАтрибута("Uniqueid1");
	UniqueID2	=    ЧтениеXML.ЗначениеАтрибута("Uniqueid2");

Объект ЧтениеXML не доступен в режиме веб клиента, потому при использовании такого режима нужно обходиться другими способами разбора строк.

Например, при использовании WEB клиента Mozilla Firefox мы реализовали разбор ответа следующим образом:

&НаКлиенте
Процедура ВнешнееСобытие(Источник, Событие, Данные)
 
	Если Источник="MikoAjamEvent" Тогда  // проверим ответ от нашей ли компоненты?	
		СтруктураПолей=РазобратьОтветАстериска(Данные);
 
		CallerID1	=   СтруктураПолей.Получить("callerid1");
		CallerID2	=   СтруктураПолей.Получить("callerid2");
		channel1	=   СтруктураПолей.Получить("channel1");
        КонецЕсли;
Конецпроцедуры;
 
&НаКлиенте
// разбирает строку XML в соответсвие ключ - значение
Функция РазобратьОтветАстериска(Данные)
	СимволДвоеточиеПробел="=";
	МассивПодстрок=РазложитьСтрокуВМассивПодстрок(Данные," ");
 
	ПараметрыОтвета=Новый Соответствие;
	Для к=0 по МассивПодстрок.Количество()-1 Цикл
		СтрокаДляРазбора	= СокрЛП(МассивПодстрок[к]);
		ПозицияРазделителя	= Найти(СтрокаДляРазбора,СимволДвоеточиеПробел);
		ДлинаСтроки			= СтрДлина(СтрокаДляРазбора);
		Если ПозицияРазделителя<>0 Тогда
			Параметр=Лев(СтрокаДляРазбора,ПозицияРазделителя-1);
			Значение=Прав(СтрокаДляРазбора,ДлинаСтроки-ПозицияРазделителя-1);
			Значение=Лев(Значение,СтрДлина(Значение)-1);
			ПараметрыОтвета.Вставить(Параметр,Значение);
		КонецЕсли;	
 
	КонецЦикла;	
	Возврат ПараметрыОтвета;
КонецФункции //РазобратьОтветАстериска	
 
&НаКлиенте
//Переданную строку, разбивает в массив
Функция РазложитьСтрокуВМассивПодстрок(Знач Стр, Разделитель = ",") Экспорт
 
	МассивСтрок = Новый Массив();
	Если Разделитель = " " Тогда
		Стр = СокрЛП(Стр);
		Пока Истина Цикл
			Поз = Найти(Стр,Разделитель);
			Если Поз=0 Тогда
				МассивСтрок.Добавить(Стр);
				Возврат МассивСтрок;
			КонецЕсли;
			МассивСтрок.Добавить(Лев(Стр,Поз-1));
			Стр = СокрЛ(Сред(Стр,Поз));
		КонецЦикла;
	Иначе
		ДлинаРазделителя = СтрДлина(Разделитель);
		Пока Истина Цикл
			Поз = Найти(Стр,Разделитель);
			Если Поз=0 Тогда
				МассивСтрок.Добавить(Стр);
				Возврат МассивСтрок;
			КонецЕсли;
			МассивСтрок.Добавить(Лев(Стр,Поз-1));
			Стр = Сред(Стр,Поз+ДлинаРазделителя);
		КонецЦикла;
	КонецЕсли;
 
КонецФункции // РазложитьСтрокуВМассивПодстрок

Полезные ссылки

Комментарии

doc/1cajam/listening.txt · Последние изменения: 2014/11/14 22:32 (внешнее изменение)