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 import Queue
34 from datetime import datetime
35 from python_qt_binding.QtCore import Qt, Signal
36 try:
37 from python_qt_binding.QtGui import QDialog, QLabel, QTextBrowser, QVBoxLayout
38 except:
39 from python_qt_binding.QtWidgets import QDialog, QLabel, QTextBrowser, QVBoxLayout
40 import threading
41 import time
42 import traceback
43
44 import rospy
45
46 from master_discovery_fkie.master_discovery import Discoverer
47 from master_discovery_fkie.udp import DiscoverSocket, QueueReceiveItem
48 import node_manager_fkie as nm
49
50
52
53 TIMEOUT = 0.1
54
55 display_clear_signal = Signal()
56 display_append_signal = Signal(str)
57 status_text_signal = Signal(str)
58 network_join_request = Signal(int)
59
60 - def __init__(self, default_mcast_group, default_port, networks_count, parent=None):
61 '''
62 Creates an input dialog.
63 @param default_port: the default discovery port
64 @type default_port: C{int}
65 @param networks_count: the count of discovering ports
66 @type networks_count: C{int}
67 '''
68 QDialog.__init__(self, parent=parent)
69 threading.Thread.__init__(self)
70 self.default_port = default_port
71 self.setObjectName('NetworkDiscoveryDialog')
72 self.setAttribute(Qt.WA_DeleteOnClose, True)
73 self.setWindowFlags(Qt.Window)
74 self.setWindowTitle('Network Discovery')
75 self.resize(728, 512)
76 self.verticalLayout = QVBoxLayout(self)
77 self.verticalLayout.setObjectName("verticalLayout")
78 self.verticalLayout.setContentsMargins(1, 1, 1, 1)
79
80 self.display = QTextBrowser(self)
81 self.display.setReadOnly(True)
82 self.verticalLayout.addWidget(self.display)
83 self.display_clear_signal.connect(self.display.clear)
84 self.display_append_signal.connect(self.display.append)
85 self.display.anchorClicked.connect(self.on_anchorClicked)
86
87 self.status_label = QLabel('0 messages', self)
88 self.verticalLayout.addWidget(self.status_label)
89 self.status_text_signal.connect(self.status_label.setText)
90 self._msg_counts = dict()
91
92 self._networks_count = networks_count
93 self._running = True
94 self._received_msgs = 0
95 self._discovered = dict()
96 self._hosts = dict()
97 self.mutex = threading.RLock()
98 self.sockets = []
99 with self.mutex:
100 for p in range(networks_count):
101 msock = DiscoverSocket(default_port + p, default_mcast_group)
102 self.sockets.append(msock)
103 msock.settimeout(self.TIMEOUT)
104 self.setDaemon(True)
105 self.start()
106
108 force_update = False
109 with self.mutex:
110 try:
111 hostname = self._hosts[address[0]]
112 except:
113 self.status_text_signal.emit("resolve %s" % address[0])
114 hostname = nm.nameres().hostname(str(address[0]), resolve=True)
115 self._hosts[address[0]] = hostname
116 try:
117 (_version, _msg_tuple) = Discoverer.msg2masterState(msg, address)
118 index = address[1] - self.default_port
119 if index not in self._discovered:
120 self._discovered[index] = dict()
121 self._discovered[index][address] = (hostname, time.time())
122 if hostname not in self._msg_counts:
123 self._msg_counts[hostname] = 0
124 self._msg_counts[hostname] += 1
125 self._received_msgs += 1
126 force_update = True
127 except:
128 print traceback.format_exc(1)
129 if force_update:
130 self._updateDisplay()
131
133 self.parent().masterlist_service.refresh(self.parent().getMasteruri(), False)
134 while (not rospy.is_shutdown()) and self._running:
135 with self.mutex:
136 for msock in self.sockets:
137 received = True
138 while received:
139 try:
140 recv_item = msock.receive_queue.get(False)
141 self._received_msgs += 1
142 self.on_heartbeat_received(recv_item.msg, recv_item.sender_addr, (recv_item.via == QueueReceiveItem.MULTICAST))
143 except Queue.Empty:
144 received = False
145 status_text = 'received messages: %d' % (self._received_msgs)
146 self.status_text_signal.emit(status_text)
147
148 time.sleep(3)
149
153
155 self._running = False
156 with self.mutex:
157 for p in range(len(self.sockets)):
158 try:
159 self.sockets[p].close()
160 except:
161 pass
162
164 self.display_clear_signal.emit()
165 text = '<div style="font-family:Fixedsys,Courier,monospace; padding:10px;">\n'
166 for index, addr_dict in self._discovered.items():
167 text = ''.join([text, 'Network <b>', str(index), '</b>: <a href="', str(index), '">join</a><dl>'])
168 for addr, (hostname, ts) in addr_dict.items():
169 text = ''.join([text, '<dt>', self._getTsStr(ts), ' <b><u>', str(hostname), '</u></b> ', str(addr), ', received messages: ', str(self._msg_counts[hostname]), '</dt>\n'])
170 text = ''.join([text, '</dl><br>'])
171 text = ''.join([text, '</div>'])
172 self.display_append_signal.emit(text)
173
175 dt = datetime.fromtimestamp(timestamp)
176 diff = time.time() - timestamp
177 diff_dt = datetime.fromtimestamp(diff)
178 before = '0 sec'
179 if (diff < 60):
180 before = diff_dt.strftime('%S sec')
181 elif (diff < 3600):
182 before = diff_dt.strftime('%M:%S min')
183 elif (diff < 86400):
184 before = diff_dt.strftime('%H:%M:%S std')
185 else:
186 before = diff_dt.strftime('%d Day(s) %H:%M:%S')
187 return ''.join([dt.strftime('%H:%M:%S'), ' (', before, ')'])
188
190 self._updateDisplay()
191 try:
192 self.network_join_request.emit(int(url.toString()))
193 except:
194 print traceback.format_exc(1)
195