Viessmann E3 CAN-bus monitor – Collect and Service 77 protocol decoder
Project description
e3candump
A command-line tool for monitoring Viessmann-specific E3 CAN-bus traffic — one abstraction layer above candump.
While candump shows raw CAN frames, e3candump works at the protocol level: it reassembles multi-frame messages and outputs one decoded line per event for two Viessmann-specific protocols invisible to generic UDS tools:
- Collect — autonomous broadcast of data-point values (no request needed)
- Service 77 — proprietary protocol for protected data points: client writes, device-initiated push notifications, and client reads
For standard UDS traffic on the same bus, see the sibling tool udsdump.
The tool is entirely passive — it never writes to the CAN bus.
11:04:25.131 COLLECT 0x0693 DID=0x0140 (320) len=9 MF
11:04:25.209 COLLECT 0x0693 DID=0x0141 (321) len=2 SF
11:04:25.140 S77-WRITE HPMUMASTER DID=0x044D (1101) CTR=0x7540 len=3 dt=2.0ms SF/SF ok
11:04:25.141 S77-WRITE HPMUMASTER DID=0x044D (1101) CTR=0x7540 len=3 dt=1.8ms SF/SF ok
11:04:25.143 S77-PUSH HPMUMASTER DID=0x044D (1101) len=3 SF
11:04:25.144 S77-PUSH VCMU DID=0x018C (396) len=2 SF
11:04:25.150 S77-READ VX3 DID=0x0509 (1289) CTR=0x3634 len=181 dt=3.2ms MF/MF ok
11:04:26.200 S77-WRITE HPMUMASTER DID=0x044D (1101) CTR=0x7541 len=3 dt=5.0ms SF/SF timeout
Features
- One line per event — Collect frames and Service 77 write/read/push/session events, each on a single line
- Multi-frame reassembly — handles Viessmann's Collect framing and standard ISO-TP (Service 77) transparently;
SF/MFin the output shows the frame type - CAN-ID disambiguation — shared IDs (e.g.
0x693carries both Collect and S77 traffic) are resolved correctly using ISO-TP state. Important: configure--s77-pairfor every CAN-ID that carries S77 traffic. Without it, S77-PUSH continuation frames (byte0x21) are structurally identical to Collect first frames and will be misidentified as Collect first frames, producing spurious Collect events. - Device names — integrates with open3e
devices.jsonto show device names instead of raw CAN-ID pairs - Configurable pairs — S77 channel pairs can be loaded from
devices.jsonand/or specified explicitly with--s77-pair - Output filters — suppress Collect, S77-PUSH, S77-READ, or S77-WRITE events independently
- Optional raw payload —
--payloadappends the reassembled data bytes as hex - JSON output —
--jsonfor machine-readable output, suitable for piping tojq
Requirements
- Python 3.10+
- python-can ≥ 4.3
- A CAN interface supported by python-can (SocketCAN, PEAK, Kvaser, virtual, …)
Installation
pip install e3candump
For local development, clone the repository and install in editable mode:
git clone https://github.com/MyHomeMyData/e3candump.git
cd e3candump
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
Quick Start
Monitor on vcan0 with default settings (SocketCAN, Collect IDs 0x451 and 0x693):
e3candump --channel vcan0
Monitor a real Vitocal 250 on can0, with open3e device names:
e3candump --channel can0 --devices
Explicit S77 pairs and Collect IDs:
e3candump --channel can0 --s77-pair 0x682:0x692 --s77-pair 0x683:0x693 --collect-id 0x451 --collect-id 0x693
JSON output, filtered with jq:
e3candump --channel can0 --devices --json | jq 'select(.type == "s77_write")'
Show only Service 77 write transactions:
e3candump --channel can0 --devices --no-collect --no-s77-push
CLI Reference
e3candump [options]
CAN interface:
--interface, -i INTERFACE python-can interface name (default: socketcan)
--channel, -c CHANNEL CAN channel (default: vcan0)
Collect configuration:
--collect-id ID CAN-ID for Collect broadcasts (hex).
May be repeated. Default: 0x451, 0x693
Service 77 configuration:
--devices [FILE] Load open3e devices.json to auto-configure S77
pairs and device names. Without a value, reads
'devices.json' in the current directory.
--s77-pair REQ:RSP S77 request:response CAN-ID pair (hex).
May be repeated. Additive to --devices.
Behaviour:
--timeout, -t SECONDS S77 write response timeout in seconds (default: 1.0)
Output:
--json One JSON object per line instead of text
--payload Append raw payload bytes (hex) to each line
--verbose, -v Show S77 session frames (0x21/0x22 keepalives)
--no-collect Suppress Collect event output
--no-s77-push Suppress S77-PUSH event output
--no-s77-read Suppress S77-READ event output
--no-s77-write Suppress S77 write/confirm event output
Output Format
Text (default)
Collect event:
HH:MM:SS.mmm COLLECT CAN_ID DID=0xNNNN (DDD) len=N FT
Service 77 write/confirm:
HH:MM:SS.mmm S77-WRITE DEVICE_or_IDs DID=0xNNNN (DDD) CTR=0xNNNN len=N dt=N.Nms FT status
Service 77 read/confirm:
HH:MM:SS.mmm S77-READ DEVICE_or_IDs DID=0xNNNN (DDD) CTR=0xNNNN len=N dt=N.Nms FT status
Service 77 device push (CTR is always 0x0000 — omitted):
HH:MM:SS.mmm S77-PUSH DEVICE_or_IDs DID=0xNNNN (DDD) len=N FT
| Field | Description |
|---|---|
HH:MM:SS.mmm |
Timestamp |
COLLECT / S77-WRITE / S77-READ / S77-PUSH |
Event type |
CAN_ID / DEVICE_or_IDs |
CAN-ID for Collect; device name or REQ→RSP hex pair for S77 |
DID=0x… (DDD) |
Data Identifier in hex and decimal |
CTR=0x… |
Session counter (S77 write and read) |
len=N |
Reassembled payload length in bytes |
dt=N.Nms |
Round-trip latency (S77 write and read); absent on timeout |
FT |
Frame type: SF (single) or MF (multi); REQ/RSP for S77 showing both directions |
status |
ok or timeout (S77 write and read) |
With --payload, the reassembled data bytes are appended as hex: data=de ad be ef.
With --verbose, S77 session keepalive frames are also shown as S77-SESSION lines.
JSON
Each event is a JSON object on a single line. Only non-empty fields are included.
Collect:
{"timestamp": 1746789865.131, "type": "collect", "can_id": 1683, "did": 320, "data_length": 9, "frame_type": "MF"}
S77 write:
{"timestamp": 1746789865.140, "type": "s77_write", "request_id": 1666, "response_id": 1682, "session_ctr": 29952, "status": "ok", "device": "HPMUMASTER", "did": 1101, "data_length": 3, "req_frame_type": "SF", "rsp_frame_type": "SF", "duration_ms": 2.0}
S77 read:
{"timestamp": 1746789865.150, "type": "s77_read", "request_id": 1089, "response_id": 1105, "session_ctr": 13876, "status": "ok", "did": 1289, "data_length": 181, "req_frame_type": "MF", "rsp_frame_type": "MF", "duration_ms": 3.2}
S77 push:
{"timestamp": 1746789865.143, "type": "s77_push", "request_id": 1666, "response_id": 1682, "session_ctr": 0, "status": "push", "device": "HPMUMASTER", "did": 1101, "data_length": 3, "rsp_frame_type": "SF"}
Integration with open3e
open3e and ioBroker.e3oncan use a devices.json file that maps device names to their UDS addresses. e3candump can read this file to auto-configure S77 channel pairs and display human-readable device names:
e3candump --channel can0 --devices /path/to/devices.json
The S77 channel pair for each device is derived from the tx field:
- Request channel:
tx + 0x02 - Response channel:
tx + 0x12
The device name is taken from the prop field. Pairs configured via --devices and --s77-pair are combined — --s77-pair can add pairs not present in devices.json.
When --devices is used, a status line is printed to stderr on startup:
e3candump: devices: loaded 5 device(s) from devices.json
Related Projects
- udsdump — sibling tool for standard UDS traffic on CAN
- open3e — Viessmann E3 data-point library
- ioBroker.e3oncan — ioBroker adapter for Viessmann E3 heat pumps
- E3onCANserver — Viessmann E3 simulator for offline testing
Development
# Install with dev dependencies
pip install -e .
pip install pytest
# Run tests
pytest
54 tests cover the Collect decoder, the Service 77 decoder, the ISO-TP reassembler, the output formatter, and the device name loader — no CAN hardware required.
Changelog
0.1.2 — 2026-05-19
- Published to PyPI; GitHub Actions for CI and automated publishing
0.1.1 — 2026-05-13
- Service 77 read decoder: client read request (
41 01 82marker) matched to device response (42 01 82), with timeout detection --no-s77-readoutput filter- Fix: short S77 pushes where the data byte has high nibble <
0x8no longer cause a crash or missing payload - 54 tests
0.1.0 — 2026-05-12
- Initial release
- Collect decoder: SF and MF reassembly, Viessmann-specific length encoding including
0xC1escape and0x8x/0xBxvariants - Service 77 decoder: client write with timeout detection, device-initiated push (CTR=0x0000), session keepalive frames (
--verbose) - CAN-ID disambiguation for shared IDs (e.g.
0x693carries both Collect and S77) --devicesto auto-configure S77 pairs and device names from open3edevices.json--s77-pairfor explicit S77 channel pairs--collect-idfor configurable Collect CAN-IDs--no-collect,--no-s77-push,--no-s77-writeoutput filters- JSON output (
--json), raw payload option (--payload) - 50 tests
License
MIT License
Copyright (c) 2026 MyHomeMyData juergen.bonfert@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file e3candump-0.1.2.tar.gz.
File metadata
- Download URL: e3candump-0.1.2.tar.gz
- Upload date:
- Size: 26.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f2fa6575b3cf196a75975aabc9fe83adab5868da7843810f940351fc21a79bc0
|
|
| MD5 |
2e48d777017d6ec87bc3d851ea71244e
|
|
| BLAKE2b-256 |
fc7ffe238165aa22836833cba605f90f7f0e598e765fafb266cef468aea577da
|
Provenance
The following attestation bundles were made for e3candump-0.1.2.tar.gz:
Publisher:
publish.yml on MyHomeMyData/e3candump
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
e3candump-0.1.2.tar.gz -
Subject digest:
f2fa6575b3cf196a75975aabc9fe83adab5868da7843810f940351fc21a79bc0 - Sigstore transparency entry: 1573687029
- Sigstore integration time:
-
Permalink:
MyHomeMyData/e3candump@644f1e4bb94242daa04d2c548ad887aca629d93c -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/MyHomeMyData
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@644f1e4bb94242daa04d2c548ad887aca629d93c -
Trigger Event:
push
-
Statement type:
File details
Details for the file e3candump-0.1.2-py3-none-any.whl.
File metadata
- Download URL: e3candump-0.1.2-py3-none-any.whl
- Upload date:
- Size: 19.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5e4adfee3613b061f96d958480cb34a80763c284fc2468ae9232428e3271d48f
|
|
| MD5 |
afa8e99cd3a89e5734536ce4a7472552
|
|
| BLAKE2b-256 |
e9eebd8f6ecf5497b914c36c732d0471f92213c8c5dac225c767232803cb96e2
|
Provenance
The following attestation bundles were made for e3candump-0.1.2-py3-none-any.whl:
Publisher:
publish.yml on MyHomeMyData/e3candump
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
e3candump-0.1.2-py3-none-any.whl -
Subject digest:
5e4adfee3613b061f96d958480cb34a80763c284fc2468ae9232428e3271d48f - Sigstore transparency entry: 1573687043
- Sigstore integration time:
-
Permalink:
MyHomeMyData/e3candump@644f1e4bb94242daa04d2c548ad887aca629d93c -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/MyHomeMyData
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@644f1e4bb94242daa04d2c548ad887aca629d93c -
Trigger Event:
push
-
Statement type: