IT security, FreeBSD, Linux, mail server hardening, post-quantum crypto, DNS, retro computing & hands-on hardware hacks. Privater Tech-Blog seit 2003.

Schlagwort: GTK4

ts3level: TeamSpeak-Identity-Level auf der GPU rechnen, mit automatischem .ini-Patch

Beitragsbild zu ts3level: Eine TeamSpeak-Identity-INI-Datei wird per GPU von Security-Level 45 auf 55 hochgerechnet und automatisch gepatcht.

Wer eine TeamSpeak-3-Identity mit einem höheren Security Level haben möchte als das, was der offizielle Client innerhalb eines Menschenlebens rausrechnet, kommt um GPU-Hilfe nicht herum. Es gibt da seit Jahren eine Handvoll Drittanbieter-Tools. Was bisher fehlte, war der unspektakuläre letzte Schritt: das gefundene Ergebnis wieder in die .ini zu schreiben. Genau diese Lücke schließt ts3level, ein neues Open-Source-Tool, an dem ich die letzten Wochen gesessen habe.

ts3level GUI Hauptfenster mit aktivem Hash-Run, Identity-Details links, GPU-Stats und Auslastungsgraph rechts
Das Hauptfenster während eines laufenden Hash-Runs. Links die geparsten Identity-Details, rechts Live-Progress, Hashrate, ETA und ein kleiner Cairo-Graph mit 60 Sekunden GPU-Auslastung.

Das Repo liegt auf GitHub unter Kernel-Error/ts-identities-security-level (MIT-Lizenz). Release v0.1.0 inklusive prebuilt Tarball für x86_64 Linux mit glibc ≥ 2.39 gibt’s hier. Der Tarball ist rund 2 MB groß, mehr braucht es nicht.

Das Problem: Single-Thread-CPU vs. exponentielles Wachstum

Das „Security Level“ einer TS3-Identity ist nichts anderes als ein Proof-of-Work. Man variiert einen uint64-Counter und hashed solange SHA1(pubkey_b64 || decimal(counter)) bis vorne genug Null-Bits stehen. Pro Level verdoppelt sich der durchschnittliche Aufwand. Der offizielle TS3-Client rechnet das in einem einzelnen CPU-Thread. Ab ungefähr Level 50 wird das schlicht unbrauchbar.

Es gibt seit Jahren GPU-beschleunigte Drittanbieter-Hasher. landave/TSIdentityTool ist die CPU-Referenz in C, mittlerweile dormant. landave/TeamSpeakHasher bringt das auf OpenCL, der CUDA-Fork von thissepic ist aktuell das aktivste Tool und schafft auf einer RTX 4070 Ti rund 20 GH/s. bratkartoffel/ts3idtools macht das in C mit pthreads auf der CPU.

Allen gemeinsam ist die UX-Lücke: keines schreibt das Ergebnis zurück. Der typische Workflow ist Pubkey aus der .ini extrahieren, Hasher füttern, Counter aufschreiben, Counter manuell in die .ini patchen, Datei re-importieren. landave begründet das bewusst mit Privatekey-Schutz, der Hasher soll den Private Key gar nicht erst zu sehen kriegen. Eine sehr saubere Trennung, aber für den Endanwender eine ziemlich friktionsreiche Angelegenheit.

Genau dort setzt ts3level an. Man zeigt auf seine .ini, der Rest passiert automatisch. Atomarer Write, einmaliges .bak, fertig. Drumherum eine GTK-GUI, NVML-Telemetrie, Übersetzungen auf en/de/es/fr, eine ehrliche ETA-Anzeige und ein Identity-Details-Panel, damit man nicht jedes Mal die Datei von Hand parsen muss.

Wie funktioniert „Security Level“ überhaupt?

Die Kernformel ist erfrischend einfach:

level = leading_zero_bits( SHA1( pubkey_b64 || decimal(counter) ) )

pubkey_b64 ist die base64 der public-key-only ASN.1 DER eines ECDSA-Keys auf der Kurve secp256r1 (NIST P-256). Es ist genau der String, den der TS3-Client im Identity-Dialog unter „Public Key“ anzeigt. decimal(counter) ist die ganz normale Dezimaldarstellung des uint64 ohne Padding, also "42" und nicht "0042". Konkatenation passiert auf ASCII-Stringebene, nicht auf irgendwelchen rohen Bytes. Klingt banal, ist aber tatsächlich die häufigste Fehlerquelle bei Re-Implementierungen.

Das Zählen der führenden Null-Bits läuft byte-0-zuerst und innerhalb jedes Bytes von LSB nach MSB. Genau die hashcat-Konvention. In Python wäre das:

zero_bytes = 0
while zero_bytes < 20 and hash[zero_bytes] == 0:
    zero_bytes += 1
zero_bits = 0
if zero_bytes < 20:
    b = hash[zero_bytes]
    while not (b & 1):
        zero_bits += 1
        b >>= 1
level = 8 * zero_bytes + zero_bits

Die Wahrscheinlichkeit dass ein einzelner Hash mindestens Level L erreicht ist 1 / 2^L. Im Mittel braucht es also 2^L Versuche pro angestrebtes Level. Auf meiner Testkarte, einer RTX 4060 Ti bei rund 2,4 GH/s, sieht das so aus:

Ziel-LevelMittlere Wartezeit
40~7 Minuten
45~4 Stunden
50~5 Tage
55~5 Monate
60~14 Jahre

Diese Werte sind statistische Mittelwerte. Die echte Wartezeit ist exponentialverteilt, man kann also mit Faktor 2 bis 3 schneller oder langsamer Glück haben. Genau deshalb zeigt das Tool die ETA auch als das was sie ist (ein Mittelwert), und nicht als seriös wirkenden Countdown.

Was im .ini-File steckt

Eine exportierte TS3-Identity sieht ungefähr so aus:

[Identity]
id=Standard
identity="<counter>V<base64_obfuscated_blob>"
nickname=Kernel-Error
phonetic_nickname=

Der Teil hinter dem V ist doppelt base64-codiert, mit einer XOR-Schicht dazwischen. Das hat landave per Black-Box-Analyse aus dem Client-Verhalten rekonstruiert. Schematisch:

data = base64_decode(blob_b64)        # outer base64
hash_part = data[20:]                  # everything past the first 20 bytes
sha = sha1(hash_part)
data[0:20] ^= sha                      # undo SHA-1 mask
data[0:min(100, len)] ^= TSKEY         # undo static-key XOR
inner_ascii = data                     # ASCII-base64 of the ASN.1 DER
asn1_der = base64_decode(inner_ascii)  # inner base64

Der amüsante Stolperstein dabei: TSKEY ist im C-Original definiert als const char *TSKEY = "b9dfaa7bee...";. Das sind nicht die 64 Hex-Bytes, sondern die 128 ASCII-Zeichen der Hex-Darstellung selbst. Eine Stunde Debugging, bis ich gemerkt habe woran es liegt. Ist halt einer dieser Punkte, bei denen die Spec ohne Quelltext nicht reichen würde.

Im inneren DER liegt der libtomcrypt-formatierte Keypair:

SEQUENCE {
  BIT STRING       flags     -- 1 bit; 0 = public-only, 1 = with private key
  SHORT INTEGER    keysize   -- 32 for P-256
  INTEGER          x
  INTEGER          y
  [INTEGER         k]        -- only when flags = 1
}

Für den Hash-Input brauchen wir nur die public-only Variante dieses DER-Blobs: gleiche Struktur, flags=0, X, Y, und der private Skalar k fällt einfach raus. Der Hasher bekommt damit nie den privaten Schlüssel zu sehen. Genau diese Trennung, die landave aus gutem Grund eingeführt hat, bleibt erhalten. Das Auto-Patchen der .ini passiert in einem separaten Modul, das den Counter zurückschreibt, ohne den Private Key überhaupt anzufassen.

