Example #1
0
    def extension_clicked(self):
        if self.extension_type is None:
            self.extension_type = ExtensionType(self)

        self.extension_type.show()
Example #2
0
class Master(PluginBase, Ui_Master):
    def __init__(self, *args):
        PluginBase.__init__(self, BrickMaster, *args)

        self.setupUi(self)

        self.master = self.device

        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.update_data)

        self.extension_type = None

        self.extensions = []
        self.num_extensions = 0

        self.extension_label.setText("None Present")
        self.tab_widget.removeTab(0)
        self.tab_widget.hide()

        if self.firmware_version >= (1, 1, 0):
            self.check_extensions = True
            self.extension_type_button.clicked.connect(self.extension_clicked)
        else:
            self.check_extensions = False
            self.extension_type_button.setEnabled(False)

        if self.firmware_version >= (1, 2, 1):
            reset = QAction('Reset', self)
            reset.triggered.connect(lambda: self.master.reset())
            self.set_actions(reset)

        self.extension_type_preset = [None, False, False, False, False, False]
        self.update_extensions_in_device_info()

    def update_extensions_in_device_info(self):
        def is_present_async(present, extension_type, name):
            self.extension_type_preset[extension_type] = present

            if present:
                if self.device_info.extensions['ext0'] == None:
                    ext = 'ext0'
                elif self.device_info.extensions['ext1'] == None:
                    ext = 'ext1'
                else:
                    return # This should never be the case

                self.device_info.extensions[ext] = infos.ExtensionInfo()
                self.device_info.extensions[ext].name = name
                self.device_info.extensions[ext].extension_type = extension_type
                self.device_info.extensions[ext].position = ext
                self.device_info.extensions[ext].master_info = self.device_info
                infos.update_info(self.uid)

                def get_wifi2_firmware_version_async(version, ext):
                    self.device_info.extensions[ext].firmware_version_installed = version
                    infos.update_info(self.uid)
                    get_main_window().update_tree_view() # FIXME: this is kind of a hack
                    self.is_wifi2_present_async(True)

                if extension_type == self.master.EXTENSION_TYPE_WIFI2:
                    self.device_info.extensions[ext].url_part = 'wifi_v2'
                    '''
                    When WIFI2 extension firmware version is being requested the
                    extension might still not be done with booting and thus the
                    message won't be received by the extension. So we delay sending
                    the request which gives enough time to the extension to finish
                    booting. Note that this delay is only induced when there is a
                    WIFI2 extension present.
                    '''
                    time.sleep(2)
                    async_call(self.master.get_wifi2_firmware_version, None, lambda v: get_wifi2_firmware_version_async(v, ext), self.increase_error_count)

        def get_connection_type_async(connection_type):
            self.device_info.connection_type = connection_type
            infos.update_info(self.uid)

        if self.firmware_version >= (1, 1, 0):
            async_call(self.master.is_chibi_present, None, lambda p: is_present_async(p, self.master.EXTENSION_TYPE_CHIBI, 'Chibi Extension'), self.increase_error_count)

        if self.firmware_version >= (1, 2, 0):
            async_call(self.master.is_rs485_present, None, lambda p: is_present_async(p, self.master.EXTENSION_TYPE_RS485, 'RS485 Extension'), self.increase_error_count)

        if self.firmware_version >= (1, 3, 0):
            async_call(self.master.is_wifi_present, None, lambda p: is_present_async(p, self.master.EXTENSION_TYPE_WIFI, 'WIFI Extension'), self.increase_error_count)

        if self.firmware_version >= (2, 1, 0):
            async_call(self.master.is_ethernet_present, None, lambda p: is_present_async(p, self.master.EXTENSION_TYPE_ETHERNET, 'Ethernet Extension'), self.increase_error_count)

        if self.firmware_version >= (2, 4, 0):
            async_call(self.master.is_wifi2_present, None, lambda p: is_present_async(p, self.master.EXTENSION_TYPE_WIFI2, 'WIFI Extension 2.0'), self.increase_error_count)
            async_call(self.master.get_connection_type, None, get_connection_type_async, self.increase_error_count)

        async_call(lambda: None, None, lambda: get_main_window().update_tree_view(), None)

    def is_wifi2_present_async(self, present):
        if present:
            wifi2 = Wifi2(self)
            self.extensions.append(wifi2)
            self.tab_widget.addTab(wifi2, 'WIFI 2.0')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

            '''
            Check if the master brick and WIFI extension 2 firmware versions support
            mesh networking feature. Also set firmware version information for the WIFI2
            extension 2 object.
            '''
            for ext in self.device_info.extensions:
                if not self.device_info.extensions[ext]:
                    continue

                if self.device_info.extensions[ext].name != 'WIFI Extension 2.0':
                    continue

                wifi2.wifi2_firmware_version = \
                    self.device_info.extensions[ext].firmware_version_installed

                if self.device_info.extensions[ext].firmware_version_installed >= (2, 0, 4) \
                and self.firmware_version >= (2, 4, 2):
                    wifi2.wifi_mode.addItem('Mesh')
                    wifi2.get_current_status()
                    break

    def is_ethernet_present_async(self, present):
        if present:
            ethernet = Ethernet(self)
            self.extensions.append(ethernet)
            self.tab_widget.addTab(ethernet, 'Ethernet')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def is_wifi_present_async(self, present):
        if present:
            wifi = Wifi(self)
            self.extensions.append(wifi)
            self.tab_widget.addTab(wifi, 'WIFI')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def is_rs485_present_async(self, present):
        if present:
            rs485 = RS485(self)
            self.extensions.append(rs485)
            self.tab_widget.addTab(rs485, 'RS485')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def is_chibi_present_async(self, present):
        if present:
            chibi = Chibi(self)
            self.extensions.append(chibi)
            self.tab_widget.addTab(chibi, 'Chibi')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def start(self):
        if self.check_extensions:
            self.check_extensions = False

            self.is_chibi_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_CHIBI])
            self.is_rs485_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_RS485])
            self.is_wifi_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_WIFI])
            self.is_ethernet_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_ETHERNET])

            '''
            For WIFI extension 2, self.is_ethernet_present_async() isn't called here but called from the
            async callback, get_wifi2_firmware_version_async(). This is to ensure that both the master brick
            and WIFI extension 2 firmware versions are avilable before creating the tab widget of the extension.
            This is required because WIFI extension 2 supports mesh networking for which the GUI is updated
            dynamically only when the version information is available.
            '''

        self.update_timer.start(1000)

    def stop(self):
        self.update_timer.stop()

    def destroy(self):
        for extension in self.extensions:
            extension.destroy()
            extension.hide()
            extension.setParent(None)

        self.extensions = []

        if self.extension_type:
            self.extension_type.close()

    def is_hardware_version_relevant(self):
        return True

    def get_url_part(self):
        return 'master'

    @staticmethod
    def has_device_identifier(device_identifier):
        return device_identifier == BrickMaster.DEVICE_IDENTIFIER

    def update_data(self):
        async_call(self.master.get_stack_voltage, None, self.get_stack_voltage_async, self.increase_error_count)
        async_call(self.master.get_stack_current, None, self.get_stack_current_async, self.increase_error_count)

        for extension in self.extensions:
            extension.update_data()

    def get_stack_voltage_async(self, voltage):
        self.stack_voltage_label.setText('{:g} V'.format(round(voltage / 1000.0, 1)))

    def get_stack_current_async(self, current):
        self.stack_current_label.setText(format_current(current / 1000.0))

    def extension_clicked(self):
        if self.extension_type is None:
            self.extension_type = ExtensionType(self)

        self.extension_type.show()
Example #3
0
    def extension_clicked(self):
        if self.extension_type is None:
            self.extension_type = ExtensionType(self)

        self.extension_type.show()
Example #4
0
class Master(PluginBase, Ui_Master):
    def __init__(self, *args):
        PluginBase.__init__(self, BrickMaster, *args)

        self.setupUi(self)

        self.master = self.device

        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.update_data)

        self.wifi2_get_firmware_version_timer = QTimer()
        self.wifi2_get_firmware_version_timer.timeout.connect(
            self.wifi2_get_firmware_version)

        self.extension_type = None

        self.extensions = []
        self.num_extensions = 0
        self.wifi2_ext = None
        self.wifi2_firmware_version = None

        self.extension_label.setText("None Present")
        self.tab_widget.removeTab(0)
        self.tab_widget.hide()

        if self.firmware_version >= (1, 1, 0):
            self.check_extensions = True
            self.extension_type_button.clicked.connect(self.extension_clicked)
        else:
            self.check_extensions = False
            self.extension_type_button.setEnabled(False)

        if self.firmware_version >= (2, 3, 2):
            self.status_led_action = QAction('Status LED', self)
            self.status_led_action.setCheckable(True)
            self.status_led_action.toggled.connect(
                lambda checked: self.master.enable_status_led()
                if checked else self.master.disable_status_led())
            self.set_configs([(0, None, [self.status_led_action])])
        else:
            self.status_led_action = None

        if self.firmware_version >= (1, 2, 1):
            reset = QAction('Reset', self)
            reset.triggered.connect(lambda: self.master.reset())
            self.set_actions([(0, None, [reset])])

        self.extension_type_preset = [
            None,  # None
            False,  # Chibi
            False,  # RS485
            False,  # WIFI
            False,  # Ethernet
            False
        ]  # WIFI 2.0
        self.update_extensions_in_device_info()

    def update_extensions_in_device_info(self):
        def is_present_async(present, extension_type, name):
            self.extension_type_preset[extension_type] = present

            if present:
                if self.device_info.extensions['ext0'] == None:
                    ext = 'ext0'
                elif self.device_info.extensions['ext1'] == None:
                    ext = 'ext1'
                else:
                    return  # This should never be the case

                self.device_info.extensions[ext] = infos.ExtensionInfo()
                self.device_info.extensions[ext].name = name
                self.device_info.extensions[
                    ext].extension_type = extension_type
                self.device_info.extensions[ext].position = ext
                self.device_info.extensions[ext].master_info = self.device_info
                infos.update_info(self.uid)

                if extension_type == self.master.EXTENSION_TYPE_WIFI2:
                    self.device_info.extensions[ext].url_part = 'wifi_v2'
                    # When WIFI2 extension firmware version is being requested the
                    # extension might still not be done with booting and thus the
                    # message won't be received by the extension. So we delay sending
                    # the request which gives enough time to the extension to finish
                    # booting. Note that this delay is only induced when there is a
                    # WIFI2 extension present.
                    self.wifi2_ext = ext
                    self.label_no_extension.setText(
                        'Waiting for WIFI Extension 2.0 firmware version...')
                    self.wifi2_get_firmware_version_timer.start(2000)

        def get_connection_type_async(connection_type):
            self.device_info.connection_type = connection_type
            infos.update_info(self.uid)

        if self.firmware_version >= (1, 1, 0):
            async_call(
                self.master.is_chibi_present, None, lambda p: is_present_async(
                    p, self.master.EXTENSION_TYPE_CHIBI, 'Chibi Extension'),
                self.increase_error_count)

        if self.firmware_version >= (1, 2, 0):
            async_call(
                self.master.is_rs485_present, None, lambda p: is_present_async(
                    p, self.master.EXTENSION_TYPE_RS485, 'RS485 Extension'),
                self.increase_error_count)

        if self.firmware_version >= (1, 3, 0):
            async_call(
                self.master.is_wifi_present, None, lambda p: is_present_async(
                    p, self.master.EXTENSION_TYPE_WIFI, 'WIFI Extension'),
                self.increase_error_count)

        if self.firmware_version >= (2, 1, 0):
            async_call(
                self.master.is_ethernet_present,
                None, lambda p: is_present_async(
                    p, self.master.EXTENSION_TYPE_ETHERNET,
                    'Ethernet Extension'), self.increase_error_count)

        if self.firmware_version >= (2, 4, 0):
            async_call(
                self.master.is_wifi2_present, None, lambda p: is_present_async(
                    p, self.master.EXTENSION_TYPE_WIFI2, 'WIFI Extension 2.0'),
                self.increase_error_count)
            async_call(self.master.get_connection_type, None,
                       get_connection_type_async, self.increase_error_count)

        async_call(lambda: None, None,
                   lambda: get_main_window().update_tree_view(), None)

    def get_wifi2_firmware_version_async(self, version):
        self.wifi2_firmware_version = version
        self.device_info.extensions[
            self.wifi2_ext].firmware_version_installed = version
        infos.update_info(self.uid)
        get_main_window().update_tree_view()  # FIXME: this is kind of a hack
        self.wifi2_present(True)

    def wifi2_get_firmware_version(self):
        if self.wifi2_firmware_version != None:
            return

        self.wifi2_get_firmware_version_timer.stop()
        async_call(self.master.get_wifi2_firmware_version, None,
                   self.get_wifi2_firmware_version_async,
                   self.increase_error_count)

    def wifi2_present(self, present):
        if present and self.wifi2_firmware_version != None and not self.check_extensions:
            wifi2 = Wifi2(self.wifi2_firmware_version, self)
            wifi2.start()
            self.extensions.append(wifi2)
            self.tab_widget.addTab(wifi2, 'WIFI 2.0')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def ethernet_present(self, present):
        if present:
            ethernet = Ethernet(self)
            ethernet.start()
            self.extensions.append(ethernet)
            self.tab_widget.addTab(ethernet, 'Ethernet')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def wifi_present(self, present):
        if present:
            wifi = Wifi(self)
            wifi.start()
            self.extensions.append(wifi)
            self.tab_widget.addTab(wifi, 'WIFI')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def rs485_present(self, present):
        if present:
            rs485 = RS485(self)
            rs485.start()
            self.extensions.append(rs485)
            self.tab_widget.addTab(rs485, 'RS485')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def chibi_present(self, present):
        if present:
            chibi = Chibi(self)
            chibi.start()
            self.extensions.append(chibi)
            self.tab_widget.addTab(chibi, 'Chibi')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def start(self):
        if self.firmware_version >= (2, 3, 2):
            async_call(self.master.is_status_led_enabled, None,
                       self.status_led_action.setChecked,
                       self.increase_error_count)

        if self.check_extensions:
            self.check_extensions = False

            self.chibi_present(
                self.extension_type_preset[self.master.EXTENSION_TYPE_CHIBI])
            self.rs485_present(
                self.extension_type_preset[self.master.EXTENSION_TYPE_RS485])
            self.wifi_present(
                self.extension_type_preset[self.master.EXTENSION_TYPE_WIFI])
            self.ethernet_present(self.extension_type_preset[
                self.master.EXTENSION_TYPE_ETHERNET])
            self.wifi2_present(
                self.extension_type_preset[self.master.EXTENSION_TYPE_WIFI2])

        self.update_timer.start(1000)

    def stop(self):
        self.update_timer.stop()

    def destroy(self):
        for extension in self.extensions:
            extension.destroy()
            extension.hide()
            extension.setParent(None)

        self.extensions = []

        if self.extension_type:
            self.extension_type.close()

    def is_hardware_version_relevant(self):
        return True

    @staticmethod
    def has_device_identifier(device_identifier):
        return device_identifier == BrickMaster.DEVICE_IDENTIFIER

    def update_data(self):
        async_call(self.master.get_stack_voltage, None,
                   self.get_stack_voltage_async, self.increase_error_count)
        async_call(self.master.get_stack_current, None,
                   self.get_stack_current_async, self.increase_error_count)

        for extension in self.extensions:
            extension.update_data()

    def get_stack_voltage_async(self, voltage):
        self.stack_voltage_label.setText('{:g} V'.format(
            round(voltage / 1000.0, 1)))

    def get_stack_current_async(self, current):
        self.stack_current_label.setText(format_current(current / 1000.0))

    def extension_clicked(self):
        if self.extension_type is None:
            self.extension_type = ExtensionType(self)

        self.extension_type.show()
