Module: Advanced CAN Gateway

Munic Box is connected to the vehicle bus, so Munic Box does interfere with the vehicle.
By installing Munic Box you acknowledge this risk and Mobile Devices Ingénierie can not be taken responsible for any trouble, harm, liability and injury caused by such connection.

Defer to your vehicle’s warranty provisions and owner’s instructions for guidance on whether any OBD II connector product might void or alter your vehicle’s warranty. Mobile Devices Ingénierie is not responsible for any costs or expenses associated with vehicle repairs or voided warranties.

If you notice any change in engine performance after connecting the device, disconnect the device immediately and contact Munic Box support. Do not use the device if it affects engine performance or acceleration in your particular make and model of vehicle.

Mobile Devices Ingénierie can, on demand, provide recommendation regarding the usage of OBD dongle & APIs.

  • ObdStacks is an advanced technology and suite of tools developped by Mobile Devices to describe, export and execute on-board vehicle specific commands (listen on a bus, send a command, etc.).
  • Basic use case is the following:
    • The user first has to describe on a file the operations that he wants to execute. The current implementation works with a JSON file.
    • The description file is sent to the device over the air.
    • Once the file is loaded, operations can be executed locally on the device.
    • The stacks sent to the device are saved on the flash and then reloaded when the device reboots.
    • To drop a saved/loaded stack, refer to the drop action.
  • This project is currently under active development, this is why you are encouraged to give ideas about future improvements.

Introduction

  • The ObdStacks script is divided in three main parts:
    • EcuDescription: The list of ECUs and the way to communicate with it
    • Command: The full definition of the command that will be sent to the device
    • Action: The operation that will be done with the result of previous commands and actions
  • ECU's, commands and actions are identified by a name (regexp [a-zA-Z][a-zA-Z0-9_]*[a-zA-Z0-9]), It has to :
    • Begin with a letter (lower or upper case)
    • Only contain letters, numbers and '_' (underscore)
    • Not end with '_' (underscore)

This name attribute is used to refer to a particular object in another object's dependencies (for example, a command will depend on an ECU, an action will depend on one or several commands).

Base structure

The base structure of the script is the obdStack object. It has only one attribute, name, which is a string name for the stack.


{
    "obdStack": {
        "name": "myStackName",
        "ecuDescription": [
            {   }
        ],
        "obdCommand": [
            {   }
        ],
        "canFrameCommand": [
            {   }
        ],
        "canCommand": [
            {   }
        ],
        "canFrameReceive": [
            {   }
        ],
        "klineCommand": [
            {   }
        ],
        "j1850Command": [
            {   }
        ],
        "j1939Command": [
            {   }
        ],
        "j1708Command": [
            {   }
        ],
        "j1587Command": [
            {   }
        ],
        "tp2Command": [
            {   }
        ],
        "sleepCommand": [
            {   }
        ],
        "expressionDefinition": [
            {   }
        ],
        "actionList": [
            {   }
        ]
    }
}

ECU Description

The ECUs are described with the following elements:

  • MANDATORY

    • name: The name of the ECU, will be used by commands to specify an ECU if needed.
    • type: the type of connection for the ECU. Possibilities are "can, "GMLAN", "kline". For retrocompatibility, if not present, type will be "can".
  • CAN related options

    • Connection

      • canConnection: Allows to specify the bus to use. Default is ALL: use any connected bus (contact us for details about pin switching capabilities).
      • canBaudRate: Default is 500000. specify the speed of the bus if you want to restrict it. Common values are 250000 or 500000.
      • Note: when you want to specify the connection or the baudrate used you need to specify both these options for them to take effect.
      • defaultReplyTimeOutMS: The default value is 100 (ms). The timeout before hanging up if no answer received. It is a long int in milliseconds. It can varies between 50 and 10000 ms.
    • Addressing

      • srcId (Mandatory if type is "can" or "GMLAN"): the source Id. Is an hexadecimal string, length MUST be 3 or 8.
      • dstId (Mandatory if type is "can"): the destination Id. Is an hexadecimal string, length MUST be 3 or 8.
      • dstIds (Can replace dstId): is an array of dstId. Is an hexadecimal string array, length of each element MUST be 3 or 8.
      • addressType: Default value is PHYSICAL. A string that can be one of these strings : FUNCTIONAL (receive all messages) or PHYSICAL (receive one message only).
      • canAddressingMode: Default is NORMAL. To be set to EXTENDED when using extended addressing on CAN 11 bits (this is not related to CAN 29 bits addressing).
      • canExtendedAddress: Default is 0. It is an integer used as a byte whenever canAddressingMode is EXTENDED.
      • canExtendedAddressMask: Default is not used. It is an integer used as a extended address mask on answers (0x00 means everything, 0xFF limits to address). (depends on canExtendedAddress).
      • canExtendedAddressFilter: Default is not used. It is an integer used as a extended address filter on answers. (depends on canExtendedAddress).
      • canIdType: specifies if can is 11 or 29 bits, default value is 11BITS, other value is 29BITS.
      • canMask: Default value is 0x7FF if 11 bit can or 0x1FFFFFFF if 29 bits can. Mask as an hexadecimal string used for CAN raw commands when connected to CAN.
      • canPaddingValue: The value to pad the data with (hexadecimal format: "FF"). Default is "00". To specify no padding, put "-1".
      • blocksize: The blocksize _u8 value for non standard IsoTp. If not set, set to 0.
      • separTime: The separe time _u8 value for non standard IsoTp. x00-0x7F : 0-127 ms, 0x80-0xF0 : reserved, 0xF1-0xF9 : 100us-900 us, 0xFA-0xFF : reserved. If not set, set to 0.
  • GMLAN related options

    • USDT (Mandatory, replaces dstId): the address for the USDT response. Is an hexadecimal string, length MUST be 3 or 8.
    • UUDT (Mandatory, replaces dstId): the address for the UUDT response. Is an hexadecimal string, length MUST be 3 or 8.
    • uudtTimeOutMS: specific timeout value to use for the UUDT answer (the USDT timeout is still defined by defaultReplyTimeOutMS).
  • KLine related options

    • Addressing
      • sourceAddress: the source address, in string format, with the prefix "0x" (Default is 0xF1).
      • targetAddress: the target address of the ECU, in string format, with the prefix "0x" (Default is 0x33).
      • forceLengthByte: (most of time false) Boolean. If true, the lenght byte of the frame format will be found in every frames, even if not relevant.
      • addressType: Can be either "FUNCTIONAL" (by default) or "PHYSICAL".

NOTE: not specifying canExtendedAddressMask and canExtendedAddressFilter but activating canExtendedAddress implies to use the default filtering on the address data field (for example 123#F140 as question will get 123#F140 as a valid answer, but
140#F123 will be filtered out).


{
    "ecuDescription": [
        {
            "name": "simple_ecu",
            "srcId": "7E0",
            "dstId": "7E8"
        },
        {
            "name": "engine_ecu",
            "srcId": "18DAF111",
            "dstId": "18DB33F1",
            "defaultReplyTimeOutMS": 1000,
            "canPaddingValue": "0D",
            "canConnection": "CAN-OBD",
            "canBaudRate": 500000,
            "canIdType": "29BITS"
        },
        {
            "name": "shield_ecu",
            "srcId": "7E0",
            "dstIds": ["023", "7E8", "03F"],
            "addressType": "PHYSICAL",
            "defaultReplyTimeOutMS": 100,
            "canAddressingMode": "EXTENDED",
            "canExtendedAddress": 96,
            "canExtendedAddressMask": 255,
            "canExtendedAddressFilter": 241,
            "canBaudRate": 500000,
            "canIdType": "11BITS",
            "canPaddingValue": "00"
        },
        {
            "name": "simple_kline_ecu",
            "type": "kline",
            "sourceAddress": "0xF1",
            "targetAddress": "0x33",
            "forceLengthByte": false,
            "addressType": "FUNCTIONAL"
        },
    ]
}

Commands

Currently supported commands are:

  • JSON
    • {"obdCommand":[ is an array of standard OBD commands
    • {"canFrameCommand":[ is an array of single frame CAN commands
    • {"canCommand":[ is an array of multi-frame CAN commands
    • {"tp2Command":[ is an array of CAN TP2 commands
    • {"gmlanCommand":[ is an array of GMLAN commands
    • {"klineCommand":[ is an array of KLine commands
    • {"j1850Command":[ is an array of J1850 commands
    • {"j1939Command":[ is an array of J1939 commands
    • {"j1708Command":[ is an array of J1708 commands
    • {"j1587Command":[ is an array of J1587 commands
    • {"sleepCommand":[ is an array of "sleep" commands. Can be used to add a waiting time between commands.
    • {"canFrameReceive":[ listen-only mode for CAN
    • {"canPolling":[ high-frequency polling for CAN

Each command returns a sequence of bytes: byte[], on which operations can be executed thanks to actions.

Standard OBD command

  • Fields description

    • name: the name of the command, will be later used by actions.
    • mode: the mode of the OBD command. is an hexa string.
    • pid: the pid of the OBD command, is an hexadecimal string. It is uneeded for DTC modes (3,4,7 and 0A) but indispensable for other modes.
    • forbiddenRawFilters: (optional) A JSON Array of raw answers that must be filtered. All the elements of the Array must be JSON Object with the following fields:

      • mask: mask on which to apply the filters. It is an array of integer values. Goes up to 8 bytes. Can be decimal or hexadecimal (in the form "0xff").
      • filters: array of arrays of integer values (same format as mask). Used to filter answers that you want to drop. If a raw data answer matches on the mask/filter combination, the answer will not be treated.

{
    "obdCommand": [
        {
            "name": "OBD_010D",
            "mode": "01",
            "pid": "0D"
        },
        {
            "name": "OBD_010C",
            "mode": "01",
            "pid": "0C",
            "forbiddenRawFilters": [
                {
                  "mask": [0, 255],
                  "filters": [[0, 128]]
                }
            ]
        }
    ]
}

Single frame can command

Used to send raw CAN frames.

  • Fields description

    • name: the name of the command, will be later used by actions.
    • ecu: the identifier of the ECU to contact. Can either be on 3 bytes or 8 bytes. It is an hexadecimal string.
    • data: the data to send, as a raw frame. It is an array of integers values. Goes up to 8 bytes. Can be decimal or hexadecimal (in the form 0xf).
    • forbiddenRawFilters: (optional) A JSON Array of raw answers that must be filtered. All the elements of the Array must be JSON Object with the following fields:

      • mask: mask on which to apply the filters. It is an array of integer values. Goes up to 8 bytes. Can be decimal or hexadecimal (in the form "0xff").
      • filters: array of arrays of integer values (same format as mask). Used to filter answers that you want to drop. If a raw data answer matches on the mask/filter combination, the answer will not be treated.

{
    "canFrameCommand": [
        {
            "name": "iso-obd-010d",
            "ecu": "engine_ecu",
            "data": [ 2, 1, 13 ]
        }
    ]
}

Multi frame can command - ISO 15765-2 (ISO-TP)

Used to send CAN frames via Iso-TP protocol.

  • Fields description

    • name: the name of the command, will be later used by actions.
    • ecu: the name of the ecu that is described in ecu description.
    • data: the data to send, as the CAN payload (without the length byte). It is an array of integer values. Goes up to 7 bytes. Can be decimal or hexadecimal (in the form "0xf").
    • forbiddenRawFilters: (optional) A JSON Array of raw answers that must be filtered. All the elements of the Array must be JSON Object with the following fields:

      • mask: mask on which to apply the filters. It is an array of integer values. Goes up to 8 bytes. Can be decimal or hexadecimal (in the form "0xff").
      • filters: array of arrays of integer values (same format as mask). Used to filter answers that you want to drop. If a raw data answer matches on the mask/filter combination, the answer will not be treated.

{
    "canCommand": [
        {
            "name": "command_rpm",
            "ecu": "engine_ecu",
            "data": [ 1, 12 ]
        },
        {
            "name": "command_vin",
            "ecu": "engine_ecu",
            "data": [ "0x09", "0x02" ]
        }
    ]
}

CAN TP2 command

  • Fields description

    • name: the name of the command, will be later used by actions.
    • ecu: the name of the ecu that is described in ecu description.
    • data: as the CAN payload (without the length byte). It is an array of integer values. Goes up to 7 bytes. Can be decimal or hexadecimal (in the form "0xf").
    • forbiddenRawFilters: (optional) A JSON Array of raw answers that must be filtered. All the elements of the Array must be JSON Object with the following fields:

      • mask: mask on which to apply the filters. It is an array of integer values. Goes up to 8 bytes. Can be decimal or hexadecimal (in the form "0xff").
      • filters: array of arrays of integer values (same format as mask). Used to filter answers that you want to drop. If a raw data answer matches on the mask/filter combination, the answer will not be treated.

{
    "tp2Command": [
        {
            "name": "command_vin",
            "ecu": "engine_ecu",
            "data": [ 9, 2 ]
        }
    ]
}

GMLAN command

Used to send CAN frames via GMLAN protocol.

  • Fields description

    • name: the name of the command, will be later used by actions.
    • ecu: the name of the ecu that is described in ecu description. ECU must be of type "GMLAN".
    • data: the data to send, as the CAN payload (without the length byte). It is an array of integer values. Goes up to 7 bytes. Can be decimal or hexadecimal (in the form "0xf").
    • forbiddenRawFilters: (optional) A JSON Array of raw answers that must be filtered. All the elements of the Array must be JSON Object
      with the following fields:

      • mask: mask on which to apply the filters. It is an array of integer values. Goes up to 8 bytes. Can be decimal or hexadecimal (in the form "0xff").
      • filters: array of arrays of integer values (same format as mask). Used to filter answers that you want to drop. If a raw data answer matches on the mask/filter combination, the answer will not be treated.

{
    "gmlanCommand": [
        {
            "name": "command_gmlan",
            "ecu": "ecu_gmlan",
            "data": [ 1, 12 ]
        }
    ]
}

KLine command

  • Fields description

    • name: Mandatory. The name of the command, will be later used by actions.
    • ecu : Optional if you use standard KLine. The name of the ECU associated with the command, if any. Ignored if raw is set to true.
    • defaultReplyTimeOutMS: Optional, default value is 100 (ms). The timeout before hanging up if no answer received. It is a long int in milliseconds. It can vary between 50 and 10000 ms.
    • raw: Optional, default to false. Indicates if the data array must be interpreted as raw. See raw interpretation differences for each following parameter.
    • data: Mandatory. Data to send as a bytes array. Bytes must be represented with decimal integers or with hexadecimal strings like "0xF". If raw parameter is not set or set to false, the array represents the message's payload, and the maximum array size is of 256 bytes. Else, if raw parameter is set to true, the array represents the whole frame, and the maximum array size is of 261 bytes.
    • headerBytes: Optional, default is 0. Used in case of multi-frame messages. Number of heading bytes to chop from each frame. If raw is set to false the KLine headers are not took into account, choping starting from the first KLine payload byte. Else, if raw is set to true KLine headers are took into account, chopping starting from the first frame byte.
    • checksumBytes: Optional, default is 0. Number of checksum bytes to chop from each frame. Ignored if raw is set to false.
    • ecuByteIndex: Optional, default to -1, which means not used. This value represents the index of the ECU identifier byte. Used to process received responses from only one ECU. Ignored if raw is set to false.
    • sequenceByteIndex: Optional, default to -1, which means not used. This value represents the index of a sequence byte in the KLine message, to check for good sequence in case of multiframe messages. If raw is set to false the index starts from the first KLine payload byte. Else, if raw is set to true the index starts from the first frame byte.
    • checksum: Optional, default is -1, which means not used. If used, the value represents an integer in the range [0,255]. If not used, the value is automatically computed by lower-level layers. Used to force own checksum in the sent KLine command. Ignored if raw is set to true.
    • forbiddenRawFilters: (optional) A JSON Array of raw answers that must be filtered. All the elements of the Array must be JSON Object with the following fields:

      • mask: mask on which to apply the filters. It is an array of integer values. Goes up to 8 bytes. Can be decimal or hexadecimal (in the form "0xff").
      • filters: array of arrays of integer values (same format as mask). Used to filter answers that you want to drop. If a raw data answer matches on the mask/filter combination, the answer will not be treated.

{
    "klineCommand": [
        {
            "name": "command_rpm",
            "data": [ 1, 12 ],
            "checksum": 201
        },
        {
            "name": "command_vin",
            "data": [ 9, 2 ],
            "defaultReplyTimeOutMS": 100,
            "headerBytes": 3,
            "sequenceByteIndex": 2
        },
        {
            "name": "command_rpm_non_standard",
            "ecu": "kline_engine_ecu",
            "data": [ 1, 12 ]
        },
        {
            "name": "command_rpm_raw",
            "raw": true,
            "data": ["0xC2", "0x33", "0xF1", "0x01", "0x0C", "0xF3"],
            "ecuByteIndex": 2,
            "checksumBytes": 1,
            "defaultReplyTimeOutMS": 200
        },
        {
            "name": "command_vin_raw",
            "raw": true,
            "data": ["0xC2", "0x33", "0xF1", "0x09", "0x02", "0xF1"],
            "headerBytes": 6,
            "checksumBytes": 1,
            "sequenceByteIndex": 5,
            "defaultReplyTimeOutMS": 200
        }
    ]
}

J1850 command

  • Fields description

    • name: the name of the command, will be later used by actions.
    • defaultReplyTimeOutMS: The default value is 100 (ms). The timeout before hanging up if no answer received. It is a long int in milliseconds. It can vary between 50 and 10000 ms.
    • data: the data to send. It is an array of integer values. Goes up to 8 bytes. Can be decimal or hexadecimal (in the form "0xf").
    • headerBytes: number of header bytes in the payload of the J1850 message (not counting the J1850 headers themselves). Used in case of multiframe messages.
    • sequenceByteIndex: index of a sequence byte in the payload of the J1850 message, to check for good sequence in case of multiframe messages.
    • forbiddenRawFilters: (optional) A JSON Array of raw answers that must be filtered. All the elements of the Array must be JSON Object with the following fields:

      • mask: mask on which to apply the filters. It is an array of integer values. Goes up to 8 bytes. Can be decimal or hexadecimal (in the form "0xff").
      • filters: array of arrays of integer values (same format as mask). Used to filter answers that you want to drop. If a raw data answer matches on the mask/filter combination, the answer will not be treated.

{
    "j1850Command": [
        {
            "name": "command_rpm",
            "data": [ 1, 12 ]
        },
        {
            "name": "command_vin",
            "data": [ 9, 2 ],
            "defaultReplyTimeOutMS": 100,
            "headerBytes": 3,
            "sequenceByteIndex": 2
        }
    ]
}

J1939 command

  • Fields description

    • name: the name of the command, will be later used by actions.
    • pgnNumber: the number of the requested PGN.
    • spnMask: mask corresponding to the requested SPN.
    • srcAddress: this parameter is optional. If set to a positif integer, srcAddress of the ECu that answered will be checked before treating the answer.
    • mode: broadcast or request.
    • interface: the name of the interface. Default: can0.
    • forbiddenRawFilters: (optional) A JSON Array of raw answers that must be filtered. All the elements of the Array must be JSON Object with the following fields:

      • mask: mask on which to apply the filters. It is an array of integer values. Goes up to 8 bytes. Can be decimal or hexadecimal (in the form "0xff").
      • filters: array of arrays of integer values (same format as mask). Used to filter answers that you want to drop. If a raw data answer matches on the mask/filter combination, the answer will not be treated.

{
    "j1939Command": [
        {
            "name": "SPN_190",
            "pgnNumber": "61444",
            "spnMask": "FFFF000000",
            "srcAddress": 0,
            "mode": "broadcast",
            "interface": "can0"
        },
        {
            "name": "PGN_65244",
            "pgnNumber": "65244",
            "spnMask": "",
            "mode": "request",
            "interface": "can0"
        }
    ]
}

J1708 command

  • Fields description

    • name: the name of the command, will be later used by actions.
    • mid: the MID of the command.
    • data: the data to send after the MID.
    • forbiddenRawFilters: (optional) A JSON Array of raw answers that must be filtered. All the elements of the Array must be JSON Object with the following fields:

      • mask: mask on which to apply the filters. It is an array of integer values. Goes up to 8 bytes. Can be decimal or hexadecimal (in the form "0xff").
      • filters: array of arrays of integer values (same format as mask). Used to filter answers that you want to drop. If a raw data answer matches on the mask/filter combination, the answer will not be treated.

{
    "j1708Command": [
        {
            "name": "MID_45",
            "mid": "45",
            "data": [ 9, 2 ]
        }
    ]
}

J1587 command

  • Fields description

    • name: the name of the command, will be later used by actions.
    • pid: the PID of the command.
    • mid: this parameter is optional. If set to a positive value, the mid of the answer will be checked before treating the command.
    • mode: broadcast or request.
    • forbiddenRawFilters: (optional) A JSON Array of raw answers that must be filtered. All the elements of the Array must be JSON Object with the following fields:

      • mask: mask on which to apply the filters. It is an array of integer values. Goes up to 8 bytes. Can be decimal or hexadecimal (in the form "0xff").
      • filters: array of arrays of integer values (same format as mask). Used to filter answers that you want to drop. If a raw data answer matches on the mask/filter combination, the answer will not be treated.

{
    "j1587Command": [
        {
            "name": "PID_45",
            "pid": "45",
            "mode": "broadcast"
        },
        {
            "name": "PID_45",
            "pid": "45",
            "mid": 128,
            "mode": "broadcast"
        }
    ]
}

Sleep command

Note: the sleep commmand does not send any data to the device.

  • Fields description
    • name: the name of the command, will be later used by actions.
    • sleepTimeMs: time to wait in the sleep.

{
    "sleepCommand": [
        {
            "name": "Sleep500Ms",
            "sleepTimeMs": 500
        }
    ]
}

Parameterized commands

Any command that uses the "data" array field can be used as a parameterized command. A parameterized command is a command that depends on the result of another command.

Notes:

  • The parameterized part of the command uses the same syntax as the result formulas (exp4j, see [[ObdStacks#Actions|Actions]] and the return field).
  • Dependencies of parameterized commands MUST be present in the same action, BEFORE the parameterized command (see action described in the example).
  • The parameterized part of the command can be multibyte (see parameterized_command in the example).
  • Warning: if the parameterized part of the command is multibyte, you cannot be sure of the number of bytes that will be sent after the computation. See difference between parameterized_command and parameterized_command_2: the latter will always send three bytes, the former will send only two bytes if RPM is < 256.

Example code:


{
    "canCommand": [
        {
            "name": "command_rpm",
            "ecu": "engine_ecu",
            "data": [ 1, 12 ]
        },
        {
            "name": "parameterized_command",
            "ecu": "engine_ecu",
            "data": [
                1,
                "command_rpm[2]*256+command_rpm[3]"
            ]
        },
        {
            "name": "parameterized_command_2",
            "ecu": "engine_ecu",
            "data": [
                1,
                "command_rpm[2]",
                "command_rpm[3]"
            ]
        }
    ],
    "actionList": [
        {
            "name": "my_action",
            "depends": [
                "command_rpm",
                "parameterized_command",
                "parameterized_command_2"
            ],
            "return": "0"
        }
    ]
}

Parameterized commands with a command of variable length result

Any command that uses the "data" array field can be used as a parameterized command with a command of variable length result. A parameterized command with a command of variable length result is a command that depends on the result with variable length of another command.

Notes:

  • The parameterized part of the command uses the same syntax as the result formulas (exp4j, see [[ObdStacks#Actions|Actions]] and the return field).
  • Dependencies of parameterized commands MUST follow the indication of the field "loop" of the action in the actionsList (see chapter [[ObdStacks#Actions|Actions]], Fields description).
  • The parameterized part of the command can be multibyte (see parameterized_command in the example).

Example code:


{
    "canCommand": [
        {
            "name": "ReportDTCByStatusMask",
            "ecu": "engine_ecu",
            "data": [
                "0x19",
                "0x02",
                "0xFF"
            ]
        },
        {
            "name": "ReportDTCSnapShot",
            "ecu": "engine_ecu",
            "data": [
                "0x19",
                "0x04",
                "ReportDTCByStatusMask_Pattern[0]",
                "ReportDTCByStatusMask_Pattern[1]",
                "ReportDTCByStatusMask_Pattern[2]",
                "0xff"
            ]
        },
        {
            "name": "ReportDTCExtData",
            "ecu": "engine_ecu",
            "data": [
                "0x19",
                "0x06",
                "ReportDTCByStatusMask_Pattern[0]",
                "ReportDTCByStatusMask_Pattern[1]",
                "ReportDTCByStatusMask_Pattern[2]",
                "0xff"
            ]
        }
    ],
    "actionList": [
        {
            "name": "doReportDTCDataForAll",
            "depends": [
                "ReportDTCByStatusMask"
            ],
            "loop": {
                "depends": [
                    "ReportDTCExtData",
                    "ReportDTCSnapShot"
                ],
                "target": "ReportDTCByStatusMask",
                "patternLength": 4,
                "startOffset": 3
            },
            "report": "all",
            "return": 0
        }
    ]
}

CAN listen mode

It is not a real command, but is used to register to ECUs in broadcast mode. Must be used with listen-mode actions.

Fields description

  • name: the name of the command, will be later used by actions.
  • ecu: the name of the ecu to listen to.
  • mask: (optional) mask on which to apply the filters. It is an array of integer values. Goes up to 8 bytes. Can be decimal or hexadecimal (in the form "0xff").
  • filter: (optional) array of arrays of integer values (same format as mask). Used to filter frames that you want to listen from the ECU. See explanation below.
  • throttlePeriodMs: (optional) throttle the received message rate to this period (in ms).

    • forbiddenRawFilters: (optional) A JSON Array of raw answers that must be filtered. All the elements of the Array must be JSON Object with the following fields:

      • mask: mask on which to apply the filters. It is an array of integer values. Goes up to 8 bytes. Can be decimal or hexadecimal (in the form "0xff").
      • filters: array of arrays of integer values (same format as mask). Used to filter answers that you want to drop. If a raw data answer matches on the mask/filter combination, the answer will not be treated.

mask and filter usage

Let us begin by an example. You want to listen to the RPM frames from the engine ECU. You can write:


{
    "canFrameReceive": [
        {
            "name": "listen_rpm",
            "ecu": "engine_ecu",
            "mask": ["0x00", "0xFF", "0xFF"],
            "filter": [
              ["0x00", "0x41", "0x0C", "0xFF", "0xFF"]
            ],
            "throttlePeriodMs": 1000
        }
    ]
}

The mask is set to the second and third bytes of the payload. The filter is "41 0C" on these two bytes: it is the static part of the frame, common to all RPM frames. Then, the "0xFF" on bytes 4 and 5 of the filter are the bits to watch for new data. If two consecutive frames sent by the ECU are identical regarding these two bytes (= if the RPM is the same), the second frame will not be treated.

Now if we also want to watch the speed, we need to update the filter to :


{
            "filter": [
              ["0x00", "0x41", "0x0C", "0xFF", "0xFF"],
              ["0x00", "0x41", "0x0D", "0xFF"]
            ]
}

(OBD Speed is on only 1 byte, RPM is on two bytes).

If you want to get all frames from an ECU, you don't need to specify the mask and filter:


{
    "canFrameReceive": [
        {
            "name": "listen",
            "ecu": "engine_ecu"
        }
    ]
}

Note: in this scenario, only the dstId of the ECU is used, not the srcId.

CAN Polling

As CanFrameReceive, CanPolling commands are only listening to the CAN bus. They are more suited for data that change all the time (wheel speed etc.), whereas CanFrameReceive are more suited to listen to event-based data (ignition, door or lamp status, etc.).
They must be used with listen mode actions.

Fields description

  • name: the name of the command, will be later used by actions.
  • ecu: the name of the ecu to listen to.
  • mask: (optional) mask on which to apply the filters. It is an array of integer values. Goes up to 8 bytes. Can be decimal or hexadecimal (in the form "0xff").
  • filter: (optional) array of arrays of integer values (same format as mask). Used to filter frames that you want to listen from the ECU. See explanation below.
  • throttlePeriodMs: (optional) throttle the received message rate to this period (in ms).

    • forbiddenRawFilters: (optional) A JSON Array of raw answers that must be filtered. All the elements of the Array must be JSON Object with the following fields:

      • mask: mask on which to apply the filters. It is an array of integer values. Goes up to 8 bytes. Can be decimal or hexadecimal (in the form "0xff").
      • filters: array of arrays of integer values (same format as mask). Used to filter answers that you want to drop. If a raw data answer matches on the mask/filter combination, the answer will not be treated.

mask and filter usage: see CanFrameReceive.


{
      "canPolling": [
        {
          "name": "rec_123",
          "ecu": "ecu_123",
          "throttlePeriodMs": 100
        }
}

Note: in this scenario, only the dstId of the ECU is used, not the srcId.

Expressions Definitions

For internal use only.
Expressions are small Java classes that implement a specific interface understood by the ObdStacks code on the device, and can be loaded to perform advanced calculations on frames.

  • Mandatory fields
    • name: the full class name.
    • data: the class data (base64-encoded dex file).

{
  "expressionDefinition": [
    {
      "name": "com.example.MyClass",
      "data": "..."
    }
  ]
}

Actions

Actions allow to to do some calculation on the result of commands and other actions, and were designed using the model of ant targets.
There are two types of actions, distinguished by the mode parameter: either request (default) or listen. request actions depend on commands with data bytes to actually send, whereas listen actions depend on passive commands (like canFrameReceive). Both types of actions have specific parameters.

Fields description

  • MANDATORY fields
    • name: The name of the action.
    • return: It is a double. The return field contains an arithmetical expression that will be used to compute the action's result. It is based on the exp4j library.
      • Expressions allow basic calculation on double values (+, -, *, /) as well as more advanced operations (abs, sin, cos, ...). For the complete list of available operations, please refer to: http://www.objecthunter.net/exp4j/index.html and to the Return and formula fields paragraph below.
      • You are allowed to put in this expression the command or action names that were declared in your dependencies. If they were not declared, your description file won't even compile when sent to the device.
      • For commands, the index of considered byte of the response is just appended to its name in square brackets, e.g.: OBD_010D[0], or ((OBD_0110[0] * 256) + OBD_0110[1]) / 100.
      • You can also refer to any DB variable, with the syntax: DB_<DB_NAME> (for example, DB_MDI_OBD_RPM). It will use the current value of the DB at the time the result is computed.
    • returnExpression: can be used in place of return field. See below section Custom Expressions.
    • Dependencies: describe all the actions/commands that have to be executed before the action is taken. It can be expressed by either of the followings fields :
      • initSession, communication, closeSession: this structure allows you to define 3 lists of actions/commands. If it fails the initSession will be executed again up to initAttempts times, and each retry will be delayed by initDelay. The communication session is the core of the action, it is the main work to execute. If one of the dependencies execution fails, then the session is interrupted. The closeSession should always be executed, without regard to the communication execution success. . They are of the form:
        • "communication":["speedKmPerHour"]: The command/action called speedKmPerHour will be executed when this action is called.
        • To prevent any misspelling or unmet dependency, you have to make sure that all dependencies have been declared before the line they are called.
        • Finally, note that dependencies will be executed following the order of their declarations.
      • OR
      • depends: It has the same form as the previously mentioned fields. We recommend the use of the other structure over this one, as it is more modular.
    • initAttempts: Maximum number of retries for the init session. Default value is 1. Use only if there's
    • initDelay: Delay in ms between two successive attempts of initSession execution. Default value is 500ms.
  • OPTIONAL fields common to all types of actions
    • exportToDB: DB field where the result of the action will be saved to each time it is executed. It allows easy reporting in tracking or easy use in user application. You can also specify the type of the result you want to store in the DB by appending ":X", with X being one of the following: D: double (default), I: int, X: hexadecimal value (example: "MY_DB:I").
    • record: tracking field to record the result of the action (without going through DB). Useful to send the result when there is no need to store it.
    • returnType: the return type of the action. Possible values: string or double. Defaults to double.
    • exports: array of other formula/db pairs to export more than one result of an action, if needed.
      • formula: the corresponding formula. Same syntax as the "return" field.
      • expression: the corresponding expression (can be used instead of formula). Same syntax as returnExpression.
      • db: the name of the db field to export to (with the optional type, same syntax as exportToDB.
      • record: tracking field to record the result of the formula (without going through DB). Useful to send the result when there is no need to store it.
    • mode: either request (default) or listen. Listen mode must be specified when using canFrameReceive or canPolling as a dependency.
    • accumulator: An accumulator aims to support cyclic counters, that are counters on a fixed number of bits that overflow periodically. Instead of returning the counter value, it will return a value accumulated (incremented) over time. Expression defined in the return / returnExpression must be the payload data. No conversion should be included in it. Use setpMultiplier instead.
      • counterMaxValue (mandatory): unsigned integer value, mandatory as soon as an accumulator object is defined. Used to define the interval of the accumulator values: [0; $counterMaxValue]. The max value specified is included in the range. These values are raw, they do not include the stepMultiplier (see next line) factor.
      • stepMultiplier (optional): floating value, defaults to 1.0. Factor applied to the accumulator value. Use case example: for an accumulator representing the fuel consumption, let's say that one accumulator's step (one unit) represents 0.25 µL of fuel, apply a stepMultiplier of 0.25 to retrieve directly the fuel consumption instead of the raw accumulator value.
  • OPTIONAL fields specific to "request" mode
    • EXECUTION
      • periodSec: It is an integer. When declaring an action, the user will be able to schedule its execution at a specific period. If set to 0 (default value), disables it ; otherwise, it repeat the action every periodSec seconds. Please, don't mixed up with an execution command of the same action, as this will degrade performances. A first execution is already done when loading the stack. Don't use too short periods if reporting to the CC is enabled since this will lead to data drops.
      • connectionState: Integer, execute the action only in a specific connection state. 1: only if we are connected to OBD, 0: only if we are not, -1 (default): always.
      • ignitionState: Integer, execute the action only in a specific ignition state. 1: only when ignition is on, 0: only when ignition is off, -1 (default): always.
      • movementState: Integer, execute the action only if the vehicle has moved (the vehicle is consider to have moved if the speed is bigger than a certain paramterable threshold, 5km/h by default). 1: only when vehicle has moved, 0: only when vehicle do not moved (ie speed is 0km/h), -1 (default): always.
      • passiveState: Integer, execute the action only in a specific passive mode state. 1: only if the passive mode is on, 0: only if the passive mode is off, -1 (default) always. Be aware : when setting the passiveState to 1, the action will be executed in listen-only. Make sure that the desired value is broadcasted on the bus.
      • maxErrors: Integer, stop executing the (periodic) action after this number of failures (and until the next reboot). If you use this parameter it is highly recommended to use connectionState, ignitionState or passiveState in conjunction with it, so that the action is executed only when it has a chance to succeed. Note: maxErrors applies only on the failure of the return formula computation, not on the additional db / formula pairs in the exports parameter.
    • REPORTING
      • report:
        • yes: The result of this action will be sent to server each time it is executed.
        • all: The result of this action along with its dependencies will be sent to server each time it is executed. if a loop field is present, all the commands of the loop will be reported too with the following nomenclature in the example described in the loop field: CommandB_DTC1, CommandB_DTC2, ..., CommandB_DTCn with DTCx representing by their bytes in hexa. For example if DTC1 is 0x0A 0x9B 0x17 with status 0x24 (ie the response of CommandA is "0x59 0x02 0x7F DTC1 (="0x0A 0x9B 0x17 0x24") DTC2 ... DTCn" there will be, in the report, a CommandB_0A9B1724.
        • if not present, the periodic action is not reported to the server.
      • serverParameters: A string that will be given back along the results.
    • PARAMETERIZED ACTIONS
      • loop: It is a JSON object. This field is used to proceed one or more parameterized commands which have a parameter that depends on a variable length response of a command. For example you may want to do the following procedure. Send a command commandA to ask the DTCs available for an ECU. Take the response and extract the different DTCs available. For each DTC send a command commandB (which will obviously be parameterized with the bytes representing the DTC). This procedure is possible with the loop option with the following mandatory fields:
        • depends: JSON array with all the commands you want to execute with the "pattern" response of the target command. In the example previously described, depends would be "commandB", target "commandA" and the pattern the DTC. Also, for all the commands of this field, if you want to use bytes of the pattern, you must use this nomenclature: "CommandA_Pattern". In the example previously described, the DTCs are representing with 4 bytes in the response of the commandA: 3 bytes for the DTC identifier and 1 byte of status. So, in commandB, you will find "CommandA_Pattern[0]", "CommandA_Pattern[1]" and "CommandA_Pattern[2]" to send the command for the right DTC for each loop step.
        • target: the name of THE command from which you want to extract the information to import in the depends field of the loop. In the example previously described target would be commandA.
        • patternLength: the length of the pattern to extract in the result of the target command. In the example previously described patternLength would be 4 (each pattern is 3 bytes for the DTC identifier + 1 byte for the status).
        • startOffset: the offset from the start of the response to start the loop. In the example previously described, if the response of commandA is "0x59 0x02 0x7F DTC1 DTC2 ... DTCn", startOffset would be 3, the first pattern to put in the loop starts at byte 3 of the response. Note: startOffset starts the count at the command payload, for example, when doing ISO 15765-4, the count starts after the length byte.
        • The precedent described procedure would be the following:
          • send commandA and receive response "0x59 0x02 DTC1 (=4bytes) DTC2 (=4bytes) ... DTCn (=4bytes)"
          • startOffset is 3 and patternLength is 4, the loop starts.
          • send commandB replacing CommandA_Pattern[O-2] with DTC1[0-2]
          • send commandB replacing CommandA_Pattern[0-2] with DTC2[0-2]
          • ...
          • send CommandB replacing CommandA_Pattern[0-2] with DTCn[0-2]
          • the loop ends.
  • OPTIONAL fields specific to listen mode
    • startListenOnLoad: If set to false, when loading the stack, don't start listening at once and wait for an executeAction request before doing so. Default: true.
    • polling: register this action to the PollingManager. This allows retrieving the action's results through the PollingClient interface. Note: this parameter only works when used with canPolling commands.

Return and formula fields

Available operations

The basic mathematical operations available are listed on
http://www.objecthunter.net/exp4j/index.html
Along with this list, some other operations can be used:

  • Bitwise & and |. Example: "CAN_FRAME[0] & 8". This operation works only on a byte and not on the complete frame.
  • Support for hexadecimal numbers. Example: "CAN_FRAME[0] & 0x08"
  • Integer parsing: getInt(data, offset, length), getIntS(data, offset, length, signed), getIntSE(data, offset, length, signed, endianness)
    • data: the full frame on which to parse the int.
    • offset: the offset in bits
    • length: number of bits
    • signed: 0: unsigned, 1: signed. Default is 0
    • endianness: 0: big endian, 1: little endian. Default is 0
    • Example: getIntSE(CAN_FRAME, 8, 12, 1, 0): get a signed integer from CAN_FRAME which is on 12 bits with an offset of 1 byte in big endian format.
  • Mathematical comparison: ==, !=, >, <, >=, <=. The result of these operators is 0 (false) or 1 (true) (as a double). To use the result in DB as a boolean, use the integer type (":I") inside the DB.
  • Binary && and ||. The result of these operators is 0 (false) or 1 (true) (as a double). To use the result in DB as a boolean, use the integer type (":I") inside the DB.

Custom Expressions

The custom expressions can be used instead of the return formulas.
The advantage is a much higher performance and efficiency, but the
number of operations is limited.
List of available operations:

ParseInt

Works only with actions that have a single dependency frame.
Allows to parse an integer (with optionnal sign and endianness) and make
linear calculation on it: Ax+B


parseInt(int bitOffset, int bitLength, boolean signed, boolean bigEndian, double valueFactor, double valueOffset)

  • bitOffset: the offset in bits.
  • bitLength: the number of bits of the integer.
  • signed: should the result be interpreted as signed or unsigned int (default: false).
  • bigEndian: boolean, false for little endian (default: true).
  • valueFactor: multiplicator for the final result (A in Ax+b) (default: 1).
  • valueOffset: offset for the final result (B in Ax+b) (default 0).

{
  "name": "ParseInt",
  "parameterTypes": [ "int", "int", "boolean", "boolean", "double", "double" ],
  "parameterValues": [ 0, 16, false, true, 2, 5 ]
}

There also exists simpler variations of the API:


parseInt(int bitOffset, int bitLength, boolean signed, boolean bigEndian)


{
  "name": "ParseInt",
  "parameterTypes": [ "int", "int", "boolean", "boolean" ],
  "parameterValues": [ 0, 16, false, true ]
}


parseInt(int bitOffset, int bitLength, double valueFactor, double valueOffset)


{
  "name": "ParseInt",
  "parameterTypes": [ "int", "int", "double", "double" ],
  "parameterValues": [ 0, 16, 2, 5 ]
}


parseInt(int bitOffset, int bitLength)


{
  "name": "ParseInt",
  "parameterTypes": [ "int", "int" ],
  "parameterValues": [ 0, 16 ]
}

ParseOneByte

Works only with actions that have a single dependency frame.
Allows to make quick computations on a single byte of a frame.


parseOneByte(int byteIndex, double valueFactor, double valueOffset)

  • byteIndex: The byte index.
  • valueFactor: multiplicator for the final result (A in Ax+b) (default: 1).
  • valueOffset: offset for the final result (B in Ax+b) (default: 0).

{
  "name": "ParseOneByte",
  "parameterTypes": [ "int", "double", "double" ],
  "parameterValues": [ 0, 2, 5 ]
}


parseOneByte(int byteIndex)


{
  "name": "ParseOneByte",
  "parameterTypes": [ "int" ],
  "parameterValues": [ 0 ]
}

Note on listen mode actions

  • Listen mode and request mode are not compatible: this means that request actions cannot depend on "listen commands" (canFrameReceive) and listen actions cannot depend on "active commands" (all other commands).
  • Listen actions must depend on one and only one canFrameReceive command. Multi-dependency for these actions is not possible for now.

{
    "actionList": [
        {
            "exportToDB": "VEHICLE_SPEED_KM_H",
            "name": "speedKmPerHour",
            "depends": [
                "OBD_010D"
            ],
            "return": "OBD_010D[0]"
        },
        {
            "exports": [
                {
                    "formula": "OBD_010D[0]",
                    "db": "VEHICLE_SPEED_KM_H2"
                }
            ],
            "name": "speedKmPerHour2",
            "depends": [
                "OBD_010D"
            ],
            "return": "0"
        },
        {
            "periodSec": 60,
            "report": "all",
            "name": "diagnostics",
            "depends": [
                "speedKmPerHour",
                "maf",
                "literPerSec",
                "literPer100Km"
            ],
            "return": "0"
        },
        {
            "name": "listenAction",
            "mode": "listen",
            "depends": [
                "broadcasted_frame"
            ],
            "return": "broadcasted_frame[0]*256+broadcasted_frame[1]"
        },
        {
            "name": "doReportDTCDataForAll",
            "depends": [
              "ReportDTCByStatusMask"
            ],
            "loop": {
              "depends": [
                "ReportDTCExtData",
                "ReportDTCSnapShot"
              ],
              "target": "ReportDTCByStatusMask",
              "patternLength": 4,
              "startOffset": 3
            },
            "report": "all",
            "return": 0
        },
        {
            "name": "requestDataInSession",
            "initSession": [
              "commandInitSession"
            ],
            "communication": [
              "dataRequest1",
              "dataRequest2"
            ],
            "closeSession": [
              "commandCloseSession"
            ],
            "initAttempts": 3,
            "initDelay": 500,
            "return": 0
        },
        {
          "name": "accumulatePeriodicFuelConsumption",
          "mode": "listen",
          "depends": [
            "fuelConsumedPeriodicFrame"
          ],
          "accumulator": {
            "counterMaxValue": 255,
            "stepMultiplier": 0.25
          },
          "returnExpression": {
            "name": "ParseOneByte",
            "parameterTypes": [
              "int"
            ],
            "parameterValues": [
              0
            ]
          }
        }
    ]
}

To retrieve the results of the execution of the OBDStacks command, you have to:

When a command is executed ( periodically with "periodSec" or through a message sent by an API command or by the deviceManager ) a mesage will be sent by webhook. This message is described below :

  • stackStatus: it is an integer that indicates if the stack is operational. 1 means OK or loaded properly or dropped properly, 0 action couldn't be performed on this stack.
  • name: A string that is the name of the current stack.
  • results: It is a JSON array that contains the list of results per action.
    • actionListName: The name of the executed action.
    • serverParameters: The value of serverParameters present in the executed actionList command. If not present or empty/NULL in actionList, it won't be send back to server.
    • result: an double that is the result of the calculation of the expression described in result from the actionList.
    • resultList: a JSON array that contains bytes from all dependancies of the executed actionList if the optional report attribute is set to all.
      • commandName: The command name
      • data: An array of integers that were returned by this command
{
    "results": [
        {
            "actionListName": "speedKmPerHour",
            "result": 255
        },
        {
            "actionListName": "EcuId",
            "serverParamters": "version3",
            "result": 0,
            "resultList": [
                {
                    "commandName": "w7E0_3E00",
                    "data": [
                        127,
                        62
                    ]
                },
                {
                    "commandName": "w7E0_3E01",
                    "data": [
                        127,
                        32,
                        18
                    ]
                }
            ]
        }
    ]
}

Using the Dashboard web interface

Make sure that your device has the app Advanced CAN Gateway binded (http://www.munic.io/documentations/how_to_link_app). Then, you just have to use the app on the DM Apps page.
When associated, an "Apps" tab is available from your Morpheus Manager interface.

Available

In the interface below, select the asset and paste the commands to load in the edition box. The session below describes the possible commands to load.

Available

Clicking on "Save changes" will immediately send the contents of the edition box to the asset(s).

Finally, the results are sent by the device in the form of message packets, not track packets. See http://www.munic.io/documentations/tracks#toc_2 for the documentation on how to parse message packets.

  • The list of possible commands are
    • Load a JSON OBDStack
    • Execute an action from the currently loaded OBDStack
    • Execute a list of actions from the currently loaded OBDStack
    • Drop the current OBDStack
    • Get the name of the current OBDStack

Using the Dashboard APIs

The general documentation for sending messages using apps is here:
https://dashboard.munic.io/api_doc/v2/versions/send_app_messages.html

The app to use is Advanced CAN Gateway with id 52.

Example POST request (to request the availability of the action named readAllDTC):

POST '/api/v2/modules/versions/52/messages':
 {
   "targeted_assets": [ "351732XXXXX95", "351732057XXXX8" ],
   "targeted_assets_group_ids" : [ 1, 2 ]
   "messages": [ "{ \"request\": \"isActionAvailable\", \"name\": \"readAllDTC\" } ]
 }

You can choose to use either targeted_assets or targeted_assets_group_ids to send the ObdStacks request to a list of assets or asset groups respectively.

Load description file

  • Load a given obdStack as described previously. The stacks are accumulated and overwritten as long as no drop action is called.
  • Whenever loading a stack and a stack is already there, if names are both set, the current name will be the concatenation of previous and new stacks's names.
  • Upon success, the current name will be returned in the field name.
  • Request to load JSON stack :

{
    "request": "loadStack",
    "requestId": "Stack",
    "jsonString": {
        "obdStack": {   }
    }
}

  • Response :

{
    "stackStatus": 1,
    "name": "stackAstackB"
}

if stack was correctly loaded, or


{
    "stackStatus": 0
}

in case of error.

Check the availability of an action

  • Check if a given action name is available for execution in the stack.
    • request is a mandatory field. It tells the program which kind of request it is. Use isActionAvailable for this type of request.
    • name is a mandatory field. The name of the action you want to check.
    • requestId is an optional field. If present, it will be found in the answer from the program. It allow one to understand to which request the answer is related.
  • Request:

{
    "request": "isActionAvailable",
    "name": "speedKmPerHour",
    "requestId":"myinternalId"
}

  • Response:

{
    "requestId":"myinternalId",
    "name": "speedKmPerHour",
    "available":true
}

Execute an action

  • Execute an action already present in the current obdStack.
    • request is a mandatory field. It tells the program which kind of request it is. Use executeAction to execute a stack action.
    • name is a mandatory field. The name of the action to execute. It must be present in the currently loaded stack.
    • requestId is an optional field. If present, it will be found in the answer from the program. It allow one to understand to which request the answer is related.
  • Request:

{
    "request": "executeAction",
    "name": "speedKmPerHour",
    "requestId":"myinternalId"
}

  • Response:

{
    "requestId":"myinternalId",
    "results": [
        {
            "actionListName": "speedKmPerHour",
            "result": 255,
        }
    ]
}

Execute a list of actions

  • Execute a list of actions already present in the current obdStack or around it. The results will arrive in several messages as soon as executed.
    • request is a mandatory field. It tells the program which kind of request it is. Use executeAction to execute a stack action.
    • actions is a mandatory field. The array of actions as a valid action request - see previous "Execute an action".
    • requestId is an optional field. If present, it will be found in the answer from the program with a dash followed by the ID of the action. It allow one to understand to which request the answer is related.
  • Request:

{
    "request": "executeActions",
    "actions": [
       {
          "request": "executeAction",
          "name": "speedKmPerHour"
       },
       {
          "request": "drop",
       }
     ],
    "requestId":"myinternalId"
}

  • Responses:

{
    "requestId":"myinternalId-1",
    "results": [
        {
            "actionListName": "speedKmPerHour",
            "result": 255,
        }
    ]
}

Then a second message


{
    "requestId":"myinternalId-2",
    "drop": true,
    "name": "my stack name"
}

Drop the current OBDStack

All messages are added to the current stack. This allow you to send your
stack with several messages.
The stacks send to the message are saved on the flash of the device and
are retreive upon reboot.

Whenever an action, command, ecu has the same name as a previous one,
the new one replaces the old one.

Whenever a message contains the drop command, then all information from
RAM, Flash are dropped before handling the message itself.
The answer has the field drop that indicates the status (true or
false) and when true, the field name that contains the dropped
stack name (No name if name is not set).

  • Request:

{
    "request": "drop"
}

  • Request with specific stack name:

{
    "request": "drop",
    "stackName": "MyStackName"
}

  • Response :

{
    "drop": true,
    "name": "my stack name"
}

if stack was correctly dropped, or


{
    "drop": false
}

in case of error.

Get the current obdStack name

  • Fetch the current obdStack name, results can be "null" (no stack), "No Name" (no name set), or the latest given stack name. Whenever several stacks with name were to be loaded with a new name, the current name is the concatenation separated with ';' of all given names following the load order.
  • Request:

{
    "request": "getName"
}

  • Response:

{
    "name": "No Name"
}

Errors

  • In case of error when attempting to execute the request, a short error message will be sent:

{
    "error": "Illegal argument: Action unknownAction doesn't exist"
}

  • If an error occurs while sending a command (e.g. no answer, no data available), the result of this command will be empty in the JSON: "".
  • If an error occurs while executing an action (e.g. divide by zero, command dependency failure ), the result of this action will be double -0.1 in the JSON: -0.1.

Get the Connection Configuration (available in 3.04029XXX and more)

You can get the current connection's configuration of a device thanks to
the following request.
You have the possibility to receive the connection's parameters from one
protocol only (CAN, KLine or J1850), or to get all of them on the same
request.

There is a description of its fields:

  • request: a string which is "getConnectionParameter"
  • protocol (optional): Specify the protocol you want the parameters. This field is a string, which can be filled with either "can", "kline", "j1850" or "all". By default, the informations about every protocol will be sent.

The response will be:

  • getConnectionParameter: a JSON Object which contain the same JSON Object as the one called "configuration" bellow

Some examples:


{
    "request": "getConnectionParameter"
}

Response:


{
    "getConnectionParameter": {
        "active": true,
        "connectionInfo": [{
            "listenOnly": false,
            "canBaudRate": 424242,
            "canConnection": "CAN-OBD-TEST"
        }, {
            "type": "j1850",
            "ifr": 42,
            "srcAddress": 42,
            "mode": 0
        }]
    }
}

And:


{
    "request": "getConnectionParameter",
    "protocol": "j1850"
}

Response:


{
    "getConnectionParameter": {
        "active": true,
        "connectionInfo": [{
            "type": "j1850",
            "ifr": 42,
            "srcAddress": 42,
            "mode": 0
        }]
    }
}

Set the Connection Configuration

This section describes the non-usual case when you want to set a
specific configuration with a setConnections request.
This is only used to access proprietary buses but is not necessary to
access standard buses.

Warning : except for CAN, setConnections is only available on 3.04029XXX and more

There is a description of it's fields:

  • request: a string which is "setConnections"
  • configuration: It is a JSON object that contains :
    • active: a boolean to indicate if you want to activate the connection after setting the configuration.
    • pinSwitchPeriodMS (optional) (for Can connections only) : the period of the PIN switch mode which will be enable if you chose to fill this field.
    • connectionInfo: It is a JSON array with the different informations of the different connections you want to set.
      • type: The type of connection. Possibilities are "can", "kline", "j1850". If not set, type will be "can".
      • CAN related options
        • canConnection (mandatory): Specify the bus to use (contact us for details about CAN PIN switching capabilities).
        • canBaudRate (mandatory): Specify the speed of the bus if you want to restrict it. Common values are 250000 or 500000.
        • listenOnly (optional): If set to true, the Can connection will be full listen only, nothing will be send on the bus, the connection will only listen the bus. if not set this option will be set to false
      • KLine related options, all OPTIONAL
        • Format parameters
          • default_configuration : Json object used to set the default values of the connections parameters.
          • configs : Json array used to store jsonObject that defines connection parameters.
          • initList : Store two value. a config name ("config"), and a number of tries ("tries"). It is used to set a connection procedure.
        • Timing related configuration
          • p1Max : Inter-byte timing parameter of the ECU, in 0.5 ms per unit.
          • p3Min : Min time between end of ECU response and new tester request, in 0.5 ms per unit.
          • p4Min : Inter-byte timing parameter of the tester, in 0.5 ms per unit.
          • w1 : Time in ms from end of address byte to start of synchronization pattern.
          • w2 : Time in ms between synchronization pattern and byte 1.
          • w3 : Time in ms between key byte 1 and 2.
          • w4 : Time in ms between key byte 2 and its inversion from the client.
          • w5 : Time in ms before client should transmit address byte.
          • tidle : Tester idle time in ms.
          • tinil : Tester low time in ms.
          • twup : Tester wakeup time in ms.
        • Other options related configuration
          • dataBits : set this value to 1 if you want a 7 bits UART KLine. if not set the precedent value (or the default value if no precedent) will be set.
          • invertPolarity : boolean value. Invert everything on the bus, including the INIT sequence and the messages.
          • initKOnly : boolean value. Only use the K-line moves during initialization.
          • initLOnly : boolean value. Only use the L-line moves during initialization.
          • TXUseLLine : boolean value. After the init, in mode uart, the messages are sent using the L-line instead of the K-line. Reception remains on the K-Line.
          • TXUseKAndL : boolean value. After the init, in mode uart, the messages are sent using the L-line and the K-line. Reception remains on the K-Line.
          • baudrate : uint32 value. if not set the precedent value (or the default value if no precedent) will be set.
          • parity : uint16 value. if not set the precedent value (or the default value if no precedent) will be set.
          • fivebaudMode : uint16 value. if not set the precedent value (or the default value if no precedent) will be set.
          • initType : string value. Can be "SLOW", "FAST, or "NONE".
          • noCheckKeywords : boolean value to indicate if you want to check to keywords sent by the vehicle. if not set the value will be false (ie keywords will be checked).
          • priorityISO9141 : boolean value. if initType has been set to "NONE", and noCheckKeywords is true, this parameter will force one of the two kline protocols.
          • pingPayload : an array byte representing the payload of a ping message. Used to keep the connection alive.
          • pingChecksum : integer used to overload the checksum of the frame used to ping.
          • startCommunicationPayload : an array byte representing the payload of a message used to start the connection. Only used for KWP2000 connections.
          • startCommunicationChecksum : integer used to overload the checksum of the frame used to start communication in KWP2000.
      • J1850 related options
        • mode : 0 for PWM, 1 for VWP, -1 to testing all cases. if not set the field will be -1.
        • srcAddress : String of length 2 representing the hexa source address for the connection. if not set the address will be 0xF1 (same as if the field is set to "F1").
        • ifr : String of length 2 representing the hexa ifr message send by the device to acknowledge a message during the connection. if not set the ifr will be 0xF1 (same as if the field is set to "F1").

NOTE: for KLine : if you set any of the field
initAddress, initSrcAddress or noCheckKeywords you
MUST use the filed ecu in ALL your klineCommand
(and, of course, have set "ecuDescription" of type "kline" before).


 {
  "request": "setConnections",
  "requestId": "Connections",
  "configuration": {
    "active": true,
    "connectionInfo": [
      {
        "type": "kline",
        "ecuInitList": [
          {
            "name": "init_procedure_0",
            "configs": [
              {
                "name": "init_config_0",
                "baudrate": 5,
                "initType": "SLOW" 
              },
              {
                "name": "init_config_1",
                "baudrate": 10400,
                "initType": "FAST" 
              }
            ],
            "initList": [
              {
                "config": "init_config_0",
                "tries": 1
              },
              {
                "config": "init_config_1",
                "tries": 2
              }
            ]
          },
          {
            "name": "init_procedure_1",
            "raw": true,
            "configs": [
              {
                "name": "init_config_0",
                "baudrate": 5,
                "initType": "SLOW",
                "pingPayload": ["0xC1", "0x33", "0xF1", "0x3E", "0x23"],
                "startCommunicationPayload": ["0x33"],
                "tidle": 300,
                "tinil": 25,
                "twup": 50
              },
              {
                "name": "init_config_1",
                "baudrate": 10400,
                "initType": "FAST",
                "pingPayload": ["0xC1", "0x33", "0xF1", "0x3E", "0x23"],
                "startCommunicationPayload": ["0xC1", "0x33", "0xF1", "0x81", "0x66"],
                "w1": 300,
                "w2": 20,
                "w3": 20,
                "w4": 25,
                "w5": 300,
                "tidle": 300,
                "tinil": 25,
                "twup": 50
              }
            ],
            "initList": [
              {
                "config": "init_config_0",
                "tries": 1
              },
              {
                "config": "init_config_1",
                "tries": 2
              }
            ]
          }
        ]
      }
    ]
  }
}


{
  "obdStack": {
    "name": "Default_OBD",
    "obdCommand": [
      {
        "name": "OBD_0101",
        "mode": "01",
        "pid": "01"
      },
      {
        "name": "OBD_012F",
        "mode": "01",
        "pid": "2F"
      },
      {
        "name": "OBD_0111",
        "mode": "01",
        "pid": "11"
      },
      {
        "name": "OBD_0104",
        "mode": "01",
        "pid": "04"
      },
      {
        "name": "OBD_010A",
        "mode": "01",
        "pid": "0A"
      },
      {
        "name": "OBD_015C",
        "mode": "01",
        "pid": "5C"
      },
      {
        "name": "OBD_RPM",
        "mode": "01",
        "pid": "0C"
      },
      {
        "name": "OBD_SPEED",
        "mode": "01",
        "pid": "0D"
      },
      {
        "name": "OBD_0144",
        "mode": "01",
        "pid": "44"
      },
      {
        "name": "OBD_015E",
        "mode": "01",
        "pid": "5E"
      },
      {
        "name": "OBD_0151",
        "mode": "01",
        "pid": "51"
      },
      {
        "name": "OBD_010F",
        "mode": "01",
        "pid": "0F"
      },
      {
        "name": "OBD_010B",
        "mode": "01",
        "pid": "0B"
      },
      {
        "name": "OBD_0110",
        "mode": "01",
        "pid": "10"
      },
      {
        "name": "OBD_014F",
        "mode": "01",
        "pid": "4F"
      },
      {
        "name": "OBD_0150",
        "mode": "01",
        "pid": "50"
      },
      {
        "name": "OBD_0105",
        "mode": "01",
        "pid": "05"
      },
      {
        "name": "OBD_VIN",
        "mode": "09",
        "pid": "02"
      }
    ],
    "actionList": [
      {
        "name": "getRPM",
        "depends": [
          "OBD_RPM"
        ],
        "exportToDB": "MDI_OBD_RPM:I",
        "return": "((OBD_RPM[0]*256)+OBD_RPM[1])/4"
      },
      {
        "name": "getVehicleSpeed",
        "depends": [
          "OBD_SPEED"
        ],
        "exportToDB": "MDI_OBD_SPEED:I",
        "return": "OBD_SPEED[0]"
      },
      {
        "name": "getThrottlePosition",
        "depends": [
          "OBD_0111"
        ],
        "exportToDB": "MDI_OBD_THROTTLE_POSITION:I",
        "return": "OBD_0111[0]*100/255"
      },
      {
        "name": "getFuelLevelInput",
        "depends": [
          "OBD_012F"
        ],
        "exportToDB": "MDI_DASHBOARD_FUEL_LEVEL:I",
        "return": "OBD_012F[0]*100/255"
      },
      {
        "name": "getEngineLoad",
        "depends": [
          "OBD_0104"
        ],
        "exportToDB": "MDI_OBD_ENGINE_LOAD:I",
        "return": "OBD_0104[0]*100/255"
      },
      {
        "name": "getFuelPressure",
        "depends": [
          "OBD_010A"
        ],
        "exportToDB": "MDI_OBD_FUEL_PRESSURE:I",
        "return": "3*OBD_010A[0]"
      },
      {
        "name": "getEngineOilTemperature",
        "depends": [
          "OBD_015C"
        ],
        "exportToDB": "MDI_OBD_ENGINE_OIL_TEMP:I",
        "return": "OBD_015C[0]-40"
      },
      {
        "name": "getCER",
        "depends": [
          "OBD_0144"
        ],
        "exportToDB": "MDI_OBD_CER:D",
        "return": "(OBD_0144[0]*256+OBD_0144[1])*2/65535"
      },
      {
        "name": "getFuelRate",
        "depends": [
          "OBD_015E"
        ],
        "exportToDB": "MDI_OBD_FUEL_RATE:D",
        "return": "((OBD_015E[0]*256)+OBD_015E[1])*0.05/3600"
      },
      {
        "name": "getMAF",
        "depends": [
          "OBD_0110"
        ],
        "exportToDB": "MDI_OBD_MAF:D",
        "return": "((OBD_0110[0]*256)+OBD_0110[1])/100"
      },
      {
        "name": "getIAT",
        "depends": [
          "OBD_010F"
        ],
        "exportToDB": "MDI_OBD_IAT:D",
        "return": "OBD_010F[0]-40"
      },
      {
        "name": "getMAP",
        "depends": [
          "OBD_010B"
        ],
        "exportToDB": "MDI_OBD_MAP:D",
        "return": "OBD_010B[0]"
      },
      {
        "name": "getEngineCoolantTemperature",
        "depends": [
          "OBD_0105"
        ],
        "exportToDB": "MDI_OBD_ENGINE_COOLANT_TEMP:I",
        "return": "OBD_0105[0] - 40"
      },
      {
        "name": "getCERScale",
        "depends": [
          "OBD_014F"
        ],
        "exportToDB": "MDI_OBD_CER_SCALE:D",
        "return": "OBD_014F[0]/2"
      },
      {
        "name": "getMAFScale",
        "depends": [
          "OBD_0150"
        ],
        "exportToDB": "MDI_OBD_MAF_SCALE:D",
        "return": "OBD_0150[0]*1000/65535"
      },
      {
        "name": "getFuelType",
        "depends": [
          "OBD_0151"
        ],
        "exportToDB": "MDI_OBD_FUEL_TYPE:I",
        "return": "OBD_0151[0]"
      },
      {
        "name": "getMonitorStatus",
        "depends": [
          "OBD_0101"
        ],
        "exportToDB": "MDI_OBD_MONITOR_STATUS:I",
        "return": "getInt(OBD_0101, 0, 32)"
      },
      {
        "name": "getVIN",
        "depends": [
          "OBD_VIN"
        ],
        "returnType": "string",
        "return": "OBD_VIN"
      }
    ]
  }
}