Warum eine GPU

SHA-1 ist ein dankbarer Kandidat für massiv-paralleles Hashing. Es gibt keine Datenabhängigkeiten zwischen verschiedenen Counter-Werten, jede der zigtausend GPU-Threads kann einen anderen Counter testen und das Ergebnis unabhängig vergleichen. Ein moderner Desktop-Kern auf der CPU kommt vielleicht in den niedrigen dreistelligen MH/s-Bereich für SHA-1, eine RTX 4060 Ti im Tool rund 2,4 GH/s. Das reicht um aus Level 50 statt „mehreren Jahren“ so etwas wie „mehreren Tagen“ zu machen, also einen Bereich, in dem ein Run überhaupt erst Sinn ergibt.

Das Tool macht nichts Heldenhaftes mit dem Kernel: simples SHA-1 in CUDA C, ein Counter pro Thread, atomarer Compare-and-Swap auf der „bester gefundener Level“-Variable im global memory. Hochoptimierte Hasher wie der von thissepic kommen mit Midstate-Precompute und LOP3.LUT-Tricks auf ungefähr das fünffache. Dieser Teil steht auf der Roadmap, ist aber für den ersten Release bewusst nicht angegangen worden. Der eigentliche Mehrwert von ts3level ist UX und Auto-Patch, nicht der letzte ausgequetschte GH/s.

Was das Tool macht: zwei Binaries, ein Source-Tree

Aus dem Workspace fallen zwei Binaries:

  • ts3level: headless CLI mit Progress-Spinner, gut für Server, tmux, SSH-Sessions
  • ts3level-gui: GTK4 + libadwaita Desktop-Anwendung, übersetzt in en/de/es/fr

Konkrete Use-Cases, die im Auge waren beim Entwurf:

  • Die eigene TS-Identity von einem aktuellen Level (z. B. 45) auf ein Wunsch-Level (z. B. 55) hochrechnen, ohne sich mit base64-Blobs und Counter-Werten herumzuschlagen.
  • Headless auf einem Server mit einer NVIDIA-Karte über Nacht laufen lassen, morgens fertige .ini aus dem Backup-Verzeichnis ziehen.
  • Endless-Mode: das Tool läuft permanent, jedes Mal wenn ein höheres Level gefunden wird, wird die Datei sofort aktualisiert. Wer kein konkretes Ziel hat und einfach gucken will, was an einem Wochenende rauskommt, fährt damit ganz gut.
  • Identity-Details ablesen, ohne die .ini per Hand zu parsen: Nickname, Fingerprint (also die TS3-„Unique ID“), Public Key, Current Level, Current Counter.

Beim Start auf eine frisch generierte Demo-Identity sieht der CLI-Output so aus:

Using device: [CUDA:0] NVIDIA GeForce RTX 4060 Ti (cc 8.9, 34 SMs, 15.6 GiB)

Nickname: DemoUser
Local ID: DemoStandard
Fingerprint: 3cltecu4AFn+OK7Lx3Ish6wZN+Y=
Current level: 25  (counter: 7131210)

note: target 1 <= 25 (current level): raising to 26
Target: 26

Und während der Run läuft sieht die Statuszeile so aus:

⠹ level: 50  counter: 1964603892897982  2.45 GH/s  ETA→+1: 0.4s  ETA→target: 10.3d  GPU: 100% 76°C 165W  (10s)

In der GUI ist genau dieselbe Information da, plus ein 60-Sekunden-Ringbuffer-Graph der GPU-Auslastung. Praktisch wenn man parallel zockt und sehen will, ob der Hash-Run noch genug Luft hat oder die Karte sich gegen das Spiel durchsetzen muss.

Architektur (kurz)

Komplett Rust, fünf Crates in einem Workspace:

