michaelwoods / onstar2mqtt

OnStarJS wrapper for MQTT
MIT License
107 stars 40 forks source link

Request: Add support for specific diagnostic values in Commands #282

Open tylerpieper opened 1 year ago

tylerpieper commented 1 year ago

It appears that the command "diagnostics" returns a fixed set of items (ODOMETER, TIRE_PRESSURE, AMBIENT_AIR_TEMPERATURE, and LAST_TRIP_DISTANCE):

    async diagnostics({diagnosticItem = [
        Commands.CONSTANTS.DIAGNOSTICS.ODOMETER,
        Commands.CONSTANTS.DIAGNOSTICS.TIRE_PRESSURE,
        Commands.CONSTANTS.DIAGNOSTICS.AMBIENT_AIR_TEMPERATURE,
        Commands.CONSTANTS.DIAGNOSTICS.LAST_TRIP_DISTANCE
    ]}) {
        return this.onstar.diagnostics({diagnosticItem});
    }

It would be great if we could specify an array of diagnostic values to retrieve (like EV_BATTERY_LEVEL and EV_CHARGE_STATE). Or, add another command (maybe "refresh"?) to run the main periodic update on demand.

My use case: I would like to set the "onstar_refresh" environment variable to a pretty high number (like an hour) and use automations in Home Assistant to request updates at faster intervals when it makes sense to. This way, I can go a longer period before OnStar decides to stop responding (since it seems to stop after 5 or so requests when the car is off) and update much more frequently when the car is in use.

For those playing along at home, I'm triggering an automation with the following triggers:

  1. Template {{'car:mac:address' in state_attr('sensor.my_phone_bluetooth_connection', 'connected_paired_devices') }} -- this will return true if the car is one of the bluetooth devices connected to my phone
  2. Same as above but with my wife's phone
  3. When the Odometer (reported by onstar2mqtt) changes

The actions are:

  1. Run the "locate car script"
  2. Wait 5m
  3. Request diagnostics (I was hoping this would refresh all values but it did not)
tylerpieper commented 1 year ago

I've been playing with this a little more, and I've been able to request additional data with the following MQTT payload:

{"command": "diagnostics", "options": { "diagnosticItem" : ["EV BATTERY LEVEL", "VEHICLE RANGE", "AMBIENT AIR TEMPERATURE" , "CHARGER POWER LEVEL" , "ENERGY EFFICIENCY" , "EV CHARGE STATE" , "EV ESTIMATED CHARGE END", "EV PLUG STATE" , "EV PLUG VOLTAGE" , "EV SCHEDULED CHARGE START" , "HYBRID BATTERY MINIMUM TEMPERATURE" , "INTERM VOLT BATT VOLT" , "LAST TRIP DISTANCE" , "LAST TRIP FUEL ECONOMY" , "ODOMETER" , "TIRE PRESSURE"] } }

But this does not seem to be publishing the new values? Maybe all that's needed is the bit from "run" that parses the diagnostic response and published the data, inside an IF statement looking for responseData.commandResponse.type = diagnostics

Here's an example request and response:

Request: {"command": "diagnostics", "options": { "diagnosticItem" : ["EV BATTERY LEVEL", "VEHICLE RANGE"] } }

Response:

{
  "responseData": {
    "commandResponse": {
      "body": {
        "diagnosticResponse": [
          {
            "diagnosticElement": [
              {
                "message": "na",
                "name": "EV BATTERY LEVEL",
                "status": "NA",
                "unit": "%",
                "value": "75.6"
              }
            ],
            "name": "EV BATTERY LEVEL"
          },
          {
            "diagnosticElement": [
              {
                "message": "na",
                "name": "EV MAX RANGE",
                "status": "NA"
              },
              {
                "message": "na",
                "name": "EV MIN RANGE",
                "status": "NA"
              },
              {
                "message": "na",
                "name": "EV RANGE",
                "status": "NA",
                "unit": "KM",
                "value": "387.0"
              },
              {
                "message": "na",
                "name": "GAS RANGE",
                "status": "NA"
              },
              {
                "message": "na",
                "name": "TOTAL RANGE",
                "status": "NA"
              }
            ],
            "name": "VEHICLE RANGE"
          }
        ]
      },
      "completionTime": "2023-06-06T17:41:04.342Z",
      "requestTime": "2023-06-06T17:41:01.162Z",
      "status": "success",
      "type": "diagnostics",
      "url": "https://api.gm.com/api/v1/account/vehicles/VIN_REDACTED/requests/41397970367"
    }
  }
}

I'd be happy to write up the documentation on how to use this if the publishing of response data is implemented.

michaelwoods commented 1 year ago

I believe the publish support would just need to be added to this section similar to location: https://github.com/michaelwoods/onstar2mqtt/blob/main/src/index.js#L92-L103

The command system could certainly use a refactor.

garyd9 commented 11 months ago

I'll add my +1 to this request. (Honestly, I wish I had time to learn node.js just so I could contribute a patch for this. I don't think it'd be difficult. There's already code there for parsing a 'diagnostics' result...

garyd9 commented 11 months ago

PR for this here: https://github.com/michaelwoods/onstar2mqtt/pull/338

tylerpieper commented 11 months ago

Thanks @garyd9 !