Professional Documents
Culture Documents
En
En
En
Connect
Moscow, 2017
Digitalization: here
and now
Part 2. API Cisco Meeting Server. When
you need to use it. API use in scripts
python. Sharing an example with In-room
control.
Sergey Yutsaytis
on collaboration technology consultant
• / CallBrandingProfiles / <call branding profile id> / DtmfProfiles / < dtmf profile id> • / System / configuration / cluster
• / CallBridges / <call bridge id> • / DirectorySearchLocations / <directory search location id> • / System / database
• / Calls / <call id> • / ForwardingDialPlanRules / <forwarding dial plan rule id> • / System / profiles
• / Calls / <call id> / participants • / InboundDialPlanRules / <inbound dial plan rule id> • / tenants
• / CallLegs / <callLeg id> • / OutboundDialPlanRules / <outbound dial plan rule id> • / turnServers
/ CallLegProfiles / <call leg profile id> / usage / IvrBrandingProfiles / <ivr branding profile id> • / Users / <user id>
• / CoSpaces / <coSpace id> / coSpaceUsers / <coSpaceUser id> • / LdapSources / <ldap source id> / WebBridges / <web bridge id> / updateCustomization
own products
What has been done and - Implemented projects with automatic creation of Spaces for Multi-
use of CMS (ACANO) API? - By pressing change the screen layout for all
voice commands
- Integration with the Cisco Spark for upravleniyal Spaces through Spark
messages
http://www.cisco.com/c/en/us/support/conferencing/meetingserver/products-programming-reference-guides-list.html
http://www.cisco.com/c/dam/en/us/td/docs/conferencing/ciscoMeetingServ er / Reference_Guides
/ Version-2-1 / Cisco-Meeting-Server-API-Reference-
Guide-2-1.pdf
https://www.acano.com/support/documentation/
The manual contains all the necessary materials and instructions supported in API CMS.
Until now, there was no change in the API terms of use or change their plans. A complete set of
commands is available in demo versions, trial version Acano and not licensed.
We need to operate with 4 types of queries:
https://10.100.1.227:9443/api/v1/callLegProfiles/ac0485e3-a3b7-47cf-91fe-ffa25ea5d795
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> 5,590,001 </ uri>
<callId> 5,590,001 </ callId> </ coSpace>
But, if the lecturer and the audience is allowed to connect with different
numbers (the URI) - it can be implemented through the API (as of version 2.1 -
different password (or password / no password))
CMS
Lecturer: calls to URI 5500@example.com, layout - quad, sees all the participants,
the microphone is active
Guest: calls to URI 5600@example.com, one large window with the speaker (lecturer),
the microphone is turned off, if the Speaker is off
- Video and voice are not received by the server
lecturer mode
1. Create a new space with the lecturer account profile
2. Create a profile for a compound Lecturer (Call Leg Profile): POST https://example.com/api/v1/callLegProfiles defaultLayout = allEqual
Create a connection method Lecturer (Access Method) with a URI and a Call ID 5500:
uri = 5500 & callLegProfile = 360b40bf-4c7d-41ff-a355-496c0e720649 & callID = 5500 (Access Method
ID: f3a7cf1a-961f-4fec-b19d-5db558851305)
Create a method of connecting guest (Access Method) with a URI and a 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)
How to make a Python REST call
Python requests Library
Cisco Connect 2017 © 2017 Cisco and / or its affiliates. All rights reserved. 31
Python requests Library
from pprint import pprint
import paramiko
import time
import re
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning # warning about not
requests.packages.urllib3.disable_warnings (InsecureRequestWarning) # Valid certificates
CMS_BASE = ' https://10.100.1.227:9443/api/v1/ ' # We set the basic parameters (e.g. IP)
CMS_HEADERS = { ' Content-type ' : 'Application / json' . 'Authorization' : "Basic YWRtaW46QzFzY28xMjM =" } # Ask login and password (take from the postman)
client = paramiko.SSHClient ()
client.set_missing_host_key_policy (paramiko.AutoAddPolicy ()) client.connect ( " 10.100.1.147 " . username = " admin " . password = " C1sco123 " ) # connection
to the server
# calls = requests.get (CMS_BASE + ' calllegs' + '? Filter =' + Number, verify = False . headers = CMS_HEADERS)
Cisco Connect 2017 © 2017 Cisco and / or its affiliates. All rights reserved. 32
Python requests Library
calls = requests.get (CMS_BASE + ' calllegs' + '? Filter =' + Number, verify = False . headers = CMS_HEADERS)
# Here we are connected to the conference, we learn all about connecting and conferences
callid = '' .join (re.findall ( r '<call> (\ w + \ - \ w + \ - \ w + \ - \ w + \ - \ w +)' . calls.text)) pprint ( " connection ID " + calleg) channel.send ( ' xCommand UserInterface Extensions
Widget SetValueWidgetId: "info3" Value: "Connection ID ' + calleg + '' \ n ' )
pprint ( " connection identifier " + callid) channel.send ( ' xCommand UserInterface Extensions Widget SetValueWidgetId: "info4" Value: "Conference ID ' + callid +
def confinfo (a): return requests.get (CMS_BASE + ' calls / ' + a, verify = False . headers = CMS_HEADERS) confinf = confinfo (callid)
pprint ( " Information about the conference: " + confinf.text)
client.close ()
Cisco Connect 2017 © 2017 Cisco and / or its affiliates. All rights reserved. 33
Encoding
<? Xml version = "1.0"?>
<CallLegs total = "4">
<CallLeg id = "9132036b-148f-49a6-9960-7bc90fabbbad"> <name> SX10
UGLICH 40210 </ name> <remoteParty> 40210@demo.cisco.ru </
remoteParty> <call> ce4a7f5f-4670-4ed8-b822 -3e28a0475678 </ call>
</ callLeg>
Cisco Connect 2017 © 2017 Cisco and / or its affiliates. All rights reserved. 34
Encoding
Encoding [ ' SX10 UGLICH 40210 ',' SX20
Р\ x92оРKRASNODAR
»ÐºÐ¾Ð²Ð ° ',' Ð \40220
x9fÐμÑ','\ Ð \ x95Ð
x82Ñ \ x80»ÐμнР° \ x82Ñ \ x80ов ']
Ð \ x9fÐμÑ
activelegs = requests.get (CMS_BASE + ' calls / ' + callid + '/ callLegs' . verify = False . headers = CMS_HEADERS) activelegs.encoding = ' utf-8
'
[ 'SX10 UGLICH 40210', 'SX20 KRASNODAR 40220', 'Elena Volkova', 'Peter Petrov']
Cisco Connect 2017 © 2017 Cisco and / or its affiliates. All rights reserved. 35
Python requests Library - the encoding
calls = requests.get (CMS_BASE + ' calllegs' + '? Filter =' + Number, verify = False . headers = CMS_HEADERS)
# Here we are connected to the conference, we learn all about connecting and conferences
callid = '' .join (re.findall ( r '<call> (\ w + \ - \ w + \ - \ w + \ - \ w + \ - \ w +)' . calls.text)) pprint ( " connection ID " + calleg) channel.send ( ' xCommand UserInterface Extensions
Widget SetValueWidgetId: "info3" Value: "Connection ID ' + calleg + '' \ n ' )
pprint ( " connection identifier " + callid) channel.send ( ' xCommand UserInterface Extensions Widget SetValueWidgetId: "info4" Value: "Conference ID ' + callid + '' \ n ' )
def confinfo (a): return requests.get (CMS_BASE + ' calls / ' + a, verify = False . headers = CMS_HEADERS) confinf = confinfo (callid)
pprint ( " Information about the conference: " + confinf.text) client.close ()
Cisco Connect 2017 © 2017 Cisco and / or its affiliates. All rights reserved. 36
What we have learned about how to connect?
<CallLegs '' total = "1"> <callLeg id = " bdac73d6-ec81-422a-bdb3-eadefb234353 ">
<Name> SX20 '' Room - '' Moscow </ name> <remoteParty> 40220@demo.cisco.ru </ remoteParty> <call> 32a41a3a-076d-4a25-b485db9f1f1ea067 </ call> </ callLeg> </
callLegs> ')
ID: bdac73d6-ec81-422a-bdb3-eadefb234353
requests.get (CMS_BASE + ' calls / ' + callid, verify = False . headers = CMS_HEADERS)
'Information about the conference: <? Xml version = "1.0"?> <Call' 'id = "32a41a3a-076d-4a25-b485-db9f1f1ea067"> <coSpace> 202a6e1c-b65b4c29-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> <all owAllMuteSelf> false </
allowAllMuteSelf> <allowAllPresentationContribution> false </ allowAllPresentationContribution> < messagePosition> mi ddle </ messagePosition> <messageDuration> 0 </
messageDuration> </ call> ')
Cisco Connect 2017 © 2017 Cisco and / or its affiliates. All rights reserved. 37
Automation of routine operations, such as connecting a large number of participants in the conference call ID famous
Virtual = [ ' 1000 ' . '1001' . '1002' . '1003' . '1004' . '1005' . '1006' . '1007' . '1008' . '1009' . '1011' . '1014' . '1017' ] # Create an object type from the list of subscribers numbers
def autoconnect (action): # We specify the function that will be convenient to call for connecting / disconnecting all users list
global callid
# connecting operation
requests.post (CMS_BASE + ' calls / ' + callid + '/ calllegs' . data = " remoteParty = " + element + "@ str.ru " . verify = False . headers = CMS_HEADERS)
autoconnect ( " off " ) # You can wait for the command from the CLI, but I did not do to minimize code
Cisco Connect 2017 © 2017 Cisco and / or its affiliates. All rights reserved. 38
Automate routine tasks, such as setting the mode for the participants in the conference call ID with a known
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)
print (Calllegs)
findlegs ()
Cisco Connect 2017 © 2017 Cisco and / or its affiliates. All rights reserved. 39
Automate routine tasks, such as setting the mode for the participants in the conference call ID with a known
Cisco Connect 2017 © 2017 Cisco and / or its affiliates. All rights reserved. 40
Information about connecting to the conference call ID and known operations with them, for example - to be installed over the
specific screen configuration
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)
def setlayout (L): calllegs = findlegs () Layout = [ ' speakerOnly ' . 'Telepresence' . 'Stacked' . 'AllEqual' . 'OnePlusN' . 'Automatic' . 'AllEqualQuarters' . 'AllEqualNinths' . 'AllEqualSixteenths' . 'AllEqualTwentyFifths' .
setlayout ( 3 )
Cisco Connect 2017 © 2017 Cisco and / or its affiliates. All rights reserved. 41
Parsing (JSON, XML)
Parsing content
• Why do it?
• parsing methods
• not parse the
• If the information is presented in easy to read format you
• foundation
• content
• Which is represented - Members? Books? the logging? the sample data? the access point?
• Driving - What is the order, form, and data requirements?
• Size - How large is the amount of information displayed? Maybe it's the size create problems?
• What you need
• The names of users and their e-mail addresses, X and Y coordinates, ID, and patient rooms
• How much you need to get records
• You have to count the number of records to obtain a representative sample, or all?
• Know that there are usually several ways of obtaining and processing content ..
if len (Calllegs.findall ( " callLeg " )) < int (Calllegs.attrib [ " total " ] ):
offset = offset + ten
activelegs = requests.get (CMS_BASE + ' calls / ' + callid + '/ callLegs? offset = ' + str (Offset), verify = False . headers = CMS_HEADERS) activelegs.encoding = ' utf-8 '
Cisco Connect 2017 © 2017 Cisco and / or its affiliates. All rights reserved. 47
Information about connecting to the conference call ID and known operations with them, for example - to be installed over the
specific screen configuration
activelegs = requests.get (CMS_BASE + ' calls / ' + callid + '/ callLegs' . verify = False . headers = CMS_HEADERS) activelegs.encoding = ' utf-8 '
Cisco Connect 2017 © 2017 Cisco and / or its affiliates. All rights reserved. 48
Understanding the structure formed xml.etree.ElementTree
< callLegs total = " 14" > - 'Total' XML attribute upper level (calllegs.attrib)
< callLeg id = " 0 d20279c-d792-4032-9206-8bf3786fca04 " > - Attribute callLeg 'id' -
properties:
< name> </ name>
< remoteParty> 1000 @ str.ru </ RemoteParty> - remoteParty.text text
< call> 32 a41a3a-076d-4a25-b485-db9f1f1ea067 </ Call>
- Text (none)
</ callLeg> </
def printElement (element, shift = 0 ): # Function, the print elements of the XML structure shifttab = "\ t " * shift;
callLegs>
# shift of
print (Shifttab, " name: " . element.tag) # Name of the root element
print (Shifttab, " text: " . element.text) # The text of the root element
for attrname in element.keys (): # Print all the attributes of the root keys
attr total: 14
name: callLeg text: None
attr id : 0 d20279c-d792-4032-9206-8bf3786fca04
name: name text: None
Cisco Connect 2017 © 2017 Cisco and / or its affiliates. All rights reserved. 49
Xpath syntax for xml.etree.ElementTree
Syntax performs
Selects all child elements of this tag. For example 'spam' selects all child elements named spam, and 'spam / egg' selects all child elements
tag
named egg child elements spam.
* Selects all child elements. For example, * / egg selects all child elements egg, all child elements.
. Selects the current level. The most useful at the beginning, to indicate levels, relative to the current
// Selects all podelementy at a level below the selected item. For example, .//egg selects all the elements in the tree.
[Tag] Selects all elements that have a child with a name tag. Only works on one level.
[Tag = 'text'] Selects all elements that have a child is completely appropriate text field at all levels of nesting
Selects an item. 'Position' may be a number (1 - the first in the list), the expression last () (for the last element), or to set the relative level (i.e., last () -
[Position]
1). For example / callLegs / callLeg [2] - returns the second callLeg
calllegs = findlegs () print ( " Callleg ID: " + calllegs.find ( "./CallLeg[remoteParty='40220@demo.cisco.ru ']" ) .Attrib [ "Id" ])
print ( " Terminal Name " + calllegs.find ( "./ callLeg [remoteParty='40220@demo.cisco.ru '] / name " ). text) print ( " conference ID: " + calllegs.find
( "./ callLeg [remoteParty='40220@demo.cisco.ru '] / call " ). text) client.close ()
CDR receiver
https://github.com/jasonneurohr/acano_cdr_receiver
Cisco Meeting Server 2.x
development plans
Cisco Meeting Server version 2.2
Usability, flexibility and Maximum scalability Best in the industry
quality compatibility
• PID: CTI-CMS-2K-BUN-K9
Support O365 with OBTP
compatibility with no additional effort
• Ease of maintenance:
Simplify log collection process
• connection quality:
Administrators will be able to capture the
quality of the connections on the SD, HD, full
HD, etc. to provide guaranteed quality for
users and more flexible management of
resources.
New Cisco
management
tools conferences
Cisco Meeting Manager
(White Glove Meeting Manger Tool)
A new tool for the operational management of conferences, standalone tool - no need
A list of all active conferences, from which you can go to the selected conference management
List of all participants of the conference, mute the sound from one or all, turn off the party, complete
fault tolerance conference for CMM (active-active)
Appearance
www.facebook.com/CiscoRu
Contacts:
www.vk.com/cisco
Tel .: +7 495 9611410
www.instagram.com/ciscoru www.cisco.com
www.youtube.com/user/CiscoRussiaMedia