node-red-contrib-power-saver 3.2.0 → 3.3.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 (60) hide show
  1. package/docs/.vuepress/config.js +5 -0
  2. package/docs/.vuepress/dist/.nojekyll +0 -0
  3. package/docs/.vuepress/dist/404.html +2 -2
  4. package/docs/.vuepress/dist/assets/js/{app.eae70176.js → app.49ad6d54.js} +1 -1
  5. package/docs/.vuepress/dist/assets/js/runtime~app.547d0f4e.js +1 -0
  6. package/docs/.vuepress/dist/assets/js/v-0b5e3c8c.3b37457f.js +1 -0
  7. package/docs/.vuepress/dist/assets/js/{v-1e2b191e.50b8fa18.js → v-1e2b191e.98cc227b.js} +1 -1
  8. package/docs/.vuepress/dist/assets/js/v-4637f9e4.b320f5e8.js +1 -0
  9. package/docs/.vuepress/dist/assets/js/v-510ed0d4.3c7e0056.js +1 -0
  10. package/docs/.vuepress/dist/changelog/index.html +3 -3
  11. package/docs/.vuepress/dist/contribute/index.html +2 -2
  12. package/docs/.vuepress/dist/examples/example-next-schedule-entity.html +2 -2
  13. package/docs/.vuepress/dist/examples/example-nordpool-current-state.html +2 -2
  14. package/docs/.vuepress/dist/examples/example-nordpool-events-state.html +2 -2
  15. package/docs/.vuepress/dist/examples/example-tibber-mqtt.html +2 -2
  16. package/docs/.vuepress/dist/examples/index.html +2 -2
  17. package/docs/.vuepress/dist/faq/index.html +2 -2
  18. package/docs/.vuepress/dist/guide/index.html +2 -2
  19. package/docs/.vuepress/dist/index.html +2 -2
  20. package/docs/.vuepress/dist/nodes/index.html +2 -2
  21. package/docs/.vuepress/dist/nodes/old-power-saver-doc.html +2 -2
  22. package/docs/.vuepress/dist/nodes/power-saver.html +2 -2
  23. package/docs/.vuepress/dist/nodes/ps-elvia-add-tariff.html +2 -2
  24. package/docs/.vuepress/dist/nodes/ps-general-add-tariff.html +3 -3
  25. package/docs/.vuepress/dist/nodes/ps-receive-price.html +2 -2
  26. package/docs/.vuepress/dist/nodes/ps-strategy-best-save.html +4 -4
  27. package/docs/.vuepress/dist/nodes/ps-strategy-lowest-price.html +4 -4
  28. package/docs/.vuepress/dist/nodes/strategy-input.html +2 -2
  29. package/docs/changelog/README.md +22 -0
  30. package/docs/examples/example-nordpool-current-state.md +0 -1
  31. package/docs/examples/example-tibber-mqtt.md +0 -1
  32. package/docs/faq/README.md +5 -1
  33. package/docs/images/best-save-config.png +0 -0
  34. package/docs/nodes/ps-strategy-best-save.md +77 -8
  35. package/docs/nodes/ps-strategy-lowest-price.md +43 -0
  36. package/package.json +1 -1
  37. package/src/general-add-tariff-functions.js +0 -1
  38. package/src/general-add-tariff.js +2 -4
  39. package/src/handle-input.js +32 -13
  40. package/src/strategy-best-save.html +0 -21
  41. package/src/strategy-best-save.js +8 -11
  42. package/test/commands-input.test.js +47 -0
  43. package/test/data/best-save-result.json +1 -2
  44. package/test/data/current-undefined-prices.json +197 -0
  45. package/test/data/current-undefined-result.json +208 -0
  46. package/test/data/lowest-price-result-missing-end.json +2 -1
  47. package/test/data/reconfigResult.js +56 -294
  48. package/test/data/reconfigResult_old2.js +75 -0
  49. package/test/data/tibber-result-end-0-24h.json +1 -0
  50. package/test/data/tibber-result-end-0.json +1 -0
  51. package/test/send-config-input.test.js +3 -37
  52. package/test/strategy-best-save-test-utils.js +2 -1
  53. package/test/test-utils.js +1 -7
  54. package/test/utils.test.js +0 -33
  55. package/docs/.vuepress/dist/assets/js/runtime~app.3384c251.js +0 -1
  56. package/docs/.vuepress/dist/assets/js/v-0b5e3c8c.d62b30f7.js +0 -1
  57. package/docs/.vuepress/dist/assets/js/v-4637f9e4.b67738ed.js +0 -1
  58. package/docs/.vuepress/dist/assets/js/v-510ed0d4.528dd6f3.js +0 -1
  59. package/test/data/adjustedResult.js +0 -302
  60. package/test/data/adjustedResult_old.js +0 -154
@@ -1,8 +1,6 @@
1
1
  const cloneDeep = require("lodash.clonedeep");
2
- const { DateTime } = require("luxon");
3
- const { addTariffToPrices, buildAllHours } = require("./general-add-tariff-functions");
4
- const { roundPrice } = require("./utils");
5
- const { extractPlanForDate, getEffectiveConfig, validationFailure } = require("./utils");
2
+ const { addTariffToPrices } = require("./general-add-tariff-functions");
3
+ const { getEffectiveConfig } = require("./utils");
6
4
 
7
5
  module.exports = function (RED) {
8
6
  function PsGeneralAddTariffNode(config) {
@@ -3,15 +3,22 @@ const { DateTime } = require("luxon");
3
3
  const { version } = require("../package.json");
4
4
 
5
5
  function handleStrategyInput(node, msg, doPlanning) {
6
- node.schedulingTimeout = null;
7
-
8
6
  const effectiveConfig = getEffectiveConfig(node, msg);
9
7
 
10
8
  if (!validateInput(node, msg)) {
11
9
  return;
12
10
  }
13
- const priceData = getPriceData(node, msg);
11
+ if (msg.payload.commands && msg.payload.commands.reset) {
12
+ node.warn("Resetting node context by command");
13
+ // Reset all saved data
14
+ node.context().set(["lastPlan", "lastPriceData", "lastSource"], [undefined, undefined, undefined]);
15
+ deleteSavedScheduleBefore(node, DateTime.now().plus({ days: 1 }), 100);
16
+ }
17
+ const { priceData, source } = getPriceData(node, msg);
14
18
  if (!priceData) {
19
+ const message = "No price data";
20
+ node.warn(message);
21
+ node.status({ fill: "yellow", shape: "dot", text: message });
15
22
  return;
16
23
  }
17
24
  const planFromTime = msg.payload.time ? DateTime.fromISO(msg.payload.time) : DateTime.now();
@@ -34,6 +41,8 @@ function handleStrategyInput(node, msg, doPlanning) {
34
41
  node.context().set("lastPlan", plan);
35
42
  dates.forEach((d) => saveDayData(node, d, extractPlanForDate(plan, d)));
36
43
 
44
+ const sentOnCommand = !!msg.payload.commands?.sendSchedule;
45
+
37
46
  // Prepare output
38
47
  let output1 = null;
39
48
  let output2 = null;
@@ -41,8 +50,9 @@ function handleStrategyInput(node, msg, doPlanning) {
41
50
  payload: {
42
51
  schedule: plan.schedule,
43
52
  hours: plan.hours,
44
- source: msg.payload.source,
53
+ source,
45
54
  config: effectiveConfig,
55
+ sentOnCommand,
46
56
  time: planFromTime.toISO(),
47
57
  version,
48
58
  },
@@ -51,7 +61,7 @@ function handleStrategyInput(node, msg, doPlanning) {
51
61
  // Find current output, and set output (if configured to do)
52
62
  const pastSchedule = plan.schedule.filter((entry) => DateTime.fromISO(entry.time) <= planFromTime);
53
63
 
54
- const sendNow = node.sendCurrentValueWhenRescheduling && pastSchedule.length > 0;
64
+ const sendNow = !!node.sendCurrentValueWhenRescheduling && pastSchedule.length > 0 && !sentOnCommand;
55
65
  const currentValue = pastSchedule[pastSchedule.length - 1]?.value;
56
66
  if (sendNow) {
57
67
  output1 = currentValue ? { payload: true } : null;
@@ -71,24 +81,28 @@ function handleStrategyInput(node, msg, doPlanning) {
71
81
 
72
82
  function getPriceData(node, msg) {
73
83
  const isConfigMsg = !!msg?.payload?.config;
84
+ const isCommandMsg = !!msg?.payload?.commands;
74
85
  const isPriceMsg = !!msg?.payload?.priceData;
75
- if (isConfigMsg && !isPriceMsg) {
76
- return node.context().get("lastPriceData");
86
+ if ((isConfigMsg || isCommandMsg) && !isPriceMsg) {
87
+ const priceData = node.context().get("lastPriceData");
88
+ const source = node.context().get("lastSource");
89
+ return { priceData, source };
77
90
  }
78
91
  const priceData = msg.payload.priceData;
92
+ const source = msg.payload.source;
79
93
  node.context().set("lastPriceData", priceData);
80
- return priceData;
94
+ node.context().set("lastSource", source);
95
+ return { priceData, source };
81
96
  }
82
97
 
83
98
  function runSchedule(node, schedule, time, currentSent = false) {
84
- let currentTime = time;
85
99
  let remainingSchedule = schedule.filter((entry) => {
86
- return DateTime.fromISO(entry.time) > DateTime.fromISO(time);
100
+ return DateTime.fromISO(entry.time) > time;
87
101
  });
88
102
  if (remainingSchedule.length > 0) {
89
103
  const entry = remainingSchedule[0];
90
104
  const nextTime = DateTime.fromISO(entry.time);
91
- const wait = nextTime - currentTime;
105
+ const wait = nextTime - time;
92
106
  const onOff = entry.value ? "on" : "off";
93
107
  node.log("Switching " + onOff + " in " + wait + " milliseconds");
94
108
  const statusMessage = `${remainingSchedule.length} changes - ${
@@ -109,12 +123,14 @@ function runSchedule(node, schedule, time, currentSent = false) {
109
123
  }
110
124
  }
111
125
 
112
- function deleteSavedScheduleBefore(node, day) {
126
+ function deleteSavedScheduleBefore(node, day, checkDays = 0) {
113
127
  let date = day;
128
+ let count = 0;
114
129
  do {
115
130
  date = date.plus({ days: -1 });
116
131
  data = node.context().set(date.toISO(), undefined);
117
- } while (data);
132
+ count++;
133
+ } while (data || count <= checkDays);
118
134
  }
119
135
 
120
136
  function saveDayData(node, date, plan) {
@@ -139,6 +155,9 @@ function validateInput(node, msg) {
139
155
  if (msg.payload.config !== undefined) {
140
156
  return true; // Got config msg
141
157
  }
158
+ if (msg.payload.commands !== undefined) {
159
+ return true; // Got command msg
160
+ }
142
161
  if (msg.payload.priceData === undefined) {
143
162
  validationFailure(node, "Payload is missing priceData");
144
163
  return;
@@ -26,11 +26,6 @@
26
26
  align: "left",
27
27
  },
28
28
  outputIfNoSchedule: { value: "true", required: true, align: "left" },
29
- scheduleOnlyFromCurrentTime: {
30
- value: "true",
31
- required: true,
32
- align: "left",
33
- },
34
29
  },
35
30
  inputs: 1,
36
31
  outputs: 3,
@@ -52,17 +47,6 @@
52
47
  },
53
48
  ],
54
49
  });
55
- $("#node-input-scheduleOnlyFromCurrentTime").typedInput({
56
- types: [
57
- {
58
- value: "nowOrStart",
59
- options: [
60
- { value: "false", label: "Whole data set" },
61
- { value: "true", label: "From current hour" },
62
- ],
63
- },
64
- ],
65
- });
66
50
  },
67
51
  });
68
52
  </script>
@@ -88,11 +72,6 @@
88
72
  <label for="node-input-minSaving"><i class="fa fa-eur"></i> Min saving</label>
89
73
  <input type="text" id="node-input-minSaving" placeholder="Minimum to save for turning off" style="width: 80px">
90
74
  </div>
91
- <div class="form-row">
92
- <label for="node-input-scheduleOnlyFromCurrentTime">Schedule for</label>
93
- <input type="text" id="node-input-scheduleOnlyFromCurrentTime" style="width: 160px">
94
- </label>
95
- </div>
96
75
  <h3>Output</h3>
97
76
  <div class="form-row">
98
77
  <label for="node-input-sendCurrentValueWhenRescheduling" style="width:240px">
@@ -1,4 +1,4 @@
1
- const { countAtEnd, makeSchedule, getSavings, getStartAtIndex, getDiff } = require("./utils");
1
+ const { countAtEnd, makeSchedule, getSavings, getDiff } = require("./utils");
2
2
  const { handleStrategyInput } = require("./handle-input");
3
3
  const { loadDayData } = require("./utils");
4
4
 
@@ -15,7 +15,6 @@ module.exports = function (RED) {
15
15
  minSaving: parseFloat(config.minSaving),
16
16
  sendCurrentValueWhenRescheduling: config.sendCurrentValueWhenRescheduling,
17
17
  outputIfNoSchedule: config.outputIfNoSchedule === "true",
18
- scheduleOnlyFromCurrentTime: config.scheduleOnlyFromCurrentTime === "true",
19
18
  };
20
19
  node.context().set("config", originalConfig);
21
20
 
@@ -43,20 +42,18 @@ function adjustSavingsPassedHours(plan, includeFromLastPlanHours) {
43
42
  }
44
43
  }
45
44
 
46
- function loadDataJustBefore(node, dateDayBefore, dateToday, startAtIndex) {
45
+ function loadDataJustBefore(node, dateDayBefore) {
47
46
  const dataDayBefore = loadDayData(node, dateDayBefore);
48
- const dataToday = loadDayData(node, dateToday);
49
47
  return {
50
- schedule: [...dataDayBefore.schedule, ...dataToday.schedule.slice(0, startAtIndex)],
51
- hours: [...dataDayBefore.hours, ...dataToday.hours.slice(0, startAtIndex)],
48
+ schedule: [...dataDayBefore.schedule],
49
+ hours: [...dataDayBefore.hours],
52
50
  };
53
51
  }
54
52
 
55
- function doPlanning(node, effectiveConfig, priceData, planFromTime, dateDayBefore, dateToday) {
56
- const startAtIndex = getStartAtIndex(effectiveConfig, priceData, planFromTime);
57
- const dataJustBefore = loadDataJustBefore(node, dateDayBefore, dateToday, startAtIndex);
58
- const values = priceData.map((d) => d.value).slice(startAtIndex);
59
- const startTimes = priceData.map((d) => d.start).slice(startAtIndex);
53
+ function doPlanning(node, _, priceData, _, dateDayBefore, _) {
54
+ const dataJustBefore = loadDataJustBefore(node, dateDayBefore);
55
+ const values = priceData.map((d) => d.value);
56
+ const startTimes = priceData.map((d) => d.start);
60
57
  const onOffBefore = dataJustBefore.hours.map((h) => h.onOff);
61
58
  const lastPlanHours = node.context().get("lastPlan")?.hours ?? [];
62
59
  const plan = makePlan(node, values, startTimes, onOffBefore);
@@ -0,0 +1,47 @@
1
+ const expect = require("expect");
2
+ const helper = require("node-red-node-test-helper");
3
+ const bestSave = require("../src/strategy-best-save.js");
4
+ const prices = require("./data/converted-prices.json");
5
+ const result = require("./data/best-save-result.json");
6
+ const { testPlan, equalPlan } = require("./test-utils");
7
+ const { makeFlow, makePayload } = require("./strategy-best-save-test-utils");
8
+
9
+ helper.init(require.resolve("node-red"));
10
+
11
+ describe("send command as input", () => {
12
+ beforeEach(function (done) {
13
+ helper.startServer(done);
14
+ });
15
+
16
+ afterEach(function (done) {
17
+ helper.unload().then(function () {
18
+ helper.stopServer(done);
19
+ });
20
+ });
21
+
22
+ it("should send output on command", function (done) {
23
+ const flow = makeFlow(3, 2, true);
24
+ let pass = 1;
25
+ helper.load(bestSave, flow, function () {
26
+ const n1 = helper.getNode("n1");
27
+ const n2 = helper.getNode("n2");
28
+ n1.sendCurrentValueWhenRescheduling = true;
29
+ n2.on("input", function (msg) {
30
+ switch (pass) {
31
+ case 1:
32
+ pass++;
33
+ expect(equalPlan(result, msg.payload)).toBeTruthy();
34
+ expect(msg.payload.sentOnCommand).toBeFalsy();
35
+ n1.receive({ payload: { commands: { sendSchedule: true } } });
36
+ break;
37
+ case 2:
38
+ expect(equalPlan(result, msg.payload)).toBeTruthy();
39
+ expect(msg.payload.sentOnCommand).toBeTruthy();
40
+ done();
41
+ break;
42
+ }
43
+ });
44
+ n1.receive({ payload: makePayload(prices, testPlan.time) });
45
+ });
46
+ });
47
+ });
@@ -351,7 +351,6 @@
351
351
  "maxHoursToSaveInSequence": 3,
352
352
  "minHoursOnAfterMaxSequenceSaved": 2,
353
353
  "minSaving": 0.001,
354
- "outputIfNoSchedule": false,
355
- "scheduleOnlyFromCurrentTime": false
354
+ "outputIfNoSchedule": false
356
355
  }
357
356
  }
@@ -0,0 +1,197 @@
1
+ {
2
+ "priceData": [
3
+ {
4
+ "value": 1.792,
5
+ "start": "2022-01-12T00:00:00+01:00"
6
+ },
7
+ {
8
+ "value": 1.761,
9
+ "start": "2022-01-12T01:00:00+01:00"
10
+ },
11
+ {
12
+ "value": 1.744,
13
+ "start": "2022-01-12T02:00:00+01:00"
14
+ },
15
+ {
16
+ "value": 1.741,
17
+ "start": "2022-01-12T03:00:00+01:00"
18
+ },
19
+ {
20
+ "value": 1.752,
21
+ "start": "2022-01-12T04:00:00+01:00"
22
+ },
23
+ {
24
+ "value": 1.773,
25
+ "start": "2022-01-12T05:00:00+01:00"
26
+ },
27
+ {
28
+ "value": 1.773,
29
+ "start": "2022-01-12T06:00:00+01:00"
30
+ },
31
+ {
32
+ "value": 1.832,
33
+ "start": "2022-01-12T07:00:00+01:00"
34
+ },
35
+ {
36
+ "value": 1.863,
37
+ "start": "2022-01-12T08:00:00+01:00"
38
+ },
39
+ {
40
+ "value": 1.826,
41
+ "start": "2022-01-12T09:00:00+01:00"
42
+ },
43
+ {
44
+ "value": 1.795,
45
+ "start": "2022-01-12T10:00:00+01:00"
46
+ },
47
+ {
48
+ "value": 1.753,
49
+ "start": "2022-01-12T11:00:00+01:00"
50
+ },
51
+ {
52
+ "value": 1.75,
53
+ "start": "2022-01-12T12:00:00+01:00"
54
+ },
55
+ {
56
+ "value": 1.738,
57
+ "start": "2022-01-12T13:00:00+01:00"
58
+ },
59
+ {
60
+ "value": 1.717,
61
+ "start": "2022-01-12T14:00:00+01:00"
62
+ },
63
+ {
64
+ "value": 1.707,
65
+ "start": "2022-01-12T15:00:00+01:00"
66
+ },
67
+ {
68
+ "value": 1.708,
69
+ "start": "2022-01-12T16:00:00+01:00"
70
+ },
71
+ {
72
+ "value": 1.707,
73
+ "start": "2022-01-12T17:00:00+01:00"
74
+ },
75
+ {
76
+ "value": 1.692,
77
+ "start": "2022-01-12T18:00:00+01:00"
78
+ },
79
+ {
80
+ "value": 1.661,
81
+ "start": "2022-01-12T19:00:00+01:00"
82
+ },
83
+ {
84
+ "value": 1.64,
85
+ "start": "2022-01-12T20:00:00+01:00"
86
+ },
87
+ {
88
+ "value": 1.634,
89
+ "start": "2022-01-12T21:00:00+01:00"
90
+ },
91
+ {
92
+ "value": 1.614,
93
+ "start": "2022-01-12T22:00:00+01:00"
94
+ },
95
+ {
96
+ "value": 1.598,
97
+ "start": "2022-01-12T23:00:00+01:00"
98
+ },
99
+ {
100
+ "value": 1.569,
101
+ "start": "2022-01-13T00:00:00+01:00"
102
+ },
103
+ {
104
+ "value": 1.548,
105
+ "start": "2022-01-13T01:00:00+01:00"
106
+ },
107
+ {
108
+ "value": 1.518,
109
+ "start": "2022-01-13T02:00:00+01:00"
110
+ },
111
+ {
112
+ "value": 1.507,
113
+ "start": "2022-01-13T03:00:00+01:00"
114
+ },
115
+ {
116
+ "value": 1.501,
117
+ "start": "2022-01-13T04:00:00+01:00"
118
+ },
119
+ {
120
+ "value": 1.508,
121
+ "start": "2022-01-13T05:00:00+01:00"
122
+ },
123
+ {
124
+ "value": 1.544,
125
+ "start": "2022-01-13T06:00:00+01:00"
126
+ },
127
+ {
128
+ "value": 1.612,
129
+ "start": "2022-01-13T07:00:00+01:00"
130
+ },
131
+ {
132
+ "value": 1.646,
133
+ "start": "2022-01-13T08:00:00+01:00"
134
+ },
135
+ {
136
+ "value": 1.654,
137
+ "start": "2022-01-13T09:00:00+01:00"
138
+ },
139
+ {
140
+ "value": 1.656,
141
+ "start": "2022-01-13T10:00:00+01:00"
142
+ },
143
+ {
144
+ "value": 1.648,
145
+ "start": "2022-01-13T11:00:00+01:00"
146
+ },
147
+ {
148
+ "value": 1.617,
149
+ "start": "2022-01-13T12:00:00+01:00"
150
+ },
151
+ {
152
+ "value": 1.613,
153
+ "start": "2022-01-13T13:00:00+01:00"
154
+ },
155
+ {
156
+ "value": 1.612,
157
+ "start": "2022-01-13T14:00:00+01:00"
158
+ },
159
+ {
160
+ "value": 1.611,
161
+ "start": "2022-01-13T15:00:00+01:00"
162
+ },
163
+ {
164
+ "value": 1.618,
165
+ "start": "2022-01-13T16:00:00+01:00"
166
+ },
167
+ {
168
+ "value": 1.616,
169
+ "start": "2022-01-13T17:00:00+01:00"
170
+ },
171
+ {
172
+ "value": 1.617,
173
+ "start": "2022-01-13T18:00:00+01:00"
174
+ },
175
+ {
176
+ "value": 1.601,
177
+ "start": "2022-01-13T19:00:00+01:00"
178
+ },
179
+ {
180
+ "value": 1.568,
181
+ "start": "2022-01-13T20:00:00+01:00"
182
+ },
183
+ {
184
+ "value": 1.565,
185
+ "start": "2022-01-13T21:00:00+01:00"
186
+ },
187
+ {
188
+ "value": 1.506,
189
+ "start": "2022-01-13T22:00:00+01:00"
190
+ },
191
+ {
192
+ "value": 1.468,
193
+ "start": "2022-01-13T23:00:00+01:00"
194
+ }
195
+ ],
196
+ "source": "Nordpool"
197
+ }
@@ -0,0 +1,208 @@
1
+ {
2
+ "schedule": [
3
+ {
4
+ "time": "2022-01-12T18:00:00+01:00",
5
+ "value": true
6
+ },
7
+ {
8
+ "time": "2022-01-13T17:00:00+01:00",
9
+ "value": false
10
+ },
11
+ {
12
+ "time": "2022-01-13T23:00:00+01:00",
13
+ "value": true
14
+ }
15
+ ],
16
+ "hours": [
17
+ {
18
+ "price": 1.692,
19
+ "onOff": true,
20
+ "start": "2022-01-12T18:00:00+01:00",
21
+ "saving": null
22
+ },
23
+ {
24
+ "price": 1.661,
25
+ "onOff": true,
26
+ "start": "2022-01-12T19:00:00+01:00",
27
+ "saving": null
28
+ },
29
+ {
30
+ "price": 1.64,
31
+ "onOff": true,
32
+ "start": "2022-01-12T20:00:00+01:00",
33
+ "saving": null
34
+ },
35
+ {
36
+ "price": 1.634,
37
+ "onOff": true,
38
+ "start": "2022-01-12T21:00:00+01:00",
39
+ "saving": null
40
+ },
41
+ {
42
+ "price": 1.614,
43
+ "onOff": true,
44
+ "start": "2022-01-12T22:00:00+01:00",
45
+ "saving": null
46
+ },
47
+ {
48
+ "price": 1.598,
49
+ "onOff": true,
50
+ "start": "2022-01-12T23:00:00+01:00",
51
+ "saving": null
52
+ },
53
+ {
54
+ "price": 1.569,
55
+ "onOff": true,
56
+ "start": "2022-01-13T00:00:00+01:00",
57
+ "saving": null
58
+ },
59
+ {
60
+ "price": 1.548,
61
+ "onOff": true,
62
+ "start": "2022-01-13T01:00:00+01:00",
63
+ "saving": null
64
+ },
65
+ {
66
+ "price": 1.518,
67
+ "onOff": true,
68
+ "start": "2022-01-13T02:00:00+01:00",
69
+ "saving": null
70
+ },
71
+ {
72
+ "price": 1.507,
73
+ "onOff": true,
74
+ "start": "2022-01-13T03:00:00+01:00",
75
+ "saving": null
76
+ },
77
+ {
78
+ "price": 1.501,
79
+ "onOff": true,
80
+ "start": "2022-01-13T04:00:00+01:00",
81
+ "saving": null
82
+ },
83
+ {
84
+ "price": 1.508,
85
+ "onOff": true,
86
+ "start": "2022-01-13T05:00:00+01:00",
87
+ "saving": null
88
+ },
89
+ {
90
+ "price": 1.544,
91
+ "onOff": true,
92
+ "start": "2022-01-13T06:00:00+01:00",
93
+ "saving": null
94
+ },
95
+ {
96
+ "price": 1.612,
97
+ "onOff": true,
98
+ "start": "2022-01-13T07:00:00+01:00",
99
+ "saving": null
100
+ },
101
+ {
102
+ "price": 1.646,
103
+ "onOff": true,
104
+ "start": "2022-01-13T08:00:00+01:00",
105
+ "saving": null
106
+ },
107
+ {
108
+ "price": 1.654,
109
+ "onOff": true,
110
+ "start": "2022-01-13T09:00:00+01:00",
111
+ "saving": null
112
+ },
113
+ {
114
+ "price": 1.656,
115
+ "onOff": true,
116
+ "start": "2022-01-13T10:00:00+01:00",
117
+ "saving": null
118
+ },
119
+ {
120
+ "price": 1.648,
121
+ "onOff": true,
122
+ "start": "2022-01-13T11:00:00+01:00",
123
+ "saving": null
124
+ },
125
+ {
126
+ "price": 1.617,
127
+ "onOff": true,
128
+ "start": "2022-01-13T12:00:00+01:00",
129
+ "saving": null
130
+ },
131
+ {
132
+ "price": 1.613,
133
+ "onOff": true,
134
+ "start": "2022-01-13T13:00:00+01:00",
135
+ "saving": null
136
+ },
137
+ {
138
+ "price": 1.612,
139
+ "onOff": true,
140
+ "start": "2022-01-13T14:00:00+01:00",
141
+ "saving": null
142
+ },
143
+ {
144
+ "price": 1.611,
145
+ "onOff": true,
146
+ "start": "2022-01-13T15:00:00+01:00",
147
+ "saving": null
148
+ },
149
+ {
150
+ "price": 1.618,
151
+ "onOff": true,
152
+ "start": "2022-01-13T16:00:00+01:00",
153
+ "saving": null
154
+ },
155
+ {
156
+ "price": 1.616,
157
+ "onOff": false,
158
+ "start": "2022-01-13T17:00:00+01:00",
159
+ "saving": 0.148
160
+ },
161
+ {
162
+ "price": 1.617,
163
+ "onOff": false,
164
+ "start": "2022-01-13T18:00:00+01:00",
165
+ "saving": 0.149
166
+ },
167
+ {
168
+ "price": 1.601,
169
+ "onOff": false,
170
+ "start": "2022-01-13T19:00:00+01:00",
171
+ "saving": 0.133
172
+ },
173
+ {
174
+ "price": 1.568,
175
+ "onOff": false,
176
+ "start": "2022-01-13T20:00:00+01:00",
177
+ "saving": 0.1
178
+ },
179
+ {
180
+ "price": 1.565,
181
+ "onOff": false,
182
+ "start": "2022-01-13T21:00:00+01:00",
183
+ "saving": 0.097
184
+ },
185
+ {
186
+ "price": 1.506,
187
+ "onOff": false,
188
+ "start": "2022-01-13T22:00:00+01:00",
189
+ "saving": 0.038
190
+ },
191
+ {
192
+ "price": 1.468,
193
+ "onOff": true,
194
+ "start": "2022-01-13T23:00:00+01:00",
195
+ "saving": null
196
+ }
197
+ ],
198
+ "source": "Nordpool",
199
+ "config": {
200
+ "maxHoursToSaveInSequence": "6",
201
+ "minHoursOnAfterMaxSequenceSaved": "3",
202
+ "minSaving": 0.1,
203
+ "sendCurrentValueWhenRescheduling": true,
204
+ "outputIfNoSchedule": true
205
+ },
206
+ "time": "2022-01-12T17:29:33.411+01:00",
207
+ "version": "3.2.3"
208
+ }
@@ -313,7 +313,8 @@
313
313
  "sendCurrentValueWhenRescheduling": true,
314
314
  "outputIfNoSchedule": false,
315
315
  "outputOutsidePeriod": false
316
- }
316
+ },
317
+ "sentOnCommand": false
317
318
  },
318
319
  "_msgid": "892aabf20811e69f"
319
320
  }