node-red-contrib-power-saver 3.4.2 → 3.5.0
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/.github/workflows/{firebase-hosting-merge.yml → publish-doc-on-merge.yml} +6 -6
- package/.github/workflows/publish-to-npm.yml +23 -0
- package/.github/workflows/test-on-pull-request.yaml +13 -0
- package/docs/.vuepress/components/BestSaveVerificator.vue +18 -7
- package/docs/.vuepress/components/DonateButtons.vue +0 -1
- package/docs/.vuepress/config.js +9 -53
- package/docs/.vuepress/navbar.js +43 -0
- package/docs/.vuepress/public/Ukraine-heart-shape-flag.png +0 -0
- package/docs/changelog/README.md +14 -0
- package/docs/examples/example-cascade-temperature-control.md +0 -13
- package/docs/examples/example-heat-capacitor.md +9 -20
- package/docs/examples/example-nordpool-current-state.md +0 -13
- package/docs/examples/example-nordpool-events-state.md +0 -13
- package/docs/examples/example-tibber-mqtt.md +0 -13
- package/docs/faq/best-save-viewer.md +1 -0
- package/docs/guide/README.md +20 -12
- package/docs/images/best-save-config.png +0 -0
- package/docs/images/lowest-price-config.png +0 -0
- package/docs/nodes/ps-strategy-best-save.md +67 -11
- package/docs/nodes/ps-strategy-lowest-price.md +69 -0
- package/package.json +9 -11
- package/src/elvia/elvia-add-tariff.html +8 -2
- package/src/elvia/elvia-config.js +7 -0
- package/src/elvia/elvia-tariff-types.js +0 -6
- package/src/handle-input.js +30 -10
- package/src/receive-price-functions.js +2 -0
- package/src/strategy-best-save.html +14 -0
- package/src/strategy-best-save.js +6 -2
- package/src/strategy-lowest-price.html +15 -2
- package/src/strategy-lowest-price.js +3 -1
- package/src/utils.js +3 -3
- package/test/data/lowest-price-result-cont.json +1 -0
- package/test/data/lowest-price-result-missing-end.json +1 -0
- package/test/data/lowest-price-result-split-allday.json +1 -0
- package/test/data/lowest-price-result-split-allday10.json +1 -0
- package/test/data/lowest-price-result-split.json +1 -0
- package/test/data/tibber-result-end-0-24h.json +1 -0
- package/test/data/tibber-result-end-0.json +1 -0
- package/.firebase/hosting.ZG9jcy8udnVlcHJlc3MvZGlzdA.cache +0 -94
- package/.github/workflows/firebase-hosting-pull-request.yml +0 -17
- package/docs/.vuepress/dist/404.html +0 -33
- package/docs/.vuepress/dist/assets/css/835.styles.c5afb22b.css +0 -1
- package/docs/.vuepress/dist/assets/css/896.styles.21a80cb6.css +0 -1
- package/docs/.vuepress/dist/assets/css/styles.1c48cbd0.css +0 -10
- package/docs/.vuepress/dist/assets/img/add-tariff-flow.eb700d4f.png +0 -0
- package/docs/.vuepress/dist/assets/img/back-to-top.8b37f773.svg +0 -1
- package/docs/.vuepress/dist/assets/img/best-save-config.79a2f39a.png +0 -0
- package/docs/.vuepress/dist/assets/img/copy-payload-best-save.b9192985.png +0 -0
- package/docs/.vuepress/dist/assets/img/elvia-config-no-config.b4bb972c.png +0 -0
- package/docs/.vuepress/dist/assets/img/elvia-config-no-tariff.3f89aba8.png +0 -0
- package/docs/.vuepress/dist/assets/img/elvia-config-select-tariff.0f73fd56.png +0 -0
- package/docs/.vuepress/dist/assets/img/elvia-config-subscription-key.8be8ab8a.png +0 -0
- package/docs/.vuepress/dist/assets/img/elvia-flow.bae2a4d5.png +0 -0
- package/docs/.vuepress/dist/assets/img/example-flow-1.3ff3e23f.png +0 -0
- package/docs/.vuepress/dist/assets/img/example-flow-2.b653b58d.png +0 -0
- package/docs/.vuepress/dist/assets/img/heat-capacitor-temperatureVsPrice.6e74905b.png +0 -0
- package/docs/.vuepress/dist/assets/img/lowest-price-config.6d66a8c2.png +0 -0
- package/docs/.vuepress/dist/assets/img/migrate-best-save.f73420f6.png +0 -0
- package/docs/.vuepress/dist/assets/img/migrate-power-saver.aae13f9d.png +0 -0
- package/docs/.vuepress/dist/assets/img/next-schedule-entity.4406856a.png +0 -0
- package/docs/.vuepress/dist/assets/img/next-schedule-flow.413ad62b.png +0 -0
- package/docs/.vuepress/dist/assets/img/next-schedule-sensor.eb896bdd.png +0 -0
- package/docs/.vuepress/dist/assets/img/node-power-saver.51ff2e5d.png +0 -0
- package/docs/.vuepress/dist/assets/img/node-ps-elvia-add-tariff.94ea2b09.png +0 -0
- package/docs/.vuepress/dist/assets/img/node-ps-general-add-tariff.a3cf6f06.png +0 -0
- package/docs/.vuepress/dist/assets/img/node-ps-receive-price.76eaa418.png +0 -0
- package/docs/.vuepress/dist/assets/img/node-ps-strategy-best-save.392292d5.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/node-ps-strategy-lowest-price.3a4ad347.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/img/power-saver-nordpool-current-state.bf14afde.png +0 -0
- package/docs/.vuepress/dist/assets/img/power-saver-nordpool-events-state.8c392507.png +0 -0
- package/docs/.vuepress/dist/assets/img/power-saver-tibber-mqtt.16891dd2.png +0 -0
- package/docs/.vuepress/dist/assets/js/229.5c5378fa.js +0 -1
- package/docs/.vuepress/dist/assets/js/331.872104cd.js +0 -1
- package/docs/.vuepress/dist/assets/js/405.f4edd94d.js +0 -2
- package/docs/.vuepress/dist/assets/js/405.f4edd94d.js.LICENSE.txt +0 -8
- package/docs/.vuepress/dist/assets/js/490.1e639e05.js +0 -1
- package/docs/.vuepress/dist/assets/js/491.bd938119.js +0 -1
- package/docs/.vuepress/dist/assets/js/555.d8963d84.js +0 -1
- package/docs/.vuepress/dist/assets/js/811.5f659592.js +0 -1
- package/docs/.vuepress/dist/assets/js/app.dfdee6f9.js +0 -1
- package/docs/.vuepress/dist/assets/js/runtime~app.f6ac32d7.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-0607240a.0193a377.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-08683c60.52e94cb6.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-0aca7ba6.cac5d4b9.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-0b5e3c8c.18561f6e.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-1ad821fa.6697a349.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-1b3a0ab8.c6c4e19b.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-1e2b191e.07b8ab21.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-29504124.00be7399.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-30acb564.28af12af.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-3706649a.c76d575b.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-4637f9e4.d334c29a.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-4c28314d.8cbb0f9d.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-510ed0d4.c04bc2e4.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-5954bcb2.dff3fc67.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-5db8da3a.e5e6d7a6.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-61f728ca.81968036.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-677dfaed.c159b0f4.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-7446a652.8fc2c591.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-7c87f26e.8ed52391.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-84304104.f3f07ed3.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-8daa1a0e.ed84ca09.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-b4a42144.9a2a0c9f.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-e8c55052.b7d52fc6.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-fffb8e28.d09ab959.js +0 -1
- package/docs/.vuepress/dist/changelog/index.html +0 -33
- package/docs/.vuepress/dist/contribute/index.html +0 -33
- package/docs/.vuepress/dist/euro.png +0 -0
- package/docs/.vuepress/dist/examples/example-cascade-temperature-control.html +0 -304
- package/docs/.vuepress/dist/examples/example-heat-capacitor.html +0 -247
- package/docs/.vuepress/dist/examples/example-next-schedule-entity.html +0 -43
- package/docs/.vuepress/dist/examples/example-nordpool-current-state.html +0 -206
- package/docs/.vuepress/dist/examples/example-nordpool-events-state.html +0 -191
- package/docs/.vuepress/dist/examples/example-tibber-mqtt.html +0 -199
- package/docs/.vuepress/dist/examples/index.html +0 -33
- package/docs/.vuepress/dist/faq/best-save-viewer.html +0 -33
- package/docs/.vuepress/dist/faq/index.html +0 -33
- package/docs/.vuepress/dist/guide/index.html +0 -70
- package/docs/.vuepress/dist/index.html +0 -33
- package/docs/.vuepress/dist/logo.png +0 -0
- package/docs/.vuepress/dist/nodes/index.html +0 -33
- package/docs/.vuepress/dist/nodes/old-power-saver-doc.html +0 -115
- package/docs/.vuepress/dist/nodes/power-saver.html +0 -33
- package/docs/.vuepress/dist/nodes/ps-elvia-add-tariff.html +0 -33
- package/docs/.vuepress/dist/nodes/ps-general-add-tariff.html +0 -33
- package/docs/.vuepress/dist/nodes/ps-receive-price.html +0 -98
- package/docs/.vuepress/dist/nodes/ps-strategy-best-save.html +0 -104
- package/docs/.vuepress/dist/nodes/ps-strategy-heat-capacitor.html +0 -260
- package/docs/.vuepress/dist/nodes/ps-strategy-lowest-price.html +0 -124
- package/docs/.vuepress/dist/nodes/strategy-input.html +0 -58
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
name: Deploy to Firebase Hosting on merge
|
|
5
|
-
'on':
|
|
1
|
+
name: "Publish docs to firebase on merge"
|
|
2
|
+
on:
|
|
6
3
|
push:
|
|
7
4
|
branches:
|
|
8
|
-
-
|
|
5
|
+
- "main"
|
|
6
|
+
paths:
|
|
7
|
+
- "docs/**"
|
|
9
8
|
jobs:
|
|
10
9
|
build_and_deploy:
|
|
11
10
|
runs-on: ubuntu-latest
|
|
12
11
|
steps:
|
|
13
12
|
- uses: actions/checkout@v2
|
|
13
|
+
- run: npm ci
|
|
14
14
|
- run: 'npm run docs:build'
|
|
15
15
|
- uses: FirebaseExtended/action-hosting-deploy@v0
|
|
16
16
|
with:
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
name: Publish to npmjs
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [created]
|
|
6
|
+
jobs:
|
|
7
|
+
build:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
steps:
|
|
10
|
+
- uses: actions/checkout@v3
|
|
11
|
+
# Setup .npmrc file to publish to npm
|
|
12
|
+
- uses: actions/setup-node@v3
|
|
13
|
+
with:
|
|
14
|
+
node-version: '16.x'
|
|
15
|
+
registry-url: 'https://registry.npmjs.org'
|
|
16
|
+
- uses: szenius/set-timezone@v1.0
|
|
17
|
+
with:
|
|
18
|
+
timezoneLinux: "Europe/Oslo"
|
|
19
|
+
- run: npm ci
|
|
20
|
+
- run: 'npm run test'
|
|
21
|
+
- run: npm publish
|
|
22
|
+
env:
|
|
23
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
name: Run tests on pull request
|
|
2
|
+
on: pull_request
|
|
3
|
+
jobs:
|
|
4
|
+
build_and_test:
|
|
5
|
+
if: '${{ github.event.pull_request.head.repo.full_name == github.repository }}'
|
|
6
|
+
runs-on: ubuntu-latest
|
|
7
|
+
steps:
|
|
8
|
+
- uses: actions/checkout@v2
|
|
9
|
+
- uses: szenius/set-timezone@v1.0
|
|
10
|
+
with:
|
|
11
|
+
timezoneLinux: "Europe/Oslo"
|
|
12
|
+
- run: npm ci
|
|
13
|
+
- run: 'npm run test'
|
|
@@ -6,8 +6,15 @@
|
|
|
6
6
|
<p>Max in sequence: {{ payload.config.maxHoursToSaveInSequence }}</p>
|
|
7
7
|
<p>Min on after max: {{ payload.config.minHoursOnAfterMaxSequenceSaved }}</p>
|
|
8
8
|
<p>Minimum saving: {{ payload.config.minSaving }}</p>
|
|
9
|
-
<p>
|
|
10
|
-
|
|
9
|
+
<p>
|
|
10
|
+
Send when rescheduling:
|
|
11
|
+
{{ payload.config.sendCurrentValueWhenRescheduling ? "Yes" : "No" }}
|
|
12
|
+
</p>
|
|
13
|
+
<p>
|
|
14
|
+
If no schedule, output:
|
|
15
|
+
{{ payload.config.outputIfNoSchedule ? "On" : "Off" }}
|
|
16
|
+
</p>
|
|
17
|
+
<p>Context is saved to: {{ payload.config.contextStorage }}</p>
|
|
11
18
|
<h3>Meta data:</h3>
|
|
12
19
|
<p>Node version: {{ payload.version }}</p>
|
|
13
20
|
<p>Data timestamp: {{ payload.time }}</p>
|
|
@@ -78,7 +85,9 @@
|
|
|
78
85
|
</tr>
|
|
79
86
|
<tr v-for="(hour, i) in payload.hours" :key="hour.start">
|
|
80
87
|
<td>{{ DateTime.fromISO(hour.start).day }}</td>
|
|
81
|
-
<td>
|
|
88
|
+
<td>
|
|
89
|
+
{{ DateTime.fromISO(hour.start).toLocaleString(DateTime.TIME_SIMPLE) }}
|
|
90
|
+
</td>
|
|
82
91
|
<td :class="priceClasses(i)">{{ hour.price }}</td>
|
|
83
92
|
<td>{{ hour.onOff ? "On" : "Off" }}</td>
|
|
84
93
|
<td>{{ hour.saving ?? "" }}</td>
|
|
@@ -106,9 +115,7 @@
|
|
|
106
115
|
|
|
107
116
|
<script setup>
|
|
108
117
|
import { computed, reactive, ref, watch } from "vue";
|
|
109
|
-
|
|
110
|
-
const { roundPrice } = import("../../../src/utils");
|
|
111
|
-
const { DateTime } = import("luxon");
|
|
118
|
+
import { DateTime } from "luxon";
|
|
112
119
|
|
|
113
120
|
const message = ref("");
|
|
114
121
|
const showNegative = ref(false);
|
|
@@ -116,7 +123,9 @@ const showNegative = ref(false);
|
|
|
116
123
|
const show = ref("avg");
|
|
117
124
|
const showSum = computed(() => show.value === "sum");
|
|
118
125
|
|
|
119
|
-
|
|
126
|
+
function roundPrice(value) {
|
|
127
|
+
return Math.round(value * 10000) / 10000;
|
|
128
|
+
}
|
|
120
129
|
|
|
121
130
|
const dataString = ref("");
|
|
122
131
|
watch(dataString, (value) => {
|
|
@@ -147,6 +156,8 @@ const totalPerSequence = reactive([]);
|
|
|
147
156
|
const averagePerSequence = reactive([]);
|
|
148
157
|
|
|
149
158
|
function calculatePotentialSavings() {
|
|
159
|
+
console.log("calculatePotentialSavings");
|
|
160
|
+
console.log({ roundPrice });
|
|
150
161
|
const hours = payload.hours;
|
|
151
162
|
|
|
152
163
|
// Savings per hour
|
package/docs/.vuepress/config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { path } = require("@vuepress/utils");
|
|
2
|
-
const
|
|
2
|
+
const navbar = require("./navbar");
|
|
3
3
|
|
|
4
4
|
module.exports = {
|
|
5
5
|
lang: "en-US",
|
|
@@ -8,36 +8,8 @@ module.exports = {
|
|
|
8
8
|
base: "/",
|
|
9
9
|
themeConfig: {
|
|
10
10
|
contributors: false,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
text: "Guide",
|
|
14
|
-
link: "/guide/",
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
text: "Nodes",
|
|
18
|
-
link: "/nodes/",
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
text: "Examples",
|
|
22
|
-
link: "/examples/",
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
text: "FAQ",
|
|
26
|
-
link: "/faq/",
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
text: "Contribute",
|
|
30
|
-
link: "/contribute/",
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
text: "Changes",
|
|
34
|
-
link: "/changelog/",
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
text: "GitHub",
|
|
38
|
-
link: "https://github.com/ottopaulsen/node-red-contrib-power-saver",
|
|
39
|
-
},
|
|
40
|
-
],
|
|
11
|
+
logo: "/Ukraine-heart-shape-flag.png",
|
|
12
|
+
navbar,
|
|
41
13
|
sidebar: {
|
|
42
14
|
"/guide/": [{ text: "Guide", children: ["/guide/README.md"] }],
|
|
43
15
|
"/nodes/": [
|
|
@@ -50,7 +22,10 @@ module.exports = {
|
|
|
50
22
|
children: [
|
|
51
23
|
"/nodes/ps-strategy-best-save.md",
|
|
52
24
|
"/nodes/ps-strategy-lowest-price.md",
|
|
53
|
-
{
|
|
25
|
+
{
|
|
26
|
+
text: "ps-strategy-heat-capacitor",
|
|
27
|
+
link: "/nodes/ps-strategy-heat-capacitor.md",
|
|
28
|
+
},
|
|
54
29
|
],
|
|
55
30
|
},
|
|
56
31
|
{ text: "Utility nodes", children: ["/nodes/ps-receive-price.md"] },
|
|
@@ -82,32 +57,13 @@ module.exports = {
|
|
|
82
57
|
"/changelog/": [{ text: "Changelog", children: ["/changelog/README.md"] }],
|
|
83
58
|
},
|
|
84
59
|
},
|
|
85
|
-
head: [
|
|
86
|
-
["link", { rel: "shortcut icon", type: "image/x-icon", href: "euro.png" }],
|
|
87
|
-
[
|
|
88
|
-
"script",
|
|
89
|
-
{
|
|
90
|
-
async: true,
|
|
91
|
-
src: "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9857859182772006",
|
|
92
|
-
crossorigin: "anonymous",
|
|
93
|
-
},
|
|
94
|
-
],
|
|
95
|
-
],
|
|
60
|
+
head: [["link", { rel: "shortcut icon", type: "image/x-icon", href: "euro.png" }]],
|
|
96
61
|
plugins: [
|
|
97
62
|
[
|
|
98
63
|
"@vuepress/register-components",
|
|
99
64
|
{
|
|
100
|
-
|
|
101
|
-
BestSaveVerificator: path.resolve(__dirname, "./components/BestSaveVerificator.vue"),
|
|
102
|
-
DonateButtons: path.resolve(__dirname, "./components/DonateButtons.vue"),
|
|
103
|
-
},
|
|
65
|
+
componentsDir: path.resolve(__dirname, "./components"),
|
|
104
66
|
},
|
|
105
67
|
],
|
|
106
68
|
],
|
|
107
|
-
bundler: "@vuepress/bundler-webpack",
|
|
108
|
-
bundlerConfig: {
|
|
109
|
-
viteOptions: {
|
|
110
|
-
plugins: [vue()],
|
|
111
|
-
},
|
|
112
|
-
},
|
|
113
69
|
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module.exports = [
|
|
2
|
+
{
|
|
3
|
+
text: "Guide",
|
|
4
|
+
link: "/guide/",
|
|
5
|
+
},
|
|
6
|
+
{
|
|
7
|
+
text: "Nodes",
|
|
8
|
+
link: "/nodes/",
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
text: "Examples",
|
|
12
|
+
link: "/examples/",
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
text: "FAQ",
|
|
16
|
+
link: "/faq/",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
text: "Contribute",
|
|
20
|
+
link: "/contribute/",
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
text: "Changes",
|
|
24
|
+
link: "/changelog/",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
text: "Links",
|
|
28
|
+
children: [
|
|
29
|
+
{
|
|
30
|
+
text: "GitHub",
|
|
31
|
+
link: "https://github.com/ottopaulsen/node-red-contrib-power-saver",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
text: "npm registry",
|
|
35
|
+
link: "https://www.npmjs.com/package/node-red-contrib-power-saver",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
text: "Node-RED Library",
|
|
39
|
+
link: "https://flows.nodered.org/node/node-red-contrib-power-saver",
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
];
|
|
Binary file
|
package/docs/changelog/README.md
CHANGED
|
@@ -6,6 +6,20 @@ sidebar: "auto"
|
|
|
6
6
|
|
|
7
7
|
List the most significant changes, starting in version 1.0.9.
|
|
8
8
|
|
|
9
|
+
## 3.5.0
|
|
10
|
+
|
|
11
|
+
- Select what context storage to store data in the node configuration.
|
|
12
|
+
- New dynamic command: `replan`, that can be sent after a restart in order to create a schedule based on the last received prices, provided `file` is used as context storage (alternatively another permanent storage).
|
|
13
|
+
- Some improvements to node status.
|
|
14
|
+
|
|
15
|
+
## 3.4.4
|
|
16
|
+
|
|
17
|
+
- Fix bug in Best Save Viewer in the documentation (under FAQ)
|
|
18
|
+
|
|
19
|
+
## 3.4.3
|
|
20
|
+
|
|
21
|
+
- Fix Elvia config so it can be used independently on any node.
|
|
22
|
+
|
|
9
23
|
## 3.4.2
|
|
10
24
|
|
|
11
25
|
- Fix bug in reset command. It did not reset daily data properly.
|
|
@@ -326,19 +326,6 @@ A cascade temperature controller is a controller which utilizes the input/setpoi
|
|
|
326
326
|
"x": 290,
|
|
327
327
|
"y": 160,
|
|
328
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
329
|
}
|
|
343
330
|
]
|
|
344
331
|
```
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Simple heat capacitor strategy flow
|
|
1
|
+
# Simple heat capacitor strategy flow
|
|
2
2
|
|
|
3
3
|
## Description
|
|
4
4
|
|
|
@@ -27,13 +27,15 @@ It is a good application for cabins/heated storage spaces, as the entity never a
|
|
|
27
27
|
> Import the flow into Node-RED
|
|
28
28
|
|
|
29
29
|
> Configure the heat-capacitor node:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
|
|
31
|
+
- Insert an approximate time it takes to increase the temperature by 1 Centigrade (could be 90 minutes)
|
|
32
|
+
- Insert an approximate time it takes to decrease 1 Centigrade
|
|
33
|
+
- Insert minimum savings for a heating/cooling cycle (should not be zero, as a cycle might have a cost)
|
|
33
34
|
|
|
34
35
|
> Configure the climate service to target the correct climate entity (this has to be edited in two places)
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
|
|
37
|
+
- Change `Entity Id` in the properties menu
|
|
38
|
+
- Change the `entity_id` value in the `Data` property
|
|
37
39
|
|
|
38
40
|
> (optional) If the `input_number` entity was named something else than `setpoint`, change the `entity_id` of the `Setpoint` node accordingly.
|
|
39
41
|
|
|
@@ -49,7 +51,6 @@ It is a good application for cabins/heated storage spaces, as the entity never a
|
|
|
49
51
|
|
|
50
52
|
---
|
|
51
53
|
|
|
52
|
-
|
|
53
54
|
::: details [Flow code]
|
|
54
55
|
|
|
55
56
|
```json:no-line-numbers
|
|
@@ -252,20 +253,8 @@ It is a good application for cabins/heated storage spaces, as the entity never a
|
|
|
252
253
|
"feedUrl": "wss://api.tibber.com/v1-beta/gql/subscriptions",
|
|
253
254
|
"queryUrl": "https://api.tibber.com/v1-beta/gql",
|
|
254
255
|
"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
256
|
}
|
|
269
257
|
]
|
|
270
258
|
```
|
|
259
|
+
|
|
271
260
|
:::
|
|
@@ -167,19 +167,6 @@ In this example, data is read from the Nord Pool sensor in HA via the `current s
|
|
|
167
167
|
"e2578f6a.210a8"
|
|
168
168
|
]
|
|
169
169
|
]
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
"id": "ec4a12a1.b2be9",
|
|
173
|
-
"type": "server",
|
|
174
|
-
"name": "Home Assistant",
|
|
175
|
-
"version": 2,
|
|
176
|
-
"addon": true,
|
|
177
|
-
"rejectUnauthorizedCerts": true,
|
|
178
|
-
"ha_boolean": "y|yes|true|on|home|open",
|
|
179
|
-
"connectionDelay": true,
|
|
180
|
-
"cacheJson": true,
|
|
181
|
-
"heartbeat": false,
|
|
182
|
-
"heartbeatInterval": 30
|
|
183
170
|
}
|
|
184
171
|
]
|
|
185
172
|
```
|
|
@@ -152,19 +152,6 @@ In this example, data is read from the Nord Pool sensor in HA via the `events: s
|
|
|
152
152
|
"x": 490,
|
|
153
153
|
"y": 620,
|
|
154
154
|
"wires": [["32f17ab2.927cf6"], ["2a3cd7db.0891f8"], ["ed7202ff.b5725"]]
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
"id": "ec4a12a1.b2be9",
|
|
158
|
-
"type": "server",
|
|
159
|
-
"name": "Home Assistant",
|
|
160
|
-
"version": 2,
|
|
161
|
-
"addon": true,
|
|
162
|
-
"rejectUnauthorizedCerts": true,
|
|
163
|
-
"ha_boolean": "y|yes|true|on|home|open",
|
|
164
|
-
"connectionDelay": true,
|
|
165
|
-
"cacheJson": true,
|
|
166
|
-
"heartbeat": false,
|
|
167
|
-
"heartbeatInterval": 30
|
|
168
155
|
}
|
|
169
156
|
]
|
|
170
157
|
```
|
|
@@ -160,19 +160,6 @@ In this example, data is read from Tibber and used to turn on/off a switch, sche
|
|
|
160
160
|
"feedUrl": "wss://api.tibber.com/v1-beta/gql/subscriptions",
|
|
161
161
|
"queryUrl": "https://api.tibber.com/v1-beta/gql",
|
|
162
162
|
"name": "Tibber API"
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
"id": "ec4a12a1.b2be9",
|
|
166
|
-
"type": "server",
|
|
167
|
-
"name": "Home Assistant",
|
|
168
|
-
"version": 2,
|
|
169
|
-
"addon": true,
|
|
170
|
-
"rejectUnauthorizedCerts": true,
|
|
171
|
-
"ha_boolean": "y|yes|true|on|home|open",
|
|
172
|
-
"connectionDelay": true,
|
|
173
|
-
"cacheJson": true,
|
|
174
|
-
"heartbeat": false,
|
|
175
|
-
"heartbeatInterval": 30
|
|
176
163
|
}
|
|
177
164
|
]
|
|
178
165
|
```
|
package/docs/guide/README.md
CHANGED
|
@@ -61,14 +61,17 @@ If you are a Tibber customer, use the `tibber-query` node from the [Tibber API](
|
|
|
61
61
|
{
|
|
62
62
|
viewer {
|
|
63
63
|
homes {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
64
|
+
currentSubscription {
|
|
65
|
+
priceInfo {
|
|
66
|
+
today {
|
|
67
|
+
total
|
|
68
|
+
startsAt
|
|
69
|
+
}
|
|
70
|
+
tomorrow {
|
|
71
|
+
total
|
|
72
|
+
startsAt
|
|
73
|
+
}
|
|
74
|
+
}
|
|
72
75
|
}
|
|
73
76
|
}
|
|
74
77
|
}
|
|
@@ -147,10 +150,11 @@ If the grid tariff is the same the whole day, you can skip this step i the flow.
|
|
|
147
150
|
|
|
148
151
|
This is the step where the value is produced. Based on the prices received, the optimal schedule for you is calculated automatically, based on your configuration. You can choose between the following strategies:
|
|
149
152
|
|
|
150
|
-
| Strategy
|
|
151
|
-
|
|
|
152
|
-
| Best
|
|
153
|
-
| Lowest
|
|
153
|
+
| Strategy | Node | Description |
|
|
154
|
+
| -------------- | ---------------------------- | ---------------------------------------------------------------------------- |
|
|
155
|
+
| Best Save | `ps-strategy-best-save` | Postpone power consumption when there is most to save. |
|
|
156
|
+
| Lowest Price | `ps-strategy-lowest-price` | Turn on power when the prices are the lowest in a given period. |
|
|
157
|
+
| Heat Capacitor | `ps-strategy-heat-capacitor` | Move consumption from expensive to cheap periods utilizing climate entities. |
|
|
154
158
|
|
|
155
159
|
These nodes must be configured for your purpose. See configuration description and other details in the documentation for each node.
|
|
156
160
|
|
|
@@ -161,12 +165,16 @@ strategy node you choose.
|
|
|
161
165
|
Choose the best save strategy if you can postpone power consumption, and expect the consumption to occur during the first hour after power is turned on again.
|
|
162
166
|
|
|
163
167
|
Choose the lowest price strategy if you need the power to be on for x hours, but it is not important when that is. Note that you can select to have all hours on in one consecutive period, or spread around on the cheapest hours.
|
|
168
|
+
|
|
169
|
+
Choose the heat capacitor strategy for controlling for example room heating, where you can turn the heat a little down when electricity is expensive, and a little up when it is cheap, using trading principles (only that you know up front when the prices will change).
|
|
164
170
|
:::
|
|
165
171
|
|
|
166
172
|
### Use schedule signals
|
|
167
173
|
|
|
168
174
|
Use the outputs to control switches, thermostats or other entities to control your power consumers.
|
|
169
175
|
|
|
176
|
+
The following os valid for the Best Save and Lowest Price strategies:
|
|
177
|
+
|
|
170
178
|
**Output 1** is used to turn on. A payload with value `true` is sent every time turning on is scheduled.
|
|
171
179
|
|
|
172
180
|
**Output 2** is used to turn off. A payload with value `false` is sent every time turning off is scheduled.
|
|
Binary file
|
|
Binary file
|
|
@@ -21,6 +21,7 @@ The picture at the bottom of the page, under [Integration with MagicMirror](#int
|
|
|
21
21
|
| Min saving | Minimum amount to save per kWh in order to bother turning it off. It is recommended to have some amount here, e.g. 2 cents / 2 øre. No point in saving 0.001, is it? |
|
|
22
22
|
| Send when rescheduling | Check this to make sure on or off output is sent immediately after rescheduling |
|
|
23
23
|
| If no schedule, send | What to do if there is no valid schedule any more (turn on or off). |
|
|
24
|
+
| Context storage | Select context storage to save data to, if more than one is configured in the Node-RED `settings.js` file. |
|
|
24
25
|
|
|
25
26
|
::: warning Min recover
|
|
26
27
|
NB! The `Min recover` only has effect if the previous save-period is of length `Max per sequence`. If the save-period is shorter, the following on-period may be as short as one hour.
|
|
@@ -33,6 +34,7 @@ It is possible to change config dynamically by sending a config message to the n
|
|
|
33
34
|
```json
|
|
34
35
|
"payload": {
|
|
35
36
|
"config": {
|
|
37
|
+
"contextStorage": "file",
|
|
36
38
|
"maxHoursToSaveInSequence": 4,
|
|
37
39
|
"minHoursOnAfterMaxSequenceSaved": 2,
|
|
38
40
|
"minSaving": 0.02,
|
|
@@ -107,13 +109,41 @@ This operation cannot be undone.
|
|
|
107
109
|
However, it is normally not a big loss, as you can just feed the node with new price data and start from scratch.
|
|
108
110
|
:::
|
|
109
111
|
|
|
112
|
+
#### replan
|
|
113
|
+
|
|
114
|
+
By sending this command, you can have the node read the last received prices from the context storage,
|
|
115
|
+
and make a plan based on those prices:
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
"payload": {
|
|
119
|
+
"commands": {
|
|
120
|
+
"replan": true,
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
If the context storage is `file` you can use this to create a new schedule after a restart,
|
|
126
|
+
instead of fetching prices again.
|
|
127
|
+
|
|
128
|
+
### Config saved in context
|
|
129
|
+
|
|
130
|
+
The nodes config is saved in the nodes context.
|
|
131
|
+
If dynamic config is sent as input, this replaces the saved config.
|
|
132
|
+
It is the config that is saved in context that is used when calculating.
|
|
133
|
+
When Node-RED starts or the flow is redeployed, the config defined in the node replaces the saved config and will be used when planning.
|
|
134
|
+
|
|
110
135
|
## Input
|
|
111
136
|
|
|
112
137
|
The input is the [common strategy input format](./strategy-input.md).
|
|
113
138
|
|
|
114
139
|
In addition to the prices sent as input,
|
|
115
140
|
the node is using the schedule for the day before it receives data for,
|
|
116
|
-
so that it can calculate the schedule in the beginning of the day according to the configured rules.
|
|
141
|
+
so that it can calculate the schedule in the beginning of the day according to the configured rules.
|
|
142
|
+
This requires of course that the node was run the day before.
|
|
143
|
+
|
|
144
|
+
When a payload with `priceData` is received, this is saved to the nodes context as `lastPriceData`.
|
|
145
|
+
The source is saved as `lastSource`. If config- or command-messages are received without price data,
|
|
146
|
+
the data saved in context is used for replanning.
|
|
117
147
|
|
|
118
148
|
## Output
|
|
119
149
|
|
|
@@ -167,6 +197,7 @@ Example of output:
|
|
|
167
197
|
],
|
|
168
198
|
"source": "Nord Pool",
|
|
169
199
|
"config": {
|
|
200
|
+
"contextStorage": "default",
|
|
170
201
|
"maxHoursToSaveInSequence": 3,
|
|
171
202
|
"minHoursOnAfterMaxSequenceSaved": "1",
|
|
172
203
|
"minSaving": 0.001,
|
|
@@ -180,9 +211,9 @@ Example of output:
|
|
|
180
211
|
|
|
181
212
|
The `schedule` array shows every time the switch is turned on or off. The `hours` array shows values per hour containing the price (received as input), whether that hour is on or off, the start time of the hour and the amount per kWh that is saved on hours that are turned off, compared to the next hour that is on.
|
|
182
213
|
|
|
183
|
-
###
|
|
214
|
+
### Output saved in context
|
|
184
215
|
|
|
185
|
-
The
|
|
216
|
+
The `schedule` and the `hours` arrays from Output 3 are both saved to the nodes context in an object with key `lastPlan`. This may be used in the plan for the next day, for example if an off-period at the end of one day continues into the next day. In that case, the `saving` values for the last hours in the day have to be recalculated, since the next hour on is changed when the new day is calculated.
|
|
186
217
|
|
|
187
218
|
You can see the saved data if you select the node in Node-RED, and view "Context data", and refresh the Node context.
|
|
188
219
|
|
|
@@ -204,23 +235,48 @@ I say "in most cases", because there is a chance that a group of two or more seq
|
|
|
204
235
|
|
|
205
236
|
Normally data is received for one or two whole days, and all this data is used to do the calculation. In addition, if the node has run before, so there is historical data, the last period on or off before the period data is received for, is considered in the calculation, so that the rules in the configuration are followed also between days.
|
|
206
237
|
|
|
207
|
-
## Restarts
|
|
238
|
+
## Restarts and saved context
|
|
208
239
|
|
|
209
|
-
The
|
|
240
|
+
The config, last received prices and the last calculated schedule are saved to the nodes context.
|
|
241
|
+
This may be saved to memory, to file or to another destination based on how your Node-RED is configured.
|
|
242
|
+
If multiple context storages are defined, you can select which one to use in the nodes config.
|
|
243
|
+
If there is only one context storage defined, this is normally `memory`. In that case, data is not saved over restarts.
|
|
244
|
+
It is common to have two different context storages defined, `memory` and `file`, but there may be more.
|
|
245
|
+
It is also common to have a `default` context storage defined, and often this points to either `memory` or `file`.
|
|
246
|
+
However, the configuration can be different from this.
|
|
210
247
|
|
|
211
|
-
|
|
212
|
-
In Home Assistant,
|
|
248
|
+
You can find this configuration in the `settings.js` file for Node-RED, usually in the node-red config folder.
|
|
249
|
+
In Home Assistant, this is normally `/config/node-red/settings.js`.
|
|
250
|
+
|
|
251
|
+
Here is an example of a configuration for the context storage:
|
|
213
252
|
|
|
214
253
|
```js
|
|
215
254
|
contextStorage: {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}
|
|
255
|
+
file: { module: "localfilesystem"},
|
|
256
|
+
default: { module: "memory" }
|
|
219
257
|
}
|
|
220
258
|
```
|
|
221
259
|
|
|
260
|
+
By default, this node saves context to the `default` context storage. In the example above, this is memory.
|
|
261
|
+
Then it is not preserved over a restart.
|
|
222
262
|
Please read the [Node-RED documentation](https://nodered.org/docs/user-guide/context) for more details about this.
|
|
223
|
-
|
|
263
|
+
|
|
264
|
+
The data that is saved is the config, the last used prices and the last calculated schedule.
|
|
265
|
+
|
|
266
|
+
When Node-RED restarts, the config is reset to what is defined in the node config, so by default,
|
|
267
|
+
nothing is read from the context storage after a restart. However, if you send a `replan` command to the
|
|
268
|
+
nodes input, a plan is recalculated, using the last received prices. One way to do this is to use an `inject` node,
|
|
269
|
+
and set `msg.payload` to the following JSON value:
|
|
270
|
+
|
|
271
|
+
```json
|
|
272
|
+
{
|
|
273
|
+
"commands": {
|
|
274
|
+
"replan": true
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
This is an alternative to fetching new prices and send as input.
|
|
224
280
|
|
|
225
281
|
## Integration with MagicMirror
|
|
226
282
|
|