Lian Li wireless fan tools

Proof-of-concept tools for the Lian Li UNI FAN SL-INF Wireless kit (SLV3 TX 0416:8040, RX 0416:8041). Protocol from sgtaziz/lian-li-linux (MIT); compression is tinyuz (MIT).

Only one program can use a dongle at a time: quit SignalRGB (it holds the TX) and L-Connect before running anything that opens the TX.

File What it does
lianli_poc.py scan / color RRGGBB / demo. Needs pip install --user pyusb libusb-package.
tuzc.exe tinyuz compressor used by lianli_poc.py (stdin to stdout, round-trip checked).
tuzd.exe reference tinyuz decoder, tuzd <size>, used by the tests.
tuz.js JavaScript tinyuz encoder (same code is inlined in the plugin).
LianLi_Wireless_SLINF_PoC.js SignalRGB plugin source. Installed copy: Documents\WhirlwindFX\Plugins.
test/tuz_test.js node test/tuz_test.js: JS encoder vs reference decoder, no hardware.
test/js_tuz_on_fan.py sends JS-compressed frames to the fan (needs TX free).
test/watch_rx.py python test/watch_rx.py [seconds]: watches the fan's effect id via the RX only; works while SignalRGB runs.
build-src/ sources for tuzc.exe / tuzd.exe.

Using it with SignalRGB

SignalRGB has no support for the wireless Lian Li kits. LianLi_Wireless_SLINF_PoC.js is a custom plugin that drives one SL-INF wireless fan through the TX dongle.

1. Pair the fan

The fan must already be bound to your TX dongle. This is done once in L-Connect 3; after that L-Connect can be uninstalled or must at least stay closed while SignalRGB runs.

2. Find your fan's address

Quit SignalRGB first (it holds the TX dongle), then:

python lianli_poc.py scan
TX master 16:e5:90:62:32:dc  channel 8  firmware 16
RX hears 1 device(s):
  device e8:b5:62:62:32:e1  SL-INF Wireless x1
    bound to this TX: yes   channel 8  rx slot 1

Copy the device address, the rx slot and the fan count (x1) into the top of the plugin:

const FAN_MAC = [0xe8, 0xb5, 0x62, 0x62, 0x32, 0xe1];
const FAN_RX_SLOT = 1;
const FAN_COUNT = 1;

The values in the repo are for the original fan; a different or re-paired fan needs new values.

3. Install the plugin

Copy the plugin into SignalRGB's user plugin folder and restart SignalRGB (it only loads plugins at startup):

cp LianLi_Wireless_SLINF_PoC.js "$USERPROFILE/Documents/WhirlwindFX/Plugins/"

The fan shows up as Lian Li SL-INF Wireless (PoC). Place and resize it on the Layouts page so it sits where the fan is in your case.

4. Settings

Setting Default What it does
Lighting Mode Canvas Canvas follows the active effect, Forced shows Forced Color.
Forced Color #009bde Colour used in Forced mode.
Shutdown Color #8000ff Colour the fan keeps after SignalRGB closes or the PC shuts down.
Update Interval (ms) 200 Minimum time between uploads to the fan (100–2000).

Limitations

  • Every colour change is a full compressed upload over the 2.4 GHz link, so the fan updates a few times per second at most. Static colours and slow effects look fine; fast and audio effects step.
  • Frames are only sent when the colours actually change.
  • The 44 LEDs per fan are mapped as three rings (centre 8, inner 10, outer 8), mirrored on both sides of the fan.
  • One fan group only, at the address set in the plugin. There is no discovery: a SignalRGB plugin can open only one USB device, and fan discovery needs the RX dongle.
  • While SignalRGB runs, lianli_poc.py and test/js_tuz_on_fan.py can't open the TX dongle.

Troubleshooting

  • Fan not listed: check SignalRGB's log in %LOCALAPPDATA%\WhirlwindFX\SignalRgb\Logs for Custom Plugin File Loaded and for errors from the 0416:8040 engine thread.
  • Listed but the fan doesn't change: run python test/watch_rx.py 10 while SignalRGB runs. A new effect id appearing every second or so means uploads are reaching the fan. If the id never changes, the address in the plugin is probably wrong or L-Connect has the dongle.
  • Back to normal: delete the plugin from Documents\WhirlwindFX\Plugins and restart SignalRGB. The fan keeps the Shutdown Color until something else sets it.

Rebuilding tuzc.exe / tuzd.exe

Clone https://github.com/sisong/tinyuz and https://github.com/sisong/HDiffPatch into build-src/, then with MinGW g++:

cd build-src
F="-O2 -DNDEBUG -D_HPATCH_IS_USED_MULTITHREAD=0 -D_IS_USED_MULTITHREAD=0 -IHDiffPatch/libParallel"
gcc $F -c tinyuz/decompress/tuz_dec.c -o tuz_dec.o
g++ $F -static -o ../tuzc.exe tuzc_main.cpp tuz_wrapper.cpp tuz_dec.o tinyuz/compress/tuz_enc.cpp tinyuz/compress/tuz_enc_private/*.cpp HDiffPatch/libHDiffPatch/HDiff/private_diff/libdivsufsort/divsufsort.cpp -x c HDiffPatch/libHDiffPatch/HPatch/patch.c
gcc -O2 -D_IS_RUN_MEM_SAFE_CHECK=1 -o ../tuzd.exe tuzd_main.c tinyuz/decompress/tuz_dec.c
S
Description
No description provided
Readme
252 KiB
0 Stars 1 Watchers 0 Forks
Languages
JavaScript 45.7%
Python 38.7%
C++ 13.4%
C 2.2%