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 self.parent().masterlist_service.refresh(self.parent().getMasteruri(), False) 110 while (not rospy.is_shutdown()) and self._running: 111 msg = None 112 address = None 113 status_text = ''.join(['listen on network: ', str(index), ' (', str(self._networks_count), ')']) 114 self.status_text_signal.emit(status_text) 115 with self.mutex: 116 while True: 117 try: 118 (msg, address) = self.sockets[index].recvfrom(1024) 119 hostname = None 120 force_update = False 121 if not address is None: 122 try: 123 hostname = self._hosts[address[0]] 124 except: 125 hostname = nm.nameres().hostname(str(address[0])) 126 if hostname is None or hostname == str(address[0]): 127 self.status_text_signal.emit(''.join(['resolve: ', str(address[0])])) 128 try: 129 (hostname, aliaslist, ipaddrlist) = socket.gethostbyaddr(str(address[0])) 130 nm.nameres().addInfo(None, hostname, hostname) 131 nm.nameres().addInfo(None, address[0], hostname) 132 except: 133 import traceback 134 print traceback.format_exc(1) 135 pass 136 self._hosts[address[0]] = hostname 137 if not msg is None: 138 try: 139 (version, msg_tuple) = Discoverer.msg2masterState(msg, address) 140 if not self._discovered.has_key(index): 141 self._discovered[index] = dict() 142 force_update = True 143 self._discovered[index][address] = (hostname, time.time()) 144 except Exception, e: 145 import traceback 146 print traceback.format_exc(1) 147 pass 148 if force_update: 149 self._updateDisplay() 150 except socket.timeout: 151 # rospy.logwarn("TIMOUT ignored") 152 break 153 except socket.error: 154 import traceback 155 rospy.logwarn("socket error: %s", traceback.format_exc(1)) 156 break 157 except: 158 break 159 index += 1 160 if index >= len(self.sockets): 161 index = 0 162 self._updateDisplay() 163 self.parent().masterlist_service.refresh(self.parent().getMasteruri(), False)
164
165 - def closeEvent (self, event):
166 self._running = False 167 with self.mutex: 168 for p in range(len(self.sockets)): 169 try: 170 self.sockets[p].close() 171 except: 172 pass 173 QtGui.QDialog.closeEvent(self, event)
174
175 - def _updateDisplay(self):
176 self.display_clear_signal.emit() 177 text = '<div style="font-family:Fixedsys,Courier,monospace; padding:10px;">\n' 178 for index, addr_dict in self._discovered.items(): 179 text = ''.join([text, 'Network <b>', str(index), '</b>: <a href="', str(index),'">join</a><dl>']) 180 for addr, (hostname, ts) in addr_dict.items(): 181 text = ''.join([text, '<dt>', self._getTsStr(ts), ' <b><u>', str(hostname), '</u></b> ', str(addr), '</dt>\n']) 182 text = ''.join([text, '</dl><br>']) 183 text = ''.join([text, '</div>']) 184 self.display_append_signal.emit(text)
185
186 - def _getTsStr(self, timestamp):
187 dt = datetime.fromtimestamp(timestamp) 188 diff = time.time()-timestamp 189 diff_dt = datetime.fromtimestamp(diff) 190 before = '0 sec' 191 if (diff < 60): 192 before = diff_dt.strftime('%S sec') 193 elif (diff < 3600): 194 before = diff_dt.strftime('%M:%S min') 195 elif (diff < 86400): 196 before = diff_dt.strftime('%H:%M:%S std') 197 else: 198 before = diff_dt.strftime('%d Day(s) %H:%M:%S') 199 return ''.join([dt.strftime('%H:%M:%S'), ' (', before, ')'])
200
201 - def on_anchorClicked(self, url):
202 self._updateDisplay() 203 try: 204 self.network_join_request.emit(int(url.toString())) 205 except: 206 import traceback 207 print traceback.format_exc(1)
208