The Control Unit Admin Bundle delivers means for unified access and management of different types of devices and services.
Contents:
The JAR of the Control Unit Admin Bundle is cuadmin.jar, located in the bundles installation directory.
|
|
The Control Unit Admin service provides access to management operations on
available control unit instances. The Control Unit Admin service is published
in the OSGi framework under the org.mbs.services.cu.ControlUnitAdmin
interface. See the "How to Manage Control Units"
chapter for more information on the Control Unit Admin usage.
The Control Unit Admin Bundle registers a Metadata Plugin for the "Control-Unit" metadata type. The ProSyst Metatype Bundle associates the Control Unit Admin Bundle with control unit metadata and asks it if to continue processing of newly defined metadata or not. See the description of the ProSyst Metatype Bundle for more information on Metadata Plugins.
The Control Unit Admin Bundle uses the following system properties:
|
To use successfully the above system properties, you have to specify them:
For more information about using system properties, refer to the "System Properties" document from "Getting Started".
The control unit paradigm aims to unify the control of miscellaneous units. In an OSGi framework, the paradigm introduces a common interface to manage different types of controllable modules - these can be devices handled by appropriate drivers, software modules, etc.
Imagine the following situation:
You are to manage X10 and LON devices registered by the appropriate drivers in an OSGi-enabled device. The APIs for contacting X10 and LON devices may significantly differ. To be able to call the devices, you must have good knowledge of both technologies and perform complex operations on managed devices. If you should contact another category of devices, for example UPnP, you will be obliged to learn another Java API.
ProSyst designed the control unit paradigm and its API to solve such troubles and to save you time and efforts in using too many and too different APIs in order to control units running in the OSGi framework environment. Through the API, developers can refer to abstract control units sharing common and comprehensive operation model regardless of specifics of the underlying APIs.
The control unit paradigm introduces a management application, called Control Unit Admin, which provides convenient access to available control units, delivered by different providers, and means for their control.
The control unit abstraction fits well into the device driver model. A control unit can be used for representing a device as a service in the framework.
Where it is possible, the base driver for a given protocol, apart from functioning as a conventional driver as defined in the OSGi Device Access Specification, registers every discovered device as a control unit instance in the Control Unit Admin.
Where the semantics of the protocol does not provide enough information (for example in a OneWire network), refining drivers do the mapping between control units and devices.
The structure that a control unit can have is illustrated in Figure 2.

Figure 1: Structure of a control unit.
A control unit is a collection of state variables and actions. State variables reflect control unit's specific parameters, for example: an X10 lamp may have a state variable for indicating on and off, and have unique ID within the control unit scope and value of certain type. You can only get a state variable's value by making a query. Direct modification with a new value is not supported. If the state variable's value can be changed from outside, the control unit should provide an action for such an operation.
The actions of a control unit are the commands that the control unit can execute, such as turning a lamp on and off. An action has ID, unique within the control unit scope, and may have input and/or output arguments.
The collection of state variable IDs and types and of action IDs form the interface of the control unit. The current values of control unit's state variables determine the present state of the control unit.
The control unit paradigm provides a unified, well-known way to monitor the state of and execute an action on a control unit resulting in a state change. Thus, although there is a great flexibility in what operations can be invoked on units and the state variables they provide, applications can manage control units in a uniform way, without the need to bind to specific knowledge about underlying resources.
Each control unit instance has associated type and ID. The control unit's type identifies its interface. It is possible to have many control unit instances of the same type, sharing the same set of state variable and action identifiers, but in different states. The control unit ID has to be unique in the scope of the corresponding type.
The interface of control units of a specific type may evolve between its successive implementations - for example, the newer version of the implementation may add some new state variables and actions. To support this scenario, the control unit type may be supplemented with version. This allows additional attributes and actions to be added without the need of introducing a new type. Newer versions of a given type should be backward compatible with the older ones. In this way an older management application may still run with the new type version, taking benefit only from the type's older features, while newer applications will be able to take advantage of the new features provided by the extended type.
All control units of the same type exported at a time in the OSGi framework should have the same version.
In order to use a specific control unit, an application has to know its interface. In general, there are two ways to deliver this knowledge:
The description of a control unit interface is called control unit metatype and is supplied by a Metatype Provider. Control unit metatyping relies on the ProSyst Metatype support which in turn is based on the OSGi Metatype Specification. For details on the format and definition of control unit metadata, see the "How to Provide Control Units" chapter.
You can build a nested structure of control units, convenient for logical grouping of units and especially useful for representing more complex resources - devices, hardware and software systems, which may be decomposed to a hierarchy of sub-components, achieving arbitrary level of granularity. For example, a control unit hierarchy may be defined to represent a controller with several devices attached to it.
The relation between parent and child control units is "soft", that is, built only on the properties specifying the parent types and IDs. This means that parent control units do not need to know their children, but a child control unit has to know its parents.
The Control Unit Admin is capable of lookup for parent or child control units saving each management application the efforts for matching child and parent IDs.
A control unit interface can extend a super control unit, meaning that it inherits all state variables and actions of its superior.
Figure 2 illustrates the architecture of the control unit paradigm.

