How I integrated a Xee connected car in Home Assistant

Víctor Lara
Nov 26, 2018 · 5 min read

I’m totally into domotize my home, I have a lot of stuff, all managed by the awesome Home Assistant platform.

This black friday, a big mechanical workshops company in my country, (Midas, in Spain) made a promotion: a device, which they install in my car, and they provide GPS tracking, a lot of information of your car, car updates notifications… only for 12€, (What a deal!!), so I decided to investigate more.

After some research, I find that the Device is a Xee connect, it’s a device made by a French company, called Xee, that mades this product. They have open api, developer accounts, a lot of online documentation, a full github repo, and even an account in Medium to share information!!

THAT’S SO COOL!

It’s really fun to go with people totally based on that philosophy, so, of course, I went to my closest workshop, get the device installed in a couple of hours. I installed the worskshop app, they show me how it works (pretty easy), and went home to investigate a little more.

I installed Xee app when I arrived home, check both apps, and try to integrate the device into my Home Assistant instance to get all the data, so I can make cool things!

Disclaimer: First of all, this is the walk that I took to get this, A LOT of things can be improved, and I love that you can share all your’s discovers, I had nothing of information of anybody who had accomplished this, and it’s a “one-day proyect”.

TALK IS CHEAP, SHOW ME THE CODE

Calm down, firstly we need a Xee Dev account, just get one from their page, create a new application, and use this configuration:

From now on, the Key is going to be refferer as client-id

Now, from a browser, call this api:

https://api.xee.com/v4/oauth/authorize?response_type=code&client_id={{client_id}}&scope=vehicles.read+vehicles.signals.read+vehicles.locations.read

A login screen will appear, log in with your USER xee account. The browser will redirect you to a page like this:

http://localhost/?code=ds3Imncv49RWFD4mfds30dmor5jr4RNMfLnFnuje093j&state=

Note that code. This is the authorization code generated by the authorization server. This code expires after 1 minute, and can be used only once.

Now, with postman, create a call with this parameters: (API)

POST https://api.xee.com/v4/oauth/token

Headers config

The autorization is a string with this format:

Basic base64(“application_key:application_secret”)

So, to obtain it, we go to any base64 converter, paste your “application_key:application_secret”, and you get it.

Body Config

Where the code is the one obtained previously in or browser.

Now we send it, and we get:

{
"access_token": "{{access_token}}",
"expires_in": 86400,
"refresh_token": "{{refresh_token}}",
"scope": "vehicles.locations.read vehicles.read vehicles.signals.read",
"token_type": "Bearer"
}

Ok, now we are totally logged in my xee acount, and with the access_token, we can call the API to get the ID of my car.

GET https://api.xee.com/v4/users/me/vehicles

In the token, use the access_token from before.

[
{
"id": "--------------------------------",
"userId": "--------------------------------",
"fleetId": null,
"name": "-----",
"brand": "",
"model": "",
"kType": null,
"licensePlate": "",
"firstEntryIntoService": null,
"device": {
"id": "-----",
"brand": "XEE",
"vehicleId": "THIS IS THE VEHICLE ID"
},
"createdAt": "2018-11-19T18:53:41.139724Z",
"updatedAt": "2018-11-20T07:22:18.449072Z"
}
]

So we got the vehicle id, now we are ready to call the endpoint that retrieve that car information, and consume it in HA.

Now let’s test the status endpoint, with the same configuration as previously:

{
"vehicleId": "EDITED",
"createdAt": "2018-11-19T18:53:41.987823041Z",
"updatedAt": "2018-11-26T19:39:45.753328972Z",
"signals": [
{
"name": "AirCondSwitchSts",
"value": 0,
"date": "2018-11-21T06:55:21.668Z"
},
{
"name": "BatteryVoltage",
"value": 12.55,
"date": "2018-11-26T19:37:39.154Z"
},
{
"name": "ComputedAccActivity",
"value": 0,
"date": "2018-11-21T06:55:44.138Z"
},
{
"name": "ComputedBatteryEngineStart",
"value": 14.193,
"date": "2018-11-21T06:52:12.34Z"
},
{
"name": "ComputedEngineState",
"value": 0,
"date": "2018-11-21T06:55:26.643Z"
},
{
"name": "ComputedFuelLevel",
"value": 42,
"date": "2018-11-20T07:28:19.304Z"
},
{
"name": "CoolantPressure",
"value": 6.4,
"date": "2018-11-21T06:55:17.582Z"
},
{
"name": "EngineSpeed",
"value": 823.68,
"date": "2018-11-21T06:55:23.729Z"
},
{
"name": "FrontLeftSeatBeltSts",
"value": 0,
"date": "2018-11-21T06:55:20.668Z"
},
{
"name": "FuelLevel",
"value": 0,
"date": "2018-11-21T06:55:23.53Z"
},
{
"name": "GpsSpeed",
"value": 0,
"date": "2018-11-21T06:55:34.942Z"
},
{
"name": "HazardSts",
"value": 0,
"date": "2018-11-20T07:26:33.127Z"
},
{
"name": "HeadLightSts",
"value": 0,
"date": "2018-11-20T07:26:33.128Z"
},
{
"name": "HighBeamSts",
"value": 0,
"date": "2018-11-21T06:55:39.376Z"
},
{
"name": "HighSpeedWiperSts",
"value": 0,
"date": "2018-11-20T07:26:33.104Z"
},
{
"name": "IgnitionSts",
"value": 0,
"date": "2018-11-21T06:55:21.617Z"
},
{
"name": "IntermittentWiperSts",
"value": 0,
"date": "2018-11-21T06:52:18.063Z"
},
{
"name": "LeftIndicatorSts",
"value": 0,
"date": "2018-11-20T17:18:39.053Z"
},
{
"name": "LockSts",
"value": 1,
"date": "2018-11-21T06:55:41.36Z"
},
{
"name": "LowBeamSts",
"value": 0,
"date": "2018-11-21T06:55:39.875Z"
},
{
"name": "LowSpeedWiperSts",
"value": 0,
"date": "2018-11-20T16:40:49.794Z"
},
{
"name": "ManualWiperSts",
"value": 0,
"date": "2018-11-20T07:26:33.104Z"
},
{
"name": "Odometer",
"value": 103999,
"date": "2018-11-20T17:17:39.766Z"
},
{
"name": "OutdoorTemp",
"value": 9.5,
"date": "2018-11-21T06:53:00.446Z"
},
{
"name": "RearFogLightSts",
"value": 0,
"date": "2018-11-20T07:26:33.128Z"
},
{
"name": "RearWiperSts",
"value": 0,
"date": "2018-11-20T07:26:33.104Z"
},
{
"name": "RightIndicatorSts",
"value": 0,
"date": "2018-11-20T17:17:46.944Z"
},
{
"name": "VehiculeSpeed",
"value": 0,
"date": "2018-11-21T06:55:16.357Z"
}
],
"location": {
"altitude": EDITED,
"latitude": EDITED,
"longitude": EDITED,
"heading": EDITED,
"date": "2018-11-21T06:55:42.022Z",
"nbSat": EDITED,
"hacc": 0
},
"accelerometer": {
"x": -EDITED,
"y": -EDITED,
"z": -EDITED,
"date": "2018-11-19T18:58:35.517Z"
},
"gyroscope": null,
"loan": null
}

THIS IS AWESOME!! We really have A LOT of data of our car! It’s what I want in Home Assistant!!

Let’s move there!

First of all, create a restful sensor

With the json_attributes, we are going to take the three info items that we are going to read.

Now create the sensors:

Pretty self-explanatory.

Now, lets make a group in the interface to show them:

YAY!!!!

Also, as I’m kind of a “day-dream” person, sometimes I don’t remember where I park, so I think a Google Maps card with my parking location whould be awesome!!

(Notice at the end of the URL that you need a Google Maps API Key)

And here it is!

SO IT’S DONE!

No, sorry.

Do you remember the token that we get before?

It expires every 48h

So we need to refresh it, my quick & dirty solution is to make a cron in my Home Assistant machine:

Check that we need the Authorization and the refresh-token retrieved when we also get the token itself

And that’s all!

Now you can do whatever you want! Use those sensors and create some magic!

I hope this can help people to create new things! If you get better ways to do the things (like automate the refresh) or improve this, please comment!

HAPPY CODING!

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade