コード例 #1
0
ファイル: io4_v2.py プロジェクト: bmwiedemann/brickv
class IO4V2(COMCUPluginBase, Ui_IO4V2):
    def __init__(self, *args):
        COMCUPluginBase.__init__(self, BrickletIO4V2, *args)

        self.setupUi(self)

        self.io = self.device

        self.has_monoflop_abort_by_set_configuration = None

        self.io.set_response_expected(self.io.FUNCTION_SET_CONFIGURATION, True)

        self.cbe_value = CallbackEmulator(self.io.get_value, None,
                                          self.cb_value,
                                          self.increase_error_count)

        self.config_direction = [None] * 4
        self.config_value = [None] * 4

        self.lbl_st_ch_v = [
            self.lbl_st_ch0_v, self.lbl_st_ch1_v, self.lbl_st_ch2_v,
            self.lbl_st_ch3_v
        ]

        self.lbl_st_ch_d = [
            self.lbl_st_ch0_d, self.lbl_st_ch1_d, self.lbl_st_ch2_d,
            self.lbl_st_ch3_d
        ]

        self.lbl_st_ch_cfg = [
            self.lbl_st_ch0_cfg, self.lbl_st_ch1_cfg, self.lbl_st_ch2_cfg,
            self.lbl_st_ch3_cfg
        ]

        self.lbl_st_ch_monoflop_t = [
            self.lbl_st_ch0_monoflop_t, self.lbl_st_ch1_monoflop_t,
            self.lbl_st_ch2_monoflop_t, self.lbl_st_ch3_monoflop_t
        ]

        self.cbox_cfg_ch_dir.setItemData(0, self.io.DIRECTION_IN)
        self.cbox_cfg_ch_dir.setItemData(1, self.io.DIRECTION_OUT)

        self.cbox_cfg_ch_v.setItemData(0, True)
        self.cbox_cfg_ch_v.setItemData(1, False)

        self.btn_monoflop_go.clicked.connect(self.btn_monoflop_go_clicked)
        self.btn_cfg_ch_save.clicked.connect(self.btn_cfg_ch_save_clicked)
        self.cbox_cfg_ch.currentIndexChanged.connect(self.cbox_cfg_ch_changed)
        self.cbox_cfg_ch_dir.currentIndexChanged.connect(
            self.cbox_cfg_ch_dir_changed)

        self.monoflop_values = []
        self.monoflop_times = []

        for i in range(4):
            monoflop_value = QComboBox()
            monoflop_value.addItem('High', 1)
            monoflop_value.addItem('Low', 0)

            self.monoflop_values.append(monoflop_value)
            self.monoflop_value_stack.addWidget(monoflop_value)

            monoflop_time = QSpinBox()
            monoflop_time.setRange(1, (1 << 31) - 1)
            monoflop_time.setValue(1000)

            self.monoflop_times.append(monoflop_time)
            self.monoflop_time_stack.addWidget(monoflop_time)

        self.monoflop = Monoflop(
            self.io, [0, 1, 2, 3],
            self.monoflop_values,
            self.cb_value_change_by_monoflop,
            self.monoflop_times,
            self.lbl_st_ch_monoflop_t,
            self,
            handle_get_monoflop_invalid_parameter_as_abort=True)

    def get_configuration_async(self, channel, direction, value):
        self.config_direction[channel] = direction
        self.config_value[channel] = value

        if direction == self.io.DIRECTION_IN:
            self.lbl_st_ch_d[channel].setText('Input')

            if value:
                self.lbl_st_ch_cfg[channel].setText('Pull-Up')
            else:
                self.lbl_st_ch_cfg[channel].setText('Default')
        else:
            self.lbl_st_ch_d[channel].setText('Output')
            self.lbl_st_ch_cfg[channel].setText('-')

        if None not in self.config_direction:  # got all channel data
            self.cbox_cfg_ch_changed(self.cbox_cfg_ch.currentIndex())

    def start(self):
        # the firmware version might change between init and start of a Co-MCU
        # Bricklet plugin, because a Co-MCU Bricklet can be restarted without
        # recreating the plugin. therefore, the firmware version has to be checked
        # on every start
        self.has_monoflop_abort_by_set_configuration = self.firmware_version >= (
            2, 0, 3)

        self.config_direction = [None] * 4
        self.config_value = [None] * 4

        for channel in range(4):
            async_call(self.io.get_configuration,
                       channel,
                       self.get_configuration_async,
                       self.increase_error_count,
                       pass_arguments_to_result_callback=True,
                       expand_result_tuple_for_callback=True)

        self.cbe_value.set_period(50)

        self.monoflop.start()

    def stop(self):
        self.cbe_value.set_period(0)

        self.monoflop.stop()

    def destroy(self):
        pass

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

    def cb_value(self, value):
        for i in range(4):
            if value[i]:
                self.lbl_st_ch_v[i].setText('High')
            else:
                self.lbl_st_ch_v[i].setText('Low')

    def cb_value_change_by_monoflop(self, channel, value):
        if value:
            self.lbl_st_ch_v[channel].setText('High')
        else:
            self.lbl_st_ch_v[channel].setText('Low')

    def btn_monoflop_go_clicked(self):
        channel = self.cbox_cfg_ch.currentIndex()

        if channel < 0:
            return

        self.monoflop.trigger(channel)

    def set_configuration_async(self, channel, direction, value):
        if not self.has_monoflop_abort_by_set_configuration and direction == self.io.DIRECTION_OUT and self.monoflop.active(
                channel):
            # the set-configuration function in firmware version < 2.0.3 doesn't
            # abort monoflops, call the set-selected-value that does abort an active monoflop
            async_call(self.io.set_selected_value, (channel, value), None,
                       self.increase_error_count)

    def btn_cfg_ch_save_clicked(self):
        channel = self.cbox_cfg_ch.currentIndex()
        direction = self.cbox_cfg_ch_dir.currentData()
        value = self.cbox_cfg_ch_v.currentData()

        if channel < 0 or direction == None or value == None:
            return

        async_call(self.io.set_configuration, (channel, direction, value),
                   self.set_configuration_async,
                   self.increase_error_count,
                   pass_arguments_to_result_callback=True,
                   expand_arguments_tuple_for_callback=True)
        async_call(self.io.get_configuration,
                   channel,
                   self.get_configuration_async,
                   self.increase_error_count,
                   pass_arguments_to_result_callback=True,
                   expand_result_tuple_for_callback=True)

    def cbox_cfg_ch_changed(self, channel):
        if channel < 0:
            return

        direction = self.config_direction[channel]
        direction_index = self.cbox_cfg_ch_dir.findData(direction)

        self.cbox_cfg_ch_dir.setCurrentIndex(direction_index)
        self.cbox_cfg_ch_dir_changed(direction_index)

        value = self.config_value[channel]
        value_index = self.cbox_cfg_ch_v.findData(value)

        self.cbox_cfg_ch_v.setCurrentIndex(value_index)

        self.monoflop_time_stack.setCurrentIndex(channel)
        self.monoflop_value_stack.setCurrentIndex(channel)

        self.btn_monoflop_go.setEnabled(direction == self.io.DIRECTION_OUT)

    def cbox_cfg_ch_dir_changed(self, index):
        channel = self.cbox_cfg_ch.currentIndex()
        direction = self.cbox_cfg_ch_dir.currentData()

        if channel < 0 or direction == None:
            return

        self.cbox_cfg_ch_v.clear()

        if direction == self.io.DIRECTION_IN:
            self.lbl_cfg_ch_v.setText('Configuration:')
            self.cbox_cfg_ch_v.addItem('Pull-Up', True)
            self.cbox_cfg_ch_v.addItem('Default', False)
        else:
            self.lbl_cfg_ch_v.setText('Value:')
            self.cbox_cfg_ch_v.addItem('High', True)
            self.cbox_cfg_ch_v.addItem('Low', False)

        value = self.config_value[channel]
        value_index = self.cbox_cfg_ch_v.findData(value)

        self.cbox_cfg_ch_v.setCurrentIndex(value_index)
