It’s most probably something else than the semantic class that you changed that fixed your issue. But glad that you got it working.
Markus
It’s most probably something else than the semantic class that you changed that fixed your issue. But glad that you got it working.
Markus
Finally I have managed to get the SPO working in our test environment. However I have not been able to configure the Heat Pump Compressor Optimizer to work as needed in our heating system.
In our current old verson system the heat pump needed hours are calculated based on temperature and a slight modification in the rule forces the needed hours in InfluxDB to be between 0.00 and 8.00 where the cheapest hours usually are. During this period our 1 900 L storage tank is heated.
The reason for this is that we have a battery in our solar system and if the heatpump would start at random times during the day it would quickly drain our battery. During the winter the battery only charges during the night and in the summer the heat pump doesn’t run at all.
The new optimizer is full with different setting possibilities but they are propably designed for a heat pump that can run at any moment during the day with low electricity price. At least I have not been able to find a setting where the heating need is calculated for the whole day but the heating occures between 0.00 and 8.00. I tried a restricted time period similar to what can be done with the Boiler Optimizer rule but then you get only a part of the needed heating hours. Can our needs be met at all without modifications?
There also seems to be some kind of problem (OS related?) with the datetime selector in the Control Parameters page,
Is there any solution for this?
Rainer
Did you try to use start & end as 00:00 and 08:00 and use just 1 heating period? That would allocate all of the heating need between this time.
And then you can use GenericOptimizer for 08:00 and 00:00 next day and just block everything.
Haven’t tested this myself but on the top of my head I can’t figure out any reasons why this would not work…
Markus
I would recommend you to open a separate thread for just this topic since this is General openHAB UI thing and not specific to the coptimizer. I’m allergic to apples myself so I have not experience how they behave with openHAB UI.
I recommend to include the complete Page configuration code and screenshots of the widget in your post.
Markus
I just rerun the heat pump optimizing for tomorrow,
A total of 4,5 hours seems to be correct, our old system has 4 hours for tomorrow between 0:00 and 4:00.
Forcing the hours to start at 0:00 and stop at 8:00 doesn’t allocate the total 4,5 hours needed beween these times.
You should be able to replicate your old behavior as follows:
Get the average temperature for tomorrow (whole day) using the openHAB persistence services. An example is a couple of comments above, as I just instructed Timo on this (the only difference is that the example was for average spot price, you want to get average temperature).
You can use the Heating Calculator service which is still available, the Heating Period Optimizer calls this under the hood. See how to call this from the documentation block: openhab-spot-price-optimizer/heating-calculator.js at main · masipila/openhab-spot-price-optimizer · GitHub
Then use Generic Optimizer to allow the needed amount of hours between 00-08 and blocked the rest.
Is this sufficient or does you need complete example (it will take some time for me to do that as I have practice this evening straight after work)?
Markus
Thank you Markus for your hints in the right direction - I got the Heat Pump needed hours calculation and allocation between 00:00 and 8:00 working.
Some small cleanup and confirmation testing weeks and then I set the SPO as our everyday system.
By the way, any ideas why the datetime selector doesn’t show up on IOS devices?
No, unfortunately not. See my comment 2 days ago how I would propose to proceed with that.
The code for the Control Parameters page is here just as copy pasted from your Github page.
config:
label: Control Parameters
sidebar: true
blocks:
- component: oh-block
config:
title: Boiler & Domestic Hot Water
slots:
default:
- component: oh-grid-row
config: {}
slots:
default:
- component: oh-grid-col
config: {}
slots:
default:
- component: oh-stepper-card
config:
item: BoilerHours
max: 24
min: 0
step: 0.25
title: Boiler hours
- component: oh-block
config:
title: Heating
slots:
default:
- component: oh-grid-row
config: {}
slots:
default:
- component: oh-grid-col
config: {}
slots:
default:
- component: oh-input-card
config:
type: datetime-local
inputmode: text
title: "Heat Pump Compressor: Force hour ON"
footer: =items.HeatPumpCompressorForceOn.state
name: HeatPumpCompressorForceOn
sendButton: true
clearButton: true
item: HeatPumpCompressorForceOn
- component: oh-block
config: {}
slots:
default:
- component: oh-grid-row
config: {}
slots:
default:
- component: oh-grid-col
config: {}
slots:
default:
- component: oh-input-card
config:
type: datetime-local
inputmode: text
title: "Heat Pump Compressor: Force hour OFF"
footer: =items.HeatPumpCompressorForceOff.state
name: HeatPumpCompressorForceOff
sendButton: true
clearButton: true
item: HeatPumpCompressorForceOff
masonry: []
grid: []
canvas: []
When run on an iMac Mini the page looks like this but the date time control doesn’t work, item setting doesn’t get set.
And when viewed on an iPad the date time picker is not shown at all.
As I mentioned earlier, this looks like an openHAB core issue, not related to the openHAB Spot Price Optimizer.
I have no idea whatsoever how the date picker is implemented under tje hood. You are (much) more likely to get support to this date picker issue if you create a completely new thread to the forum which is specific to the datepicker thing.
Markus
After the latest IOS update the DateTime picker is now shown with the time selection shown in the Apple scrolling style and it is setting the ForceOn/Off item state.
My next issue that I have been tried to figure out is how to modify the UI Examples Page ForceON, ForceOFF and CloneControlPoints failsafe version 3 rules to rules that works in version 4 without influx.js - so far with little success.
Are you by any chance at some point going to update them for version 4?
No need for updated version 4 rules.
I finally figured out that I can modify the Boiler optimizer rule for adding an additional heating period later during the day if needed by setting the start and end times with the DateTime pickers on the ControlParameters page and add some validation for valid date and time.
Also noticed that the CloneControlPoints is already in the version 4 package.
It seems that I sometimes ask for help before I have slept over one night…
Hello, I would have a question about the usage of the Heating Period Optimizer, or also using the general optimizer:
Currently the Optimzer provides control points to switch the heatpump (or consumption) On/OFF as I understood.
Our heatpump supports the SG ready (SmartGrid ready ) inputs like shown below. And the heatpump is doing hot water generation (based on temperature control) and heating (currently also base on indoor temperature control)
Are there any means or thoughts available in the algorithm to instead of only ON/OFF control points to use a more stepwise control?
I could simply convert
OFF command to translate to “1” (forced off)
ON command to translite to “2” (normal)
But it would be smarter to use also the other steps somehow (e.g. the most cheapest ours to switch to “5” or “6”…)
Many thanks for any thoughts on that!
SG ready modes
0: Do not use
1: Forced off (equal to TB_SG1=close /TB_SG2=open)
2: Normal operation (equal to TB_SG1=open /TB_SG2=close)
3 : On recommendation (equal to TB_SG1=open /TB_SG2=close)
4 : On command (equal to TB_SG1=close /TB_SG2=open)
5 : On command step 2 (++ power consumption compared to normal)
6 : On recommendation step 1 (+ power consumption compared to normal)
7 : Energy saving mode (power consumption compared to normal)
8 : Super energy saving mode (- power consumption compared to normal)"
I am using version 3 of the spot price oprimizer. For some reason the graph for current day shows the bars as very thin lines. In addition the stack has a “ghost member” that shows up as a fully transparent bar, that I can not identify.
Graph for today:
Graph for previous days is always ok, except for the “ghost bar” that can be seen in the wee hours of the morning . Here is the graph for yesterday:
I have removed and rewritten all graph YAMLs to no avail. Any ideas where to continue debugging?
Hi @jrieder !
You’re raising excellent questions! Even though all Spot Price Optimizer examples are binary ON or OFF, it doesn’t mean that your devices need to be controlled in ON/OFF manner. You can for example let it run with it’s own internal “default” mode most of the time and then use the Generic Optimizer to change it to different mode for example for the cheapest time of the day and to another mode for the most expensive time of the day.
I haven’t tested this but this should / could be conceptually possible already now:
If you would need more fine-grained modes, then you would need to use the lower level API of the GenericOptimizer, which is the setControlForPeriod method. This method allows you to write any numeric values to your database as control point values, not just 1 or 0.
The real question here is what does the “it would be smarter to also use the different modes somehow” mean in the real world. The first thing that you need to investigate is what exactly does your heat pump do when it is in mode 5 or mode 6 and what is the difference between them. And what exactly does the pump do when it is in mode 7 or 8 and what is the difference between them. Then, you can start thinking about your use cases on conceptual level, and I’m more than happy to exchange ideas and experiences regarding these.
Cheers,
Markus
This means that there are control points in your database with lesser resolution than 15 minutes.The first thing is to try pinpoint if this is happening to all of your items (heat pump compressor, polestart charging, leaf charging, dish washer, washing machine) or just one of them.
So try to toggle down all these control points in your graph (don’t modify the code, click the legend to hide it temporarily). Then enable the items one by one to see if you get the “normal” thicker bars (that happens when you have data with 15 min resolution) or if you get thinner bars (that happens when you have at least 1 control point which is between the normal control points that you have at 00, 15, 30 and 45 min past a full hour. You can either move your mouse carefully over the graph to see the timestamps for the control points that you have, or you can write a temporary small script that prints all control points to the log.
Once you identify which item is causing the narrow bars, you need to start thinking that what else than the optimzer rules could be persisting data to those items. It can be for example that you have define the persistence strategy to be like “on every change” or “on every update”, and that you have some other stuff that you have built for UI purposes that is writing data to your database.
Markus
A small problem occured in the system last night - the heat pump did not stop at the end of the heating period. In our setup the time window for the optimization is between 22.00 and 7.00. If the heat pump is optimized to run for example between 1.00 and 3.00 everything works fine but if the run hours are like last night 3.30 and 7.00 the heat pump does not stop at 7.00 that also is the optimization window end.
The chart in openHAB looks OK but if you look at the InfluxDB chart you can see that there are no 0 values after 7.00. In a chart where the heating period stops before 7.00 there are correct values for the whole day. The red Influx curve is the heat pump.
The code optimizing the heat pump is based on your earlier suggestions.
// CALCULATE AVERAGE TEMPERATURE ======================================================
// Define the temperature item and the optimization period low tariff 22 - 7.
var tempItem = items.getItem('FMI_Weather_Forecast_Temperature');
var start = time.toZDT('22:00');
var end = start.plusDays(1);
// Calculate the average temperature and print it to the log
var avgtemp = tempItem.persistence.averageBetween(start, end);
var avg = avgtemp.numericState.toFixed(2);
//console.log("Average temperature: " + avg);
// Update the new average temperature item which you have created
var avgItem = items.getItem('AverageTemp');
avgItem.postUpdate(avg);
// CALCULATE HEATING HOURS NEEDED =======================================================
// Load modules and create service factory.
var { HeatingCalculator } = require('openhab-spot-price-optimizer/heating-calculator.js');
var heatcalc = new HeatingCalculator();
var heatCurve = [];
// Required optimization parameters, heat curve can have 2 or more points.
heatCurve = [ // Heat curve:
{temperature : -25, hours: 8}, // - Average temperature -25°C, heat 24h / day
{temperature : 2, hours: 5}, // - Average temperature +2°C, heat 7h / day
{temperature : 13, hours: 1} // - Average temperature +13°C, heat 2h / day
];
// Read the average day temperature from the AverageTemp item.
var avgTempItem = items.getItem('AverageTemp');
var temperature = avgTempItem.numericState;
var numberOfPeriods = 1; // Number of heating periods in a day, 1 = 24h.
var hours = 0;
// Calculate the heating hours needed.
hours = heatcalc.calculateHeatingHoursLinear(heatCurve, temperature, numberOfPeriods);
hours = hours.toFixed(2);
// Modify the hours with the Heating Need Adjustment value
var adjItem = items.getItem("HeatingNeedAdjustment");
var adjHours = parseFloat(adjItem.numericState);
hours = +hours + +adjHours; // The + before the variable names ensures they are treated as numbers!
//console.log("Adjustment: " + hours);
// Update the new heating hours item which you have created
var avgItem = items.getItem('HeatingHours');
avgItem.postUpdate(hours);
// CREATE OPTIMAL CONTROL POINTS FOR THE HEATING HOURS ================================
// Load module and create service.
var { GenericOptimizer } = require('openhab-spot-price-optimizer/generic-optimizer.js');
var optimizer = new GenericOptimizer();
// Define price item and control item here.
var priceItem = items.getItem('TotalPrice');
var controlItem = items.getItem('HeatPumpCompressorControl');
// Read how many heating hours are needed from the HeatingHours item.
var item = items.getItem("HeatingHours");
var hours = parseFloat(item.numericState);
// Define the optimization time window.
var start = time.toZDT('22:00');
var end = time.toZDT('07:00').plusDays(1);
// Define the delay (seconds) to ensure prices have been saved first.
var delay = 60;
// Read prices from the database, optimize and save the control points.
var delayedFunction = function() {
var prices = priceItem.persistence.getAllStatesBetween(start, end);
optimizer.setPrices(prices);
// optimizer.allowPeriod(hours);
optimizer.allowIndividualHours(hours);
optimizer.blockAllRemaining();
var timeseries = optimizer.getControlPoints();
controlItem.persistence.persist(timeseries);
};
// Create a timer that calls delayedFucntion after the delay.
actions.ScriptExecution.createTimer(time.toZDT().plusSeconds(delay), delayedFunction);
Bye the way, the same problem also occures with the boiler if the heating period ends at the optimizing window time. Any ideas how to fix this issue?
Create another rule action / modify your existing rule which blocks everything between 07 and 22.
You can do this using GenericOptimizer, using 07-22 as the window and using the blockAllRemaining method.
This will guarantee that you have control points 1 or 0 for the whole day. First created by your existing rule and the rest by this “block all” rule.
Markus
Thx once again Markus. Modified the rule according to your suggestions and temporarely modified the end and start times to re-run last nights optimization. Now the InfluxDB got 0 values for the 7.00 to 22.00 time window.
Rainer
Hi
Super nice work as before, I updated to the newest relaease today and have openHab 4.3.4 with Entsoe-E binding and FMI binding installed and configured. I get data in influx db from them but whe i try to execute generic optimizer I get the following error measseages. 1 is the amount of hours to be active between the two following timestamps, that is set by an item. As far as I understand the generic-optimizer.js this error comes when you have les than two points in the spotprice item, however I have data for today and tomorrow. Doesn anyone have any idea what could have been going wrong?
16:47:59.794 [INFO ] [enhab.automation.script.ui.df884217b9] - 1
16:47:59.800 [INFO ] [enhab.automation.script.ui.df884217b9] - 2025-04-14T12:37:32.302+02:00[Europe/Stockholm]
16:47:59.806 [INFO ] [enhab.automation.script.ui.df884217b9] - 2025-04-14T20:47:59.801+02:00[Europe/Stockholm]
16:47:59.914 [ERROR] [enhab.automation.script.ui.df884217b9] - generic-optimizer.js: Not enough prices for optimizations!
16:47:59.915 [ERROR] [enhab.automation.script.ui.df884217b9] - generic-optimizer.js: Aborting optimization, see previous errors!
16:47:59.916 [INFO ] [enhab.automation.script.ui.df884217b9] - generic-optimizer.js: block all remaining...
16:47:59.916 [ERROR] [enhab.automation.script.ui.df884217b9] - generic-optimizer.js: Aborting optimization, see previous errors!
16:47:59.917 [ERROR] [enhab.automation.script.ui.df884217b9] - generic-optimizer.js: Aborting optimization, see previous errors!
Part of rule that have been edited to get start and possible end time from item.
// Read how many hours are needed from the BoilerHours item.
var item = items.getItem('EV2_estimated_charging');
var hours = parseFloat(item.numericState);
console.log(hours)
// Define the optimization window here, this example optimizes tomorrow.
var startItem = items.getItem("Evconnected");
var start = time.toZDT(startItem);
console.log(start);
var end = time.toZDT().plusHours(4);