BEAN ↔ CAN || CAN ↔ BEAN Mapping Design Guide
Explain, step by step, how to design mappings in the graphical editors, how every source type works, how to choose selectors, how to use expressions and helper functions, how to calculate scaling, and how to validate the resulting physical traffic safely.
BEAN ↔ CAN || CAN ↔ BEAN Mapping Design Guide — Expanded Engineering Edition
Document revision: 2.0 Date: 2026-09-21 Language: English Applies to: BEANalyzer UltraPro 5 BEAN → CAN format: BEANalyzer_Gateway_Mapping, version 3 CAN → BEAN format: BEANalyzer_CAN_to_BEAN_Mapping, version 1 Current UI terminology: CAN Interface Purpose: Explain, step by step, how to design mappings in the graphical editors, how every source type works, how to choose selectors, how to use expressions and helper functions, how to calculate scaling, and how to validate the resulting physical traffic safely.
1. Read this first
The Mapping editors are not simple “copy byte A to byte B” tools.
They are small protocol translators.
A correct Mapping describes:
WHAT source message is allowed to enter
↓
WHAT source value is used
↓
HOW that value is transformed
↓
WHERE the transformed value is placed
↓
WHEN the output is transmitted
↓
WHAT happens if the source stops updatingThe best way to design a Mapping is to write those six answers down before touching the editor.
A Mapping that works by accident is difficult to maintain.
A Mapping that can be explained as:
“Match this exact source message, extract this field, convert it with this formula, put it into these exact destination bits, and transmit it with this timing policy”
is reproducible engineering.
2. The two directions are intentionally separate
BEANalyzer has two independent Mapping editors.
BEAN → CAN
Open:
Devices / CAN Gateway
↓
BEAN → CAN Mapping
↓
Open BEAN → CAN Mapping Editor...This editor receives Toyota/Lexus BEAN information and builds one or more Classic CAN frames.
CAN → BEAN
Open:
Devices / CAN Gateway
↓
CAN → BEAN Mapping
↓
Open CAN → BEAN Mapping Editor...This editor receives Classic CAN frames and builds BEAN application messages.
The CAN → BEAN editor does not ask you to construct a complete captured BEAN electrical frame.
It produces:
DID + MID + DATAThe BEAN bridge owns the link layer.
3. Mental model
BEAN → CAN
BEAN RX
↓
Message tab
BEAN match / source selector
↓
Payload Fields
↓
Source
↓
Encoding
↓
CAN destination bits
↓
Transmit policy
↓
CAN Interface
↓
physical CANCAN → BEAN
CAN RX
↓
Message tab
CAN match / source selector
↓
Payload Fields
↓
Source
↓
Encoding
↓
BEAN DATA destination bits
↓
Transmit policy
↓
BEAN bridge
↓
physical BEAN4. Raw values versus physical values
This is the most important distinction in the entire Mapping system.
Consider coolant temperature.
Current project decoding:
coolant_temp = raw / 2If BEAN DATA contains:
6Bthen:
0x6B = 107 decimal
107 / 2 = 53.5 °CTwo different Mapping designs are possible.
Raw-preserving Mapping
source = raw byte 0x6B
scale = 1
offset = 0
output = 0x6BPhysical-value Mapping
source = decoded coolant_temp = 53.5
scale = 0.5
offset = 0
output = round(53.5 / 0.5)
= 107
= 0x6BBoth are correct if intentional.
The mistake is to mix the two models.
5. Encoding formula
Both Mapping directions use the same destination encoding rule:
destination_raw = round((source_value - offset) / scale)This means:
Exact copy
scale = 1
offset = 0Physical value of 0.5 units per bit
scale = 0.5Example:
physical = 53.5
raw = 53.5 / 0.5
= 107Physical value using an offset
Suppose:
physical = raw - 48Rearrange:
raw = physical + 48In BEANalyzer:
scale = 1
offset = -48because:
raw = (physical - (-48)) / 1
= physical + 486. Destination bit numbering
BEANalyzer uses linear LSB0 destination bit numbering.
Byte 0 = bits 0..7
Byte 1 = bits 8..15
Byte 2 = bits 16..23
Byte 3 = bits 24..31
Byte 4 = bits 32..39
Byte 5 = bits 40..47
Byte 6 = bits 48..55
Byte 7 = bits 56..63Therefore:
first complete byte → start_bit 0
second complete byte → start_bit 8
third complete byte → start_bit 16
fourth complete byte → start_bit 24Do not use:
start_bit = 9when you mean “second byte”.
9 means:
Byte 1, bit 17. Signed fields
If Signed is disabled, a field of N bits accepts:
0 .. (2^N - 1)Examples:
8-bit unsigned = 0..255
16-bit unsigned = 0..65535If Signed is enabled, the accepted range is:
-(2^(N-1)) .. +(2^(N-1)-1)Examples:
8-bit signed = -128..127
16-bit signed = -32768..32767Negative signed values are packed using two’s-complement representation.
Example:
-1 in signed 8-bit = 0xFF8. Endianness
Single-byte fields are straightforward.
Multi-byte fields need careful byte order.
Example:
raw = 0x3C00Big Endian:
3C 00Little Endian:
00 3CIn the current Mapping implementation, Big Endian fields wider than 8 bits must be byte-aligned.
Examples of valid Big Endian destinations:
start_bit = 0, length = 16
start_bit = 8, length = 16
start_bit = 16, length = 32Example of an invalid Big Endian multi-byte destination:
start_bit = 3
length = 16PART I — BEAN → CAN
9. Creating a new BEAN → CAN Mapping
Open:
Devices / CAN Gateway
↓
BEAN → CAN Mapping
↓
Open BEAN → CAN Mapping Editor...Press:
New documentThe left side of the editor is:
CAN messages / mappingsEach item in this list represents one outgoing CAN message definition.
Press:
Addto create a new CAN message Mapping.
10. BEAN → CAN: Message tab
Select the Mapping on the left, then open:
MessageThe tab contains four important groups:
Mapping identity
BEAN match / source selector
Transmit policy
Stale-source policy
CAN output frame11. Mapping identity
Go to:
Message
↓
Mapping identitySet:
Name
Enabled
NotesExample:
Name:
IS200 Powertrain Summary
Enabled:
YES
Notes:
Packs outside temperature, coolant, vehicle speed and RPM into CAN 0x500.During initial development, it is reasonable to leave:
Enabled = NOuntil Preview / Test is correct.
12. BEAN match / source selector
Go to:
Message
↓
BEAN match / source selectorYou will see:
CTX
DID
MID
Required DATA lengthThese are selectors.
They determine which BEAN messages are considered matching input for this Mapping.
They are not automatically copied into the CAN payload.
13. How to use CTX = ANY
The CTX field accepts a hexadecimal context/header byte, or no restriction.
The editor placeholder shows:
ANY or A3Values interpreted as no restriction include:
ANY
any
*
blankTherefore, if context is irrelevant:
Message
↓
BEAN match / source selector
↓
CTX = ANYmeans:
accept any BEAN context/headerExample:
CTX = ANY
DID = FE
MID = 2CThis means:
match FE/2C regardless of CTX14. How to use DID = ANY
Example:
CTX = A3
DID = ANY
MID = 1EThis means:
match MID 0x1E in context 0xA3 regardless of DIDUse ANY only when the missing selector is genuinely irrelevant.
A selector that is too broad can make unrelated messages feed the same Mapping.
15. How to use MID = ANY
Example:
CTX = ANY
DID = FE
MID = ANYmeans:
accept any message ID sent to DID FEThis is powerful but broad.
It is usually better to select a specific MID unless the Mapping intentionally needs a family of messages.
16. Required DATA length
The field:
Required DATA lengthis optional.
Examples:
blankmeans:
do not require a specific DATA lengthExample:
2means:
only match messages whose application DATA length is exactly 2 bytesThis can help distinguish messages with the same DID/MID but different payload structures.
17. Selector recipes
Recipe A — Specific coolant message
Message
↓
BEAN match / source selector
CTX = ANY
DID = FE
MID = 2C
Required DATA length = 1Meaning:
accept FE/2C with one DATA byte, regardless of CTXRecipe B — Specific RPM message
CTX = ANY
DID = FE
MID = 26
Required DATA length = 2Recipe C — Specific lighting-switch context
Current project example:
CTX = A3
DID = FE
MID = 1E
Required DATA length = 1Recipe D — Any message from DID FE
CTX = ANY
DID = FE
MID = ANY
Required DATA length = blankUse this only if fields/expressions are intentionally designed to work for all such messages.
Recipe E — Completely open selector
CTX = ANY
DID = ANY
MID = ANY
Required DATA length = blankThis is effectively a wildcard source.
It is useful for mappings based only on the global decoded-signal cache, but it can be too broad for direct raw-field extraction.
18. CTX/DID/MID are hexadecimal
In these selector text fields, values are interpreted as hexadecimal by convention.
Examples:
26 = 0x26
A3 = 0xA3
FE = 0xFE
0x26 = 0x26Do not interpret 26 as decimal 26.
It means hexadecimal 0x26.
19. Transmit policy
Go to:
Message
↓
Transmit policyControls:
Trigger
Period (ms)
Heartbeat (ms)Trigger choices are:
Every matching BEAN message
On output value change
Fixed periodic rate
On change + heartbeat
Manual / test only20. Trigger: Every matching BEAN message
Select:
Trigger = Every matching BEAN messageBehavior:
matching BEAN message arrives
↓
Mapping composes CAN frame
↓
CAN frame transmittedUse when every source update must be mirrored.
Example:
BEAN FE/24 speed arrives
↓
CAN 0x510 speed frame sent21. Trigger: On output value change
Select:
Trigger = On output value changeBehavior:
source produces 6B → transmit
source produces 6B → no transmit
source produces 6B → no transmit
source produces 6C → transmitCounters and checksums are ignored when determining whether the semantic output changed.
This prevents a rolling counter from causing a frame to appear “changed” by itself.
Good uses:
light switch state
door status
temperature
gear
warning flags22. Trigger: Fixed periodic rate
Select:
Trigger = Fixed periodic rateThen configure:
Period (ms)Example:
Period = 100means approximately:
10 HzThe runtime first needs a valid matching source sample.
It does not invent data before the first source message.
23. Trigger: On change \\\+ heartbeat
Select:
Trigger = On change + heartbeatConfigure:
Heartbeat (ms)Example:
Heartbeat = 1000Behavior:
value changes → transmit immediately
no change → transmit again every ~1000 msThis is useful when the destination expects periodic proof that a state is still alive.
24. Trigger: Manual / test only
Select:
Trigger = Manual / test onlyNo automatic CAN transmission occurs from runtime.
Use this while designing a new Mapping.
Recommended initial workflow:
Manual / test only
↓
Preview
↓
Send Test Frame via CAN Interface
↓
independent CAN capture
↓
only then choose automatic trigger25. Stale-source policy
Go to:
Message
↓
Stale-source policyControls:
Source timeout (ms, 0=disabled)
When stale
Invalid valueAvailable actions:
Keep last value
Set zero
Set configured invalid value
Suppress CAN frame26. Stale policy: Keep last value
Example:
Source timeout = 2000 ms
When stale = Keep last valueIf source stops updating:
last value = 60 km/hperiodic output may continue using:
60 km/hThis is only appropriate when retaining the last state is safe.
27. Stale policy: Set zero
Example:
When stale = Set zeroAll source data/signals used by stale substitution are replaced with zero.
Use only if zero is a meaningful and safe fallback.
For speed:
0 km/hmay be sensible in some bench systems.
For coolant temperature:
0may be misleading.
28. Stale policy: Set configured invalid value
Example:
When stale = Set configured invalid value
Invalid value = 255Useful when the destination protocol defines:
0xFF = unavailableDo not invent 0xFF as invalid unless the target protocol actually defines it.
29. Stale policy: Suppress CAN frame
Example:
When stale = Suppress CAN frameNo CAN frame is transmitted while the source is stale.
This is usually the safest choice when the target protocol has no documented invalid encoding.
30. CAN output frame
Go to:
Message
↓
CAN output frameSet:
CAN ID
29-bit extended CAN ID
DLCExample:
CAN ID = 0x500
29-bit extended CAN ID = OFF
DLC = 8Equivalent textual ID:
500Standard CAN maximum:
0x7FFExtended maximum:
0x1FFFFFFF31. Payload Fields tab
Go to:
Payload FieldsEach row represents one contribution to the outgoing CAN DATA payload.
Press:
Add fieldThe field editor opens with three tabs:
Source
Destination
EncodingThis is where most Mapping design happens.
32. BEAN → CAN Source type: BEAN raw byte/bit
Go to:
Payload Fields
↓
Add field
↓
Source
↓
Source type = BEAN raw byte/bitControls:
BEAN DATA byte
Start bit in byte (LSB=0)
Source length (bits)
Byte order
Signed33. Raw example: copy a complete BEAN byte
Suppose source DATA is:
6BConfigure:
BEAN DATA byte = 0
Start bit = 0
Source length = 8
Byte order = little
Signed = OFFThen go to:
DestinationSet:
CAN start bit = 8
Length = 8
Byte order = little
Signed = OFFThen:
EncodingSet:
CAN scale = 1
CAN offset = 0
Clamp raw minimum = blank
Clamp raw maximum = blankResult:
BEAN DATA0 = 0x6B
↓
CAN byte1 = 0x6B34. Raw example: extract a single bit
Suppose:
BEAN DATA0 bit4 = taillights ONConfigure Source:
BEAN DATA byte = 0
Start bit = 4
Source length = 1
Byte order = little
Signed = OFFDestination example:
CAN start bit = 0
Length = 1Result:
BEAN bit4 → CAN bit0If source byte is:
0x11 = 00010001bbit4 is 1.
35. Raw example: extract low nibble
Source byte:
0xAB = 1010 1011Configure:
BEAN DATA byte = 0
Start bit = 0
Source length = 4Extracted value:
0xBDestination:
CAN start bit = 12
Length = 4This places the nibble in CAN Byte1 bits4..7.
36. Raw example: extract high nibble
Source:
0xABConfigure:
BEAN DATA byte = 0
Start bit = 4
Source length = 4Extracted:
0xA37. Raw example: 16-bit Big Endian RPM
If BEAN DATA is:
3C 00configure:
BEAN DATA byte = 0
Start bit = 0
Source length = 16
Byte order = big
Signed = OFFExact raw-preserving destination:
CAN start bit = 24
Length = 16
Byte order = big
Signed = OFFEncoding:
scale = 1
offset = 0Result:
CAN B3-B4 = 3C 0038. BEAN → CAN Source type: Decoded BEAN signal
Go to:
Payload Fields
↓
Add field
↓
Source
↓
Source type = Decoded BEAN signalControl:
Signal nameExamples:
rpm
speed
coolant_temp
outside_tempThis source uses the latest numeric value decoded by BEAN-DBC.
It is extremely useful for combining information from separate BEAN messages into one CAN frame.
39. Decoded example: coolant temperature
Set:
Signal name = coolant_tempCurrent formula:
coolant_temp = raw / 2If you want the CAN byte to preserve the Toyota raw encoding:
Destination:
CAN start bit = 8
Length = 8
Encoding:
CAN scale = 0.5
CAN offset = 0For:
coolant_temp = 53.5CAN raw becomes:
round(53.5 / 0.5)
= 107
= 0x6B40. Decoded example: outside temperature
Current formula:
outside_temp = raw - 48To reproduce Toyota raw:
Signal name = outside_temp
Destination:
CAN start bit = 0
Length = 8
Encoding:
scale = 1
offset = -48For:
outside_temp = 30result:
(30 - (-48)) / 1
= 78
= 0x4E41. Decoded example: speed
Current project interpretation:
speed = raw km/hUse:
Signal name = speed
Destination:
start_bit = 16
length = 8
Encoding:
scale = 1
offset = 0Example:
60 km/h → 0x3C42. Decoded example: RPM
Current formula:
rpm = raw / 5.12To restore raw encoding:
Signal name = rpm
Destination:
start_bit = 24
length = 16
byte_order = big
Encoding:
scale = 0.1953125
offset = 0because:
1 / 5.12 = 0.1953125Example:
3000 / 0.1953125
= 15360
= 0x3C0043. BEAN → CAN Source type: Constant
Go to:
Source type = ConstantControl:
Numeric valueUse constants for fields that should not depend on source traffic.
Examples:
protocol version
fixed mode byte
reserved zero
fixed enable bit
manufacturer marker44. Constant example: fixed zero byte
Set:
Numeric value = 0
Destination:
CAN start bit = 40
Length = 8
Encoding:
scale = 1
offset = 0Result:
CAN B5 = 0045. Constant example: fixed 0xA5 byte
Set:
Numeric value = 165because:
0xA5 = 165 decimalDestination:
CAN start bit = 56
Length = 8Result:
CAN B7 = A5The Constant input is numeric. A decimal value is the safest UI entry unless the current field parser explicitly accepts another numeric notation.
46. Constant example: single enable bit
Set:
Numeric value = 1Destination:
CAN start bit = 7
Length = 1Result:
CAN Byte0 bit7 = 147. BEAN → CAN Source type: Expression
Go to:
Source type = ExpressionBEAN expression variables are:
raw0 .. raw15
ctx
did
mid
dlc
decoded numeric signal namesExample environment:
raw0 = BEAN DATA0
raw1 = BEAN DATA1
...
ctx = context/header
did = DID
mid = MID
dlc = number of BEAN DATA bytes
rpm = decoded signal, if present
speed = decoded signal, if present48. Allowed expression operations
Supported arithmetic:
+
-
*
/
//
%
**Examples:
raw0 + 1
raw0 * 2
raw0 / 2
raw0 // 4
raw0 % 16
2 ** raw0Supported bitwise operators:
&
|
^
<<
>>
~Examples:
raw0 & 0x0F
raw0 | 0x80
raw0 ^ raw1
raw0 << 1
raw1 >> 2
~raw0Supported comparisons:
==
!=
<
<=
>
>=Supported Boolean operators:
and
or
notSupported conditional expression:
A if condition else BExample:
1 if speed > 0 else 049. Allowed helper functions
The only callable helper functions currently allowed are:
abs()
min()
max()
round()
int()
float()
floor()
ceil()Arbitrary Python calls are rejected.
Attribute access is rejected.
Imports are rejected.
Keyword arguments are rejected.
The expression engine is deliberately restricted.
50. Helper function: abs()
Purpose:
absolute valueExamples:
abs(-5)
→ 5abs(outside_temp)Potential automotive use:
abs(target_speed - speed)51. Helper function: min()
Purpose:
choose the smallest valueExamples:
min(raw0, 100)This limits the expression result to no more than 100.
Example:
min(speed, 255)52. Helper function: max()
Purpose:
choose the largest valueExample:
max(raw0, 10)ensures the expression is at least 10.
Combined clamp-like expression:
min(max(speed, 0), 255)53. Helper function: round()
Purpose:
round a numeric value before encodingExample:
round(rpm / 100)Note that the Mapping encoder itself also applies round() when converting the final source value to destination raw.
54. Helper function: int()
Purpose:
convert a numeric value to integerExample:
int(rpm / 100)This truncates toward zero before the encoder.
Difference:
int(12.9) = 12
round(12.9) = 1355. Helper function: float()
Purpose:
force numeric value to floating-pointExample:
float(raw0) / 2It is rarely required because division already produces numeric output, but it is available.
56. Helper function: floor()
Purpose:
round downwardExample:
floor(12.9)
→ 12Negative example:
floor(-1.2)
→ -257. Helper function: ceil()
Purpose:
round upwardExample:
ceil(12.1)
→ 13Negative example:
ceil(-1.2)
→ -158. Expression example: combine two BEAN bytes
If:
raw0 = high byte
raw1 = low byteuse:
(raw0 << 8) | raw1Example:
raw0 = 0x3C
raw1 = 0x00
(raw0 << 8) | raw1
= 0x3C0059. Expression example: convert raw RPM to physical RPM
Current BEAN RPM raw formula:
RPM = raw16 / 5.12Expression:
((raw0 << 8) | raw1) / 5.12If destination CAN field is physical RPM with:
1 rpm/bitset Encoding:
scale = 1
offset = 060. Expression example: map one status bit to 0/1
1 if (raw0 & 0x10) != 0 else 0This converts any non-zero masked bit into exactly:
0 or 161. Expression example: invert a Boolean status
0 if (raw0 & 0x10) != 0 else 162. Expression example: pack two nibbles
Suppose:
raw0 low nibble → destination low nibble
raw1 low nibble → destination high nibbleExpression:
(raw0 & 0x0F) | ((raw1 & 0x0F) << 4)63. Expression example: use CTX/DID/MID
Because selectors are not copied automatically, you can explicitly create them.
Examples:
ctx
did
midTo put MID into CAN B0:
Source type = Expression
Expression = mid
Destination:
start_bit = 0
length = 8
Encoding:
scale = 1
offset = 064. BEAN → CAN Source type: Rolling counter
Go to:
Source type = Rolling counterControls:
Counter width
Initial value
Step
Wrap atExample:
Counter width = 4
Initial value = 0
Step = 1
Wrap at = 16Sequence after successful transmissions:
0
1
2
3
...
15
0
1
...The counter advances after successful output transmission.
65. Counter example: 4-bit alive counter in low nibble
Source:
Counter width = 4
Initial value = 0
Step = 1
Wrap at = 16Destination:
CAN start bit = 48
Length = 4Output sequence:
B6 low nibble:
0,1,2,3,...F,0...66. Counter example: step by 2
Initial = 0
Step = 2
Wrap = 16Sequence:
0,2,4,6,8,A,C,E,0...67. Counter width versus wrap
Counter width describes the intended counter size and provides a natural default concept for wrapping.
Wrap at is the actual runtime modulus.
Example:
width = 4
wrap = 10sequence is:
0..9not:
0..15Make sure the destination bit length can hold the complete counter range.
68. BEAN → CAN Source type: Checksum / CRC
Go to:
Source type = Checksum / CRCAlgorithms:
xor8
sum8
crc8Controls:
First CAN byte
Last CAN byte
CRC polynomial
CRC init
CRC xoroutChecksum fields are calculated after normal fields have been packed.
69. XOR8
For bytes:
B0 B1 B2XOR8 computes:
B0 ^ B1 ^ B2Example:
12 ^ 34 ^ 56
= 70So:
XOR8 = 0x7070. SUM8
SUM8 computes:
sum(bytes) & 0xFFExample:
0xF0 + 0x30
= 0x120
0x120 & 0xFF
= 0x2071. CRC8 implementation
Current Mapping CRC8 is an MSB-first left-shifting implementation.
Configurable:
poly
init
xoroutDefault UI values:
poly = 0x07
init = 0x00
xorout = 0x00There are no separate refin / refout controls in the current UI.
Do not assume this CRC matches an ECU protocol simply because the polynomial is the same.
CRC parameter conventions can differ.
72. Checksum range example
Suppose CAN layout is:
B0 data
B1 data
B2 data
B3 data
B4 data
B5 data
B6 counter
B7 checksumChecksum field:
Algorithm = xor8
First CAN byte = 0
Last CAN byte = 6Destination:
CAN start bit = 56
Length = 8Recommended:
exclude checksum destination byte from its own source rangeunless the target protocol specifically defines otherwise.
73. Destination tab
Every field has:
DestinationControls:
CAN start bit (byte0 bit0 = 0)
Length (bits)
Byte order
SignedExamples:
B0 → start 0, length 8
B1 → start 8, length 8
B2 bit3 → start 19, length 1
B3-B4 BE → start 24, length 16, big74. Encoding tab
Every field has:
EncodingControls:
CAN scale (physical/bit)
CAN offset
Clamp raw minimum
Clamp raw maximumFormula:
CAN_raw = round((source_value - offset) / scale)75. Clamp example
Suppose source can exceed an 8-bit field.
Set:
Clamp raw minimum = 0
Clamp raw maximum = 255This prevents values below 0 or above 255 from escaping that range before destination-fit validation.
Without clamp, an out-of-range encoded value raises an error.
76. Complete BEAN → CAN walkthrough: packed IS200 summary frame
Goal:
CAN 0x500 DLC8
B0 outside_temp raw
B1 coolant raw
B2 speed raw
B3-B4 RPM raw Big Endian
B5-B7 00Step 1 — Message tab
Go to:
MessageSet:
Mapping identity
Name = IS200 Powertrain Summary
Enabled = YESStep 2 — BEAN match / source selector
Because this Mapping uses cached decoded signals from several BEAN messages:
CTX = ANY
DID = ANY
MID = ANY
Required DATA length = blankThis is intentionally broad.
Step 3 — Transmit policy
For a stable output frame:
Trigger = Fixed periodic rate
Period = 20 ms
Heartbeat = 1000 ms20 ms corresponds to:
50 HzStep 4 — Stale-source policy
Example:
Source timeout = 3000 ms
When stale = Keep last value
Invalid value = 0Step 5 — CAN output frame
CAN ID = 0x500
29-bit extended = OFF
DLC = 8Step 6 — Payload Fields: outside
Add field
Source:
Field name = OutsideTemp
Enabled = YES
Source type = Decoded BEAN signal
Signal name = outside_temp
Destination:
CAN start bit = 0
Length = 8
Byte order = little
Signed = OFF
Encoding:
CAN scale = 1
CAN offset = -48
Clamp min = 0
Clamp max = 255Step 7 — coolant
Source type = Decoded BEAN signal
Signal = coolant_temp
Destination:
start_bit = 8
length = 8
Encoding:
scale = 0.5
offset = 0
clamp 0..255Step 8 — speed
Signal = speed
Destination:
start_bit = 16
length = 8
Encoding:
scale = 1
offset = 0
clamp 0..255Step 9 — RPM
Signal = rpm
Destination:
start_bit = 24
length = 16
byte_order = big
signed = OFF
Encoding:
scale = 0.1953125
offset = 0
clamp 0..65535Step 10 — reserved bytes
Create three Constant fields:
B5: value 0 → start_bit 40 length 8
B6: value 0 → start_bit 48 length 8
B7: value 0 → start_bit 56 length 877. Preview / Test for BEAN → CAN
Go to:
Preview / TestFields:
CTX
DID
MID
BEAN DATA bytes
Decoded signals JSON
Counter values JSONFor the packed summary example, use:
CTX = 0xA3
DID = 0xFE
MID = 0x26
BEAN DATA = 00 00Decoded signals JSON:
{
"outside_temp": 30,
"coolant_temp": 53.5,
"speed": 60,
"rpm": 3000
}Press:
Compose CAN PreviewExpected:
CAN ID: 0x500
DATA: 4E 6B 3C 3C 00 00 00 00Then:
Send Test Frame via CAN InterfaceOnly do this on a controlled CAN network.
78. Preview trace
The Preview output includes a packing trace.
Typical line concept:
RPM: source=3000 -> encoded=15360 -> bits 24..39Use the trace to answer:
What value did the source produce?
What raw value did Encoding produce?
Which bits received it?If the final bytes are wrong, the trace usually identifies which stage is wrong.
79. Raw JSON tab
Go to:
Raw JSONButtons:
Refresh JSON from editor
Apply JSON to editorUse this for advanced editing or bulk changes.
Do not edit JSON and assume it is valid.
After editing:
Apply JSON to editorwhich validates and reloads the visual editor.
PART II — CAN → BEAN
80. Creating a new CAN → BEAN Mapping
Open:
Devices / CAN Gateway
↓
CAN → BEAN Mapping
↓
Open CAN → BEAN Mapping Editor...Press:
New documentLeft list:
BEAN output messages / mappingsEach Mapping in this list represents:
one CAN selector
↓
one BEAN output application message81. CAN → BEAN Message tab
Select a Mapping and open:
MessageGroups:
Mapping identity
CAN match / source selector
Transmit policy
Stale-source policy
BEAN output application message82. CAN match / source selector
Go to:
Message
↓
CAN match / source selectorControls:
CAN ID
29-bit extended CAN ID
Required DLCExample:
CAN ID = 0x500
29-bit extended CAN ID = OFF
Required DLC = 8Only matching RX frames feed the Mapping.
The CAN ID is not automatically copied into BEAN DATA.
83. CAN ID notation
Text IDs are hexadecimal.
Equivalent:
500
0x500Extended example:
18DAF110
0x18DAF110For the extended example:
29-bit extended CAN ID = ON84. Required DLC
Examples:
blankmeans:
accept any DLCExample:
8means:
only CAN frames with exactly 8 data bytesIf the CAN layout is fixed, specifying DLC is strongly recommended.
85. Current CAN match limitation
The current selector matches:
CAN ID
Extended flag
DLCIt does not yet provide generic payload conditions like:
can1 == 0x41
can2 == 0x0Cinside the selector.
This matters for diagnostic traffic.
Example:
0x7E8can carry many different OBD-II responses.
Matching only 0x7E8 DLC8 does not prove the response is PID 0C RPM.
86. BEAN output application message
Go to:
Message
↓
BEAN output application messageControls:
DID / destination
MID / message
DATA lengthExample:
DID = 62
MID = 2C
DATA length = 1Output application payload:
62 2C <DATA0>87. Do not add CRC/EOM
The Mapping output is not:
header + DID + MID + DATA + CRC + EOM + post-EOMIt is only:
DID + MID + DATACorrect example:
62 2C 6BIncorrect:
62 2C 6B xx 7E 40The BEAN bridge/BeanMPX layer creates the physical link-layer representation.
88. Maximum CAN → BEAN DATA length
Current bridge payload maximum:
16 bytes totalDID \\\+ MID consume:
2 bytesTherefore:
maximum DATA length = 14The editor allows:
0..14DATA bytes.
89. CAN → BEAN Payload Fields
Go to:
Payload Fields
↓
Add fieldField editor tabs:
Source
Destination
EncodingSource types:
CAN raw byte/bit
Decoded CAN signal
Constant
Expression
Rolling counter
Application checksum / CRC90. CAN raw byte/bit
Go to:
Source
↓
Source type = CAN raw byte/bitControls:
CAN DATA byte
Start bit in byte (LSB=0)
Source length (bits)
Byte order
SignedCAN DATA byte range is:
0..7because current input is Classic CAN.
91. CAN raw example: exact byte copy
Incoming:
500#4E6B3C3C00000000Need:
CAN B1 = 6B
→
BEAN DATA0 = 6BSource:
CAN DATA byte = 1
Start bit = 0
Source length = 8
Byte order = little
Signed = OFFDestination:
BEAN DATA start bit = 0
Length = 8
Byte order = little
Signed = OFFEncoding:
BEAN output scale = 1
BEAN output offset = 092. CAN raw example: single bit
Suppose:
CAN B0 bit7 = warning activeSource:
CAN DATA byte = 0
Start bit = 7
Source length = 1Destination:
BEAN DATA start bit = 4
Length = 1This maps:
CAN B0 bit7 → BEAN DATA0 bit493. CAN raw example: Big Endian RPM
Incoming:
B3 = 3C
B4 = 00Source:
CAN DATA byte = 3
Start bit = 0
Source length = 16
Byte order = big
Signed = OFFDestination:
BEAN DATA start bit = 0
Length = 16
Byte order = big
Signed = OFFEncoding:
scale = 1
offset = 0Result:
BEAN DATA = 3C 0094. Decoded CAN signal
Go to:
Source type = Decoded CAN signalControl:
Signal nameThe current live CAN Interface path is raw-byte based and does not yet automatically add a CAN-DBC decoder.
Therefore:
CAN raw byte/bit
Expressionare normally the practical live sources today.
Decoded CAN signal works when numeric decoded signals are supplied by the input pipeline, Preview, tests, or future decoder integration.
95. Decoded CAN signal example: physical coolant
Suppose input pipeline supplies:
coolant_temp = 53.5Target BEAN raw formula:
raw = temperature × 2Use:
Signal name = coolant_temp
Destination:
start_bit = 0
length = 8
Encoding:
scale = 0.5
offset = 0Result:
53.5 → 0x6B96. CAN → BEAN Constant
Example fixed BEAN flag:
Source type = Constant
Numeric value = 1Destination:
BEAN DATA start bit = 7
Length = 1Result:
DATA0 bit7 = 197. CAN → BEAN Expression variables
Available variables:
can0
can1
can2
can3
can4
can5
can6
can7
can_id
dlc
decoded numeric CAN signal names, when supplied98. CAN expression example: combine two bytes
(can3 << 8) | can4For:
can3 = 0x3C
can4 = 0x00result:
0x3C0099. CAN expression example: scale OBD RPM into BEAN RPM
OBD PID 0C:
RPM = ((A << 8) | B) / 4BEAN:
RPM = BEAN_raw / 5.12Therefore:
BEAN_raw = OBD_raw × 1.28Exact ratio:
32 / 25Expression:
(((can3 << 8) | can4) * 32) / 25Destination:
start_bit = 0
length = 16
byte_order = bigEncoding:
scale = 1
offset = 0100. OBD RPM worked example
3000 rpm:
OBD raw = 3000 × 4
= 12000
= 0x2EE0Example raw CAN response layout:
04 41 0C 2E E0 00 00 00Therefore:
can3 = 0x2E
can4 = 0xE0Expression:
(((0x2E << 8) | 0xE0) * 32) / 25
= 15360
= 0x3C00BEAN decoder:
0x3C00 / 5.12
= 3000 rpm101. OBD RPM warning
Do not automatically enable:
CAN ID = 0x7E8
DLC = 8and assume every frame is RPM.
The current selector does not validate:
can1 == 0x41
can2 == 0x0CA different PID response on the same CAN ID could be transformed incorrectly.
102. CAN expression example: threshold
1 if can0 >= 100 else 0Potential use:
activate BEAN bit when CAN value crosses threshold103. CAN expression example: mask and move bits
(can1 & 0x03) << 4Takes:
CAN B1 bits0..1and moves them to:
bits4..5of the numeric result.
104. CAN expression example: choose greater sensor value
max(can0, can1)105. CAN expression example: clamp
min(max(can0, 10), 200)Range:
10..200106. CAN → BEAN Rolling counter
Source:
Rolling counterExample:
Counter width = 4
Initial value = 0
Step = 1
Wrap at = 16Destination:
BEAN DATA start bit = 0
Length = 4Counter advances only after a successful BEAN TX callback.
107. CAN → BEAN Application checksum / CRC
Go to:
Source type = Application checksum / CRCControls:
Algorithm
First BEAN DATA byte
Last BEAN DATA byte
CRC polynomial
CRC init
CRC xoroutAlgorithms:
xor8
sum8
crc8Important:
This is not the physical BEAN CRC.
It is only for an application-level byte inside BEAN DATA.
108. CAN → BEAN checksum example
Output DATA layout:
DATA0 source
DATA1 source
DATA2 source
DATA3 XOR8Normal fields populate:
DATA0..DATA2Checksum field:
Algorithm = xor8
First BEAN DATA byte = 0
Last BEAN DATA byte = 2
Destination:
start_bit = 24
length = 8Then:
DATA3 = DATA0 ^ DATA1 ^ DATA2109. CAN → BEAN destination bits
Examples:
DATA0 → start_bit 0
DATA1 → start_bit 8
DATA2 → start_bit 16
DATA3 → start_bit 24
DATA0 bit4 → start_bit 4
DATA1 bit2 → start_bit 10Maximum current BEAN DATA bit range:
0..111because:
14 bytes × 8 = 112 bits110. Complete CAN → BEAN walkthrough: packed 0x500 back to four BEAN messages
Incoming:
500#4E6B3C3C00000000Goal:
outside
coolant
speed
RPMas four separate BEAN messages.
You must create four Mapping entries.
111. Mapping A — Outside temperature
Left panel:
BEAN output messages / mappings
↓
AddMessage tab:
Mapping identity
Name = CAN500 Outside Temp
Enabled = YESCAN match / source selector:
CAN ID = 0x500
29-bit extended = OFF
Required DLC = 8Transmit policy, first test:
Trigger = Manual / test onlyBEAN output application message:
DID = 62
MID = CD
DATA length = 1Payload Fields:
Add fieldSource:
Source type = CAN raw byte/bit
CAN DATA byte = 0
Start bit = 0
Source length = 8
Byte order = little
Signed = OFFDestination:
BEAN DATA start bit = 0
Length = 8Encoding:
scale = 1
offset = 0Expected:
62 CD 4E112. Mapping B — Coolant
Duplicate Mapping A or press Add.
Message:
Name = CAN500 Coolant
CAN ID = 0x500
Required DLC = 8
DID = 62
MID = 2C
DATA length = 1Field:
CAN DATA byte = 1
bit = 0
length = 8Destination:
start_bit = 0
length = 8Encoding:
scale = 1
offset = 0Expected:
62 2C 6B113. Mapping C — Speed
Name = CAN500 Speed
CAN ID = 0x500
DID = 62
MID = 24
DATA length = 1Field:
CAN DATA byte = 2
length = 8Expected:
62 24 3C114. Mapping D — RPM
Name = CAN500 RPM
CAN ID = 0x500
DID = 62
MID = 26
DATA length = 2Field Source:
CAN DATA byte = 3
Start bit = 0
Source length = 16
Byte order = big
Signed = OFFDestination:
BEAN DATA start bit = 0
Length = 16
Byte order = big
Signed = OFFEncoding:
scale = 1
offset = 0Expected:
62 26 3C 00115. FE versus 62
Project evidence must remain separated.
Observed/captured vehicle traffic includes forms such as:
FE 26 ...
FE 2C ...
FE 24 ...
FE CD ...Bridge-oriented transmit templates commonly use:
62 26 ...
62 2C ...
62 24 ...
62 CD ...Do not silently assume:
FE == 62for transmission semantics.
Use the DID that is validated for your specific bridge/target test.
Document which form was:
observed
transmitted
accepted by target ECU116. CAN → BEAN Preview / Test
Go to:
Preview / TestControls:
CAN ID
29-bit extended
CAN DATA bytes
Decoded CAN signals JSON
Counter values JSONExample:
CAN ID = 0x500
Extended = OFF
CAN DATA = 4E 6B 3C 3C 00 00 00 00
Decoded signals JSON = {}
Counter values JSON = {}Press:
Compose BEAN PreviewFor coolant Mapping expected application payload:
62 2C 6BThen:
Send Test Frame via BEANrequires the physical BEAN interface.
117. CAN → BEAN live activation
The default Mapping behavior is intentionally safe.
A new Mapping is normally:
Enabled = NO
Trigger = Manual / test onlyAfter validation:
- Connect the physical BEAN interface.
- Open the desired CAN → BEAN Mapping file.
- Enable the desired Mapping entries.
- Select an automatic Trigger.
- Save.
- Return to
Devices / CAN Gateway. - Enable:
Enable CAN → BEAN MappingThe gateway does not auto-arm at application startup.
118. Editing the active CAN → BEAN Mapping
Changing/opening/saving the active Mapping while live output is active disarms the runtime.
This is intentional.
Workflow:
live gateway active
↓
open/save/change active Mapping
↓
runtime stops
↓
Enable CAN → BEAN Mapping clears
↓
user must re-arm explicitlyThis prevents an edited rule from becoming electrically live mid-transaction.
PART III — HELPER FUNCTION REFERENCE
119. abs(x)
Returns absolute magnitude.
Examples:
abs(-10) → 10
abs(raw0-50)
abs(speed-target_speed)120. min(a, b, ...)
Returns smallest argument.
Examples:
min(raw0, 255)
min(speed, 200)
min(raw0, raw1, raw2)121. max(a, b, ...)
Returns largest argument.
Examples:
max(raw0, 0)
max(speed, 10)
max(raw0, raw1)122. min/max as a clamp
min(max(value, minimum), maximum)Example:
min(max(speed, 0), 250)123. round(x)
Rounds numeric value.
Example:
round(12.7) → 13Useful:
round(rpm / 100)The final destination encoder also rounds after applying scale/offset.
124. int(x)
Converts to integer by truncation toward zero.
Examples:
int(12.9) → 12
int(-12.9) → -12125. float(x)
Converts numeric value to floating-point.
Example:
float(raw0) / 2126. floor(x)
Rounds toward negative infinity.
Examples:
floor(12.9) → 12
floor(-1.2) → -2127. ceil(x)
Rounds toward positive infinity.
Examples:
ceil(12.1) → 13
ceil(-1.2) → -1128. Allowed arithmetic examples
raw0 + raw1
raw0 - raw1
raw0 * 2
raw0 / 2
raw0 // 2
raw0 % 16
raw0 ** 2129. Allowed bitwise examples
raw0 & 0x0F
raw0 | 0x80
raw0 ^ raw1
raw0 << 2
raw0 >> 2
~raw0When using ~, remember Python represents integers with unlimited signed precision.
If you need an 8-bit inverted value, mask it:
(~raw0) & 0xFF130. Allowed comparison examples
raw0 == 0
raw0 != 0
raw0 > 100
raw0 >= 100
raw0 < 10
raw0 <= 10131. Allowed Boolean examples
(raw0 > 10) and (raw1 > 20)
(raw0 == 1) or (raw1 == 1)
not (raw0 == 0)Since the final expression must produce a numeric result, it is usually clearer to wrap Boolean logic in a conditional expression.
Example:
1 if (raw0 > 10 and raw1 > 20) else 0132. Conditional expression examples
1 if speed > 0 else 0255 if coolant_temp > 120 else 0raw0 if raw0 < 200 else 2000 if rpm < 500 else rpm133. What expressions cannot do
Do not use:
import
object.attribute
os.system(...)
open(...)
__import__(...)
list indexing syntax requiring unsupported AST nodes
arbitrary function calls
keyword argumentsThe evaluator intentionally accepts only a limited expression subset.
PART IV — EXAMPLE LIBRARY
134. Example: copy BEAN byte to CAN byte
BEAN DATA0 = 0x42
CAN B4 targetSource:
bean_raw
byte 0
bit 0
length 8Destination:
start_bit 32
length 8Encoding:
1 / 0Result:
CAN B4 = 42135. Example: copy CAN byte to BEAN byte
CAN B5 = 0x77
BEAN DATA2 targetSource:
can_raw
byte 5
bit 0
length 8Destination:
start_bit = 16
length = 8Result:
BEAN DATA2 = 77136. Example: BEAN Boolean bit to CAN byte
Source:
BEAN DATA0 bit4Expression alternative:
1 if (raw0 & 0x10) else 0Destination:
CAN B0Encoding:
scale 1
offset 0CAN B0 becomes:
00 or 01instead of merely setting one bit.
137. Example: CAN Boolean bit to BEAN flag bit
Source:
CAN B2 bit3Raw source:
byte 2
bit 3
length 1Destination:
BEAN DATA0 start_bit 6
length 1138. Example: temperature conversion to standard “°C \\\+ 40” CAN encoding
Suppose BEAN decoded source:
outside_temp = actual °CTarget CAN protocol uses:
raw = °C + 40Use:
scale = 1
offset = -40For:
25 °Cresult:
65 decimal = 0x41139. Example: 0.1 km/h per bit
Source:
speed = 63.4 km/hTarget CAN:
0.1 km/h / bitUse:
scale = 0.1
offset = 0Result:
634 decimalRequires more than 8 bits.
Use:
16-bit destination140. Example: signed temperature
Suppose source:
outside_temp = -14 °CTarget destination is signed 8-bit, 1 °C/bit.
Use:
Destination:
length = 8
Signed = ON
Encoding:
scale = 1
offset = 0Raw signed value:
-14packed two’s-complement:
0xF2141. Example: map BEAN two-byte unsigned value into 12 CAN bits
Suppose:
source value = 0xABCDestination:
start_bit = 0
length = 12
byte_order = littleThe generic bit packer places low-order source bits into consecutive destination LSB0 positions.
For non-byte-aligned fields, document the exact bit layout and test Preview carefully.
142. Example: use DID as a CAN field
Message selector:
DID = ANYExpression field:
didDestination:
CAN B0This explicitly exports the BEAN DID.
BEANalyzer never inserts it automatically.
143. Example: use CAN ID low byte inside BEAN DATA
CAN → BEAN expression:
can_id & 0xFFDestination:
BEAN DATA0Example:
CAN ID = 0x523result:
0x23144. Example: derive message size
BEAN expression:
dlcFor BEAN expression environment, dlc is the length of source DATA.
CAN expression:
dlcis the CAN data length.
You can place it into a destination field if the target protocol requires an explicit payload length field.
145. Example: threshold RPM warning
BEAN → CAN:
Expression:
1 if rpm >= 2500 else 0Destination:
CAN start bit = 0
length = 1146. Example: RPM range code
0 if rpm < 1000 else 1 if rpm < 3000 else 2Possible result:
0 = low
1 = medium
2 = highDestination needs at least 2 bits.
147. Example: pack three Boolean states into one byte
Expression:
(1 if signal_a else 0) |
((1 if signal_b else 0) << 1) |
((1 if signal_c else 0) << 2)Use decoded signal names only if those numeric names are actually available.
PART V — MATCHING STRATEGY
148. Narrow selector versus broad selector
A narrow BEAN selector:
CTX = A3
DID = FE
MID = 1E
DATA length = 1is safer for raw extraction.
A broad selector:
CTX = ANY
DID = ANY
MID = ANYis useful when the output is driven by cached decoded signals and timing rather than current raw message bytes.
Rule:
The broader the selector, the less you should rely onraw0,raw1, etc. unless every matching message has the same layout.
149. Why raw fields and ANY can be dangerous
Suppose:
CTX = ANY
DID = ANY
MID = ANYand field:
raw0 → CAN B0Every matching BEAN message may have a different meaning for DATA0.
Result:
CAN B0 changes according to unrelated BEAN messagesThat is usually wrong.
Use a specific selector for direct raw extraction.
150. Why decoded signals and ANY can be useful
Suppose Mapping uses:
outside_temp
coolant_temp
speed
rpmfrom the decoded-state cache.
A periodic CAN summary frame may be intentionally independent of whichever BEAN message arrived last.
In that design, a broad selector can be acceptable because the actual fields are not raw0..rawN.
Document this architecture clearly.
PART VI — TIMING
151. Do not copy CAN timing blindly into BEAN
CAN may run at:
500 kbpswhile BEAN is a much slower network.
If CAN produces an update every:
5 msdo not automatically transmit a BEAN frame every 5 ms simply because the source does.
Prefer:
On changeor a validated periodic interval.
152. Example timing design for slow temperature
Temperature changes slowly.
Possible policy:
Trigger = On change + heartbeat
Heartbeat = 1000 msThis gives:
fast reaction when temperature changes
+
one refresh per second153. Example timing design for RPM
RPM changes rapidly.
Possible policies:
Every matching messageif source and destination networks can safely support it,
or:
Fixed periodic rate
Period = 50 msfor 20 Hz.
The correct rate must come from capture/ECU behavior, not from guesswork.
154. Example timing design for door status
Door state is event-like.
Use:
On output value changeOptionally heartbeat if the target needs refresh.
PART VII — ANTI-LOOP
155. Why bidirectional gateways can loop
Potential loop:
BEAN
↓
BEAN → CAN
↓
CAN
↓
CAN → BEAN
↓
BEAN
↓
...Current CAN → BEAN runtime includes local CAN TX echo suppression.
It fingerprints:
CAN ID
Extended flag
DATA
timestampA recent identical CAN RX matching a local CAN TX can be suppressed once.
Default local echo window:
120 msThis protects the local echo path.
It is not a universal distributed gateway-loop detector.
156. One-shot echo consumption
One locally transmitted CAN frame creates one fingerprint.
If an identical RX appears quickly:
fingerprint consumed
frame suppressedA later identical external frame is allowed.
This prevents a broad “ignore identical frame for 120 ms” rule from hiding legitimate traffic.
PART VIII — TROUBLESHOOTING
157. No CAN output from BEAN → CAN
Check:
Mapping Enabled?
Correct active file?
Trigger not Manual?
Selector matches?
Required DATA length matches?
Source raw byte exists?
Decoded signal name exact?
Destination fits DLC?
CAN Interface connected?
Runtime active?158. CAN frame exists but field is zero
Possible causes:
wrong source byte
wrong source bit
decoded signal missing
expression variable name wrong
stale policy replaced data
field disabled
destination overwritten by another field159. Correct source but wrong destination byte
Check:
start_bit
length
endiannessRemember:
B0 = 0
B1 = 8
B2 = 16
B3 = 24160. Value doubled or halved
This is usually a scaling misunderstanding.
Ask:
Is source raw?
or
Is source already physical?Example:
coolant decoded = 53.5If you use:
scale = 1you get approximately:
54not Toyota raw 107.
To restore raw:
scale = 0.5161. RPM bytes reversed
Expected:
3C 00Got:
00 3CCheck:
byte_order = bigfor the 16-bit source/destination where appropriate.
162. CAN → BEAN produces no output
Check:
physical BEAN interface connected
CAN Interface receiving
active CAN → BEAN file correct
Mapping Enabled
Trigger automatic
Enable CAN → BEAN Mapping checked
CAN ID exact
extended flag exact
DLC exact
source byte valid
DATA length large enough
runtime not fail-closed after backend error163. Periodic Mapping produces nothing at startup
Expected behavior.
Periodic mode waits for:
first matching source samplebefore it has state to retransmit.
164. Mapping immediately disables
Potential causes:
backend exception
invalid field
value outside destination range
invalid expression
BEAN output too long
disconnected BEAN bridgeCAN → BEAN backend errors fail closed.
165. Expression validation fails
Check for unsupported syntax.
Allowed:
raw0 + 1
(raw0 << 8) | raw1
1 if raw0 > 10 else 0
min(max(raw0, 0), 255)Not allowed:
some_object.attribute
__import__("os")
open("file")PART IX — VALIDATION PROCEDURE
166. Phase 1 — mathematical validation
Before transmitting anything:
source value
formula
expected destination raw
expected bytesmust be manually calculable.
Example:
RPM = 3000
raw = 3000 × 5.12
= 15360
= 0x3C00167. Phase 2 — Preview validation
Use:
Preview / TestVerify exact bytes.
Do not continue because “the number looks about right”.
Verify the exact hexadecimal payload.
168. Phase 3 — physical bus capture
For CAN:
BEANalyzer
↓
CAN Interface
↓
CAN bus
↓
independent receiverThe project has confirmed CANalyst-II TX at 500 kbps using an independent Arduino CAN receiver.
For BEAN:
BEANalyzer
↓
BEAN bridge
↓
BEAN wire
↓
independent captureis still the correct validation principle.
169. Phase 4 — target ECU behavior
Physical bytes on the wire do not automatically prove:
target ECU understood themValidate actual target behavior.
Examples:
cluster needle moves
warning lamp changes
A/C display updates
ECU state changesOnly then can target acceptance be considered vehicle-confirmed.
170. Phase 5 — timing validation
Test:
single frame
repeated frame
on-change
periodic
heartbeat
source stale
source recovery
long-duration operation171. Phase 6 — loop validation
With both directions active:
verify no local CAN echo becomes BEAN feedback
verify no external gateway creates a repeated cyclePART X — EVIDENCE CLASSIFICATION
172. Evidence levels
Recommended project labels:
CONFIRMED BY MANUFACTURER
CONFIRMED IN VEHICLE
CONFIRMED BY CAPTURE
CONFIRMED BY WORKING CODE
CORROBORATED
EXPERIMENTAL
HYPOTHESIS
PENDING VALIDATION
UNKNOWN173. Example evidence chain
Formula implemented in Mapping composer
→ CONFIRMED BY CODE
CANalyst-II physically transmitted frame and Arduino received it
→ CONFIRMED BY CAPTURE
Generated BEAN frame observed on wire
→ CONFIRMED BY CAPTURE
IS200 cluster accepts generated frame
→ CONFIRMED IN VEHICLEDo not merge those into one claim.
PART XI — JSON REFERENCE
174. BEAN → CAN document
{
"format": "BEANalyzer_Gateway_Mapping",
"version": 3,
"name": "My BEAN to CAN Mapping",
"notes": "",
"mappings": []
}175. CAN → BEAN document
{
"format": "BEANalyzer_CAN_to_BEAN_Mapping",
"version": 1,
"name": "My CAN to BEAN Mapping",
"notes": "",
"mappings": []
}176. BEAN → CAN Mapping example
{
"id": "mapping_001",
"name": "Coolant to CAN",
"enabled": true,
"notes": "",
"match": {
"bus": "BEAN",
"context": null,
"did": "FE",
"mid": "2C",
"data_len": 1
},
"trigger": {
"mode": "on_bean_message",
"period_ms": 100,
"heartbeat_ms": 1000
},
"stale": {
"timeout_ms": 1000,
"action": "suppress_frame",
"invalid_value": 0
},
"output": {
"bus": "CAN",
"id": "0x500",
"extended": false,
"dlc": 8
},
"fields": []
}null selector corresponds to:
ANYin conceptual UI use.
177. CAN → BEAN Mapping example
{
"id": "can_to_bean_001",
"name": "CAN500 Coolant to BEAN",
"enabled": true,
"notes": "",
"match": {
"bus": "CAN",
"id": "0x500",
"extended": false,
"dlc": 8
},
"trigger": {
"mode": "on_can_message",
"period_ms": 100,
"heartbeat_ms": 1000
},
"stale": {
"timeout_ms": 1000,
"action": "suppress_frame",
"invalid_value": 0
},
"output": {
"bus": "BEAN",
"did": "62",
"mid": "2C",
"data_len": 1
},
"fields": []
}178. Raw field JSON example
BEAN → CAN:
{
"name": "CoolantRaw",
"enabled": true,
"source": {
"type": "bean_raw",
"byte": 0,
"bit": 0,
"length": 8,
"byte_order": "little",
"signed": false
},
"destination": {
"start_bit": 8,
"length": 8,
"byte_order": "little",
"signed": false
},
"encoding": {
"scale": 1.0,
"offset": 0.0,
"clamp_min": 0,
"clamp_max": 255
}
}CAN → BEAN equivalent source:
"type": "can_raw"179. Expression JSON example
{
"source": {
"type": "expression",
"expression": "((raw0 << 8) | raw1) / 5.12"
}
}CAN → BEAN:
{
"source": {
"type": "expression",
"expression": "(((can3 << 8) | can4) * 32) / 25"
}
}180. Counter JSON example
{
"source": {
"type": "counter",
"bits": 4,
"initial": 0,
"step": 1,
"wrap": 16
}
}181. Checksum JSON example
{
"source": {
"type": "checksum",
"algorithm": "crc8",
"from_byte": 0,
"to_byte": 6,
"poly": "0x07",
"init": "0x00",
"xorout": "0x00"
}
}PART XII — PRACTICAL DESIGN TEMPLATES
182. Template: direct raw translator
Use when source and destination intentionally share the same raw representation.
Source:
raw byte/bit
Encoding:
scale = 1
offset = 0
Destination:
same bit lengthAdvantages:
simple
easy to verify
minimal numerical ambiguity183. Template: semantic translator
Use when protocols encode the same physical value differently.
Example:
BEAN RPM raw / 5.12
→ physical RPM
→ destination uses 0.25 rpm/bitUse decoded signal:
rpmDestination encoding:
scale = 0.25
offset = 0At:
3000 rpmdestination raw:
12000 = 0x2EE0184. Template: status normalizer
Source status may use a mask:
raw0 & 0x40Normalize:
1 if (raw0 & 0x40) else 0Destination can then use:
one bitor:
one byte185. Template: packed gateway frame
Use decoded-signal state cache.
Example CAN frame:
B0 temperature
B1 coolant
B2 speed
B3-B4 RPM
B5 status
B6 counter
B7 checksumThis is a good architecture when one external CAN node needs a compact vehicle-state summary.
186. Template: fan-out CAN → BEAN
One CAN frame:
0x500contains several values.
Create multiple mappings:
Mapping 1 → BEAN outside
Mapping 2 → BEAN coolant
Mapping 3 → BEAN speed
Mapping 4 → BEAN RPMDo not create one BEAN message containing unrelated MIDs.
187. Template: event-to-state conversion
CAN event byte:
1 = active
0 = inactiveBEAN target needs bit4.
Source:
can0Destination:
start_bit = 4
length = 1If CAN source can contain values other than 0/1, normalize:
1 if can0 != 0 else 0188. Template: state-to-event conversion
BEAN bit:
raw0 & 0x10CAN target byte:
0xAA active
0x55 inactiveExpression:
0xAA if (raw0 & 0x10) else 0x55Destination:
8 bitsPART XIII — FINAL CHECKLIST
189. Before Save
Verify:
Mapping name descriptive
Enabled intentional
Selector not too broad
Trigger intentional
Stale behavior intentional
Output ID/DID/MID correct
DLC/DATA length correct
Every field enabled intentionally
Start bits non-overlapping unless overlap is intentional
Endianness correct
Signedness correct
Scale non-zero
Clamp values sensible190. Before physical transmission
Verify:
Preview exact hex output
Independent expected calculation
Bench network controlled
Correct bitrate
Correct CAN standard/extended mode
BEAN bridge connected if CAN → BEAN
CAN Interface connected if BEAN → CAN191. Before automatic runtime
Verify:
Manual test successful
Physical frame captured
Target behavior understood
Trigger frequency safe
Stale policy safe
No feedback loop
Long-duration traffic acceptable192. Final engineering rule
Every Mapping should be reconstructable as:
WHAT was mapped
WHY it was mapped
HOW the source was selected
HOW the value was decoded
HOW the value was encoded
WHERE the bits were placed
WHEN the message was transmitted
HOW stale data was handled
WHAT was physically observed
WHAT the target ECU did
WHAT remains unverifiedIf those answers are documented, the Mapping is maintainable.
If they are not, it is only an experiment.
193. Quick UI cheat sheet — BEAN → CAN
Devices / CAN Gateway
↓
Open BEAN → CAN Mapping Editor
↓
Add
↓
Message
├─ Mapping identity
├─ BEAN match / source selector
│ CTX = ANY / A3 / ...
│ DID = ANY / FE / ...
│ MID = ANY / 26 / ...
│ Required DATA length = blank / 1 / 2 / ...
├─ Transmit policy
│ Trigger
│ Period
│ Heartbeat
├─ Stale-source policy
│ Timeout
│ Action
│ Invalid value
└─ CAN output frame
CAN ID
Extended
DLC
Payload Fields
↓
Add field
├─ Source
├─ Destination
└─ Encoding
Preview / Test
↓
Compose CAN Preview
↓
Send Test Frame via CAN Interface
Raw JSON194. Quick UI cheat sheet — CAN → BEAN
Devices / CAN Gateway
↓
Open CAN → BEAN Mapping Editor
↓
Add
↓
Message
├─ Mapping identity
├─ CAN match / source selector
│ CAN ID
│ Extended
│ Required DLC
├─ Transmit policy
│ Trigger
│ Period
│ Heartbeat
├─ Stale-source policy
│ Timeout
│ Action
│ Invalid value
└─ BEAN output application message
DID
MID
DATA length
Payload Fields
↓
Add field
├─ Source
├─ Destination
└─ Encoding
Preview / Test
↓
Compose BEAN Preview
↓
Send Test Frame via BEAN
Raw JSON195. Current implementation limitations to remember
Classic CAN only in these Mapping paths
CAN payload maximum = 8 bytes
CAN → BEAN DATA maximum = 14 bytes
CAN → BEAN live input is normally raw-byte based
No automatic CAN-DBC decoder in the current live CAN Interface path
CAN selector currently matches ID / Extended / DLC, not arbitrary payload signatures
Big Endian multi-byte fields must be byte-aligned
Local CAN echo protection is not a universal distributed-loop detector
BEAN transmit DID semantics such as FE vs 62 must be validated for the actual bridge/target pathAE&D — Anyzun Electronics & Development BEANalyzer UltraPro 5 BEAN ↔ CAN Mapping Design Guide — Expanded Engineering Edition