def flashing_pressed(self): first = False if self.flashing_window is None: first = True self.flashing_window = FlashingWindow(self) self.update_flashing_window() self.flashing_window.show() self.flashing_window.refresh_updates_pressed() if first: self.flashing_window.refresh_firmware_and_plugin_infos()
class MainWindow(QMainWindow, Ui_MainWindow): callback_enumerate_signal = pyqtSignal(str, str, int, bool) def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.setupUi(self) self.setWindowIcon(QIcon("brickv-icon.png")) signal.signal(signal.SIGINT, self.exit_brickv) signal.signal(signal.SIGTERM, self.exit_brickv) self.setWindowTitle("Brick Viewer " + config.BRICKV_VERSION) self.table_view_header = ['Stack ID', 'Device Name', 'UID', 'FW Version', 'Chip Temp.', 'Reset'] # Remove dummy tab self.tab_widget.removeTab(1) self.last_tab = 0 self.plugins = [(self, None, None, None)] self.ipcon = None self.flashing_window = None self.advanced_window = None self.reset_view() self.button_advanced.setDisabled(True) self.callback_enumerate_signal.connect(self.callback_enumerate) self.tab_widget.currentChanged.connect(self.tab_changed) self.connect.pressed.connect(self.connect_pressed) self.button_flashing.pressed.connect(self.flashing_pressed) self.button_advanced.pressed.connect(self.advanced_pressed) self.plugin_manager = PluginManager() self.host.setText(config.get_host()) self.port.setValue(config.get_port()) self.mtm = None self.chip_temp_timer = QTimer() self.chip_temp_timer.timeout.connect(self.update_chip_temp) self.chip_temp_timer.setInterval(2000) self.chip_temp_timer.start() def closeEvent(self, event): self.exit_brickv() def exit_brickv(self, signl=None, frme=None): config.set_host(str(self.host.text())) config.set_port(self.port.value()) if self.ipcon != None: self.reset_view() if signl != None and frme != None: print "Received SIGINT or SIGTERM, shutting down." sys.exit() def start(self): self.update_chip_temp() self.chip_temp_timer.start() def stop(self): self.chip_temp_timer.stop() def destroy(self): pass def tab_changed(self, i): self.plugins[i][0].start() self.plugins[self.last_tab][0].stop() self.last_tab = i def reset_view(self): self.tab_widget.setCurrentIndex(0) for i in reversed(range(1, len(self.plugins))): try: self.plugins[i][0].stop() self.plugins[i][0].destroy() except AttributeError: pass self.tab_widget.removeTab(i) self.plugins = [(self, None, None, None)] self.update_table_view() if self.ipcon: self.ipcon.destroy() self.ipcon = None def flashing_pressed(self): if self.flashing_window is None: self.flashing_window = FlashingWindow(self) self.update_flashing_window() self.flashing_window.show() def advanced_pressed(self): if self.advanced_window is None: self.advanced_window = AdvancedWindow(self) self.update_advanced_window() self.advanced_window.show() def connect_pressed(self): if not self.ipcon: try: self.ipcon = IPConnection(self.host.text(), self.port.value()) self.ipcon.enumerate(self.callback_enumerate_signal.emit) self.connect.setText("Disconnect") self.port.setDisabled(True) self.host.setDisabled(True) except (Error, socket.error): self.ipcon = None box_head = 'Could not connect' box_text = 'Please check host, check port and ' + \ 'check if brickd is running.' QMessageBox.critical(self, box_head, box_text) else: self.reset_view() self.connect.setText("Connect") self.button_advanced.setDisabled(True) self.port.setDisabled(False) self.host.setDisabled(False) def callback_enumerate(self, uid, name, stack_id, is_new): if is_new: for plugin in self.plugins: # Plugin already loaded if plugin[3] == uid: return plugin = self.plugin_manager.get_plugin_from_name(name, self.ipcon, uid) if plugin is not None: self.tab_widget.addTab(plugin, name) self.plugins.append((plugin, stack_id, name, uid)) else: for i in range(len(self.plugins)): if self.plugins[i][3] == uid: self.tab_widget.setCurrentIndex(0) self.plugins[i][0].stop() self.plugins[i][0].destroy() self.tab_widget.removeTab(i) self.plugins.remove(self.plugins[i]) self.update_table_view() return self.update_table_view() def update_table_view(self): data = [] for p in self.plugins[1:]: if p[0] is not None: data.append([p[1], p[2], p[3], p[0].version, '', '']) self.mtm = MainTableModel(self.table_view_header, data) self.table_view.setModel(self.mtm) for r in range(len(data)): p = self.plugins[r + 1] if p[0] is not None and ' Brick ' in p[2]: button = QPushButton('Reset') if p[0].has_reset_device(): button.clicked.connect(p[0].reset_device) else: button.setDisabled(True) self.table_view.setIndexWidget(self.mtm.index(r, 5), button) self.update_flashing_window() self.update_advanced_window() def update_flashing_window(self): if self.flashing_window is not None: devices = [] for plugin in self.plugins[1:]: if ' Brick ' in plugin[2]: devices.append((plugin[2], plugin[0].device)) self.flashing_window.set_devices(devices) def update_advanced_window(self): devices = [] for plugin in self.plugins[1:]: if ' Brick ' in plugin[2]: devices.append((plugin[2], plugin[0].device)) self.button_advanced.setEnabled(len(devices) > 0) if self.advanced_window is not None: self.advanced_window.set_devices(devices) def update_chip_temp(self): if self.mtm is None: return for r in range(len(self.plugins) - 1): p = self.plugins[r + 1] if p[0] is not None: try: self.mtm.setData(self.mtm.index(r, 4), p[0].get_chip_temperature(), Qt.DisplayRole) except Error: # abort update here to avoid requesting chtip temp from a # whole disconnected stack return
def flashing_pressed(self): if self.flashing_window is None: self.flashing_window = FlashingWindow(self) self.update_flashing_window() self.flashing_window.show()
class MainWindow(QMainWindow, Ui_MainWindow): qtcb_enumerate = pyqtSignal(str, str, 'char', type((0,)), type((0,)), int, int) qtcb_connected = pyqtSignal(int) qtcb_disconnected = pyqtSignal(int) def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.setupUi(self) self.setWindowIcon(QIcon(os.path.join(ProgramPath.program_path(), "brickv-icon.png"))) signal.signal(signal.SIGINT, self.exit_brickv) signal.signal(signal.SIGTERM, self.exit_brickv) self.async_thread = async_start_thread(self) self.setWindowTitle("Brick Viewer " + config.BRICKV_VERSION) self.tree_view_model_labels = ['Name', 'UID', 'FW Version'] self.tree_view_model = QStandardItemModel() self.tree_view.setModel(self.tree_view_model) self.set_tree_view_defaults() # Remove dummy tab self.tab_widget.removeTab(1) self.last_tab = 0 self.name = '<unknown>' self.uid = '<unknown>' self.version = (0, 0, 0) self.disconnect_times = [] self.qtcb_enumerate.connect(self.cb_enumerate) self.qtcb_connected.connect(self.cb_connected) self.qtcb_disconnected.connect(self.cb_disconnected) self.ipcon = IPConnection() self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE, self.qtcb_enumerate.emit) self.ipcon.register_callback(IPConnection.CALLBACK_CONNECTED, self.qtcb_connected.emit) self.ipcon.register_callback(IPConnection.CALLBACK_DISCONNECTED, self.qtcb_disconnected.emit) self.flashing_window = None self.advanced_window = None self.delayed_refresh_updates_timer = QTimer() self.delayed_refresh_updates_timer.timeout.connect(self.delayed_refresh_updates) self.delayed_refresh_updates_timer.setInterval(500) self.reset_view() self.button_advanced.setDisabled(True) self.tab_widget.currentChanged.connect(self.tab_changed) self.connect.pressed.connect(self.connect_pressed) self.button_flashing.pressed.connect(self.flashing_pressed) self.button_advanced.pressed.connect(self.advanced_pressed) self.plugin_manager = PluginManager() self.combo_host.addItem(config.get_host()) self.combo_host.addItems(config.get_host_history(HOST_HISTORY_SIZE - 1)) self.spinbox_port.setValue(config.get_port()) self.last_host = self.combo_host.currentText() self.last_port = self.spinbox_port.value() def closeEvent(self, event): self.exit_brickv() def exit_brickv(self, signl=None, frme=None): host = str(self.combo_host.currentText()) history = [] for i in range(self.combo_host.count()): h = str(self.combo_host.itemText(i)) if h != host and h not in history: history.append(h) config.set_host(host) config.set_host_history(history[:HOST_HISTORY_SIZE - 1]) config.set_port(self.spinbox_port.value()) self.reset_view() try: self.ipcon.disconnect() except: pass if signl != None and frme != None: print "Received SIGINT or SIGTERM, shutting down." sys.exit() def start(self): pass def stop(self): pass def destroy(self): pass def tab_changed(self, i): try: uid = self.tab_widget.widget(i)._uid infos.infos[uid].plugin.start() except: pass try: uid = self.tab_widget.widget(self.last_tab)._uid infos.infos[uid].plugin.stop() except: pass self.last_tab = i def reset_view(self): self.tab_widget.setCurrentIndex(0) keys_to_remove = [] for key in infos.infos: if infos.infos[key].type in ('brick', 'bricklet'): infos.infos[key].plugin.stop() infos.infos[key].plugin.destroy() keys_to_remove.append(key) for key in keys_to_remove: try: infos.infos.pop(key) except: pass for i in reversed(range(1, self.tab_widget.count())): self.tab_widget.removeTab(i) self.update_tree_view() def flashing_pressed(self): first = False if self.flashing_window is None: first = True self.flashing_window = FlashingWindow(self) self.update_flashing_window() self.flashing_window.show() self.flashing_window.refresh_updates_pressed() if first: self.flashing_window.refresh_firmware_and_plugin_infos() def advanced_pressed(self): if self.advanced_window is None: self.advanced_window = AdvancedWindow(self) self.update_advanced_window() self.advanced_window.show() def connect_pressed(self): if self.ipcon.get_connection_state() == IPConnection.CONNECTION_STATE_DISCONNECTED: try: self.last_host = self.combo_host.currentText() self.last_port = self.spinbox_port.value() self.connect.setDisabled(True) self.ipcon.connect(self.last_host, self.last_port) except: self.connect.setDisabled(False) QMessageBox.critical(self, 'Could not connect', 'Please check host, check port and ' + 'check if the Brick Daemon is running') else: self.reset_view() async_next_session() self.ipcon.disconnect() def create_plugin_container(self, plugin, connected_uid, position): container = QWidget() container._uid = plugin.uid layout = QVBoxLayout(container) info = QHBoxLayout() # uid info.addWidget(QLabel('UID:')) label = QLabel('{0}'.format(plugin.uid)) label.setTextInteractionFlags(Qt.TextSelectableByMouse | Qt.TextSelectableByKeyboard) info.addWidget(label) info.addSpacerItem(QSpacerItem(1, 1, QSizePolicy.Expanding)) # connected uid if connected_uid != '0': info.addWidget(QLabel('Connected to:')) label = QLabel('{0}'.format(connected_uid)) label.setTextInteractionFlags(Qt.TextSelectableByMouse | Qt.TextSelectableByKeyboard) info.addWidget(label) info.addSpacerItem(QSpacerItem(1, 1, QSizePolicy.Expanding)) # position info.addWidget(QLabel('Position:')) info.addWidget(QLabel('{0}'.format(position.upper()))) info.addSpacerItem(QSpacerItem(1, 1, QSizePolicy.Expanding)) # firmware version info.addWidget(QLabel('FW Version:')) info.addWidget(QLabel('{0}'.format(plugin.version_str))) info.addSpacerItem(QSpacerItem(1, 1, QSizePolicy.Expanding)) # timeouts info.addWidget(QLabel('Timeouts:')) label_timeouts = QLabel('0') info.addWidget(label_timeouts) layout.addLayout(info) if plugin.is_brick(): button = QPushButton('Reset') if plugin.has_reset_device(): button.clicked.connect(plugin.reset_device) else: button.setDisabled(True) info.addSpacerItem(QSpacerItem(40, 20, QSizePolicy.Expanding)) info.addWidget(button) line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) plugin.label_timeouts = label_timeouts plugin.layout().setContentsMargins(0, 0, 0, 0) layout.addWidget(line) layout.addWidget(plugin) return container def tab_for_uid(self, uid): for i in range(1, self.tab_widget.count()): try: widget = self.tab_widget.widget(i) if widget._uid == uid: return i except: pass return -1 def cb_enumerate(self, uid, connected_uid, position, hardware_version, firmware_version, device_identifier, enumeration_type): if self.ipcon.get_connection_state() != IPConnection.CONNECTION_STATE_CONNECTED: # ignore enumerate callbacks that arrived after the connection got closed return if enumeration_type in [IPConnection.ENUMERATION_TYPE_AVAILABLE, IPConnection.ENUMERATION_TYPE_CONNECTED]: if device_identifier == BrickMaster.DEVICE_IDENTIFIER: info = infos.BrickMasterInfo() elif position in ('a', 'b', 'c', 'd', 'A', 'B', 'C', 'D'): position = position.lower() info = infos.BrickletInfo() else: info = infos.BrickInfo() if uid in infos.infos: info = infos.infos[uid] else: infos.infos[uid] = info for device in infos.infos.values(): if device.type == 'brick': if info.type == 'bricklet': if device.uid == connected_uid: device.bricklets[position] = info if device.type == 'bricklet': if info.type == 'brick': if uid == device.connected_uid: info.bricklets[device.position] = device info.uid = uid info.connected_uid = connected_uid info.position = position info.hardware_version = hardware_version info.firmware_version_installed = firmware_version info.device_identifier = device_identifier info.protocol_version = 2 info.enumeration_type = enumeration_type for device in infos.infos.values(): if device.type in ('brick', 'bricklet'): if device.uid == uid and device.plugin != None: return plugin = self.plugin_manager.get_plugin(device_identifier, self.ipcon, uid, firmware_version) if plugin is not None: info.plugin = plugin if plugin.is_hardware_version_relevant(hardware_version): info.name = '{0} {1}.{2}'.format(plugin.name, hardware_version[0], hardware_version[1]) else: info.name = plugin.name info.url_part = plugin.get_url_part() c = self.create_plugin_container(plugin, connected_uid, position) info.plugin_container = c self.tab_widget.addTab(c, info.name) elif enumeration_type == IPConnection.ENUMERATION_TYPE_DISCONNECTED: for device_info in infos.infos.values(): if device_info.type in ('brick', 'bricklet'): if device_info.uid == uid: try: self.tab_widget.setCurrentIndex(0) if device_info.plugin: device_info.plugin.stop() device_info.plugin.destroy() i = self.tab_for_uid(device_info.uid) self.tab_widget.removeTab(i) except: pass if device_info.type == 'brick': for port in device_info.bricklets: if device_info.bricklets[port]: if device_info.bricklets[port].uid == uid: device_info.bricklets[port] = None try: infos.infos.pop(uid) except: pass self.update_tree_view() def cb_connected(self, connect_reason): self.update_ui_state() if connect_reason == IPConnection.CONNECT_REASON_REQUEST: self.ipcon.set_auto_reconnect(True) index = self.combo_host.findText(self.last_host) if index >= 0: self.combo_host.removeItem(index) self.combo_host.insertItem(-1, self.last_host) self.combo_host.setCurrentIndex(0) while self.combo_host.count() > HOST_HISTORY_SIZE: self.combo_host.removeItem(self.combo_host.count() - 1) try: self.ipcon.enumerate() except: self.update_ui_state() elif connect_reason == IPConnection.CONNECT_REASON_AUTO_RECONNECT: try: self.ipcon.enumerate() except: self.update_ui_state() QMessageBox.information(self, 'Connection', 'Successfully reconnected!', QMessageBox.Ok) else: try: self.ipcon.enumerate() except: self.update_ui_state() def cb_disconnected(self, disconnect_reason): if disconnect_reason == IPConnection.DISCONNECT_REASON_REQUEST or not self.ipcon.get_auto_reconnect(): self.update_ui_state() elif len(self.disconnect_times) >= 3 and self.disconnect_times[-3] < time.time() + 1: self.disconnect_times = [] self.ipcon.set_auto_reconnect(False) self.update_ui_state() self.reset_view() QMessageBox.critical(self, 'Connection', 'Stopped automatic reconnecting due to multiple connection errors in a row.', QMessageBox.Ok) else: self.disconnect_times.append(time.time()) self.connect.setText('Abort Automatic Reconnecting') if disconnect_reason == IPConnection.DISCONNECT_REASON_ERROR: QMessageBox.critical(self, 'Connection', 'Connection lost, an error occured!\n' + 'Trying to reconnect.', QMessageBox.Ok) elif disconnect_reason == IPConnection.DISCONNECT_REASON_SHUTDOWN: QMessageBox.critical(self, 'Connection', 'Connection lost, socket disconnected by server!\n' + 'Trying to reconnect.', QMessageBox.Ok) def set_tree_view_defaults(self): self.tree_view_model.setHorizontalHeaderLabels(self.tree_view_model_labels) self.tree_view.expandAll() self.tree_view.setColumnWidth(0, 260) self.tree_view.setColumnWidth(1, 75) self.tree_view.setColumnWidth(2, 85) self.tree_view.setSortingEnabled(True) self.tree_view.header().setSortIndicator(0, Qt.AscendingOrder) def update_ui_state(self): connection_state = self.ipcon.get_connection_state() self.connect.setDisabled(False) if connection_state == IPConnection.CONNECTION_STATE_DISCONNECTED: self.connect.setText('Connect') self.button_advanced.setDisabled(True) self.combo_host.setDisabled(False) self.spinbox_port.setDisabled(False) elif connection_state == IPConnection.CONNECTION_STATE_CONNECTED: self.connect.setText("Disconnect") self.combo_host.setDisabled(True) self.spinbox_port.setDisabled(True) def update_tree_view(self): self.tree_view_model.clear() for device_info in sorted(infos.infos.values(), cmp=lambda x, y: cmp(x.name, y.name)): if device_info.type == 'brick': parent = [QStandardItem(device_info.name), QStandardItem(device_info.uid), QStandardItem('.'.join(map(str, device_info.firmware_version_installed)))] for item in parent: item.setFlags(item.flags() & ~Qt.ItemIsEditable) self.tree_view_model.appendRow(parent) for port in sorted(device_info.bricklets): if device_info.bricklets[port] and device_info.bricklets[port].protocol_version == 2: child = [QStandardItem(port.upper() + ': ' +device_info.bricklets[port].name), QStandardItem(device_info.bricklets[port].uid), QStandardItem('.'.join(map(str, device_info.bricklets[port].firmware_version_installed)))] for item in child: item.setFlags(item.flags() & ~Qt.ItemIsEditable) parent[0].appendRow(child) self.set_tree_view_defaults() self.update_flashing_window() self.update_advanced_window() self.delayed_refresh_updates_timer.start() def update_flashing_window(self): if self.flashing_window is not None: self.flashing_window.update_bricks() def update_advanced_window(self): has_brick = False for info in infos.infos.values(): if info.type == 'brick': has_brick = True self.button_advanced.setEnabled(has_brick) if self.advanced_window is not None: self.advanced_window.update_bricks() def delayed_refresh_updates(self): self.delayed_refresh_updates_timer.stop() if self.flashing_window is not None and self.flashing_window.isVisible(): self.flashing_window.refresh_updates_pressed()