jonasbkarlsson / ev_smart_charging

Electric vehicle smart charging for Home Assistant.
MIT License
175 stars 25 forks source link

Optimization for opportunistic charging #114

Open janneho opened 1 year ago

janneho commented 1 year ago

Is your feature request related to a problem? Please describe. No.

Describe the solution you'd like Have option to trigger opportunistic charging when tomorrows price is lower than this night, even if price for this night is under price limit. Picture attached for this night. Something that would trigger opportunistic charging when price for last hour of tomorrow is cheaper than it would be tonight (maybe even another slider so that if tomorrows price is 0-200% from the price it would cost tonight to charge after minium SOC has been reached).

Describe alternatives you've considered N/A

Additional context Thanks for integration, it has been working great!

Here is charging schedule for tonight. Price tonight is under price limit and opportunistic level limit. It clearly still would be chaper to charge to minium SOC (in picture current EV SOC>minium EV SOC), and charge to full next night. Prices vary so much from night to night, that it is hard to have fixed monetary limit. It would be easy to set percent limit that controls opportunistic charging (for example 110% from tonights price).

kuva

jonasbkarlsson commented 1 year ago

Thanks for the feedback and the question.

What is the SOC of the car? If it's below 60% (below the Minium EV SOC), then that could explain what you see.

janneho commented 1 year ago

It is 69% now.

Inam not good at explaining (in english). I mean that it would be nice to charge only to minium soc when price for tomorrow last hours are lower than it would be this night, even if prices for tonight are lower than set price limit/optimistic limit. Maybe even settable percentage.

For example if this nights price to charge over minium soc is 10cent and last price for tomorrow is 9 cent, charging is stopped at minium soc setting. Because prices almost allways drop even more after midnight, percentage setting would be nice (for example if price to charge over is 10cent, and last price next day is 11cent, and this setting is 80% it would still charge to minium soc only (11*0,8<10))

jonasbkarlsson commented 1 year ago

If you check the attributes of the main sensor entity, what is Charging is planned set to?

janneho commented 1 year ago

Charging is planned: true

jonasbkarlsson commented 1 year ago

Hmm. Weird. Can you paste all the attributes here? And what Target SOC and number.ev_smart_charging_charging_speed do you have?

janneho commented 1 year ago

Target SOC=80, charging speed 14

current_price: 14.303300000000002
EV SOC: 67
EV target SOC: 80
Charging is planned: true
Charging start time: 2023-01-27T00:00:00+02:00
Charging stop time: 2023-01-27T01:00:00+02:00
Charging number of hours: 1
raw_two_days: 
- start: '2023-01-26T00:00:00+02:00'
  end: '2023-01-26T01:00:00+02:00'
  value: 3.3011000000000004
- start: '2023-01-26T01:00:00+02:00'
  end: '2023-01-26T02:00:00+02:00'
  value: 4.2702
- start: '2023-01-26T02:00:00+02:00'
  end: '2023-01-26T03:00:00+02:00'
  value: 4.395600000000001
- start: '2023-01-26T03:00:00+02:00'
  end: '2023-01-26T04:00:00+02:00'
  value: 4.398900000000001
- start: '2023-01-26T04:00:00+02:00'
  end: '2023-01-26T05:00:00+02:00'
  value: 4.3703
- start: '2023-01-26T05:00:00+02:00'
  end: '2023-01-26T06:00:00+02:00'
  value: 4.4
- start: '2023-01-26T06:00:00+02:00'
  end: '2023-01-26T07:00:00+02:00'
  value: 4.9544
- start: '2023-01-26T07:00:00+02:00'
  end: '2023-01-26T08:00:00+02:00'
  value: 10.440100000000001
- start: '2023-01-26T08:00:00+02:00'
  end: '2023-01-26T09:00:00+02:00'
  value: 13.9634
- start: '2023-01-26T09:00:00+02:00'
  end: '2023-01-26T10:00:00+02:00'
  value: 14.323100000000002
