6 Copyright (C) 2009-2014     8     RT-Synthesis Research Group     9     Intelligent Systems Research Institute,    10     National Institute of Advanced Industrial Science and Technology (AIST),    13 Licensed under the Eclipse Public License -v 1.0 (EPL)    14 http://www.opensource.org/licenses/eclipse-1.0.txt    16 Object representing a component node in the tree.    32 from rtctree.utils import build_attr_string, nvlist_to_dict, dict_to_nvlist
    39     '''Node representing a component on a name server.    41     Component nodes can occur below name server and directory nodes. They    42     cannot contain any children.    44     Component nodes store all the properties of a component, as well as    45     references to the actual objects and object types used in the component.    47     This node can be made dynamic by setting the 'dynamic' property to True.    48     The following callbacks are available on this node type when it is dynamic:    50     - rtc_status(ec_handle, status)    51       The component's state has changed in the specified execution context. The    52       new status is one of Component.INACTIVE, Component.ACTIVE,    53       Component.ERROR, Component.UNKNOWN and Component.CREATED.    54     - component_profile(items)    55       One or more members of the component's profiles have been updated. The    56       updated items are listed in the "items" argument.    57     - ec_event(ec_handle, event)    58       A change in one of the attached execution contexts has occurred. The    59       event is one of Component.EC_ATTACHED, Component.EC_DETACHED,    60       Component.EC_RATE_CHANGED, Component.EC_STARTUP, and    61       Component.EC_SHUTDOWN.    62     - port_event(port_name, event)    63       A change on the specified port has occurred. The event is one of    64       Component.PORT_ADD, Component.PORT_REMOVE, Component.PORT_CONNECT and    65       Component.PORT_DISCONNECT.    66     - config_event(config_set_name, event)    67       A change in the component's configuration sets has occurred. The event is    68       one of Component.CFG_UPDATE_SET, Component.CFG_UPDATE_PARAM,    69       Component.CFG_UPDATE_PARAM_IN_ACTIVE, Component.CFG_ADD_SET,    70       Component.CFG_REMOVE_SET and Component.CFG_ACTIVATE_SET.    72       A heartbeat was received from the component. The time the beat was    76     def __init__(self, name=None, parent=None, obj=None, *args, **kwargs):
    79         @param name Name of this component (i.e. its entry in the path).    80         @param parent The parent node of this node, if any.    81         @param obj The CORBA LightweightRTObject object to wrap.    89         super(Component, self).
__init__(name=name, parent=parent,
    91         self.
_set_events([
'rtc_status', 
'component_profile', 
'ec_event',
    92             'port_event', 
'config_event', 
'heartbeat'])
    97         '''Reparse the component's information.    99         This will cause a delayed reparse of most information. This means that   100         a piece of information, such as the list of ports, will be cleared and   101         remain empty until it is next requested, at which point a fresh list   102         will be retrieved from the component.   104         If you only want to reparse a specific piece of information, use one of   105         the reparse_X() methods.   112         '''Delayed reparse configuration sets.'''   116         '''Delayed reparse all execution contexts.'''   121         '''Delayed reparse only owned execution contexts.'''   125         '''Delayed reparse only participating execution contexts.'''   129         '''Delayed reparse ports.'''   133         '''Delayed reparse the component's profile.'''   141         '''The category in which the component belongs.'''   147         '''The component's description.'''   153         '''Instance name of the component.'''   159         '''The name of the component's parent object (typically another   160         component), if it has one.   168         '''The component's extra properties dictionary.'''   174         '''Type name of the component.'''   180         '''The component's vendor.'''   186         '''The component's version.'''   194         '''Add other RT Components to this composite component as members.   196         This component must be a composite component.   205         org.add_members([x.object 
for x 
in rtcs])
   210         '''Remove other RT Components from this composite component.   212         rtcs is a list of components to remove. Each element must be either an   213         rtctree.Component object or a string containing a component's instance   214         name. rtctree.Component objects are more reliable.   216         This component must be a composite component.   222         members = org.get_members()
   227                 rtc_name = rtc.instance_name
   232             org.remove_member(rtc_name)
   238         '''The parent component in the composition.   240         None if this component is not a member of a composition.   247         '''Is the component a composite component.'''   248         return self._obj.get_owned_organizations() != []
   252         '''Is the component a member of a composite component.'''   253         return self._obj.get_organizations() != []
   256         '''Is the given component a member of this composition?   258         rtc may be a Component object or a string containing a component's   259         instance name. Component objects are more reliable.   261         Returns False if the given component is not a member of this   264         Raises NotCompositeError if this component is not a composition.   272                 if m.get_component_profile().instance_name == rtc:
   276                 if m._is_equivalent(rtc.object):
   282         '''Member components if this component is composite.'''   288                     self.
_members[o.org_id] = o.obj.get_members()
   293         '''The organisations of this composition.'''   295             def __init__(self, sdo_id, org_id, members, obj):
   303                 for org 
in self._obj.get_owned_organizations():
   304                     owner = org.get_owner()
   306                         sdo_id = owner._narrow(SDOPackage.SDO).get_sdo_id()
   309                     org_id = org.get_organization_id()
   310                     members = [m.get_sdo_id() 
for m 
in org.get_members()]
   311                     self._orgs.append(Org(sdo_id, org_id, members, org))
   316         '''The organisation IDs of this composition.'''   317         return [sdo.get_organization_id() 
for sdo 
in \
   318                 self._obj.get_owned_organizations()]
   322         '''The organisation IDs of the compositions this RTC belongs to.'''   323         return [sdo.get_organization_id() 
for sdo 
in \
   324                 self._obj.get_organizations() 
if sdo]
   328         '''The SDO IDs of the compositions this RTC belongs to.'''   329         return [sdo.get_owner()._narrow(SDOPackage.SDO).get_sdo_id() \
   330                 for sdo 
in self._obj.get_organizations() 
if sdo]
   334         '''The organisations this RTC belongs to.'''   342                 for sdo 
in self._obj.get_organizations():
   345                     owner = sdo.get_owner()
   347                         sdo_id = owner._narrow(SDOPackage.SDO).get_sdo_id()
   350                     org_id = sdo.get_organization_id()
   351                     self._parent_orgs.append(ParentOrg(sdo_id, org_id))
   358         '''Stop the component's execution contexts and finalise it.   360         This will have flow-on effects to any other components using this   361         component's execution contexts and any child components.   363         @return The result of attempting to exit.   367             return self._obj.exit()
   370         '''Activate this component in an execution context.   372         @param ec_index The index of the execution context to activate in.   373                         This index is into the total array of contexts, that   374                         is both owned and participating contexts. If the value   375                         of ec_index is greater than the length of   376                         @ref owned_ecs, that length is subtracted from   377                         ec_index and the result used as an index into   378                         @ref participating_ecs.   389             ec.activate_component(self.
_obj)
   392         '''Deactivate this component in an execution context.   394         @param ec_index The index of the execution context to deactivate in.   395                         This index is into the total array of contexts, that   396                         is both owned and participating contexts. If the value   397                         of ec_index is greater than the length of   398                         @ref owned_ecs, that length is subtracted from   399                         ec_index and the result used as an index into   400                         @ref participating_ecs.   411             ec.deactivate_component(self.
_obj)
   414         '''Make a component exit.   416         This function will make the component exit, shutting down its CORBA   417         object in the process. It will not remove the node from the tree; a   418         reparse is necessary to do that.   424         '''Get a reference to the execution context with the given handle.   426         @param ec_handle The handle of the execution context to look for.   428         @return A reference to the ExecutionContext object corresponding to   430         @raises NoECWithHandleError   435                 if ec.handle == ec_handle:
   438                 if ec.handle == ec_handle:
   440             raise NoECWithHandleError
   444         '''Get the index of the execution context with the given handle.   446         @param ec_handle The handle of the execution context to look for.   448         @return The index into the owned + participated arrays, suitable for   449         use in methods such as @ref activate_in_ec, or -1 if the EC was not   451         @raises NoECWithHandleError   456                 if ec.handle == ec_handle:
   459                 if ec.handle == ec_handle:
   461             raise NoECWithHandleError
   464         '''Get the state of this component as an optionally-coloured string.   466         @param add_colour If True, ANSI colour codes will be added to the   468         @return A string describing the state of this component.   473                 result = 
'Inactive', [
'bold', 
'blue']
   475                 result = 
'Active', [
'bold', 
'green']
   477                 result = 
'Error', [
'bold', 
'white', 
'bgred']
   479                 result = 
'Unknown', [
'bold', 
'red']
   481                 result = 
'Created', [
'reset']
   489         '''Get the state of the component in an execution context as a string.   491         @param ec_index The index of the execution context to check the state   492                         in. This index is into the total array of contexts,   493                         that is both owned and participating contexts. If the   494                         value of ec_index is greater than the length of @ref   495                         owned_ecs, that length is subtracted from ec_index and   496                         the result used as an index into @ref   509             result = 
