Windrose Technology · Open Vehicle Data

How to Read a Truck

A truck describes itself thousands of times a second, and almost nobody can read it. We are publishing the file that makes it legible for the Windrose E700 platform — the half that lets you read the vehicle, not the half that lets you drive it. Free, for anyone, with a fifty-dollar adapter.

The controllers of one truck, in their real positions, each wired to the gateway. Drag to turn it. The three buses highlighted in green are the ones in the database published here.

What the wire carries
  
Address

Twenty-nine bits, not bytes. Who is speaking and what about. Identical in every one of these frames, and the bus itself reads it to decide who goes first.

Content

Eight bytes — sixty-four switches. What the controller is actually reporting. Different in the next frame, ten milliseconds later.

Every pair is clickable — tap one to see what those eight switches say.

With the database
Motor speed
2,400 rpm
Actual torque
1,200 N·m
Available torque limit
500 N·m
Motor mode
Torque mode
IGBT gate state
Gate ON
HV loop status
OK
Fault class
No fault

Same eight bytes. The difference is a 42 KB text file. Every truck on the road broadcasts frames like this a thousand times a second, and almost none of them can be read by the person who owns the truck.

19,700values per second
10 msfastest message — 100 Hz
Apache-2.0licence

Why — The bus was never the boundary

The reason for doing this

A CAN bus is a pair of twisted wires that every module on the vehicle shouts onto. It has no access control and never has. Anyone with a fifty-dollar adapter and a paperclip can listen to all of it.

What they cannot do is understand it — because the file that says which bits mean what has always stayed with the manufacturer. That is the whole control: not a lock on the wire, a dictionary kept in a drawer.

Which makes the status quo strange when you say it plainly. The operator owns the truck, the truck describes itself continuously, and the operator cannot read the description. They buy a subset back — a telematics box forwarding perhaps twenty signals once every ten seconds, out of the several hundred the vehicle is already broadcasting a hundred times a second.

We already publish the CAD for this vehicle. This is the same idea one layer up: if you own the machine, you should be able to read what it says about itself.

What — It moves the line to where it belongs

What it actually changes

The interesting part is not that data becomes available. It is where the security boundary ends up.

Withholding the dictionary was never a real control — it is obscurity, and it fails against anyone motivated enough to spend a fortnight with a logic analyser. Meanwhile it fails completely in the other direction: it stops the legitimate owner, the independent workshop and the fleet engineer, every single time.

Splitting the database by direction rather than by document puts the boundary somewhere defensible. Reading a vehicle never changes it; commanding one does. The read half is published. The write half — torque, gear and gate commands, and the checksum and rolling-counter rules that make a forged command acceptable — stays closed, and now it is closed for a reason rather than by default.

DomainMessagesSignals
Battery — cell voltages, temperatures, SOC, pack current3109
Motor & inverter — speed, torque, phase current, temperatures1692
Vehicle state — speed, odometer, gear, ratio, hours1088
Gearbox — output shaft speed, shift status, fault registers1069
HV distribution & insulation resistance240
Brakes & individual wheel speeds329
Vehicle alarm bitmap119
Thermal management312
Total48458

Deliberately not included

  • Command messages — torque, speed, direction, gate, gear
  • Diagnostic services, security access, flashing routines
  • Checksum and rolling-counter definitions — 42 signals removed
  • Third-party supplier diagnostic specifications

The last one is not our decision to make. Communication matrices for bought-in brake, suspension and steering systems belong to those suppliers and are covered by technical agreements. Any honest open-data release from a vehicle manufacturer has this boundary in it.

What this is worth in practice: a workshop with a sixty-dollar adapter can watch motor speed, gearbox output shaft speed and wheel speed at once, and tell a controller fault from a motor fault from a broken axle — without flying anyone in, and without a tool that has no distributor on their continent.

Anatomy — How eight bytes become seven facts

The whole mechanism, in one frame

There is no encryption here and no key. A signal is defined by four numbers: where it starts, how long it is, what to multiply it by, and what to add. That is the entire trick.

First — what a byte is

A wire can only be in two states: on or off. Write them 1 and 0. That is the whole vocabulary of a truck — a long row of switches, nothing else.

The truck never sends them one at a time. It sends them in eights:

10001111

Eight switches is a byte, and a byte has 256 possible settings — 0 to 255. Those eight above are byte 3 of the frame at the top of this page. The byte is the unit that actually exists on the wire: nothing smaller is ever transmitted on its own.

It is also not a truck convention. A byte is the same unit a computer uses, which is the only reason a fifty-dollar adapter and a laptop can read a truck at all — the two already speak in the same currency. A classic CAN frame is eight of them: sixty-four switches, and nothing else.

So why C0 and not 192

Because a byte is one digit in base 256 — and there is no alphabet of 256 characters to write such a digit with. Ten symbols is all any ordinary number system has.

So the byte gets cut in half instead. Half a byte is four switches, and four switches have only sixteen settings — and sixteen symbols we can manage: the ten digits, plus six letters borrowed at the point where the digits run out. That is all a letter in the middle of a number means here.

Half a byteWritten outCounts asOne character
000000all four off — the smallest half-byte there is
000111only the last switch on
001022
001133
010044
010155
011066
011177
100088
100199the last ordinary digit — decimal has nothing after this
101010Aten. We are out of digits, so the letters start here
101111B
110012C
110113D
111014E
111115Fall four on — and two of these make a full byte, 255

So F is not a letter here. It is the number fifteen, written in one character. This counting system is called hexadecimal, hex for short, because it counts in sixteens.

Two of those characters cover a whole byte exactly, with nothing left over, because 16 × 16 = 256. Read C0 as two halves: C is 1100, 0 is 0000, so C0 is 1100 0000 — the 192nd of the byte's 256 settings. The machine counts in 256s; hex is only how we write it down. And eight bytes is exactly one CAN frame: the sixteen hex characters at the top of this page are the sixty-four switches below.

So how does 0xA410 become 42,000

Exactly the way 42,000 works in ordinary decimal: each step to the left is worth more than the one before it. In decimal each step is worth ten times the last. Here each step is worth sixteen times the last — that is the only difference.

CharacterCounts asPlace is worthSo it contributes
A1016³ = 4,09640,960
4416² = 2561,024
1116¹ = 1616
0016⁰ = 10
0xA41042,000

Or count it a byte at a time instead, and the answer has to come out the same, because it is the same sixteen switches grouped differently:

0xA4 is 164, 0x10 is 16, and 164 × 256 + 16 = 41,984 + 16 = 42,000. Base 16 four times over, or base 256 twice — the switches do not know the difference.

And the number in front — 0x18012774

The eight bytes are the contents. The number printed in front of them is the address on the envelope. Every controller on the wire reads it first and decides whether the rest is any of its business. The two are not the same kind of thing at all:

1801277400 10 C0 8F …
What it isAn addressThe contents
How wide29 bits — written as 8 hex characters because that fills a 32-bit register, but the top 3 are padding and never go on the wire8 bytes — 64 bits, and always a whole number of bytes
Is it bytes?No. Only the bottom three of its fields land on byte boundaries; the priority sits in the top 3 bits of a byte it does not fillYes. The byte is the unit; signals are then cut out of the bits inside
Does it change?Never, for a given message. This one is 0x18012774 every 10 ms for the life of the truckEvery frame. That is the entire point of sending it again ten milliseconds later
Who reads itThe bus itself. Two controllers starting at once resolve it bit by bit, and the lower number wins — no collision, no retryOnly the controller the message is for, and anyone else listening
Needs the database?No. Its layout is fixed by the standard, the same on every J1939 vehicleYes. Without it the eight bytes are eight numbers between 0 and 255
In the DBC fileThe BO_ line — one per messageThe SG_ lines under it — one per signal

Neither group is the whole frame, incidentally. On the wire there is also a length field, a CRC, an acknowledgement slot and stuffing bits — about 110 bits of traffic to carry 64 bits of payload. Those are the controller’s business, not the database’s, and no analyser shows them to you.

The address is read two characters at a time, and each pair answers a different question:

18priority 6

