Source code for mesycontrol.devices.mhv4_v20
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# mesycontrol - Remote control for mesytec devices.
# Copyright (C) 2015-2016 mesytec GmbH & Co. KG <info@mesytec.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
__author__ = 'Florian Lüke'
__email__ = 'f.lueke@mesytec.com'
from .. qt import pyqtSlot
from .. qt import Qt
from .. qt import QtCore
from .. qt import QtGui
import itertools
import weakref
from .. import parameter_binding as pb
from .. import util
from .. specialized_device import DeviceBase
from .. specialized_device import DeviceWidgetBase
import mhv4_v20_profile
NUM_CHANNELS = 4
MAX_VOLTAGE_V = 400.0
Polarity = mhv4_v20_profile.Polarity
# ========== Device ==========
[docs]class MHV4_V20(DeviceBase):
def __init__(self, app_device, display_mode, write_mode, parent=None):
super(MHV4_V20, self).__init__(app_device, display_mode, write_mode, parent)
def _on_hw_parameter_changed(self, address, value):
super(MHV4_V20, self)._on_hw_parameter_changed(address, value)
# ========== GUI ==========
[docs]class WheelEventFilter(QtCore.QObject):
"""Event filter to filter out QEvent::Wheel events."""
def __init__(self, parent=None):
super(WheelEventFilter, self).__init__(parent)
[docs] def eventFilter(self, obj, event):
return event.type() == QtCore.QEvent.Wheel
[docs]class PolarityLabelBinding(pb.DefaultParameterBinding):
def __init__(self, pixmaps, **kwargs):
super(PolarityLabelBinding, self).__init__(**kwargs)
self._pixmaps = pixmaps
def _update(self, rf):
try:
self.target.setPixmap(self._pixmaps[int(rf)])
except Exception:
pass
[docs]class ChannelEnablePolarityBinding(pb.DefaultParameterBinding):
"""Used for the polarity label. Disables/enables the label depending on the
channels enable state."""
def __init__(self, **kwargs):
super(ChannelEnablePolarityBinding, self).__init__(**kwargs)
def _update(self, rf):
self.target.setEnabled(int(rf))
[docs]class ChannelWidget(QtGui.QWidget):
def __init__(self, device, channel, display_mode, write_mode, parent=None):
super(ChannelWidget, self).__init__(parent)
util.loadUi(":/ui/mhv4_v20_channel.ui", self)
self.device = device
self.channel = channel
self.bindings = list()
self.pb_channelstate.installEventFilter(self)
sz = self.label_polarity.minimumSize()
self.polarity_pixmaps = {
Polarity.positive: QtGui.QPixmap(":/polarity-positive.png").scaled(
sz, Qt.KeepAspectRatio, Qt.SmoothTransformation),
Polarity.negative: QtGui.QPixmap(":/polarity-negative.png").scaled(
sz, Qt.KeepAspectRatio, Qt.SmoothTransformation)
}
self._last_temperature = None
self._last_tcomp_source = None
self.slider_target_voltage.installEventFilter(WheelEventFilter(self))
# Voltage write
self.bindings.append(pb.factory.make_binding(
device=device,
profile=device.profile['channel%d_voltage_write' % channel],
display_mode=display_mode,
write_mode=write_mode,
target=self.spin_target_voltage,
unit_name='volt'))
self.bindings.append(pb.factory.make_binding(
device=device,
profile=device.profile['channel%d_voltage_write' % channel],
display_mode=display_mode,
write_mode=write_mode,
target=self.slider_target_voltage,
unit_name='volt', update_on='slider_released'))
# Polarity
self.bindings.append(PolarityLabelBinding(
device=device, profile=device.profile['channel%d_polarity_read' % channel],
target=self.label_polarity, display_mode=display_mode, write_mode=write_mode,
pixmaps=self.polarity_pixmaps))
# Channel enable
self.bindings.append(ChannelEnablePolarityBinding(
device=device, profile=pb.ReadWriteProfile(
device.profile['channel%d_enable_read' % channel],
device.profile['channel%d_enable_write' % channel]),
target=self.label_polarity, display_mode=display_mode, write_mode=write_mode))
self.bindings.append(ChannelEnableButtonBinding(
device=device, profile=pb.ReadWriteProfile(
device.profile['channel%d_enable_read' % channel],
device.profile['channel%d_enable_write' % channel]),
target=self.pb_channelstate, display_mode=display_mode, write_mode=write_mode))
# Voltage
self.bindings.append(pb.factory.make_binding(
device=device, profile=device.profile['channel%d_voltage_read' % channel],
target=self.lcd_voltage, display_mode=display_mode, write_mode=write_mode,
unit_name='volt', precision=2))
# Voltage limit label
self.bindings.append(pb.TargetlessParameterBinding(
device=device, profile=device.profile['voltage_range_read'],
display_mode=display_mode, write_mode=write_mode
).add_update_callback(self._voltage_range_updated))
# Current
self.bindings.append(pb.factory.make_binding(
device=device, profile=device.profile['channel%d_current_read' % channel],
target=self.lcd_current, display_mode=display_mode, write_mode=write_mode,
unit_name='microamps', precision=3
).add_update_callback(self._current_updated))
# Current limit
self.bindings.append(pb.TargetlessParameterBinding(
device=device, profile=device.profile['channel%d_current_limit_read' % channel],
display_mode=display_mode, write_mode=write_mode
).add_update_callback(self._current_limit_updated))
def _voltage_range_updated(self, rf):
voltage_range = int(rf)
voltage = 100 if voltage_range == mhv4_v20_profile.VoltageRange.range_100v else 400
self.spin_target_voltage.setMaximum(voltage)
self.slider_target_voltage.setMaximum(voltage)
self.slider_target_voltage.setTickInterval(100 if voltage > 200.0 else 10)
self.label_upper_voltage_limit.setText(str(voltage) + " V")
def _current_updated(self, f_current):
def done(f_current_limit):
self._update_current_lcd_color(f_current, f_current_limit)
self.device.get_parameter('channel%d_current_limit_read' % self.channel
).add_done_callback(done)
def _current_limit_updated(self, f_current_limit):
def done(f_current):
self._update_current_lcd_color(f_current, f_current_limit)
self.device.get_parameter('channel%d_current_read' % self.channel
).add_done_callback(done)
def _update_current_lcd_color(self, f_current, f_current_limit):
# Set LCD color to red if current limit is exceeded
try:
limit = int(f_current_limit)
current = abs(int(f_current))
color = 'red' if current >= limit else 'black'
css = 'QLCDNumber { color: %s; }' % color
self.lcd_current.setStyleSheet(css)
except (KeyError, TypeError):
pass
@pyqtSlot(int)
idc = 17
device_class = MHV4_V20
device_ui_class = MHV4_V20_Widget
profile_dict = mhv4_v20_profile.profile_dict