1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 from python_qt_binding.QtCore import QObject, Signal
34 import random
35 import socket
36 import threading
37 import time
38 import xmlrpclib
39
40 import rospy
41
42 from master_discovery_fkie.master_info import MasterInfo
43 from node_manager_fkie.common import utf8
44
45
47 '''
48 A thread to retrieve the state about ROS master from remote discovery node and
49 publish it be sending a QT signal.
50 '''
51 update_signal = Signal(MasterInfo)
52 '''
53 @ivar: update_signal is a signal, which is emitted, if a new
54 U{master_discovery_fkie.MasterInfo<http://docs.ros.org/api/master_discovery_fkie/html/modules.html#module-master_discovery_fkie.master_info>} is retrieved.
55 '''
56
57 master_errors_signal = Signal(str, list)
58 '''
59 @ivar: master_errors_signal is a signal (masteruri, list of errors),
60 which is emitted, if we get a list with errors from remote master_discovery.
61 '''
62
63 error_signal = Signal(str, str)
64 '''
65 @ivar: error_signal is a signal (masteruri, error message), which is emitted,
66 if an error while retrieving a master info was occurred.
67 '''
68
69 timediff_signal = Signal(str, float)
70 '''
71 @ivar: timediff_signal is a signal (masteruri, time difference), which is emitted
72 after the difference of time to the remote host is determined.
73 '''
74
75 - def __init__(self, monitoruri, masteruri, delayed_exec=0., parent=None):
76 '''
77 @param masteruri: the URI of the remote ROS master
78 @type masteruri: C{str}
79 @param monitoruri: the URI of the monitor RPC interface of the master_discovery node
80 @type monitoruri: C{str}
81 @param delayed_exec: Delay the execution of the request for given seconds.
82 @type delayed_exec: C{float}
83 '''
84 QObject.__init__(self)
85 threading.Thread.__init__(self)
86 self._monitoruri = monitoruri
87 self._masteruri = masteruri
88 self._delayed_exec = delayed_exec
89 self.setDaemon(True)
90
92 '''
93 '''
94 try:
95 delay = self._delayed_exec + 0.5 + random.random()
96
97 time.sleep(delay)
98
99 socket.setdefaulttimeout(25)
100 remote_monitor = xmlrpclib.ServerProxy(self._monitoruri)
101
102 try:
103 muri, errors = remote_monitor.masterErrors()
104 self.master_errors_signal.emit(muri, errors)
105 except xmlrpclib.Fault as _err:
106 rospy.logwarn("Older master_discovery on %s detected. It does not support master error reports!" % self._masteruri)
107
108 try:
109 myts = time.time()
110 muri, remote_ts = remote_monitor.getCurrentTime()
111 self.timediff_signal.emit(muri, remote_ts - myts - (time.time() - myts) / 2.0)
112 except xmlrpclib.Fault as _errts:
113 rospy.logwarn("Older master_discovery on %s detected. It does not support master error reports!" % self._masteruri)
114
115 remote_info = remote_monitor.masterInfo()
116 master_info = MasterInfo.from_list(remote_info)
117 master_info.check_ts = time.time()
118
119 self.update_signal.emit(master_info)
120 except:
121 import traceback
122
123 formatted_lines = traceback.format_exc(1).splitlines()
124 rospy.logwarn("Cannot update ROS state, connection to %s failed:\n\t%s", utf8(self._monitoruri), formatted_lines[-1])
125
126 self.error_signal.emit(self._masteruri, formatted_lines[-1])
127 finally:
128 if socket is not None:
129 socket.setdefaulttimeout(None)
130