1
2
3
4
5
6
7
8
9
10 import rospy
11 import rocon_app_manager_msgs.msg as rapp_manager_msgs
12 import rocon_app_manager_msgs.srv as rapp_manager_srvs
13 import concert_msgs.msg as concert_msgs
14 import gateway_msgs.msg as gateway_msgs
15 import gateway_msgs.srv as gateway_srvs
16
17
18
19
20
21
23 """Exception class for concert client related errors"""
24 pass
25
26
27
28
29
30
32
33 - def __init__(self, client_name, gateway_name, is_local_client=False):
34 '''
35 Initialise, finally ending with a call on the service to the client's
36 platform info service.
37
38 @param client_name : a string (+ index) human consumable form of the name
39 @type str
40 @param gateway_name : the name with 16 byte hash attached
41 @type str
42 @param is_local_client : differentiates an interactive local client from a gateway client
43 @type bool
44
45 @raise ConcertClientException : when platform info service is unavailable
46 '''
47
48 self.data = concert_msgs.ConcertClient()
49 self.gateway_name = gateway_name
50 self.name = client_name
51
52 self.platform_info = None
53 self.service_execution = {}
54 self._is_local_client = is_local_client
55 if not self._is_local_client:
56 self._pull_concert_client()
57
58 self._init()
59 self._setup_service_proxies()
60
61 try:
62 self._update()
63 except ConcertClientException:
64 raise
65
67 '''
68 Pulls platform information from the advertised platform_info on another
69 ros system. It is just a one-shot only used at construction time.
70
71 It pulls platform_info and list_apps information.
72
73 It also pulls the required handles in for further manipulation ('status' and 'invite')
74 '''
75 rospy.loginfo("Conductor: retrieving client information [%s]" % self.name)
76 pull_service = rospy.ServiceProxy('~pull', gateway_srvs.Remote)
77 req = gateway_srvs.RemoteRequest()
78 req.cancel = False
79 req.remotes = []
80 for service_name in ['platform_info', 'list_apps', 'status', 'invite']:
81 rule = gateway_msgs.Rule()
82 rule.name = str('/' + self.gateway_name + '/' + service_name)
83 rule.node = ''
84 rule.type = gateway_msgs.ConnectionType.SERVICE
85 req.remotes.append(gateway_msgs.RemoteRule(self.gateway_name.lstrip('/'), rule))
86 resp = pull_service(req)
87 if resp.result != 0:
88 rospy.logwarn("Conductor: failed to pull the platform info service from the client.")
89 return None
90
92
93 platform_info_service = rospy.ServiceProxy(str('/' + self.gateway_name + '/' + 'platform_info'), rapp_manager_srvs.GetPlatformInfo)
94 list_app_service = rospy.ServiceProxy(str('/' + self.gateway_name + '/' + 'list_apps'), rapp_manager_srvs.GetAppList)
95
96 self._status_service = rospy.ServiceProxy('/' + str(self.gateway_name + '/' + 'status'), rapp_manager_srvs.Status)
97 self._invite_service = rospy.ServiceProxy('/' + str(self.gateway_name + '/' + 'invite'), rapp_manager_srvs.Invite)
98 try:
99 platform_info_service.wait_for_service()
100 list_app_service.wait_for_service()
101 self._status_service.wait_for_service()
102 self._invite_service.wait_for_service()
103 except rospy.ServiceException, e:
104 raise e
105 platform_info = platform_info_service().platform_info
106 self.data.name = platform_info.name
107 self.data.platform = platform_info.platform
108 self.data.system = platform_info.system
109 self.data.robot = platform_info.robot
110
111 try:
112 list_app_service.wait_for_service()
113 except rospy.ServiceException, e:
114 raise e
115 self.data.apps = list_app_service().apps
116
131
133 '''
134 Adds the current client status to the platform_info, list_apps information already
135 retrieved from the client and puts them in a convenient msg format,
136 ready for exposing outside the conductor (where? I can't remember).
137
138 @raise rospy.service.ServiceException : when assumed service link is unavailable
139 '''
140 try:
141 status = self._status_service(rapp_manager_srvs.StatusRequest())
142 except rospy.service.ServiceException:
143 raise ConcertClientException("client platform information services unavailable (disconnected?)")
144 self.data.name = self.name
145 self.data.gateway_name = self.gateway_name
146
147 self.data.last_connection_timestamp = rospy.Time.now()
148 if status.remote_controller == rapp_manager_msgs.Constants.NO_REMOTE_CONNECTION:
149 self.data.client_status = concert_msgs.Constants.CONCERT_CLIENT_STATUS_AVAILABLE
150
151
152
153 else:
154 self.data.client_status = concert_msgs.Constants.CONCERT_CLIENT_STATUS_CONNECTED
155
156
157 - def invite(self, concert_gateway_name, client_local_name, ok_flag):
158 '''
159 Bit messy with ok_flag here as we are mid-transition to using 'cancel' flag in the
160 invite services.
161
162 @param concert_gateway_name : have to let the client know the concert gateway name
163 so they can flip us topics...
164 @type str
165 '''
166 req = rapp_manager_srvs.InviteRequest(concert_gateway_name, client_local_name, not ok_flag)
167 resp = self._invite_service(req)
168
169 if resp.result == True:
170 self._setup_service_proxies()
171 else:
172 raise Exception(str("Invitation Failed : " + self.name))
173
175 '''
176 @param app_name : string unique identifier for the app
177 @type string
178 @param remappings : list of (from,to) pairs
179 @type list of tuples
180 '''
181 self._start_app_service.wait_for_service()
182 req = rapp_manager_srvs.StartAppRequest()
183 req.name = app_name
184 req.remappings = []
185 for remapping in remappings:
186 req.remappings.append(rapp_manager_msgs.Remapping(remapping[0], remapping[1]))
187 unused_resp = self._start_app_service(req)
188
190 self._start_app_service = rospy.ServiceProxy(str(self.name + '/start_app'), rapp_manager_srvs.StartApp)
191 self._stop_app_service = rospy.ServiceProxy(str(self.name + '/stop_app'), rapp_manager_srvs.StopApp)
192