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()
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): 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
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()
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
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
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 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}' )
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 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)
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()
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() LOGGER.debug('Configuration of usb device: {}'.format(self.cfg)) 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) LOGGER.debug('endpoint_out is {}'.format(self.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()
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')
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 ?' )
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')
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 __init__(self, initial_model: FanModel = None): self._continue = False self._thread = Thread(target=self._main_loop) self._devices = [] self._model = initial_model LOGGER.debug(f'creating FanManager object: [model: {initial_model}]')
def set_controller(self, model: FanModel): LOGGER.debug(f'setting fan model: {model.__class__.__name__}') if isinstance(model, FanModel): LOGGER.debug(f'SUCCESS: set fan model: {model.__class__.__name__}') self._model = model
def main(self): LOGGER.debug(f'Setting fan speed to {self.speed}%') return self.speed
def run(self): self._continue = True LOGGER.debug('starting lighting manager') self.lighting_manager.start() LOGGER.debug('starting fan manager') self.fan_manager.start()
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)