def test_initialize_lighting_node(lightingNodeProDevice): responses = [ '000009d4000000000000000000000000', # firmware '00000500000000000000000000000000' # bootloader ] for d in responses: lightingNodeProDevice.device.preload_read(Report(0, bytes.fromhex(d))) res = lightingNodeProDevice.initialize() assert len(res) == 2 assert res[0][1] == '0.9.212' assert res[1][1] == '0.5' data = lightingNodeProDevice._data.load('fan_modes', None) assert data is None data = lightingNodeProDevice._data.load('temp_sensors_connected', None) assert data is None
def test_set_color_hardware_direction_default(commanderProDevice): ignore = Report(0, bytes(16)) for _ in range(6): commanderProDevice.device.preload_read(ignore) colors = [[0xaa, 0xbb, 0xcc]] commanderProDevice.set_color('led1', 'fixed', colors) # check the commands sent sent = commanderProDevice.device.sent assert len(sent) == 5 assert sent[3].data[0] == 0x35 assert sent[3].data[6] == 0x01 effects = commanderProDevice._data.load('saved_effects', default=None) assert effects is not None assert len(effects) == 1
def test_set_speed_profile_valid_unconfigured(commanderProDevice): responses = [ '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000' ] for d in responses: commanderProDevice.device.preload_read(Report(0, bytes.fromhex(d))) commanderProDevice._data.store('temp_sensors_connected', [0x00, 0x00, 0x00, 0x00]) commanderProDevice._data.store('fan_modes', [0x01, 0x00, 0x01, 0x01, 0x00, 0x00]) with pytest.raises(ValueError): commanderProDevice.set_speed_profile('fan2', [(10, 500), (20, 1000)]) # check the commands sent sent = commanderProDevice.device.sent assert len(sent) == 0
def test_set_speed_profile_lighting(lightingNodeProDevice): responses = [ '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000' ] for d in responses: lightingNodeProDevice.device.preload_read(Report(0, bytes.fromhex(d))) lightingNodeProDevice._data.store('temp_sensors_connected', [0x01, 0x00, 0x00, 0x00]) lightingNodeProDevice._data.store('fan_modes', [0x01, 0x00, 0x01, 0x01, 0x00, 0x00]) with pytest.raises(NotSupportedByDevice): lightingNodeProDevice.set_speed_profile('sync', [(10, 500), (20, 1000)]) # check the commands sent sent = lightingNodeProDevice.device.sent assert len(sent) == 0
def test_set_color_hardware_invalid_mode(commanderProDevice): responses = [ '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000' ] for d in responses: commanderProDevice.device.preload_read(Report(0, bytes.fromhex(d))) colors = [[0xaa, 0xbb, 0xcc]] with pytest.raises(ValueError): commanderProDevice.set_color('led1', 'invalid', colors) # check the commands sent sent = commanderProDevice.device.sent assert len(sent) == 0 effects = commanderProDevice._data.load('saved_effects', default=None) assert effects is None
def test_set_color_hardware_multipe_commands(commanderProDevice): responses = [ '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000' ] for d in responses: commanderProDevice.device.preload_read(Report(0, bytes.fromhex(d))) effect = { 'channel': 0x01, 'start_led': 0x00, 'num_leds': 0x0f, 'mode': 0x0a, 'speed': 0x00, 'direction': 0x00, 'random_colors': 0x00, 'colors': [0xaa, 0xbb, 0xcc] } commanderProDevice._data.store('saved_effects', [effect]) commanderProDevice.set_color('led1', 'fixed', [[0x00, 0x11, 0x22]], start_led=16, maximum_leds=5) # check the commands sent sent = commanderProDevice.device.sent assert len(sent) == 6 assert sent[3].data[0] == 0x35 assert sent[4].data[0] == 0x35 effects = commanderProDevice._data.load('saved_effects', default=None) assert effects is not None assert len(effects) == 2
def test_set_color_hardware_channel(commanderProDevice, channel, expected): ignore = Report(0, bytes(16)) for _ in range(6): commanderProDevice.device.preload_read(ignore) colors = [[0xaa, 0xbb, 0xcc]] commanderProDevice.set_color(channel, 'fixed', colors) # check the commands sent sent = commanderProDevice.device.sent assert len(sent) == 5 assert sent[0].data[1] == expected assert sent[1].data[1] == expected assert sent[2].data[1] == expected assert sent[3].data[0] == 0x35 assert sent[3].data[1] == expected effects = commanderProDevice._data.load('saved_effects', default=None) assert effects is not None assert len(effects) == 1
def test_set_color_hardware_too_few_colors(commanderProDevice): ignore = Report(0, bytes(16)) for _ in range(6): commanderProDevice.device.preload_read(ignore) commanderProDevice.set_color('led1', 'fixed', []) # check the commands sent sent = commanderProDevice.device.sent assert len(sent) == 5 assert sent[3].data[0] == 0x35 assert sent[3].data[7] == 0x01 assert sent[3].data[9] == 0x00 assert sent[3].data[10] == 0x00 assert sent[3].data[11] == 0x00 effects = commanderProDevice._data.load('saved_effects', default=None) assert effects is not None assert len(effects) == 1
def test_reads_status_directly(mock_smart2, has_hwmon, direct_access): if has_hwmon: mock_smart2._hwmon = HwmonDevice(None, None) mock_smart2.device.preload_read(Report(0, SAMPLE_STATUS)) expected = [ ("Fan 1 speed", 1020, "rpm"), ("Fan 1 duty", 50, "%"), ("Fan 1 control mode", "PWM", ""), ("Fan 2 speed", 0, "rpm"), ("Fan 2 duty", 40, "%"), ("Fan 2 control mode", None, ""), ("Fan 3 speed", 0, "rpm"), ("Fan 3 duty", 40, "%"), ("Fan 3 control mode", None, ""), ("Noise level", 48, "dB"), ] got = mock_smart2.get_status(direct_access=direct_access) assert sorted(got) == sorted(expected)
def test_set_speed_profile_valid(commanderProDevice): ignore = Report(0, bytes(16)) for _ in range(5): commanderProDevice.device.preload_read(ignore) commanderProDevice._data.store('temp_sensors_connected', [0x01, 0x01, 0x00, 0x01]) commanderProDevice._data.store('fan_modes', [0x01, 0x00, 0x01, 0x01, 0x00, 0x00]) commanderProDevice.set_speed_profile('fan3', [(10, 500), (20, 1000)]) # check the commands sent sent = commanderProDevice.device.sent assert len(sent) == 1 assert sent[0].data[0] == 0x25 assert sent[0].data[1] == 0x02 assert sent[0].data[2] == 0x00 assert sent[0].data[3] == 0x03 assert sent[0].data[4] == 0xe8 assert sent[0].data[15] == 0x01 assert sent[0].data[16] == 0xf4
def test_set_color_hardware_valid_mode(commanderProDevice, modeStr, expected): responses = [ '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000' ] for d in responses: commanderProDevice.device.preload_read(Report(0, bytes.fromhex(d))) commanderProDevice.set_color('led1', modeStr, []) # check the commands sent sent = commanderProDevice.device.sent assert len(sent) == 5 assert sent[3].data[0] == 0x35 assert sent[3].data[4] == expected effects = commanderProDevice._data.load('saved_effects', default=None) assert effects is not None assert len(effects) == 1
def test_set_color_hardware_too_many_colors(commanderProDevice): ignore = Report(0, bytes(16)) for _ in range(6): commanderProDevice.device.preload_read(ignore) colors = [[0xaa, 0xbb, 0xcc], [0x00, 0x11, 0x22], [0x33, 0x44, 0x55]] commanderProDevice.set_color('led1', 'fixed', colors) # check the commands sent sent = commanderProDevice.device.sent assert len(sent) == 5 assert sent[3].data[0] == 0x35 assert sent[3].data[7] == 0x00 assert sent[3].data[9] == 0xaa assert sent[3].data[10] == 0xbb assert sent[3].data[11] == 0xcc effects = commanderProDevice._data.load('saved_effects', default=None) assert effects is not None assert len(effects) == 1
def test_set_color_hardware_num_leds(commanderProDevice, numLED, expected): ignore = Report(0, bytes(16)) for _ in range(6): commanderProDevice.device.preload_read(ignore) colors = [[0xaa, 0xbb, 0xcc]] commanderProDevice.set_color('led1', 'fixed', colors, start_led=1, maximum_leds=numLED) # check the commands sent sent = commanderProDevice.device.sent assert len(sent) == 5 assert sent[3].data[0] == 0x35 assert sent[3].data[3] == expected # num leds effects = commanderProDevice._data.load('saved_effects', default=None) assert effects is not None assert len(effects) == 1
def test_set_color_hardware_off(commanderProDevice): responses = [ '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000' ] effect = { 'channel': 0x01, 'start_led': 0x00, 'num_leds': 0x0F, 'mode': 0x0A, 'speed': 0x00, 'direction': 0x00, 'random_colors': 0x00, 'colors': [] } commanderProDevice._data.store('saved_effects', [effect]) for d in responses: commanderProDevice.device.preload_read(Report(0, bytes.fromhex(d))) commanderProDevice.set_color('led1', 'off', []) # check the commands sent sent = commanderProDevice.device.sent assert len(sent) == 5 assert sent[3].data[0] == 0x35 assert sent[3].data[4] == 0x04 effects = commanderProDevice._data.load('saved_effects', default=None) assert effects == None
def test_set_color_hardware_random_color(commanderProDevice): responses = [ '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000' ] for d in responses: commanderProDevice.device.preload_read(Report(0, bytes.fromhex(d))) colors = [] commanderProDevice.set_color('led1', 'fixed', colors) # check the commands sent sent = commanderProDevice.device.sent assert len(sent) == 5 assert sent[3].data[0] == 0x35 assert sent[3].data[7] == 0x01 effects = commanderProDevice._data.load('saved_effects', default=None) assert effects is not None assert len(effects) == 1
def test_set_color_hardware_speed(commanderProDevice, speedStr, expected): responses = [ '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000' ] for d in responses: commanderProDevice.device.preload_read(Report(0, bytes.fromhex(d))) colors = [[0xaa, 0xbb, 0xcc]] commanderProDevice.set_color('led1', 'fixed', colors, speed=speedStr) # check the commands sent sent = commanderProDevice.device.sent assert len(sent) == 5 assert sent[3].data[0] == 0x35 assert sent[3].data[5] == expected effects = commanderProDevice._data.load('saved_effects', default=None) assert effects is not None assert len(effects) == 1
def test_set_speed_profile_valid_multi_fan(commanderProDevice): responses = [ '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000', '00000000000000000000000000000000' ] for d in responses: commanderProDevice.device.preload_read(Report(0, bytes.fromhex(d))) commanderProDevice._data.store('temp_sensors_connected', [0x01, 0x01, 0x00, 0x01]) commanderProDevice._data.store('fan_modes', [0x01, 0x00, 0x01, 0x01, 0x00, 0x00]) commanderProDevice.set_speed_profile('sync', [(10, 500), (20, 1000)]) # check the commands sent sent = commanderProDevice.device.sent assert len(sent) == 3 assert sent[0].data[0] == 0x25 assert sent[0].data[1] == 0x00 assert sent[0].data[2] == 0x00 assert sent[0].data[3] == 0x03 assert sent[0].data[4] == 0xe8 assert sent[0].data[15] == 0x01 assert sent[0].data[16] == 0xf4 assert sent[1].data[0] == 0x25 assert sent[1].data[1] == 0x02 assert sent[1].data[2] == 0x00 assert sent[2].data[0] == 0x25 assert sent[2].data[1] == 0x03 assert sent[2].data[2] == 0x00
def test_initialize_commander_pro(commanderProDevice, has_hwmon, direct_access, tmp_path): if has_hwmon and not direct_access: commanderProDevice._hwmon = HwmonDevice('mock_module', tmp_path) (tmp_path / 'temp1_input').write_text('10000\n') (tmp_path / 'temp2_input').write_text('20000\n') (tmp_path / 'temp4_input').write_text('40000\n') (tmp_path / 'fan1_input').write_text('1100\n') (tmp_path / 'fan1_label').write_text('fan1 3pin\n') (tmp_path / 'fan2_input').write_text('1200\n') (tmp_path / 'fan2_label').write_text('fan1 3pin\n') (tmp_path / 'fan3_input').write_text('1300\n') (tmp_path / 'fan3_label').write_text('fan1 4pin\n') else: if has_hwmon: commanderProDevice._hwmon = HwmonDevice('invalid_module', None) responses = [ '000009d4000000000000000000000000', # firmware '00000500000000000000000000000000', # bootloader '00010100010000000000000000000000', # temp probes '00010102000000000000000000000000' # fan probes ] for d in responses: commanderProDevice.device.preload_read(Report(0, bytes.fromhex(d))) res = commanderProDevice.initialize(direct_access=direct_access) if has_hwmon and not direct_access: assert len(res) == 10 i = 0 else: assert len(res) == 12 assert res[0] == ('Firmware version', '0.9.212', '') assert res[1] == ('Bootloader version', '0.5', '') i = 2 assert res[i + 0] == ('Temperature probe 1', True, '') assert res[i + 1] == ('Temperature probe 2', True, '') assert res[i + 2] == ('Temperature probe 3', False, '') assert res[i + 3] == ('Temperature probe 4', True, '') assert res[i + 4] == ('Fan 1 control mode', 'DC', '') assert res[i + 5] == ('Fan 2 control mode', 'DC', '') assert res[i + 6] == ('Fan 3 control mode', 'PWM', '') assert res[i + 7] == ('Fan 4 control mode', None, '') assert res[i + 8] == ('Fan 5 control mode', None, '') assert res[i + 9] == ('Fan 6 control mode', None, '') data = commanderProDevice._data.load('fan_modes', None) assert data is not None assert len(data) == 6 assert data[0] == 0x01 assert data[1] == 0x01 assert data[2] == 0x02 assert data[3] == 0x00 assert data[4] == 0x00 assert data[5] == 0x00 data = commanderProDevice._data.load('temp_sensors_connected', None) assert data is not None assert len(data) == 4 assert data[0] == 0x01 assert data[1] == 0x01 assert data[2] == 0x00 assert data[3] == 0x01
import pytest from _testutils import MockHidapiDevice, Report from collections import deque from liquidctl.driver.aura_led import AuraLed # Sample data for Aura LED controller from Asus ProArt Z690-Creator WiFi _INIT_19AF_FIRMWARE_DATA = bytes.fromhex( 'ec0241554c41332d415233322d30323037000000000000000000000000000000' '000000000000000000000000000000000000000000000000000000000000000000' ) _INIT_19AF_FIRMWARE = Report(_INIT_19AF_DATA[0], _INIT_19AF_DATA[1:]) _INIT_19AF_CONFIG_DATA = bytes.fromhex( 'ec3000001e9f03010000783c00010000783c00010000783c0000000000000001' '040201f40000000000000000000000000000000000000000000000000000000000' ) _INIT_19AF_CONFIG = Report(_INIT_19AF_CONFIG_DATA[0], _INIT_19AF_CONFIG_DATA[1:]) @pytest.fixture def mockAuraLed_19AFDevice(): device = MockHidapiDevice(vendor_id=0x0b05, product_id=0x19af, address='addr') dev = AuraLed(device, 'mock Aura LED Controller') dev.connect() return dev def test_aura_led_19AF_device_command_format(mockAuraLed_19AFDevice):
def test_kracken_x_device_warns_if_faulty_temperature(mockKrakenXDevice, caplog): mockKrakenXDevice.device.preload_read(Report(0, _FAULTY_STATUS)) mockKrakenXDevice.get_status() assert 'unexpected temperature reading' in caplog.text
def test_warns_if_faulty_temperature(self): self.mock_hid.preload_read(Report(0, _FAULTY_STATUS)) with self.assertLogs(level='WARNING') as cm: self.device.get_status() self.assertIn('unexpected temperature reading', ''.join(cm.output))
def write(self, data): reply = bytearray(64) if data[1] in [_CORSAIR_12V_OCP_MODE, _CORSAIR_FAN_CONTROL_MODE]: reply[2] = 1 # just a valid mode self.preload_read(Report(0, reply)) # ignore report ID for now
def test_parses_status_fields(self): self.mock_hid.preload_read(Report(0, _SAMPLE_STATUS)) temperature, pump_speed, pump_duty = self.device.get_status() assert temperature == ('Liquid temperature', 33.1, '°C') assert pump_speed == ('Pump speed', 1704, 'rpm') assert pump_duty == ('Pump duty', 53, '%')
def test_get_status_commander_pro(commanderProDevice, has_hwmon, direct_access, tmp_path): if has_hwmon and not direct_access: commanderProDevice._hwmon = HwmonDevice('mock_module', tmp_path) (tmp_path / 'temp1_input').write_text('26910\n') (tmp_path / 'temp2_input').write_text('29220\n') (tmp_path / 'temp4_input').write_text('25740\n') (tmp_path / 'fan1_input').write_text('940\n') (tmp_path / 'fan1_label').write_text('fan1 3pin\n') (tmp_path / 'fan2_input').write_text('939\n') (tmp_path / 'fan2_label').write_text('fan1 3pin\n') (tmp_path / 'fan3_input').write_text('987\n') (tmp_path / 'fan3_label').write_text('fan1 4pin\n') (tmp_path / 'in0_input').write_text('12066\n') (tmp_path / 'in1_input').write_text('4965\n') (tmp_path / 'in2_input').write_text('3359\n') else: if has_hwmon: commanderProDevice._hwmon = HwmonDevice('invalid_module', None) responses = [ '000a8300000000000000000000000000', # temp sensor 1 '000b6a00000000000000000000000000', # temp sensor 2 '000a0e00000000000000000000000000', # temp sensor 4 '0003ac00000000000000000000000000', # fan speed 1 '0003ab00000000000000000000000000', # fan speed 2 '0003db00000000000000000000000000', # fan speed 3 '002f2200000000000000000000000000', # get 12v '00136500000000000000000000000000', # get 5v '000d1f00000000000000000000000000', # get 3.3v ] for d in responses: commanderProDevice.device.preload_read(Report(0, bytes.fromhex(d))) commanderProDevice._data.store('fan_modes', [0x01, 0x01, 0x02, 0x00, 0x00, 0x00]) commanderProDevice._data.store('temp_sensors_connected', [0x01, 0x01, 0x00, 0x01]) res = commanderProDevice.get_status(direct_access=direct_access) print(res) assert len(res) == 9 # temp probes assert res[0] == ('Temperature 1', pytest.approx(26.91, abs=1e-3), '°C') assert res[1] == ('Temperature 2', pytest.approx(29.22, abs=1e-3), '°C') assert res[2] == ('Temperature 4', pytest.approx(25.74, abs=1e-3), '°C') # fans rpm assert res[3] == ('Fan 1 speed', 940, 'rpm') assert res[4] == ('Fan 2 speed', 939, 'rpm') assert res[5] == ('Fan 3 speed', 987, 'rpm') # voltages assert res[6] == ('+12V rail', pytest.approx(12.066, abs=1e-3), 'V') assert res[7] == ('+5V rail', pytest.approx(4.965, abs=1e-3), 'V') assert res[8] == ('+3.3V rail', pytest.approx(3.359, abs=1e-3), 'V') if not has_hwmon or direct_access: # check the commands sent sent = commanderProDevice.device.sent assert len(sent) == 9 assert sent[0].data[0] == 0x11 assert sent[1].data[0] == 0x11 assert sent[2].data[0] == 0x11 assert sent[3].data[0] == 0x21 assert sent[4].data[0] == 0x21 assert sent[5].data[0] == 0x21 assert sent[6].data[0] == 0x12 assert sent[7].data[0] == 0x12 assert sent[8].data[0] == 0x12
def test_kracken_x_device_parses_status_fields(mockKrakenXDevice): mockKrakenXDevice.device.preload_read(Report(0, _SAMPLE_STATUS)) temperature, pump_speed, pump_duty = mockKrakenXDevice.get_status() assert temperature == ('Liquid temperature', 33.1, '°C') assert pump_speed == ('Pump speed', 1704, 'rpm') assert pump_duty == ('Pump duty', 53, '%')
def test_dont_inject_report_ids(self): status = self.device.get_status() get_fw = self.mock_hid.sent[0] assert get_fw == Report(0, [0xad, 0, 3, 1, 0x60, 0xfc] + 58 * [0])
import pytest from collections import deque from liquidctl.driver.rgb_fusion2 import RgbFusion2 from _testutils import MockHidapiDevice, Report # Sample data for 5702 controller from a Gigabyte Z490 Vision D # https://github.com/liquidctl/liquidctl/issues/151#issuecomment-663213956 _INIT_5702_DATA = bytes.fromhex( 'cc01000701000a00000000004954353730322d47494741425954452056312e30' '2e31302e30000000000102000200010002000100000102000001025700000000') _INIT_5702_SAMPLE = Report(_INIT_5702_DATA[0], _INIT_5702_DATA[1:]) # Sample data for 8297 controller from a Gigabyte X570 Aorus Elite rev 1.0 # https://github.com/liquidctl/liquidctl/issues/151#issuecomment-663247422 # (note: original data had a trailing 0x61 byte, but that seems to be an artifact) _INIT_8297_DATA = bytes.fromhex( '00010001010006000000000049543832393742582d4742583537300000000000' '0000000000000000000000000200010002000100000102000001978200000000') _INIT_8297_SAMPLE = Report(_INIT_8297_DATA[0], _INIT_8297_DATA[1:]) @pytest.fixture def mockRgbFusion2_5702Device(): device = MockHidapiDevice(vendor_id=0x048d, product_id=0x5702, address='addr') dev = RgbFusion2(device, 'mock 5702 Controller') dev.connect() return dev