Example #5
0
class Master(PluginBase, Ui_Master):
    def __init__(self, *args):
        PluginBase.__init__(self, BrickMaster, *args)

        self.setupUi(self)

        self.master = self.device

        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.update_data)

        self.extension_type = None

        self.extensions = []
        self.num_extensions = 0

        self.extension_label.setText("None Present")
        self.tab_widget.removeTab(0)
        self.tab_widget.hide()

        if self.firmware_version >= (1, 1, 0):
            self.check_extensions = True
            self.extension_type_button.clicked.connect(self.extension_clicked)
        else:
            self.check_extensions = False
            self.extension_type_button.setEnabled(False)

        if self.firmware_version >= (1, 2, 1):
            reset = QAction('Reset', self)
            reset.triggered.connect(lambda: self.master.reset())
            self.set_actions(reset)

        self.extension_type_preset = [None, False, False, False, False, False]
        self.update_extensions_in_device_info()

    def update_extensions_in_device_info(self):
        def is_present_async(present, extension_type, name):
            self.extension_type_preset[extension_type] = present

            if present:
                if self.device_info.extensions['ext0'] == None:
                    ext = 'ext0'
                elif self.device_info.extensions['ext1'] == None:
                    ext = 'ext1'
                else:
                    return # This should never be the case

                self.device_info.extensions[ext] = infos.ExtensionInfo()
                self.device_info.extensions[ext].name = name
                self.device_info.extensions[ext].extension_type = extension_type
                self.device_info.extensions[ext].position = ext
                self.device_info.extensions[ext].master_info = self.device_info
                infos.update_info(self.uid)

                def get_wifi2_firmware_version_async(version, ext):
                    self.device_info.extensions[ext].firmware_version_installed = version
                    infos.update_info(self.uid)

                if extension_type == self.master.EXTENSION_TYPE_WIFI2:
                    self.device_info.extensions[ext].url_part = 'wifi_v2'
                    async_call(self.master.get_wifi2_firmware_version, None, lambda v: get_wifi2_firmware_version_async(v, ext), self.increase_error_count)

        def get_connection_type_async(connection_type):
            self.device_info.connection_type = connection_type
            infos.update_info(self.uid)

        if self.firmware_version >= (1, 1, 0):
            async_call(self.master.is_chibi_present, None, lambda p: is_present_async(p, self.master.EXTENSION_TYPE_CHIBI, 'Chibi Extension'), self.increase_error_count)

        if self.firmware_version >= (1, 2, 0):
            async_call(self.master.is_rs485_present, None, lambda p: is_present_async(p, self.master.EXTENSION_TYPE_RS485, 'RS485 Extension'), self.increase_error_count)

        if self.firmware_version >= (1, 3, 0):
            async_call(self.master.is_wifi_present, None, lambda p: is_present_async(p, self.master.EXTENSION_TYPE_WIFI, 'WIFI Extension'), self.increase_error_count)

        if self.firmware_version >= (2, 1, 0):
            async_call(self.master.is_ethernet_present, None, lambda p: is_present_async(p, self.master.EXTENSION_TYPE_ETHERNET, 'Ethernet Extension'), self.increase_error_count)

        if self.firmware_version >= (2, 4, 0):
            async_call(self.master.is_wifi2_present, None, lambda p: is_present_async(p, self.master.EXTENSION_TYPE_WIFI2, 'WIFI Extension 2.0'), self.increase_error_count)
            async_call(self.master.get_connection_type, None, get_connection_type_async, self.increase_error_count)

        async_call(lambda: None, None, lambda: get_main_window().update_tree_view(), None)

    def is_wifi2_present_async(self, present):
        if present:
            wifi2 = Wifi2(self)
            self.extensions.append(wifi2)
            self.tab_widget.addTab(wifi2, 'WIFI 2.0')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def is_ethernet_present_async(self, present):
        if present:
            ethernet = Ethernet(self)
            self.extensions.append(ethernet)
            self.tab_widget.addTab(ethernet, 'Ethernet')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def is_wifi_present_async(self, present):
        if present:
            wifi = Wifi(self)
            self.extensions.append(wifi)
            self.tab_widget.addTab(wifi, 'WIFI')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def is_rs485_present_async(self, present):
        if present:
            rs485 = RS485(self)
            self.extensions.append(rs485)
            self.tab_widget.addTab(rs485, 'RS485')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def is_chibi_present_async(self, present):
        if present:
            chibi = Chibi(self)
            self.extensions.append(chibi)
            self.tab_widget.addTab(chibi, 'Chibi')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def start(self):
        if self.check_extensions:
            self.check_extensions = False

            self.is_chibi_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_CHIBI])
            self.is_rs485_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_RS485])
            self.is_wifi_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_WIFI])
            self.is_ethernet_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_ETHERNET])
            self.is_wifi2_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_WIFI2])

        self.update_timer.start(1000)

    def stop(self):
        self.update_timer.stop()

    def destroy(self):
        for extension in self.extensions:
            extension.destroy()
            extension.hide()
            extension.setParent(None)

        self.extensions = []

        if self.extension_type:
            self.extension_type.close()

    def is_hardware_version_relevant(self):
        return True

    def get_url_part(self):
        return 'master'

    @staticmethod
    def has_device_identifier(device_identifier):
        return device_identifier == BrickMaster.DEVICE_IDENTIFIER

    def update_data(self):
        async_call(self.master.get_stack_voltage, None, self.get_stack_voltage_async, self.increase_error_count)
        async_call(self.master.get_stack_current, None, self.get_stack_current_async, self.increase_error_count)

        for extension in self.extensions:
            extension.update_data()

    def get_stack_voltage_async(self, voltage):
        self.stack_voltage_label.setText('{:g} V'.format(round(voltage / 1000.0, 1)))

    def get_stack_current_async(self, current):
        self.stack_current_label.setText(format_current(current / 1000.0))

    def extension_clicked(self):
        if self.extension_type is None:
            self.extension_type = ExtensionType(self)

        self.extension_type.show()
