Control a water heater and ground source heat pump based on cheap hours of spot priced electricity

Can you just use a static number of hours that you allow for every day? Or does the needed heating depend on your outside temperature? To allow 1 hour (the cheapest hour of the day), you would do like this:

dh = require('kolapuuntie/date-helper.js');
nibe = require('kolapuuntie/nibe.js');
influx = require('kolapuuntie/influx.js');

start = dh.getMidnight('start');
stop = dh.getMidnight('stop');

// Allow 1 hour of heating every day
n = 1;

// Don't split the day into slices
slices = 1;

// Slices are not used, this is not needed.
min_heating = 0;

// Prepare and save the control points to the database
points = nibe.determineHours(start, stop, n, slices, min_heating);
influx.writePoints('balboa_control', points);

Your rule could be called like “DetermineCarChargingHours”, which would be very similar than the script actions you have used above. You would not run that on schedule basis, but you would trigger this rule “When CarNeedsToBeReady item has changed”.

In this script action, you could read the number of needed hours (the variable “n”) as follows:

// Read desired amount of hours and cast float to int.
item = items.getItem("CarChargingHours");
n = Math.round(item.state);

Similarly, you would modify these two lines:

start = dh.getMidnight('start');
stop = dh.getMidnight('stop');

“start” would no longer be a midnight, but you would populate the current datetime there, and “stop” would not be the next midnight, it would be the datetime you had entered using the datetime input. I’ll leave this as an exercise to you.

You could do for example something like this:

  1. Create an Item and input slider where you can select how many hours you want to charge the car
    image

  2. Create another Item and datetime widget where you can define when the car needs to be charged
    image

  3. Create a rule, which says that “after the datetime Item has been updated, find the X cheapest hours between now and the time when the car needs to be ready”, where X is the number you defined with the slider. You can either use the waterheater.js for this, if you want that the charging must not get interrupted, or nibe.js, if it is OK that the charging gets interrupted in between.

This is exactly what I and many others are looking for. Great work!
But many are not that Openhab savvy.
Do you think you could make a binding of it? At least the fetching of spot prices part?

Unfortunately I don’t have time to make this a binding and to support it. I have a day job, family with small kids and I’m an athlete playing on World Championships level so I just don’t have enough hours in my days.

The code is published above, so anyone wishing to take over and make this a binding is more than welcome to do so.

@masipila

Thanks for more input and an interesting idea, I will try to make this kind of happen but I will test out a wife friendley concept that takes timestamp from connecting te car as start and have a static stop as tomoroow att 07:00 which I later on may get from Kia api I set ready to go time in kia app, and thats pretty much allmost set to 07:00 and the the car itselfs handles to get charged and warm in the wintertime.

All this will take sometime due to busy weekends for the coming months, so I may onlys start with timestamp and a static ready time.

1 Like

I’m closing into the target I created a DateTime item Evconnected that updates when charger operation mode changes from disconnected to waiting for smart charging, however it throws errors when i try to consume that item in script

Log output using datetimeitem.state to string
11:04:15.681 [INFO ] [org.openhab.core.model.script.test ] - 2022-09-02T11:01:17.024534+0200

Log output using datteimitem.state
11:09:15.715 [INFO ] [org.openhab.core.model.script.test ] - Tidpunkt 2022-09-02T11:06:17.020741+0200

Here’s some methods i Tested no one rally works it ends upp with errors

//start_item = time.toZDT(items.getItem("Evconnected"));
//stop_item = items.getItem("EvCarReady").rawState;
start = dh.getMidnight('start');
stop = dh.getMidnight('stop');
//start = (start_item.state);
//stop = (stop_item.state);


Failed to execute script:
org.graalvm.polyglot.PolyglotException: TypeError: undefined has no such function "toISOString"
        at <js>.getPoints(/openhab/conf/automation/js/node_modules/kolapuuntie/influx.js:101) ~[?:?]
        at <js>.getPrices(/openhab/conf/automation/js/node_modules/kolapuuntie/influx.js:74) ~[?:?]
        at <js>.determineHours(/openhab/conf/automation/js/node_modules/kolapuuntie/nibe.js:129) ~[?:?]
        at <js>.:program(<eval>:15) ~[?:?]
        at org.graalvm.polyglot.Context.eval(Context.java:379) ~[?:?]

Quick comments without having a chance to dive too deep in this.

//start_item = time.toZDT(items.getItem("Evconnected"));
//stop_item = items.getItem("EvCarReady").rawState;
start = dh.getMidnight('start');
stop = dh.getMidnight('stop');
//start = (start_item.state);
//stop = (stop_item.state);

You are on the right tracks here.

  • You need to comment out getMidnight(‘start’)
  • You want that start is eventually coming from your Evconnected

You will eventually pass start as an input arguments to the nibe.determineHours method, but at this point start must be a JavaScript Date object, not String.

It should work something like this.

  • When you are able to print “2022-09-02T11:01:17.024534+0200” to a log, you are only one step away from this.
  • Let’s say that you have a variable start_string that contains value “2022-09-02T11:01:17.024534+0200”

You then create a Date object like this:

start = new Date(start_string);

And similar logic to the stop.

Nice input once again

Code below seems to work properly, but not yet really modfied and no error handling for connecting car when dayahead prices is unknown, it will not happen us to often but it might happend.

dh = require('kolapuuntie/date-helper.js');
nibe = require('kolapuuntie/nibe.js');
influx = require('kolapuuntie/influx.js');

start_item = items.getItem("Evconnected").rawState;
start = new Date(start_item);
stop_item = items.getItem("EvCarReady").rawState;
stop = new Date(stop_item);
//start = dh.getMidnight('start');
//stop = dh.getMidnight('stop');
//start = (start_item.state);
//stop = (stop_item.state);

n = 4;
slices = 12;
min = 0;
points = nibe.determineHours(start, stop, n, slices, min);
influx.writePoints('carcharger_control_advanced', points);
n = 4;
slices = 12;
min = 0;

The slices = 12 does not make much sense. You want to use just 1 slice between your start and stop and find the cheapest hours from there. You can keep min as 0.

I guess your right as allways, I will keep fine tuning parameters until it gets really good. Power consumption really goes the right way below is s photo of my hourly consumption from 1st of september and as soon as price drops my consumptions peaks. Average idling consumption with two home offices running is 2kw per hour and nightly peak of more than 10kw an hour.

1 Like

August average spot price was 32.4 c/kWh in Finland (incl. tax). If we would have a spot price contract, we would have paid 22.5 c/kWh. In other words, we were 9.9 c/kWh below the average.

Our contract is 14.8 +/- delta, where delta was in August this -9.9. So we pay 14.8-9.9 = 4.9 c/kWh. This translates to 67% discount. :slight_smile:

Here’s the last 7 days consumption vs. spot price graph

1 Like

Well it seems like my timestamps run into some trouble because when rules isn’t run in even hours the time offset for measurments in database can be up 18:20 instead of 18:00 and then the control script doesn’t find any measurment and defaults to 1, so theres still some work to be done with my date time items triggering the funkctions
1 Set hours for ev charger N hours from dateitem1.state and until dateitem2.state this seems to get offsets in influx db so that next script that checks if control = 0 or = 1 and toggle switchitem in OH. I will keep troubleshooting this first of all run the rule every hour but only if ev is connected and the maybe be able to use that time for start time.

First of all Markus a big thanx for all the information you have put down here for others to use!

In our house here in Finland we have the following energy forms - wood/electricity/ground pump/solar heat panels/PV system and an electric car after a month. Our electricity contact is running out in January and we will likely have a spot contract after that. So we will definitely benefit from your work here.

I have been playing with computers, electronics, programming and electricity all my life so I have a basical understanding of related things at a hobbyist level.

I have now been able to set up a openHABian + InfluxDB2 + Add-ons system on a Raspberry Pi 4 fitted on a Waveshare 8-relay board.

The big trouble I have now is to set up the rules and scripts.I have started with only the rule to fetch the FMI weather data by making a time triggered rule that runs the first script part (and put in our location) that calls fmi.js and influx.js. The scripts are set as type ECMAScript 262 Edition 11. Triggering the rule ends in a GraalVM-polyglot error message,

2022-09-13 19:03:23.065 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘5fe8f3d523’ failed: org.graalvm.polyglot.PolyglotException: EvalError: /etc/openhab/automation/js/node_modules/kotikolo/fmi.js

