Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 import copy
00012 import re
00013 import rocon_gateway_utils
00014
00015 from . import utils
00016 from . import interactive_interface
00017
00018
00019
00020
00021
00022
00023 class PulledInterface(interactive_interface.InteractiveInterface):
00024
00025 '''
00026 The pulled interface is the set of rules
00027 (pubs/subs/services/actions) and rules controlling pulls from
00028 other gateways.
00029 '''
00030
00031 def __init__(self, default_rule_blacklist, default_rules, all_targets):
00032 '''
00033 Initialises the pulled interface.
00034
00035 @param default_rule_blacklist : used when in flip all mode
00036 @type dictionary of gateway
00037 @param default_rules : static rules to pull on startup
00038 @type gateway_msgs.msg.RemoteRule[]
00039 @param all_targets : static pull all targets to pull to on startup
00040 @type string[]
00041 '''
00042 interactive_interface.InteractiveInterface.__init__(self, default_rule_blacklist, default_rules, all_targets)
00043
00044
00045 self.pulled = self.active
00046 self.pull_all = self.add_all
00047 self.unpull_all = self.remove_all
00048
00049 def update(self, remote_connections, unique_name):
00050 '''
00051 Computes a new pulled interface from the incoming connections list
00052 and returns two dictionaries -
00053 removed and newly added pulls so the watcher thread can take
00054 appropriate action ((un)registrations).
00055
00056 This is run in the watcher thread (warning: take care - other
00057 additions come from ros service calls in different threads!)
00058
00059 @param remote_gateway_hub_index : full gateway-hub database index to parse
00060 @type gateway hash names keyed into a dic with a list of their hubs
00061 '''
00062
00063
00064 pulled = utils.create_empty_connection_type_dictionary()
00065 new_pulls = utils.create_empty_connection_type_dictionary()
00066 removed_pulls = utils.create_empty_connection_type_dictionary()
00067
00068 self._lock.acquire()
00069
00070 for remote_gateway in remote_connections.keys():
00071 connections = remote_connections[remote_gateway]
00072 for connection_type in connections:
00073 for connection in connections[connection_type]:
00074 pulled[connection_type].extend(
00075 self._generate_pulls(
00076 connection.rule.type,
00077 connection.rule.name,
00078 connection.rule.node,
00079 remote_gateway,
00080 unique_name))
00081 for connection_type in utils.connection_types:
00082 new_pulls[connection_type] = utils.difflist(pulled[connection_type], self.pulled[connection_type])
00083 removed_pulls[connection_type] = utils.difflist(self.pulled[connection_type], pulled[connection_type])
00084 self.pulled = copy.deepcopy(pulled)
00085 self._lock.release()
00086 return new_pulls, removed_pulls
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 def _generate_pulls(self, connection_type, name, node, gateway, unique_name):
00111 '''
00112 Checks if a local rule (obtained from master.get_system_state)
00113 is a suitable association with any of the rules or patterns. This can
00114 return multiple matches, since the same local rule
00115 properties can be multiply pulled to different remote gateways.
00116
00117 Used in the update() call above that is run in the watcher thread.
00118
00119 Note, don't need to lock here as the update() function takes care of it.
00120
00121 @param connection_type : rule type
00122 @type str : string constant from gateway_msgs.Rule
00123
00124 @param name : fully qualified topic, service or action name
00125 @type str
00126
00127 @param node : ros node name (coming from master.get_system_state)
00128 @type str
00129
00130 @param gateway : remote gateway hash name.
00131 @type str
00132
00133 @return all the pull rules that match this local rule
00134 @return list of RemoteRule objects updated with node names from self.watchlist
00135 '''
00136 matched_pull_rules = []
00137 for rule in self.watchlist[connection_type]:
00138
00139 gateway_match_result = re.match(rule.gateway, gateway)
00140 matched = False
00141 if gateway_match_result and gateway_match_result.group() == gateway:
00142 matched = True
00143 elif rule.gateway == rocon_gateway_utils.gateway_basename(gateway):
00144 matched = True
00145 if not matched:
00146 continue
00147
00148
00149 rule_name = rule.rule.name
00150 matched = self.is_matched(rule, rule_name, name, node)
00151 if not matched:
00152 rule_name = '/' + unique_name + '/' + rule.rule.name
00153 matched = self.is_matched(rule, rule_name, name, node)
00154
00155 if not matched:
00156 rule_name = '/' + rule.rule.name
00157 matched = self.is_matched(rule, rule_name, name, node)
00158
00159 if matched:
00160 matched_pull = copy.deepcopy(rule)
00161 matched_pull.gateway = gateway
00162 matched_pull.rule.name = name
00163 matched_pull.rule.node = node
00164 matched_pull_rules.append(matched_pull)
00165 return matched_pull_rules
00166
00167
00168
00169
00170
00171 def list_remote_gateway_names(self):
00172 '''
00173 Collects all gateways that it should watch for (i.e. those
00174 currently handled by existing registrations).
00175
00176 @return set of gateway string ids
00177 @rtype set of string
00178 '''
00179 gateways = []
00180 for connection_type in utils.connection_types:
00181 for registration in self.registrations[connection_type]:
00182 if registration.remote_gateway not in gateways:
00183 gateways.append(registration.remote_gateway)
00184 return gateways