of eight. Lower wins the wire when two controllers talk at once — the brake messages in this file are priority 2.

01message no. 1

this sender's first message. Its Msg2, Msg3 and Msg4 carry temperatures, currents and counters.

27to the VDC

address 39 — the vehicle domain controller, which is who this report is for.

74from MCU1

address 116 — the first motor controller. MCU2 is 117, MCU3 118, MCU4 119.

So 0x18012774 says: motor controller 1, reporting to the vehicle controller, message one, at ordinary priority. Change the last character and you get 0x18012775 — the same message from the second motor. Both are in the published file, which is why the four e-axles read identically and differ only in that last byte.

The same frame, one switch at a time
00byte 0
00000000
10byte 1
00001000
C0byte 2
00000011
8Fbyte 3
11110001
10byte 4
00001000
A4byte 5
00100101
DCbyte 6
00111011
42byte 7
01000010
motor speed torque torque limit mode fault class IGBT HV loop direction, damping, discharge empty — the checksum was removed
Reading the sixteen switches marked “motor speed”
1 The switches

Bits 16 to 31 — bytes 2 and 3. Byte 3 is the high half, byte 2 the low half. That ordering is called little-endian, and the database says which one a signal uses.

1000 1111 · 1100 0000
2 As one plain integer

Those sixteen switches, read as a single binary number. Nothing has been interpreted yet — this is not a speed.

36,800
3 Apply the two numbers the database gives

Scale 0.5, offset −16,000. Every signal has a pair like this.

36,800 × 0.5 − 16,000
4 The physical value

Now it means something.

2,400 rpm
Why not just send the number 2,400?
The offset exists so the value can go negative.

Sixteen switches can only hold 0 to 65,535 — never below zero. But the motor turns both ways. So the zero point is moved to the middle of the range.

032,00065,535
−16,000 rpm0 rpm+16,768 rpm
The scale trades range against resolution.

65,536 steps × 0.5 covers about 32,768 rpm at half-rpm resolution. A scale of 1 would double the range and halve the precision. The designer picks the pair; the database records it.

Frame 0x18012774 · MCU1 · every 10 ms
00  10   C0   8F   10   A4   DC   42
byte 0   1    2    3    4    5    6    7

Underlined terms explain themselves — click one. Each idea is explained where it first appears.

Motor speed — bytes 2–3
byte 2 = , byte 3 =       = 
36,800 ×  + ()     =  
          scale     offset
Actual torque — bytes 4–5
byte 4 = 10, byte 5 = A4     little-endian  →  0xA410 = 42,000
42,000 × 0.1 + (−3,000)      =  1,200 N·m
Available torque limit — byte 6
byte 6 = 
220 × 5 + (−600)             =  500 N·m
Byte 7 — four states in one byte
byte 7 = 42 = 

    0010  =  2   →  motor mode      Torque mode
  bits 60–61    00  =  0   →  fault class     No fault
  bit  62        1        →  IGBT gate       ON — closed
  bit  63        0        →  HV loop         OK

Byte 0 is empty on purpose. That is where the message checksum sits. It is one of the 42 signals removed from the published file — you can read the frame, but the file does not tell you how to forge one.

Budget — Why sixteen bits, and not eight or thirty-two

Two questions people ask, and they are different questions

Why write it in hex rather than ordinary decimal? Because the machine counts in 256s — a byte at a time — and sixteen is the only convenient window onto that. 256 = 16², so one byte is exactly two hex characters, every time, with no remainder. Decimal never lines up: a byte holds 0–255, which needs three decimal digits, but three decimal digits reach 999 — three quarters of the room wasted, and no visible seam between one byte and the next. You can see two separate bytes in C0 8F. You cannot see them at all in 192 143.

Why sixteen bits for the speed? That one is not a convention. It is arithmetic:

WidthStepsResolution over ±16,000 rpmVerdict
8 bits256128 rpmA 100 rpm drop would be invisible
10 bits1,02432 rpmStill too coarse to diagnose with
12 bits4,0968 rpmUsable for display, not for control
16 bits65,5360.5 rpmChosen — and the scale lands on a round 0.5
32 bits4.3 billion0.0000076 rpmAbsurd — and it wastes sixteen bits someone else needed

