elmobd

package module
v0.0.0-...-8fbd115 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 28, 2025 License: MIT Imports: 12 Imported by: 0

README

# -*- org-confirm-babel-evaluate: nil -*-

* README

[[file:https://img.shields.io/badge/status-active-green.svg]]
[[https://travis-ci.org/rzetterberg/elmobd][file:https://travis-ci.org/rzetterberg/elmobd.svg?branch=master]]
[[https://goreportcard.com/report/github.com/rzetterberg/elmobd][file:https://goreportcard.com/badge/github.com/rzetterberg/elmobd?status.svg]]
[[https://godoc.org/github.com/rzetterberg/elmobd][file:https://godoc.org/github.com/rzetterberg/elmobd?status.svg]]

#+NAME: version_output
#+begin_src emacs-lisp :results raw :exports results
(with-temp-buffer
  (insert-file-contents "./VERSION")
  (format "- Version :: %s" (buffer-string))))
#+end_src

#+RESULTS: version_output
- Version :: 0.8.0

Go library for communicating with cars [[https://en.wikipedia.org/wiki/On-board_diagnostics][OBD-II]] system using [[https://www.elmelectronics.com/ic/elm327/][ELM327]] based
USB-devices.

To make this library as good as possible - feedback, bug reports and feature
requests are very welcome in the GitHub issues of this project.

** How it works

There are more than 10 different OBD-II signal protocol variations used by the
various cars that exist. To avoid having to handle all the details of these
protocols the ELM327 exists. The ELM327 acts a [[https://en.wikipedia.org/wiki/Facade_pattern][facade]] between the computer and
the car. You talk to the ELM327 using a simple text based protocol similar to
the [[https://en.wikipedia.org/wiki/Hayes_command_set][Hayes command set]] and the ELM327 takes care of the communication details
of the car.

#+LATEX: \vspace{0.5cm}
#+LATEX: \begin{center}
#+ATTR_LATEX: :width 8cm
#+RESULTS: fig:overview
[[file:docs/assets/overview-diagram.png]]
#+LATEX: \end{center}

As shown in the diagram above this library connects to a serial device of the
operating system. The library is not concerned with what is connected to that
serial device, whether it's a bluetooth USB-dongle with a ELM327 at the other
end or a ELM327 connected directly via an USB-cable.

Communicating with the ELM327 is similar to communicating with a web server.
You make a *request* and wait for a *response*. However, in this context we are
*calling a command* and waiting for *one or more responses*.

This library is designed to be used in a way that resembles the way you
physically use the device. You have a type called ~Device~ that represents
a ELM327 device connected to the computer. This ~Device~ then has a function
called ~RunCommand~ that sends a command to the actual device and then waits
for a response.

This library aims to be as type safe as possible, which means that you don't
deal with raw text commands, instead you have different command /types/.

All command /types/ need to implement the ~OBDCommand~ /interface/ to be
able to be run on the device. Since there are A LOT of OBD commands, you can
easily extend this library, by just implementing the ~OBDCommand~ /interface/
of your commands.

Let's start by looking at some example of how you use the library.

** Example usage

*Note:* these examples are performed on Linux. If you are using another platform
there should be minimal changes, but they are not documented yet. Go ahead
and put a :+1: on issue #11 if you think this should be prioritized.

First of all, you need to plug in your ELM327 device into your computer and
get the path to the device. You can plugin the device and check dmesg, this is
what I get on my computer:

#+BEGIN_EXAMPLE
$ dmesg | tail
[359720.858480] usb 6-2: Manufacturer: FTDI
[359720.858482] usb 6-2: SerialNumber: A503GJEX
[359720.897717] usbcore: registered new interface driver usbserial
[359720.897733] usbcore: registered new interface driver usbserial_generic
[359720.897748] usbserial: USB Serial support registered for generic
[359720.901755] usbcore: registered new interface driver ftdi_sio
[359720.901767] usbserial: USB Serial support registered for FTDI USB Serial Device
[359720.901839] ftdi_sio 6-2:1.0: FTDI USB Serial Device converter detected
[359720.901913] usb 6-2: Detected FT232RL
[359720.904481] usb 6-2: FTDI USB Serial Device converter now attached to ttyUSB0
#+END_EXAMPLE

Now that I know that the device is available at ~/dev/ttyUSB0~ I can use the
library to connect to the device and check the ~ELM327~ version of the device:

*example1.go*
#+NAME: src:example1
#+BEGIN_SRC go :tangle ./examples/example_1/main.go :mkdirp yes
package main

import (
	"flag"
	"fmt"
	"github.com/rzetterberg/elmobd"
)

func main() {
	serialPath := flag.String(
		"serial",
		"/dev/ttyUSB0",
		"Path to the serial device to use",
	)

	flag.Parse()

	dev, err := elmobd.NewTestDevice(*serialPath, false)

	if err != nil {
		fmt.Println("Failed to create new device", err)
		return
	}

	version, err := dev.GetVersion()

	if err != nil {
		fmt.Println("Failed to get version", err)
		return
	}

	fmt.Println("Device has version", version)
}
#+END_SRC

*Note:* These examples uses the function ~NewTestDevice~, which uses a mocked
ELM327 device. To use a real ELM327 device, you instead use ~NewDevice~. The
reason why a mocked device is used is because the examples should be runnable
without using a real device.

#+BEGIN_EXAMPLE
$ go run example.go
Device has version OBDII by elm329@gmail.com
#+END_EXAMPLE

The next step is to run some OBD commands on the device. For this we need to
plug in the ELM327 into our car and turn on the ignition.

Like mentioned before you use the function ~RunCommand~ that accepts a
~OBDCommand~ to run. A ~OBDCommand~ has 3 responsibilities:

- Tell the ELM327 what command to run
- Store the value
- Convert the value to a common format

So you start out by creating a new ~OBDCommand~ that does not contain a value.
You then take that ~OBDCommand~ and call the ~RunCommand~ function with it.
~RunCommand~ will then return the ~OBDCommand~ with the value from the car.

Let's try this out by checking the RPM of the engine. There is a ~OBDCommand~
for that defined in the library already, called ~EngineRPM~. We start by
creating a new ~EngineRPM~ that we call ~RunCommand~ with:

*example2.go*
#+NAME: src:example2
#+BEGIN_SRC go :tangle ./examples/example_2/main.go :mkdirp yes
package main

import (
	"flag"
	"fmt"
	"github.com/rzetterberg/elmobd"
)

func main() {
	serialPath := flag.String(
		"serial",
		"/dev/ttyUSB0",
		"Path to the serial device to use",
	)

	flag.Parse()

	dev, err := elmobd.NewTestDevice(*serialPath, false)

	if err != nil {
		fmt.Println("Failed to create new device", err)
		return
	}

	rpm, err := dev.RunOBDCommand(elmobd.NewEngineRPM())

	if err != nil {
		fmt.Println("Failed to get rpm", err)
		return
	}

	fmt.Printf("Engine spins at %s RPMs\n", rpm.ValueAsLit())
}
#+END_SRC

There are more than 180 different OBD commands, and cars have different support
for these commands. So to avoid sending OBD commands to the car that it does not
support we can check what commands the car support:

*example3.go*
#+NAME: src:example3
#+BEGIN_SRC go :tangle ./examples/example_3/main.go :mkdirp yes
package main

import (
	"flag"
	"fmt"
	"github.com/rzetterberg/elmobd"
)

func main() {
	serialPath := flag.String(
		"serial",
		"/dev/ttyUSB0",
		"Path to the serial device to use",
	)

	flag.Parse()

	dev, err := elmobd.NewTestDevice(*serialPath, false)

	if err != nil {
		fmt.Println("Failed to create new device", err)
		return
	}

	supported, err := dev.CheckSupportedCommands()

	if err != nil {
		fmt.Println("Failed to check supported commands", err)
		return
	}

	rpm := elmobd.NewEngineRPM()

	if supported.IsSupported(rpm) {
		fmt.Println("The car supports checking RPM")
	} else {
		fmt.Println("The car does NOT supports checking RPM")
	}
}
#+END_SRC

The ~supported~ here is a ~SupportedCommands~ which is a special type that
stores the raw lookup table and exposes two helper functions that reads this
table:

- ~IsSupported~ :: Check if given command is supported
- ~FilterSupported~ :: Filters out supported commands from given list

For simplicity there's a function called ~GetSensorCommands~ which gives you a
list of all the commands defined in the library. You can use this list of
commands and filter out what commands are supported on by car:

*example4.go*
#+NAME: src:example4
#+BEGIN_SRC go :tangle ./examples/example_4/main.go :mkdirp yes
package main

import (
	"flag"
	"fmt"
	"github.com/rzetterberg/elmobd"
)

func main() {
	serialPath := flag.String(
		"serial",
		"/dev/ttyUSB0",
		"Path to the serial device to use",
	)

	flag.Parse()

	dev, err := elmobd.NewTestDevice(*serialPath, false)

	if err != nil {
		fmt.Println("Failed to create new device", err)
		return
	}

	supported, err := dev.CheckSupportedCommands()

	if err != nil {
		fmt.Println("Failed to check supported commands", err)
		return
	}

	allCommands := elmobd.GetSensorCommands()
	carCommands := supported.FilterSupported(allCommands)

	fmt.Printf("%d of %d commands supported:\n", len(carCommands), len(allCommands))

	for _, cmd := range carCommands {
		fmt.Printf("- %s supported\n", cmd.Key())
	}
}
#+END_SRC

Besides checking sensor values, you can also check whether the [[https://en.wikipedia.org/wiki/Check_engine_light][MIL]] is on and if there are
any [[https://en.wikipedia.org/wiki/On-board_diagnostics#EOBD_fault_codes][DTCs]]:

*example5.go*
#+NAME: src:example5
#+BEGIN_SRC go :tangle ./examples/example_5/main.go :mkdirp yes
package main

import (
	"flag"
	"fmt"
	"github.com/rzetterberg/elmobd"
)

func main() {
	serialPath := flag.String(
		"serial",
		"/dev/ttyUSB0",
		"Path to the serial device to use",
	)

	flag.Parse()

	dev, err := elmobd.NewTestDevice(*serialPath, false)

	if err != nil {
		fmt.Println("Failed to create new device", err)
		return
	}

	cmd, err := dev.RunOBDCommand(elmobd.NewMonitorStatus())

	if err != nil {
		fmt.Println("Failed to get monitor status", err)
		return
	}

        status := cmd.(*elmobd.MonitorStatus)

	fmt.Printf("MIL is on: %t, DTCamount: %d\n", status.MilActive, status.DtcAmount)
}
#+END_SRC

Please see [[https://godoc.org/github.com/rzetterberg/elmobd][the godocs]] for a more detailed explanation of the library and it's
structure.

** Features

- [X] Reading sensor data
- [ ] Reading trouble codes
- [ ] Resetting Check Engine Light
- [ ] Reading freezed sensor data

** Roadmap

The project uses quarterly milestones to plan upcoming changes. The current
quarter will focus on implementing new features. To see the details of what
will be done see the milestone [[https://github.com/rzetterberg/elmobd/milestone/4][2018 Q3]].

Changes of the library are tracked in the [[file:CHANGELOG.md][CHANGELOG]].

** Compability

*** Platforms

The library has been built and tested on the following platforms:

| Operating system    | Go version |
|---------------------+------------|
| Linux 4.9.25 x86_64 | 1.9        |

*** Cars

The library has been used successfully on the following cars:

| Car                       | Library version | Tester       |
|---------------------------+-----------------+--------------|
| Lexus IS200 Manual 2004   |           0.3.0 | @rzetterberg |
| Ford Ka 2011              |           0.5.0 | @Enrico204   |
| Ford Transit Automat 2019 |           0.6.0 | @mikspec     |

Documentation

Overview

Package elmobd provides communication with cars OBD-II system using ELM327 based USB-devices.

Using this library and a ELM327-based USB-device you can communicate with your cars on-board diagnostics system to read sensor data. Reading trouble codes and resetting them is not yet implemented.

All assumptions this library makes are based on the official Elm Electronics datasheet of the ELM327 IC: https://www.elmelectronics.com/wp-content/uploads/2017/01/ELM327DS.pdf

After that introduction - Welcome! I hope you'll find this library useful and its documentation easy to digest. If that's not the case, please create a GitHub-issue: https://github.com/rzetterberg/elmobd/issues

You'll note that this package has the majority its types and functions exported. The reason for that is that there are many different commands you can send to a ELM327 device, and this library will never we able to define all commands, so most functionality is exported so that you can easily extend it.

You'll also note that there are A LOT of types. The reason for this is each command that can be sent to the ELM327 device is defined as it's own type. The approach I wanted to take with this library was to get as much type safety as possible.

With that said, as an end user of this library you'll only need to know about two kinds types: the Device type and types that implement the OBDCommand interface.

The Device type represents an active connection with an ELM327 device. You plug in your device into your computer, get the path to the device and initialize a new device:

package main

import (
    "flag"
    "fmt"
    "github.com/05sec/elmobd"
)

func main() {
    serialPath := flag.String(
        "serial",
        "/dev/ttyUSB0",
        "Path to the serial device to use",
    )

    flag.Parse()

    dev, err := elmobd.NewDevice(*serialPath, false)

    if err != nil {
        fmt.Println("Failed to create new device", err)
        return
    }
}

This library is design to be as high level as possible, you shouldn't need to handle baud rates, setting protocols or anything like that. After the Device has been initialized you can just start sending commands.

The function you will be using the most is the Device.RunOBDCommand, which accepts a command, sends the command to the device, waits for a response, parses the response and gives it back to you. Which means this command is blocking execution until it has been finished. The default timeout is currently set to 5 seconds.

The RunOBDCommand accepts a single argument, a type that implements the OBDCommand interface. That interface has a couple of functions that needs to exist in order to be able to generate the low-level request for the device and parse the low-level response. Basically you send in an empty OBDCommand and get back a OBDCommand with the processed value retrieved from the device.

Suppose that after checking the device connection (in our example above) we would like to retrieve the vehicles speed. There's a type called VehicleSpeed that implements the OBDCommand interface that we can use. We start by creating a new VehicleSpeed using its constructor NewVehicleSpeed that we then give to RunOBDCommand:

speed, err := dev.RunOBDCommand(elmobd.NewVehicleSpeed())

if err != nil {
    fmt.Println("Failed to get vehicle speed", err)
    return
}

fmt.Printf("Vehicle speed: %d km/h\n", speed.Value)

At the moment there are around 15 sensor commands defined in this library. They are all defined in the file commands.go of the library (https://github.com/rzetterberg/elmobd/blob/master/commands.go). If you look in the end of that file you'll find an internal static variable with all the sensor commands called sensorCommands.

That's the basics of this library - you create a device connection and then run commands. Documentation of more advanced use-cases is in the works, so don't worry! If there's something that you wish would be documented, or something that is not clear in the current documentation, please create a GitHub-issue.

Index

Constants

View Source
const PartRange = 0x20

PartRange represents how many PIDs there are in one part

View Source
const SERVICE_01_ID = 0x01
View Source
const SERVICE_04_ID = 0x04

Variables

This section is empty.

Functions

This section is empty.

Types

type AbsoluteBarometricPressure

type AbsoluteBarometricPressure struct {
	IntCommand
	// contains filtered or unexported fields
}

AbsoluteBarometricPressure

func NewAbsoluteBarometricPressure

func NewAbsoluteBarometricPressure() *AbsoluteBarometricPressure

NewAbsoluteBarometricPressure creates a new AbsoluteBarometricPressure with the right parameters.

func (*AbsoluteBarometricPressure) DataWidth

func (cmd *AbsoluteBarometricPressure) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*AbsoluteBarometricPressure) Key

func (cmd *AbsoluteBarometricPressure) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*AbsoluteBarometricPressure) ModeID

func (cmd *AbsoluteBarometricPressure) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*AbsoluteBarometricPressure) ParameterID

func (cmd *AbsoluteBarometricPressure) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*AbsoluteBarometricPressure) SetValue

func (cmd *AbsoluteBarometricPressure) SetValue(result *Result) error

SetValue processes the byte array value into the right integer value.

func (*AbsoluteBarometricPressure) ToCommand

func (cmd *AbsoluteBarometricPressure) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type AmbientTemperature

type AmbientTemperature struct {
	IntCommand
	// contains filtered or unexported fields
}

AmbientTemperature represents a command that checks the engine coolant temperature in Celsius.

Min: -40 Max: 215

func NewAmbientTemperature

func NewAmbientTemperature() *AmbientTemperature

NewAmbientTemperature creates a new AmbientTemperature with the right parameters.

func (*AmbientTemperature) DataWidth

func (cmd *AmbientTemperature) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*AmbientTemperature) Key

func (cmd *AmbientTemperature) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*AmbientTemperature) ModeID

func (cmd *AmbientTemperature) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*AmbientTemperature) ParameterID

func (cmd *AmbientTemperature) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*AmbientTemperature) SetValue

func (cmd *AmbientTemperature) SetValue(result *Result) error

SetValue processes the byte array value into the right integer value.

func (*AmbientTemperature) ToCommand

func (cmd *AmbientTemperature) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type ClearTroubleCodes

type ClearTroubleCodes struct {
	ResultLessCommand
	// contains filtered or unexported fields
}

func NewClearTroubleCodes

func NewClearTroubleCodes() *ClearTroubleCodes

NewClearTroubleCodes creates a new ClearTroubleCodes with the right parameters..

func (*ClearTroubleCodes) DataWidth

func (cmd *ClearTroubleCodes) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*ClearTroubleCodes) Key

func (cmd *ClearTroubleCodes) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*ClearTroubleCodes) ModeID

func (cmd *ClearTroubleCodes) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*ClearTroubleCodes) ParameterID

func (cmd *ClearTroubleCodes) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*ClearTroubleCodes) ToCommand

func (cmd *ClearTroubleCodes) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type Conn

type Conn interface {
	io.ReadWriteCloser
	Flush() error
}

type ControlModuleVoltage

type ControlModuleVoltage struct {
	FloatCommand
	// contains filtered or unexported fields
}

Control module voltage

func NewControlModuleVoltage

func NewControlModuleVoltage() *ControlModuleVoltage

NewControlModuleVoltage creates a new ControlModuleVoltage with the right parameters.

func (*ControlModuleVoltage) DataWidth

func (cmd *ControlModuleVoltage) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*ControlModuleVoltage) Key

func (cmd *ControlModuleVoltage) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*ControlModuleVoltage) ModeID

func (cmd *ControlModuleVoltage) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*ControlModuleVoltage) ParameterID

func (cmd *ControlModuleVoltage) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*ControlModuleVoltage) SetValue

func (cmd *ControlModuleVoltage) SetValue(result *Result) error

SetValue processes the byte array value into the right float value.

func (*ControlModuleVoltage) ToCommand

func (cmd *ControlModuleVoltage) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type CoolantTemperature

type CoolantTemperature struct {
	IntCommand
	// contains filtered or unexported fields
}

CoolantTemperature represents a command that checks the engine coolant temperature in Celsius.

Min: -40 Max: 215

func NewCoolantTemperature

func NewCoolantTemperature() *CoolantTemperature

NewCoolantTemperature creates a new CoolantTemperature with the right parameters.

func (*CoolantTemperature) DataWidth

func (cmd *CoolantTemperature) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*CoolantTemperature) Key

func (cmd *CoolantTemperature) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*CoolantTemperature) ModeID

func (cmd *CoolantTemperature) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*CoolantTemperature) ParameterID

func (cmd *CoolantTemperature) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*CoolantTemperature) SetValue

func (cmd *CoolantTemperature) SetValue(result *Result) error

SetValue processes the byte array value into the right integer value.

func (*CoolantTemperature) ToCommand

func (cmd *CoolantTemperature) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type Device

type Device struct {
	// contains filtered or unexported fields
}

Device represents the connection to a ELM327 device. This is the data type you use to run commands on the connected ELM327 device, see NewDevice for creating a Device and RunOBDCommand for running commands.

func NewDevice

func NewDevice(addr string, debug bool) (*Device, error)

NewDevice constructs a Device by initializing the serial connection and setting the protocol to talk with the car to "automatic".

func (*Device) CheckSupportedCommands

func (dev *Device) CheckSupportedCommands() (*SupportedCommands, error)

CheckSupportedCommands check which commands are supported by the car connected to the ELM327 device.

func (*Device) GetIgnitionState

func (dev *Device) GetIgnitionState() (bool, error)

GetIgnitionState retrieves the current state of the cars ignition

func (*Device) GetVersion

func (dev *Device) GetVersion() (string, error)

GetVersion gets the version of the connected ELM327 device. The latest version being v2.2.

func (*Device) GetVoltage

func (dev *Device) GetVoltage() (float32, error)

GetVoltage gets the current battery voltage of the vehicle as measured by the ELM327 device.

func (*Device) RunManyOBDCommands

func (dev *Device) RunManyOBDCommands(commands []OBDCommand) ([]OBDCommand, error)

RunManyOBDCommands is a helper function to run multiple commands in series.

func (*Device) RunOBDCommand

func (dev *Device) RunOBDCommand(cmd OBDCommand) (OBDCommand, error)

RunOBDCommand runs the given OBDCommand on the connected ELM327 device and populates the OBDCommand with the parsed output from the device.

func (*Device) SetAutomaticProtocol

func (dev *Device) SetAutomaticProtocol() error

SetAutomaticProtocol tells the ELM327 device to automatically discover what protocol to talk to the car with. How the protocol is chosen is something that the ELM327 does internally. If you're interested in how this works you can look in the data sheet linked in the beginning of the package description.

type DistSinceDTCClear

type DistSinceDTCClear struct {
	UIntCommand
	// contains filtered or unexported fields
}

DistSinceDTCClear represents a command that checks distance since last DTC clear

Min: 0 Max: 65535

func NewDistSinceDTCClear

func NewDistSinceDTCClear() *DistSinceDTCClear

NewDistSinceDTCClear creates a new commend distance since DTC clear with the correct parameters.

func (*DistSinceDTCClear) DataWidth

func (cmd *DistSinceDTCClear) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*DistSinceDTCClear) Key

func (cmd *DistSinceDTCClear) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*DistSinceDTCClear) ModeID

func (cmd *DistSinceDTCClear) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*DistSinceDTCClear) ParameterID

func (cmd *DistSinceDTCClear) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*DistSinceDTCClear) SetValue

func (cmd *DistSinceDTCClear) SetValue(result *Result) error

SetValue processes the byte array value into the right uint value.

func (*DistSinceDTCClear) ToCommand

func (cmd *DistSinceDTCClear) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type EngineLoad

type EngineLoad struct {
	FloatCommand
	// contains filtered or unexported fields
}

EngineLoad represents a command that checks the engine load in percent

Min: 0.0 Max: 1.0

func NewEngineLoad

func NewEngineLoad() *EngineLoad

NewEngineLoad creates a new EngineLoad with the correct parameters.

func (*EngineLoad) DataWidth

func (cmd *EngineLoad) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*EngineLoad) Key

func (cmd *EngineLoad) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*EngineLoad) ModeID

func (cmd *EngineLoad) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*EngineLoad) ParameterID

func (cmd *EngineLoad) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*EngineLoad) SetValue

func (cmd *EngineLoad) SetValue(result *Result) error

SetValue processes the byte array value into the right float value.

func (*EngineLoad) ToCommand

func (cmd *EngineLoad) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type EngineOilTemperature

type EngineOilTemperature struct {
	IntCommand
	// contains filtered or unexported fields
}

EngineOilTemperature represents a command that checks the engine oil temperature in Celsius.

Min: -40 Max: 215

func NewEngineOilTemperature

func NewEngineOilTemperature() *EngineOilTemperature

NewEngineOilTemperature creates a new EngineOilTemperature with the right parameters.

func (*EngineOilTemperature) DataWidth

func (cmd *EngineOilTemperature) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*EngineOilTemperature) Key

func (cmd *EngineOilTemperature) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*EngineOilTemperature) ModeID

func (cmd *EngineOilTemperature) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*EngineOilTemperature) ParameterID

func (cmd *EngineOilTemperature) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*EngineOilTemperature) SetValue

func (cmd *EngineOilTemperature) SetValue(result *Result) error

SetValue processes the byte array value into the right integer value.

func (*EngineOilTemperature) ToCommand

func (cmd *EngineOilTemperature) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type EngineRPM

type EngineRPM struct {
	FloatCommand
	// contains filtered or unexported fields
}

EngineRPM represents a command that checks eEngine revolutions per minute.

Min: 0.0 Max: 16383.75

func NewEngineRPM

func NewEngineRPM() *EngineRPM

NewEngineRPM creates a new EngineRPM with the right parameters.

func (*EngineRPM) DataWidth

func (cmd *EngineRPM) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*EngineRPM) Key

func (cmd *EngineRPM) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*EngineRPM) ModeID

func (cmd *EngineRPM) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*EngineRPM) ParameterID

func (cmd *EngineRPM) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*EngineRPM) SetValue

func (cmd *EngineRPM) SetValue(result *Result) error

SetValue processes the byte array value into the right float value.

func (*EngineRPM) ToCommand

func (cmd *EngineRPM) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type FloatCommand

type FloatCommand struct {
	Value float32
}

FloatCommand is just a shortcut for commands that retrieve floating point values from the ELM327 device.

func (*FloatCommand) ValueAsLit

func (cmd *FloatCommand) ValueAsLit() string

ValueAsLit retrieves the value as a literal representation.

type Fuel

type Fuel struct {
	FloatCommand
	// contains filtered or unexported fields
}

Fuel represents a command that checks the fuel quantity in percent

Min: 0.0 Max: 1.0

func NewFuel

func NewFuel() *Fuel

NewFuel creates a new Fuel with the correct parameters.

func (*Fuel) DataWidth

func (cmd *Fuel) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*Fuel) Key

func (cmd *Fuel) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*Fuel) ModeID

func (cmd *Fuel) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*Fuel) ParameterID

func (cmd *Fuel) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*Fuel) SetValue

func (cmd *Fuel) SetValue(result *Result) error

SetValue processes the byte array value into the right float value.

func (*Fuel) ToCommand

func (cmd *Fuel) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type FuelPressure

type FuelPressure struct {
	UIntCommand
	// contains filtered or unexported fields
}

FuelPressure represents a command that checks the fuel pressure in kPa.

Min: 0 Max: 765

func NewFuelPressure

func NewFuelPressure() *FuelPressure

NewFuelPressure creates a new FuelPressure with the right parameters.

func (*FuelPressure) DataWidth

func (cmd *FuelPressure) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*FuelPressure) Key

func (cmd *FuelPressure) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*FuelPressure) ModeID

func (cmd *FuelPressure) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*FuelPressure) ParameterID

func (cmd *FuelPressure) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*FuelPressure) SetValue

func (cmd *FuelPressure) SetValue(result *Result) error

SetValue processes the byte array value into the right unsigned integer value.

func (*FuelPressure) ToCommand

func (cmd *FuelPressure) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type IntCommand

