0
# Message Handling
1
2
CAN message creation, manipulation, and validation with comprehensive support for all CAN message types including standard and extended arbitration IDs, remote frames, error frames, and CAN FD messages with flexible data rates.
3
4
## Capabilities
5
6
### Message Creation
7
8
Create CAN messages with full control over all message properties and automatic validation.
9
10
```python { .api }
11
class Message:
12
def __init__(self, timestamp=0.0, arbitration_id=0, is_extended_id=True,
13
is_remote_frame=False, is_error_frame=False, channel=None,
14
dlc=None, data=None, is_fd=False, is_rx=True,
15
bitrate_switch=False, error_state_indicator=False, check=False):
16
"""
17
Create a CAN message object.
18
19
Parameters:
20
- timestamp: Message timestamp in seconds (float)
21
- arbitration_id: CAN arbitration ID (0-0x1FFFFFFF for extended, 0-0x7FF for standard)
22
- is_extended_id: True for 29-bit extended ID, False for 11-bit standard ID
23
- is_remote_frame: True for remote transmission request frames
24
- is_error_frame: True for error frames
25
- channel: Channel identifier (backend specific)
26
- dlc: Data Length Code (0-8 for CAN 2.0, 0-64 for CAN FD)
27
- data: Message data as bytes, bytearray, or list of integers
28
- is_fd: True for CAN FD frames
29
- is_rx: True for received messages, False for transmitted
30
- bitrate_switch: True for CAN FD bitrate switching
31
- error_state_indicator: True for CAN FD error state indicator
32
- check: If True, validate message parameters (raises ValueError on invalid)
33
34
Raises:
35
- ValueError: Invalid message parameters (only if check=True)
36
- TypeError: Invalid data type
37
"""
38
```
39
40
### Message Properties
41
42
Access and modify message properties with automatic type conversion and validation.
43
44
```python { .api }
45
# Message properties (all read/write)
46
timestamp: float # Message timestamp in seconds
47
arbitration_id: int # CAN arbitration ID
48
is_extended_id: bool # Extended (29-bit) vs standard (11-bit) ID
49
is_remote_frame: bool # Remote transmission request
50
is_error_frame: bool # Error frame indicator
51
channel: Any # Channel identifier
52
dlc: int # Data Length Code
53
data: bytearray # Message data bytes
54
is_fd: bool # CAN FD frame
55
is_rx: bool # Receive (True) vs transmit (False)
56
bitrate_switch: bool # CAN FD bitrate switching
57
error_state_indicator: bool # CAN FD error state indicator
58
```
59
60
### Message Comparison
61
62
Compare messages with configurable tolerance and optional field exclusions.
63
64
```python { .api }
65
def equals(self, other: Message, timestamp_delta=1e-6, check_channel=True,
66
check_direction=True) -> bool:
67
"""
68
Compare this message with another message.
69
70
Parameters:
71
- other: Message to compare with
72
- timestamp_delta: Maximum timestamp difference in seconds (None to ignore)
73
- check_channel: Whether to compare message channels
74
- check_direction: Whether to compare message directions (Rx/Tx)
75
76
Returns:
77
True if messages are equal within specified tolerances
78
"""
79
```
80
81
### Message Validation
82
83
Validate message parameters and detect invalid configurations.
84
85
```python { .api }
86
def _check(self) -> None:
87
"""
88
Check if message parameters are valid.
89
90
Validates:
91
- Timestamp is not negative, infinite, or NaN
92
- Remote and error frames are mutually exclusive
93
- CAN FD compatibility with remote frames
94
- Arbitration ID ranges (11-bit: 0-0x7FF, 29-bit: 0-0x1FFFFFFF)
95
- DLC ranges (CAN 2.0: 0-8, CAN FD: 0-64)
96
- Data consistency with DLC and frame type
97
- CAN FD specific flags only used with CAN FD frames
98
99
Raises:
100
- ValueError: Invalid message parameters
101
"""
102
```
103
104
### String Representation
105
106
Convert messages to human-readable string formats with comprehensive information display.
107
108
```python { .api }
109
def __str__(self) -> str:
110
"""
111
Return human-readable string representation.
112
113
Format: Timestamp ID Flags DL Data ASCII Channel
114
Example: " 12.345678 ID: 123 S Rx DL: 8 01 02 03 04 05 06 07 08 'test'"
115
"""
116
117
def __repr__(self) -> str:
118
"""
119
Return unambiguous string representation suitable for recreating the message.
120
121
Example: "can.Message(timestamp=12.345, arbitration_id=0x123, ...)"
122
"""
123
124
def __format__(self, format_spec: str) -> str:
125
"""Format message using format specification (empty spec uses __str__)."""
126
```
127
128
### Data Access
129
130
Access message data through multiple interfaces for different use cases.
131
132
```python { .api }
133
def __len__(self) -> int:
134
"""Return the DLC (works for remote frames)."""
135
136
def __bytes__(self) -> bytes:
137
"""Return message data as bytes."""
138
139
def __bool__(self) -> bool:
140
"""Messages are always truthy."""
141
```
142
143
### Message Copying
144
145
Create copies of messages with full or shallow copying support.
146
147
```python { .api }
148
def __copy__(self) -> Message:
149
"""Create a shallow copy of the message."""
150
151
def __deepcopy__(self, memo) -> Message:
152
"""Create a deep copy of the message with all referenced objects copied."""
153
```
154
155
## Usage Examples
156
157
### Basic Message Creation
158
159
```python
160
import can
161
162
# Standard 11-bit ID message
163
msg1 = can.Message(
164
arbitration_id=0x123,
165
data=[0x11, 0x22, 0x33, 0x44],
166
is_extended_id=False
167
)
168
169
# Extended 29-bit ID message
170
msg2 = can.Message(
171
arbitration_id=0x18FF1234,
172
data=b'\x01\x02\x03\x04\x05\x06\x07\x08',
173
is_extended_id=True
174
)
175
176
# Remote frame
177
remote_msg = can.Message(
178
arbitration_id=0x456,
179
is_remote_frame=True,
180
dlc=8, # Request 8 bytes
181
is_extended_id=False
182
)
183
184
print(f"Standard message: {msg1}")
185
print(f"Extended message: {msg2}")
186
print(f"Remote frame: {remote_msg}")
187
```
188
189
### CAN FD Messages
190
191
```python
192
import can
193
194
# CAN FD message with up to 64 bytes
195
fd_msg = can.Message(
196
arbitration_id=0x123,
197
data=list(range(64)), # 64 bytes of data
198
is_fd=True,
199
bitrate_switch=True,
200
is_extended_id=False
201
)
202
203
print(f"CAN FD message length: {len(fd_msg)}")
204
print(f"CAN FD data: {fd_msg.data[:10]}...") # First 10 bytes
205
```
206
207
### Message Validation
208
209
```python
210
import can
211
212
try:
213
# This will raise ValueError because remote frames can't carry data
214
invalid_msg = can.Message(
215
arbitration_id=0x123,
216
data=[1, 2, 3, 4],
217
is_remote_frame=True,
218
check=True # Enable validation
219
)
220
except ValueError as e:
221
print(f"Validation error: {e}")
222
223
# Valid message creation
224
valid_msg = can.Message(
225
arbitration_id=0x123,
226
data=[1, 2, 3, 4],
227
check=True
228
)
229
```
230
231
### Message Comparison
232
233
```python
234
import can
235
import time
236
237
# Create two similar messages
238
msg1 = can.Message(
239
timestamp=time.time(),
240
arbitration_id=0x123,
241
data=[1, 2, 3, 4]
242
)
243
244
time.sleep(0.001) # Small delay
245
246
msg2 = can.Message(
247
timestamp=time.time(),
248
arbitration_id=0x123,
249
data=[1, 2, 3, 4]
250
)
251
252
# Compare with default timestamp tolerance (1µs)
253
if msg1.equals(msg2):
254
print("Messages are equal (within timestamp tolerance)")
255
256
# Compare ignoring timestamps
257
if msg1.equals(msg2, timestamp_delta=None):
258
print("Messages have identical content")
259
260
# Strict comparison (identity)
261
if msg1 is msg2:
262
print("Same message object")
263
else:
264
print("Different message objects")
265
```
266
267
### Working with Message Data
268
269
```python
270
import can
271
272
msg = can.Message(
273
arbitration_id=0x123,
274
data=[0x48, 0x65, 0x6C, 0x6C, 0x6F] # "Hello" in ASCII
275
)
276
277
# Access data in different ways
278
print(f"Data as list: {list(msg.data)}")
279
print(f"Data as bytes: {bytes(msg)}")
280
print(f"Data as hex: {msg.data.hex()}")
281
print(f"Data length: {len(msg)}")
282
283
# Modify data
284
msg.data[0] = 0x48 # Set first byte
285
msg.data.extend([0x21]) # Add exclamation mark
286
msg.dlc = len(msg.data) # Update DLC
287
288
print(f"Modified message: {msg}")
289
```
290
291
### Message Copying
292
293
```python
294
import can
295
import copy
296
297
original = can.Message(
298
arbitration_id=0x123,
299
data=[1, 2, 3, 4],
300
channel="can0"
301
)
302
303
# Shallow copy
304
shallow_copy = copy.copy(original)
305
shallow_copy.arbitration_id = 0x456
306
307
# Deep copy
308
deep_copy = copy.deepcopy(original)
309
deep_copy.data[0] = 99
310
311
print(f"Original: {original}")
312
print(f"Shallow copy: {shallow_copy}")
313
print(f"Deep copy: {deep_copy}")
314
```
315
316
## Types
317
318
```python { .api }
319
from typing import Union, Optional, Any
320
from collections.abc import Sequence
321
322
# Type aliases for message data
323
CanData = Union[bytes, bytearray, Sequence[int]]
324
Channel = Union[str, int, Any]
325
326
class Message:
327
"""CAN message representation with support for all CAN variants."""
328
329
# Slots for memory efficiency
330
__slots__ = (
331
"__weakref__",
332
"arbitration_id", "bitrate_switch", "channel", "data", "dlc",
333
"error_state_indicator", "is_error_frame", "is_extended_id",
334
"is_fd", "is_remote_frame", "is_rx", "timestamp"
335
)
336
```