- start: '2023-01-26T10:00:00+02:00'
  end: '2023-01-26T11:00:00+02:00'
  value: 14.257100000000001
- start: '2023-01-26T11:00:00+02:00'
  end: '2023-01-26T12:00:00+02:00'
  value: 14.434200000000002
- start: '2023-01-26T12:00:00+02:00'
  end: '2023-01-26T13:00:00+02:00'
  value: 14.433100000000005
- start: '2023-01-26T13:00:00+02:00'
  end: '2023-01-26T14:00:00+02:00'
  value: 14.484800000000003
- start: '2023-01-26T14:00:00+02:00'
  end: '2023-01-26T15:00:00+02:00'
  value: 13.885300000000003
- start: '2023-01-26T15:00:00+02:00'
  end: '2023-01-26T16:00:00+02:00'
  value: 13.667500000000002
- start: '2023-01-26T16:00:00+02:00'
  end: '2023-01-26T17:00:00+02:00'
  value: 14.3836
- start: '2023-01-26T17:00:00+02:00'
  end: '2023-01-26T18:00:00+02:00'
  value: 14.6311
- start: '2023-01-26T18:00:00+02:00'
  end: '2023-01-26T19:00:00+02:00'
  value: 14.777400000000002
- start: '2023-01-26T19:00:00+02:00'
  end: '2023-01-26T20:00:00+02:00'
  value: 14.826900000000002
- start: '2023-01-26T20:00:00+02:00'
  end: '2023-01-26T21:00:00+02:00'
  value: 14.303300000000002
- start: '2023-01-26T21:00:00+02:00'
  end: '2023-01-26T22:00:00+02:00'
  value: 12.1308
- start: '2023-01-26T22:00:00+02:00'
  end: '2023-01-26T23:00:00+02:00'
  value: 11.718300000000001
- start: '2023-01-26T23:00:00+02:00'
  end: '2023-01-27T00:00:00+02:00'
  value: 7.591100000000001
- start: '2023-01-27T00:00:00+02:00'
  end: '2023-01-27T01:00:00+02:00'
  value: 6.7188
- start: '2023-01-27T01:00:00+02:00'
  end: '2023-01-27T02:00:00+02:00'
  value: 8.6416
- start: '2023-01-27T02:00:00+02:00'
  end: '2023-01-27T03:00:00+02:00'
  value: 9.0101
- start: '2023-01-27T03:00:00+02:00'
  end: '2023-01-27T04:00:00+02:00'
  value: 10.071600000000002
- start: '2023-01-27T04:00:00+02:00'
  end: '2023-01-27T05:00:00+02:00'
  value: 10.445599999999999
- start: '2023-01-27T05:00:00+02:00'
  end: '2023-01-27T06:00:00+02:00'
  value: 12.036200000000001
- start: '2023-01-27T06:00:00+02:00'
  end: '2023-01-27T07:00:00+02:00'
  value: 13.550899999999999
- start: '2023-01-27T07:00:00+02:00'
  end: '2023-01-27T08:00:00+02:00'
  value: 16.2129
- start: '2023-01-27T08:00:00+02:00'
  end: '2023-01-27T09:00:00+02:00'
  value: 19.371000000000002
- start: '2023-01-27T09:00:00+02:00'
  end: '2023-01-27T10:00:00+02:00'
  value: 21.450000000000003
- start: '2023-01-27T10:00:00+02:00'
  end: '2023-01-27T11:00:00+02:00'
  value: 21.1717
- start: '2023-01-27T11:00:00+02:00'
  end: '2023-01-27T12:00:00+02:00'
  value: 17.6
- start: '2023-01-27T12:00:00+02:00'
  end: '2023-01-27T13:00:00+02:00'
  value: 17.0423
- start: '2023-01-27T13:00:00+02:00'
  end: '2023-01-27T14:00:00+02:00'
  value: 17.598900000000004
- start: '2023-01-27T14:00:00+02:00'
  end: '2023-01-27T15:00:00+02:00'
  value: 16.4978
