00001
00002
00003
00004 '''rtsprofile
00005
00006 Copyright (C) 2009-2010
00007 Geoffrey Biggs
00008 RT-Synthesis Research Group
00009 Intelligent Systems Research Institute,
00010 National Institute of Advanced Industrial Science and Technology (AIST),
00011 Japan
00012 All rights reserved.
00013 Licensed under the Eclipse Public License -v 1.0 (EPL)
00014 http://www.opensource.org/licenses/eclipse-1.0.txt
00015
00016 File: message_sending.py
00017
00018 Objects for the message sending interface.
00019
00020 '''
00021
00022 __version__ = '$Revision: $'
00023
00024
00025
00026 from rtsprofile import RTS_NS, RTS_NS_S, RTS_EXT_NS, RTS_EXT_NS_S, \
00027 RTS_EXT_NS_YAML
00028 from rtsprofile.exceptions import InvalidParticipantNodeError
00029 from rtsprofile.targets import TargetExecutionContext
00030 from rtsprofile.utils import get_direct_child_elements_xml, \
00031 indent_string, validate_attribute
00032
00033
00034
00035
00036
00037 class MessageSending(object):
00038 '''Defines the orderings and conditions components in the RT system for
00039 various actions.
00040
00041 '''
00042
00043 def __init__(self, targets=[]):
00044 '''@param targets Orderings and conditions.'''
00045 validate_attribute(targets, 'message_sending.Targets',
00046 expected_type=list, required=False)
00047 self._targets = targets
00048
00049 def __str__(self):
00050 result = self.__class__.__name__ + '\n'
00051 if self.targets:
00052 result += 'Targets:\n'
00053 for t in self.targets:
00054 result += '{0}\n'.format(indent_string(str(t)))
00055 return result[:-1]
00056
00057 @property
00058 def targets(self):
00059 '''Orderings and conditions.'''
00060 return self._targets
00061
00062 @targets.setter
00063 def targets(self, targets):
00064 validate_attribute(targets, 'message_sending.targets',
00065 expected_type=list, required=False)
00066 self._targets = targets
00067
00068 def parse_xml_node(self, node):
00069 '''Parse an xml.dom Node object representing a message sending object
00070 into this object.
00071
00072 '''
00073 self._targets = []
00074 for c in node.getElementsByTagNameNS(RTS_NS, 'targets'):
00075 if c.getElementsByTagNameNS(RTS_NS, 'WaitTime'):
00076 new_target = WaitTime()
00077 elif c.getElementsByTagNameNS(RTS_NS, 'Preceding'):
00078 new_target = Preceding()
00079 else:
00080 new_target = Condition()
00081 new_target.parse_xml_node(c)
00082 self._targets.append(new_target)
00083 return self
00084
00085 def parse_yaml(self, y):
00086 '''Parse a YAML speficication of a message sending object into this
00087 object.
00088
00089 '''
00090 self._targets = []
00091 if 'targets' in y:
00092 for t in y['targets']:
00093 if 'waitTime' in t['condition']:
00094 new_target = WaitTime()
00095 elif 'preceding' in t['condition']:
00096 new_target = Preceding()
00097 else:
00098 new_target = Condition()
00099 new_target.parse_yaml(t)
00100 self._targets.append(new_target)
00101 return self
00102
00103 def save_xml(self, doc, element):
00104 '''Save this message_sending object into an xml.dom.Element object.'''
00105 for cond in self._targets:
00106 new_element = doc.createElementNS(RTS_NS, RTS_NS_S + 'targets')
00107 cond.save_xml(doc, new_element)
00108 element.appendChild(new_element)
00109
00110 def to_dict(self):
00111 '''Save this message sending object into a dictionary.'''
00112 targets = []
00113 for cond in self._targets:
00114 targets.append(cond.to_dict())
00115 if targets:
00116 return {'targets': targets}
00117 else:
00118 return {}
00119
00120
00121
00122
00123
00124 class StartUp(MessageSending):
00125 '''Specifies the start order and conditions of components when the RT
00126 system is started.
00127
00128 '''
00129 pass
00130
00131
00132
00133
00134
00135 class ShutDown(MessageSending):
00136 '''Specifies the stop order and conditions of components when the RT system
00137 is stopped.
00138
00139 '''
00140 pass
00141
00142
00143
00144
00145
00146 class Activation(MessageSending):
00147 '''Specifies the activation order and conditions of components when the RT
00148 system is activated.
00149
00150 '''
00151 pass
00152
00153
00154
00155
00156
00157 class Deactivation(MessageSending):
00158 '''Specifies the deactivation order and conditions of components when the RT
00159 system is deactivated.
00160
00161 '''
00162 pass
00163
00164
00165
00166
00167
00168 class Resetting(MessageSending):
00169 '''Specifies the reset order and conditions of components when the RT
00170 system is reset.
00171
00172 '''
00173 pass
00174
00175
00176
00177
00178
00179 class Initialize(MessageSending):
00180 '''Specifies the initialisation order and conditions of components when the
00181 RT system is initialised.
00182
00183 '''
00184 pass
00185
00186
00187
00188
00189
00190 class Finalize(MessageSending):
00191 '''Specifies the finalisation order and conditions of components when the
00192 RT system is finalised.
00193
00194 '''
00195 pass
00196
00197
00198
00199
00200
00201 class Condition(object):
00202 '''Specifies execution orderings and conditions for RT components in the RT
00203 system.
00204
00205 Execution conditions can include the time to wait before executing and
00206 order of precedence for components. The involved RT component is specified
00207 using @ref TargetExecutionContext.
00208
00209 '''
00210
00211 def __init__(self, sequence=0, target_component=TargetExecutionContext()):
00212 '''Constructor.
00213
00214 @param sequence Execution order of the target component.
00215 @type sequence int
00216 @param target_component The target of the condition.
00217 @type target_component TargetComponent
00218 '''
00219 validate_attribute(sequence, 'conditions.sequence',
00220 expected_type=int, required=False)
00221 self._sequence = sequence
00222 validate_attribute(target_component, 'conditions.TargetComponent',
00223 expected_type=TargetExecutionContext,
00224 required=True)
00225 self._target_component = target_component
00226 self._properties = {}
00227
00228 def __str__(self):
00229 result = 'Sequence: {0}\nTargetEC:\n{1}\n'.format(self.sequence,
00230 indent_string(str(self.target_component)))
00231 if self.properties:
00232 result += 'Properties:\n'
00233 for p in self.properties:
00234 result += ' {0}: {1}\n'.format(p, self.properties[p])
00235 return result[:-1]
00236
00237 @property
00238 def sequence(self):
00239 '''The execution order of the target components for the various
00240 actions.
00241
00242 '''
00243 return self._sequence
00244
00245 @sequence.setter
00246 def sequence(self, sequence):
00247 validate_attribute(sequence, 'conditions.sequence',
00248 expected_type=int, required=False)
00249 self._sequence = sequence
00250
00251 @property
00252 def target_component(self):
00253 '''Target component of the condition.'''
00254 return self._target_component
00255
00256 @target_component.setter
00257 def target_component(self, target_component):
00258 validate_attribute(target_component, 'conditions.TargetComponent',
00259 expected_type=TargetExecutionContext,
00260 required=True)
00261 self._target_component = target_component
00262
00263 @property
00264 def properties(self):
00265 '''Miscellaneous properties.
00266
00267 Stores key/value pair properties.
00268
00269 Part of the extended profile.
00270
00271 '''
00272 return self._properties
00273
00274 @properties.setter
00275 def properties(self, properties):
00276 validate_attribute(properties, 'conditions.ext.Properties',
00277 expected_type=dict, required=False)
00278 self._properties = properties
00279
00280 def parse_xml_node(self, node):
00281 '''Parse an xml.dom Node object representing a condition into this
00282 object.
00283
00284 '''
00285 self.sequence = int(node.getAttributeNS(RTS_NS, 'sequence'))
00286 c = node.getElementsByTagNameNS(RTS_NS, 'TargetComponent')
00287 if c.length != 1:
00288 raise InvalidParticipantNodeError
00289 self.target_component = TargetExecutionContext().parse_xml_node(c[0])
00290 for c in get_direct_child_elements_xml(node, prefix=RTS_EXT_NS,
00291 local_name='Properties'):
00292 name, value = parse_properties_xml(c)
00293 self._properties[name] = value
00294 return self
00295
00296 def parse_yaml(self, y):
00297 '''Parse a YAML specification of a condition into this object.'''
00298 self.sequence = int(y['sequence'])
00299 self.target_component = \
00300 TargetExecutionContext().parse_yaml(y['targetComponent'])
00301 if RTS_EXT_NS_YAML + 'properties' in y:
00302 for p in y.get(RTS_EXT_NS_YAML + 'properties'):
00303 if 'value' in p:
00304 value = p['value']
00305 else:
00306 value = None
00307 self._properties[p['name']] = value
00308 return self
00309
00310 def save_xml(self, doc, element):
00311 '''Save this condition into an xml.dom.Element object.'''
00312 element.setAttributeNS(RTS_NS, RTS_NS_S + 'sequence',
00313 str(self.sequence))
00314 new_element = doc.createElementNS(RTS_NS, RTS_NS_S + 'TargetComponent')
00315 self.target_component.save_xml(doc, new_element)
00316 element.appendChild(new_element)
00317 for p in self.properties:
00318 new_prop_element = doc.createElementNS(RTS_EXT_NS,
00319 RTS_EXT_NS_S + 'Properties')
00320 properties_to_xml(new_prop_element, p, self.properties[p])
00321 element.appendChild(new_prop_element)
00322
00323 def to_dict(self):
00324 '''Save this condition into a dictionary.'''
00325 d = {'sequence': self.sequence,
00326 'targetComponent': self.target_component.to_dict()}
00327 props = []
00328 for name in self.properties:
00329 p = {'name': name}
00330 if self.properties[name]:
00331 p['value'] = str(self.properties[name])
00332 props.append(p)
00333 if props:
00334 d[RTS_EXT_NS_YAML + 'properties'] = props
00335 return d
00336
00337
00338
00339
00340
00341 class Preceding(Condition):
00342 '''Specifies that the target RT component should precede other RT
00343 components that are part of the same action (e.g. activation) when that
00344 action is executed.
00345
00346 '''
00347
00348 def __init__(self, sequence=0, target_component=TargetExecutionContext(),
00349 timeout=0, sending_timing='', preceding_components=[]):
00350 '''Constructor.
00351
00352 @param sequence Execution order of the target component.
00353 @type sequence int
00354 @param target_component The target of the condition.
00355 @type target_component TargetComponent
00356 @param timeout Status check timeout.
00357 @type timeout int
00358 @param sending_timing Timing for executing actions.
00359 @type sending_timing str
00360 @param preceding_components Preceding components of the condition.
00361 @type preceding components list(TargetExecutionContext)
00362
00363 '''
00364 super(Preceding, self).__init__(sequence, target_component)
00365 validate_attribute(timeout, 'preceding.timeout',
00366 expected_type=int, required=False)
00367 self._timeout = timeout
00368 validate_attribute(sending_timing, 'preceding.sendingTiming',
00369 expected_type=[str, unicode], required=False)
00370 self._sending_timing = sending_timing
00371 validate_attribute(preceding_components,
00372 'preceding.PrecedingComponents',
00373 expected_type=list, required=False)
00374 self._preceding_components = preceding_components
00375
00376 def __str__(self):
00377 result = 'Timeout: {0}\nSending timing: {1}\n{2}'.format(self.timeout,
00378 self.sending_timing, Condition.__str__(self))
00379 if self.preceding_components:
00380 for pc in self.preceding_components:
00381 result += '\nPreceding component:\n{0}'.format(\
00382 indent_string(str(pc)))
00383 return result
00384
00385 @property
00386 def timeout(self):
00387 '''Time out for checking if the target component has executed the
00388 action successfully.
00389
00390 Can be zero. Specified in milliseconds.
00391
00392 '''
00393 return self._timeout
00394
00395 @timeout.setter
00396 def timeout(self, timeout):
00397 validate_attribute(timeout, 'preceding.timeout',
00398 expected_type=int, required=False)
00399 self._timeout = timeout
00400
00401 @property
00402 def sending_timing(self):
00403 '''Timing for executing actions.
00404
00405 Either wait for the preceding RT component to finish executing the
00406 action (specified by "SYNC"), or execute the action without waiting for
00407 the preceding RT component to finish (specified by "ASYNC"). When not
00408 specified, the first option will be assumed.
00409
00410 '''
00411 return self._sending_timing
00412
00413 @sending_timing.setter
00414 def sending_timing(self, sending_timing):
00415 validate_attribute(sending_timing, 'preceding.sendingTiming',
00416 expected_type=[str, unicode], required=False)
00417 self._sending_timing = sending_timing
00418
00419 @property
00420 def preceding_components(self):
00421 '''Preceding components of this condition.'''
00422 return self._preceding_components
00423
00424 @preceding_components.setter
00425 def preceding_components(self, preceding_components):
00426 validate_attribute(sending_timing, 'preceding.PrecedingComponents',
00427 expected_type=list, required=False)
00428 self._preceding_components = preceding_components
00429
00430 def parse_xml_node(self, node):
00431 '''Parse an xml.dom Node object representing a preceding condition into
00432 this object.
00433
00434 '''
00435 super(Preceding, self).parse_xml_node(node)
00436 p_nodes = node.getElementsByTagNameNS(RTS_NS, 'Preceding')
00437 if p_nodes.length != 1:
00438 raise InvalidParticipantNodeError
00439 p_node = p_nodes[0]
00440 if p_node.hasAttributeNS(RTS_NS, 'timeout'):
00441 self.timeout = int(p_node.getAttributeNS(RTS_NS, 'timeout'))
00442 else:
00443 self.timeout = 0
00444 if p_node.hasAttributeNS(RTS_NS, 'sendingTiming'):
00445 self.sending_timing = p_node.getAttributeNS(RTS_NS, 'sendingTiming')
00446 else:
00447 self.sending_timing = 'ASYNC'
00448 self._preceding_components = []
00449 for c in p_node.getElementsByTagNameNS(RTS_NS, 'PrecedingComponents'):
00450 self._preceding_components.append(TargetExecutionContext().parse_xml_node(c))
00451 return self
00452
00453 def parse_yaml(self, y):
00454 '''Parse a YAML specification of a preceding condition into this
00455 object.
00456
00457 '''
00458 super(Preceding, self).parse_yaml(y)
00459 c = y['condition']['preceding']
00460 if 'timeout' in c:
00461 self.timeout = int(c['timeout'])
00462 else:
00463 self.timeout = 0
00464 if 'sendingTiming' in c:
00465 self.sending_timing = c['sendingTiming']
00466 else:
00467 self.sending_timing = 'ASYNC'
00468 self._preceding_components = []
00469 if 'precedingComponents' in c:
00470 for p in c.get('precedingComponents'):
00471 self._preceding_components.append(TargetExecutionContext().parse_yaml(p))
00472 return self
00473
00474 def save_xml(self, doc, element):
00475 '''Save this preceding condition into an xml.dom.Element object.'''
00476 super(Preceding, self).save_xml(doc, element)
00477 pre_element = doc.createElementNS(RTS_NS, RTS_NS_S + 'Preceding')
00478 if self.timeout:
00479 pre_element.setAttributeNS(RTS_NS, RTS_NS_S + 'timeout',
00480 str(self.timeout))
00481 if self.sending_timing:
00482 pre_element.setAttributeNS(RTS_NS, RTS_NS_S + 'sendingTiming',
00483 self.sending_timing)
00484 for pc in self._preceding_components:
00485 new_element = doc.createElementNS(RTS_NS,
00486 RTS_NS_S + 'PrecedingComponents')
00487 pc.save_xml(doc, new_element)
00488 pre_element.appendChild(new_element)
00489 element.appendChild(pre_element)
00490
00491 def to_dict(self):
00492 '''Save this preceding condition into a dictionary.'''
00493 d = super(Preceding, self).to_dict()
00494 e = {}
00495 if self.timeout != 0:
00496 e['timeout'] = self.timeout
00497 if self.sending_timing:
00498 e['sendingTiming'] = self.sending_timing
00499 pcs = []
00500 for pc in self._preceding_components:
00501 pcs.append(pc.to_dict())
00502 if pcs:
00503 e['precedingComponents'] = pcs
00504 d['condition'] = {'preceding': e}
00505 return d
00506
00507
00508
00509
00510
00511 class WaitTime(Condition):
00512 '''Specifies the time to wait before executing the specified action on the
00513 target RT component. After the action command is received by the RT
00514 component, it will wait the specified length of time before executing it.
00515
00516 '''
00517
00518 def __init__(self, wait_time=0, sequence=0,
00519 target_component=TargetExecutionContext()):
00520 '''Constructor.
00521
00522 @param sequence Execution order of the target component.
00523 @type sequence int
00524 @param target_component The target of the condition.
00525 @type target_component TargetComponent
00526 @param wait_time The length of time to wait, in milliseconds.
00527 @type wait_time int
00528
00529 '''
00530 super(WaitTime, self).__init__(sequence, target_component)
00531 validate_attribute(wait_time, 'wait_time.waitTime',
00532 expected_type=int, required=False)
00533 self._wait_time = wait_time
00534
00535 def __str__(self):
00536 return 'Wait time: {0}\n{1}'.format(self.wait_time,
00537 Condition.__str__(self))
00538
00539 @property
00540 def wait_time(self):
00541 '''The length of time to wait before executing the specified action.
00542
00543 In milliseconds.
00544
00545 '''
00546 return self._wait_time
00547
00548 @wait_time.setter
00549 def wait_time(self, wait_time):
00550 validate_attribute(wait_time, 'wait_time.waitTime',
00551 expected_type=int, required=False)
00552 self._wait_time = wait_time
00553
00554 def parse_xml_node(self, node):
00555 '''Parse an xml.dom Node object representing a wait_time condition into
00556 this object.
00557
00558 '''
00559 super(WaitTime, self).parse_xml_node(node)
00560 wait_time_nodes = node.getElementsByTagNameNS(RTS_NS, 'WaitTime')
00561 if wait_time_nodes.length != 1:
00562 raise InvalidParticipantNodeError
00563 self.wait_time = int(wait_time_nodes[0].getAttributeNS(RTS_NS,
00564 'waitTime'))
00565 return self
00566
00567 def parse_yaml(self, y):
00568 '''Parse a YAML specification of a wait_time condition into this
00569 object.
00570
00571 '''
00572 super(WaitTime, self).parse_yaml(y)
00573 self.wait_time = int(y['condition']['waitTime']['waitTime'])
00574 return self
00575
00576 def save_xml(self, doc, element):
00577 '''Save this wait_time condition into an xml.dom.Element object.'''
00578 super(WaitTime, self).save_xml(doc, element)
00579 new_element = doc.createElementNS(RTS_NS, RTS_NS_S + 'WaitTime')
00580 new_element.setAttributeNS(RTS_NS, RTS_NS_S + 'waitTime',
00581 str(self.wait_time))
00582 element.appendChild(new_element)
00583
00584 def to_dict(self):
00585 '''Save this wait_time condition into a dictionary.'''
00586 d = super(WaitTime, self).to_dict()
00587 d['condition'] = {'waitTime': {'waitTime': self.wait_time}}
00588 return d
00589
00590
00591
00592