Add README.md and conversation_recap.md
README covers installation, collector CLI reference, push server protocol, GUI client usage, and output format. conversation_recap documents the full development history: features, bugs fixed, and design decisions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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`)
|
||||
|
||||
```json
|
||||
{
|
||||
"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:
|
||||
|
||||
```json
|
||||
{
|
||||
"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`)
|
||||
|
||||
```bash
|
||||
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`)
|
||||
|
||||
```bash
|
||||
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.
|
||||
Reference in New Issue
Block a user