Modern Qt-based system tray GUI for NUT (Network UPS Tools) — monitor UPS status, battery, load, view historical graphs, and send commands.
- System Tray Application: Full-featured tray icon with status indicators and context menu
- Multi-UPS Support: Monitor multiple UPS devices simultaneously with connection profiles
- Real-time Monitoring: Live display of UPS status, battery charge, load, voltage, temperature, and runtime
- Dual Y-Axis Graphs: Historical data visualization with separate axes for percentages (left) and absolute values (right)
- UPS Commands: Execute instant commands (beeper control, shutdown, etc.) directly from the GUI
- Favorites System: Save and quickly connect to frequently used UPS configurations
- Auto-Reconnect: Automatically restore connections to previously monitored UPSes on startup
- Desktop Notifications: Alerts for power events (on battery, low battery, back online, replace battery)
- Four Variables: Battery charge (%), UPS load (%), battery voltage (V), remaining runtime (s)
- Dual Y-Axis: Left axis for percentages (0-100%), right axis for absolute values
- Configurable Retention: Adjustable data retention period (60-86400 seconds)
- Variable Visibility: Toggle individual variables without losing historical data
- State Persistence: Graph visibility state saved across application restarts
- Main Window: Split-pane layout with UPS list and detail tabs
- Status Tab: Real-time UPS information with progress bars and color-coded status
- Commands Tab: Dropdown for selecting and executing UPS instant commands
- Connect Dialog: User-friendly connection setup with authentication support
- Preferences Dialog: Graphical configuration for polling interval, graph retention, and visible variables
- Modern Python: Built with Python 3.14+ and comprehensive type hints
- PyQt6 Framework: Native Qt6 application with proper event handling
- Asyncio NUT Client: Non-blocking network communication with NUT daemon
- Thread-Safe Architecture: Proper separation of UI and network threads
- Settings Persistence: QSettings-based configuration
- Comprehensive Testing: 129 unit tests with pytest and pytest-qt
- Python >= 3.14
- PyQt6 >= 6.5
- pyqtgraph >= 0.13
- NUT daemon (upsd) running and accessible
uv tool install pynut_qtgit clone https://github.com/gunchev/pynut_qt.git
cd pynut_qt
uv sync --group dev
uv run pynut_qtpynut_qtOr:
python -m pynut_qt- Click the tray icon and select "Connect..." or use File → Connect...
- Enter the NUT server host (default: localhost)
- Enter the port (default: 3493)
- Select the UPS name from the dropdown (or enter manually)
- If authentication is required, check "Use authentication" and enter credentials
- Click "Test Connection" to verify (optional)
- Click "Connect"
- After connecting, click "Save as Favorite" in the connect dialog
- Enter a name for the favorite
- Access favorites from the tray icon context menu or File → Favorites
- Enable "View → Show Graphs" from the main window menu
- The graph panel appears on the right side
- Select a UPS from the list to view its graphs
- Configure visible variables in Preferences
- Select a UPS from the list
- Click the "Commands" tab
- Select a command from the dropdown
- Click "Execute Command"
- Confirm the action in the dialog
Access via File → Preferences:
- Polling Interval: How often to query the UPS (1-60 seconds)
- Graph Retention: How long to keep graph data (60-86400 seconds)
- Graphed Variables: Select which variables to display in graphs
Settings are stored in:
- Linux:
~/.config/pynut_qt/general.conf - macOS:
~/Library/Preferences/pynut_qt.plist - Windows: Registry or
%APPDATA%\pynut_qt
git clone https://github.com/gunchev/pynut_qt.git
cd pynut_qt
uv sync --group devmake check # lint + typecheck + test
make test # run tests only
make format # auto-format code
make coverage # test with coverage reportmake run # run in development mode- app.py: Main application and tray icon management
- nut_client.py: Asyncio-based NUT protocol client
- models.py: Data models for UPS status and connection profiles
- settings.py: Thread-safe settings management
- main_window.py: Main window with UPS list and detail tabs
- ups_detail_widget.py: UPS detail tabs (status, commands)
- graphs_widget.py: Historical graphs with dual Y-axis
- connect_dialog.py: Connection dialog with favorites
- command_dialog.py: UPS command execution dialog
- preferences_dialog.py: Application preferences
- Main Thread: Qt event loop and UI
- Poll Thread: Asyncio event loop for NUT communication
- Signal/Slot: Thread-safe communication between threads
The project includes comprehensive tests:
- Unit Tests: 129 tests covering all core functionality
- Live Integration Tests: Verified against real NUT daemon
- Test Isolation: Separate settings namespace for tests
- Type Checking: Pyright validation
- Linting: Ruff and autopep8 compliance
Run tests with:
QT_QPA_PLATFORM=offscreen make checkIf you see "System tray is not available":
- Ensure your desktop environment supports system tray
- On Wayland, you may need a tray implementation (e.g., waybar, polybar)
- Try running with a different desktop environment
If connection fails:
- Verify NUT daemon is running:
systemctl status nut-server - Check NUT configuration:
/etc/nut/upsd.conf - Verify permissions in
/etc/nut/upsd.users - Test with
upsc <ups_name>@<host>
If graphs don't appear:
- Enable via View → Show Graphs
- Select a UPS from the list
- Check that variables are enabled in Preferences
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Run
make checkto ensure all tests pass - Submit a pull request
GPL-3.0-only
Based on the original NUT-Monitor GTK application by David Goncalves.
Modernized with:
- Python 3.14+
- PyQt6 instead of GTK2
- Asyncio instead of telnetlib
- Modern architecture and testing
- Repository: https://github.com/gunchev/pynut_qt
- NUT Project: https://networkupstools.org/
- PyQt6: https://www.riverbankcomputing.com/software/pyqt/
- pyqtgraph: https://pyqtgraph.org/