- start: '2023-01-27T15:00:00+02:00'
  end: '2023-01-27T16:00:00+02:00'
  value: 13.561900000000001
- start: '2023-01-27T16:00:00+02:00'
  end: '2023-01-27T17:00:00+02:00'
  value: 10.9406
- start: '2023-01-27T17:00:00+02:00'
  end: '2023-01-27T18:00:00+02:00'
  value: 9.3511
- start: '2023-01-27T18:00:00+02:00'
  end: '2023-01-27T19:00:00+02:00'
  value: 12.9602
- start: '2023-01-27T19:00:00+02:00'
  end: '2023-01-27T20:00:00+02:00'
  value: 13.390300000000002
- start: '2023-01-27T20:00:00+02:00'
  end: '2023-01-27T21:00:00+02:00'
  value: 8.5151
- start: '2023-01-27T21:00:00+02:00'
  end: '2023-01-27T22:00:00+02:00'
  value: 4.811400000000001
- start: '2023-01-27T22:00:00+02:00'
  end: '2023-01-27T23:00:00+02:00'
  value: 5.4472000000000005
- start: '2023-01-27T23:00:00+02:00'
  end: '2023-01-28T00:00:00+02:00'
  value: 3.5134000000000007

charging_schedule: 
- start: '2023-01-26T00:00:00+02:00'
  end: '2023-01-26T01:00:00+02:00'
  value: 0
- start: '2023-01-26T01:00:00+02:00'
  end: '2023-01-26T02:00:00+02:00'
  value: 0
- start: '2023-01-26T02:00:00+02:00'
  end: '2023-01-26T03:00:00+02:00'
  value: 0
- start: '2023-01-26T03:00:00+02:00'
  end: '2023-01-26T04:00:00+02:00'
  value: 0
- start: '2023-01-26T04:00:00+02:00'
  end: '2023-01-26T05:00:00+02:00'
  value: 0
- start: '2023-01-26T05:00:00+02:00'
  end: '2023-01-26T06:00:00+02:00'
  value: 0
- start: '2023-01-26T06:00:00+02:00'
  end: '2023-01-26T07:00:00+02:00'
  value: 0
- start: '2023-01-26T07:00:00+02:00'
  end: '2023-01-26T08:00:00+02:00'
  value: 0
- start: '2023-01-26T08:00:00+02:00'
  end: '2023-01-26T09:00:00+02:00'
  value: 0
- start: '2023-01-26T09:00:00+02:00'
  end: '2023-01-26T10:00:00+02:00'
  value: 0
- start: '2023-01-26T10:00:00+02:00'
  end: '2023-01-26T11:00:00+02:00'
  value: 0
- start: '2023-01-26T11:00:00+02:00'
  end: '2023-01-26T12:00:00+02:00'
  value: 0
- start: '2023-01-26T12:00:00+02:00'
  end: '2023-01-26T13:00:00+02:00'
  value: 0
- start: '2023-01-26T13:00:00+02:00'
  end: '2023-01-26T14:00:00+02:00'
  value: 0
- start: '2023-01-26T14:00:00+02:00'
  end: '2023-01-26T15:00:00+02:00'
  value: 0
- start: '2023-01-26T15:00:00+02:00'
  end: '2023-01-26T16:00:00+02:00'
  value: 0
- start: '2023-01-26T16:00:00+02:00'
  end: '2023-01-26T17:00:00+02:00'
  value: 0
- start: '2023-01-26T17:00:00+02:00'
  end: '2023-01-26T18:00:00+02:00'
  value: 0
- start: '2023-01-26T18:00:00+02:00'
  end: '2023-01-26T19:00:00+02:00'
  value: 0
- start: '2023-01-26T19:00:00+02:00'
  end: '2023-01-26T20:00:00+02:00'
  value: 0
- start: '2023-01-26T20:00:00+02:00'
  end: '2023-01-26T21:00:00+02:00'
  value: 0
- start: '2023-01-26T21:00:00+02:00'
  end: '2023-01-26T22:00:00+02:00'
  value: 0
- start: '2023-01-26T22:00:00+02:00'
  end: '2023-01-26T23:00:00+02:00'
  value: 0
- start: '2023-01-26T23:00:00+02:00'
  end: '2023-01-27T00:00:00+02:00'
  value: 0
- start: '2023-01-27T00:00:00+02:00'
  end: '2023-01-27T01:00:00+02:00'
  value: 16.087500000000002
- start: '2023-01-27T01:00:00+02:00'
  end: '2023-01-27T02:00:00+02:00'
  value: 0
- start: '2023-01-27T02:00:00+02:00'
  end: '2023-01-27T03:00:00+02:00'
  value: 0
- start: '2023-01-27T03:00:00+02:00'
  end: '2023-01-27T04:00:00+02:00'
  value: 0
- start: '2023-01-27T04:00:00+02:00'
  end: '2023-01-27T05:00:00+02:00'
  value: 0
- start: '2023-01-27T05:00:00+02:00'
  end: '2023-01-27T06:00:00+02:00'
  value: 0
- start: '2023-01-27T06:00:00+02:00'
  end: '2023-01-27T07:00:00+02:00'
  value: 0
- start: '2023-01-27T07:00:00+02:00'
  end: '2023-01-27T08:00:00+02:00'
  value: 0
- start: '2023-01-27T08:00:00+02:00'
  end: '2023-01-27T09:00:00+02:00'
  value: 0
- start: '2023-01-27T09:00:00+02:00'
  end: '2023-01-27T10:00:00+02:00'
  value: 0
- start: '2023-01-27T10:00:00+02:00'
  end: '2023-01-27T11:00:00+02:00'
  value: 0
- start: '2023-01-27T11:00:00+02:00'
  end: '2023-01-27T12:00:00+02:00'
  value: 0
- start: '2023-01-27T12:00:00+02:00'
  end: '2023-01-27T13:00:00+02:00'
  value: 0
- start: '2023-01-27T13:00:00+02:00'
  end: '2023-01-27T14:00:00+02:00'
  value: 0
- start: '2023-01-27T14:00:00+02:00'
  end: '2023-01-27T15:00:00+02:00'
  value: 0
- start: '2023-01-27T15:00:00+02:00'
  end: '2023-01-27T16:00:00+02:00'
  value: 0
- start: '2023-01-27T16:00:00+02:00'
  end: '2023-01-27T17:00:00+02:00'
  value: 0
- start: '2023-01-27T17:00:00+02:00'
  end: '2023-01-27T18:00:00+02:00'
  value: 0
- start: '2023-01-27T18:00:00+02:00'
  end: '2023-01-27T19:00:00+02:00'
  value: 0
- start: '2023-01-27T19:00:00+02:00'
  end: '2023-01-27T20:00:00+02:00'
  value: 0
- start: '2023-01-27T20:00:00+02:00'
  end: '2023-01-27T21:00:00+02:00'
  value: 0
- start: '2023-01-27T21:00:00+02:00'
  end: '2023-01-27T22:00:00+02:00'
  value: 0
- start: '2023-01-27T22:00:00+02:00'
  end: '2023-01-27T23:00:00+02:00'
  value: 0
- start: '2023-01-27T23:00:00+02:00'
  end: '2023-01-28T00:00:00+02:00'
  value: 0

icon: mdi:flash
friendly_name: EV Smart Charging Charging
jonasbkarlsson commented 1 year ago

Thanks. I will look into this more.

By the way, did this happen directly after restarting Home Assistant?

If you click on "Smart charging activated" twice (to turn it off and then on again), the charging schedule should be recalculated, and maybe that will give you a correct charging schedule.

janneho commented 1 year ago

Maybe i explained this badly.

it recalculates it ok. It changes when i change price limit etc. If i understand opportunistic mode right, this is how it should work now? It is scheduled 1 hour at 0.00, That is cheapest hour before 7.00 (completion.time). Also at 0.00 price is 6,72cent < 12cent0,6 (Price limit Opportunistic level).

What i am suggesting that there is new/alternative mechanism for opportunistic charging that works something like this temp When price at A is higher than at B * settable percent, only charge to minimum SOC and do not care at all what price limit is set at. Here A is first cheapest hour AFTER minimum SOC has been reached.

jonasbkarlsson commented 1 year ago

I understand what you mean. What you ask for is how it should work. If opportunistic charging is enabled, there shouldn't be any charging at A. And since you have set the completion time to 07:00, then there should not be any charging at B either now. The charging at B should appear after noon tomorrow, after the prices for the day after tomorrow is available.

So if you have had opportunistic charging enabled and the integration has scheduled charging at A, then there is something wrong.

janneho commented 1 year ago

Ok. i did not understand opportunistic charging right then. Now it just seems to lower price limit to Electricity price limit * Opportunistic level / 100 when I have opportunistic charging on.

I understand that there should not be any scheduled charging at B, Price at B should still used as Electricity price limit as it is lower than any price between now and 7:00 morning?

jonasbkarlsson commented 1 year ago

Sorry. Now I looked again. I did missunderstood you.

There is no bug in the code. It is working as intended.

My intention was that if the last hour tomorrow has a price less than Electricity price limit * Opportunistic level / 100 then the price limit will be lowered to Electricity price limit * Opportunistic level / 100.

I think what you ask for could be expressed as in addition to lower the price limit, the select.ev_smart_charging_charge_completion_time should be ignored.

jonasbkarlsson commented 1 year ago

So then it will become like this instead:

image
janneho commented 1 year ago

Kinda yes. but also no.

If select.ev_smart_charging_charge_completion_time is set, it must always be scheduled to meet minium ev soc limit to be charged before that. If price for last hours next day (black bar in your drawing) is lower than lowest price before select.ev_smart_charging_charge_completion_time (after reaching minimum soc level), then stop charging for this session. No need to calculate any electricity price limit/opportunistic level, becouse it is 100% sure that next night is cheaper in any case (atleast for first hour or so).

jonasbkarlsson commented 1 year ago

Yes, agree. And then it becomes much more complicated than I first thought. The integration is now started to reach the limit on how complicated rules the current design can handle. I need to think if this can be achieve with a reasonable effort.

Note that another way to look at this is that you could have set number.ev_smart_charging_opportunistic_level to a lower value if you wanted to be more agressive in the opportunistic savings. If it had been set to 50%, you wouldn't had get any scheduled charging this night.

janneho commented 1 year ago

What if last hour of tomorrow * opportunistic level (50%-150%) is used as Electricity price limit?

I would like to have some kind of set and forget, that is why this automation is so good. But when electricity price range from 0,5cent to 50cent/kwh in one month, it is impossible to set any limits to price that would work. We all know that if last hour of tomorrow is lower than tonight, it is more than likely cheaper to postpone charging. That is not fixed as electricity price limit is.

jonasbkarlsson commented 1 year ago

Thanks for that suggestion. That would be easy to implement. Let me think about that.

It is my intention to make it "set and forget".

jonasbkarlsson commented 1 year ago

The intention of the current switch.ev_smart_charging_apply_price_limit is to avoid charging at home if the electrity price is high compared to other ways of charging, such as public charging or charging at you work place.

And then switch.ev_smart_charging_opportunistic_charging was added to make it possible to optimize the cost a little more.

Now, with the suggestion "last hour of tomorrow * opportunistic level (50%-150%) is used as Electricity price limit", the orignal fixed price set by switch.ev_smart_charging_apply_price_limit is not used at all, right?

So my observation is that this suggestion is not an improvement of the current switch.ev_smart_charging_apply_price_limit and switch.ev_smart_charging_opportunistic_charging, but a suggestion to have a different strategy to limit charging. And this strategy does not have an upper limit on the electricity price, meaning that charging will happen even if the price might be very high.

Would you agree on that? And is that what you really want? I don't think that was in your original request.

janneho commented 1 year ago

That would be ok for me. Charging to min soc for whatever price should be done anyways.

Is it possible to leave price limit as it is, and have option to turn this new limit on? When using price limit, we are allready ok with the possibility that charging stops on minium soc level.

Then i ihink that logick could be something like this. If (price to charge over minimum soc) > (price limit OR last price next day) --> only charge to minimum soc. So use price last hour next day if it is lower than price limit, if not then use price limit.

oveand commented 1 year ago

Sorry for interfering but was trying out the opportunistic charging feature and didn't really understand how this was calculated, was first looking into the code/PR, which lead me to this issue.

I just want to quickly describe my take on this challenge. Every day I compute a custom price limit as an average of the price at 23:00 today and the price at 23:00 tomorrow, i.e., if today's price at 23:00 is DKK 1.50 and tomorrows price at 23:00 is DKK 1.10 then I will set a custom price limit of DKK 1.30. This has been working out quite well for a month and will keep postpone charging "until tomorrow" if the price is continuously dropping. Of cause minimum SoC is still obeyed as long as the original price limit is the max. An opportunistic level could of cause balance how strict towards highest vs lowest "23:00" price one wants to set the custom limit, though for me an average price has worked out quite well.

Just my 2 cents..

janneho commented 1 year ago

That is about same as i am doing (except we got prices always to 1;00 morning).

So if instead just using fixed price limit, could we use last price (1:00 here) as limit if it is lower than fixed price limit? And maybe settable percent on top of last price.

So when price limit is 10cent, and last price tomorrow is 11 cent, limit would be 10 as it is now. If last price tomorrow is 9 cent, use that as price limit instead of 10 cent. I have used tomorrows last price-10%, but i thik average could also work as well if not even better.

oveand commented 1 year ago

@janneho Yes this does indeed sound quite like the same approach, defining a variable max price limit to either prioritize charging this night, if price seems lower, or postpone until tomorrow if we estimate prices will drop lower then. I started out using lowest price of tonight 23 vs tomorrow at 23 (last avaliable hour in DK) but sometimes prices doesn't drop any further during the night and only few hours were able to charge due to limit. I guess the usual price variations may vary between countries?

janneho commented 1 year ago

It really is somewhat guessing for tomorrows price but it works quite well and do not charge if tomorrows price is lower.

I have made quick dumb hacky automation, that somewhat works... It just calculates limits at 15:00 (we get new prices at 14:00) Everything is hard coded, 10 cent is max price limit.

description: Calculate limit from nordpool
trigger:
  - platform: time
    at: "15:00:00"
condition: []
action:
  - if:
      - condition: template
        value_template: >-
          {{ (((state_attr('sensor.nordpool_kwh_fi_eur_3_10_01', 'today')[23]) +
          (state_attr('sensor.nordpool_kwh_fi_eur_3_10_01', 'tomorrow')[23])) /
          2) < 10}}
    then:
      - service: number.set_value
        data:
          value: >-
            {{ ((state_attr('sensor.nordpool_kwh_fi_eur_3_10_01', 'today')[23])
            + (state_attr('sensor.nordpool_kwh_fi_eur_3_10_01',
            'tomorrow')[23])) /2}}
        target:
          entity_id: number.ev_smart_charging_electricity_price_limit
    else:
      - service: number.set_value
        data:
          value: "10"
        target:
          entity_id: number.ev_smart_charging_electricity_price_limit
mode: single
oveand commented 1 year ago

Lol, almost a 1:1 copy of my automation, except I use energi data service 😁

oveand commented 1 year ago

fun_power Though some times this rule of thumb just does not apply :)

janneho commented 1 year ago

It is true that it does not always work. But still a lot better than fixed limit.

I have used this for a month for price limit, and it does work really well. So no averaging, just last price.

{{ ((state_attr('sensor.nordpool_kwh_fi_eur_3_10_01',
            'tomorrow')[23]) )}}