class SolidStateRelayV2(COMCUPluginBase, Ui_SolidStateRelayV2): def __init__(self, *args): COMCUPluginBase.__init__(self, BrickletSolidStateRelayV2, *args) self.setupUi(self) self.ssr = self.device self.state_combobox.setItemData(0, True) self.state_combobox.setItemData(1, False) self.monoflop = Monoflop(self.ssr, None, self.state_combobox, self.cb_state_change_by_monoflop, self.time_spinbox, None, self) self.ssr_button.clicked.connect(self.ssr_clicked) self.go_button.clicked.connect(self.go_clicked) self.a_pixmap = load_masked_pixmap( 'plugin_system/plugins/solid_state_relay/relay_a.bmp') self.b_pixmap = load_masked_pixmap( 'plugin_system/plugins/solid_state_relay/relay_b.bmp') def get_state_async(self, state): width = self.ssr_button.width() if self.ssr_button.minimumWidth() < width: self.ssr_button.setMinimumWidth(width) if state: self.ssr_button.setText('Switch Off') self.ssr_image.setPixmap(self.a_pixmap) else: self.ssr_button.setText('Switch On') self.ssr_image.setPixmap(self.b_pixmap) def start(self): async_call(self.ssr.get_state, None, self.get_state_async, self.increase_error_count) self.monoflop.start() def stop(self): self.monoflop.stop() def destroy(self): pass @staticmethod def has_device_identifier(device_identifier): return device_identifier == BrickletSolidStateRelayV2.DEVICE_IDENTIFIER def ssr_clicked(self): width = self.ssr_button.width() if self.ssr_button.minimumWidth() < width: self.ssr_button.setMinimumWidth(width) state = 'On' in self.ssr_button.text().replace('&', '') if state: self.ssr_button.setText('Switch Off') self.ssr_image.setPixmap(self.a_pixmap) else: self.ssr_button.setText('Switch On') self.ssr_image.setPixmap(self.b_pixmap) async_call(self.ssr.set_state, state, None, self.increase_error_count) def go_clicked(self): self.monoflop.trigger() def cb_state_change_by_monoflop(self, state): if state: self.ssr_button.setText('Switch Off') self.ssr_image.setPixmap(self.a_pixmap) else: self.ssr_button.setText('Switch On') self.ssr_image.setPixmap(self.b_pixmap)
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)
class IndustrialDigitalOut4(PluginBase, Ui_IndustrialDigitalOut4): def __init__(self, *args): PluginBase.__init__(self, BrickletIndustrialDigitalOut4, *args) self.setupUi(self) self.ido4 = self.device self.gnd_pixmap = load_masked_pixmap('plugin_system/plugins/industrial_digital_out_4/dio_gnd.bmp') self.vcc_pixmap = load_masked_pixmap('plugin_system/plugins/industrial_digital_out_4/dio_vcc.bmp') self.pin_buttons = [self.b0, self.b1, self.b2, self.b3, self.b4, self.b5, self.b6, self.b7, self.b8, self.b9, self.b10, self.b11, self.b12, self.b13, self.b14, self.b15] self.pin_button_icons = [self.b0_icon, self.b1_icon, self.b2_icon, self.b3_icon, self.b4_icon, self.b5_icon, self.b6_icon, self.b7_icon, self.b8_icon, self.b9_icon, self.b10_icon, self.b11_icon, self.b12_icon, self.b13_icon, self.b14_icon, self.b15_icon] self.pin_button_labels = [self.b0_label, self.b1_label, self.b2_label, self.b3_label, self.b4_label, self.b5_label, self.b6_label, self.b7_label, self.b8_label, self.b9_label, self.b10_label, self.b11_label, self.b12_label, self.b13_label, self.b14_label, self.b15_label] self.groups = [self.group0, self.group1, self.group2, self.group3] for icon in self.pin_button_icons: icon.setPixmap(self.gnd_pixmap) icon.show() self.lines = [[self.line0, self.line0a, self.line0b, self.line0c], [self.line1, self.line1a, self.line1b, self.line1c], [self.line2, self.line2a, self.line2b, self.line2c], [self.line3, self.line3a, self.line3b, self.line3c]] for lines in self.lines: for line in lines: line.setVisible(False) self.available_ports = 0 for i in range(len(self.pin_buttons)): self.pin_buttons[i].clicked.connect(functools.partial(self.pin_button_clicked, i)) self.monoflop_states = [] self.monoflop_times = [] for i in range(16): monoflop_state = QComboBox() monoflop_state.addItem('High', 1) monoflop_state.addItem('Low', 0) self.monoflop_states.append(monoflop_state) self.monoflop_state_stack.addWidget(monoflop_state) 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, list(range(16)), self.monoflop_states, self.cb_state_change_by_monoflop, self.monoflop_times, None, self, setter_uses_bitmasks=True, callback_uses_bitmasks=True, handle_get_monoflop_invalid_parameter_as_abort=True) self.set_group.clicked.connect(self.set_group_clicked) self.monoflop_pin.currentIndexChanged.connect(self.monoflop_pin_changed) self.monoflop_go.clicked.connect(self.monoflop_go_clicked) def start(self): self.reconfigure_everything() def stop(self): self.monoflop.stop() def destroy(self): pass @staticmethod def has_device_identifier(device_identifier): return device_identifier == BrickletIndustrialDigitalOut4.DEVICE_IDENTIFIER def get_value_async(self, value_mask): for pin in range(16): if value_mask & (1 << pin): self.pin_buttons[pin].setText('Switch Low') self.pin_button_icons[pin].setPixmap(self.vcc_pixmap) else: self.pin_buttons[pin].setText('Switch High') self.pin_button_icons[pin].setPixmap(self.gnd_pixmap) def get_group_async(self, group): for i in range(4): if group[i] == 'n': self.groups[i].setCurrentIndex(0) else: item = 'Port ' + group[i].upper() index = self.groups[i].findText(item, Qt.MatchStartsWith) if index == -1: self.groups[i].setCurrentIndex(0) else: self.groups[i].setCurrentIndex(index) self.monoflop_pin.clear() if group[0] == 'n' and group[1] == 'n' and group[2] == 'n' and group[3] == 'n': self.show_buttons(0) self.hide_buttons(1) self.hide_buttons(2) self.hide_buttons(3) for pin in range(4): self.monoflop_pin.addItem('Pin {0}'.format(pin), pin) else: for i in range(4): if group[i] == 'n': self.hide_buttons(i) else: for j in range(4): pin = i * 4 + j self.monoflop_pin.addItem('Pin {0}'.format(pin), pin) self.show_buttons(i) self.monoflop_pin.setCurrentIndex(0) async_call(self.ido4.get_value, None, self.get_value_async, self.increase_error_count) self.monoflop.start() def get_available_for_group_aysnc(self, available_ports): self.available_ports = available_ports for i in range(4): self.groups[i].clear() self.groups[i].addItem('Off') for j in range(4): if self.available_ports & (1 << j): item = 'Port ' + chr(ord('A') + j) self.groups[i].addItem(item) async_call(self.ido4.get_group, None, self.get_group_async, self.increase_error_count) def reconfigure_everything(self): async_call(self.ido4.get_available_for_group, None, self.get_available_for_group_aysnc, self.increase_error_count) def show_buttons(self, num): for i in range(num * 4, (num + 1) * 4): self.pin_buttons[i].setVisible(True) self.pin_button_icons[i].setVisible(True) self.pin_button_labels[i].setVisible(True) for line in self.lines[num]: line.setVisible(True) def hide_buttons(self, num): for i in range(num * 4, (num + 1) * 4): self.pin_buttons[i].setVisible(False) self.pin_button_icons[i].setVisible(False) self.pin_button_labels[i].setVisible(False) for line in self.lines[num]: line.setVisible(False) def set_group_clicked(self): group = ['n', 'n', 'n', 'n'] for i in range(len(self.groups)): text = self.groups[i].currentText() if 'Port A' in text: group[i] = 'a' elif 'Port B' in text: group[i] = 'b' elif 'Port C' in text: group[i] = 'c' elif 'Port D' in text: group[i] = 'd' if group != ['n', 'n', 'n', 'n']: abort_group = group else: abort_group = ['x', 'n', 'n', 'n'] for i, g in enumerate(abort_group): if g == 'n': for j in range(4): pin = i * 4 + j # changing grouping doesn't abort active monoflops. manually # abort tracking for monoflops that are out of scope now self.monoflop.abort_tracking(pin) self.ido4.set_group(group) self.reconfigure_everything() def pin_button_clicked(self, button): selection = 1 << button value = 0 if 'High' in self.pin_buttons[button].text().replace('&', ''): value |= 1 << button self.pin_buttons[button].setText('Switch Low') self.pin_button_icons[button].setPixmap(self.vcc_pixmap) else: self.pin_buttons[button].setText('Switch High') self.pin_button_icons[button].setPixmap(self.gnd_pixmap) async_call(self.ido4.set_selected_values, (selection, value), None, self.increase_error_count) def cb_state_change_by_monoflop(self, pin, state): if state: self.pin_buttons[pin].setText('Switch Low') self.pin_button_icons[pin].setPixmap(self.vcc_pixmap) else: self.pin_buttons[pin].setText('Switch High') self.pin_button_icons[pin].setPixmap(self.gnd_pixmap) def monoflop_pin_changed(self): pin = self.monoflop_pin.currentData() if pin == None: return self.monoflop_time_stack.setCurrentIndex(pin) self.monoflop_state_stack.setCurrentIndex(pin) def monoflop_go_clicked(self): pin = self.monoflop_pin.currentData() if pin == None: return self.monoflop.trigger(pin)
class IndustrialQuadRelayV2(COMCUPluginBase, Ui_IndustrialQuadRelayV2): def __init__(self, *args): COMCUPluginBase.__init__(self, BrickletIndustrialQuadRelayV2, *args) self.setupUi(self) self.iqr = self.device self.open_pixmap = load_masked_pixmap( 'plugin_system/plugins/industrial_quad_relay/relay_open.bmp') self.close_pixmap = load_masked_pixmap( 'plugin_system/plugins/industrial_quad_relay/relay_close.bmp') self.relay_buttons = [self.b0, self.b1, self.b2, self.b3] self.relay_button_icons = [ self.b0_icon, self.b1_icon, self.b2_icon, self.b3_icon ] self.relay_button_labels = [ self.b0_label, self.b1_label, self.b2_label, self.b3_label ] for icon in self.relay_button_icons: icon.setPixmap(self.open_pixmap) icon.show() for i in range(len(self.relay_buttons)): self.relay_buttons[i].clicked.connect( functools.partial(self.relay_button_clicked, i)) self.monoflop_values = [] self.monoflop_times = [] for i in range(4): self.monoflop_channel.setItemData(i, i) monoflop_value = QComboBox() monoflop_value.addItem('On', True) monoflop_value.addItem('Off', 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.iqr, [0, 1, 2, 3], self.monoflop_values, self.cb_value_change_by_monoflop, self.monoflop_times, None, self) self.monoflop_channel.currentIndexChanged.connect( self.monoflop_channel_changed) self.monoflop_go.clicked.connect(self.monoflop_go_clicked) self.cbox_cs0_cfg.currentIndexChanged.connect( self.cbox_cs0_cfg_changed) self.cbox_cs1_cfg.currentIndexChanged.connect( self.cbox_cs1_cfg_changed) self.cbox_cs2_cfg.currentIndexChanged.connect( self.cbox_cs2_cfg_changed) self.cbox_cs3_cfg.currentIndexChanged.connect( self.cbox_cs3_cfg_changed) def get_value_async(self, value): for button in range(4): if value[button]: self.relay_buttons[button].setText('Switch Off') self.relay_button_icons[button].setPixmap(self.close_pixmap) else: self.relay_buttons[button].setText('Switch On') self.relay_button_icons[button].setPixmap(self.open_pixmap) def get_channel_led_config_async(self, idx, cfg): if idx == 0: self.cbox_cs0_cfg.setCurrentIndex(cfg) elif idx == 1: self.cbox_cs1_cfg.setCurrentIndex(cfg) elif idx == 2: self.cbox_cs2_cfg.setCurrentIndex(cfg) elif idx == 3: self.cbox_cs3_cfg.setCurrentIndex(cfg) def cbox_cs0_cfg_changed(self, idx): self.iqr.set_channel_led_config(0, idx) def cbox_cs1_cfg_changed(self, idx): self.iqr.set_channel_led_config(1, idx) def cbox_cs2_cfg_changed(self, idx): self.iqr.set_channel_led_config(2, idx) def cbox_cs3_cfg_changed(self, idx): self.iqr.set_channel_led_config(3, idx) def start(self): async_call(self.iqr.get_value, None, self.get_value_async, self.increase_error_count) for channel in range(4): async_call(self.iqr.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 == BrickletIndustrialQuadRelayV2.DEVICE_IDENTIFIER def relay_button_clicked(self, button): value = 'On' in self.relay_buttons[button].text().replace('&', '') if value: self.relay_buttons[button].setText('Switch Off') self.relay_button_icons[button].setPixmap(self.close_pixmap) else: self.relay_buttons[button].setText('Switch On') self.relay_button_icons[button].setPixmap(self.open_pixmap) self.iqr.set_selected_value(button, value) def cb_value_change_by_monoflop(self, channel, value): if value: self.relay_buttons[channel].setText('Switch Off') self.relay_button_icons[channel].setPixmap(self.close_pixmap) else: self.relay_buttons[channel].setText('Switch On') self.relay_button_icons[channel].setPixmap(self.open_pixmap) def monoflop_channel_changed(self): channel = self.monoflop_channel.currentData() if channel == None: return self.monoflop_time_stack.setCurrentIndex(channel) self.monoflop_value_stack.setCurrentIndex(channel) def monoflop_go_clicked(self): channel = self.monoflop_channel.currentData() if channel == None: return self.monoflop.trigger(channel)
class IO16V2(COMCUPluginBase, Ui_IO16V2): def __init__(self, *args): COMCUPluginBase.__init__(self, BrickletIO16V2, *args) self.setupUi(self) self.io = self.device 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] * 16 self.config_value = [None] * 16 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_ch4_v, self.lbl_st_ch5_v, self.lbl_st_ch6_v, self.lbl_st_ch7_v, self.lbl_st_ch8_v, self.lbl_st_ch9_v, self.lbl_st_ch10_v, self.lbl_st_ch11_v, self.lbl_st_ch12_v, self.lbl_st_ch13_v, self.lbl_st_ch14_v, self.lbl_st_ch15_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_ch4_d, self.lbl_st_ch5_d, self.lbl_st_ch6_d, self.lbl_st_ch7_d, self.lbl_st_ch8_d, self.lbl_st_ch9_d, self.lbl_st_ch10_d, self.lbl_st_ch11_d, self.lbl_st_ch12_d, self.lbl_st_ch13_d, self.lbl_st_ch14_d, self.lbl_st_ch15_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_ch4_cfg, self.lbl_st_ch5_cfg, self.lbl_st_ch6_cfg, self.lbl_st_ch7_cfg, self.lbl_st_ch8_cfg, self.lbl_st_ch9_cfg, self.lbl_st_ch10_cfg, self.lbl_st_ch11_cfg, self.lbl_st_ch12_cfg, self.lbl_st_ch13_cfg, self.lbl_st_ch14_cfg, self.lbl_st_ch15_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.lbl_st_ch4_monoflop_t, self.lbl_st_ch5_monoflop_t, self.lbl_st_ch6_monoflop_t, self.lbl_st_ch7_monoflop_t, self.lbl_st_ch8_monoflop_t, self.lbl_st_ch9_monoflop_t, self.lbl_st_ch10_monoflop_t, self.lbl_st_ch11_monoflop_t, self.lbl_st_ch12_monoflop_t, self.lbl_st_ch13_monoflop_t, self.lbl_st_ch14_monoflop_t, self.lbl_st_ch15_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(16): 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 = QDoubleSpinBox() self.monoflop_times.append(monoflop_time) self.monoflop_time_stack.addWidget(monoflop_time) self.monoflop = Monoflop( self.io, list(range(16)), 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): self.config_direction = [None] * 16 self.config_value = [None] * 16 for channel in range(16): 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() @staticmethod def has_device_identifier(device_identifier): return device_identifier == BrickletIO16V2.DEVICE_IDENTIFIER def cb_value(self, value): for i in range(16): 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 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), None, 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)
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)
class SolidStateRelayV2(COMCUPluginBase, Ui_SolidStateRelayV2): def __init__(self, *args): COMCUPluginBase.__init__(self, BrickletSolidStateRelayV2, *args) self.setupUi(self) self.ssr = self.device self.state_combobox.setItemData(0, True) self.state_combobox.setItemData(1, False) self.monoflop = Monoflop(self.ssr, None, self.state_combobox, self.cb_state_change_by_monoflop, self.time_spinbox, None, self) self.ssr_button.clicked.connect(self.ssr_clicked) self.go_button.clicked.connect(self.go_clicked) self.a_pixmap = load_masked_pixmap('plugin_system/plugins/solid_state_relay/relay_a.bmp') self.b_pixmap = load_masked_pixmap('plugin_system/plugins/solid_state_relay/relay_b.bmp') def get_state_async(self, state): width = self.ssr_button.width() if self.ssr_button.minimumWidth() < width: self.ssr_button.setMinimumWidth(width) if state: self.ssr_button.setText('Switch Off') self.ssr_image.setPixmap(self.a_pixmap) else: self.ssr_button.setText('Switch On') self.ssr_image.setPixmap(self.b_pixmap) def start(self): async_call(self.ssr.get_state, None, self.get_state_async, self.increase_error_count) self.monoflop.start() def stop(self): self.monoflop.stop() def destroy(self): pass @staticmethod def has_device_identifier(device_identifier): return device_identifier == BrickletSolidStateRelayV2.DEVICE_IDENTIFIER def ssr_clicked(self): width = self.ssr_button.width() if self.ssr_button.minimumWidth() < width: self.ssr_button.setMinimumWidth(width) state = 'On' in self.ssr_button.text().replace('&', '') if state: self.ssr_button.setText('Switch Off') self.ssr_image.setPixmap(self.a_pixmap) else: self.ssr_button.setText('Switch On') self.ssr_image.setPixmap(self.b_pixmap) async_call(self.ssr.set_state, state, None, self.increase_error_count) def go_clicked(self): self.monoflop.trigger() def cb_state_change_by_monoflop(self, state): if state: self.ssr_button.setText('Switch Off') self.ssr_image.setPixmap(self.a_pixmap) else: self.ssr_button.setText('Switch On') self.ssr_image.setPixmap(self.b_pixmap)
class IndustrialDualRelay(COMCUPluginBase, Ui_IndustrialDualRelay): def __init__(self, *args): COMCUPluginBase.__init__(self, BrickletIndustrialDualRelay, *args) self.setupUi(self) self.idr = self.device self.value0_combobox.setItemData(0, True) self.value0_combobox.setItemData(1, False) self.value1_combobox.setItemData(0, True) self.value1_combobox.setItemData(1, False) self.monoflop = Monoflop(self.idr, [0, 1], [self.value0_combobox, self.value1_combobox], self.cb_value_change_by_monoflop, [self.time0_spinbox, self.time1_spinbox], None, self) self.ch0_button.clicked.connect(self.ch0_clicked) self.ch1_button.clicked.connect(self.ch1_clicked) self.go0_button.clicked.connect(self.go0_clicked) self.go1_button.clicked.connect(self.go1_clicked) self.a0_pixmap = load_masked_pixmap('plugin_system/plugins/industrial_dual_relay/channel0_a.bmp') self.a1_pixmap = load_masked_pixmap('plugin_system/plugins/industrial_dual_relay/channel1_a.bmp') self.b0_pixmap = load_masked_pixmap('plugin_system/plugins/industrial_dual_relay/channel0_b.bmp') self.b1_pixmap = load_masked_pixmap('plugin_system/plugins/industrial_dual_relay/channel1_b.bmp') def get_value_async(self, value): width = self.ch0_button.width() if self.ch0_button.minimumWidth() < width: self.ch0_button.setMinimumWidth(width) width = self.ch1_button.width() if self.ch1_button.minimumWidth() < width: self.ch1_button.setMinimumWidth(width) ch0, ch1 = value if ch0: self.ch0_button.setText('Switch Off') self.ch0_image.setPixmap(self.a0_pixmap) else: self.ch0_button.setText('Switch On') self.ch0_image.setPixmap(self.b0_pixmap) if ch1: self.ch1_button.setText('Switch Off') self.ch1_image.setPixmap(self.a1_pixmap) else: self.ch1_button.setText('Switch On') self.ch1_image.setPixmap(self.b1_pixmap) def start(self): async_call(self.idr.get_value, None, self.get_value_async, self.increase_error_count) self.monoflop.start() def stop(self): self.monoflop.stop() def destroy(self): pass @staticmethod def has_device_identifier(device_identifier): return device_identifier == BrickletIndustrialDualRelay.DEVICE_IDENTIFIER def ch0_clicked(self): width = self.ch0_button.width() if self.ch0_button.minimumWidth() < width: self.ch0_button.setMinimumWidth(width) value = 'On' in self.ch0_button.text().replace('&', '') if value: self.ch0_button.setText('Switch Off') self.ch0_image.setPixmap(self.a0_pixmap) else: self.ch0_button.setText('Switch On') self.ch0_image.setPixmap(self.b0_pixmap) async_call(self.idr.set_selected_value, (0, value), None, self.increase_error_count) def ch1_clicked(self): width = self.ch1_button.width() if self.ch1_button.minimumWidth() < width: self.ch1_button.setMinimumWidth(width) value = 'On' in self.ch1_button.text().replace('&', '') if value: self.ch1_button.setText('Switch Off') self.ch1_image.setPixmap(self.a1_pixmap) else: self.ch1_button.setText('Switch On') self.ch1_image.setPixmap(self.b1_pixmap) async_call(self.idr.set_selected_value, (1, value), None, self.increase_error_count) def go0_clicked(self): self.monoflop.trigger(0) def go1_clicked(self): self.monoflop.trigger(1) def cb_value_change_by_monoflop(self, channel, value): if channel == 0: if value: self.ch0_button.setText('Switch Off') self.ch0_image.setPixmap(self.a0_pixmap) else: self.ch0_button.setText('Switch On') self.ch0_image.setPixmap(self.b0_pixmap) elif channel == 1: if value: self.ch1_button.setText('Switch Off') self.ch1_image.setPixmap(self.a1_pixmap) else: self.ch1_button.setText('Switch On') self.ch1_image.setPixmap(self.b1_pixmap)
class DualRelay(PluginBase, Ui_DualRelay): def __init__(self, *args): PluginBase.__init__(self, BrickletDualRelay, *args) self.setupUi(self) self.dr = self.device self.state1_combobox.setItemData(0, True) self.state1_combobox.setItemData(1, False) self.state2_combobox.setItemData(0, True) self.state2_combobox.setItemData(1, False) self.monoflop = Monoflop(self.dr, [1, 2], [self.state1_combobox, self.state2_combobox], self.cb_state_change_by_monoflop, [self.time1_spinbox, self.time2_spinbox], None, self) self.dr1_button.clicked.connect(self.dr1_clicked) self.dr2_button.clicked.connect(self.dr2_clicked) self.go1_button.clicked.connect(self.go1_clicked) self.go2_button.clicked.connect(self.go2_clicked) self.a1_pixmap = load_masked_pixmap( 'plugin_system/plugins/dual_relay/relay_a1.bmp') self.a2_pixmap = load_masked_pixmap( 'plugin_system/plugins/dual_relay/relay_a2.bmp') self.b1_pixmap = load_masked_pixmap( 'plugin_system/plugins/dual_relay/relay_b1.bmp') self.b2_pixmap = load_masked_pixmap( 'plugin_system/plugins/dual_relay/relay_b2.bmp') def get_state_async(self, dr1, dr2): width = self.dr1_button.width() if self.dr1_button.minimumWidth() < width: self.dr1_button.setMinimumWidth(width) width = self.dr2_button.width() if self.dr2_button.minimumWidth() < width: self.dr2_button.setMinimumWidth(width) if dr1: self.dr1_button.setText('Switch Off') self.dr1_image.setPixmap(self.a1_pixmap) else: self.dr1_button.setText('Switch On') self.dr1_image.setPixmap(self.b1_pixmap) if dr2: self.dr2_button.setText('Switch Off') self.dr2_image.setPixmap(self.a2_pixmap) else: self.dr2_button.setText('Switch On') self.dr2_image.setPixmap(self.b2_pixmap) def start(self): async_call(self.dr.get_state, None, self.get_state_async, self.increase_error_count, expand_result_tuple_for_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 == BrickletDualRelay.DEVICE_IDENTIFIER def dr1_clicked(self): width = self.dr1_button.width() if self.dr1_button.minimumWidth() < width: self.dr1_button.setMinimumWidth(width) state = 'On' in self.dr1_button.text().replace('&', '') if state: self.dr1_button.setText('Switch Off') self.dr1_image.setPixmap(self.a1_pixmap) else: self.dr1_button.setText('Switch On') self.dr1_image.setPixmap(self.b1_pixmap) async_call(self.dr.set_selected_state, (1, state), None, self.increase_error_count) def dr2_clicked(self): width = self.dr2_button.width() if self.dr2_button.minimumWidth() < width: self.dr2_button.setMinimumWidth(width) state = 'On' in self.dr2_button.text().replace('&', '') if state: self.dr2_button.setText('Switch Off') self.dr2_image.setPixmap(self.a2_pixmap) else: self.dr2_button.setText('Switch On') self.dr2_image.setPixmap(self.b2_pixmap) async_call(self.dr.set_selected_state, (2, state), None, self.increase_error_count) def go1_clicked(self): self.monoflop.trigger(1) def go2_clicked(self): self.monoflop.trigger(2) def cb_state_change_by_monoflop(self, relay, state): if relay == 1: if state: self.dr1_button.setText('Switch Off') self.dr1_image.setPixmap(self.a1_pixmap) else: self.dr1_button.setText('Switch On') self.dr1_image.setPixmap(self.b1_pixmap) elif relay == 2: if state: self.dr2_button.setText('Switch Off') self.dr2_image.setPixmap(self.a2_pixmap) else: self.dr2_button.setText('Switch On') self.dr2_image.setPixmap(self.b2_pixmap)
class DualRelay(PluginBase, Ui_DualRelay): def __init__(self, *args): PluginBase.__init__(self, BrickletDualRelay, *args) self.setupUi(self) self.dr = self.device self.state1_combobox.setItemData(0, True) self.state1_combobox.setItemData(1, False) self.state2_combobox.setItemData(0, True) self.state2_combobox.setItemData(1, False) self.monoflop = Monoflop(self.dr, [1, 2], [self.state1_combobox, self.state2_combobox], self.cb_state_change_by_monoflop, [self.time1_spinbox, self.time2_spinbox], None, self) self.dr1_button.clicked.connect(self.dr1_clicked) self.dr2_button.clicked.connect(self.dr2_clicked) self.go1_button.clicked.connect(self.go1_clicked) self.go2_button.clicked.connect(self.go2_clicked) self.a1_pixmap = load_masked_pixmap('plugin_system/plugins/dual_relay/relay_a1.bmp') self.a2_pixmap = load_masked_pixmap('plugin_system/plugins/dual_relay/relay_a2.bmp') self.b1_pixmap = load_masked_pixmap('plugin_system/plugins/dual_relay/relay_b1.bmp') self.b2_pixmap = load_masked_pixmap('plugin_system/plugins/dual_relay/relay_b2.bmp') def get_state_async(self, dr1, dr2): width = self.dr1_button.width() if self.dr1_button.minimumWidth() < width: self.dr1_button.setMinimumWidth(width) width = self.dr2_button.width() if self.dr2_button.minimumWidth() < width: self.dr2_button.setMinimumWidth(width) if dr1: self.dr1_button.setText('Switch Off') self.dr1_image.setPixmap(self.a1_pixmap) else: self.dr1_button.setText('Switch On') self.dr1_image.setPixmap(self.b1_pixmap) if dr2: self.dr2_button.setText('Switch Off') self.dr2_image.setPixmap(self.a2_pixmap) else: self.dr2_button.setText('Switch On') self.dr2_image.setPixmap(self.b2_pixmap) def start(self): async_call(self.dr.get_state, None, self.get_state_async, self.increase_error_count, expand_result_tuple_for_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 == BrickletDualRelay.DEVICE_IDENTIFIER def dr1_clicked(self): width = self.dr1_button.width() if self.dr1_button.minimumWidth() < width: self.dr1_button.setMinimumWidth(width) state = 'On' in self.dr1_button.text().replace('&', '') if state: self.dr1_button.setText('Switch Off') self.dr1_image.setPixmap(self.a1_pixmap) else: self.dr1_button.setText('Switch On') self.dr1_image.setPixmap(self.b1_pixmap) async_call(self.dr.set_selected_state, (1, state), None, self.increase_error_count) def dr2_clicked(self): width = self.dr2_button.width() if self.dr2_button.minimumWidth() < width: self.dr2_button.setMinimumWidth(width) state = 'On' in self.dr2_button.text().replace('&', '') if state: self.dr2_button.setText('Switch Off') self.dr2_image.setPixmap(self.a2_pixmap) else: self.dr2_button.setText('Switch On') self.dr2_image.setPixmap(self.b2_pixmap) async_call(self.dr.set_selected_state, (2, state), None, self.increase_error_count) def go1_clicked(self): self.monoflop.trigger(1) def go2_clicked(self): self.monoflop.trigger(2) def cb_state_change_by_monoflop(self, relay, state): if relay == 1: if state: self.dr1_button.setText('Switch Off') self.dr1_image.setPixmap(self.a1_pixmap) else: self.dr1_button.setText('Switch On') self.dr1_image.setPixmap(self.b1_pixmap) elif relay == 2: if state: self.dr2_button.setText('Switch Off') self.dr2_image.setPixmap(self.a2_pixmap) else: self.dr2_button.setText('Switch On') self.dr2_image.setPixmap(self.b2_pixmap)
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)
class IO4(PluginBase, Ui_IO4): def __init__(self, *args): PluginBase.__init__(self, BrickletIO4, *args) self.setupUi(self) self.io = self.device self.cbe_value = CallbackEmulator(self, self.io.get_value, None, self.cb_value, self.increase_error_count) self.port_value = [self.av0, self.av1, self.av2, self.av3] self.port_direction = [self.ad0, self.ad1, self.ad2, self.ad3] self.port_config = [self.ac0, self.ac1, self.ac2, self.ac3] self.port_time = [self.at0, self.at1, self.at2, self.at3] self.save_button.clicked.connect(self.save_clicked) self.pin_box.currentIndexChanged.connect(self.pin_changed) self.direction_box.currentIndexChanged.connect(self.direction_changed) self.debounce_save.clicked.connect(self.debounce_save_clicked) self.go_button.clicked.connect(self.go_clicked) 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 = QDoubleSpinBox() 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.port_time, self, setter_uses_bitmasks=True, callback_uses_bitmasks=True) self.pin_changed(0) def init_async(self): self.init_value = 0 self.init_dir = 0 self.init_config = 0 def get_port_async(value): self.init_value = value next(self.init_async_generator) def get_port_configuration_async(conf): self.init_dir, self.init_config = conf next(self.init_async_generator) def get_debounce_period_async(debounce_period): self.debounce_edit.setText(str(debounce_period)) self.pin_changed(0) async_call(self.io.get_value, None, get_port_async, self.increase_error_count) yield async_call(self.io.get_configuration, None, get_port_configuration_async, self.increase_error_count) yield self.init_values(self.init_value, self.init_dir, self.init_config) async_call(self.io.get_debounce_period, None, get_debounce_period_async, self.increase_error_count) def start(self): self.init_async_generator = self.init_async() next(self.init_async_generator) 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 == BrickletIO4.DEVICE_IDENTIFIER def init_values(self, value, direction, config): for i in range(4): if direction & (1 << i): self.port_direction[i].setText('Input') if config & (1 << i): self.port_config[i].setText('Pull-Up') else: self.port_config[i].setText('Default') else: self.port_direction[i].setText('Output') self.port_config[i].setText('-') if value & (1 << i): self.port_value[i].setText('High') else: self.port_value[i].setText('Low') self.update_monoflop_ui_state() def update_monoflop_ui_state(self): pin = int(self.pin_box.currentText()) self.go_button.setEnabled( self.port_direction[pin].text().replace('&', '') == 'Output') def save_clicked(self): pin = int(self.pin_box.currentText()) direction = self.direction_box.currentText()[0].lower() if direction == 'o': value = self.value_box.currentText() == 'High' self.port_value[pin].setText(self.value_box.currentText()) else: value = self.value_box.currentText() == 'Pull-Up' async_call(self.io.set_configuration, (1 << pin, direction, value), None, self.increase_error_count) self.port_direction[pin].setText(self.direction_box.currentText()) if direction == 'i': self.port_config[pin].setText(self.value_box.currentText()) else: self.port_config[pin].setText('-') self.update_monoflop_ui_state() def cb_value(self, value): for i in range(4): if value & (1 << i): self.port_value[i].setText('High') else: self.port_value[i].setText('Low') def pin_changed(self, pin): if self.port_direction[pin].text().replace('&', '') == 'Input': index = 0 else: index = 1 self.direction_box.setCurrentIndex(index) self.direction_changed(index) self.monoflop_time_stack.setCurrentIndex(pin) self.monoflop_value_stack.setCurrentIndex(pin) self.update_monoflop_ui_state() def direction_changed(self, direction): pin = int(self.pin_box.currentText()) self.value_box.clear() if direction == 1: self.value_label.setText('Value:') self.value_box.addItem('High') self.value_box.addItem('Low') if self.port_value[pin].text().replace('&', '') == 'High': self.value_box.setCurrentIndex(0) else: self.value_box.setCurrentIndex(1) else: self.value_label.setText('Config:') self.value_box.addItem('Pull-Up') self.value_box.addItem('Default') if self.port_config[pin].text().replace('&', '') == 'Pull-Up': self.value_box.setCurrentIndex(0) else: self.value_box.setCurrentIndex(1) self.update_monoflop_ui_state() def debounce_save_clicked(self): debounce = int(self.debounce_edit.text()) async_call(self.io.set_debounce_period, debounce, None, self.increase_error_count) def go_clicked(self): pin = int(self.pin_box.currentText()) self.monoflop.trigger(pin) def cb_value_change_by_monoflop(self, pin, value): if value: self.port_value[pin].setText('High') else: self.port_value[pin].setText('Low') self.port_config[pin].setText('-') selected_pin = int(self.pin_box.currentText()) if pin == selected_pin: if value: self.value_box.setCurrentIndex(0) else: self.value_box.setCurrentIndex(1)
class IndustrialQuadRelayV2(COMCUPluginBase, Ui_IndustrialQuadRelayV2): def __init__(self, *args): COMCUPluginBase.__init__(self, BrickletIndustrialQuadRelayV2, *args) self.setupUi(self) self.iqr = self.device self.open_pixmap = load_masked_pixmap('plugin_system/plugins/industrial_quad_relay/relay_open.bmp') self.close_pixmap = load_masked_pixmap('plugin_system/plugins/industrial_quad_relay/relay_close.bmp') self.relay_buttons = [self.b0, self.b1, self.b2, self.b3] self.relay_button_icons = [self.b0_icon, self.b1_icon, self.b2_icon, self.b3_icon] self.relay_button_labels = [self.b0_label, self.b1_label, self.b2_label, self.b3_label] for icon in self.relay_button_icons: icon.setPixmap(self.open_pixmap) icon.show() for i in range(len(self.relay_buttons)): self.relay_buttons[i].clicked.connect(functools.partial(self.relay_button_clicked, i)) self.monoflop_values = [] self.monoflop_times = [] for i in range(4): self.monoflop_channel.setItemData(i, i) monoflop_value = QComboBox() monoflop_value.addItem('On', True) monoflop_value.addItem('Off', 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.iqr, [0, 1, 2, 3], self.monoflop_values, self.cb_value_change_by_monoflop, self.monoflop_times, None, self) self.monoflop_channel.currentIndexChanged.connect(self.monoflop_channel_changed) self.monoflop_go.clicked.connect(self.monoflop_go_clicked) self.cbox_cs0_cfg.currentIndexChanged.connect(self.cbox_cs0_cfg_changed) self.cbox_cs1_cfg.currentIndexChanged.connect(self.cbox_cs1_cfg_changed) self.cbox_cs2_cfg.currentIndexChanged.connect(self.cbox_cs2_cfg_changed) self.cbox_cs3_cfg.currentIndexChanged.connect(self.cbox_cs3_cfg_changed) def get_value_async(self, value): for button in range(4): if value[button]: self.relay_buttons[button].setText('Switch Off') self.relay_button_icons[button].setPixmap(self.close_pixmap) else: self.relay_buttons[button].setText('Switch On') self.relay_button_icons[button].setPixmap(self.open_pixmap) def get_channel_led_config_async(self, idx, cfg): if idx == 0: self.cbox_cs0_cfg.setCurrentIndex(cfg) elif idx == 1: self.cbox_cs1_cfg.setCurrentIndex(cfg) elif idx == 2: self.cbox_cs2_cfg.setCurrentIndex(cfg) elif idx == 3: self.cbox_cs3_cfg.setCurrentIndex(cfg) def cbox_cs0_cfg_changed(self, idx): self.iqr.set_channel_led_config(0, idx) def cbox_cs1_cfg_changed(self, idx): self.iqr.set_channel_led_config(1, idx) def cbox_cs2_cfg_changed(self, idx): self.iqr.set_channel_led_config(2, idx) def cbox_cs3_cfg_changed(self, idx): self.iqr.set_channel_led_config(3, idx) def start(self): async_call(self.iqr.get_value, None, self.get_value_async, self.increase_error_count) for channel in range(4): async_call(self.iqr.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 == BrickletIndustrialQuadRelayV2.DEVICE_IDENTIFIER def relay_button_clicked(self, button): value = 'On' in self.relay_buttons[button].text().replace('&', '') if value: self.relay_buttons[button].setText('Switch Off') self.relay_button_icons[button].setPixmap(self.close_pixmap) else: self.relay_buttons[button].setText('Switch On') self.relay_button_icons[button].setPixmap(self.open_pixmap) self.iqr.set_selected_value(button, value) def cb_value_change_by_monoflop(self, channel, value): if value: self.relay_buttons[channel].setText('Switch Off') self.relay_button_icons[channel].setPixmap(self.close_pixmap) else: self.relay_buttons[channel].setText('Switch On') self.relay_button_icons[channel].setPixmap(self.open_pixmap) def monoflop_channel_changed(self): channel = self.monoflop_channel.currentData() if channel == None: return self.monoflop_time_stack.setCurrentIndex(channel) self.monoflop_value_stack.setCurrentIndex(channel) def monoflop_go_clicked(self): channel = self.monoflop_channel.currentData() if channel == None: return self.monoflop.trigger(channel)
class IO16V2(COMCUPluginBase, Ui_IO16V2): def __init__(self, *args): COMCUPluginBase.__init__(self, BrickletIO16V2, *args) self.setupUi(self) self.io = self.device 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] * 16 self.config_value = [None] * 16 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_ch4_v, self.lbl_st_ch5_v, self.lbl_st_ch6_v, self.lbl_st_ch7_v, self.lbl_st_ch8_v, self.lbl_st_ch9_v, self.lbl_st_ch10_v, self.lbl_st_ch11_v, self.lbl_st_ch12_v, self.lbl_st_ch13_v, self.lbl_st_ch14_v, self.lbl_st_ch15_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_ch4_d, self.lbl_st_ch5_d, self.lbl_st_ch6_d, self.lbl_st_ch7_d, self.lbl_st_ch8_d, self.lbl_st_ch9_d, self.lbl_st_ch10_d, self.lbl_st_ch11_d, self.lbl_st_ch12_d, self.lbl_st_ch13_d, self.lbl_st_ch14_d, self.lbl_st_ch15_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_ch4_cfg, self.lbl_st_ch5_cfg, self.lbl_st_ch6_cfg, self.lbl_st_ch7_cfg, self.lbl_st_ch8_cfg, self.lbl_st_ch9_cfg, self.lbl_st_ch10_cfg, self.lbl_st_ch11_cfg, self.lbl_st_ch12_cfg, self.lbl_st_ch13_cfg, self.lbl_st_ch14_cfg, self.lbl_st_ch15_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.lbl_st_ch4_monoflop_t, self.lbl_st_ch5_monoflop_t, self.lbl_st_ch6_monoflop_t, self.lbl_st_ch7_monoflop_t, self.lbl_st_ch8_monoflop_t, self.lbl_st_ch9_monoflop_t, self.lbl_st_ch10_monoflop_t, self.lbl_st_ch11_monoflop_t, self.lbl_st_ch12_monoflop_t, self.lbl_st_ch13_monoflop_t, self.lbl_st_ch14_monoflop_t, self.lbl_st_ch15_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(16): 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, list(range(16)), 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): self.config_direction = [None] * 16 self.config_value = [None] * 16 for channel in range(16): 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() @staticmethod def has_device_identifier(device_identifier): return device_identifier == BrickletIO16V2.DEVICE_IDENTIFIER def cb_value(self, value): for i in range(16): 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 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), None, 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)
class IndustrialDigitalOutHS4(COMCUPluginBase, Ui_IndustrialDigitalOutHS4): def __init__(self, *args): COMCUPluginBase.__init__(self, BrickletIndustrialDigitalOutHS4, *args) self.setupUi(self) self.ido4 = self.device self.pixmap_low = load_masked_pixmap('plugin_system/plugins/industrial_digital_out_hs_4/ido4_low.bmp') self.pixmap_high = load_masked_pixmap('plugin_system/plugins/industrial_digital_out_hs_4/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] self.lbl_vol = [self.lbl_vol0, self.lbl_vol1, self.lbl_vol2, self.lbl_vol3] self.lbl_cur = [self.lbl_cur0, self.lbl_cur1, self.lbl_cur2, self.lbl_cur3] # 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) # Measurements self.cbe_measurements = CallbackEmulator(self.ido4.get_measurements, None, self.cb_measurements, self.increase_error_count) def cb_measurements(self, measurements): self.lbl_vol[0].setText('{0:.2f} V'.format(measurements.voltage[0] / 1000.0)) self.lbl_vol[1].setText('{0:.2f} V'.format(measurements.voltage[0] / 1000.0)) self.lbl_vol[2].setText('{0:.2f} V'.format(measurements.voltage[1] / 1000.0)) self.lbl_vol[3].setText('{0:.2f} V'.format(measurements.voltage[1] / 1000.0)) self.lbl_cur[0].setText('{0} mA'.format(measurements.current[0])) self.lbl_cur[1].setText('{0} mA'.format(measurements.current[1])) self.lbl_cur[2].setText('{0} mA'.format(measurements.current[2])) self.lbl_cur[3].setText('{0} mA'.format(measurements.current[3])) 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): 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.cbe_measurements.set_period(250) self.monoflop.start() def stop(self): self.cbe_measurements.set_period(0) self.monoflop.stop() def destroy(self): pass @staticmethod def has_device_identifier(device_identifier): return device_identifier == BrickletIndustrialDigitalOutHS4.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) 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)