wubbl0rz / FiatChamp

FIAT (uconnect) Home Assistant Addon 🚗
https://github.com/wubbl0rz/FiatChamp
MIT License
91 stars 17 forks source link

Commands for Jeep #27

Open cgraf opened 1 year ago

cgraf commented 1 year ago

Hello again!

I can't stay away. I guess I'd like to working on Jeep commands. It is clear that many/most for Fiat don't work for Jeep. I've been looking at a bit of output and debug, and am starting to understand a few things. It looks like you have all of the interesting Fiat commands documented in FiatCommand.cs. These correspond to the surfaced HA controls.

DEEPREFRESH = DeepRefresh VF = Location update
HBLF = Battery refresh ? CNOW = ChargeNow ROPRECOND = HVAC On? ROPRECOND_OFF = HVAC Off? ROTRUNKUNLOCK = Trunk unlock ROTRUNKLOCK = Trunk lock RDU = Door unlock RDL = Door lock

I don't see any of your Fiat "services" output anywhere, but some of the commands you list here seem to correspond to the Jeep services listed in the vehicle output.

        {
          "vehicleCapable": true,
          "service": "VF",
          "serviceEnabled": true
        },
...
        {
          "vehicleCapable": true,
          "service": "RDU",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "RDL",
          "serviceEnabled": true
        },
...
        {
          "vehicleCapable": true,
          "service": "HBLF",
          "serviceEnabled": true
        },
...
        {
          "vehicleCapable": true,
          "service": "CNOW",
          "serviceEnabled": true
        },

This would indicate that all of theses are available commands for the Jeep. HVAC and Trunk controls are not listed anywhere in the vehicle services.

Is it possible to suppress surfacing those controls in HA if the service does not exist for the vehicle?

For the services that are listed as "true" for Jeep, I'm getting some errors. For RDU (remote door unlock) for example:

[15:47:23 INF] SEND COMMAND RDU: 
[15:47:26 ERR] Command: RDU ERROR. Maybe wrong pin?
[15:47:26 DBG] Flurl.Http.FlurlHttpException: Call failed with status code 403 (Forbidden): POST https://mfa.fcl-01.fcagcv.com/v1/accounts/<removed>/ignite/pin/authenticate
   at Flurl.Http.FlurlRequest.HandleExceptionAsync(FlurlCall call, Exception ex, CancellationToken token)
   at Flurl.Http.FlurlRequest.SendAsync(HttpMethod verb, HttpContent content, CancellationToken cancellationToken, HttpCompletionOption completionOption)
   at Flurl.Http.FlurlRequest.SendAsync(HttpMethod verb, HttpContent content, CancellationToken cancellationToken, HttpCompletionOption completionOption)
   at Flurl.Http.ResponseExtensions.ReceiveJson[T](Task`1 response)
   at FiatChamp.FiatClient.SendCommand(String vin, String command, String pin, String action) in /home/runner/work/FiatChamp/FiatChamp/FiatChampAddon/FiatClient/FiatClient.cs:line 529
   at Program.<>c__DisplayClass0_0.<<<Main>$>g__TrySendCommand|1>d.MoveNext() in /home/runner/work/FiatChamp/FiatChamp/FiatChampAddon/FiatClient/Program.cs:line 259

Same error for RDL (remote door lock).

Same error for DEEPREFRESH. It appears that RefreshBatteryStatus button simply pushes DeepRefresh under the hood. Seems superfluous to have two buttons surfaced in HA that are called different things and do the same things. I know your docs say DeepRefresh is the same as RefreshBatteryStatus, but actually it seems to be the reverse, and you might as well remove one if they do the same thing. I'm kind of curious what happens if you send HBLF for battery refresh instead of DEEPREFRESH.

Error is a little different for VF (location update):

[15:55:20 INF] SEND COMMAND VF: 
[15:55:21 ERR] Command: VF ERROR. Maybe wrong pin?
[15:55:21 DBG] Flurl.Http.FlurlHttpException: Call failed with status code 403 (Forbidden): POST https://mfa.fcl-01.fcagcv.com/v1/accounts/<removed>/ignite/pin/authenticate
   at Flurl.Http.FlurlRequest.HandleExceptionAsync(FlurlCall call, Exception ex, CancellationToken token)
   at Flurl.Http.FlurlRequest.SendAsync(HttpMethod verb, HttpContent content, CancellationToken cancellationToken, HttpCompletionOption completionOption)
   at Flurl.Http.FlurlRequest.SendAsync(HttpMethod verb, HttpContent content, CancellationToken cancellationToken, HttpCompletionOption completionOption)
   at Flurl.Http.ResponseExtensions.ReceiveJson[T](Task`1 response)
   at FiatChamp.FiatClient.SendCommand(String vin, String command, String pin, String action) in /home/runner/work/FiatChamp/FiatChamp/FiatChampAddon/FiatClient/FiatClient.cs:line 552
   at Program.<>c__DisplayClass0_0.<<<Main>$>g__TrySendCommand|1>d.MoveNext() in /home/runner/work/FiatChamp/FiatChamp/FiatChampAddon/FiatClient/Program.cs:line 271