'Inactive', [
'bold', 
'blue']
   510         elif state == self.
ACTIVE:
   511             result = 
'Active', [
'bold', 
'green']
   512         elif state == self.
ERROR:
   513             result = 
'Error', [
'bold', 
'white', 
'bgred']
   515             result = 
'Unknown', [
'bold', 
'red']
   517             result = 
'Created', [
'reset']
   521                     supported=add_colour)
   526         '''Reset this component in an execution context.   528         @param ec_index The index of the execution context to reset in. This   529                         index is into the total array of contexts, that is both   530                         owned and participating contexts. If the value of   531                         ec_index is greater than the length of @ref owned_ecs,   532                         that length is subtracted from ec_index and the result   533                         used as an index into @ref participating_ecs.   544             ec.reset_component(self.
_obj)
   547         '''Get the state of the component in an execution context.   549         @param ec_index The index of the execution context to check the state   550                         in. This index is into the total array of contexts,   551                         that is both owned and participating contexts. If the   552                         value of ec_index is greater than the length of @ref   553                         owned_ecs, that length is subtracted from ec_index and   554                         the result used as an index into @ref   568         '''Get the up-to-date state of the component in an execution context.   570         This function will update the state, rather than using the cached   571         value. This may take time, if the component is executing on a remote   574         @param ec_index The index of the execution context to check the state   575                         in. This index is into the total array of contexts,   576                         that is both owned and participating contexts. If the   577                         value of ec_index is greater than the length of @ref   578                         owned_ecs, that length is subtracted from ec_index and   579                         the result used as an index into @ref   597         '''Is this component alive?'''   599             if self.exec_contexts:
   600                 for ec 
in self.exec_contexts:
   601                     if self._obj.is_alive(ec):
   607         '''The state of each execution context this component owns.'''   621         '''A list of the execution contexts owned by this component.'''   625                     self._obj.get_context_handle(ec)) \
   626                     for ec 
in self._obj.get_owned_contexts()]
   631         '''The state of each execution context this component is participating   648         '''A list of the execution contexts this component is participating in.   654                                     self._obj.get_context_handle(ec)) \
   655                              for ec 
in self._obj.get_participating_contexts()]
   660         '''The state of this component as a string without colour.'''   665         '''The merged state of all the execution context states, which can be   666         used as the overall state of this component.   668         The order of precedence is:   669             Error > Active > Inactive > Created > Unknown   672         def merge_state(current, new):
   673             if new == self.
