Example #1
0
    def remove_device_info(self, uid):
        tab_id = self.tab_for_uid(uid)
        device_info = inventory.get_info(uid)

        device_info.plugin.stop_plugin()
        device_info.plugin.destroy_plugin()

        if tab_id >= 0:
            self.tab_widget.removeTab(tab_id)

        # ensure that the widget gets correctly destroyed. otherwise QWidgets
        # tend to leak as Python is not able to collect their PyQt object
        tab_window = device_info.tab_window
        device_info.tab_window = None

        # If we reboot the RED Brick, the tab_window sometimes is
        # already None here
        if tab_window != None:
            tab_window.hide()
            tab_window.setParent(None)

        plugin = device_info.plugin
        device_info.plugin = None

        if plugin != None:
            plugin.hide()
            plugin.setParent(None)

        inventory.remove_info(uid)
Example #2
0
    def cb_statistics(self, statistics):
        self.label_messages_from_brick.setText(
            str(statistics.messages_from_brick))
        self.label_messages_from_bricklet.setText(
            str(statistics.messages_from_bricklet))

        try:
            name = inventory.get_info(statistics.connected_bricklet_uid
                                      ).plugin.device_class.DEVICE_DISPLAY_NAME
        except:
            name = None

        if statistics.connected_bricklet_uid != '' and name != None:
            self.label_isolated_bricklet.setText(
                '<b>{0}</b> with UID "{1}"'.format(
                    name, statistics.connected_bricklet_uid))
            self.button_bricklet.setText('Open {0}'.format(name))

            if self.last_connected != statistics.connected_bricklet_uid:
                self.last_connected = statistics.connected_bricklet_uid

                try:
                    self.button_bricklet.clicked.disconnect()
                except:
                    pass

                self.button_bricklet.clicked.connect(lambda: get_main_window(
                ).show_plugin(statistics.connected_bricklet_uid))

            self.button_bricklet.setEnabled(True)
        else:
            self.label_isolated_bricklet.setText(
                'Unknown Bricklet (Did you connect a Bricklet?)')
            self.button_bricklet.setText('Open Bricklet')
            self.button_bricklet.setEnabled(False)
Example #3
0
    def update_metric_values(self, parent=None):
        if not self.isVisible():
            return

        self.update_metric_values_timer.stop()

        if parent == None:
            parent = self.tree_view_model.invisibleRootItem()

        def make_async_call(info, uid, index):
            async_call(
                info.plugin.get_health_metric_values, None,
                lambda metric_values: self.get_health_metric_values_async(
                    uid, index, metric_values),
                lambda: self.get_health_metric_values_error(uid, index))

        # FIXME: avoid getter burst!
        for r in range(parent.rowCount()):
            child = parent.child(r, 0)
            index = child.index()
            uid = parent.child(r, 1).text()
            info = inventory.get_info(uid)

            if info == None:
                # FIXME: unknown UID, remove row or mark it as broken?
                continue

            make_async_call(info, uid, index)

            self.update_metric_values(parent=child)

        async_call(lambda: None, None, self.update_metric_values_timer.start,
                   None)
Example #4
0
    def remove_device_tab(self, uid):
        device_info = inventory.get_info(uid)

        if device_info == None:
            return

        assert isinstance(device_info, DeviceInfo)

        self.tab_widget.setCurrentIndex(0)
        self.remove_device_info(device_info.uid)

        for other_info in inventory.get_device_infos():
            other_info.connections_remove_value(device_info)

        self.update_tree_view()
Example #5
0
    def start_async(self):
        self.update_address = 0
        self.update_address_slave = 0

        def get_rs485_address_async(address_async):
            self.update_address = address_async
            next(self.update_generator)

        def get_rs485_slave_address_async(update_address_slave_async):
            self.update_address_slave = update_address_slave_async
            next(self.update_generator)

        async_call(self.master.get_rs485_address, None,
                   get_rs485_address_async, self.parent.increase_error_count)
        yield

        address_slave = []
        for i in range(32):
            async_call(self.master.get_rs485_slave_address, i,
                       get_rs485_slave_address_async,
                       self.parent.increase_error_count)
            yield

            if self.update_address_slave == 0:
                break
            else:
                address_slave.append(str(self.update_address_slave))

        address_slave_text = ', '.join(address_slave)
        typ = 0

        if self.update_address == 0:
            typ = 1

            # trigger enumerate for rs485 slaves
            if inventory.get_info(
                    self.parent.uid
            ).enumeration_type == IPConnection.ENUMERATION_TYPE_CONNECTED:
                self.parent.ipcon.enumerate()

        self.lineedit_slave_addresses.setText(address_slave_text)
        self.address_spinbox.setValue(self.update_address)

        self.save_button.clicked.connect(self.save_clicked)
        self.rs485_type.currentIndexChanged.connect(self.rs485_type_changed)

        self.rs485_type.setCurrentIndex(typ)
        self.rs485_type_changed(typ)
Example #6
0
    def hack_to_remove_red_brick_tab(self, uid):
        device_info = inventory.get_info(uid)

        if device_info == None:
            return

        assert isinstance(device_info, DeviceInfo)

        self.tab_widget.setCurrentIndex(0)
        self.remove_device_info(device_info.uid)

        self.red_session_losts += 1
        self.label_red_session_losts.setText(
            'RED Brick Session Loss Count: {0}'.format(self.red_session_losts))
        self.label_red_session_losts.show()

        self.update_tree_view()
Example #7
0
    def show_plugin(self, uid):
        device_info = inventory.get_info(uid)

        if device_info == None:
            return

        index = self.tab_for_uid(uid)
        tab_window = device_info.tab_window

        if index > 0 and self.tab_widget.isTabEnabled(index):
            self.tab_widget.setCurrentIndex(index)

        QApplication.setActiveWindow(tab_window)

        tab_window.show()
        tab_window.activateWindow()
        tab_window.raise_()

        return device_info.plugin
Example #8
0
    def update_bricklets(self):
        info = inventory.get_info(self.uid)

        if info == None:
            return

        for i in range(4):
            port = chr(ord('a') + i)

            try:
                bricklet = info.connections_get(port)[0]
                text = '{0} ({1})'.format(bricklet.name, bricklet.uid)

                if text != self.ports[i].text():
                    self.ports[i].setText(text)
                    self.ports[i].setProperty('_bricklet_uid', bricklet.uid)
                    self.ports[i].setEnabled(True)
            except:
                self.ports[i].setText('Not Connected')
                self.ports[i].setProperty('_bricklet_uid', None)
                self.ports[i].setEnabled(False)
Example #9
0
    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
        ]:
            device_info = inventory.get_info(uid)

            # If the enum_type is CONNECTED, the bricklet was restarted externally.
            # The plugin could now be in an inconsistent state.
            if enumeration_type == IPConnection.ENUMERATION_TYPE_CONNECTED and device_info is not None:
                if device_info.connected_uid != connected_uid:
                    # Fix connections if bricklet was connected to another brick.
                    parent_info = inventory.get_info(device_info.connected_uid)

                    if parent_info is not None:
                        parent_info.connections_remove_item(
                            (device_info.position, device_info))
                        self.show_status(
                            "Hot plugging is not supported! Please reset Brick with UID {} and reconnect Brick Viewer."
                            .format(device_info.connected_uid),
                            message_id='mainwindow_hotplug')

                    device_info.reverse_connection = connected_uid
                elif device_info.position != position:
                    # Bricklet was connected to the same brick, but to another port
                    self.show_status(
                        "Hot plugging is not supported! Please reset Brick with UID {} and reconnect Brick Viewer."
                        .format(device_info.connected_uid),
                        message_id='mainwindow_hotplug')

                # If the plugin is not running, pause will do nothing, so it is always save to call it.
                # The plugin will be (unconditionally) resumed later, as resume also only does something
                # if it was paused before (e.g. here).
                if device_info.plugin is not None:
                    device_info.plugin.pause_plugin()

            if device_info == None:
                if device_identifier == BrickMaster.DEVICE_IDENTIFIER:
                    device_info = BrickMasterInfo()
                elif device_identifier == BrickRED.DEVICE_IDENTIFIER:
                    device_info = BrickREDInfo()
                elif hat_brick_supported and device_identifier == BrickHAT.DEVICE_IDENTIFIER:
                    device_info = BrickHATInfo()
                elif hat_zero_brick_supported and device_identifier == BrickHATZero.DEVICE_IDENTIFIER:
                    device_info = BrickHATZeroInfo()
                elif device_identifier == BrickletIsolator.DEVICE_IDENTIFIER:
                    device_info = BrickletIsolatorInfo()
                elif str(device_identifier).startswith('20'):
                    device_info = TNGInfo()
                elif '0' <= position <= '9':
                    device_info = BrickInfo()
                else:
                    device_info = BrickletInfo()

            position = position.lower()

            device_info.uid = uid
            device_info.connected_uid = connected_uid
            device_info.position = position
            device_info.hardware_version = hardware_version

            if device_identifier != BrickRED.DEVICE_IDENTIFIER:
                device_info.firmware_version_installed = firmware_version

            device_info.device_identifier = device_identifier
            device_info.enumeration_type = enumeration_type

            # Update connections and reverse_connection with new device
            for info in inventory.get_device_infos():
                if info == device_info:
                    continue

                def add_to_connections(info_to_add, connected_info):
                    hotplug = connected_info.connections_add_item(
                        (info_to_add.position, info_to_add))
                    info_to_add.reverse_connection = connected_info

                    # '0' is the port where other stacks connected by RS485 extensions are connected. Multiple connections are allowed here.
                    if hotplug and info_to_add.position != '0':
                        self.show_status(
                            "Hot plugging is not supported! Please reset Brick with UID {} and reconnect Brick Viewer."
                            .format(connected_info.uid),
                            message_id='mainwindow_hotplug')

                if info.uid != '' and info.uid == device_info.connected_uid:
                    if device_info in info.connections_values(
                    ):  # device was already connected, but to another port
                        info.connections_remove_value(device_info)

                    if device_info not in info.connections_get(
                            device_info.position):
                        add_to_connections(device_info, info)

                if info.connected_uid != '' and info.connected_uid == device_info.uid:
                    if info in device_info.connections_values(
                    ):  # device was already connected, but to another port
                        device_info.connections_remove_value(info)

                    if info not in device_info.connections_get(info.position):
                        add_to_connections(info, device_info)

            if device_info.plugin == None:
                self.plugin_manager.create_plugin_instance(
                    device_identifier, self.ipcon, device_info)

                device_info.tab_window = self.create_tab_window(
                    device_info, self.ipcon)
                device_info.tab_window.setWindowFlags(Qt.Widget)
                device_info.tab_window.tab()

                inventory.add_info(device_info)

            device_info.update_firmware_version_latest()

            inventory.sync()

            # The plugin was paused before if it was reconnected.
            device_info.plugin.resume_plugin()
        elif enumeration_type == IPConnection.ENUMERATION_TYPE_DISCONNECTED:
            self.remove_device_tab(uid)