That last row is the real constraint. A classic CAN frame carries sixty-four bits and no more. Precision bought for one signal is precision taken from another. This frame is exactly full:

Frame 0x18012774 — the whole budget
Motor speed16
Actual torque16
Available torque limit8
Motor mode4
Fault class2
Discharge state2
Rotation direction1
Damped control1
IGBT gate1
HV loop1
Data52
Checksum (removed from this release)8
Rolling counter (removed)4
Frame64

So a signal is never given a round number of bits out of habit. The width is ⌈log₂(range ÷ resolution)⌉, and the proof that this is done signal by signal is that the same database uses nine different widths — 1, 2, 3, 4, 5, 8, 12, 16 and 32 bits.

SignalWidthRangeResolutionWhy that width
AC phase current12±1,024 A0.5 A2,048 ÷ 0.5 = 4,096 = 2¹²
DC-link voltage120–2,047.5 V0.5 VSame arithmetic, same answer
Gearbox output shaft speed12±1,000 rpm0.5 rpmBehind the reduction gear — an order of magnitude slower than the motor, so four bits are handed back
Shift status38 statesEnough to number the states, nothing more
IGBT gate1open / closedOne switch answers the question

Motor speed at sixteen bits and gearbox output shaft speed at twelve is the pair that shows it best. Both are speeds. One sits before the reduction gear and one after, so one needs a range an order of magnitude larger — and the four bits saved go to somebody else in the same sixty-four.

Scale — Roughly twenty thousand values a second

How much data this actually is

The file is 42 KB. What it unlocks is not.

19,700signal values per second
140 MBper hour, logging everything
10 msfastest message — 100 Hz
22 / 48messages at 20 ms or faster — 50 Hz+

For comparison: the regulatory telematics box on the same vehicle uplinks on the order of a hundred values every ten seconds. This is roughly three orders of magnitude more resolution — on data the truck was already broadcasting to nobody.

Kind of signalCount
Status and mode flags — including 65 single-bit151
Counts, codes, versions, identifiers109
Temperature — °C58
Voltage — V43
Rotational speed — rpm22
Torque — N·m20
Current — A18
Vehicle speed — km/h13
Power — kW10
Percentage — state of charge, load, duty8
Distance, insulation resistance, pressure, consumption6

Reach — What the truck says, what a fleet box hears

Where the 458 signals sit inside the whole vehicle

The published file is one read channel. The vehicle itself carries about twenty CAN buses under four domain controllers, and the numbers below are counted from the full internal signal matrix, not from this file.

5,597signals on the whole truck — 565 messages, 79 transmitting nodes
3,459of them are telemetry — battery, charging, motors, thermal, brakes, body, faults
66messages a fleet telematics box sees today on the standard FMS connector
458signals in this open file — 48 messages, the read channel
What is on the truckMessagesSignalsWhere it lives
Telemetry — every measured state and fault3463,4592,410 on classic CAN, 1,049 on CAN FD
Perception — camera and radar object lists531,924CAN FD, ADAS domain — not fleet data
Diagnostics and commands — UDS, control requests166214Write path — stays private by design
Total5655,597

The gap that matters is the third tile. A fleet box plugged into the FMS connector is classic CAN — eight-byte frames at 250 kbit/s — and the vehicle’s richest data (battery alarms, cell temperatures, charging state, cumulative energy) travels in CAN FD frames of up to 64 bytes that such a box physically cannot receive. So today it hears 66 messages out of 565.

We are closing that gap from the vehicle side. The vehicle controller will repack the FD content into standard eight-byte frames and broadcast the full telemetry set on the FMS connector: 3,459 signals in about 331 frames, fast dynamics at 10 Hz and everything else at 1 Hz, which fits in 17–41 % of the connector’s bandwidth. The decoding file for those frames will be published here in the same DBC format, so the truck stays compatible with every classic-CAN telematics device already in service. To see how the buses and gateways connect inside the vehicle, open the Truck CAN Meridian.

Reuse — Some of it works on any truck

Whether this is useful beyond our vehicles

