Example #1
0
def _prepare_profile(original, critcalTempature):
    clamped = ((temp, clamp(duty, 0, _MAX_FAN_RPM)) for temp, duty in original)
    normal = normalize_profile(clamped, critcalTempature, _MAX_FAN_RPM)
    missing = _PROFILE_LENGTH - len(normal)
    if missing < 0:
        raise ValueError(f'too many points in profile (remove {-missing})')
    if missing > 0:
        normal += missing * [(critcalTempature, _MAX_FAN_RPM)]
    return normal
Example #2
0
def _prepare_profile(original):
    clamped = ((temp, clamp(duty, 0, 100)) for temp, duty in original)
    normal = normalize_profile(clamped, _CRITICAL_TEMPERATURE)
    missing = _PROFILE_LENGTH - len(normal)
    if missing < 0:
        raise ValueError(f'too many points in profile (remove {-missing})')
    if missing > 0:
        normal += missing * [(_CRITICAL_TEMPERATURE, 100)]
    return normal
Example #3
0
 def set_speed_profile(self, channel, profile, **kwargs):
     """Set channel to use a speed profile."""
     if channel != 'pump':
         assert False, 'kraken X3 devices only support changing pump speeds'
     header = [0x72, 0x01, 0x00, 0x00]
     norm = normalize_profile(profile, _CRITICAL_TEMPERATURE)
     interp = [(interpolate_profile(norm, t)) for t in range(20, 60)]
     LOGGER.debug('setting pump curve: %s',
                  [(num + 20, duty) for (num, duty) in enumerate(interp)])
     self._write(header + interp)
Example #4
0
 def set_speed_profile(self, channel, profile, **kwargs):
     """Set channel to use a speed profile."""
     cid, dmin, dmax = self._speed_channels[channel]
     header = [0x72, cid, 0x00, 0x00]
     norm = normalize_profile(profile, _CRITICAL_TEMPERATURE)
     stdtemps = list(range(20, _CRITICAL_TEMPERATURE + 1))
     interp = [clamp(interpolate_profile(norm, t), dmin, dmax) for t in stdtemps]
     for temp, duty in zip(stdtemps, interp):
         _LOGGER.info('setting %s PWM duty to %d%% for liquid temperature >= %d°C',
                      channel, duty, temp)
     self._write(header + interp)
Example #5
0
def parse_profile(arg, mintemp=0, maxtemp=100, minduty=0, maxduty=100):
    """Parse, validate and normalize a temperature–duty profile.

    >>> parse_profile('(20,30),(30,50),(34,80),(40,90)', 0, 60, 25, 100)
    [(20, 30), (30, 50), (34, 80), (40, 90), (60, 100)]
    >>> parse_profile('35', 0, 60, 25, 100)
    [(0, 35), (59, 35), (60, 100)]

    The profile is validated in structure and acceptable ranges.  Duty is
    checked against `minduty` and `maxduty`.  Temperature must be between
    `mintemp` and `maxtemp`.

    >>> parse_profile('(20,30),(50,100', 0, 60, 25, 100)
    Traceback (most recent call last):
        ...
    ValueError: Profile must be comma-separated (temperature, duty) tuples
    >>> parse_profile('(20,30),(50,100,2)', 0, 60, 25, 100)
    Traceback (most recent call last):
        ...
    ValueError: Profile must be comma-separated (temperature, duty) tuples
    >>> parse_profile('(20,30),(50,97.6)', 0, 60, 25, 100)
    Traceback (most recent call last):
        ...
    ValueError: Duty must be integer number between 25 and 100
    >>> parse_profile('(20,15),(50,100)', 0, 60, 25, 100)
    Traceback (most recent call last):
        ...
    ValueError: Duty must be integer number between 25 and 100
    >>> parse_profile('(20,30),(70,100)', 0, 60, 25, 100)
    Traceback (most recent call last):
        ...
    ValueError: Temperature must be integer number between 0 and 60

    """
    try:
        val = ast.literal_eval('[' + arg + ']')
        if len(val) == 1 and isinstance(val[0], int):
            # for arg == '<number>' set fixed duty between mintemp and maxtemp - 1
            val = [(mintemp, val[0]), (maxtemp - 1, val[0])]
    except:
        raise ValueError('profile must be comma-separated (temperature, duty) tuples')
    for step in val:
        if not isinstance(step, tuple) or len(step) != 2:
            raise ValueError('profile must be comma-separated (temperature, duty) tuples')
        temp, duty = step
        if not isinstance(temp, int) or temp < mintemp or temp > maxtemp:
            raise ValueError('temperature must be integer between {} and {}'.format(mintemp, maxtemp))
        if not isinstance(duty, int) or duty < minduty or duty > maxduty:
            raise ValueError('duty must be integer between {} and {}'.format(minduty, maxduty))
    return normalize_profile(val, critx=maxtemp)
Example #6
0
 def set_speed_profile(self, channel, profile, **kwargs):
     """Set channel to use a speed profile."""
     if not self.supports_cooling_profiles:
         raise NotSupportedByDevice()
     norm = normalize_profile(profile, _CRITICAL_TEMPERATURE)
     # due to a firmware limitation the same set of temperatures must be
     # used on both channels; we reduce the number of writes by trimming the
     # interval and/or resolution to the most useful range
     stdtemps = list(range(20, 50)) + list(range(50, 60, 2)) + [60]
     interp = [(t, interpolate_profile(norm, t)) for t in stdtemps]
     cbase, dmin, dmax = _SPEED_CHANNELS[channel]
     for i, (temp, duty) in enumerate(interp):
         duty = clamp(duty, dmin, dmax)
         LOGGER.info('setting %s PWM duty to %i%% for liquid temperature >= %i°C',
                      channel, duty, temp)
         self._write([0x2, 0x4d, cbase + i, temp, duty])
Example #7
0
 def set_speed_profile(self, channel, profile, **kwargs):
     """Set channel to use a speed profile."""
     if not self.supports_cooling_profiles:
         raise NotImplementedError()
     cbase, dmin, dmax = _SPEED_CHANNELS[channel]
     # ideally we could just call normalize_profile (optionally followed by autofill_profile),
     # but Kraken devices currently require the same set of temperatures on both channels
     stdtemps = range(20, 62, 2)
     tmp = normalize_profile(profile, _CRITICAL_TEMPERATURE)
     norm = [(t, interpolate_profile(tmp, t)) for t in stdtemps]
     for i, (temp, duty) in enumerate(norm):
         duty = clamp(duty, dmin, dmax)
         LOGGER.info('setting %s PWM duty to %i%% for liquid temperature >= %i°C',
                      channel, duty, temp)
         self._write([0x2, 0x4d, cbase + i, temp, duty])
     self.device.release()