Skip to content

Instantly share code, notes, and snippets.

@sakalauskas
Last active October 23, 2024 23:53
Show Gist options
  • Save sakalauskas/b7affadd817845c6e492ee1c880ed4f6 to your computer and use it in GitHub Desktop.
Save sakalauskas/b7affadd817845c6e492ee1c880ed4f6 to your computer and use it in GitHub Desktop.
HomeAssistant Excess Solar/Offpeak/Nordpool charging automation for Tesla

Hardware

  • Shelly 3em
  • Tesla Wall Connector (3gen)
  • Huawei Solar Inverter
  • Tesla Model 3

Automations

There are four charge modes based on input_select.tesla_charger_speed selection:

  1. Charge only by excess solar
  2. Charge bypass - Fastest mode
  3. Offpeak with early stop
  4. Nordpool

Automations are triggered based on Tesla Wall Connector state. If using a different charger that does not expose plug connector state, conditions/triggers can be substituted to trigger if Tesla is home and cable is connected. e.g.

    - alias: "Is home"
      condition: state
      entity_id: device_tracker.tesla_location
      state: "home"
    - alias: "Is plugged in"
      condition: state
      entity_id: binary_sensor.tesla_model_3_charger
      state: "on"
- alias: Tesla Wall Connector connected - turn off charge immediatelly
description: "When Tesla is connected it starts the charging automatically. Stop chargning unless 'Fastest' is selected. After 15 seconds other automations will take over"
# todo merge everything into a single automation
# Other automations (solar/nordpool/offpeak) will trigger 15 seconds after Tesla Wall Connector connected
trigger:
- platform: state
entity_id:
- binary_sensor.tesla_wall_connector_vehicle_connected
to:
- "on"
condition:
- condition: state
alias: "If not vacation"
entity_id: input_boolean.vacation_mode
state: "off"
action:
- service: button.press
alias: "Force update car state when cable connected"
target:
entity_id: button.tesla_model_3_force_data_update
- if:
- condition: state
entity_id: input_select.tesla_charger_speed
state:
# - "Fastest"
- "Only Solar"
- "Nordpool"
- "Offpeak"
then:
- service: switch.turn_off
target:
entity_id: switch.tesla_model_3_charger
- id: tesla_offpeak_charge
alias: Tesla Charge mode - Offpeak
description: During the offpeak hours (utility_meter integration), turn on charging at max current to reach the 70% battery limit
trigger:
- platform: homeassistant
event: start
- entity_id: utility_meter.daily_house_energy
platform: state
to: "offpeak"
- platform: state
for:
seconds: 15
entity_id: binary_sensor.tesla_wall_connector_vehicle_connected
to: "on"
- platform: state
entity_id: input_select.tesla_charger_speed
to: "Offpeak"
condition:
- condition: state
alias: "If not vacation"
entity_id: input_boolean.vacation_mode
state: "off"
- alias: "Offpeak rate"
condition: state
entity_id: utility_meter.daily_house_energy
state: "offpeak"
- alias: "Charge Cable plugged in"
condition: state
entity_id: binary_sensor.tesla_wall_connector_vehicle_connected
state: "on"
- alias: "Offpeak charge mode selected"
condition: state
entity_id: input_select.tesla_charger_speed
state: "Offpeak"
action:
- delay: 00:01:00
- service: switch.turn_on
target:
entity_id: switch.tesla_model_3_charger
- service: number.set_value
alias: Set charging amps to max
data:
value: '{{ state_attr("number.tesla_model_3_charging_amps", "max") }}'
target:
entity_id: number.tesla_model_3_charging_amps
- choose:
- alias: "Set charge limit to 70%, if it is not set to 100%"
conditions: "{{ (states('number.tesla_model_3_charge_limit') |int(0)) < 100 }}"
sequence:
- service: number.set_value
data:
value: 70
target:
entity_id: number.tesla_model_3_charge_limit
- alias: Tesla Charge mode - Offpeak (stop)
id: tesla_stop_peak_charge
description: Stop charging when offpeak tariff ends and we don't need max range
trigger:
- entity_id: utility_meter.daily_house_energy
platform: state
from: "offpeak"
to: "peak"
condition:
- condition: state
alias: "If not vacation"
entity_id: input_boolean.vacation_mode
state: "off"
- alias: "Charge Cable plugged in"
condition: state
entity_id: binary_sensor.tesla_wall_connector_vehicle_connected
state: "on"
- alias: "Offpeak charge mode selected"
condition: state
entity_id: input_select.tesla_charger_speed
state: "Offpeak"
action:
- entity_id: switch.tesla_model_3_charger
service: switch.turn_off
- alias: Tesla Charge mode - Offpeak (early stop)
description: If the predicted solar production is high, stop offpeak charging when reached 60% and continue the charge (60% to 95%) later in the day.
id: tesla_stop_peak_charge_early
trigger:
- entity_id: sensor.tesla_model_3_battery
platform: numeric_state
above: 60
for:
minutes: 1
condition:
- condition: state
alias: "If not vacation"
entity_id: input_boolean.vacation_mode
state: "off"
- alias: "Tesla at home"
condition: state
entity_id: device_tracker.tesla_location
state: "home"
- alias: "Offpeak rate"
condition: state
entity_id: utility_meter.daily_house_energy
state: "offpeak"
- alias: "Predicted high solar production today"
condition: numeric_state
entity_id: sensor.energy_production_today
above: 50
action:
- entity_id: switch.tesla_model_3_charger
service: switch.turn_off
- alias: Tesla Charge mode - Fastest
id: tesla_fast_charge
description: When the "Fastest" is selected, charge immediatelly on max current to 100%
trigger:
- platform: homeassistant
event: start
- platform: state
for:
seconds: 15
entity_id: binary_sensor.tesla_wall_connector_vehicle_connected
to: "on"
- platform: state
entity_id: input_select.tesla_charger_speed
to: "Fastest"
condition:
- condition: state
alias: "If not vacation"
entity_id: input_boolean.vacation_mode
state: "off"
- alias: "Charge Cable plugged in"
condition: state
entity_id: binary_sensor.tesla_wall_connector_vehicle_connected
state: "on"
- alias: "Fastest charge mode selected"
condition: state
entity_id: input_select.tesla_charger_speed
state: "Fastest"
action:
- service: switch.turn_on
target:
entity_id: switch.tesla_model_3_charger
- service: number.set_value
alias: "Set charging amps to max available"
data:
value: '{{ state_attr("number.tesla_model_3_charging_amps", "max") }}'
target:
entity_id: number.tesla_model_3_charging_amps
- alias: "Set charge limit to 100%"
service: number.set_value
data:
value: 100
target:
entity_id: number.tesla_model_3_charge_limit
- alias: Tesla Charge mode - Nordpool
description: "Will charge based on EV Smart Charging integration (Nordpool)"
trigger:
- platform: state
for:
seconds: 15
entity_id:
- binary_sensor.tesla_wall_connector_vehicle_connected
to:
- "on"
- "off"
condition:
- condition: state
alias: "If not vacation"
entity_id: input_boolean.vacation_mode
state: "off"
- alias: "Nordpool charge mode selected"
condition: state
entity_id: input_select.tesla_charger_speed
state: "Nordpool"
action:
- service: button.press
target:
entity_id: button.tesla_model_3_force_data_update
- delay: 00:00:05
- if:
- condition: state
entity_id: binary_sensor.tesla_wall_connector_vehicle_connected
state: "on"
then:
- if:
- condition: state
entity_id: sensor.ev_smart_charging_charging
state: "off"
then:
- service: switch.turn_off
target:
entity_id: switch.tesla_model_3_charger
else:
- service: switch.turn_on
target:
entity_id: switch.tesla_model_3_charger
- service: switch.turn_on
data: {}
target:
entity_id: switch.ev_smart_charging_ev_connected
else:
- if:
- condition: state
entity_id: binary_sensor.tesla_wall_connector_vehicle_connected
state: "off"
then:
- service: switch.turn_off
data: {}
target:
entity_id: switch.ev_smart_charging_ev_connected
mode: single
- alias: Tesla Charge mode - Only Solar
id: smart_solar_charge_tesla
description: "To only use excess power from solar, limit the number of Amps Tesla charger use. We'll stop charging if it drops below 5A"
trigger:
- platform: time_pattern
minutes: "/1"
# This will run automation every minute
- platform: state
for:
seconds: 15
entity_id: binary_sensor.tesla_wall_connector_vehicle_connected
to: "on"
- platform: state
entity_id: input_select.tesla_charger_speed
to: "Only Solar"
condition:
- condition: state
alias: "If not vacation"
entity_id: input_boolean.vacation_mode
state: "off"
- alias: "Is plugged in"
condition: state
entity_id: binary_sensor.tesla_wall_connector_vehicle_connected
state: "on"
- alias: "Sun is shining"
condition: numeric_state
entity_id: sensor.elevation
above: 5
- alias: "Charge mode 'Only Solar' selected"
condition: state
entity_id: input_select.tesla_charger_speed
state: "Only Solar"
variables:
# Calculate ideal charging amps, so it would only use electricity from solar, we should set the Tesla charger to
# AMPS = (current power usage (i.e. -2000W) + 200W overhead, converted to amps)
amps: '{{ [[((states("sensor.tesla_charger_actual_current")|int(0)) - ((max([states("sensor.shelly_channel_b_power")|float(0), states("sensor.shelly_channel_c_power")|float(0), states("sensor.shelly_channel_a_power")|float(0)]) + 200) / (states("sensor.shelly_channel_a_voltage")|int(0)))|int(0)),0]|max, state_attr("number.tesla_model_3_charging_amps", "max") | int(0) ]|min }}'
# Above is for three phase charging. Optimal current is calculated from the phase which is most loaded.
# For single phase chargers, only a single phase needs to be measured - in my case Channel B
# '{{ [[((states("sensor.tesla_charger_actual_current")|int(0)) - ((states("sensor.shelly_channel_b_power")|float(0) + 200) / (states("sensor.shelly_channel_b_voltage")|int(0)))|int(0)),0]|max, state_attr("sensor.tesla_model_3_charging_rate_sensor", "charge_current_request_max") | int(0) ]|min }}'
# todo: More optimal calculation may be possible?
action:
- choose:
- alias: "Enough energy to charge"
conditions: "{{ amps >= 3 }}"
sequence:
- choose:
- alias: "Turn on charger if off"
conditions:
- condition: state
entity_id: switch.tesla_model_3_charger
state: "off"
sequence:
- entity_id: switch.tesla_model_3_charger
service: switch.turn_on
- choose:
- alias: "Update Current if changed"
conditions:
- "{{ amps >= 3 and amps != (states('sensor.tesla_charger_actual_current')|int(0)) }}"
sequence:
- service: number.set_value
data:
value: "{{ amps }}"
target:
entity_id: number.tesla_model_3_charging_amps
# ELSE (Turn off charging charging - it seems to be too slow below 3A (5A for single phase))
default:
- choose:
- alias: "Turn off charger if on"
conditions:
- condition: state
entity_id: switch.tesla_model_3_charger
state: "on"
sequence:
- entity_id: switch.tesla_model_3_charger
service: switch.turn_off
- choose:
- alias: "Set charging limit to 100%" # For SR+, 100% is optimal
conditions: "{{ (states('number.tesla_model_3_charge_limit') |int(0)) < 95 }}"
sequence:
- service: number.set_value
data:
value: 100
target:
entity_id: number.tesla_model_3_charge_limit
tesla_charger_speed:
name: Charge method
options:
- "Fastest"
- "Only Solar"
- "Nordpool"
- "Offpeak"
initial: Only Solar
icon: mdi:ev-station
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment