node-red-contrib-power-saver 5.1.5 → 5.2.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/README.md +1 -2
- package/examples/price-filter.json +139 -0
- package/package.json +4 -2
- package/src/elvia/elvia-add-tariff.js +1 -1
- package/src/general-add-tariff-functions.js +3 -3
- package/src/general-add-tariff.html +2 -2
- package/src/handle-input.js +0 -1
- package/src/handle-output.js +0 -3
- package/src/light-saver.html +697 -646
- package/src/price-filter.html +72 -0
- package/src/price-filter.js +100 -0
- package/src/schedule-merger.js +2 -2
- package/src/strategy-best-save-functions.js +20 -5
- package/src/strategy-best-save.js +1 -1
- package/src/strategy-fixed-schedule.html +2 -2
- package/src/strategy-functions.js +1 -1
- package/src/strategy-heat-capacitor-functions.js +4 -4
- package/src/strategy-heat-capacitor.js +2 -2
- package/src/strategy-lowest-price.html +1 -2
- package/src/strategy-lowest-price.js +3 -4
- package/src/utils.js +4 -5
package/README.md
CHANGED
|
@@ -6,5 +6,4 @@ A Node-RED node to save money when power prices are changing by the hour.
|
|
|
6
6
|
|
|
7
7
|
## Please read more in the [documentation](https://powersaver.no/).
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
[](https://powersaver.no/contribute/#donate)
|
|
9
|
+
[](https://powersaver.no/contribute/#donate)
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "pf01a2b3c4d5e6f7",
|
|
4
|
+
"type": "inject",
|
|
5
|
+
"z": "pf01tab01tab01t1",
|
|
6
|
+
"name": "Refresh prices (every hour)",
|
|
7
|
+
"props": [
|
|
8
|
+
{
|
|
9
|
+
"p": "payload"
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"repeat": "3600",
|
|
13
|
+
"crontab": "",
|
|
14
|
+
"once": true,
|
|
15
|
+
"onceDelay": "1",
|
|
16
|
+
"topic": "",
|
|
17
|
+
"payload": "{viewer{homes{currentSubscription{priceInfo(resolution:QUARTER_HOURLY){today{totalstartsAt}tomorrow{totalstartsAt}}}}}}",
|
|
18
|
+
"payloadType": "str",
|
|
19
|
+
"x": 180,
|
|
20
|
+
"y": 80,
|
|
21
|
+
"wires": [["pf02a2b3c4d5e6f7"]]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "pf02a2b3c4d5e6f7",
|
|
25
|
+
"type": "tibber-query",
|
|
26
|
+
"z": "pf01tab01tab01t1",
|
|
27
|
+
"name": "Get Tibber prices",
|
|
28
|
+
"active": true,
|
|
29
|
+
"apiEndpointRef": "pf0btibberapi01",
|
|
30
|
+
"x": 430,
|
|
31
|
+
"y": 80,
|
|
32
|
+
"wires": [["pf03a2b3c4d5e6f7"]]
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": "pf03a2b3c4d5e6f7",
|
|
36
|
+
"type": "ps-receive-price",
|
|
37
|
+
"z": "pf01tab01tab01t1",
|
|
38
|
+
"name": "Price Receiver",
|
|
39
|
+
"x": 170,
|
|
40
|
+
"y": 180,
|
|
41
|
+
"wires": [["pf04a2b3c4d5e6f7"]]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"id": "pf04a2b3c4d5e6f7",
|
|
45
|
+
"type": "ps-strategy-lowest-price",
|
|
46
|
+
"z": "pf01tab01tab01t1",
|
|
47
|
+
"name": "4 Cheapest Hours",
|
|
48
|
+
"fromHour": "00",
|
|
49
|
+
"fromMinute": "00",
|
|
50
|
+
"toHour": "00",
|
|
51
|
+
"toMinute": "00",
|
|
52
|
+
"minutesOn": "240",
|
|
53
|
+
"maxPrice": "",
|
|
54
|
+
"doNotSplit": false,
|
|
55
|
+
"sendCurrentValueWhenRescheduling": true,
|
|
56
|
+
"outputValueForOn": "true",
|
|
57
|
+
"outputValueForOff": "false",
|
|
58
|
+
"outputValueForOntype": "bool",
|
|
59
|
+
"outputValueForOfftype": "bool",
|
|
60
|
+
"outputIfNoSchedule": "false",
|
|
61
|
+
"outputOutsidePeriod": "false",
|
|
62
|
+
"contextStorage": "default",
|
|
63
|
+
"x": 390,
|
|
64
|
+
"y": 180,
|
|
65
|
+
"wires": [[], [], ["pf05a2b3c4d5e6f7"]]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"id": "pf05a2b3c4d5e6f7",
|
|
69
|
+
"type": "ps-price-filter",
|
|
70
|
+
"z": "pf01tab01tab01t1",
|
|
71
|
+
"name": "No heating above 1.00",
|
|
72
|
+
"turn": "off",
|
|
73
|
+
"condition": "over",
|
|
74
|
+
"limit": 1,
|
|
75
|
+
"x": 630,
|
|
76
|
+
"y": 180,
|
|
77
|
+
"wires": [["pf06a2b3c4d5e6f7"], ["pf07a2b3c4d5e6f7"], ["pf08a2b3c4d5e6f7"]]
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"id": "pf06a2b3c4d5e6f7",
|
|
81
|
+
"type": "debug",
|
|
82
|
+
"z": "pf01tab01tab01t1",
|
|
83
|
+
"name": "Turn ON",
|
|
84
|
+
"active": true,
|
|
85
|
+
"tosidebar": true,
|
|
86
|
+
"console": false,
|
|
87
|
+
"tostatus": false,
|
|
88
|
+
"complete": "payload",
|
|
89
|
+
"targetType": "msg",
|
|
90
|
+
"x": 860,
|
|
91
|
+
"y": 140,
|
|
92
|
+
"wires": []
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"id": "pf07a2b3c4d5e6f7",
|
|
96
|
+
"type": "debug",
|
|
97
|
+
"z": "pf01tab01tab01t1",
|
|
98
|
+
"name": "Turn OFF",
|
|
99
|
+
"active": true,
|
|
100
|
+
"tosidebar": true,
|
|
101
|
+
"console": false,
|
|
102
|
+
"tostatus": false,
|
|
103
|
+
"complete": "payload",
|
|
104
|
+
"targetType": "msg",
|
|
105
|
+
"x": 860,
|
|
106
|
+
"y": 180,
|
|
107
|
+
"wires": []
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"id": "pf08a2b3c4d5e6f7",
|
|
111
|
+
"type": "debug",
|
|
112
|
+
"z": "pf01tab01tab01t1",
|
|
113
|
+
"name": "Filtered Schedule",
|
|
114
|
+
"active": true,
|
|
115
|
+
"tosidebar": true,
|
|
116
|
+
"console": false,
|
|
117
|
+
"tostatus": false,
|
|
118
|
+
"complete": "payload",
|
|
119
|
+
"targetType": "msg",
|
|
120
|
+
"x": 870,
|
|
121
|
+
"y": 220,
|
|
122
|
+
"wires": []
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"id": "pf0btibberapi01",
|
|
126
|
+
"type": "tibber-api-endpoint",
|
|
127
|
+
"queryUrl": "https://api.tibber.com/v1-beta/gql",
|
|
128
|
+
"name": "Tibber API"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"id": "cd9babd81a9c291a",
|
|
132
|
+
"type": "global-config",
|
|
133
|
+
"env": [],
|
|
134
|
+
"modules": {
|
|
135
|
+
"node-red-contrib-tibber-api": "6.4.1",
|
|
136
|
+
"node-red-contrib-power-saver": "5.1.5"
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-power-saver",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.0",
|
|
4
4
|
"description": "A module for Node-RED that you can use to turn on and off a switch based on power prices",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"ps-elvia-tariff-types": "src/elvia/elvia-tariff-types.js",
|
|
33
33
|
"ps-elvia-tariff": "src/elvia/elvia-tariff.js",
|
|
34
34
|
"ps-elvia-add-tariff": "src/elvia/elvia-add-tariff.js",
|
|
35
|
-
"ps-general-add-tariff": "src/general-add-tariff.js"
|
|
35
|
+
"ps-general-add-tariff": "src/general-add-tariff.js",
|
|
36
|
+
"ps-price-filter": "src/price-filter.js"
|
|
36
37
|
},
|
|
37
38
|
"version": ">=2.2.0"
|
|
38
39
|
},
|
|
@@ -59,6 +60,7 @@
|
|
|
59
60
|
"mocha": "^11.7.5",
|
|
60
61
|
"node-red": "^4.1.5",
|
|
61
62
|
"node-red-node-test-helper": "0.3.6",
|
|
63
|
+
"prettier": "^3.8.1",
|
|
62
64
|
"sass-embedded": "^1.97.3",
|
|
63
65
|
"sass-loader": "^16.0.7",
|
|
64
66
|
"vuepress": "2.0.0-rc.26"
|
|
@@ -15,7 +15,7 @@ module.exports = function (RED) {
|
|
|
15
15
|
const prices = msg.payload.priceData;
|
|
16
16
|
if (!prices) {
|
|
17
17
|
node.warn(
|
|
18
|
-
"No price data received on input. Did you use the ps-receive-price node or convert to correct format otherwise?"
|
|
18
|
+
"No price data received on input. Did you use the ps-receive-price node or convert to correct format otherwise?",
|
|
19
19
|
);
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
@@ -68,13 +68,13 @@ function addTariffToPrices(node, config, prices) {
|
|
|
68
68
|
if (p.start.substring(0, 10) >= validFrom && p.start.substring(0, 10) <= validTo && config.days[day]) {
|
|
69
69
|
p.sum = roundPrice(p.value + p.add);
|
|
70
70
|
} else {
|
|
71
|
-
p.sum = p.value
|
|
71
|
+
p.sum = p.value;
|
|
72
72
|
}
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
-
const result = sortedPeriods.map(p => ({start: p.start, value: p.sum}))
|
|
75
|
+
const result = sortedPeriods.map((p) => ({ start: p.start, value: p.sum }));
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
// Set end on last period
|
|
78
78
|
result[result.length - 1].end = lastEnd;
|
|
79
79
|
|
|
80
80
|
return result;
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
["for", id],
|
|
81
81
|
["style", "margin-right: 10px;"],
|
|
82
82
|
],
|
|
83
|
-
[]
|
|
83
|
+
[],
|
|
84
84
|
);
|
|
85
85
|
label.innerHTML = text;
|
|
86
86
|
const inp = createElement("input", [
|
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
["for", id],
|
|
161
161
|
["style", " margin: 4px 10px 0px 2px;width: 30px; text-align: left;"],
|
|
162
162
|
],
|
|
163
|
-
[]
|
|
163
|
+
[],
|
|
164
164
|
);
|
|
165
165
|
label.innerHTML = day;
|
|
166
166
|
const attrs = [
|
package/src/handle-input.js
CHANGED
|
@@ -74,7 +74,6 @@ function makePlanFromPriceData(node, msg, config, doPlanning, calcSavings) {
|
|
|
74
74
|
const startTimes = priceDatePerMinute.map((d) => d.start);
|
|
75
75
|
const prices = priceDatePerMinute.map((d) => d.value);
|
|
76
76
|
|
|
77
|
-
|
|
78
77
|
const onOff = doPlanning(node, priceDatePerMinute);
|
|
79
78
|
const savings = calcSavings(prices, onOff);
|
|
80
79
|
const minutes = startTimes.map((v, i) => ({
|
package/src/handle-output.js
CHANGED