Open mcnutter1 opened 5 years ago
I tried unlock but it did not work. I may just not have found the right syntax but could not get it to work. Location I think requires a specific 'plan' from OnStar that is not the basic once included with the car
If you GET /api/v1/account/vehicles/YOURVIN/commands
, you'll get back a response that partially describes the available commands (converted to YAML to slightly increase readability):
- name: cancelAlert
description: Cancel a vehicle alert (honk horns/flash lights).
url: https://api.gm.com/api/v1/account/vehicles/YOURVIN/commands/cancelAlert
isPrivSessionRequired: true
- name: getHotspotInfo
description: Retrives the WiFi Hotspot info
url: https://api.gm.com/api/v1/account/vehicles/YOURVIN/hotspot/commands/getInfo
isPrivSessionRequired: false
- name: lockDoor
description: Locks the doors.
url: https://api.gm.com/api/v1/account/vehicles/YOURVIN/commands/lockDoor
isPrivSessionRequired: true
- name: unlockDoor
description: Unlocks the doors.
url: https://api.gm.com/api/v1/account/vehicles/YOURVIN/commands/unlockDoor
isPrivSessionRequired: true
- name: alert
description: Triggers a vehicle alert (honk horns/flash lights).
url: https://api.gm.com/api/v1/account/vehicles/YOURVIN/commands/alert
isPrivSessionRequired: true
- name: start
description: Remotely starts the vehicle.
url: https://api.gm.com/api/v1/account/vehicles/YOURVIN/commands/start
isPrivSessionRequired: true
- name: cancelStart
description: Cancels previous remote start command.
url: https://api.gm.com/api/v1/account/vehicles/YOURVIN/commands/cancelStart
isPrivSessionRequired: true
- name: diagnostics
description: Retrieves diagnostic vehicle data.
url: https://api.gm.com/api/v1/account/vehicles/YOURVIN/commands/diagnostics
isPrivSessionRequired: false
commandData:
supportedDiagnostics:
supportedDiagnostic:
- ENGINE COOLANT TEMP
- ENGINE RPM
- LAST TRIP FUEL ECONOMY
- TIRE PRESSURE
- AMBIENT AIR TEMPERATURE
- LAST TRIP DISTANCE
- INTERM VOLT BATT VOLT
- OIL LIFE
- LIFETIME FUEL ECON
- FUEL TANK INFO
- HOTSPOT CONFIG
- LIFETIME FUEL USED
- ODOMETER
- VEHICLE RANGE
- HOTSPOT STATUS
- name: sendTBTRoute
description: Calculates route and initiate download of turn by turn directions to
the vehicle.
url: https://api.gm.com/api/v1/account/vehicles/YOURVIN/commands/sendTBTRoute
isPrivSessionRequired: false
- name: location
description: Retrieves the vehicle's current location.
url: https://api.gm.com/api/v1/account/vehicles/YOURVIN/commands/location
isPrivSessionRequired: true
- name: sendNavDestination
description: Calculate route and send it to the vehicle's nav unit.
url: https://api.gm.com/api/v1/account/vehicles/YOURVIN/navUnit/commands/sendNavDestination
isPrivSessionRequired: false
- name: connect
description: Initiates a connection to the vehicle
url: https://api.gm.com/api/v1/account/vehicles/YOURVIN/commands/connect
isPrivSessionRequired: false
- name: getHotspotStatus
description: Retrive WiFi status
url: https://api.gm.com/api/v1/account/vehicles/YOURVIN/hotspot/commands/getStatus
isPrivSessionRequired: false
- name: setHotspotInfo
description: update the WiFi SSID and passPhrase
url: https://api.gm.com/api/v1/account/vehicles/YOURVIN/hotspot/commands/setInfo
isPrivSessionRequired: true
- name: disableHotspot
description: Disable WiFi Hotspot
url: https://api.gm.com/api/v1/account/vehicles/YOURVIN/hotspot/commands/disable
isPrivSessionRequired: true
- name: enableHotspot
description: Enable WiFi Hotspot
url: https://api.gm.com/api/v1/account/vehicles/YOURVIN/hotspot/commands/enable
isPrivSessionRequired: true
This reveals that controlling the doors uses the commands lockDoor
and unlockDoor
, rather than the arguably more intuitive lock
and unlock
that I also assumed would be the commands. isPrivSessionRequired
indicates whether or not you're expected to call /oauth/token/upgrade
.
However, you'll notice that while unlocking works with just {}
as the request body, requests to lock the doors will be rejected with {"error":{"code":"ONS-105","description":"Invalid Input."}}
. This took me a while to figure out, but after decompiling the Android app in a (failed) attempt to locate the API keys without needing to recompile the app, I found the classes involved with making these requests, and noticed that the lockDoor command expects a delay
parameter, wrapped with lockDoorRequest
. I'm not sure when you'd ever want to send a request to lock the doors at any time other than "right now", so you can probably just stick with a hardcoded {"lockDoorRequest":{"delay":0}}
.
There's also some additional interesting endpoints that aren't under /commands, and I noticed someone else has already uploaded the decompiled RemoteAPIService
interface to a public Gist. That class lists all the endpoints that are available to you along with which HTTP method to use, but doesn't include what POST data they expect. I haven't dug into them all, but you can do so yourself if needed by running the myChevrolet APK through dex2jar and the passing the result to a tool like jd-gui. I'm new to both of those utilities, so you're probably better off reading their documentation yourself rather than me trying to explain them and probably getting things wrong.
I was also particularly interested in pulling diagnostic information, which is also a bit complicated. This endpoint also expects instructions in the request body, and you actually need to list each data point you want to receive. The list is included in the /commands
response above, but you may want to make that request yourself in case your vehicle responds with a different list of supported diagnostic items. Also the format shown in the response isn't the same as what expects you to send it -- digging into the decompiled Android source once again, I came up with this:
{
"diagnosticsRequest": {
"diagnosticItem": [
"ENGINE COOLANT TEMP",
"ENGINE RPM",
"LAST TRIP FUEL ECONOMY",
"TIRE PRESSURE",
"AMBIENT AIR TEMPERATURE",
"LAST TRIP DISTANCE",
"INTERM VOLT BATT VOLT",
"OIL LIFE",
"LIFETIME FUEL ECON",
"FUEL TANK INFO",
"LIFETIME FUEL USED",
"ODOMETER",
"VEHICLE RANGE"
]
}
}
You can change the items in the list as you see fit; the example above requests everything except WiFi hotspot information, which I know I don't care about tracking.
Once you've connected to the vehicle and then sent that request, you should get a 202 Accepted response code, and a JSON object that includes a commandResponse
object with a url
property. You'll want to GET that URL (passing the same Authorization header you've been using with every other request) and check for "status": "success"
in the response object that it returns. You can poll every couple seconds until that's the case, at which point it will also include a body
with all the diagnostic information data you requested.
Do note that there is a limit to how many consecutive remote requests you're allowed to make. This count does NOT appear to reset with time, and you must instead get into your vehicle and start it yourself. As soon as you do this, your API requests will start working again. When polling at a 30-minute interval, I've been seeing requests start to fail after about 16 requests with {"error":{"code":"ONS-216","description":"Unable to establish packet session to the vehicle"}}
. I've switched to only polling once an hour, but that was less than 16 hours ago, so we'll see if I get cut off after the same number of requests.
I've just gotten started with this a couple days ago, so I'm by no means an expert, but hopefully the time I spent banging my head against the wall can save a couple other folks from having to go through the same thing.
I've mapped out a bunch of the API requests and bundled them into a NodeJS library: OnStarJS. Also have a homebridge plugin that uses it for Siri support: homebridge-onstar.
All of this was thanks to this repo <3
SNEEZE
"commands": {
"command": [
{
"description": "Enrolls a vehicle in telemetry.",
"name": "telemetryOptIn",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/commands/telemetryOptIn"
},
{
"description": "Unenrolls a vehicle from telemetry..",
"name": "telemetryOptOut",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/commands/telemetryOptOut"
},
{
"description": "Locks the doors.",
"name": "lockDoor",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/commands/lockDoor"
},
{
"description": "Unlocks the doors.",
"name": "unlockDoor",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/commands/unlockDoor"
},
{
"description": "Triggers a vehicle alert (honk horns/flash lights).",
"name": "alert",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/commands/alert"
},
{
"description": "Cancels vehicle alert (honk horns/flash lights) in progress.",
"name": "cancelAlert",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/commands/cancelAlert"
},
{
"description": "Remotely starts the vehicle.",
"name": "start",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/commands/start"
},
{
"description": "Cancels previous remote start command.",
"name": "cancelStart",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/commands/cancelStart"
},
{
"commandData": {
"supportedDiagnostics": {
"supportedDiagnostic": [
"LIFETIME FUEL USED",
"LIFETIME FUEL ECON",
"LAST TRIP DISTANCE",
"ODOMETER",
"LAST TRIP FUEL ECONOMY",
"TIRE PRESSURE",
"OIL LIFE",
"FUEL TANK INFO",
"VEHICLE RANGE",
"EV BATTERY LEVEL",
"GET CHARGE MODE",
"LIFETIME EV ODOMETER",
"GET COMMUTE SCHEDULE"
]
}
},
"description": "Retrieves diagnostic vehicle data.",
"name": "diagnostics",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/commands/diagnostics"
},
{
"description": "Calculates route and initiate download of turn by turn directions to the vehicle.",
"name": "sendTBTRoute",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/commands/sendTBTRoute"
},
{
"description": "Retrieves the vehicle's current location.",
"name": "location",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/commands/location"
},
{
"description": "Calculate route and send it to the vehicle's nav unit.",
"name": "sendNavDestination",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/commands/sendNavDestination"
},
{
"description": "get charging profile.",
"name": "getChargingProfile",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/commands/getChargingProfile"
},
{
"description": "set charging profile.",
"name": "setChargingProfile",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/commands/setChargingProfile"
},
{
"description": "charge Override",
"name": "chargeOverride",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/commands/chargeOverride"
},
{
"description": "get commute schedule",
"name": "getCommuteSchedule",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/commands/getCommuteSchedule"
},
{
"description": "set commute schedule",
"name": "setCommuteSchedule",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/commands/setCommuteSchedule"
},
{
"description": "Disables the hotspot on your vehicle",
"name": "disableHotspot",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/hotspot/commands/disable"
},
{
"description": "Enables the hotspot on your vehicle",
"name": "enableHotspot",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/hotspot/commands/enable"
},
{
"description": "Fetches hotspot information on your vehicle",
"name": "getHotspotInfo",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/hotspot/commands/getHotspotInfo"
},
{
"description": "Fetches hotspot status information on your vehicle",
"name": "getHotspotStatus",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/hotspot/commands/getHotspotStatus"
},
{
"description": "Set hotspot information on your vehicle",
"name": "setHotspotInfo",
"url": "https://api.gm.com/api/v1/account/vehicles/VIN/hotspot/commands/setHotspotInfo"
}
]
},
has anyone mapped the other API functions? Lock/Unlock, Vehicle Status, Location?