jensandClaude Sonnet 4.6 d0e4ec374c Plot tab: axis-selective wheel zoom (X default, Shift+wheel for Y)
Add PlotViewBox subclassing pg.ViewBox. Overrides wheelEvent to route
plain scroll to the X axis and Shift+scroll to the Y axis, both centred
on the cursor position. Passed as viewBox= to every PlotWidget so the
behaviour applies uniformly across all 8 plots.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 16:56:02 +02:00

we_monitor

Periodically polls a VW WeConnect vehicle via the weconnect library, stores timestamped records as JSON, and pushes live data to connected TCP clients. A PyQt5 GUI client visualises the data in real time.

Repository layout

collect.py          — collector daemon (entry point)
gui_client.py       — PyQt5 GUI client
client.py           — minimal CLI test client
server/
  data_model.py     — domain extractors, collect_snapshot()
  network.py        — TCP push server (accept loop + broadcast)
  storage_helpers.py— load / save JSON store, midnight rotation helpers
  we_connect.py     — WeConnect login and vehicle selection
  log_config.py     — logging setup
credentials/        — JSON config files (gitignored)
requirements.txt

Requirements

pip install weconnect PyQt5 pyqtgraph

Or use the installer which also sets up a systemd user service:

./install.sh

Collector (collect.py)

Connects to WeConnect, polls selected domains at a configurable interval, and appends records to a rotating JSON log. Simultaneously runs a TCP push server so clients receive every new snapshot the moment it is collected.

Quick start

python collect.py -c credentials/my_car.json

Username and password can also be supplied via environment variables (override the credentials file):

export WC_USER=me@example.com
export WC_PASS=secret
python collect.py -c credentials/my_car.json

Credentials file

All connection and collection settings live in a single JSON file:

{
  "credentials": {
    "username": "me@example.com",
    "password": "secret"
  },
  "vin":        "WVWZZZE1ZMP000000",
  "domains":    ["charging", "measurements", "readiness"],
  "interval_s": 300,
  "host":       "0.0.0.0",
  "port":       9999,
  "log_dir":    "./logs"
}
Key Default Description
credentials.username WeConnect / MyVolkswagen email
credentials.password WeConnect password
vin first vehicle Target VIN
domains ["charging","measurements","readiness"] Domains to collect (list or "all")
interval_s 300 Collection interval in seconds
host "0.0.0.0" Push server bind address
port 9999 Push server TCP port
log_dir "./logs" Directory for rotating JSON log files
diff false Enable diff mode for push server transmission

CLI reference

CLI flags override the corresponding credentials file value when given.

Flag Overrides Description
-c FILE Credentials / settings file
-u / -p credentials.username/password Username / password (also WC_USER / WC_PASS)
-d DOMAINS domains Domains to collect (comma-separated or all)
-i SECONDS interval_s Collection interval in seconds
--host HOST host Push server bind address
--port PORT port Push server TCP port
--log-dir DIR log_dir Directory for rotating log files
--max-records N Keep only the last N records per file
--diff diff Send diffs instead of full snapshots (must match client setting)
--dry Skip WeConnect; run push server only (for testing)
-v Verbose / debug logging
--list-domains Print available domains and exit

Available domains: charging, climatisation, measurements, readiness, parking, access

Log rotation

A new file is started automatically after midnight UTC; previous files are kept intact. On startup and on each new client connection the collector sends the last 24 hours of records, so clients always receive a full rolling window regardless of when midnight falls.

Output format

Log files are named YYYY_MM_DD_HH_MM_SS_<VIN>.json and contain:

{
  "meta": { "vin": "...", "created_at": "...", "interval_seconds": 300 },
  "records": [
    {
      "ts": "2025-05-25T10:00:00+00:00",
      "charging": {
        "batteryStatus": {
          "currentSOC":            { "value": 80,  "unit": "%" },
          "cruisingRangeElectric": { "value": 310, "unit": "km" }
        }
      }
    }
  ]
}

Physical values are always {"value": …, "unit": …} objects.

Push server protocol

The server listens on the host:port from the credentials file (default 0.0.0.0:9999).

  • On connect: sends all records from the last 24 hours, sorted by timestamp.
  • On each new poll: sends the new snapshot immediately.

All messages are newline-delimited JSON (one record per line, \n terminated).

Diff mode (--diff)

When enabled on the server, the history burst is compressed: the first record is sent in full, subsequent records as jay_diff_full diffs ({"_diff": true, "update_add": {…}, "delete": {…}}). Live snapshots are also diffed against the previous broadcast. Enable --diff on the client side (client.py) or check Diff mode in the GUI Connector tab to reconstruct full snapshots from the stream. Both sides must agree — a mismatch produces garbled output.

GUI client (gui_client.py)

python gui_client.py

Dark theme. Three tabs:

Connector tab

Enter host and port, then click Connect. Settings are saved automatically and restored on the next launch. All plot data is cleared on each connect so fresh server history is never mixed with stale local data.

Dashboard tab

Live tree view of the latest snapshot — domain → status object → field, showing value and unit. Expand state is preserved across updates.

Plot tab

8 plots (4 × 2) in a scrollable grid. Each plot has its own control bar:

  • Time window spinner — show the last 124 hours (per plot).
  • Dropdown + + — select a signal and add it as a trace (max 4 per plot).
  • Colored chips (name ×) — click to remove a trace.
  • Zoom / pan with mouse; crosshair cursor tracks mouse position.
  • When available data is less than the selected window, the x-axis adjusts to the actual data extent — no empty gap on the left.

Trace selections, time windows, and connection settings are persisted to ~/.config/we_monitor/plot_settings.json and restored automatically on the next launch.

CLI test client (client.py)

python client.py --host 192.168.1.10 --port 9999

Connects to the push server and prints every incoming snapshot as pretty-printed JSON with a running record counter.

S
Description
Periodically polls a VW WeConnect vehicle via the weconnect library, stores timestamped records as JSON, and pushes live data to connected TCP clients. A PyQt5 GUI client visualises the data in real time.
Readme
742 KiB
Languages
Python 89.2%
Shell 10.8%