Tessie API Integration

Hi I just wanted to share my quick and dirty Tessie integration since google assistant “Talk to Tessie” support is going away in June. When I have time I might make a full fledged component but for now api commands will have to do.

In secrets.yaml add 2 secrets 1 with your vin and the other with a token generated here: Loading

tessie_token: Bearer [token from tessie]
tesla_vin: [your vin]

In your configuration.yaml either add to or create a rest_command: section

rest_command:
  tessie_command: 
    url: "https://api.tessie.com/{{ states('input_text.tesla_vin') }}/command/{{ command }}"
    headers:
      authorization: !secret tessie_token
      accept: application/json

also create or add to a input_text: section

input_text:
  tesla_vin:
    name: Tesla VIN
    initial: !secret tesla_vin

You can then use the new rest_command.tessie_command service with the data: { command: "command_from_tessie_api" } eg. data: { command: "start_climate" }

You can use this service in automations or make a custom switch.

To make a switch first create a sensor using tessie’s state command (this creates three binary sensors for door locks, climate, and trunk) use binary_sensor for booleans and sensor for everything else:

binary_sensor:
  - name: Tesla Locked
    platform: rest
    device_class: lock
    resource_template: "https://api.tessie.com/{{ states('input_text.tesla_vin') }}/state?use_cache=true"
    headers:
      authorization: !secret tessie_token
      accept: application/json
    value_template: '{{ value_json.vehicle_state.locked == False }}'
  - name: Tesla Climate
    platform: rest
    device_class: running
    resource_template: "https://api.tessie.com/{{ states('input_text.tesla_vin') }}/state?use_cache=true"
    headers:
      authorization: !secret tessie_token
      accept: application/json
    value_template: '{{ value_json.climate_state.is_climate_on }}'
  - name: Tesla Trunk
    platform: rest
    device_class: garage_door
    resource_template: "https://api.tessie.com/{{ states('input_text.tesla_vin') }}/state?use_cache=true"
    headers:
      authorization: !secret tessie_token
      accept: application/json
    value_template: '{{ value_json.vehicle_state.rt > 0 }}'

Then create the switches:

switches:
  - platform: template
    switches:
      tesla_doors:
        friendly_name: Tesla Door Locks
        value_template: "{{ is_state('binary_sensor.tesla_locked', 'on') }}"
        turn_on:
          service: rest_command.tessie_command
          data:
            command: unlock
        turn_off:
          service: rest_command.tessie_command
          data:
            command: lock
        icon_template: >-
            {% if is_state('binary_sensor.tesla_locked', 'on') %}
              mdi:lock-open
            {% else %}
              mdi:lock
            {% endif %}
      tesla_climate:
        friendly_name: Tesla Climate
        value_template: "{{ is_state('binary_sensor.tesla_climate', 'on') }}"
        turn_on:
          service: rest_command.tessie_command
          data:
            command: start_climate
        turn_off:
          service: rest_command.tessie_command
          data:
            command: stop_climate
        icon_template: >-
            {% if is_state('binary_sensor.tesla_climate', 'on') %}
              mdi:fan
            {% else %}
              mdi:fan-off
            {% endif %}
      tesla_trunk:
        friendly_name: Tesla Trunk
        value_template: "{{ is_state('binary_sensor.tesla_trunk', 'on') }}"
        turn_on:
          service: rest_command.tessie_command
          data:
            command: activate_rear_trunk
        turn_off:
          service: rest_command.tessie_command
          data:
            command: activate_rear_trunk
        icon_template: >-
            {% if is_state('binary_sensor.tesla_trunk', 'on') %}
              mdi:garage-open
            {% else %}
              mdi:garage
            {% endif %}

Now that you have switches if you have google assistant integrated with home assistant you can control your tesla via home assistant by the switch name you just made eg “ok google turn on telsa climate”.

Note: Tessie takes about 30 seconds to actually execute a command so the switch may appear to “undo” the action if you toggle it in home assistant, then after tessie finishes it will take the correct state.

Here are some sensors for battery and range:

