/ can

Monitoring GMLAN with Node.js

Before General Motors unceremoniously divested Saab Automobile AB and subsequently sentenced the moniker to a slowpainful death, they managed to produce the 9-3 Sport Sedan. The 9-3 was the modern incarnation of the classic 900, a quirky hatchback that has been ushering eccentric architects and designers about town for decades. In 2006 Saab introduced a new power plant to the model – the 2.8L V6 available only in the Aero trim. The engine could also be found – albeit naturally-aspirated – in the Cadillac CTS. But Saab took the engine, strapped a turbo to it, and found it to be an excellent combination. I tend to agree.

As the platform and engine were borne from GM plans, one can draw many correlations between it and other vehicles in the GM lineup. However, it just wasn’t Svenska enough for the engineers at Saab. So as they had become accustomed, they proceeded to implement a decidedly nordic interpretation of the familiar parts and resources they were given.

One example of this is particularly interesting (and frustrating) to those of us who occasionally don our engineer hat – GMLAN. GM designed a low speed, single-wire CAN bus intended to pass non-critical data around the vehicle – things like relaying a button press, or feeding data to the gauges. Saab refers to their implementation of GMLAN as I-Bus, as in Instrumentation Bus. This follows a naming convention pre-dating the use of GMLAN in their vehicles. There are a small number of resources for both the I-Bus and GMLAN, including the venerable GMLAN bible. However the I-Bus resources generally refer to a previous incantation of the bus using a typical two-wire CAN bus operating at an atypical bitrate. The GMLAN resources don’t offer much assistance either as they seem to be very Pontiac-centric, and it is immediately apparent after reviewing some of the data that Saab chose to eschew the established GM message format for their own. So we have some reverse-engineering ahead of us.

Good, great, grand, wonderful

The good news is that the physical interface follows the GMLAN spec, so it is relatively easy to connect to the bus and start sending and receiving messages. I chose the OBDLink MX as it supports GMLAN out of the box and made it very easy to get started. The MX is a bluetooth device that connects to the OBDII interface under the steering wheel, and GMLAN is exposed on pin 1 of the connector. After pairing, you can connect to the serial port provided by the MX with a serial terminal. On OSX I use screen /dev/tty.OBDLinkMX-STN-SPP You will be greeted by an ELM version message, and some quick configuration commands will get you setup and receiving messages.

ATL1 OK >STP 61 OK >ATMA

No yelling on the bus

At this point you will find yourself buried in a never-ending stream of indecipherable characters scrolling your terminal forever and ever. I was able to discover some messages almost by accident just by filtering for a specific ID and haphazardly mashing buttons about the cabin. But there must be a better way…

Let’s code

Although it wasn’t my first choice, Node.js ended up being an excellent way to quickly prototype a tool that would allow me to really interpret these messages, as well as keep my sanity. There are some existing CAN monitor projects that are both commercial and open source, all in varying degrees of complexity and cost. But the commercial tools are cost-prohibitive and the open source projects didn’t fit my requirements and/or were abandoned and wouldn’t compile. What I really needed was a simple tool that would

  • Match messages by ID and update in place, rather than appending a new line and scrolling the display
  • Indicate when a message was updating and which bytes were changing
  • Parse the bytes as ascii characters and display the interpreted text inline

The last point was important to me because I was hoping to discover messages that would write text to the Saab Information Display (SID). Spoiler alert: I didn’t because they’re not there.

The code is written in coffeescript (because it’s awesome) but the compiled javascript is checked into the repo for those that don’t know any better. I’m using serialport for the business end, charm for easy structured and colored terminal output, and underscore for some utility functions. It has some limitations as is, but I plan on making some minor improvements as I need them.

Check out the GitHub repo for code

All in all it was a fun couple hours of hacking in the car, and I have to admit it was pretty cool to see javascript wiping the windshield and rolling down the windows. And in the end I was able to compile a list of Saab I-Bus messages for the 9-3 SS. There is still a lot of unknown data there, so please contact me if you have any more information.