1
2
3
4
5
6
7
8
9
10
11 import copy
12 import re
13 import rocon_utilities
14
15 import utils
16 import interactive_interface
17
18
19
20
21
22
24 '''
25 The pulled interface is the set of rules
26 (pubs/subs/services/actions) and rules controlling pulls from
27 other gateways.
28 '''
29 - def __init__(self, default_rule_blacklist, default_rules, all_targets):
30 '''
31 Initialises the pulled interface.
32
33 @param default_rule_blacklist : used when in flip all mode
34 @type dictionary of gateway
35 @param default_rules : static rules to pull on startup
36 @type gateway_msgs.msg.RemoteRule[]
37 @param all_targets : static pull all targets to pull to on startup
38 @type string[]
39 '''
40 interactive_interface.InteractiveInterface.__init__(self, default_rule_blacklist, default_rules, all_targets)
41
42
43 self.pulled = self.active
44 self.pull_all = self.add_all
45 self.unpull_all = self.remove_all
46
47 - def update(self, remote_connections, unique_name):
48 '''
49 Computes a new pulled interface from the incoming connections list
50 and returns two dictionaries -
51 removed and newly added pulls so the watcher thread can take
52 appropriate action ((un)registrations).
53
54 This is run in the watcher thread (warning: take care - other
55 additions come from ros service calls in different threads!)
56
57 @param remote_gateway_hub_index : full gateway-hub database index to parse
58 @type gateway hash names keyed into a dic with a list of their hubs
59 '''
60
61
62 pulled = utils.create_empty_connection_type_dictionary()
63 new_pulls = utils.create_empty_connection_type_dictionary()
64 removed_pulls = utils.create_empty_connection_type_dictionary()
65 diff = lambda l1,l2: [x for x in l1 if x not in l2]
66 self._lock.acquire()
67
68 for remote_gateway in remote_connections.keys():
69 connections = remote_connections[remote_gateway]
70 for connection_type in connections:
71 for connection in connections[connection_type]:
72 pulled[connection_type].extend(self._generate_pulls(connection.rule.type, connection.rule.name, connection.rule.node, remote_gateway, unique_name))
73 for connection_type in utils.connection_types:
74 new_pulls[connection_type] = diff(pulled[connection_type], self.pulled[connection_type])
75 removed_pulls[connection_type] = diff(self.pulled[connection_type], pulled[connection_type])
76 self.pulled = copy.deepcopy(pulled)
77 self._lock.release()
78 return new_pulls, removed_pulls
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 - def _generate_pulls(self, connection_type, name, node, gateway, unique_name):
103 '''
104 Checks if a local rule (obtained from master.get_system_state)
105 is a suitable association with any of the rules or patterns. This can
106 return multiple matches, since the same local rule
107 properties can be multiply pulled to different remote gateways.
108
109 Used in the update() call above that is run in the watcher thread.
110
111 Note, don't need to lock here as the update() function takes care of it.
112
113 @param connection_type : rule type
114 @type str : string constant from gateway_msgs.Rule
115
116 @param name : fully qualified topic, service or action name
117 @type str
118
119 @param node : ros node name (coming from master.get_system_state)
120 @type str
121
122 @param gateway : remote gateway hash name.
123 @type str
124
125 @return all the pull rules that match this local rule
126 @return list of RemoteRule objects updated with node names from self.watchlist
127 '''
128 matched_pull_rules = []
129 for rule in self.watchlist[connection_type]:
130
131 gateway_match_result = re.match(rule.gateway, gateway)
132 matched = False
133 if gateway_match_result and gateway_match_result.group() == gateway:
134 matched = True
135 elif rule.gateway == rocon_utilities.gateway_basename(gateway):
136 matched = True
137 if not matched:
138 continue
139
140
141 rule_name = rule.rule.name
142 matched = self.is_matched(rule, rule_name, name, node)
143 if not matched:
144 rule_name = '/' + unique_name + '/' + rule.rule.name
145 matched = self.is_matched(rule, rule_name, name, node)
146
147 if not matched:
148 rule_name = '/' + rule.rule.name
149 matched = self.is_matched(rule, rule_name, name, node)
150
151 if matched:
152 matched_pull = copy.deepcopy(rule)
153 matched_pull.gateway = gateway
154 matched_pull.rule.name = name
155 matched_pull.rule.node = node
156 matched_pull_rules.append(matched_pull)
157 return matched_pull_rules
158
159
160
161
162
164 '''
165 Collects all gateways that it should watch for (i.e. those
166 currently handled by existing registrations).
167
168 @return set of gateway string ids
169 @rtype set of string
170 '''
171 gateways = []
172 for connection_type in utils.connection_types:
173 for registration in self.registrations[connection_type]:
174 if registration.remote_gateway not in gateways:
175 gateways.append(registration.remote_gateway)
176 return gateways
177