Example #10
0
    def start_async(self):
        self.update_address = 0
        self.update_chibi_slave_address = 0
        self.update_chibi_master_address = 0
        self.update_chibi_frequency = 0
        self.update_chibi_channel = 0

        def get_chibi_address_async(address_async):
            self.update_address = address_async
            next(self.update_generator)

        def get_chibi_slave_address_async(chibi_slave_address_async):
            self.update_chibi_slave_address = chibi_slave_address_async
            next(self.update_generator)

        def get_chibi_master_address_async(chibi_master_address_async):
            self.update_chibi_master_address = chibi_master_address_async
            next(self.update_generator)

        def get_chibi_frequency_async(chibi_frequency_async):
            self.update_chibi_frequency = chibi_frequency_async
            next(self.update_generator)

        def get_chibi_channel_async(chibi_channel_async):
            self.update_chibi_channel = chibi_channel_async
            next(self.update_generator)

        async_call(self.master.get_chibi_address, None, get_chibi_address_async, self.parent.increase_error_count)
        yield

        address_slave = []

        for i in range(32):
            async_call(self.master.get_chibi_slave_address, i, get_chibi_slave_address_async, self.parent.increase_error_count)
            yield

            if self.update_chibi_slave_address == 0:
                break
            else:
                address_slave.append(str(self.update_chibi_slave_address))

        address_slave_text = ', '.join(address_slave)

        async_call(self.master.get_chibi_master_address, None, get_chibi_master_address_async, self.parent.increase_error_count)
        yield

        async_call(self.master.get_chibi_frequency, None, get_chibi_frequency_async, self.parent.increase_error_count)
        yield

        async_call(self.master.get_chibi_channel, None, get_chibi_channel_async, self.parent.increase_error_count)
        yield

        typ = 0

        if self.update_address == self.update_chibi_master_address:
            typ = 1

            # trigger enumerate for chibi slaves
            if inventory.get_info(self.parent.uid).enumeration_type == IPConnection.ENUMERATION_TYPE_CONNECTED:
                self.parent.ipcon.enumerate()

        self.lineedit_slave_address.setText(address_slave_text)
        self.address_spinbox.setValue(self.update_address)
        self.master_address_spinbox.setValue(self.update_chibi_master_address)
        self.chibi_frequency.setCurrentIndex(self.update_chibi_frequency)
        self.chibi_channel.setCurrentIndex(self.update_chibi_channel)

        self.save_button.clicked.connect(self.save_clicked)
        self.chibi_type.currentIndexChanged.connect(self.chibi_type_changed)
        self.chibi_frequency.currentIndexChanged.connect(self.chibi_frequency_changed)
        self.chibi_channel.currentIndexChanged.connect(self.chibi_channel_changed)

        self.chibi_type.setCurrentIndex(typ)
        self.chibi_type_changed(typ)
        self.new_max_count()