コード例 #2
0
class IndustrialDigitalOut4V2(COMCUPluginBase, Ui_IndustrialDigitalOut4V2):
    def __init__(self, *args):
        COMCUPluginBase.__init__(self, BrickletIndustrialDigitalOut4V2, *args)

        self.setupUi(self)

        self.ido4 = self.device

        self.has_monoflop_abort = None

        self.pixmap_low = load_masked_pixmap('plugin_system/plugins/industrial_digital_out_4_v2/ido4_low.bmp')
        self.pixmap_high = load_masked_pixmap('plugin_system/plugins/industrial_digital_out_4_v2/ido4_high.bmp')

        self.btn_v_c = [self.btn_v_c0, self.btn_v_c1, self.btn_v_c2, self.btn_v_c3]
        self.lbl_s_i_c = [self.lbl_s_i_c0, self.lbl_s_i_c1, self.lbl_s_i_c2, self.lbl_s_i_c3]
        self.cbox_clc_c = [self.cbox_clc_c0, self.cbox_clc_c1, self.cbox_clc_c2, self.cbox_clc_c3]

        # Set initial channel status icon
        for lbl in self.lbl_s_i_c:
            lbl.setPixmap(self.pixmap_low)

        # Register value toggle button slots
        for c, b in enumerate(self.btn_v_c):
            b.clicked.connect(functools.partial(self.btn_v_c_clicked, c))

        # Monoflop
        self.cbox_m_c.currentIndexChanged.connect(self.cbox_m_c_changed)
        self.btn_m_go.clicked.connect(self.btn_m_go_clicked)

        self.monoflop_values = []
        self.monoflop_times = []

        for i in range(4):
            self.cbox_m_c.setItemData(i, i)

            monoflop_value = QComboBox()
            monoflop_value.addItem('High', True)
            monoflop_value.addItem('Low', False)

            self.monoflop_values.append(monoflop_value)
            self.monoflop_value_stack.addWidget(monoflop_value)

            monoflop_time = QSpinBox()
            monoflop_time.setRange(1, (1 << 31) - 1)
            monoflop_time.setValue(1000)

            self.monoflop_times.append(monoflop_time)
            self.monoflop_time_stack.addWidget(monoflop_time)

        self.monoflop = Monoflop(self.ido4,
                                 [0, 1, 2, 3],
                                 self.monoflop_values,
                                 self.cb_value_change_by_monoflop,
                                 self.monoflop_times,
                                 None,
                                 self)

        # Channel status LED config
        self.cbox_clc_c0.currentIndexChanged.connect(self.cbox_clc_c0_changed)
        self.cbox_clc_c1.currentIndexChanged.connect(self.cbox_clc_c1_changed)
        self.cbox_clc_c2.currentIndexChanged.connect(self.cbox_clc_c2_changed)
        self.cbox_clc_c3.currentIndexChanged.connect(self.cbox_clc_c3_changed)

    def get_value_async(self, value):
        for i, b in enumerate(self.btn_v_c):
            if value[i]:
                b.setText('Set Low')
                self.lbl_s_i_c[i].setPixmap(self.pixmap_high)
            else:
                b.setText('Set High')
                self.lbl_s_i_c[i].setPixmap(self.pixmap_low)

    def get_channel_led_config_async(self, channel, config):
        if channel == 0:
            self.cbox_clc_c0.setCurrentIndex(config)
        elif channel == 1:
            self.cbox_clc_c1.setCurrentIndex(config)
        elif channel == 2:
            self.cbox_clc_c2.setCurrentIndex(config)
        elif channel == 3:
            self.cbox_clc_c3.setCurrentIndex(config)

    def cbox_clc_c0_changed(self, config):
        self.ido4.set_channel_led_config(0, config)

    def cbox_clc_c1_changed(self, config):
        self.ido4.set_channel_led_config(1, config)

    def cbox_clc_c2_changed(self, config):
        self.ido4.set_channel_led_config(2, config)

    def cbox_clc_c3_changed(self, config):
        self.ido4.set_channel_led_config(3, config)

    def start(self):
        # the firmware version might change between init and start of a Co-MCU
        # Bricklet plugin, because a Co-MCU Bricklet can be restarted without
        # recreating the plugin. therefore, the firmware version has to be checked
        # on every start
        self.has_monoflop_abort = self.firmware_version >= (2, 0, 1)

        async_call(self.ido4.get_value, None, self.get_value_async, self.increase_error_count)

        for channel in range(4):
            async_call(self.ido4.get_channel_led_config, channel, self.get_channel_led_config_async, self.increase_error_count,
                       pass_arguments_to_result_callback=True)

        self.monoflop.start()

    def stop(self):
        self.monoflop.stop()

    def destroy(self):
        pass

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

    def btn_v_c_clicked(self, channel):
        value = 'High' in self.btn_v_c[channel].text().replace('&', '')

        if value:
            self.btn_v_c[channel].setText('Set Low')
            self.lbl_s_i_c[channel].setPixmap(self.pixmap_high)
        else:
            self.btn_v_c[channel].setText('Set High')
            self.lbl_s_i_c[channel].setPixmap(self.pixmap_low)

        if not self.has_monoflop_abort and self.monoflop.active(channel):
            # abuse monoflop to set selected value while also aborting an active
            # monoflop, because firmware version < 2.0.1 doesn't abort an active
            # monoflop if the set-value or set-selected-value function is called.
            # this workaround has the disadvantage of shortly inverting the
            # output value before settling on the requested value. that's why it
            # is only used if a monoflop is really active
            async_call(self.ido4.set_monoflop, (channel, not value, 0), None, self.increase_error_count)
        else:
            async_call(self.ido4.set_selected_value, (channel, value), None, self.increase_error_count)

    def cb_value_change_by_monoflop(self, channel, value):
        if value:
            self.btn_v_c[channel].setText('Set Low')
            self.lbl_s_i_c[channel].setPixmap(self.pixmap_high)
        else:
            self.btn_v_c[channel].setText('Set High')
            self.lbl_s_i_c[channel].setPixmap(self.pixmap_low)

    def cbox_m_c_changed(self):
        channel = self.cbox_m_c.currentIndex()

        if channel < 0:
            return

        self.monoflop_time_stack.setCurrentIndex(channel)
        self.monoflop_value_stack.setCurrentIndex(channel)

    def btn_m_go_clicked(self):
        channel = self.cbox_m_c.currentIndex()

        if channel < 0:
            return

        self.monoflop.trigger(channel)
コード例 #3
0
class IndustrialDigitalOut4V2(COMCUPluginBase, Ui_IndustrialDigitalOut4V2):
    def __init__(self, *args):
        COMCUPluginBase.__init__(self, BrickletIndustrialDigitalOut4V2, *args)

        self.setupUi(self)

        self.ido4 = self.device

        self.has_monoflop_abort = None

        self.pixmap_low = load_masked_pixmap(
            'plugin_system/plugins/industrial_digital_out_4_v2/ido4_low.bmp')
        self.pixmap_high = load_masked_pixmap(
            'plugin_system/plugins/industrial_digital_out_4_v2/ido4_high.bmp')

        self.btn_v_c = [
            self.btn_v_c0, self.btn_v_c1, self.btn_v_c2, self.btn_v_c3
        ]
        self.lbl_s_i_c = [
            self.lbl_s_i_c0, self.lbl_s_i_c1, self.lbl_s_i_c2, self.lbl_s_i_c3
        ]
        self.cbox_clc_c = [
            self.cbox_clc_c0, self.cbox_clc_c1, self.cbox_clc_c2,
            self.cbox_clc_c3
        ]

        # Set initial channel status icon
        for lbl in self.lbl_s_i_c:
            lbl.setPixmap(self.pixmap_low)

        # Register value toggle button slots
        for c, b in enumerate(self.btn_v_c):
            b.clicked.connect(functools.partial(self.btn_v_c_clicked, c))

        # Monoflop
        self.cbox_m_c.currentIndexChanged.connect(self.cbox_m_c_changed)
        self.btn_m_go.clicked.connect(self.btn_m_go_clicked)

        self.monoflop_values = []
        self.monoflop_times = []

        for i in range(4):
            self.cbox_m_c.setItemData(i, i)

            monoflop_value = QComboBox()
            monoflop_value.addItem('High', True)
            monoflop_value.addItem('Low', False)

            self.monoflop_values.append(monoflop_value)
            self.monoflop_value_stack.addWidget(monoflop_value)

            monoflop_time = QDoubleSpinBox()

            self.monoflop_times.append(monoflop_time)
            self.monoflop_time_stack.addWidget(monoflop_time)

        self.monoflop = Monoflop(self.ido4, [0, 1, 2, 3], self.monoflop_values,
                                 self.cb_value_change_by_monoflop,
                                 self.monoflop_times, None, self)

        # Channel status LED config
        self.cbox_clc_c0.currentIndexChanged.connect(self.cbox_clc_c0_changed)
        self.cbox_clc_c1.currentIndexChanged.connect(self.cbox_clc_c1_changed)
        self.cbox_clc_c2.currentIndexChanged.connect(self.cbox_clc_c2_changed)
        self.cbox_clc_c3.currentIndexChanged.connect(self.cbox_clc_c3_changed)

    def get_value_async(self, value):
        for i, b in enumerate(self.btn_v_c):
            if value[i]:
                b.setText('Set Low')
                self.lbl_s_i_c[i].setPixmap(self.pixmap_high)
            else:
                b.setText('Set High')
                self.lbl_s_i_c[i].setPixmap(self.pixmap_low)

    def get_channel_led_config_async(self, channel, config):
        if channel == 0:
            self.cbox_clc_c0.setCurrentIndex(config)
        elif channel == 1:
            self.cbox_clc_c1.setCurrentIndex(config)
        elif channel == 2:
            self.cbox_clc_c2.setCurrentIndex(config)
        elif channel == 3:
            self.cbox_clc_c3.setCurrentIndex(config)

    def cbox_clc_c0_changed(self, config):
        self.ido4.set_channel_led_config(0, config)

    def cbox_clc_c1_changed(self, config):
        self.ido4.set_channel_led_config(1, config)

    def cbox_clc_c2_changed(self, config):
        self.ido4.set_channel_led_config(2, config)

    def cbox_clc_c3_changed(self, config):
        self.ido4.set_channel_led_config(3, config)

    def start(self):
        # the firmware version might change between init and start of a Co-MCU
        # Bricklet plugin, because a Co-MCU Bricklet can be restarted without
        # recreating the plugin. therefore, the firmware version has to be checked
        # on every start
        self.has_monoflop_abort = self.firmware_version >= (2, 0, 1)

        async_call(self.ido4.get_value, None, self.get_value_async,
                   self.increase_error_count)

        for channel in range(4):
            async_call(self.ido4.get_channel_led_config,
                       channel,
                       self.get_channel_led_config_async,
                       self.increase_error_count,
                       pass_arguments_to_result_callback=True)

        self.monoflop.start()

    def stop(self):
        self.monoflop.stop()

    def destroy(self):
        pass

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

    def btn_v_c_clicked(self, channel):
        value = 'High' in self.btn_v_c[channel].text().replace('&', '')

        if value:
            self.btn_v_c[channel].setText('Set Low')
            self.lbl_s_i_c[channel].setPixmap(self.pixmap_high)
        else:
            self.btn_v_c[channel].setText('Set High')
            self.lbl_s_i_c[channel].setPixmap(self.pixmap_low)

        if not self.has_monoflop_abort and self.monoflop.active(channel):
            # abuse monoflop to set selected value while also aborting an active
            # monoflop, because firmware version < 2.0.1 doesn't abort an active
            # monoflop if the set-value or set-selected-value function is called.
            # this workaround has the disadvantage of shortly inverting the
            # output value before settling on the requested value. that's why it
            # is only used if a monoflop is really active
            async_call(self.ido4.set_monoflop, (channel, not value, 0), None,
                       self.increase_error_count)
        else:
            async_call(self.ido4.set_selected_value, (channel, value), None,
                       self.increase_error_count)

    def cb_value_change_by_monoflop(self, channel, value):
        if value:
            self.btn_v_c[channel].setText('Set Low')
            self.lbl_s_i_c[channel].setPixmap(self.pixmap_high)
        else:
            self.btn_v_c[channel].setText('Set High')
            self.lbl_s_i_c[channel].setPixmap(self.pixmap_low)

    def cbox_m_c_changed(self):
        channel = self.cbox_m_c.currentIndex()

        if channel < 0:
            return

        self.monoflop_time_stack.setCurrentIndex(channel)
        self.monoflop_value_stack.setCurrentIndex(channel)

    def btn_m_go_clicked(self):
        channel = self.cbox_m_c.currentIndex()

        if channel < 0:
            return

        self.monoflop.trigger(channel)