Engine heater automation

Hi!

This is my take on an automation for a car heater. Perhaps it might be useful for someone else.

It is in the form of a home assistant package. Copy it to your packages folder.

You also need to change the entity id of your outside temperature sensor.

Features:

  • The departure time is selected with sliders
  • Slider for sample temperature which will update calculated run time and start time based on departure time.
  • A sample of the outside temperature is taken 3h before departure time. This will update the value of above sample temp.
  • Engine heater run time is calculated using a linear equation adjusted for the conditions where I live (10 degrees = 0,5h, 0 degrees = 1h and -10 degrees = 1,5h)
    Of course you can change this if necessary
    I used this online calculator https://keisan.casio.com/exec/system/1223508685
  • Selector for enabling/disabling the car heater automation and if it should be run on weekdays only.

This is my first “more advanced” automation in Home assistant. I’m pretty new to this and still learning.
Please let me know if you have suggestions on how to improve it.

Big thanks to all of you who have helped me with questions on the forum! :slightly_smiling_face:

Now I only have to wait for the winter… :slight_smile:
If I only had a robot connecting the cable… hmmm… :thinking:

BR/Nylund

3 Likes

Hi,

I was just trying this car heater automation out as it sounds useful for the cold winter that is coming fast. I immediately ran into a problem. Both of the automations fail when HA tries to update them.

Update for sensor.car_heater_start_time fails
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 261, in async_update_ha_state
await self.async_device_update()
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 439, in async_device_update
await self.async_update()
File "/usr/src/homeassistant/homeassistant/components/template/sensor.py", line 238, in async_update
self._state = self._template.async_render()
File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 215, in async_render
return compiled.render(kwargs).strip()
File "/usr/local/lib/python3.7/site-packages/jinja2/asyncsupport.py", line 76, in render
return original_render(self, *args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/jinja2/environment.py", line 1008, in render
return self.environment.handle_exception(exc_info, True)
File "/usr/local/lib/python3.7/site-packages/jinja2/environment.py", line 780, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.7/site-packages/jinja2/_compat.py", line 37, in reraise
raise value.with_traceback(tb)
File "", line 2, in top-level template code
TypeError: unsupported operand type(s) for -: 'NoneType' and 'float'
Update for sensor.car_heater_3h_before_start_time fails
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 261, in async_update_ha_state
await self.async_device_update()
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 439, in async_device_update
await self.async_update()
File "/usr/src/homeassistant/homeassistant/components/template/sensor.py", line 238, in async_update
self._state = self._template.async_render()
File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 215, in async_render
return compiled.render(kwargs).strip()
File "/usr/local/lib/python3.7/site-packages/jinja2/asyncsupport.py", line 76, in render
return original_render(self, *args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/jinja2/environment.py", line 1008, in render
return self.environment.handle_exception(exc_info, True)
File "/usr/local/lib/python3.7/site-packages/jinja2/environment.py", line 780, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.7/site-packages/jinja2/_compat.py", line 37, in reraise
raise value.with_traceback(tb)
File "", line 1, in top-level template code
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'´

Any idea what could be causing this?

Hi!

I also get these errors when starting home assistant. Probably because an entity or service is not available yet. The errors can be ignored.
Have not found how to get rid of the errors. Perhaps someone else know?

BR/Nicklas

I have committed a fix to the problem. Please try! Works for me.

any idea why i got error

Error while executing automation automation.sample_temperature_3h_before_departure_time. Invalid data for call_service at pos 1: expected float for dictionary value @ data[‘value’]

Did you change the entity id of your outside temperature sensor?

Sorry im really noob for HA. Where i but it?

Thanks for sharing.
Will try it out. Currently I’m using Tasker on Android to do the same based on when my alarm is set.
One thing I’m missing from my Tasker integration is to be able to set “Extra heat time”

Lets say my “Departure time” is set to 06:30. Since my working schedule is flexible I actually leave sometime between 06:30-07:00. Hence I would like a slider to add extra heat time in minutes. So when I slide it to 30 minutes the actual off time would be 07:00.
The heat time calculation should still calculate against 06:30, and just let it heat a little longer if I don’t leave on time.

Basically the “Stop engine heater at departure time” automation should take “states.sensor.car_heater_departure_time.state” + extra_heat_time

Would you consider adding this feature?

I still get this error though, can this be ignored?:

Update for sensor.car_heater_3h_before_start_time fails
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 268, in async_update_ha_state
    await self.async_device_update()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 446, in async_device_update
    await self.async_update()
  File "/usr/src/homeassistant/homeassistant/components/template/sensor.py", line 248, in async_update
    self._state = self._template.async_render()
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 215, in async_render
    return compiled.render(kwargs).strip()
  File "/usr/local/lib/python3.7/site-packages/jinja2/asyncsupport.py", line 76, in render
    return original_render(self, *args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/jinja2/environment.py", line 1008, in render
    return self.environment.handle_exception(exc_info, True)
  File "/usr/local/lib/python3.7/site-packages/jinja2/environment.py", line 780, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.7/site-packages/jinja2/_compat.py", line 37, in reraise
    raise value.with_traceback(tb)
  File "<template>", line 2, in top-level template code
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'

Maybe not a robot for connecting the cable but I have an idea to create an additional automation that activates the switch for 30 seconds around 22.00, measures if there is any load and, if no load and car heater is active, send me a notification.

I am still waiting for a Sonoff in the mail to play with it though.

1 Like

Hello and thank you! It works almost perfect but my heater needs to run a little longer. What do I need change? Thank you in advance. I found it. I changed 0.05 to a higher number.

@Olov_Frykeras

Use the online calculator here:

Here I have put the values I used to get the equation:


10 degrees = 0.5h
-10 degrees = 1.5h
Equation: y= -0.05x +1

10 degrees = 0.5h
-10 degrees = 2h
Equation: y= -0.075 + 1.25

Change this line accordingly:
{{(states(‘input_number.car_heater_3h_before_temp’)|float * (-0.05) + 1)|round(1)}}

I use the second example (2h when -10 degrees) now since I also noticed that I need to run it a little bit longer when it’s cold.
{{(states(‘input_number.car_heater_3h_before_temp’)|float * (-0.075) + 1.25)|round(1)}}

1 Like

@larre Good idea! Will look into it!

These errors can be ignored if they appear when restarting home assistant. I have not figured out how to get rid of them.

Thank you!

Thanks for the explanation, but be aware, using this example or any value that makes the possible run time longer than 2,5 hours:
{{(states(‘input_number.car_heater_3h_before_temp’)|float * (-0.075) + 1.25)|round(1)}}
Makes the maximum heating time 3,5 hours. Meaning that already at -23 degress the run time will be 3 hours hence the sample temperature automation won´t run on time.
Changing:
{{ strptime(((as_timestamp('1970-01-01 ’ ~ states(‘sensor.car_heater_departure_time’)) - (10800))|timestamp_local), ‘%Y-%m-%d %H:%M:%S’).strftime("%H:%M") }}
to:
{{ strptime(((as_timestamp('1970-01-01 ’ ~ states(‘sensor.car_heater_departure_time’)) - (12960))|timestamp_local), ‘%Y-%m-%d %H:%M:%S’).strftime("%H:%M") }}
Should fix it and the sample temp will be checked 6 minutes before the max 3,5h run time.

Can somebody help me adding “extra heat time” slider so I can heat for x minutes after departure time? I can´t get my head around it.

I just found out that the slider for sample temp goes from -30 to +30.
But the automation that gets the sample temp actually sets the temperature to whatever the actual temperature of the senor is.
So if you live far north the temperature can actually be lower than -30 and then this action sets it to whatever it is:

    action:
      service: input_number.set_value
      data_template:
        entity_id: input_number.car_heater_3h_before_temp
        value: '{{ states.sensor.ute.state }}'

This sets the calculated run time too late since it actually should already have started.

I’m not good at all the “if else” stuff in yaml otherwise I would try to help out at github.
But what the above action needs is something like:
If sensor <-30
set value to -30.
Else
set value to: actual sensor value.

I just wanted to share my lovelace setup for this package, I think i turned out really niceley, maybe it will help someone :slight_smile:

(it 's in swedish but I think you will be able to change it to your language)

You will need two community plugins and one community integration.

Integration:

  • Browser mod (for the settings popup)

Plugins

  • Vertical Stack In Card (to combine multiple cards in one)
  • Button Entity Row (for the buttons)

Lovelace code:

type: 'custom:vertical-stack-in-card'
title: Motorvärmare
cards:
  - entities:
      - entity: sensor.heater_departuretime
      - entity: sensor.heater_activationtime
      - entity: sensor.heater_temptime
      - entity: sensor.heater_forecast
        name: Prognos
    show_header_toggle: false
    title: null
    type: glance
    show_icon: false
  - entities:
      - type: 'custom:button-entity-row'
        buttons:
          - entity: input_boolean.heater_active
            name: Aktiv
            state_icons:
              'off': 'mdi:play'
              'on': 'mdi:pause'
          - entity: switch.shelly_outside_garageport_right_socket_switch_2
            name: Manuell start
            state_icons:
              'off': 'mdi:play'
              'on': 'mdi:pause'
          - entity: sensor.heater_forecast
            name: Inställningar
            icon: 'mdi:settings'
            service: browser_mod.popup
            service_data:
              deviceID: this
              title: Inställningar motorvärmare
              card:
                type: entities
                entities:
                  - entity: input_number.heater_hour
                  - entity: input_number.heater_minute
                  - entity: input_number.heater_delay
                  - entity: input_number.heater_maxmin
                  - entity: input_boolean.workdays_only
    show_header_toggle: false
    title: null
    type: entities

Winter slowly coming closer - again…

Slowly trying to wrap my head around yaml, powerfull as it seem it is a bit like reverse Polish notation - a bit backwards…

How to edit the setting of sampled temperature if the departure time is less than 3h from “now”?
Can that be tested/done in the platform sensor for departure time, or should it be in the automaton (sample temp 3h before dept)?

Just to clarify, which entites is needed to change according to my own configuration?

Hi! I still possible to use this?

And for the time of departure, and instead of sample temp maybe it’s possible to use some from here?