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

Because I am no coder I asked ChatGPT how to call the windchill calculator method. This is what it suggested:

I further asked it to add start and end times to the script. Here is what it suggested. Would this be what you expected @masipila?

// Import the InfluxDB client library
const Influx = require('influx');

// Create a new InfluxDB client instance
const influx = new Influx.InfluxDB({
    host: 'localhost',
    database: 'mydb',

// Define the start and end times for the import
const startTime = '2022-02-01T00:00:00Z'; // Replace with your start time
const endTime = '2022-02-28T23:59:59Z'; // Replace with your end time

// Define the query to fetch the temperature and windspeed data for the specified time range
const temperatureQuery = `
    SELECT "value"
    FROM "temperature"
    WHERE time >= '${startTime}' AND time <= '${endTime}'
const windspeedQuery = `
    SELECT "value"
    FROM "windspeed"
    WHERE time >= '${startTime}' AND time <= '${endTime}'

// Fetch the temperature data from InfluxDB
    .then(result => {
        // Create an array of temperature points
        let temperaturePoints = => {
            return {
                datetime: row.time,
                value: row.value,

        // Fetch the windspeed data from InfluxDB
        return influx.query(windspeedQuery)
            .then(result => {
                // Create an array of windspeed points
                let windspeedPoints = => {
                    return {
                        datetime: row.time,
                        value: row.value,

                // Call the calculateWindChillTempPoints function with the fetched data
                let windChillTempPoints = calculateWindChillTempPoints(temperaturePoints, windspeedPoints);

    .catch(error => {

I’m literally laughing my lungs out!

I’ll put the kids to bed and try to stop laughing and will get back to you shortly.


@timo12357 the comment #13 now has the same version of the fmi.js that I’m using myself which has the methods for storing also other weather forecast measurements than just the temperature. It also has the method for calculating the wind chill compensated temperature.

Pay attention also to the updated script action for the rule that fetches the weather forecast from FMI API.


1 Like

Great @masipila, wind compensation seems to work now, even if I do 't really understand how.

I do not want to be a pain in the butt… but have you considered the solar thermal effect? has a feature that reduces the needed heating hours on very sunny days. Do you have ideas how to implement that on this platform? Where does get the expected solar thermal power data from?

You are already now persisting Temperature,
WindSpeedMS from the FMI response XML.

If you read through the fmi.js and more specifically the row where the API call is made to the FMI API, you can see that were actually requesting for many other weather forecasts. The cloud coverqge is one of them. You can save that to your database exactly the same way as you do for the temperature and wind speed.

How you want to take the cloudiness into account in calculating the number of heating hours is purely up to you.

I haven’t even tried yet, even though its clear that it plays a significant factor now that the days are getting longer. We have 3.6 m x 3.6 m windows to South and the temperature in the living room bumps significantly on sunny days.


1 Like

Some reporting of how well the code now works.

Control 15.3.2023

Actual energy consumption from power company reporting system for 15.3.2023

Control 16.3.2023

Actual consumption 16.3.2023

One can see from the graphs that heating is the dominating energy consumption in our house and @masipila 's code succeeds nicely in controlling our heat pump to run only on the cheapest hours. Thanks Markus, this is great!

We buy our electricity from Oomi, that has hourly reporting on the consumption. I have not found an API that could be machine read, to plot the consumption values in the same graph with the control.

Can the data be extracted from the web content ( plots ) ?
Have you had a look into GitHub - sremes/oomi: Download electricity consumption data from Oomi and upload it into Google Firestore. ?

1 Like

Nice find! It seems to have InfluxDB support, too.

I’ll look into this.

1 Like

@masipila Seems like the transition to daylight saving time messed up the software. It does not calculate tomorrows heating as it only has 23 spot times.

2023-03-26 17:47:00.339 [INFO ] [nhab.automation.script.ui.00b077135e] - nibe.js: Calculating forecasted average temperature...
2023-03-26 17:47:00.384 [INFO ] [nhab.automation.script.ui.00b077135e] - nibe.js: average temperature: -8.295833333333334
2023-03-26 17:47:00.387 [INFO ] [nhab.automation.script.ui.00b077135e] - nibe.js: Calculating number of ON hours for Nibe...
2023-03-26 17:47:00.391 [INFO ] [nhab.automation.script.ui.00b077135e] - nibe.js: Number of needed hours: 8.994074074074074
2023-03-26 17:47:00.393 [INFO ] [nhab.automation.script.ui.00b077135e] - control-point-optimizer-slicing.js: Searching for cheapest hours...
2023-03-26 17:47:00.396 [INFO ] [nhab.automation.script.ui.00b077135e] - influx.js: Reading spot prices from the database...
2023-03-26 17:47:00.432 [ERROR] [nhab.automation.script.ui.00b077135e] - control-point-optimizer-slicing.js: Not enough spot prices! Expected 24 but found 23
2023-03-26 17:47:00.435 [INFO ] [nhab.automation.script.ui.00b077135e] - influx.js: Preparing to write 0 points to the database for nibe_control
2023-03-26 17:47:00.437 [INFO ] [nhab.automation.script.ui.00b077135e] - influx.js: Points successfully saved for measurement nibe_control

I got this circumvented by editing row 132 of nibe.js like so:

    const duration = (Math.abs(stop-start) / (60*60*1000))-1;

After this the software agreed to calculate heating hours for tomorrow. This cludge is not a good solution, but at least gives one more day time to find a real solution to the problem.

I finally managed to understand (read: reverse engineer) the logic behind the Entso-E API and it’s input paramaters.

The root of all evil is that Entso-E does not respect the ISO8601 standard in the periodStart and periodEnd input arguments which are implicitly assumed to be CET/CEST. Their API responses are properly respecting ISO8601.

In addition to this, the periodStart and periodEnd arguments are NOT the start and end times for which we will get data back, and I had previously never fully understood how their API works when it comes to periodStart and periodEnd. Now I finally know, after experimenting their API for a couple of hours with different dates. They will always return full days worth of spot prices and they will all the days that are are at least partially between periodStart and periodEnd.

Because of my previous “I-wonder-how-the-f*ck-does-this-work-since-they-don’t-respect-ISO8601” I had made incorrect assumptions and as a result, I had a bug in my own code that parses their responses. I’ll need to clean it up still before I publish a new version.