Automation to start charging X hours before 6am every morning

Hi folks,

I want to create an automation that turns a charger on X hours before 6am every morning, where X is the calculated # of hours needed to reach a full charge.

I already have X since I know the charge rate/hr and I have a template sensor that calculates how many hours the car needs to charge for to be full at ~6am

I’m having trouble figuring out a way to create the automation within node-red though. It seems like something that would be relatively simple to do, but I can’t quite figure it out. Can anybody help me out?

Thanks

You can use a normal function node to calculate the start time and than sending this time to a Cron node.

To make it more fancy you can send your “X” offset to this Node which can consider either 6am or Sunrise

Any chance you’d be able to walk me through it or know a good guide to using function nodes? I’m a total newbie with this

Currently this is what I have:

binary sensor for whether the car is plugged in (charger_sensor=on/off)
sensor to calculate a number of hrs needed to reach full charge, rounded up to the hour (tt_charge=n)
switch to control whether the car is charging or not (charger_switch=on/off)

I have a flow triggered when the car is plugged in (charger_sensor=on) --> it checks whether it’s between 9PM and 6AM --> if it is, turn charger off (charger_switch=off) --> wait and I want charging (switch_charger=on) to start at (0630 - (tt_charge))

That flow should be easy. I’ll be back home tomorrow and will try to get you a sample

Thank you so much!

I’m curious, why wouldn’t you just charge until it’s full every time it’s plugged in? If you get home at 9:30 and plug your car in, and it takes 3 hours to charge, you’re done at 12:30 and it’s still good to go at 6:30am when you need it. Or, with this automation, you could wait until 3:30am to charge it and it’s still good to go at 6:30am. But… what’s the purpose of waiting?

I don’t own an electric car. So this answer may be obvious to those that do.

I’ve done something to run a task 15 minutes before an alarm goes off, it might be what your after,

      time_plus_15min:
        friendly_name: 'Time +15min'
        value_template: >
          {{ (as_timestamp(now()) | int + 900) | timestamp_custom("%H:%M") }}
        entity_id: sensor.time

900 is the number of seconds before the current time I want to do something.

- id: alarm1_execute
  alias: 'Alarm 1 Execution Script'
  hide_entity: True
  initial_state: 'on'
  trigger:
    - platform: template
      value_template: "{% if states.sensor.alarm1_time.state == states.sensor.time_plus_15min.state %}true{% endif %}" 

Therefore if the time in my alarm is equal to the time+900 seconds, do something (e.g. this will trigger when the real time is actually 15 minutes before).

Great question =)

Batteries don’t like very cold weather and the car performs better overall with a warm battery (measured by various things but regenerative braking in particular). If I just have the car charge when I plug it in, it’ll be done by midnight and when I get in it to go to work at 630, I’ll be leaving with a cold battery. If I can automate the charge to end just prior to when I leave in the morning, the battery will be warm and performance won’t be compromised.

Alongside the automated charging, I can automate the hvac controls to warm the interior of the car ~15 mins before I leave so I’m getting into a car with a warm battery, and a warm cabin =)

ahhhh! That makes a lot of sense! Thanks for taking the time to help me understand.

I haven’t used Node Red in quite a while, but I can answer a few questions. A “function node” is just pure JavaScript.

If your template sensor updates only when the car is plugged in, you’re almost there already. You’d need something like:

A node that triggers when that template sensor changes ->
A function node to take the value from the payload subtract that from 6:30am and determine how many seconds need to pass to get to that time ->
A delay node to wait that long ->
A node that turns on the charging function

The function node will depend entirely on what the payload from the template sensor looks like.

Hmm…this might actually help get me where I need to go. I might have been thinking of this the wrong way, instead of starting at 6AM and looking back, I need to start at the current time and figure out how long to delay the start for

Thanks

Yup, I was approaching it from the wrong angle. Going to try reading up on function nodes and see if I can figure out how to do what you suggest

Thanks!

You could calculate how long you need to charge, then add this to the timestamp in seconds. If you then trigger the automation when this template sensor then == 6am.

When you need 4 hours of charging, current time would be 2am, that sensor would read 6am now. therefore start charging.

      charge_start_time:
        friendly_name: 'Charge Start Time'
        value_template: >
          {{ (as_timestamp(now()) | int + states.sensor.required_charge_time.state | int) | timestamp_custom("%H:%M") }}
        entity_id: 
          - sensor.time
          - sensor.required_charge_time

- id: car_charge_start
  alias: 'Car Charge Start'
  trigger:
    - platform: template
      value_template: "{% if states.sensor.charge_start_time.state == '06:00' %}true{% endif %}" 
1 Like

That’s literally just what I was just setting up. Thanks!

A flow in Node-Red would look like this

[
    {
        "id": "60be7652.de6108",
        "type": "function",
        "z": "bb7ec6f1.afceb8",
        "name": "set",
        "func": "var value = msg.payload.toString();\n\nmsg.payload=msg.topic+\" \"+value;\n\nif (msg.topic==\"onoffset\" || msg.topic== \"offoffset\" ) msg.payload=msg.topic+\" -\"+value;\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 260,
        "y": 310,
        "wires": [
            [
                "c6e65297.130e5"
            ]
        ]
    },
    {
        "id": "c6e65297.130e5",
        "type": "schedex",
        "z": "bb7ec6f1.afceb8",
        "name": "",
        "suspended": false,
        "lat": "150",
        "lon": "-33",
        "ontime": "16:00",
        "ontopic": "",
        "onpayload": "ON",
        "onoffset": 0,
        "onrandomoffset": 0,
        "offtime": "goldenHour",
        "offtopic": "16:10",
        "offpayload": "OFF",
        "offoffset": 0,
        "offrandomoffset": 0,
        "mon": true,
        "tue": true,
        "wed": true,
        "thu": true,
        "fri": true,
        "sat": true,
        "sun": true,
        "x": 440,
        "y": 310,
        "wires": [
            [
                "9a0e9fb.da1fa6"
            ]
        ]
    },
    {
        "id": "ff3820fe.e1e66",
        "type": "ui_switch",
        "z": "bb7ec6f1.afceb8",
        "name": "",
        "label": "switch",
        "tooltip": "",
        "group": "f733af23.d1c35",
        "order": 1,
        "width": 0,
        "height": 0,
        "passthru": true,
        "decouple": "false",
        "topic": "suspended",
        "style": "",
        "onvalue": "true",
        "onvalueType": "bool",
        "onicon": "",
        "oncolor": "",
        "offvalue": "false",
        "offvalueType": "bool",
        "officon": "",
        "offcolor": "",
        "x": 110,
        "y": 290,
        "wires": [
            [
                "60be7652.de6108"
            ]
        ]
    },
    {
        "id": "c26093ca.d4417",
        "type": "ui_text_input",
        "z": "bb7ec6f1.afceb8",
        "name": "",
        "label": "ON-offset",
        "tooltip": "",
        "group": "f733af23.d1c35",
        "order": 2,
        "width": 0,
        "height": 0,
        "passthru": true,
        "mode": "number",
        "delay": "0",
        "topic": "onoffset",
        "x": 100,
        "y": 320,
        "wires": [
            [
                "60be7652.de6108"
            ]
        ]
    },
    {
        "id": "9a0e9fb.da1fa6",
        "type": "debug",
        "z": "bb7ec6f1.afceb8",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "x": 630,
        "y": 310,
        "wires": []
    },
    {
        "id": "f733af23.d1c35",
        "type": "ui_group",
        "z": "",
        "name": "Charger",
        "tab": "f38bec72.435",
        "order": 1,
        "disp": true,
        "width": "6",
        "collapse": false
    },
    {
        "id": "f38bec72.435",
        "type": "ui_tab",
        "z": "",
        "name": "Test",
        "icon": "dashboard",
        "order": 15,
        "disabled": false,
        "hidden": false
    }
]

Awesome thanks!

Thanks for all of the above even though it has been a few years. I took a slightly different approach as I wanted to be able to display when the charger will come on.

  - platform: template
    sensors:
      mgzsev_delayed_start_time:
        friendly_name: "MGZS Delayed Start Time"
        value_template: >
          {% if (is_state("automation.car_charger_turn_off_when_battery_at_80","on")) -%}
            {{ (as_timestamp(strptime("06:00","%H:%M")) | float - states.sensor.mgzsev_estimated_time_to_80.state | float * 3600) | timestamp_custom("%H:%M") }}
          {%- else -%}
            {{ (as_timestamp(strptime("06:00","%H:%M")) | float - states.sensor.mgzsev_estimated_time_to_100.state | float * 3600) | timestamp_custom("%H:%M") }}
          {%- endif %}

The above calculates what time to turn on the charger based on whether the 80% or 100% selection has been made. Then to actually turn on the charger:

- id: car_charger_delayed_start_on
  alias: Car Charger Delayed Start On
  trigger:
  - platform: template
    value_template: "{% if states.sensor.mgzsev_delayed_start_time.state == states.sensor.time.state %}true{% endif %}" 
  condition:
    condition: state
    entity_id: input_boolean.car_charger_delayed_start
    state: 'on'   
  action:
  - service: switch.turn_on
    entity_id: switch.car_charger

Do you read out the battery status from your car? What I do with my iPhone is charge it and when the battery status 100% turn the charger off with a zigbee plug. If the battery status is under 90% it sets the charger already on. Also did this in Node Red