Eleven of the forty-eight messages are standard SAE J1939. Those 57 signals are defined by the standard rather than by us, and they decode on any J1939 commercial vehicle — truck, bus, trailer or off-highway machine, whoever built it. Speed, distance, torque, gear, wheel speeds and brake state are all in there.

MessagePGN standard numberPeriodSignalsWhat it carries
EBC161441100 ms18Brake control — ABS and traction control active flags, brake pedal position, brake switch, retarder
ETC16144210 ms5Driveline — output and input shaft speed, driveline engaged, shift in process
EEC26144350 ms3Pedal — accelerator position, low-idle switch, percent load at current speed
EEC16144420 ms4Torque and speed — actual and driver-demanded percent torque, motor speed
ETC261445100 ms3Gear — selected gear, current gear, actual gear ratio
TCO16513250 ms2Tachograph — vehicle speed, output shaft speed
HRW6513420 ms4Wheel speeds — all four wheels, individually
EBC26521550 ms7Axle speeds — front axle speed plus per-wheel relative speed on three axles
VDHR652171 s2Distance — total vehicle distance and trip distance, high resolution
EEC365247250 ms2Losses — nominal friction torque, estimated parasitic losses
CCVS65265100 ms7Vehicle state — wheel-based speed, park brake, brake switch, cruise control, PTO
Standard SAE J1939 — decodes on any commercial vehicle57

The remaining 37 messages and 401 signals are ours: our message IDs, our bit layouts, our network design. They will not decode anything on another manufacturer's vehicle — and by the same token, nothing in this file is a security concern for anybody else's product.

Within our own range this is the E700 platform matrix. The regional variants share the great majority of it; charging, some driver assistance and regional telematics differ. Accurate for the platform — verify the market-specific messages against the vehicle in front of you.

We could not find another vehicle manufacturer that has published its own production CAN database. The closest things that exist are community reverse-engineering projects — whose own documentation warns the files “should be regarded as completely untrustworthy” — and industry standard subsets, which are not any one manufacturer’s matrix. If you know of a counterexample, we would genuinely like to see it.

How hard — Four things that were genuinely difficult

What the work actually consisted of

Publishing a file is easy. Deciding what belongs in it is not, and most of the effort went there rather than into the release.

  1. The line does not fall between documents

    The first instinct is to publish some files and withhold others. That fails immediately: the same message set contains both what the vehicle reports and what the vehicle is told. The split had to be made inside the files, by direction of information flow — message by message rather than folder by folder.

  2. The write path hides in small signals

    Removing the obvious command frames is not sufficient. Nearly every safety-relevant message carries a checksum and a rolling counter, and their definitions are precisely what separate a valid command from a rejected one. Forty-two such signals had to come out — none of them interesting to read, all of them load-bearing for anyone trying to write.

  3. Not all of it is ours

    A vehicle is an assembly of other companies' engineering. The diagnostic specifications for the brake, suspension and steering electronics arrived under technical agreements and cannot be redistributed, however much we would like the release to be complete. What we publish is what we designed.

  4. The source was less authoritative than expected

    Bus bit rates turned out not to exist anywhere in the communication matrix — they live only in the legend of a network topology drawing. Connector pin numbers were unreadable until the drawing was rendered at 800 dpi, and two revisions of it disagreed. The human-readable labels in the machine-readable source had been corrupted and had to be rewritten. Publishing forces a level of verification that internal use quietly tolerates skipping, which is on its own a good argument for publishing.

Use — Any tool that reads a DBC

Getting started

The format is DBC — plain text, defined by Vector in the 1990s, understood by every CAN tool in existence: SavvyCAN, BusMaster, CANoe, TSMaster, python-can.

import cantools, can

db  = cantools.database.load_file('E700_Open_Telemetry.dbc')
bus = can.Bus(channel='can0', interface='socketcan')   # listen-only

for msg in bus:
    try:
        print(db.decode_message(msg.arbitration_id, msg.data))
    except KeyError:
        pass

Configure the interface in listen-only / silent mode. This database describes a read channel; a tool that transmits on a live vehicle bus can disturb it regardless of what it sends.

