Exemplo n.º 1
0
    def set_lighting(self, values: list = None, mode=0x18, speed=0x00) -> None:
        """
        for the sake of performance this will assume the data your passing in is correct.
        if it isnt the worst that will happen (i guess) is the lights wont show up as
        expected.
        :param values: [r,g,b...]
        :param mode: lighting mode(hex)
        :param speed: light update speed(hex)
        """

        ## Reading https://github.com/MoshiMoshi0/ttrgbplusapi/blob/master/controllers/riing-trio.md
        ## It says the data sent to the controller for colors is:
        ## "For Riing Trio fans the COLORS (30 colors, 3 zones, 12+12+6) list is split in 2 chunks (19+11)"
        ## "CHUNK_ID indicates the chunk number starting from 1"
        ## Thus I need to send two lists, the first with 19 numbers, the second with 11.
        ##                                                                       v Chunk 1
        first_chunk = [
            PROTOCOL_SET, PROTOCOL_LIGHT, self.port, mode + speed, 3, 1, 0
        ]
        ##                                                                        v Chunk 2
        second_chunk = [
            PROTOCOL_SET, PROTOCOL_LIGHT, self.port, mode + speed, 3, 2, 0
        ]
        ## It is worth noting that I am still using the mode as defined in the riing plus, not the riing trio.
        ## This is probably wrong, but it is very late and I will poke at this after some soonze.
        ## Also, this actually seems to work.
        first_chunk.extend(values)
        second_chunk.extend(values)
        LOGGER.debug('{} set lighting: raw hex: {}'.format(
            self.__class__.__name__, first_chunk))
        self.controller.driver.write_out(first_chunk)
        LOGGER.debug('{} set lighting: raw hex: {}'.format(
            self.__class__.__name__, second_chunk))
        self.controller.driver.write_out(second_chunk)
    def __init__(self, config):
        self.points = config.get('points')
        self.sensor_name = config.get('sensor_name')
        LOGGER.debug(f'curve fan points: {self.points}')
        # ensure the curve starts at 0, 0
        has_zero = False
        for point in self.points:
            if point[0] == 0:
                has_zero = True

        if not has_zero:
            self.points.insert(0, [0, 0])

        self.points.sort(key=lambda s: s[0])

        temps = []
        speeds = []
        for set_ in self.points:
            temps.append(set_[0])
            speeds.append(set_[1])

        self._array = []

        # this involved alot of stack overflow and admittedly im not 100% sure how it works
        # basically given a set of points it extrapolates that into a line consisting of one
        # point per degree.
        x = np.asarray(temps)
        y = np.asarray(speeds)
        pch = pchip(x, y)
        xx = np.linspace(x[0], x[-1], x[-1])
        line2d = pyplot.plot(xx, pch(xx), 'g-')
        self.temps = line2d[0].get_xdata()
        self.speeds = line2d[0].get_ydata()
Exemplo n.º 3
0
 def stop(self):
     self._continue = False
     self.lighting_manager.stop()
     self.fan_manager.stop()
     self._thread.join()
     LOGGER.debug('saving controller profiles')
     for controller in self.controllers.values():
         controller.save_profile()
Exemplo n.º 4
0
    def register_attached_device(self, unit, port, dev=None):
        if isinstance(dev, devices.ThermaltakeFanDevice):
            LOGGER.debug('  registering %s with fan manager', dev.model)
            self.fan_manager.attach_device(dev)
        if isinstance(dev, devices.ThermaltakeRGBDevice):
            LOGGER.debug('  registering %s with lighting manager', dev.model)
            self.lighting_manager.attach_device(dev)

        self.attached_devices[f'{unit}:{port}'] = dev
Exemplo n.º 5
0
 def write_out(self, data: list, length: int = 64) -> list:
     output = list(data)
     try:
         ##output = self.endpoint_out.write(self._populate_partial_data_array(data, length))
         output = self.endpoint_out.write(
             self._populate_partial_data_array(data, length))
         LOGGER.debug('write_out returned: {}'.format(output))
         return output
     except OverflowError:
         return output
Exemplo n.º 6
0
 def factory(cls, unit_type, unit_identifier=None):
     subclass_dict = {clazz.model: clazz for clazz in cls.inheritors()}
     try:
         # TODO: remove copy pasta
         if unit_identifier is not None:
             return subclass_dict.get(unit_type.lower())(unit=unit_identifier)
         else:
             return subclass_dict.get(unit_type.lower())()
     except KeyError as e:
         LOGGER.warn('%s not a valid controller type', e)
    def start(self):
        values = []
        try:
            g, r, b = self._config['g'], self._config['r'], self._config['b']
            for i in range(12):
                values.extend([g, r, b])
        except KeyError as e:
            LOGGER.warn('%s not found in config item: lighting_controller', e)

        for device in self._devices:
            device.set_lighting(mode=RGB.Mode.FULL, speed=0x00, values=values)
Exemplo n.º 8
0
    def main(self):
        temp = self._get_temp()
        speed = (((temp - self.target) * self.multiplier) + self.last_speed) / 2

        if speed < 0:
            speed = 0
        elif speed > 100:
            speed = 100

        LOGGER.debug(f'Temperature is {temp}°C, setting fan speed to {speed}%')
        return speed
    def start(self):
        try:
            g, r, b = self._config['g'], self._config['r'], self._config['b']
        except KeyError as e:
            LOGGER.warn('%s not found in config item: lighting_controller', e)
            return

        for device in self._devices:
            device.set_lighting(mode=RGB.Mode.RIPPLE,
                                speed=self._speed,
                                values=[g, r, b])
Exemplo n.º 10
0
 def factory(cls, model, controller=None, port=None):
     subclass_dict = {
         clazz.model.lower(): clazz
         for clazz in cls.inheritors() if clazz.model is not None
     }
     try:
         dev = subclass_dict[model.lower()](controller, port)
         LOGGER.debug('created {} device'.format(dev.__class__.__name__))
         return dev
     except KeyError:
         LOGGER.warn(
             f'model {model} not found. controller: {controller} port: {port}'
         )
Exemplo n.º 11
0
    def load_config(self):
        with open('{}/{}'.format(self.config_dir,
                                 self.config_file_name)) as cfg:
            cfg_str = cfg.readlines()
        cfg_lines = []
        for s in cfg_str:
            # remove comments and blank lines
            if not s.strip().startswith('#') and len(s) > 1:
                cfg_lines.append(s)

        cfg = ''.join(cfg_lines)
        LOGGER.debug('raw config file\n** start **\n\n%s\n** end **\n', cfg)
        return yaml.load(cfg)
    def start(self):
        try:
            g, r, b = self._config['g'], self._config['r'], self._config['b']
        except KeyError as e:
            LOGGER.warn('%s not found in config item: lighting_controller', e)
            return

        for device in self._devices:
            values = []
            for i in range(12):
                values.extend([g, r, b])
            device.set_lighting(mode=RGB.Mode.PULSE,
                                speed=self._speed,
                                values=values)
Exemplo n.º 13
0
 def set_lighting(self, values: list = None, mode=0x18, speed=0x00) -> None:
     """
     for the sake of performance this will assume the data your passing in is correct.
     if it isnt the worst that will happen (i guess) is the lights wont show up as
     expected.
     :param values: [r,g,b...]
     :param mode: lighting mode(hex)
     :param speed: light update speed(hex)
     """
     data = [PROTOCOL_SET, PROTOCOL_LIGHT, self.port, mode + speed]
     if values:
         data.extend(values)
     LOGGER.debug(data)
     self.controller.driver.write_out(data)
Exemplo n.º 14
0
 def stop(self):
     LOGGER.debug('recieved exit command')
     self._continue = False
     LOGGER.debug('stopping lighting manager')
     self.lighting_manager.stop()
     LOGGER.debug('stopping fan manager')
     self.fan_manager.stop()
     LOGGER.debug('saving controller profiles')
     for controller in self.controllers.values():
         controller.save_profile()
