16 import rocon_gateway_utils
17 from gateway_msgs.msg
import RemoteRuleWithStatus
20 from .
import interactive_interface
30 The flipped interface is the set of rules 31 (pubs/subs/services/actions) and rules controlling flips 35 def __init__(self, firewall, default_rule_blacklist, default_rules, all_targets):
37 Initialises the flipped interface. 39 @param firewall : flag to prevent this gateway from accepting flips 41 @param default_rule_blacklist : used when in flip all mode 42 @type dictionary of gateway 43 @param default_rules : static rules to flip on startup 44 @type gateway_msgs.msg.RemoteRule[] 45 @param all_targets : static flip all targets to flip to on startup 49 interactive_interface.InteractiveInterface.__init__(self, default_rule_blacklist, default_rules, all_targets)
56 self.
flip_status = utils.create_empty_connection_type_dictionary()
64 def update(self, connections, remote_gateway_hub_index, unique_name, master):
66 Computes a new flipped interface and returns two dictionaries - 67 removed and newly added flips so the watcher thread can take 68 appropriate action (inform the remote gateways). 70 This is run in the watcher thread (warning: take care - other 71 additions come from ros service calls in different threads!) 73 @param connections : list of all the system state connections from the local master 74 @type connection type keyed dictionary of utils.Connection sets. 76 @param remote_gateway_hub_index : full gateway-hub database index to parse 77 @type gateway hash names keyed into a dic with a list of their hubs 79 @param unique_name : this gateway's unique hash name 82 @param master : local master 83 @type rocon_gateway.LocalMaster 85 @return new_flips, removed_flips (i.e. those that are no longer on the local master) 86 @rtype pair of connection type keyed dictionary of gateway_msgs.msg.Rule lists. 89 remote_gateways = remote_gateway_hub_index.keys()
97 new_flips, removed_flips, flipped = self.
_prepare_flips(connections, remote_gateways, unique_name, master)
104 return new_flips, removed_flips
126 for connection_type
in flipped.keys():
127 updated_flipped[connection_type] = [copy.deepcopy(r)
for r
in flipped[connection_type]
if not r
in filtered_flips[connection_type]]
128 return updated_flipped
132 Gateway should not flip out the flipped-in interface. 134 filtered_flips = utils.create_empty_connection_type_dictionary()
135 for connection_type
in utils.connection_types:
136 for rule
in flipped_in_registrations[connection_type]:
139 filtered_flips[connection_type].append(r)
141 for connection_type
in new_flips.keys():
142 new_flips[connection_type] = [r
for r
in new_flips[connection_type]
if not r
in filtered_flips[connection_type]]
144 rospy.logdebug(
"Gateway : filtered flip list to prevent cyclic flipping - %s"%str(filtered_flips))
146 return new_flips, filtered_flips
149 for r
in new_flip_remote_rules:
150 node = r.rule.node.split(
",")[0]
151 if rule.local_node == node
and rule.remote_gateway == r.gateway
and rule.connection.rule.name == r.rule.name:
157 Update the status of a flip from the hub. This should be called right 158 after update once self.flipped is established 160 @return True if status was indeed changed, False otherwise 163 state_changed =
False 166 index = self.
flipped[flip.rule.type].index(flip)
167 state_changed = (self.
flip_status[flip.rule.type][index] != status)
177 Removes a flip, so that it can be resent as necessary 181 self.
flipped[flip.rule.type].remove(flip)
190 def _generate_flips(self, connection_type, name, node, remote_gateways, unique_name, master):
192 Checks if a local rule (obtained from master.get_system_state) 193 is a suitable association with any of the rules or patterns. This can 194 return multiple matches, since the same local rule 195 properties can be multiply flipped to different remote gateways. 197 Used in the update() call above that is run in the watcher thread. 198 Note, don't need to lock here as the update() function takes care of it. 200 @param connection_type : rule type 201 @type str : string constant from gateway_msgs.msg.Rule 203 @param name : fully qualified topic, service or action name 206 @param node : ros node name (coming from master.get_system_state) 209 @param gateways : gateways that are available (registered on the hub) 212 @param master : local master 213 @type rocon_gateway.LocalMaster 215 @return all the flip rules that match this local rule 216 @return list of RemoteRule objects updated with node names from self.watchlist 218 matched_flip_rules = []
219 for flip_rule
in self.
watchlist[connection_type]:
222 if not matched_gateways:
226 rule_name = flip_rule.rule.name
227 matched = self.
is_matched(flip_rule, rule_name, name, node)
229 if not utils.is_all_pattern(flip_rule.rule.name):
231 rule_name =
'/' + unique_name +
'/' + flip_rule.rule.name
232 matched = self.
is_matched(flip_rule, rule_name, name, node)
236 rule_name =
'/' + flip_rule.rule.name
237 matched = self.
is_matched(flip_rule, rule_name, name, node)
240 for gateway
in matched_gateways:
242 matched_flip = copy.deepcopy(flip_rule)
243 matched_flip.gateway = gateway
244 matched_flip.rule.name = name
245 matched_flip.rule.node =
"%s,%s"%(node, master.lookupNode(node))
246 matched_flip_rules.append(matched_flip)
247 except rosgraph.masterapi.MasterError
as e:
250 except socket.error
as e:
251 rospy.logwarn(
"Gateway : socket error while generate flips [%s]"%str(e))
252 return matched_flip_rules
256 for connection_type
in utils.connection_types:
258 flipped[connection_type] = [flip
for flip
in self.
flipped[connection_type]
if flip.gateway
in remote_gateways]
263 flipped = utils.create_empty_connection_type_dictionary()
264 new_flips = utils.create_empty_connection_type_dictionary()
265 removed_flips = utils.create_empty_connection_type_dictionary()
267 for connection_type
in connections:
268 for connection
in connections[connection_type]:
269 matched_flip_rules = self.
_generate_flips(connection.rule.type, connection.rule.name, connection.rule.node, remote_gateways, unique_name, master)
270 flipped[connection_type].extend(matched_flip_rules)
272 new_flips[connection_type] = utils.difflist(flipped[connection_type], self.
flipped[connection_type])
273 removed_flips[connection_type] = utils.difflist(self.
flipped[connection_type], flipped[connection_type])
274 return new_flips, removed_flips, flipped
277 flip_status = utils.create_empty_connection_type_dictionary()
280 for connection_type
in utils.connection_types:
281 flip_status[connection_type] = [RemoteRuleWithStatus.UNKNOWN] * len(flipped[connection_type])
283 for connection_type
in utils.connection_types:
286 for new_index, flip
in enumerate(flipped[connection_type]):
288 index = self.
flipped[connection_type].index(flip)
289 flip_status[connection_type][new_index] = self.
flip_status[connection_type][index]
299 matched_gateways = []
300 for gateway
in remote_gateways:
302 gateway_match_result = re.match(flip_rule.gateway, gateway)
303 if gateway_match_result
and gateway_match_result.group() == gateway:
304 matched_gateways.append(gateway)
305 elif flip_rule.gateway == rocon_gateway_utils.gateway_basename(gateway):
306 matched_gateways.append(gateway)
307 return matched_gateways
315 Gets the flipped connections list for GatewayInfo consumption. 317 @return the list of flip rules that are activated and have been flipped. 320 flipped_connections = []
321 for connection_type
in utils.connection_types:
322 for i, connection
in enumerate(self.
flipped[connection_type]):
323 flipped_connections.append(RemoteRuleWithStatus(connection, self.
flip_status[connection_type][i]))
324 return flipped_connections
327 if __name__ ==
"__main__":
329 gateways = [
'dude',
'dudette']
330 dudes = [
'fred',
'dude']
331 dudes[:] = [x
for x
in dudes
if x
in gateways]
def _filter_flipped_in_interfaces(self, new_flips, flipped_in_registrations)
def _prepare_flips(self, connections, remote_gateways, unique_name, master)
def is_matched(self, rule, rule_name, name, node)
Accessors for Gateway Info.
def get_flipped_connections(self)
Accessors for Gateway Info.
def _update_flipped(self, flipped, filtered_flips)
def update_flip_status(self, flip, status)
def _get_matched_gateways(self, flip_rule, remote_gateways)
def _generate_flips(self, connection_type, name, node, remote_gateways, unique_name, master)
Utility Methods.
def add_all(self, gateway, blacklist)
def remove_all(self, gateway)
def _is_registration_in_remote_rule(self, rule, new_flip_remote_rules)
def _prune_unavailable_gateway_flips(self, flipped, remote_gateways)
def update(self, connections, remote_gateway_hub_index, unique_name, master)
Monitoring.
def _prepare_flip_status(self, flipped)
def remove_flip(self, flip)
def __init__(self, firewall, default_rule_blacklist, default_rules, all_targets)