Inspired by Bert Hubert's presentation at Joy of Coding:
"Save the world, write more efficient code."
A repeatable measurement framework that correlates:
- Power consumption over time (via Shelly Plug S Gen3)
- User interaction events (keyboard/mouse)
- Application/process activity
Understand the energy footprint of your software and work habits.
# Clone the repository
git clone https://github.com/NickAldewereld/shellyplugpowerlogger.git
cd shellyplugpowerlogger
# Install dependencies
pip install -r requirements.txt
# For input event capture (recommended)
pip install pynputSet your Shelly device IP:
export SHELLY_URL="http://192.168.1.38/rpc/Switch.GetStatus?id=0"Or edit directly in scripts/config.
# Capture for 60 seconds
python -m src.correlate capture --duration 60This simultaneously:
- Polls power from Shelly device
- Captures keyboard/mouse events
- Samples top processes by CPU
python -m src.correlate analyze --plotProduces:
data/session_summary.json- Statistics and metricsdata/aligned_timeseries.csv- Correlated datadata/event_costs.csv- Energy cost per event typedata/plots/session.png- Visualization
SESSION SUMMARY
==================================================
Duration: 1m 0s
Readings: 60 valid / 60 total
Power:
Average: 45.2 W
Min/Max: 32.1 / 89.3 W
Median: 43.5 W
Total Energy: 2712.0 J (0.753 Wh)
Baseline (idle): 35.2 W
Input Events:
key_press: 245
mouse_click: 42
mouse_move: 189
Energy per Event Type (avg):
key_press: 0.125 J
mouse_click: 0.089 J
- Power Logging: Robust polling from Shelly Plug S Gen3 with error handling
- Input Tracking: Privacy-first keyboard/mouse event capture (timestamps only, no content)
- Process Sampling: Track which applications consume CPU during measurements
- Correlation Engine: Align data sources and compute energy attribution
- Visualization: Power plots with event markers and baseline
- Extensible: Export to InfluxDB, MQTT, REST APIs
We never capture keystroke content. Only event timestamps and types are recorded.
See docs/security.md for full privacy documentation.
shellyplugpowerlogger/
├── README.md
├── LICENSE # MIT License
├── requirements.txt
├── pyproject.toml
│
├── scripts/
│ ├── shelly_log.sh # Standalone bash logger
│ ├── start_session.sh # Start measurement session
│ └── stop_session.sh # Stop running session
│
├── src/
│ ├── common/ # Shared utilities
│ │ ├── config.py # Configuration management
│ │ └── timeutil.py # Timestamp utilities
│ │
│ ├── correlate/ # Core measurement modules
│ │ ├── __main__.py # CLI entrypoint
│ │ ├── input_events.py # Keyboard/mouse capture
│ │ ├── proc_sample.py # Process sampling
│ │ ├── shelly_reader.py # Shelly device communication
│ │ ├── align.py # Correlation engine
│ │ └── export.py # Output formatters
│ │
│ └── visualize/
│ └── plot_power.py # Matplotlib visualizations
│
├── examples/
│ ├── api_push_example.sh # Push data to REST API
│ ├── mqtt_forwarder.md # MQTT integration guide
│ └── influx_write_example.py # InfluxDB integration
│
├── docs/
│ ├── metrics.md # Metric definitions
│ ├── experiments.md # Experiment templates
│ ├── security.md # Privacy & security
│ └── architecture.md # Technical architecture
│
├── data/ # Output directory (gitignored except .gitkeep)
│
└── [legacy files] # Original scripts (kept for reference)
├── mainshellyscript # Original bash logger
├── visualizeinpython # Original matplotlib script
└── externalconnectshelly # Original integration notes
# Simple power logging without Python
./scripts/shelly_log.sh --url http://192.168.1.38/rpc/Switch.GetStatus?id=0 --out data/power.csv# 5-minute session with all features
python -m src.correlate capture \
--duration 300 \
--url http://192.168.1.38/rpc/Switch.GetStatus?id=0 \
--output-dir data/session_001
# Analyze
python -m src.correlate analyze \
--input-dir data/session_001 \
--plot# If pynput doesn't work (e.g., Wayland)
python -m src.correlate capture \
--duration 60 \
--input-backend xinput# Power only
python -m src.correlate capture --duration 60 --no-input --no-proc- Check Shelly is on the network:
ping 192.168.1.38 - Test the API:
curl http://192.168.1.38/rpc/Switch.GetStatus?id=0 - Ensure Shelly firmware is up to date (Gen3 required)
On Linux (X11):
# Usually works without special permissions
python -m src.correlate capture --duration 10On Linux (Wayland):
# pynput has limited Wayland support
# Use xinput fallback (X11 apps only):
python -m src.correlate capture --input-backend xinput
# Or run with elevated permissions (not recommended)# Install xinput (Debian/Ubuntu)
sudo apt install xinput
# Verify
xinput listIO counters may require elevated privileges:
# Run with sudo (not recommended for regular use)
sudo python -m src.correlate capture --duration 60Environment variables:
| Variable | Default | Description |
|---|---|---|
SHELLY_URL |
http://192.168.1.38/rpc/Switch.GetStatus?id=0 |
Shelly RPC endpoint |
DATA_DIR |
data |
Output directory |
INPUT_BACKEND |
pynput |
Input capture backend (pynput/xinput) |
POLL_INTERVAL |
1.0 |
Power polling interval (seconds) |
PROC_INTERVAL |
1.0 |
Process sampling interval (seconds) |
export INFLUX_URL="http://localhost:8086"
export INFLUX_TOKEN="your-token"
export INFLUX_ORG="your-org"
export INFLUX_BUCKET="power"
python examples/influx_write_example.pySee examples/mqtt_forwarder.md for integration with:
- Home Assistant
- Node-RED
- Grafana/Telegraf
export API_ENDPOINT="https://your-api.com/power"
./examples/api_push_example.sh- Metrics Reference - What we measure and how
- Experiment Guide - Templates for common experiments
- Security & Privacy - Privacy guarantees and security model
- Architecture - Technical deep-dive
Software efficiency matters. Most developers have no visibility into the energy impact of their code. This tool aims to:
- Make energy visible - See real power consumption as you work
- Enable experimentation - Compare editors, browsers, build tools
- Build awareness - Understand what activities consume energy
- Stay lightweight - Minimal dependencies, runs anywhere
"To measure is to know. If you cannot measure it, you cannot improve it." — Lord Kelvin
Contributions welcome! Areas of interest:
- macOS/Windows input capture support
- Additional visualization types
- More export formats
- Hardware acceleration detection
MIT License - See LICENSE
Nick Aldewereld
The original simple scripts are preserved for reference:
mainshellyscript→ Now atscripts/shelly_log.sh(enhanced)visualizeinpython→ Now atsrc/visualize/plot_power.py(enhanced)externalconnectshelly→ Now atexamples/directory