Programmer’s
Manual – Node Services
This manual is a guide for developers interested in creating
services for an Access Grid node. The manual gives an overview of the node
services infrastructure currently available in the Access Grid Toolkit and
provides step-by-step instructions on how to build a service. In addition, this
document describes how to package and install a service to make it available in
Venue Clients. The Access Grid team highly encourages developers to build node
services, and this manual provides necessary information to successfully
implement the task.
The media tools for the Access Grid Toolkit 2.3 (AGTk), VIC for video and RAT for audio, are encapsulated in
the node service infrastructure illustrated in Figure 1.
Figure 1 Node Setup
For each machine in the node, an AGServiceManager
is started to administer AGServices controlling media
tools on that machine. The Venue Client connects to the AGNodeService,
the central communication point for AGServiceManagers,
to collect information and communicate with the AGServices
distributed in the node. This configuration allows for flexibility of your AG
room arrangement; you can add hardware such as an extra machine or cameras
based on your specific requirements. The node in Figure 1 is running a VIC
video consumer service on the Video Display Machine, and a RAT audio service
and three VIC video producer services for camera capture on the Audio and Video
Capture Machine.
The AGTk is not restricted
to using VIC and RAT for media but can be extended with new services using
other tools. Here we focus on how to create a simple service, from concept to
installation, providing a step-by-step example of how to get started developing
a new media service for the Access Grid.
The following example, creation of a simple Debug
Service, describes necessary steps for implementing a new service. Please note
that the example is used simply to demonstrate the concept. The following
sections provide a walkthrough of the Debug Service code given below. You can
also find the Debug Service package here.
import os
import sys
from AccessGrid.GUID import GUID
from AccessGrid.AGService import AGService, AGServiceI, RunService
from AccessGrid.Types import
Capability
from AccessGrid.AGParameter import
ValueParameter, OptionSetParameter
from AccessGrid.AGParameter import
RangeParameter, TextParameter
1.
class DebugService(AGService):
2.
"""
3.
Simple service that prints configuration
information. It claims to
4.
be a video and audio producer and consumer just to get
information.
5.
"""
6.
def __init__(self):
7.
AGService.__init__(self)
8.
self.log.debug("DebugService.__init__:
Init Service")
9.
self.id = str(GUID())
10.
# Set capabilities
11.
self.capabilities = [ Capability( Capability.CONSUMER,
Capability.AUDIO
Capability( Capability.CONSUMER,
Capability.VIDEO
),
Capability( Capability.PRODUCER,
"debug" ) ]
12.
# Set executable
13.
self.executable = None
14.
# Set configuration parameters
15.
self.param1 = OptionSetParameter("Configuration
Parameter 1:
16.
",
"On", ["On", "Off"] )
17.
self.param2 = RangeParameter( "Configuration
Parameter 2: ",
1.
0, 0, 100 )
18.
self.param3 = TextParameter( "Configuration
Parameter 3: ",
1.
"DebugService"
)
19.
self.param4 = ValueParameter("Configuration
Parameter 4:", 25)
20.
# Append parameters to the configuration
list
21.
self.configuration.append(self.param1)
22.
self.configuration.append(self.param2)
23.
self.configuration.append(self.param3)
24.
self.configuration.append(self.param4)
25.
#
------------------------------------------------------------
26.
# overridden methods inherited from AGService
27.
#
------------------------------------------------------------
28.
def Start(self):
29.
self.log.debug("DebugService.Start")
30.
def Stop(self):
31.
self.log.debug("DebugService.Stop")
32.
def ConfigureStream(self, streamDescription):
33.
self.log.debug("DebugService.ConfigureStream %s
34.
"%streamDescription)
35.
if
self.param1.value == "On":
self.log.info("DebugService.ConfigureStream: value
parameter
is on!")
36.
def SetIdentity(self, profile):
37.
self.log.debug("DebugService.Set Identity %s"%profile)
38.
if self.param1.value
== "On":
self.log.info("DebugService.SetIdentity: value
parameter is
on!")
39.
if __name__ == '__main__':
40.
# The port argument should always be set to
sys.argv[1]
41.
port = int(sys.argv[1])
42.
# Create the display service
43.
debugService = DebugService()
44.
# Create the SOAP interface for the service
45.
debugServiceI = AGServiceI(debugService)
46.
# Start the service
47.
RunService(debugService, debugServiceI,
port)
The AGService is the base
class to use when creating services for your node. It includes the core
functionality necessary to create a node service. The new class should inherit
from the AGService class and override appropriate
methods.
1.
class DebugService(AGService):
2.
"""
3.
Simple service that prints
configuration information. It claims to
4.
be a video and audio producer and consumer just to get
information.
5.
"""
6.
def __init__(self):
7.
AGService.__init__(self)
Each service is defined by its capabilities,
describing what actions the service is able to perform. In the 2.3 version of
the toolkit, a capability consists of the role and type parameters; the role
reflects whether the service is a consumer or a producer, and the type
specifies what kind of content is exchanged. The Debug Service specifies three
capabilities: audio consumer, audio producer, and video consumer. The video
consumer capability also adds a custom type, “debug,” which demonstrates how a
new type may be set. When entering a venue, each new producer of a certain type
is assigned its own multicast address in the venue for communication.
10. # Set capabilities
11. self.capabilities = [ Capability( Capability.CONSUMER,
Capability.AUDIO
Capability(
Capability.CONSUMER,
Capability.VIDEO
),
Capability(
Capability.PRODUCER,
"debug" ) ]
When entering a venue, the service gets information
about streams it will consume or produce via the ConfigureStream
method. The overridden method should include necessary code for configuring the
service. Profile information, which may be use for RTP data, is received via
the SetIdentity method.
32. def ConfigureStream(self, streamDescription):
33. self.log.debug("DebugService.ConfigureStream %s
34. "%streamDescription)
35. if self.param1.value == "On":
self.log.info("DebugService.ConfigureStream:
value
parameter is on!")
36. def SetIdentity(self,
profile):
37. self.log.debug("DebugService.Set Identity %s"%profile)
38. if self.param1.value == "On":
self.log.info("DebugService.SetIdentity: value
parameter is on!")
The service must specify the name of the executable
file; for the standard audio service this is rat. Since the Debug Service does
not really do anything, we just set the executable to None.
12. # Set executable
13. self.executable = None
The new service must implement Start and Stop methods
with correct code to initialize and shut down the service. The Access Grid team recommends using the AGService._Start(options) method
from the super class. To actually start the executable file with an option
list, you would add this in the Start() method, as
indicated below.
28. def Start(self):
29. self.log.debug("DebugService.Start")
30. def Stop(self):
31. self.log.debug("DebugService.Stop")
If the service needs configurable parameters, they can
be added to the configuration list of the AGService.
The parameters will be displayed and editable in the Node Management window if
you select to configure a service; see Figure 2. There are four kinds of
parameters (i.e., four ways to display configurable options for the user):
OptionSetParameter(name, defaultOption, optionsList) - The optionsList
will be displayed in a dropdown menu with defaultOption
set as default.
RangeParameter(name, initialValue, startValue, stopValue) –
Shows a slider with startValue as minimum value and stopValue as maximum value. The initialValue
will be the starting point for the slider.
TextParameter(name, value) – Represents a text field set to value as a string.
ValueParameter() –
Represents a integer field set to value as an integer.
The Debug Service implements
following configuration parameters:
# Set configuration parameters
15. self.param1
= OptionSetParameter(Configuration
Parameter 1:
16. ,
On, [On, Off])
17. self.param2 = RangeParameter(Configuration Parameter 2: ,
0, 0, 100 )
18. self.param3
= TextParameter(Configuration
Parameter 3: ,
DebugService)
19. self.param4
= ValueParameter(Configuration
Parameter 4:, 25)
20. # Append parameters to the configuration
list
21. self.configuration.append(self.param1)
22. self.configuration.append(self.param2)
23. self.configuration.append(self.param3)
24. self.configuration.append(self.param4)
Figure 2 shows how the Debug Service parameters above
are displayed in the Node Configuration Dialog accessible from the Node
Management window. You can open the dialog by right-clicking a service and then
select Configure….

Figure 2 Configuration Dialog.
Each service must be
accessible via a SOAP interface for the AGServiceManagers
to connect to services over the network. To expose a SOAP interface in the AGTk 2.3, create a service instance from the AGServiceI class. The RunService(implementation, interface, port)
function is available in AGService to start the SOAP
service. It takes the implementation object, the SOAP interface object, and a
port as parameters. The port is always specified via the command line. The
following code must be in the main module of the service to make it start
properly.
39. if __name__
== '__main__':
40. # The port argument should always be
set to sys.argv[1]
41. port = int(sys.argv[1])
42. # Create the display service
43. debugService = DebugService()
44. # Create the SOAP interface for the
service
45. debugServiceI = AGServiceI(debugService)
46. # Start the service
47. RunService(debugService, debugServiceI,
port)
To distribute your service, you should create a
service package. The zip archive should contain the service file, executable
files, and a SVC file describing the service. The following is DebugService.svc:
[ServiceDescription]
name = DebugService
description =
Example Debug Service
capabilities =
Capability1 Capability2 Capability3
executable = DebugService.py
platform =
neutral
version = 1.0
[Capability1]
role = consumer
type = audio
[Capability2]
role = consumer
type = video
[Capability3]
role = producer
type = debug
After creating the package, use the Access Grid
Package Manager (AGPM) to install it with following command agpm.py
--package=/path/to/package.zip. The --help flag lists
all possible options for agpm.
The service package is stored in
Windows: C:\Program
Files\AGTk-2.3\NodeServices
Linux: /etc/AccessGrid/NodeServices
All services in this directory are listed in the
service dialog available from the Node Management window, see Figure 3.

Figure 3 Service Dialog.
When first added in the Node Management window, the
service gets extracted into the following directory:
Windows: C:\Documents and
Settings\<user>\Application Data\AccessGrid\local_services
Linux: ~/.AccessGrid/local_services
This situation happens once; if a service with the
same version is already present, the package will not be extracted.
Once the service has been added, the Node Management window
can be used to start, stop, and configure the service. From the Venue Client
menu, open Preferences – Manage My Node…,
select a ServiceManager
from the list, and go to Services – Add…
in the menu. Select the service, and click OK. If you right-click the added service, you will find available
user options.
Error and debug information added in your code will
be stored in the log files. On Windows platforms you can find this information
in
Windows: C:\Documents and
Settings\<user>\Application Data\AccessGrid\Logs
Linux: ~/.AccessGrid/Logs