crates/ts3level-core/    parser, obfuscation, pubkey extraction, CPU SHA-1, atomic writer
crates/ts3level-engine/  HashEngine trait, preflight, driver loop, NVML telemetry
crates/ts3level-cuda/    SHA-1 kernel in CUDA C, bound via cudarc
crates/ts3level-cli/     clap + indicatif + gettext
crates/ts3level-gui/     gtk4-rs + libadwaita + Cairo graph

Beim Build ruft build.rs einmal nvcc --fatbin auf und erzeugt eine Fatbin mit echtem SASS für sm_70, sm_75, sm_80, sm_86, sm_89, sm_90, plus PTX-Fallback für künftige Architekturen. Diese Fatbin wird per include_bytes! direkt in das Rust-Binary einkompiliert. Der Endanwender braucht damit nur den NVIDIA-Treiber, kein CUDA-Toolkit. libcuda.so.1 und libnvidia-ml.so.1 werden zur Laufzeit per dlopen gezogen, das funktioniert ab Treiber 525 ohne Klimmzüge.

Das Zurückschreiben in die .ini macht das Tool über flock(LOCK_EX) auf die Datei, einmaliges .bak wenn keines existiert, neue Bytes in eine tempfile::NamedTempFile im selben Verzeichnis, fsync, anschließend rename(2) drüber. POSIX-atomar. Bei Stromausfall mittendrin gibt es entweder die alte oder die neue Datei, nie ein halbgares Gemisch.

Vor jedem Run prüft ein Preflight neun Bedingungen: libcuda ladbar, CUDA-Devices vorhanden, Zugriffsrechte auf /dev/nvidia*, .ini lesbar, schreibbar, Parent-Dir schreibbar, Datei strukturell gültig, kein konkurrierender Lock, genug Platz für eine .bak. Fehler werden als strukturierte Codes ausgegeben, dokumentiert in der README. Backtraces gibt es nicht, weil sie für Endanwender nur Lärm sind.

Tests stehen bei 68 verteilt über alle Crates: 40 in ts3level-core (Parser, Obfuscation, Pubkey, Level-Berechnung, Writer, Sign-Prefix-Edge-Cases), 18 in ts3level-engine (Preflight, Driver, ETA, GpuStats), 3 in ts3level-cuda (eine Million Counter Parity GPU vs. CPU, Hashrate-Probe), 7 in ts3level-cli (Smoke-Tests, End-to-End gegen eine echte GPU, i18n).

Validierung gegen den echten TS3-Client

Einfacher aber wichtiger Schritt: nachdem das Tool intern korrekt aussah, habe ich eine reale Identity aus dem TS3-Client exportiert und parallel den vom Tool berechneten Fingerprint und das Security Level mit der Anzeige im Client verglichen. Beides byte-identisch. Heisst: die Algorithmus-Spec stimmt, es gibt kein Off-by-One zwischen meiner Implementierung und dem, was ein TS-Server für die Identifikation tatsächlich sieht. Wer den Counter mit ts3level hochrechnet, bekommt eine Identity, die der Client genauso akzeptiert, als hätte er den Aufwand selbst betrieben.

Hardware-Support

Out-of-the-Box im prebuilt Tarball:

GenerationBeispieleCompute Cap
VoltaTitan V, V100sm_70
TuringRTX 2060/70/80, T4sm_75
Ampere DCA100sm_80
Ampere ConsumerRTX 3060/70/80/90sm_86
AdaRTX 4060/70/80/90sm_89
HopperH100sm_90
Blackwell und künftigeRTX 5xxx, GB200sm_100+ via JIT

Pascal (GTX 10-Serie) und älter sind bewusst nicht dabei. Eine Zeile in build.rs ergänzen und neu bauen reicht, dann läuft auch das, nur ist die SHA-1-Performance auf diesen Karten ohnehin nicht konkurrenzfähig.

Installation

Auf Ubuntu, Mint oder Debian sieht das so aus:

