jensandClaude Sonnet 4.6 efc21763a3 gui_client: fit x-axis to actual data when less than window size
Track the earliest timestamp across plotted traces (starting from None,
not cutoff) so setXRange uses the first real data point as the left
bound — no empty gap when data doesn't fill the full time window.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 13:31:40 +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
requirements.txt

Requirements

pip install weconnect PyQt5 pyqtgraph

Collector (collect.py)

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

Quick start

# Credentials via environment variables, all defaults
export WC_USER=me@example.com
export WC_PASS=secret
python collect.py

# Credentials from a JSON file, 10-minute interval
python collect.py -c credentials/my_car.json -i 600

Credentials file (-c FILE)

{
  "username": "me@example.com",
  "password": "secret",
  "vin":      "WVWZZZE1ZMP000000",
  "domains":  ["charging", "measurements", "readiness"]
}

All keys are optional; explicit CLI flags and WC_USER / WC_PASS environment variables take precedence.

CLI reference

Flag Default Description
-c FILE JSON credentials file
-u / -p WC_USER / WC_PASS Username / password
--vin first vehicle Target VIN
-d DOMAINS charging,measurements,readiness Comma-separated domains or all
-i SECONDS 300 Collection interval
-o FILE logs/YYYY_MM_DD_HH_MM_SS_<VIN>.json Output file
--max-records N unlimited Keep only last N records
--host 0.0.0.0 Push server bind address
--port 9999 Push server TCP port
-v Verbose / debug logging
--list-domains Print available domains and exit

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

Log rotation

When using the default logs/ directory the collector automatically starts a new file after midnight UTC, keeping all previous files intact. On startup the full day's records are pre-loaded from disk so newly connected clients receive the complete history.

Output format

Each file is a JSON object:

{
  "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 --host:--port (default 0.0.0.0:9999).

  • On connect: sends all records from the current day, sorted by timestamp.
  • On each new poll: sends the new snapshot immediately.

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

GUI client (gui_client.py)

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

Dark theme matching nmea_client. Three tabs:

Connector tab

Host / port fields, Connect / Disconnect button, and connection status.

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:

  • 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.

Trace selections are persisted to ~/.config/we_monitor/plot_settings.json and restored automatically on the next launch once matching signals arrive.

Signal labels use short human-readable names (e.g. SOC, range, outside temp) defined in _TRACE_LABELS near the top of gui_client.py.

CLI test client (client.py)

python 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%