[TASK] Added README.md to explain the configuration of the script
This commit is contained in:
61
README.md
Normal file
61
README.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Boiler Control - AppDaemon
|
||||
|
||||
AppDaemon script that optimizes when to power (heat up) the boiler with respect to the hourly (dynamic) electricity prices.
|
||||
|
||||
## Configuration
|
||||
Copy boilercontrol.py to your appdaemon config `/apps` folder.
|
||||
|
||||
In `apps.yaml`, activate the app by adding something like this:
|
||||
```yml
|
||||
boiler_control:
|
||||
module: boilercontrol
|
||||
class: BoilerControl
|
||||
# Switch entity that turns on/off the boiler
|
||||
boiler_switch: switch.boiler_switch_0
|
||||
# Sensor entity which contains the current dynamic electricity prices. This sensor should have an attribute "raw_today", which contains a dictionary with the prices per hour
|
||||
price_sensor: sensor.nordpool
|
||||
# (Optional) sensor to add to home assistant which contains the output of the optimization script
|
||||
output_sensor: sensor.boiler_control_output
|
||||
|
||||
# Minimal number of hours the boiler should be powered per day
|
||||
boiler_on_for_hours: 6
|
||||
# The algorithm splits the day up into equal size "periods", and tries to ensure the boiler gets at least one hour of power during each period.
|
||||
# This variable controls how many periods of boiler activity each day should have
|
||||
boiler_reheat_periods_per_day: 4
|
||||
```
|
||||
|
||||
You can use [ApexCharts](https://github.com/RomRider/apexcharts-card) to display to output of the algorithm. Config:
|
||||
```yml
|
||||
type: custom:apexcharts-card
|
||||
graph_span: 24h
|
||||
header:
|
||||
title: Energy price today (€/kWh)
|
||||
show: true
|
||||
span:
|
||||
start: day
|
||||
now:
|
||||
show: true
|
||||
label: Now
|
||||
series:
|
||||
- entity: sensor.nordpool
|
||||
float_precision: 3
|
||||
type: column
|
||||
data_generator: |
|
||||
return entity.attributes.raw_today.map((start, index) => {
|
||||
return [new Date(start["start"]).getTime() + 30 * 1000 * 60, entity.attributes.raw_today[index]["value"]];
|
||||
});
|
||||
- entity: sensor.boiler_control_output
|
||||
float_precision: 0
|
||||
name: Boiler controller
|
||||
type: line
|
||||
curve: stepline
|
||||
stroke_width: 2
|
||||
data_generator: |
|
||||
const val = entity.attributes.average_price
|
||||
return [[0,0], ...entity.attributes.merged_blocks.flatMap(b => {
|
||||
return [[new Date(b["start"]).getTime(), val], [new Date(b["end"]).getTime(), 0]]
|
||||
})]
|
||||
yaxis:
|
||||
- min: 0
|
||||
decimals: 2
|
||||
```
|
||||
@@ -78,7 +78,7 @@ class BoilerControl(hass.Hass):
|
||||
self.run_at(self.turn_boiler_off, block["end"])
|
||||
|
||||
if (self.output_sensor != None):
|
||||
self.set_state(self.output_sensor, state="on" if currently_on else "off", attributes={"active_blocks": boiler_active_blocks, "merged_blocks": merged_blocks})
|
||||
self.set_state(self.output_sensor, state="on" if currently_on else "off", attributes={"active_blocks": boiler_active_blocks, "merged_blocks": merged_blocks, "average_price": sum([block["value"] for block in boiler_active_blocks]) / len(boiler_active_blocks)})
|
||||
|
||||
|
||||
def turn_boiler_on(self, cb_args=None):
|
||||
|
||||
Reference in New Issue
Block a user