03-05-2019 08:23 AM
Hello,
We have about 400 TP endpoints (latest CE version) registered CUCM 11.5 and planning to deploy macro for end user feedback and survey about TP call experience. It is time consuming to add this script manually to all the TP endpoints. Is there any tool I can utilize to deploy macro or other TP endpoints configuration without using CUCM?
03-05-2019 08:31 AM
You can use python. I used python for something similar to deploy macros and in-room control
03-12-2019 08:53 AM
Hi Ayodeji,
I am very new to Python. Would you mind sharing the example you have deployed?
03-13-2019 08:03 AM
It would be great if you could share how it could be implemented. I am interested too
04-24-2019 01:31 AM
Gents,
Apologies for my late reply. Here is my python code for uploading macros to multiple TP endpoint.
++ The python code +++
# This code worked with python 3.6
# This code is used to configure in room control and macros on TP endpoints.
# It reads the IP addresses of the endpoint from a CSV file and
# reads the macros as well as in room control commands from an xml file
# The credentials module is used to get the username/password for the endpoint. When using an IDE like pycharm you need
# to run the code in debug mode for you to get the username/password input
import httplib2
import credentials
import csv
import socket
from multiprocessing.pool import ThreadPool
import datetime
#CSV file which contains the IP addresses of all TP codecs
filename = 'TP_List.csv'
#log path. configure complete path along with filename
Logfile = "TP_codec_config_update_report.txt"
with open(Logfile, "a+") as text_file:
text_file.write('\n' + datetime.datetime.now().strftime("%A, %d. %B %Y %I:%M%p") + '\n')
text_file.write("==========================" + '\n')
rows = []
try:
with open(filename, 'r') as csvfile:
# creating a csv reader object
csvreader = csv.reader(csvfile)
# extracting field names through first row
fields = next(csvreader) # python3
# extracting each data row one by one
for row in csvreader:
rows.append(row)
# get total number of rows
print("Total no. of rows: %d" % (csvreader.line_num))
lines = int(csvreader.line_num)
except FileNotFoundError:
print(filename + " Input file not found in current directory")
fieldindex = fields.index('IP Address')
codecIPs = []
for row in rows:
codecIPs.append(row[fieldindex])
print("codecIPs are {}".format(codecIPs))
username, password = credentials.get_credentials()
httpexception = httplib2.HttpLib2Error
# There are two xml files used
# xml_file: contains the xml code to enable macros on the TP endpoints because some of
# them do not have macros enabled by default
# xml_file_2: contains the inroom control and the java script config to enable macros. Without the inroom control config
# users wil not see the actual icon to be pressed to enable the macro functionality
xml_file = 'macros-enable.xml'
xml_file_2 = 'macros-zoom.xml'
# This function is where the magic happens. I am using request to open the xml file and then posting the content
# to the url of each TP endpoint based on the IP address obtained from the CSV file
# NB that http needs to be enabled on the TP endpoint otherwise you will get a 302 error.
def do_upload(ip):
try:
request = open(xml_file, "r").read()
h = httplib2.Http(".cache")
h.add_credentials(username, password)
url = "http://{}/putxml".format(ip)
print('-'*40)
print('Enabling Macros on {}'.format(ip))
resp, content = h.request(url, "POST", body=request,
headers={'content-type': 'text/xml; charset=UTF-8'})
with open(Logfile, "a+") as text_file:
text_file.write("The Status of Macros enabling on codec IP {} |---->>>".format(ip) + '\n')
text_file.write(str(content.decode('utf-8') +'\n'))
request = open(xml_file_2, "r").read()
h = httplib2.Http(".cache")
h.add_credentials(username, password)
url = "http://{}/putxml".format(ip)
print('-' * 40)
print('Configuring In-Room Control and Macros on {}'.format(ip))
resp, content = h.request(url, "POST", body=request,
headers={'content-type': 'text/xml; charset=UTF-8'})
with open(Logfile, "a+") as text_file:
text_file.write("The Status of In-Room Control and Macros Config on codec {} |---->>".format(ip) + '\n')
text_file.write(str(content.decode('utf-8')) +'\n')
# print(content)
except (socket.timeout, socket.error, httpexception) as e:
with open(Logfile, "a+") as text_file:
text_file.write('failed to connect to {} : {}'.format(ip, str(e)))
def main():
''' This Section uses multi-threading to send config to ten TP endpoint at a time'''
pool = ThreadPool(10)
results = pool.map(do_upload, codecIPs)
pool.close()
pool.join()
return results
main()
++ The credentials code ++
from getpass import getpass
def get_input(prompt=''):
try:
line = input(prompt)
except NameError:
line = input(prompt)
return line
def get_credentials():
''' Prompts and return a username and password.'''
username = get_input('Enter Username: ')
password = None
while not password:
password = getpass()
password_verify = getpass('Retype your password: ')
if password != password_verify:
print('Passwords do not match. Try again')
password = None
return username, password
+++ The XML files +++
1 macros-enable.xml
<?xml version="1.0"?>
<Configuration>
<Macros>
<Mode>On</Mode>
</Macros>
</Configuration>
2. macros-zoom.xml
<?xml version="1.0"?>
<Command>
<UserInterface>
<Extensions>
<Panel>
<Save>
<PanelId>zoomcall</PanelId>
<body><Extensions>
<Version>1.5</Version>
<Panel>
<Type>Home</Type>
<Icon>Camera</Icon>
<Order>3</Order>
<Color>#3386FF</Color>
<Name>Zoom</Name>
</Panel>
</Extensions></body>
</Save>
</Panel>
</Extensions>
</UserInterface>
<Macros>
<Macro>
<Save>
<Name>Zoom</Name>
<Overwrite>False</Overwrite>
<body>
const xapi = require('xapi');
const KEYBOARD_TYPES = {
NUMERIC : 'Numeric'
, SINGLELINE : 'SingleLine'
, PASSWORD : 'Password'
, PIN : 'PIN'
}
const CALL_TYPES = {
AUDIO : 'Audio'
, VIDEO : 'Video'
}
const DIALPAD_ID = 'zoomdialpad';
const INROOMCONTROL_AUDIOCONTROL_PANELID = 'zoomcall';
/* Use these to check that its a valid number (depending on what you want to allow users to call */
const REGEXP_URLDIALER = /([a-zA-Z0-9@_\-\.]+)/; /* . Use this one if you want to allow URL dialling */
const REGEXP_NUMERICDIALER = /^([0-9]{3,10})$/; /* Use this one if you want to limit calls to numeric only. In this example, require number to be between 3 and 10 digits. */
const DIALPREFIX_AUDIO_GATEWAY = '0';
function showDialPad(text){
xapi.command("UserInterface Message TextInput Display", {
InputType: KEYBOARD_TYPES.NUMERIC
, Placeholder: "Use keypad to enter meeting ID"
, Title: "Audio Call"
, Text: text
, SubmitText: "Call"
, FeedbackId: DIALPAD_ID
}).catch((error) => { console.error(error); });
}
/* This is the listener for the in-room control panel button that will trigger the dial panel to appear */
xapi.event.on('UserInterface Extensions Panel Clicked', (event) => {
if(event.PanelId === INROOMCONTROL_AUDIOCONTROL_PANELID){
showDialPad("Please type in Zoom meeting ID:" );
}
});
/* Event listener for the dial pad been posted */
xapi.event.on('UserInterface Message TextInput Response', (event) => {
switch(event.FeedbackId){
case DIALPAD_ID:
var regex =REGEXP_URLDIALER; //change this to whatever filter you want to check for validity
var match = regex.exec(event.Text);
if (match !== null) {
var zoom = match[1] + "@zoomcrc.com"
xapi.command("dial", {Number: zoom}).catch((error) => { console.error(error); });
}
else{
showDialPad("You typed in an invalid number. Please try again." );
}
break;
}
});
</body>
</Save>
<Activate>
<Name>Zoom</Name>
</Activate>
</Macro>
<Runtime>
<Restart command='True'></Restart>
</Runtime>
</Macros>
</Command>
03-28-2020 09:48 AM
Hi,
With your macros-zoom.xml file, how would you add code in to it for Zoom meetings that are password protected?
Ideally on the Touch 10, the user will first be prompted for the Zoom meeting ID, then prompt them if there is a password on the meeting, then if they have the Host PIN, then dial normally whether they enter in...
1) Just the Zoom meeting ID
2) Zoom meeting ID + password
3) Zoom meeting ID + Host PIN
4) Zoom meeting ID + password + Host PIN
Cheers,
David
03-29-2020 02:06 PM
Hi David,
I am sure you are going to need another set of macros to do this. You might want to check Github for this as there are tons of already configured macros for situations like this
06-16-2022 07:55 AM
Good morning
Is this used for cisco endpoints, such as Desktop Pro, and Room kits?
Are we able to add Banner, Provisioning address and so forth?
06-22-2022 05:22 PM
If you want a really powerful tool that can do pretty much everything you want, have a look at CE-Deploy.
I was introduced to it a few weeks ago and have found it extremely useful.
Please remember to mark helpful responses and to set your question as answered if appropriate.
06-24-2019 02:41 AM
Endpoints can get Macros from web Server using xCommand Provisioning Service Fetch. I have done it.
Now I hope to insert the command into configuration Schema and template, so that endpoints are provisioned through TMS PE , endpoints can get Macros automatically.
Is it possible to do this?
Jianfeng
12-07-2021 04:19 PM
Hi
Can you share the syntax that you used to create a TMS template using xml of the command? I am able to SSH into an endpoint and run the command successfully but I want to add this to a TMS template in order to add in bulk to our endpoints
08-01-2019 06:03 AM
Hello Team,
Could you kindly confirm the steps to implement feedback option manually.
I want to see how it works and than take this forward.
Kindly confirm where this feedback is stored once user selects the option.
06-18-2020 01:57 AM
How do you manage to deploy the macros on personal devices which are not connected to the company network? Are there any ways or ideas to accomplish that? For my understanding you need to have direct network access to deploy these macros. Thanks in advance
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide