Intro

I recently got an Electric Vehicle (EV) and of course I want to get it integrated in Home Assistant :) Luckily, I found a HACS integration for MercedesME that provides me with a lot of data about my car and allows me to send some commands to it as well.

In a previous blog post I discussed how I used this custom integration to manage my battery charge target. In this blog post, I’ll explain how I set up my dashboard to control the car’s preconditioning.

Triggering the preconditioning of the car will have it ventilate the car’s interior air for a few minutes, after which it will start the airconditioning (AC) to heat/cool the car to my desired temp. It will even start the heated seat so you can enter the car without freezing your behind in winter ;)

Installing the MercedesME integration

Installation of this integration is easy as it comes as a HACS integration.

You open HACS, go to the Integrations section and install the “MercedesME 2020” integration. After a reboot of HA, the integration can be added as a Home Assistant integration.

You will need to have used the Mercedes ME mobile app at least once before as you’ll need to login using that account in the integration. For certain services, like unlocking or remotely starting your car, you will also need to have setup a security PIN within the app and then pass it to the integration.

Managing preconditioning from HA

Below I’ll simply put some screenshots and YAML for the stuff I did to manage the preconditioning of my car. Most of it should be self-explanatory.

Screenshot of Lovelace dashboard controlling cars preconditioning
Lovelace setup

The YAML itself in the end is fairly compact:

switch:
  - platform: template
    switches:
      car_preconditioning_active:
        friendly_name: Preconditioning active
        unique_id: car_preconditioning_active
        value_template: >-
          {{ state_attr('sensor.licenseplate_range_electric', 'precondActive') 
          or state_attr('sensor.licenseplate_range_electric', 'precondNow') }}          
        turn_on:
          service: mbapi2020.preheat_start
          data:
            type: "0"
            vin: !secret car_vin
        turn_off:
          service: mbapi2020.preheat_stop
          data:
            vin: !secret car_vin
        icon_template: >-
          {%- if is_state('switch.car_preconditioning_active', 'on') %}
            mdi:air-conditioner
          {%- else %}
            mdi:car-off
          {% endif %}          

input_datetime:
  car_preconditioning_time:
      name: Preconditioning time
      has_date: false
      has_time: true

script:
  car_preconditioning_timer:
    alias: Car Preconditioning Timer
    description: Set time to start preconditioning
    icon: mdi:timer-play-outline
    mode: restart
    sequence:
      - alias: Call preheat service with departure time
        service: mbapi2020.preheat_start_departure_time
        data:
          vin: !secret car_vin
          time: >
            {%- set time = strptime(states('input_datetime.car_preconditioning_time'), '%H:%M:%S') %}
            {%- set hour = time.hour | int  %}
            {%- set minutes = time.minute | int %}
            {{ hour * 60 + minutes }}            

The lovelace cards are also very easy to set up:

type: horizontal-stack
cards:
  - type: entities
    entities:
      - entity: input_datetime.car_preconditioning_time
        name: Time
      - type: button
        name: Schedule
        tap_action:
          action: call-service
          service: script.car_preconditioning_timer
  - type: button
    name: Precon Now
    entity: switch.car_preconditioning_active
    show_name: true
    show_icon: true
    show_state: false

Notes

Just a few things you need to be aware off:

precondNow vs precondActive

If you start the preconditioning manually via the button or the app, only the precondNow attribute of sensor.licenseplate_range_electric changes to on/true. However if you use a timed start of the precon, either through the timer here or via the app, it’s the precondActive attribute that toggles.
So that’s why I check both for the value_template of the switch.

Timer calculation

The time passed to this services is formatted as minutes since midnight. That’s why I need to do a small calculation in the script. It also means you cannot schedule preconditioning more than 24 hours in the future using this script.

Tracking the next scheduled preconditioning

A recent update of the integration has exposed the info from the app on the next scheduled departure time. The integration doesn’t do any calculations, so you need to do your own based on the attributes provided:

  • The state of sensor.licenseplate_departure_time shows only the departure time in 24-hour or 12-hour format.
  • The Original value attribute of this sensor has this time formatted in minutes since midnight.
  • The DepartureTimeWeekday reports 0-6 for Monday through Sunday.

Combining this together, we get the following datetime sensor:

template:
  sensor:
    - name: Car Departure Time
      unique_id: "car_departure_time"
      device_class: timestamp
      state: >-
        {% set depart_weekday = state_attr('sensor.licenseplate_departure_time', 'departureTimeWeekday') | int %}
        {% set depart_minutes = state_attr('sensor.licenseplate_departure_time', 'original_value') | int %}
        {% set depart_time = today_at(timedelta(minutes = depart_minutes)) %}
        {% if depart_weekday == now().weekday() and depart_time < now() %}
          {{ (depart_time + timedelta(days = 7)).isoformat() }}
        {% else -%}
          {{ (depart_time + timedelta(days = (depart_weekday - now().weekday()) % 7)).isoformat() }}
        {%endif %}        

Since we use device_class: timestamp Home Assistant will show a human friendly value when we use this sensor in a card. So you’ll get text like tomorrow or Sunday displayed in the card, while the entity details will show the exact timestamp. If you prefer to always see this timestamp in the card, drop the device_class from the config and use e.g. | timestamp_local(default) or | timestamp_custom(format_string, local=True, default) instead of .isoformat() to get the prefered output.

Screenshot showing next scheduled preconditioning
Next scheduled precon

Changelog

  • 2023-03-24: Added section “Tracking the next scheduled preconditioning”