sudo apt install nvidia-driver-550 libgtk-4-1 libadwaita-1-0 gettext-base
sudo usermod -aG render $USER   # log out and back in afterwards
curl -LO https://github.com/Kernel-Error/ts-identities-security-level/releases/download/v0.1.0/ts3level-v0.1.0-x86_64-linux.tar.gz
tar -xzf ts3level-v0.1.0-x86_64-linux.tar.gz
cd ts3level-v0.1.0-x86_64-linux
sudo install -m755 bin/ts3level     /usr/local/bin/
sudo install -m755 bin/ts3level-gui /usr/local/bin/
sudo cp -r share/locale/*           /usr/share/locale/

Verifizieren mit ts3level --list-devices. Die volle Installationsanleitung inklusive Rechte-Setup und Troubleshooting steht im Repo unter docs/installation.md.

Bekannte Grenzen und Roadmap

Ehrlich bleiben:

  • 2,4 GH/s auf der 4060 Ti sind nur ungefähr ein Achtel dessen, was thissepic mit hand-optimierten Kernels rausholt. Midstate-Precompute, In-Place-Counter-Inkrement und LOP3.LUT-PTX-Tricks würden das in den 10 GH/s-Bereich heben. Steht auf der Roadmap, aber nicht für den ersten Release.
  • v0.1 ist NVIDIA-only. Das HashEngine-Trait ist allerdings genau dafür gedacht: ein OpenCL-Backend für AMD und Intel wäre ein relativ entspannter Drop-In.
  • Kein Flatpak bisher. Wer auf älteren Distros sitzt, etwa Ubuntu 22.04 mit glibc 2.35, muss aus den Quellen bauen. Lässt sich machen, ist aber nicht das Plug-and-Play das man von einem Tarball erwartet.
  • Pascal und älter brauchen den oben erwähnten Einzeiler in build.rs.

Die volle Roadmap mit Effort/Impact-Einschätzung liegt im Repo unter docs/roadmap.md.

Lizenz, Repo, Disclaimer

MIT-Lizenz, Repo unter github.com/Kernel-Error/ts-identities-security-level. Releases inklusive prebuilt Tarball werden auf der Releases-Seite veröffentlicht.

Dieses Tool ist nicht mit der TeamSpeak Systems GmbH affiliiert, von ihr endorsed oder gesponsort. „TeamSpeak“ ist eine Wortmarke der TeamSpeak Systems GmbH und wird hier ausschließlich beschreibend verwendet.

Das Tool kommuniziert nicht mit TS-Servern, umgeht keine Zugangsbeschränkungen, rechnet ausschließlich offline auf einer Datei, die dem Anwender selbst gehört. Algorithmisch dasselbe was der offizielle Client auch tut, nur eben auf der GPU. §69d UrhG (Beobachtung, Untersuchung und Testen von Software) deckt die Black-Box-Analyse ab, aus der die Algorithmus-Specs in Tools wie landave/TSIdentityTool über Jahre öffentlich entstanden sind. §202c StGB greift nicht: kein Bypass einer Zugangskontrolle, keine fremden Systeme, eigene Daten. Mein Versuch einer rechtliche Einordnung steht im Repo unter docs/legal.md.

Siehe auch: Voltcraft CM 2016 mit GTK4-GUI unter Linux (anderes GTK4-Projekt, andere Hardware), peon-ping Sound-Benachrichtigungen (kleines Rust-Tool fuer den Desktop).

Fragen, Kommentare oder Verbesserungsvorschläge gerne über die fragen-Seite oder als Issue im Repo.

Voltcraft CM 2016: Endlich eine Linux-GUI für das Ladegerät

Seit bestimmt zehn Jahren steht hier ein Voltcraft Charge Manager CM 2016 auf dem Schreibtisch. Irgendwann bei Conrad gekauft, als die tatsächlich noch Geschäfte in der Innenstadt hatten. Damals mit zwei kleinen Kindern war der Akkuverbrauch enorm. Spielzeugautos, Taschenlampen, Fernbedienungen, irgendwas war immer leer. Einwegbatterien waren teurer als heute (zumindest in meiner Erinnerung), und so wurde das Ladegerät schnell zum wichtigsten Gerät im Haushalt.

Das CM 2016 hat sechs unabhängige Ladeschächte (vier für AA/AAA, zwei für 9V-Blöcke) und kann deutlich mehr als nur Laden. Es misst Kapazitäten, erkennt defekte Akkus, kann Lade-/Entladezyklen fahren und hält Akkus per Trickle-Charge am Leben. Wer seine Akkus ernsthaft pflegen will, braucht so ein Gerät. Damit halten die Zellen länger, man kann sie wiederaufbereiten und erkennt rechtzeitig, wann einer reif für die Tonne ist.

Voltcraft Charge Manager CM 2016 Frontansicht mit Display und eingelegtem Akku
Der Voltcraft Charge Manager CM 2016 mit eingelegtem Akku

In den letzten Jahren wurde es zugegebenermaßen weniger eingesetzt. Trotzdem laufen noch immer diverse Smarthome-Geräte und Notfall-Taschenlampen mit Akkus, und da ist ein ordentliches Ladegerät einfach Pflicht.

Das Problem: kein Linux, kein gar nichts

Das CM 2016 kommt mit einer Windows-Software. CM2016 Logger V2.10, eine .NET-Anwendung von 2013. Unter Linux funktioniert die selbstverständlich nicht. Es gibt ein paar Projekte, die das Gerät auf der Kommandozeile auslesen können, ein Java-Tool hier, ein Python-Script dort. Eine echte GUI für Linux oder FreeBSD? Fehlanzeige. Selbst als ich vor ein paar Tagen noch einmal gesucht habe: nichts. Eine kommerzielle Java-GUI existiert zwar, aber nur als 30-Tage-Trial.

Also habe ich mich selbst daran gesetzt.

Das Ergebnis: eine native GTK4-Anwendung

Das Ergebnis ist eine vollständige Desktop-Anwendung in Python mit GTK4 und libadwaita. Quelloffen, MIT-lizenziert, auf GitHub:

https://github.com/Kernel-Error/voltcraft-cm2016

Voltcraft CM 2016 GUI: Hauptfenster mit Datentabelle und Live-Aufzeichnung
Hauptfenster mit Datentabelle während einer Live-Aufzeichnung

Die App erkennt das CM 2016 automatisch per USB (Silicon Labs CP210x Chip) und zeigt alle sechs Schächte in Echtzeit an. Alle zwei Sekunden kommen neue Messdaten rein: Spannung, Strom, Kapazität, Laufzeit, Programmstatus.

Was die App kann

  • Echtzeit-Überwachung aller 6 Ladeschächte mit Autoscroll und Slot-Filterung
  • Spannungs- und Strom-Diagramme als Linien- oder Balkendiagramm mit Zeitfenster-Steuerung
  • Chart-Zoom per Maus-Drag, Scrollrad oder Tastatur, dazu Daten-Tooltips
  • Export als CSV oder Spreadsheet (.xlsx mit eingebetteten Diagrammen)
  • Druckfunktion für Messprotokolle im DIN A4 Querformat
  • Speichern und Laden von Aufzeichnungen (.cm2016 Dateien), inklusive Crash-Recovery über Temp-Dateien
  • Sleep-Inhibit: das System schläft nicht ein, solange aufgezeichnet wird
  • 7 Sprachen: Deutsch, Englisch, Französisch, Niederländisch, Italienisch, Spanisch, Polnisch
Voltcraft CM 2016 GUI: Spannungs- und Strom-Diagramme
Liniendiagramme für Spannung und Strom über die Zeit
Voltcraft CM 2016 GUI: Balkendiagramm
Balkendiagramm-Ansicht
Voltcraft CM 2016 GUI: Port-Auswahl Dialog
Port-Auswahl mit automatischer Geräteerkennung

Das Protokoll: nicht ganz so dokumentiert wie gedacht

Das CM 2016 sendet alle zwei Sekunden einen 127-Byte-Frame über die serielle Schnittstelle (19200 Baud, 8N1). Die ersten sieben Bytes sind immer CM2016 , dann folgen zehn Bytes Header und je 18 Bytes pro Ladeschacht.

Klingt einfach. Ist es auch, bis man die existierende Dokumentation mit echten Messdaten vergleicht. Dabei sind mir ein paar Dinge aufgefallen, die so nirgendwo korrekt dokumentiert waren:

  • Kapazitätsfelder sind 32-Bit Little-Endian, nicht 24-Bit wie es in mehreren Quellen steht. Charge-Capacity und Discharge-Capacity belegen jeweils vier Bytes.
  • Der dokumentierte Byte-Swap für Discharge-Capacity war falsch. Mehrere Referenzprojekte haben die Bytes in der falschen Reihenfolge gelesen, was zu absurden Kapazitätswerten geführt hat.
  • Die Header-Bytes 7-16 waren bisher größtenteils undokumentiert. Tatsächlich stecken da die Firmware-Version, die eingestellte Akku-Chemie (NiMH/NiZn), Temperaturdaten und ein Action-Counter drin. Alles Big-Endian, im Gegensatz zu den Slot-Daten, die Little-Endian sind.
  • Die Kapazitätsskalierung hängt vom Slot-Typ ab: Slots 1-4 (AA/AAA) teilen durch 100, die beiden 9V-Slots teilen durch 1000. Gleiches gilt für den Strom: AA/AAA-Slots durch 1000, 9V-Slots durch 10000.

Das alles musste mit dem echten Gerät verifiziert werden. Akku rein, verschiedene Programme durchlaufen lassen, Rohwerte mit dem Display vergleichen. Klassisches Reverse Engineering, nur eben mit Ladeströmen statt mit Netzwerkpaketen.

Technik unter der Haube

Die Anwendung nutzt GTK4 mit libadwaita für eine zeitgemäße GNOME-Oberfläche. Dark Mode funktioniert automatisch. Die Diagramme werden mit Cairo gerendert, Benachrichtigungen laufen über den libadwaita ToastOverlay. Für den seriellen Zugriff kommt pyserial zum Einsatz, die CP210x-Erkennung läuft über die USB Vendor/Product ID von Silicon Labs.

Der Spreadsheet-Export erzeugt .xlsx-Dateien mit eingebetteten Diagrammen über openpyxl. Die Druckfunktion generiert DIN A4 Querformat mit allen Slots und Diagrammen. Sessions lassen sich als .cm2016-Dateien speichern und wieder laden, und falls die Anwendung während einer Aufzeichnung abstürzt, gibt es eine automatische Recovery über Temp-Dateien.

Insgesamt 135 Unit-Tests decken Parser, Protokoll und die Export-Funktionen ab.

Installation

Die App braucht GTK 4.14+ und libadwaita 1.5+. Unter Debian/Ubuntu/Mint:

sudo apt install python3-gi python3-gi-cairo gir1.2-gtk-4.0 gir1.2-adw-1
git clone https://github.com/Kernel-Error/voltcraft-cm2016.git
cd voltcraft-cm2016
python3 -m venv --system-site-packages .venv
source .venv/bin/activate
pip install -e .

Unter Fedora:

sudo dnf install python3-gobject gtk4 libadwaita

Unter Arch:

sudo pacman -S python-gobject gtk4 libadwaita

Dann einfach cm2016 starten, USB-Kabel anschließen, fertig.

Ein .deb-Paket gibt es auf der GitHub Releases Seite. Ein Flatpak-Manifest liegt im Repository, die Einreichung bei Flathub ist eingereicht.

Falls jemand das gleiche Gerät hat und Fragen zur App oder zum Protokoll hat, einfach fragen.

Siehe auch: NB-2033-U: Reverse Engineering eines Fingerabdrucklesers für Linux

© 2026 -=Kernel-Error=-RSS

Theme von Anders NorénHoch ↑