ERROR:
   694                     merged_state = merge_state(merged_state, ec_state)
   697                     merged_state = merge_state(merged_state, ec_state)
   702         '''The state of this component as a colourised string.'''   709         '''Disconnect all connections to all ports of this component.'''   715         '''Get a port of this component by name.'''   718                 if p.name == port_name:
   723         '''Get a port of this component by reference to a CORBA PortService   729                 if p.object._is_equivalent(port_ref):
   734         '''Check if this component has a port by the given name.'''   741         '''Check if this component has a port by the given reference to a CORBA   752         '''The list of all input ports belonging to this component that are   753         connected to one or more other ports.   756         return [p 
for p 
in self.
ports \
   757                 if p.__class__.__name__ == 
'DataInPort' and p.is_connected]
   761         '''The list of all output ports belonging to this component that are   762         connected to one or more other ports.   765         return [p 
for p 
in self.
ports \
   766                     if p.__class__.__name__ == 
'DataOutPort' \
   771         '''The list of all ports belonging to this component that are connected   772         to one or more other ports.   775         return [p 
for p 
in self.
ports if p.is_connected]
   779         '''The list of all service ports belonging to this component that are   780         connected to one or more other ports.   783         return [p 
for p 
in self.
ports \
   784                 if p.__class__.__name__ == 
'CorbaPort' and p.is_connected]
   788         '''The list of all input ports belonging to this component.'''   789         return [p 
for p 
in self.
ports if p.__class__.__name__ == 
'DataInPort']
   793         '''The list of all output ports belonging to this component.'''   794         return [p 
for p 
in self.
ports if p.__class__.__name__ == 
'DataOutPort']
   798         '''The list of all ports belonging to this component.'''   802                                for port 
in self._obj.get_ports()]
   807         '''The list of all service ports belonging to this component.'''   808         return [p 
for p 
in self.
ports if p.__class__.__name__ == 
'CorbaPort']
   815         '''The time of the last heartbeat.   817         Updated only when the node is dynamic.   824         '''Is this node a component?'''   829         '''Returns the list of logger IDs attached to this component.'''   830         return self._loggers.keys()
   834         '''The LightweightRTObject this object wraps.'''   839         '''Add a callback to receive log events from this component.   841         @param cb The callback function to receive log events. It must have the   842             signature cb(name, time, source, level, message), where name is the   843             name of the component the log record came from, time is a   844             floating-point time stamp, source is the name of the logger that   845             provided the log record, level is the log level of the record and   846             message is a text string.   847         @param level The maximum level of log records to receive.   848         @param filters Filter the objects from which to receive log messages.   849         @return An ID for this logger. Use this ID in future operations such as   850                 removing this logger.   851         @raises AddLoggerError   856             uuid_val = uuid.uuid4()
   857             intf_type = obs._this()._NP_RepositoryId
   858             props = {
'logger.log_level': level,
   859                     'logger.filter': filters}
   861             sprof = SDOPackage.ServiceProfile(id=uuid_val.get_bytes(),
   862                     interface_type=intf_type, service=obs._this(),
   864             conf = self.object.get_configuration()
   865             res = conf.add_service_profile(sprof)
   874         @param cb_id The ID of the logger to remove.   875         @raises NoLoggerError   880         conf = self.object.get_configuration()
   881         res = conf.remove_service_profile(cb_id.get_bytes())
   888         '''Activate a configuration set by name.   890         @raises NoSuchConfSetError   896             self._conf.activate_configuration_set(set_name)
   899         '''Set a configuration set parameter value.   901         @param set_name The name of the configuration set the destination   903         @param param The name of the parameter to set.   904         @param value The new value for the parameter.   905         @raises NoSuchConfSetError, NoSuchConfParamError   911             if not self.
conf_sets[set_name].has_param(param):
   913             self.
conf_sets[set_name].set_param(param, value)
   914             self._conf.set_configuration_set_values(\
   919         '''The currently-active configuration set.'''   929         '''The name of the currently-active configuration set.'''   939         '''The dictionary of configuration sets in this component, if any.'''   950         raise CannotHoldChildrenError
   957                     cs = self._conf.get_configuration_set(name)
   958                     self.
_conf_sets[name]._reload(cs, cs.description,
   962                     cset, param = name.split(
'.')
   963                     cs = self._conf.get_configuration_set(cset)
   965                     self.
_conf_sets[cset].set_param(param, data[param])
   968                     cs = self._conf.get_configuration_set(name)
   979         self.
_call_cb(
'config_event', (name, event))
   984             uuid_val = uuid.uuid4().get_bytes()
   985             intf_type = obs._this()._NP_RepositoryId
   987                 'heartbeat.interval': 
'1.0',
   988                 'observed_status': 
'ALL'})
   989             sprof = SDOPackage.ServiceProfile(id=uuid_val,
   990                     interface_type=intf_type, service=obs._this(),
   992             conf = self.object.get_configuration()
   993             res = conf.add_service_profile(sprof)
  1001             conf = self.object.get_configuration()
  1002             res = conf.remove_service_profile(self.
_obs_id)
  1014                     if ec.handle == ec_handle:
  1020                     if ec.handle == ec_handle:
  1030                     self._obj.get_context(ec_handle), ec_handle))
  1035                 ec, loc = 