Example #6
0
class Master(PluginBase, Ui_Master):
    def __init__(self, *args):
        PluginBase.__init__(self, BrickMaster, *args)

        self.setupUi(self)

        self.master = self.device
        
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.update_data)

        self.extension_type = None

        self.extensions = []
        self.num_extensions = 0

        self.extension_label.setText("None Present")
        self.tab_widget.removeTab(0)
        self.tab_widget.hide()

        if self.firmware_version >= (1, 1, 0):
            self.check_extensions = True
            self.extension_type_button.clicked.connect(self.extension_clicked)
        else:
            self.check_extensions = False
            self.extension_type_button.setEnabled(False)

        if self.firmware_version >= (1, 2, 1):
            reset = QAction('Reset', self)
            reset.triggered.connect(lambda: self.master.reset())
            self.set_actions(reset)

        self.extension_type_preset = [None, False, False, False, False, False]
        self.update_extensions_in_device_info()

    def update_extensions_in_device_info(self):
        def is_present(present, extension_type, name):
            self.extension_type_preset[extension_type] = present
            if present:
                if self.device_info.extensions['ext0'] == None:
                    self.device_info.extensions['ext0'] = infos.ExtensionInfo()
                    self.device_info.extensions['ext0'].name = name
                    self.device_info.extensions['ext0'].extension_type = extension_type
                elif self.device_info.extensions['ext1'] == None:
                    self.device_info.extensions['ext1'] = infos.ExtensionInfo()
                    self.device_info.extensions['ext1'].name = name
                    self.device_info.extensions['ext1'].extension_type = extension_type
                else:
                    pass # This should never be the case

        if self.firmware_version >= (1, 1, 0):
            async_call(self.master.is_chibi_present, None, lambda p: is_present(p, self.master.EXTENSION_TYPE_CHIBI, 'Chibi Extension'), self.increase_error_count)

        if self.firmware_version >= (1, 2, 0):
            async_call(self.master.is_rs485_present, None, lambda p: is_present(p, self.master.EXTENSION_TYPE_RS485, 'RS485 Extension'), self.increase_error_count)

        if self.firmware_version >= (1, 3, 0):
            async_call(self.master.is_wifi_present, None, lambda p: is_present(p, self.master.EXTENSION_TYPE_WIFI, 'WIFI Extension'), self.increase_error_count)

        if self.firmware_version >= (2, 1, 0):
            async_call(self.master.is_ethernet_present, None, lambda p: is_present(p, self.master.EXTENSION_TYPE_ETHERNET, 'Ethernet Extension'), self.increase_error_count)

        if self.firmware_version >= (2, 4, 0):
            async_call(self.master.is_wifi2_present, None, lambda p: is_present(p, self.master.EXTENSION_TYPE_WIFI2, 'WIFI Extension 2.0'), self.increase_error_count)

        async_call(lambda: None, None, lambda: get_main_window().update_tree_view(), None)

    def is_wifi2_present_async(self, present):
        if present:
            wifi2 = Wifi2(self)
            self.extensions.append(wifi2)
            self.tab_widget.addTab(wifi2, 'Wifi 2.0')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def is_ethernet_present_async(self, present):
        if present:
            ethernet = Ethernet(self)
            self.extensions.append(ethernet)
            self.tab_widget.addTab(ethernet, 'Ethernet')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def is_wifi_present_async(self, present):
        if present:
            wifi = Wifi(self)
            self.extensions.append(wifi)
            self.tab_widget.addTab(wifi, 'WIFI')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()
            
    def is_rs485_present_async(self, present):
        if present:
            rs485 = RS485(self)
            self.extensions.append(rs485)
            self.tab_widget.addTab(rs485, 'RS485')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()
            
    def is_chibi_present_async(self, present):
        if present:
            chibi = Chibi(self)
            self.extensions.append(chibi)
            self.tab_widget.addTab(chibi, 'Chibi')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def start(self):
        if self.check_extensions:
            self.check_extensions = False

            self.is_chibi_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_CHIBI])
            self.is_rs485_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_RS485])
            self.is_wifi_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_WIFI])
            self.is_ethernet_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_ETHERNET])
            self.is_wifi2_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_WIFI2])

        self.update_timer.start(1000)

    def stop(self):
        self.update_timer.stop()

    def destroy(self):
        for extension in self.extensions:
            extension.destroy()
            extension.hide()
            extension.setParent(None)

        self.extensions = []

        if self.extension_type:
            self.extension_type.close()

    def is_hardware_version_relevant(self):
        return True

    def get_url_part(self):
        return 'master'

    @staticmethod
    def has_device_identifier(device_identifier):
        return device_identifier == BrickMaster.DEVICE_IDENTIFIER
    
    def update_data(self):
        async_call(self.master.get_stack_voltage, None, self.stack_voltage_update, self.increase_error_count)
        async_call(self.master.get_stack_current, None, self.stack_current_update, self.increase_error_count)
        
        for extension in self.extensions:
            extension.update_data()
        
    def stack_voltage_update(self, sv):
        sv_str = "%gV"  % round(sv/1000.0, 1)
        self.stack_voltage_label.setText(sv_str)
        
    def stack_current_update(self, sc):
        if sc < 999:
            sc_str = "%gmA" % sc
        else:
            sc_str = "%gA" % round(sc/1000.0, 1)   
        self.stack_current_label.setText(sc_str)
        
    def extension_clicked(self):
        if self.extension_type is None:
            self.extension_type = ExtensionType(self)

        self.extension_type.show()
Example #7
0
class Master(PluginBase, Ui_Master):
    def __init__(self, ipcon, uid, version):
        PluginBase.__init__(self, ipcon, uid, 'Master Brick', version)
        
        self.setupUi(self)

        self.master = BrickMaster(uid, ipcon)
        self.device = self.master
        
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.update_data)

        self.extension_type = None

        self.extensions = []
        self.num_extensions = 0

        self.extension_label.setText("None Present")
        
        # Chibi widget
        if self.version >= (1, 1, 0):
            self.extension_type_button.pressed.connect(self.extension_pressed)
            async_call(self.master.is_chibi_present, None, self.is_chibi_present_async, self.increase_error_count)
        else:
            self.extension_type_button.setEnabled(False)
            
        # RS485 widget
        if self.version >= (1, 2, 0):
            async_call(self.master.is_rs485_present, None, self.is_rs485_present_async, self.increase_error_count)
                
        # Wifi widget
        if self.version >= (1, 3, 0):
            async_call(self.master.is_wifi_present, None, self.is_wifi_present_async, self.increase_error_count)
        
        # Ethernet widget
        if self.version >= (2, 1, 0):
            async_call(self.master.is_ethernet_present, None, self.is_ethernet_present_async, self.increase_error_count)

    def is_ethernet_present_async(self, present):
        if present:
            ethernet = Ethernet(self)
            self.extensions.append(ethernet)
            self.extension_layout.addWidget(ethernet)
            self.num_extensions += 1
            self.extension_label.setText("" + str(self.num_extensions) + " Present")

    def is_wifi_present_async(self, present):
        if present:
            wifi = Wifi(self)
            self.extensions.append(wifi)
            self.extension_layout.addWidget(wifi)
            self.num_extensions += 1
            self.extension_label.setText("" + str(self.num_extensions) + " Present")
            
    def is_rs485_present_async(self, present):
        if present:
            rs485 = RS485(self)
            self.extensions.append(rs485)
            self.extension_layout.addWidget(rs485)
            self.num_extensions += 1
            self.extension_label.setText("" + str(self.num_extensions) + " Present")
            
    def is_chibi_present_async(self, present):
        if present:
            chibi = Chibi(self)
            self.extensions.append(chibi)
            self.extension_layout.addWidget(chibi)
            self.num_extensions += 1
            self.extension_label.setText("" + str(self.num_extensions) + " Present")

    def start(self):
        self.update_timer.start(1000)

    def stop(self):
        self.update_timer.stop()

    def destroy(self):
        for extension in self.extensions:
            extension.destroy()

        if self.extension_type:
            self.extension_type.close()

    def has_reset_device(self):
        return self.version >= (1, 2, 1)

    def reset_device(self):
        if self.has_reset_device():
            self.master.reset()

    def is_brick(self):
        return True

    def is_hardware_version_relevant(self, hardware_version):
        return True

    def get_url_part(self):
        return 'master'

    @staticmethod
    def has_device_identifier(device_identifier):
        return device_identifier == BrickMaster.DEVICE_IDENTIFIER
    
    def update_data(self):
        async_call(self.master.get_stack_voltage, None, self.stack_voltage_update, self.increase_error_count)
        async_call(self.master.get_stack_current, None, self.stack_current_update, self.increase_error_count)
        
        for extension in self.extensions:
            extension.update_data()
        
    def stack_voltage_update(self, sv):
        sv_str = "%gV"  % round(sv/1000.0, 1)
        self.stack_voltage_label.setText(sv_str)
        
    def stack_current_update(self, sc):
        if sc < 999:
            sc_str = "%gmA" % sc
        else:
            sc_str = "%gA" % round(sc/1000.0, 1)   
        self.stack_current_label.setText(sc_str)
        
    def extension_pressed(self):
        if self.extension_type is None:
            self.extension_type = ExtensionType(self)

        self.extension_type.show()
