What BEAN-DBC actually is
BEAN-DBC is a project-specific JSON database used by BEANalyzer UltraPro 5. It is conceptually inspired by the role of a DBC, but it is not a standard Vector CAN .dbc file.
The application normally uses a JSON database such as config/bean_dbc_default.json. A BEAN-DBC file can identify messages, assign names, describe signals, define formulas and units, preserve engineering metadata and evidence, and optionally provide transmission templates for Lab Workbench.
Do not force CAN DBC assumptions onto BEAN-DBC. Treat the BEANalyzer implementation and JSON schema described here as the authority.
{
"name": "My BEAN Database",
"version": "1.0",
"description": "Minimal example",
"plausible_dids": ["FE"],
"messages": [
{
"name": "Vehicle speed",
"did": "FE",
"mid": "24",
"category": "vehicle",
"function": "vehicle_speed",
"doc_status": "EXPERIMENTAL",
"signals": [
{
"name": "speed",
"kind": "u8",
"offset": 0,
"unit": "km/h"
}
]
}
]
}
Find DATA before you define signals
A captured physical frame can include interface/SOF marker, BEAN header/context, DID, MID, DATA, CRC, EOM and a post-EOM response byte. BEANalyzer separates these fields before giving DATA to the decoder when the physical frame validates correctly.
offset begins at DATA, not at the first captured byte. In the frame above, DATA[0] = 0x40, so a signal in that byte uses "offset": 0.
The BEAN header used by BEANalyzer combines priority and ML. Conceptually, bits 7..4 are priority and bits 3..0 are ML. ML counts DID + MID + DATA, therefore DATA length = ML - 2. The current implementation treats ML 3..13 as the normal range, giving 1..11 DATA bytes.
Keep the database simple and explicit
The two most important top-level elements for decoding are plausible_dids and messages. Metadata such as name, version, description and notes makes the file understandable and traceable.
plausible_dids
Used when a message definition does not declare a fixed DID. If the DID is already known, define it explicitly to reduce false matches.
messages
The central array. Each object represents one BEAN message interpretation, including its identity, signals, evidence and optional TX templates.
Use double-quoted strings, no trailing comma on the final item, and no // or /* */ comments. Put engineering notes in real fields such as notes.
DID + MID is the base identity. Context can disambiguate it.
A message normally declares hexadecimal did and mid strings. The same DID/MID pair can still mean different things under different BEAN headers, so BEANalyzer also supports context, header or bean_header as equivalent context declarations.
Use descriptive metadata such as category, function, source, source_ecu, doc_status, example, notes and references. These fields are valuable even when they do not participate directly in decoding.
Choose the signal kind that matches the data
Each item in signals describes how to interpret one or more bytes inside DATA. The current decoder supports the following signal kinds.
u8Unsigned single-byte valueoffset, optional formulau16beTwo-byte big-endian valueoffset, optional formulaboolOne specific bitoffset + hex maskbool_exprBoolean state requiring an expressionoffset + formulaflagsIndependent bits sharing one byteflags mapmapMutually exclusive enumerated valuesmap objectconstantThe message presence is itself meaningfulvaluemap is recommended for new enumerations; the decoder also keeps compatibility with the historical values form. A bool mask is hexadecimal: 01, 02, 04, 08, 10, 20, 40, 80.
unit, card, plot
Use unit for the physical unit, card to associate a dashboard card, and plot: true when the signal is a candidate for graphing.
special_values
Use named exceptional raw values only with the behavior supported by the current decoder. At present, the documented path applies them to u8 signals with a formula; test this pattern before extending it.
The current route does not natively provide u16le, s8, s16 or float32. Extend the decoder explicitly when the real data requires a new type.
formula transforms RAW into the physical value
For numeric signals, raw is the value extracted before conversion. A formula such as raw / 5.12 turns the stored integer into the value shown by BEANalyzer.
raw / 10.0Divisionraw * 0.01Scalingraw - 48Offsetraw * 0.5 + 16Scale + offsetThe formula evaluator is intentionally restricted rather than executing arbitrary Python. It supports arithmetic, bitwise operators, comparisons, boolean logic, the Python ternary expression, variables raw and data, functions len, min, max, abs, round, and allowed public math functions/constants after validation.
You can access other DATA bytes with constant indices such as data[2]. Protect variable-length frames, for example: (raw + data[2]) / 2 if len(data) > 2 else raw.
For u8 and u16be, the current implementation falls back to RAW if formula evaluation fails. Always test known input/output examples.
Three patterns cover a lot of real work
{
"name": "Vehicle speed",
"did": "FE",
"mid": "24",
"category": "vehicle",
"function": "vehicle_speed",
"signals": [
{
"name": "speed",
"kind": "u8",
"offset": 0,
"unit": "km/h",
"card": "speed",
"plot": true
}
]
}
If DATA0 is 0x3C, u8 produces decimal 60, so the value is 60 km/h.
{
"name": "Engine RPM",
"did": "FE",
"mid": "26",
"category": "engine",
"function": "tachometer_rpm",
"signals": [
{
"name": "rpm",
"kind": "u16be",
"offset": 0,
"formula": "raw / 5.12",
"unit": "rpm",
"card": "rpm",
"plot": true
}
]
}
With DATA 0D E1, RAW is 0x0DE1 = 3553, therefore 3553 / 5.12 ≈ 694 rpm.
{
"name": "Light switch position",
"context": "A3",
"did": "FE",
"mid": "1E",
"category": "body_lighting",
"signals": [
{
"name": "light_switch_mode",
"kind": "map",
"offset": 0,
"map": {
"00": "OFF",
"02": "POSITION",
"03": "LOW_BEAM",
"04": "AUTO"
}
},
{
"name": "low_beam_switch",
"kind": "bool_expr",
"offset": 0,
"formula": "raw == 0x03"
}
]
}
Multiple signals may intentionally read the same DATA byte: keep the RAW view, a friendly enumeration and derived states when that helps analysis.
Keep RX knowledge separate from TX knowledge
A BEAN-DBC can include tx_templates, but a received DID/MID never proves the correct transmit payload. BEANalyzer prefers bridge_payload; historical payload and bytes forms are fallback inputs.
"tx_templates": [
{
"name": "Light switch POSITION reference",
"bridge_payload": "62 1E 02",
"reset_payload": "62 1E 00",
"notes": "EXPERIMENTAL — validate before use"
}
]
bridge_payload
The preferred logical payload sent by the bridge, for example 62 26 0D E1. It is not a complete physical capture.
low_level_payload
Can preserve a logical low-level DST + MID + DATA reference separately from the validated bridge route.
reset_payload defines a neutral/release message for momentary controls. The complete physical capture — marker, header, CRC, EOM and post-EOM response — must never be pasted into bridge_payload.
Workbench runtime actions such as Send Once, Pulse, Periodic and Repeat Times are not the basic message-definition schema. The BEAN-DBC describes the message/template; Workbench decides how it is exercised at runtime.
The receiver may require wake-up state, keep-alives, timing, bursts or another destination/prefix. Mark candidate TX templates as experimental until tested.
Decode in one direction. Encode in the other.
Lab Workbench can construct controls from BEAN-DBC metadata: boolean signals can become checkboxes, flags become multiple checkboxes, maps become selections, numeric signals become sliders, and control: "dial" can request dial-like behavior.
{
"name": "rpm",
"kind": "u16be",
"offset": 0,
"formula": "raw / 5.12",
"unit": "rpm",
"workbench": {
"control": "dial",
"value_min": 0,
"value_max": 8000,
"value_step": 1,
"encode": {
"type": "linear",
"raw_scale": 5.12,
"raw_offset": 0
}
}
}
physical = raw / 5.12raw = physical × 5.12Workbench may derive an inverse automatically only when it can prove an affine relationship decoded = a × raw + b. Bitfields, comparisons, saturation, formulas using other bytes and other non-linear expressions must stay RAW or use explicit encoding metadata.
Start RAW. Promote meaning only with evidence.
- Capture RAW.Create a conservative
u8view before assigning semantics. - Form a hypothesis.Add candidate bits, masks or enumerations while keeping the status explicit.
- Repeat controlled tests.Compare states, transitions, events and multiple captures.
- Rename only when justified.Do not turn correlation into confirmation silently.
- Add TX last.Only after a real or clearly experimental transmission route exists.
For documented work, prefer explicit DID, use uppercase two-digit hexadecimal strings, keep context-specific interpretations separate, and record what remains unknown in notes.
Fields such as source, source_ecu, function, category, references, notes and optional gateway metadata may support UI, search, documentation or CAN-gateway planning without changing the basic decoded value.
Production checklist
python3 -m json.tool bean_dbc_custom.json > /dev/null
Use the Hub's JSON Syntax Verifier to paste JSON or read a local file directly in your browser. The draft is not uploaded to the server.
Begin conservatively, then add evidence
This template intentionally starts with one RAW byte and a pending-validation status. Remove context if the message truly is generic. Do not add tx_templates until TX evidence exists.
{
"name": "MESSAGE NAME",
"context": "A3",
"did": "FE",
"mid": "00",
"category": "unknown",
"function": "unknown_function",
"source": "Unknown",
"source_ecu": "Unknown",
"doc_status": "PENDING VALIDATION",
"example": "FE 00 00",
"notes": [
"Explain what was observed.",
"Explain what remains unknown."
],
"references": [
"Capture / document / test source"
],
"signals": [
{
"name": "data0_raw",
"kind": "u8",
"offset": 0,
"unit": "raw"
}
]
}
Document what the decoder supports — not what BEAN could theoretically support
u16leDo not pretend big-endian matches little-endian data.Every BEAN-DBC entry should let another engineer reconstruct what the message is, which bytes are DATA, what each signal means, how it is transformed, what evidence supports it, how TX differs from RX, how Workbench controls it, and what remains unconfirmed.