type IntCommand struct {
	Value int
}

IntCommand is just a shortcut for commands that retrieve integer values from the ELM327 device.

func (*IntCommand) ValueAsLit

func (cmd *IntCommand) ValueAsLit() string

ValueAsLit retrieves the value as a literal representation.

type IntakeAirTemperature

type IntakeAirTemperature struct {
	IntCommand
	// contains filtered or unexported fields
}

IntakeAirTemperature represents a command that checks the intake air temperature in Celsius.

Min: -40 Max: 215

func NewIntakeAirTemperature

func NewIntakeAirTemperature() *IntakeAirTemperature

NewIntakeAirTemperature creates a new IntakeAirTemperature with the right parameters.

func (*IntakeAirTemperature) DataWidth

func (cmd *IntakeAirTemperature) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*IntakeAirTemperature) Key

func (cmd *IntakeAirTemperature) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*IntakeAirTemperature) ModeID

func (cmd *IntakeAirTemperature) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*IntakeAirTemperature) ParameterID

func (cmd *IntakeAirTemperature) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*IntakeAirTemperature) SetValue

func (cmd *IntakeAirTemperature) SetValue(result *Result) error

SetValue processes the byte array value into the right integer value.

func (*IntakeAirTemperature) ToCommand

func (cmd *IntakeAirTemperature) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type IntakeManifoldPressure

type IntakeManifoldPressure struct {
	UIntCommand
	// contains filtered or unexported fields
}

IntakeManifoldPressure represents a command that checks the intake manifold pressure in kPa.

Min: 0 Max: 255

func NewIntakeManifoldPressure

func NewIntakeManifoldPressure() *IntakeManifoldPressure

NewIntakeManifoldPressure creates a new IntakeManifoldPressure with the right parameters.

func (*IntakeManifoldPressure) DataWidth

func (cmd *IntakeManifoldPressure) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*IntakeManifoldPressure) Key

func (cmd *IntakeManifoldPressure) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*IntakeManifoldPressure) ModeID

func (cmd *IntakeManifoldPressure) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*IntakeManifoldPressure) ParameterID

func (cmd *IntakeManifoldPressure) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*IntakeManifoldPressure) SetValue

func (cmd *IntakeManifoldPressure) SetValue(result *Result) error

SetValue processes the byte array value into the right unsigned integer value.

func (*IntakeManifoldPressure) ToCommand

func (cmd *IntakeManifoldPressure) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type LongFuelTrim1

type LongFuelTrim1 struct {
	// contains filtered or unexported fields
}

LongFuelTrim1 represents a command that checks the long term fuel trim for bank 1.

func NewLongFuelTrim1

func NewLongFuelTrim1() *LongFuelTrim1

NewLongFuelTrim1 creates a new LongFuelTrim1 with the right parameters.

func (*LongFuelTrim1) SetValue

func (cmd *LongFuelTrim1) SetValue(result *Result) error

SetValue processes the byte array value into the right float value.

type LongFuelTrim2

type LongFuelTrim2 struct {
	// contains filtered or unexported fields
}

LongFuelTrim2 represents a command that checks the long term fuel trim for bank 2.

func NewLongFuelTrim2

func NewLongFuelTrim2() *LongFuelTrim2

NewLongFuelTrim2 creates a new LongFuelTrim2 with the right parameters.

func (*LongFuelTrim2) SetValue

func (cmd *LongFuelTrim2) SetValue(result *Result) error

SetValue processes the byte array value into the right float value.

type MafAirFlowRate

type MafAirFlowRate struct {
	FloatCommand
	// contains filtered or unexported fields
}

MafAirFlowRate represents a command that checks the mass Air Flow sensor flow rate grams/second.

Min: 0 Max: 655.35

More information about MAF: https://en.wikipedia.org/wiki/Mass_flow_sensor

func NewMafAirFlowRate

func NewMafAirFlowRate() *MafAirFlowRate

NewMafAirFlowRate creates a new MafAirFlowRate with the right parameters.

func (*MafAirFlowRate) DataWidth

func (cmd *MafAirFlowRate) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*MafAirFlowRate) Key

func (cmd *MafAirFlowRate) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*MafAirFlowRate) ModeID

func (cmd *MafAirFlowRate) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*MafAirFlowRate) ParameterID

func (cmd *MafAirFlowRate) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*MafAirFlowRate) SetValue

func (cmd *MafAirFlowRate) SetValue(result *Result) error

SetValue processes the byte array value into the right float value.

func (*MafAirFlowRate) ToCommand

func (cmd *MafAirFlowRate) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type MockDevice

type MockDevice struct {
}

MockDevice represent a mocked serial connection

func (*MockDevice) RunCommand

func (dev *MockDevice) RunCommand(command string) RawResult

RunCommand mocks the given AT/OBD command by just returning a result for the mocked outputs set earlier.

type MockResult

type MockResult struct {
	// contains filtered or unexported fields
}

MockResult represents the raw text output of running a raw command, including information used in debugging to show what input caused what error, how long the command took, etc.

func (*MockResult) Failed

func (res *MockResult) Failed() bool

Failed checks if the result is successful or not

func (*MockResult) FormatOverview

func (res *MockResult) FormatOverview() string

FormatOverview formats a result as an overview of what command was run and how long it took.

func (*MockResult) GetError

func (res *MockResult) GetError() error

GetError returns the results current error

func (*MockResult) GetOutputs

func (res *MockResult) GetOutputs() []string

GetOutputs returns the outputs of the result

type MonitorStatus

type MonitorStatus struct {
	MilActive bool
	DtcAmount byte
	// contains filtered or unexported fields
}

MonitorStatus represents a command that checks the status since DTCs were cleared last time. This includes the MIL status and the amount of DTCs.

func NewMonitorStatus

func NewMonitorStatus() *MonitorStatus

NewMonitorStatus creates a new MonitorStatus.

func (*MonitorStatus) DataWidth

func (cmd *MonitorStatus) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*MonitorStatus) Key

func (cmd *MonitorStatus) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*MonitorStatus) ModeID

func (cmd *MonitorStatus) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*MonitorStatus) ParameterID

func (cmd *MonitorStatus) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*MonitorStatus) SetValue

func (cmd *MonitorStatus) SetValue(result *Result) error

SetValue processes the byte array value into the right unsigned integer value.

func (*MonitorStatus) ToCommand

func (cmd *MonitorStatus) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

func (*MonitorStatus) ValueAsLit

func (cmd *MonitorStatus) ValueAsLit() string

ValueAsLit retrieves the value as a literal representation.

type OBDCommand

type OBDCommand interface {
	ModeID() byte
	ParameterID() OBDParameterID
	DataWidth() byte
	Key() string
	SetValue(*Result) error
	ValueAsLit() string
	ToCommand() string
}

OBDCommand is an interface that all OBD commands needs to implement to be able to be used with the Device.

func GetSensorCommands

