1
2
3
4
5
6
7
8
9
10
11 import copy
12 import re
13 import rocon_utilities
14
15
16 import utils
17 import interactive_interface
18
19
20
21
22
23
25 '''
26 The flipped interface is the set of rules
27 (pubs/subs/services/actions) and rules controlling flips
28 to other gateways.
29 '''
30 - def __init__(self, firewall, default_rule_blacklist, default_rules, all_targets):
31 '''
32 Initialises the flipped interface.
33
34 @param firewall : flag to prevent this gateway from accepting flips
35 @type Bool
36 @param default_rule_blacklist : used when in flip all mode
37 @type dictionary of gateway
38 @param default_rules : static rules to flip on startup
39 @type gateway_msgs.msg.RemoteRule[]
40 @param all_targets : static flip all targets to flip to on startup
41 @type string[]
42
43 '''
44 interactive_interface.InteractiveInterface.__init__(self, default_rule_blacklist, default_rules, all_targets)
45
46 self.firewall = firewall
47
48
49 self.flipped = self.active
50 self.flip_all = self.add_all
51 self.unflip_all = self.remove_all
52
53
54
55
56
57 - def update(self, connections, remote_gateway_hub_index, unique_name):
58 '''
59 Computes a new flipped interface and returns two dictionaries -
60 removed and newly added flips so the watcher thread can take
61 appropriate action (inform the remote gateways).
62
63 This is run in the watcher thread (warning: take care - other
64 additions come from ros service calls in different threads!)
65
66 @param connections : list of all the system state connections from the local master
67 @type connection type keyed dictionary of utils.Connection lists.
68
69 @param remote_gateway_hub_index : full gateway-hub database index to parse
70 @type gateway hash names keyed into a dic with a list of their hubs
71
72 @param unique_name : this gateway's unique hash name
73 @type string
74
75 @return new_flips, removed_flips (i.e. those that are no longer on the local master)
76 @rtype pair of connection type keyed dictionary of gateway_msgs.msg.Rule lists.
77 '''
78
79
80 flipped = utils.create_empty_connection_type_dictionary()
81 new_flips = utils.create_empty_connection_type_dictionary()
82 removed_flips = utils.create_empty_connection_type_dictionary()
83 remote_gateways = remote_gateway_hub_index.keys()
84 diff = lambda l1, l2: [x for x in l1 if x not in l2]
85 self._lock.acquire()
86
87 for connection_type in utils.connection_types:
88
89 self.flipped[connection_type] = [flip for flip in self.flipped[connection_type] if flip.gateway in remote_gateways]
90
91 for connection_type in connections:
92 for connection in connections[connection_type]:
93 flipped[connection_type].extend(self._generate_flips(connection.rule.type, connection.rule.name, connection.rule.node, remote_gateways, unique_name))
94 new_flips[connection_type] = diff(flipped[connection_type], self.flipped[connection_type])
95 removed_flips[connection_type] = diff(self.flipped[connection_type], flipped[connection_type])
96 self.flipped = copy.deepcopy(flipped)
97 self._lock.release()
98 return new_flips, removed_flips
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122 - def _generate_flips(self, connection_type, name, node, remote_gateways, unique_name):
123 '''
124 Checks if a local rule (obtained from master.get_system_state)
125 is a suitable association with any of the rules or patterns. This can
126 return multiple matches, since the same local rule
127 properties can be multiply flipped to different remote gateways.
128
129 Used in the update() call above that is run in the watcher thread.
130 Note, don't need to lock here as the update() function takes care of it.
131
132 @param connection_type : rule type
133 @type str : string constant from gateway_msgs.msg.Rule
134
135 @param name : fully qualified topic, service or action name
136 @type str
137
138 @param node : ros node name (coming from master.get_system_state)
139 @type str
140
141 @param gateways : gateways that are available (registered on the hub)
142 @type string
143
144 @return all the flip rules that match this local rule
145 @return list of RemoteRule objects updated with node names from self.watchlist
146 '''
147 matched_flip_rules = []
148 for flip_rule in self.watchlist[connection_type]:
149
150 matched_gateways = []
151 for gateway in remote_gateways:
152
153 gateway_match_result = re.match(flip_rule.gateway, gateway)
154 if gateway_match_result and gateway_match_result.group() == gateway:
155 matched_gateways.append(gateway)
156 elif flip_rule.gateway == rocon_utilities.gateway_basename(gateway):
157 matched_gateways.append(gateway)
158 if not matched_gateways:
159 continue
160
161
162 rule_name = flip_rule.rule.name
163 matched = self.is_matched(flip_rule, rule_name, name, node)
164
165 if not utils.is_all_pattern(flip_rule.rule.name):
166 if not matched:
167 rule_name = '/' + unique_name + '/' + flip_rule.rule.name
168 matched = self.is_matched(flip_rule, rule_name, name, node)
169
170 if not matched:
171 rule_name = '/' + flip_rule.rule.name
172 matched = self.is_matched(flip_rule, rule_name, name, node)
173
174 if matched:
175 for gateway in matched_gateways:
176 matched_flip = copy.deepcopy(flip_rule)
177 matched_flip.gateway = gateway
178 matched_flip.rule.name = name
179 matched_flip.rule.node = node
180 matched_flip_rules.append(matched_flip)
181
182 return matched_flip_rules
183
184
185
186
187
189 '''
190 Gets the flipped connections list for GatewayInfo consumption.
191
192 @return the list of flip rules that are activated and have been flipped.
193 @rtype RemoteRule[]
194 '''
195 flipped_connections = []
196 for connection_type in utils.connection_types:
197 flipped_connections.extend(copy.deepcopy(self.flipped[connection_type]))
198 return flipped_connections
199
200
201 if __name__ == "__main__":
202
203 gateways = ['dude', 'dudette']
204 dudes = ['fred', 'dude']
205 dudes[:] = [x for x in dudes if x in gateways]
206 print dudes
207