sensors:
  - name: Tesla Battery %
    platform: rest
    device_class: battery
    resource_template: "https://api.tessie.com/{{ states('input_text.tesla_vin') }}/state?use_cache=true"
    headers:
      authorization: !secret tessie_token
      accept: application/json
    value_template: '{{ value_json.charge_state.battery_level }}'
    unit_of_measurement: '%'
  - name: Tesla Ideal Range
    platform: rest
    device_class: distance
    resource_template: "https://api.tessie.com/{{ states('input_text.tesla_vin') }}/state?use_cache=true"
    headers:
      authorization: !secret tessie_token
      accept: application/json
    value_template: '{{ value_json.charge_state.battery_range }}'
    unit_of_measurement: mi
  - name: Tesla Real Range
    platform: rest
    device_class: distance
    resource_template: "https://api.tessie.com/{{ states('input_text.tesla_vin') }}/state?use_cache=true"
    headers:
      authorization: !secret tessie_token
      accept: application/json
    value_template: '{{ value_json.charge_state.est_battery_range }}'
    unit_of_measurement: mi

This is my glance card configuration for the dashboard:

          - entities:
              - entity: switch.tesla_doors
                name: Doors
                tap_action:
                  action: toggle
              - entity: switch.tesla_climate
                name: Climate
                tap_action:
                  action: toggle
              - entity: switch.tesla_trunk
                name: Trunk
                tap_action:
                  action: toggle
              - entity: sensor.tesla_battery
                name: Battery
              - entity: sensor.tesla_real_range
                name: Range
            show_header_toggle: false
            title: Tesla
            type: glance

I hope this helps someone!

4 Likes

Thanks. But does get you anything that the existing custom component doesn’t do? GitHub - alandtse/tesla: Tesla custom integration for Home Assistant. This requires a refresh token be generated by third-party apps to login.

I was unaware of this one, but I suppose by using Tessie’s api and not Tesla’s directly this leverages Tessie caching vehicle status and won’t unnecessarily wake up the car.

4 Likes

Hi Nick,

I’m really interested in your Tessie integration. I’ve tried the normal Tesla integration, but that one keeps draining the battery of the car. That’s why Tessie is such a great app as it gives you the option to check the car without waking the car up.

I’ve walked through every step you’ve written above, but run into a problem: This is my error I’m getting:

“kan service homeassistant/reload_all niet aanroepen. Cannot quick reload all YAML configurations because the configuration is not valid: Invalid config for [input_text]: value should be a string for dictionary value @ data[‘input_text’][‘tesla_vin’][‘initial’]. Got [’*******************’]. (See /config/configuration.yaml, line 113).”

Is this something you can help me with?

Kind regards

What does your config for input text look like? Also for the secret for vin the square brackets are just part of my placeholder in the example it should be like tesla_vin: 7SAY...

1 Like

Thanks. It was the square brackets which caused the problem.

So know I’ve just copied your glance card configuration, and I get the error “No type specified” (or something along those lines in Dutch) that’s weird. I’ve also copied all the indentations the right way… Any clue what is going on here?

In the meen time I’ve made my own glance cards, just via the visual card editor. But the entities aren’t receiving any values. For example: the Tesla Battery % value is Unknown. Am I missing something?

Thanks again for the great help!

I would look in the developer state tab and make sure you’re seeing data come through.
https://your-homeassistant-url/developer-tools/state If it’s not you should probably mess around with postman and the tessie api to troubleshoot why you’re not seeing data for your vin.

1 Like

I got it working… I left forgot to remove the square brackets at the api key secret.

It works! Great, one more question. The range is in miles, is there a way to get this converted to km? What do I need to change in the code to get that.

Thanks for the great work!

try changing unit_of_measurements from mi to km it may convert it. if it doesn’t leave it as km but multiply by 1.60934

1 Like

Thanks! It worked. Also had to put in the code for not showing the decimals, But now it looks great! Would be nice if Tessie made a real integration for HA. So we can see all the other entities as well.

For now, thanks again!

If you want to go nuts with all the datapoints you can use this:

- name: Tesla State
  platform: rest
  resource_template: "https://api.tessie.com/{{ states('input_text.tesla_vin') }}/state?use_cache=true"
  headers:
    authorization: !secret tessie_token
    accept: application/json
  value_template: '{{ value_json.state }}'
  json_attributes:
    - charge_state
    - climate_state
    - drive_state
    - vehicle_state

then use template sensors for things you’re interested in (I did this after I wrote the post).

create/edit template.yaml and include it in your main config template: !include template.yaml

sensor:
  - name: "Tesla Battery %"
    device_class: battery
    state: "{{ state_attr('sensor.tesla_state', 'charge_state')['battery_level'] }}"
    state_class: measurement
    unit_of_measurement: '%'
  - name: "Tesla Ideal Range"
    device_class: distance
    state: "{{ state_attr('sensor.tesla_state', 'charge_state')['battery_range'] }}"
    state_class: measurement
    unit_of_measurement: mi
  - name: "Tesla Real Range"
    device_class: distance
    state: "{{ state_attr('sensor.tesla_state', 'charge_state')['est_battery_range'] }}"
    state_class: measurement
    unit_of_measurement: mi
  - name: "Tesla Charge Amps"
    device_class: current
    state: "{{ state_attr('sensor.tesla_state', 'charge_state')['charge_amps'] }}"
    state_class: measurement
    attributes:
      max_request: "{{ state_attr('sensor.tesla_state', 'charge_state')['charge_current_request_max'] }}"
      request: "{{ state_attr('sensor.tesla_state', 'charge_state')['charge_current_request'] }}"
    unit_of_measurement: A
  - name: "Tesla Charge Volts"
    device_class: voltage
    state: "{{ state_attr('sensor.tesla_state', 'charge_state')['charger_voltage'] }}"
    state_class: measurement
    unit_of_measurement: V
  - name: "Tesla Charge Limit"
    device_class: battery
    state: "{{ state_attr('sensor.tesla_state', 'charge_state')['charge_limit_soc'] }}"
    state_class: measurement
    unit_of_measurement: "%"
  - name: "Tesla Charge Energy Added"
    device_class: energy
    state: "{{ state_attr('sensor.tesla_state', 'charge_state')['charge_energy_added'] }}"
    state_class: total_increasing
    unit_of_measurement: kWh
  - name: "Tesla Time to Full Charge"
    state: "{{ state_attr('sensor.tesla_state', 'charge_state')['minutes_to_full_charge'] }}"
    state_class: measurement
    icon: mdi:clock-end
    unit_of_measurement: "minutes"
  - name: "Tesla Heading"
    state: "{{ state_attr('sensor.tesla_state', 'drive_state')['heading'] }}"
    state_class: measurement
    unit_of_measurement: "°"
  - name: "Tesla Latitude"
    state: "{{ state_attr('sensor.tesla_state', 'drive_state')['latitude'] }}"
    state_class: measurement
    unit_of_measurement: "°"
  - name: "Tesla Longitude"
    state: "{{ state_attr('sensor.tesla_state', 'drive_state')['longitude'] }}"
    state_class: measurement
    unit_of_measurement: "°"
  - name: "Tesla Destination Latitude"
    state: "{{ state_attr('sensor.tesla_state', 'drive_state')['active_route_latitude'] }}"
    state_class: measurement
    unit_of_measurement: "°"
  - name: "Tesla Destination Longitude"
    state: "{{ state_attr('sensor.tesla_state', 'drive_state')['active_route_longitude'] }}"
    state_class: measurement
    unit_of_measurement: "°"
  - name: "Tesla Destination Traffic Delay"
    state: "{{ state_attr('sensor.tesla_state', 'drive_state')['active_route_traffic_minutes_delay'] }}"
    state_class: measurement
    unit_of_measurement: "minutes"
  - name: "Tesla Speed"
    device_class: speed
    state: "{{ state_attr('sensor.tesla_state', 'drive_state')['speed'] }}"
    state_class: measurement
    unit_of_measurement: "mph"
  - name: "Tesla Inside Temperature"
    device_class: temperature
    state: "{{ (state_attr('sensor.tesla_state', 'climate_state')['inside_temp'] | default(0) * 9/5 + 32) | round(0) }}"
    state_class: measurement
    unit_of_measurement: "°F"
  - name: "Tesla Outside Temperature"
    device_class: temperature
    state: "{{ (state_attr('sensor.tesla_state', 'climate_state')['outside_temp'] | default(0) * 9/5 + 32) | round(0) }}"
    state_class: measurement
    unit_of_measurement: "°F"
  - name: "Tesla Driver Climate Temperature"
    device_class: temperature
    state: "{{ (state_attr('sensor.tesla_state', 'climate_state')['driver_temp_setting'] | default(0) * 9/5 + 32) | round(0) }}"
    state_class: measurement
    unit_of_measurement: "°F"
  - name: "Tesla Passenger Climate Temperature"
    device_class: temperature
    state: "{{ (state_attr('sensor.tesla_state', 'climate_state')['passenger_temp_setting'] | default(0) * 9/5 + 32) | round(0) }}"
    state_class: measurement
    unit_of_measurement: "°F"
binary_sensor:
  - name: "Tesla Locked"
    device_class: lock
    state: "{{ state_attr('sensor.tesla_state', 'vehicle_state')['locked'] == False }}"
  - name: "Tesla Climate"
    device_class: running
    state: "{{ state_attr('sensor.tesla_state', 'climate_state')['is_climate_on'] }}"
  - name: "Tesla Trunk"
    device_class: garage_door
    state: "{{ state_attr('sensor.tesla_state', 'vehicle_state')['rt'] > 0 }}"
  - name: "Tesla Sentry"
    device_class: light
    state: "{{ state_attr('sensor.tesla_state', 'vehicle_state')['sentry_mode'] }}"
  - name: "Tesla FD Window"
    device_class: window
    state: "{{ state_attr('sensor.tesla_state', 'vehicle_state')['fd_window'] > 0 }}"
  - name: "Tesla FP Window"
    device_class: window
    state: "{{ state_attr('sensor.tesla_state', 'vehicle_state')['fp_window'] > 0 }}"
  - name: "Tesla RD Window"
    device_class: window
    state: "{{ state_attr('sensor.tesla_state', 'vehicle_state')['rd_window'] > 0 }}"
  - name: "Tesla RP Window"
    device_class: window
    state: "{{ state_attr('sensor.tesla_state', 'vehicle_state')['rp_window'] > 0 }}"
  - name: "Tesla Windows"
    device_class: window
    state: "{{ states('binary_sensor.tesla_fd_window') and states('binary_sensor.tesla_fp_window') and states('binary_sensor.tesla_rd_window') and states('binary_sensor.tesla_rp_window') }}"
2 Likes

FYI

Oh that’s really nice! I’m gonna play with that, great!

As you’ve already noticed, I’m a noob, so I’m running into errors all the time. Tried different things, but still run into problems. So I’ve added the first part of your last post. And now tried to add the different sensors. So in the code underneath you’ll see I’ve added the “Tesla Window” sensor (last part) But it keeps giving errors:
"Missing property “device_id”.
“Property device_class is not allowed.”
“Property_state is not allowed.”

Obviously It’s my fault, but I can not get it fixed. Even if I copy the whole code you’ve posted in the last post.

My questions are:

  • With the latest two additions of your code (in the last post) do I need to remove some of the older code?
  • Overall: What am I doing wrong here?

Thnx!

sensor:
  - platform: systemmonitor
    resources:
      - type: disk_use_percent
        arg: /config
      - type: memory_free
      - type: memory_use_percent
      - type: processor_use
      - type: processor_temperature
      - type: ipv4_address
        arg: /config
  - name: Tesla Battery %
    platform: rest
    device_class: battery
    resource_template: "https://api.tessie.com/{{ states('input_text.tesla_vin') }}/state?use_cache=true"
    headers:
      authorization: !secret tessie_token
      accept: application/json
    value_template: "{{ value_json.charge_state.battery_level }}"
    unit_of_measurement: "%"
  - name: Tesla Ideal Range
    platform: rest
    device_class: distance
    resource_template: "https://api.tessie.com/{{ states('input_text.tesla_vin') }}/state?use_cache=true"
    headers:
      authorization: !secret tessie_token
      accept: application/json
    value_template: "{{ (value_json.charge_state.battery_range*1.60934) | int(0)}}"
    unit_of_measurement: km
  - name: Tesla Real Range
    platform: rest
    device_class: distance
    resource_template: "https://api.tessie.com/{{ states('input_text.tesla_vin') }}/state?use_cache=true"
    headers:
      authorization: !secret tessie_token
      accept: application/json
    value_template: "{{ (value_json.charge_state.est_battery_range*1.60934)  | int(0) }}"
    unit_of_measurement: km
  - name: "Tesla Windows"
    device_class: window
    state: "{{ states('binary_sensor.tesla_fd_window') and states('binary_sensor.tesla_fp_window') and states('binary_sensor.tesla_rd_window') and states('binary_sensor.tesla_rp_window') }}"

Sorry I updated my last reply. that was my template.yaml not sensors. And yes they will conflict with the parent post config.

No problem, got it working! (as in no errors) But I’m only getting back 0 values. As in: inside temp: 0 outside temp: 0. Any clue what’s going wrong here?

What do the attributes on your tesla state sensor look like?

ah… somewhere in the process the “Tesla State” code got removed from the configuration.yaml. Now it’s working great! Thnx again!

If you want to change the range to km change:
value_template: ‘{{ value_json.charge_state.est_battery_range }}’
to:
value_template: “{{ (value_json.charge_state.est_battery_range|float*1.609)|round }}”

@nhorvath If I want to use the updated method you shared to pull in all of the datapoints where does this section go?