- Python 55.7%
- JavaScript 20.4%
- CSS 9.3%
- PowerShell 7.5%
- Shell 3.8%
- Other 3.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| assets | ||
| images | ||
| install | ||
| static | ||
| vendor/VU-Server | ||
| .gitattributes | ||
| .gitignore | ||
| games.py | ||
| launcher.py | ||
| README.md | ||
| requirements.txt | ||
| run.sh | ||
| sensors.py | ||
| supervisor.py | ||
| updater.py | ||
| vu1.py | ||
| web_app.py | ||
VU1
Controller for Streacom VU1 dials: a web UI (:8765) that shows CPU/GPU
load, temperatures and fan speed on the dials, with reactive backlights. Runs on Linux and
Windows, and every installed machine updates itself when this repo's main branch changes.
Install
Linux
curl -fsSL https://git.ihatenetflix.com/kadir/vu1/raw/branch/main/install/install.sh | bash
Windows 10/11 — in a normal (not elevated) PowerShell window:
irm https://git.ihatenetflix.com/kadir/vu1/raw/branch/main/install/install.ps1 | iex
Or download and double-click
Install-VU1.cmd,
which runs the same command.
Both are safe to re-run; settings and dial data are kept. Then open http://localhost:8765.
| Linux | Windows | |
|---|---|---|
| Install dir | ~/.local/share/vu1 |
%LOCALAPPDATA%\VU1 |
| Starts at login via | systemd user unit vu1.service |
scheduled tasks VU1 and VU1 Sensors |
| Temperatures / fans from | kernel (hwmon, sysfs, nvidia-smi) |
LibreHardwareMonitor on 127.0.0.1:8085 |
| Web UI listens on | all interfaces | localhost only (set VU1_HOST to change) |
| Needs admin | sudo once, for the serial-port udev rule |
one UAC prompt |
| Uninstall | install/uninstall.sh [--purge] |
install\uninstall.ps1 [-Purge] |
What the Windows installer adds
Windows can't report CPU/GPU temperatures or fan speeds by itself, so the installer also sets up:
- LibreHardwareMonitor (latest release, into
%LOCALAPPDATA%\VU1\LibreHardwareMonitor) with its web server switched on and start-minimised-to-tray. It runs elevated — that is what lets it read the sensors — from theVU1 Sensorsscheduled task. - PawnIO, the signed kernel driver LibreHardwareMonitor reads hardware through.
- Python 3.13 via winget, only if no Python 3.10+ is present.
If LibreHardwareMonitor is already running with its web server on :8085, that one is used
instead. -NoSensors skips all of it (temperature and fan dials then read 0).
Alternating faces
A dial can take turns between several metrics. Under Assign Metric, pick what to Alternate with and how many seconds each face stays up; the dial then cycles through its assigned metric and the chosen ones, swapping the face and the needle together.
- The minimum is 10 seconds, because the e-ink display needs a few seconds to redraw.
- The dial's custom scale applies to its assigned metric; the others use their default scale.
- While a game is on a dial in game mode, the cycle pauses and picks up again afterwards.
Game mode
Switch a dial to Show game FPS in the web UI and, while a game runs, that dial shows the game's frame rate on a face made for the game, with the backlight in the game's colour. When the game exits, the dial gets its previous face, metric and backlight back.
- Face: the game's logo from Steam, reduced to black and white for the e-ink (falls back to the name in plain lettering when Steam has no logo or the game isn't on Steam), above an FPS scale.
- Scale: fixed at 0–500 FPS by default, printed in large numbers. Change both ends with the FPS scale boxes in the Game mode bar; it applies to every game.
- Tuned games: Dota 2, PUBG, FC 26, FC 27, Factorio, Oxygen Not Included, Counter-Strike 2
and DayZ have hand-picked colours (
PROFILESingames.py). Any other game gets its Steam logo and a colour taken from its Steam banner, or just its name. - Preview: the Game mode bar in the UI can fake a running game for 60 seconds.
Where the frame rate comes from:
| Source | What it needs | |
|---|---|---|
| Linux / Bazzite | MangoHud's live log | MangoHud active for the game. The installer adds ~/.config/environment.d/vu1-mangohud.conf so MangoHud logs whenever it runs (log out and in once). In Steam desktop mode add mangohud %command% to a game's launch options, or enable MangoHud globally; in Bazzite's Game Mode keep the performance overlay at level 1 or higher. Flatpak Steam can't write to the log folder without extra permissions. |
| Windows | Intel PresentMon (tools\PresentMon.exe) |
Membership of the "Performance Log Users" group, which the installer adds (sign out and in once). The game is the fullscreen or borderless window in front. |
On Linux a Steam game is recognised even without MangoHud (the face and colour change, the needle stays at 0), which is the sign that MangoHud isn't active for that game.
How updates work
launcher.py the one process the OS starts; swaps versions in and rolls them back
└─ supervisor.py keeps the two programs below alive, checks the repo every 5 minutes
├─ vu-server vendored VU-Server, talks to the hub over USB serial (:5340)
└─ web_app.py web UI + metrics loop (:8765)
git pushtomain.- Within 5 minutes each machine sees the new commit, downloads it, checks that it compiles
and installs any new packages from
requirements.txt. - The dials pause for a few seconds while the new version is swapped in.
- The new version must answer
/api/healthwithin 2 minutes. If it doesn't, the previous version is put back and that commit is skipped until a newer one is pushed.
The web UI header shows the running version as v<build> · <date>: the build number is the
count of commits on main up to the installed one, the date is when that commit was made
(hover for the commit hash and message). state.json has the full hash; logs/supervisor.log
in the install dir has the history. instance.json holds the repo URL, branch and
check_interval (seconds). For a private repo, pass --token / -Token to the installer.
Not covered by self-update: launcher.py itself (new code loads at next login) and the
service/task definitions (re-run the installer).
Per-machine state lives outside the code and survives updates: data/settings.json (dial
assignments, colours, ranges) and vu-server/ (dial database, config, uploaded faces).
Development
./run.sh web # web UI from this checkout, state kept next to the code
./run.sh # terminal UI
install/install.sh --source . installs the working copy instead of downloading it.
vendor/VU-Server is an unmodified snapshot of
SasaKaranovic/VU-Server at 62a4059.