def initialize(self, **kwargs): """Initialize the device and get the fan modes.""" with self._wake_device_context(): # Get Firmware res = self._send_command(_CMD_GET_FIRMWARE) fw_version = (res[3], res[4], res[5]) status = [('Firmware version', '{}.{}.{}'.format(*fw_version), '')] # Get LEDs per fan res = self._read_data(_MODE_LED_COUNT, _DATA_TYPE_LED_COUNT) num_devices = res[0] led_data = res[1:1 + num_devices * 4] for i in range(0, num_devices): connected = u16le_from(led_data, offset=i * 4) == 2 num_leds = u16le_from(led_data, offset=i * 4 + 2) label = 'AIO LED count' if i == 0 else f'RGB port {i} LED count' status += [(label, num_leds if connected else None, '')] # Get what fans are connected res = self._read_data(_MODE_CONNECTED_SPEEDS, _DATA_TYPE_CONNECTED_SPEEDS) num_devices = res[0] for i in range(0, num_devices): label = 'AIO port connected' if i == 0 else f'Fan port {i} connected' status += [(label, res[i + 1] == 0x07, '')] # Get what temp sensors are connected for i, temp in enumerate(self._get_temps()): connected = temp is not None label = 'Water temperature sensor' if i == 0 else f'Temperature sensor {i}' status += [(label, connected, '')] return status
def get_status(self, **kwargs): """Get a status report. Returns a list of `(property, value, unit)` tuples. """ res = self._send_command(_FEATURE_COOLING, _CMD_GET_STATUS) assert len(self._fan_names) == 2, f'cannot yet parse with {len(self._fan_names)} fans' return [ ('Liquid temperature', res[8] + res[7] / 255, '°C'), ('Fan 1 speed', u16le_from(res, offset=15), 'rpm'), ('Fan 2 speed', u16le_from(res, offset=22), 'rpm'), ('Pump speed', u16le_from(res, offset=29), 'rpm'), ]
def get_status(self, **kwargs): """Get a status report. Returns a list of `(property, value, unit)` tuples. """ res = self._send_command(_FEATURE_COOLING, _CMD_GET_STATUS) status = [ ('Liquid temperature', res[8] + res[7] / 255, '°C'), ('Pump speed', u16le_from(res, offset=29), 'rpm'), ] if len(self._fan_names) == 2: status.extend([ ('Fan 1 speed', u16le_from(res, offset=15), 'rpm'), ('Fan 2 speed', u16le_from(res, offset=22), 'rpm'), ]) elif len(self._fan_names) == 1: status.append(('Fan speed', u16le_from(res, offset=15), 'rpm'), ) else: assert False, f'unxpected {len(self._fan_names)} fans to parse' return status
def _get_speeds(self): speeds = [] res = self._read_data(_MODE_GET_SPEEDS, _DATA_TYPE_SPEEDS) num_speeds = res[0] speeds_data = res[1:1 + num_speeds * 2] for i in range(0, num_speeds): speeds.append(u16le_from(speeds_data, offset=i * 2)) return speeds
def get_status(self, **kwargs): """Get a status report. Returns a list of `(property, value, unit)` tuples. """ dataPackages = list() dataPackages.append(self._build_data_package(_COMMAND_TEMP_READ, _OP_CODE_READ_TWO_BYTES)) dataPackages.append(self._build_data_package(_COMMAND_FAN_SELECT, _OP_CODE_WRITE_ONE_BYTE, params=bytes([0]))) dataPackages.append(self._build_data_package(_COMMAND_FAN_READ_RPM, _OP_CODE_READ_TWO_BYTES)) dataPackages.append(self._build_data_package(_COMMAND_FAN_SELECT, _OP_CODE_WRITE_ONE_BYTE, params=bytes([1]))) dataPackages.append(self._build_data_package(_COMMAND_FAN_READ_RPM, _OP_CODE_READ_TWO_BYTES)) dataPackages.append(self._build_data_package(_COMMAND_FAN_SELECT, _OP_CODE_WRITE_ONE_BYTE, params=bytes([2]))) dataPackages.append(self._build_data_package(_COMMAND_FAN_READ_RPM, _OP_CODE_READ_TWO_BYTES)) res = self._send_command(dataPackages) temp = res[3] + res[2] / 255 return [ ('Liquid temperature', temp, '°C'), ('Fan 1 speed', u16le_from(res, offset=8), 'rpm'), ('Fan 2 speed', u16le_from(res, offset=14), 'rpm'), ('Pump speed', u16le_from(res, offset=20), 'rpm'), ]
def _get_temps(self): temps = [] res = self._read_data(_MODE_GET_TEMPS, _DATA_TYPE_TEMPS) num_temps = res[0] temp_data = res[1:1 + num_temps * 3] for i in range(0, num_temps): connected = temp_data[i * 3] == 0x00 if connected: temps.append(u16le_from(temp_data, offset=i * 3 + 1) / 10) else: temps.append(None) return temps
def write(self, data): data = bytes(data) # ensure data is convertible to bytes self._last_write = data if data[0] != 0x00 or data[1] != 0x08: raise ValueError('Start of packets going out should be 00:08') if data[2] == 0x0d: channel = data[3] if self._modes[channel] is None: self._modes[channel] = data[4:6] elif data[2] == 0x05 and data[3] == 0x01: self._modes[data[4]] = None elif data[2] == 0x01 and data[3] == 0x03 and data[4] == 0x00: self._awake = data[5] == 0x02 elif self._awake: if data[2] == 0x06: # Write command channel = data[3] mode = self._modes[channel] length = u16le_from(data[4:6]) data_type = data[8:10] written_data = data[10:8 + length] if mode[1] == 0x6d: if mode[0] == 0x60 and list(data_type) == [0x03, 0x00]: self.speeds_mode = tuple( written_data[i + 1] for i in range(0, written_data[0])) elif mode[0] == 0x61 and list(data_type) == [0x04, 0x00]: self.fixed_speeds = tuple( u16le_from(written_data[i * 2 + 1:i * 2 + 3]) for i in range(0, written_data[0])) else: raise NotImplementedError('Invalid Write command') else: raise NotImplementedError('Invalid Write command') return len(data)
def get_status(self, **kwargs): """Get a status report. Returns a list of `(property, value, unit)` tuples. """ res = self._send_command(_FEATURE_COOLING, _CMD_GET_STATUS) info = [ ('Liquid temperature', res[8] + res[7] / 255, '°C'), ] channels = [('Fan 1', 14), ('Fan 2', 21), ('Fan 3', 42)][:len(self._fan_names)] channels.append(('Pump', 28)) for name, base in channels: info.append((f'{name} speed', u16le_from(res, offset=base + 1), 'rpm')) info.append((f'{name} duty', round(res[base] / 255 * 100), '%')) return info