Torque OBDII Vehicle integration

I use the android Torque app connected to my phone through generic ELM327 Bluetooth OBD2 adapter every time I drive and would like to incorporate that data into my OpenHAB model environment for logging and event control. I found a a git repo for importing the data to MySQL and was wondering if anyway it could be made to go through openhab first.

edit:add link to Torque

1 Like

Have a look at the Mojio binding (I believe it is still a pull request). It uses a REST API to a service in the cloud, but you might consider publishing to an MQTT broker from your mobile device, and then just use the MQTT item binding.

There is no reference to that binding in the OpenHAB Wiki…

Plus I already have the torque app and a ELM327 Bluetooth obd2 device and I paid a total of $25 for both. where as the device you referenced cost $150 needs it’s own AT&T data plan. so I will not be using the Mojio device when I have all the same functionality from something much cheaper.

A quick look at that repo shows that it works as the following:

  • The Torque app is configured to publish to a webserver URL. This would be your own web server hosted locally on your machine with a port exposed the the Internet and presumable a DynDNS type host name.
  • The webserver consists of a bunch of php scripts which takes the REST calls sent from the Torque app and saves them to MySQL.

So, to get this to work someone would need to fork that repo and replace all the MySQL code with REST calls or MQTT calls into openHAB instead/in addition to the MySQL calls.

Another alternative could be to write a script that polls the MySQL database and publishes updates to openHAB. This is an admittedly unsatisfactory approach but it is used for integration with Zoneminder and it appears to work fairly well.

No matter what though, this is going to require some significant coding to achieve.

Would there be a way to have OpenHAB be the receiver of the data from Torque and put it on the bus as if it was a sensor? I just noticed that Home Assistant IO did something with it thats why I ask. https://home-assistant.io/components/sensor.torque/

The problem is, at least based on my looking at that repo, is that the Torque app doesn’t publish the data in a way that openHAB can understand (i.e. it doesn’t conform to OH’s REST API) so you need something in between to translate the data coming in from Torque to something OH can understand. The root of the problem is that the only web server that OH supports that allow other programs to make HTTP calls TO openHAB is its REST API.

Hi all, I came across this device, which can be used world wide, any idea if it can be integrated into OH?
OBD

My 5c here. I haven’t cared enough to connect my car OBD to OH, however I rough way might be…

Dash app (instead of Torque) to gather trip info, saving overall trip info to Google Sheets, and then Google Sheets to OH? (Both piped via IFTTT).

As I say I haven’t bothered to try the whole of that, and it would only provide overall trip info (not realtime gauge info).

I know the first half works (Dash > IFTTT > Google Sheets) as I do that myself to record trips, notify me when time for servicing, etc.

I know OH now connects to IFTTT. Remains to be seen if the OH IFTTT connector can pass enough info thru.

I ended up using Node-Red as the interface to the Torque app it receives the data and retransmits it via MQTT for all apps and programs to devour. If anyone is interested I’ll post the flow to this thread.

4 Likes

OK here is the flow. the simple part is receiving the get.
The HTTP in node splits out the data and the HTTP out node gives the “OK!” the torque app is looking for.
I also have a write to MySQL to store the data. that can be removed if youonly want to see it real time or have openHAB do the logging.

In torque under Settings > Data Logging and Upload
Select what to log = All the PID’s you want to sent to node-red
Upload to web server = checked
Webserver URL = http://your.nodered.server:1880/torque/

let me know if you have any more questions.

[
    {
        "id": "2ce0055.8743efa",
        "type": "tab",
        "label": "Torque",
        "disabled": false,
        "info": ""
    },
    {
        "id": "67436221.b54c0c",
        "type": "http in",
        "z": "2ce0055.8743efa",
        "name": "",
        "url": "/torque",
        "method": "get",
        "upload": true,
        "swaggerDoc": "",
        "x": 221,
        "y": 143,
        "wires": [
            [
                "f98f22cc.807ba",
                "557d7766.022168",
                "33d571b3.db242e",
                "69b56cf.77bc694",
                "683933fa.d76f1c",
                "ab2ff853.e8b808",
                "c005b8b1.f06b98",
                "96abaa53.c70988",
                "ee5bc723.594bf8",
                "dfdc4763.7a8fd8",
                "cee9fa09.98b6d8",
                "f2d748c5.d92da8",
                "936bc33f.bcd27",
                "97ab65f2.1a0728"
            ]
        ]
    },
    {
        "id": "f98f22cc.807ba",
        "type": "http response",
        "z": "2ce0055.8743efa",
        "name": "",
        "statusCode": "",
        "headers": {
            "OK!": ""
        },
        "x": 1290,
        "y": 140,
        "wires": []
    },
    {
        "id": "557d7766.022168",
        "type": "change",
        "z": "2ce0055.8743efa",
        "name": "Barometer",
        "rules": [
            {
                "t": "move",
                "p": "payload.kff1270",
                "pt": "msg",
                "to": "payload",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "topic",
                "pt": "msg",
                "to": "torque\\phone\\barometer",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 731,
        "y": 403,
        "wires": [
            [
                "536ae3f0.1980dc",
                "5ef6a21e.75ce4c"
            ]
        ]
    },
    {
        "id": "3b30fefa.3f9012",
        "type": "ui_gauge",
        "z": "2ce0055.8743efa",
        "name": "",
        "group": "9b558fbc.438aa",
        "order": 1,
        "width": "6",
        "height": "6",
        "gtype": "gage",
        "title": "RPM",
        "label": "RPM",
        "format": "{{value}}",
        "min": 0,
        "max": "7000",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "x": 1061,
        "y": 443,
        "wires": []
    },
    {
        "id": "33d571b3.db242e",
        "type": "change",
        "z": "2ce0055.8743efa",
        "name": "RPM",
        "rules": [
            {
                "t": "move",
                "p": "payload.kc",
                "pt": "msg",
                "to": "payload",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "topic",
                "pt": "msg",
                "to": "torque\\vehicle\\rpm",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 721,
        "y": 443,
        "wires": [
            [
                "3b30fefa.3f9012",
                "5ef6a21e.75ce4c"
            ]
        ]
    },
    {
        "id": "69b56cf.77bc694",
        "type": "change",
        "z": "2ce0055.8743efa",
        "name": "Mass Air Flow Rate",
        "rules": [
            {
                "t": "move",
                "p": "payload.k10",
                "pt": "msg",
                "to": "payload",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "topic",
                "pt": "msg",
                "to": "torque\\vehicle\\mafrate",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 761,
        "y": 483,
        "wires": [
            [
                "7ee21162.28cdb",
                "5ef6a21e.75ce4c"
            ]
        ]
    },
    {
        "id": "683933fa.d76f1c",
        "type": "change",
        "z": "2ce0055.8743efa",
        "name": "Throttle Position",
        "rules": [
            {
                "t": "move",
                "p": "payload.k11",
                "pt": "msg",
                "to": "payload",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "topic",
                "pt": "msg",
                "to": "torque\\vehicle\\throttle",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 751,
        "y": 523,
        "wires": [
            [
                "3765c6b.fb70f3a",
                "5ef6a21e.75ce4c"
            ]
        ]
    },
    {
        "id": "ab2ff853.e8b808",
        "type": "change",
        "z": "2ce0055.8743efa",
        "name": "Coolant Temp",
        "rules": [
            {
                "t": "move",
                "p": "payload.k5",
                "pt": "msg",
                "to": "payload",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "topic",
                "pt": "msg",
                "to": "torque\\vehicle\\coolant",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 741,
        "y": 563,
        "wires": [
            [
                "258b6f62.e82ab"
            ]
        ]
    },
    {
        "id": "c005b8b1.f06b98",
        "type": "change",
        "z": "2ce0055.8743efa",
        "name": "Volage",
        "rules": [
            {
                "t": "move",
                "p": "payload.kff1238",
                "pt": "msg",
                "to": "payload",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "topic",
                "pt": "msg",
                "to": "torque\\obd\\voltage",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 721,
        "y": 603,
        "wires": [
            [
                "5b8bdb33.d96134",
                "5ef6a21e.75ce4c"
            ]
        ]
    },
    {
        "id": "96abaa53.c70988",
        "type": "change",
        "z": "2ce0055.8743efa",
        "name": "Vacuum",
        "rules": [
            {
                "t": "move",
                "p": "payload.kff1202",
                "pt": "msg",
                "to": "payload",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "topic",
                "pt": "msg",
                "to": "torque\\vehicle\\vacuum",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 731,
        "y": 643,
        "wires": [
            [
                "913a6311.540cd",
                "5ef6a21e.75ce4c"
            ]
        ]
    },
    {
        "id": "3765c6b.fb70f3a",
        "type": "ui_gauge",
        "z": "2ce0055.8743efa",
        "name": "",
        "group": "9b558fbc.438aa",
        "order": 2,
        "width": "3",
        "height": "3",
        "gtype": "donut",
        "title": "Throttle Position",
        "label": "%",
        "format": "{{value}}",
        "min": 0,
        "max": "100",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "x": 1091,
        "y": 523,
        "wires": []
    },
    {
        "id": "ee5bc723.594bf8",
        "type": "change",
        "z": "2ce0055.8743efa",
        "name": "Speed",
        "rules": [
            {
                "t": "move",
                "p": "payload.kd",
                "pt": "msg",
                "to": "payload",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "topic",
                "pt": "msg",
                "to": "torque\\vehicle\\speed",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 721,
        "y": 683,
        "wires": [
            [
                "c3863c64.b8c2d",
                "5ef6a21e.75ce4c"
            ]
        ]
    },
    {
        "id": "c3863c64.b8c2d",
        "type": "ui_gauge",
        "z": "2ce0055.8743efa",
        "name": "",
        "group": "ea9cdc42.4bbc8",
        "order": 0,
        "width": 0,
        "height": 0,
        "gtype": "gage",
        "title": "Speed",
        "label": "MPH",
        "format": "{{value}}",
        "min": 0,
        "max": "100",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "x": 1061,
        "y": 683,
        "wires": []
    },
    {
        "id": "7ee21162.28cdb",
        "type": "ui_gauge",
        "z": "2ce0055.8743efa",
        "name": "",
        "group": "9b558fbc.438aa",
        "order": 3,
        "width": "2",
        "height": "3",
        "gtype": "wave",
        "title": "Mass Air Flow",
        "label": "g/s",
        "format": "{{value}}",
        "min": 0,
        "max": "100",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "x": 1091,
        "y": 483,
        "wires": []
    },
    {
        "id": "536ae3f0.1980dc",
        "type": "ui_gauge",
        "z": "2ce0055.8743efa",
        "name": "",
        "group": "26a930d9.ff8c",
        "order": 0,
        "width": "3",
        "height": "3",
        "gtype": "gage",
        "title": "Barometer",
        "label": "units",
        "format": "{{value}}",
        "min": "800",
        "max": "1100",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "x": 1071,
        "y": 403,
        "wires": []
    },
    {
        "id": "dfdc4763.7a8fd8",
        "type": "change",
        "z": "2ce0055.8743efa",
        "name": "Speed GPS",
        "rules": [
            {
                "t": "move",
                "p": "payload.kff1001",
                "pt": "msg",
                "to": "payload",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "topic",
                "pt": "msg",
                "to": "torque\\phone\\speed",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 741,
        "y": 723,
        "wires": [
            [
                "535662ad.f1628c",
                "5ef6a21e.75ce4c"
            ]
        ]
    },
    {
        "id": "535662ad.f1628c",
        "type": "ui_gauge",
        "z": "2ce0055.8743efa",
        "name": "",
        "group": "26a930d9.ff8c",
        "order": 0,
        "width": "3",
        "height": "3",
        "gtype": "gage",
        "title": "Speed GPS",
        "label": "MPH",
        "format": "{{value}}",
        "min": 0,
        "max": "100",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "x": 1081,
        "y": 723,
        "wires": []
    },
    {
        "id": "5b8bdb33.d96134",
        "type": "ui_gauge",
        "z": "2ce0055.8743efa",
        "name": "",
        "group": "ea9cdc42.4bbc8",
        "order": 0,
        "width": "3",
        "height": "3",
        "gtype": "gage",
        "title": "Voltage",
        "label": "V",
        "format": "{{value}}",
        "min": "9",
        "max": "15",
        "colors": [
            "#ff0000",
            "#008000",
            "#ff0000"
        ],
        "seg1": "13",
        "seg2": "14.3",
        "x": 1071,
        "y": 603,
        "wires": []
    },
    {
        "id": "b0123228.4a063",
        "type": "ui_gauge",
        "z": "2ce0055.8743efa",
        "name": "",
        "group": "9b558fbc.438aa",
        "order": 5,
        "width": "3",
        "height": "3",
        "gtype": "gage",
        "title": "Coolant Temp",
        "label": "F",
        "format": "{{value}}",
        "min": 0,
        "max": "250",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "x": 1081,
        "y": 563,
        "wires": []
    },
    {
        "id": "913a6311.540cd",
        "type": "ui_gauge",
        "z": "2ce0055.8743efa",
        "name": "",
        "group": "9b558fbc.438aa",
        "order": 6,
        "width": "3",
        "height": "3",
        "gtype": "donut",
        "title": "Vacuum",
        "label": "",
        "format": "{{value}}",
        "min": "-20",
        "max": "0",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "x": 1071,
        "y": 643,
        "wires": []
    },
    {
        "id": "cee9fa09.98b6d8",
        "type": "json",
        "z": "2ce0055.8743efa",
        "name": "",
        "pretty": false,
        "x": 751,
        "y": 198,
        "wires": [
            [
                "3b9be5d8.84e04a"
            ]
        ]
    },
    {
        "id": "f2d748c5.d92da8",
        "type": "function",
        "z": "2ce0055.8743efa",
        "name": "Parse Date",
        "func": "var date = parseInt(msg.payload.time);\n\nmsg.payload = new Date(date* 1).toLocaleString([], { hour12: true}).slice(0, 19).replace('T', ' ');\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 730,
        "y": 780,
        "wires": [
            [
                "88bfc628.5727b8"
            ]
        ]
    },
    {
        "id": "88bfc628.5727b8",
        "type": "ui_text",
        "z": "2ce0055.8743efa",
        "group": "26a930d9.ff8c",
        "order": 1,
        "width": 0,
        "height": 0,
        "name": "Last Update",
        "label": "Updated",
        "format": "{{msg.payload}}",
        "layout": "row-spread",
        "x": 1070,
        "y": 780,
        "wires": []
    },
    {
        "id": "258b6f62.e82ab",
        "type": "function",
        "z": "2ce0055.8743efa",
        "name": "CtoF",
        "func": "var tempc = msg.payload;\n    tempf = tempc * 9/5 + 32;\n    tempf = Math.round(tempf * 10) / 10;\n    msg.payload = tempf;\n    return msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 910,
        "y": 560,
        "wires": [
            [
                "b0123228.4a063",
                "5ef6a21e.75ce4c"
            ]
        ]
    },
    {
        "id": "936bc33f.bcd27",
        "type": "change",
        "z": "2ce0055.8743efa",
        "name": "IntakeTemp",
        "rules": [
            {
                "t": "move",
                "p": "payload.kf",
                "pt": "msg",
                "to": "payload",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "topic",
                "pt": "msg",
                "to": "torque\\vehicle\\intake",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 730,
        "y": 840,
        "wires": [
            [
                "a6732e91.735a9"
            ]
        ]
    },
    {
        "id": "ee354102.4a8d8",
        "type": "ui_gauge",
        "z": "2ce0055.8743efa",
        "name": "",
        "group": "9b558fbc.438aa",
        "order": 4,
        "width": "3",
        "height": "3",
        "gtype": "gage",
        "title": "Intake Temp",
        "label": "F",
        "format": "{{value}}",
        "min": 0,
        "max": "250",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "",
        "seg2": "",
        "x": 1070,
        "y": 840,
        "wires": []
    },
    {
        "id": "a6732e91.735a9",
        "type": "function",
        "z": "2ce0055.8743efa",
        "name": "CtoF",
        "func": "var tempc = msg.payload;\n    tempf = tempc * 9/5 + 32;\n    tempf = Math.round(tempf * 10) / 10;\n    msg.payload = tempf;\n    return msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 899,
        "y": 837,
        "wires": [
            [
                "ee354102.4a8d8",
                "5ef6a21e.75ce4c"
            ]
        ]
    },
    {
        "id": "3b9be5d8.84e04a",
        "type": "change",
        "z": "2ce0055.8743efa",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "topic",
                "pt": "msg",
                "to": "torque\\raw",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 1034,
        "y": 202,
        "wires": [
            [
                "5ef6a21e.75ce4c"
            ]
        ]
    },
    {
        "id": "5ef6a21e.75ce4c",
        "type": "mqtt out",
        "z": "2ce0055.8743efa",
        "name": "",
        "topic": "",
        "qos": "0",
        "retain": "true",
        "broker": "fee1fac2.261a88",
        "x": 1292,
        "y": 193,
        "wires": []
    },
    {
        "id": "97ab65f2.1a0728",
        "type": "function",
        "z": "2ce0055.8743efa",
        "name": "copy to json",
        "func": "msg.payload.json = JSON.stringify(msg.payload);\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 770,
        "y": 100,
        "wires": [
            [
                "72347975.0e2688"
            ]
        ]
    },
    {
        "id": "72347975.0e2688",
        "type": "function",
        "z": "2ce0055.8743efa",
        "name": "Create query in topic",
        "func": "var out = \"INSERT INTO torque_json (timestamp,json)\"\nvar date = Number(msg.payload.time);\nout = out + \"VALUES ('\" + new Date(date* 1).toISOString().slice(0, 19).replace('T', ' ') + \"','\" \nout = out + String(msg.payload.json)  + \"');\"\n    \nmsg.topic=out;\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 960,
        "y": 100,
        "wires": [
            [
                "dba0040d.49d798"
            ]
        ]
    },
    {
        "id": "dba0040d.49d798",
        "type": "mysql",
        "z": "2ce0055.8743efa",
        "mydb": "4cd2c8.ee368d38",
        "name": "",
        "x": 1300,
        "y": 100,
        "wires": [
            []
        ]
    },
    {
        "id": "9b558fbc.438aa",
        "type": "ui_group",
        "z": "",
        "name": "Motor",
        "tab": "ac99e377.fdb83",
        "order": 1,
        "disp": true,
        "width": "9"
    },
    {
        "id": "ea9cdc42.4bbc8",
        "type": "ui_group",
        "z": "",
        "name": "Van",
        "tab": "ac99e377.fdb83",
        "order": 2,
        "disp": true,
        "width": "6"
    },
    {
        "id": "26a930d9.ff8c",
        "type": "ui_group",
        "z": "",
        "name": "Phone",
        "tab": "ac99e377.fdb83",
        "order": 3,
        "disp": true,
        "width": "6"
    },
    {
        "id": "fee1fac2.261a88",
        "type": "mqtt-broker",
        "z": "",
        "broker": "mqtt.YOUR.SERVER",
        "port": "1883",
        "clientid": "nodered",
        "usetls": false,
        "compatmode": true,
        "keepalive": "60",
        "cleansession": true,
        "willTopic": "",
        "willQos": "0",
        "willPayload": "",
        "birthTopic": "",
        "birthQos": "0",
        "birthPayload": ""
    },
    {
        "id": "4cd2c8.ee368d38",
        "type": "MySQLdatabase",
        "z": "",
        "host": "drobo5n.YOUR.SERVER",
        "port": "3306",
        "db": "openhab",
        "tz": "CST"
    },
    {
        "id": "ac99e377.fdb83",
        "type": "ui_tab",
        "z": "",
        "name": "Torque",
        "icon": "fa-car",
        "order": 2
    }
]
6 Likes

Did you get any futher with this project?
I´m actually thinking to add an ODB scanner (read) to my car as well.

My node red to mqtt implementation still works great when I use torque android app

1 Like

Looks great…
I´m not using Nodered. I was thinking perhaps using mqtt insted. But I have no idea how to get from the Tourque app to my mqtt server. (this is to prevent opening my server to the internet, ie portforward).
Also I would like it to “dump” the data, whenever the car is at home (connected to Wifi). I´m not sure if this is possible at all.

Tourque doesn’t speak MQTT. You need to have something that understands the http calls that Tourque makes and translates those to MQTT. David had implemented this go between using NodeRed. If you don’t want NodeRed, you need to create something else that does sander thing. And if you host that on your LAN you will need to NAT the port.

I know. I just hoped I could use mqtt insted, rather than to install yet another server.

I kinda hoped Torque could work on LAN only using wifi, and then dump the data when car is getting home.

torque does save log files in your phone. but you would have to setup some kind of mechanism on your phone to transfer the files when you are on your home network

Tasker can probably manage this.