Package node_manager_fkie :: Module network_discovery_dialog
[frames] | no frames]

Source Code for Module node_manager_fkie.network_discovery_dialog

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2012, Fraunhofer FKIE/US, Alexander Tiderko 
  4  # All rights reserved. 
  5  # 
  6  # Redistribution and use in source and binary forms, with or without 
  7  # modification, are permitted provided that the following conditions 
  8  # are met: 
  9  # 
 10  #  * Redistributions of source code must retain the above copyright 
 11  #    notice, this list of conditions and the following disclaimer. 
 12  #  * Redistributions in binary form must reproduce the above 
 13  #    copyright notice, this list of conditions and the following 
 14  #    disclaimer in the documentation and/or other materials provided 
 15  #    with the distribution. 
 16  #  * Neither the name of Fraunhofer nor the names of its 
 17  #    contributors may be used to endorse or promote products derived 
 18  #    from this software without specific prior written permission. 
 19  # 
 20  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 21  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 22  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 23  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 24  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 25  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 26  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 27  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 28  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 29  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 30  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 31  # POSSIBILITY OF SUCH DAMAGE. 
 32   
 33   
 34  from python_qt_binding import QtCore, QtGui 
 35   
 36  import time 
 37  from datetime import datetime 
 38   
 39  import roslib 
 40  import roslib.message 
 41  import rospy 
 42  import threading 
 43  import socket 
 44   
 45  from master_discovery_fkie.udp import McastSocket 
 46  from master_discovery_fkie.master_discovery import Discoverer 
 47  import node_manager_fkie as nm 
 48   
49 -class NetworkDiscoveryDialog(QtGui.QDialog, threading.Thread):
50 51 TIMEOUT = 0.1 52 53 display_clear_signal = QtCore.Signal() 54 display_append_signal = QtCore.Signal(str) 55 status_text_signal = QtCore.Signal(str) 56 network_join_request = QtCore.Signal(int) 57 58
59 - def __init__(self, default_mcast_group, default_port, networks_count, parent=None):
60 ''' 61 Creates an input dialog. 62 @param default_port: the default discovery port 63 @type default_port: C{int} 64 @param networks_count: the count of discovering ports 65 @type networks_count: C{int} 66 ''' 67 QtGui.QDialog.__init__(self, parent=parent) 68 threading.Thread.__init__(self) 69 self.setObjectName('NetworkDiscoveryDialog') 70 self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True) 71 self.setWindowFlags(QtCore.Qt.Window) 72 self.setWindowTitle('Network Discovery') 73 self.resize(728,512) 74 self.verticalLayout = QtGui.QVBoxLayout(self) 75 self.verticalLayout.setObjectName("verticalLayout") 76 self.verticalLayout.setContentsMargins(1, 1, 1, 1) 77 78 self.display = QtGui.QTextBrowser(self) 79 self.display.setReadOnly(True) 80 self.verticalLayout.addWidget(self.display); 81 self.display_clear_signal.connect(self.display.clear) 82 self.display_append_signal.connect(self.display.append) 83 self.display.anchorClicked.connect(self.on_anchorClicked) 84 85 self.status_label = QtGui.QLabel('0 messages', self) 86 self.verticalLayout.addWidget(self.status_label) 87 self.status_text_signal.connect(self.status_label.setText) 88 89 self._networks_count = networks_count 90 self.sockets = [] 91 for p in range(networks_count): 92 msock = McastSocket(default_port+p, default_mcast_group) 93 self.sockets.append(msock) 94 msock.settimeout(self.TIMEOUT) 95 self._running = True 96 97 self._discovered = dict() 98 99 self._hosts = dict() # resolution for hostname and address 100 101 self.mutex = threading.RLock() 102 # thread = threading.Thread(target=self._listen) 103 self.setDaemon(True) 104 self.start()
105 106
107 - def run(self):
108 index = 0 109 while (not rospy.is_shutdown()) and self._running: 110 msg = None 111 address = None 112 status_text = ''.join(['listen on network: ', str(index), ' (', str(self._networks_count), ')']) 113 self.status_text_signal.emit(status_text) 114 with self.mutex: 115 while True: 116 try: 117 (msg, address) = self.sockets[index].recvfrom(1024) 118 hostname = None 119 force_update = False 120 if not address is None: 121 try: 122 hostname = self._hosts[address[0]] 123 except: 124 hostname = nm.nameres().hostname(str(address[0])) 125 if hostname is None or hostname == str(address[0]): 126 self.status_text_signal.emit(''.join(['resolve: ', str(address[0])])) 127 try: 128 (hostname, aliaslist, ipaddrlist) = socket.gethostbyaddr(str(address[0])) 129 nm.nameres().addInfo(None, hostname, hostname) 130 nm.nameres().addInfo(None, address[0], hostname) 131 except: 132 import traceback 133 print traceback.format_exc() 134 pass 135 self._hosts[address[0]] = hostname 136 if not msg is None: 137 try: 138 (version, msg_tuple) = Discoverer.msg2masterState(msg, address) 139 if not self._discovered.has_key(index): 140 self._discovered[index] = dict() 141 force_update = True 142 self._discovered[index][address] = (hostname, time.time()) 143 except Exception, e: 144 import traceback 145 print traceback.format_exc() 146 pass 147 if force_update: 148 self._updateDisplay() 149 except socket.timeout: 150 # rospy.logwarn("TIMOUT ignored") 151 break 152 except socket.error: 153 import traceback 154 rospy.logwarn("socket error: %s", traceback.format_exc()) 155 break 156 except: 157 break 158 index += 1 159 if index >= len(self.sockets): 160 index = 0 161 self._updateDisplay()
162
163 - def closeEvent (self, event):
164 self._running = False 165 with self.mutex: 166 for p in range(len(self.sockets)): 167 try: 168 self.sockets[p].close() 169 except: 170 pass 171 QtGui.QDialog.closeEvent(self, event)
172
173 - def _updateDisplay(self):
174 self.display_clear_signal.emit() 175 text = '<div style="font-family:Fixedsys,Courier,monospace; padding:10px;">\n' 176 for index, addr_dict in self._discovered.items(): 177 text = ''.join([text, 'Network <b>', str(index), '</b>: <a href="', str(index),'">join</a><dl>']) 178 for addr, (hostname, ts) in addr_dict.items(): 179 text = ''.join([text, '<dt>', self._getTsStr(ts), ' <b><u>', str(hostname), '</u></b> ', str(addr), '</dt>\n']) 180 text = ''.join([text, '</dl><br>']) 181 text = ''.join([text, '</div>']) 182 self.display_append_signal.emit(text)
183
184 - def _getTsStr(self, timestamp):
185 dt = datetime.fromtimestamp(timestamp) 186 diff = time.time()-timestamp 187 diff_dt = datetime.fromtimestamp(diff) 188 before = '0 sec' 189 if (diff < 60): 190 before = diff_dt.strftime('%S sec') 191 elif (diff < 3600): 192 before = diff_dt.strftime('%M:%S min') 193 elif (diff < 86400): 194 before = diff_dt.strftime('%H:%M:%S std') 195 else: 196 before = diff_dt.strftime('%d Day(s) %H:%M:%S') 197 return ''.join([dt.strftime('%H:%M:%S'), ' (', before, ')'])
198
199 - def on_anchorClicked(self, url):
200 self._updateDisplay() 201 try: 202 self.network_join_request.emit(int(url.toString())) 203 except: 204 import traceback 205 print traceback.format_exc()
206