node-red-contrib-power-saver 3.3.2 → 3.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.firebase/hosting.ZG9jcy8udnVlcHJlc3MvZGlzdA.cache +94 -0
- package/.firebaserc +5 -0
- package/.github/workflows/firebase-hosting-merge.yml +20 -0
- package/.github/workflows/firebase-hosting-pull-request.yml +17 -0
- package/README.md +1 -1
- package/docs/.vuepress/components/BestSaveVerificator.vue +3 -3
- package/docs/.vuepress/config.js +15 -1
- package/docs/.vuepress/dist/404.html +23 -5
- package/docs/.vuepress/dist/assets/css/896.styles.21a80cb6.css +1 -0
- package/docs/.vuepress/dist/assets/css/styles.1c48cbd0.css +10 -0
- package/docs/.vuepress/dist/assets/img/heat-capacitor-temperatureVsPrice.6e74905b.png +0 -0
- package/docs/.vuepress/dist/assets/img/node-ps-strategy-heat-capacitor-cascade-control.2e75ed9e.png +0 -0
- package/docs/.vuepress/dist/assets/img/node-ps-strategy-heat-capacitor-simple-flow-example.29d9bf59.png +0 -0
- package/docs/.vuepress/dist/assets/img/oven-setpoint-calculation.5bda0eec.png +0 -0
- package/docs/.vuepress/dist/assets/img/overshoot-time.b3b5d70e.png +0 -0
- package/docs/.vuepress/dist/assets/js/229.5c5378fa.js +1 -0
- package/docs/.vuepress/dist/assets/js/331.872104cd.js +1 -0
- package/docs/.vuepress/dist/assets/js/405.f4edd94d.js +2 -0
- package/docs/.vuepress/dist/assets/js/{619.8ba1b1f6.js.LICENSE.txt → 405.f4edd94d.js.LICENSE.txt} +0 -0
- package/docs/.vuepress/dist/assets/js/490.1e639e05.js +1 -0
- package/docs/.vuepress/dist/assets/js/{491.17a98f38.js → 491.bd938119.js} +1 -1
- package/docs/.vuepress/dist/assets/js/555.d8963d84.js +1 -0
- package/docs/.vuepress/dist/assets/js/{811.6a3392d5.js → 811.5f659592.js} +0 -0
- package/docs/.vuepress/dist/assets/js/app.dfdee6f9.js +1 -0
- package/docs/.vuepress/dist/assets/js/runtime~app.f6ac32d7.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-0607240a.0193a377.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-08683c60.52e94cb6.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-0aca7ba6.cac5d4b9.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-0b5e3c8c.18561f6e.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-1ad821fa.6697a349.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-1b3a0ab8.c6c4e19b.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-1e2b191e.07b8ab21.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-29504124.00be7399.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-30acb564.28af12af.js +1 -0
- package/docs/.vuepress/dist/assets/js/{v-3706649a.d7f73384.js → v-3706649a.c76d575b.js} +1 -1
- package/docs/.vuepress/dist/assets/js/v-4637f9e4.d334c29a.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-4c28314d.8cbb0f9d.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-510ed0d4.c04bc2e4.js +1 -0
- package/docs/.vuepress/dist/assets/js/{v-5954bcb2.937005d0.js → v-5954bcb2.dff3fc67.js} +1 -1
- package/docs/.vuepress/dist/assets/js/v-5db8da3a.e5e6d7a6.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-61f728ca.81968036.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-677dfaed.c159b0f4.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-7446a652.8fc2c591.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-7c87f26e.8ed52391.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-84304104.f3f07ed3.js +1 -0
- package/docs/.vuepress/dist/assets/js/{v-8daa1a0e.c63afc2b.js → v-8daa1a0e.ed84ca09.js} +1 -1
- package/docs/.vuepress/dist/assets/js/{v-b4a42144.733e4e7c.js → v-b4a42144.9a2a0c9f.js} +1 -1
- package/docs/.vuepress/dist/assets/js/v-e8c55052.b7d52fc6.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-fffb8e28.d09ab959.js +1 -0
- package/docs/.vuepress/dist/changelog/index.html +23 -5
- package/docs/.vuepress/dist/contribute/index.html +23 -5
- package/docs/.vuepress/dist/examples/example-cascade-temperature-control.html +304 -0
- package/docs/.vuepress/dist/examples/example-heat-capacitor.html +247 -0
- package/docs/.vuepress/dist/examples/example-next-schedule-entity.html +27 -9
- package/docs/.vuepress/dist/examples/example-nordpool-current-state.html +24 -6
- package/docs/.vuepress/dist/examples/example-nordpool-events-state.html +24 -6
- package/docs/.vuepress/dist/examples/example-tibber-mqtt.html +24 -6
- package/docs/.vuepress/dist/examples/index.html +23 -5
- package/docs/.vuepress/dist/faq/best-save-viewer.html +23 -5
- package/docs/.vuepress/dist/faq/index.html +23 -5
- package/docs/.vuepress/dist/guide/index.html +24 -6
- package/docs/.vuepress/dist/index.html +23 -5
- package/docs/.vuepress/dist/nodes/index.html +23 -5
- package/docs/.vuepress/dist/nodes/old-power-saver-doc.html +25 -7
- package/docs/.vuepress/dist/nodes/power-saver.html +23 -5
- package/docs/.vuepress/dist/nodes/ps-elvia-add-tariff.html +23 -5
- package/docs/.vuepress/dist/nodes/ps-general-add-tariff.html +23 -5
- package/docs/.vuepress/dist/nodes/ps-receive-price.html +26 -8
- package/docs/.vuepress/dist/nodes/ps-strategy-best-save.html +32 -9
- package/docs/.vuepress/dist/nodes/ps-strategy-heat-capacitor.html +260 -0
- package/docs/.vuepress/dist/nodes/ps-strategy-lowest-price.html +30 -7
- package/docs/.vuepress/dist/nodes/strategy-input.html +24 -6
- package/docs/README.md +1 -1
- package/docs/changelog/README.md +14 -0
- package/docs/contribute/README.md +8 -0
- package/docs/examples/README.md +8 -2
- package/docs/examples/example-cascade-temperature-control.md +346 -0
- package/docs/examples/example-heat-capacitor.md +271 -0
- package/docs/images/heat-capacitor-temperatureVsPrice.png +0 -0
- package/docs/images/node-ps-strategy-heat-capacitor-cascade-control.png +0 -0
- package/docs/images/node-ps-strategy-heat-capacitor-simple-flow-example.png +0 -0
- package/docs/images/node-ps-strategy-heat-capacitor.png +0 -0
- package/docs/images/oven-setpoint-calculation.png +0 -0
- package/docs/images/overshoot-time.png +0 -0
- package/docs/images/temperature-manipulation-config.png +0 -0
- package/docs/nodes/README.md +7 -1
- package/docs/nodes/ps-strategy-heat-capacitor.md +346 -0
- package/examples/add-general-tariff.json +103 -0
- package/examples/best-save-for-water-heater.json +140 -0
- package/examples/elvia-add-tariff.json +99 -0
- package/examples/elvia-get-tariff-types.json +58 -0
- package/examples/elvia-get-tariff.json +60 -0
- package/examples/heat-capacitor-for-room-heating.json +186 -0
- package/examples/lowest-price-for-heating-cables.json +159 -0
- package/firebase.json +6 -0
- package/package.json +17 -9
- package/public/404.html +33 -0
- package/public/index.html +89 -0
- package/src/elvia/elvia-tariff.js +2 -1
- package/src/handle-input.js +6 -3
- package/src/strategy-heat-capacitor-functions.js +246 -0
- package/src/strategy-heat-capacitor.html +85 -0
- package/src/strategy-heat-capacitor.js +125 -0
- package/test/data/converted-prices.json +1 -1
- package/test/data/multiple-trades.json +53 -0
- package/test/data/tibber-decreasing-24h.json +101 -0
- package/test/data/tibber-decreasing2-24h.json +101 -0
- package/test/strategy-heat-capacitor-node.test.js +183 -0
- package/test/strategy-heat-capacitor.test.js +103 -0
- package/test/strategy-lowest-price-functions.test.js +1 -1
- package/test/utils.test.js +0 -2
- package/docs/.vuepress/dist/.nojekyll +0 -0
- package/docs/.vuepress/dist/assets/css/563.styles.99f4a8aa.css +0 -1
- package/docs/.vuepress/dist/assets/css/styles.031dcf27.css +0 -9
- package/docs/.vuepress/dist/assets/js/262.cf2c57d2.js +0 -1
- package/docs/.vuepress/dist/assets/js/293.08ea5200.js +0 -1
- package/docs/.vuepress/dist/assets/js/331.15ee3c51.js +0 -1
- package/docs/.vuepress/dist/assets/js/619.8ba1b1f6.js +0 -2
- package/docs/.vuepress/dist/assets/js/app.b705176c.js +0 -1
- package/docs/.vuepress/dist/assets/js/runtime~app.47f4f812.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-0607240a.a57c2199.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-08683c60.ccafdcab.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-0aca7ba6.25903946.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-0b5e3c8c.a6a015b4.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-1ad821fa.5978386f.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-1e2b191e.88dc5555.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-29504124.4aca27d5.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-30acb564.529a3c16.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-4637f9e4.703b1d96.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-510ed0d4.7b142a81.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-5db8da3a.3de3588d.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-61f728ca.21d432fe.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-677dfaed.44a653b9.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-7446a652.74b21d0b.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-7c87f26e.ee5be992.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-e8c55052.ab0a79ec.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-fffb8e28.525be02a.js +0 -1
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
# Cascade temperature control
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
The controller changes the setpoint of climate entities to regulate the temperature of room with increased responsiveness, accuracy, and stability.
|
|
6
|
+
|
|
7
|
+
### An example
|
|
8
|
+
|
|
9
|
+
A room has a temperature sensor and en electric heater. Given a setpoint temperature, the controller can make the sensor match the given value by adjusting the temperature settings of the electric heater. This type of control usually reacts faster and is more accurate then the alternative of simply changing the temperature settings of the heater. The flow requires that node-red, home assistant, and the connection to the climate entity are stable.
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
The example utilizes a PID controller to provide a number between 0 and 1 to indicate a load on the heater
|
|
16
|
+
|
|
17
|
+
A cascade temperature controller is a controller which utilizes the input/setpoints of other controllers/climate entities to regulate to its own setpoint
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Requirements
|
|
22
|
+
|
|
23
|
+
- Home assistant integrated with Node-RED
|
|
24
|
+
|
|
25
|
+
- The PID node installed - https://flows.nodered.org/node/node-red-contrib-pid
|
|
26
|
+
|
|
27
|
+
- A climate entity
|
|
28
|
+
|
|
29
|
+
## Instructions
|
|
30
|
+
|
|
31
|
+
- Create an `input_number` entity in Home Assistant and name it "cascade_setpoint"
|
|
32
|
+
|
|
33
|
+
- Create an `input_boolean` entity in Home Assistant and name it `cascade_enabled`
|
|
34
|
+
|
|
35
|
+
* When set to false, this will disengage the controller
|
|
36
|
+
|
|
37
|
+
- Import the flow into Node-RED
|
|
38
|
+
|
|
39
|
+
- Enter the correct sensor tempertaure entity in the `Temp sensor` node
|
|
40
|
+
|
|
41
|
+
- Change the climate entity name in three places
|
|
42
|
+
|
|
43
|
+
* Current climate settings - node
|
|
44
|
+
* Set Temperature node - two places
|
|
45
|
+
- `Entity ID`
|
|
46
|
+
- `Data`
|
|
47
|
+
|
|
48
|
+
- (optional) Change the oven setpoint range - see figure below.
|
|
49
|
+
|
|
50
|
+
* This regulates what values the controller sends to the oven. As a default, the value sent is oven_setpoint = setpoint +- 5 degrees. That is, for a setoint of 10C, the controller will be sending setpoints between 5 and 15 C to the oven. This is further limited to whole numbers, a minimum value of 5, and a maximum value of 30.
|
|
51
|
+
|
|
52
|
+
- (reccomended) Tune the PID controller - Detailed instructions can be found here: http://blog.clanlaw.org.uk/pid-loop-tuning.html
|
|
53
|
+
|
|
54
|
+
* Measure the system and find the overshoot time
|
|
55
|
+
- Set the proportional band to **zero** and place the setpoint a bit above the current measured value (se figure).
|
|
56
|
+
- Wait for the system to overshoot the target temperature and measure the time it takes for the system to return to the setpoint.
|
|
57
|
+
* Set the proportional band. This is the value indicates how much the measured temperature is allowed to deviate from the setpoint before max load is applied.
|
|
58
|
+
* Spesify the integral time. A good value is two times the overshoot time.
|
|
59
|
+
* Insert the derivative time. A good value here is half of the overshoot time.
|
|
60
|
+
|
|
61
|
+

|
|
62
|
+

|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Flow
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
::: details Flow code
|
|
71
|
+
|
|
72
|
+
```json:no-line-numbers
|
|
73
|
+
[
|
|
74
|
+
{
|
|
75
|
+
"id": "29fde6c61057362b",
|
|
76
|
+
"type": "tab",
|
|
77
|
+
"label": "PID Controller - cascade",
|
|
78
|
+
"disabled": false,
|
|
79
|
+
"info": "",
|
|
80
|
+
"env": []
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"id": "61ae0bee1a382102",
|
|
84
|
+
"type": "server-state-changed",
|
|
85
|
+
"z": "29fde6c61057362b",
|
|
86
|
+
"name": "Setpoint",
|
|
87
|
+
"server": "e2dd69fb.8f70a8",
|
|
88
|
+
"version": 3,
|
|
89
|
+
"exposeToHomeAssistant": false,
|
|
90
|
+
"haConfig": [
|
|
91
|
+
{ "property": "name", "value": "" },
|
|
92
|
+
{ "property": "icon", "value": "" }
|
|
93
|
+
],
|
|
94
|
+
"entityidfilter": "input_number.cascade_setpoint",
|
|
95
|
+
"entityidfiltertype": "exact",
|
|
96
|
+
"outputinitially": true,
|
|
97
|
+
"state_type": "num",
|
|
98
|
+
"haltifstate": "",
|
|
99
|
+
"halt_if_type": "str",
|
|
100
|
+
"halt_if_compare": "is",
|
|
101
|
+
"outputs": 1,
|
|
102
|
+
"output_only_on_state_change": false,
|
|
103
|
+
"for": 0,
|
|
104
|
+
"forType": "num",
|
|
105
|
+
"forUnits": "minutes",
|
|
106
|
+
"ignorePrevStateNull": false,
|
|
107
|
+
"ignorePrevStateUnknown": false,
|
|
108
|
+
"ignorePrevStateUnavailable": false,
|
|
109
|
+
"ignoreCurrentStateUnknown": true,
|
|
110
|
+
"ignoreCurrentStateUnavailable": true,
|
|
111
|
+
"outputProperties": [
|
|
112
|
+
{ "property": "payload", "propertyType": "msg", "value": "", "valueType": "entityState" },
|
|
113
|
+
{ "property": "data", "propertyType": "msg", "value": "", "valueType": "eventData" },
|
|
114
|
+
{ "property": "topic", "propertyType": "msg", "value": "", "valueType": "triggerId" }
|
|
115
|
+
],
|
|
116
|
+
"x": 120,
|
|
117
|
+
"y": 100,
|
|
118
|
+
"wires": [["f8958d382348c254"]]
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"id": "ef1c6050d6de41c7",
|
|
122
|
+
"type": "server-state-changed",
|
|
123
|
+
"z": "29fde6c61057362b",
|
|
124
|
+
"name": "Temp. sensor",
|
|
125
|
+
"server": "e2dd69fb.8f70a8",
|
|
126
|
+
"version": 3,
|
|
127
|
+
"exposeToHomeAssistant": false,
|
|
128
|
+
"haConfig": [
|
|
129
|
+
{ "property": "name", "value": "" },
|
|
130
|
+
{ "property": "icon", "value": "" }
|
|
131
|
+
],
|
|
132
|
+
"entityidfilter": "sensor.kjokken_temp",
|
|
133
|
+
"entityidfiltertype": "exact",
|
|
134
|
+
"outputinitially": true,
|
|
135
|
+
"state_type": "num",
|
|
136
|
+
"haltifstate": "",
|
|
137
|
+
"halt_if_type": "str",
|
|
138
|
+
"halt_if_compare": "is",
|
|
139
|
+
"outputs": 1,
|
|
140
|
+
"output_only_on_state_change": false,
|
|
141
|
+
"for": 0,
|
|
142
|
+
"forType": "num",
|
|
143
|
+
"forUnits": "seconds",
|
|
144
|
+
"ignorePrevStateNull": false,
|
|
145
|
+
"ignorePrevStateUnknown": false,
|
|
146
|
+
"ignorePrevStateUnavailable": false,
|
|
147
|
+
"ignoreCurrentStateUnknown": true,
|
|
148
|
+
"ignoreCurrentStateUnavailable": true,
|
|
149
|
+
"outputProperties": [
|
|
150
|
+
{ "property": "payload", "propertyType": "msg", "value": "", "valueType": "entityState" },
|
|
151
|
+
{ "property": "data", "propertyType": "msg", "value": "", "valueType": "eventData" },
|
|
152
|
+
{ "property": "topic", "propertyType": "msg", "value": "", "valueType": "triggerId" }
|
|
153
|
+
],
|
|
154
|
+
"x": 130,
|
|
155
|
+
"y": 160,
|
|
156
|
+
"wires": [["ee1904546f36bdcb"]]
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"id": "f8958d382348c254",
|
|
160
|
+
"type": "function",
|
|
161
|
+
"z": "29fde6c61057362b",
|
|
162
|
+
"name": "Specify topic",
|
|
163
|
+
"func": "msg.topic = \"setpoint\"\nflow.set('setpoint',msg.payload)\nreturn msg",
|
|
164
|
+
"outputs": 1,
|
|
165
|
+
"noerr": 0,
|
|
166
|
+
"initialize": "",
|
|
167
|
+
"finalize": "",
|
|
168
|
+
"libs": [],
|
|
169
|
+
"x": 270,
|
|
170
|
+
"y": 100,
|
|
171
|
+
"wires": [["6f77dd60c21180e1"]]
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"id": "6f77dd60c21180e1",
|
|
175
|
+
"type": "PID",
|
|
176
|
+
"z": "29fde6c61057362b",
|
|
177
|
+
"name": "",
|
|
178
|
+
"setpoint": "7",
|
|
179
|
+
"pb": "0.6",
|
|
180
|
+
"ti": "3600",
|
|
181
|
+
"td": "900",
|
|
182
|
+
"integral_default": 0.5,
|
|
183
|
+
"smooth_factor": "2",
|
|
184
|
+
"max_interval": "600",
|
|
185
|
+
"enable": 1,
|
|
186
|
+
"disabled_op": 0,
|
|
187
|
+
"x": 430,
|
|
188
|
+
"y": 140,
|
|
189
|
+
"wires": [["ea6adedb7e2fc14e"]]
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"id": "ea6adedb7e2fc14e",
|
|
193
|
+
"type": "function",
|
|
194
|
+
"z": "29fde6c61057362b",
|
|
195
|
+
"name": "Calc oven setpoint",
|
|
196
|
+
"func": "msg.load = msg.payload\n//Max adjustment is +-5 degrees\ntemp = flow.get('setpoint')+ 5 * 2 * (msg.load-0.5)\n//Some ovens have max and min temperature settings\nif(temp<5) {temp=5.0;}\nif(temp>30) {temp=30.0;}\n//Many ovens cannot deal with decimals.\ntemp = Math.round(temp)\nmsg.heater_setpoint=temp\nreturn msg",
|
|
197
|
+
"outputs": 1,
|
|
198
|
+
"noerr": 0,
|
|
199
|
+
"initialize": "",
|
|
200
|
+
"finalize": "",
|
|
201
|
+
"libs": [],
|
|
202
|
+
"x": 590,
|
|
203
|
+
"y": 140,
|
|
204
|
+
"wires": [["45925567a1177d5b"]]
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"id": "5fa07ec0c1842823",
|
|
208
|
+
"type": "api-current-state",
|
|
209
|
+
"z": "29fde6c61057362b",
|
|
210
|
+
"name": "Current climate settings",
|
|
211
|
+
"server": "e2dd69fb.8f70a8",
|
|
212
|
+
"version": 3,
|
|
213
|
+
"outputs": 1,
|
|
214
|
+
"halt_if": "",
|
|
215
|
+
"halt_if_type": "str",
|
|
216
|
+
"halt_if_compare": "is",
|
|
217
|
+
"entity_id": "climate.my_climate",
|
|
218
|
+
"state_type": "str",
|
|
219
|
+
"blockInputOverrides": false,
|
|
220
|
+
"outputProperties": [
|
|
221
|
+
{ "property": "payload", "propertyType": "msg", "value": "", "valueType": "entityState" },
|
|
222
|
+
{ "property": "data", "propertyType": "msg", "value": "", "valueType": "entity" }
|
|
223
|
+
],
|
|
224
|
+
"for": 0,
|
|
225
|
+
"forType": "num",
|
|
226
|
+
"forUnits": "minutes",
|
|
227
|
+
"x": 950,
|
|
228
|
+
"y": 140,
|
|
229
|
+
"wires": [["ba7e48582e04c14c", "0a7c09c92a01178e"]]
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"id": "ba7e48582e04c14c",
|
|
233
|
+
"type": "switch",
|
|
234
|
+
"z": "29fde6c61057362b",
|
|
235
|
+
"name": "Not same?",
|
|
236
|
+
"property": "data.attributes.temperature",
|
|
237
|
+
"propertyType": "msg",
|
|
238
|
+
"rules": [{ "t": "neq", "v": "heater_setpoint", "vt": "msg" }],
|
|
239
|
+
"checkall": "true",
|
|
240
|
+
"repair": false,
|
|
241
|
+
"outputs": 1,
|
|
242
|
+
"x": 1150,
|
|
243
|
+
"y": 140,
|
|
244
|
+
"wires": [["1114bb7e63d16e98", "0a7c09c92a01178e"]]
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"id": "1114bb7e63d16e98",
|
|
248
|
+
"type": "api-call-service",
|
|
249
|
+
"z": "29fde6c61057362b",
|
|
250
|
+
"name": "Sett temperatur",
|
|
251
|
+
"server": "e2dd69fb.8f70a8",
|
|
252
|
+
"version": 3,
|
|
253
|
+
"debugenabled": false,
|
|
254
|
+
"service_domain": "climate",
|
|
255
|
+
"service": "set_temperature",
|
|
256
|
+
"entityId": "climate.my_climate",
|
|
257
|
+
"data": "{\"entity_id\":\"climate.my_climate\",\"temperature\":\"{{heater_setpoint}}\"}",
|
|
258
|
+
"dataType": "json",
|
|
259
|
+
"mergecontext": "",
|
|
260
|
+
"mustacheAltTags": false,
|
|
261
|
+
"outputProperties": [],
|
|
262
|
+
"queue": "none",
|
|
263
|
+
"x": 1320,
|
|
264
|
+
"y": 140,
|
|
265
|
+
"wires": [[]]
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"id": "45925567a1177d5b",
|
|
269
|
+
"type": "api-current-state",
|
|
270
|
+
"z": "29fde6c61057362b",
|
|
271
|
+
"name": "Enabled?",
|
|
272
|
+
"server": "e2dd69fb.8f70a8",
|
|
273
|
+
"version": 3,
|
|
274
|
+
"outputs": 2,
|
|
275
|
+
"halt_if": "true",
|
|
276
|
+
"halt_if_type": "bool",
|
|
277
|
+
"halt_if_compare": "is",
|
|
278
|
+
"entity_id": "input_boolean.cascade_enabled",
|
|
279
|
+
"state_type": "habool",
|
|
280
|
+
"blockInputOverrides": false,
|
|
281
|
+
"outputProperties": [
|
|
282
|
+
{ "property": "enabled", "propertyType": "msg", "value": "", "valueType": "entityState" },
|
|
283
|
+
{ "property": "data", "propertyType": "msg", "value": "", "valueType": "entity" }
|
|
284
|
+
],
|
|
285
|
+
"for": 0,
|
|
286
|
+
"forType": "num",
|
|
287
|
+
"forUnits": "minutes",
|
|
288
|
+
"x": 760,
|
|
289
|
+
"y": 140,
|
|
290
|
+
"wires": [["5fa07ec0c1842823"], []]
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"id": "0a7c09c92a01178e",
|
|
294
|
+
"type": "debug",
|
|
295
|
+
"z": "29fde6c61057362b",
|
|
296
|
+
"name": "",
|
|
297
|
+
"active": false,
|
|
298
|
+
"tosidebar": true,
|
|
299
|
+
"console": false,
|
|
300
|
+
"tostatus": false,
|
|
301
|
+
"complete": "true",
|
|
302
|
+
"targetType": "full",
|
|
303
|
+
"statusVal": "",
|
|
304
|
+
"statusType": "auto",
|
|
305
|
+
"x": 1330,
|
|
306
|
+
"y": 240,
|
|
307
|
+
"wires": []
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
"id": "ee1904546f36bdcb",
|
|
311
|
+
"type": "delay",
|
|
312
|
+
"z": "29fde6c61057362b",
|
|
313
|
+
"name": "",
|
|
314
|
+
"pauseType": "delay",
|
|
315
|
+
"timeout": "100",
|
|
316
|
+
"timeoutUnits": "milliseconds",
|
|
317
|
+
"rate": "1",
|
|
318
|
+
"nbRateUnits": "1",
|
|
319
|
+
"rateUnits": "second",
|
|
320
|
+
"randomFirst": "1",
|
|
321
|
+
"randomLast": "5",
|
|
322
|
+
"randomUnits": "seconds",
|
|
323
|
+
"drop": false,
|
|
324
|
+
"allowrate": false,
|
|
325
|
+
"outputs": 1,
|
|
326
|
+
"x": 290,
|
|
327
|
+
"y": 160,
|
|
328
|
+
"wires": [["6f77dd60c21180e1"]]
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
"id": "e2dd69fb.8f70a8",
|
|
332
|
+
"type": "server",
|
|
333
|
+
"name": "Home Assistant",
|
|
334
|
+
"version": 2,
|
|
335
|
+
"addon": true,
|
|
336
|
+
"rejectUnauthorizedCerts": true,
|
|
337
|
+
"ha_boolean": "y|yes|true|on|home|open",
|
|
338
|
+
"connectionDelay": false,
|
|
339
|
+
"cacheJson": true,
|
|
340
|
+
"heartbeat": true,
|
|
341
|
+
"heartbeatInterval": "30"
|
|
342
|
+
}
|
|
343
|
+
]
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
:::
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# Simple heat capacitor strategy flow
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
The heat capacitor strategy utilizes a large body of mass, like your house or cabin, to procure heat at a time where electricity is cheap, and divest at a time where electricity is expensive.
|
|
6
|
+
|
|
7
|
+
This is achieved by increasing the temperature setpoint of one or several climate entities at times when electricity is cheap, and reducing it when electricity is expensive.
|
|
8
|
+
|
|
9
|
+
It is a good application for cabins/heated storage spaces, as the entity never actually shuts off the climate entities and should therefore be rather safe to apply (still at you own risk :-)). It can also be used for you house, jacuzzi, and/or pool.
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Requirements
|
|
16
|
+
|
|
17
|
+
> Home assistant integrated with Node-RED
|
|
18
|
+
|
|
19
|
+
> Tibber node installed and correctly configured
|
|
20
|
+
|
|
21
|
+
> A climate entity
|
|
22
|
+
|
|
23
|
+
## Instructions
|
|
24
|
+
|
|
25
|
+
> Create an `input_number` entity in Home Assistant named `setpoint`
|
|
26
|
+
|
|
27
|
+
> Import the flow into Node-RED
|
|
28
|
+
|
|
29
|
+
> Configure the heat-capacitor node:
|
|
30
|
+
- Insert an approximate time it takes to increase the temperature by 1 Centigrade (could be 90 minutes)
|
|
31
|
+
- Insert an approximate time it takes to decrease 1 Centigrade
|
|
32
|
+
- Insert minimum savings for a heating/cooling cycle (should not be zero, as a cycle might have a cost)
|
|
33
|
+
|
|
34
|
+
> Configure the climate service to target the correct climate entity (this has to be edited in two places)
|
|
35
|
+
- Change `Entity Id` in the properties menu
|
|
36
|
+
- Change the `entity_id` value in the `Data` property
|
|
37
|
+
|
|
38
|
+
> (optional) If the `input_number` entity was named something else than `setpoint`, change the `entity_id` of the `Setpoint` node accordingly.
|
|
39
|
+
|
|
40
|
+
### Advanced set-up
|
|
41
|
+
|
|
42
|
+
> Replace the `Set temperature` node with a [Cascade controller](./example-cascade-temperature-control.md) to improve the heaters accuracy and response time.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Flow
|
|
47
|
+
|
|
48
|
+

|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
::: details [Flow code]
|
|
54
|
+
|
|
55
|
+
```json:no-line-numbers
|
|
56
|
+
[
|
|
57
|
+
{
|
|
58
|
+
"id": "135c4e7649611314",
|
|
59
|
+
"type": "tab",
|
|
60
|
+
"label": "PowerSaver",
|
|
61
|
+
"disabled": false,
|
|
62
|
+
"info": "",
|
|
63
|
+
"env": []
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"id": "cf5908a52e0aee5e",
|
|
67
|
+
"type": "ps-receive-price",
|
|
68
|
+
"z": "135c4e7649611314",
|
|
69
|
+
"name": "Price Receiver",
|
|
70
|
+
"x": 400,
|
|
71
|
+
"y": 320,
|
|
72
|
+
"wires": [
|
|
73
|
+
[
|
|
74
|
+
"b7b85590b7d28ba6"
|
|
75
|
+
]
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"id": "b08bc12bf8734c5a",
|
|
80
|
+
"type": "tibber-query",
|
|
81
|
+
"z": "135c4e7649611314",
|
|
82
|
+
"name": "",
|
|
83
|
+
"active": true,
|
|
84
|
+
"apiEndpointRef": "9ea07b03b88cb526",
|
|
85
|
+
"x": 230,
|
|
86
|
+
"y": 320,
|
|
87
|
+
"wires": [
|
|
88
|
+
[
|
|
89
|
+
"cf5908a52e0aee5e"
|
|
90
|
+
]
|
|
91
|
+
]
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"id": "d0d4dd31efe67e85",
|
|
95
|
+
"type": "inject",
|
|
96
|
+
"z": "135c4e7649611314",
|
|
97
|
+
"name": "",
|
|
98
|
+
"props": [
|
|
99
|
+
{
|
|
100
|
+
"p": "payload"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"p": "topic",
|
|
104
|
+
"vt": "str"
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
"repeat": "60",
|
|
108
|
+
"crontab": "",
|
|
109
|
+
"once": true,
|
|
110
|
+
"onceDelay": "1",
|
|
111
|
+
"topic": "",
|
|
112
|
+
"payload": "{ viewer { homes { currentSubscription { priceInfo { today { total startsAt } tomorrow { total startsAt } } } } } }",
|
|
113
|
+
"payloadType": "str",
|
|
114
|
+
"x": 90,
|
|
115
|
+
"y": 320,
|
|
116
|
+
"wires": [
|
|
117
|
+
[
|
|
118
|
+
"b08bc12bf8734c5a"
|
|
119
|
+
]
|
|
120
|
+
]
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"id": "4831f393a0066565",
|
|
124
|
+
"type": "api-call-service",
|
|
125
|
+
"z": "135c4e7649611314",
|
|
126
|
+
"name": "Set temperature",
|
|
127
|
+
"server": "e2dd69fb.8f70a8",
|
|
128
|
+
"version": 3,
|
|
129
|
+
"debugenabled": false,
|
|
130
|
+
"service_domain": "climate",
|
|
131
|
+
"service": "set_temperature",
|
|
132
|
+
"entityId": "climate.my_climate",
|
|
133
|
+
"data": "{\"entity_id\":\"climate.my_climate\",\"temperature\":\"{{adj_setpoint}}\"}",
|
|
134
|
+
"dataType": "json",
|
|
135
|
+
"mergecontext": "",
|
|
136
|
+
"mustacheAltTags": false,
|
|
137
|
+
"outputProperties": [],
|
|
138
|
+
"queue": "none",
|
|
139
|
+
"x": 980,
|
|
140
|
+
"y": 320,
|
|
141
|
+
"wires": [
|
|
142
|
+
[]
|
|
143
|
+
]
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"id": "027f4267d969e1b8",
|
|
147
|
+
"type": "server-state-changed",
|
|
148
|
+
"z": "135c4e7649611314",
|
|
149
|
+
"name": "Setpoint",
|
|
150
|
+
"server": "e2dd69fb.8f70a8",
|
|
151
|
+
"version": 3,
|
|
152
|
+
"exposeToHomeAssistant": false,
|
|
153
|
+
"haConfig": [
|
|
154
|
+
{
|
|
155
|
+
"property": "name",
|
|
156
|
+
"value": ""
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"property": "icon",
|
|
160
|
+
"value": ""
|
|
161
|
+
}
|
|
162
|
+
],
|
|
163
|
+
"entityidfilter": "input_number.setpoint",
|
|
164
|
+
"entityidfiltertype": "exact",
|
|
165
|
+
"outputinitially": true,
|
|
166
|
+
"state_type": "num",
|
|
167
|
+
"haltifstate": "",
|
|
168
|
+
"halt_if_type": "str",
|
|
169
|
+
"halt_if_compare": "is",
|
|
170
|
+
"outputs": 1,
|
|
171
|
+
"output_only_on_state_change": false,
|
|
172
|
+
"for": 0,
|
|
173
|
+
"forType": "num",
|
|
174
|
+
"forUnits": "minutes",
|
|
175
|
+
"ignorePrevStateNull": false,
|
|
176
|
+
"ignorePrevStateUnknown": false,
|
|
177
|
+
"ignorePrevStateUnavailable": false,
|
|
178
|
+
"ignoreCurrentStateUnknown": true,
|
|
179
|
+
"ignoreCurrentStateUnavailable": true,
|
|
180
|
+
"outputProperties": [
|
|
181
|
+
{
|
|
182
|
+
"property": "payload.config.setpoint",
|
|
183
|
+
"propertyType": "msg",
|
|
184
|
+
"value": "",
|
|
185
|
+
"valueType": "entityState"
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"property": "data",
|
|
189
|
+
"propertyType": "msg",
|
|
190
|
+
"value": "",
|
|
191
|
+
"valueType": "eventData"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"property": "topic",
|
|
195
|
+
"propertyType": "msg",
|
|
196
|
+
"value": "",
|
|
197
|
+
"valueType": "triggerId"
|
|
198
|
+
}
|
|
199
|
+
],
|
|
200
|
+
"x": 420,
|
|
201
|
+
"y": 360,
|
|
202
|
+
"wires": [
|
|
203
|
+
[
|
|
204
|
+
"b7b85590b7d28ba6"
|
|
205
|
+
]
|
|
206
|
+
]
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"id": "b7b85590b7d28ba6",
|
|
210
|
+
"type": "ps-strategy-heat-capacitor",
|
|
211
|
+
"z": "135c4e7649611314",
|
|
212
|
+
"name": "Heat capacitor",
|
|
213
|
+
"timeHeat1C": "70",
|
|
214
|
+
"timeCool1C": 50,
|
|
215
|
+
"maxTempAdjustment": "1",
|
|
216
|
+
"boostTempHeat": "2",
|
|
217
|
+
"boostTempCool": "2",
|
|
218
|
+
"minSavings": 0.08,
|
|
219
|
+
"setpoint": 23,
|
|
220
|
+
"x": 600,
|
|
221
|
+
"y": 320,
|
|
222
|
+
"wires": [
|
|
223
|
+
[
|
|
224
|
+
"2b7cbdef3203a482"
|
|
225
|
+
],
|
|
226
|
+
[],
|
|
227
|
+
[]
|
|
228
|
+
]
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
"id": "2b7cbdef3203a482",
|
|
232
|
+
"type": "function",
|
|
233
|
+
"z": "135c4e7649611314",
|
|
234
|
+
"name": "Adjust setpoint",
|
|
235
|
+
"func": "//In case the climate entity can only handle integers\n//Calculate rounded setpoint for the climate entity and return the msg\nmsg.adj_setpoint=Math.round(msg.payload);\nreturn msg\n",
|
|
236
|
+
"outputs": 1,
|
|
237
|
+
"noerr": 0,
|
|
238
|
+
"initialize": "",
|
|
239
|
+
"finalize": "",
|
|
240
|
+
"libs": [],
|
|
241
|
+
"x": 800,
|
|
242
|
+
"y": 320,
|
|
243
|
+
"wires": [
|
|
244
|
+
[
|
|
245
|
+
"4831f393a0066565"
|
|
246
|
+
]
|
|
247
|
+
]
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
"id": "9ea07b03b88cb526",
|
|
251
|
+
"type": "tibber-api-endpoint",
|
|
252
|
+
"feedUrl": "wss://api.tibber.com/v1-beta/gql/subscriptions",
|
|
253
|
+
"queryUrl": "https://api.tibber.com/v1-beta/gql",
|
|
254
|
+
"name": "Tibber"
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"id": "e2dd69fb.8f70a8",
|
|
258
|
+
"type": "server",
|
|
259
|
+
"name": "Home Assistant",
|
|
260
|
+
"version": 2,
|
|
261
|
+
"addon": false,
|
|
262
|
+
"rejectUnauthorizedCerts": true,
|
|
263
|
+
"ha_boolean": "y|yes|true|on|home|open",
|
|
264
|
+
"connectionDelay": false,
|
|
265
|
+
"cacheJson": true,
|
|
266
|
+
"heartbeat": false,
|
|
267
|
+
"heartbeatInterval": 30
|
|
268
|
+
}
|
|
269
|
+
]
|
|
270
|
+
```
|
|
271
|
+
:::
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/docs/nodes/README.md
CHANGED
|
@@ -16,7 +16,7 @@ These are the nodes used to calculate and control saving.
|
|
|
16
16
|
|
|
17
17
|

|
|
18
18
|
|
|
19
|
-
Strategy to find the best hours to
|
|
19
|
+
Strategy to find the best hours to postpone power consumption to achieve the most saving.
|
|
20
20
|
|
|
21
21
|
### [ps-strategy-lowest-price](./ps-strategy-lowest-price)
|
|
22
22
|
|
|
@@ -24,6 +24,12 @@ Strategy to find the best hours to turn off for most saving.
|
|
|
24
24
|
|
|
25
25
|
Strategy to find the x hours with lowest price in a given period each day.
|
|
26
26
|
|
|
27
|
+
### [ps-strategy-heat-capacitor](./ps-strategy-heat-capacitor) <Badge type="warning">Experimental</Badge>
|
|
28
|
+
|
|
29
|
+

|
|
30
|
+
|
|
31
|
+
A strategy for moving consumption from expensive to cheap periods utilizing climate entities and trading principles.
|
|
32
|
+
|
|
27
33
|
## Utility nodes
|
|
28
34
|
|
|
29
35
|
### [ps-receive-price](./ps-receive-price)
|