3.x ‐ Usage example: Generic Optimizer ‐ heating domestic hot water during the cheapest hours of the day - masipila/openhab-spot-price-optimizer GitHub Wiki
Important note
- These instructions apply only to version 3.x of openHAB Spot Price Optimizer.
- See separate wiki page for version 4.x of openHAB Spot Price Optimizer.
Overview
This page gives an example how to use the GenericOptimizer
class of the openhab-spot-price-optimizer
module.
As the name suggests, the GenericOptimizer
algorithms are generic and can be used for many different use cases such as water boilers or charging electric vehicles. This page shows how to find given number of cheapest hours of the day to heat the domestic hot water with a water boiler that can be controlled with openHAB. Further examples can be found on separate documentation page.
WARNING: Do not try to optimize the heating of domestic hot water too agressively.
- The boiler should always have enough hours to reach the thermostate max temperature.
- Legionella bacteria reproduces in temperatures between 20 - 45 ° celcius.
- In Finland, there is a law that the water temperature in the boiler must always be at least 55 ° celcius to ensure that legionella bacteria will die.
Pre-requisites
- The boiler can be controlled with an openHAB Item.
- The rest of this tutorial assumes you can control your boiler with an item called
BoilerPower
. - See example how to control boiler via openHAB
- The rest of this tutorial assumes you can control your boiler with an item called
- Spot prices are available in your database
Create two new Items
Create an Item 'BoilerHours'
- In order to optimize the heating of domestic hot water, our optimizing script needs to know how many hours the boiler needs to be ON to reach its thermostate max temperature.
- We don't want to hard code this number to our script, so let's create an Item
BoilerHours
which we can easily update with an user interface widget. - The type of this Item must be Number
- See an example of a Control parameters page which shows how this value can be easily changed
Create an item 'BoilerControl'
- The rule below optimizes when the boiler should heat water and writes
BoilerControl
control points timeseries to our database. - The type of this Item must be Number
- See an example of control point visualization chart
Create a Rule 'BoilerOptimizer' to calculate the control points
- This rule will create control points for each 15 minute period of the day
- Control point value 1 means the power supply will be ON during and value 0 means that power supply will be OFF.
- This Rule will be triggered whenever the Item
BoilerHours
changes. - We will also configure this Rule to be run after the spot prices have been fetched.
Version 3.x: Inline script action for the rule
Important This script works only on version 3.x of openHAB Spot Price Optimizer. See separate instructions for version 4.x of openHAB Spot Price Optimizer.
- The following rule first reads the SpotPrice values from midnight to midnight
- It then reads how many hours the boiler needs to be ON from the
BoilerHours
item - It then finds the cheapest consecutive period for this many hours.
- All remaining hours will be blocked.
- Finally, the control points will be saved to InfluxDB as
BoilerControl
.
// Load modules. Database connection parameters must be defined in config.js.
var { Influx } = require('openhab-spot-price-optimizer/influx.js');
var { GenericOptimizer } = require('openhab-spot-price-optimizer/generic-optimizer.js');
// Create services.
var influx = new Influx();
var optimizer = new GenericOptimizer();
//If the script is called after 14.00, optimize tomorrow. Otherwise optimize today.
var start = time.toZDT('00:00');
if (time.toZDT().isBetweenTimes('14:00', '23:59')) {
start = start.plusDays(1);
}
var stop = start.plusDays(1);
// Read spot prices from InfluxDB and pass them for the optimizer.
var prices = influx.getPoints('SpotPrice', start, stop);
optimizer.setPrices(prices);
// Read how many hours are needed from the BoilerHours item.
var item = items.getItem("BoilerHours");
var hours = Math.round(item.state);
// Optimize the control points and save them to the database.
optimizer.allowPeriod(hours);
optimizer.blockAllRemaining();
var points = optimizer.getControlPoints();
influx.writePoints('BoilerControl', points);
List of all optimization algorithms provided by GenericOptimizer
The GenericOptimizer
optimizing class provides several optimization methods for different use cases. If you want to for example charge an electric vehicle so that you want to find the cheapest period between 21.00 and 06.00, that can easily be achieved. See more usage examples on a separate wiki page.
Invoke this Rule also after the spot prices have been fetched
- The rule was defined to be run every time after the item
BoilerHours
changes. But what if this value is kept unchanged day after a day, what triggers this Rule to be executed? - The solution differs between versions 3.x and 4.x. of openHAB Spot Price Optimizer.
In version 3.x, the solution is to modify the previously created FetchSpotPrices
Rule so that we execute the BoilerOptimizer
rule as an additional action immediately after the spot prices have been fetched.
- Go to edit the previously created
FetchSpotPrices
Rule and add the additional action as illustrated in the picture below.
Create a Rule 'BoilerController' to toggle the boiler ON and OFF
- This rule will run every 15 minutes and turn the boiler ON or OFF based on the current control point
- If the boiler is currently OFF and the current control point is 1, the boiler will be turned ON and vice versa.
Version 3.x: Inline script action for the rule
// Load modules. Database connection parameters must be defined in config.js.
var { Influx } = require('openhab-spot-price-optimizer/influx.js');
// Create services.
var influx = new Influx();
// Read the control value for the current hour from the database.
var control = influx.getCurrentControl('BoilerControl');
// BoilerPower: Send the commands if state change is needed.
var BoilerPower = items.getItem("BoilerPower");
if (BoilerPower.state == "ON" && control == 0) {
console.log("BoilerPower: Send OFF")
BoilerPower.sendCommand('OFF');
}
else if (BoilerPower.state == "OFF" && control == 1) {
console.log("BoilerPower: Send OFF")
BoilerPower.sendCommand('ON');
}
else {
console.log("BoilerPower: No state change needed")
}
3.x: Script for deleting control points
When developing your solution and experimenting, you might want to delete points from your Influx database. The script below can be used for that.
// Load modules. Database connection parameters must be defined in config.js.
var { Influx } = require('openhab-spot-price-optimizer/influx.js');
// Create services.
var influx = new Influx();
// Delete BoilerControl points for today.
var start = time.toZDT('00:00');
var stop = start.plusDays(1);
influx.deletePoints('BoilerControl', start, stop);