Figure 2: Control unit architecture.
Basically, the usage model of the control unit abstraction outlines two development roles: one of a developer who writes a bundle which uses control units; and one of a developer that implements a control unit. Users of the control unit paradigm work straight with the control units by calling the common methods of the Control Unit Admin instead of different methods provided in different APIs.
The control unit abstraction is not bound to any visual representation of the data it carries. It does not require any special GUI components, and it does not put any restrictions on the visual applications that use it. Developers may build user interfaces in Swing, HTML, XML, PGUI , mGUI or any other library of graphical components.
The Provider Layer of the control unit paradigm contains control unit provider applications. Control unit providers map miscellaneous manageable entities (devices, applications, services, etc.) to control units.
The control unit paradigm includes a special API, Control Unit Provider API,
for creation of control units, accessible through the Control Unit Admin, and
for interaction with the Admin Layer. The Control Unit Provider API components
are included in the org.mbs.services.cu.spi package. For more information
on plugging new control units, refer to the "How to
Provide Control Units" chapter.
The Admin Layer acts as an intermediary between provided control units and
applications wishing to manage them. The Admin Layer directly calls control
unit providers over the Control Unit Provider API and makes provided control
units available to applications over the Control Unit Admin API (defined in
the org.mbs.services.cu package). The basic component of the Admin
Layer is the Control Unit Admin module, which "translates" raw control
units into more sophisticated entries. For more information on managing control
units through the Control Unit Admin, refer to the "Managing
Control Units" chapter.
The Application Layer consists of custom applications working with control units. Such application may be generic management applications, which provide control and monitoring of all available control units in the OSGi framework, or may be applications, specialized in interacting with particular type(s) of control units.
This chapter discusses the basic concepts in implementing control units by
using the Control Unit Provider API (org.mbs.services.cu.spi).
Basically, the control unit paradigm outlines two approaches: implement a Managed
Control Unit for associating a control unit instance with a single entity or
implement a Control Unit Factory, capable of producing and managing multiple
control unit instances of the same type. The factory approach allows a provider
to produce a large number of control units without loading the OSGi framework
registry.
Tip: You can use the Control Unit Generator API and the Control Unit Generator tool to provide Managed Control Units and Control Unit Factories.
Managed Control Units should implement and register an org.mbs.services.cu.spi.ManagedControlUnit
service object in the OSGi framework. A Managed Control Unit is restricted to
have only one parent and cannot use the mechanism for definition of constructors,
destructors and finders.
The Managed Control Unit service should have the following registration properties
with string keys and values, available as fields of the ControlConstants
interface:
ControlConstants.TYPE) - Specifies
the control unit type. Required.ControlConstants.ID) - Indicates the
control unit ID. Required.ControlConstants.PARENT_TYPE)
- Shows the type of the parent control unit. Optional.ControlConstants.PARENT_ID) -
Indicates the ID of the parent control unit. Optional.ControlConstants.VERSION) - Contains
the version of the control unit type. Optional.Besides providing multiple control units, a Control Unit Factory can also offer methods for constructing and destroying control unit instances. This can be useful if some initial information is necessary to start managing an entity (see also "Control Unit Constructors" and "Control Unit Destructors"). For example, if a user wants to control devices manageable through a Control Unit Factory and the user is the only one having the knowledge how to contact the devices. To manage a device, the user asks the Control Unit Factory to create a control unit for it passing the known contact parameters. Thereafter the device can be managed through the newly created unit. When the device is disconnected or no further management is needed, the user asks the Control Unit Factory to destroy it.
Another beneficial option of a Control Unit Factory is the ability to define custom finder methods for retrieving control units. Such methods can give an optimal and efficient way for control unit searching. For more information on definition of finder methods, refer to "Control Unit Finders".
A Control Unit Factory service should be registered with the following properties in the OSGi framework:
ControlConstants.TYPE) - Specifies
the control unit type as a String. Required.ControlConstants.PARENT_TYPE)
- Shows the types of parent control units - can be a String or
String[]. Optional.ControlConstants.VERSION) - Contains
the version of the control unit type as a String. Optional.A control unit provider should describe the interface of control units of a given type through metadata. Supplied metadata is loaded in the Control Unit Admin, which management applications can use in combination with the Metadata Manager of the ProSyst Metatype Bundle for passing and retrieving information in a correct way.
Control unit metadata is based on the ProSyst Metatype API and should describe a specific control unit type.
The metatype of a Managed Control Unit describes the control unit itself and of a Control Unit Factory - the interface of the control unit instances, which the factory is able to produce.
Control unit metatypes are handled by the ProSyst Metatype Bundle, which implements the OSGi Metatype Specification and supports the ProSyst Metatype API. The bundle's Metadata Manager processes available control unit metatypes and delivers the information to the Control Unit Admin Bundle.
The following lines outline the most important and typical entries, required for a control unit metatype. Detailed description of all metatype entries is available in the description of the ProSyst Metatype Bundle.
A control unit metatype can be access through a Metatype Provider whose ID (i.e. PID) is equal to the control unit type. The control unit is represented by an ObjectClassDefinition whose ID should be also equal to the control unit type. Name, description and icon can be used for control unit representation in a UI application.
AttributeDefinitions within the control unit ObjectClassDefinition describe the state variables. A state variable AttributeDefinition has an ID, type, cardinality and additional key/value constraining properties. Name, description and option labels/values can be used in a UI application.
If the control unit has one or more parents, their type should be specified
by a special attribute with ID "mbs.parent.type" of type String,
cardinality equal to the number of parents (maximum Integer.MAX_VALUE)
and default value indicating the types of parent control units.
If the control unit is designed to inherit another, "super" control
unit, that is, acquire all attributes of its "superior", the the control
unit metatype should contain an attribute with ID "super", type String,
cardinality 0 and default value indicating the type of the super control unit.
An ObjectClassDefinition within the ObjectClassDefinition of the control unit holds the metadata of a control unit action. Input and output arguments should be defined as AttributeDefinitions with modifier "modifier" equal respectively to "in" and "out".
Following is a summarized structure of a control unit metatype:
In order to export the metadata, describing a control unit type, you have two options:
org.mbs.services.metatype.MetatypeProvider service.
To announce that the Metatype Provider delivers a control unit metatype, the provider should have the following string registration properties:
org.osgi.service.metatype.Constants.SERVICE_PID - Indicates
the ID of the metatype this Metatype Provider is designed for. It should
be identical with the control unit type.In its getObjectClassDefinition method
the Metatype Provider service should supply an org.mbs.services.metatype.ObjectClassDefinitionEx
object for the ObjectClassDefinition of the control unit interface.
Control unit actions should be described by separate
ObjectClassDefinitionEx instances, returned by the getObjectClassDefinitions
and getObjectClassDefinition(String id) method of the control
unit ObjectClassDefinitionEx.
AttributeDefinitionEx instances should
wrap state variable and action argument metadata. State variable AttributeDefinitionEx's
should be provided by the control unit ObjectClassDefinitionEx.
AttributeDefinitionEx's for action arguments should be returned
by the corresponding action ObjectClassDefinitionEx's in
conformance with the filter supplied in the getAttributeDefinitions
method - it can be ObjectClassDefinitionEx.INPUT or ObjectClassDefinitionEx.OUTPUT.
A bundle developer can create a metadata XML in compliance with the DTD, required by the ProSyst Metatype Bundle, and place it in the bundle JAR file. The path to the metadata XML and the Metatype Provider ID should be specified in the Control-Unit manifest header:
Control-Unit: xml=<path_to_xml>; pid=<control_unit_type>; name=<user_friendly_name>; version=<control_unit_type_version>
where:
The Control Unit Admin supports the following data types of state variables and action arguments:
Integer, Long,
Byte, Short, Double, Float,
Character, BooleanStringVectors of the above
typesString and values of type wrapper
of a primitive Java type or String.Optionally, control unit providers can support several predefined actions, described in the next paragraphs.
A control unit provider can support setter actions for specific state variables with action IDs in the form of $set.<state_var_id>, where <state_var_id> must be the ID of the state variable the setter action is intended for. Such an action must have a single input argument of the same type as the associated state variable and no output arguments.
A control unit provider can implement one or more actions for filtering control
units, called finders, in a Control Unit Factory. Such an action must
have ID prefixed by $find. (ControlConstants.FINDER_PREFIX)
and can take arbitrary number and type of arguments. The Control Unit Admin
does executes a finder action in a special way - by invoking the findControlUnits
method of the Control Unit Factory with arguments compliant with the finder
action's metadata.
A constructor action can be defined for explicit creation of control
units in a Control Unit Factory. Such an action is whose ID starts with $create.
(ControlConstants.CONSTRUCTOR_PREFIX). and may have
arbitrary number and type of arguments. The Control Unit Admin calls a constructor
through the createControlUnit method of the Control Unit Factory.
By analogy with constructor actions, a Control Unit Factory can support a single
destructor action, whose ID starts with $destroy (ControlConstants.DESTRUCTOR)
and has no arguments, for explicit removal of control units. The Control Unit
Admin executes the destructor action through the destroyControlUnit
method of the Control Unit Factory.
Both a Managed Control Unit and a Control Unit Factory should notify the Control Unit Admin of changes concerning state variables as well as a Control Unit Factory provide notification of created/destroyed control units and of attachment to/detachment from parents as well. The Control Unit Admin will then notify interested listeners of custom applications.
When the Control Unit Admin detects a new Managed Control Unit or Control Unit
Factory, it registers a callback instance (org.mbs.services.cu.spi.CUAdminCallback)
in the Managed Control Unit or in the Control Unit Factory by calling the unit's
or factory's setControlUnitCallback method.
When there are changes in the control unit's state variables, the Managed Control
Unit should call the stateVariableChanged method of the CUAdminCallback
instance passing the new variable value.
A Control Unit Factory should inform the Control Unit Admin of the following changes in the control units it maintains:
The Control Unit Factory should call the controlUnitEvent
method of CUAdminCallback passing event type ControlUnitListener.CONTROL_UNIT_ADDED
or ControlUnitListener.CONTROL_UNIT_REMOVED.
The Control Unit Factory should call the hierarchyChanged
method of CUAdminCallback passing event type HierarchyListener.ATTACHED
or HierarchyListener.DETACHED.
The Control Unit Factory should call the the stateVariableChanged
method of CUAdminCallback passing the new variable value.
The following example contains a simple Managed Control Unit of type "tuner" and ID "test.cu". For simplicity the control unit has one state variable, showing the current state of the tuner, and one action changing the state variable.
ManagedControlUnit Implementation. Listing 1.1 contains the implementation
of the ManagedControlUnit interface. The invokeAction
method, called by the Control Unit Admin on request from a management application,
changes the value of the state variable and notifies the Control Unit Admin
of the change by using the supplied CUAdminCallback instance.
import org.mbs.services.cu.spi.CUAdminCallback; public class MyManagedControlUnit implements ManagedControlUnit {
private CUAdminCallback callback = null; // Constant for the control unit ID public void setControlUnitCallback(CUAdminCallback callback) {
public String getId() {
public String getType() {
public Object invokeAction(String actionId, Object args) throws Exception {
public Object queryStateVariable(String arg0) {
|
Managed Control Unit Registration. Listing 1.2 contains is a bundle activator, which registers the Managed Control Unit in the OSGi service registry, specifying the control unit's type and ID as service registration properties.
import java.util.Hashtable; public class MyControlUnitActivator implements BundleActivator {
private ServiceRegistration cuReg = null; public void start(BundleContext bc) throws Exception {
public void stop(BundleContext bc) throws Exception {
|
Managed Control Unit Metadata. Listing 1.3 contains the metatype of the example Managed Control Unit in XML format. The metatype defines that the control unit's state variable is an integer with ID tuner_state and its action has ID setState and takes an integer input argument.
<?xml version="1.0" encoding="UTF-8"?> |
The metadata XML can be exported by including the following information in the Control-Unit manifest header with the metadata XML file specified as the cu.xml file within the root directory of the bundle JAR file:
Control-Unit: xml=cu.xml; pid=tuner; name=Test Control Unit; version=1.0.0
Following is an example of a Control Unit Factory for type "tuner", which on startup generates 10 control unit instances. The factory also supports a constructor, which creates new control units with the specified IDs, and a finder which is able to find control instances whose IDs start with a specified string.
ControlUnitFactory Implementation. Listing 2.1 contains a simple implementation
of the ControlUnitFactory interface. As supported control unit
instances does not have any parent types, the getControlUnits and
getParents methods return null. The factory does not
have a destructor action, so its the destroyControlUnit method
returns null as well.
import java.util.Enumeration; import org.mbs.services.cu.ControlUnit; public class MyControlUnitFactory implements ControlUnitFactory {
protected CUAdminCallback callback = null; protected MyControlUnitFactory() {
// Creates 10 control unit instances with IDs from 0 to 9 public void setControlUnitCalluback(CUAdminCallback callback) {
public ControlUnit getControlUnit(String cuId) {
public String[] getControlUnits(String arg0, String arg1) {
public String[] listControlUnits() {
// Returns control units whose IDs start with the specified string public String[] getParents(String arg0, String arg1) {
public Object queryStateVariable(String cuId, String varId) {
public Object invokeAction(String cuId, String actionId, Object args) // Creates a control unit instance with specified string ID public void destroyControlUnit(String arg0) throws Exception {
|
Control Unit Factory Registration. Listing 2.2 contains a bundle activator, which registers the Control Unit Factory as a service in the OSGi framework, specifying supported control unit type.
import java.util.Hashtable; |
Control Unit Factory Metadata. Listing 2.3 contains the XML variant of the metadata of the "tuner" control unit type, supported by the example Control Unit Factory. It is similar to Listing 1.3 except for the definition of constructor and finder actions.
<?xml version="1.0" encoding="UTF-8"?> |
The metadata for the Control Unit Factory above, can be specified by providing the next information in the Control-Unit manifest header:
Control-Unit: xml=factcu.xml; pid=tuner; name=Tuner Control Units; version=1.0.0
As previously discussed in this document, the Admin Layer, and namely the Control
Unit Admin, is responsible for granting administration applications access to
control unit instances. Administration applications can call the Control Unit
Admin as a org.mbs.services.cu.ControlUnitAdmin service object
from the OSGi framework registry.
To check which control unit types are currently available, use the getControlUnitTypes
method of the Control Unit Admin. If you need a specific version of a particular
control unit type, call the getControlUnitTypeVersion method to
check it.
To be able to use a control instance by correctly querying its state variables and invoking its actions, a management application should be aware of the control unit type metadata. As previously discussed, control unit metadata is compliant with the ProSyst Metatype API. Data defined through this API can be accessed through the Metadata Manager of the ProSyst Metatype Bundle. For more information on metadata management operations, see the description of the ProSyst Metatype Bundle.
An application can access a control unit of a specific type and with specific
ID by using the getControlUnit method of the Control Unit Admin.
The getControlUnit method returns the control unit as an org.mbs.services.cu.ControlUnit
instance - by using this instance you can further invoke its actions and query
its state variables.
To get the IDs of control units of a specific type, you can use the findControlUnits
method by passing the type of interest and null for finder ID and
arguments.
To perform a query for a state variable, call the queryStateVariable
method of the Control Unit Admin. As a result, the Control Unit Admin will provide
the appropriate object representing the current state variable value.
The Control Unit Admin invokes a control unit action on calling its invokeAction
method, which takes as parameters the control unit type and ID, the action ID
and input arguments. The method returns the result of the action according to
the metadata for the action's output arguments.
The Control Unit Admin is capable of associating parent control units with their descendants and provide this information to interested applications.
To get the parent or sub types of a control unit type through the Control Unit
Admin, you can use respectively the getParentControlUnitTypes or
getSubControlUnitTypes method.
Knowing the type and ID of a control unit and the types of its parents or children,
an application can get the IDs of present parent or child control units by invoking
Control Unit Admin's getParentControlUnits and getSubControlUnits
methods respectively.
If supported by the control unit provider (see "Predefined Actions"), for a control unit type a management application can explicitly create and destroy a control unit instance as well as look for specific instances. The format of input and output arguments for these operations can be taken from the control unit metadata.
To create a control unit instance through a specific constructor action, call
the createControlUnit method of Control Unit Admin, and to destroy
a control unit instance - the destroyControlUnit method. Finder
actions can be invoked through the Control Unit Admin findControlUnits
method. As action ID prefixes, you can use the corresponding constants from
the org.mbs.services.cu.ControlConstants interface.
The Control Unit Admin API defines several types of listeners, which applications can implement in order to receive notifications about control unit changes.
To make control unit related listeners functional, you should register them as services in the OSGi framework. Defined listener types share a common set of service registration properties, which specify control unit types and IDs of interest as well as request synchronous event delivery:
ControlConstants.EVENT_FILTER - A String representation of
an LDAP filter for specifying control unit types and IDs to receive events
from. Filtering is done on the basis of the ControlConstants.TYPE
and ControlConstants.ID search attributes. A Control Unit Listener
with no filter specified receives events for all control units. ControlConstants.EVENT_SYNC - A property with arbitrary value
indicating that the listener asks for synchronous receiving of events.The following listener types exist in the Control Unit Admin API:
ControlUnitListener - Receives events for created or deleted
control unit types and instances.StateVariableListener - Receives events for changes in the
value of a state variable.
In addition to the common filter attributes, a State Variable
Listener can also specify the IDs of state variables of interest by including
the ControlConstants.STATE_VARIABLE_ID search attribute in
the ControlConstants.EVENT_FILTER service registration property.
StateVariableListener.RECEIVE_VALUES_ON_REGISTER
with arbitrary value. The prerequisite for using this option is that subscribed
control unit types have a state variable with ID ControlConstants.SV_LIST_SV_ID
and String[] value containing the IDs of all other state variables.StateVariableBatchListener - Receives events for multiple state
variables' changes, which happened simultaneously for a given control unit,
in a single batch. An application that implements this interface and that
are registered to receive initial state variables' values, will receive the
initial values in a single batch per control unit.HierarchyListener - Receives events for changes in the control
unit hierarchy. Besides the control unit type and ID, the LDAP filter of the
ControlConstants.EVENT_FILTER property should contain the following
search attributes:
ControlConstants.EVENT_TYPE - Specifies whether to receive
events for attached or detached parents of a control unit, or for both.
This attribute can be related to HierarchyListener.ATTACHED
or HierarchyListener.DETACHED.ControlConstants.PARENT_TYPE and ControlConstants.PARENT_ID
- Specifies the type and ID of parent control units to receive events
for.The SimpleControlUnitManager example class, included in Listing
3, uses the Control Unit Admin and Metadata Manager to print the state variable
IDs of currently available control unit types. As the example registers itself
as a Control Unit Listener service, it is also able to print state variable
information for newly appeared control unit types.
import java.io.IOException; |
mBS offers convenient tools for management and generation of control units:
For backward compatibility, this release of the Framework Professional Edition Package includes the previous version of the Control Unit API as well. The "old" Control Unit API is available in the Control Unit Bundle whose JAR file is oldcus.jar located in the bundles installation directory. The Control Unit Bundle also contains the abstract classes from the org.mbs.services.control.util for implementing control units on top of the old Control Unit API, and the
helper classes for easier processing control units' data from the
org.mbs.services.control.helper package.
You can find more information about the previous version of the Control Unit API in the mBS 5.2.03 user documentation.
Note: You can use the Control Unit Converter bundle for accessing control units compliant with the previous version of the Control Unit API through the Control Unit Admin service.