Glossary — The words used above

Plain definitions

BitOne switch: on or off, written 1 or 0. It is the only thing that physically exists on the wire. Everything else on this page is a way of grouping bits so a person can read them.
ByteEight bits taken together, holding one of 256 settings, 0 to 255. The byte is the unit that is actually transmitted — nothing smaller ever travels on its own — and it is the same unit a computer uses, which is why ordinary computer hardware can read a truck at all.
Base 256What a multi-byte number really is. In a two-byte number the high byte is worth 256 of the low byte, exactly as a tens digit is worth ten of a units digit: 0xA4 × 256 + 0x10 = 42,000.
HexadecimalCounting in sixteens, and the way bytes are written down. There is no alphabet of 256 characters, so a byte is split in half and each half — four bits, sixteen possible settings — gets one character: the ten digits, then A to F for ten through fifteen. Two characters cover a byte exactly, because 16 × 16 = 256.
FrameOne complete transmission on the wire: the identifier, the data, and the machinery around them — a length field, a checksum, an acknowledgement slot. A classic CAN frame spends about 110 bits to deliver 64 bits of data. Only the identifier and the data concern the database.
PayloadThe data half of a frame — the eight bytes. The half that changes from one frame to the next, and the half that needs the database to mean anything.
ArbitrationHow the bus settles two controllers talking at once. They transmit their identifiers simultaneously and compare bit by bit; the lower number wins and the other stops and waits. Nothing is lost and nothing is retried — which is why the identifier carries a priority at all.
Byte orderWhich half of a two-byte number comes first. Little-endian puts the low byte first, so bytes C0 8F assemble into 0x8FC0, not 0xC08F. Every signal in the database records its order, because getting it backwards is silent: the same two bytes would read 8,647 rpm instead of 2,400.
Scale & offsetThe two numbers that turn a raw count into a reading. physical = raw × scale + offset. The scale says what one step is worth; the offset says where zero sits, and is what lets a value go negative when the switches themselves cannot.
Bit fieldA signal narrower than a byte. Signals do not have to stop at byte edges — the database says where each one starts and how many bits it occupies, so a single byte can carry a 4-bit mode, a 2-bit fault class and two separate flags.
CAN busTwo twisted wires that every electronic module on the vehicle shares. Each module shouts short messages onto it; everyone hears everything. There is no addressing in the postal sense and no access control.
MessageOne transmission on that wire: an identifying number followed by its data — eight bytes on classic CAN, up to 64 on CAN FD. A truck sends thousands per second.
CAN IDThe number at the front of a message. It says who is speaking and what about — not who should listen. Written in hexadecimal, e.g. 0x18012774.
SignalOne measurement packed inside a message. Motor speed might occupy bits 16–31 of a particular message; torque the next sixteen. One message typically carries several signals.
DBCThe database file — the dictionary. It records which CAN ID is which message, which bits inside are which signal, what to multiply them by, and what unit comes out. Plain text. This is the thing being published.
J1939An industry standard from SAE that defines a common set of messages for heavy commercial vehicles, so that a brake supplier and an engine supplier can understand each other without a private agreement. It is why some of this file works on anyone’s truck.
PGNParameter Group Number. J1939’s catalogue number for a standard message. PGN 65134 is defined by the standard as the four individual wheel speeds — on every compliant vehicle, from any manufacturer. A message with a PGN is public knowledge; a message without one is the manufacturer’s own.
CAN FDA faster version of the same bus — up to 64 bytes per message instead of 8, and a quicker data phase. Older hardware physically cannot receive these messages.
Period / rateHow often a message repeats. A 10 ms period means a hundred times a second — 100 Hz. Shorter period, higher rate, finer detail.
Listen-onlyA mode in which the interface receives but never transmits — not even the acknowledgement a CAN controller would normally send. The safe way to attach anything to a working vehicle.
Download

github.com/Windrose-Electric/windrose-open

dbc/E700_Open_Telemetry.dbc — 42 KB · Apache-2.0 · no account needed

Windrose Technology · E700 platform github.com/Windrose-Electric/windrose-open Apache-2.0