Example #8
0
class Master(PluginBase, Ui_Master):
    def __init__(self, *args):
        PluginBase.__init__(self, BrickMaster, *args)

        self.setupUi(self)

        self.master = self.device
        
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.update_data)

        self.extension_type = None

        self.extensions = []
        self.num_extensions = 0

        self.extension_label.setText("None Present")
        self.tab_widget.removeTab(0)
        self.tab_widget.hide()

        if self.firmware_version >= (1, 1, 0):
            self.check_extensions = True
            self.extension_type_button.clicked.connect(self.extension_clicked)
        else:
            self.check_extensions = False
            self.extension_type_button.setEnabled(False)

        if self.firmware_version >= (1, 2, 1):
            reset = QAction('Reset', self)
            reset.triggered.connect(lambda: self.master.reset())
            self.set_actions(reset)

    def is_ethernet_present_async(self, present):
        if present:
            ethernet = Ethernet(self)
            self.extensions.append(ethernet)
            self.tab_widget.addTab(ethernet, 'Ethernet')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def is_wifi_present_async(self, present):
        if present:
            wifi = Wifi(self)
            self.extensions.append(wifi)
            self.tab_widget.addTab(wifi, 'WIFI')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()
            
    def is_rs485_present_async(self, present):
        if present:
            rs485 = RS485(self)
            self.extensions.append(rs485)
            self.tab_widget.addTab(rs485, 'RS485')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()
            
    def is_chibi_present_async(self, present):
        if present:
            chibi = Chibi(self)
            self.extensions.append(chibi)
            self.tab_widget.addTab(chibi, 'Chibi')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def start(self):
        if self.check_extensions:
            self.check_extensions = False

            # Chibi widget
            if self.firmware_version >= (1, 1, 0):
                async_call(self.master.is_chibi_present, None, self.is_chibi_present_async, self.increase_error_count)

            # RS485 widget
            if self.firmware_version >= (1, 2, 0):
                async_call(self.master.is_rs485_present, None, self.is_rs485_present_async, self.increase_error_count)

            # Wifi widget
            if self.firmware_version >= (1, 3, 0):
                async_call(self.master.is_wifi_present, None, self.is_wifi_present_async, self.increase_error_count)

            # Ethernet widget
            if self.firmware_version >= (2, 1, 0):
                async_call(self.master.is_ethernet_present, None, self.is_ethernet_present_async, self.increase_error_count)

        self.update_timer.start(1000)

    def stop(self):
        self.update_timer.stop()

    def destroy(self):
        for extension in self.extensions:
            extension.destroy()
            extension.hide()
            extension.setParent(None)

        self.extensions = []

        if self.extension_type:
            self.extension_type.close()

    def is_hardware_version_relevant(self):
        return True

    def get_url_part(self):
        return 'master'

    @staticmethod
    def has_device_identifier(device_identifier):
        return device_identifier == BrickMaster.DEVICE_IDENTIFIER
    
    def update_data(self):
        async_call(self.master.get_stack_voltage, None, self.stack_voltage_update, self.increase_error_count)
        async_call(self.master.get_stack_current, None, self.stack_current_update, self.increase_error_count)
        
        for extension in self.extensions:
            extension.update_data()
        
    def stack_voltage_update(self, sv):
        sv_str = "%gV"  % round(sv/1000.0, 1)
        self.stack_voltage_label.setText(sv_str)
        
    def stack_current_update(self, sc):
        if sc < 999:
            sc_str = "%gmA" % sc
        else:
            sc_str = "%gA" % round(sc/1000.0, 1)   
        self.stack_current_label.setText(sc_str)
        
    def extension_clicked(self):
        if self.extension_type is None:
            self.extension_type = ExtensionType(self)

        self.extension_type.show()
Example #9
0
class Master(PluginBase, Ui_Master):
    def __init__(self, *args):
        PluginBase.__init__(self, BrickMaster, *args)

        self.setupUi(self)

        self.master = self.device

        # the firmware version of a Brick can (under common circumstances) not
        # change during the lifetime of a Brick plugin. therefore, it's okay to
        # make final decisions based on it here
        self.has_status_led = self.firmware_version >= (2, 3, 2)

        self.update_timer = QTimer(self)
        self.update_timer.timeout.connect(self.update_data)

        self.extension_type = None

        self.extension_tabs = []

        self.wifi2_firmware_version = None

        self.wifi2_update_button = IconButton(
            QIcon(load_pixmap('update-icon-normal.png')),
            QIcon(load_pixmap('update-icon-hover.png')), self.tab_widget)
        self.wifi2_update_button.setToolTip('Update available')
        self.wifi2_update_button.clicked.connect(lambda: get_main_window(
        ).show_extension_update(self.device_info.uid))
        self.wifi2_update_button.hide()

        self.wifi2_tab_idx = None
        self.wifi2_start_done = False

        self.extension_label.setText("None Present")
        self.tab_widget.removeTab(0)
        self.tab_widget.hide()

        self.start_extensions = True
        self.extension_type_button.clicked.connect(self.extension_clicked)

        if self.has_status_led:
            self.status_led_action = QAction('Status LED', self)
            self.status_led_action.setCheckable(True)
            self.status_led_action.toggled.connect(
                lambda checked: self.master.enable_status_led()
                if checked else self.master.disable_status_led())
            self.set_configs([(0, None, [self.status_led_action])])
        else:
            self.status_led_action = None

        reset = QAction('Reset', self)
        reset.triggered.connect(self.master.reset)
        self.set_actions([(0, None, [reset])])

        self.extension_type_present = [
            None,  # None
            False,  # Chibi
            False,  # RS485
            False,  # WIFI
            False,  # Ethernet
            False
        ]  # WIFI 2.0

        self.query_extensions()

    def show_wifi_update(self):
        self.device_info.tab_window.show_update_tab_button(
            'WIFI Extension 2.0 Update available', lambda: get_main_window().
            show_extension_update(self.device_info.uid))

        if self.wifi2_tab_idx is not None:
            self.tab_widget.tabBar().setTabButton(self.wifi2_tab_idx,
                                                  QTabBar.LeftSide,
                                                  self.wifi2_update_button)
            self.wifi2_update_button.show()

            for ext in self.extension_tabs:
                if isinstance(ext, Wifi2):
                    ext.wifi_update_firmware_button.show()

    def hide_wifi_update(self):
        self.device_info.tab_window.hide_update_tab_button()

        if self.wifi2_tab_idx is not None:
            self.tab_widget.tabBar().setTabButton(self.wifi2_tab_idx,
                                                  QTabBar.LeftSide, None)

        if self.wifi2_update_button is not None:
            self.wifi2_update_button.hide()

            for ext in self.extension_tabs:
                if isinstance(ext, Wifi2):
                    ext.wifi_update_firmware_button.hide()

    def hide_master_update(self):
        self.device_info.tab_window.hide_update_tab_button()

        if self.device_info.tab_window is not None:
            self.device_info.tab_window.button_update.hide()

    def show_master_update(self):
        self.device_info.tab_window.show_update_tab_button(
            'Update available', lambda: get_main_window().show_brick_update(
                self.device_info.url_part))

        if self.device_info.tab_window is not None:
            self.device_info.tab_window.button_update.show()

    # overrides PluginBase.device_info_changed
    def device_info_changed(self, uid):
        if uid != self.device_info.uid:
            return

        if self.extension_type_present[self.master.EXTENSION_TYPE_WIFI2]:
            wifi_info = self.device_info.get_extension_info(
                self.master.EXTENSION_TYPE_WIFI2)

            if wifi_info is None:
                wifi_update_avail = False
            else:
                wifi_update_avail = wifi_info.firmware_version_installed != (
                    0, 0, 0
                ) and wifi_info.firmware_version_installed < wifi_info.firmware_version_latest
        else:
            wifi_update_avail = False

        brick_update_avail = self.device_info.firmware_version_installed < self.device_info.firmware_version_latest

        # As the master and wifi update share buttons, first hide all updates,
        # then show all updates. Control flow such as
        #   if master_update: show else: hide
        #   if wifi_update: show else: hide
        # would hide some of the controls for the master update if there is no wifi update.
        if not brick_update_avail:
            self.hide_master_update()

        if not wifi_update_avail:
            self.hide_wifi_update()

        if brick_update_avail:
            self.show_master_update()

        # Intentionally override possible Master Brick update notification: The Extension update is easier for users
        # so they are more likely to update at least the Extension. Also when the Extension is updated, device_info_changed
        # will be called again, then notifying the user of the Master Brick update.
        if wifi_update_avail:
            self.show_wifi_update()

    def query_extensions(self):
        def is_present_async(extension_type, name, present):
            self.extension_type_present[extension_type] = present

            if not present:
                return

            if self.device_info.extensions['ext0'] == None:
                ext = 'ext0'
            elif self.device_info.extensions['ext1'] == None:
                ext = 'ext1'
            else:
                return  # This should never be the case

            self.device_info.extensions[ext] = ExtensionInfo()
            self.device_info.extensions[ext].name = name
            self.device_info.extensions[ext].extension_type = extension_type
            self.device_info.extensions[ext].position = ext
            self.device_info.extensions[ext].master_info = self.device_info

            if extension_type == self.master.EXTENSION_TYPE_WIFI2:
                self.device_info.extensions[ext].url_part = 'wifi_v2'

                self.device_info.extensions[
                    ext].update_firmware_version_latest()

                label = QLabel(
                    'Waiting for WIFI Extension 2.0 firmware version...')
                label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)

                wrapper = QWidget()

                layout = QVBoxLayout(wrapper)
                layout.addWidget(label)
                layout.setContentsMargins(0, 0, 0, 0)

                self.wifi2_tab_idx = self.tab_widget.addTab(
                    wrapper, 'WIFI 2.0')

                # When WIFI2 extension firmware version is being requested the
                # extension might still not be done with booting and thus the
                # message won't be received by the extension. So we delay sending
                # the request which gives enough time to the extension to finish
                # booting. Note that this delay is only induced when there is a
                # WIFI2 extension present.
                async_call(self.master.get_wifi2_firmware_version,
                           None,
                           functools.partial(
                               self.get_wifi2_firmware_version_async, ext),
                           self.increase_error_count,
                           delay=2.0)

            inventory.sync()

        def get_connection_type_async(connection_type):
            self.device_info.connection_type = connection_type
            inventory.sync()

        async_call(
            self.master.is_chibi_present, None,
            functools.partial(is_present_async,
                              self.master.EXTENSION_TYPE_CHIBI,
                              'Chibi Extension'), self.increase_error_count)
        async_call(
            self.master.is_rs485_present, None,
            functools.partial(is_present_async,
                              self.master.EXTENSION_TYPE_RS485,
                              'RS485 Extension'), self.increase_error_count)
        async_call(
            self.master.is_wifi_present, None,
            functools.partial(is_present_async,
                              self.master.EXTENSION_TYPE_WIFI,
                              'WIFI Extension'), self.increase_error_count)

        if self.firmware_version >= (2, 1, 0):
            async_call(
                self.master.is_ethernet_present, None,
                functools.partial(is_present_async,
                                  self.master.EXTENSION_TYPE_ETHERNET,
                                  'Ethernet Extension'),
                self.increase_error_count)

        if self.firmware_version >= (2, 4, 0):
            async_call(
                self.master.is_wifi2_present, None,
                functools.partial(is_present_async,
                                  self.master.EXTENSION_TYPE_WIFI2,
                                  'WIFI Extension 2.0'),
                self.increase_error_count)
            async_call(self.master.get_connection_type, None,
                       get_connection_type_async, self.increase_error_count)

        async_call(lambda: None, None,
                   get_main_window().update_tree_view, None)

    def get_wifi2_firmware_version_async(self, ext, version):
        self.wifi2_firmware_version = version

        self.device_info.extensions[ext].firmware_version_installed = version

        # Start the plugin before sending the device_info_changed signal, so that
        # the slot registered to the signal will already see the plugin in self.extension_tabs.
        self.wifi2_start()

        inventory.sync()

    def wifi2_start(self):
        if self.wifi2_start_done or self.wifi2_firmware_version == None:
            return

        self.wifi2_start_done = True

        wifi2 = Wifi2(self.wifi2_firmware_version, self)
        wifi2.start()

        self.extension_tabs.append(wifi2)

        wrapper = self.tab_widget.widget(self.wifi2_tab_idx)
        wrapper.layout().replaceWidget(wrapper.layout().itemAt(0).widget(),
                                       wifi2)

    def add_non_wifi2_tab(self, widget, title):
        if self.wifi2_tab_idx != None:
            self.tab_widget.insertTab(self.wifi2_tab_idx, widget, title)
            self.wifi2_tab_idx += 1
        else:
            self.tab_widget.addTab(widget, title)

        self.tab_widget.setCurrentIndex(0)

    def ethernet_start(self):
        ethernet = Ethernet(self)
        ethernet.start()

        self.extension_tabs.append(ethernet)
        self.add_non_wifi2_tab(ethernet, 'Ethernet')

    def wifi_start(self):
        wifi = Wifi(self)
        wifi.start()

        self.extension_tabs.append(wifi)
        self.add_non_wifi2_tab(wifi, 'WIFI')

    def rs485_start(self):
        rs485 = RS485(self)
        rs485.start()

        self.extension_tabs.append(rs485)
        self.add_non_wifi2_tab(rs485, 'RS485')

    def chibi_start(self):
        chibi = Chibi(self)
        chibi.start()

        self.extension_tabs.append(chibi)
        self.add_non_wifi2_tab(chibi, 'Chibi')

    def start(self):
        if self.has_status_led:
            async_call(self.master.is_status_led_enabled, None,
                       self.status_led_action.setChecked,
                       self.increase_error_count)

        if self.start_extensions:
            self.start_extensions = False

            if self.extension_type_present[self.master.EXTENSION_TYPE_CHIBI]:
                self.chibi_start()

            if self.extension_type_present[self.master.EXTENSION_TYPE_RS485]:
                self.rs485_start()

            if self.extension_type_present[self.master.EXTENSION_TYPE_WIFI]:
                self.wifi_start()

            if self.extension_type_present[
                    self.master.EXTENSION_TYPE_ETHERNET]:
                self.ethernet_start()

            if self.extension_type_present[self.master.EXTENSION_TYPE_WIFI2]:
                self.wifi2_start()

            if self.tab_widget.count() > 0:
                self.tab_widget.show()
                self.extension_label.setText(
                    str(self.tab_widget.count()) + " Present")
                self.label_no_extension.hide()

        self.update_timer.start(1000)

    def show_extension(self, ext_idx):
        self.tab_widget.setCurrentIndex(ext_idx)

    def stop(self):
        self.update_timer.stop()

    def destroy(self):
        for ext in self.extension_tabs:
            ext.destroy()
            ext.hide()
            ext.setParent(None)

        self.extension_tabs = []

        if self.extension_type:
            self.extension_type.close()

    def is_hardware_version_relevant(self):
        return True

    @staticmethod
    def has_device_identifier(device_identifier):
        return device_identifier == BrickMaster.DEVICE_IDENTIFIER

    def update_data(self):
        async_call(self.master.get_stack_voltage, None,
                   self.get_stack_voltage_async, self.increase_error_count)
        async_call(self.master.get_stack_current, None,
                   self.get_stack_current_async, self.increase_error_count)

        for ext in self.extension_tabs:
            ext.update_data()

    def get_stack_voltage_async(self, voltage):
        self.stack_voltage_label.setText('{:g} V'.format(
            round(voltage / 1000.0, 1)))

    def get_stack_current_async(self, current):
        self.stack_current_label.setText(format_current(current / 1000.0))

    def extension_clicked(self):
        if self.extension_type is None:
            self.extension_type = ExtensionType(self)

        self.extension_type.show()
