mcp_io_can 0.2.1
mcp_io_can: ^0.2.1 copied to clipboard
CAN bus adapter for mcp_io. Classic CAN 2.0A/B frame codec (SocketCAN layout) + pluggable transport.
mcp_io_can #
CAN bus adapter for mcp_io —
Classic CAN 2.0A / 2.0B + CAN-FD over the same 4-Primitive surface,
with CANopen and J1939 catalog helpers.
The web-safe core ships frame codecs, filters, and a paired
in-memory transport. Production deployments opt in to the Linux
SocketCAN binding via the separate lib/native.dart entry point.
Capability matrix #
| Area | Support |
|---|---|
| Frames | CAN 2.0A (11-bit), CAN 2.0B (29-bit), CAN-FD (DLC 9..15, BRS, ESI), RTR |
| Filter | Acceptance code+mask, ID list, ID range, AnyOf |
| Capabilities | can.send_frame / subscribe_frames · canopen.sdo_read / sdo_write / pdo_subscribe / nmt · j1939.send_pgn / subscribe_pgn |
| CANopen catalog | CiA-301 standard objects (Identity 0x1018, Heartbeat 0x1017, Error Register 0x1001, ...), CiA-401 generic I/O, CiA-402 motion (Controlword/Statusword/Position/Velocity/Torque) |
| J1939 catalog | Curated PGN dictionary (EEC1, EEC2, ET1, ETC1/2, CCVS1, DM1/2, ...) with byNumber / byAcronym lookup |
| Transports | InMemoryCanTransport (web-safe, tests) · SocketCanTransport (Linux production via lib/native.dart) — vendor SDKs (PEAK / Vector / Kvaser) plug in via custom CanTransport |
Web-safe quick start #
import 'package:mcp_io_can/mcp_io_can.dart';
final transport = InMemoryCanTransport.loopback();
final adapter = CanAdapter(deviceId: 'bus', transport: transport);
await adapter.connect();
await adapter.execute(const Command(
action: 'can.send_frame', target: 'can/0x180',
args: {'data': [0x10, 0x20]},
));
adapter.subscribe(const TopicSpec(uri: 'can/#'))
.listen((env) => print('frame: ${env.payload.value}'));
Linux SocketCAN production #
import 'package:mcp_io_can/mcp_io_can.dart';
import 'package:mcp_io_can/native.dart';
final transport = SocketCanTransport(interfaceName: 'can0');
final adapter = CanAdapter(deviceId: 'engine-bus', transport: transport);
await adapter.connect();
The host system needs the kernel CAN modules (modprobe can,
modprobe can_raw) and the interface up
(ip link set up can0 type can bitrate 500000).
CANopen + J1939 helpers #
// CANopen — read CiA-402 Statusword from node 5.
await adapter.execute(Command(
action: 'canopen.sdo_read', target: '',
args: {
'nodeId': 5,
'index': CiA402.statusword.index,
'subIndex': CiA402.statusword.subIndex,
},
));
// J1939 — look up Engine Controller 1 by acronym, send a PGN.
final pgn = J1939Pgns.byAcronym('EEC1')!;
await adapter.execute(Command(
action: 'j1939.subscribe_pgn', target: '',
args: {'pgn': pgn.pgn},
));
License #
MIT — see LICENSE.