I do have the PIN set, and dangerous commands enabled, so like you said, they may be a missing or incorrect API key, since it is producing 403.

I can tell you that the services that are available in the Jeep iPhone app are:

Unlock Doors = RDU Lock Doors = RDL Start Engine = REON (remote engine on)? Cancel Engine = REOFF (remote engine off)? Honk Horn = VHS (vehicle horn sound maybe)?

I don't have access to the Android app, so I probably won't be able to capture the real commands for these. I gotta say that I'm intrigued by the 63 services that are enumerated as being true for this vehicle. Maybe some are just standard informational stuff that is already being returned. Definitely needs some documentation. Hard keeping Pandora's box closed on these...

cgraf commented 1 year ago

Ah I see. You don't yet know the PIN URL and API key for non-Fiat.


        _authApiKey = "JWRYW7IYhW9v0RqDghQSx4UcRYRILNmc8zAuh5ys"; // UNKNOWN
        _authUrl = "https://mfa.fcl-01.fcagcv.com"; // UNKNOWN

You could probably try https://mfa.fcl-02.fcagcv.com, since simple incrementation worked everywhere else, but that won't help you without the API key. Hence the need to sniff the submission from the Android app when the service is called. Unfortunately can't help you there.

cgraf commented 1 year ago

I did get a sniffer and SSL decrypter going on iPhone, and I see connections to mfa.fcl-02.fcagcv.com, but no x-api-key for mfa and no pin parameter traversing the stream. Maybe I am looking in the wrong place, or they are doing commands a different way for Jeep.

wubbl0rz commented 1 year ago

you can use the uconnect website and browser dev tools its easier. later i will post you a screenshot with the request you need to look for.

cgraf commented 1 year ago

I think I know the request from the code.

https://mfa.fcl-02.fcagcv.com/v1/accounts/<userid>/ignite/pin/authenticate

and you want x-api-key there. But Jeep Uconnect doesn't expose services on the browser site. They are only available in the app, unless I'm missing something.

cgraf commented 1 year ago

Hmm. I can change the PIN on the browser site. Maybe it authenticates the PIN there. Let me get a sniffer set up and I will look there.

cgraf commented 1 year ago

Ah yep. No sniffer required. Just dev tools.

_authURL: https://mfa.fcl-02.fcagcv.com
_authApiKey: fNQO6NjR1N6W0E5A6sTzR3YY4JGbuPv48Nj9aZci

I'll submit a PR

wubbl0rz commented 1 year ago

nice i have a look 😄

wubbl0rz commented 1 year ago

3.0.7 is live and has your fix included :clap:

cgraf commented 1 year ago

Awesome! I have not deep testing yet, but a couple of the surfaced functions (lock/unlock, refresh) do appear to work, and no errors in the debug logs. I haven't looked through the HA portion of the code to see if it is dynamically determining service api capabilities reported by the vehicle as I mentioned at the top of #27. I suspect the controls for the commands are hard-coded for EU Fiat right now, so things like engine start and stop are not surfaced in HA for Jeep. Would you rather conditionally assign a static set of controls per vehicle/region or dynamically assign them based on reported capability from the API? I imagine it is best to start with the static assignment of those services that are known from the official app. At some point I will write my own client, so I can test some of those reported commands.

cgraf commented 1 year ago

Did a bit of testing.

