node-red-contrib-power-saver 3.5.5 → 3.6.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.
Files changed (39) hide show
  1. package/docs/.vuepress/config.js +1 -0
  2. package/docs/changelog/README.md +15 -0
  3. package/docs/examples/example-grid-tariff-capacity-part.md +272 -0
  4. package/docs/images/lowest-price-config.png +0 -0
  5. package/docs/nodes/ps-general-add-tariff.md +15 -1
  6. package/docs/nodes/ps-strategy-best-save.md +4 -2
  7. package/docs/nodes/ps-strategy-lowest-price.md +27 -13
  8. package/package.json +2 -2
  9. package/src/elvia/elvia-add-tariff.html +1 -1
  10. package/src/elvia/elvia-add-tariff.js +6 -4
  11. package/src/elvia/elvia-api.js +6 -5
  12. package/src/general-add-tariff-functions.js +3 -1
  13. package/src/general-add-tariff.html +54 -3
  14. package/src/general-add-tariff.js +1 -0
  15. package/src/power-saver.html +1 -1
  16. package/src/receive-price.html +1 -1
  17. package/src/strategy-best-save.html +1 -1
  18. package/src/strategy-heat-capacitor.html +1 -3
  19. package/src/strategy-lowest-price.html +13 -1
  20. package/src/strategy-lowest-price.js +11 -2
  21. package/src/utils.js +5 -2
  22. package/test/data/lowest-price-result-cont-max-fail.json +14 -0
  23. package/test/data/lowest-price-result-cont-max.json +20 -0
  24. package/test/data/lowest-price-result-cont.json +6 -5
  25. package/test/data/lowest-price-result-missing-end.json +7 -3
  26. package/test/data/lowest-price-result-split-allday.json +9 -8
  27. package/test/data/lowest-price-result-split-allday10.json +8 -7
  28. package/test/data/lowest-price-result-split-max.json +22 -0
  29. package/test/data/lowest-price-result-split.json +8 -7
  30. package/test/data/nordpool-3-days-result.json +10 -5
  31. package/test/data/result.js +9 -0
  32. package/test/data/tibber-result-end-0-24h.json +9 -4
  33. package/test/data/tibber-result-end-0.json +5 -2
  34. package/test/data/tibber-result.json +28 -14
  35. package/test/general-add-tariff-functions.test.js +2 -0
  36. package/test/general-add-tariff.test.js +40 -1
  37. package/test/power-saver.test.js +6 -0
  38. package/test/strategy-lowest-price.test.js +88 -31
  39. package/test/utils.test.js +9 -8
@@ -26,5 +26,5 @@
26
26
  A node to receive price data from one of the supported sources,
27
27
  and adapt it for calculation in the Power Saver strategy nodes.
28
28
 
29
- Please read more in the [node documentation](https://ottopaulsen.github.io/node-red-contrib-power-saver/nodes/ps-receive-price)
29
+ Please read more in the [node documentation](https://powersaver.no/nodes/ps-receive-price)
30
30
  </script>
@@ -105,5 +105,5 @@
105
105
  <script type="text/markdown" data-help-name="ps-strategy-best-save">
106
106
  A node you can use to save money by turning off and on a switch based on power prices.
107
107
 
108
- Please read more in the [node documentation](https://ottopaulsen.github.io/node-red-contrib-power-saver/nodes/ps-strategy-best-save)
108
+ Please read more in the [node documentation](https://powersaver.no/nodes/ps-strategy-best-save)
109
109
  </script>
@@ -79,7 +79,5 @@
79
79
  | Cooling Boost [C] | An extra decrease in temperature to the setpoint for the divestment period |
80
80
  | Min Savings | The minimum amount of savings required for a buy/sell cycle. |
81
81
 
82
-
83
- Please read more in the [node documentation](https://ottopaulsen.github.io/node-red-contrib-power-saver/nodes/ps-strategy-heat-capacitor)
84
-
82
+ Please read more in the [node documentation](https://powersaver.no/nodes/ps-strategy-heat-capacitor)
85
83
  </script>
@@ -43,6 +43,14 @@
43
43
  value: "12",
44
44
  required: true,
45
45
  },
46
+ maxPrice: {
47
+ value: null,
48
+ required: false,
49
+ validate: function (v) {
50
+ console.log("validating " + v);
51
+ return v == null || v == "" || (!isNaN(parseFloat(v)) && isFinite(v));
52
+ },
53
+ },
46
54
  doNotSplit: {
47
55
  value: "false",
48
56
  required: true,
@@ -145,6 +153,10 @@
145
153
  <label for="node-input-hoursOn"><i class="fa fa-arrows-h"></i> Hours on</label>
146
154
  <input type="text" id="node-input-hoursOn" style="width: 80px">
147
155
  </div>
156
+ <div class="form-row">
157
+ <label for="node-input-maxPrice"><i class="fa fa-minus"></i> Max price</label>
158
+ <input type="text" id="node-input-maxPrice" placeholder="Max price" style="width: 80px">
159
+ </div>
148
160
  <div class="form-row">
149
161
  <label for="node-input-doNotSplit">Consecutive on-period</label>
150
162
  <input type="checkbox" id="node-input-doNotSplit" style="display:inline-block; width:22px; vertical-align:top;">
@@ -177,5 +189,5 @@
177
189
  <script type="text/markdown" data-help-name="ps-strategy-lowest-price">
178
190
  A node to turn on a switch the hours when the price is lowest.
179
191
 
180
- Please read more in the [node documentation](https://ottopaulsen.github.io/node-red-contrib-power-saver/nodes/ps-strategy-lowest-price)
192
+ Please read more in the [node documentation](https://powersaver.no/nodes/ps-strategy-lowest-price)
181
193
  </script>
@@ -13,6 +13,7 @@ module.exports = function (RED) {
13
13
  fromTime: config.fromTime,
14
14
  toTime: config.toTime,
15
15
  hoursOn: parseInt(config.hoursOn),
16
+ maxPrice: config.maxPrice == null || config.maxPrice == "" ? null : parseFloat(config.maxPrice),
16
17
  doNotSplit: booleanConfig(config.doNotSplit),
17
18
  sendCurrentValueWhenRescheduling: booleanConfig(config.sendCurrentValueWhenRescheduling),
18
19
  outputIfNoSchedule: booleanConfig(config.outputIfNoSchedule),
@@ -22,7 +23,6 @@ module.exports = function (RED) {
22
23
  node.context().set("config", originalConfig);
23
24
  node.contextStorage = originalConfig.contextStorage;
24
25
 
25
-
26
26
  node.on("close", function () {
27
27
  clearTimeout(node.schedulingTimeout);
28
28
  });
@@ -123,8 +123,17 @@ function makePlan(node, values, onOff, fromIndex, toIndex) {
123
123
  const res = node.doNotSplit
124
124
  ? getBestContinuous(valuesInPeriod, node.hoursOn)
125
125
  : getBestX(valuesInPeriod, node.hoursOn);
126
+ const sumPriceOn = res.reduce((p, v, i) => {
127
+ return p + (v ? valuesInPeriod[i] : 0);
128
+ }, 0);
129
+ const average = sumPriceOn / node.hoursOn;
126
130
  res.forEach((v, i) => {
127
- onOff[fromIndex + i] = v;
131
+ onOff[fromIndex + i] =
132
+ node.maxPrice == null
133
+ ? v
134
+ : node.doNotSplit
135
+ ? v && average <= node.maxPrice
136
+ : v && valuesInPeriod[i] <= node.maxPrice;
128
137
  });
129
138
  return onOff;
130
139
  }
package/src/utils.js CHANGED
@@ -138,13 +138,16 @@ function countAtEnd(arr, value) {
138
138
  function makeSchedule(onOff, startTimes, initial = null) {
139
139
  const res = [];
140
140
  let prev = initial;
141
+ let prevRecord;
141
142
  for (let i = 0; i < startTimes.length; i++) {
142
143
  const value = onOff[i];
143
- if (value !== prev) {
144
+ if (value !== prev || i === 0) {
144
145
  const time = startTimes[i];
145
- res.push({ time, value });
146
+ prevRecord = { time, value, countHours: 0 };
147
+ res.push(prevRecord);
146
148
  prev = value;
147
149
  }
150
+ prevRecord.countHours++;
148
151
  }
149
152
  return res;
150
153
  }
@@ -0,0 +1,14 @@
1
+ {
2
+ "schedule": [{ "time": "2021-10-11T00:00:00.000+02:00", "value": false, "countHours": 48 }],
3
+ "config": {
4
+ "contextStorage": "default",
5
+ "doNotSplit": true,
6
+ "fromTime": "10",
7
+ "hoursOn": 4,
8
+ "maxPrice": 0.23,
9
+ "outputIfNoSchedule": true,
10
+ "outputOutsidePeriod": false,
11
+ "sendCurrentValueWhenRescheduling": true,
12
+ "toTime": "20"
13
+ }
14
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "schedule": [
3
+ { "time": "2021-10-11T00:00:00.000+02:00", "value": false, "countHours": 11 },
4
+ { "time": "2021-10-11T11:00:00.000+02:00", "value": true, "countHours": 4 },
5
+ { "time": "2021-10-11T15:00:00.000+02:00", "value": false, "countHours": 21 },
6
+ { "time": "2021-10-12T12:00:00.000+02:00", "value": true, "countHours": 4 },
7
+ { "time": "2021-10-12T16:00:00.000+02:00", "value": false, "countHours": 8 }
8
+ ],
9
+ "config": {
10
+ "contextStorage": "default",
11
+ "doNotSplit": true,
12
+ "fromTime": "10",
13
+ "hoursOn": 4,
14
+ "maxPrice": 1,
15
+ "outputIfNoSchedule": true,
16
+ "outputOutsidePeriod": false,
17
+ "sendCurrentValueWhenRescheduling": true,
18
+ "toTime": "20"
19
+ }
20
+ }
@@ -1,16 +1,17 @@
1
1
  {
2
2
  "schedule": [
3
- { "time": "2021-10-11T00:00:00.000+02:00", "value": false },
4
- { "time": "2021-10-11T11:00:00.000+02:00", "value": true },
5
- { "time": "2021-10-11T15:00:00.000+02:00", "value": false },
6
- { "time": "2021-10-12T12:00:00.000+02:00", "value": true },
7
- { "time": "2021-10-12T16:00:00.000+02:00", "value": false }
3
+ { "time": "2021-10-11T00:00:00.000+02:00", "value": false, "countHours": 11 },
4
+ { "time": "2021-10-11T11:00:00.000+02:00", "value": true, "countHours": 4 },
5
+ { "time": "2021-10-11T15:00:00.000+02:00", "value": false, "countHours": 21 },
6
+ { "time": "2021-10-12T12:00:00.000+02:00", "value": true, "countHours": 4 },
7
+ { "time": "2021-10-12T16:00:00.000+02:00", "value": false, "countHours": 8 }
8
8
  ],
9
9
  "config": {
10
10
  "contextStorage": "default",
11
11
  "doNotSplit": true,
12
12
  "fromTime": "10",
13
13
  "hoursOn": 4,
14
+ "maxPrice": null,
14
15
  "outputIfNoSchedule": true,
15
16
  "outputOutsidePeriod": false,
16
17
  "sendCurrentValueWhenRescheduling": true,
@@ -3,15 +3,18 @@
3
3
  "schedule": [
4
4
  {
5
5
  "time": "2021-12-15T00:00:00+01:00",
6
- "value": false
6
+ "value": false,
7
+ "countHours": 22
7
8
  },
8
9
  {
9
10
  "time": "2021-12-15T22:00:00+01:00",
10
- "value": true
11
+ "value": true,
12
+ "countHours": 3
11
13
  },
12
14
  {
13
15
  "time": "2021-12-16T01:00:00+01:00",
14
- "value": false
16
+ "value": false,
17
+ "countHours": 23
15
18
  }
16
19
  ],
17
20
  "hours": [
@@ -310,6 +313,7 @@
310
313
  "fromTime": "22",
311
314
  "toTime": "08",
312
315
  "hoursOn": 3,
316
+ "maxPrice": null,
313
317
  "doNotSplit": true,
314
318
  "sendCurrentValueWhenRescheduling": true,
315
319
  "outputIfNoSchedule": false,
@@ -1,19 +1,20 @@
1
1
  {
2
2
  "schedule": [
3
- { "time": "2021-10-11T00:00:00.000+02:00", "value": true },
4
- { "time": "2021-10-11T06:00:00.000+02:00", "value": false },
5
- { "time": "2021-10-11T12:00:00.000+02:00", "value": true },
6
- { "time": "2021-10-11T14:00:00.000+02:00", "value": false },
7
- { "time": "2021-10-12T00:00:00.000+02:00", "value": true },
8
- { "time": "2021-10-12T07:00:00.000+02:00", "value": false },
9
- { "time": "2021-10-12T14:00:00.000+02:00", "value": true },
10
- { "time": "2021-10-12T15:00:00.000+02:00", "value": false }
3
+ { "time": "2021-10-11T00:00:00.000+02:00", "value": true, "countHours": 6 },
4
+ { "time": "2021-10-11T06:00:00.000+02:00", "value": false, "countHours": 6 },
5
+ { "time": "2021-10-11T12:00:00.000+02:00", "value": true, "countHours": 2 },
6
+ { "time": "2021-10-11T14:00:00.000+02:00", "value": false, "countHours": 10 },
7
+ { "time": "2021-10-12T00:00:00.000+02:00", "value": true, "countHours": 7 },
8
+ { "time": "2021-10-12T07:00:00.000+02:00", "value": false, "countHours": 7 },
9
+ { "time": "2021-10-12T14:00:00.000+02:00", "value": true, "countHours": 1 },
10
+ { "time": "2021-10-12T15:00:00.000+02:00", "value": false, "countHours": 9 }
11
11
  ],
12
12
  "config": {
13
13
  "contextStorage": "default",
14
14
  "doNotSplit": false,
15
15
  "fromTime": "00",
16
16
  "hoursOn": 8,
17
+ "maxPrice": null,
17
18
  "outputIfNoSchedule": true,
18
19
  "outputOutsidePeriod": false,
19
20
  "sendCurrentValueWhenRescheduling": true,
@@ -1,18 +1,19 @@
1
1
  {
2
2
  "schedule": [
3
- { "time": "2021-10-11T00:00:00.000+02:00", "value": true },
4
- { "time": "2021-10-11T10:00:00.000+02:00", "value": false },
5
- { "time": "2021-10-11T12:00:00.000+02:00", "value": true },
6
- { "time": "2021-10-11T14:00:00.000+02:00", "value": false },
7
- { "time": "2021-10-12T00:00:00.000+02:00", "value": true },
8
- { "time": "2021-10-12T08:00:00.000+02:00", "value": false },
9
- { "time": "2021-10-12T10:00:00.000+02:00", "value": true }
3
+ { "time": "2021-10-11T00:00:00.000+02:00", "value": true, "countHours": 10 },
4
+ { "time": "2021-10-11T10:00:00.000+02:00", "value": false, "countHours": 2 },
5
+ { "time": "2021-10-11T12:00:00.000+02:00", "value": true, "countHours": 2 },
6
+ { "time": "2021-10-11T14:00:00.000+02:00", "value": false, "countHours": 10 },
7
+ { "time": "2021-10-12T00:00:00.000+02:00", "value": true, "countHours": 8 },
8
+ { "time": "2021-10-12T08:00:00.000+02:00", "value": false, "countHours": 2 },
9
+ { "time": "2021-10-12T10:00:00.000+02:00", "value": true, "countHours": 14 }
10
10
  ],
11
11
  "config": {
12
12
  "contextStorage": "default",
13
13
  "doNotSplit": false,
14
14
  "fromTime": "10",
15
15
  "hoursOn": 10,
16
+ "maxPrice": null,
16
17
  "outputIfNoSchedule": true,
17
18
  "outputOutsidePeriod": false,
18
19
  "sendCurrentValueWhenRescheduling": true,
@@ -0,0 +1,22 @@
1
+ {
2
+ "schedule": [
3
+ { "time": "2021-10-11T00:00:00.000+02:00", "value": false, "countHours": 12 },
4
+ { "time": "2021-10-11T12:00:00.000+02:00", "value": true, "countHours": 3 },
5
+ { "time": "2021-10-11T15:00:00.000+02:00", "value": false, "countHours": 21 },
6
+ { "time": "2021-10-12T12:00:00.000+02:00", "value": true, "countHours": 4 },
7
+ { "time": "2021-10-12T16:00:00.000+02:00", "value": false, "countHours": 3 },
8
+ { "time": "2021-10-12T19:00:00.000+02:00", "value": true, "countHours": 1 },
9
+ { "time": "2021-10-12T20:00:00.000+02:00", "value": false, "countHours": 4 }
10
+ ],
11
+ "config": {
12
+ "contextStorage": "default",
13
+ "doNotSplit": false,
14
+ "fromTime": "10",
15
+ "hoursOn": 6,
16
+ "maxPrice": 0.51,
17
+ "outputIfNoSchedule": true,
18
+ "outputOutsidePeriod": false,
19
+ "sendCurrentValueWhenRescheduling": true,
20
+ "toTime": "20"
21
+ }
22
+ }
@@ -1,18 +1,19 @@
1
1
  {
2
2
  "schedule": [
3
- { "time": "2021-10-11T00:00:00.000+02:00", "value": false },
4
- { "time": "2021-10-11T11:00:00.000+02:00", "value": true },
5
- { "time": "2021-10-11T17:00:00.000+02:00", "value": false },
6
- { "time": "2021-10-12T12:00:00.000+02:00", "value": true },
7
- { "time": "2021-10-12T16:00:00.000+02:00", "value": false },
8
- { "time": "2021-10-12T18:00:00.000+02:00", "value": true },
9
- { "time": "2021-10-12T20:00:00.000+02:00", "value": false }
3
+ { "time": "2021-10-11T00:00:00.000+02:00", "value": false, "countHours": 11 },
4
+ { "time": "2021-10-11T11:00:00.000+02:00", "value": true, "countHours": 6 },
5
+ { "time": "2021-10-11T17:00:00.000+02:00", "value": false, "countHours": 19 },
6
+ { "time": "2021-10-12T12:00:00.000+02:00", "value": true, "countHours": 4 },
7
+ { "time": "2021-10-12T16:00:00.000+02:00", "value": false, "countHours": 2 },
8
+ { "time": "2021-10-12T18:00:00.000+02:00", "value": true, "countHours": 2 },
9
+ { "time": "2021-10-12T20:00:00.000+02:00", "value": false, "countHours": 4 }
10
10
  ],
11
11
  "config": {
12
12
  "contextStorage": "default",
13
13
  "doNotSplit": false,
14
14
  "fromTime": "10",
15
15
  "hoursOn": 6,
16
+ "maxPrice": null,
16
17
  "outputIfNoSchedule": true,
17
18
  "outputOutsidePeriod": false,
18
19
  "sendCurrentValueWhenRescheduling": true,
@@ -2,23 +2,28 @@
2
2
  "schedule": [
3
3
  {
4
4
  "time": "2022-01-03T00:00:00+01:00",
5
- "value": false
5
+ "value": false,
6
+ "countHours": 28
6
7
  },
7
8
  {
8
9
  "time": "2022-01-04T04:00:00+01:00",
9
- "value": true
10
+ "value": true,
11
+ "countHours": 1
10
12
  },
11
13
  {
12
14
  "time": "2022-01-04T05:00:00+01:00",
13
- "value": false
15
+ "value": false,
16
+ "countHours": 22
14
17
  },
15
18
  {
16
19
  "time": "2022-01-05T03:00:00+01:00",
17
- "value": true
20
+ "value": true,
21
+ "countHours": 1
18
22
  },
19
23
  {
20
24
  "time": "2022-01-05T04:00:00+01:00",
21
- "value": false
25
+ "value": false,
26
+ "countHours": 20
22
27
  }
23
28
  ],
24
29
  "hours": [
@@ -3,38 +3,47 @@ module.exports = {
3
3
  {
4
4
  time: "2021-06-20T01:50:00.000+02:00",
5
5
  value: true,
6
+ countHours: 3,
6
7
  },
7
8
  {
8
9
  time: "2021-06-20T01:50:00.030+02:00",
9
10
  value: false,
11
+ countHours: 2,
10
12
  },
11
13
  {
12
14
  time: "2021-06-20T01:50:00.050+02:00",
13
15
  value: true,
16
+ countHours: 1,
14
17
  },
15
18
  {
16
19
  time: "2021-06-20T01:50:00.060+02:00",
17
20
  value: false,
21
+ countHours: 2,
18
22
  },
19
23
  {
20
24
  time: "2021-06-20T01:50:00.080+02:00",
21
25
  value: true,
26
+ countHours: 1,
22
27
  },
23
28
  {
24
29
  time: "2021-06-20T01:50:00.090+02:00",
25
30
  value: false,
31
+ countHours: 3,
26
32
  },
27
33
  {
28
34
  time: "2021-06-20T01:50:00.120+02:00",
29
35
  value: true,
36
+ countHours: 3,
30
37
  },
31
38
  {
32
39
  time: "2021-06-20T01:50:00.150+02:00",
33
40
  value: false,
41
+ countHours: 3,
34
42
  },
35
43
  {
36
44
  time: "2021-06-20T01:50:00.180+02:00",
37
45
  value: true,
46
+ countHours: 2,
38
47
  },
39
48
  ],
40
49
  hours: [
@@ -2,19 +2,23 @@
2
2
  "schedule": [
3
3
  {
4
4
  "time": "2021-12-14T00:00:00.000+01:00",
5
- "value": false
5
+ "value": false,
6
+ "countHours": 21
6
7
  },
7
8
  {
8
9
  "time": "2021-12-14T21:00:00.000+01:00",
9
- "value": true
10
+ "value": true,
11
+ "countHours": 3
10
12
  },
11
13
  {
12
14
  "time": "2021-12-15T00:00:00.000+01:00",
13
- "value": false
15
+ "value": false,
16
+ "countHours": 21
14
17
  },
15
18
  {
16
19
  "time": "2021-12-15T21:00:00.000+01:00",
17
- "value": true
20
+ "value": true,
21
+ "countHours": 3
18
22
  }
19
23
  ],
20
24
  "hours": [
@@ -313,6 +317,7 @@
313
317
  "fromTime": "16",
314
318
  "toTime": "00",
315
319
  "hoursOn": 3,
320
+ "maxPrice": null,
316
321
  "doNotSplit": false,
317
322
  "sendCurrentValueWhenRescheduling": true,
318
323
  "outputIfNoSchedule": false,
@@ -2,11 +2,13 @@
2
2
  "schedule": [
3
3
  {
4
4
  "time": "2021-12-14T00:00:00.000+01:00",
5
- "value": false
5
+ "value": false,
6
+ "countHours": 21
6
7
  },
7
8
  {
8
9
  "time": "2021-12-14T21:00:00.000+01:00",
9
- "value": true
10
+ "value": true,
11
+ "countHours": 3
10
12
  }
11
13
  ],
12
14
  "hours": [
@@ -161,6 +163,7 @@
161
163
  "fromTime": "16",
162
164
  "toTime": "00",
163
165
  "hoursOn": 3,
166
+ "maxPrice": null,
164
167
  "doNotSplit": false,
165
168
  "sendCurrentValueWhenRescheduling": true,
166
169
  "outputIfNoSchedule": false,
@@ -2,59 +2,73 @@
2
2
  "schedule": [
3
3
  {
4
4
  "time": "2021-10-11T00:00:00.000+02:00",
5
- "value": false
5
+ "value": false,
6
+ "countHours": 2
6
7
  },
7
8
  {
8
9
  "time": "2021-10-11T02:00:00.000+02:00",
9
- "value": true
10
+ "value": true,
11
+ "countHours": 5
10
12
  },
11
13
  {
12
14
  "time": "2021-10-11T07:00:00.000+02:00",
13
- "value": false
15
+ "value": false,
16
+ "countHours": 4
14
17
  },
15
18
  {
16
19
  "time": "2021-10-11T11:00:00.000+02:00",
17
- "value": true
20
+ "value": true,
21
+ "countHours": 7
18
22
  },
19
23
  {
20
24
  "time": "2021-10-11T18:00:00.000+02:00",
21
- "value": false
25
+ "value": false,
26
+ "countHours": 2
22
27
  },
23
28
  {
24
29
  "time": "2021-10-11T20:00:00.000+02:00",
25
- "value": true
30
+ "value": true,
31
+ "countHours": 1
26
32
  },
27
33
  {
28
34
  "time": "2021-10-11T21:00:00.000+02:00",
29
- "value": false
35
+ "value": false,
36
+ "countHours": 4
30
37
  },
31
38
  {
32
39
  "time": "2021-10-12T01:00:00.000+02:00",
33
- "value": true
40
+ "value": true,
41
+ "countHours": 8
34
42
  },
35
43
  {
36
44
  "time": "2021-10-12T09:00:00.000+02:00",
37
- "value": false
45
+ "value": false,
46
+ "countHours": 4
38
47
  },
39
48
  {
40
49
  "time": "2021-10-12T13:00:00.000+02:00",
41
- "value": true
50
+ "value": true,
51
+ "countHours": 3
42
52
  },
43
53
  {
44
54
  "time": "2021-10-12T16:00:00.000+02:00",
45
- "value": false
55
+ "value": false,
56
+ "countHours": 4
46
57
  },
47
58
  {
48
59
  "time": "2021-10-12T20:00:00.000+02:00",
49
- "value": true
60
+ "value": true,
61
+ "countHours": 2
50
62
  },
51
63
  {
52
64
  "time": "2021-10-12T22:00:00.000+02:00",
53
- "value": false
65
+ "value": false,
66
+ "countHours": 1
54
67
  },
55
68
  {
56
69
  "time": "2021-10-12T23:00:00.000+02:00",
57
- "value": true
70
+ "value": true,
71
+ "countHours": 1
58
72
  }
59
73
  ],
60
74
  "hours": [
@@ -45,6 +45,7 @@ describe("general-add-tariff-functions", () => {
45
45
  { start: "06", value: 10 },
46
46
  { start: "22", value: 11 },
47
47
  ],
48
+ days: { Mon: true, Tue: true, Wed: true, Thu: true, Fri: true, Sat: true, Sun: true },
48
49
  };
49
50
  const values = [];
50
51
  fillResult(values, 0, 5, 21);
@@ -75,6 +76,7 @@ describe("general-add-tariff-functions", () => {
75
76
  { start: "06", value: 10 },
76
77
  { start: "22", value: 11 },
77
78
  ],
79
+ days: { Mon: true, Tue: true, Wed: true, Thu: true, Fri: true, Sat: true, Sun: true },
78
80
  };
79
81
  const values = [];
80
82
  fillResult(values, 0, 23, 10);
@@ -24,7 +24,7 @@ const prices = {
24
24
  },
25
25
  {
26
26
  value: 2.1,
27
- start: "2021-10-12T00:00:00.000+02:00",
27
+ start: "2021-10-12T00:00:00.000+02:00", // Tuesday
28
28
  },
29
29
  {
30
30
  value: 2.2,
@@ -66,6 +66,7 @@ describe("general-add-tariff node", function () {
66
66
  { start: "01", value: "0.50" },
67
67
  { start: "03", value: "0.80" },
68
68
  ],
69
+ days: { Mon: true, Tue: true, Wed: true, Thu: true, Fri: true, Sat: true, Sun: true },
69
70
  },
70
71
  { id: "n2", type: "helper" },
71
72
  ];
@@ -89,6 +90,41 @@ describe("general-add-tariff node", function () {
89
90
  n1.receive({ payload });
90
91
  });
91
92
  });
93
+ it("should add to price only for correct days", function (done) {
94
+ const flow = [
95
+ {
96
+ id: "n1",
97
+ type: "ps-general-add-tariff",
98
+ name: "Add tariff",
99
+ wires: [["n2"]],
100
+ periods: [
101
+ { start: "01", value: "0.50" },
102
+ { start: "03", value: "0.80" },
103
+ ],
104
+ days: { Mon: true, Tue: false, Wed: true, Thu: true, Fri: true, Sat: true, Sun: true },
105
+ },
106
+ { id: "n2", type: "helper" },
107
+ ];
108
+ const result = cloneDeep(prices);
109
+ result.priceData[0].value = 1.0;
110
+ result.priceData[1].value = 0.8;
111
+ result.priceData[2].value = 0.6;
112
+ result.priceData[3].value = 2.0345;
113
+ result.priceData[4].value = 2.1;
114
+ result.priceData[5].value = 2.2;
115
+ result.config = { abc: 123 };
116
+ helper.load(addTariff, flow, function () {
117
+ const n1 = helper.getNode("n1");
118
+ const n2 = helper.getNode("n2");
119
+ n2.on("input", function (msg) {
120
+ expect(msg).toHaveProperty("payload", result);
121
+ done();
122
+ });
123
+ const payload = cloneDeep(prices);
124
+ payload.config = { abc: 123 };
125
+ n1.receive({ payload });
126
+ });
127
+ });
92
128
  it("should add to price when only first day is valid", function (done) {
93
129
  const flow = [
94
130
  {
@@ -100,6 +136,7 @@ describe("general-add-tariff node", function () {
100
136
  { start: "01", value: "0.50" },
101
137
  { start: "03", value: "0.80" },
102
138
  ],
139
+ days: { Mon: true, Tue: true, Wed: true, Thu: true, Fri: true, Sat: true, Sun: true },
103
140
  validFrom: "2021-10-11",
104
141
  validTo: "2021-10-11",
105
142
  },
@@ -134,6 +171,7 @@ describe("general-add-tariff node", function () {
134
171
  { start: "01", value: "0.50" },
135
172
  { start: "03", value: "0.80" },
136
173
  ],
174
+ days: { Mon: true, Tue: true, Wed: true, Thu: true, Fri: true, Sat: true, Sun: true },
137
175
  validFrom: "2021-10-12",
138
176
  },
139
177
  { id: "n2", type: "helper" },
@@ -163,6 +201,7 @@ describe("general-add-tariff node", function () {
163
201
  name: "Add tariff",
164
202
  wires: [["n2"]],
165
203
  periods: [{ start: "01", value: "0.50" }],
204
+ days: { Mon: true, Tue: true, Wed: true, Thu: true, Fri: true, Sat: true, Sun: true },
166
205
  },
167
206
  { id: "n2", type: "helper" },
168
207
  ];