Exemplo n.º 15
0
    def _initialize_device(self):
        self.device = usb.core.find(idVendor=self.vendor_id,
                                    idProduct=self.product_id)
        # fail safe incase last device usage was dirty
        self.device.reset()

        if self.device is None:
            raise ValueError('Device not found')

        # Linux kernel sets up a device driver for USB device, which you have
        # to detach. Otherwise trying to interact with the device gives a
        # 'Resource Busy' error.
        try:
            self.device.detach_kernel_driver(0)
        except Exception:
            LOGGER.warning('kernel driver already detached')

        self.device.set_configuration()

        # claim the device
        try:
            usb.util.claim_interface(self.device, 0)
        except usb.core.USBError as e:
            LOGGER.error('{} while claiming interface for device'.format(e))
            raise e

        self.cfg = self.device.get_active_configuration()
        self.interface = self.cfg[(0, 0)]
        self.endpoint_out = usb.util.find_descriptor(
            self.interface,
            custom_match=lambda e: usb.util.endpoint_direction(
                e.bEndpointAddress) == usb.util.ENDPOINT_OUT)
        assert self.endpoint_out is not None

        self.endpoint_in = usb.util.find_descriptor(
            self.interface,
            custom_match=lambda e: usb.util.endpoint_direction(
                e.bEndpointAddress) == usb.util.ENDPOINT_IN)
        assert self.endpoint_in is not None

        # initialize/reset the device
        self.init_controller()
Exemplo n.º 16
0
 def parse_config(self, config):
     self.controllers = config.get('controllers')
     LOGGER.debug(config.get('controllers'))
     # self.devices = config.get('devices')
     LOGGER.debug(config.get('fan_manager'))
     self.fan_manager = config.get('fan_manager')
     LOGGER.debug(config.get('lighting_manager'))
     self.lighting_manager = config.get('lighting_manager')
Exemplo n.º 17
0
    def __init__(self, config):
        self.points = np.array(config.get('points'))
        self.temps = self.points[:, 0]
        self.speeds = self.points[:, 1]
        self.sensor_name = config.get('sensor_name')
        LOGGER.debug(f'curve fan points: {self.points}')

        if np.min(self.speeds) < 0:
            raise ValueError(
                f'Fan curve contains negative speeds, speed should be in [0,100]'
            )
        if np.max(self.speeds) > 100:
            raise ValueError(
                f'Fan curve contains speeds greater than 100, speed should be in [0,100]'
            )
        if np.any(np.diff(self.temps) <= 0):
            raise ValueError(
                f'Fan curve points should be strictly monotonically increasing, configuration error ?'
            )
        if np.any(np.diff(self.speeds) < 0):
            raise ValueError(
                f'Curve fan speeds should be monotonically increasing, configuration error ?'
            )
Exemplo n.º 18
0
 def _main_loop(self):
     LOGGER.debug(f'entering {self.__class__.__name__} main loop')
     while self._continue:
         speed = self._model.main()
         LOGGER.debug(f'new fan speed {speed}')
         for dev in self._devices:
             dev.set_fan_speed(speed)
         time.sleep(1)
     LOGGER.debug(f'exiting {self.__class__.__name__} main loop')
Exemplo n.º 19
0
    def test_basic_startup(self, init_dev):
        LOGGER.setLevel(logging.DEBUG)
        stream = StringIO()
        stream_handler = logging.StreamHandler(stream)
        # stream_handler = logging.StreamHandler(sys.stdout)

        LOGGER.addHandler(stream_handler)
        try:
            daemon = ThermaltakeDaemon()
        finally:
            stream_handler.flush()
            LOGGER.removeHandler(stream_handler)
        self.assertIsNotNone(daemon)
        self.assertIsNotNone(daemon.config.controllers)
        self.assertTrue(init_dev.called)

        logging_output = stream.getvalue()
        print(logging_output)
        for keyword in ('** start **', '** end **'):
            self.assertIn(keyword, logging_output)
Exemplo n.º 20
0
    def __init__(self):
        # if we have config in /etc, use it, otherwise try and use repository config file
        if os.path.isdir(self.abs_config_dir):
            if os.path.isfile(
                    os.path.join(self.abs_config_dir, self.config_file_name)):
                self.config_dir = self.abs_config_dir
        elif os.path.isdir(self.rel_config_dir):
            if os.path.isfile(
                    os.path.join(self.rel_config_dir, self.config_file_name)):
                self.config_dir = self.rel_config_dir

        with open('{}/{}'.format(self.config_dir,
                                 self.config_file_name)) as cfg:
            config = yaml.load(cfg)
            self.controllers = config.get('controllers')
            LOGGER.debug(config.get('controllers'))
            # self.devices = config.get('devices')
            LOGGER.debug(config.get('fan_manager'))
            self.fan_manager = config.get('fan_manager')
            LOGGER.debug(config.get('lighting_manager'))
            self.lighting_manager = config.get('lighting_manager')
 def factory(cls, config):
     subclass_dict = {clazz.model: clazz for clazz in cls.inheritors()}
     try:
         return subclass_dict.get(config.pop('model').lower())(config)
     except KeyError as e:
         LOGGER.warn('%s not found in config item', e)
 def __init__(self, config):
     self._config = config
     self._devices = []
     LOGGER.info(f'initializing {self.__class__.__name__} light controller')
Exemplo n.º 23
0
 def start(self):
     LOGGER.info(f'Starting fan manager ({self._model})...')
     self._continue = True
     self._thread.start()
Exemplo n.º 24
0
 def start(self):
     LOGGER.info(f'Starting lighting manager ({self._controller})...')
     self._continue = True
     self._thread.start()
Exemplo n.º 25
0
 def main(self):
     LOGGER.debug(f'Setting fan speed to {self.speed}%')
     return self.speed
Exemplo n.º 26
0
 def run(self):
     self._continue = True
     LOGGER.debug('starting lighting manager')
     self.lighting_manager.start()
     LOGGER.debug('starting fan manager')
     self.fan_manager.start()
Exemplo n.º 27
0
 def stop(self):
     LOGGER.info(f'Stopping lighting manager...')
     self._continue = False
     self._thread.join()
Exemplo n.º 28
0
    def __init__(self):
        LOGGER.info('initializing thermaltake rgb daemon')

        LOGGER.debug('loading config')
        self.config = Config()

        LOGGER.debug('creating fan manager')
        fan_model = FanModel.factory(self.config.fan_manager)
        self.fan_manager = FanManager(fan_model)

        LOGGER.debug('creating lighting manager')
        self.lighting_manager = LightingEffect.factory(
            self.config.lighting_manager)

        self.attached_devices = {}
        self.controllers = {}

        LOGGER.debug('configuring controllers')
        for controller in self.config.controllers:
            self.controllers[
                controller['unit']] = ThermaltakeController.factory(
                    controller['type'], controller.get('unit'))
            for id, model in controller['devices'].items():
                LOGGER.debug(' configuring devices for controller %s: %s',
                             controller['type'], controller.get('unit'))
                dev = ThermaltakeDevice.factory(
                    model, self.controllers[controller['unit']], id)
                self.controllers[controller['unit']].attach_device(id, dev)
                self.register_attached_device(controller['unit'], id, dev)

        self._continue = False
Exemplo n.º 29
0
from linux_thermaltake_rgb.globals import RGB
import time

logging.basicConfig(stream=sys.stdout,
                    level=logging.DEBUG,
                    format='%(message)s')

self_config = Config()
self_lighting_manager = LightingEffect.factory(self_config.lighting_manager)
self_fan_manager = None

self_attached_devices = {}
self_controllers = {}

self_attached_devices = {}
LOGGER.debug('configuring controllers')
for controller in self_config.controllers:
    self_controllers[controller['unit']] = ThermaltakeController.factory(
        controller['type'], controller.get('unit'))
    for id, model in controller['devices'].items():
        dev = ThermaltakeDevice.factory(model,
                                        self_controllers[controller['unit']],
                                        id)
        self_controllers[controller['unit']].attach_device(id, dev)

        if isinstance(dev, devices.ThermaltakeFanDevice) and self_fan_manager:
            LOGGER.debug('  registering %s with fan manager', dev.model)
            self_fan_manager.attach_device(dev)
        if isinstance(dev,
                      devices.ThermaltakeRGBDevice) and self_lighting_manager:
            LOGGER.debug('  registering %s with lighting manager', dev.model)
Exemplo n.º 30
0
 def factory(cls, model, controller, port):
     subclass_dict = {clazz.model.lower(): clazz for clazz in cls.inheritors() if clazz.model is not None}
     try:
         return subclass_dict[model.lower()](controller, port)
     except KeyError:
         LOGGER.warn(f'model {model} not found. controller: {controller} port: {port}')