def on_actionNetwork_structure_activated(self): self.dlgNetwork = DialogNetwork(self.nodes) self.dlgNetwork.show()
class SnifferWindow(QtGui.QMainWindow, ui_snifferMainWindow.Ui_SnifferMainWindow): """ Main window class. """ state = NONE # let's say it's finite state machine filename = None def __init__(self, parent=None): super(SnifferWindow, self).__init__(parent) # GUI things... self.setupUi(self) self.iconStop = QtGui.QIcon() self.iconStop.addPixmap(QtGui.QPixmap(":/icons/media-playback-stop.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.iconStart = QtGui.QIcon() self.iconStart.addPixmap(QtGui.QPixmap(":/icons/media-playback-start.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.update_ui() self.btnNew.setDefaultAction(self.actionNew) self.btnImport.setDefaultAction(self.actionImport) self.btnSave.setDefaultAction(self.actionSave) self.btnSniff.setDefaultAction(self.actionSniff) self.btnScanChannel.setDefaultAction(self.actionScan_channel) self.btnScanChannels.setDefaultAction(self.actionScan_channels) self.btnNameNodes.setDefaultAction(self.actionName_nodes) self.btnStatistics.setDefaultAction(self.actionStatistics) # data collecting and presenting... self.packets = PacketsModel() self.channels = ChannelsModel() self.details = DetailsModel() self.treePackets.setModel(self.packets) self.treePackets.setItemDelegate(PacketsDelegate(self)) self.treeChannels.setModel(self.channels) self.connect(self.packets, QtCore.SIGNAL("changed"), self.update_ui) self.connect(self.packets.nodes, QtCore.SIGNAL("changed"), self.update_ui) self.sniffer = snifferViaRS.Sniffer() self.connect(self.sniffer, QtCore.SIGNAL("rx"), self.readserial) self.channel = 0 def closeEvent(self, event): """ This event takes care about unsaved data and running serial transmission while user wants to exit app. """ if self.state not in (NONE, STOP): reply = QtGui.QMessageBox.question(self, 'Close ZigBee Snifer application', "Sniffer is working. Are you sure to quit?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) if reply == QtGui.QMessageBox.Yes: self.sniffer.disconnect_() event.accept() else: event.ignore() elif self.packets.changed() or self.packets.nodes.changed(): reply = QtGui.QMessageBox.question(self, 'Close ZigBee Snifer application', "There is unsaved data in current sniff log. Are you sure to quit?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) if reply == QtGui.QMessageBox.Yes: event.accept() else: event.ignore() else: event.accept() def update_ui(self): """ Depending on the state of (so called here) finite state machine, this function sets the widgets on main window form (enables and disables, etc.) """ if self.state == STOP: self.actionScan_channels.setText('Scan channels') self.actionScan_channels.setToolTip('Scan channels') self.actionScan_channel.setText('Scan channel') self.actionScan_channel.setToolTip('Scan channel') self.actionSniff.setText('Sniff') self.actionSniff.setToolTip('Sniff') self.actionSniff.setIcon(self.iconStart) self.enable_controls(self.actionNew, self.actionImport, self.actionScan_channels, self.treeChannels) if self.packets.changed() or self.packets.nodes.changed(): self.actionSave.setEnabled(True) else: self.actionSave.setDisabled(True) if self.channel: #if there is any channel selected.... self.enable_controls(self.actionScan_channel, self.actionSniff) if int(self.packets.rowCount()) > 0: self.setStatusTip('Stopped, ready. Packets recieved: ' + str(self.packets.rowCount())) self.enable_controls(self.actionStatistics, self.actionName_nodes) if self.state in (SCAN_CHANNELS, SCAN_CHANNEL, SNIFF): #turn off all buttons self.disable_controls(self.actionNew, self.actionImport, self.actionSave, self.actionStatistics, self.actionName_nodes, self.actionScan_channels, self.actionScan_channel, self.actionSniff, self.treeChannels) if self.state == SCAN_CHANNELS: self.actionScan_channels.setText('Stop scanning channels') self.actionScan_channels.setToolTip('Stop scanning channels') self.setStatusTip('Scanning channels...') self.actionScan_channels.setEnabled(True) elif self.state == SCAN_CHANNEL: self.actionScan_channel.setText('Stop scanning channel %i' % self.channel) self.actionScan_channel.setToolTip('Stop scanning channel %i' % self.channel) self.setStatusTip('Scanning channel %i' % self.channel) self.actionScan_channel.setEnabled(True) elif self.state == SNIFF: self.actionSniff.setIcon(self.iconStop) self.actionSniff.setText('Stop sniffing') self.actionSniff.setToolTip('Stop sniffing') self.setStatusTip('Sniffing on channel %i' % self.channel) self.actionSniff.setEnabled(True) def enable_controls(self, *args, **kwargs): """ Enable/disable all widgets given. Widgets are in args, value is in kwargs (e.g. value=True) """ if not kwargs.has_key('value'): kwargs['value'] = True for widget in args: widget.setEnabled(kwargs['value']) def disable_controls(self, *args): """ Disable all given widgets """ self.enable_controls(*args, value=False) def on_actionAbout_sniffer_activated(self): pass # TODO: about @QtCore.pyqtSignature("") def on_actionSniff_activated(self): """ Start/stop sniffing packets on selected channel. """ if self.state in (STOP, NONE): self.sniffer.start_reading() self.sniffer.cmd_sniff(self.channel) self.state = SNIFF elif self.state == SNIFF: self.sniffer.cmd_stop() self.sniffer.stop_reading() self.state = STOP self.update_ui() @QtCore.pyqtSignature("") def on_actionScan_channel_activated(self): """ Start/stop scanning selected channel. """ if self.state == SCAN_CHANNEL: self.sniffer.cmd_stop() self.sniffer.stop_reading() self.state = STOP else: self.sniffer.start_reading() self.sniffer.cmd_scan_channel(self.channel) self.state = SCAN_CHANNEL self.update_ui() @QtCore.pyqtSignature("") def on_actionScan_channels_activated(self): """ Start/stop scanning channels. """ if self.state == SCAN_CHANNELS: self.timerScan.stop() self.sniffer.cmd_stop() self.sniffer.stop_reading() self.channel = self.rememberChannel self.state = STOP else: self.rememberChannel = int(self.channel) self.channel = 10 # it'll be incremented, so it'll start from 11 self.timerScan = QtCore.QTimer() self.timerScan.connect(self.timerScan, QtCore.SIGNAL("timeout()"), self.scan_channels) self.scan_channels() self.timerScan.start(2500) self.state = SCAN_CHANNELS self.update_ui() @QtCore.pyqtSignature("") def on_actionNew_activated(self): """ Clear collected data and start everything from scratch. """ self.packets.clear() self.packets.nodes.clear() self.state = STOP self.update_ui() @QtCore.pyqtSignature("") def on_actionImport_activated(self): """ Import data from file. """ fname = '.' fname = QtGui.QFileDialog.getOpenFileName(self, 'ZigBee Sniffer - Import a log file', fname, 'IEEE 802.15.4 log files (*.154)') if fname: # if file dialog not rejected, picked some file with open(fname, 'r') as fh: self.on_actionNew_activated() # clear previous data self.packets.load(fh) self.state = STOP self.update_ui() @QtCore.pyqtSignature("") def on_actionSave_activated(self): """ Save collected data into a file. """ fname = '.' fname = QtGui.QFileDialog.getSaveFileName(self, 'ZigBee Sniffer - save log file', fname, 'IEEE 802.15.4 log files (*.154)') if fname: # if file dialog not rejected, picked some file if '.' not in fname: fname += '.154' with open(fname, 'w') as fh: self.packets.save(fh) self.update_ui() def on_actionName_nodes_activated(self): self.dlgNodes = DialogNodes(self.packets.nodes) self.dlgNodes.show() def on_actionStatistics_activated(self): stats = """Frames recieved: {frames_count} Invalid frames: {invalid_count} Error rate: {error_rate} % Nodes: {nodes_count} Beacon frames: {bcn_count} Data frames: {data_count} Ack. frames: {ack_count} Command frames: {cmd_count}""".format( frames_count = self.packets.rowCount(), invalid_count = self.packets.invlaid_count(), error_rate = round(self.packets.error_rate(), 1), nodes_count = self.packets.nodes.rowCount(), bcn_count = self.packets.type_count(TYPE_BCN), data_count = self.packets.type_count(TYPE_DATA), ack_count = self.packets.type_count(TYPE_ACK), cmd_count = self.packets.type_count(TYPE_CMD) ) for cmd in (CMD_ASS_REQ, CMD_ASS_RESP, CMD_DIS_NOT, CMD_DAT_REQ, CMD_PAN_ID_CON, CMD_ORP_NOT, CMD_BCN_REQ, CMD_CRD_REL, CMD_GTS_REQ): if self.packets.type_count(TYPE_CMD, cmd): stats += '\r\n - {0}s: {1}'.format(cmd, self.packets.type_count(TYPE_CMD, cmd)) QtGui.QMessageBox.information(self, 'Statistics', stats.replace('\t', ''), QtGui.QMessageBox.Yes) #@QtCore.pyqtSignature("") def on_treePackets_activated(self, index): """ This 'slot' updates detailed view of current selected packet. """ #self.details.setPacket(self.packets.getPacket(index)) #a = QtGui.QMessageBox.question(self, u'podgląd', #str(index.row()), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) updatePacketDetails(self.treeDetails, self.packets.packets[index.row()]) self.treeDetails.expandAll() self.treeDetails.resizeColumnToContents(0) self.treeDetails.resizeColumnToContents(1) def on_actionNetwork_structure_activated(self): self.dlgNetwork = DialogNetwork(self.nodes) self.dlgNetwork.show() def on_treeDetails_activated(self, index): pass #if hasattr(index, 'row'): # a = QtGui.QMessageBox.question(self, u'podgląd', # str(index.row())+ ' '+str(index.parent.row()), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) #@QtCore.pyqtSignature("") def on_treeChannels_activated(self, index): """ We make sure here that there is any channel selected to sniff or to scan. """ self.channel = self.channels.clickedChannel(index) if self.state in (NONE, STOP): self.enable_controls(self.actionSniff, self.actionScan_channel) def readserial(self, rx): """ This function is responsible for sending recieved data to right objects depending on applications state. """ print 'Sniffer: %s' % rx.rstrip() if rx[:2] == 'F:': #if this was a frame load = rx.rstrip()[2:].split(',')[1:] load = [int(x) for x in load] timee = datetime.datetime.now() m = '000' + str(timee.microsecond / 1000) m = m[-3:] timee = (str(timee.hour), str(timee.minute), str(timee.second), m) # format the time "H,M,S,m" packet = Packet(load, timee) if self.state == SNIFF: self.packets.append(packet) elif self.state in (SCAN_CHANNEL, SCAN_CHANNELS): if packet.frameType == TYPE_BCN: bcnIndex = self.channels.index(self.channel-11, 3) bcn = int(self.channels.data(bcnIndex)) + 1 self.channels.setData(bcnIndex, bcn) lqiIndex = self.channels.index(self.channel-11, 2) lqi = int(self.channels.data(lqiIndex).toString()) lqi = average(lqi, int(packet.LQI[:-1])) lqi = str(lqi) self.channels.setData(lqiIndex, lqi) def scan_channels(self): """ This function is called by timer. Its job is to scan next channel each time it's called. """ if self.channel < 26: self.sniffer.stop_reading() self.channel += 1 self.sniffer.start_reading() self.sniffer.cmd_scan_channel(self.channel) else: if self.state == SCAN_CHANNELS: #check for sure #this should stop the scan: self.actionScan_channels.emit(QtCore.SIGNAL("activated()"))