Showing results for 
Search instead for 
Did you mean: 

Bulk deploy macros on TelePresence Endpoints

Mohammed Emran
Level 1
Level 1


  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?

12 Replies 12

Ayodeji Okanlawon
VIP Alumni
VIP Alumni

You can use python. I used python for something similar to deploy macros and in-room control

Please rate all useful posts

Hi Ayodeji,

  I am very new to Python. Would you mind sharing the example you have deployed?

It would be great if you could share how it could be implemented. I am interested too


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' +"%A, %d. %B %Y %I:%M%p") + '\n')
text_file.write("==========================" + '\n')

rows = []

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:

# 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:

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):

request = open(xml_file, "r").read()
h = httplib2.Http(".cache")
h.add_credentials(username, password)
url = "http://{}/putxml".format(ip)
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 =, codecIPs)
return results



++ The credentials code ++

from getpass import getpass

def get_input(prompt=''):
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"?>

2. macros-zoom.xml

<?xml version="1.0"?>

const xapi = require('xapi');

NUMERIC : 'Numeric'
, SINGLELINE : 'SingleLine'
, PASSWORD : 'Password'
, PIN : 'PIN'
const CALL_TYPES = {
AUDIO : 'Audio'
, VIDEO : 'Video'

const DIALPAD_ID = 'zoomdialpad';

/* 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. */


function showDialPad(text){

xapi.command("UserInterface Message TextInput Display", {
, 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) => {
showDialPad("Please type in Zoom meeting ID:" );

/* Event listener for the dial pad been posted */

xapi.event.on('UserInterface Message TextInput Response', (event) => {

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] + ""
xapi.command("dial", {Number: zoom}).catch((error) => { console.error(error); });
showDialPad("You typed in an invalid number. Please try again." );
<Restart command='True'></Restart>


Please rate all useful posts


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



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

Please rate all useful posts

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?

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.

Level 1
Level 1

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?




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

Level 1
Level 1

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.

Level 1
Level 1

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