Ejemplo n.º 1
0
    def loadEdfFile(self):
        filePath = QFileDialog.getOpenFileName(self,
                                               u'Choose edf to load',
                                               "./output/",
                                               filter="*.edf",
                                               selectedFilter="*.edf")
        if filePath:
            try:
                self.tabCount += 1
                fileName = ntpath.basename(unicode(filePath))
                jobWidget = JobWidget(self.getParams())
                jobWidget.jobProgressWidget.hide()
                jobWidget.runtimeWidget.hide()
                tabIndex = self.jobTabs.addTab(jobWidget,
                                               u"{0}".format(fileName))
                self.jobs[self.tabCount] = jobWidget
                self.showJobGroup(True)
                self.jobTabs.setCurrentIndex(tabIndex)
                jobWidget.sigCloseJob.connect(
                    lambda jobIndex=self.tabCount: self.closeJob(jobIndex))

                self.uiFinishWait()
                jobWidget.status = STATUS_FINISHED
                jobWidget.displayOutput(unicode(filePath))
            except Exception as e:
                message = QErrorMessage(self)
                message.showMessage(
                    u"Unable to load {0}. Error message: {1}".format(
                        filePath, e.message))
                jobWidget.closeJob()
Ejemplo n.º 2
0
 def accept(self):
     """Acepta el dialogo. Coge la operacion con la que esta trabajando 
     el usuario e inicia el procedimiento de calculo"""
     from pyrqt.excepciones import OpcionesIncorrectaException
     import rpy
     nombre = unicode(self.ui.treeWidget.currentItem().text(0))
     widget = self.__widgets["operaciones"][nombre]
     try:
         resultado = self.__gestoroperaciones[nombre].procedimiento(widget.seleccion(), widget.opciones())
     except OpcionesIncorrectaException:
         errormessage = QErrorMessage(self)
         errormessage.showMessage(u"Las opciones no son correctas")
     #except IndexError:
     #    errormessage = QErrorMessage(self)
     #    errormessage.showMessage(u"Seleccion incorrecta")
     #    LOG.exception("excepcion capturada")
     except KeyError:
         QErrorMessage(self).showMessage(u"Hay elementos de la salida sin definir(o mal definidos) en la operación")
         LOG.exception("Excepción Generada por un módulo de operaciones")
     except rpy.RException:
         QErrorMessage(self).showMessage(u"R devolvio un error")
         log.exception("Excepción de RPY")
     except AssertionError:
         QErrorMessage(self).showMessage(u"Error desconocido")
     else:
         self.__vsalida.ana_res(resultado) #Añadir a la salida el resultado
         self.__vsalida.hide() #TODO averiguar como hacer para que recupere el foco sin ocultar la ventana
         self.__vsalida.show()
Ejemplo n.º 3
0
    def input_device_changed(self, index):
        success, index = self.audio_device.select_input_device(index)
        self.ui.DeviceList.setCurrentIndex(index)
        self.fft_plot.must_plot = True
        if not success:
# Note: the error message is a child of the settings dialog, so that
# that dialog remains on top when the error message is closed
            error_message = QErrorMessage(self.settings_dialog)
            error_message.setWindowTitle("Input device error")
            error_message.showMessage("Impossible to use the selected input"
                                      " device, reverting to the previous one")
Ejemplo n.º 4
0
	def second_channel_changed(self, index):
		self.ui.actionStart.setChecked(False)
		
		success, index = self.audiobackend.select_second_channel(index)
		
		self.settings_dialog.comboBox_secondChannel.setCurrentIndex(index)
		
		if not success:
			# Note: the error message is a child of the settings dialog, so that
			# that dialog remains on top when the error message is closed
			error_message = QErrorMessage(self.settings_dialog)
			error_message.setWindowTitle("Input device error")
			error_message.showMessage("Impossible to use the selected channel as the second channel, reverting to the previous one")
		
		self.ui.actionStart.setChecked(True)
 def loadParameterSet(self):
     s = QSettings()
     name = self.configCombo.currentText()
     s.beginGroup('ParameterSets')
     if not name in s.childGroups():
         dlg = QErrorMessage(self)
         dlg.setWindowTitle('Error')
         dlg.showMessage('No saved parameters available for %s' % name)
         return
     s.beginGroup(name)
     for item in self.parameterItems:
         item.setValue(s.value(item.objectName(), item.value(), type=float))
     self.adjustExcitationCb.setChecked(s.value('adjustExcitation', False, type=bool))
     self.sensorNameLe.setText(s.value('sensorName', '', type=QString))
     self.visaCombo.setCurrentIndex(self.visaCombo.findText(s.value('sr830Visa', 'GPIB0::12', type=QString)))
     self.autoRangingCb.setChecked(s.value('autoRanging', True, type=bool))
     self.minSensitivityCombo.setCurrentCodeSilently(s.value('minSensitivity', 0, type=int))
     s.endGroup()
     s.endGroup()
Ejemplo n.º 6
0
    def addScanNumbers(self):
        result = self.range_dialog.exec_()
        if result == QDialog.Accepted:
            text = self.range_ui.range_edit.text()
            if text:
                not_found = []
                numbers = mythen.parse_range_list(text)
                year, visit = self.getYearAndVisit()
                progress = QProgressDialog(
                    "Locating scan files from numbers...", "Stop", 0,
                    len(numbers), self)
                progress.setWindowModality(Qt.WindowModal)
                progress.forceShow()
                progress.setValue(0)
                for n in numbers:
                    progress.setValue(progress.value() + 1)
                    if progress.wasCanceled():
                        break

                    files = mythen.find_mythen_files(
                        n, visit=visit,
                        year=year)  # FIXME needs to be in separate thread(!)
                    if files:
                        files = [f for f in files if f not in self.scans]
                        self.scans.extend(files)
                        self.scans_model.setStringList(self.scans)
                    else:
                        not_found.append(n)

                progress.setValue(progress.maximum())

                if not_found:
                    error = QErrorMessage(self)
                    msg = "The following numbers were not found: "
                    for n in not_found:
                        msg = msg + str(n) + ", "
                    error.showMessage(msg[:-2])
Ejemplo n.º 7
0
class DC(PluginBase, Ui_DC):
    qtcb_position_reached = pyqtSignal(int)
    qtcb_under_voltage = pyqtSignal(int)
    qtcb_emergency_shutdown = pyqtSignal()
    
    def __init__(self, ipcon, uid, version):
        PluginBase.__init__(self, ipcon, uid, 'DC Brick', version)
        
        self.setupUi(self)
        self.encoder_hide_all()
        
        self.dc = BrickDC(uid, ipcon)
        self.device = self.dc
        
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.update_data)
        
        self.speedometer = SpeedoMeter()
        self.vertical_layout_right.insertWidget(4, self.speedometer)
        
        self.new_value = 0
        self.update_counter = 0
        
        self.full_brake_time = 0
        
        self.velocity_slider.sliderReleased.connect(self.velocity_slider_released)
        self.velocity_slider.valueChanged.connect(self.velocity_spin.setValue)
        self.velocity_spin.editingFinished.connect(self.velocity_spin_finished)
        
        self.acceleration_slider.sliderReleased.connect(self.acceleration_slider_released)
        self.acceleration_slider.valueChanged.connect(self.acceleration_spin.setValue)
        self.acceleration_spin.editingFinished.connect(self.acceleration_spin_finished)
        
        self.frequency_slider.sliderReleased.connect(self.frequency_slider_released)
        self.frequency_slider.valueChanged.connect(self.frequency_spin.setValue)
        self.frequency_spin.editingFinished.connect(self.frequency_spin_finished)
        
        self.radio_mode_brake.toggled.connect(self.brake_value_changed)
        self.radio_mode_coast.toggled.connect(self.coast_value_changed)
        
        self.minimum_voltage_button.pressed.connect(self.minimum_voltage_button_pressed)
        self.full_brake_button.pressed.connect(self.full_brake_pressed)
        self.enable_checkbox.stateChanged.connect(self.enable_state_changed)
        
        self.emergency_signal = None
        self.under_signal = None
        self.current_velocity_signal = None
        self.velocity_reached_signal = None
        
        self.qem = QErrorMessage(self)
        
        self.qtcb_under_voltage.connect(self.cb_under_voltage)
        self.dc.register_callback(self.dc.CALLBACK_UNDER_VOLTAGE,
                                  self.qtcb_under_voltage.emit) 
        
        self.qtcb_emergency_shutdown.connect(self.cb_emergency_shutdown)
        self.dc.register_callback(self.dc.CALLBACK_EMERGENCY_SHUTDOWN,
                                  self.qtcb_emergency_shutdown.emit) 
        
        self.qtcb_position_reached.connect(self.update_velocity)
        self.dc.register_callback(self.dc.CALLBACK_VELOCITY_REACHED,
                                  self.qtcb_position_reached.emit) 
        self.dc.register_callback(self.dc.CALLBACK_CURRENT_VELOCITY,
                                  self.qtcb_position_reached.emit)
        
#        if self.version >= (2, 0, 1):
#            self.enable_encoder_checkbox.stateChanged.connect(self.enable_encoder_state_changed)
#            self.encoder_show()
#        else:
#            self.enable_encoder_checkbox.setText('Enable Encoder (Firmware >= 2.01 required)')
#            self.enable_encoder_checkbox.setEnabled(False)
    
    def start(self):
        self.update_timer.start(1000)
        async_call(self.dc.set_current_velocity_period, 100, None, self.increase_error_count)
        self.update_start()
        self.update_data()
        
    def stop(self):
        self.update_timer.stop()
        async_call(self.dc.set_current_velocity_period, 0, None, self.increase_error_count)

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

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

    def is_brick(self):
        return True

    def get_url_part(self):
        return 'dc'

    @staticmethod
    def has_device_identifier(device_identifier):
        return device_identifier == BrickDC.DEVICE_IDENTIFIER
        
    def cb_emergency_shutdown(self):
        if not self.qem.isVisible():
            self.qem.setWindowTitle("Emergency Shutdown")
            self.qem.showMessage("Emergency Shutdown: Short-Circuit or Over-Temperature")
        
    def cb_under_voltage(self, ov):
        mv_str = self.minimum_voltage_label.text()
        ov_str = "%gV"  % round(ov/1000.0, 1)
        if not self.qem.isVisible():
            self.qem.setWindowTitle("Under Voltage")
            self.qem.showMessage("Under Voltage: Output Voltage of " + ov_str +
                                 " is below minimum voltage of " + mv_str,
                                 "DC_UnderVoltage")
            
    def encoder_hide_all(self):
        self.enable_encoder_checkbox.hide()
        self.encoder_hide()
            
    def encoder_hide(self):
        self.p_label.hide()
        self.p_spinbox.hide()
        self.i_label.hide()
        self.i_spinbox.hide()
        self.d_label.hide()
        self.d_spinbox.hide()
        self.st_label.hide()
        self.st_spinbox.hide()
        self.cpr_label.hide()
        self.cpr_spinbox.hide()
        self.encoder_spacer.hide()
        
    def encoder_show(self):
        self.p_label.show()
        self.p_spinbox.show()
        self.i_label.show()
        self.i_spinbox.show()
        self.d_label.show()
        self.d_spinbox.show()
        self.st_label.show()
        self.st_spinbox.show()
        self.cpr_label.show()
        self.cpr_spinbox.show()
        self.encoder_spacer.show()          
         
    def enable_encoder_state_changed(self, state):
        try:
            if state == Qt.Checked:
                self.dc.enable_encoder()
                self.update_encoder()
            elif state == Qt.Unchecked:
                self.dc.disable_encoder()

        except ip_connection.Error:
            return
        
    def enable_state_changed(self, state):
        try:
            if state == Qt.Checked:
                self.dc.enable()
            elif state == Qt.Unchecked:
                self.dc.disable()
        except ip_connection.Error:
            return
            
    def brake_value_changed(self, checked):
        if checked:
            try:
                self.dc.set_drive_mode(0)
            except ip_connection.Error:
                return
        
    def coast_value_changed(self, checked):
        if checked:
            try:
                self.dc.set_drive_mode(1)
            except ip_connection.Error:
                return
        
    def full_brake_pressed(self):
        try:
            self.dc.full_brake()
        except ip_connection.Error:
            return
        
    def minimum_voltage_selected(self, value):
        try:
            self.dc.set_minimum_voltage(value)
        except ip_connection.Error:
            return
        
    def minimum_voltage_button_pressed(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(5000)
        qid.setIntMaximum(0xFFFF)
        qid.setIntStep(100)
        async_call(self.dc.get_minimum_voltage, None, qid.setIntValue, self.increase_error_count)
        qid.intValueSelected.connect(self.minimum_voltage_selected)
        qid.setLabelText("Choose minimum motor voltage in mV.")
        qid.open()
        
    def stack_input_voltage_update(self, sv):
        sv_str = "%gV"  % round(sv/1000.0, 1)
        self.stack_voltage_label.setText(sv_str)
        
    def external_input_voltage_update(self, ev):
        ev_str = "%gV"  % round(ev/1000.0, 1)
        self.external_voltage_label.setText(ev_str)
        
    def minimum_voltage_update(self, mv):
        mv_str = "%gV"  % round(mv/1000.0, 1)
        self.minimum_voltage_label.setText(mv_str)
        
    def drive_mode_update(self, dm):
        if dm == 0:
            self.radio_mode_brake.setChecked(True)
            self.radio_mode_coast.setChecked(False)
        else:
            self.radio_mode_brake.setChecked(False)
            self.radio_mode_coast.setChecked(True)
            
    def current_consumption_update(self, cc):
        if cc >= 1000:
            cc_str = "%gA"  % round(cc/1000.0, 1)
        else:
            cc_str = "%gmA" % cc
            
        self.current_label.setText(cc_str)

    
    def update_velocity(self, value):
        if value != self.speedometer.value():
            self.speedometer.set_velocity(value)
        
    def get_velocity_async(self, velocity):
        if not self.velocity_slider.isSliderDown():
            if velocity != self.velocity_slider.sliderPosition():
                self.velocity_slider.setSliderPosition(velocity)
                self.velocity_spin.setValue(velocity)
        
    def get_acceleration_async(self, acceleration):
        if not self.acceleration_slider.isSliderDown():
            if acceleration != self.acceleration_slider.sliderPosition():
                self.acceleration_slider.setSliderPosition(acceleration)
                self.acceleration_spin.setValue(acceleration)
        
    def get_pwm_frequency_async(self, frequency):
        if not self.frequency_slider.isSliderDown():
            if frequency != self.frequency_slider.sliderPosition():
                self.frequency_slider.setSliderPosition(frequency)
                self.frequency_spin.setValue(frequency)
        
    def is_enabled_async(self, enabled):
        if enabled:
            self.enable_checkbox.setCheckState(Qt.Checked)
        else:
            self.enable_checkbox.setCheckState(Qt.Unchecked)
            
    def is_encoder_enabled_async(self, enabled):
        if enabled:
            self.enable_encoder_checkbox.setCheckState(Qt.Checked)
        else:
            self.enable_encoder_checkbox.setCheckState(Qt.Unchecked)
            
    def get_encoder_config_async(self, cpr):
        self.cpr_spinbox.setValue(cpr)
    
    def get_encoder_pid_config_async(self, pid_config):
        self.p_spinbox.setValue(pid_config.p)
        self.i_spinbox.setValue(pid_config.i)
        self.d_spinbox.setValue(pid_config.d)
        self.st_spinbox.setValue(pid_config.sample_time)
        
    def update_encoder(self):
        async_call(self.dc.get_encoder_config, None, self.get_encoder_config_async, self.increase_error_count)
        async_call(self.dc.get_encoder_pid_config, None, self.get_encoder_pid_config_async, self.increase_error_count)
        async_call(self.dc.is_encoder_enabled, None, self.is_encoder_enabled_async, self.increase_error_count)
        
        
    def update_start(self):
        async_call(self.dc.get_drive_mode, None, self.drive_mode_update, self.increase_error_count)
        async_call(self.dc.get_velocity, None, self.get_velocity_async, self.increase_error_count)
        async_call(self.dc.get_acceleration, None, self.get_acceleration_async, self.increase_error_count)
        async_call(self.dc.get_pwm_frequency, None, self.get_pwm_frequency_async, self.increase_error_count)
        async_call(self.dc.is_enabled, None, self.is_enabled_async, self.increase_error_count)
#        if self.version >= (2, 0, 1):
#            self.update_encoder()
            

    def update_data(self):
        async_call(self.dc.get_stack_input_voltage, None, self.stack_input_voltage_update, self.increase_error_count)
        async_call(self.dc.get_external_input_voltage, None, self.external_input_voltage_update, self.increase_error_count)
        async_call(self.dc.get_minimum_voltage, None, self.minimum_voltage_update, self.increase_error_count)
        async_call(self.dc.get_current_consumption, None, self.current_consumption_update, self.increase_error_count)
        
    def acceleration_slider_released(self):
        value = self.acceleration_slider.value()
        self.acceleration_spin.setValue(value)
        try:
            self.dc.set_acceleration(value)
        except ip_connection.Error:
            return
        
    def acceleration_spin_finished(self):
        value = self.acceleration_spin.value()
        self.acceleration_slider.setValue(value)
        try:
            self.dc.set_acceleration(value)
        except ip_connection.Error:
            return
        
    def velocity_slider_released(self):
        value = self.velocity_slider.value()
        self.velocity_spin.setValue(value)
        try:
            self.dc.set_velocity(value)
        except ip_connection.Error:
            return
        
    def velocity_spin_finished(self):
        value = self.velocity_spin.value()
        self.velocity_slider.setValue(value)
        try:
            self.dc.set_velocity(value)
        except ip_connection.Error:
            return
        
    def frequency_slider_released(self):
        value = self.frequency_slider.value()
        self.frequency_spin.setValue(value)
        try:
            self.dc.set_pwm_frequency(value)
        except ip_connection.Error:
            return
        
    def frequency_spin_finished(self):
        value = self.frequency_spin.value()
        self.frequency_slider.setValue(value)
        try:
            self.dc.set_pwm_frequency(value)
        except ip_connection.Error:
            return
Ejemplo n.º 8
0
class ImagesWidget(QWidget, Ui_Images):
    images = None

    def __init__(self, parent, app):
        super(QWidget, self).__init__()
        self.app = app

        self.setupUi(self)

        self.error_msg = QErrorMessage()
        self.error_msg.setWindowTitle("Starter Kit: Blinkenlights Demo " + config.DEMO_VERSION)

        self.slider_frame_rate.valueChanged.connect(self.slider_frame_rate_changed)
        self.spinbox_frame_rate.valueChanged.connect(self.spinbox_frame_rate_changed)
        self.button_choose.pressed.connect(self.choose_pressed)
        self.button_show.pressed.connect(self.show_pressed)
        self.button_default.pressed.connect(self.default_pressed)

        self.update_frame_rate_timer = QTimer(self)
        self.update_frame_rate_timer.timeout.connect(self.update_frame_rate)

        self.default_pressed()

    def start(self):
        self.images = Images(self.app.ipcon)

        self.update_frame_rate()

        self.images.frame_rendered(0)

    def stop(self):
        if self.images:
            self.images.stop_rendering()
            self.images = None

    def spinbox_frame_rate_changed(self, frame_rate):
        self.slider_frame_rate.setValue(frame_rate)
        self.update_frame_rate_timer.start(100)

    def slider_frame_rate_changed(self, frame_rate):
        self.spinbox_frame_rate.setValue(frame_rate)

    def show_pressed(self):
        if self.images:
            files = unicode(self.text_edit_files.toPlainText()).strip()

            if len(files) > 0:
                new_images = files.split('\n')

                try:
                    self.images.set_new_images(new_images)
                except Exception as e:
                    self.error_msg.showMessage(str(e))

                self.images.frame_prepare_next()
                self.images.frame_rendered(0)

    def choose_pressed(self):
        for filename in QFileDialog.getOpenFileNames(self, 'Choose Images', QDir.homePath()):
            self.text_edit_files.append(filename)

    def default_pressed(self):
        self.spinbox_frame_rate.setValue(1)

    def update_frame_rate(self):
        self.update_frame_rate_timer.stop()

        config.IMAGES_FRAME_RATE = self.spinbox_frame_rate.value()

        if self.images:
            self.images.update_frame_rate()
Ejemplo n.º 9
0
class SilentStepper(PluginBase, Ui_SilentStepper):
    qtcb_position_reached = pyqtSignal(int)
    qtcb_under_voltage = pyqtSignal(int)

    def __init__(self, *args):
        PluginBase.__init__(self, BrickSilentStepper, *args)

        self.setupUi(self)

        self.silent_stepper = self.device

        self.endis_all(False)

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

        self.speedometer = SpeedoMeter()
        self.vertical_layout_right.insertWidget(5, self.speedometer)

        self.new_value = 0
        self.update_counter = 0

        self.full_brake_time = 0

        self.qem = QErrorMessage(self)
        self.qem.setWindowTitle("Under Voltage")

        self.velocity_syncer = SliderSpinSyncer(self.velocity_slider,
                                                self.velocity_spin,
                                                self.velocity_changed)

        self.acceleration_syncer = SliderSpinSyncer(self.acceleration_slider,
                                                    self.acceleration_spin,
                                                    self.acceleration_changed)

        self.deceleration_syncer = SliderSpinSyncer(self.deceleration_slider,
                                                    self.deceleration_spin,
                                                    self.deceleration_changed)

        self.enable_checkbox.stateChanged.connect(self.enable_state_changed)
        self.forward_button.clicked.connect(self.forward_clicked)
        self.stop_button.clicked.connect(self.stop_clicked)
        self.full_brake_button.clicked.connect(self.full_brake_clicked)
        self.backward_button.clicked.connect(self.backward_clicked)
        self.to_button.clicked.connect(self.to_button_clicked)
        self.steps_button.clicked.connect(self.steps_button_clicked)
        self.motor_current_button.clicked.connect(self.motor_current_button_clicked)
        self.minimum_motor_voltage_button.clicked.connect(self.minimum_motor_voltage_button_clicked)

        self.qtcb_position_reached.connect(self.cb_position_reached)
        self.silent_stepper.register_callback(self.silent_stepper.CALLBACK_POSITION_REACHED,
                                              self.qtcb_position_reached.emit)

        self.qtcb_under_voltage.connect(self.cb_under_voltage)
        self.silent_stepper.register_callback(self.silent_stepper.CALLBACK_UNDER_VOLTAGE,
                                              self.qtcb_under_voltage.emit)

        # Step Configuration
        self.step_resolution_dropbox.currentIndexChanged.connect(self.step_configuration_changed)
        self.interpolate_checkbox.stateChanged.connect(self.step_configuration_changed)

        # Basic Configuration
        self.standstill_current_spin.valueChanged.connect(self.basic_configuration_changed)
        self.motor_run_current_spin.valueChanged.connect(self.basic_configuration_changed)
        self.standstill_delay_time_spin.valueChanged.connect(self.basic_configuration_changed)
        self.power_down_time_spin.valueChanged.connect(self.basic_configuration_changed)
        self.stealth_threshold_spin.valueChanged.connect(self.basic_configuration_changed)
        self.coolstep_threashold_spin.valueChanged.connect(self.basic_configuration_changed)
        self.classic_threshold_spin.valueChanged.connect(self.basic_configuration_changed)
        self.high_velocity_chopper_mode_checkbox.stateChanged.connect(self.basic_configuration_changed)

        # Spreadcycle Configuration
        self.slow_decay_duration_spin.valueChanged.connect(self.spreadcycle_configuration_changed)
        self.enable_random_slow_decay_checkbox.stateChanged.connect(self.spreadcycle_configuration_changed)
        self.fast_decay_duration_spin.valueChanged.connect(self.spreadcycle_configuration_changed)
        self.hysteresis_start_value_spin.valueChanged.connect(self.spreadcycle_configuration_changed)
        self.hysteresis_end_value_spin.valueChanged.connect(self.spreadcycle_configuration_changed)
        self.sine_wave_offset_spin.valueChanged.connect(self.spreadcycle_configuration_changed)
        self.chopper_mode_combo.currentIndexChanged.connect(self.spreadcycle_configuration_changed)
        self.comparator_blank_time_combo.currentIndexChanged.connect(self.spreadcycle_configuration_changed)
        self.fast_decay_without_comparator_checkbox.stateChanged.connect(self.spreadcycle_configuration_changed)

        # Stealth Configuration
        self.enable_stealth_checkbox.stateChanged.connect(self.stealth_configuration_changed)
        self.amplitude_spin.valueChanged.connect(self.stealth_configuration_changed)
        self.gradient_spin.valueChanged.connect(self.stealth_configuration_changed)
        self.enable_autoscale_checkbox.stateChanged.connect(self.stealth_configuration_changed)
        self.force_symmetric_checkbox.stateChanged.connect(self.stealth_configuration_changed)
        self.freewheel_mode_combo.currentIndexChanged.connect(self.stealth_configuration_changed)

        # Coolstep Configuration
        self.minimum_stallguard_value_spin.valueChanged.connect(self.coolstep_configuration_changed)
        self.maximum_stallguard_value_spin.valueChanged.connect(self.coolstep_configuration_changed)
        self.current_up_step_width_combo.currentIndexChanged.connect(self.coolstep_configuration_changed)
        self.current_down_step_width_combo.currentIndexChanged.connect(self.coolstep_configuration_changed)
        self.minimum_current_combo.currentIndexChanged.connect(self.coolstep_configuration_changed)
        self.stallguard_threshold_value_spin.valueChanged.connect(self.coolstep_configuration_changed)
        self.stallguard_mode_combo.currentIndexChanged.connect(self.coolstep_configuration_changed)

        # Misc Configuration
        self.disable_short_to_ground_protection_checkbox.stateChanged.connect(self.misc_configuration_changed)
        self.synchronize_phase_frequency_spin.valueChanged.connect(self.misc_configuration_changed)

        self.ste = 0
        self.pos = 0
        self.current_velocity = 0
        self.cur = 0
        self.sv  = 0
        self.ev  = 0
        self.mv  = 0
        self.mod = 0

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

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

    def start(self):
        async_call(self.silent_stepper.is_status_led_enabled, None, self.status_led_action.setChecked, self.increase_error_count)

        self.update_timer.start(100)
        self.update_start()

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

    def destroy(self):
        pass

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

    def cb_position_reached(self, position):
        self.position_update(position)
        self.endis_all(True)

    def disable_list(self, button_list):
        for button in button_list:
            button.setEnabled(False)

    def endis_all(self, value):
        self.forward_button.setEnabled(value)
        self.stop_button.setEnabled(value)
        self.backward_button.setEnabled(value)
        self.to_button.setEnabled(value)
        self.steps_button.setEnabled(value)
        self.full_brake_button.setEnabled(value)

    def step_configuration_changed(self, _):
        step_resolution = self.step_resolution_dropbox.currentIndex()
        interpolation = self.interpolate_checkbox.isChecked()
        try:
            self.silent_stepper.set_step_configuration(step_resolution, interpolation)
        except ip_connection.Error:
            return

    def basic_configuration_changed(self, _):
        standstill_current = self.standstill_current_spin.value()
        motor_run_current = self.motor_run_current_spin.value()
        standstill_delay_time = self.standstill_delay_time_spin.value()
        power_down_time = self.power_down_time_spin.value()
        stealth_threshold = self.stealth_threshold_spin.value()
        coolstep_threshold = self.coolstep_threashold_spin.value()
        classic_threshold = self.classic_threshold_spin.value()
        high_velocity_chopper_mode = self.high_velocity_chopper_mode_checkbox.isChecked()

        try:
            self.silent_stepper.set_basic_configuration(standstill_current, motor_run_current, standstill_delay_time, power_down_time, stealth_threshold, coolstep_threshold, classic_threshold, high_velocity_chopper_mode)
        except ip_connection.Error:
            return

    def spreadcycle_configuration_changed(self, _):
        slow_decay_duration = self.slow_decay_duration_spin.value()
        enable_random_slow_decay = self.enable_random_slow_decay_checkbox.isChecked()
        fast_decay_duration = self.fast_decay_duration_spin.value()
        hysteresis_start_value = self.hysteresis_start_value_spin.value()
        hysteresis_end_value = self.hysteresis_end_value_spin.value()
        sine_wave_offset = self.sine_wave_offset_spin.value()
        chopper_mode = self.chopper_mode_combo.currentIndex()
        comparator_blank_time = self.comparator_blank_time_combo.currentIndex()
        fast_decay_without_comparator = self.fast_decay_without_comparator_checkbox.isChecked()

        try:
            self.silent_stepper.set_spreadcycle_configuration(slow_decay_duration, enable_random_slow_decay, fast_decay_duration, hysteresis_start_value, hysteresis_end_value, sine_wave_offset, chopper_mode, comparator_blank_time, fast_decay_without_comparator)
        except ip_connection.Error:
            return

    def stealth_configuration_changed(self, _):
        enable_stealth = self.enable_stealth_checkbox.isChecked()
        amplitude = self.amplitude_spin.value()
        gradient = self.gradient_spin.value()
        enable_autoscale = self.enable_autoscale_checkbox.isChecked()
        force_symmetric = self.force_symmetric_checkbox.isChecked()
        freewheel_mode = self.freewheel_mode_combo.currentIndex()

        try:
            self.silent_stepper.set_stealth_configuration(enable_stealth, amplitude, gradient, enable_autoscale, force_symmetric, freewheel_mode)
        except ip_connection.Error:
            return

    def coolstep_configuration_changed(self, _):
        minimum_stallguard_value = self.minimum_stallguard_value_spin.value()
        maximum_stallguard_value = self.maximum_stallguard_value_spin.value()
        current_up_step_width = self.current_up_step_width_combo.currentIndex()
        current_down_step_width = self.current_down_step_width_combo.currentIndex()
        minimum_current = self.minimum_current_combo.currentIndex()
        stallguard_threshold_value = self.stallguard_threshold_value_spin.value()
        stallguard_mode = self.stallguard_mode_combo.currentIndex()

        try:
            self.silent_stepper.set_coolstep_configuration(minimum_stallguard_value, maximum_stallguard_value, current_up_step_width, current_down_step_width, minimum_current, stallguard_threshold_value, stallguard_mode)
        except ip_connection.Error:
            return

    def misc_configuration_changed(self, _):
        disable_short_to_ground_protection = self.disable_short_to_ground_protection_checkbox.isChecked()
        synchronize_phase_frequency = self.synchronize_phase_frequency_spin.value()

        try:
            self.silent_stepper.set_misc_configuration(disable_short_to_ground_protection, synchronize_phase_frequency)
        except ip_connection.Error:
            return

    def forward_clicked(self):
        try:
            self.silent_stepper.drive_forward()
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, self.steps_button])

    def backward_clicked(self):
        try:
            self.silent_stepper.drive_backward()
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, self.steps_button])

    def stop_clicked(self):
        try:
            self.silent_stepper.stop()
        except ip_connection.Error:
            return
        self.endis_all(True)

    def full_brake_clicked(self):
        try:
            self.silent_stepper.full_brake()
        except ip_connection.Error:
            return
        self.endis_all(True)

    def to_button_clicked(self):
        drive_to = self.to_spin.value()
        try:
            self.silent_stepper.set_target_position(drive_to)
        except ip_connection.Error:
            return
        self.disable_list([self.to_button,
                           self.steps_button,
                           self.forward_button,
                           self.backward_button])

    def steps_button_clicked(self):
        drive_steps = self.steps_spin.value()
        try:
            self.silent_stepper.set_steps(drive_steps)
        except ip_connection.Error:
            return
        self.disable_list([self.to_button,
                           self.steps_button,
                           self.forward_button,
                           self.backward_button])

    def motor_current_button_clicked(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(360)
        qid.setIntMaximum(1640)
        qid.setIntStep(100)
        async_call(self.silent_stepper.get_motor_current, None, qid.setIntValue, self.increase_error_count)
        qid.intValueSelected.connect(self.motor_current_selected)
        qid.setLabelText("Choose motor current in mA.")
        qid.open()

    def minimum_motor_voltage_button_clicked(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(0)
        qid.setIntMaximum(40000)
        qid.setIntStep(100)
        async_call(self.silent_stepper.get_minimum_voltage, None, qid.setIntValue, self.increase_error_count)
        qid.intValueSelected.connect(self.minimum_motor_voltage_selected)
        qid.setLabelText("Choose minimum motor voltage in mV.")
        qid.open()

    def motor_current_selected(self, value):
        try:
            self.silent_stepper.set_motor_current(value)
        except ip_connection.Error:
            return

    def minimum_motor_voltage_selected(self, value):
        try:
            self.silent_stepper.set_minimum_voltage(value)
        except ip_connection.Error:
            return

    def cb_under_voltage(self, ov):
        mv_str = self.minimum_voltage_label.text()
        ov_str = "%gV"  % round(ov/1000.0, 1)
        if not self.qem.isVisible():
            self.qem.showMessage("Under Voltage: Output Voltage of " + ov_str +
                                 " is below minimum voltage of " + mv_str,
                                 "SilentStepper_UnderVoltage")

    def enable_state_changed(self, state):
        try:
            if state == Qt.Checked:
                self.endis_all(True)
                self.silent_stepper.enable()
            elif state == Qt.Unchecked:
                self.endis_all(False)
                self.silent_stepper.disable()
        except ip_connection.Error:
            return

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

    def external_input_voltage_update(self, ev):
        ev_str = "%gV"  % round(ev/1000.0, 1)
        self.external_voltage_label.setText(ev_str)

    def minimum_voltage_update(self, mv):
        mv_str = "%gV"  % round(mv/1000.0, 1)
        self.minimum_voltage_label.setText(mv_str)

    def maximum_current_update(self, cur):
        cur_str = "%gA"  % round(cur/1000.0, 1)
        self.maximum_current_label.setText(cur_str)

    def position_update(self, pos):
        pos_str = "%d" % pos
        self.position_label.setText(pos_str)

    def remaining_steps_update(self, ste):
        ste_str = "%d" % ste
        self.remaining_steps_label.setText(ste_str)

    def driver_status_update(self, update):
        if update.open_load == 0:
            self.status_open_load.setText('No')
        elif update.open_load == 1:
            self.status_open_load.setText('Phase A')
        elif update.open_load == 2:
            self.status_open_load.setText('Phase B')
        elif update.open_load == 3:
            self.status_open_load.setText('Phase A and B')
        else:
            self.status_open_load.setText('Unknown')

        if update.short_to_ground == 0:
            self.status_short_to_ground.setText('No')
        elif update.short_to_ground == 1:
            self.status_short_to_ground.setText('Phase A')
        elif update.short_to_ground == 2:
            self.status_short_to_ground.setText('Phase B')
        elif update.short_to_ground == 3:
            self.status_short_to_ground.setText('Phase A and B')
        else:
            self.status_short_to_ground.setText('Unknown')

        if update.over_temperature == 0:
            self.status_over_temperature.setText('No')
        elif update.over_temperature == 1:
            self.status_over_temperature.setText('<font color=yellow>Warning</font>')
        elif update.over_temperature == 2:
            self.status_over_temperature.setText('<font color=red>Limit</font>')

        if update.motor_stalled:
            self.status_motor_stalled.setText('Yes')
        else:
            self.status_motor_stalled.setText('No')

        self.status_actual_motor_current.setText(str(update.actual_motor_current))

        if update.full_step_active:
            self.status_full_step_active.setText('Yes')
        else:
            self.status_full_step_active.setText('No')

        self.status_stallguard_result.setText(str(update.stallguard_result))
        self.status_stealth_voltage_amplitude.setText(str(update.stealth_voltage_amplitude))

    def get_max_velocity_async(self, velocity):
        if not self.velocity_slider.isSliderDown():
            if velocity != self.velocity_slider.sliderPosition():
                self.velocity_slider.setSliderPosition(velocity)
                self.velocity_spin.setValue(velocity)

    def get_speed_ramping_async(self, ramp):
        acc, dec = ramp
        if not self.acceleration_slider.isSliderDown() and \
           not self.deceleration_slider.isSliderDown():
            if acc != self.acceleration_slider.sliderPosition():
                self.acceleration_slider.setSliderPosition(acc)
                self.acceleration_spin.setValue(acc)
            if dec != self.deceleration_slider.sliderPosition():
                self.deceleration_slider.setSliderPosition(dec)
                self.deceleration_spin.setValue(dec)

    def is_enabled_async(self, enabled):
        if enabled:
            if not self.enable_checkbox.isChecked():
                self.endis_all(True)
                self.enable_checkbox.blockSignals(True)
                self.enable_checkbox.setChecked(True)
                self.enable_checkbox.blockSignals(False)
        else:
            if self.enable_checkbox.isChecked():
                self.endis_all(False)
                self.enable_checkbox.blockSignals(True)
                self.enable_checkbox.setChecked(False)
                self.enable_checkbox.blockSignals(False)

    def get_step_configuration_async(self, conf):
        self.step_resolution_dropbox.blockSignals(True)
        self.step_resolution_dropbox.setCurrentIndex(conf.step_resolution)
        self.step_resolution_dropbox.blockSignals(False)

        self.interpolate_checkbox.blockSignals(True)
        self.interpolate_checkbox.setChecked(conf.interpolation)
        self.interpolate_checkbox.blockSignals(False)

    def get_basic_configuration_async(self, conf):
        self.standstill_current_spin.blockSignals(True)
        self.standstill_current_spin.setValue(conf.standstill_current)
        self.standstill_current_spin.blockSignals(False)

        self.motor_run_current_spin.blockSignals(True)
        self.motor_run_current_spin.setValue(conf.motor_run_current)
        self.motor_run_current_spin.blockSignals(False)

        self.standstill_delay_time_spin.blockSignals(True)
        self.standstill_delay_time_spin.setValue(conf.standstill_delay_time)
        self.standstill_delay_time_spin.blockSignals(False)

        self.power_down_time_spin.blockSignals(True)
        self.power_down_time_spin.setValue(conf.power_down_time)
        self.power_down_time_spin.blockSignals(False)

        self.stealth_threshold_spin.blockSignals(True)
        self.stealth_threshold_spin.setValue(conf.stealth_threshold)
        self.stealth_threshold_spin.blockSignals(False)

        self.coolstep_threashold_spin.blockSignals(True)
        self.coolstep_threashold_spin.setValue(conf.coolstep_threshold)
        self.coolstep_threashold_spin.blockSignals(False)

        self.classic_threshold_spin.blockSignals(True)
        self.classic_threshold_spin.setValue(conf.classic_threshold)
        self.classic_threshold_spin.blockSignals(False)

        self.high_velocity_chopper_mode_checkbox.blockSignals(True)
        self.high_velocity_chopper_mode_checkbox.setChecked(conf.high_velocity_chopper_mode)
        self.high_velocity_chopper_mode_checkbox.blockSignals(False)

    def get_spreadcycle_configuration_async(self, conf):
        self.slow_decay_duration_spin.blockSignals(True)
        self.slow_decay_duration_spin.setValue(conf.slow_decay_duration)
        self.slow_decay_duration_spin.blockSignals(False)

        self.enable_random_slow_decay_checkbox.blockSignals(True)
        self.enable_random_slow_decay_checkbox.setChecked(conf.enable_random_slow_decay)
        self.enable_random_slow_decay_checkbox.blockSignals(False)

        self.fast_decay_duration_spin.blockSignals(True)
        self.fast_decay_duration_spin.setValue(conf.fast_decay_duration)
        self.fast_decay_duration_spin.blockSignals(False)

        self.hysteresis_start_value_spin.blockSignals(True)
        self.hysteresis_start_value_spin.setValue(conf.hysteresis_start_value)
        self.hysteresis_start_value_spin.blockSignals(False)

        self.hysteresis_end_value_spin.blockSignals(True)
        self.hysteresis_end_value_spin.setValue(conf.hysteresis_end_value)
        self.hysteresis_end_value_spin.blockSignals(False)

        self.sine_wave_offset_spin.blockSignals(True)
        self.sine_wave_offset_spin.setValue(conf.sine_wave_offset)
        self.sine_wave_offset_spin.blockSignals(False)

        self.chopper_mode_combo.blockSignals(True)
        self.chopper_mode_combo.setCurrentIndex(conf.chopper_mode)
        self.chopper_mode_combo.blockSignals(False)

        self.standstill_current_spin.blockSignals(True)
        self.comparator_blank_time_combo.setCurrentIndex(conf.comparator_blank_time)
        self.standstill_current_spin.blockSignals(False)

        self.fast_decay_without_comparator_checkbox.blockSignals(True)
        self.fast_decay_without_comparator_checkbox.setChecked(conf.fast_decay_without_comparator)
        self.fast_decay_without_comparator_checkbox.blockSignals(False)


    def get_stealth_configuration_async(self, conf):
        self.enable_stealth_checkbox.blockSignals(True)
        self.enable_stealth_checkbox.setChecked(conf.enable_stealth)
        self.enable_stealth_checkbox.blockSignals(False)

        self.amplitude_spin.blockSignals(True)
        self.amplitude_spin.setValue(conf.amplitude)
        self.amplitude_spin.blockSignals(False)

        self.gradient_spin.blockSignals(True)
        self.gradient_spin.setValue(conf.gradient)
        self.gradient_spin.blockSignals(False)

        self.enable_autoscale_checkbox.blockSignals(True)
        self.enable_autoscale_checkbox.setChecked(conf.enable_autoscale)
        self.enable_autoscale_checkbox.blockSignals(False)

        self.force_symmetric_checkbox.blockSignals(True)
        self.force_symmetric_checkbox.setChecked(conf.force_symmetric)
        self.force_symmetric_checkbox.blockSignals(False)

        self.freewheel_mode_combo.blockSignals(True)
        self.freewheel_mode_combo.setCurrentIndex(conf.freewheel_mode)
        self.freewheel_mode_combo.blockSignals(False)

    def get_coolstep_configuration_async(self, conf):
        self.minimum_stallguard_value_spin.blockSignals(True)
        self.minimum_stallguard_value_spin.setValue(conf.minimum_stallguard_value)
        self.minimum_stallguard_value_spin.blockSignals(False)

        self.maximum_stallguard_value_spin.blockSignals(True)
        self.maximum_stallguard_value_spin.setValue(conf.maximum_stallguard_value)
        self.maximum_stallguard_value_spin.blockSignals(False)

        self.current_up_step_width_combo.blockSignals(True)
        self.current_up_step_width_combo.setCurrentIndex(conf.current_up_step_width)
        self.current_up_step_width_combo.blockSignals(False)

        self.current_down_step_width_combo.blockSignals(True)
        self.current_down_step_width_combo.setCurrentIndex(conf.current_down_step_width)
        self.current_down_step_width_combo.blockSignals(False)

        self.minimum_current_combo.blockSignals(True)
        self.minimum_current_combo.setCurrentIndex(conf.minimum_current)
        self.minimum_current_combo.blockSignals(False)

        self.stallguard_threshold_value_spin.blockSignals(True)
        self.stallguard_threshold_value_spin.setValue(conf.stallguard_threshold_value)
        self.stallguard_threshold_value_spin.blockSignals(False)

        self.stallguard_mode_combo.blockSignals(True)
        self.stallguard_mode_combo.setCurrentIndex(conf.stallguard_mode)
        self.stallguard_mode_combo.blockSignals(False)

    def get_misc_configuration_async(self, conf):
        self.disable_short_to_ground_protection_checkbox.blockSignals(True)
        self.disable_short_to_ground_protection_checkbox.setChecked(conf.disable_short_to_ground_protection)
        self.disable_short_to_ground_protection_checkbox.blockSignals(False)

        self.synchronize_phase_frequency_spin.blockSignals(True)
        self.synchronize_phase_frequency_spin.setValue(conf.synchronize_phase_frequency)
        self.synchronize_phase_frequency_spin.blockSignals(False)

    def update_start(self):
        async_call(self.silent_stepper.get_max_velocity, None, self.get_max_velocity_async, self.increase_error_count)
        async_call(self.silent_stepper.get_speed_ramping, None, self.get_speed_ramping_async, self.increase_error_count)
        async_call(self.silent_stepper.is_enabled, None, self.is_enabled_async, self.increase_error_count)
        async_call(self.silent_stepper.get_step_configuration, None, self.get_step_configuration_async, self.increase_error_count)
        async_call(self.silent_stepper.get_basic_configuration, None, self.get_basic_configuration_async, self.increase_error_count)
        async_call(self.silent_stepper.get_spreadcycle_configuration, None, self.get_spreadcycle_configuration_async, self.increase_error_count)
        async_call(self.silent_stepper.get_stealth_configuration, None, self.get_stealth_configuration_async, self.increase_error_count)
        async_call(self.silent_stepper.get_coolstep_configuration, None, self.get_coolstep_configuration_async, self.increase_error_count)
        async_call(self.silent_stepper.get_misc_configuration, None, self.get_misc_configuration_async, self.increase_error_count)

    def update_data(self):
        async_call(self.silent_stepper.get_remaining_steps, None, self.remaining_steps_update, self.increase_error_count)
        async_call(self.silent_stepper.get_current_position, None, self.position_update, self.increase_error_count)
        async_call(self.silent_stepper.get_current_velocity, None, self.speedometer.set_velocity, self.increase_error_count)

        self.update_counter += 1
        if self.update_counter % 10 == 0:
            async_call(self.silent_stepper.get_motor_current, None, self.maximum_current_update, self.increase_error_count)
            async_call(self.silent_stepper.get_stack_input_voltage, None, self.stack_input_voltage_update, self.increase_error_count)
            async_call(self.silent_stepper.get_external_input_voltage, None, self.external_input_voltage_update, self.increase_error_count)
            async_call(self.silent_stepper.get_minimum_voltage, None, self.minimum_voltage_update, self.increase_error_count)
            async_call(self.silent_stepper.get_driver_status, None, self.driver_status_update, self.increase_error_count)

    def velocity_changed(self, value):
        try:
            self.silent_stepper.set_max_velocity(value)
        except ip_connection.Error:
            return

    def acceleration_changed(self, value):
        dec = self.deceleration_spin.value()
        try:
            self.silent_stepper.set_speed_ramping(value, dec)
        except ip_connection.Error:
            return

    def deceleration_changed(self, value):
        acc = self.acceleration_slider.value()
        try:
            self.silent_stepper.set_speed_ramping(acc, value)
        except ip_connection.Error:
            return
Ejemplo n.º 10
0
class WeatherStation(QApplication):
    HOST = "localhost"
    PORT = 4223

    ipcon = None
    lcd = None
    al = None
    al_v2 = None
    hum = None
    baro = None

    projects = []
    active_project = None

    error_msg = None

    def __init__(self, args):
        super(QApplication, self).__init__(args)

        self.error_msg = QErrorMessage()
        self.ipcon = IPConnection()

        signal.signal(signal.SIGINT, self.exit_demo)
        signal.signal(signal.SIGTERM, self.exit_demo)

        timer = QTimer(self)
        timer.setSingleShot(True)
        timer.timeout.connect(self.connect)
        timer.start(1)

        self.lcd_timer = QTimer(self)
        self.lcd_timer.timeout.connect(self.mute_lcd)
        self.lcd_timer.start(10000)

    def exit_demo(self, signl=None, frme=None):
        try:
            self.ipcon.disconnect()
            self.timer.stop()
            self.tabs.destroy()
        except:
            pass

        sys.exit()

    def open_gui(self):
        self.main = MainWindow(self)
        self.main.setFixedSize(930, 530)
        self.main.setWindowIcon(
            QIcon(load_pixmap('starter_kit_weather_station_demo-icon.png')))

        self.tabs = QTabWidget()

        widget = QWidget()
        layout = QVBoxLayout()
        layout.addWidget(self.tabs)
        widget.setLayout(layout)

        self.main.setCentralWidget(widget)

        self.projects.append(ProjectEnvDisplay(self.tabs, self))
        self.projects.append(ProjectStatistics(self.tabs, self))
        self.projects.append(ProjectXively(self.tabs, self))

        self.tabs.addTab(self.projects[0], "Display Environment Measurements")
        self.tabs.addTab(self.projects[1],
                         "Show Statistics with Button Control")
        self.tabs.addTab(self.projects[2], "Connect to Xively")

        self.active_project = self.projects[0]

        self.tabs.currentChanged.connect(self.tabChangedSlot)
        self.tabs.setCurrentIndex(1)

        self.main.setWindowTitle("Starter Kit: Weather Station Demo " +
                                 DEMO_VERSION)
        self.main.show()

    def connect(self):
        try:
            self.ipcon.connect(WeatherStation.HOST, WeatherStation.PORT)
        except Error as e:
            self.error_msg.showMessage('Connection Error: ' +
                                       str(e.description) +
                                       "\nBrickd installed and running?")
            return
        except socket.error as e:
            self.error_msg.showMessage('Socket error: ' + str(e) +
                                       "\nBrickd installed and running?")
            return

        self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE,
                                     self.cb_enumerate)
        self.ipcon.register_callback(IPConnection.CALLBACK_CONNECTED,
                                     self.cb_connected)

        try:
            self.ipcon.enumerate()
        except Error as e:
            self.error_msg.showMessage('Enumerate Error: ' +
                                       str(e.description))
            return

        self.open_gui()

    def tabChangedSlot(self, tabIndex):

        if self.lcd is not None:
            self.lcd.clear_display()

        self.active_project = self.projects[tabIndex]

    def cb_illuminance(self, illuminance):
        for p in self.projects:
            p.update_illuminance(illuminance / 10.0)

    def cb_illuminance_v2(self, illuminance):
        for p in self.projects:
            p.update_illuminance(illuminance / 100.0)

    def cb_humidity(self, humidity):
        for p in self.projects:
            p.update_humidity(humidity / 10.0)

    def cb_air_pressure(self, air_pressure):
        for p in self.projects:
            p.update_air_pressure(air_pressure / 1000.0)

        try:
            temperature = self.baro.get_chip_temperature()
        except Error as e:
            print('Could not get temperature: ' + str(e.description))
            return

        for p in self.projects:
            p.update_temperature(temperature / 100.0)

    def configure_custom_chars(self):
        c = [[0x00 for x in range(8)] for y in range(8)]

        c[0] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff]
        c[1] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff]
        c[2] = [0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff]
        c[3] = [0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]
        c[4] = [0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff]
        c[5] = [0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
        c[6] = [0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
        c[7] = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]

        for i in range(len(c)):
            self.lcd.set_custom_character(i, c[i])

    def cb_button_pressed(self, button):
        if self.lcd.is_backlight_on():
            for p in self.projects:
                p.button_pressed(button)
        else:
            self.lcd.backlight_on()
            self.lcd_timer.start()

    def mute_lcd(self):
        self.lcd.backlight_off()

    def cb_enumerate(self, uid, connected_uid, position, hardware_version,
                     firmware_version, device_identifier, enumeration_type):
        if enumeration_type == IPConnection.ENUMERATION_TYPE_CONNECTED or \
           enumeration_type == IPConnection.ENUMERATION_TYPE_AVAILABLE:
            if device_identifier == LCD20x4.DEVICE_IDENTIFIER:
                try:
                    self.lcd = LCD20x4(uid, self.ipcon)
                    self.lcd.clear_display()
                    self.lcd.backlight_on()
                    self.lcd.register_callback(
                        self.lcd.CALLBACK_BUTTON_PRESSED,
                        self.cb_button_pressed)
                    self.configure_custom_chars()
                except Error as e:
                    self.error_msg.showMessage('LCD 20x4 init failed: ' +
                                               str(e.description))
                    self.lcd = None
            elif device_identifier == AmbientLight.DEVICE_IDENTIFIER:
                try:
                    self.al = AmbientLight(uid, self.ipcon)
                    self.al.set_illuminance_callback_period(1000)
                    self.al.register_callback(self.al.CALLBACK_ILLUMINANCE,
                                              self.cb_illuminance)
                except Error as e:
                    self.error_msg.showMessage('Ambient Light init failed: ' +
                                               str(e.description))
                    self.al = None
            elif device_identifier == AmbientLightV2.DEVICE_IDENTIFIER:
                try:
                    self.al_v2 = AmbientLightV2(uid, self.ipcon)
                    self.al_v2.set_configuration(
                        AmbientLightV2.ILLUMINANCE_RANGE_64000LUX,
                        AmbientLightV2.INTEGRATION_TIME_200MS)
                    self.al_v2.set_illuminance_callback_period(1000)
                    self.al_v2.register_callback(
                        self.al_v2.CALLBACK_ILLUMINANCE,
                        self.cb_illuminance_v2)
                except Error as e:
                    self.error_msg.showMessage(
                        'Ambient Light 2.0 init failed: ' + str(e.description))
                    self.al = None
            elif device_identifier == Humidity.DEVICE_IDENTIFIER:
                try:
                    self.hum = Humidity(uid, self.ipcon)
                    self.hum.set_humidity_callback_period(1000)
                    self.hum.register_callback(self.hum.CALLBACK_HUMIDITY,
                                               self.cb_humidity)
                except Error as e:
                    self.error_msg.showMessage('Humidity init failed: ' +
                                               str(e.description))
                    self.hum = None
            elif device_identifier == Barometer.DEVICE_IDENTIFIER:
                try:
                    self.baro = Barometer(uid, self.ipcon)
                    self.baro.set_air_pressure_callback_period(1000)
                    self.baro.register_callback(
                        self.baro.CALLBACK_AIR_PRESSURE, self.cb_air_pressure)
                except Error as e:
                    self.error_msg.showMessage('Barometer init failed: ' +
                                               str(e.description))
                    self.baro = None

    def cb_connected(self, connected_reason):
        if connected_reason == IPConnection.CONNECT_REASON_AUTO_RECONNECT:

            while True:
                try:
                    self.ipcon.enumerate()
                    break
                except Error as e:
                    self.error_msg.showMessage('Enumerate Error: ' +
                                               str(e.description))
                    time.sleep(1)
Ejemplo n.º 11
0
class SilentStepper(PluginBase, Ui_SilentStepper):
    qtcb_position_reached = pyqtSignal(int)
    qtcb_under_voltage = pyqtSignal(int)
    
    def __init__(self, *args):
        PluginBase.__init__(self, BrickSilentStepper, *args)

        self.setupUi(self)
     
        self.silent_stepper = self.device
     
        self.endis_all(False)
        
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.update_data)

        self.speedometer = SpeedoMeter()
        self.vertical_layout_right.insertWidget(5, self.speedometer)
        
        self.new_value = 0
        self.update_counter = 0
        
        self.full_brake_time = 0

        self.qem = QErrorMessage(self)
        self.qem.setWindowTitle("Under Voltage")

        self.velocity_syncer = SliderSpinSyncer(self.velocity_slider,
                                                self.velocity_spin,
                                                self.velocity_changed)

        self.acceleration_syncer = SliderSpinSyncer(self.acceleration_slider,
                                                    self.acceleration_spin,
                                                    self.acceleration_changed)

        self.deceleration_syncer = SliderSpinSyncer(self.deceleration_slider,
                                                    self.deceleration_spin,
                                                    self.deceleration_changed)

        self.enable_checkbox.stateChanged.connect(self.enable_state_changed)
        self.forward_button.clicked.connect(self.forward_clicked)
        self.stop_button.clicked.connect(self.stop_clicked)
        self.full_brake_button.clicked.connect(self.full_brake_clicked)
        self.backward_button.clicked.connect(self.backward_clicked)
        self.to_button.clicked.connect(self.to_button_clicked)
        self.steps_button.clicked.connect(self.steps_button_clicked)
        self.motor_current_button.clicked.connect(self.motor_current_button_clicked)
        self.minimum_motor_voltage_button.clicked.connect(self.minimum_motor_voltage_button_clicked)

        self.qtcb_position_reached.connect(self.cb_position_reached)
        self.silent_stepper.register_callback(self.silent_stepper.CALLBACK_POSITION_REACHED, 
                                              self.qtcb_position_reached.emit)
        
        self.qtcb_under_voltage.connect(self.cb_under_voltage)
        self.silent_stepper.register_callback(self.silent_stepper.CALLBACK_UNDER_VOLTAGE, 
                                              self.qtcb_under_voltage.emit)
        
        # Step Configuration
        self.step_resolution_dropbox.currentIndexChanged.connect(self.step_configuration_changed)
        self.interpolate_checkbox.stateChanged.connect(self.step_configuration_changed)
        
        # Basic Configuration
        self.standstill_current_spin.valueChanged.connect(self.basic_configuration_changed)
        self.motor_run_current_spin.valueChanged.connect(self.basic_configuration_changed)
        self.standstill_delay_time_spin.valueChanged.connect(self.basic_configuration_changed)
        self.power_down_time_spin.valueChanged.connect(self.basic_configuration_changed)
        self.stealth_threshold_spin.valueChanged.connect(self.basic_configuration_changed)
        self.coolstep_threashold_spin.valueChanged.connect(self.basic_configuration_changed)
        self.classic_threshold_spin.valueChanged.connect(self.basic_configuration_changed)
        self.high_velocity_chopper_mode_checkbox.stateChanged.connect(self.basic_configuration_changed)
        
        # Spreadcycle Configuration
        self.slow_decay_duration_spin.valueChanged.connect(self.spreadcycle_configuration_changed)
        self.enable_random_slow_decay_checkbox.stateChanged.connect(self.spreadcycle_configuration_changed)
        self.fast_decay_duration_spin.valueChanged.connect(self.spreadcycle_configuration_changed)
        self.hysteresis_start_value_spin.valueChanged.connect(self.spreadcycle_configuration_changed)
        self.hysteresis_end_value_spin.valueChanged.connect(self.spreadcycle_configuration_changed)
        self.sinewave_offset_spin.valueChanged.connect(self.spreadcycle_configuration_changed)
        self.chopper_mode_combo.currentIndexChanged.connect(self.spreadcycle_configuration_changed)
        self.comperator_blank_time_combo.currentIndexChanged.connect(self.spreadcycle_configuration_changed)
        self.fast_decay_without_comperator_checkbox.stateChanged.connect(self.spreadcycle_configuration_changed)
        
        # Stealth Configuration
        self.enable_stealth_checkbox.stateChanged.connect(self.stealth_configuration_changed)
        self.amplitude_spin.valueChanged.connect(self.stealth_configuration_changed)
        self.gradient_spin.valueChanged.connect(self.stealth_configuration_changed)
        self.enable_autoscale_checkbox.stateChanged.connect(self.stealth_configuration_changed)
        self.force_symmetric_checkbox.stateChanged.connect(self.stealth_configuration_changed)
        self.freewheel_mode_combo.currentIndexChanged.connect(self.stealth_configuration_changed)
        
        # Coolstep Configuration
        self.minimum_stallguard_value_spin.valueChanged.connect(self.coolstep_configuration_changed)
        self.maximum_stallguard_value_spin.valueChanged.connect(self.coolstep_configuration_changed)
        self.current_up_step_width_combo.currentIndexChanged.connect(self.coolstep_configuration_changed)
        self.current_down_step_width_combo.currentIndexChanged.connect(self.coolstep_configuration_changed)
        self.minimum_current_combo.currentIndexChanged.connect(self.coolstep_configuration_changed)
        self.stallguard_threshold_value_spin.valueChanged.connect(self.coolstep_configuration_changed)
        self.stallguard_mode_combo.currentIndexChanged.connect(self.coolstep_configuration_changed)
        
        # Misc Configuration
        self.disable_short_to_ground_protection_checkbox.stateChanged.connect(self.misc_configuration_changed)
        self.synchronize_phase_frequency_spin.valueChanged.connect(self.misc_configuration_changed)
        
        self.ste = 0
        self.pos = 0
        self.current_velocity = 0
        self.cur = 0
        self.sv  = 0
        self.ev  = 0
        self.mv  = 0
        self.mod = 0

        reset = QAction('Reset', self)
        reset.triggered.connect(lambda: self.silent_stepper.reset())
        self.set_actions(reset)
        
    def start(self):
        self.update_timer.start(100)
        self.update_start()
        
    def stop(self):
        self.update_timer.stop()

    def destroy(self):
        pass

    def get_url_part(self):
        return 'silent_stepper'

    @staticmethod
    def has_device_identifier(device_identifier):
        return device_identifier == BrickSilentStepper.DEVICE_IDENTIFIER
    
    def cb_position_reached(self, position):
        self.position_update(position)
        self.endis_all(True)
            
    def disable_list(self, button_list):
        for button in button_list:
            button.setEnabled(False)
        
    def endis_all(self, value):
        self.forward_button.setEnabled(value)
        self.stop_button.setEnabled(value)
        self.backward_button.setEnabled(value)
        self.to_button.setEnabled(value)
        self.steps_button.setEnabled(value)
        self.full_brake_button.setEnabled(value)
        
    def step_configuration_changed(self, _):
        step_resolution = self.step_resolution_dropbox.currentIndex()
        interpolation = self.interpolate_checkbox.isChecked()
        try:
            self.silent_stepper.set_step_configuration(step_resolution, interpolation)
        except ip_connection.Error:
            return
        
    def basic_configuration_changed(self, _):
        standstill_current = self.standstill_current_spin.value()
        motor_run_current = self.motor_run_current_spin.value()
        standstill_delay_time = self.standstill_delay_time_spin.value()
        power_down_time = self.power_down_time_spin.value()
        stealth_threshold = self.stealth_threshold_spin.value()
        coolstep_threshold = self.coolstep_threashold_spin.value()
        classic_threshold = self.classic_threshold_spin.value()
        high_velocity_chopper_mode = self.high_velocity_chopper_mode_checkbox.isChecked()
        
        try:
            self.silent_stepper.set_basic_configuration(standstill_current, motor_run_current, standstill_delay_time, power_down_time, stealth_threshold, coolstep_threshold, classic_threshold, high_velocity_chopper_mode)
        except ip_connection.Error:
            return

    def spreadcycle_configuration_changed(self, _):
        slow_decay_duration = self.slow_decay_duration_spin.value()
        enable_random_slow_decay = self.enable_random_slow_decay_checkbox.isChecked()
        fast_decay_duration = self.fast_decay_duration_spin.value()
        hysteresis_start_value = self.hysteresis_start_value_spin.value()
        hysteresis_end_value = self.hysteresis_end_value_spin.value()
        sinewave_offset = self.sinewave_offset_spin.value()
        chopper_mode = self.chopper_mode_combo.currentIndex()
        comperator_blank_time = self.comperator_blank_time_combo.currentIndex()
        fast_decay_without_comperator = self.fast_decay_without_comperator_checkbox.isChecked()
        
        try:
            self.silent_stepper.set_spreadcycle_configuration(slow_decay_duration, enable_random_slow_decay, fast_decay_duration, hysteresis_start_value, hysteresis_end_value, sinewave_offset, chopper_mode, comperator_blank_time, fast_decay_without_comperator)
        except ip_connection.Error:
            return
        
    def stealth_configuration_changed(self, _):
        enable_stealth = self.enable_stealth_checkbox.isChecked()
        amplitude = self.amplitude_spin.value()
        gradient = self.gradient_spin.value()
        enable_autoscale = self.enable_autoscale_checkbox.isChecked()
        force_symmetric = self.force_symmetric_checkbox.isChecked()
        freewheel_mode = self.freewheel_mode_combo.currentIndex()
        
        try:
            self.silent_stepper.set_stealth_configuration(enable_stealth, amplitude, gradient, enable_autoscale, force_symmetric, freewheel_mode)
        except ip_connection.Error:
            return
        
    def coolstep_configuration_changed(self, _):
        minimum_stallguard_value = self.minimum_stallguard_value_spin.value()
        maximum_stallguard_value = self.maximum_stallguard_value_spin.value()
        current_up_step_width = self.current_up_step_width_combo.currentIndex()
        current_down_step_width = self.current_down_step_width_combo.currentIndex()
        minimum_current = self.minimum_current_combo.currentIndex()
        stallguard_threshold_value = self.stallguard_threshold_value_spin.value()
        stallguard_mode = self.stallguard_mode_combo.currentIndex()
        
        try:
            self.silent_stepper.set_coolstep_configuration(minimum_stallguard_value, maximum_stallguard_value, current_up_step_width, current_down_step_width, minimum_current, stallguard_threshold_value, stallguard_mode)
        except ip_connection.Error:
            return
        
    def misc_configuration_changed(self, _):
        disable_short_to_ground_protection = self.disable_short_to_ground_protection_checkbox.isChecked()
        synchronize_phase_frequency = self.synchronize_phase_frequency_spin.value()
        
        try:
            self.silent_stepper.set_misc_configuration(disable_short_to_ground_protection, synchronize_phase_frequency)
        except ip_connection.Error:
            return
        
    def forward_clicked(self):
        try:
            self.silent_stepper.drive_forward()
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, self.steps_button])
        
    def backward_clicked(self):
        try:
            self.silent_stepper.drive_backward()
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, self.steps_button])
        
    def stop_clicked(self):
        try:
            self.silent_stepper.stop()
        except ip_connection.Error:
            return
        self.endis_all(True)
        
    def full_brake_clicked(self):
        try:
            self.silent_stepper.full_brake()
        except ip_connection.Error:
            return
        self.endis_all(True)
        
    def to_button_clicked(self):
        drive_to = self.to_spin.value()
        try:
            self.silent_stepper.set_target_position(drive_to)
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, 
                           self.steps_button, 
                           self.forward_button,
                           self.backward_button])
        
    def steps_button_clicked(self):
        drive_steps = self.steps_spin.value()
        try:
            self.silent_stepper.set_steps(drive_steps)
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, 
                           self.steps_button, 
                           self.forward_button,
                           self.backward_button])
        
    def motor_current_button_clicked(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(0)
        qid.setIntMaximum(2500)
        qid.setIntStep(100)
        async_call(self.silent_stepper.get_motor_current, None, qid.setIntValue, self.increase_error_count)
        qid.intValueSelected.connect(self.motor_current_selected)
        qid.setLabelText("Choose motor current in mA.")
        qid.open()
        
    def minimum_motor_voltage_button_clicked(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(0)
        qid.setIntMaximum(40000)
        qid.setIntStep(100)
        async_call(self.silent_stepper.get_minimum_voltage, None, qid.setIntValue, self.increase_error_count)
        qid.intValueSelected.connect(self.minimum_motor_voltage_selected)
        qid.setLabelText("Choose minimum motor voltage in mV.")
        qid.open()
        
    def motor_current_selected(self, value):
        try:
            self.silent_stepper.set_motor_current(value)
        except ip_connection.Error:
            return
        
    def minimum_motor_voltage_selected(self, value):
        try:
            self.silent_stepper.set_minimum_voltage(value)
        except ip_connection.Error:
            return
        
    def cb_under_voltage(self, ov):
        mv_str = self.minimum_voltage_label.text()
        ov_str = "%gV"  % round(ov/1000.0, 1)
        if not self.qem.isVisible():
            self.qem.showMessage("Under Voltage: Output Voltage of " + ov_str +
                                 " is below minimum voltage of " + mv_str,
                                 "SilentStepper_UnderVoltage")
        
    def enable_state_changed(self, state):
        try:
            if state == Qt.Checked:
                self.endis_all(True)
                self.silent_stepper.enable()
            elif state == Qt.Unchecked:
                self.endis_all(False)
                self.silent_stepper.disable()
        except ip_connection.Error:
            return
        
    def stack_input_voltage_update(self, sv):
        sv_str = "%gV"  % round(sv/1000.0, 1)
        self.stack_voltage_label.setText(sv_str)
        
    def external_input_voltage_update(self, ev):
        ev_str = "%gV"  % round(ev/1000.0, 1)
        self.external_voltage_label.setText(ev_str)
        
    def minimum_voltage_update(self, mv):
        mv_str = "%gV"  % round(mv/1000.0, 1)
        self.minimum_voltage_label.setText(mv_str)
        
    def maximum_current_update(self, cur):
        cur_str = "%gA"  % round(cur/1000.0, 1)
        self.maximum_current_label.setText(cur_str)
        
    def position_update(self, pos):
        pos_str = "%d" % pos
        self.position_label.setText(pos_str)
        
    def remaining_steps_update(self, ste):
        ste_str = "%d" % ste
        self.remaining_steps_label.setText(ste_str)
        
    def driver_status_update(self, update):
        if update.open_load == 0:
            self.status_open_load.setText('No')
        elif update.open_load == 1:
            self.status_open_load.setText('Phase A')
        elif update.open_load == 2:
            self.status_open_load.setText('Phase B')
        elif update.open_load == 3:
            self.status_open_load.setText('Phase A and B')
        else:
            self.status_open_load.setText('Unkown')
            
        if update.short_to_ground == 0:
            self.status_short_to_ground.setText('No')
        elif update.short_to_ground == 1:
            self.status_short_to_ground.setText('Phase A')
        elif update.short_to_ground == 2:
            self.status_short_to_ground.setText('Phase B')
        elif update.short_to_ground == 3:
            self.status_short_to_ground.setText('Phase A and B')
        else:
            self.status_short_to_ground.setText('Unkown')
            
        if update.over_temperature == 0:
            self.status_over_temperature.setText('No')
        elif update.over_temperature == 1:
            self.status_over_temperature.setText('<font color=yellow>Warning</font>')
        elif update.over_temperature == 2:
            self.status_over_temperature.setText('<font color=red>Limit</font>')
        
        if update.motor_stalled:
            self.status_motor_stalled.setText('Yes')
        else:
            self.status_motor_stalled.setText('No')
            
        self.status_actual_motor_current.setText(str(update.actual_motor_current))
        
        if update.full_step_active:
            self.status_full_step_active.setText('Yes')
        else:
            self.status_full_step_active.setText('No')
            
        self.status_stallguard_result.setText(str(update.stallguard_result))
        self.status_stealth_voltage_amplitude.setText(str(update.stealth_voltage_amplitude))
            
    def get_max_velocity_async(self, velocity):
        if not self.velocity_slider.isSliderDown():
            if velocity != self.velocity_slider.sliderPosition():
                self.velocity_slider.setSliderPosition(velocity)
                self.velocity_spin.setValue(velocity)
        
    def get_speed_ramping_async(self, ramp):
        acc, dec = ramp
        if not self.acceleration_slider.isSliderDown() and \
           not self.deceleration_slider.isSliderDown():
            if acc != self.acceleration_slider.sliderPosition():
                self.acceleration_slider.setSliderPosition(acc)
                self.acceleration_spin.setValue(acc)
            if dec != self.deceleration_slider.sliderPosition():
                self.deceleration_slider.setSliderPosition(dec)
                self.deceleration_spin.setValue(dec)
        
    def is_enabled_async(self, enabled):
        if enabled:
            if not self.enable_checkbox.isChecked():
                self.endis_all(True)
                self.enable_checkbox.blockSignals(True)
                self.enable_checkbox.setChecked(True)
                self.enable_checkbox.blockSignals(False)
        else:
            if self.enable_checkbox.isChecked():
                self.endis_all(False)
                self.enable_checkbox.blockSignals(True)
                self.enable_checkbox.setChecked(False)
                self.enable_checkbox.blockSignals(False)
                        
    def get_step_configuration_async(self, conf):
        self.step_resolution_dropbox.blockSignals(True)
        self.step_resolution_dropbox.setCurrentIndex(conf.step_resolution)
        self.step_resolution_dropbox.blockSignals(False)
        
        self.interpolate_checkbox.blockSignals(True)
        self.interpolate_checkbox.setChecked(conf.interpolation)
        self.interpolate_checkbox.blockSignals(False)
        
    def get_basic_configuration_async(self, conf):
        self.standstill_current_spin.blockSignals(True)
        self.standstill_current_spin.setValue(conf.standstill_current)
        self.standstill_current_spin.blockSignals(False)

        self.motor_run_current_spin.blockSignals(True)
        self.motor_run_current_spin.setValue(conf.motor_run_current)
        self.motor_run_current_spin.blockSignals(False)
        
        self.standstill_delay_time_spin.blockSignals(True)
        self.standstill_delay_time_spin.setValue(conf.standstill_delay_time)
        self.standstill_delay_time_spin.blockSignals(False)
        
        self.power_down_time_spin.blockSignals(True)
        self.power_down_time_spin.setValue(conf.power_down_time)
        self.power_down_time_spin.blockSignals(False)
        
        self.stealth_threshold_spin.blockSignals(True)
        self.stealth_threshold_spin.setValue(conf.stealth_threshold)
        self.stealth_threshold_spin.blockSignals(False)
        
        self.coolstep_threashold_spin.blockSignals(True)
        self.coolstep_threashold_spin.setValue(conf.coolstep_threshold)
        self.coolstep_threashold_spin.blockSignals(False)
        
        self.classic_threshold_spin.blockSignals(True)
        self.classic_threshold_spin.setValue(conf.classic_threshold)
        self.classic_threshold_spin.blockSignals(False)
        
        self.high_velocity_chopper_mode_checkbox.blockSignals(True)
        self.high_velocity_chopper_mode_checkbox.setChecked(conf.high_velocity_chopper_mode)
        self.high_velocity_chopper_mode_checkbox.blockSignals(False)
    
    def get_spreadcycle_configuration_async(self, conf):
        self.slow_decay_duration_spin.blockSignals(True)
        self.slow_decay_duration_spin.setValue(conf.slow_decay_duration)
        self.slow_decay_duration_spin.blockSignals(False)
        
        self.enable_random_slow_decay_checkbox.blockSignals(True)
        self.enable_random_slow_decay_checkbox.setChecked(conf.enable_random_slow_decay)
        self.enable_random_slow_decay_checkbox.blockSignals(False)
        
        self.fast_decay_duration_spin.blockSignals(True)
        self.fast_decay_duration_spin.setValue(conf.fast_decay_duration)
        self.fast_decay_duration_spin.blockSignals(False)
        
        self.hysteresis_start_value_spin.blockSignals(True)
        self.hysteresis_start_value_spin.setValue(conf.hysteresis_start_value)
        self.hysteresis_start_value_spin.blockSignals(False)
        
        self.hysteresis_end_value_spin.blockSignals(True)
        self.hysteresis_end_value_spin.setValue(conf.hysteresis_end_value)
        self.hysteresis_end_value_spin.blockSignals(False)
        
        self.sinewave_offset_spin.blockSignals(True)
        self.sinewave_offset_spin.setValue(conf.sinewave_offset)
        self.sinewave_offset_spin.blockSignals(False)
        
        self.chopper_mode_combo.blockSignals(True)
        self.chopper_mode_combo.setCurrentIndex(conf.chopper_mode)
        self.chopper_mode_combo.blockSignals(False)
        
        self.standstill_current_spin.blockSignals(True)
        self.comperator_blank_time_combo.setCurrentIndex(conf.comperator_blank_time)
        self.standstill_current_spin.blockSignals(False)
        
        self.fast_decay_without_comperator_checkbox.blockSignals(True)
        self.fast_decay_without_comperator_checkbox.setChecked(conf.fast_decay_without_comperator)
        self.fast_decay_without_comperator_checkbox.blockSignals(False)
        
    
    def get_stealth_configuration_async(self, conf):
        self.enable_stealth_checkbox.blockSignals(True)
        self.enable_stealth_checkbox.setChecked(conf.enable_stealth)
        self.enable_stealth_checkbox.blockSignals(False)
        
        self.amplitude_spin.blockSignals(True)
        self.amplitude_spin.setValue(conf.amplitude)
        self.amplitude_spin.blockSignals(False)
        
        self.gradient_spin.blockSignals(True)
        self.gradient_spin.setValue(conf.gradient)
        self.gradient_spin.blockSignals(False)
        
        self.enable_autoscale_checkbox.blockSignals(True)
        self.enable_autoscale_checkbox.setChecked(conf.enable_autoscale)
        self.enable_autoscale_checkbox.blockSignals(False)
        
        self.force_symmetric_checkbox.blockSignals(True)
        self.force_symmetric_checkbox.setChecked(conf.force_symmetric)
        self.force_symmetric_checkbox.blockSignals(False)
        
        self.freewheel_mode_combo.blockSignals(True)
        self.freewheel_mode_combo.setCurrentIndex(conf.freewheel_mode)
        self.freewheel_mode_combo.blockSignals(False)
    
    def get_coolstep_configuration_async(self, conf):
        self.minimum_stallguard_value_spin.blockSignals(True)
        self.minimum_stallguard_value_spin.setValue(conf.minimum_stallguard_value)
        self.minimum_stallguard_value_spin.blockSignals(False)
    
        self.maximum_stallguard_value_spin.blockSignals(True)
        self.maximum_stallguard_value_spin.setValue(conf.maximum_stallguard_value)
        self.maximum_stallguard_value_spin.blockSignals(False)
    
        self.current_up_step_width_combo.blockSignals(True)
        self.current_up_step_width_combo.setCurrentIndex(conf.current_up_step_width)
        self.current_up_step_width_combo.blockSignals(False)
    
        self.current_down_step_width_combo.blockSignals(True)
        self.current_down_step_width_combo.setCurrentIndex(conf.current_down_step_width)
        self.current_down_step_width_combo.blockSignals(False)
    
        self.minimum_current_combo.blockSignals(True)
        self.minimum_current_combo.setCurrentIndex(conf.minimum_current)
        self.minimum_current_combo.blockSignals(False)
    
        self.stallguard_threshold_value_spin.blockSignals(True)
        self.stallguard_threshold_value_spin.setValue(conf.stallguard_threshold_value)
        self.stallguard_threshold_value_spin.blockSignals(False)
    
        self.stallguard_mode_combo.blockSignals(True)
        self.stallguard_mode_combo.setCurrentIndex(conf.stallguard_mode)
        self.stallguard_mode_combo.blockSignals(False)
        
    def get_misc_configuration_async(self, conf):
        self.disable_short_to_ground_protection_checkbox.blockSignals(True)
        self.disable_short_to_ground_protection_checkbox.setChecked(conf.disable_short_to_ground_protection)
        self.disable_short_to_ground_protection_checkbox.blockSignals(False)
        
        self.synchronize_phase_frequency_spin.blockSignals(True)
        self.synchronize_phase_frequency_spin.setValue(conf.synchronize_phase_frequency)
        self.synchronize_phase_frequency_spin.blockSignals(False)
        
    def update_start(self):
        async_call(self.silent_stepper.get_max_velocity, None, self.get_max_velocity_async, self.increase_error_count)
        async_call(self.silent_stepper.get_speed_ramping, None, self.get_speed_ramping_async, self.increase_error_count)
        async_call(self.silent_stepper.is_enabled, None, self.is_enabled_async, self.increase_error_count)
        async_call(self.silent_stepper.get_step_configuration, None, self.get_step_configuration_async, self.increase_error_count)
        async_call(self.silent_stepper.get_basic_configuration, None, self.get_basic_configuration_async, self.increase_error_count)
        async_call(self.silent_stepper.get_spreadcycle_configuration, None, self.get_spreadcycle_configuration_async, self.increase_error_count)
        async_call(self.silent_stepper.get_stealth_configuration, None, self.get_stealth_configuration_async, self.increase_error_count)
        async_call(self.silent_stepper.get_coolstep_configuration, None, self.get_coolstep_configuration_async, self.increase_error_count)
        async_call(self.silent_stepper.get_misc_configuration, None, self.get_misc_configuration_async, self.increase_error_count)

    def update_data(self):
        async_call(self.silent_stepper.get_remaining_steps, None, self.remaining_steps_update, self.increase_error_count)
        async_call(self.silent_stepper.get_current_position, None, self.position_update, self.increase_error_count)
        async_call(self.silent_stepper.get_current_velocity, None, self.speedometer.set_velocity, self.increase_error_count)

        self.update_counter += 1
        if self.update_counter % 10 == 0:
            async_call(self.silent_stepper.get_motor_current, None, self.maximum_current_update, self.increase_error_count)
            async_call(self.silent_stepper.get_stack_input_voltage, None, self.stack_input_voltage_update, self.increase_error_count)
            async_call(self.silent_stepper.get_external_input_voltage, None, self.external_input_voltage_update, self.increase_error_count)
            async_call(self.silent_stepper.get_minimum_voltage, None, self.minimum_voltage_update, self.increase_error_count)
            async_call(self.silent_stepper.get_driver_status, None, self.driver_status_update, self.increase_error_count)

    def velocity_changed(self, value):
        try:
            self.silent_stepper.set_max_velocity(value)
        except ip_connection.Error:
            return

    def acceleration_changed(self, value):
        dec = self.deceleration_spin.value()
        try:
            self.silent_stepper.set_speed_ramping(value, dec)
        except ip_connection.Error:
            return
            
    def deceleration_changed(self, value):
        acc = self.acceleration_slider.value()
        try:
            self.silent_stepper.set_speed_ramping(acc, value)
        except ip_connection.Error:
            return
Ejemplo n.º 12
0
class Stepper(PluginBase, Ui_Stepper):
    qtcb_position_reached = pyqtSignal(int)
    qtcb_under_voltage = pyqtSignal(int)

    def __init__(self, *args):
        PluginBase.__init__(self, BrickStepper, *args)

        self.setupUi(self)

        self.stepper = self.device

        self.endis_all(False)

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

        self.new_value = 0
        self.update_counter = 0

        self.full_brake_time = 0

        self.qem = QErrorMessage(self)
        self.qem.setWindowTitle("Under Voltage")

        self.decay_widget.hide()

        self.setting_sync_rect_checkbox = False

        self.velocity_syncer = SliderSpinSyncer(self.velocity_slider,
                                                self.velocity_spin,
                                                self.velocity_changed)

        self.acceleration_syncer = SliderSpinSyncer(self.acceleration_slider,
                                                    self.acceleration_spin,
                                                    self.acceleration_changed)

        self.deceleration_syncer = SliderSpinSyncer(self.deceleration_slider,
                                                    self.deceleration_spin,
                                                    self.deceleration_changed)

        self.decay_syncer = SliderSpinSyncer(self.decay_slider,
                                             self.decay_spin,
                                             self.decay_changed)

        self.enable_checkbox.toggled.connect(self.enable_toggled)
        self.forward_button.clicked.connect(self.forward_clicked)
        self.stop_button.clicked.connect(self.stop_clicked)
        self.full_brake_button.clicked.connect(self.full_brake_clicked)
        self.backward_button.clicked.connect(self.backward_clicked)
        self.to_button.clicked.connect(self.to_button_clicked)
        self.steps_button.clicked.connect(self.steps_button_clicked)
        self.motor_current_button.clicked.connect(
            self.motor_current_button_clicked)
        self.minimum_motor_voltage_button.clicked.connect(
            self.minimum_motor_voltage_button_clicked)
        self.sync_rect_checkbox.toggled.connect(self.sync_rect_toggled)

        self.mode_dropbox.currentIndexChanged.connect(self.mode_changed)

        self.qtcb_position_reached.connect(self.cb_position_reached)
        self.stepper.register_callback(self.stepper.CALLBACK_POSITION_REACHED,
                                       self.qtcb_position_reached.emit)

        self.qtcb_under_voltage.connect(self.cb_under_voltage)
        self.stepper.register_callback(self.stepper.CALLBACK_UNDER_VOLTAGE,
                                       self.qtcb_under_voltage.emit)

        self.ste = 0
        self.pos = 0
        self.current_velocity = 0
        self.cur = 0
        self.sv = 0
        self.ev = 0
        self.mv = 0
        self.mod = 0

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

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

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

        self.update_timer.start(100)
        self.update_start()

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

    def destroy(self):
        pass

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

    def cb_position_reached(self, position):
        self.position_update(position)
        self.endis_all(True)

    def disable_list(self, button_list):
        for button in button_list:
            button.setEnabled(False)

    def endis_all(self, value):
        self.forward_button.setEnabled(value)
        self.stop_button.setEnabled(value)
        self.backward_button.setEnabled(value)
        self.to_button.setEnabled(value)
        self.steps_button.setEnabled(value)
        self.full_brake_button.setEnabled(value)

    def mode_changed(self, index):
        try:
            self.stepper.set_step_mode(1 << index)
            self.mod = 1 << index
        except ip_connection.Error:
            return

    def forward_clicked(self):
        try:
            self.stepper.drive_forward()
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, self.steps_button])

    def backward_clicked(self):
        try:
            self.stepper.drive_backward()
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, self.steps_button])

    def stop_clicked(self):
        try:
            self.stepper.stop()
        except ip_connection.Error:
            return
        self.endis_all(True)

    def full_brake_clicked(self):
        try:
            self.stepper.full_brake()
        except ip_connection.Error:
            return
        self.endis_all(True)

    def to_button_clicked(self):
        drive_to = self.to_spin.value()
        try:
            self.stepper.set_target_position(drive_to)
        except ip_connection.Error:
            return
        self.disable_list([
            self.to_button, self.steps_button, self.forward_button,
            self.backward_button
        ])

    def steps_button_clicked(self):
        drive_steps = self.steps_spin.value()
        try:
            self.stepper.set_steps(drive_steps)
        except ip_connection.Error:
            return
        self.disable_list([
            self.to_button, self.steps_button, self.forward_button,
            self.backward_button
        ])

    def motor_current_button_clicked(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(0)
        qid.setIntMaximum(2500)
        qid.setIntStep(100)
        async_call(self.stepper.get_motor_current, None, qid.setIntValue,
                   self.increase_error_count)
        qid.intValueSelected.connect(self.motor_current_selected)
        qid.setLabelText("Choose motor current in mA.")
        #                         "<font color=red>Setting this too high can destroy your Motor.</font>")
        qid.open()

    def minimum_motor_voltage_button_clicked(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(0)
        qid.setIntMaximum(40000)
        qid.setIntStep(100)
        async_call(self.stepper.get_minimum_voltage, None, qid.setIntValue,
                   self.increase_error_count)
        qid.intValueSelected.connect(self.minimum_motor_voltage_selected)
        qid.setLabelText("Choose minimum motor voltage in mV.")
        qid.open()

    def motor_current_selected(self, value):
        try:
            self.stepper.set_motor_current(value)
        except ip_connection.Error:
            return

    def minimum_motor_voltage_selected(self, value):
        try:
            self.stepper.set_minimum_voltage(value)
        except ip_connection.Error:
            return

    def cb_under_voltage(self, ov):
        mv_str = self.minimum_voltage_label.text()
        ov_str = "%gV" % round(ov / 1000.0, 1)
        if not self.qem.isVisible():
            self.qem.showMessage(
                "Under Voltage: Output Voltage of " + ov_str +
                " is below minimum voltage of " + mv_str,
                "Stepper_UnderVoltage")

    def enable_toggled(self, checked):
        try:
            if checked:
                if not self.stepper.is_enabled():
                    self.endis_all(True)
                    self.stepper.enable()
            else:
                if self.stepper.is_enabled():
                    self.endis_all(False)
                    self.stepper.disable()
        except ip_connection.Error:
            return

    def sync_rect_toggled(self, checked):
        if not self.setting_sync_rect_checkbox and checked:
            rc = QMessageBox.warning(
                get_main_window(), 'Synchronous Rectification',
                'If you want to use high speeds (> 10000 steps/s) for a large stepper motor with a '
                +
                'large inductivity we strongly suggest that you do not enable synchronous rectification. '
                +
                'Otherwise the Brick may not be able to cope with the load and overheat.',
                QMessageBox.Ok | QMessageBox.Cancel)

            if rc != QMessageBox.Ok:
                self.sync_rect_checkbox.setChecked(False)
                return

        try:
            self.stepper.set_sync_rect(checked)
        except ip_connection.Error:
            return

        self.decay_widget.setVisible(checked)

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

    def external_input_voltage_update(self, ev):
        ev_str = "%gV" % round(ev / 1000.0, 1)
        self.external_voltage_label.setText(ev_str)

    def minimum_voltage_update(self, mv):
        mv_str = "%gV" % round(mv / 1000.0, 1)
        self.minimum_voltage_label.setText(mv_str)

    def maximum_current_update(self, cur):
        cur_str = "%gA" % round(cur / 1000.0, 1)
        self.maximum_current_label.setText(cur_str)

    def position_update(self, pos):
        pos_str = "%d" % pos
        self.position_label.setText(pos_str)

    def remaining_steps_update(self, ste):
        ste_str = "%d" % ste
        self.remaining_steps_label.setText(ste_str)

    def current_velocity_update(self, velocity):
        velocity_str = "%d" % velocity
        self.current_velocity_label.setText(velocity_str)
        self.speedometer.set_velocity(velocity)

    def mode_update(self, mod):
        if mod == 8:
            index = 3
        elif mod == 4:
            index = 2
        elif mod == 2:
            index = 1
        else:
            index = 0

        self.mode_dropbox.setCurrentIndex(index)

    def get_max_velocity_async(self, velocity):
        if not self.velocity_slider.isSliderDown():
            if velocity != self.velocity_slider.sliderPosition():
                self.velocity_slider.setSliderPosition(velocity)
                self.velocity_spin.setValue(velocity)

    def get_speed_ramping_async(self, ramp):
        acc, dec = ramp
        if not self.acceleration_slider.isSliderDown() and \
           not self.deceleration_slider.isSliderDown():
            if acc != self.acceleration_slider.sliderPosition():
                self.acceleration_slider.setSliderPosition(acc)
                self.acceleration_spin.setValue(acc)
            if dec != self.deceleration_slider.sliderPosition():
                self.deceleration_slider.setSliderPosition(dec)
                self.deceleration_spin.setValue(dec)

    def get_decay_async(self, decay):
        if not self.decay_slider.isSliderDown():
            if decay != self.decay_slider.sliderPosition():
                self.decay_slider.setSliderPosition(decay)
                self.decay_spin.setValue(decay)

    def is_enabled_async(self, enabled):
        if enabled:
            if not self.enable_checkbox.isChecked():
                self.endis_all(True)
                self.enable_checkbox.setChecked(True)
        else:
            if self.enable_checkbox.isChecked():
                self.endis_all(False)
                self.enable_checkbox.setChecked(False)

    def is_sync_rect_async(self, sync_rect):
        self.setting_sync_rect_checkbox = True
        self.sync_rect_checkbox.setChecked(sync_rect)
        self.setting_sync_rect_checkbox = False

    def update_start(self):
        async_call(self.stepper.get_max_velocity, None,
                   self.get_max_velocity_async, self.increase_error_count)
        async_call(self.stepper.get_speed_ramping, None,
                   self.get_speed_ramping_async, self.increase_error_count)
        async_call(self.stepper.get_decay, None, self.get_decay_async,
                   self.increase_error_count)
        async_call(self.stepper.is_enabled, None, self.is_enabled_async,
                   self.increase_error_count)
        async_call(self.stepper.is_sync_rect, None, self.is_sync_rect_async,
                   self.increase_error_count)

    def update_data(self):
        async_call(self.stepper.get_remaining_steps, None,
                   self.remaining_steps_update, self.increase_error_count)
        async_call(self.stepper.get_current_position, None,
                   self.position_update, self.increase_error_count)
        async_call(self.stepper.get_current_velocity, None,
                   self.current_velocity_update, self.increase_error_count)

        self.update_counter += 1
        if self.update_counter % 10 == 0:
            async_call(self.stepper.get_motor_current, None,
                       self.maximum_current_update, self.increase_error_count)
            async_call(self.stepper.get_stack_input_voltage, None,
                       self.stack_input_voltage_update,
                       self.increase_error_count)
            async_call(self.stepper.get_external_input_voltage, None,
                       self.external_input_voltage_update,
                       self.increase_error_count)
            async_call(self.stepper.get_minimum_voltage, None,
                       self.minimum_voltage_update, self.increase_error_count)
            async_call(self.stepper.get_step_mode, None, self.mode_update,
                       self.increase_error_count)

    def velocity_changed(self, value):
        try:
            self.stepper.set_max_velocity(value)
        except ip_connection.Error:
            return

    def acceleration_changed(self, value):
        dec = self.deceleration_spin.value()
        try:
            self.stepper.set_speed_ramping(value, dec)
        except ip_connection.Error:
            return

    def deceleration_changed(self, value):
        acc = self.acceleration_slider.value()
        try:
            self.stepper.set_speed_ramping(acc, value)
        except ip_connection.Error:
            return

    def decay_changed(self, value):
        try:
            self.stepper.set_decay(value)
        except ip_connection.Error:
            return
Ejemplo n.º 13
0
        listener = create_listener()
    except socket.error:  # Good si is correct (on UNIX)
        otherinstance = True
    else:
        # On windows only singleinstance can be trusted
        otherinstance = True if iswindows else False
    if not otherinstance and not opts.shutdown_running_calibre:
        return run_gui(opts, args, listener, app, gui_debug=gui_debug)

    communicate(opts, args)

    return 0


if __name__ == '__main__':
    try:
        sys.exit(main())
    except Exception as err:
        if not iswindows:
            raise
        tb = traceback.format_exc()
        from PyQt4.QtGui import QErrorMessage
        logfile = os.path.join(os.path.expanduser('~'), 'calibre.log')
        if os.path.exists(logfile):
            log = open(logfile).read().decode('utf-8', 'ignore')
            d = QErrorMessage()
            d.showMessage(
                ('<b>Error:</b>%s<br><b>Traceback:</b><br>'
                 '%s<b>Log:</b><br>%s') % (unicode(err), unicode(tb).replace(
                     '\n', '<br>'), log.replace('\n', '<br>')))
Ejemplo n.º 14
0
class MainWindow(QMainWindow, Ui_MainWindow):
    """The Main window of Luma.
    """

    logger = logging.getLogger(__name__)
    languages = {}
    translator = None
    languageHandler = None
    currentLanguage = ''

    def __init__(self, parent=None):
        """The constructor sets up the MainWindow widget, and connects
        all necessary signals and slots
        """
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        # We store the window size to make sure the previous window size
        # is restored when leaving fullscreen mode. This varible is used
        # in the toggleFullscreen slot.
        self.__tmpWinSize = self.size()
        self.eventFilter = LumaEventFilter(self)

        self.mainTabs.installEventFilter(self.eventFilter)

        self.translator = QTranslator()
        self.languageHandler = LanguageHandler()
        self.languages = self.languageHandler.availableLanguages

        #self.__createPluginToolBar()
        self.__createLoggerWidget()
        self.__loadSettings()
        self.__createLanguageOptions()

        self.setStatusBar(self.statusBar)

        self.mainTabs.setTabsClosable(True)
        self.mainTabs.setContextMenuPolicy(Qt.CustomContextMenu)
        self.mainTabs.customContextMenuRequested.connect(
            self.__mainTabsContextMenu)

        self.defaultTabStyle = ''
        self.lumaHeadStyle = 'background: url(:/icons/luma-gray);\n' + \
                     'background-position: bottom right;\n' + \
                     'background-attachment: fixed;\n' + \
                     'background-repeat:  no-repeat;'

        #Sets up pluginWidget
        #self in parameter is used to call pluginSelected here...
        self.pluginWidget = PluginListWidget(self)
        self.showPlugins()

        self.welcomeTab = WelcomeTab()
        self.welcomeTab.textBrowser.setStyleSheet(self.lumaHeadStyle)

        #This value comes from __loadSettings()
        #Its a checkbox set in WelcomeTab
        if self.showWelcomeSettings == 2:
            self.showWelcome()
        else:
            # Let's do some styling of the tab widget when no tabs are opened
            if self.mainTabs.currentIndex() == -1:
                self.__setTabWidgetStyle(self.lumaHeadStyle)

            self.actionShowWelcomeTab.setEnabled(True)

        self.serversChangedMessage = QErrorMessage(self)

    def __mainTabsContextMenu(self, pos):
        menu = QMenu()
        if self.mainTabs.count() > 0:
            return
            # The menu is displayed even when the rightclick is not
            # done over the actual tabs so to avoid confusion the
            # function is disabled entirey
            #menu.addAction(QApplication.translate(
            #    "MainWindow", "Close all plugin-tabs"), self.tabCloseAll)
        else:
            # If there's no tabs, offer to display the pluginlist
            menu.addAction(self.actionShowPluginList)
        menu.exec_(self.mainTabs.mapToGlobal(pos))

    def __createPluginToolBar(self):
        """Creates the pluign toolbar.
        """
        self.pluginToolBar = PluginToolBar(self)
        self.pluginToolBar.setWindowTitle(
            QApplication.translate('MainWindow', 'Plugintoolbar', None,
                                   QApplication.UnicodeUTF8))
        self.pluginToolBar.setObjectName('pluginToolBar')
        self.addToolBar(self.pluginToolBar)
        self.pluginToolBar.hide()

    def __createLoggerWidget(self):
        """Creates the logger widget.
        """
        self.loggerDockWindow = QDockWidget(self)
        self.loggerDockWindow.setObjectName('loggerDockWindow')
        self.loggerDockWindow.visibilityChanged[bool].connect(
            self.actionShowLogger.setChecked)
        self.loggerDockWindow.setWindowTitle(
            QApplication.translate('MainWindow', 'Logger', None,
                                   QApplication.UnicodeUTF8))
        self.loggerWidget = LoggerWidget(self.loggerDockWindow)
        self.loggerDockWindow.setWidget(self.loggerWidget)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.loggerDockWindow)
        self.loggerDockWindow.hide()

    def __createLanguageOptions(self):
        """Creates the language selection in the menubar.
        """
        self.langGroup = QActionGroup(self)
        self.langGroup.setExclusive(True)
        self.langGroup.triggered['QAction*'].connect(self.languageChanged)

        for key, name in self.languages.iteritems():
            action = QAction(self)
            action.setCheckable(True)
            action.setData(key)
            action.setText(name[0])
            action.setStatusTip(name[1])
            action.setActionGroup(self.langGroup)
            self.menuLanguage.addAction(action)
            if key == self.currentLanguage:
                action.setChecked(True)

    def __loadSettings(self, mainWin=True):
        """Loads settings from file.

        :param mainWin: If set to ``False``, neither the values for the
         window size or the window position will be loaded. This is
         i.e done when the settings dialog returns 1.
        :type mainWin: bool
        """
        settings = Settings()
        # We might want to use these methods to restore the
        # application state and geometry.
        if mainWin:
            self.restoreGeometry(settings.geometry)
        #self.restoreState(settings.state)

        # If the geometry saved inticates fullscreen mode,
        # we need to explicitly set the fullscreen menuaction checkbox
        if self.isFullScreen():
            self.actionFullscreen.setChecked(True)

        # Logger

        # Logger
        # The `allwaysShowLoggerOnStart` a precedence on the
        # `showLogger` value.
        if settings.showLoggerOnStart:
            self.actionShowLogger.setChecked(True)
        else:
            self.actionShowLogger.setChecked(settings.showLogger)

        self.loggerWidget.errorBox.setChecked(settings.showErrors)
        self.loggerWidget.debugBox.setChecked(settings.showDebug)
        self.loggerWidget.infoBox.setChecked(settings.showInfo)

        self.toggleLoggerWindow(self.actionShowLogger.isChecked())

        # Language
        self.loadLanguage(settings.language)

        #Tabs
        self.showWelcomeSettings = settings.value("showWelcome", 2).toInt()[0]

    def __writeSettings(self):
        """Save settings to file.
        """
        settings = Settings()
        # We might want to use these methods to restore the
        # application state and geometry.
        settings.geometry = self.saveGeometry()
        #settings.state = self.saveState()

        # Mainwin
        #max = self.isMaximized()
        #settings.maximize = max
        #if not max:
        #    settings.size = self.size()
        #    settings.position = self.pos()

        # The global logger settings is managed from the settings dialog.
        # Logger
        settings.showLogger = self.actionShowLogger.isChecked()
        settings.showErrors = self.loggerWidget.errorBox.isChecked()
        settings.showDebug = self.loggerWidget.debugBox.isChecked()
        settings.showInfo = self.loggerWidget.infoBox.isChecked()

        # Language
        settings.language = self.currentLanguage

    def __switchTranslator(self, translator, qmFile):
        """Called when a new language is loaded.

        :param translator: The translator object to install.
        :type translator: QTranslator
        :qmFile: The translation file for the loaded language.
        :type qmFile: string
        """
        qApp.removeTranslator(translator)
        if translator.load(qmFile):
            qApp.installTranslator(translator)

    def __setTabWidgetStyle(self, stylesheet):
        self.mainTabs.setStyleSheet(stylesheet)

    @pyqtSlot('QAction*')
    @pyqtSlot(int)
    def languageChanged(self, value):
        """This slot is called by actions and signals related to
        application translations. The slot contains validation for
        those parameters defined by the pyqtSlot meta info in the
        method header.

        :param value: Can be either a ``QAction`` or an integer value.
         I.e. menu actions provide ``QActions`` but a ``QCombobox``
         might send it's index.
        :type value: QAction/int
        """
        locale = None
        if isinstance(value, int):
            locale = self.languageSelector.itemData(value).toString()
        elif isinstance(value, QAction):
            locale = value.data().toString()
        #else:
        #    locale = value
        if locale:
            self.loadLanguage(locale)

    def loadLanguage(self, locale):
        """Loads a language by the given language iso code.

        :param locale: A twoletter lowercase ISO 639 language code and
         possibly a twoletter uppercase ISO 3166 country code separeted
         by a underscore.
        :type locale: string
        """
        if self.currentLanguage != locale:
            self.currentLanguage = locale
            qmFile = self.languageHandler.getQmFile(locale)
            self.__switchTranslator(self.translator, qmFile)

    def changeEvent(self, event):
        """This event is called when a new translator is loaded or the
        system language (locale) is changed.

        :param event: The event that generated the `changeEvent`.
        :type event: QEvent
        """
        if None != event:
            type = event.type()
            if QEvent.LanguageChange == type or QEvent.LocaleChange == type:
                self.retranslateUi(self)
                self.loggerWidget.retranslateUi(self.loggerWidget)

    def showAboutLuma(self):
        """Slot for displaying the about dialog.
        """
        AboutDialog().exec_()

    @pyqtSlot(bool)
    def toggleLoggerWindow(self, show):
        """Slot for toggling the logger window.

        :param show: a boolean value indicating whether the logger window
         should be shown or not.
        :type show: bool
        """
        if show:
            self.loggerDockWindow.show()
        else:
            self.loggerDockWindow.hide()

    @pyqtSlot(bool)
    def toggleStatusbar(self, show):
        """Slot for toggling the logger window.

        :param show: a boolean value indicating whether the statusbar
         should be shown or not.
        :type show: bool
        """
        if show:
            self.statusBar.show()
        else:
            self.statusBar.hide()

    @pyqtSlot(bool)
    def toggleFullscreen(self, fullscreen):
        """Slot for toggling the logger window.

        :param fullscreen: a boolean value indicating whether to enter
         fullscreenmode or not.
        :type fullcreen: bool
        """
        if fullscreen:
            self.__tmpWinSize = self.size()
            self.showFullScreen()
        else:
            self.showNormal()
            self.resize(self.__tmpWinSize)

    def showServerEditor(self):
        """Slot to display the server editor dialog.
        """
        serverEditor = ServerDialog()
        r = serverEditor.exec_()
        if r:
            #TODO -- only display if plugins open:
            self.serversChangedMessage.showMessage(
                QApplication.translate(
                    "MainWindow",
                    "You may need to restart plugins for changes to take effect."
                ))

    def showTempPasswordDialog(self):
        """ Sets overridePassword for a server.
        Using this one doesn't actually have to enter the password
        in the ServerDialog (and by extension save to disk).
        """
        serverList = ServerList()

        # Create a stringlist to be used by the qinputdialog
        stringList = []
        for server in serverList.getTable():
            stringList.append(server.name)

        # Display list of servers
        (serverString, ok) = QInputDialog.getItem(
            self,
            QApplication.translate("MainWindow", "Select server"),
            QApplication.translate("MainWindow", "Server:"),
            stringList,
            editable=False)
        if ok:
            server = serverList.getServerObjectByName(serverString)
            if server != None:
                # Ask for password
                (value, ok) = QInputDialog.getText(
                    self,
                    QApplication.translate("MainWindow", "Temporary password"),
                    QApplication.translate("MainWindow", "Enter password:"******"""Slot to display the settings dialog. If the settings dialog
        returns 1, i.e. the user has clicked the ok button, the
        loadSettings method is called with mainWin=False, to load the
        (assumed) newly changed settings.

        :param tab: The index of the tab to display in the settings
         dialog.
        :type tab: int
        """
        #settingsDialog = SettingsDialog(self.currentLanguage, self.languages)
        settingsDialog = SettingsDialog()
        if tab < 0:
            tab = 0
        settingsDialog.tabWidget.setCurrentIndex(tab)
        if settingsDialog.exec_():
            self.reloadPlugins()


#            # We assume that some settings is changed
#            # if the user clicked the ok button, and
#            # reloads the application settings
#            self.__loadSettings(mainWin=False)
#            # A Hack but it'll do for now
#            for a in self.langGroup.actions():
#                if a.data().toString() == self.currentLanguage:
#                    a.setChecked(True)

    def configurePlugins(self):
        """Slot to display the plugins configuration. This currently
        calls `showSettingsDialog` with tab index set to 2.
        """
        self.showSettingsDialog(1)

    def reloadPlugins(self):
        """Slot to reload plugins.
        """
        self.pluginWidget.updatePlugins()

    def pluginSelected(self, item):
        """This method will be called from the `PluginListWidget`.
        """
        # Clear the stylesheet when a tab is opened
        self.__setTabWidgetStyle(self.defaultTabStyle)

        widget = item.plugin.getPluginWidget(None, self)

        if platform.system() == "Windows":
            scroll = QScrollArea()
            scroll.setWidget(widget)
            scroll.setWidgetResizable(True)
            index = self.mainTabs.addTab(scroll, item.icon(),
                                         item.plugin.pluginUserString)
        else:
            index = self.mainTabs.addTab(widget, item.icon(),
                                         item.plugin.pluginUserString)

        self.mainTabs.setCurrentIndex(index)

    def tabClose(self, index):
        """Slot for the signal `tabCloseRequest(int)` for the tabMains.
        """

        widget = self.mainTabs.widget(index)

        # If the tab closed is one of these, enable the toggle-action
        if widget == self.pluginWidget:
            self.actionShowPluginList.setEnabled(True)
        if widget == self.welcomeTab:
            self.actionShowWelcomeTab.setEnabled(True)

        self.mainTabs.removeTab(index)

        # Unparent the widget since it was reparented by the QTabWidget
        # so it's garbage collected
        widget.setParent(None)

        # In case the widget contained circular references
        # -- force GC to take care of the objects since there can be
        #    quite many if it was BrowserWidget that was closed.
        # Can't call it directly since that'll be too soon
        QTimer.singleShot(1000, self.gc)

        # Let's do some styling of the tab widget when no tabs are opened
        if self.mainTabs.currentIndex() == -1:
            self.__setTabWidgetStyle(self.lumaHeadStyle)

    def gc(self):
        """Runs Python's garbage-collection manually.
        Used to make sure circular references are taken care of *now*.
        """
        gc.collect()

    def showWelcome(self):
        """Shows the Welcome-tab
        """
        self.__setTabWidgetStyle(self.defaultTabStyle)
        index = self.mainTabs.addTab(
            self.welcomeTab, QApplication.translate("MainWindow", "Welcome"))

        self.mainTabs.setCurrentIndex(index)
        self.actionShowWelcomeTab.setEnabled(False)

    def showPlugins(self):
        """Will show the pluginlistwidget-tab
        """
        self.__setTabWidgetStyle(self.defaultTabStyle)
        if self.mainTabs.indexOf(self.pluginWidget) == -1:
            index = self.mainTabs.addTab(
                self.pluginWidget,
                QApplication.translate("MainWindow", "Plugins"))
            self.mainTabs.setCurrentIndex(index)
            self.actionShowPluginList.setEnabled(False)

    def closeEvent(self, e):
        """Overrides the ``QMainWindow.closeEvent`` slot to save
        settings before we tear down the application.
        """
        self.__writeSettings()
        QMainWindow.closeEvent(self, e)
Ejemplo n.º 15
0
class ProjectXively(QWidget):
    qtcb_update_illuminance = pyqtSignal(float)
    qtcb_update_air_pressure = pyqtSignal(float)
    qtcb_update_temperature = pyqtSignal(float)
    qtcb_update_humidity = pyqtSignal(float)
    qtcb_button_pressed = pyqtSignal(int)

    lcdwidget = None

    xively_host = "api.xively.com"
    xively_agent = "Tinkerforge Starter Kit Weather Station Demo"
    xively_channel = "Enter Feed ID here"
    xively_api_key = "Enter API Key here"

    xively_items = {}
    xively_headers = None
    xively_params = ""
    xively_update_rate = 5  # in minutes

    text_agent = None
    text_channel = None
    text_api_key = None
    number_update_rate = None

    save_button = None

    xively_timer = None

    error_message = None

    label_upload_active = None

    last_upload = None

    def __init__(self, parent, app):
        super(QWidget, self).__init__()

        self.lcdwidget = LCDWidget(self, app)
        self.lcdwidget.hide()

        self.text_agent = QLineEdit(self)
        self.text_agent.setText(self.xively_agent)

        self.text_channel = QLineEdit(self)
        self.text_channel.setText(self.xively_channel)

        self.text_api_key = QLineEdit(self)
        self.text_api_key.setText(self.xively_api_key)

        self.number_update_rate = QSpinBox(self)
        self.number_update_rate.setRange(1, 1440)
        self.number_update_rate.setSuffix(' min')
        self.number_update_rate.setValue(self.xively_update_rate)

        layout1 = QHBoxLayout()
        layout2 = QVBoxLayout()

        layout1.addStretch()
        layout1.addLayout(layout2)
        layout1.addStretch()

        layout2.addSpacerItem(QSpacerItem(LCDWidget.FIXED_WIDGTH, 0))

        label = QLabel(self)
        label.setText(
            "Project: <b>Connect to Xively</b>. This project uploads the measured values to Xively. Please find documentation how to configure it and program sources in Python <a href=\"http://www.tinkerforge.com/en/doc/Kits/WeatherStation/WeatherStation.html#connect-to-xively\">here</a>.<br>"
        )
        label.setTextFormat(Qt.RichText)
        label.setTextInteractionFlags(Qt.TextBrowserInteraction)
        label.setOpenExternalLinks(True)
        label.setWordWrap(True)
        label.setAlignment(Qt.AlignJustify)

        layout2.addSpacing(10)
        layout2.addWidget(label)
        layout2.addSpacing(10)

        layout3a = QHBoxLayout()
        label = QLabel("Agent Description:")
        label.setMinimumWidth(150)
        layout3a.addWidget(label)
        layout3a.addWidget(self.text_agent, 1)

        layout2.addLayout(layout3a)
        layout2.addSpacing(10)

        layout3b = QHBoxLayout()
        label = QLabel("Feed:")
        label.setMinimumWidth(150)
        layout3b.addWidget(label)
        layout3b.addWidget(self.text_channel, 1)

        layout2.addLayout(layout3b)
        layout2.addSpacing(10)

        layout3c = QHBoxLayout()
        label = QLabel("API Key:")
        label.setMinimumWidth(150)
        layout3c.addWidget(label)
        layout3c.addWidget(self.text_api_key, 1)

        layout2.addLayout(layout3c)
        layout2.addSpacing(10)

        layout3d = QHBoxLayout()
        label = QLabel("Update Rate:")
        label.setMinimumWidth(150)
        layout3d.addWidget(label)
        layout3d.addWidget(self.number_update_rate, 1)

        layout2.addLayout(layout3d)
        layout2.addSpacing(10)

        self.label_upload_active = QLabel("Not Active", self)
        self.label_upload_active.setMinimumWidth(150)
        font = QFont()
        font.setPixelSize(20)
        self.label_upload_active.setFont(font)
        self.set_active_label(False)

        self.save_button = QPushButton("Save/Activate")

        layout4 = QHBoxLayout()
        layout4.addWidget(self.label_upload_active)
        layout4.addWidget(self.save_button, 1)

        layout2.addLayout(layout4)
        layout2.addStretch()

        self.setLayout(layout1)

        self.qtcb_update_illuminance.connect(self.update_illuminance_data_slot)
        self.qtcb_update_air_pressure.connect(
            self.update_air_pressure_data_slot)
        self.qtcb_update_temperature.connect(self.update_temperature_data_slot)
        self.qtcb_update_humidity.connect(self.update_humidity_data_slot)
        self.qtcb_button_pressed.connect(self.button_pressed_slot)
        self.save_button.clicked.connect(self.save_configuration)

        self.lcdwidget.clear(self)

        self.error_message = QErrorMessage(self)

    def set_active_label(self, value):
        palette = self.label_upload_active.palette()
        if value:
            palette.setColor(self.foregroundRole(), Qt.darkGreen)
            self.label_upload_active.setText("Active")
        else:
            palette.setColor(self.foregroundRole(), Qt.red)
            self.label_upload_active.setText("Not Active")

        self.label_upload_active.setPalette(palette)

    def save_configuration(self):
        try:
            self.xively_agent = str(self.text_agent.text()).decode('ascii')
            self.xively_channel = str(self.text_channel.text()).decode('ascii')
            self.xively_api_key = str(self.text_api_key.text()).decode('ascii')
        except:
            self.error_message.showMessage(
                'Agent, Feed and API Key can only contain ASCII characters')
            return

        self.xively_update_rate = self.number_update_rate.value()

        self.xively_headers = {
            "Content-Type": "application/x-www-form-urlencoded",
            "X-ApiKey": self.xively_api_key,
            "User-Agent": self.xively_agent,
        }
        self.xively_params = "/v2/feeds/" + self.xively_channel

        if self.xively_timer is None:
            self.xively_timer = QTimer(self)
            self.xively_timer.timeout.connect(self.update_xively)
            self.xively_timer.start(self.xively_update_rate * 60 * 1000)

        self.set_active_label(True)
        self.update_xively()

    def write_lcd(self):
        if self.last_upload == None:
            tmp = "Last: Never"
        else:
            tmp = "Last: " + self.last_upload

        self.lcdwidget.write_line(0, 0, "Xively Upload", self)
        self.lcdwidget.write_line(2, 0, tmp, self)

    def update_xively(self):
        if len(self.xively_items) == 0:
            return

        stream_items = []
        for identifier, value in self.xively_items.items():
            stream_items.append({
                'id': identifier,
                'current_value': value[0],
                'min_value': value[1],
                'max_value': value[2]
            })

        data = {'version': '1.0.0', 'datastreams': stream_items}
        self.xively_items = {}
        body = json.dumps(data)

        try:
            http = httplib.HTTPSConnection(self.xively_host)
            http.request('PUT', self.xively_params, body, self.xively_headers)
            response = http.getresponse()
            http.close()

            if response.status != 200:
                self.error_message.showMessage(
                    'Could not upload to xively -> Response:' +
                    str(response.status) + ': ' + response.reason +
                    '. Check your configuration.')
                self.xively_timer.stop()
                self.xively_timer = None
                self.set_active_label(False)
                return
        except Exception as e:
            self.error_message.showMessage('HTTP error: ' + str(e))
            self.xively_timer.stop()
            self.xively_timer = None
            self.set_active_label(False)
            return

        # set upload time if upload was a success
        self.last_upload = time.strftime("%H:%M:%S")

    def put(self, identifier, value):
        self.write_lcd()
        try:
            _, min_value, max_value = self.xively_items[identifier]
            if value < min_value:
                min_value = value
            if value > max_value:
                max_value = value
            self.xively_items[identifier] = (value, min_value, max_value)
        except:
            self.xively_items[identifier] = (value, value, value)

    def update_illuminance_data_slot(self, illuminance):
        self.put('AmbientLight', illuminance)

    def update_illuminance(self, illuminance):
        self.qtcb_update_illuminance.emit(illuminance)

    def update_humidity_data_slot(self, humidity):
        self.put('Humidity', humidity)

    def update_humidity(self, humidity):
        self.qtcb_update_humidity.emit(humidity)

    def update_air_pressure_data_slot(self, air_pressure):
        self.put('AirPressure', air_pressure)

    def update_air_pressure(self, air_pressure):
        self.qtcb_update_air_pressure.emit(air_pressure)

    def update_temperature_data_slot(self, temperature):
        self.put('Temperature', temperature)

    def update_temperature(self, temperature):
        self.qtcb_update_temperature.emit(temperature)

    def button_pressed_slot(self, button):
        pass

    def button_pressed(self, button):
        self.qtcb_button_pressed.emit(button)
Ejemplo n.º 16
0
class MainWindow(QMainWindow, Ui_MainWindow):
    """The Main window of Luma.
    """

    logger = logging.getLogger(__name__)
    languages = {}
    translator = None
    languageHandler = None
    currentLanguage = ''

    def __init__(self, parent=None):
        """The constructor sets up the MainWindow widget, and connects
        all necessary signals and slots
        """
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        # We store the window size to make sure the previous window size
        # is restored when leaving fullscreen mode. This varible is used
        # in the toggleFullscreen slot.
        self.__tmpWinSize = self.size()
        self.eventFilter = LumaEventFilter(self)

        self.mainTabs.installEventFilter(self.eventFilter)

        self.translator = QTranslator()
        self.languageHandler = LanguageHandler()
        self.languages = self.languageHandler.availableLanguages

        #self.__createPluginToolBar()
        self.__createLoggerWidget()
        self.__loadSettings()
        self.__createLanguageOptions()

        self.setStatusBar(self.statusBar)

        self.mainTabs.setTabsClosable(True)
        self.mainTabs.setContextMenuPolicy(Qt.CustomContextMenu)
        self.mainTabs.customContextMenuRequested.connect(
            self.__mainTabsContextMenu)

        self.defaultTabStyle = ''
        self.lumaHeadStyle = 'background: url(:/icons/luma-gray);\n' + \
                     'background-position: bottom right;\n' + \
                     'background-attachment: fixed;\n' + \
                     'background-repeat:  no-repeat;'

        #Sets up pluginWidget
        #self in parameter is used to call pluginSelected here...
        self.pluginWidget = PluginListWidget(self)
        self.showPlugins()

        self.welcomeTab = WelcomeTab()
        self.welcomeTab.textBrowser.setStyleSheet(self.lumaHeadStyle)

        #This value comes from __loadSettings()
        #Its a checkbox set in WelcomeTab
        if self.showWelcomeSettings == 2:
            self.showWelcome()
        else:
            # Let's do some styling of the tab widget when no tabs are opened
            if self.mainTabs.currentIndex() == -1:
                self.__setTabWidgetStyle(self.lumaHeadStyle)

            self.actionShowWelcomeTab.setEnabled(True)

        self.serversChangedMessage = QErrorMessage(self)

    def __mainTabsContextMenu(self, pos):
        menu = QMenu()
        if self.mainTabs.count() > 0:
            return
            # The menu is displayed even when the rightclick is not
            # done over the actual tabs so to avoid confusion the
            # function is disabled entirey
            #menu.addAction(QApplication.translate(
            #    "MainWindow", "Close all plugin-tabs"), self.tabCloseAll)
        else:
            # If there's no tabs, offer to display the pluginlist
            menu.addAction(self.actionShowPluginList)
        menu.exec_(self.mainTabs.mapToGlobal(pos))

    def __createPluginToolBar(self):
        """Creates the pluign toolbar.
        """
        self.pluginToolBar = PluginToolBar(self)
        self.pluginToolBar.setWindowTitle(QApplication.translate(
            'MainWindow', 'Plugintoolbar', None, QApplication.UnicodeUTF8))
        self.pluginToolBar.setObjectName('pluginToolBar')
        self.addToolBar(self.pluginToolBar)
        self.pluginToolBar.hide()

    def __createLoggerWidget(self):
        """Creates the logger widget.
        """
        self.loggerDockWindow = QDockWidget(self)
        self.loggerDockWindow.setObjectName('loggerDockWindow')
        self.loggerDockWindow.visibilityChanged[bool].connect(
            self.actionShowLogger.setChecked)
        self.loggerDockWindow.setWindowTitle(QApplication.translate(
            'MainWindow', 'Logger', None, QApplication.UnicodeUTF8))
        self.loggerWidget = LoggerWidget(self.loggerDockWindow)
        self.loggerDockWindow.setWidget(self.loggerWidget)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.loggerDockWindow)
        self.loggerDockWindow.hide()

    def __createLanguageOptions(self):
        """Creates the language selection in the menubar.
        """
        self.langGroup = QActionGroup(self)
        self.langGroup.setExclusive(True)
        self.langGroup.triggered['QAction*'].connect(self.languageChanged)

        for key, name in self.languages.iteritems():
            action = QAction(self)
            action.setCheckable(True)
            action.setData(key)
            action.setText(name[0])
            action.setStatusTip(name[1])
            action.setActionGroup(self.langGroup)
            self.menuLanguage.addAction(action)
            if key == self.currentLanguage:
                action.setChecked(True)

    def __loadSettings(self, mainWin=True):
        """Loads settings from file.

        :param mainWin: If set to ``False``, neither the values for the
         window size or the window position will be loaded. This is
         i.e done when the settings dialog returns 1.
        :type mainWin: bool
        """
        settings = Settings()
        # We might want to use these methods to restore the
        # application state and geometry.
        if mainWin:
            self.restoreGeometry(settings.geometry)
        #self.restoreState(settings.state)

        # If the geometry saved inticates fullscreen mode,
        # we need to explicitly set the fullscreen menuaction checkbox
        if self.isFullScreen():
            self.actionFullscreen.setChecked(True)

        # Logger

        # Logger
        # The `allwaysShowLoggerOnStart` a precedence on the
        # `showLogger` value.
        if settings.showLoggerOnStart:
            self.actionShowLogger.setChecked(True)
        else:
            self.actionShowLogger.setChecked(settings.showLogger)

        self.loggerWidget.errorBox.setChecked(settings.showErrors)
        self.loggerWidget.debugBox.setChecked(settings.showDebug)
        self.loggerWidget.infoBox.setChecked(settings.showInfo)

        self.toggleLoggerWindow(self.actionShowLogger.isChecked())

        # Language
        self.loadLanguage(settings.language)

        #Tabs
        self.showWelcomeSettings = settings.value("showWelcome", 2).toInt()[0]

    def __writeSettings(self):
        """Save settings to file.
        """
        settings = Settings()
        # We might want to use these methods to restore the
        # application state and geometry.
        settings.geometry = self.saveGeometry()
        #settings.state = self.saveState()

        # Mainwin
        #max = self.isMaximized()
        #settings.maximize = max
        #if not max:
        #    settings.size = self.size()
        #    settings.position = self.pos()

        # The global logger settings is managed from the settings dialog.
        # Logger
        settings.showLogger = self.actionShowLogger.isChecked()
        settings.showErrors = self.loggerWidget.errorBox.isChecked()
        settings.showDebug = self.loggerWidget.debugBox.isChecked()
        settings.showInfo = self.loggerWidget.infoBox.isChecked()

        # Language
        settings.language = self.currentLanguage

    def __switchTranslator(self, translator, qmFile):
        """Called when a new language is loaded.

        :param translator: The translator object to install.
        :type translator: QTranslator
        :qmFile: The translation file for the loaded language.
        :type qmFile: string
        """
        qApp.removeTranslator(translator)
        if translator.load(qmFile):
            qApp.installTranslator(translator)

    def __setTabWidgetStyle(self, stylesheet):
        self.mainTabs.setStyleSheet(stylesheet)

    @pyqtSlot('QAction*')
    @pyqtSlot(int)
    def languageChanged(self, value):
        """This slot is called by actions and signals related to
        application translations. The slot contains validation for
        those parameters defined by the pyqtSlot meta info in the
        method header.

        :param value: Can be either a ``QAction`` or an integer value.
         I.e. menu actions provide ``QActions`` but a ``QCombobox``
         might send it's index.
        :type value: QAction/int
        """
        locale = None
        if isinstance(value, int):
            locale = self.languageSelector.itemData(value).toString()
        elif isinstance(value, QAction):
            locale = value.data().toString()
        #else:
        #    locale = value
        if locale:
            self.loadLanguage(locale)

    def loadLanguage(self, locale):
        """Loads a language by the given language iso code.

        :param locale: A twoletter lowercase ISO 639 language code and
         possibly a twoletter uppercase ISO 3166 country code separeted
         by a underscore.
        :type locale: string
        """
        if self.currentLanguage != locale:
            self.currentLanguage = locale
            qmFile = self.languageHandler.getQmFile(locale)
            self.__switchTranslator(self.translator, qmFile)

    def changeEvent(self, event):
        """This event is called when a new translator is loaded or the
        system language (locale) is changed.

        :param event: The event that generated the `changeEvent`.
        :type event: QEvent
        """
        if None != event:
            type = event.type()
            if QEvent.LanguageChange == type or QEvent.LocaleChange == type:
                self.retranslateUi(self)
                self.loggerWidget.retranslateUi(self.loggerWidget)

    def showAboutLuma(self):
        """Slot for displaying the about dialog.
        """
        AboutDialog().exec_()

    @pyqtSlot(bool)
    def toggleLoggerWindow(self, show):
        """Slot for toggling the logger window.

        :param show: a boolean value indicating whether the logger window
         should be shown or not.
        :type show: bool
        """
        if show:
            self.loggerDockWindow.show()
        else:
            self.loggerDockWindow.hide()

    @pyqtSlot(bool)
    def toggleStatusbar(self, show):
        """Slot for toggling the logger window.

        :param show: a boolean value indicating whether the statusbar
         should be shown or not.
        :type show: bool
        """
        if show:
            self.statusBar.show()
        else:
            self.statusBar.hide()

    @pyqtSlot(bool)
    def toggleFullscreen(self, fullscreen):
        """Slot for toggling the logger window.

        :param fullscreen: a boolean value indicating whether to enter
         fullscreenmode or not.
        :type fullcreen: bool
        """
        if fullscreen:
            self.__tmpWinSize = self.size()
            self.showFullScreen()
        else:
            self.showNormal()
            self.resize(self.__tmpWinSize)

    def showServerEditor(self):
        """Slot to display the server editor dialog.
        """
        serverEditor = ServerDialog()
        r = serverEditor.exec_()
        if r:
            #TODO -- only display if plugins open:
            self.serversChangedMessage.showMessage(QApplication.translate(
                "MainWindow",
                "You may need to restart plugins for changes to take effect."))

    def showTempPasswordDialog(self):
        """ Sets overridePassword for a server.
        Using this one doesn't actually have to enter the password
        in the ServerDialog (and by extension save to disk).
        """
        serverList = ServerList()

        # Create a stringlist to be used by the qinputdialog
        stringList = []
        for server in serverList.getTable():
            stringList.append(server.name)

        # Display list of servers
        (serverString, ok) = QInputDialog.getItem(
            self,
            QApplication.translate("MainWindow", "Select server"),
            QApplication.translate("MainWindow", "Server:"),
            stringList,
            editable=False
        )
        if ok:
            server = serverList.getServerObjectByName(serverString)
            if server != None:
                # Ask for password
                (value, ok) = QInputDialog.getText(
                    self,
                    QApplication.translate("MainWindow", "Temporary password"),
                    QApplication.translate("MainWindow", "Enter password:"******"""Slot to display the settings dialog. If the settings dialog
        returns 1, i.e. the user has clicked the ok button, the
        loadSettings method is called with mainWin=False, to load the
        (assumed) newly changed settings.

        :param tab: The index of the tab to display in the settings
         dialog.
        :type tab: int
        """
        #settingsDialog = SettingsDialog(self.currentLanguage, self.languages)
        settingsDialog = SettingsDialog()
        if tab < 0:
            tab = 0
        settingsDialog.tabWidget.setCurrentIndex(tab)
        if settingsDialog.exec_():
            self.reloadPlugins()
#            # We assume that some settings is changed
#            # if the user clicked the ok button, and
#            # reloads the application settings
#            self.__loadSettings(mainWin=False)
#            # A Hack but it'll do for now
#            for a in self.langGroup.actions():
#                if a.data().toString() == self.currentLanguage:
#                    a.setChecked(True)

    def configurePlugins(self):
        """Slot to display the plugins configuration. This currently
        calls `showSettingsDialog` with tab index set to 2.
        """
        self.showSettingsDialog(1)

    def reloadPlugins(self):
        """Slot to reload plugins.
        """
        self.pluginWidget.updatePlugins()

    def pluginSelected(self, item):
        """This method will be called from the `PluginListWidget`.
        """
        # Clear the stylesheet when a tab is opened
        self.__setTabWidgetStyle(self.defaultTabStyle)

        widget = item.plugin.getPluginWidget(None, self)

        if platform.system() == "Windows":
            scroll = QScrollArea()
            scroll.setWidget(widget)
            scroll.setWidgetResizable(True)
            index = self.mainTabs.addTab(
                scroll, item.icon(), item.plugin.pluginUserString)
        else:
            index = self.mainTabs.addTab(
                widget, item.icon(), item.plugin.pluginUserString)

        self.mainTabs.setCurrentIndex(index)

    def tabClose(self, index):
        """Slot for the signal `tabCloseRequest(int)` for the tabMains.
        """

        widget = self.mainTabs.widget(index)

        # If the tab closed is one of these, enable the toggle-action
        if widget == self.pluginWidget:
            self.actionShowPluginList.setEnabled(True)
        if widget == self.welcomeTab:
            self.actionShowWelcomeTab.setEnabled(True)

        self.mainTabs.removeTab(index)

        # Unparent the widget since it was reparented by the QTabWidget
        # so it's garbage collected
        widget.setParent(None)

        # In case the widget contained circular references
        # -- force GC to take care of the objects since there can be
        #    quite many if it was BrowserWidget that was closed.
        # Can't call it directly since that'll be too soon
        QTimer.singleShot(1000, self.gc)

        # Let's do some styling of the tab widget when no tabs are opened
        if self.mainTabs.currentIndex() == -1:
            self.__setTabWidgetStyle(self.lumaHeadStyle)

    def gc(self):
        """Runs Python's garbage-collection manually.
        Used to make sure circular references are taken care of *now*.
        """
        gc.collect()

    def showWelcome(self):
        """Shows the Welcome-tab
        """
        self.__setTabWidgetStyle(self.defaultTabStyle)
        index = self.mainTabs.addTab(self.welcomeTab,
        QApplication.translate("MainWindow", "Welcome"))

        self.mainTabs.setCurrentIndex(index)
        self.actionShowWelcomeTab.setEnabled(False)

    def showPlugins(self):
        """Will show the pluginlistwidget-tab
        """
        self.__setTabWidgetStyle(self.defaultTabStyle)
        if self.mainTabs.indexOf(self.pluginWidget) == -1:
            index = self.mainTabs.addTab(
                self.pluginWidget, QApplication.translate(
                    "MainWindow", "Plugins"))
            self.mainTabs.setCurrentIndex(index)
            self.actionShowPluginList.setEnabled(False)

    def closeEvent(self, e):
        """Overrides the ``QMainWindow.closeEvent`` slot to save
        settings before we tear down the application.
        """
        self.__writeSettings()
        QMainWindow.closeEvent(self, e)
Ejemplo n.º 17
0
class DC(PluginBase, Ui_DC):
    qtcb_position_reached = pyqtSignal(int)
    qtcb_under_voltage = pyqtSignal(int)
    qtcb_emergency_shutdown = pyqtSignal()
    
    def __init__ (self, ipcon, uid):
        PluginBase.__init__(self, ipcon, uid)
     
        self.setupUi(self)
        
        self.dc = brick_dc.DC(self.uid)
        self.device = self.dc
        self.ipcon.add_device(self.dc)
        self.version = '.'.join(map(str, self.dc.get_version()[1]))
        
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.update_data)
        

        self.speedometer = SpeedoMeter()
        self.vertical_layout_right.insertWidget(4, self.speedometer)
        
        self.new_value = 0
        self.update_counter = 0
        
        self.full_brake_time = 0
        
        self.velocity_slider.sliderReleased.connect(self.velocity_slider_released)
        self.velocity_slider.valueChanged.connect(self.velocity_spin.setValue)
        self.velocity_spin.editingFinished.connect(self.velocity_spin_finished)
        
        self.acceleration_slider.sliderReleased.connect(self.acceleration_slider_released)
        self.acceleration_slider.valueChanged.connect(self.acceleration_spin.setValue)
        self.acceleration_spin.editingFinished.connect(self.acceleration_spin_finished)
        
        self.frequency_slider.sliderReleased.connect(self.frequency_slider_released)
        self.frequency_slider.valueChanged.connect(self.frequency_spin.setValue)
        self.frequency_spin.editingFinished.connect(self.frequency_spin_finished)
        
        self.radio_mode_brake.toggled.connect(self.brake_value_changed)
        self.radio_mode_coast.toggled.connect(self.coast_value_changed)
        
        self.minimum_voltage_button.pressed.connect(self.minimum_voltage_button_pressed)
        self.full_brake_button.pressed.connect(self.full_brake_pressed)
        self.enable_checkbox.stateChanged.connect(self.enable_state_changed)
        
        self.emergency_signal = None
        self.under_signal = None
        self.current_velocity_signal = None
        self.velocity_reached_signal = None
        
        self.qem = QErrorMessage(self)
        
        self.qtcb_under_voltage.connect(self.cb_under_voltage)
        self.dc.register_callback(self.dc.CALLBACK_UNDER_VOLTAGE,
                                  self.qtcb_under_voltage.emit) 
        
        self.qtcb_emergency_shutdown.connect(self.cb_emergency_shutdown)
        self.dc.register_callback(self.dc.CALLBACK_EMERGENCY_SHUTDOWN,
                                  self.qtcb_emergency_shutdown.emit) 
        
        self.qtcb_position_reached.connect(self.update_velocity)
        self.dc.register_callback(self.dc.CALLBACK_VELOCITY_REACHED,
                                  self.qtcb_position_reached.emit) 
        self.dc.register_callback(self.dc.CALLBACK_CURRENT_VELOCITY,
                                  self.qtcb_position_reached.emit) 
    
    def start(self):
        self.update_timer.start(1000)
        try:
            self.dc.set_current_velocity_period(100)
            self.update_start()
            self.update_data()
        except ip_connection.Error:
            return
        
    def stop(self):
        self.update_timer.stop()
        try:
            self.dc.set_current_velocity_period(0)
        except ip_connection.Error:
            return
        
    @staticmethod
    def has_name(name):
        return 'DC Brick' in name 
        
    def cb_emergency_shutdown(self):
        if not self.qem.isVisible():
            self.qem.setWindowTitle("Emergency Shutdown")
            self.qem.showMessage("Emergency Shutdown: Short-Circuit or Over-Temperature")
        
    def cb_under_voltage(self, ov):
        mv_str = self.minimum_voltage_label.text()
        ov_str = "%gV"  % round(ov/1000.0, 1)
        if not self.qem.isVisible():
            self.qem.setWindowTitle("Under Voltage")
            self.qem.showMessage("Under Voltage: Output Voltage of " + ov_str +
                                 " is below minimum voltage of " + mv_str)
        
    def enable_state_changed(self, state):
        try:
            if state == Qt.Checked:
                self.dc.enable()
            elif state == Qt.Unchecked:
                self.dc.disable()
        except ip_connection.Error:
            return
            
    def brake_value_changed(self, checked):
        if checked:
            try:
                self.dc.set_drive_mode(0)
            except ip_connection.Error:
                return
        
    def coast_value_changed(self, checked):
        if checked:
            try:
                self.dc.set_drive_mode(1)
            except ip_connection.Error:
                return
        
    def full_brake_pressed(self):
        try:
            self.dc.full_brake()
        except ip_connection.Error:
            return
        
    def minimum_voltage_selected(self, value):
        try:
            self.dc.set_minimum_voltage(value)
        except ip_connection.Error:
            return
        
    def minimum_voltage_button_pressed(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(5000)
        qid.setIntMaximum(0xFFFF)
        qid.setIntStep(100)
        try:
            qid.setIntValue(self.dc.get_minimum_voltage())
        except ip_connection.Error:
            return
        qid.intValueSelected.connect(self.minimum_voltage_selected)
        qid.setLabelText("Choose minimum motor voltage in mV.")
        qid.open()
        
    def stack_input_voltage_update(self, sv):
        sv_str = "%gV"  % round(sv/1000.0, 1)
        self.stack_voltage_label.setText(sv_str)
        
    def external_input_voltage_update(self, ev):
        ev_str = "%gV"  % round(ev/1000.0, 1)
        self.external_voltage_label.setText(ev_str)
        
    def minimum_voltage_update(self, mv):
        mv_str = "%gV"  % round(mv/1000.0, 1)
        self.minimum_voltage_label.setText(mv_str)
        
    def drive_mode_update(self, dm):
        if dm == 0:
            self.radio_mode_brake.setChecked(True)
            self.radio_mode_coast.setChecked(False)
        else:
            self.radio_mode_brake.setChecked(False)
            self.radio_mode_coast.setChecked(True)
            
    def current_consumption_update(self, cc):
        if cc >= 1000:
            cc_str = "%gA"  % round(cc/1000.0, 1)
        else:
            cc_str = "%gmA" % cc
            
        self.current_label.setText(cc_str)

    
    def update_velocity(self, value):
        if value != self.speedometer.value():
            self.speedometer.set_velocity(value)
        
    def update_start(self):
        try:
            dm = self.dc.get_drive_mode()
            self.drive_mode_update(dm)
            
            if not self.velocity_slider.isSliderDown():
                velocity = self.dc.get_velocity()
                if velocity != self.velocity_slider.sliderPosition():
                    self.velocity_slider.setSliderPosition(velocity)
                    self.velocity_spin.setValue(velocity)
                 
            if not self.acceleration_slider.isSliderDown():
                acceleration = self.dc.get_acceleration()
                if acceleration != self.acceleration_slider.sliderPosition():
                    self.acceleration_slider.setSliderPosition(acceleration)
                    self.acceleration_spin.setValue(acceleration)
                    
            if not self.frequency_slider.isSliderDown():
                frequency = self.dc.get_pwm_frequency()
                if frequency != self.frequency_slider.sliderPosition():
                    self.frequency_slider.setSliderPosition(frequency)
                    self.frequency_spin.setValue(frequency)
    
            enabled = self.dc.is_enabled()
            if enabled:
                self.enable_checkbox.setCheckState(Qt.Checked)
            else:
                self.enable_checkbox.setCheckState(Qt.Unchecked)
        except ip_connection.Error:
            return
        
    def update_data(self):
        try:
            sv = self.dc.get_stack_input_voltage()
            ev = self.dc.get_external_input_voltage()
            mv = self.dc.get_minimum_voltage()
            cc = self.dc.get_current_consumption()
        except ip_connection.Error:
            return
        
        self.stack_input_voltage_update(sv)
        self.external_input_voltage_update(ev)
        self.minimum_voltage_update(mv)
        self.current_consumption_update(cc)
        
    def acceleration_slider_released(self):
        value = self.acceleration_slider.value()
        self.acceleration_spin.setValue(value)
        try:
            self.dc.set_acceleration(value)
        except ip_connection.Error:
            return
        
    def acceleration_spin_finished(self):
        value = self.acceleration_spin.value()
        self.acceleration_slider.setValue(value)
        try:
            self.dc.set_acceleration(value)
        except ip_connection.Error:
            return
        
    def velocity_slider_released(self):
        value = self.velocity_slider.value()
        self.velocity_spin.setValue(value)
        try:
            self.dc.set_velocity(value)
        except ip_connection.Error:
            return
        
    def velocity_spin_finished(self):
        value = self.velocity_spin.value()
        self.velocity_slider.setValue(value)
        try:
            self.dc.set_velocity(value)
        except ip_connection.Error:
            return
        
    def frequency_slider_released(self):
        value = self.frequency_slider.value()
        self.frequency_spin.setValue(value)
        try:
            self.dc.set_pwm_frequency(value)
        except ip_connection.Error:
            return
        
    def frequency_spin_finished(self):
        value = self.frequency_spin.value()
        self.frequency_slider.setValue(value)
        try:
            self.dc.set_pwm_frequency(value)
        except ip_connection.Error:
            return
Ejemplo n.º 18
0
class Stepper(PluginBase, Ui_Stepper):
    qtcb_position_reached = pyqtSignal(int)
    qtcb_under_voltage = pyqtSignal(int)

    def __init__(self, ipcon, uid):
        PluginBase.__init__(self, ipcon, uid)
        self.setupUi(self)

        self.stepper = brick_stepper.Stepper(self.uid)
        self.device = self.stepper
        self.ipcon.add_device(self.stepper)
        self.version = '.'.join(map(str, self.stepper.get_version()[1]))

        self.endis_all(False)

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

        self.speedometer = SpeedoMeter()
        self.vertical_layout_right.insertWidget(5, self.speedometer)

        self.new_value = 0
        self.update_counter = 0

        self.full_brake_time = 0

        self.qem = QErrorMessage(self)
        self.qem.setWindowTitle("Under Voltage")

        self.velocity_slider.sliderReleased.connect(
            self.velocity_slider_released)
        self.velocity_slider.valueChanged.connect(self.velocity_spin.setValue)
        self.velocity_spin.editingFinished.connect(self.velocity_spin_finished)

        self.acceleration_slider.sliderReleased.connect(
            self.acceleration_slider_released)
        self.acceleration_slider.valueChanged.connect(
            self.acceleration_spin.setValue)
        self.acceleration_spin.editingFinished.connect(
            self.acceleration_spin_finished)

        self.deceleration_slider.sliderReleased.connect(
            self.deceleration_slider_released)
        self.deceleration_slider.valueChanged.connect(
            self.deceleration_spin.setValue)
        self.deceleration_spin.editingFinished.connect(
            self.deceleration_spin_finished)

        self.decay_slider.sliderReleased.connect(self.decay_slider_released)
        self.decay_slider.valueChanged.connect(self.decay_spin.setValue)
        self.decay_spin.editingFinished.connect(self.decay_spin_finished)

        self.enable_checkbox.stateChanged.connect(self.enable_state_changed)
        self.forward_button.pressed.connect(self.forward_pressed)
        self.stop_button.pressed.connect(self.stop_pressed)
        self.full_brake_button.pressed.connect(self.full_brake_pressed)
        self.backward_button.pressed.connect(self.backward_pressed)
        self.to_button.pressed.connect(self.to_button_pressed)
        self.steps_button.pressed.connect(self.steps_button_pressed)
        self.motor_current_button.pressed.connect(
            self.motor_current_button_pressed)
        self.minimum_motor_voltage_button.pressed.connect(
            self.minimum_motor_voltage_button_pressed)

        self.mode_dropbox.currentIndexChanged.connect(self.mode_changed)

        self.qtcb_position_reached.connect(self.cb_position_reached)
        self.stepper.register_callback(self.stepper.CALLBACK_POSITION_REACHED,
                                       self.qtcb_position_reached.emit)

        self.qtcb_under_voltage.connect(self.cb_under_voltage)
        self.stepper.register_callback(self.stepper.CALLBACK_UNDER_VOLTAGE,
                                       self.qtcb_under_voltage.emit)

    def start(self):
        self.update_timer.start(100)
        self.update_start()

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

    @staticmethod
    def has_name(name):
        return 'Stepper Brick' in name

    def cb_position_reached(self, position):
        self.position_update(position)
        self.endis_all(True)

    def disable_list(self, button_list):
        for button in button_list:
            button.setEnabled(False)

    def endis_all(self, value):
        self.forward_button.setEnabled(value)
        self.stop_button.setEnabled(value)
        self.backward_button.setEnabled(value)
        self.to_button.setEnabled(value)
        self.steps_button.setEnabled(value)
        self.full_brake_button.setEnabled(value)

    def mode_changed(self, index):
        try:
            self.stepper.set_step_mode(1 << index)
        except ip_connection.Error:
            return

    def forward_pressed(self):
        try:
            self.stepper.drive_forward()
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, self.steps_button])

    def backward_pressed(self):
        try:
            self.stepper.drive_backward()
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, self.steps_button])

    def stop_pressed(self):
        try:
            self.stepper.stop()
        except ip_connection.Error:
            return
        self.endis_all(True)

    def full_brake_pressed(self):
        try:
            self.stepper.full_brake()
        except ip_connection.Error:
            return
        self.endis_all(True)

    def to_button_pressed(self):
        drive_to = self.to_spin.value()
        try:
            self.stepper.set_target_position(drive_to)
        except ip_connection.Error:
            return
        self.disable_list([
            self.to_button, self.steps_button, self.forward_button,
            self.backward_button
        ])

    def steps_button_pressed(self):
        drive_steps = self.steps_spin.value()
        try:
            self.stepper.set_steps(drive_steps)
        except ip_connection.Error:
            return
        self.disable_list([
            self.to_button, self.steps_button, self.forward_button,
            self.backward_button
        ])

    def motor_current_button_pressed(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(0)
        qid.setIntMaximum(2500)
        qid.setIntStep(100)
        try:
            qid.setIntValue(self.stepper.get_motor_current())
        except ip_connection.Error:
            return
        qid.intValueSelected.connect(self.motor_current_selected)
        qid.setLabelText("Choose motor current in mA.")
        #                         "<font color=red>Setting this too high can destroy your Motor.</font>")
        qid.open()

    def minimum_motor_voltage_button_pressed(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(0)
        qid.setIntMaximum(40000)
        qid.setIntStep(100)
        try:
            qid.setIntValue(self.stepper.get_minimum_voltage())
        except ip_connection.Error:
            return
        qid.intValueSelected.connect(self.minimum_motor_voltage_selected)
        qid.setLabelText("Choose minimum motor voltage in mV.")
        qid.open()

    def motor_current_selected(self, value):
        try:
            self.stepper.set_motor_current(value)
        except ip_connection.Error:
            return

    def minimum_motor_voltage_selected(self, value):
        try:
            self.stepper.set_minimum_voltage(value)
        except ip_connection.Error:
            return

    def cb_under_voltage(self, ov):
        mv_str = self.minimum_voltage_label.text()
        ov_str = "%gV" % round(ov / 1000.0, 1)
        if not self.qem.isVisible():
            self.qem.showMessage("Under Voltage: Output Voltage of " + ov_str +
                                 " is below minimum voltage of " + mv_str)

    def enable_state_changed(self, state):
        try:
            if state == Qt.Checked:
                self.endis_all(True)
                self.stepper.enable()
            elif state == Qt.Unchecked:
                self.endis_all(False)
                self.stepper.disable()
        except ip_connection.Error:
            return

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

    def external_input_voltage_update(self, ev):
        ev_str = "%gV" % round(ev / 1000.0, 1)
        self.external_voltage_label.setText(ev_str)

    def minimum_voltage_update(self, mv):
        mv_str = "%gV" % round(mv / 1000.0, 1)
        self.minimum_voltage_label.setText(mv_str)

    def maximum_current_update(self, cur):
        cur_str = "%gA" % round(cur / 1000.0, 1)
        self.maximum_current_label.setText(cur_str)

    def position_update(self, pos):
        pos_str = "%g" % pos
        self.position_label.setText(pos_str)

    def remaining_steps_update(self, ste):
        ste_str = "%g" % ste
        self.remaining_steps_label.setText(ste_str)

    def mode_update(self, mod):
        if mod == 8:
            index = 3
        elif mod == 4:
            index = 2
        elif mod == 2:
            index = 1
        else:
            index = 0

        self.mode_dropbox.setCurrentIndex(index)

    def update_start(self):
        try:
            if not self.velocity_slider.isSliderDown():
                velocity = self.stepper.get_max_velocity()
                if velocity != self.velocity_slider.sliderPosition():
                    self.velocity_slider.setSliderPosition(velocity)
                    self.velocity_spin.setValue(velocity)

            if not self.acceleration_slider.isSliderDown() and \
               not self.deceleration_slider.isSliderDown():
                acc, dec = self.stepper.get_speed_ramping()
                if acc != self.acceleration_slider.sliderPosition():
                    self.acceleration_slider.setSliderPosition(acc)
                    self.acceleration_spin.setValue(acc)
                if dec != self.deceleration_slider.sliderPosition():
                    self.deceleration_slider.setSliderPosition(dec)
                    self.deceleration_spin.setValue(dec)

            if not self.decay_slider.isSliderDown():
                dec = self.stepper.get_decay()
                if dec != self.decay_slider.sliderPosition():
                    self.decay_slider.setSliderPosition(dec)
                    self.decay_spin.setValue(dec)

            enabled = self.stepper.is_enabled()
            if enabled:
                if self.enable_checkbox.checkState() != Qt.Checked:
                    self.endis_all(True)
                    self.enable_checkbox.setCheckState(Qt.Checked)
            else:
                if self.enable_checkbox.checkState() != Qt.Unchecked:
                    self.endis_all(False)
                    self.enable_checkbox.setCheckState(Qt.Unchecked)
        except ip_connection.Error:
            return

    def update_infos(self):
        try:
            cur = self.stepper.get_motor_current()
            sv = self.stepper.get_stack_input_voltage()
            ev = self.stepper.get_external_input_voltage()
            mv = self.stepper.get_minimum_voltage()
            mod = self.stepper.get_step_mode()
        except ip_connection.Error:
            return

        self.maximum_current_update(cur)
        self.stack_input_voltage_update(sv)
        self.external_input_voltage_update(ev)
        self.minimum_voltage_update(mv)
        self.mode_update(mod)

    def update_values(self):
        try:
            ste = self.stepper.get_remaining_steps()
            pos = self.stepper.get_current_position()
            self.remaining_steps_update(ste)
            self.position_update(pos)

            current_velocity = self.stepper.get_current_velocity()
            if current_velocity != self.speedometer.value():
                self.speedometer.set_velocity(current_velocity)
        except ip_connection.Error:
            return

    def update_data(self):
        try:
            ste = self.stepper.get_remaining_steps()
            pos = self.stepper.get_current_position()
            self.remaining_steps_update(ste)
            self.position_update(pos)

            current_velocity = self.stepper.get_current_velocity()
            if current_velocity != self.speedometer.value():
                self.speedometer.set_velocity(current_velocity)
        except ip_connection.Error:
            return
        self.update_counter += 1
        if self.update_counter % 10 == 0:
            self.update_infos()

        self.update_values()

    def velocity_slider_released(self):
        value = self.velocity_slider.value()
        self.velocity_spin.setValue(value)
        try:
            self.stepper.set_max_velocity(value)
        except ip_connection.Error:
            return

    def velocity_spin_finished(self):
        value = self.velocity_spin.value()
        self.velocity_slider.setValue(value)
        try:
            self.stepper.set_max_velocity(value)
        except ip_connection.Error:
            return

    def acceleration_slider_released(self):
        acc = self.acceleration_slider.value()
        dec = self.deceleration_slider.value()
        self.acceleration_spin.setValue(acc)
        try:
            self.stepper.set_speed_ramping(acc, dec)
        except ip_connection.Error:
            return

    def acceleration_spin_finished(self):
        acc = self.acceleration_spin.value()
        dec = self.deceleration_spin.value()
        self.acceleration_slider.setValue(acc)
        try:
            self.stepper.set_speed_ramping(acc, dec)
        except ip_connection.Error:
            return

    def deceleration_slider_released(self):
        acc = self.acceleration_slider.value()
        dec = self.deceleration_slider.value()
        self.deceleration_spin.setValue(dec)
        try:
            self.stepper.set_speed_ramping(acc, dec)
        except ip_connection.Error:
            return

    def deceleration_spin_finished(self):
        acc = self.acceleration_spin.value()
        dec = self.deceleration_spin.value()
        self.deceleration_slider.setValue(dec)
        try:
            self.stepper.set_speed_ramping(acc, dec)
        except ip_connection.Error:
            return

    def decay_slider_released(self):
        value = self.decay_slider.value()
        self.decay_spin.setValue(value)
        try:
            self.stepper.set_decay(value)
        except ip_connection.Error:
            return

    def decay_spin_finished(self):
        value = self.decay_spin.value()
        self.decay_slider.setValue(value)
        try:
            self.stepper.set_decay(value)
        except ip_connection.Error:
            return
Ejemplo n.º 19
0
class ImagesWidget(QWidget, Ui_Images):
    images = None

    def __init__(self, parent, app):
        super(QWidget, self).__init__()
        self.app = app

        self.setupUi(self)

        self.error_msg = QErrorMessage()
        self.error_msg.setWindowTitle("Starter Kit: Blinkenlights Demo " +
                                      config.DEMO_VERSION)

        self.slider_frame_rate.valueChanged.connect(
            self.slider_frame_rate_changed)
        self.spinbox_frame_rate.valueChanged.connect(
            self.spinbox_frame_rate_changed)
        self.button_choose.pressed.connect(self.choose_pressed)
        self.button_show.pressed.connect(self.show_pressed)
        self.button_default.pressed.connect(self.default_pressed)

        self.update_frame_rate_timer = QTimer(self)
        self.update_frame_rate_timer.timeout.connect(self.update_frame_rate)

        self.default_pressed()

    def start(self):
        self.images = Images(self.app.ipcon)

        self.update_frame_rate()

        self.images.frame_rendered(0)

    def stop(self):
        if self.images:
            self.images.stop_rendering()
            self.images = None

    def spinbox_frame_rate_changed(self, frame_rate):
        self.slider_frame_rate.setValue(frame_rate)
        self.update_frame_rate_timer.start(100)

    def slider_frame_rate_changed(self, frame_rate):
        self.spinbox_frame_rate.setValue(frame_rate)

    def show_pressed(self):
        if self.images:
            files = unicode(self.text_edit_files.toPlainText()).strip()

            if len(files) > 0:
                new_images = files.split('\n')

                try:
                    self.images.set_new_images(new_images)
                except Exception as e:
                    self.error_msg.showMessage(str(e))

                self.images.frame_prepare_next()
                self.images.frame_rendered(0)

    def choose_pressed(self):
        dialog = QFileDialog()
        dialog.setDirectory(QDir.homePath())
        dialog.setFileMode(QFileDialog.ExistingFiles)

        if dialog.exec_():
            filenames = dialog.selectedFiles()
            for filename in filenames:
                self.text_edit_files.append(filename)

    def default_pressed(self):
        self.spinbox_frame_rate.setValue(1)

    def update_frame_rate(self):
        self.update_frame_rate_timer.stop()

        config.IMAGES_FRAME_RATE = self.spinbox_frame_rate.value()

        if self.images:
            self.images.update_frame_rate()
Ejemplo n.º 20
0
class Stepper(PluginBase, Ui_Stepper):
    qtcb_position_reached = pyqtSignal(int)
    qtcb_under_voltage = pyqtSignal(int)
    
    def __init__(self, *args):
        PluginBase.__init__(self, BrickStepper, *args)

        self.setupUi(self)
     
        self.stepper = self.device
     
        self.endis_all(False)
        
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.update_data)
        
        self.new_value = 0
        self.update_counter = 0
        
        self.full_brake_time = 0

        self.qem = QErrorMessage(self)
        self.qem.setWindowTitle("Under Voltage")

        self.decay_widget.hide()

        self.setting_sync_rect_checkbox = False

        self.velocity_syncer = SliderSpinSyncer(self.velocity_slider,
                                                self.velocity_spin,
                                                self.velocity_changed)

        self.acceleration_syncer = SliderSpinSyncer(self.acceleration_slider,
                                                    self.acceleration_spin,
                                                    self.acceleration_changed)

        self.deceleration_syncer = SliderSpinSyncer(self.deceleration_slider,
                                                    self.deceleration_spin,
                                                    self.deceleration_changed)

        self.decay_syncer = SliderSpinSyncer(self.decay_slider,
                                             self.decay_spin,
                                             self.decay_changed)

        self.enable_checkbox.toggled.connect(self.enable_toggled)
        self.forward_button.clicked.connect(self.forward_clicked)
        self.stop_button.clicked.connect(self.stop_clicked)
        self.full_brake_button.clicked.connect(self.full_brake_clicked)
        self.backward_button.clicked.connect(self.backward_clicked)
        self.to_button.clicked.connect(self.to_button_clicked)
        self.steps_button.clicked.connect(self.steps_button_clicked)
        self.motor_current_button.clicked.connect(self.motor_current_button_clicked)
        self.minimum_motor_voltage_button.clicked.connect(self.minimum_motor_voltage_button_clicked)
        self.sync_rect_checkbox.toggled.connect(self.sync_rect_toggled)
        
        self.mode_dropbox.currentIndexChanged.connect(self.mode_changed)
        
        self.qtcb_position_reached.connect(self.cb_position_reached)
        self.stepper.register_callback(self.stepper.CALLBACK_POSITION_REACHED, 
                                       self.qtcb_position_reached.emit)
        
        self.qtcb_under_voltage.connect(self.cb_under_voltage)
        self.stepper.register_callback(self.stepper.CALLBACK_UNDER_VOLTAGE, 
                                       self.qtcb_under_voltage.emit)

        self.ste = 0
        self.pos = 0
        self.current_velocity = 0
        self.cur = 0
        self.sv  = 0
        self.ev  = 0
        self.mv  = 0
        self.mod = 0

        if self.firmware_version >= (1, 1, 4):
            reset = QAction('Reset', self)
            reset.triggered.connect(lambda: self.stepper.reset())
            self.set_actions(reset)
        
    def start(self):
        self.update_timer.start(100)
        self.update_start()
        
    def stop(self):
        self.update_timer.stop()

    def destroy(self):
        pass

    def get_url_part(self):
        return 'stepper'

    @staticmethod
    def has_device_identifier(device_identifier):
        return device_identifier == BrickStepper.DEVICE_IDENTIFIER
    
    def cb_position_reached(self, position):
        self.position_update(position)
        self.endis_all(True)
            
    def disable_list(self, button_list):
        for button in button_list:
            button.setEnabled(False)
        
    def endis_all(self, value):
        self.forward_button.setEnabled(value)
        self.stop_button.setEnabled(value)
        self.backward_button.setEnabled(value)
        self.to_button.setEnabled(value)
        self.steps_button.setEnabled(value)
        self.full_brake_button.setEnabled(value)
        
    def mode_changed(self, index):
        try:
            self.stepper.set_step_mode(1 << index)
            self.mod = 1 << index
        except ip_connection.Error:
            return
        
    def forward_clicked(self):
        try:
            self.stepper.drive_forward()
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, self.steps_button])
        
    def backward_clicked(self):
        try:
            self.stepper.drive_backward()
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, self.steps_button])
        
    def stop_clicked(self):
        try:
            self.stepper.stop()
        except ip_connection.Error:
            return
        self.endis_all(True)
        
    def full_brake_clicked(self):
        try:
            self.stepper.full_brake()
        except ip_connection.Error:
            return
        self.endis_all(True)
        
    def to_button_clicked(self):
        drive_to = self.to_spin.value()
        try:
            self.stepper.set_target_position(drive_to)
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, 
                           self.steps_button, 
                           self.forward_button,
                           self.backward_button])
        
    def steps_button_clicked(self):
        drive_steps = self.steps_spin.value()
        try:
            self.stepper.set_steps(drive_steps)
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, 
                           self.steps_button, 
                           self.forward_button,
                           self.backward_button])
        
    def motor_current_button_clicked(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(0)
        qid.setIntMaximum(2500)
        qid.setIntStep(100)
        async_call(self.stepper.get_motor_current, None, qid.setIntValue, self.increase_error_count)
        qid.intValueSelected.connect(self.motor_current_selected)
        qid.setLabelText("Choose motor current in mA.")
#                         "<font color=red>Setting this too high can destroy your Motor.</font>")
        qid.open()
        
    def minimum_motor_voltage_button_clicked(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(0)
        qid.setIntMaximum(40000)
        qid.setIntStep(100)
        async_call(self.stepper.get_minimum_voltage, None, qid.setIntValue, self.increase_error_count)
        qid.intValueSelected.connect(self.minimum_motor_voltage_selected)
        qid.setLabelText("Choose minimum motor voltage in mV.")
        qid.open()
        
    def motor_current_selected(self, value):
        try:
            self.stepper.set_motor_current(value)
        except ip_connection.Error:
            return
        
    def minimum_motor_voltage_selected(self, value):
        try:
            self.stepper.set_minimum_voltage(value)
        except ip_connection.Error:
            return
        
    def cb_under_voltage(self, ov):
        mv_str = self.minimum_voltage_label.text()
        ov_str = "%gV" % round(ov/1000.0, 1)
        if not self.qem.isVisible():
            self.qem.showMessage("Under Voltage: Output Voltage of " + ov_str +
                                 " is below minimum voltage of " + mv_str,
                                 "Stepper_UnderVoltage")

    def enable_toggled(self, checked):
        try:
            if checked:
                if not self.stepper.is_enabled():
                    self.endis_all(True)
                    self.stepper.enable()
            else:
                if self.stepper.is_enabled():
                    self.endis_all(False)
                    self.stepper.disable()
        except ip_connection.Error:
            return

    def sync_rect_toggled(self, checked):
        if not self.setting_sync_rect_checkbox and checked:
            rc = QMessageBox.warning(get_main_window(), 'Synchronous Rectification',
                                     'If you want to use high speeds (> 10000 steps/s) for a large stepper motor with a ' +
                                     'large inductivity we strongly suggest that you do not enable synchronous rectification. ' +
                                     'Otherwise the Brick may not be able to cope with the load and overheat.',
                                     QMessageBox.Ok | QMessageBox.Cancel)

            if rc != QMessageBox.Ok:
                self.sync_rect_checkbox.setChecked(False)
                return

        try:
            self.stepper.set_sync_rect(checked)
        except ip_connection.Error:
            return

        self.decay_widget.setVisible(checked)

    def stack_input_voltage_update(self, sv):
        sv_str = "%gV"  % round(sv/1000.0, 1)
        self.stack_voltage_label.setText(sv_str)
        
    def external_input_voltage_update(self, ev):
        ev_str = "%gV"  % round(ev/1000.0, 1)
        self.external_voltage_label.setText(ev_str)
        
    def minimum_voltage_update(self, mv):
        mv_str = "%gV"  % round(mv/1000.0, 1)
        self.minimum_voltage_label.setText(mv_str)
        
    def maximum_current_update(self, cur):
        cur_str = "%gA"  % round(cur/1000.0, 1)
        self.maximum_current_label.setText(cur_str)
        
    def position_update(self, pos):
        pos_str = "%d" % pos
        self.position_label.setText(pos_str)
        
    def remaining_steps_update(self, ste):
        ste_str = "%d" % ste
        self.remaining_steps_label.setText(ste_str)
        
    def current_velocity_update(self, velocity):
        velocity_str = "%d" % velocity
        self.current_velocity_label.setText(velocity_str)
        self.speedometer.set_velocity(velocity)

    def mode_update(self, mod):
        if mod == 8:
            index = 3
        elif mod == 4:
            index = 2
        elif mod == 2:
            index = 1
        else:
            index = 0
            
        self.mode_dropbox.setCurrentIndex(index)
        
    def get_max_velocity_async(self, velocity):
        if not self.velocity_slider.isSliderDown():
            if velocity != self.velocity_slider.sliderPosition():
                self.velocity_slider.setSliderPosition(velocity)
                self.velocity_spin.setValue(velocity)
        
    def get_speed_ramping_async(self, ramp):
        acc, dec = ramp
        if not self.acceleration_slider.isSliderDown() and \
           not self.deceleration_slider.isSliderDown():
            if acc != self.acceleration_slider.sliderPosition():
                self.acceleration_slider.setSliderPosition(acc)
                self.acceleration_spin.setValue(acc)
            if dec != self.deceleration_slider.sliderPosition():
                self.deceleration_slider.setSliderPosition(dec)
                self.deceleration_spin.setValue(dec)

    def get_decay_async(self, decay):
        if not self.decay_slider.isSliderDown():
            if decay != self.decay_slider.sliderPosition():
                self.decay_slider.setSliderPosition(decay)
                self.decay_spin.setValue(decay)
        
    def is_enabled_async(self, enabled):
        if enabled:
            if not self.enable_checkbox.isChecked():
                self.endis_all(True)
                self.enable_checkbox.setChecked(True)
        else:
            if self.enable_checkbox.isChecked():
                self.endis_all(False)
                self.enable_checkbox.setChecked(False)

    def is_sync_rect_async(self, sync_rect):
        self.setting_sync_rect_checkbox = True
        self.sync_rect_checkbox.setChecked(sync_rect)
        self.setting_sync_rect_checkbox = False

    def update_start(self):
        async_call(self.stepper.get_max_velocity, None, self.get_max_velocity_async, self.increase_error_count)
        async_call(self.stepper.get_speed_ramping, None, self.get_speed_ramping_async, self.increase_error_count)
        async_call(self.stepper.get_decay, None, self.get_decay_async, self.increase_error_count)
        async_call(self.stepper.is_enabled, None, self.is_enabled_async, self.increase_error_count)
        async_call(self.stepper.is_sync_rect, None, self.is_sync_rect_async, self.increase_error_count)

    def update_data(self):
        async_call(self.stepper.get_remaining_steps, None, self.remaining_steps_update, self.increase_error_count)
        async_call(self.stepper.get_current_position, None, self.position_update, self.increase_error_count)
        async_call(self.stepper.get_current_velocity, None, self.current_velocity_update, self.increase_error_count)

        self.update_counter += 1
        if self.update_counter % 10 == 0:
            async_call(self.stepper.get_motor_current, None, self.maximum_current_update, self.increase_error_count)
            async_call(self.stepper.get_stack_input_voltage, None, self.stack_input_voltage_update, self.increase_error_count)
            async_call(self.stepper.get_external_input_voltage, None, self.external_input_voltage_update, self.increase_error_count)
            async_call(self.stepper.get_minimum_voltage, None, self.minimum_voltage_update, self.increase_error_count)
            async_call(self.stepper.get_step_mode, None, self.mode_update, self.increase_error_count)

    def velocity_changed(self, value):
        try:
            self.stepper.set_max_velocity(value)
        except ip_connection.Error:
            return

    def acceleration_changed(self, value):
        dec = self.deceleration_spin.value()
        try:
            self.stepper.set_speed_ramping(value, dec)
        except ip_connection.Error:
            return
            
    def deceleration_changed(self, value):
        acc = self.acceleration_slider.value()
        try:
            self.stepper.set_speed_ramping(acc, value)
        except ip_connection.Error:
            return

    def decay_changed(self, value):
        try:
            self.stepper.set_decay(value)
        except ip_connection.Error:
            return
Ejemplo n.º 21
0
class WeatherStation(QApplication):
    HOST = "localhost"
    PORT = 4223

    ipcon = None
    lcd = None
    al = None
    hum = None
    baro = None

    projects = []
    active_project = None

    error_msg = None

    def __init__(self, args):
        super(QApplication, self).__init__(args)

        self.error_msg = QErrorMessage()
        self.ipcon = IPConnection()

        signal.signal(signal.SIGINT, self.exit_demo)
        signal.signal(signal.SIGTERM, self.exit_demo)

        timer = QTimer(self)
        timer.setSingleShot(True)
        timer.timeout.connect(self.connect)
        timer.start(1)

    def exit_demo(self, signl=None, frme=None):
        try:
            self.ipcon.disconnect()
            self.timer.stop()
            self.tabs.destroy()
        except:
            pass

        sys.exit()

    def open_gui(self):
        self.main = MainWindow(self)
        self.main.setFixedSize(730, 430)
        self.main.setWindowIcon(QIcon(os.path.join(ProgramPath.program_path(), "demo-icon.png")))
        
        self.tabs = QTabWidget()
        
        widget = QWidget()
        layout = QVBoxLayout()
        layout.addWidget(self.tabs)
        widget.setLayout(layout)

        self.main.setCentralWidget(widget)
        
        self.projects.append(ProjectEnvDisplay(self.tabs, self))
        self.projects.append(ProjectStatistics(self.tabs, self))
        self.projects.append(ProjectXively(self.tabs, self))

        self.tabs.addTab(self.projects[0], "Display Environment Measurements")
        self.tabs.addTab(self.projects[1], "Show Statistics with Button Control")
        self.tabs.addTab(self.projects[2], "Connect to Xively")

        self.active_project = self.projects[0]

        self.tabs.currentChanged.connect(self.tabChangedSlot)

        self.main.setWindowTitle("Starter Kit: Weather Station Demo " + config.DEMO_VERSION)
        self.main.show()

    def connect(self):
        try:
            self.ipcon.connect(WeatherStation.HOST, WeatherStation.PORT)
        except Error as e:
            self.error_msg.showMessage('Connection Error: ' + str(e.description) + "\nBrickd installed and running?")
            return
        except socket.error as e:
            self.error_msg.showMessage('Socket error: ' + str(e) + "\nBrickd installed and running?")
            return

        self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE,
                                     self.cb_enumerate)
        self.ipcon.register_callback(IPConnection.CALLBACK_CONNECTED,
                                     self.cb_connected)

        try:
            self.ipcon.enumerate()
        except Error as e:
            self.error_msg.showMessage('Enumerate Error: ' + str(e.description))
            return

        self.open_gui()

    def tabChangedSlot(self, tabIndex):

        if self.lcd is not None:
            self.lcd.clear_display()

        self.active_project = self.projects[tabIndex]

    def cb_illuminance(self, illuminance):
        for p in self.projects:
            p.update_illuminance(illuminance)

    def cb_humidity(self, humidity):
        for p in self.projects:
            p.update_humidity(humidity)

    def cb_air_pressure(self, air_pressure):
        for p in self.projects:
            p.update_air_pressure(air_pressure)

        try:
            temperature = self.baro.get_chip_temperature()
        except Error as e:
            print('Could not get temperature: ' + str(e.description))
            return

        for p in self.projects:
            p.update_temperature(temperature)

    def configure_custom_chars(self):
        c = [[0x00 for x in range(8)] for y in range(8)]
	
        c[0] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff]
        c[1] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff]
        c[2] = [0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff]
        c[3] = [0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]
        c[4] = [0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff]
        c[5] = [0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
        c[6] = [0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
        c[7] = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]

        for i in range(len(c)):
            self.lcd.set_custom_character(i, c[i]);

    def cb_button_pressed(self, button):
        for p in self.projects:
            p.button_pressed(button)

    def cb_enumerate(self, uid, connected_uid, position, hardware_version,
                     firmware_version, device_identifier, enumeration_type):
        if enumeration_type == IPConnection.ENUMERATION_TYPE_CONNECTED or \
           enumeration_type == IPConnection.ENUMERATION_TYPE_AVAILABLE:
            if device_identifier == LCD20x4.DEVICE_IDENTIFIER:
                try:
                    self.lcd = LCD20x4(uid, self.ipcon)
                    self.lcd.clear_display()
                    self.lcd.backlight_on()
                    self.lcd.register_callback(self.lcd.CALLBACK_BUTTON_PRESSED, self.cb_button_pressed)
                    self.configure_custom_chars()

                except Error as e:
                    self.error_msg.showMessage('LCD 20x4 init failed: ' + str(e.description))
                    self.lcd = None
            elif device_identifier == AmbientLight.DEVICE_IDENTIFIER:
                try:
                    self.al = AmbientLight(uid, self.ipcon)
                    self.al.set_illuminance_callback_period(1000)
                    self.al.register_callback(self.al.CALLBACK_ILLUMINANCE,
                                              self.cb_illuminance)
                except Error as e:
                    self.error_msg.showMessage('Ambient Light init failed: ' + str(e.description))
                    self.al = None
            elif device_identifier == Humidity.DEVICE_IDENTIFIER:
                try:
                    self.hum = Humidity(uid, self.ipcon)
                    self.hum.set_humidity_callback_period(1000)
                    self.hum.register_callback(self.hum.CALLBACK_HUMIDITY,
                                               self.cb_humidity)
                except Error as e:
                    self.error_msg.showMessage('Humidity init failed: ' + str(e.description))
                    self.hum = None
            elif device_identifier == Barometer.DEVICE_IDENTIFIER:
                try:
                    self.baro = Barometer(uid, self.ipcon)
                    self.baro.set_air_pressure_callback_period(1000)
                    self.baro.register_callback(self.baro.CALLBACK_AIR_PRESSURE,
                                                self.cb_air_pressure)
                except Error as e:
                    self.error_msg.showMessage('Barometer init failed: ' + str(e.description))
                    self.baro = None

    def cb_connected(self, connected_reason):
        if connected_reason == IPConnection.CONNECT_REASON_AUTO_RECONNECT:

            while True:
                try:
                    self.ipcon.enumerate()
                    break
                except Error as e:
                    self.error_msg.showMessage('Enumerate Error: ' + str(e.description))
                    time.sleep(1)
Ejemplo n.º 22
0
class Stepper(PluginBase, Ui_Stepper):
    qtcb_position_reached = pyqtSignal(int)
    qtcb_under_voltage = pyqtSignal(int)
    
    def __init__(self, ipcon, uid, version):
        PluginBase.__init__(self, ipcon, uid, 'Stepper Brick', version)
        
        self.setupUi(self)
     
        self.stepper = BrickStepper(uid, ipcon)
        self.device = self.stepper
     
        self.endis_all(False)
        
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.update_data)

        self.speedometer = SpeedoMeter()
        self.vertical_layout_right.insertWidget(5, self.speedometer)
        
        self.new_value = 0
        self.update_counter = 0
        
        self.full_brake_time = 0

        self.qem = QErrorMessage(self)
        self.qem.setWindowTitle("Under Voltage")
        
        self.velocity_slider.sliderReleased.connect(self.velocity_slider_released)
        self.velocity_slider.valueChanged.connect(self.velocity_spin.setValue)
        self.velocity_spin.editingFinished.connect(self.velocity_spin_finished)
        
        self.acceleration_slider.sliderReleased.connect(self.acceleration_slider_released)
        self.acceleration_slider.valueChanged.connect(self.acceleration_spin.setValue)
        self.acceleration_spin.editingFinished.connect(self.acceleration_spin_finished)
        
        self.deceleration_slider.sliderReleased.connect(self.deceleration_slider_released)
        self.deceleration_slider.valueChanged.connect(self.deceleration_spin.setValue)
        self.deceleration_spin.editingFinished.connect(self.deceleration_spin_finished)
        
#        self.decay_slider.sliderReleased.connect(self.decay_slider_released)
#        self.decay_slider.valueChanged.connect(self.decay_spin.setValue)
#        self.decay_spin.editingFinished.connect(self.decay_spin_finished)
        
        self.enable_checkbox.stateChanged.connect(self.enable_state_changed)
        self.forward_button.pressed.connect(self.forward_pressed)
        self.stop_button.pressed.connect(self.stop_pressed)
        self.full_brake_button.pressed.connect(self.full_brake_pressed)
        self.backward_button.pressed.connect(self.backward_pressed)
        self.to_button.pressed.connect(self.to_button_pressed)
        self.steps_button.pressed.connect(self.steps_button_pressed)
        self.motor_current_button.pressed.connect(self.motor_current_button_pressed)
        self.minimum_motor_voltage_button.pressed.connect(self.minimum_motor_voltage_button_pressed)
        
        self.mode_dropbox.currentIndexChanged.connect(self.mode_changed)
        
        self.qtcb_position_reached.connect(self.cb_position_reached)
        self.stepper.register_callback(self.stepper.CALLBACK_POSITION_REACHED, 
                                       self.qtcb_position_reached.emit)
        
        self.qtcb_under_voltage.connect(self.cb_under_voltage)
        self.stepper.register_callback(self.stepper.CALLBACK_UNDER_VOLTAGE, 
                                       self.qtcb_under_voltage.emit)
        
        self.update_data_async_thread = None
        
        self.ste = 0
        self.pos = 0
        self.current_velocity = 0
        self.cur = 0
        self.sv  = 0
        self.ev  = 0
        self.mv  = 0
        self.mod = 0
        
    def start(self):
        self.update_timer.start(100)
        self.update_start()
        
    def stop(self):
        self.update_timer.stop()

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

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

    def is_brick(self):
        return True

    def get_url_part(self):
        return 'stepper'

    @staticmethod
    def has_device_identifier(device_identifier):
        return device_identifier == BrickStepper.DEVICE_IDENTIFIER
    
    def cb_position_reached(self, position):
        self.position_update(position)
        self.endis_all(True)
            
    def disable_list(self, button_list):
        for button in button_list:
            button.setEnabled(False)
        
    def endis_all(self, value):
        self.forward_button.setEnabled(value)
        self.stop_button.setEnabled(value)
        self.backward_button.setEnabled(value)
        self.to_button.setEnabled(value)
        self.steps_button.setEnabled(value)
        self.full_brake_button.setEnabled(value)
        
    def mode_changed(self, index):
        try:
            self.stepper.set_step_mode(1 << index)
            self.mod = 1 << index
        except ip_connection.Error:
            return
        
    def forward_pressed(self):
        try:
            self.stepper.drive_forward()
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, self.steps_button])
        
    def backward_pressed(self):
        try:
            self.stepper.drive_backward()
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, self.steps_button])
        
    def stop_pressed(self):
        try:
            self.stepper.stop()
        except ip_connection.Error:
            return
        self.endis_all(True)
        
    def full_brake_pressed(self):
        try:
            self.stepper.full_brake()
        except ip_connection.Error:
            return
        self.endis_all(True)
        
    def to_button_pressed(self):
        drive_to = self.to_spin.value()
        try:
            self.stepper.set_target_position(drive_to)
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, 
                           self.steps_button, 
                           self.forward_button,
                           self.backward_button])
        
    def steps_button_pressed(self):
        drive_steps = self.steps_spin.value()
        try:
            self.stepper.set_steps(drive_steps)
        except ip_connection.Error:
            return
        self.disable_list([self.to_button, 
                           self.steps_button, 
                           self.forward_button,
                           self.backward_button])
        
    def motor_current_button_pressed(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(0)
        qid.setIntMaximum(2500)
        qid.setIntStep(100)
        async_call(self.stepper.get_motor_current, None, qid.setIntValue, self.increase_error_count)
        qid.intValueSelected.connect(self.motor_current_selected)
        qid.setLabelText("Choose motor current in mA.")
#                         "<font color=red>Setting this too high can destroy your Motor.</font>")
        qid.open()
        
    def minimum_motor_voltage_button_pressed(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(0)
        qid.setIntMaximum(40000)
        qid.setIntStep(100)
        async_call(self.stepper.get_minimum_voltage, None, qid.setIntValue, self.increase_error_count)
        qid.intValueSelected.connect(self.minimum_motor_voltage_selected)
        qid.setLabelText("Choose minimum motor voltage in mV.")
        qid.open()
        
    def motor_current_selected(self, value):
        try:
            self.stepper.set_motor_current(value)
        except ip_connection.Error:
            return
        
    def minimum_motor_voltage_selected(self, value):
        try:
            self.stepper.set_minimum_voltage(value)
        except ip_connection.Error:
            return
        
    def cb_under_voltage(self, ov):
        mv_str = self.minimum_voltage_label.text()
        ov_str = "%gV"  % round(ov/1000.0, 1)
        if not self.qem.isVisible():
            self.qem.showMessage("Under Voltage: Output Voltage of " + ov_str +
                                 " is below minimum voltage of " + mv_str,
                                 "Stepper_UnderVoltage")
        
    def enable_state_changed(self, state):
        try:
            if state == Qt.Checked:
                self.endis_all(True)
                self.stepper.enable()
            elif state == Qt.Unchecked:
                self.endis_all(False)
                self.stepper.disable()
        except ip_connection.Error:
            return
        
    def stack_input_voltage_update(self, sv):
        sv_str = "%gV"  % round(sv/1000.0, 1)
        self.stack_voltage_label.setText(sv_str)
        
    def external_input_voltage_update(self, ev):
        ev_str = "%gV"  % round(ev/1000.0, 1)
        self.external_voltage_label.setText(ev_str)
        
    def minimum_voltage_update(self, mv):
        mv_str = "%gV"  % round(mv/1000.0, 1)
        self.minimum_voltage_label.setText(mv_str)
        
    def maximum_current_update(self, cur):
        cur_str = "%gA"  % round(cur/1000.0, 1)
        self.maximum_current_label.setText(cur_str)
        
    def position_update(self, pos):
        pos_str = "%d" % pos
        self.position_label.setText(pos_str)
        
    def remaining_steps_update(self, ste):
        ste_str = "%d" % ste
        self.remaining_steps_label.setText(ste_str)
        
    def mode_update(self, mod):
        if mod == 8:
            index = 3
        elif mod == 4:
            index = 2
        elif mod == 2:
            index = 1
        else:
            index = 0
            
        self.mode_dropbox.setCurrentIndex(index)
        
    def get_max_velocity_async(self, velocity):
        if not self.velocity_slider.isSliderDown():
            if velocity != self.velocity_slider.sliderPosition():
                self.velocity_slider.setSliderPosition(velocity)
                self.velocity_spin.setValue(velocity)
        
    def get_speed_ramping_async(self, ramp):
        acc, dec = ramp
        if not self.acceleration_slider.isSliderDown() and \
           not self.deceleration_slider.isSliderDown():
            if acc != self.acceleration_slider.sliderPosition():
                self.acceleration_slider.setSliderPosition(acc)
                self.acceleration_spin.setValue(acc)
            if dec != self.deceleration_slider.sliderPosition():
                self.deceleration_slider.setSliderPosition(dec)
                self.deceleration_spin.setValue(dec)
        
    def is_enabled_async(self, enabled):
        if enabled:
            if self.enable_checkbox.checkState() != Qt.Checked:
                self.endis_all(True)
                self.enable_checkbox.setCheckState(Qt.Checked)
        else:
            if self.enable_checkbox.checkState() != Qt.Unchecked:
                self.endis_all(False)
                self.enable_checkbox.setCheckState(Qt.Unchecked)
        
    def update_start(self):
        async_call(self.stepper.get_max_velocity, None, self.get_max_velocity_async, self.increase_error_count)
        async_call(self.stepper.get_speed_ramping, None, self.get_speed_ramping_async, self.increase_error_count)
        async_call(self.stepper.is_enabled, None, self.is_enabled_async, self.increase_error_count)

    def update_data(self):
        async_call(self.stepper.get_remaining_steps, None, self.remaining_steps_update, self.increase_error_count)
        async_call(self.stepper.get_current_position, None, self.position_update, self.increase_error_count)
        async_call(self.stepper.get_current_velocity, None, self.speedometer.set_velocity, self.increase_error_count)

        self.update_counter += 1
        if self.update_counter % 10 == 0:
            async_call(self.stepper.get_motor_current, None, self.maximum_current_update, self.increase_error_count)
            async_call(self.stepper.get_stack_input_voltage, None, self.stack_input_voltage_update, self.increase_error_count)
            async_call(self.stepper.get_external_input_voltage, None, self.external_input_voltage_update, self.increase_error_count)
            async_call(self.stepper.get_minimum_voltage, None, self.minimum_voltage_update, self.increase_error_count)
            async_call(self.stepper.get_step_mode, None, self.mode_update, self.increase_error_count)
        
    def velocity_slider_released(self):
        value = self.velocity_slider.value()
        self.velocity_spin.setValue(value)
        try:
            self.stepper.set_max_velocity(value)
        except ip_connection.Error:
            return
 
    def velocity_spin_finished(self):
        value = self.velocity_spin.value()
        self.velocity_slider.setValue(value)
        try:
            self.stepper.set_max_velocity(value)
        except ip_connection.Error:
            return
    
    def acceleration_slider_released(self):
        acc = self.acceleration_slider.value()
        dec = self.deceleration_slider.value()
        self.acceleration_spin.setValue(acc)
        try:
            self.stepper.set_speed_ramping(acc, dec)
        except ip_connection.Error:
            return
 
    def acceleration_spin_finished(self):
        acc = self.acceleration_spin.value()
        dec = self.deceleration_spin.value()
        self.acceleration_slider.setValue(acc)
        try:
            self.stepper.set_speed_ramping(acc, dec)
        except ip_connection.Error:
            return
            
    def deceleration_slider_released(self):
        acc = self.acceleration_slider.value()
        dec = self.deceleration_slider.value()
        self.deceleration_spin.setValue(dec)
        try:
            self.stepper.set_speed_ramping(acc, dec)
        except ip_connection.Error:
            return
 
    def deceleration_spin_finished(self):
        acc = self.acceleration_spin.value()
        dec = self.deceleration_spin.value()
        self.deceleration_slider.setValue(dec)
        try:
            self.stepper.set_speed_ramping(acc, dec)
        except ip_connection.Error:
            return
Ejemplo n.º 23
0
class ProjectXively(QWidget):

    qtcb_update_illuminance = pyqtSignal(float)
    qtcb_update_air_pressure = pyqtSignal(float)
    qtcb_update_temperature = pyqtSignal(float)
    qtcb_update_humidity = pyqtSignal(float)
    qtcb_button_pressed = pyqtSignal(int)

    lcdwidget = None

    xively_host = "api.xively.com"
    xively_agent = "Tinkerforge Starter Kit Weather Station Demo"
    xively_channel = "Enter Feed ID here"
    xively_api_key = "Enter API Key here"

    xively_items = {}
    xively_headers = None
    xively_params = ""
    xively_update_rate = 5 # in minutes

    text_agent = None
    text_channel = None
    text_api_key = None
    number_update_rate = None

    save_button = None

    xively_timer = None

    error_message = None

    label_upload_active = None

    last_upload = None

    def __init__(self, parent, app):
        super(QWidget, self).__init__()

        self.lcdwidget = LCDWidget(self, app)
        self.lcdwidget.hide()

        self.text_agent = QLineEdit(self)
        self.text_agent.setText(self.xively_agent)
        
        self.text_channel = QLineEdit(self)
        self.text_channel.setText(self.xively_channel)
        
        self.text_api_key = QLineEdit(self)
        self.text_api_key.setText(self.xively_api_key)
        
        self.number_update_rate = QSpinBox(self)
        self.number_update_rate.setRange(1, 1440)
        self.number_update_rate.setSuffix(' min')
        self.number_update_rate.setValue(self.xively_update_rate)

        layout1 = QHBoxLayout()
        layout2 = QVBoxLayout()
        
        layout1.addStretch()
        layout1.addLayout(layout2)
        layout1.addStretch()
        
        layout2.addSpacerItem(QSpacerItem(LCDWidget.FIXED_WIDGTH, 0))

        label = QLabel(self)
        label.setText("Project: <b>Connect to Xively</b>. This project uploads the measured values to Xively. Please find documentation how to configure it and program sources in Python <a href=\"http://www.tinkerforge.com/en/doc/Kits/WeatherStation/WeatherStation.html#connect-to-xively\">here</a>.<br>")
        label.setTextFormat(Qt.RichText)
        label.setTextInteractionFlags(Qt.TextBrowserInteraction)
        label.setOpenExternalLinks(True)
        label.setWordWrap(True)
        label.setAlignment(Qt.AlignJustify)

        layout2.addSpacing(10)
        layout2.addWidget(label)
        layout2.addSpacing(10)

        layout3a = QHBoxLayout()
        label = QLabel("Agent Description:")
        label.setMinimumWidth(150)
        layout3a.addWidget(label)
        layout3a.addWidget(self.text_agent, 1)

        layout2.addLayout(layout3a)
        layout2.addSpacing(10)

        layout3b = QHBoxLayout()
        label = QLabel("Feed:")
        label.setMinimumWidth(150)
        layout3b.addWidget(label)
        layout3b.addWidget(self.text_channel, 1)

        layout2.addLayout(layout3b)
        layout2.addSpacing(10)

        layout3c = QHBoxLayout()
        label = QLabel("API Key:")
        label.setMinimumWidth(150)
        layout3c.addWidget(label)
        layout3c.addWidget(self.text_api_key, 1)

        layout2.addLayout(layout3c)
        layout2.addSpacing(10)

        layout3d = QHBoxLayout()
        label = QLabel("Update Rate:")
        label.setMinimumWidth(150)
        layout3d.addWidget(label)
        layout3d.addWidget(self.number_update_rate, 1)

        layout2.addLayout(layout3d)
        layout2.addSpacing(10)

        self.label_upload_active = QLabel("Not Active", self)
        self.label_upload_active.setMinimumWidth(150)
        font = QFont()
        font.setPixelSize(20)
        self.label_upload_active.setFont(font)
        self.set_active_label(False)

        self.save_button = QPushButton("Save/Activate")

        layout4 = QHBoxLayout()
        layout4.addWidget(self.label_upload_active)
        layout4.addWidget(self.save_button, 1)

        layout2.addLayout(layout4)
        layout2.addStretch()

        self.setLayout(layout1)

        self.qtcb_update_illuminance.connect(self.update_illuminance_data_slot)
        self.qtcb_update_air_pressure.connect(self.update_air_pressure_data_slot)
        self.qtcb_update_temperature.connect(self.update_temperature_data_slot)
        self.qtcb_update_humidity.connect(self.update_humidity_data_slot)
        self.qtcb_button_pressed.connect(self.button_pressed_slot)
        self.save_button.clicked.connect(self.save_configuration)

        self.lcdwidget.clear(self)

        self.error_message = QErrorMessage(self)

    def set_active_label(self, value):
        palette = self.label_upload_active.palette()
        if value:
            palette.setColor(self.foregroundRole(), Qt.darkGreen)
            self.label_upload_active.setText("Active")
        else:
            palette.setColor(self.foregroundRole(), Qt.red)
            self.label_upload_active.setText("Not Active")

        self.label_upload_active.setPalette(palette)

    def save_configuration(self):
        try:
            self.xively_agent = str(self.text_agent.text()).decode('ascii')
            self.xively_channel = str(self.text_channel.text()).decode('ascii')
            self.xively_api_key = str(self.text_api_key.text()).decode('ascii')
        except:
            self.error_message.showMessage('Agent, Feed and API Key can only contain ASCII characters')
            return

        self.xively_update_rate = self.number_update_rate.value()

        self.xively_headers = {
            "Content-Type"  : "application/x-www-form-urlencoded",
            "X-ApiKey"      : self.xively_api_key,
            "User-Agent"    : self.xively_agent,
        }
        self.xively_params = "/v2/feeds/" + self.xively_channel

        if self.xively_timer is None:
            self.xively_timer = QTimer(self)
            self.xively_timer.timeout.connect(self.update_xively)
            self.xively_timer.start(self.xively_update_rate*60*1000)

        self.set_active_label(True)
        self.update_xively()

    def write_lcd(self):
        if self.last_upload == None:
            tmp = "Last: Never"
        else:
            tmp = "Last: " + self.last_upload

        self.lcdwidget.write_line(0, 0, "Xively Upload", self)
        self.lcdwidget.write_line(2, 0, tmp, self)

    def update_xively(self):
        if len(self.xively_items) == 0:
            return

        stream_items = []
        for identifier, value in self.xively_items.items():
            stream_items.append({'id': identifier,
                                 'current_value': value[0],
                                 'min_value': value[1],
                                 'max_value': value[2]})

        data = {'version': '1.0.0',
                    'datastreams': stream_items}
        self.xively_items = {}
        body = json.dumps(data)

        try:
            http = httplib.HTTPSConnection(self.xively_host)
            http.request('PUT', self.xively_params, body, self.xively_headers)
            response = http.getresponse()
            http.close()

            if response.status != 200:
                self.error_message.showMessage('Could not upload to xively -> Response:' +
                          str(response.status) + ': ' + response.reason + '. Check your configuration.')
                self.xively_timer.stop()
                self.xively_timer = None
                self.set_active_label(False)
                return
        except Exception as e:
            self.error_message.showMessage('HTTP error: ' + str(e))
            self.xively_timer.stop()
            self.xively_timer = None
            self.set_active_label(False)
            return

        # set upload time if upload was a success
        self.last_upload = time.strftime("%H:%M:%S")


    def put(self, identifier, value):
        self.write_lcd()
        try:
            _, min_value, max_value = self.xively_items[identifier]
            if value < min_value:
                min_value = value
            if value > max_value:
                max_value = value
            self.xively_items[identifier] = (value, min_value, max_value)
        except:
            self.xively_items[identifier] = (value, value, value)

    def update_illuminance_data_slot(self, illuminance):
        self.put('AmbientLight', illuminance/10.0)

    def update_illuminance(self, illuminance):
        self.qtcb_update_illuminance.emit(illuminance)

    def update_humidity_data_slot(self, humidity):
        self.put('Humidity', humidity/10.0)
    
    def update_humidity(self, humidity):
        self.qtcb_update_humidity.emit(humidity)

    def update_air_pressure_data_slot(self, air_pressure):
        self.put('AirPressure', air_pressure/1000.0)
    
    def update_air_pressure(self, air_pressure):
        self.qtcb_update_air_pressure.emit(air_pressure)

    def update_temperature_data_slot(self, temperature):
        self.put('Temperature', temperature/100.0)

    def update_temperature(self, temperature):
        self.qtcb_update_temperature.emit(temperature)

    def button_pressed_slot(self, button):
        pass

    def button_pressed(self, button):
        self.qtcb_button_pressed.emit(button)
Ejemplo n.º 24
0
class Editor(editor_base.EditorBase):
    """Representa el editor de texto que aparece en el panel derecho.

    El editor soporta autocompletado de código y resaltado de sintáxis.
    """

    # Señal es emitida cuando el Editor ejecuta codigo
    signal_ejecutando = QtCore.pyqtSignal()

    def __init__(self, main, interpreterLocals, consola_lanas, ventana_interprete):
        super(Editor, self).__init__()
        self.cantidad_ejecuciones = 0
        self.consola_lanas = consola_lanas
        self.ventana_interprete = ventana_interprete
        self.ruta_del_archivo_actual = None
        self.interpreterLocals = interpreterLocals
        self.setLineWrapMode(QTextEdit.NoWrap)
        self._cambios_sin_guardar = False
        self.main = main
        self.nombre_de_archivo_sugerido = ""
        self.watcher = pilasengine.watcher.Watcher(None, self.cuando_cambia_archivo_de_forma_externa)

    def crear_archivo_inicial(self):
        dirpath = tempfile.mkdtemp()
        archivo_temporal = os.path.join(dirpath, "mi_juego.py")
        archivo = codecs.open(archivo_temporal, "w", 'utf-8')
        archivo.write(CODIGO_INICIAL)
        archivo.close()
        #print("Creando el archivo " + str(archivo_temporal))
        self.abrir_archivo_del_proyecto(archivo_temporal)

    def es_archivo_iniciar_sin_guardar(self):
        return self.nombre_de_archivo_sugerido == ""

    def crear_y_seleccionar_archivo(self, nombre):
        # Quita la extension si llega a tenerla.
        nombre = nombre.replace('.py', '')
        nombre += ".py"
        nombre_de_archivo = nombre

        if self.ruta_del_archivo_actual:
            base_path = os.path.abspath(os.path.dirname(self.ruta_del_archivo_actual))
            ruta = os.path.join(base_path, unicode(nombre_de_archivo))
        else:
            ruta = unicode(nombre_de_archivo)

        if os.path.exists(ruta):
            self._tmp_dialog = QErrorMessage(self)
            self._tmp_dialog.showMessage("Ya existe un archivo con ese nombre")
        else:
            self._crear_archivo_nuevo_en(ruta)

            self.cargar_contenido_desde_archivo(ruta)
            self.ruta_del_archivo_actual = ruta
            self.watcher.cambiar_archivo_a_observar(ruta)
            self.ejecutar()
            self.main.actualizar_el_listado_de_archivos()

    def _crear_archivo_nuevo_en(self, ruta):
        fo = open(ruta, "wb")
        fo.write("# contenido")
        fo.close()

    def obtener_archivos_del_proyecto(self):
        base_path = os.path.dirname(self.nombre_de_archivo_sugerido)
        listado = os.listdir(base_path)

        return [x for x in listado if x.endswith('.py')]

    def keyPressEvent(self, event):
        "Atiene el evento de pulsación de tecla."
        self._cambios_sin_guardar = True

        # Permite usar tab como seleccionador de la palabra actual
        # en el popup de autocompletado.
        if event.key() in [Qt.Key_Tab]:
            if self.completer and self.completer.popup().isVisible():
                event.ignore()
                nuevo_evento = QKeyEvent(QKeyEvent.KeyPress, Qt.Key_Return, Qt.NoModifier)
                try:
                    if self.autocomplete(nuevo_evento):
                        return None
                except UnicodeEncodeError:
                    pass
                return None


        if editor_base.EditorBase.keyPressEvent(self, event):
            return None

        # Elimina los pares de caracteres especiales si los encuentra
        if event.key() == Qt.Key_Backspace:
            self._eliminar_pares_de_caracteres()
            self._borrar_un_grupo_de_espacios(event)

        if self.autocomplete(event):
            return None


        if event.key() == Qt.Key_Return:
            cursor = self.textCursor()
            block = self.document().findBlockByNumber(cursor.blockNumber())
            whitespace = re.match(r"(\s*)", unicode(block.text())).group(1)

            linea_anterior = str(block.text()[:])
            cantidad_espacios = linea_anterior.count(' ') / 4

            if linea_anterior[-1:] == ':':
                whitespace = '    ' * (cantidad_espacios + 1)
            else:
                whitespace = '    ' * (cantidad_espacios)

            QTextEdit.keyPressEvent(self, event)
            return self.insertPlainText(whitespace)



        return QTextEdit.keyPressEvent(self, event)

    def _borrar_un_grupo_de_espacios(self, event):
        cursor = self.textCursor()
        block = self.document().findBlockByNumber(cursor.blockNumber())
        whitespace = re.match(r"(.*)", unicode(block.text())).group(1)

        if whitespace.endswith('    '):
            QTextEdit.keyPressEvent(self, event)
            QTextEdit.keyPressEvent(self, event)
            QTextEdit.keyPressEvent(self, event)

    def tiene_cambios_sin_guardar(self):
        return self._cambios_sin_guardar

    def _get_current_line(self):
        "Obtiene la linea en donde se encuentra el cursor."
        tc = self.textCursor()
        tc.select(QTextCursor.LineUnderCursor)
        return tc.selectedText()

    def _get_position_in_block(self):
        tc = self.textCursor()
        position = tc.positionInBlock() - 1
        return position

    def cargar_contenido_desde_archivo(self, ruta):
        "Carga todo el contenido del archivo indicado por ruta."
        with codecs.open(unicode(ruta), 'r', 'utf-8') as archivo:
            contenido = archivo.read()
        self.setText(contenido)

        self.nombre_de_archivo_sugerido = ruta
        self._cambios_sin_guardar = False

    def abrir_dialogo_cargar_archivo(self):
        return QFileDialog.getOpenFileName(self, "Abrir Archivo",
                                   self.nombre_de_archivo_sugerido,
                                   "Archivos python (*.py)",
                                   options=QFileDialog.DontUseNativeDialog)

    def abrir_archivo_del_proyecto(self, nombre_de_archivo):
        if self.tiene_cambios_sin_guardar():
            if self.mensaje_guardar_cambios_abrir():
                if not self.guardar_contenido_con_dialogo():
                    return
            else:
                return

        if self.ruta_del_archivo_actual:
            base_path = os.path.dirname(self.ruta_del_archivo_actual)
            ruta = os.path.join(base_path, unicode(nombre_de_archivo))
        else:
            ruta = unicode(nombre_de_archivo)

        self.cargar_contenido_desde_archivo(ruta)
        self.ruta_del_archivo_actual = ruta
        self.watcher.cambiar_archivo_a_observar(ruta)
        self.ejecutar()
        self.main.actualizar_el_listado_de_archivos()

    def abrir_archivo_con_dialogo(self):
        if self.tiene_cambios_sin_guardar():
            if self.mensaje_guardar_cambios_abrir():
                if not self.guardar_contenido_con_dialogo():
                    return
            else:
                return

        ruta = self.abrir_dialogo_cargar_archivo()

        if ruta:
            ruta = unicode(ruta)
            self.cargar_contenido_desde_archivo(ruta)
            self.ruta_del_archivo_actual = ruta
            self.watcher.cambiar_archivo_a_observar(ruta)
            self.ejecutar()
            self.main.actualizar_el_listado_de_archivos()

    def cuando_cambia_archivo_de_forma_externa(self):
        self.recargar_archivo_actual()

    def recargar_archivo_actual(self):
        if self.ruta_del_archivo_actual:
            self.cargar_contenido_desde_archivo(self.ruta_del_archivo_actual)
            self.ejecutar()

    def mensaje_guardar_cambios_abrir(self):
        """Realizar una consulta usando un cuadro de dialogo simple
        se utiliza cuando hay cambios sin guardar y se desea abrir un archivo.
        Retorna True si el usuario presiona el boton *Guardar*,
        Retorna False si el usuario presiona *No*."""
        titulo = u"¿Deseas guardar el contenido antes de abrir un archivo?"
        mensaje = u"El contenido se perdera sino los guardas"

        mensaje = QMessageBox.question(self, titulo, mensaje, "Guardar", "No")

        return (not mensaje)

    def mensaje_guardar_cambios_salir(self):
        """Realizar una consulta usando un cuadro de dialogo simple
        se utiliza cuando hay cambios sin guardar y se desa salir del Editor.
        Retorna 0 si el usuario presiona el boton *Salir sin guardar*,
        Retorna 1 si el usuario presiona *Guardar*
        Retorna 2 si presiona *Cancelar*."""

        titulo = u"¿Deseas guardar el contenido antes de salir?"
        mensaje = u"El contenido se perdera sino los guardas"

        return QMessageBox.question(self, titulo, mensaje,
                                    "Salir sin guardar", "Guardar", "Cancelar")

    def marcar_error_en_la_linea(self, numero, descripcion):
        hi_selection = QTextEdit.ExtraSelection()

        hi_selection.format.setBackground(QColor(255, 220, 220))
        hi_selection.format.setProperty(QTextFormat.FullWidthSelection, QVariant(True))
        hi_selection.cursor = self.textCursor()
        posicion_linea = self.document().findBlockByLineNumber(numero).position()
        hi_selection.cursor.setPosition(posicion_linea)
        hi_selection.cursor.clearSelection()

        self.setExtraSelections([hi_selection])

    def guardar_contenido_con_dialogo(self):
        ruta = self.abrir_dialogo_guardar_archivo()

        if not ruta:
            return False

        ruta = unicode(ruta)

        if not ruta.endswith('.py'):
            ruta += '.py'

        if ruta:
            self.guardar_contenido_en_el_archivo(ruta)
            self._cambios_sin_guardar = False
            self.ruta_del_archivo_actual = ruta
            self.nombre_de_archivo_sugerido = ruta
            self.watcher.cambiar_archivo_a_observar(ruta)
            self.cargar_contenido_desde_archivo(ruta)
            self.ejecutar()
            self.main.actualizar_el_listado_de_archivos()
            self.main.habilitar_boton_nuevo()
            return True

    def guardar_contenido_directamente(self):
        if self.nombre_de_archivo_sugerido:
            self.guardar_contenido_en_el_archivo(self.nombre_de_archivo_sugerido)
            self._cambios_sin_guardar = False
            self.main.actualizar_el_listado_de_archivos()
            self.prevenir_live_reload()
        else:
            self.guardar_contenido_con_dialogo()

    def prevenir_live_reload(self):
        self.watcher.prevenir_reinicio()

    def salir(self):
        """Retorna True si puede salir y False si no"""
        if self.tiene_cambios_sin_guardar():
            mensaje = self.mensaje_guardar_cambios_salir()
            if mensaje == 1:
                self.guardar_contenido_con_dialogo()
            elif mensaje == 2:
                return False

        return True

    def obtener_contenido(self):
        return unicode(self.document().toPlainText())

    def ejecutar(self):
        ruta_personalizada = os.path.dirname(self.ruta_del_archivo_actual)
        #print "ejecutando texto desde widget editor"
        texto = self.obtener_contenido()
        #texto = self.editor.obtener_texto_sanitizado(self)
        # elimina cabecera de encoding.
        contenido = re.sub('coding\s*:\s*', '', texto)
        contenido = contenido.replace('import pilasengine', '')
        contenido = contenido.replace('pilas = pilasengine.iniciar', 'pilas.reiniciar')

        for x in contenido.split('\n'):
            if "__file__" in x:
                contenido = contenido.replace(x, "# livecoding: " + x + "\n")

        sys.path.append(ruta_personalizada)
        self.interpreterLocals['sys'] = sys

        # Muchos códigos personalizados necesitan cargar imágenes o sonidos
        # desde el directorio que contiene al archivo. Para hacer esto posible,
        # se llama a la función "pilas.utils.agregar_ruta_personalizada" con el
        # path al directorio que representa el script. Así la función "obtener_ruta_al_recurso"
        # puede evaluar al directorio del script en busca de recursos también.
        if ruta_personalizada:
            ruta_personalizada = ruta_personalizada.replace('\\', '/')
            agregar_ruta_personalizada = 'pilas.utils.agregar_ruta_personalizada("%s")' %(ruta_personalizada)
            contenido = contenido.replace('pilas.reiniciar(', agregar_ruta_personalizada+'\n'+'pilas.reiniciar(')

        modulos_a_recargar = [x for x in self.interpreterLocals.values()
                                    if inspect.ismodule(x)
                                    and x.__name__ not in ['pilasengine', 'inspect']
                                    and 'pilasengine.' not in x.__name__]

        for m in modulos_a_recargar:
            reload(m)

        self.cantidad_ejecuciones += 1

        # Limpia la consola a partir de la primer ejecucion luego de iniciar.
        if self.cantidad_ejecuciones > 1:
            self.main.limpiar_interprete()

        try:
            exec(contenido, self.interpreterLocals)
        except Exception, e:
            self.consola_lanas.insertar_error_desde_exception(e)
            self.ventana_interprete.mostrar_el_interprete()
            #self.marcar_error_en_la_linea(10, "pepepe")

        self.signal_ejecutando.emit()
Ejemplo n.º 25
0
class Blinkenlights(QApplication):
    HOST = "localhost"
    PORT = 4223

    ipcon = None

    projects = []
    active_project = None

    error_msg = None

    def __init__(self, args):
        super(QApplication, self).__init__(args)

        self.error_msg = QErrorMessage()
        self.error_msg.setWindowTitle("Starter Kit: Blinkenlights Demo " + config.DEMO_VERSION)

        signal.signal(signal.SIGINT, self.exit_demo)
        signal.signal(signal.SIGTERM, self.exit_demo)

        self.make_gui()
        self.connect()

    def exit_demo(self, signl=None, frme=None):
        try:
            self.ipcon.disconnect()
            self.timer.stop()
            self.tabs.destroy()
        except:
            pass

        sys.exit()

    def make_gui(self):
        self.main = MainWindow(self)
        self.main.setWindowIcon(QIcon(os.path.join(ProgramPath.program_path(), "demo-icon.png")))

        self.tabs = QTabWidget()

        widget = QWidget()
        layout = QVBoxLayout()
        layout.addWidget(self.tabs)
        widget.setLayout(layout)

        self.main.setCentralWidget(widget)

        self.setup = SetupWidget(self.tabs, self)
        self.tetris = TetrisWidget(self.tabs, self)
        self.pong = PongWidget(self.tabs, self)
        self.fire = FireWidget(self.tabs, self)
        self.text = TextWidget(self.tabs, self)
        self.images = ImagesWidget(self.tabs, self)
        self.rainbow = RainbowWidget(self.tabs, self)

        self.projects.append(self.setup)
        self.projects.append(self.tetris)
        self.projects.append(self.pong)
        self.projects.append(self.fire)
        self.projects.append(self.text)
        self.projects.append(self.images)
        self.projects.append(self.rainbow)

        self.tabs.addTab(self.setup, "Setup")
        self.tabs.addTab(self.tetris, "Tetris")
        self.tabs.addTab(self.pong, "Pong")
        self.tabs.addTab(self.fire, "Fire")
        self.tabs.addTab(self.text, "Text")
        self.tabs.addTab(self.images, "Images")
        self.tabs.addTab(self.rainbow, "Rainbow")

        self.active_project = self.projects[0]

        self.tabs.currentChanged.connect(self.tab_changed_slot)

        self.main.setWindowTitle("Starter Kit: Blinkenlights Demo " + config.DEMO_VERSION)
        self.main.show()

    def connect(self):
        config.UID_LED_STRIP_BRICKLET = None
        self.setup.label_led_strip_found.setText('No')
        self.setup.label_led_strip_uid.setText('None')

        config.UID_MULTI_TOUCH_BRICKLET = None
        self.setup.label_multi_touch_found.setText('No')
        self.setup.label_multi_touch_uid.setText('None')

        config.UID_DUAL_BUTTON_BRICKLET = (None, None)
        self.setup.label_dual_button1_found.setText('No')
        self.setup.label_dual_button1_uid.setText('None')
        self.setup.label_dual_button2_found.setText('No')
        self.setup.label_dual_button2_uid.setText('None')

        config.UID_PIEZO_SPEAKER_BRICKLET = None
        self.setup.label_piezo_speaker_found.setText('No')
        self.setup.label_piezo_speaker_uid.setText('None')

        config.UID_SEGMENT_DISPLAY_4X7_BRICKLET = None
        self.setup.label_segment_display_found.setText('No')
        self.setup.label_segment_display_uid.setText('None')

        if self.ipcon != None:
            try:
                self.ipcon.disconnect()
            except:
                pass

        self.ipcon = IPConnection()

        host = self.setup.edit_host.text()
        port = self.setup.spinbox_port.value()
        try:
            self.ipcon.connect(host, port)
        except Error as e:
            self.error_msg.showMessage('Connection Error: ' + str(e.description) + "<br><br>Brickd installed and running?")
            return
        except socket.error as e:
            self.error_msg.showMessage('Socket error: ' + str(e) + "<br><br>Brickd installed and running?")
            return

        self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE,
                                     self.cb_enumerate)
        self.ipcon.register_callback(IPConnection.CALLBACK_CONNECTED,
                                     self.cb_connected)

        # Wait for a second to give user visual feedback
        timer = QTimer(self)
        timer.setSingleShot(True)
        timer.timeout.connect(self.ipcon.enumerate)
        timer.start(250)

    def tab_changed_slot(self, tabIndex):
        self.active_project.stop()
        self.active_project = self.projects[tabIndex]
        self.active_project.start()

    def cb_enumerate(self, uid, connected_uid, position, hardware_version,
                     firmware_version, device_identifier, enumeration_type):
        if enumeration_type == IPConnection.ENUMERATION_TYPE_CONNECTED or \
           enumeration_type == IPConnection.ENUMERATION_TYPE_AVAILABLE:
            if device_identifier == LEDStrip.DEVICE_IDENTIFIER:
                config.UID_LED_STRIP_BRICKLET = uid
                self.setup.label_led_strip_found.setText('Yes')
                self.setup.label_led_strip_uid.setText(uid)
            elif device_identifier == MultiTouch.DEVICE_IDENTIFIER:
                config.UID_MULTI_TOUCH_BRICKLET = uid
                self.setup.label_multi_touch_found.setText('Yes')
                self.setup.label_multi_touch_uid.setText(uid)
            elif device_identifier == DualButton.DEVICE_IDENTIFIER:
                if config.UID_DUAL_BUTTON_BRICKLET[0] == None:
                    config.UID_DUAL_BUTTON_BRICKLET = (uid, None)
                    self.setup.label_dual_button1_found.setText('Yes')
                    self.setup.label_dual_button1_uid.setText(uid)
                else:
                    config.UID_DUAL_BUTTON_BRICKLET = (config.UID_DUAL_BUTTON_BRICKLET[0], uid)
                    self.setup.label_dual_button2_found.setText('Yes')
                    self.setup.label_dual_button2_uid.setText(uid)
            elif device_identifier == PiezoSpeaker.DEVICE_IDENTIFIER:
                config.UID_PIEZO_SPEAKER_BRICKLET = uid
                self.setup.label_piezo_speaker_found.setText('Yes')
                self.setup.label_piezo_speaker_uid.setText(uid)
            elif device_identifier == SegmentDisplay4x7.DEVICE_IDENTIFIER:
                config.UID_SEGMENT_DISPLAY_4X7_BRICKLET = uid
                self.setup.label_segment_display_found.setText('Yes')
                self.setup.label_segment_display_uid.setText(uid)

    def cb_connected(self, connected_reason):
        if connected_reason == IPConnection.CONNECT_REASON_AUTO_RECONNECT:
            while True:
                try:
                    self.ipcon.enumerate()
                    break
                except Error as e:
                    self.error_msg.showMessage('Enumerate Error: ' + str(e.description))
                    time.sleep(1)
Ejemplo n.º 26
0
    except socket.error:  # Good si is correct (on UNIX)
        otherinstance = True
    else:
        # On windows only singleinstance can be trusted
        otherinstance = True if iswindows else False
    if not otherinstance and not opts.shutdown_running_calibre:
        return run_gui(opts, args, listener, app, gui_debug=gui_debug)

    communicate(opts, args)

    return 0


if __name__ == "__main__":
    try:
        sys.exit(main())
    except Exception as err:
        if not iswindows:
            raise
        tb = traceback.format_exc()
        from PyQt4.QtGui import QErrorMessage

        logfile = os.path.join(os.path.expanduser("~"), "calibre.log")
        if os.path.exists(logfile):
            log = open(logfile).read().decode("utf-8", "ignore")
            d = QErrorMessage()
            d.showMessage(
                ("<b>Error:</b>%s<br><b>Traceback:</b><br>" "%s<b>Log:</b><br>%s")
                % (unicode(err), unicode(tb).replace("\n", "<br>"), log.replace("\n", "<br>"))
            )
Ejemplo n.º 27
0
        otherinstance = True
    else:
        # On windows only singleinstance can be trusted
        otherinstance = True if iswindows else False
    if not otherinstance and not opts.shutdown_running_calibre:
        return run_gui(opts, args, actions, listener, app, gui_debug=gui_debug)

    communicate(opts, args)

    return 0


if __name__ == '__main__':
    try:
        sys.exit(main())
    except Exception as err:
        if not iswindows:
            raise
        tb = traceback.format_exc()
        from PyQt4.QtGui import QErrorMessage
        logfile = os.path.join(os.path.expanduser('~'), 'calibre.log')
        if os.path.exists(logfile):
            log = open(logfile).read().decode('utf-8', 'ignore')
            d = QErrorMessage()
            d.showMessage(('<b>Error:</b>%s<br><b>Traceback:</b><br>'
                '%s<b>Log:</b><br>%s')%(unicode(err),
                    unicode(tb).replace('\n', '<br>'),
                    log.replace('\n', '<br>')))


Ejemplo n.º 28
0
class Servo(PluginBase, Ui_Servo):
    qtcb_under_voltage = pyqtSignal(int)

    def __init__(self, *args):
        PluginBase.__init__(self, BrickServo, *args)

        self.setupUi(self)

        self.servo = self.device

        self.position_list = []
        self.velocity_list = []
        self.acceleration_list = []
        self.enable_list = []

        self.up_cur = 0
        self.up_siv = 0
        self.up_eiv = 0
        self.up_opv = 0
        self.up_mv = 0

        self.up_ena = [0] * 7
        self.up_pos = [0] * 7
        self.up_vel = [0] * 7
        self.up_acc = [0] * 7

        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.update_apply)
        self.update_timer.setInterval(50)

        self.alive = True

        for i in range(1, 8):
            label = QLabel()
            label.setText('Off')
            self.enable_list.append(label)
            self.status_grid.addWidget(label, i, 1)

        for i in range(1, 8):
            pk = PositionKnob()
            self.position_list.append(pk)
            self.status_grid.addWidget(pk, i, 2)

        for i in range(1, 8):
            cb = ColorBar(Qt.Vertical)
            self.velocity_list.append(cb)
            self.status_grid.addWidget(cb, i, 3)

        for i in range(1, 8):
            cb = ColorBar(Qt.Vertical)
            self.acceleration_list.append(cb)
            self.status_grid.addWidget(cb, i, 4)

        self.qem = QErrorMessage(self)
        self.qem.setWindowTitle("Under Voltage")

        self.test_button.clicked.connect(self.test_button_clicked)
        self.output_voltage_button.clicked.connect(
            self.output_voltage_button_clicked)

        self.servo_dropbox.currentIndexChanged.connect(
            lambda x: self.update_servo_specific())
        self.enable_checkbox.stateChanged.connect(self.enable_state_changed)

        self.position_syncer = SliderSpinSyncer(self.position_slider,
                                                self.position_spin,
                                                self.position_changed)

        self.velocity_syncer = SliderSpinSyncer(self.velocity_slider,
                                                self.velocity_spin,
                                                self.velocity_changed)

        self.acceleration_syncer = SliderSpinSyncer(self.acceleration_slider,
                                                    self.acceleration_spin,
                                                    self.acceleration_changed)

        self.period_syncer = SliderSpinSyncer(self.period_slider,
                                              self.period_spin,
                                              self.period_changed)

        self.pulse_width_min_spin.editingFinished.connect(
            self.pulse_width_spin_finished)
        self.pulse_width_max_spin.editingFinished.connect(
            self.pulse_width_spin_finished)
        self.degree_min_spin.editingFinished.connect(self.degree_spin_finished)
        self.degree_max_spin.editingFinished.connect(self.degree_spin_finished)

        self.minimum_voltage_button.clicked.connect(
            self.minimum_voltage_button_clicked)

        self.qtcb_under_voltage.connect(self.cb_under_voltage)
        self.servo.register_callback(self.servo.CALLBACK_UNDER_VOLTAGE,
                                     self.qtcb_under_voltage.emit)

        class WorkerThread(QThread):
            def __init__(self, parent=None, func=None):
                QThread.__init__(self, parent)
                self.func = func

            def run(self):
                self.func()

        self.test_event = Event()
        self.test_thread_object = WorkerThread(self, self.test_thread)
        self.update_event = Event()
        self.update_thread_object = WorkerThread(self, self.update_thread)

        self.update_thread_first_time = False

        self.update_done_event = Event()
        self.update_done_event.set()

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

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

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

        self.alive = True
        self.test_event.clear()
        self.update_done_event.set()
        self.update_event.set()

        if not self.test_thread_object.isRunning():
            self.test_thread_object.start()

        if not self.update_thread_object.isRunning():
            self.update_thread_object.start()

        self.update_servo_specific()

        self.update_timer.start()

    def stop(self):
        if self.test_button.text() == "Stop Test":
            self.test_button_clicked()

        self.update_timer.stop()

        self.update_event.clear()
        self.alive = False
        self.update_done_event.wait()

    def destroy(self):
        self.test_event.set()
        self.update_event.set()

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

    def get_period_async(self, per):
        self.period_spin.setValue(per)
        self.period_slider.setValue(per)

    def is_enabled_async(self, ena):
        self.enable_checkbox.setChecked(ena)

    def get_position_async(self, pos):
        self.position_spin.setValue(pos)
        self.position_slider.setValue(pos)

    def get_velocity_async(self, vel):
        self.velocity_spin.setValue(vel)
        self.velocity_slider.setValue(vel)

    def get_acceleration_async(self, acc):
        self.acceleration_spin.setValue(acc)
        self.acceleration_slider.setValue(acc)

    def get_degree_async(self, deg, i):
        deg_min, deg_max = deg

        self.degree_min_spin.setValue(deg_min)
        self.degree_max_spin.setValue(deg_max)

        self.position_slider.setMinimum(deg_min)
        self.position_slider.setMaximum(deg_max)
        self.position_spin.setMinimum(deg_min)
        self.position_spin.setMaximum(deg_max)

        self.position_list[i].set_total_angle((deg_max - deg_min) / 100)
        self.position_list[i].set_range(deg_min / 100, deg_max / 100)

    def get_pulse_width_async(self, pulse):
        pulse_min, pulse_max = pulse
        self.pulse_width_min_spin.setValue(pulse_min)
        self.pulse_width_max_spin.setValue(pulse_max)

    def update_servo_specific(self):
        i = self.selected_servo()
        if i == 255:
            self.enable_checkbox.setChecked(False)
            return

        async_call(self.servo.get_position, i, self.get_position_async,
                   self.increase_error_count)
        async_call(self.servo.get_velocity, i, self.get_velocity_async,
                   self.increase_error_count)
        async_call(self.servo.get_acceleration, i, self.get_acceleration_async,
                   self.increase_error_count)
        async_call(self.servo.get_period, i, self.get_period_async,
                   self.increase_error_count)
        async_call(self.servo.is_enabled, i, self.is_enabled_async,
                   self.increase_error_count)

        def get_lambda_deg(i):
            return lambda x: self.get_degree_async(x, i)

        async_call(self.servo.get_degree, i, get_lambda_deg(i),
                   self.increase_error_count)
        async_call(self.servo.get_pulse_width, i, self.get_pulse_width_async,
                   self.increase_error_count)

    def error_handler(self, error):
        pass

    def servo_current_update(self, value):
        self.current_label.setText(str(value) + "mA")

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

    def external_input_voltage_update(self, ev):
        ev_str = "%gV" % round(ev / 1000.0, 1)
        self.external_voltage_label.setText(ev_str)

    def output_voltage_update(self, ov):
        ov_str = "%gV" % round(ov / 1000.0, 1)
        self.output_voltage_label.setText(ov_str)

    def minimum_voltage_update(self, mv):
        mv_str = "%gV" % round(mv / 1000.0, 1)
        self.minimum_voltage_label.setText(mv_str)

    def position_update(self, i, pos):
        self.position_list[i].set_value(pos / 100)

    def velocity_update(self, i, vel):
        self.velocity_list[i].set_height(vel * 100 / 0xFFFF)

    def acceleration_update(self, i, acc):
        self.acceleration_list[i].set_height(acc * 100 / 0xFFFF)

    def deactivate_servo(self, i):
        if self.enable_list[i].text() != 'Off':
            self.velocity_list[i].grey()
            self.acceleration_list[i].grey()

    def activate_servo(self, i):
        if self.enable_list[i].text() != 'On':
            self.velocity_list[i].color()
            self.acceleration_list[i].color()

    def selected_servo(self):
        try:
            return int(self.servo_dropbox.currentText()[-1:])
        except:
            return 255

    def enable_state_changed(self, state):
        s = self.selected_servo()
        try:
            if state == Qt.Checked:
                self.servo.enable(s)
            elif state == Qt.Unchecked:
                self.servo.disable(s)
        except ip_connection.Error:
            return

    def update_apply(self):
        if not self.update_thread_first_time:
            return

        self.servo_current_update(self.up_cur)
        self.stack_input_voltage_update(self.up_siv)
        self.external_input_voltage_update(self.up_eiv)
        self.output_voltage_update(self.up_opv)
        self.minimum_voltage_update(self.up_mv)
        for i in range(7):
            if self.up_ena[i]:
                self.activate_servo(i)

                self.position_update(i, self.up_pos[i])
                self.velocity_update(i, self.up_vel[i])
                self.acceleration_update(i, self.up_acc[i])

                self.enable_list[i].setText('On')
            else:
                self.deactivate_servo(i)
                self.enable_list[i].setText('Off')

    def update_thread(self):
        while self.alive:
            time.sleep(0.1)

            try:
                servo = self.selected_servo()
                if servo == 255:
                    self.up_cur = self.servo.get_overall_current()
                else:
                    self.up_cur = self.servo.get_servo_current(servo)

                self.up_siv = self.servo.get_stack_input_voltage()
                self.up_eiv = self.servo.get_external_input_voltage()
                self.up_opv = self.servo.get_output_voltage()
                self.up_mv = self.servo.get_minimum_voltage()

                for i in range(7):
                    self.up_ena[i] = self.servo.is_enabled(i)
                    if self.up_ena[i]:
                        self.activate_servo(i)
                        self.up_pos[i] = self.servo.get_current_position(i)
                        self.up_vel[i] = self.servo.get_current_velocity(i)
                        self.up_acc[i] = self.servo.get_acceleration(i)

                #self.update_apply()

                self.update_done_event.set()
                self.update_event.wait()
                self.update_done_event.clear()
            except ip_connection.Error:
                pass

            self.update_thread_first_time = True

        self.update_done_event.set()

    def test_thread(self):
        def test(num, ena, acc, vel, pos):
            if not self.alive:
                return

            try:
                if ena:
                    self.servo.enable(num)
                else:
                    self.servo.disable(num)
                self.servo.set_acceleration(num, acc)
                self.servo.set_velocity(num, vel)
                self.servo.set_position(num, pos)
            except ip_connection.Error:
                return

        def random_test():
            for i in range(7):
                test(i, random.randrange(0, 2), random.randrange(0, 65536),
                     random.randrange(0, 65536), random.randrange(-9000, 9001))

        while self.alive:
            self.test_event.wait()
            if not self.alive:
                return

            # Full Speed left for 2 seconds
            for i in range(7):
                test(i, True, 65535, 65535, 9000)
            time.sleep(2)
            self.test_event.wait()
            if not self.alive:
                return

            # Full Speed right for 2 seconds
            for i in range(7):
                test(i, True, 65535, 65535, -9000)
            time.sleep(2)
            self.test_event.wait()
            if not self.alive:
                return

            # Test different speeds
            for i in range(19):
                for j in range(7):
                    test(j, True, 65535, 65535 * i / 18, -9000 + i * 1000)
                time.sleep(0.1)
                self.test_event.wait()
                if not self.alive:
                    return
            time.sleep(1)
            self.test_event.wait()
            if not self.alive:
                return

            # Test acceleration
            for i in range(7):
                test(i, True, 100, 65535, -9000)

            time.sleep(3)
            self.test_event.wait()
            if not self.alive:
                return

            # Random for 3 seconds
            random_test()
            time.sleep(3)

    def test_button_clicked(self):
        if self.test_button.text() == "Start Test":
            self.test_button.setText("Stop Test")
            self.test_event.set()
        else:
            self.test_button.setText("Start Test")
            self.test_event.clear()

    def output_voltage_button_clicked(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(2000)
        qid.setIntMaximum(9000)
        qid.setIntStep(100)
        async_call(self.servo.get_output_voltage, None, qid.setIntValue,
                   self.increase_error_count)
        qid.intValueSelected.connect(self.output_voltage_selected)
        qid.setLabelText("Choose Output Voltage in mV.")
        #                         "<font color=red>Setting this too high can destroy your servo.</font>")
        qid.open()

    def output_voltage_selected(self, value):
        try:
            self.servo.set_output_voltage(value)
        except ip_connection.Error:
            return

    def position_changed(self, value):
        try:
            self.servo.set_position(self.selected_servo(), value)
        except ip_connection.Error:
            return

    def velocity_changed(self, value):
        try:
            self.servo.set_velocity(self.selected_servo(), value)
        except ip_connection.Error:
            return

    def acceleration_changed(self, value):
        try:
            self.servo.set_acceleration(self.selected_servo(), value)
        except ip_connection.Error:
            return

    def period_changed(self, value):
        try:
            self.servo.set_period(self.selected_servo(), value)
        except ip_connection.Error:
            return

    def pulse_width_spin_finished(self):
        try:
            self.servo.set_pulse_width(self.selected_servo(),
                                       self.pulse_width_min_spin.value(),
                                       self.pulse_width_max_spin.value())
        except ip_connection.Error:
            return

    def degree_spin_finished(self):
        min = self.degree_min_spin.value()
        max = self.degree_max_spin.value()
        servo = self.selected_servo()

        self.position_slider.setMinimum(min)
        self.position_slider.setMaximum(max)
        self.position_spin.setMinimum(min)
        self.position_spin.setMaximum(max)
        if servo == 255:
            for i in range(7):
                self.position_list[i].set_total_angle((max - min) / 100)
                self.position_list[i].set_range(min / 100, max / 100)
        else:
            self.position_list[servo].set_total_angle((max - min) / 100)
            self.position_list[servo].set_range(min / 100, max / 100)

        try:
            self.servo.set_degree(servo, min, max)
        except ip_connection.Error:
            return

    def cb_under_voltage(self, ov):
        mv_str = self.minimum_voltage_label.text()
        ov_str = "%gV" % round(ov / 1000.0, 1)
        if not self.qem.isVisible():
            self.qem.showMessage(
                "Under Voltage: Output Voltage of " + ov_str +
                " is below minimum voltage of " + mv_str, "Servo_UnterVoltage")

    def minimum_voltage_selected(self, value):
        try:
            self.servo.set_minimum_voltage(value)
        except ip_connection.Error:
            return

    def minimum_voltage_button_clicked(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(5000)
        qid.setIntMaximum(0xFFFF)
        qid.setIntStep(100)
        async_call(self.servo.get_minimum_voltage, None, qid.setIntValue,
                   self.increase_error_count)
        qid.intValueSelected.connect(self.minimum_voltage_selected)
        qid.setLabelText("Choose minimum servo voltage in mV.")
        qid.open()
Ejemplo n.º 29
0
class Editor(editor_base.EditorBase):
    """Representa el editor de texto que aparece en el panel derecho.

    El editor soporta autocompletado de código y resaltado de sintáxis.
    """

    # Señal es emitida cuando el Editor ejecuta codigo
    signal_ejecutando = QtCore.pyqtSignal()

    def __init__(self, main, interpreterLocals, consola_lanas,
                 ventana_interprete):
        super(Editor, self).__init__()
        self.cantidad_ejecuciones = 0
        self.consola_lanas = consola_lanas
        self.ventana_interprete = ventana_interprete
        self.ruta_del_archivo_actual = None
        self.interpreterLocals = interpreterLocals
        self.setLineWrapMode(QTextEdit.NoWrap)
        self._cambios_sin_guardar = False
        self.main = main
        self.nombre_de_archivo_sugerido = ""
        self.watcher = pilasengine.watcher.Watcher(
            None, self.cuando_cambia_archivo_de_forma_externa)

    def crear_archivo_inicial(self):
        dirpath = tempfile.mkdtemp()
        archivo_temporal = os.path.join(dirpath, "mi_juego.py")
        archivo = codecs.open(archivo_temporal, "w", 'utf-8')
        archivo.write(CODIGO_INICIAL)
        archivo.close()
        #print("Creando el archivo " + str(archivo_temporal))
        self.abrir_archivo_del_proyecto(archivo_temporal)

    def es_archivo_iniciar_sin_guardar(self):
        return self.nombre_de_archivo_sugerido == ""

    def crear_y_seleccionar_archivo(self, nombre):
        # Quita la extension si llega a tenerla.
        nombre = nombre.replace('.py', '')
        nombre += ".py"
        nombre_de_archivo = nombre

        if self.ruta_del_archivo_actual:
            base_path = os.path.abspath(
                os.path.dirname(self.ruta_del_archivo_actual))
            ruta = os.path.join(base_path, unicode(nombre_de_archivo))
        else:
            ruta = unicode(nombre_de_archivo)

        if os.path.exists(ruta):
            self._tmp_dialog = QErrorMessage(self)
            self._tmp_dialog.showMessage("Ya existe un archivo con ese nombre")
        else:
            self._crear_archivo_nuevo_en(ruta)

            self.cargar_contenido_desde_archivo(ruta)
            self.ruta_del_archivo_actual = ruta
            self.watcher.cambiar_archivo_a_observar(ruta)
            self.ejecutar()
            self.main.actualizar_el_listado_de_archivos()

    def _crear_archivo_nuevo_en(self, ruta):
        fo = open(ruta, "wb")
        fo.write("# contenido")
        fo.close()

    def obtener_archivos_del_proyecto(self):
        base_path = os.path.dirname(self.nombre_de_archivo_sugerido)
        listado = os.listdir(base_path)

        return [x for x in listado if x.endswith('.py')]

    def keyPressEvent(self, event):
        "Atiene el evento de pulsación de tecla."
        self._cambios_sin_guardar = True

        # Permite usar tab como seleccionador de la palabra actual
        # en el popup de autocompletado.
        if event.key() in [Qt.Key_Tab]:
            if self.completer and self.completer.popup().isVisible():
                event.ignore()
                nuevo_evento = QKeyEvent(QKeyEvent.KeyPress, Qt.Key_Return,
                                         Qt.NoModifier)
                try:
                    if self.autocomplete(nuevo_evento):
                        return None
                except UnicodeEncodeError:
                    pass
                return None

        if editor_base.EditorBase.keyPressEvent(self, event):
            return None

        # Elimina los pares de caracteres especiales si los encuentra
        if event.key() == Qt.Key_Backspace:
            self._eliminar_pares_de_caracteres()
            self._borrar_un_grupo_de_espacios(event)

        if self.autocomplete(event):
            return None

        if event.key() == Qt.Key_Return:
            cursor = self.textCursor()
            block = self.document().findBlockByNumber(cursor.blockNumber())
            whitespace = re.match(r"(\s*)", unicode(block.text())).group(1)

            linea_anterior = str(block.text()[:])
            cantidad_espacios = linea_anterior.count(' ') / 4

            if linea_anterior[-1:] == ':':
                whitespace = '    ' * (cantidad_espacios + 1)
            else:
                whitespace = '    ' * (cantidad_espacios)

            QTextEdit.keyPressEvent(self, event)
            return self.insertPlainText(whitespace)

        return QTextEdit.keyPressEvent(self, event)

    def _borrar_un_grupo_de_espacios(self, event):
        cursor = self.textCursor()
        block = self.document().findBlockByNumber(cursor.blockNumber())
        whitespace = re.match(r"(.*)", unicode(block.text())).group(1)

        if whitespace.endswith('    '):
            QTextEdit.keyPressEvent(self, event)
            QTextEdit.keyPressEvent(self, event)
            QTextEdit.keyPressEvent(self, event)

    def tiene_cambios_sin_guardar(self):
        return self._cambios_sin_guardar

    def _get_current_line(self):
        "Obtiene la linea en donde se encuentra el cursor."
        tc = self.textCursor()
        tc.select(QTextCursor.LineUnderCursor)
        return tc.selectedText()

    def _get_position_in_block(self):
        tc = self.textCursor()
        position = tc.positionInBlock() - 1
        return position

    def cargar_contenido_desde_archivo(self, ruta):
        "Carga todo el contenido del archivo indicado por ruta."
        with codecs.open(unicode(ruta), 'r', 'utf-8') as archivo:
            contenido = archivo.read()
        self.setText(contenido)

        self.nombre_de_archivo_sugerido = ruta
        self._cambios_sin_guardar = False

    def abrir_dialogo_cargar_archivo(self):
        return QFileDialog.getOpenFileName(
            self,
            "Abrir Archivo",
            self.nombre_de_archivo_sugerido,
            "Archivos python (*.py)",
            options=QFileDialog.DontUseNativeDialog)

    def abrir_archivo_del_proyecto(self, nombre_de_archivo):
        if self.tiene_cambios_sin_guardar():
            if self.mensaje_guardar_cambios_abrir():
                if not self.guardar_contenido_con_dialogo():
                    return
            else:
                return

        if self.ruta_del_archivo_actual:
            base_path = os.path.dirname(self.ruta_del_archivo_actual)
            ruta = os.path.join(base_path, unicode(nombre_de_archivo))
        else:
            ruta = unicode(nombre_de_archivo)

        self.cargar_contenido_desde_archivo(ruta)
        self.ruta_del_archivo_actual = ruta
        self.watcher.cambiar_archivo_a_observar(ruta)
        self.ejecutar()
        self.main.actualizar_el_listado_de_archivos()

    def abrir_archivo_con_dialogo(self):
        if self.tiene_cambios_sin_guardar():
            if self.mensaje_guardar_cambios_abrir():
                if not self.guardar_contenido_con_dialogo():
                    return
            else:
                return

        ruta = self.abrir_dialogo_cargar_archivo()

        if ruta:
            ruta = unicode(ruta)
            self.cargar_contenido_desde_archivo(ruta)
            self.ruta_del_archivo_actual = ruta
            self.watcher.cambiar_archivo_a_observar(ruta)
            self.ejecutar()
            self.main.actualizar_el_listado_de_archivos()

    def cuando_cambia_archivo_de_forma_externa(self):
        self.recargar_archivo_actual()

    def recargar_archivo_actual(self):
        if self.ruta_del_archivo_actual:
            self.cargar_contenido_desde_archivo(self.ruta_del_archivo_actual)
            self.ejecutar()

    def mensaje_guardar_cambios_abrir(self):
        """Realizar una consulta usando un cuadro de dialogo simple
        se utiliza cuando hay cambios sin guardar y se desea abrir un archivo.
        Retorna True si el usuario presiona el boton *Guardar*,
        Retorna False si el usuario presiona *No*."""
        titulo = u"¿Deseas guardar el contenido antes de abrir un archivo?"
        mensaje = u"El contenido se perdera sino los guardas"

        mensaje = QMessageBox.question(self, titulo, mensaje, "Guardar", "No")

        return (not mensaje)

    def mensaje_guardar_cambios_salir(self):
        """Realizar una consulta usando un cuadro de dialogo simple
        se utiliza cuando hay cambios sin guardar y se desa salir del Editor.
        Retorna 0 si el usuario presiona el boton *Salir sin guardar*,
        Retorna 1 si el usuario presiona *Guardar*
        Retorna 2 si presiona *Cancelar*."""

        titulo = u"¿Deseas guardar el contenido antes de salir?"
        mensaje = u"El contenido se perdera sino los guardas"

        return QMessageBox.question(self, titulo, mensaje, "Salir sin guardar",
                                    "Guardar", "Cancelar")

    def marcar_error_en_la_linea(self, numero, descripcion):
        hi_selection = QTextEdit.ExtraSelection()

        hi_selection.format.setBackground(QColor(255, 220, 220))
        hi_selection.format.setProperty(QTextFormat.FullWidthSelection,
                                        QVariant(True))
        hi_selection.cursor = self.textCursor()
        posicion_linea = self.document().findBlockByLineNumber(
            numero).position()
        hi_selection.cursor.setPosition(posicion_linea)
        hi_selection.cursor.clearSelection()

        self.setExtraSelections([hi_selection])

    def guardar_contenido_con_dialogo(self):
        ruta = self.abrir_dialogo_guardar_archivo()

        if not ruta:
            return False

        ruta = unicode(ruta)

        if not ruta.endswith('.py'):
            ruta += '.py'

        if ruta:
            self.guardar_contenido_en_el_archivo(ruta)
            self._cambios_sin_guardar = False
            self.ruta_del_archivo_actual = ruta
            self.nombre_de_archivo_sugerido = ruta
            self.watcher.cambiar_archivo_a_observar(ruta)
            self.cargar_contenido_desde_archivo(ruta)
            self.ejecutar()
            self.main.actualizar_el_listado_de_archivos()
            self.main.habilitar_boton_nuevo()
            return True

    def guardar_contenido_directamente(self):
        if self.nombre_de_archivo_sugerido:
            self.guardar_contenido_en_el_archivo(
                self.nombre_de_archivo_sugerido)
            self._cambios_sin_guardar = False
            self.main.actualizar_el_listado_de_archivos()
            self.prevenir_live_reload()
        else:
            self.guardar_contenido_con_dialogo()

    def prevenir_live_reload(self):
        self.watcher.prevenir_reinicio()

    def salir(self):
        """Retorna True si puede salir y False si no"""
        if self.tiene_cambios_sin_guardar():
            mensaje = self.mensaje_guardar_cambios_salir()
            if mensaje == 1:
                self.guardar_contenido_con_dialogo()
            elif mensaje == 2:
                return False

        return True

    def obtener_contenido(self):
        return unicode(self.document().toPlainText())

    def ejecutar(self):
        ruta_personalizada = os.path.dirname(self.ruta_del_archivo_actual)
        #print "ejecutando texto desde widget editor"
        texto = self.obtener_contenido()
        #texto = self.editor.obtener_texto_sanitizado(self)
        # elimina cabecera de encoding.
        contenido = re.sub('coding\s*:\s*', '', texto)
        contenido = contenido.replace('import pilasengine', '')
        contenido = contenido.replace('pilas = pilasengine.iniciar',
                                      'pilas.reiniciar')

        for x in contenido.split('\n'):
            if "__file__" in x:
                contenido = contenido.replace(x, "# livecoding: " + x + "\n")

        sys.path.append(ruta_personalizada)
        self.interpreterLocals['sys'] = sys

        # Muchos códigos personalizados necesitan cargar imágenes o sonidos
        # desde el directorio que contiene al archivo. Para hacer esto posible,
        # se llama a la función "pilas.utils.agregar_ruta_personalizada" con el
        # path al directorio que representa el script. Así la función "obtener_ruta_al_recurso"
        # puede evaluar al directorio del script en busca de recursos también.
        if ruta_personalizada:
            ruta_personalizada = ruta_personalizada.replace('\\', '/')
            agregar_ruta_personalizada = 'pilas.utils.agregar_ruta_personalizada("%s")' % (
                ruta_personalizada)
            contenido = contenido.replace(
                'pilas.reiniciar(',
                agregar_ruta_personalizada + '\n' + 'pilas.reiniciar(')

        modulos_a_recargar = [
            x for x in self.interpreterLocals.values()
            if inspect.ismodule(x) and x.__name__ not in
            ['pilasengine', 'inspect'] and 'pilasengine.' not in x.__name__
        ]

        for m in modulos_a_recargar:
            reload(m)

        self.cantidad_ejecuciones += 1

        # Limpia la consola a partir de la primer ejecucion luego de iniciar.
        if self.cantidad_ejecuciones > 1:
            self.main.limpiar_interprete()

        try:
            exec(contenido, self.interpreterLocals)
        except Exception, e:
            self.consola_lanas.insertar_error_desde_exception(e)
            self.ventana_interprete.mostrar_el_interprete()
            #self.marcar_error_en_la_linea(10, "pepepe")

        self.signal_ejecutando.emit()
Ejemplo n.º 30
0
class DC(PluginBase, Ui_DC):
    qtcb_velocity_reached = pyqtSignal(int)
    qtcb_under_voltage = pyqtSignal(int)
    qtcb_emergency_shutdown = pyqtSignal()

    def __init__(self, *args):
        PluginBase.__init__(self, BrickDC, *args)

        self.setupUi(self)

        self.dc = self.device

        self.encoder_hide_all()

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

        self.speedometer = SpeedoMeter()
        self.vertical_layout_right.insertWidget(4, self.speedometer)

        self.new_value = 0
        self.update_counter = 0

        self.full_brake_time = 0

        self.velocity_syncer = SliderSpinSyncer(self.velocity_slider,
                                                self.velocity_spin,
                                                self.velocity_changed)

        self.acceleration_syncer = SliderSpinSyncer(self.acceleration_slider,
                                                    self.acceleration_spin,
                                                    self.acceleration_changed)

        self.frequency_syncer = SliderSpinSyncer(self.frequency_slider,
                                                 self.frequency_spin,
                                                 self.frequency_changed)

        self.radio_mode_brake.toggled.connect(self.brake_value_changed)
        self.radio_mode_coast.toggled.connect(self.coast_value_changed)

        self.minimum_voltage_button.clicked.connect(
            self.minimum_voltage_button_clicked)
        self.full_brake_button.clicked.connect(self.full_brake_clicked)
        self.enable_checkbox.stateChanged.connect(self.enable_state_changed)

        self.emergency_signal = None
        self.under_signal = None
        self.current_velocity_signal = None
        self.velocity_reached_signal = None

        self.qem = QErrorMessage(self)

        self.qtcb_under_voltage.connect(self.cb_under_voltage)
        self.dc.register_callback(self.dc.CALLBACK_UNDER_VOLTAGE,
                                  self.qtcb_under_voltage.emit)

        self.qtcb_emergency_shutdown.connect(self.cb_emergency_shutdown)
        self.dc.register_callback(self.dc.CALLBACK_EMERGENCY_SHUTDOWN,
                                  self.qtcb_emergency_shutdown.emit)

        self.qtcb_velocity_reached.connect(self.update_velocity)
        self.dc.register_callback(self.dc.CALLBACK_VELOCITY_REACHED,
                                  self.qtcb_velocity_reached.emit)

        self.cbe_current_velocity = CallbackEmulator(
            self.dc.get_current_velocity, self.update_velocity,
            self.increase_error_count)

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

#        if self.firmware_version >= (2, 0, 1):
#            self.enable_encoder_checkbox.stateChanged.connect(self.enable_encoder_state_changed)
#            self.encoder_show()
#        else:
#            self.enable_encoder_checkbox.setText('Enable Encoder (FW Version >= 2.0.1 required)')
#            self.enable_encoder_checkbox.setEnabled(False)

    def start(self):
        self.update_timer.start(1000)
        self.cbe_current_velocity.set_period(100)
        self.update_start()
        self.update_data()

    def stop(self):
        self.update_timer.stop()
        self.cbe_current_velocity.set_period(0)

    def destroy(self):
        pass

    def get_url_part(self):
        return 'dc'

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

    def cb_emergency_shutdown(self):
        if not self.qem.isVisible():
            self.qem.setWindowTitle("Emergency Shutdown")
            self.qem.showMessage(
                "Emergency Shutdown: Short-Circuit or Over-Temperature")

    def cb_under_voltage(self, ov):
        mv_str = self.minimum_voltage_label.text()
        ov_str = "%gV" % round(ov / 1000.0, 1)
        if not self.qem.isVisible():
            self.qem.setWindowTitle("Under Voltage")
            self.qem.showMessage(
                "Under Voltage: Output Voltage of " + ov_str +
                " is below minimum voltage of " + mv_str, "DC_UnderVoltage")

    def encoder_hide_all(self):
        self.enable_encoder_checkbox.hide()
        self.encoder_hide()

    def encoder_hide(self):
        self.p_label.hide()
        self.p_spinbox.hide()
        self.i_label.hide()
        self.i_spinbox.hide()
        self.d_label.hide()
        self.d_spinbox.hide()
        self.st_label.hide()
        self.st_spinbox.hide()
        self.cpr_label.hide()
        self.cpr_spinbox.hide()
        self.encoder_spacer.hide()

    def encoder_show(self):
        self.p_label.show()
        self.p_spinbox.show()
        self.i_label.show()
        self.i_spinbox.show()
        self.d_label.show()
        self.d_spinbox.show()
        self.st_label.show()
        self.st_spinbox.show()
        self.cpr_label.show()
        self.cpr_spinbox.show()
        self.encoder_spacer.show()

    def enable_encoder_state_changed(self, state):
        try:
            if state == Qt.Checked:
                self.dc.enable_encoder()
                self.update_encoder()
            elif state == Qt.Unchecked:
                self.dc.disable_encoder()

        except ip_connection.Error:
            return

    def enable_state_changed(self, state):
        try:
            if state == Qt.Checked:
                self.dc.enable()
            elif state == Qt.Unchecked:
                self.dc.disable()
        except ip_connection.Error:
            return

    def brake_value_changed(self, checked):
        if checked:
            try:
                self.dc.set_drive_mode(0)
            except ip_connection.Error:
                return

    def coast_value_changed(self, checked):
        if checked:
            try:
                self.dc.set_drive_mode(1)
            except ip_connection.Error:
                return

    def full_brake_clicked(self):
        try:
            self.dc.full_brake()
        except ip_connection.Error:
            return

    def minimum_voltage_selected(self, value):
        try:
            self.dc.set_minimum_voltage(value)
        except ip_connection.Error:
            return

    def minimum_voltage_button_clicked(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(5000)
        qid.setIntMaximum(0xFFFF)
        qid.setIntStep(100)
        async_call(self.dc.get_minimum_voltage, None, qid.setIntValue,
                   self.increase_error_count)
        qid.intValueSelected.connect(self.minimum_voltage_selected)
        qid.setLabelText("Choose minimum motor voltage in mV.")
        qid.open()

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

    def external_input_voltage_update(self, ev):
        ev_str = "%gV" % round(ev / 1000.0, 1)
        self.external_voltage_label.setText(ev_str)

    def minimum_voltage_update(self, mv):
        mv_str = "%gV" % round(mv / 1000.0, 1)
        self.minimum_voltage_label.setText(mv_str)

    def drive_mode_update(self, dm):
        if dm == 0:
            self.radio_mode_brake.setChecked(True)
            self.radio_mode_coast.setChecked(False)
        else:
            self.radio_mode_brake.setChecked(False)
            self.radio_mode_coast.setChecked(True)

    def current_consumption_update(self, cc):
        if cc >= 1000:
            cc_str = "%gA" % round(cc / 1000.0, 1)
        else:
            cc_str = "%gmA" % cc

        self.current_label.setText(cc_str)

    def update_velocity(self, value):
        self.speedometer.set_velocity(value)

    def get_velocity_async(self, velocity):
        if not self.velocity_slider.isSliderDown():
            if velocity != self.velocity_slider.sliderPosition():
                self.velocity_slider.setSliderPosition(velocity)
                self.velocity_spin.setValue(velocity)

        self.speedometer.set_velocity(velocity)

    def get_acceleration_async(self, acceleration):
        if not self.acceleration_slider.isSliderDown():
            if acceleration != self.acceleration_slider.sliderPosition():
                self.acceleration_slider.setSliderPosition(acceleration)
                self.acceleration_spin.setValue(acceleration)

    def get_pwm_frequency_async(self, frequency):
        if not self.frequency_slider.isSliderDown():
            if frequency != self.frequency_slider.sliderPosition():
                self.frequency_slider.setSliderPosition(frequency)
                self.frequency_spin.setValue(frequency)

    def is_enabled_async(self, enabled):
        self.enable_checkbox.setChecked(enabled)

    def is_encoder_enabled_async(self, enabled):
        self.enable_encoder_checkbox.setChecked(enabled)

    def get_encoder_config_async(self, cpr):
        self.cpr_spinbox.setValue(cpr)

    def get_encoder_pid_config_async(self, pid_config):
        self.p_spinbox.setValue(pid_config.p)
        self.i_spinbox.setValue(pid_config.i)
        self.d_spinbox.setValue(pid_config.d)
        self.st_spinbox.setValue(pid_config.sample_time)

    def update_encoder(self):
        async_call(self.dc.get_encoder_config, None,
                   self.get_encoder_config_async, self.increase_error_count)
        async_call(self.dc.get_encoder_pid_config, None,
                   self.get_encoder_pid_config_async,
                   self.increase_error_count)
        async_call(self.dc.is_encoder_enabled, None,
                   self.is_encoder_enabled_async, self.increase_error_count)

    def update_start(self):
        async_call(self.dc.get_drive_mode, None, self.drive_mode_update,
                   self.increase_error_count)
        async_call(self.dc.get_velocity, None, self.get_velocity_async,
                   self.increase_error_count)
        async_call(self.dc.get_acceleration, None, self.get_acceleration_async,
                   self.increase_error_count)
        async_call(self.dc.get_pwm_frequency, None,
                   self.get_pwm_frequency_async, self.increase_error_count)
        async_call(self.dc.is_enabled, None, self.is_enabled_async,
                   self.increase_error_count)
#        if self.firmware_version >= (2, 0, 1):
#            self.update_encoder()

    def update_data(self):
        async_call(self.dc.get_stack_input_voltage, None,
                   self.stack_input_voltage_update, self.increase_error_count)
        async_call(self.dc.get_external_input_voltage, None,
                   self.external_input_voltage_update,
                   self.increase_error_count)
        async_call(self.dc.get_minimum_voltage, None,
                   self.minimum_voltage_update, self.increase_error_count)
        async_call(self.dc.get_current_consumption, None,
                   self.current_consumption_update, self.increase_error_count)

    def acceleration_changed(self, value):
        try:
            self.dc.set_acceleration(value)
        except ip_connection.Error:
            return

    def velocity_changed(self, value):
        try:
            self.dc.set_velocity(value)
        except ip_connection.Error:
            return

    def frequency_changed(self, value):
        try:
            self.dc.set_pwm_frequency(value)
        except ip_connection.Error:
            return
Ejemplo n.º 31
0
class Servo(PluginBase, Ui_Servo):
    qtcb_under_voltage = pyqtSignal(int)
    
    def __init__ (self, ipcon, uid):
        PluginBase.__init__(self, ipcon, uid)
        self.setupUi(self)
        
        self.servo = brick_servo.Servo(self.uid)
        self.device = self.servo
        self.ipcon.add_device(self.servo)
        self.version = '.'.join(map(str, self.servo.get_version()[1]))
        
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(self.update_apply)
        self.update_timer.setInterval(0)
        self.update_timer.setSingleShot(True)
        
        layout = QVBoxLayout(self)
        layout.addWidget(QLabel('Servo'))
        self.position_list = []
        self.velocity_list = []
        self.acceleration_list = []
        self.enable_list = []
        
        self.up_ena = [0]*7
        self.up_pos = [0]*7
        self.up_vel = [0]*7
        self.up_acc = [0]*7
        
        self.alive = True
        
        for i in range(1, 8):
            label = QLabel()
            label.setText('Off')
            self.enable_list.append(label)
            self.status_grid.addWidget(label, i, 1)
            
        for i in range(1, 8):
            pk = PositionKnob()
            self.position_list.append(pk)
            self.status_grid.addWidget(pk, i, 2)
            
        for i in range(1, 8):
            cb = ColorBar(Qt.Vertical)
            self.velocity_list.append(cb)
            self.status_grid.addWidget(cb, i, 3)
            
        for i in range(1, 8):
            cb = ColorBar(Qt.Vertical)
            self.acceleration_list.append(cb)
            self.status_grid.addWidget(cb, i, 4)
            
        self.qem = QErrorMessage(self)
        self.qem.setWindowTitle("Under Voltage")
            
        self.test_button.clicked.connect(self.test_button_clicked)
        self.output_voltage_button.clicked.connect(self.output_voltage_button_clicked)
            
        self.servo_dropbox.currentIndexChanged.connect(lambda x: self.update_servo_specific())
        self.enable_checkbox.stateChanged.connect(self.enable_state_changed)
        
        self.position_slider.sliderReleased.connect(self.position_slider_released)
        self.position_slider.valueChanged.connect(self.position_spin.setValue)
        self.position_spin.editingFinished.connect(self.position_spin_finished)
        
        self.velocity_slider.sliderReleased.connect(self.velocity_slider_released)
        self.velocity_slider.valueChanged.connect(self.velocity_spin.setValue)
        self.velocity_spin.editingFinished.connect(self.velocity_spin_finished)
        
        self.acceleration_slider.sliderReleased.connect(self.acceleration_slider_released)
        self.acceleration_slider.valueChanged.connect(self.acceleration_spin.setValue)
        self.acceleration_spin.editingFinished.connect(self.acceleration_spin_finished)
        
        self.period_slider.sliderReleased.connect(self.period_slider_released)
        self.period_slider.valueChanged.connect(self.period_spin.setValue)
        self.period_spin.editingFinished.connect(self.period_spin_finished)
        
        self.pulse_width_min_spin.editingFinished.connect(self.pulse_width_spin_finished)
        self.pulse_width_max_spin.editingFinished.connect(self.pulse_width_spin_finished)
        self.degree_min_spin.editingFinished.connect(self.degree_spin_finished)
        self.degree_max_spin.editingFinished.connect(self.degree_spin_finished)
        
        self.minimum_voltage_button.pressed.connect(self.minimum_voltage_button_pressed)
        
        self.qtcb_under_voltage.connect(self.cb_under_voltage)
        self.servo.register_callback(self.servo.CALLBACK_UNDER_VOLTAGE,
                                     self.qtcb_under_voltage.emit) 
        
        class WorkerThread(QThread):
            def __init__(self, parent = None, func = None):
                QThread.__init__(self, parent)
                self.func = func
                
            def run(self):
                self.func()
        
        
        self.test_event = Event()
        self.test_thread_object = WorkerThread(self, self.test_thread)
        self.update_event = Event()
        self.update_thread_object = WorkerThread(self, self.update_thread)
        
        self.update_done_event = Event()
        self.update_done_event.set()

    def stop(self):
        if self.test_button.text() == "Stop Test":
            self.test_button_clicked()
        self.update_event.clear()
        self.alive = False
        self.update_done_event.wait()
        
    def start(self):
        self.alive = True
        self.test_event.clear()
        self.update_done_event.set()
        self.update_event.set()
        
        if not self.test_thread_object.isRunning():
            self.test_thread_object.start()
            
        if not self.update_thread_object.isRunning():
            self.update_thread_object.start() 
            
        self.update_servo_specific()
        
    def destroy(self):
        self.test_event.set()
        self.update_event.set()
    
    @staticmethod
    def has_name(name):
        return 'Servo Brick' in name 
    
    def update_servo_specific(self):
        i = self.selected_servo()
        if i == 255:
            self.enable_checkbox.setCheckState(Qt.Unchecked)
            return
        
        try:
            pos = self.servo.get_position(i);
            vel = self.servo.get_velocity(i);
            acc = self.servo.get_acceleration(i);
            per = self.servo.get_period(i)
            ena = self.servo.is_enabled(i)
            deg_min, deg_max = self.servo.get_degree(i)
            pulse_min, pulse_max = self.servo.get_pulse_width(i)
        except ip_connection.Error:
            return
        
        self.position_spin.setValue(pos)
        self.velocity_spin.setValue(vel)
        self.acceleration_spin.setValue(acc)
        self.period_spin.setValue(per)
        self.position_slider.setValue(pos)
        self.velocity_slider.setValue(vel)
        self.acceleration_slider.setValue(acc)
        self.period_slider.setValue(per)
        if ena:
            self.enable_checkbox.setCheckState(Qt.Checked)
        else:
            self.enable_checkbox.setCheckState(Qt.Unchecked)
    
        self.pulse_width_min_spin.setValue(pulse_min)
        self.pulse_width_max_spin.setValue(pulse_max)
        self.degree_min_spin.setValue(deg_min)
        self.degree_max_spin.setValue(deg_max)
        
        self.position_slider.setMinimum(deg_min)
        self.position_slider.setMaximum(deg_max)
        self.position_spin.setMinimum(deg_min)
        self.position_spin.setMaximum(deg_max)
        self.position_list[i].setTotalAngle((deg_max - deg_min)/100)
        self.position_list[i].setRange(deg_min/100, deg_max/100)
        
    def error_handler(self, error):
        pass
        
    def servo_current_update(self, value):
        self.current_label.setText(str(value) + "mA")
    
    def stack_input_voltage_update(self, sv):
        sv_str = "%gV"  % round(sv/1000.0, 1)
        self.stack_voltage_label.setText(sv_str)
        
    def external_input_voltage_update(self, ev):
        ev_str = "%gV"  % round(ev/1000.0, 1)
        self.external_voltage_label.setText(ev_str)
        
    def output_voltage_update(self, ov):
        ov_str = "%gV"  % round(ov/1000.0, 1)
        self.output_voltage_label.setText(ov_str)
        
    def minimum_voltage_update(self, mv):
        mv_str = "%gV"  % round(mv/1000.0, 1)
        self.minimum_voltage_label.setText(mv_str)
        
    def position_update(self, i, pos):
        self.position_list[i].setValue(pos/100)
    
    def velocity_update(self, i, vel):
        self.velocity_list[i].set_height(vel*100/0xFFFF)

    def acceleration_update(self, i, acc):
        self.acceleration_list[i].set_height(acc*100/0xFFFF)
    
    def deactivate_servo(self, i):
        if self.enable_list[i].text() != 'Off':
            self.velocity_list[i].grey()
            self.acceleration_list[i].grey()
            
    def activate_servo(self, i):
        if self.enable_list[i].text() != 'On':
            self.velocity_list[i].color()
            self.acceleration_list[i].color()
        
    def selected_servo(self):
        try:
            return int(self.servo_dropbox.currentText()[-1:])
        except:
            return 255

    def enable_state_changed(self, state):
        s = self.selected_servo()
        try:
            if state == Qt.Checked:
                self.servo.enable(s)
            elif state == Qt.Unchecked:
                self.servo.disable(s)
        except ip_connection.Error:
            return
            
    def update_apply(self):
        self.servo_current_update(self.up_cur)
        self.stack_input_voltage_update(self.up_siv)
        self.external_input_voltage_update(self.up_eiv)
        self.output_voltage_update(self.up_opv)
        self.minimum_voltage_update(self.up_mv)
        for i in range(7):
            if self.up_ena[i]:
                self.activate_servo(i)
                
                self.position_update(i, self.up_pos[i])
                self.velocity_update(i, self.up_vel[i])
                self.acceleration_update(i, self.up_acc[i])
                
                self.enable_list[i].setText('On')
            else:
                self.deactivate_servo(i)
                self.enable_list[i].setText('Off')
                
    def update_thread(self):
        while self.alive:
            time.sleep(0.1)
            
            try:
                servo = self.selected_servo()
                if servo == 255:
                    self.up_cur = self.servo.get_overall_current()
                else:
                    self.up_cur = self.servo.get_servo_current(servo)
                    
                self.up_siv = self.servo.get_stack_input_voltage()
                self.up_eiv = self.servo.get_external_input_voltage()
                self.up_opv = self.servo.get_output_voltage()
                self.up_mv = self.servo.get_minimum_voltage()
                
                for i in range(7):
                    self.up_ena[i] = self.servo.is_enabled(i)
                    if self.up_ena[i]:
                        self.activate_servo(i)
                        self.up_pos[i] = self.servo.get_current_position(i)
                        self.up_vel[i] = self.servo.get_current_velocity(i)
                        self.up_acc[i] = self.servo.get_acceleration(i)
    
                self.update_timer.start()
                #self.update_apply()
                
                self.update_done_event.set()
                self.update_event.wait()
                self.update_done_event.clear()
            except ip_connection.Error:
                pass
        self.update_done_event.set()
            
    def test_thread(self):
        def test(num, ena, acc, vel, pos):
            if not self.alive:
                return

            try:
                if ena:
                    self.servo.enable(num)
                else:
                    self.servo.disable(num)
                self.servo.set_acceleration(num, acc)
                self.servo.set_velocity(num, vel)
                self.servo.set_position(num, pos)
            except ip_connection.Error:
                return
        
        def random_test():
            for i in range(7):
                test(i,
                     random.randrange(0, 2),
                     random.randrange(0, 65536),
                     random.randrange(0, 65536),
                     random.randrange(-9000, 9001))
            
        while self.alive:
            self.test_event.wait()
            if not self.alive:
                return
            
            # Full Speed left for 2 seconds
            for i in range(7):
                test(i, True, 65535, 65535, 9000)
            time.sleep(2)
            self.test_event.wait()
            if not self.alive:
                return
            
            # Full Speed right for 2 seconds
            for i in range(7):
                test(i, True, 65535, 65535, -9000)
            time.sleep(2)
            self.test_event.wait()
            if not self.alive:
                return
            
            # Test different speeds
            for i in range(19):
                for j in range(7):
                    test(j, True, 65535, 65535*i/18, -9000+i*1000)
                time.sleep(0.1)
                self.test_event.wait()  
                if not self.alive:
                    return
            time.sleep(1)
            self.test_event.wait()
            if not self.alive:
                return
            
            # Test acceleration
            for i in range(7):
                test(i, True, 100, 65535, -9000)
                
            time.sleep(3)
            self.test_event.wait()
            if not self.alive:
                return
            
            # Random for 3 seconds
            random_test()
            time.sleep(3)
    
    def test_button_clicked(self):
        if self.test_button.text() == "Start Test":
            self.test_button.setText("Stop Test")
            self.test_event.set()
        else:
            self.test_button.setText("Start Test")        
            self.test_event.clear()
    
    def output_voltage_button_clicked(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(5000)
        qid.setIntMaximum(27000)
        qid.setIntStep(100)
        try:
            qid.setIntValue(self.servo.get_output_voltage())
        except ip_connection.Error:
            return
        qid.intValueSelected.connect(self.output_voltage_selected)
        qid.setLabelText("Choose Output Voltage in mV.")
#                         "<font color=red>Setting this too high can destroy your servo.</font>")
        qid.open()
        
    def output_voltage_selected(self, value):
        try:
            self.servo.set_output_voltage(value)
        except ip_connection.Error:
            return
        
    def position_slider_released(self):
        value = self.position_slider.value()
        self.position_spin.setValue(value)
        try:
            self.servo.set_position(self.selected_servo(), value)
        except ip_connection.Error:
            return
 
    def position_spin_finished(self):
        value = self.position_spin.value()
        self.position_slider.setValue(value)
        try:
            self.servo.set_position(self.selected_servo(), value)
        except ip_connection.Error:
            return
        
    def velocity_slider_released(self):
        value = self.velocity_slider.value()
        self.velocity_spin.setValue(value)
        try:
            self.servo.set_velocity(self.selected_servo(), value)
        except ip_connection.Error:
            return
        
    def velocity_spin_finished(self):
        value = self.velocity_spin.value()
        self.velocity_slider.setValue(value)
        try:
            self.servo.set_velocity(self.selected_servo(), value)
        except ip_connection.Error:
            return
        
    def acceleration_slider_released(self):
        value = self.acceleration_slider.value()
        self.acceleration_spin.setValue(value)
        try:
            self.servo.set_acceleration(self.selected_servo(), value)
        except ip_connection.Error:
            return
        
    def acceleration_spin_finished(self):
        value = self.acceleration_spin.value()
        self.acceleration_slider.setValue(value)
        try:
            self.servo.set_acceleration(self.selected_servo(), value)
        except ip_connection.Error:
            return
        
    def period_slider_released(self):
        value = self.period_slider.value()
        self.period_spin.setValue(value)
        try:
            self.servo.set_period(self.selected_servo(), value)
        except ip_connection.Error:
            return
        
    def period_spin_finished(self):
        value = self.period_spin.value()
        self.period_slider.setValue(value)
        try:
            self.servo.set_period(self.selected_servo(), value)
        except ip_connection.Error:
            return
        
    def pulse_width_spin_finished(self):
        try:
            self.servo.set_pulse_width(self.selected_servo(), 
                                       self.pulse_width_min_spin.value(), 
                                       self.pulse_width_max_spin.value())
        except ip_connection.Error:
            return
    
    def degree_spin_finished(self):
        min = self.degree_min_spin.value()
        max = self.degree_max_spin.value()
        servo = self.selected_servo()
        
        self.position_slider.setMinimum(min)
        self.position_slider.setMaximum(max)
        self.position_spin.setMinimum(min)
        self.position_spin.setMaximum(max)
        self.position_list[servo].setTotalAngle((max - min)/100)
        self.position_list[servo].setRange(min/100, max/100)
        
        try:
            self.servo.set_degree(servo, min, max)
        except ip_connection.Error:
            return
        
    def cb_under_voltage(self, ov):
        mv_str = self.minimum_voltage_label.text()
        ov_str = "%gV"  % round(ov/1000.0, 1)
        if not self.qem.isVisible():
            self.qem.showMessage("Under Voltage: Output Voltage of " + ov_str +
                                 " is below minimum voltage of " + mv_str)
            
    def minimum_voltage_selected(self, value):
        try:
            self.servo.set_minimum_voltage(value)
        except ip_connection.Error:
            return

    def minimum_voltage_button_pressed(self):
        qid = QInputDialog(self)
        qid.setInputMode(QInputDialog.IntInput)
        qid.setIntMinimum(5000)
        qid.setIntMaximum(0xFFFF)
        qid.setIntStep(100)
        try:
            qid.setIntValue(self.servo.get_minimum_voltage())
        except ip_connection.Error:
            return
        qid.intValueSelected.connect(self.minimum_voltage_selected)
        qid.setLabelText("Choose minimum servo voltage in mV.")
        qid.open()
Ejemplo n.º 32
-1
    def input_device_changed(self, index):
        self.ui.actionStart.setChecked(False)

        success, index = self.audiobackend.select_input_device(index)

        self.settings_dialog.comboBox_inputDevice.setCurrentIndex(index)

        if not success:
            # Note: the error message is a child of the settings dialog, so that
            # that dialog remains on top when the error message is closed
            error_message = QErrorMessage(self.settings_dialog)
            error_message.setWindowTitle("Input device error")
            error_message.showMessage(
                "Impossible to use the selected input device, reverting to the previous one"
            )

        # reset the channels
        first_channel = self.audiobackend.get_current_first_channel()
        self.settings_dialog.comboBox_firstChannel.setCurrentIndex(
            first_channel)
        second_channel = self.audiobackend.get_current_second_channel()
        self.settings_dialog.comboBox_secondChannel.setCurrentIndex(
            second_channel)

        self.ui.actionStart.setChecked(True)