Monitore os sensores e controle o visor LCD do seu water cooler NZXT Kraken no Linux — sem o software oficial (que só existe para Windows). Interface de linha de comando e gráfica (GUI), com carrossel de imagens, reprodução de GIF e telas de temperatura do sistema.
# 1. Instalar (com interface gráfica)
pip install --user ".[gui]"
# 2. Permitir acesso ao dispositivo sem root (uma vez só)
sudo cp assets/udev/99-kraken.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules
# reconecte o cabo USB do Kraken
# 3. Conferir e usar
kraken device list # detecta o dispositivo
kraken status # lê temperatura/RPM
kraken lcd static imagem.png # envia uma imagem para o visor
kraken-gui # abre a interface gráficaA documentação completa (Manual do Usuário e Documentação Técnica) está logo abaixo neste
README e também em arquivos separados na pasta docs/.
- Marca registrada: NZXT e Kraken são marcas da NZXT, Inc. Este é um projeto independente e de código aberto, mantido pela comunidade, sem qualquer afiliação, endosso ou patrocínio da NZXT. O nome é usado apenas para identificar a compatibilidade de hardware.
- Somente leitura do dispositivo: o Kraken lê sensores (temperatura, RPM) e escreve conteúdo no visor (imagens, animações, telas geradas). Ele não altera a velocidade da bomba, a curva dos ventiladores nem a iluminação RGB.
- Sem garantias: este software é fornecido "COMO ESTÁ", sem nenhuma garantia, nos termos da Licença Pública Geral GNU v3 (veja LICENSE). Ele se comunica com hardware via USB; use por sua conta e risco.
- Mídia de exemplo não incluída: imagens e GIFs de demonstração não acompanham este repositório por questões de direitos autorais. Use seus próprios arquivos (PNG, JPG, BMP, WebP ou GIF).
Distribuído sob a GNU General Public License v3.0 ou posterior (GPL-3.0-or-later). Veja o arquivo LICENSE para o texto completo.
A escolha da GPLv3 é também uma exigência de compatibilidade: o projeto utiliza a biblioteca liquidctl, licenciada sob GPL-3.0.
Este projeto só é possível graças aos seguintes projetos de código aberto:
| Projeto | Licença | Uso no Kraken |
|---|---|---|
| liquidctl | GPL-3.0-or-later | Comunicação USB com o dispositivo e operações de LCD |
| Click | BSD-3-Clause | Framework da interface de linha de comando |
| Pillow | HPND (MIT-CMU) | Validação, redimensionamento e renderização de imagens |
| psutil | BSD-3-Clause | Temperaturas de CPU e métricas do sistema |
| tomli-w | MIT | Escrita do arquivo de configuração TOML |
| PySide6 / Qt | LGPL-3.0 (opcional) | Interface gráfica (GUI) |
| Python | PSF License | Linguagem base (≥ 3.12) |
Agradecimento especial ao driver de kernel nzxt-kraken3 (parte do kernel Linux,
GPL-2.0), que expõe os sensores via hwmon/sysfs e é a fonte primária de leitura usada aqui.
Contribuições são bem-vindas! Sinta-se à vontade para abrir issues (relatos de bug, pedidos
de recurso) e pull requests. Ao contribuir, mantenha o estilo do projeto: núcleo (core)
sem dependências de UI, testes em tests/ com pytest, e Python 3.12+.
Abaixo, na sequência: (1) Manual do Usuário — para qualquer pessoa, mesmo sem
conhecimento técnico — e (2) Documentação Técnica — arquitetura, decisões de projeto e
referência interna. Os mesmos textos estão disponíveis separadamente em
docs/MANUAL_DO_USUARIO.md e
docs/DOCUMENTACAO_TECNICA.md.
Kraken é um programa para Linux que mostra informações e imagens no visor (a telinha redonda/LCD) do seu water cooler NZXT Kraken.
Este manual foi escrito para qualquer pessoa, mesmo sem conhecimento técnico. Vá lendo na ordem: cada seção parte da anterior.
- O que é o Kraken (e o que ele NÃO faz)
- O que você precisa
- Instalação passo a passo
- Primeiros passos
- Usando pela interface gráfica (a janela)
- Usando pela linha de comando (o terminal)
- Deixando o Kraken trabalhar sozinho
- Perguntas frequentes e solução de problemas
- Glossário
O NZXT Kraken é um water cooler — uma peça que refrigera o processador do computador. Os modelos mais novos têm um pequeno visor (LCD) no centro da bomba. De fábrica, esse visor é controlado por um aplicativo que só existe para Windows.
O Kraken (este programa) é a alternativa para quem usa Linux. Pense nele como um "controle remoto do visor": com ele você decide o que aparece naquela telinha — uma imagem, uma animação, a temperatura da CPU, etc. — e também consegue ler a temperatura da água e a velocidade da bomba e do ventilador.
- 📊 Mostra os sensores: temperatura do líquido, rotação da bomba (RPM) e do ventilador.
- 🖼️ Põe uma imagem no visor (PNG, JPG, BMP, WebP).
- 🎞️ Toca um GIF animado no visor.
- 🌡️ Mostra a temperatura da CPU/GPU desenhada na telinha.
- 🔁 Faz um "carrossel": várias imagens/telas se alternando automaticamente.
- 🔆 Ajusta o brilho e a orientação (rotação) do visor.
O Kraken é somente leitura no que diz respeito ao funcionamento do cooler. Ou seja:
- ❌ Ele não muda a velocidade da bomba.
- ❌ Ele não controla a curva dos ventiladores.
- ❌ Ele não mexe na iluminação RGB.
Ele só lê esses números e escreve conteúdo no visor. Nada que ele faça coloca a refrigeração do seu computador em risco.
-
Um computador com Linux.
-
Um water cooler NZXT Kraken com visor. Modelos suportados:
Modelo Tamanho do visor Kraken 2023 Standard 240×240 Kraken 2023 Elite 640×640 Kraken 2024 Plus 240×240 Kraken 2024 Elite RGB 640×640 -
Uma permissão para o programa conversar com o aparelho via USB. Isso é resolvido uma única vez, instalando um pequeno arquivo de "regra" (explicado na próxima seção). Sem essa permissão, você teria que usar o programa como administrador (
sudo) toda vez — o que não é recomendado.
As etapas abaixo usam o Terminal (aquele programa de texto onde você digita comandos). Não tenha medo: é só copiar e colar.
O Kraken é um programa em Python. A forma recomendada é instalar com pip:
# instala o Kraken junto com a interface gráfica
pip install --user ".[gui]"Se você só quer a linha de comando (sem janela), pode instalar sem o
[gui].
O projeto já traz pronto o arquivo de permissão. Copie-o para a pasta do sistema e recarregue as regras:
sudo cp assets/udev/99-kraken.rules /etc/udev/rules.d/
sudo udevadm control --reload-rulesDepois disso, desconecte e reconecte o cabo USB do Kraken (ou reinicie o computador) para a permissão valer.
kraken device listSe aparecer o nome do seu Kraken, está tudo certo! 🎉 Se der erro, pule para a seção 8. Solução de problemas.
Antes de enviar imagens, é bom "acordar" o aparelho uma vez:
kraken device initIsso mostra informações como versão de firmware, número de série e o tamanho do visor.
kraken statusVocê verá algo como:
Liquid Temp: 29.1 C
Pump Speed: 2703 RPM
Fan Speed: 1050 RPM
Quer acompanhar ao vivo? Adicione --watch (atualiza sozinho; pare com Ctrl+C):
kraken status --watchSe você instalou com [gui], abra a janela com:
kraken-guiA janela tem 5 abas no topo. Veja o que cada uma faz:
Mostra três mostradores grandes, atualizados a cada 2 segundos:
- Temperatura do líquido (em °C)
- Velocidade da bomba (RPM)
- Velocidade do ventilador (RPM)
É a aba para monitorar o cooler.
Aqui você controla o que aparece no visor:
- Clique em "Escolher Imagem/GIF…" e selecione um arquivo (PNG, JPG, BMP, WebP ou GIF).
- Veja uma prévia de como vai ficar.
- Clique em Upload para enviar a imagem.
- Se escolher um GIF, ele começa a tocar e aparece o botão "Stop GIF" (com a contagem dos quadros, ex.: "frame 5/120"). Clique nele para parar a animação.
- Use o controle de brilho (0 a 100%) e clique em Aplicar.
- Use a orientação (0°, 90°, 180° ou 270°) para girar a imagem e clique em Aplicar.
- O botão "Modo Temperatura do Líquido" volta o visor para a tela nativa de temperatura.
Monta uma sequência de telas que se alternam sozinhas:
- Use "Adicionar Imagem…" (pode escolher várias de uma vez).
- Ou "Adicionar SysInfo" (slide com a temperatura da CPU/GPU).
- Ou "Adicionar Liquid" (slide com a temperatura do líquido nativa).
- Defina por quantos segundos cada slide fica na tela.
- Reordene arrastando os itens na lista.
- Clique em Iniciar para começar. Você pode Pausar/Retomar e Parar quando quiser.
A sua lista é salva automaticamente, então ela continua lá na próxima vez que abrir.
Desenha a temperatura do computador no visor:
- Marque "Mostrar Temperatura da CPU" e/ou "Mostrar Temperatura da GPU".
- Escolha de quantos em quantos segundos atualizar.
- Clique em Iniciar. Clique em Salvar para guardar a configuração.
Mostra (somente para leitura) os dados do aparelho — nome, firmware, resolução, série — e tem um botão para abrir o arquivo de configuração num editor de texto.
Quem prefere o terminal tem todos os recursos disponíveis. Abaixo, "receitas" prontas.
kraken lcd static /caminho/para/minha-imagem.pngkraken lcd gif /caminho/para/animacao.gifPor padrão, ele toca para sempre (pare com Ctrl+C). Para tocar um número fixo de vezes:
kraken lcd gif /caminho/para/animacao.gif --loops 3💡 Os GIFs tocam no máximo a cerca de 8 quadros por segundo — é um limite do próprio aparelho, não do programa. Por isso animações muito rápidas ficam mais lentas.
kraken lcd brightness 75 # brilho em 75%
kraken lcd orientation 90 # gira o visor 90 grauskraken lcd liquidkraken sysinfo config --cpu --no-gpu --refresh 2.5 # configura
kraken sysinfo start # começa a mostrarkraken carousel add /fotos/logo.png --seconds 15 # adiciona uma imagem
kraken carousel add --sysinfo --seconds 20 # adiciona a tela de CPU/GPU
kraken carousel add --liquid --seconds 10 # adiciona a tela de líquido
kraken carousel list # confere a lista
kraken carousel start # inicia (Ctrl+C para parar)kraken config show # mostra tudo
kraken config path # mostra ONDE fica o arquivo de configuração
kraken config edit # abre o arquivo no seu editor📁 O arquivo de configuração fica em
~/.config/kraken/config.toml.
Você pode fazer o carrossel (ou o ícone na bandeja) iniciar junto com o computador, sem precisar abrir nada manualmente.
kraken trayIsso coloca um ícone perto do relógio, mostrando a temperatura do líquido ao passar o mouse.
O projeto traz "serviços" prontos. Para o carrossel iniciar sozinho:
cp assets/systemd/kraken-carousel.service ~/.config/systemd/user/
systemctl --user enable kraken-carousel
systemctl --user start kraken-carouselPara o ícone da bandeja iniciar sozinho, faça o mesmo com kraken-tray.service.
⚠️ Atenção: o arquivo de serviço do carrossel, como vem hoje, usa uma opção (--foreground) que a versão atual do programa não reconhece. Se o serviço não iniciar, edite o arquivo e troque a linhaExecStartpara usar simplesmentekraken carousel start(sem--foreground). Veja mais detalhes na documentação técnica.
"Nenhum dispositivo encontrado" / o programa não acha o Kraken.
- Confirme que o cabo USB interno do Kraken está conectado.
- Verifique se você instalou a regra de permissão (Passo 2 da instalação) e reconectou o cabo.
- Teste com
kraken device list.
"Pede senha / só funciona com sudo."
- Isso quer dizer que a regra de permissão (udev) não foi aplicada. Refaça o Passo 2 da instalação e reconecte o cabo USB (ou reinicie).
"O GIF está lento ou 'travado'."
- Isso é esperado em animações rápidas. O visor aceita no máximo ~8 quadros por segundo.
- Na primeira vez, o programa precisa "preparar" o GIF (separar os quadros). As próximas
vezes são mais rápidas, pois ele reaproveita o que já preparou
(guardado em
~/.cache/kraken/gif_frames/).
"A imagem não aparece / aparece cortada."
- Use imagens quadradas. O visor é redondo/quadrado (240×240 ou 640×640), então imagens muito largas ou muito altas podem ficar estranhas.
- Formatos aceitos: PNG, JPG, JPEG, BMP, WebP (e GIF para animação).
"Não aparece a temperatura da CPU."
- Nem todo computador expõe esse sensor. Tente
--gpuem vez de--cpu, ou veja se okraken status(temperatura do líquido) funciona — esse quase sempre funciona.
- LCD / visor: a telinha no centro da bomba do Kraken.
- Sensor: medidor. Aqui: temperatura do líquido e rotação da bomba/ventilador.
- RPM: "rotações por minuto" — a velocidade de giro da bomba ou do ventilador.
- Firmware: o "programa interno" que vem de fábrica dentro do aparelho.
- Carrossel: sequência de telas que se alternam automaticamente.
- Terminal: a janela preta onde você digita comandos.
- udev: o sistema do Linux que decide quem pode usar cada aparelho USB.
- systemd: o sistema do Linux que inicia programas automaticamente.
- GIF: tipo de imagem que contém uma pequena animação.
- Brilho / orientação: intensidade da luz do visor e o ângulo de rotação da imagem.
Quer entender como o Kraken funciona por dentro? Veja a Documentação Técnica a seguir
neste README (também em docs/DOCUMENTACAO_TECNICA.md).
Gerenciador de LCD e sensores do NZXT Kraken para Linux.
Este documento descreve a especificação, a arquitetura, as decisões críticas e a
referência interna do projeto, de forma que qualquer pessoa com conhecimento em
informática consiga entender o que foi feito, como foi projetado, estruturado e
desenvolvido. Para uso final, consulte o Manual do Usuário acima neste README (também em
docs/MANUAL_DO_USUARIO.md).
- Visão geral e objetivos
- Stack e requisitos
- Arquitetura em camadas
- Estrutura de diretórios
- Módulos em detalhe
- Decisões críticas de projeto
- Modelo de dados e esquema de configuração
- Referência da CLI e mapeamento da GUI
- Fluxos principais
- Suporte multi-modelo, udev e systemd
- Testes
- Problemas conhecidos e evoluções futuras
O Kraken é uma ferramenta em Python para Linux que monitora sensores e gerencia o visor LCD dos water coolers NZXT Kraker da geração com tela.
Princípios que guiaram o projeto:
- Somente leitura do dispositivo: o programa lê sensores (temperatura, RPM) e escreve conteúdo no visor (imagens, animações, telas geradas). Ele não altera curva da bomba, dos ventiladores nem iluminação RGB. Isso elimina toda uma classe de riscos operacionais sobre a refrigeração.
- Núcleo (
core) independente de UI: a lógica de negócio não importa nada de Click (CLI) nem de PySide6 (GUI). As duas interfaces consomem o mesmo núcleo, garantindo paridade de comportamento entre CLI e GUI. - Simplicidade operacional para um cenário de usuário único / dispositivo único: sem daemon próprio, sem DBus, sem servidor. As operações em segundo plano usam threads simples.
hwmon/sysfscomo fonte primária de sensores: leitura rápida e não bloqueante, evitando contenção no canal USB;liquidctlé o caminho de fallback.
| Item | Valor |
|---|---|
| Linguagem | Python ≥ 3.12 |
| Layout | src/ layout |
| CLI | Click ≥ 8 |
| GUI | PySide6 (Qt6) ≥ 6.5 (opcional) |
| Comunicação USB | liquidctl ≥ 1.14 (como biblioteca, não subprocess) |
| Imagens | Pillow ≥ 10 |
| Sistema/temperaturas | psutil ≥ 5.9 |
| Config (escrita) | tomli_w ≥ 1.0 (leitura via tomllib da stdlib) |
| Testes | pytest ≥ 8, pytest-cov, ruff, mypy |
Pontos de entrada (pyproject.toml):
[project.scripts]
kraken = "kraken.cli.app:cli"
[project.gui-scripts]
kraken-gui = "kraken.gui.app:main"A aplicação é organizada em camadas, das fontes de hardware (embaixo) até as interfaces de usuário (em cima). As setas indicam dependência ("usa").
┌─────────────────────────┐ ┌─────────────────────────┐
│ CLI (Click) │ │ GUI (PySide6) │
│ src/kraken/cli/ │ │ src/kraken/gui/ │
└────────────┬────────────┘ └────────────┬────────────┘
│ (ambas dependem só do núcleo)
┌────────────┴───────────────────────────────┴───────────┐
│ NÚCLEO / serviços │
│ core/ · carousel/ · sysinfo/ · config/ │
│ (sem nenhuma importação de Click ou PySide6) │
└───────┬──────────────────────────────────────┬─────────┘
│ │
┌───────┴────────┐ ┌────────┴────────┐
│ hwmon/ (sysfs)│ ← fonte primária │ liquidctl │ ← fallback / LCD
│ /sys/class/.. │ │ (USB HID) │
└────────────────┘ └─────────────────┘
▼ ▼
┌──────────────────────────────────┐
│ NZXT Kraken (hardware) │
└──────────────────────────────────┘
Observações:
- Leitura de sensores prefere
hwmon(sysfs) e cai paraliquidctlse necessário. - Escrita no LCD (imagens, brilho, orientação, modo líquido) é sempre via
liquidctl. carousel,sysinfoeconfigsão serviços que orquestram ocore, mas continuam livres de qualquer dependência de UI.
src/kraken/
├── core/ # Lógica central, independente de UI
│ ├── device.py # KrakenDevice: ciclo de vida USB, set_screen, lock
│ ├── sensors.py # read_sensors(): abstração hwmon/liquidctl
│ ├── lcd.py # validação + upload de imagem, brilho, orientação, modo líquido
│ ├── models.py # dataclasses de dados e de configuração
│ ├── gif.py # extração/cache de frames + reprodução de GIF
│ └── exceptions.py # hierarquia de exceções de domínio
├── hwmon/ # Leitura direta de sysfs
│ ├── discovery.py # find_kraken_hwmon()
│ └── reader.py # read_hwmon_sensors()
├── carousel/ # Engine de carrossel de imagens
│ ├── playlist.py # Playlist (add/remove/move/clear/validate)
│ └── engine.py # CarouselEngine: thread de ciclo em segundo plano
├── sysinfo/ # Renderização de stats do sistema para o LCD
│ ├── collector.py # collect_stats() (CPU/GPU/uso)
│ └── renderer.py # render_stats_image() + SysInfoEngine
├── config/ # Configuração TOML (XDG)
│ ├── paths.py # diretórios XDG (~/.config/kraken/…)
│ ├── schema.py # (de)serialização dict ↔ dataclasses
│ └── manager.py # load_config() / save_config()
├── cli/ # Interface de linha de comando (Click)
│ ├── app.py # grupo raiz `cli` + versão
│ └── commands/ # device, status, lcd, carousel, sysinfo, tray, config_cmd
└── gui/ # Interface gráfica (PySide6/Qt6)
├── app.py # main()
├── main_window.py # MainWindow (5 abas)
├── threads.py # SensorWorker, LCDUploadWorker, GifPlaybackWorker
├── tray.py # ícone de bandeja
└── widgets/ # status_panel, lcd_panel, carousel_panel, sysinfo_panel, device_info
Recursos de apoio fora de src/:
assets/
├── sample_config.toml # config de exemplo comentada
├── udev/99-kraken.rules # permissão de acesso USB sem root
└── systemd/ # serviços de usuário (carousel, tray)
scripts/gif_black_bg.py # utilitário de conversão de GIF (fundo preto)
tests/ # 133 testes (pytest)
KrakenDevice encapsula uma instância de dispositivo do liquidctl e serializa todas as
operações USB através de um threading.Lock interno (evita contenção entre leitura de
sensores e upload para o LCD).
class KrakenDevice:
@classmethod
def find() -> KrakenDevice # descobre o primeiro Kraken suportado pelo PID
def connect() -> None # abre a conexão USB
def initialize() -> DeviceInfo # consulta firmware, série, resolução do LCD
def disconnect() -> None
def get_status() -> list # lê sensores via liquidctl
def set_screen(mode, value=None) -> None # imagem / brilho / orientação / modo líquido
def __enter__/__exit__ # suporte a context managerConstantes relevantes: KRAKEN_LCD_PIDS (PIDs suportados) e LCD_RESOLUTIONS
(mapa PID → resolução).
def read_sensors(device, hwmon_path) -> SensorDataPrefere hwmon (leitura de sysfs, rápida e não bloqueante) e cai para liquidctl
(_read_from_liquidctl) quando o hwmon não está disponível. Devolve um SensorData
com liquid_temp_c, pump_rpm, fan_rpm e timestamp (relógio monotônico).
def validate_image_file(path) -> Path # existência + extensão suportada
def upload_static(device, path) # imagem fixa
def upload_gif(device, path) # delega para core.gif
def upload_image(device, path) # auto-detecta tipo e roteia
def set_liquid_mode(device) # tela nativa de temperatura
def set_brightness(device, value) # 0–100
def set_orientation(device, degrees) # 0/90/180/270Constantes: SUPPORTED_STATIC_EXTENSIONS = {.png, .jpg, .jpeg, .bmp, .webp};
SUPPORTED_GIF_EXTENSIONS = {.gif}; BRIGHTNESS_MIN/MAX = 0/100;
VALID_ORIENTATIONS = (0, 90, 180, 270).
Dataclasses imutáveis para dados e mutáveis (com validação em __post_init__) para
configuração:
SensorData(liquid_temp_c, pump_rpm, fan_rpm, timestamp)(frozen)DeviceInfo(description, firmware_version, lcd_resolution, serial_number, product_id)(frozen)LCDConfig(brightness=50, orientation=0)— valida faixa/valoresCarouselItem(path, display_seconds=10.0, media_type="")—is_specialp/sysinfo/liquidCarouselConfig(enabled=False, items=[], loop=True)SysInfoConfig(enabled=False, show_cpu_temp=True, show_gpu_temp=False, refresh_seconds=5.0)TrayConfig(enabled=False, show_temp=True)AppConfig(device_serial="", lcd, carousel, sysinfo, tray)— raiz da configuração
O firmware 2.x ignora a animação nativa de GIFs. A solução: explodir o GIF em quadros PNG, guardá-los em cache em disco e reproduzi-los como uploads estáticos sequenciais.
def extract_frames(gif_path, cache_root=CACHE_ROOT) -> list[GifFrame]
def play_animated_gif(device, gif_path, loops=0, stop_event=None,
deadline=None, on_frame=None, on_error=None,
cache_root=CACHE_ROOT)- Quadros redimensionados para 240×240 com reamostragem LANCZOS e salvos como
frame_NNNN.png. - Cache em
~/.cache/kraken/gif_frames/<hash>/, commanifest.txt(nome do quadro + duração). A chave de cache é um fingerprint estável:mtime + tamanho + hash dos primeiros 4 KBdo arquivo. Apagar o cache força a re-extração. - Teto de hardware
MIN_FRAME_INTERVAL_MS = 120(~8 fps): durações abaixo disso são limitadas. loops=0= infinito;stop_event/deadlinepermitem cancelamento cooperativo entre quadros;on_frame(i, total)atualiza a UI.
KrakenError (base) → DeviceNotFoundError, DeviceConnectionError,
DeviceNotInitializedError, LCDError (→ ImageValidationError), CarouselError,
ConfigError, HwmonNotFoundError.
discovery.find_kraken_hwmon(base=None): varre/sys/class/hwmon/*/nameprocurando driverskraken2023/nzxt-kraken3/kraken3; devolve o diretório do hwmon.reader.read_hwmon_sensors(hwmon_path): lêtemp1_input(m°C → °C ÷1000),fan1_input(bomba, RPM) efan2_input(ventilador, RPM); devolveSensorData.
playlist.Playlist:add,add_special(sysinfo/liquid),remove,move,clear,validate_paths. Valida caminhos de imagem (exceto itens especiais) e auto-detecta o tipo pela extensão.engine.CarouselEngine(device, playlist, loop=True, on_item_changed=None, on_error=None, sysinfo_refresh_seconds=5.0): roda uma thread daemon que percorre os itens. Para cada item: disparaon_item_changed, trata o tipo (liquid→ modo nativo;sysinfo→ renderização periódica;gif→ reprodução por quadros; estático →upload_image), esperadisplay_seconds(interrompível) e avança. Suportastart/stop/pause/resume.
collector.collect_stats(include_cpu=True, include_gpu=False) -> SystemStats: CPU viapsutil.sensors_temperatures()(tentacoretemp,k10temp,zenpower,cpu_thermal); GPU varrendo/sys/class/hwmonporamdgpu/nvidia; uso viapsutil.cpu_percent.renderer.render_stats_image(stats, size=(240,240)) -> PIL.Image: fundo preto, texto de temperatura + barra de progresso, com cor dependente da temperatura (≈ azul ≤30 °C → verde → amarelo → vermelho >70 °C via_temp_color). Layout adapta-se a 1 ou 2 sensores. Usa fonte DejaVu Sans quando disponível.renderer.SysInfoEngine(device, config, on_error=None): thread que coleta, renderiza e envia ao LCD a cadarefresh_seconds.
paths: respeita$XDG_CONFIG_HOME(default~/.config) e$XDG_DATA_HOME; expõeget_config_dir(),get_config_file()(→~/.config/kraken/config.toml),get_data_dir().schema:config_from_dict/config_to_dictconvertem entredict(TOML) eAppConfig, com defaults para chaves ausentes.manager:load_config(path=None)(devolve default se o arquivo não existir;ConfigErrorem falha de parse) esave_config(config, path=None)(cria diretórios;ConfigErrorem falha).
main_window.MainWindow:QMainWindowcom 5 abas (Status, LCD, Carousel, System Info, Config) e barra de status. Inicializa hwmon e dispositivo e dispara oSensorWorker.threads:SensorWorker(QThread)— polling de sensores (≈2 s), emitedata_updated.LCDUploadWorker(QThread)— uploads (imagem/brilho/orientação) sem travar a UI.GifPlaybackWorker(QThread)— reprodução de GIF por quadros com sinal de parada e progresso de frame.
widgets:status_panel(gauges),lcd_panel(preview, escolher arquivo, upload, Stop GIF, brilho, orientação, modo líquido),carousel_panel(lista com drag-drop, add imagem/sysinfo/liquid, duração, start/pause/stop),sysinfo_panel(toggles CPU/GPU, refresh, start/stop, salvar),device_info(dados do dispositivo + abrir config).tray.py:QSystemTrayIconcom tooltip de temperatura e menu (mostrar janela / sair).
| Decisão | Motivo |
|---|---|
hwmon/sysfs como fonte primária de sensores |
Leitura rápida e não bloqueante; evita contenção no canal USB usado para o LCD. liquidctl fica só como fallback. |
liquidctl como biblioteca (não subprocess) |
Evita custo e fragilidade de iniciar processos; permite reaproveitar a mesma conexão e o lock interno. |
| Threading, não asyncio | liquidctl é síncrono e o domínio é simples (1 usuário/1 dispositivo). Threads daemon bastam para carrossel, sysinfo e polling. |
Lock de USB + drain da fila HID antes de set_screen |
Operações USB são serializadas por um threading.Lock; relatórios HID não solicitados são drenados antes de enviar a tela, evitando erros de "mensagens faltando". |
| GIF por extração + cache + teto de ~8 fps | Contorna a limitação do firmware 2.x (ignora animação nativa). O cache por fingerprint evita re-decodificar a cada execução. |
core sem dependência de UI |
Paridade entre CLI e GUI e testabilidade; UI vira uma casca fina sobre o núcleo. |
| Dataclasses imutáveis com validação | Dados (SensorData, DeviceInfo) frozen; configs validam faixa/valores em __post_init__, falhando cedo. |
| Sem daemon próprio / sem DBus | Simplicidade. Persistência em segundo plano fica por conta de serviços systemd --user, quando desejado. |
A configuração vive em ~/.config/kraken/config.toml (respeitando $XDG_CONFIG_HOME).
Exemplo comentado em assets/sample_config.toml.
[device]
serial = "" # vazio = auto-detecta
[lcd]
brightness = 50 # 0–100
orientation = 0 # 0, 90, 180 ou 270
[carousel]
enabled = false
loop = true
[[carousel.items]]
path = "/home/user/images/logo.png"
seconds = 10 # media_type auto-detectado pela extensão
[[carousel.items]]
path = ""
media_type = "sysinfo" # item especial: stats do sistema
seconds = 20
[[carousel.items]]
path = ""
media_type = "liquid" # item especial: temperatura nativa
seconds = 10
[sysinfo]
enabled = false
show_cpu_temp = true
show_gpu_temp = false
refresh_seconds = 5.0 # >= 1.0
[tray]
enabled = false
show_temp = trueTipos de mídia do carrossel: static (PNG/JPG/BMP/WebP), gif, sysinfo, liquid
(string vazia ⇒ auto-detecta pela extensão).
Validações: brilho 0–100; orientação ∈ {0,90,180,270}; display_seconds > 0;
refresh_seconds ≥ 1.0.
| Comando | Opções/Argumentos | Função |
|---|---|---|
kraken --version / --help |
— | versão / ajuda |
kraken device list |
— | lista o dispositivo detectado |
kraken device init |
— | inicializa (firmware, série, resolução) |
kraken device info |
— | mostra metadados, incl. PID em hex |
kraken status |
--watch/-w, --interval/-i (def. 2.0), --json-output/--json |
leitura de sensores |
kraken lcd static |
<image_path> |
envia imagem fixa |
kraken lcd gif |
<gif_path>, --loops N (def. 0 = infinito) |
reproduz GIF |
kraken lcd liquid |
— | tela nativa de temperatura |
kraken lcd brightness |
<0–100> |
ajusta brilho |
kraken lcd orientation |
<0|90|180|270> |
rotaciona |
kraken carousel start |
--daemon/-d |
inicia o carrossel |
kraken carousel stop |
— | para o carrossel |
kraken carousel add |
[<image_path>], --seconds/-s (def. 10), --position/-p, --sysinfo, --liquid |
adiciona item |
kraken carousel remove |
<index> |
remove pelo índice |
kraken carousel list / clear / status |
— | lista / limpa / estado |
kraken sysinfo start |
--daemon/-d |
inicia render de stats |
kraken sysinfo stop |
— | para |
kraken sysinfo config |
--cpu/--no-cpu, --gpu/--no-gpu, --refresh N |
configura |
kraken tray |
--no-gui |
ícone de bandeja |
kraken config show / path / edit |
— | mostra / caminho / edita ($EDITOR) |
| Aba da GUI | Usa do núcleo |
|---|---|
| Status | sensors.read_sensors (via SensorWorker) |
| LCD | lcd.upload_image/upload_static, gif.play_animated_gif, lcd.set_brightness/set_orientation/set_liquid_mode |
| Carousel | carousel.Playlist + carousel.CarouselEngine; persiste via config.save_config |
| System Info | sysinfo.SysInfoEngine + sysinfo.collect_stats/render_stats_image |
| Config | device.initialize (DeviceInfo) + config.paths.get_config_file |
KrakenDevice.find() → varre USB via liquidctl pelos PIDs suportados
↓
.connect() → abre conexão HID (precisa da regra udev p/ rodar sem root)
↓
.initialize() → consulta firmware, série, resolução → DeviceInfo
↓
operações set_screen() → serializadas pelo lock; fila HID drenada antes do envio
read_sensors(device, hwmon_path)
│
├─ hwmon disponível? → read_hwmon_sensors() (temp1/fan1/fan2 do sysfs)
│
└─ senão → _read_from_liquidctl(device) (parse do status)
↓
SensorData(liquid_temp_c, pump_rpm, fan_rpm, timestamp)
play_animated_gif()
→ extract_frames() (cache hit? reusa : decodifica, redimensiona 240², salva + manifest)
→ para cada loop / quadro:
upload do PNG como imagem estática
respeita duração (mínimo 120 ms)
checa stop_event / deadline; chama on_frame(i, total)
| PID | Modelo | Resolução |
|---|---|---|
0x300C |
Kraken 2023 Elite | 640×640 |
0x300E |
Kraken 2023 Standard | 240×240 |
0x3012 |
Kraken 2024 Elite RGB | 640×640 |
0x3014 |
Kraken 2024 Plus | 240×240 |
Os quadros de GIF são sempre gerados em 240×240. O dispositivo-alvo de desenvolvimento é o Kraken 2023 Standard (
0x300E, 240×240).
Concede acesso USB sem root (MODE="0666", TAG+="uaccess") para os quatro PIDs.
Instalação:
sudo cp assets/udev/99-kraken.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules
# reconectar o cabo USB do Krakenkraken-carousel.service— mantém o carrossel rodando.kraken-tray.service— mantém o ícone de bandeja (kraken tray --no-gui).
cp assets/systemd/kraken-*.service ~/.config/systemd/user/
systemctl --user enable --now kraken-tray133 testes com pytest, cobrindo núcleo, serviços e CLI. Distribuição por arquivo:
| Arquivo | Testes | Cobertura |
|---|---|---|
tests/test_carousel.py |
24 | playlist (add/remove/move/clear) e engine (start/stop/pause/resume) |
tests/test_cli.py |
21 | comandos via click.testing.CliRunner |
tests/test_lcd.py |
21 | upload estático/GIF, validação de brilho/orientação |
tests/test_models.py |
21 | validação dos dataclasses |
tests/test_config.py |
10 | (de)serialização e load/save TOML |
tests/test_gif.py |
10 | extração de frames, cache, durações, playback |
tests/test_hwmon.py |
10 | discovery e leitura de sysfs |
tests/test_sysinfo.py |
10 | coleta de stats e renderização |
tests/test_sensors.py |
6 | leitura de sensores e fallback |
Padrões: unittest.mock para dispositivo/arquivos, fixtures compartilhadas em
conftest.py, tmp_path para arquivos temporários e CliRunner para a CLI (sem
subprocesso). Execução: pytest tests/.
- Serviço de carrossel desatualizado.
assets/systemd/kraken-carousel.serviceexecutakraken carousel start --foreground, mas a CLI atual não possui a opção--foreground(o padrão já é primeiro plano; a opção existente é--daemon). Como está, o serviço falharia ao iniciar. Workaround: editar oExecStartpara… kraken carousel start(sem--foreground). Documentado, não corrigido, conforme a natureza somente-leitura desta tarefa.
- Teto de ~8 fps na reprodução de GIF (firmware 2.x ignora animação nativa). Animações
rápidas são limitadas a
MIN_FRAME_INTERVAL_MS = 120ms por quadro.
- Suporte/validação mais ampla dos demais modelos (Elite/Plus/RGB 640×640) — a arquitetura
(mapa PID → resolução em
LCD_RESOLUTIONS) já está preparada. - Alinhar o serviço systemd à CLI atual.
Documento gerado a partir de leitura direta do código-fonte (núcleo, CLI, GUI, testes, assets), sem qualquer modificação no projeto.