kraken3: add LCD screen support for Kraken Z coolers (#479)
Closes: #444
This commit is contained in:
parent
a2b4391408
commit
f455e3f446
|
@ -62,7 +62,9 @@ jobs:
|
|||
hidapi \
|
||||
pytest \
|
||||
pyusb \
|
||||
pillow \
|
||||
"libusb-package; sys_platform == 'win32' or sys_platform == 'cygwin'" \
|
||||
"winusbcdc; sys_platform == 'win32'" \
|
||||
"smbus; sys_platform == 'linux'"
|
||||
|
||||
- name: Run unit tests and module doctests
|
||||
|
|
|
@ -123,7 +123,7 @@ subjective "from more to less liquid control-ly" order.
|
|||
| AIO liquid cooler | [NZXT Kraken X31, X41, X61](docs/asetek-690lc-guide.md) | USB | <sup>_LZ_</sup> |
|
||||
| AIO liquid cooler | [NZXT Kraken X42, X52, X62, X72](docs/kraken-x2-m2-guide.md) | USB HID | <sup>_h_</sup> |
|
||||
| AIO liquid cooler | [NZXT Kraken X53, X63, X73](docs/kraken-x3-z3-guide.md) | USB HID | <sup>_h_</sup> |
|
||||
| AIO liquid cooler | [NZXT Kraken Z53, Z63, Z73](docs/kraken-x3-z3-guide.md) | USB & USB HID | <sup>_p_</sup> |
|
||||
| AIO liquid cooler | [NZXT Kraken Z53, Z63, Z73](docs/kraken-x3-z3-guide.md) | USB & USB HID | |
|
||||
| Pump controller | [Aquacomputer D5 Next](docs/aquacomputer-d5next-guide.md) | USB HID | <sup>_ehnp_</sup> |
|
||||
| Fan/LED controller | [Aquacomputer Octo](docs/aquacomputer-octo-guide.md) | USB HID | <sup>_ehnp_</sup> |
|
||||
| Fan/LED controller | [Aquacomputer Quadro](docs/aquacomputer-quadro-guide.md) | USB HID | <sup>_ehnp_</sup> |
|
||||
|
@ -406,9 +406,14 @@ already installed on the environment (virtual or global), manually install
|
|||
them:
|
||||
|
||||
```
|
||||
python -m pip install --upgrade colorlog docopt hidapi pytest pyusb setuptools setuptools_scm
|
||||
python -m pip install --upgrade colorlog docopt hidapi pytest pyusb setuptools setuptools_scm pillow
|
||||
python -m pip install --upgrade "libusb-package; sys_platform == 'win32' or sys_platform == 'cygwin'"
|
||||
python -m pip install --upgrade "smbus; sys_platform == 'linux'"
|
||||
|
||||
```
|
||||
For KrakenZ devices only
|
||||
```
|
||||
python -m pip install --upgrade "winusbcdc; sys_platform == 'win32'"
|
||||
```
|
||||
|
||||
At this point, the environment is set up. To run the test suite, execute:
|
||||
|
|
|
@ -21,8 +21,6 @@ The most notable difference between Kraken X and Kraken Z models is the replacem
|
|||
|
||||
In addition to this, Kraken Z coolers restore the embedded fan controller that is missing from the current Kraken X models.
|
||||
|
||||
The LCD screen cannot yet be controlled with liquidctl, but all other hardware capabilities are supported.
|
||||
|
||||
|
||||
## Initialization
|
||||
|
||||
|
@ -158,8 +156,16 @@ they will be removed in a future version and are kept for now for backward compa
|
|||
|
||||
## The LCD screen (only Z models)
|
||||
|
||||
To be implemented.
|
||||
Liquidctl supports the following functions for controlling the lcd screen
|
||||
|
||||
```
|
||||
liquidctl [options] set lcd screen liquid
|
||||
liquidctl [options] set lcd screen brightness <value>
|
||||
liquidctl [options] set lcd screen orientation (0|90|180|270)
|
||||
liquidctl [options] set lcd screen (static|gif) <path to image>
|
||||
```
|
||||
|
||||
images and GiFs are automatically resized and rotated to match the device orientation so there is no need for any preprocessing
|
||||
|
||||
## Interaction with Linux hwmon drivers
|
||||
[Linux hwmon]: #interaction-with-linux-hwmon-drivers
|
||||
|
|
|
@ -7,6 +7,7 @@ Usage:
|
|||
liquidctl [options] set <channel> speed (<temperature> <percentage>) ...
|
||||
liquidctl [options] set <channel> speed <percentage>
|
||||
liquidctl [options] set <channel> color <mode> [<color>] ...
|
||||
liquidctl [options] set <channel> screen <mode> [<value>]
|
||||
liquidctl --help
|
||||
liquidctl --version
|
||||
|
||||
|
@ -279,6 +280,8 @@ def _device_set_color(dev, args, **opts):
|
|||
color = map(color_from_str, args['<color>'])
|
||||
dev.set_color(args['<channel>'].lower(), args['<mode>'].lower(), color, **opts)
|
||||
|
||||
def _device_set_screen(dev, args, **opts):
|
||||
dev.set_screen(args["<channel>"], args["<mode>"], args["<value>"], **opts)
|
||||
|
||||
def _device_set_speed(dev, args, **opts):
|
||||
if len(args['<temperature>']) > 0:
|
||||
|
@ -468,6 +471,8 @@ def main():
|
|||
_device_set_speed(dev, args, **opts)
|
||||
elif args['set'] and args['color']:
|
||||
_device_set_color(dev, args, **opts)
|
||||
elif args['set'] and args['screen']:
|
||||
_device_set_screen(dev, args, **opts)
|
||||
else:
|
||||
assert False, 'unreachable'
|
||||
except OSError as err:
|
||||
|
|
|
@ -186,6 +186,10 @@ class _Base690Lc(UsbDriver):
|
|||
|
||||
super().disconnect(**kwargs)
|
||||
|
||||
def set_screen(self, channel, mode, value, **kwargs):
|
||||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice()
|
||||
|
||||
|
||||
class _ModernBase690Lc(_Base690Lc):
|
||||
|
||||
|
@ -427,7 +431,7 @@ class Legacy690Lc(_Base690Lc):
|
|||
|
||||
def set_speed_profile(self, channel, profile, **kwargs):
|
||||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice
|
||||
raise NotSupportedByDevice()
|
||||
|
||||
|
||||
class Hydro690Lc(_ModernBase690Lc):
|
||||
|
|
|
@ -257,6 +257,10 @@ class HydroPro(_Base690Lc):
|
|||
else:
|
||||
raise ValueError(f'unknown channel: {channel}')
|
||||
|
||||
def set_screen(self, channel, mode, value, **kwargs):
|
||||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice()
|
||||
|
||||
@classmethod
|
||||
def probe(cls, handle, **kwargs):
|
||||
return super().probe(handle, **kwargs)
|
||||
|
|
|
@ -343,3 +343,7 @@ class AuraLed(UsbHidDriver):
|
|||
def _write(self, data):
|
||||
padding = [0x0] * (_WRITE_LENGTH - len(data))
|
||||
self.device.write(data + padding)
|
||||
|
||||
def set_screen(self, channel, mode, value, **kwargs):
|
||||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice()
|
||||
|
|
|
@ -92,6 +92,11 @@ class BaseDriver:
|
|||
|
||||
raise NotImplementedError()
|
||||
|
||||
def set_screen(self, channel, mode, value, **kwargs):
|
||||
"""Set the screen mode and content."""
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
def set_speed_profile(self, channel, profile, **kwargs):
|
||||
"""Set channel to follow a speed duty profile."""
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import logging
|
|||
from contextlib import contextmanager
|
||||
|
||||
from liquidctl.driver.usb import UsbHidDriver
|
||||
from liquidctl.error import ExpectationNotMet, NotSupportedByDriver
|
||||
from liquidctl.error import ExpectationNotMet, NotSupportedByDriver, NotSupportedByDevice
|
||||
from liquidctl.util import clamp, u16le_from
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -274,3 +274,7 @@ class CommanderCore(UsbHidDriver):
|
|||
if self._has_pump:
|
||||
fan_names.insert(0, "pump")
|
||||
raise ValueError(f'unknown channel, should be one of: "{fan_names_part}" or "fans"')
|
||||
|
||||
def set_screen(self, channel, mode, value, **kwargs):
|
||||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice
|
||||
|
|
|
@ -561,3 +561,7 @@ class CommanderPro(UsbHidDriver):
|
|||
self.device.write(buf)
|
||||
buf = bytes(self.device.read(_RESPONSE_LENGTH))
|
||||
return buf
|
||||
|
||||
def set_screen(self, channel, mode, value, **kwargs):
|
||||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice()
|
||||
|
|
|
@ -296,6 +296,10 @@ class CorsairHidPsu(UsbHidDriver):
|
|||
secs = int.from_bytes(self._exec(WriteBit.READ, command)[2:], byteorder='little')
|
||||
return timedelta(seconds=secs)
|
||||
|
||||
def set_screen(self, channel, mode, value, **kwargs):
|
||||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice()
|
||||
|
||||
|
||||
# deprecated aliases
|
||||
CorsairHidPsuDriver = CorsairHidPsu
|
||||
|
|
|
@ -261,6 +261,10 @@ class Ddr4Temperature(SmbusDriver):
|
|||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice()
|
||||
|
||||
def set_screen(self, channel, mode, value, **kwargs):
|
||||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice()
|
||||
|
||||
|
||||
class VengeanceRgb(Ddr4Temperature):
|
||||
"""Corsair Vengeance RGB DDR4 module."""
|
||||
|
|
|
@ -20,6 +20,7 @@ import re
|
|||
from enum import Enum, unique
|
||||
|
||||
from liquidctl.driver.usb import UsbHidDriver
|
||||
from liquidctl.error import NotSupportedByDevice
|
||||
from liquidctl.keyval import RuntimeStorage
|
||||
from liquidctl.pmbus import compute_pec
|
||||
from liquidctl.util import RelaxedNamesEnum, clamp, fraction_of_byte, \
|
||||
|
@ -420,3 +421,7 @@ class HydroPlatinum(UsbHidDriver):
|
|||
self._send_command(_FEATURE_COOLING2, _CMD_SET_COOLING, data=data2)
|
||||
|
||||
return self._send_command(_FEATURE_COOLING, _CMD_SET_COOLING, data=data)
|
||||
|
||||
def set_screen(self, channel, mode, value, **kwargs):
|
||||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice()
|
||||
|
|
|
@ -291,6 +291,10 @@ class Kraken2(UsbHidDriver):
|
|||
padding = [0x0]*(_WRITE_LENGTH - len(data))
|
||||
self.device.write(data + padding)
|
||||
|
||||
def set_screen(self, channel, mode, value, **kwargs):
|
||||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice()
|
||||
|
||||
|
||||
# deprecated aliases
|
||||
KrakenTwoDriver = Kraken2
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -304,6 +304,10 @@ class EvgaPascal(SmbusDriver, _NvidiaI2CDriver):
|
|||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice()
|
||||
|
||||
def set_screen(self, channel, mode, value, **kwargs):
|
||||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice()
|
||||
|
||||
|
||||
class RogTuring(SmbusDriver, _NvidiaI2CDriver):
|
||||
"""NVIDIA series 10 (Pascal) or 20 (Turing) graphics card from ASUS."""
|
||||
|
@ -533,3 +537,7 @@ class RogTuring(SmbusDriver, _NvidiaI2CDriver):
|
|||
def set_fixed_speed(self, channel, duty, **kwargs):
|
||||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice()
|
||||
|
||||
def set_screen(self, channel, mode, value, **kwargs):
|
||||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice()
|
||||
|
|
|
@ -145,6 +145,10 @@ class NzxtEPsu(UsbHidDriver):
|
|||
ascam_ver = int.from_bytes(bytes.fromhex(human_ver), byteorder='big')
|
||||
return (human_ver, ascam_ver)
|
||||
|
||||
def set_screen(self, channel, mode, value, **kwargs):
|
||||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice()
|
||||
|
||||
|
||||
# deprecated aliases
|
||||
SeasonicEDriver = NzxtEPsu
|
||||
|
|
|
@ -243,6 +243,10 @@ class RgbFusion2(UsbHidDriver):
|
|||
"""Request for the previously sent lighting settings to be applied."""
|
||||
self._send_feature_report([_REPORT_ID, 0x28, 0xff])
|
||||
|
||||
def set_screen(self, channel, mode, value, **kwargs):
|
||||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice()
|
||||
|
||||
|
||||
# Acknowledgments:
|
||||
#
|
||||
|
|
|
@ -198,6 +198,10 @@ class _BaseSmartDevice(UsbHidDriver):
|
|||
def _write_fixed_duty(self, cid, duty):
|
||||
raise NotImplementedError()
|
||||
|
||||
def set_screen(self, channel, mode, value, **kwargs):
|
||||
"""Not supported by this device."""
|
||||
raise NotSupportedByDevice()
|
||||
|
||||
|
||||
class SmartDevice(_BaseSmartDevice):
|
||||
"""NZXT Smart Device (V1) or Grid+ V3."""
|
||||
|
|
|
@ -41,7 +41,6 @@ extend-exclude = '''
|
|||
| (^/liquidctl/driver/ddr4\.py$)
|
||||
| (^/liquidctl/driver/hydro_platinum\.py$)
|
||||
| (^/liquidctl/driver/kraken2\.py$)
|
||||
| (^/liquidctl/driver/kraken3\.py$)
|
||||
| (^/liquidctl/driver/nvidia\.py$)
|
||||
| (^/liquidctl/driver/nzxt_epsu\.py$)
|
||||
| (^/liquidctl/driver/rgb_fusion2\.py$)
|
||||
|
@ -72,6 +71,7 @@ extend-exclude = '''
|
|||
| (^/tests/test_hydro_platinum\.py$)
|
||||
| (^/tests/test_keyval\.py$)
|
||||
| (^/tests/test_kraken2\.py$)
|
||||
| (^/tests/test_krakenz3_response\.py$)
|
||||
| (^/tests/test_nvidia\.py$)
|
||||
| (^/tests/test_nzxt_epsu\.py$)
|
||||
| (^/tests/test_rgb_fusion2\.py$)
|
||||
|
|
|
@ -47,7 +47,9 @@ install_requires =
|
|||
docopt
|
||||
hidapi
|
||||
pyusb
|
||||
pillow
|
||||
libusb-package; sys_platform == 'win32' or sys_platform == 'cygwin'
|
||||
winusbcdc; sys_platform == 'win32'
|
||||
smbus; sys_platform == "linux"
|
||||
|
||||
[options.entry_points]
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 6.1 KiB |
|
@ -1,7 +1,9 @@
|
|||
# uses the psf/black style
|
||||
|
||||
import pytest
|
||||
from _testutils import MockHidapiDevice, Report
|
||||
import os
|
||||
|
||||
from _testutils import MockHidapiDevice, MockPyusbDevice, Report
|
||||
|
||||
from liquidctl.driver.hwmon import HwmonDevice
|
||||
from liquidctl.driver.kraken3 import KrakenX3, KrakenZ3
|
||||
|
@ -11,6 +13,8 @@ from liquidctl.driver.kraken3 import (
|
|||
_COLOR_CHANNELS_KRAKENZ,
|
||||
_SPEED_CHANNELS_KRAKENZ,
|
||||
)
|
||||
from test_krakenz3_response import krakenz3_response
|
||||
|
||||
from liquidctl.util import HUE2_MAX_ACCESSORIES_IN_CHANNEL as MAX_ACCESSORIES
|
||||
from liquidctl.util import Hue2Accessory
|
||||
|
||||
|
@ -44,7 +48,7 @@ def mock_krakenx3():
|
|||
@pytest.fixture
|
||||
def mock_krakenz3():
|
||||
raw = MockKraken(raw_led_channels=1)
|
||||
dev = KrakenZ3(
|
||||
dev = MockKrakenZ3(
|
||||
raw,
|
||||
"Mock Kraken Z73",
|
||||
speed_channels=_SPEED_CHANNELS_KRAKENZ,
|
||||
|
@ -70,10 +74,74 @@ class MockKraken(MockHidapiDevice):
|
|||
if self.raw_led_channels > 1:
|
||||
reply[15 + 1 * MAX_ACCESSORIES] = Hue2Accessory.KRAKENX_GEN4_RING.value
|
||||
reply[15 + 2 * MAX_ACCESSORIES] = Hue2Accessory.KRAKENX_GEN4_LOGO.value
|
||||
elif data[0:2] == [0x30, 0x01]:
|
||||
reply[0:2] = [0x31, 0x01]
|
||||
reply[0x18] = 50 # lcd brightness
|
||||
reply[0x1A] = 0 # lcd orientation
|
||||
elif data[0:2] == [0x32, 0x1]: # setup bucket
|
||||
reply[14] = 0x1
|
||||
elif data[0:2] == [0x32, 0x2]: # delete bucker
|
||||
reply[0:2] = [0x33, 0x02]
|
||||
reply[14] = 0x1
|
||||
elif data[0:2] == [0x38, 0x1]: # switch bucket
|
||||
reply[14] = 0x1
|
||||
|
||||
self.preload_read(Report(0, reply))
|
||||
return super().write(data)
|
||||
|
||||
|
||||
class MockKrakenZ3(KrakenZ3):
|
||||
def __init__(self, device, description, speed_channels, color_channels, **kwargs):
|
||||
KrakenX3.__init__(self, device, description, speed_channels, color_channels, **kwargs)
|
||||
|
||||
self.bulk_device = MockPyusbDevice(0x1E71, 0x3008)
|
||||
self.bulk_device.close_winusb_device = self.bulk_device.release
|
||||
|
||||
self.orientation = 0
|
||||
self.brightness = 50
|
||||
|
||||
self.screen_mode = None
|
||||
|
||||
def set_screen(self, channel, mode, value, **kwargs):
|
||||
self.screen_mode = mode
|
||||
self.hid_data_index = 0
|
||||
self.bulk_data_index = 0
|
||||
|
||||
super().set_screen(channel, mode, value, **kwargs)
|
||||
|
||||
assert self.hid_data_index == len(
|
||||
krakenz3_response[self.screen_mode + "_hid"]
|
||||
), f"Incorrect number of hid messages sent for mode: {mode}"
|
||||
|
||||
if mode == "static" or mode == "gif":
|
||||
assert (
|
||||
self.bulk_data_index == 801
|
||||
if mode == "static"
|
||||
else len(krakenz3_response[self.screen_mode + "_bulk"])
|
||||
), f"Incorrect number of bulk messages sent for mode: {mode}"
|
||||
|
||||
def _write(self, data):
|
||||
if self.screen_mode:
|
||||
assert (
|
||||
data == krakenz3_response[self.screen_mode + "_hid"][self.hid_data_index]
|
||||
), f"HID write failed, wrong data for mode: {self.screen_mode}, data index: {self.hid_data_index}"
|
||||
self.hid_data_index += 1
|
||||
return super()._write(data)
|
||||
|
||||
def _bulk_write(self, data):
|
||||
fixed_data_index = self.bulk_data_index
|
||||
if (
|
||||
self.screen_mode == "static" and self.bulk_data_index > 1
|
||||
): # the rest of the message should be identical to index 1
|
||||
fixed_data_index = 1
|
||||
|
||||
assert (
|
||||
data == krakenz3_response[self.screen_mode + "_bulk"][fixed_data_index]
|
||||
), f"Bulk write failed, wrong data for mode: {self.screen_mode}, data index: {self.bulk_data_index}"
|
||||
self.bulk_data_index += 1
|
||||
return super()._bulk_write(data)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("has_hwmon,direct_access", [(False, False), (True, True), (True, False)])
|
||||
def test_krakenx3_initializes(mock_krakenx3, has_hwmon, direct_access, tmp_path):
|
||||
if has_hwmon:
|
||||
|
@ -142,3 +210,14 @@ def test_krakenz3_not_totally_broken(mock_krakenz3):
|
|||
_ = mock_krakenz3.get_status()
|
||||
mock_krakenz3.set_speed_profile(channel="fan", profile=iter([(20, 20), (30, 50), (40, 100)]))
|
||||
mock_krakenz3.set_fixed_speed(channel="pump", duty=50)
|
||||
|
||||
# set_screen should be the last set of functions called
|
||||
mock_krakenz3.set_screen("lcd", "liquid", None)
|
||||
mock_krakenz3.set_screen("lcd", "brightness", "60")
|
||||
mock_krakenz3.set_screen("lcd", "orientation", "90")
|
||||
mock_krakenz3.set_screen(
|
||||
"lcd", "static", os.path.join(os.path.dirname(os.path.abspath(__file__)), "yellow.jpg")
|
||||
)
|
||||
mock_krakenz3.set_screen(
|
||||
"lcd", "gif", os.path.join(os.path.dirname(os.path.abspath(__file__)), "rgb.gif")
|
||||
)
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
krakenz3_response = {
|
||||
"liquid_hid": [[48, 1], [56, 1, 2, 0]],
|
||||
"brightness_hid": [[48, 1], [48, 2, 1, 60, 0, 0, 1, 0]],
|
||||
"orientation_hid": [[48, 1], [48, 2, 1, 50, 0, 0, 1, 1]],
|
||||
"static_hid": [
|
||||
[48, 1],
|
||||
[54, 3],
|
||||
[48, 4, 0],
|
||||
[48, 4, 1],
|
||||
[48, 4, 2],
|
||||
[48, 4, 3],
|
||||
[48, 4, 4],
|
||||
[48, 4, 5],
|
||||
[48, 4, 6],
|
||||
[48, 4, 7],
|
||||
[48, 4, 8],
|
||||
[48, 4, 9],
|
||||
[48, 4, 10],
|
||||
[48, 4, 11],
|
||||
[48, 4, 12],
|
||||
[48, 4, 13],
|
||||
[48, 4, 14],
|
||||
[48, 4, 15],
|
||||
[32, 3],
|
||||
[116, 1],
|
||||
[112, 1],
|
||||
[116, 1],
|
||||
[50, 2, 0],
|
||||
[50, 1, 0, 1, 0, 0, 144, 1, 1],
|
||||
[54, 1, 0],
|
||||
[54, 2],
|
||||
[56, 1, 4, 0],
|
||||
],
|
||||
"gif_hid": [[48,1],
|
||||
[54,3],
|
||||
[48,4,0],
|
||||
[48,4,1],
|
||||
[48,4,2],
|
||||
[48,4,3],
|
||||
[48,4,4],
|
||||
[48,4,5],
|
||||
[48,4,6],
|
||||
[48,4,7],
|
||||
[48,4,8],
|
||||
[48,4,9],
|
||||
[48,4,10],
|
||||
[48,4,11],
|
||||
[48,4,12],
|
||||
[48,4,13],
|
||||
[48,4,14],
|
||||
[48,4,15],
|
||||
[32,3],
|
||||
[116,1],
|
||||
[112,1],
|
||||
[116,1],
|
||||
[50,2,0],
|
||||
[50,1,0,1,0,0,2,0,1],
|
||||
[54,1,0],
|
||||
[54,2],
|
||||
[56,1,4,0]],
|
||||
"static_bulk": [
|
||||
[18,250,1,232,171,205,239,152,118,84,50,16,2,0,0,0,0,64,6],
|
||||
[255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0,255,255,1,0]],
|
||||
"gif_bulk": [
|
||||
[18,250,1,232,171,205,239,152,118,84,50,16,1,0,0,0,189,6,0],
|
||||
[71,73,70,56,57,97,64,1,64,1,129,3,0,255,0,0,0,0,0,0,0,0,0,0,0,33,255,11,78,69,84,83,67,65,80,69,50,46,48,3,1,0,0,0,44,0,0,0,0,64,1,64,1,0,8,255,0,1,8,28,72,176,160,193,131,8,19,42,92,200,176,161,195,135,16,35,74,156,72,177,162,197,139,24,51,106,220,200,177,163,199,143,32,67,138,28,73,178,164,201,147,40,83,170,92,201,178,165,203,151,48,99,202,156,73,179,166,205,155,56,115,234,220,201,179,167,207,159,64,131,10,29,74,180,168,209,163,72,147,42,93,202,180,169,211,167,80,163,74,157,74,181,170,213,171,88,179,106,221,202,181,171,215,175,96,195,138,29,75,182,172,217,179,104,211,170,93,203,182,173,219,183,112,227,202,157,75,183,174,221,187,120,243,234,221,203,183,175,223,191,128,3,11,30,76,184,176,225,195,136,19,43,94,204,184,177,227,199,144,35,75,158,76,185,178,229,203,152,51,107,222,204,185,179,231,207,160,67,139,30,77,186,180,233,211,168,83,171,94,205,186,181,235,215,176,99,203,158,77,187,182,237,219,184,115,235,222,205,187,183,239,223,192,131,11,31,78,188,184,241,227,200,147,43,95,206,188,185,243,231,208,163,75,159,78,189,186,245,235,216,179,107,223,206,189,187,247,239,224,195,139,255,31,79,190,188,249,243,232,211,171,95,207,190,189,251,247,240,227,203,159,79,191,190,253,251,248,243,235,223,207,191,191,255,255,0,6,40,224,128,4,22,104,224,129,8,38,168,224,130,12,54,232,224,131,16,70,40,225,132,20,86,104,225,133,24,102,168,225,134,28,118,232,225,135,32,134,40,226,136,36,150,104,226,137,40,166,168,226,138,44,182,232,226,139,48,198,40,227,140,52,214,104,227,141,56,230,168,227,142,60,246,232,227,143,64,6,41,228,144,68,22,105,228,145,72,38,169,228,146,76,54,233,228,147,80,70,41,229,148,84,86,105,229,149,88,102,169,229,150,92,118,233,229,151,96,134,41,230,152,100,150,105,230,153,104,166,169,230,154,108,182,233,230,155,112,198,41,231,156,116,214,105,231,157,120,230,169,231,158,124,246,233,231,159,128,6,42,232,160,132,22],
|
||||
[106,232,161,136,38,170,232,162,140,54,234,232,163,144,70,42,233,164,148,86,106,233,165,152,102,170,233,166,156,118,234,233,167,160,134,42,234,168,164,150,106,234,169,168,166,170,234,170,172,182,234,234,171,176,198,27,42,235,172,180,214,106,235,173,184,230,170,235,174,188,246,234,235,175,192,6,43,236,176,196,90,20,16,0,44,0,0,0,0,64,1,64,1,129,0,255,0,0,0,0,0,0,0,0,0,0,8,255,0,1,8,28,72,176,160,193,131,8,19,42,92,200,176,161,195,135,16,35,74,156,72,177,162,197,139,24,51,106,220,200,177,163,199,143,32,67,138,28,73,178,164,201,147,40,83,170,92,201,178,165,203,151,48,99,202,156,73,179,166,205,155,56,115,234,220,201,179,167,207,159,64,131,10,29,74,180,168,209,163,72,147,42,93,202,180,169,211,167,80,163,74,157,74,181,170,213,171,88,179,106,221,202,181,171,215,175,96,195,138,29,75,182,172,217,179,104,211,170,93,203,182,173,219,183,112,227,202,157,75,183,174,221,187,120,243,234,221,203,183,175,223,191,128,3,11,30,76,184,176,225,195,136,19,43,94,204,184,177,227,199,144,35,75,158,76,185,178,229,203,152,51,107,222,204,185,179,231,207,160,67,139,30,77,186,180,233,211,168,83,171,94,205,186,181,235,215,176,99,203,158,77,187,182,237,219,184,115,235,222,205,187,183,239,223,192,131,11,31,78,188,184,241,227,200,147,43,95,206,188,185,243,231,208,163,75,159,78,189,186,245,235,216,179,107,223,206,189,187,247,239,224,195,139,255,31,79,190,188,249,243,232,211,171,95,207,190,189,251,247,240,227,203,159,79,191,190,253,251,248,243,235,223,207,191,191,255,255,0,6,40,224,128,4,22,104,224,129,8,38,168,224,130,12,54,232,224,131,16,70,40,225,132,20,86,104,225,133,24,102,168,225,134,28,118,232,225,135,32,134,40,226,136,36,150,104,226,137,40,166,168,226,138,44,182,232,226,139,48,198,40,227,140,52,214,104,227,141,56,230,168,227,142,60,246,232,227,143,64,6,41,228,144,68,22,105,228,145,72,38,169,228,146,76,54,233,228,147,80,70,41,229,148,84,86,105,229,149,88,102,169,229,150],
|
||||
[92,118,233,229,151,96,134,41,230,152,100,150,105,230,153,104,166,169,230,154,108,182,233,230,155,112,198,41,231,156,116,214,105,231,157,120,230,169,231,158,124,246,233,231,159,128,6,42,232,160,132,22,106,232,161,136,38,170,232,162,140,54,234,232,163,144,70,42,233,164,148,86,106,233,165,152,102,170,233,166,156,118,234,233,167,160,134,42,234,168,164,150,106,234,169,168,166,170,234,170,172,182,234,234,171,176,198,27,42,235,172,180,214,106,235,173,184,230,170,235,174,188,246,234,235,175,192,6,43,236,176,196,90,20,16,0,44,0,0,0,0,64,1,64,1,129,0,0,255,0,0,0,0,0,0,0,0,0,8,255,0,1,8,28,72,176,160,193,131,8,19,42,92,200,176,161,195,135,16,35,74,156,72,177,162,197,139,24,51,106,220,200,177,163,199,143,32,67,138,28,73,178,164,201,147,40,83,170,92,201,178,165,203,151,48,99,202,156,73,179,166,205,155,56,115,234,220,201,179,167,207,159,64,131,10,29,74,180,168,209,163,72,147,42,93,202,180,169,211,167,80,163,74,157,74,181,170,213,171,88,179,106,221,202,181,171,215,175,96,195,138,29,75,182,172,217,179,104,211,170,93,203,182,173,219,183,112,227,202,157,75,183,174,221,187,120,243,234,221,203,183,175,223,191,128,3,11,30,76,184,176,225,195,136,19,43,94,204,184,177,227,199,144,35,75,158,76,185,178,229,203,152,51,107,222,204,185,179,231,207,160,67,139,30,77,186,180,233,211,168,83,171,94,205,186,181,235,215,176,99,203,158,77,187,182,237,219,184,115,235,222,205,187,183,239,223,192,131,11,31,78,188,184,241,227,200,147,43,95,206,188,185,243,231,208,163,75,159,78,189,186,245,235,216,179,107,223,206,189,187,247,239,224,195,139,255,31,79,190,188,249,243,232,211,171,95,207,190,189,251,247,240,227,203,159,79,191,190,253,251,248,243,235,223,207,191,191,255,255,0,6,40,224,128,4,22,104,224,129,8,38,168,224,130,12,54,232,224,131,16,70,40,225,132,20,86,104,225,133,24,102,168,225,134,28,118,232,225,135,32,134,40,226,136,36,150,104,226,137,40,166,168,226,138,44,182,232,226,139,48,198,40],
|
||||
[227,140,52,214,104,227,141,56,230,168,227,142,60,246,232,227,143,64,6,41,228,144,68,22,105,228,145,72,38,169,228,146,76,54,233,228,147,80,70,41,229,148,84,86,105,229,149,88,102,169,229,150,92,118,233,229,151,96,134,41,230,152,100,150,105,230,153,104,166,169,230,154,108,182,233,230,155,112,198,41,231,156,116,214,105,231,157,120,230,169,231,158,124,246,233,231,159,128,6,42,232,160,132,22,106,232,161,136,38,170,232,162,140,54,234,232,163,144,70,42,233,164,148,86,106,233,165,152,102,170,233,166,156,118,234,233,167,160,134,42,234,168,164,150,106,234,169,168,166,170,234,170,172,182,234,234,171,176,198,27,42,235,172,180,214,106,235,173,184,230,170,235,174,188,246,234,235,175,192,6,43,236,176,196,90,20,16,0,59]]
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
Loading…
Reference in New Issue