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 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
- [![Donation](./donation.png)](https://powersaver.no/contribute/#donate)
9
+ [![Donation](./donation.png)](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.1.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
- // Set end on last period
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 = [
@@ -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) => ({
@@ -114,9 +114,6 @@ function collapseMinutes(minutes) {
114
114
  return a.price === b.price && a.onOff === b.onOff && a.saving === b.saving;
115
115
  }
116
116
 
117
-
118
-
119
-
120
117
  if (!Array.isArray(minutes) || minutes.length === 0) {
121
118
  return [];
122
119
  }