Cisco Connect...Гость: звонит наURI [email protected], одно большое окно...
Transcript of Cisco Connect...Гость: звонит наURI [email protected], одно большое окно...
CiscoConnectМосква, 2017
Цифровизация: здесь и сейчас
Часть 2. API Cisco MeetingServer. Когда необходимо его использовать. Использования API в скриптах python. Пример совместного использования с In-room control.
© 2017 Cisco and/or its affiliates. All rights reserved.
Юцайтис Сергей
Консультант по технологиям совместной работы
CMS использует API для настройки не стандартных конфигураций, для обеспечения интеграции с другими решениями и для предоставления информации другим устройствам и приложениям.
CMS поддерживает RESTful API или ‘Rest API’ (сокр. от англ. Representational State Transfer — «передача состояния представления»)
Практически все серверные приложения и сервисы сегодня поддерживают ту или иную форму API, но обычно API используют для собственных нужд разработчиков (например интеграции с другими продуктами производителя). Поэтому использование API может лицензироваться отдельно, либо он может иметь ограниченные возможности.
Acano изначально приняло решение о поддержки открытого APIs в котором любое действие доступно без каких либо лицензионных или других отчислений и выплат, даже на демонстрационной VM. Эту традицию мы продолжим с CMS.
Работа с API обычно выполняется через выполнение вызовов (‘API Call’)
Можно например сделать API вызов для создания конференции (Space)
Множество API вызовов может быть сделано одновременно, что позволяет, например, автоматизировать их запуск скриптом. Последовательное выполнение API вызовов в составе скрипта может быть существенно более быстрым чем в ручном режиме.
Можно использовать разные языки программирования для работы с APIs, но так исторически сложилось, что программисты Acano в основном использовали Python.
Существуют примеры с использованием Java, Powershell, Curl, Ruby, HTTP, PHP, и многие другие.
Вы можете выполнять API вызовы прямо из браузера используя такие расширения как POSTer, POSTman иAdvanced Rest Client.
API вызовы
Доступные API вызовы• /accessQuery
• /callBrandingProfiles
• /callBrandingProfiles/<call branding profile id>
• /callBridges
• /callBridges/<call bridge id>
• /calls
• /calls/<call id>
• /calls/<call id>/callLegs
• /calls/<call id>/participants
• /callLegs
• /callLegs/<callLeg id>
/callLegs/<callLeg id>/callLegProfileTrace
/callLegProfiles
• /callLegProfiles/<call leg profile id>
/callLegProfiles/<call leg profile id>/usage
• /callProfiles
/callProfiles/<call profile id>
• /coSpaces
• /coSpaces/<coSpace id>
• /coSpaces/<coSpace id>/coSpaceUsers
• /coSpaces/<coSpace id>/coSpaceUsers/<coSpaceUser id>
• /coSpaces/<coSpace id>/messages
• /coSpaces/<coSpace id>/accessMethods
/coSpaces/<coSpace id>/accessMethods/<access method id>
• /dialTransforms
/dialTransforms/<dial transform id>
• /dtmfProfiles
/dtmfProfiles/<dtmf profile id>
• /directorySearchLocations
• /directorySearchLocations/<directory search location id>
• /forwardingDialPlanRules
• /forwardingDialPlanRules/<forwarding dial plan rule id>
• /inboundDialPlanRules
• /inboundDialPlanRules/<inbound dial plan rule id>
• /outboundDialPlanRules
• /outboundDialPlanRules/<outbound dial plan rule id>
• /ivrs
• /ivrs/<ivr id>
/ivrBrandingProfiles
/ivrBrandingProfiles/<ivr branding profile id>
• /ldapMappings
• /ldapMapping/<ldap mapping id>
• /ldapServers
• /ldapServers/<ldap server id>
• /ldapSources
• /ldapSources/<ldap source id>
• /ldapSyncs
• /ldapSyncs/<ldap sync id>
• /participants
• /participants/<participant id>
• /participants/<participant id>/callLegs
• /system/alarms
• /system/configuration/cluster
• /system/configuration/xmpp
• /system/database
• /system/status
• /system/profiles
• /system/cdrReceiver
• /tenants
• /tenants/<tenant id>
• /turnServers
• /turnServers/<turn server id>
• /turnServers/<turn server id>/status
/users
• /users/<user id>
• /users/<user id>/usercoSpaces
/userProfiles
/userProfiles/<user profile id>
/webBridges
• /webBridges/<web bridge id>
/webBridges/<web bridge id>/updateCustomization
• И другие ,,,,
coSpace
UricallId
Owner (Id, Jd)Secret
defaultLayout
coSpaceUsers
User (Id, Jd)callLegProfile
canDestroycanAddRemoveMembercanChangeNamecanChangeUricanChangeCallIdcanChangePasscodecanPostMessagecanRemoveSelfcanDeleteAllMessages
accessMethods
URI / passcode / callIDSecretScope
Call Leg ProfileneedsActivationdefaultLayout changeLayoutAllowed participantLabels presentationDisplayModepresentationContributionAllowed presentationViewingAllowed endCallAllowedmuteOthersAllowed videoMuteOthersAllowed muteSelfAllowed videoMuteSelfAllowedjoinToneParticipantThreshold leaveToneParticipantThreshold videoModerxAudioMutetxAudioMuterxVideoMutetxVideoMute sipMediaEncryption audioPacketSizeMs deactivationModedeactivationModeTime telepresenceCallsAllowed sipPresentationChannelEnabledbfcpMode
system/profiles
callLegProfilecallProfile
dtmfProfile
Messages (post)Message, from(delete)minAge, maxAge
7
Что было сделано и что можно сделать с использованием CMS (ACANO) API?
• Проведено большое количество интеграций, решающих специфичные для
разных Заказчиков задачи или ориентированные на работу с их
собственными продуктами
• Что еще сделано:
– Созданы тысячи Spaces с использованием CSV файлов для Заказчиков
не использующих LDAP
– Реализованы проекты с автоматическим созданием Spaces по Multi-
way технологии
– Менялись PIN коды для каждого Space на сервере
– По нажатию клавиши менялись экранные раскладки для всех
подключенных участников конференции, за исключением презентора
– Интегрировались с SFDC, создавая Space для каждого пользователя
– Интеграция с Amazon Echo (Alexa) для управления конференции с
помощью голосовых команд
– Интеграция с Cisco Spark для управленияl Spaces через Spark
сообщения
– IFTTT интеграция с использованием различных каналов
– И многое другое…
В первых версиях Acano интеграция с Amazon Echo позволяла пользователям посредством голосовых команд начинать встречи, выполнять исходящие вызовы,управлять экранными раскладками, выключать голос, видео и отключать абонентов, завершать конференции.
Пример – Amazon Echo для управления конференциями
Руководство по программированию CMS API
http://www.cisco.com/c/en/us/support/conferencing/meeting-server/products-programming-reference-guides-list.html
http://www.cisco.com/c/dam/en/us/td/docs/conferencing/ciscoMeetingServer/Reference_Guides/Version-2-1/Cisco-Meeting-Server-API-Reference-Guide-2-1.pdf
https://www.acano.com/support/documentation/
Рекомендуется использовать руководства API последней версии продукта.
Руководство содержит все необходимые материалы и команды, поддержанные в API CMS.
До сих пор не было изменений в правилах использования API или планов изменить их. Полный набор команд доступен в демо версиях, триальных версиях Acano и не лицензируется.
CMS API Guide
Нам необходимо оперировать 4-мя типами запросов:
GET – вывести (считать) информацию
POST – создать новую запись
PUT – изменить существующую запись
DELETE – удалить существующую запись
Инструменты
Bеб браузерЛично я рекомендую Chrome : http://getchrome.com
Python 3.5+https://www.python.org/downloads/release/python-351/
РедакторЛюбой удобный Вам текстовый редактор (советую выбирать понимающий ключевые операторы языков высокого уровня - например TextWrangler) или Integrated Development Environment (Я использую PyCharm)Можно использовать IDLE, который устанавливает Python
Githttp://git-scm.com/
PostmanСкачайте из Chrome Web Store или (рекомендую именно этот вариант) – отдельно устанавливаемую версию http://www.getpostman.com/
Можно скачать приложения, коллекцию postman для CMS2.1 и примеры кода с моего файла обменного ящика:
https://cisco.box.com/v/sergey
Postman – использование коллекций:
Находим CallProfile по умолчанию:
Включаем в нем messageBoard:
Проверяем сделанную запись:
dtmfProfile:
<?xml version="1.0"?><dtmfProfile id="722b45a2-1784-4060-bdf2-1d88df5c7818">
<muteSelfAudio></muteSelfAudio><unmuteSelfAudio>0</unmuteSelfAudio><toggleMuteSelfAudio></toggleMuteSelfAudio><lockCall></lockCall><unlockCall></unlockCall><muteAllExceptSelfAudio></muteAllExceptSelfAudio><unmuteAllExceptSelfAudio></unmuteAllExceptSelfAudio><endCall></endCall><nextLayout>8</nextLayout><previousLayout>2</previousLayout><startRecording>*1</startRecording><stopRecording>*0</stopRecording><startStreaming></startStreaming><stopStreaming></stopStreaming><allowAllMuteSelf></allowAllMuteSelf><cancelAllowAllMuteSelf></cancelAllowAllMuteSelf><allowAllPresentationContribution></allowAllPresentationContribution><cancelAllowAllPresentationContribution></cancelAllowAllPresentationContribution><muteAllNewAudio></muteAllNewAudio><unmuteAllNewAudio></unmuteAllNewAudio><defaultMuteAllNewAudio></defaultMuteAllNewAudio><muteAllNewAndAllExceptSelfAudio></muteAllNewAndAllExceptSelfAudio><unmuteAllNewAndAllExceptSelfAudio></unmuteAllNewAndAllExceptSelfAudio>
</dtmfProfile>
СallLegProfile:
https://10.100.1.227:9443/api/v1/callLegProfiles/ac0485e3-a3b7-47cf-91fe-ffa25ea5d795
<?xml version="1.0"?><callLegProfile id="ac0485e3-a3b7-47cf-91fe-ffa25ea5d795">
<defaultLayout>onePlusFive</defaultLayout> - экранная раскладка<participantLabels>true</participantLabels> - показывать имена участников<sipMediaEncryption>optional</sipMediaEncryption><muteOthersAllowed>true</muteOthersAllowed> - разрешать выключать звук другим участникам<videoMuteOthersAllowed>true</videoMuteOthersAllowed> - разрешать выключать видео другим участникам<muteSelfAllowed>true</muteSelfAllowed><videoMuteSelfAllowed>true</videoMuteSelfAllowed><disconnectOthersAllowed>true</disconnectOthersAllowed> - разрешать отключать других участников<telepresenceCallsAllowed>false</telepresenceCallsAllowed><sipPresentationChannelEnabled>true</sipPresentationChannelEnabled><changeLayoutAllowed>true</changeLayoutAllowed> - разрешать менять свою экранную раскладку<bfcpMode>serverAndClient</bfcpMode>
</callLegProfile>
Управление участником конференции из видео окна приложения:
Планирование CMS 2.0 c TMS 15.3
Выполнение исходящего вызова
Продление конференции
Завершение/ удалениеконференции
GET https://10.100.1.227:9443/api/v1/Cospaces
<coSpace id="4a5d366d-1b73-4c55-baa1-c323e90d70cb"><name>TMS_Scheduled_Meeting_5590001</name><autoGenerated>false</autoGenerated><uri>5590001</uri><callId>5590001</callId>
</coSpace>
POST https://10.100.1.227:9443/api/v1/Cospaces/4a5d366d-1b73-4c55-baa1-c323e90d70cb/coSpaceUsers
userJid = admin@domain
Установка для администратора или оператора прав владельца конференции
Режим лектора
CMS
В текущей версии 2.0 на CMS не реализован режим лектора.
Но, если допускается подключения лектора и аудитории с использованием разных номеров (URI) – его можно реализовать через API (а с версии 2.1 – разных паролей (или пароль/без пароля))
Лектор: звонит на URI [email protected], раскладка - квадратор, видит всех участников, микрофон активен
Гость: звонит на URI [email protected], одно большое окно с говорящим (лектором), микрофон выключен, если Лектор отключен – видео и голос не принимается сервером
Режим лектора1. Создайте новый space с аккаунтом лектора в профиле
2. Создайте профиль соединения для Лектора (Call Leg Profile): POST https://example.com/api/v1/callLegProfiles defaultLayout=allEqual
3. Создайте профиль соединения для гостя: POST https://example.com/api/v1/callLegProfiles needsActivation=true&defaultLayout=speakerOnly&rxAudioMute=true&deactivationMode=deactivate
4. Узнайте идентификаторы профилей соединения (Call Leg Profile): GET https://example.com/api/v1/callLegProfiles
Допустим что Call Leg Profile ID лектора: 360b40bf-4c7d-41ff-a355-496c0e720649Call Leg Profile ID гостя: 5546a47f-262a-4399-a799-0a03ddc2c66c
Узнайте идентификатор space (space ID): GET https://example.com/api/v1/coSpacesДопустим что Space ID: 83b4f7d0-ffb7-4fbc-83c0-91ebe04f2af3
Создайте метод подключения Лектора (Access Method) с URI и Call ID 5500:
POST https:// example.com/api/v1/coSpaces/83b4f7d0-ffb7-4fbc-83c0-91ebe04f2af3/accessMethods
uri=5500&callLegProfile= 360b40bf-4c7d-41ff-a355-496c0e720649&callID=5500(Access Method ID: f3a7cf1a-961f-4fec-b19d-5db558851305 )
Создайте метод подключения гостя (Access Method) с URI и Call ID 5600:
POST https://example.com/api/v1/coSpaces/83b4f7d0-ffb7-4fbc-83c0-91ebe04f2af3/accessMethods
uri=5600&callLegProfile=5546a47f-262a-4399-a799-0a03ddc2c66c&callID=5600 (Access Method ID: 056a58ee-12bc-404f-b863-834cba4707db)
Как в Python сделать REST вызов
Библиотека Python requests
requests – HTTP библиотека Python. Ближайший аналог – urllib2.
Содержит в себе встроенную библиотеку urllib3.
Домашняя страница проекта – http://docs.python-requests.org
Установить requests можно с помощью PIP: $ pip install requests
>>> r = requests.get('https://api.github.com/events')
>>> r = requests.post('http://httpbin.org/post', data = {'key':'value'})
>>> r = requests.put('http://httpbin.org/put', data = {'key':'value'})
>>> r = requests.delete('http://httpbin.org/delete')
Cisco Connect 2017 © 2017 Cisco and/or its affiliates. All rights reserved. 31
Библиотека Python requestsfrom pprint import pprintimport paramikoimport timeimport reimport requestsfrom requests.packages.urllib3.exceptions import InsecureRequestWarning # отключаем предупреждение о не requests.packages.urllib3.disable_warnings(InsecureRequestWarning) # достоверных сертификатах
CMS_BASE='https://10.100.1.227:9443/api/v1/' # Задаем основные параметры (например IP)CMS_HEADERS = {'Content-type': 'application/json', 'authorization': "Basic YWRtaW46QzFzY28xMjM="} # Задаем логин-пароль (берем из postman)
client = paramiko.SSHClient()client.set_missing_host_key_policy(paramiko.AutoAddPolicy())client.connect("10.100.1.147", username="admin", password="C1sco123") # соединение с сервером
channel = client.invoke_shell()channel.send('xst SIP Registration 1 URI\n')time.sleep(0.5)output = channel.recv(2000)
Number = ''.join(re.findall(r'\[email protected]', str(output)))print('номер видеосистемы: ' + ''.join(Number)) # Номер своей видеосистемы нам понадобится для нахождения данных о ее подключении
Cisco Connect 2017 © 2017 Cisco and/or its affiliates. All rights reserved. 32
# calls = requests.get(CMS_BASE + 'calllegs' + '?filter=' + Number, verify=False, headers=CMS_HEADERS)
calls = requests.get(CMS_BASE + 'calllegs' + '?filter=' + Number, verify=False, headers=CMS_HEADERS)
if calls.status_code == 200:pprint("это то, что выдал request.get:" + calls.text)
# Это наш callleg:calleg = ''.join(re.findall(r'<callLeg id="(\w+\-\w+\-\w+\-\w+\-\w+)', calls.text))if len(calleg) > 0:
# Здесь мы подключены к конференции, узнаем все о подключении и конференции
callid = ''.join(re.findall(r'<call>(\w+\-\w+\-\w+\-\w+\-\w+)', calls.text))pprint("Идентификатор подключения: " + calleg)channel.send('xCommand UserInterface Extensions Widget SetValue WidgetId: "info3" Value: "Идентификатор соединения:' + calleg + '"\n')pprint("Идентификатор соединения: " + callid)channel.send('xCommand UserInterface Extensions Widget SetValue WidgetId: "info4" Value: "Идентификатор конференции:' + callid +
'"\n')
def confinfo(a) : return requests.get(CMS_BASE + 'calls/' + a, verify=False, headers=CMS_HEADERS)confinf = confinfo(callid)pprint("Информация о конференции: " + confinf.text)
client.close()
Cisco Connect 2017 © 2017 Cisco and/or its affiliates. All rights reserved. 33
Библиотека Python requests
Кодировка
Cisco Connect 2017 © 2017 Cisco and/or its affiliates. All rights reserved. 34
<?xml version="1.0"?><callLegs total="4">
<callLeg id="9132036b-148f-49a6-9960-7bc90fabbbad"><name>SX10 UGLICH 40210</name><remoteParty>[email protected]</remoteParty><call>ce4a7f5f-4670-4ed8-b822-3e28a0475678</call>
</callLeg><callLeg id="ee4d87a6-f56e-41d5-bd7f-154f672e348d">
<name>SX20 KRASNODAR 40220</name><remoteParty>[email protected]</remoteParty><call>ce4a7f5f-4670-4ed8-b822-3e28a0475678</call>
</callLeg><callLeg id="990a91a7-f571-40ac-8c58-55eb4edab6cf">
<name>Елена Волкова</name><remoteParty>[email protected]</remoteParty><call>ce4a7f5f-4670-4ed8-b822-3e28a0475678</call>
</callLeg><callLeg id="668bffaa-e813-4898-9088-2f671c9a4435">
<name>Петр Петров</name><remoteParty>[email protected]</remoteParty><call>ce4a7f5f-4670-4ed8-b822-3e28a0475678</call>
</callLeg></callLegs>
Кодировка
Cisco Connect 2017 © 2017 Cisco and/or its affiliates. All rights reserved. 35
Кодировка ['SX10 UGLICH 40210', 'SX20 KRASNODAR 40220', 'Ð\x95ленаÐ\x92олкова', 'Ð\x9fеÑ\x82Ñ\x80 Ð\x9fеÑ\x82Ñ\x80ов']
activelegs = requests.get(CMS_BASE + 'calls/' + callid + '/callLegs', verify=False, headers=CMS_HEADERS)activelegs.encoding = 'utf-8'
['SX10 UGLICH 40210', 'SX20 KRASNODAR 40220', 'Елена Волкова', 'Петр Петров']
Cisco Connect 2017 © 2017 Cisco and/or its affiliates. All rights reserved. 36
calls = requests.get(CMS_BASE + 'calllegs' + '?filter=' + Number, verify=False, headers=CMS_HEADERS)
calls.encoding = 'utf-8' # задаем кодировку
if calls.status_code == 200:pprint("это то, что выдал request.get:" + calls.text)
# Это наш callleg:calleg = ''.join(re.findall(r'<callLeg id="(\w+\-\w+\-\w+\-\w+\-\w+)', calls.text))if len(calleg) > 0:
# Здесь мы подключены к конференции, узнаем все о подключении и конференции
callid = ''.join(re.findall(r'<call>(\w+\-\w+\-\w+\-\w+\-\w+)', calls.text))pprint("Идентификатор подключения: " + calleg)channel.send('xCommand UserInterface Extensions Widget SetValue WidgetId: "info3" Value: "Идентификатор соединения:' + calleg + '"\n')pprint("Идентификатор соединения: " + callid)channel.send('xCommand UserInterface Extensions Widget SetValue WidgetId: "info4" Value: "Идентификатор конференции:' + callid + '"\n')
def confinfo(a) : return requests.get(CMS_BASE + 'calls/' + a, verify=False, headers=CMS_HEADERS)confinf = confinfo(callid)pprint("Информация о конференции: " + confinf.text)
client.close()
Библиотека Python requests - кодировка
Cisco Connect 2017 © 2017 Cisco and/or its affiliates. All rights reserved. 37
<callLegs ' 'total="1"><callLeg id="bdac73d6-ec81-422a-bdb3-eadefb234353"><name>SX20 ' 'Room - ' 'Москва</name><remoteParty>[email protected]</remoteParty><call>32a41a3a-076d-4a25-b485-db9f1f1ea067</call></callLeg></callLegs>')
callid = ''.join(re.findall(r'<call>(\w+\-\w+\-\w+\-\w+\-\w+)', calls.text))
Наш Callleg ID: bdac73d6-ec81-422a-bdb3-eadefb234353
Наш Call ID: 32a41a3a-076d-4a25-b485-db9f1f1ea067
calleg = ''.join(re.findall(r'<callLeg id="(\w+\-\w+\-\w+\-\w+\-\w+)', calls.text))
'Информация о конференции: <?xml version="1.0"?><call ' 'id="32a41a3a-076d-4a25-b485-db9f1f1ea067"><coSpace>202a6e1c-b65b-4c29-a2eb-234925419eb2</coSpace><callCorrelator>0704eef6-4c7c-4215-8903-2459d1a1efb5</callCorrelator><durationSeconds>2428</durationSeconds><numCallLegs>15</numCallLegs><maxCallLegs>15</maxCallLegs><numParticipantsLocal>15</numParticipantsLocal><locked>false</locked><recording>false</recording><streaming>false</streaming><allowAllMuteSelf>false</allowAllMuteSelf><allowAllPresentationContribution>false</allowAllPresentationContribution><messagePosition>middle</messagePosition><messageDuration>0</messageDuration></call>')
requests.get(CMS_BASE + 'calls/' + callid, verify=False, headers=CMS_HEADERS)
Что мы узнали о подключении?
Автоматизация рутинных операций, например подключение большого количества участников в конференцию с известным call ID
Cisco Connect 2017 © 2017 Cisco and/or its affiliates. All rights reserved. 38
Virtual = ['1000', '1001', '1002', '1003', '1004', '1005', '1006', '1007', '1008', '1009', '1011', '1014', '1017'] # Создаем объект, тип список с номерами абонентов
def autoconnect(action) : # Определяем функцию, которую будет удобно вызывать для подключения / отключения всех абонентов спискаglobal callid
if action == "on" : # подключаем абонентов из спискаfor element in Virtual :
pprint (element) # отслеживаем работу скриптаconnect = requests.get(CMS_BASE + 'calllegs?filter=' + element, verify=False, headers=CMS_HEADERS) # проверяем не подключен ли он уже к серверу?if ''.join(re.findall(r'callLegs total="(\d)', connect.text)) == '0' :
# операция подключенияrequests.post(CMS_BASE + 'calls/' + callid + '/calllegs', data="remoteParty=" + element + "@str.ru", verify=False, headers=CMS_HEADERS)
if action == "off": # отключаем абонентов из списка for element in Virtual:
pprint (element)connect = requests.get(CMS_BASE + 'calllegs?filter=' + element, verify=False, headers=CMS_HEADERS)if ''.join(re.findall(r'callLegs total="(\d)', connect.text)) != '0':
calllegidcurrent = ''.join(re.findall(r'callLeg id="(\w+\-\w+\-\w+\-\w+\-\w+)', connect.text))pprint(calllegidcurrent)requests.delete(CMS_BASE + 'calllegs/' + calllegidcurrent, verify=False, headers=CMS_HEADERS)
autoconnect("off") # Можно ждать команды из CLI, но я не стал этого делать для минимизации кода
def findlegs():
offset = 0
activelegs = requests.get(CMS_BASE + 'calls/' + callid + '/callLegs', verify=False, headers=CMS_HEADERS)
print (activelegs.text)
collegstotal = int(''.join(re.findall(r'callLegs total="(\d+)', activelegs.text)))
calllegs = re.findall(r'callLeg id="(\w+\-\w+\-\w+\-\w+\-\w+)', activelegs.text)
if len(calllegs) < collegstotal :
offset = offset + 10
activelegs = requests.get(CMS_BASE + 'calls/' + callid + '/callLegs?offset=' + str(offset), verify=False, headers=CMS_HEADERS)
calllegs = calllegs + re.findall(r'callLeg id="(\w+\-\w+\-\w+\-\w+\-\w+)', activelegs.text)
print(calllegs)
findlegs()
Cisco Connect 2017 © 2017 Cisco and/or its affiliates. All rights reserved. 39
Автоматизация рутинных операций, например установка режима для участников в конференции с известным call ID
<?xml version="1.0"?><callLegs total="15"><callLeg id="0d20279c-d792-4032-9206-8bf3786fca04"><name></name><remoteParty>[email protected]</remoteParty><call>32a41a3a-076d-4a25-b485-db9f1f1ea067</call></callLeg><callLegid="0e8d0458-0172-4a6a-bf3d-c26e8f0863b8"><name></name><remoteParty>[email protected]</remoteParty><call>32a41a3a-076d-4a25-b485-db9f1f1ea067</call></callLeg><callLeg id="113ef87c-8925-4929-bf10-467649f53ed7"><name></name><remoteParty>[email protected]</remoteParty><call>32a41a3a-076d-4a25-b485-db9f1f1ea067</call></callLeg><callLegid="3105f6b5-d3ca-4c3b-9e6c-2e6159284fa4"><name></name><remoteParty>[email protected]</remoteParty><call>32a41a3a-076d-4a25-b485-db9f1f1ea067</call></callLeg><callLeg id="80737b65-1385-463d-aa90-64a52f03e60f"><name></name><remoteParty>[email protected]</remoteParty><call>32a41a3a-076d-4a25-b485-db9f1f1ea067</call></callLeg><callLegid="aefb65b6-6043-4603-b6a9-7cd0182095a2"><name></name><remoteParty>[email protected]</remoteParty><call>32a41a3a-076d-4a25-b485-db9f1f1ea067</call></callLeg><callLeg id="af961c3b-e8e3-4daa-884d-89e29a32a4d8"><name></name><remoteParty>[email protected]</remoteParty><call>32a41a3a-076d-4a25-b485-db9f1f1ea067</call></callLeg><callLegid="b882fdf6-3d4c-46e7-b3b6-9d0f0b87475f"><name></name><remoteParty>[email protected]</remoteParty><call>32a41a3a-076d-4a25-b485-db9f1f1ea067</call></callLeg><callLeg id="c28d8918-c516-405f-a9db-382db87de3b0"><name></name><remoteParty>[email protected]</remoteParty><call>32a41a3a-076d-4a25-b485-db9f1f1ea067</call></callLeg><callLegid="c45016cf-7812-4c9f-8b95-a0eb024ebc4c"><name></name><remoteParty>[email protected]</remoteParty><call>32a41a3a-076d-4a25-b485-db9f1f1ea067</call></callLeg></callLegs>
['0d20279c-d792-4032-9206-8bf3786fca04', '0e8d0458-0172-4a6a-bf3d-c26e8f0863b8', '113ef87c-8925-4929-bf10-467649f53ed7', '3105f6b5-d3ca-4c3b-
9e6c-2e6159284fa4', '80737b65-1385-463d-aa90-64a52f03e60f', 'aefb65b6-6043-4603-b6a9-7cd0182095a2', 'af961c3b-e8e3-4daa-884d-89e29a32a4d8',
'b882fdf6-3d4c-46e7-b3b6-9d0f0b87475f', 'c28d8918-c516-405f-a9db-382db87de3b0', 'c45016cf-7812-4c9f-8b95-a0eb024ebc4c', 'd7cebcb4-799f-4ef8-9090-
1ed25b0e2b7d', 'e73cb349-1281-4f47-a9e2-b228dbedceb5', 'f7749b16-6173-46b1-ab1d-4a85451269fc', 'bdac73d6-ec81-422a-bdb3-eadefb234353',
'0373aa04-8c1f-40d0-8f9a-b5f78f98fa21']
Cisco Connect 2017 © 2017 Cisco and/or its affiliates. All rights reserved. 40
Автоматизация рутинных операций, например установка режима для участников в конференции с известным call ID
Получение информации о подключениях к конференции с известным call ID и операции с ними, например – для установки всем определенной конфигурации экрана
Cisco Connect 2017 © 2017 Cisco and/or its affiliates. All rights reserved. 41
def findlegs():offset = 0
activelegs = requests.get(CMS_BASE + 'calls/' + callid + '/callLegs', verify=False, headers=CMS_HEADERS)print (activelegs.text)collegstotal = int(''.join(re.findall(r'callLegs total="(\d+)', activelegs.text)))calllegs = re.findall(r'callLeg id="(\w+\-\w+\-\w+\-\w+\-\w+)', activelegs.text)if len(calllegs) < collegstotal :
offset = offset + 10activelegs = requests.get(CMS_BASE + 'calls/' + callid + '/callLegs?offset=' + str(offset), verify=False, headers=CMS_HEADERS)calllegs = calllegs + re.findall(r'callLeg id="(\w+\-\w+\-\w+\-\w+\-\w+)', activelegs.text)
print(calllegs)return calllegs # Необходимо использовать, чтобы получить доступ к значению переменной из другой функции
def setlayout(L):calllegs = findlegs()Layout = ['speakerOnly', 'telepresence', 'stacked', 'allEqual', 'onePlusN', 'automatic', 'allEqualQuarters','allEqualNinths', 'allEqualSixteenths', 'allEqualTwentyFifths',
'onePlusFive', 'onePlusSeven', 'onePlusNine'] # Создаем список всех существующих конфигураций экранов# Применяем экранную раскладку# Организуем цикл и перебираем все calllegs, не забывая сравнить со своим (ведь надо поменять всем, кроме себя)
pprint("Устанавливаем всем раскладку, кроме себя - " + Layout[L])i = 0for element in calllegs:
if calllegs[i] != calleg: # Здесь мы проверяем что callleg с которым мы будем проводить операцию не совпадает с callleg нашего терминалаrequests.put(CMS_BASE + 'calllegs/' + calllegs[i], data="defaultLayout=" + Layout[L], verify=False, headers=CMS_HEADERS)pprint(calllegs[i])i = i + 1
setlayout(3)
Parsing (JSON, XML)
Зачем это нужно?
Методы парсинга Не парсить
Если информация представляется в легко читаемом Вами виде
Do-It-Yourself (DIY) строковый парсинг (то что мы делали до сих пор)
Полезно в случае если требуемая Вам информация реально просто находится
Создание или использование Фреймворк / библиотек
Множество уже готовых библиотек и инструментов на все случаи жизни доступно
Parsing контент
Парсинг и выделение информации
Основы
Контент
Что представлено – Пользователи? Книги? Записи логов? Образец данных? Точки доступа?
Схема – Какой порядок, форма, и требования к данным?
Размер – Насколько велик объем выводимой информации? Может это ее размер создать проблемы?
Что Вам нужно
Имена пользователей и их почтовые адреса, X и Y координаты, ID и номера пациентов
Сколько Вам нужно получить записей
Вам надо посчитать количество записей, получить репрезентативную выборку, или все?
Знайте, что обычно существует несколько способов получения и обработки контента..
Различные WEB библиотеки (urllib, urllib2, Requests, и т.д.)
Различные JSON парсеры (JSON, SimpleJSON, UltraJSON, и т.д.)
Различные XML парсеры (xml.etree.ElementTree, lxml, xml.dom.minidom и т.д.)
Синтаксический анализ и обработка результатов
Как данные конвертируются по умолчанию Python <-> JSON
https://{{mmpHost}}/api/v1/calllegs
<?xml version="1.0"?><callLegs total="14"><callLeg id="14076e5e-72fb-42ec-998a-7f0602687e41"><name></name><remoteParty>[email protected]</remoteParty><call>41b79d90-9358-4b4d-952e-c4f6d0df2c09</call></callLeg><callLeg id="1bee0f35-7250-479a-b3de-3c026d3c1498"><name></name><remoteParty>[email protected]</remoteParty><call>41b79d90-9358-4b4d-952e-c4f6d0df2c09</call></callLeg><callLeg id="28dfbd95-a81a-40dc-849f-0c0efaec6b72"><name></name><remoteParty>[email protected]</remoteParty><call>41b79d90-9358-4b4d-952e-c4f6d0df2c09</call></callLeg><callLeg id="467772e0-f676-4784-b9bb-393a3a6e8a20"><name></name><remoteParty>[email protected]</remoteParty><call>41b79d90-9358-4b4d-952e-c4f6d0df2c09</call></callLeg><callLeg id="609e2fe9-0577-4884-9eab-72f8165a58c1"><name></name><remoteParty>[email protected]</remoteParty><call>41b79d90-9358-4b4d-952e-c4f6d0df2c09</call></callLeg><callLeg id="9338fa97-e95a-49e4-af04-34fc596ccf30"><name></name><remoteParty>[email protected]</remoteParty></callLeg></callLegs>
<callLegs total="14"><callLeg id="14076e5e-72fb-42ec-998a-7f0602687e41">
<name></name>
<remoteParty>[email protected]</remoteParty>
<call>41b79d90-9358-4b4d-952e-c4f6d0df2c09</call></callLeg>
<callLeg id="1bee0f35-7250-479a-b3de-3c026d3c1498">
<name></name>
<remoteParty>[email protected]</remoteParty>
<call>41b79d90-9358-4b4d-952e-c4f6d0df2c09</call></callLeg>
<callLeg id="28dfbd95-a81a-40dc-849f-0c0efaec6b72">
<name></name>
<remoteParty>[email protected]</remoteParty>
<call>41b79d90-9358-4b4d-952e-c4f6d0df2c09</call></callLeg>
<callLeg id="467772e0-f676-4784-b9bb-393a3a6e8a20">
<name></name>
<remoteParty>[email protected]</remoteParty>
<call>41b79d90-9358-4b4d-952e-c4f6d0df2c09</call></callLeg>
<callLeg id="609e2fe9-0577-4884-9eab-72f8165a58c1">
<name></name>
<remoteParty>[email protected]</remoteParty>
<call>41b79d90-9358-4b4d-952e-c4f6d0df2c09</call></callLeg>
<callLeg id="9338fa97-e95a-49e4-af04-34fc596ccf30">
<name></name>
<remoteParty>[email protected]</remoteParty>
<call>41b79d90-9358-4b4d-952e-c4f6d0df2c09</call></callLeg>
</callLegs>
Parsing XML
Cisco Connect 2017 © 2017 Cisco and/or its affiliates. All rights reserved. 47
def findlegs():offset=0activelegs = requests.get(CMS_BASE + 'calls/' + callid + '/callLegs', verify=False, headers=CMS_HEADERS)activelegs.encoding = 'utf-8'calllegs = ET.fromstring(activelegs.text)
if len(calllegs.findall("callLeg")) < int( calllegs.attrib["total"] ) :offset=offset+10activelegs = requests.get(CMS_BASE + 'calls/' + callid + '/callLegs?offset=' + str(offset), verify=False, headers=CMS_HEADERS)activelegs.encoding = 'utf-8'calllegs.extend( ET.fromstring(activelegs.text) .findall("callLeg") )
return calllegs
https://docs.python.org/2/library/xml.etree.elementtree.htmlПарсинг XML с помощью xml.etree.ElementTree
Получение информации о подключениях к конференции с известным call ID и операции с ними, например – для установки всем определенной конфигурации экрана
Cisco Connect 2017 © 2017 Cisco and/or its affiliates. All rights reserved. 48
def findlegs():offset = 0
activelegs = requests.get(CMS_BASE + 'calls/' + callid + '/callLegs', verify=False, headers=CMS_HEADERS)activelegs.encoding = 'utf-8'calllegs = re.findall(r'callLeg id="(\w+\-\w+\-\w+\-\w+\-\w+)', activelegs.text)print(calllegs)
def findlegs():activelegs = requests.get(CMS_BASE + 'calls/' + callid + '/callLegs', verify=False, headers=CMS_HEADERS)activelegs.encoding = 'utf-8'calllegs = ET.fromstring(activelegs.text)pprint(calllegs)all_legs = calllegs.findall("callLeg")pprint(all_legs)
<Element 'callLegs' at 0x105666a48>
[<Element 'callLeg' at 0x10573b9a8>, <Element 'callLeg' at 0x105675728>, <Element 'callLeg' at 0x105675408>, <Element 'callLeg' at 0x105675638>, <Element 'callLeg' at 0x1057cd5e8>, <Element 'callLeg' at 0x1057d8d68>, <Element 'callLeg' at 0x1057d8ea8>, <Element 'callLeg' at 0x1057dd048>, <Element 'callLeg' at 0x1057dd188>, <Element 'callLeg' at 0x1057dd2c8>]
['0d20279c-d792-4032-9206-8bf3786fca04', '0e8d0458-0172-4a6a-
bf3d-c26e8f0863b8', '113ef87c-8925-4929-bf10-467649f53ed7',
'3105f6b5-d3ca-4c3b-9e6c-2e6159284fa4', '80737b65-1385-463d-
aa90-64a52f03e60f', 'aefb65b6-6043-4603-b6a9-7cd0182095a2',
'af961c3b-e8e3-4daa-884d-89e29a32a4d8', 'b882fdf6-3d4c-46e7-
b3b6-9d0f0b87475f', 'c28d8918-c516-405f-a9db-382db87de3b0',
'c45016cf-7812-4c9f-8b95-a0eb024ebc4c', 'd7cebcb4-799f-4ef8-9090-
1ed25b0e2b7d', 'e73cb349-1281-4f47-a9e2-b228dbedceb5',
'f7749b16-6173-46b1-ab1d-4a85451269fc', 'bdac73d6-ec81-422a-
bdb3-eadefb234353', '0373aa04-8c1f-40d0-8f9a-b5f78f98fa21']
Cisco Connect 2017 © 2017 Cisco and/or its affiliates. All rights reserved. 49
name : callLegstext : Noneattr total : 14
name : callLegtext : Noneattr id : 0d20279c-d792-4032-9206-8bf3786fca04
name : nametext : Nonename : remotePartytext : [email protected] : calltext : 32a41a3a-076d-4a25-b485-db9f1f1ea067
<callLegs total="14"> - ‘total ’ аттрибут верхнего уровня XML (calllegs.attrib)<callLeg id="0d20279c-d792-4032-9206-8bf3786fca04"> – атрибут callLeg ‘id’ -
свойства:<name></name>
<remoteParty>[email protected]</remoteParty> - remoteParty.text текст<call>32a41a3a-076d-4a25-b485-db9f1f1ea067</call>
- текст (отсутствует)</callLeg>
</callLegs>def printElement(element, shift=0): # Функция, печатающая элементы структуры XML
shifttab = "\t" * shift; # сдвижка
print(shifttab, "name : ", element.tag) # Имя корневого элемента
print(shifttab, "text : ", element.text) # Текст корневого элемента
for attrname in element.keys(): # Печать всех атрибутов ключей корня
print(shifttab, "attr ", attrname, " : ", element.attrib[attrname])
for subelement in element: # Для каждого элемента нижнего уровня
printElement(subelement, shift + 1) # Напечатать его с помощью этой
# функции, увеличивая сдвижку
Понимание структуры, формируемой xml.etree.ElementTree
Xpath синтаксис для xml.etree.ElementTree
calllegs=findlegs()print ("Callleg ID: " + calllegs.find( "./callLeg[remoteParty='[email protected]']" ) .attrib["id"] )print ("Имя терминала: " + calllegs.find( "./callLeg[remoteParty='[email protected]']/name" ).text)print ("Идентификатор конференции: " + calllegs.find( "./callLeg[remoteParty='[email protected]']/call" ).text)client.close()
Callleg ID: 8646379f-fb0d-4dff-aae1-7ac02b65c59bИмя терминала: SX20 Room – МоскваИдентификатор конференции: 32a41a3a-076d-4a25-b485-db9f1f1ea067
Синтаксис Выполняет
tagВыбирает все дочерние элементы с этим тегом. Например ’spam’ выбирает все дочерние элементы с именем spam, а ’spam/egg’ выбирает все дочерние элементы с именем egg дочерних элементов spam.
* Выбирает все дочерние элементы. Например, */egg выбирает все дочерние элементы egg, всех дочерних элементов.
. Выбирает текущий уровень. Наиболее полезно в начале пути, для обозначения уровней, относительно текущего
// Выбирает все поделементы на уровне ниже выбранного элемента. Например, .//egg выбирает все элементы дерева.
.. Выбирает родительский элемент
[@attrib] Выбирает все элементы с этими атрибутами
[@attrib='value']Выбирает все элементы у которых указанный атрибут равен указанному значению. Значение не может включать одинарные кавычки.
[tag] Выбирает все элементы, у которых есть дочерние с именем tag. Работает только на один уровень.
[tag='text'] Выбирает все элементы у которых есть дочерние полностью соответствующие полю text на всех уровнях вложенности
[position]Выбирает элемент. ‘position’ может быть цифрой (1 – первый в списке), выражением last() (для последнего элемента), или задавать относительный уровень (т.е. last()-1). Например /callLegs/callLeg[2] - вернет второй callLeg
Ресурсы с открытым исходным кодом
CDR ресивер https://github.com/jasonneurohr/acano_cdr_receiver
Canopy, Python SDK для Cisco CMShttps://github.com/gnisbetcisco/canopy
Планы развития
Cisco Meeting Server 2.x
Cisco Meeting Server версии 2.2
Планируется на апрель – май 2017
Удобство работы, гибкость и качество
Новые возможности конференцсвязи
Максимальная масштабируемость
Большее количество подключений и
балансирование нагрузки
Лучшая в индустрии совместимость
Поддержка нескольких профилей качества с S4B и
O365
Позволяет выводить изображения
участников на 2 экрана
Требуется CMS 2.2 (май этого года)
Требуется CE9.1 (июнь этого года)
Поддерживается на: SX80, MX800
Dual, MX700 Dual, Spark Kit, Spark Kit
Plus
Поддержка работы с живым видео на двух экранахВозможно только с решениями Cisco Collaboration
Cisco Meeting Server 2000Лучшая масштабируемость в индустрии
На старте продаж емкость 500 HD
подключений
Требует получение разрешения на
ввоз (ПО предустановлено,
шифрование трафика – встроенная,
не блокируемая ключом
возможность) Высоко производительный сервер, основанный
на шасси UCS 5108 и 6 B200 лезвиях
Полностью сконфигурированное шасси продается
как единый сервер
GPL : 200,954 USD
PID: CTI-CMS-2K-BUN-K9
Поддержка O365 с OBTPсовместимость без дополнительных усилий
Планирование конференций с
помощью привычных для
пользователей Skype инструментов
Microsoft (Skype плагина)
Cisco устройства могут использовать
OBTP
O365 клиенты могут участвовать в
dual-home конференциях
Требует TMS15.5 и XE5.5
Расширенные возможности работы группы Call Bridge Лучшая масштабируемость в индустрии
Улучшите масштабируемость, без
ухудшения качества восприятия,
посредством многопоточного
каскадирования
CMS 2.1 умел балансировать только
входящие SIP соединения
CMS 2.2 добавляет механизмы
балансирование и для исходящих
SIP вызовов
Возможность задания «важного» участника (Important Participant Pane Placement)
Наилучшие возможности для работы с конференциями Cisco
Фокусируйте внимание участников
конференции на важных участниках
Идеально для лекций, выступления
руководителей и других конференциях,
где важно выделить определенные окна
Не зависит от выбранной экранной
раскладки
В версии 2.2 будет доступно через CMS
API.
Планируется в дальнейшем добавить
уровни важности и поддержку с CMA/
CMM
Другие новые возможности
Упрощения обслуживания:
Упрощение процесса сбора логов
Пауза для DTMF: Посылка с
задержкой, определяемой символом
запятой – “ , ”
Качество подключения:
Администратор сможет фиксировать
качество подключений на SD, HD, full
HD, и т.д. для обеспечения
гарантированного качества для
пользователей и более гибкого
управления ресурсами.
Новые инструменты
Cisco для управления
конференциями
Cisco Meeting Manager (White Glove Meeting Manger Tool)
Новый инструмент для оперативного управления конференциями
Самостоятельный инструмент – не требует для работы TMS
Будет поставляться в виде виртуальной машины
Web интерфейс управления (Firefox, Chrome, Safari)
Возможности, планируемый в первой версии:
Список всех активных конференций, из которого можно перейти к управлению выбранной конференцией
Список всех участников конференции, выключить звук от одного или всех, отключить участника, закончить конференцию
Отказоустойчивость для CMM (active-active)
Внешний вид
• Единый портал в который интегрированы различные компоненты
• Унифицированный интерфейс пользователя (UX и UI) и информационная архитектура (IA) с порталом управления облачными сервисами Cisco.
Список активных конференций
Установки конференции и ее участники
Детали подключения участника конференции
Планы по развитию CMM
• Провижионингпользователей и PMP
• Портал самообслуживания• Управление терминалами• Тонкая настройки
конференций и дополнительные возможности управления конференциями
• Большее колличествовиджетов
• Монитор лицензий• Конфигурация CMS • Дополнительные
возможности управления конференциями
Дальнейшие планы
• Управление конференцией (Meeting Manager)
• Портал Администратора• Основные виджеты
CMM 1.0 CMM 1.1
TMS планируется продолжить использовать для планирования и других ролей
#CiscoConnectRu#CiscoConnectRu
Спасибо за внимание!Оцените данную сессию в мобильном приложении конференции
© 2017 Cisco and/or its affiliates. All rights reserved.
Контакты:
Тел.: +7 495 9611410www.cisco.com
www.facebook.com/CiscoRu
www.vk.com/cisco
www.instagram.com/ciscoru
www.youtube.com/user/CiscoRussiaMedia