Example #10
0
class Master(PluginBase, Ui_Master):
    def __init__(self, *args):
        PluginBase.__init__(self, BrickMaster, *args)

        self.setupUi(self)

        self.master = self.device

        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.update_data)

        self.extension_type = None

        self.extensions = []
        self.num_extensions = 0

        self.extension_label.setText("None Present")
        self.tab_widget.removeTab(0)
        self.tab_widget.hide()

        if self.firmware_version >= (1, 1, 0):
            self.check_extensions = True
            self.extension_type_button.clicked.connect(self.extension_clicked)
        else:
            self.check_extensions = False
            self.extension_type_button.setEnabled(False)

        if self.firmware_version >= (1, 2, 1):
            reset = QAction("Reset", self)
            reset.triggered.connect(lambda: self.master.reset())
            self.set_actions(reset)

        self.extension_type_preset = [None, False, False, False, False, False]
        self.update_extensions_in_device_info()

    def update_extensions_in_device_info(self):
        def is_present(present, extension_type, name):
            self.extension_type_preset[extension_type] = present
            if present:
                if self.device_info.extensions["ext0"] == None:
                    self.device_info.extensions["ext0"] = infos.ExtensionInfo()
                    self.device_info.extensions["ext0"].name = name
                    self.device_info.extensions["ext0"].extension_type = extension_type
                elif self.device_info.extensions["ext1"] == None:
                    self.device_info.extensions["ext1"] = infos.ExtensionInfo()
                    self.device_info.extensions["ext1"].name = name
                    self.device_info.extensions["ext1"].extension_type = extension_type
                else:
                    pass  # This should never be the case

        if self.firmware_version >= (1, 1, 0):
            async_call(
                self.master.is_chibi_present,
                None,
                lambda p: is_present(p, self.master.EXTENSION_TYPE_CHIBI, "Chibi Extension"),
                self.increase_error_count,
            )

        if self.firmware_version >= (1, 2, 0):
            async_call(
                self.master.is_rs485_present,
                None,
                lambda p: is_present(p, self.master.EXTENSION_TYPE_RS485, "RS485 Extension"),
                self.increase_error_count,
            )

        if self.firmware_version >= (1, 3, 0):
            async_call(
                self.master.is_wifi_present,
                None,
                lambda p: is_present(p, self.master.EXTENSION_TYPE_WIFI, "WIFI Extension"),
                self.increase_error_count,
            )

        if self.firmware_version >= (2, 1, 0):
            async_call(
                self.master.is_ethernet_present,
                None,
                lambda p: is_present(p, self.master.EXTENSION_TYPE_ETHERNET, "Ethernet Extension"),
                self.increase_error_count,
            )

        if self.firmware_version >= (2, 4, 0):
            async_call(
                self.master.is_wifi2_present,
                None,
                lambda p: is_present(p, self.master.EXTENSION_TYPE_WIFI2, "WIFI Extension 2.0"),
                self.increase_error_count,
            )

        async_call(lambda: None, None, lambda: get_main_window().update_tree_view(), None)

    def is_wifi2_present_async(self, present):
        if present:
            wifi2 = Wifi2(self)
            self.extensions.append(wifi2)
            self.tab_widget.addTab(wifi2, "Wifi 2.0")
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def is_ethernet_present_async(self, present):
        if present:
            ethernet = Ethernet(self)
            self.extensions.append(ethernet)
            self.tab_widget.addTab(ethernet, "Ethernet")
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def is_wifi_present_async(self, present):
        if present:
            wifi = Wifi(self)
            self.extensions.append(wifi)
            self.tab_widget.addTab(wifi, "WIFI")
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def is_rs485_present_async(self, present):
        if present:
            rs485 = RS485(self)
            self.extensions.append(rs485)
            self.tab_widget.addTab(rs485, "RS485")
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def is_chibi_present_async(self, present):
        if present:
            chibi = Chibi(self)
            self.extensions.append(chibi)
            self.tab_widget.addTab(chibi, "Chibi")
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def start(self):
        if self.check_extensions:
            self.check_extensions = False

            self.is_chibi_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_CHIBI])
            self.is_rs485_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_RS485])
            self.is_wifi_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_WIFI])
            self.is_ethernet_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_ETHERNET])
            self.is_wifi2_present_async(self.extension_type_preset[self.master.EXTENSION_TYPE_WIFI2])

        self.update_timer.start(1000)

    def stop(self):
        self.update_timer.stop()

    def destroy(self):
        for extension in self.extensions:
            extension.destroy()
            extension.hide()
            extension.setParent(None)

        self.extensions = []

        if self.extension_type:
            self.extension_type.close()

    def is_hardware_version_relevant(self):
        return True

    def get_url_part(self):
        return "master"

    @staticmethod
    def has_device_identifier(device_identifier):
        return device_identifier == BrickMaster.DEVICE_IDENTIFIER

    def update_data(self):
        async_call(self.master.get_stack_voltage, None, self.stack_voltage_update, self.increase_error_count)
        async_call(self.master.get_stack_current, None, self.stack_current_update, self.increase_error_count)

        for extension in self.extensions:
            extension.update_data()

    def stack_voltage_update(self, sv):
        sv_str = "%gV" % round(sv / 1000.0, 1)
        self.stack_voltage_label.setText(sv_str)

    def stack_current_update(self, sc):
        if sc < 999:
            sc_str = "%gmA" % sc
        else:
            sc_str = "%gA" % round(sc / 1000.0, 1)
        self.stack_current_label.setText(sc_str)

    def extension_clicked(self):
        if self.extension_type is None:
            self.extension_type = ExtensionType(self)

        self.extension_type.show()
