TestManager Python Scripts

Along with the TM Script language, TestManager also supports writing scripts in Python. This requires IronPython to be installed.

The Python environment within TestManager is much the same as that provided by IronPython, but with two important differences. Firstly, TestManager defines a global object tm to allow access to the TestManager API. Secondly, the import mechanism has been extended to allow scripts defined within TestManager to be imported as normal Python modules.

When Python scripts are run from within TestManager, certain internal aspects of the application are exposed via an API, for example to list set-top boxes (STBs), send IR signals etc.

Below are some examples of Python code in TestManager.

Importing a Script

If there is a script called Foo within a script folder called Python which contains the following code:

def Message():
    print 'Hello, World!'

Message can then be called like so:

import scripts.Python.Foo as foo

Note that the names of the folders and scripts involved must be valid Python module names for the import to succeed.

Sending a Signal to a STB

To send an IR signal to a known STB, it first needs to be reserved. This is achieved by using the global ‘tm’ object and prevents other scripts from using it.

stbs = tm.reserve_stbs(['My STB'])
tm.send('play', stbs)


Sending a Signal to All STBs Except One

To send a signal to all STBs except one, a list of STBs known about by TestManager is required.

all_stbs = tm.get_stb_names()
my_stbs = [stb for stb in all_stbs if stb != 'STB-8']
stbs = tm.reserve_stbs(my_stbs)
tm.send('play', stbs)


Sending a Signal to a Zone

rack1 = tm.reserve_zone('Rack 1')
tm.send('play', rack1)


Sending a Signal Multiple Times

A signal can be sent multiple times using a For loop.

import time

stb = tm.reserve_stbs(['my_stb'])

for loopNum in range(0, 5):
    tm.send( ' Vol+ ', stb )
    print 'Loop Number:', loopNum + 1

    # Wait 1 second
    time.sleep( 1 )


Sending a Sequence of Signals

For actions which consist of multiple signals e.g. changing the channel number, a sequence of signals can be sent.

signals = ['1', '0', '1']
stb = tm.reserve_stbs(['my_stb'])

for signal in signals:
    tm.send(signal, stb)


Using a Macro

A macro can be retrieved as follows:

all_macros = tm.get_macro_names()
my_macro = [macro for macro in all_macros if macro == 'BBC1']

It can then be sent in a similar fashion to sending a signal.

rack1 = tm.reserve_zone('Rack 1')
tm.send(my_macro[0], rack1)


Creating Automated Operations

The following code shows an example of how to create automated access to a TV’s Picture menu. First the necessary functions are created in a script called Utils.

class MenuAccess():

# Clear any menu currently accessed
    def __init__(self):
        tm.send('exit', stb);

# Loop required in order to access menus by repeating signals (e.g. 'left', 'right')
    def MoveSelect(self, direction, amount):
        for i in range(0, amount):
            tm.send(direction, stb);

# Access Main menu
    def MoveMenu(self, amount):
        tm.send('menu', stb);
        self.MoveSelect('right', amount);

# Access Picture menu
    def GetPictureMenu(self):

GetPictureMenu can then be called like so:

import scripts.Python.Utils as utils;

# Allow access to 'tm' and 'stb' objects in 'Utils'
utils.tm = tm;
utils.stb = tm.reserve_stbs(['My TV']);

# Access the Picture option in the TV menu


Creating Logging Capabilities

The following code shows an example of how to create a logging file using a script called LogCreator.

import os;

# Set the default directory path
logDir = os.environ['HOMEPATH'] + '\Desktop\Logs';

class Logger():

    def __init__(self):
        self.string = '';

# Create log directory if one does not exist
    if not os.path.isdir(logDir):

# Create log file if one does not exist
    if not os.path.exists(logDir + '\Last Session.txt'):
        fd = os.open(logDir + '\Last Session.txt', os.O_CREAT);
# Open file for writing only
    self.fd = os.open(logDir + '\Last Session.txt', os.O_WRONLY);

# Set text to be written to file
    def Log(self, string):
        self.string = self.string + string + "\n";

# Write text and close file
    def End(self):
        os.write(self.fd, self.string);

Log can then be called like so:

import time;
import scripts.Python.LogCreator as logCreator;

debug = logCreator.Logger();

# Give text to print to log file
debug.Log("Hello world");
debug.Log("Goodbye world");

# Print to and Close log file


Advanced: Writing Scripts for Concurrent Execution

The following code shows an example of how to send a sequence of signals on multiple threads using the .NET Task Parallel Library.

import clr

from System import *
from System.Threading import *
from System.Threading.Tasks import *

import random
import scripts.Python.TmTasks as tmtasks

# Sends a signal and then waits a random period of time.
def send(signal, stb):
    tm.send(signal, stb)
    Thread.Sleep(random.uniform(50, 2500))

# Sends a sequence of signals.
def sendSeq(stb):
    tmtasks.printMessage("Starting output to " + stb.name)

    for count in range(0, 2):
        tmtasks.printMessage("Loop " + str(count) + " to " + stb.name)
        send('0', stb)
        send('1', stb)
        send('2', stb)
        send('3', stb)
        send('4', stb)

    tmtasks.printMessage("Output complete " + stb.name)

# How to handle exceptions
    res = tm.get_stb_names()
    print res
except Exception as inst:
    print type(inst)
    print inst

# Reserve the STBs we want to use.
stbs = tm.reserve_stbs(tm.get_stb_names())

tmtasks = tmtasks.TmTasks()

# Create all our jobs and start them
for i in range(len(stbs)):
    # Slightly strange syntax: 'x=param' is needed to capture the actual param instance.
    # See lambda function closures.
    tmtasks.startTask(lambda x=stbs[i]: sendSeq(x))

# Wait until all tasks finished.

print "Done!"

View the TestManager main page here

This site uses cookies. Find out more about this site’s cookies.