Charging Tesla with excess power from solar panels

Hi,

I am trying to set up an automation to charge my Tesla with excess power from my solar panels. Every 30 seconds (in the daytime, and if the car is plugged in) the export or excess power from the house electricity meter (pow_k) is measured. The idea is to keep the export power close to 0, by adjusting the charging amps of the car. If it is above 688w, the Tesla charging amps will be increased by 1. If it is below, they will be decreased by 1.

HA gives the error message Message malformed: expected float for dictionary value @ data[‘value’]. Any assistance to this novice would be greatly appreciated.

alias: Charging EV (T-Ray) with excess solar power
description: ""
trigger:
  - platform: time_pattern
    seconds: "30"
condition:
  - condition: sun
    before: sunset
    after: sunrise
  - type: is_plugged_in
    condition: device
    device_id: b4929c45bca6cfb24b68e22f7f0f9977
    entity_id: binary_sensor.t_ray_charger
    domain: binary_sensor
action:
  - if:
      - type: is_power
        condition: device
        device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
        entity_id: sensor.pow_k_po
        domain: sensor
        above: 688
    then:
      - device_id: b4929c45bca6cfb24b68e22f7f0f9977
        domain: number
        entity_id: number.t_ray_charging_amps
        type: set_value
        value: {{ (states.number.t_ray_charging_amps.state | int ) + 1 }}
    else:
      - device_id: b4929c45bca6cfb24b68e22f7f0f9977
        domain: number
        entity_id: number.t_ray_charging_amps
        type: set_value
        value: {{ (states.number.t_ray_charging_amps.state | int ) - 1 }}
mode: single

1 Like

try removing the quotes around “30” (seconds) so it’s a number and not text

Sorry, I should have explained that the problem is around the value statement:

value: {{ (states.number.t_ray_charging_amps.state | int ) + 1 }}

If I put in a number eg. like this:

value: 5

the automation works perfectly. But with the curly bracket statement, I get an error message:

Message malformed: expected float for dictionary value @ data['value']

Any help is greatly appreciated.

1 Like

UPDATE: SOLUTION FOUND
Action statement changed to this:

action:
  - service: number.set_value
    data_template:
      entity_id: number.t_ray_charging_amps
      value: >-
        {% set current_amps = states('number.t_ray_charging_amps') | int %} {{
        current_amps + 1 }}

Now it works.

Hi! I’m looking to create an automation to do the same thing.

A couple of questions:

  1. I think your automation will constantly adjust 1 A up or down every 30 seconds. Currently there is no option for it to leave the charging current as it is.

  2. The Tesla app has a minimum set charging current of 5 A. Does the API allow it to go lower? Edit: it does! I thought you had to do a minimum of 5 A charging. That’s cool!

1 Like

Alright, just played around with it for a bit.

Seeing the current to 0 (zero) amps and turning it on seems to draw around 400-500 Watts, but I’m not sure it charges the car. I think it just powers on the onboard charger. So I think the efficiency will be very low at low amps.

My electrical bill is net metering per hour (if import == export within a clock hour, my bill will be zero), so I might want to do things in bursts of 5A for low solar surplus, if that increases charging efficiency.

I will post my automation here when I get it woeking, either with or without burst charging.

Cheers!

True. I just had troubles to make the value statement (+/- amps) working. Now I start building the complete set of triggers, conditions etc. around the +/- amp function.

Also agree on the probably low efficiency at low amps, but want to try it and see how it works.

I will post as I progress and appreciate your thoughts.

Thanks.

Hello @Finnray

I tried your automation, and it seems awesome… I just cannot make it work.

Can you or anyone else help me?

Be aware that im not very skilled at this stuff.

YALM from automation (Im not getting any error):

alias: Tesla Charging
description: ""
trigger:
  - platform: time_pattern
    minutes: "2"
condition:
  - condition: sun
    before: sunset
    after: sunrise
  - type: is_plugged_in
    condition: device
    device_id: 4ebe9b1fbd57c840e4235fbb8af7cbbb
    entity_id: binary_sensor.charger
    domain: binary_sensor
action:
  - if:
      - condition: numeric_state
        entity_id: sensor.omcsbln02t_export_to_grid
        above: 0.6
    then:
      - service: input_number.set_value
        entity_id: number.charging_amps
        data_template:
          value: >-
            {% set current_amps = states('number.charging_amps') | int %} {{
            current_amps + 1 }}
    else:
      - service: input_number.set_value
        entity_id: number.charging_amps
        data_template:
          value: >-
            {% set current_amps = states('number.charging_amps') | int %} {{
            current_amps - 1 }}
mode: single

Currently I’m charging my car with 6 amps. And “sensor.omcsbln02t_export_to_grid” is below 0.6 so it should change the amps to 5, which it actually seems like its trying, but nothing happens.

Log from Trace:

Executed: April 9, 2023 at 10:35:56
Result:
params:
  domain: input_number
  service: set_value
  service_data:
    value: 5
    entity_id:
      - number.charging_amps
  target:
    entity_id:
      - number.charging_amps
running_script: false
limit: 10

There is something in value: called “current_amps”. I’m not sure what this value/sensor is, and maybe this could be the issue. I just thought that as soon as it gives the right value, it would change number.charging_amps to this value?

Thanks a lot

I got it working!

I think the problem was

input_number.set_value

was changed to:

number.set_value

Thanks :slight_smile:

1 Like

Glad to hear that you got it working Karsten.

Actually, I also got it working and have since refined it quite a bit. Here is the code that I use today:

alias: T-Ray solar charging
description: ""
trigger:
  # Time interval for triggering set
  - platform: time_pattern
    seconds: "30"
condition:
  # Continue if T-Ray is plugged in charger (or exit)  
  - type: is_plugged_in
    condition: device
    device_id: b4929c45bca6cfb24b68e22f7f0f9977
    entity_id: binary_sensor.t_ray_charger
    domain: binary_sensor
  # Continue if T-Ray SOC is below 1% of charge limit (or exit)      
  - condition: template
    value_template: >-
      {{(states('number.t_ray_charge_limit') | int -
      states('sensor.t_ray_battery') | int) > 1}}
action:
  # Continue if more than 688w EXPORT power is available (else)  
  - if:
      - type: is_power
        condition: device
        device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
        entity_id: sensor.pow_k_po
        domain: sensor
        above: 688
    then:
      # Turn ON charger if it is OFF and continue (or just continue)
      - if:
          - condition: device
            type: is_off
            device_id: b4929c45bca6cfb24b68e22f7f0f9977
            entity_id: switch.t_ray_charger
            domain: switch
        then:
          - type: turn_on
            device_id: b4929c45bca6cfb24b68e22f7f0f9977
            entity_id: switch.t_ray_charger
            domain: switch
      # Choose number of charging amps to add relative to current EXPORT power  (Note: If current EXPORT power is below 688w -> no change)
      - choose:
          - conditions:
              - type: is_power
                condition: device
                device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
                entity_id: sensor.pow_k_po
                domain: sensor
                above: 5504
            sequence:
              - service: number.set_value
                data_template:
                  entity_id: number.t_ray_charging_amps
                  value: >-
                    {% set current_amps = states('number.t_ray_charging_amps') |
                    int %} {{ current_amps + 8 }}
          - conditions:
              - type: is_power
                condition: device
                device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
                entity_id: sensor.pow_k_po
                domain: sensor
                above: 4816
            sequence:
              - service: number.set_value
                data_template:
                  entity_id: number.t_ray_charging_amps
                  value: >-
                    {% set current_amps = states('number.t_ray_charging_amps') |
                    int %} {{ current_amps + 7 }}
          - conditions:
              - type: is_power
                condition: device
                device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
                entity_id: sensor.pow_k_po
                domain: sensor
                above: 4128
            sequence:
              - service: number.set_value
                data_template:
                  entity_id: number.t_ray_charging_amps
                  value: >-
                    {% set current_amps = states('number.t_ray_charging_amps') |
                    int %} {{ current_amps + 6 }}
          - conditions:
              - type: is_power
                condition: device
                device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
                entity_id: sensor.pow_k_po
                domain: sensor
                above: 3440
            sequence:
              - service: number.set_value
                data_template:
                  entity_id: number.t_ray_charging_amps
                  value: >-
                    {% set current_amps = states('number.t_ray_charging_amps') |
                    int %} {{ current_amps + 5 }}
          - conditions:
              - type: is_power
                condition: device
                device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
                entity_id: sensor.pow_k_po
                domain: sensor
                above: 2752
            sequence:
              - service: number.set_value
                data_template:
                  entity_id: number.t_ray_charging_amps
                  value: >-
                    {% set current_amps = states('number.t_ray_charging_amps') |
                    int %} {{ current_amps + 4 }}
          - conditions:
              - type: is_power
                condition: device
                device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
                entity_id: sensor.pow_k_po
                domain: sensor
                above: 2064
            sequence:
              - service: number.set_value
                data_template:
                  entity_id: number.t_ray_charging_amps
                  value: >-
                    {% set current_amps = states('number.t_ray_charging_amps') |
                    int %} {{ current_amps + 3 }}
          - conditions:
              - type: is_power
                condition: device
                device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
                entity_id: sensor.pow_k_po
                domain: sensor
                above: 1376
            sequence:
              - service: number.set_value
                data_template:
                  entity_id: number.t_ray_charging_amps
                  value: >-
                    {% set current_amps = states('number.t_ray_charging_amps') |
                    int %} {{ current_amps + 2 }}
          - conditions:
              - type: is_power
                condition: device
                device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
                entity_id: sensor.pow_k_po
                domain: sensor
                above: 688
            sequence:
              - service: number.set_value
                data_template:
                  entity_id: number.t_ray_charging_amps
                  value: >-
                    {% set current_amps = states('number.t_ray_charging_amps') |
                    int %} {{ current_amps + 1 }}
    else:
      # Check if power is being imported
      - if:
          - type: is_power
            condition: device
            device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
            entity_id: sensor.pow_k_p
            domain: sensor
            above: 0
        then:
          # Turn OFF charger if power is being imported, but current charging power is below 550w and exit
          - if:
              - type: is_power
                condition: device
                device_id: 3efa4551c778fefe170f4c0c7b4dad6f
                entity_id: sensor.go_echarger_110504_nrg_12
                domain: sensor
                below: 550
            then:
              - type: turn_off
                device_id: b4929c45bca6cfb24b68e22f7f0f9977
                entity_id: switch.t_ray_charger
                domain: switch
            else:
              # Choose number of charging amps to subtract relative to current IMPORT power (Note: If current IMPORT power is below 688w -> no change)
              - choose:
                  - conditions:
                      - type: is_power
                        condition: device
                        device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
                        entity_id: sensor.pow_k_p
                        domain: sensor
                        above: 5504
                    sequence:
                      - service: number.set_value
                        data_template:
                          entity_id: number.t_ray_charging_amps
                          value: >-
                            {% set current_amps =
                            states('number.t_ray_charging_amps') | int %} {{
                            current_amps - 8 }}
                  - conditions:
                      - type: is_power
                        condition: device
                        device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
                        entity_id: sensor.pow_k_p
                        domain: sensor
                        above: 4816
                    sequence:
                      - service: number.set_value
                        data_template:
                          entity_id: number.t_ray_charging_amps
                          value: >-
                            {% set current_amps =
                            states('number.t_ray_charging_amps') | int %} {{
                            current_amps - 7 }}
                  - conditions:
                      - type: is_power
                        condition: device
                        device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
                        entity_id: sensor.pow_k_p
                        domain: sensor
                        above: 4128
                    sequence:
                      - service: number.set_value
                        data_template:
                          entity_id: number.t_ray_charging_amps
                          value: >-
                            {% set current_amps =
                            states('number.t_ray_charging_amps') | int %} {{
                            current_amps - 6 }}
                  - conditions:
                      - type: is_power
                        condition: device
                        device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
                        entity_id: sensor.pow_k_p
                        domain: sensor
                        above: 3440
                    sequence:
                      - service: number.set_value
                        data_template:
                          entity_id: number.t_ray_charging_amps
                          value: >-
                            {% set current_amps =
                            states('number.t_ray_charging_amps') | int %} {{
                            current_amps - 5 }}
                  - conditions:
                      - type: is_power
                        condition: device
                        device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
                        entity_id: sensor.pow_k_p
                        domain: sensor
                        above: 2752
                    sequence:
                      - service: number.set_value
                        data_template:
                          entity_id: number.t_ray_charging_amps
                          value: >-
                            {% set current_amps =
                            states('number.t_ray_charging_amps') | int %} {{
                            current_amps - 4 }}
                  - conditions:
                      - type: is_power
                        condition: device
                        device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
                        entity_id: sensor.pow_k_p
                        domain: sensor
                        above: 2064
                    sequence:
                      - service: number.set_value
                        data_template:
                          entity_id: number.t_ray_charging_amps
                          value: >-
                            {% set current_amps =
                            states('number.t_ray_charging_amps') | int %} {{
                            current_amps - 3 }}
                  - conditions:
                      - type: is_power
                        condition: device
                        device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
                        entity_id: sensor.pow_k_p
                        domain: sensor
                        above: 1376
                    sequence:
                      - service: number.set_value
                        data_template:
                          entity_id: number.t_ray_charging_amps
                          value: >-
                            {% set current_amps =
                            states('number.t_ray_charging_amps') | int %} {{
                            current_amps - 2 }}
                  - conditions:
                      - type: is_power
                        condition: device
                        device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
                        entity_id: sensor.pow_k_p
                        domain: sensor
                        above: 688
                    sequence:
                      - service: number.set_value
                        data_template:
                          entity_id: number.t_ray_charging_amps
                          value: >-
                            {% set current_amps =
                            states('number.t_ray_charging_amps') | int %} {{
                            current_amps - 1 }}
mode: single

Hi @Finnray

I wondered why you made the long list of conditions. Is there any obvious reason that you couldn’t just calculate the number you want to adjust the charging current with?
E.g:

      value: >-
            {{ states('number.charging_amps') | int - (states('sensor.active_import_average_5_min')|int / 688) | round(0,'floor') }}

Then you could make the automation much simpler.

And another thing: Did you choose the 30 seconds interval for some specific reason?
I don’t have a better value, but I choose every 5 minutes and made the export value a 5 minutes moving average.
Just because I thought it was too often to adjust the charging current more often than this. But I have no strong considerations behind my choice.

Hi @vester,

Thanks for your input. Calculating the charging current adjustment is definitely more rational. I just got down another avenue and blindsighted on that obvious improvement to the code.

The 30 second interval is because I want to adjust close to real time, so that any change in solar production (for instance a cloud passing) and house consumption (for instance a thermostat turning on the electric heating in my garage) is (almost) immediately reflected in the charging amps. Thus minimizing the import of power from the grid.

Here is my updated code:

alias: T-Ray solar charging
description: ""
trigger:
  # Time interval for triggering set
  - platform: time_pattern
    seconds: "30"
condition:
  # Continue if T-Ray is plugged in charger (or exit)  
  - type: is_plugged_in
    condition: device
    device_id: b4929c45bca6cfb24b68e22f7f0f9977
    entity_id: binary_sensor.t_ray_charger
    domain: binary_sensor
  # Continue if T-Ray SOC is below 1% of charge limit (or exit)      
  - condition: template
    value_template: >-
      {{(states('number.t_ray_charge_limit') | int -
      states('sensor.t_ray_battery') | int) > 1}}
action:
  # Continue if more than 688w EXPORT power is available (else)  
  - if:
      - type: is_power
        condition: device
        device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
        entity_id: sensor.pow_k_po
        domain: sensor
        above: 688
    then:
      # Turn ON charger if it is OFF and continue (or just continue)
      - if:
          - condition: device
            type: is_off
            device_id: b4929c45bca6cfb24b68e22f7f0f9977
            entity_id: switch.t_ray_charger
            domain: switch
        then:
          - type: turn_on
            device_id: b4929c45bca6cfb24b68e22f7f0f9977
            entity_id: switch.t_ray_charger
            domain: switch
      # Calculate number of charging amps to add relative to current EXPORT power  (Note: If current EXPORT power is below 688w -> no change)
      - service: number.set_value
        data_template:
          entity_id: number.t_ray_charging_amps
          value: >-
            {% set current_amps = states('number.t_ray_charging_amps') | int %}
            {% set add_amps = (states('sensor.pow_k_po') | int / 688) | round(0,'floor') %}
            {{ current_amps + add_amps }}
    else:
      # Check if power is being imported
      - if:
          - type: is_power
            condition: device
            device_id: 5ab015508a4f0ce2f17d992b8f68c3f0
            entity_id: sensor.pow_k_p
            domain: sensor
            above: 0
        then:
          # Turn OFF charger if power is being imported, but current charging power is below 550w and exit
          - if:
              - type: is_power
                condition: device
                device_id: 3efa4551c778fefe170f4c0c7b4dad6f
                entity_id: sensor.go_echarger_110504_nrg_12
                domain: sensor
                below: 550
            then:
              - type: turn_off
                device_id: b4929c45bca6cfb24b68e22f7f0f9977
                entity_id: switch.t_ray_charger
                domain: switch
            else:
              # Calculate number of charging amps to subtract relative to current IMPORT power (Note: If current IMPORT power is below 688w -> no change)
              - service: number.set_value
                data_template:
                  entity_id: number.t_ray_charging_amps
                  value: >-
                    {% set current_amps = states('number.t_ray_charging_amps') | int %}
                    {% set sub_amps = (states('sensor.pow_k_p') | int / 688) | round(0,'floor') %}
                    {{ current_amps - sub_amps }}
mode: single

3 Likes

Hi there,
Many thanks for all your work. I am a full novice to coding :rofl:
Got enphase solar, a shelly that shows the net total returned to the grid (positive value) or negative value if I import.
Also go 2 tesla home.
Got an issue: amps rapidly rocket to the max (32A) and then stop, but it seem to not adapt.
Here is the code, if you could help :slight_smile:

Alias: Cocotte solar charging
description: ""
trigger:
  - platform: time_pattern
    seconds: "30"
condition:
  - type: is_plugged_in
    condition: device
    device_id: b27fa242ee51ac63d7d7c1d3db0a2b99
    entity_id: binary_sensor.cocotte_charger
    domain: binary_sensor
  - condition: template
    value_template: >-
      {{(states('number.cocotte_charge_limit') | int -
      states('sensor.cocotte_battery') | int) > 1}}
  - condition: device
    device_id: b27fa242ee51ac63d7d7c1d3db0a2b99
    domain: device_tracker
    entity_id: device_tracker.cocotte_location_tracker
    type: is_home
action:
  - if:
      - type: is_power
        condition: device
        device_id: c65fef9bafaa8cbba8bf3eeb386fb2b8
        entity_id: sensor.shellyem_244cab43175e_channel_1_power
        domain: sensor
        above: 688
    then:
      - if:
          - condition: device
            type: is_off
            device_id: b27fa242ee51ac63d7d7c1d3db0a2b99
            entity_id: switch.cocotte_charger
            domain: switch
        then:
          - type: turn_on
            device_id: b27fa242ee51ac63d7d7c1d3db0a2b99
            entity_id: switch.cocotte_charger
            domain: switch
      - service: number.set_value
        data_template:
          entity_id: number.cocotte_charging_amps
          value: >-
            {% set current_amps = states('number.cocotte_charging_amps') | int
            %} {% set add_amps =
            (states('sensor.shellyem_244cab43175e_channel_1_power') | int / 688)
            | round(0,'floor') %} {{ current_amps + add_amps }}
    else:
      - if:
          - type: is_power
            condition: device
            device_id: c65fef9bafaa8cbba8bf3eeb386fb2b8
            entity_id: sensor.shellyem_244cab43175e_channel_1_power
            domain: sensor
            below: 300
        then:
          - if:
              - type: is_power
                condition: device
                device_id: c65fef9bafaa8cbba8bf3eeb386fb2b8
                entity_id: sensor.shellyem_244cab43175e_channel_2_power
                domain: sensor
                below: 6000
            then:
              - type: turn_off
                device_id: b27fa242ee51ac63d7d7c1d3db0a2b99
                entity_id: switch.cocotte_charger
                domain: switch
            else:
              - service: number.set_value
                data_template:
                  entity_id: number.cocotte_charging_amps
                  value: >-
                    {% set current_amps = states('number.cocotte_charging_amps')
                    | int %} {% set sub_amps =
                    (states('sensor.shellyem_244cab43175e_channel_1_power') |
                    int / 688) | round(0,'floor') %} {{ current_amps - sub_amps
                    }}
mode: single
1 Like

OP, is 688 the standard power draw for your house? I keep getting errors saying 17 is out of the range, which it is. 16 is the max ampage for my house.

I’m trying to work out where the math is going wrong.

@finnarne and everyone who is trying this. This is a great idea and thanks for sharing the code. I tried to make it work but i found one issue so far.

My condition always pass to check that Tesla charger in:
type: is_plugged_in
condition: device
device_id: 322d00bd1327c12f2a7be379c7ce50d2 (TeslaCar)
entity_id: 0b60e87852146865b8bd6a6394622eaf (TeslaCar Charger is plugged in)
domain: binary_sensor

My Car polling is on, i had to do force data update in that Tesla Custom Integration plugin. And here are my settings any recommendations?
image

Tesla at home also makes sense, that’s at least what I did :smiling_face:

Hello everyone :slight_smile: I’m new here, I’m trying to figure things out ! (Sorry for my bad English, I’m french !).
I just bought 6 solar panels for 2.88kw (plug and play), and of course, I would like to charge my tesla with the excess power instead of putting it into the grid. Home Assistant seems to be awesome and I can’t wait to get it (just bought a raspberryPi). You code is awesome, but how you car is connected, I mean with an EvStation (Mine is 7kw/h) ? Through a connected plug (max 3kw/h) ? Thank you !