DEV Community

Muhammad Umer Saeed
Muhammad Umer Saeed

Posted on

I Built an Open-Source J1939 CAN Bus Emulator (Because Vector Tools Cost Too Much)

If you've ever tried to test J1939 diagnostics tooling, integrate a telematics app, or just learn how heavy-duty vehicle networks work, you've probably hit the same wall I did: the real tools are excellent, expensive, and closed. A Vector CANoe/CANalyzer license is a serious purchase, and even once you have it, you still need a real ECU — or a very good simulation — to test against.

So I built one. This post covers why, what it does, and how it's put together. Three companion deep-dive posts cover the protocol internals (PGNs & address claim, DTCs & transport protocol, VIN & BAM) if you want to go further.

Why This Needed to Exist

A few things kept coming up whenever I talked to people trying to get started with J1939:

  • The established tools are expensive. Vector, Peak, and similar platforms are the industry standard for good reason, but the entry cost is real, especially for a startup or a solo developer who just wants to prototype.
  • They're hard to configure without deep CAN/J1939 knowledge already. The tooling assumes you know the protocol; it doesn't teach it.
  • Reading raw CAN traffic isn't the hard part — decoding it is. SPN scaling factors, byte ordering, PGN structure — none of that is obvious from a raw frame dump.
  • Python-can changes the economics. It's open-source, actively maintained, and supports a wide range of hardware — from professional-grade Vector interfaces down to a $30 CANable adapter.
  • Cheap hardware is genuinely good now. CANable and similar SLCAN-based adapters are inexpensive and easy to buy, and they work.
  • Virtual CAN means you don't need hardware at all for a lot of development. python-can supports virtual buses, so telematics and application-layer development can happen entirely in software.
  • The library ecosystem is mature. Logging, J1939 message handling, ISO-TP — the building blocks already exist in Python; they just hadn't been assembled into an approachable emulator.

That gap — approachable, cheap, open, and genuinely educational — is what this project fills.

What I Built

A python-can based J1939 ECU emulator, available as both a CLI and a GUI, running entirely on your machine.

CLI mode

  • Runs in a Docker container, so it fits into existing CI/CD or cloud infrastructure without modification
  • Virtual ECUs let you build and test a telematics application with zero hardware in the loop
  • Can be deployed to the cloud as a virtual vehicle for solution development and integration testing
  • Suited to automated testing pipelines, since it's fully scriptable

GUI mode

  • Runs on localhost, on a port you choose
  • Select your hardware, set the baud rate, and configure PGNs — five PGNs ship in v1.0, each with live sliders
  • Watch raw CAN values update in real time as you change signal values
  • Configurable PGN broadcast timing
  • Set or modify the VIN live
  • Inject and clear DTCs (both single-frame and multi-frame) to test fault-handling logic

Platform support

Runs in Chrome, Safari, Firefox, and Edge, and works cross-platform on Windows, Linux, and macOS.

Learning resources

  • YouTube playlist: install/run walkthrough, plus dedicated explainers on PGNs, DTCs, VIN, address claim, and the BAM/RTS-CTS transport mechanisms — watch here
  • GitHub repo: full source, README with setup and hardware instructions — github.com/EmbeddedVerse/j1939-emulator

Core protocol features

  • PGN broadcast (5 signals in v1.0)
  • DTCs — both single-frame and multi-frame (DM1)
  • VIN — multi-frame broadcast (BAM)
  • Address claim (J1939-81)
  • Configurable timing across all of the above

Who This Is Actually Useful For

  • Testing a J1939 scanner tool against a predictable, controllable ECU
  • ECU-to-ECU communication development and testing
  • Telematics application development — build against a virtual vehicle before any hardware exists
  • Learning how J1939 actually works — the emulator plus the video series is closer to a lab than a black box
  • Minimum-effort setup — one command line gets a running virtual ECU
  • Backed by documentation, cheap supported hardware, and a full video walkthrough series

How I Built It

Choosing the stack

  • python-can — open-source, wide hardware support, active community
  • NiceGUI — for the localhost GUI
  • CLI mode — built specifically to fit cloud-native/containerized deployment
  • CANable — the reference hardware, because it's cheap, easy to buy, and easy to test against

Architecture
The emulator was architected from the start to support both CLI and GUI from the same core, rather than bolting a GUI onto a script:

  • A CLI terminal layer for runtime parameter changes
  • The CLI path is what makes cloud-native deployment realistic
  • The GUI path is aimed at local development and fault injection, where a human is actively watching and adjusting values
  • Runtime value changes and signal calculation (scaling, encoding) happen live, not just at startup

Testing
I didn't just trust the code — I verified it against real hardware and a real analyzer:

  • Used CANable paired with TSMaster, and separately with a Vector VN1610
  • Verified raw CAN frames, timing, and data byte-for-byte
  • Specifically verified multi-frame (transport protocol) reassembly, since that's where most naive implementations break

Try It

If you want the protocol internals — how PGNs and address claim actually work on the wire, how DTCs get split across multiple CAN frames, why VIN broadcast needs its own transport session — the three companion posts in this series go deep on each.

I build custom CAN/J1939/OBD2 diagnostic tooling and embedded firmware for hardware product teams. Reach out if that's useful to you.

Top comments (0)