get_ec(ec_handle)
  1042                 ec, loc = 
get_ec(ec_handle)
  1044                     ec._set_running(
True)
  1046                 ec, loc = 
get_ec(ec_handle)
  1048                     ec._set_running(
False)
  1050         self.
_call_cb(
'ec_event', (ec_handle, state))
  1054         if self._obj.is_alive(ec._obj):
  1055             ec_state = ec.get_component_state(self.
_obj)
  1056             if ec_state == RTC.ACTIVE_STATE:
  1058             elif ec_state == RTC.ERROR_STATE:
  1060             elif ec_state == RTC.INACTIVE_STATE:
  1075             self.
_conf = self.object.get_configuration()
  1077             for cs 
in self._conf.get_configuration_sets():
  1082             except SDOPackage.NotAvailable:
  1088             profile = self._obj.get_component_profile()
  1097                         profile.parent.get_component_profile().instance_name
  1103         def get_port_obj(port_name):
  1104             for p_obj 
in self._obj.get_ports():
  1105                 prof = p_obj.get_port_profile()
  1106                 if prof.name == port_name:
  1108             raise ValueError(port_name)
  1114                     p_obj = get_port_obj(port_name)
  1119                     self._ports.remove(p)
  1123                     p.reparse_connections()
  1127                     p.reparse_connections()
  1129         self.
_call_cb(
'port_event', (port_name, event))
  1135         self.
_call_cb(
'component_profile', items)
  1188         self.
_call_cb(
'rtc_status', (ec_handle, state))
  1206     EC_RATE_CHANGED = 13
  1219     PORT_DISCONNECT = 24
  1224     CFG_UPDATE_PARAM = 32
  1232     CFG_ACTIVATE_SET = 36
 Execution context object. 
def get_ec(self, ec_handle)
def activate_conf_set(self, set_name)
Configuration set management. 
def _add_child(self)
Internal API. 
def deactivate_in_ec(self, ec_index)
def __init__(self, name=None, parent=None, obj=None, args, kwargs)
def set_conf_set_value(self, set_name, param, value)
def get_state_in_ec_string(self, ec_index, add_colour=True)
def participating_ec_states(self)
def activate_in_ec(self, ec_index)
def add_members(self, rtcs)
Composite component information and management. 
def _profile_update(self, items)
def refresh_state_in_ec(self, ec_index)
def add_logger(self, cb, level='NORMAL', filters='ALL')
def disconnect_all(self)
Port management. 
def _reset_participating_ec_states(self)
def has_port_by_ref(self, port_ref)
def state_in_ec(self, ec_index)
def category(self)
Component information. 
def connected_outports(self)
def parent_organisations(self)
def remove_logger(self, cb_id)
def exit(self)
State management. 
def active_conf_set_name(self)
def connected_inports(self)
def connected_svcports(self)
Configuration set object. 
def parent_org_sdo_ids(self)
def plain_state_string(self)
def get_state_string(self, add_colour=True)
def _ec_event(self, ec_handle, event)
def _reset_participating_ecs(self)
def _config_event(self, name, event)
def reparse_owned_ecs(self)
def is_composite_member(self)
def remove_members(self, rtcs)
def reparse_participating_ecs(self)
def _port_event(self, port_name, event)
def build_attr_string(attrs, supported=True)
def active_conf_set(self)
def get_port_by_name(self, port_name)
def heartbeat_time(self)
Node functionality. 
def reset_in_ec(self, ec_index)
def _get_ec_state(self, ec)
def _set_state_in_ec(self, ec_handle, state)
def has_port_by_name(self, port_name)
def composite_parent(self)
def nvlist_to_dict(nvlist)
def owned_ec_states(self)
def participating_ecs(self)
def _reset_owned_ec_states(self)
def connected_ports(self)
def _parse_configuration(self)
def reparse_conf_sets(self)
def _enable_dynamic(self, enable=True)
def parse_port(port_obj, owner)
API functions. 
def _call_cb(self, event, value)
def _set_events(self, events)
def reparse_profile(self)
def _reset_composite(self)
def _reset_conf_sets(self)
def get_port_by_ref(self, port_ref)
def get_ec_index(self, ec_handle)
def _reset_owned_ecs(self)