Example #11
0
class Master(PluginBase, Ui_Master):
    def __init__(self, *args):
        PluginBase.__init__(self, BrickMaster, *args)

        self.setupUi(self)

        self.master = self.device

        # the firmware version of a Brick can (under common circumstances) not
        # change during the lifetime of a Brick plugin. therefore, it's okay to
        # make final decisions based on it here
        self.has_status_led = self.firmware_version >= (2, 3, 2)

        self.update_timer = QTimer(self)
        self.update_timer.timeout.connect(self.update_data)

        self.extension_type = None

        self.extensions = []
        self.num_extensions = 0
        self.wifi2_ext = None
        self.wifi2_firmware_version = None
        self.wifi_update_button = IconButton(QIcon(load_pixmap('update-icon-normal.png')),
                                             QIcon(load_pixmap('update-icon-hover.png')),
                                             self.tab_widget)
        self.wifi_update_button.setToolTip('Update available')
        self.wifi_update_button.clicked.connect(lambda: get_main_window().show_extension_update(self.device_info.uid))
        self.wifi_update_button.hide()

        self.wifi_update_available = False
        self.wifi_tab_idx = None

        self.extension_label.setText("None Present")
        self.tab_widget.removeTab(0)
        self.tab_widget.hide()

        self.check_extensions = True
        self.extension_type_button.clicked.connect(self.extension_clicked)

        if self.has_status_led:
            self.status_led_action = QAction('Status LED', self)
            self.status_led_action.setCheckable(True)
            self.status_led_action.toggled.connect(lambda checked: self.master.enable_status_led() if checked else self.master.disable_status_led())
            self.set_configs([(0, None, [self.status_led_action])])
        else:
            self.status_led_action = None

        reset = QAction('Reset', self)
        reset.triggered.connect(self.master.reset)
        self.set_actions([(0, None, [reset])])

        self.extension_type_preset = [None,  # None
                                      False, # Chibi
                                      False, # RS485
                                      False, # WIFI
                                      False, # Ethernet
                                      False] # WIFI 2.0

        self.update_extensions_in_device_info()

    # overrides PluginBase.device_infos_changed
    def device_infos_changed(self, uid):
        if uid != self.device_info.uid:
            return

        if self.extension_type_preset[self.master.EXTENSION_TYPE_WIFI2]:
            try:
                wifi_info = next(ext for ext in self.device_info.extensions.values() if ext.extension_type == self.master.EXTENSION_TYPE_WIFI2)
                wifi_update_avail = wifi_info.firmware_version_installed != (0, 0, 0) and wifi_info.firmware_version_installed < wifi_info.firmware_version_latest
            except StopIteration:
                wifi_update_avail = False
        else:
            wifi_update_avail = False

        brick_update_avail = self.device_info.firmware_version_installed < self.device_info.firmware_version_latest

        tab_idx = get_main_window().tab_widget.indexOf(self.device_info.tab_window)

        if not brick_update_avail and not wifi_update_avail:
            if self.device_info.tab_window is not None:
                self.device_info.tab_window.button_update.hide()
            get_main_window().tab_widget.tabBar().setTabButton(tab_idx, QTabBar.RightSide, None)

            if self.wifi_tab_idx is not None:
                self.tab_widget.tabBar().setTabButton(self.wifi_tab_idx, QTabBar.LeftSide, None)
                if self.wifi_update_button is not None:
                    self.wifi_update_button.hide()
            return

        self.update_tab_button = IconButton(QIcon(load_pixmap('update-icon-normal.png')), QIcon(load_pixmap('update-icon-hover.png')))

        if brick_update_avail:
            if self.device_info.tab_window is not None:
                self.device_info.tab_window.button_update.show()
            self.update_tab_button.setToolTip('Update available')
            self.update_tab_button.clicked.connect(lambda: get_main_window().show_brick_update(self.device_info.url_part))

            if self.wifi_tab_idx is not None:
                self.tab_widget.tabBar().setTabButton(self.wifi_tab_idx, QTabBar.LeftSide, None)
                if self.wifi_update_button is not None:
                    self.wifi_update_button.hide()

        # Intentionally override possible Master Brick update notification: The Extension update is easier for users
        # so they are more likely to update at least the Extension. Also when the Extension is updated, device_infos_changed
        # will be called again, then notifying the user of the Master Brick update.
        if wifi_update_avail:
            self.update_tab_button.setToolTip('WIFI Extension 2.0 Update available')
            self.update_tab_button.clicked.connect(lambda: get_main_window().show_extension_update(self.device_info.uid))

            if self.wifi_tab_idx is not None:
                self.tab_widget.tabBar().setTabButton(self.wifi_tab_idx, QTabBar.LeftSide, self.wifi_update_button)
                self.wifi_update_button.show()


        get_main_window().tab_widget.tabBar().setTabButton(tab_idx, QTabBar.RightSide, self.update_tab_button)

    def update_extensions_in_device_info(self):
        def is_present_async(present, extension_type, name):
            self.extension_type_preset[extension_type] = present

            if present:
                if self.device_info.extensions['ext0'] == None:
                    ext = 'ext0'
                elif self.device_info.extensions['ext1'] == None:
                    ext = 'ext1'
                else:
                    return # This should never be the case

                self.device_info.extensions[ext] = infos.ExtensionInfo()
                self.device_info.extensions[ext].name = name
                self.device_info.extensions[ext].extension_type = extension_type
                self.device_info.extensions[ext].position = ext
                self.device_info.extensions[ext].master_info = self.device_info

                if extension_type == self.master.EXTENSION_TYPE_WIFI2:
                    self.device_info.extensions[ext].url_part = 'wifi_v2'
                    # When WIFI2 extension firmware version is being requested the
                    # extension might still not be done with booting and thus the
                    # message won't be received by the extension. So we delay sending
                    # the request which gives enough time to the extension to finish
                    # booting. Note that this delay is only induced when there is a
                    # WIFI2 extension present.
                    self.wifi2_ext = ext
                    self.label_no_extension.setText('Waiting for WIFI Extension 2.0 firmware version...')
                    async_call(self.master.get_wifi2_firmware_version, None, self.get_wifi2_firmware_version_async, self.increase_error_count, delay=2.0)

                infos.update_info(self.uid)

        def get_connection_type_async(connection_type):
            self.device_info.connection_type = connection_type
            infos.update_info(self.uid)

        async_call(self.master.is_chibi_present, None, lambda p: is_present_async(p, self.master.EXTENSION_TYPE_CHIBI, 'Chibi Extension'), self.increase_error_count)
        async_call(self.master.is_rs485_present, None, lambda p: is_present_async(p, self.master.EXTENSION_TYPE_RS485, 'RS485 Extension'), self.increase_error_count)
        async_call(self.master.is_wifi_present, None, lambda p: is_present_async(p, self.master.EXTENSION_TYPE_WIFI, 'WIFI Extension'), self.increase_error_count)

        if self.firmware_version >= (2, 1, 0):
            async_call(self.master.is_ethernet_present, None, lambda p: is_present_async(p, self.master.EXTENSION_TYPE_ETHERNET, 'Ethernet Extension'), self.increase_error_count)

        if self.firmware_version >= (2, 4, 0):
            async_call(self.master.is_wifi2_present, None, lambda p: is_present_async(p, self.master.EXTENSION_TYPE_WIFI2, 'WIFI Extension 2.0'), self.increase_error_count)
            async_call(self.master.get_connection_type, None, get_connection_type_async, self.increase_error_count)

        async_call(lambda: None, None, get_main_window().update_tree_view, None)

    def get_wifi2_firmware_version_async(self, version):
        self.wifi2_firmware_version = version
        self.device_info.extensions[self.wifi2_ext].firmware_version_installed = version
        infos.update_info(self.uid)
        get_main_window().update_tree_view() # FIXME: this is kind of a hack
        self.wifi2_present(True)

    def wifi2_present(self, present):
        if present and self.wifi2_firmware_version != None and not self.check_extensions:
            wifi2 = Wifi2(self.wifi2_firmware_version, self)
            wifi2.start()
            self.extensions.append(wifi2)
            self.wifi_tab_idx = self.tab_widget.addTab(wifi2, 'WIFI 2.0')
            self.device_infos_changed(self.device_info.uid) # Trigger device_infos_changed to show potential wifi updates.
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def ethernet_present(self, present):
        if present:
            ethernet = Ethernet(self)
            ethernet.start()
            self.extensions.append(ethernet)
            self.tab_widget.addTab(ethernet, 'Ethernet')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def wifi_present(self, present):
        if present:
            wifi = Wifi(self)
            wifi.start()
            self.extensions.append(wifi)
            self.tab_widget.addTab(wifi, 'WIFI')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def rs485_present(self, present):
        if present:
            rs485 = RS485(self)
            rs485.start()
            self.extensions.append(rs485)
            self.tab_widget.addTab(rs485, 'RS485')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def chibi_present(self, present):
        if present:
            chibi = Chibi(self)
            chibi.start()
            self.extensions.append(chibi)
            self.tab_widget.addTab(chibi, 'Chibi')
            self.tab_widget.show()
            self.num_extensions += 1
            self.extension_label.setText(str(self.num_extensions) + " Present")
            self.label_no_extension.hide()

    def start(self):
        if self.has_status_led:
            async_call(self.master.is_status_led_enabled, None, self.status_led_action.setChecked, self.increase_error_count)

        if self.check_extensions:
            self.check_extensions = False

            self.chibi_present(self.extension_type_preset[self.master.EXTENSION_TYPE_CHIBI])
            self.rs485_present(self.extension_type_preset[self.master.EXTENSION_TYPE_RS485])
            self.wifi_present(self.extension_type_preset[self.master.EXTENSION_TYPE_WIFI])
            self.ethernet_present(self.extension_type_preset[self.master.EXTENSION_TYPE_ETHERNET])
            self.wifi2_present(self.extension_type_preset[self.master.EXTENSION_TYPE_WIFI2])

        self.update_timer.start(1000)

    def stop(self):
        self.update_timer.stop()

    def destroy(self):
        for extension in self.extensions:
            extension.destroy()
            extension.hide()
            extension.setParent(None)

        self.extensions = []

        if self.extension_type:
            self.extension_type.close()

    def is_hardware_version_relevant(self):
        return True

    @staticmethod
    def has_device_identifier(device_identifier):
        return device_identifier == BrickMaster.DEVICE_IDENTIFIER

    def update_data(self):
        async_call(self.master.get_stack_voltage, None, self.get_stack_voltage_async, self.increase_error_count)
        async_call(self.master.get_stack_current, None, self.get_stack_current_async, self.increase_error_count)

        for extension in self.extensions:
            extension.update_data()

    def get_stack_voltage_async(self, voltage):
        self.stack_voltage_label.setText('{:g} V'.format(round(voltage / 1000.0, 1)))

    def get_stack_current_async(self, current):
        self.stack_current_label.setText(format_current(current / 1000.0))

    def extension_clicked(self):
        if self.extension_type is None:
            self.extension_type = ExtensionType(self)

        self.extension_type.show()