The current "Blink" is horn and hazard and hazard flashers, basically like setting off the car alarm. Door lock works Door unlock works

Can't test engine start/stop since it is not surfaced and not sure if we know the commands. I suspect REON and REOFF.

wubbl0rz commented 1 year ago

commands are not fiat EU specific. its just copy & pasted from a json file in the android app :grin: but i think not all work on all cars. if they have a car capability response in their api this would be the best case. i think hardcoding for different vendors and cars is unmanageable. maybe i can finde something :smile:

cgraf commented 1 year ago

Cool. Isn't it this list, returned from one of the early commands, the list of service capabilities of the specific vehicle, along with what the API command for that service would be?


 "services": [
        {
          "vehicleCapable": true,
          "service": "SVLAAPP",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "SVLA",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": false,
          "service": "ROC",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": true,
          "service": "RDU",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "RDL",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "HUC",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "AOTAC",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "BCALL",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "SOS",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "ASSIST",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "ECALL",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "HBLF",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "ASOS",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "DTC",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "NAV_OB_FUEL_FINDER",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "NAV_OB_PARKING_FINDER",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "NAV_OB_ROUTE_DRM",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "NAV_OB_SEARCH",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "NAV_OB_SPEED_CAMERA",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "NAV_OB_TRAFFIC",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "NAV_OB_WEATHER",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "PARENT",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "REOFF",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "REON",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "SDV",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": false,
          "service": "SQDF",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": true,
          "service": "TA",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "VF",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "VHSG",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "VRC",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "WIFIHOTSPOT",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": false,
          "service": "FTD",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": true,
          "service": "IVA",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "IVM",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": false,
          "service": "PHEV",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": true,
          "service": "ALEXAVA",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "WIFIP",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "VHS",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "CNOW",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "CSL",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": true,
          "service": "CP",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": true,
          "service": "EVNOT",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "ELECPAGES",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "ORP",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": false,
          "service": "GSKILLL",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": true,
          "service": "LASTMILE",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "AOTACI",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "ROAD",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "CARE",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "ROCRANKINHIBITON",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "ROCRANKINHIBITOFF",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "TA_SUP",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": false,
          "service": "DRIVEMODES",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": false,
          "service": "RACEOPTIONS",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": true,
          "service": "NAV_OB_MOTA_CELL",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "NAV_OB_MOTA_WIFI",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "NAV_OB_MOTA_WIFI_CELL",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "BRAND",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "DUMMY",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "DEEPREFRESH",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": false,
          "service": "FRONTSEAT",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": true,
          "service": "MACMEDIAAPP",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": false,
          "service": "L2DATALOG",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": false,
          "service": "L2MAPSGEO",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": false,
          "service": "L2GPSCORRECTION",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": true,
          "service": "TUTORIALS",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "ORPPLUS",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "ADA_TBM",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "NAV_TOMTOM",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "ROCLRPERSDATA",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "ROC2",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "ADA_UBI",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": true,
          "service": "CPCHRG2",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": false,
          "service": "CPA",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": true,
          "service": "CSEV",
          "serviceEnabled": true
        },
        {
          "vehicleCapable": false,
          "service": "TRAILERTP",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": false,
          "service": "KNGLNKOUT",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": false,
          "service": "DUMMY_EVAS",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": false,
          "service": "DUMMY_ENHDCAM",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": false,
          "service": "DUMMY_TECHFEE",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": false,
          "service": "DUMMY_WIRECAM",
          "serviceEnabled": false
        },
        {
          "vehicleCapable": false,
          "service": "DUMMY_TRAILERTP",
          "serviceEnabled": false
        }
      ],
wubbl0rz commented 1 year ago

yes looks like it. some as "ROTRUNKLOCK" are not listed. so i think everything not listed or set to "false" is not supported. is this in the response from vehicleDetails request ? v2/accountsUSERID/vehicles/VEHICLE_VIN/status ?

cgraf commented 1 year ago

Not sure. I thought I had pulled it from Postman, but it must've been from your debug. I only have Postman working up until the Cognito part. I'm going to eventually write my own standalone client, but right now my main hobby time is working on a WLED project. ;)

pageb018 commented 1 year ago

Wondering if you had any luck in getting remote start/stop to work?