What am I missing here? I have checked, and double-checked, googled for some days now without any progress from here.

Could you please Markus point me in the right direction so I could get on with this very exciting project?

I replied to the other thread where you asked about the ECMA script issue: How on earth can I get my ECMA scripts working on openHABian? - #6 by masipila

I’ll also update the comment marked as the solution so that it mentions that the file permissions must be correctly set up.

Sorry for the inconvenience, hopefully this helps a bit and you’re able to make some progress.

Cheers,
Markus

Hi all

I have this solution running really nice now and I also get estimated needed chargingtime from my Kia via nodered integration that publish car status via MQTT.

Due to the fact that my target time for EV charging is most typically att tomorrow att 06:00, I made some modifications for nibe.js so it doesn’t defaults to 1 but defaults to 2 so I know when there’s no spotprice availible for target time and the compute against midnight, but when it get price for 06:00 it recomputes with correct target time.

I would have been happy is there’s a way to cast some state when prices is updated for tomorrow and whats and when the lowest, highest and whats the average cost for tomorrow or between two dattime items.state.

In that solution I would allow some stuffs like winter preserving my spa to run when price is lower than xx amount regardless if it’s really needed just for bunkering energy in case the coming days is more expensive.

I will try to get the control rules to run ahead of every hour and set some state so that toogle things on or off is done either xx:59 if its off or xx:00 if its on, just to make sure not spend 5 times prices even if it’s just for a minute. That may seem cheap but soem stuff lik ev charger takes a while to get up or down i consumption.

But this soulution is as said really good, we are having an average electricity cost of 2,9SEK abou 0,29EUR and average day price so far for September is 4SEK and bes of all thanks to automation it doesn’t affect our life as much or at all.

/Marcus

I’m super glad to hear that you’ve been able to achieve almost 30% savings with this solution. Moving consumption out from the high-demand peak hours helps the whole society and also helps us here in Finland because we are completely dependent on the import from you guys in Sweden… So please spread the word in Sweden!

This starts to go exactly to the direction which I saw coming. Which is why I originally wrote this:

I’m not saying that those use cases would not be interesting or worth doing, but I personally don’t have time or energy for them with two small kids and curling world championships coming in a month from now. This thread is already almost 100 comments long so I’d kindly ask you to open a separate thread for those use cases. You are more than welcome to add links to those new threads from this topic so that other community members can find them since they are closely related.

If anyone is interested in transforming the code to real bindings, you are absolutely more than welcome to grab the code and continue from there.

Cheers,
Markus

1 Like

Hi,

This is an interesting project. Thank you Markus for providing the instructions and code.
I’m new to OpenHab and I don’t have much programming background. I’m an electronics designer but I have done some Java and C programming. Anyway, I would like to build a system to control the heat pump (Nibe F1226) to run on cheapest hours. First I’m trying to make this work on Windows and later move it to Raspberry Pi.
I think everything is now up and running, but for some reason the data is not saved to InfluxDB. OpenHab is giving the following log info:


When I increase the log level, I can see an InfluxDB related error which says “X-Platform-Error-Code: not found”. InfluxDB is run via Powershell and there I can see errors “database not found” and “unable to write gathered points”.
How do I configure InfluxDB to receive the data correctly?

Are you able to log in to the Influxdb web user interface?

If yes, pay attention to the IP address, port and user credentials and update them to influx.js. after making the updates to influx.js, you need to re-save the openHab rule to make those changes take effect.

Markus

Yes, I can log in to the Influxdb and I have updated the user credentials to influx.js.
I run OpenHab via command prompt using command ssh -p 8101 openhab@localhost and InfluxDB via Powershell with command ./influxd in the influxd.exe folder.
OpenHab opens in address localhost:8080 and InfluxDB in localhost:8086. I have no idea what I’m doing but I feel I’m almost there :smiley:
Do I need to make a query in InfluxDB or should the spot prices appear there automatically after running the “FetchSpotPrices” script in OpenHAb? I can’t see any buckets or data there. I have created an AllAccess API and it is updated to the influx.js.

This is the powershell window view:

You need to create the Influxdb bucket first and have an operational InfluxDB, otherwise the script has no place where it would write the data. The Influx user also need to have write access to your bucket.

Refer to the influxdb tutorials on their website.

Cheers,
Markus