func GetSensorCommands() []OBDCommand

GetSensorCommands returns all the defined commands that are not commands that check command availability on the connected car.

type OBDParameterID

type OBDParameterID byte

OBDParameterID is an alias to give meaning to this particular byte.

type OBDStandards

type OBDStandards struct {
	UIntCommand
	// contains filtered or unexported fields
}

OBDStandards represents a command that checks the OBD standards this vehicle conforms to as a single decimal value:

- 1 OBD-II as defined by the CARB - 2 OBD as defined by the EPA - 3 OBD and OBD-II - 4 OBD-I - 5 Not OBD compliant - 6 EOBD (Europe) - 7 EOBD and OBD-II - 8 EOBD and OBD - 9 EOBD, OBD and OBD II - 10 JOBD (Japan) - 11 JOBD and OBD II - 12 JOBD and EOBD - 13 JOBD, EOBD, and OBD II - 14 Reserved - 15 Reserved - 16 Reserved - 17 Engine Manufacturer Diagnostics (EMD) - 18 Engine Manufacturer Diagnostics Enhanced (EMD+) - 19 Heavy Duty On-Board Diagnostics (Child/Partial) (HD OBD-C) - 20 Heavy Duty On-Board Diagnostics (HD OBD) - 21 World Wide Harmonized OBD (WWH OBD) - 22 Reserved - 23 Heavy Duty Euro OBD Stage I without NOx control (HD EOBD-I) - 24 Heavy Duty Euro OBD Stage I with NOx control (HD EOBD-I N) - 25 Heavy Duty Euro OBD Stage II without NOx control (HD EOBD-II) - 26 Heavy Duty Euro OBD Stage II with NOx control (HD EOBD-II N) - 27 Reserved - 28 Brazil OBD Phase 1 (OBDBr-1) - 29 Brazil OBD Phase 2 (OBDBr-2) - 30 Korean OBD (KOBD) - 31 India OBD I (IOBD I) - 32 India OBD II (IOBD II) - 33 Heavy Duty Euro OBD Stage VI (HD EOBD-IV) - 34-250 Reserved - 251-255 Not available for assignment (SAE J1939 special meaning)

func NewOBDStandards

func NewOBDStandards() *OBDStandards

NewOBDStandards creates a new OBDStandards with the right parameters.

func (*OBDStandards) DataWidth

func (cmd *OBDStandards) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*OBDStandards) Key

func (cmd *OBDStandards) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*OBDStandards) ModeID

func (cmd *OBDStandards) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*OBDStandards) ParameterID

func (cmd *OBDStandards) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*OBDStandards) SetValue

func (cmd *OBDStandards) SetValue(result *Result) error

SetValue processes the byte array value into the right unsigned integer value.

func (*OBDStandards) ToCommand

func (cmd *OBDStandards) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type Odometer

type Odometer struct {
	FloatCommand
	// contains filtered or unexported fields
}

Odometer represents the distance travelled in kilometers

Min: 0 Max: 429,496,729.5

func NewOdometer

func NewOdometer() *Odometer

NewOdometer creates a new odometer value with the correct parameters.

func (*Odometer) DataWidth

func (cmd *Odometer) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*Odometer) Key

func (cmd *Odometer) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*Odometer) ModeID

func (cmd *Odometer) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*Odometer) ParameterID

func (cmd *Odometer) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*Odometer) SetValue

func (cmd *Odometer) SetValue(result *Result) error

SetValue processes the byte array value into the right uint value.

func (*Odometer) ToCommand

func (cmd *Odometer) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type PartSupported

type PartSupported struct {
	UIntCommand
	// contains filtered or unexported fields
}

PartSupported represents a command that checks which 31 PIDs are supported of a part.

All PIDs are divided into parts 7 parts with the following PIDs:

- Part 1 (0x00): 0x01 to 0x20 - Part 2 (0x20): 0x21 to 0x40 - Part 3 (0x40): 0x41 to 0x60 - Part 4 (0x60): 0x61 to 0x80 - Part 5 (0x80): 0x81 to 0xA0 - Part 6 (0xA0): 0xA1 to 0xC0 - Part 7 (0xC0): 0xC1 to 0xE0

PID 0x00 checks which PIDs that are supported of part 1, after that, the last PID of each part checks the whether the next part is supported.

So PID 0x20 of Part 1 checks which PIDs in part 2 are supported, PID 0x40 of part 2 checks which PIDs in part 3 are supported, etc etc.

func NewPartSupported

func NewPartSupported(index byte) *PartSupported

NewPartSupported creates a new PartSupported.

func (*PartSupported) CommandInRange

func (part *PartSupported) CommandInRange(cmd OBDCommand) bool

CommandInRange checks if the PID of the given command is in range of the current part.

For example, if the current part is 1 (0x01 to 0x20) and the given command has a PID of 0x10, then this function returns true.

If the given command has a PID of 0x31 then this function returns false.

func (*PartSupported) DataWidth

func (cmd *PartSupported) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*PartSupported) Index

func (part *PartSupported) Index() byte

Index returns the part index.

func (*PartSupported) Key

func (cmd *PartSupported) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*PartSupported) ModeID

func (cmd *PartSupported) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*PartSupported) PIDInRange

func (part *PartSupported) PIDInRange(comparePID OBDParameterID) bool

PIDInRange checks if the given is in range of the current part.

For example, if the current part is 1 (0x01 to 0x20) and the given command has a PID of 0x10, then this function returns true.

If the given command has a PID of 0x31 then this function returns false.

func (*PartSupported) ParameterID

func (cmd *PartSupported) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*PartSupported) SetRawValue

func (part *PartSupported) SetRawValue(val uint32)

SetRawValue sets the raw value directly without any validation or parsing.

func (*PartSupported) SetValue

func (part *PartSupported) SetValue(result *Result) error

SetValue processes the byte array value into the right unsigned integer value.

func (*PartSupported) SupportsCommand

func (part *PartSupported) SupportsCommand(cmd OBDCommand) bool

SupportsCommand checks if the given command is supported in the current part.

Note: returns false if the given PID is not handled in the current part

func (*PartSupported) SupportsNextPart

func (part *PartSupported) SupportsNextPart() bool

SupportsNextPart checks if the PID that is used to check the next part is supported. This PID is always the last PID of the current part, which means we can simply check if the D0 bit is set.

func (*PartSupported) SupportsPID

func (part *PartSupported) SupportsPID(comparePID OBDParameterID) bool

SupportsPID checks if the given command is supported in the current part.

To figure out if a PID is supported we need to understand what the Value of a PartSupported represents.

It represents the supported/not supported state of 32 PIDs.

It does this by encoding this information as 32 bits, where each bit represents the state of a PID:

- When the bit is set, it represents the PID being supported - When the bit is unset, it represents the PID being unsupported

To make it easier to map PID values to actual bits, Bit-Encoded-Notation is used, where each bit has a name. Each name as a letter representing the byte and a number representing the bit in the byte.

Here's how Bit-Encoded-Notation maps against the bits:

A7 A0 B7 B0 C7 C0 D7 D0 | | | | | | | | v v v v v v v v 00000000 00000000 00000000 00000000

The state of the first PID is kept at bit A7, the second PID at A6, all the way until we get to PID 0x20 (32) which is kept in bit D0.

In order to check if a bit is active, we can either:

  • Shift the bits of the value to the right until the bit we want to check has the position D0 and then use a AND bitwise conditional with the mask 0x1
  • Shift the bits of the mask 0x1 to the left until it has the same position as the bit we want to check and then use a AND bitwise conditional with value

This function uses the first method of checking if the bit is active.

In order to figure out which bit position has, we take the position of the first PID, which is 32 and subtract the PID number to get the bit position. This means that 32 - PID 1 = 31 (A7) and 32 - PID 32 = 0 (D0).

Now we know how to figure out what bit holds the information and how to read the information from the bit.

This works well for checking if part 1 supported PIDs between 0x1 and 0x20, but it fails for parts 2,3,4,5,6,7 and PIDs about 0x20.

In order to make this work for other parts besides 1, we simply normalize the PID number by removing 32 times the part index, instead of hard coding the value to subtract to 32.

func (*PartSupported) ToCommand

func (cmd *PartSupported) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type RawDevice

type RawDevice interface {
	RunCommand(string) RawResult
}

RawDevice represent the low level device, which can either be the real implementation or a mock implementation used for testing.

type RawResult

type RawResult interface {
	Failed() bool
	GetError() error
	GetOutputs() []string
	FormatOverview() string
}

RawResult represents the raw text output of running a raw command, including information used in debugging to show what input caused what error, how long the command took, etc.

type RealDevice

type RealDevice struct {
	// contains filtered or unexported fields
}

RealDevice represent the low level serial connection.

func NewNetDevice

func NewNetDevice(u *url.URL) (*RealDevice, error)

func NewSerialDevice

func NewSerialDevice(addr *url.URL) (*RealDevice, error)

NewSerialDevice creates a new low-level ELM327 device manager by connecting to the device at given path.

After a connection has been established the device is reset, and a minimum of 800 ms blocking wait will occur. This makes sure the device does not have any custom settings that could make this library handle the device incorrectly.

func (*RealDevice) Reset

func (dev *RealDevice) Reset() error

Reset restarts the device, resets all the settings to factory defaults and makes sure it actually is a ELM327 device we are talking to.

In case this doesn't work, you should turn off/on the device.

func (*RealDevice) RunCommand

func (dev *RealDevice) RunCommand(command string) RawResult

RunCommand runs the given AT/OBD command by sending it to the device and waiting for the output. There are no restrictions on what commands you can run with this function, so be careful.

WARNING: Do not turn off echoing, because the underlying write function relies on echo being on so that it can compare the input command and the echo from the device.

For more information about AT/OBD commands, see: https://en.wikipedia.org/wiki/Hayes_command_set https://en.wikipedia.org/wiki/OBD-II_PIDs

type RealResult

type RealResult struct {
	// contains filtered or unexported fields
}

RealResult represents the raw text output of running a raw command, including information used in debugging to show what input caused what error, how long the command took, etc.

func (*RealResult) Failed

func (res *RealResult) Failed() bool

Failed checks if the result is successful or not

func (*RealResult) FormatOverview

func (res *RealResult) FormatOverview() string

FormatOverview formats a result as an overview of what command was run and how long it took.

func (*RealResult) GetError

func (res *RealResult) GetError() error

GetError returns the results current error

func (*RealResult) GetOutputs

func (res *RealResult) GetOutputs() []string

GetOutputs returns the outputs of the result

type Result

type Result struct {
	// contains filtered or unexported fields
}

Result represents the results from running a command on the ELM327 device, encoded as a byte array. When you run a command on the ELM327 device the response is a space-separated string of hex bytes, which looks something like this:

41 0C 1A F8

The first 2 bytes are control bytes, while the rest of the bytes represent the actual result. So this data type contains an array of those bytes in binary.

This data type is only used internally to produce the processed value of the run OBDCommand, so the end user will never use this data type.

func NewResult

func NewResult(rawLine string) (*Result, error)

NewResult constructors a Result by taking care of parsing the hex bytes into binary representation.

func (*Result) PayloadAsByte

func (res *Result) PayloadAsByte() (byte, error)

PayloadAsByte is a helper for getting payload as byte.

func (*Result) PayloadAsUInt16

func (res *Result) PayloadAsUInt16() (uint16, error)

PayloadAsUInt16 is a helper for getting payload as uint16.

func (*Result) PayloadAsUInt32

func (res *Result) PayloadAsUInt32() (uint32, error)

PayloadAsUInt32 is a helper for getting payload as uint32.

func (*Result) PayloadAsUInt64

func (res *Result) PayloadAsUInt64() (uint64, error)

PayloadAsUInt64 is a helper for getting payload as uint64.

func (*Result) Validate

func (res *Result) Validate(cmd OBDCommand) error

Validate checks that the result is for the given OBDCommand by: - Comparing the bytes received and the expected amount of bytes to receive - Comparing the received mode ID and the expected mode ID - Comparing the received parameter ID and the expected parameter ID

type ResultLessCommand

type ResultLessCommand struct {
}

ResultLessCommand is a command implementing empty functions for setting values (commands without results)

func (*ResultLessCommand) SetValue

func (cmd *ResultLessCommand) SetValue(result *Result) error

func (*ResultLessCommand) ValueAsLit

func (cmd *ResultLessCommand) ValueAsLit() string

type RuntimeSinceStart

type RuntimeSinceStart struct {
	UIntCommand
	// contains filtered or unexported fields
}

RuntimeSinceStart represents a command that checks the run time since engine start.

Min: 0 Max: 65535

func NewRuntimeSinceStart

func NewRuntimeSinceStart() *RuntimeSinceStart

NewRuntimeSinceStart creates a new RuntimeSinceStart with the right parameters.

func (*RuntimeSinceStart) DataWidth

func (cmd *RuntimeSinceStart) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*RuntimeSinceStart) Key

func (cmd *RuntimeSinceStart) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*RuntimeSinceStart) ModeID

func (cmd *RuntimeSinceStart) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*RuntimeSinceStart) ParameterID

func (cmd *RuntimeSinceStart) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*RuntimeSinceStart) SetValue

func (cmd *RuntimeSinceStart) SetValue(result *Result) error

SetValue processes the byte array value into the right unsigned integer value.

func (*RuntimeSinceStart) ToCommand

func (cmd *RuntimeSinceStart) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type ShortFuelTrim1

type ShortFuelTrim1 struct {
	// contains filtered or unexported fields
}

ShortFuelTrim1 represents a command that checks the short term fuel trim for bank 1.

func NewShortFuelTrim1

func NewShortFuelTrim1() *ShortFuelTrim1

NewShortFuelTrim1 creates a new ShortFuelTrim1 with the right parameters.

func (*ShortFuelTrim1) SetValue

func (cmd *ShortFuelTrim1) SetValue(result *Result) error

SetValue processes the byte array value into the right float value.

type ShortFuelTrim2

type ShortFuelTrim2 struct {
	// contains filtered or unexported fields
}

ShortFuelTrim2 represents a command that checks the short term fuel trim for bank 2.

func NewShortFuelTrim2

func NewShortFuelTrim2() *ShortFuelTrim2

NewShortFuelTrim2 creates a new ShortFuelTrim2 with the right parameters.

func (*ShortFuelTrim2) SetValue

func (cmd *ShortFuelTrim2) SetValue(result *Result) error

SetValue processes the byte array value into the right float value.

type SupportedCommands

type SupportedCommands struct {
	// contains filtered or unexported fields
}

SupportedCommands represents the lookup table for which commands (PID 1 to PID 160) that are supported by the car connected to the ELM327 device.

func NewSupportedCommands

func NewSupportedCommands(partValues []uint32) (*SupportedCommands, error)

NewSupportedCommands creates a new PartSupported.

func (*SupportedCommands) AddPart

func (sc *SupportedCommands) AddPart(part *PartSupported)

AddPart adds the given part to the slice of parts checked.

func (*SupportedCommands) FilterSupported

func (sc *SupportedCommands) FilterSupported(commands []OBDCommand) []OBDCommand

FilterSupported filters out the OBDCommands that are supported.

func (*SupportedCommands) GetPart

func (sc *SupportedCommands) GetPart(index byte) (*PartSupported, error)

GetPart gets the part at the given index.

func (*SupportedCommands) GetPartByPID

func (sc *SupportedCommands) GetPartByPID(pid OBDParameterID) (*PartSupported, error)

GetPartByPID gets the part at the given index.

func (*SupportedCommands) IsSupported

func (sc *SupportedCommands) IsSupported(cmd OBDCommand) bool

IsSupported checks if the given OBDCommand is supported.

It does this by comparing the PID of the OBDCommand against the lookup table.

type ThrottlePosition

type ThrottlePosition struct {
	FloatCommand
	// contains filtered or unexported fields
}

ThrottlePosition represents a command that checks the throttle position in percentage.

Min: 0.0 Max: 100.0

func NewThrottlePosition

func NewThrottlePosition() *ThrottlePosition

NewThrottlePosition creates a new ThrottlePosition with the right parameters.

func (*ThrottlePosition) DataWidth

func (cmd *ThrottlePosition) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*ThrottlePosition) Key

func (cmd *ThrottlePosition) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*ThrottlePosition) ModeID

func (cmd *ThrottlePosition) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*ThrottlePosition) ParameterID

func (cmd *ThrottlePosition) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*ThrottlePosition) SetValue

func (cmd *ThrottlePosition) SetValue(result *Result) error

SetValue processes the byte array value into the right float value.

func (*ThrottlePosition) ToCommand

func (cmd *ThrottlePosition) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type TimingAdvance

type TimingAdvance struct {
	FloatCommand
	// contains filtered or unexported fields
}

TimingAdvance represents a command that checks the timing advance in degrees before TDC.

Min: -64 Max: 63.5

For more info about TDC: https://en.wikipedia.org/wiki/Dead_centre_(engineering)

func NewTimingAdvance

func NewTimingAdvance() *TimingAdvance

NewTimingAdvance creates a new TimingAdvance with the right parameters.

func (*TimingAdvance) DataWidth

func (cmd *TimingAdvance) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*TimingAdvance) Key

func (cmd *TimingAdvance) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*TimingAdvance) ModeID

func (cmd *TimingAdvance) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*TimingAdvance) ParameterID

func (cmd *TimingAdvance) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*TimingAdvance) SetValue

func (cmd *TimingAdvance) SetValue(result *Result) error

SetValue processes the byte array value into the right float value.

func (*TimingAdvance) ToCommand

func (cmd *TimingAdvance) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type TransmissionActualGear

type TransmissionActualGear struct {
	FloatCommand
	// contains filtered or unexported fields
}

TransmissionActualGear represents the gear ratio

Min: 0 Max: 65.535

func NewTransmissionActualGear

func NewTransmissionActualGear() *TransmissionActualGear

NewTransmissionActualGear creates a new transmission actual gear ratio with the correct parameters.

func (*TransmissionActualGear) DataWidth

func (cmd *TransmissionActualGear) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*TransmissionActualGear) Key

func (cmd *TransmissionActualGear) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*TransmissionActualGear) ModeID

func (cmd *TransmissionActualGear) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*TransmissionActualGear) ParameterID

func (cmd *TransmissionActualGear) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*TransmissionActualGear) SetValue

func (cmd *TransmissionActualGear) SetValue(result *Result) error

SetValue processes the byte array value into the right uint value.

func (*TransmissionActualGear) ToCommand

func (cmd *TransmissionActualGear) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

type UIntCommand

type UIntCommand struct {
	Value uint32
}

UIntCommand is just a shortcut for commands that retrieve unsigned integer values from the ELM327 device.

func (*UIntCommand) ValueAsLit

func (cmd *UIntCommand) ValueAsLit() string

ValueAsLit retrieves the value as a literal representation.

type VehicleSpeed

type VehicleSpeed struct {
	UIntCommand
	// contains filtered or unexported fields
}

VehicleSpeed represents a command that checks the vehicle speed in km/h.

Min: 0 Max: 255

func NewVehicleSpeed

func NewVehicleSpeed() *VehicleSpeed

NewVehicleSpeed creates a new VehicleSpeed with the right parameters

func (*VehicleSpeed) DataWidth

func (cmd *VehicleSpeed) DataWidth() byte

DataWidth retrieves the amount of bytes the command expects from the ELM327 devices.

func (*VehicleSpeed) Key

func (cmd *VehicleSpeed) Key() string

Key retrieves the unique literal key of the command, used when exporting commands.

func (*VehicleSpeed) ModeID

func (cmd *VehicleSpeed) ModeID() byte

ModeID retrieves the mode ID of the command.

func (*VehicleSpeed) ParameterID

func (cmd *VehicleSpeed) ParameterID() OBDParameterID

ParameterID retrieves the Parameter ID (also called PID) of the command.

func (*VehicleSpeed) SetValue

func (cmd *VehicleSpeed) SetValue(result *Result) error

SetValue processes the byte array value into the right unsigned integer value.

func (*VehicleSpeed) ToCommand

func (cmd *VehicleSpeed) ToCommand() string

ToCommand retrieves the raw command that can be sent to the ELM327 device.

The command is sent without spaces between the parts, the amount of data lines is added to the end of the command to speed up the communication. See page 33 of the ELM327 data sheet for details on why we do this.

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL