ottopaulsen / node-red-contrib-power-saver

A Node-RED node to saver money by turning off when the power is most expensive
Other
71 stars 17 forks source link

best save not working well #86

Open vidarak opened 1 year ago

vidarak commented 1 year ago

bestsave heats my water at too many expensive hours. It's configured with 2H recovery but runs at least 4 hours/day - and tomorrow will run 7 hours of which 4 are quite expensive compared to the 3 cheapest hours that day (which SHOULD have been the only hours picked). image

{"schedule":[{"time":"2022-09-16T00:00:00+02:00","value":false,"countHours":4},{"time":"2022-09-16T04:00:00+02:00","value":true,"countHours":4},{"time":"2022-09-16T08:00:00+02:00","value":false,"countHours":22},{"time":"2022-09-17T06:00:00+02:00","value":true,"countHours":2},{"time":"2022-09-17T08:00:00+02:00","value":false,"countHours":8},{"time":"2022-09-17T16:00:00+02:00","value":true,"countHours":2},{"time":"2022-09-17T18:00:00+02:00","value":false,"countHours":1},{"time":"2022-09-17T19:00:00+02:00","value":true,"countHours":1},{"time":"2022-09-17T20:00:00+02:00","value":false,"countHours":2},{"time":"2022-09-17T22:00:00+02:00","value":true,"countHours":2}],"hours":[{"price":2.8061,"onOff":false,"start":"2022-09-16T00:00:00+02:00","saving":0.522},{"price":2.5601,"onOff":false,"start":"2022-09-16T01:00:00+02:00","saving":0.276},{"price":3.2771,"onOff":false,"start":"2022-09-16T02:00:00+02:00","saving":0.993},{"price":2.7001,"onOff":false,"start":"2022-09-16T03:00:00+02:00","saving":0.416},{"price":2.2841,"onOff":true,"start":"2022-09-16T04:00:00+02:00","saving":null},{"price":3.1831,"onOff":true,"start":"2022-09-16T05:00:00+02:00","saving":null},{"price":5.1421,"onOff":true,"start":"2022-09-16T06:00:00+02:00","saving":null},{"price":5.8301,"onOff":true,"start":"2022-09-16T07:00:00+02:00","saving":null},{"price":5.7561,"onOff":false,"start":"2022-09-16T08:00:00+02:00","saving":4.146},{"price":5.5991,"onOff":false,"start":"2022-09-16T09:00:00+02:00","saving":3.989},{"price":5.6261,"onOff":false,"start":"2022-09-16T10:00:00+02:00","saving":4.016},{"price":5.6081,"onOff":false,"start":"2022-09-16T11:00:00+02:00","saving":3.998},{"price":5.6651,"onOff":false,"start":"2022-09-16T12:00:00+02:00","saving":4.055},{"price":5.6431,"onOff":false,"start":"2022-09-16T13:00:00+02:00","saving":4.033},{"price":5.6411,"onOff":false,"start":"2022-09-16T14:00:00+02:00","saving":4.031},{"price":5.6261,"onOff":false,"start":"2022-09-16T15:00:00+02:00","saving":4.016},{"price":5.5781,"onOff":false,"start":"2022-09-16T16:00:00+02:00","saving":3.968},{"price":3.8571,"onOff":false,"start":"2022-09-16T17:00:00+02:00","saving":2.247},{"price":4.6161,"onOff":false,"start":"2022-09-16T18:00:00+02:00","saving":3.006},{"price":5.2701,"onOff":false,"start":"2022-09-16T19:00:00+02:00","saving":3.66},{"price":5.0891,"onOff":false,"start":"2022-09-16T20:00:00+02:00","saving":3.479},{"price":3.4701,"onOff":false,"start":"2022-09-16T21:00:00+02:00","saving":1.86},{"price":3.8851,"onOff":false,"start":"2022-09-16T22:00:00+02:00","saving":2.275},{"price":3.3911,"onOff":false,"start":"2022-09-16T23:00:00+02:00","saving":1.781},{"price":5.3271,"onOff":false,"start":"2022-09-17T00:00:00+02:00","saving":3.717},{"price":5.0041,"onOff":false,"start":"2022-09-17T01:00:00+02:00","saving":3.394},{"price":3.5241,"onOff":false,"start":"2022-09-17T02:00:00+02:00","saving":1.914},{"price":3.5031,"onOff":false,"start":"2022-09-17T03:00:00+02:00","saving":1.893},{"price":3.4931,"onOff":false,"start":"2022-09-17T04:00:00+02:00","saving":1.883},{"price":2.9181,"onOff":false,"start":"2022-09-17T05:00:00+02:00","saving":1.308},{"price":1.6101,"onOff":true,"start":"2022-09-17T06:00:00+02:00","saving":null},{"price":3.6631,"onOff":true,"start":"2022-09-17T07:00:00+02:00","saving":null},{"price":3.4731,"onOff":false,"start":"2022-09-17T08:00:00+02:00","saving":2.484},{"price":5.4191,"onOff":false,"start":"2022-09-17T09:00:00+02:00","saving":4.43},{"price":5.4881,"onOff":false,"start":"2022-09-17T10:00:00+02:00","saving":4.499},{"price":5.4021,"onOff":false,"start":"2022-09-17T11:00:00+02:00","saving":4.413},{"price":5.4131,"onOff":false,"start":"2022-09-17T12:00:00+02:00","saving":4.424},{"price":3.4631,"onOff":false,"start":"2022-09-17T13:00:00+02:00","saving":2.474},{"price":2.8711,"onOff":false,"start":"2022-09-17T14:00:00+02:00","saving":1.882},{"price":2.9381,"onOff":false,"start":"2022-09-17T15:00:00+02:00","saving":1.949},{"price":0.9891,"onOff":true,"start":"2022-09-17T16:00:00+02:00","saving":null},{"price":1.4051,"onOff":true,"start":"2022-09-17T17:00:00+02:00","saving":null},{"price":3.5291,"onOff":false,"start":"2022-09-17T18:00:00+02:00","saving":0.128},{"price":3.4011,"onOff":true,"start":"2022-09-17T19:00:00+02:00","saving":null},{"price":4.8271,"onOff":false,"start":"2022-09-17T20:00:00+02:00","saving":1.262},{"price":5.5131,"onOff":false,"start":"2022-09-17T21:00:00+02:00","saving":1.948},{"price":3.5651,"onOff":true,"start":"2022-09-17T22:00:00+02:00","saving":null},{"price":3.8011,"onOff":true,"start":"2022-09-17T23:00:00+02:00","saving":null}],"source":"Nordpool","config":{"maxHoursToSaveInSequence":"22","minHoursOnAfterMaxSequenceSaved":"2","minSaving":0.02,"sendCurrentValueWhenRescheduling":true,"outputIfNoSchedule":false,"contextStorage":"memory"},"sentOnCommand":false,"time":"2022-09-16T23:40:41.117+02:00","version":"3.6.2","current":false}

ottopaulsen commented 1 year ago

I believe you have interpreted the result incorrect. It finds the best saving at 08:00 on the 16th, and it saves for 22 hours, that is your maximum. That period is selected first. Then it selects some additional periods that also gives savings, but there is no room for other that long periods. This is how Best Save is supposed to work. You can try yourself here: https://powersaver.no/faq/best-save-viewer.html#tool

If you expect another result, maybe what you need is the Lowest Price node?

vidarak commented 1 year ago

I guess I want a lowest price node that finds the lowest price for the configured amount of non-consecutive hours but still provides power on other scattered hours where the price is low (a configurable % diff from min/avg/max) in the selected period.

Regardless, bestsave logic/idea seems a bit broken. If it is set with recovery for 2 hours after a 22 hour period, there is no need for bestsave to power on for 2 consecutive much pricier hours at scattered times within the 22 hour saving period as well. It should only power on for single hours beyond the 2 hours configured for recovery.

I don't understand why these would be ON since their price is much higher than the minimum price in that period: {"price":3.4011,"onOff":true,"start":"2022-09-17T19:00:00+02:00","saving":null}, {"price":3.5651,"onOff":true,"start":"2022-09-17T22:00:00+02:00","saving":null}, {"price":3.8011,"onOff":true,"start":"2022-09-17T23:00:00+02:00","saving":null}

ottopaulsen commented 1 year ago

I dont't think you understand the idea with the Best Save node. It assumes that energy is consumed more or less continuously, like you do with a water heater, for example, or a jacuzzi, etc. However, it is also assumed that you can postpone the "replacement" of the consumed energy, that is you can postpone heating the water, and the idea is that you can postpone this up to a certain number of hours. But you postpone only if that makes you save money. If there is nothing to save, there is no reason to postpone. Then you can just as well heat the water immediately.

For me it makes little sense to postpone for 22 hours. If that is ok, you can just look for the 2 cheapest hours in the whole day and use them. That is what you do with the Lowest Price node. The Best Save node looks for the optimal places to postpone consumption within the rules that are configured. And it is absolutely not broken. And as far as I can see it is working well in your case too. Maybe not what you want, but it is working as it is supposed to do.

vidarak commented 1 year ago

I'm using it for my water heater. Usually 2 hours/day is enough. Sometimes not (so I wouldn't mind it to heating the water during some slightly more expensive hours also - especially if they are scattered a bit throughout the day).

I just think in my example it shouldn't have planned to heat water in the mentioned hours where the price was 2x or 3x higher than just a few hours earlier in that day.

On the 16th it shouldn't have heated these hours: {"price":5.1421,"onOff":true,"start":"2022-09-16T06:00:00+02:00","saving":null} {"price":5.8301,"onOff":true,"start":"2022-09-16T07:00:00+02:00","saving":null} (which were directly following these much cheaper hours: {"price":2.2841,"onOff":true,"start":"2022-09-16T04:00:00+02:00","saving":null} {"price":3.1831,"onOff":true,"start":"2022-09-16T05:00:00+02:00","saving":null}

Instead if could have heated these hours on the 16th: {"price":3.4701,"onOff":false,"start":"2022-09-16T21:00:00+02:00","saving":1.86} {"price":3.3911,"onOff":false,"start":"2022-09-16T23:00:00+02:00","saving":1.781}

Are you able to explain why you think the bestsave plan in my example is better than my proposal?

Consider this; on 16th the plan started heating at 4AM. At this point and also at 5AM, 6AM and 7AM it only knows the price until midnight... so it doesn't know the price 22 hours ahead. It does however know that at 9PM and 11PM (last hour it knows the price for) the price is going to be cheaper than at 6AM and 7AM. Despite this, it choses to heat 6AM-7AM (Directly after a 2-hour recovery period where one would expect the water to be fully heated)...? It just doesn't make sense.

marhoy commented 1 year ago

@vidarak What @ottopaulsen said.

If you want to make sure you heat water at the cheapest periods, use the "lowest price" node. I'm using two of them, each looking at a 12hour interval, to make sure I run the heater at least a couple of hours every 12 hours. See my response here for details.

vidarak commented 1 year ago

Thanks, I'm not a developer but I was hoping to fix this by building my own forked and optimized powersaver module. As a start, I'm now using the dynamic configuration option. image It checks if tomorrow's price data is available and configures Lowest Price from 14:00 to 14:00 based on that. (if not, from 00 to 00). It also looks at price deviation beyond the configured hours while considering how many hours have passed since the water last reached max temp (no power drawn while switch is still on) to possibly add a couple of extra hours. If the price in the evening (2300) is high (prices likely trending upwards) it will try adding an extra hour today. If the price in the evening is low, it will avoid adding extra hours that day (anticipating lower prices the next day). Saturdays and Sundays I add an extra hour just because prices are typically low. Code is ugly and not rigorously tested/tuned so prefer not to share publicly yet (It should have heated 2 hours today). ;-)

olle-j commented 1 year ago

I have a very similar issue, that is clearly visible in the chart above. The algorithm above finds the hour with lowest cost, and then run for the recovery time.

The issue I have is that the lowest cost for the recovering time may not start on the our with lowest cost, it may very well be some hours before if you are recovering for several hours.

Take a look at the image from @vidarak. It starts at about 6 in the morning, and then recovers during the most costly time of day. That is because the least costly and most costly hours are next to each other.

What would be more interesting, for an end user perspective, is to have the recovery during the least costly period, not starting on the least costly hour. In this case it may have been better to start an hour earlier to avoid the very costly time.

Instead of doing:

Consider doing:

ottopaulsen commented 1 year ago

It is true that the algorithm assumes that you recover all the saved energy during the first hour of recovery, and as you suggest, it would have been more accurate to use the average price for all the recovery hours. I will consider making such a change.