@energiok/node-red-contrib-pricecontrol-thermal 1.2.0 → 1.2.2

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.
@@ -1,15 +1,15 @@
1
1
  const { expect } = require("chai");
2
2
  const {
3
3
  calculateCoastTime,
4
- findPeaks,
5
- findTroughs,
6
4
  createSchedule,
7
5
  getCurrentMode,
8
6
  enforceMinimumDurations,
9
- findExpensiveWindows,
10
7
  validateConfig,
11
8
  ckmeans,
12
9
  classifyPricesWithCkmeans,
10
+ groupPricesByLocalDay,
11
+ mergePartialDays,
12
+ classifyPricesPerDay,
13
13
  } = require("../src/strategy-smart-thermal-functions.js");
14
14
  const { DateTime } = require("luxon");
15
15
 
@@ -71,61 +71,6 @@ describe("strategy-smart-thermal-functions", function () {
71
71
  });
72
72
  });
73
73
 
74
- describe("findPeaks", function () {
75
- it("should identify top 20% as peaks", function () {
76
- const prices = [
77
- { time: "2026-01-15T00:00:00+01:00", value: 0.5 },
78
- { time: "2026-01-15T01:00:00+01:00", value: 0.6 },
79
- { time: "2026-01-15T02:00:00+01:00", value: 0.8 },
80
- { time: "2026-01-15T03:00:00+01:00", value: 1.2 }, // peak
81
- { time: "2026-01-15T04:00:00+01:00", value: 1.5 }, // peak
82
- ];
83
- const peaks = findPeaks(prices, 20);
84
- expect(peaks).to.deep.equal([false, false, false, true, true]);
85
- });
86
-
87
- it("should handle empty array", function () {
88
- const peaks = findPeaks([], 20);
89
- expect(peaks).to.deep.equal([]);
90
- });
91
-
92
- it("should handle single price", function () {
93
- const prices = [{ time: "2026-01-15T00:00:00+01:00", value: 1.0 }];
94
- const peaks = findPeaks(prices, 20);
95
- expect(peaks).to.deep.equal([true]);
96
- });
97
-
98
- it("should handle different threshold", function () {
99
- const prices = [
100
- { time: "2026-01-15T00:00:00+01:00", value: 0.5 },
101
- { time: "2026-01-15T01:00:00+01:00", value: 0.8 }, // peak
102
- { time: "2026-01-15T02:00:00+01:00", value: 1.0 }, // peak
103
- { time: "2026-01-15T03:00:00+01:00", value: 1.2 }, // peak
104
- ];
105
- const peaks = findPeaks(prices, 50); // Top 50% (includes threshold value)
106
- expect(peaks).to.deep.equal([false, true, true, true]);
107
- });
108
- });
109
-
110
- describe("findTroughs", function () {
111
- it("should identify bottom 20% as troughs", function () {
112
- const prices = [
113
- { time: "2026-01-15T00:00:00+01:00", value: 0.3 }, // trough
114
- { time: "2026-01-15T01:00:00+01:00", value: 0.4 }, // trough
115
- { time: "2026-01-15T02:00:00+01:00", value: 0.8 },
116
- { time: "2026-01-15T03:00:00+01:00", value: 1.0 },
117
- { time: "2026-01-15T04:00:00+01:00", value: 1.2 },
118
- ];
119
- const troughs = findTroughs(prices, 20);
120
- expect(troughs).to.deep.equal([true, true, false, false, false]);
121
- });
122
-
123
- it("should handle empty array", function () {
124
- const troughs = findTroughs([], 20);
125
- expect(troughs).to.deep.equal([]);
126
- });
127
- });
128
-
129
74
  describe("createSchedule", function () {
130
75
  it("should create schedule with boost and coast periods", function () {
131
76
  const prices = [
@@ -327,14 +272,9 @@ describe("strategy-smart-thermal-functions", function () {
327
272
  }
328
273
 
329
274
  const config = {
330
- setpoint: 22,
331
- comfortMin: 20,
332
- comfortMax: 24,
333
275
  heatLossCoefficient: 0.05,
334
- peakThreshold: 20,
335
- intervalMinutes: 15,
336
- minCoastMinutes: 60, // Require 1 hour minimum
337
- minBoostMinutes: 60,
276
+ minModeDuration: 60, // Require 1 hour minimum
277
+ minSavingsPercent: 5,
338
278
  };
339
279
 
340
280
  const schedule = createSchedule(prices, 5, config);
@@ -403,35 +343,6 @@ describe("strategy-smart-thermal-functions", function () {
403
343
  });
404
344
  });
405
345
 
406
- describe("findExpensiveWindows", function () {
407
- it("should find expensive windows above average", function () {
408
- const prices = [0.5, 0.6, 1.2, 1.5, 0.7, 0.4];
409
- const avgPrice = 0.82;
410
- const windows = findExpensiveWindows(prices, avgPrice, 0);
411
- expect(windows.length).to.equal(1);
412
- expect(windows[0].start).to.equal(2);
413
- expect(windows[0].end).to.equal(3);
414
- expect(windows[0].peakPrice).to.equal(1.5);
415
- });
416
-
417
- it("should respect minimum savings threshold", function () {
418
- const prices = [0.5, 0.6, 0.85, 0.9, 0.7, 0.4]; // prices close to avg
419
- const avgPrice = 0.65;
420
- const threshold = 0.3; // High threshold
421
- const windows = findExpensiveWindows(prices, avgPrice, threshold);
422
- // Only 0.9 exceeds avgPrice + 0.3 = 0.95? No, 0.9 < 0.95
423
- expect(windows.length).to.equal(0);
424
- });
425
-
426
- it("should sort windows by peak price (highest first)", function () {
427
- const prices = [0.5, 1.0, 0.5, 0.5, 1.5, 0.5]; // Two separate peaks
428
- const avgPrice = 0.75;
429
- const windows = findExpensiveWindows(prices, avgPrice, 0);
430
- expect(windows.length).to.equal(2);
431
- expect(windows[0].peakPrice).to.be.greaterThan(windows[1].peakPrice);
432
- });
433
- });
434
-
435
346
  describe("createSchedule with negative prices", function () {
436
347
  it("should handle negative prices", function () {
437
348
  const prices = [
@@ -859,6 +770,7 @@ describe("strategy-smart-thermal-functions", function () {
859
770
  heatLossCoefficient: 0.05,
860
771
  minModeDuration: 15,
861
772
  minSavingsPercent: 0, // Allow any clustering
773
+ clusterPerDay: false, // Use global clustering for this test
862
774
  };
863
775
 
864
776
  const schedule = createSchedule(prices, 5, config);
@@ -871,4 +783,256 @@ describe("strategy-smart-thermal-functions", function () {
871
783
  expect(schedule[0].tuning.clustering.method).to.equal("ckmeans");
872
784
  });
873
785
  });
786
+
787
+ describe("Per-day clustering", function () {
788
+ describe("groupPricesByLocalDay", function () {
789
+ it("should group prices by local calendar day", function () {
790
+ const prices = [
791
+ { time: "2026-01-15T23:00:00Z", value: 100 }, // 00:00 Oslo = Jan 16
792
+ { time: "2026-01-16T00:00:00Z", value: 110 }, // 01:00 Oslo = Jan 16
793
+ { time: "2026-01-16T10:00:00Z", value: 120 }, // 11:00 Oslo = Jan 16
794
+ { time: "2026-01-16T23:00:00Z", value: 130 }, // 00:00 Oslo = Jan 17
795
+ { time: "2026-01-17T05:00:00Z", value: 140 }, // 06:00 Oslo = Jan 17
796
+ ];
797
+
798
+ const groups = groupPricesByLocalDay(prices, "Europe/Oslo");
799
+
800
+ expect(groups.size).to.equal(2);
801
+ expect(groups.get("2026-01-16")).to.have.length(3);
802
+ expect(groups.get("2026-01-17")).to.have.length(2);
803
+ });
804
+
805
+ it("should preserve original indices", function () {
806
+ const prices = [
807
+ { time: "2026-01-15T23:00:00Z", value: 100 },
808
+ { time: "2026-01-16T05:00:00Z", value: 110 },
809
+ ];
810
+
811
+ const groups = groupPricesByLocalDay(prices, "Europe/Oslo");
812
+ const day16 = groups.get("2026-01-16");
813
+
814
+ expect(day16[0].originalIndex).to.equal(0);
815
+ expect(day16[1].originalIndex).to.equal(1);
816
+ });
817
+ });
818
+
819
+ describe("mergePartialDays", function () {
820
+ it("should not merge days with enough intervals", function () {
821
+ const sortedDays = [
822
+ ["2026-01-15", [{ originalIndex: 0 }, { originalIndex: 1 }, { originalIndex: 2 }, { originalIndex: 3 }]],
823
+ ["2026-01-16", [{ originalIndex: 4 }, { originalIndex: 5 }, { originalIndex: 6 }, { originalIndex: 7 }]],
824
+ ];
825
+
826
+ const result = mergePartialDays(sortedDays, 4);
827
+
828
+ expect(result).to.have.length(2);
829
+ expect(result[0][0]).to.equal("2026-01-15");
830
+ expect(result[1][0]).to.equal("2026-01-16");
831
+ });
832
+
833
+ it("should merge small first day with next day", function () {
834
+ const sortedDays = [
835
+ ["2026-01-15", [{ originalIndex: 0 }, { originalIndex: 1 }]], // Too small
836
+ ["2026-01-16", [{ originalIndex: 2 }, { originalIndex: 3 }, { originalIndex: 4 }, { originalIndex: 5 }]],
837
+ ];
838
+
839
+ const result = mergePartialDays(sortedDays, 4);
840
+
841
+ expect(result).to.have.length(1);
842
+ expect(result[0][0]).to.equal("2026-01-15+2026-01-16");
843
+ expect(result[0][1]).to.have.length(6);
844
+ });
845
+
846
+ it("should merge small last day with previous day", function () {
847
+ const sortedDays = [
848
+ ["2026-01-15", [{ originalIndex: 0 }, { originalIndex: 1 }, { originalIndex: 2 }, { originalIndex: 3 }]],
849
+ ["2026-01-16", [{ originalIndex: 4 }, { originalIndex: 5 }]], // Too small
850
+ ];
851
+
852
+ const result = mergePartialDays(sortedDays, 4);
853
+
854
+ expect(result).to.have.length(1);
855
+ expect(result[0][0]).to.equal("2026-01-15+2026-01-16");
856
+ expect(result[0][1]).to.have.length(6);
857
+ });
858
+ });
859
+
860
+ describe("classifyPricesPerDay", function () {
861
+ it("should cluster each day independently", function () {
862
+ // Day 1: Low prices (50-100), Day 2: High prices (150-200)
863
+ const prices = [
864
+ // Day 1 (Oslo time) - all low prices
865
+ { time: "2026-01-15T23:00:00Z", value: 50 }, // Jan 16 00:00 Oslo
866
+ { time: "2026-01-16T02:00:00Z", value: 60 }, // Jan 16 03:00 Oslo
867
+ { time: "2026-01-16T05:00:00Z", value: 70 }, // Jan 16 06:00 Oslo
868
+ { time: "2026-01-16T08:00:00Z", value: 80 }, // Jan 16 09:00 Oslo
869
+ { time: "2026-01-16T11:00:00Z", value: 90 }, // Jan 16 12:00 Oslo
870
+ { time: "2026-01-16T14:00:00Z", value: 100 }, // Jan 16 15:00 Oslo
871
+ { time: "2026-01-16T17:00:00Z", value: 90 }, // Jan 16 18:00 Oslo
872
+ { time: "2026-01-16T20:00:00Z", value: 80 }, // Jan 16 21:00 Oslo
873
+ // Day 2 (Oslo time) - all high prices
874
+ { time: "2026-01-16T23:00:00Z", value: 150 }, // Jan 17 00:00 Oslo
875
+ { time: "2026-01-17T02:00:00Z", value: 160 }, // Jan 17 03:00 Oslo
876
+ { time: "2026-01-17T05:00:00Z", value: 170 }, // Jan 17 06:00 Oslo
877
+ { time: "2026-01-17T08:00:00Z", value: 180 }, // Jan 17 09:00 Oslo
878
+ { time: "2026-01-17T11:00:00Z", value: 190 }, // Jan 17 12:00 Oslo
879
+ { time: "2026-01-17T14:00:00Z", value: 200 }, // Jan 17 15:00 Oslo
880
+ { time: "2026-01-17T17:00:00Z", value: 190 }, // Jan 17 18:00 Oslo
881
+ { time: "2026-01-17T20:00:00Z", value: 180 }, // Jan 17 21:00 Oslo
882
+ ];
883
+
884
+ const result = classifyPricesPerDay(prices, "Europe/Oslo", 5, 3, 4);
885
+
886
+ expect(result.assignments).to.have.length(16);
887
+ expect(result.dailyClustering).to.have.length(2);
888
+
889
+ // Each day should have its own clustering
890
+ expect(result.dailyClustering[0].date).to.equal("2026-01-16");
891
+ expect(result.dailyClustering[1].date).to.equal("2026-01-17");
892
+
893
+ // Day 1: 50 should be cheapest (boost=0), 100 should be expensive (coast=2)
894
+ expect(result.assignments[0]).to.equal(0); // 50 = boost
895
+ expect(result.assignments[5]).to.equal(2); // 100 = coast
896
+
897
+ // Day 2: 150 should be cheapest (boost=0), 200 should be expensive (coast=2)
898
+ expect(result.assignments[8]).to.equal(0); // 150 = boost (for day 2!)
899
+ expect(result.assignments[13]).to.equal(2); // 200 = coast
900
+ });
901
+
902
+ it("should include per-day stats in dailyClustering", function () {
903
+ const prices = [
904
+ { time: "2026-01-15T23:00:00Z", value: 50 },
905
+ { time: "2026-01-16T02:00:00Z", value: 60 },
906
+ { time: "2026-01-16T05:00:00Z", value: 70 },
907
+ { time: "2026-01-16T08:00:00Z", value: 80 },
908
+ { time: "2026-01-16T11:00:00Z", value: 90 },
909
+ { time: "2026-01-16T14:00:00Z", value: 100 },
910
+ { time: "2026-01-16T17:00:00Z", value: 90 },
911
+ { time: "2026-01-16T20:00:00Z", value: 80 },
912
+ ];
913
+
914
+ const result = classifyPricesPerDay(prices, "Europe/Oslo", 0, 3, 4);
915
+
916
+ expect(result.dailyClustering[0]).to.have.property("avgPrice");
917
+ expect(result.dailyClustering[0]).to.have.property("minPrice");
918
+ expect(result.dailyClustering[0]).to.have.property("maxPrice");
919
+ expect(result.dailyClustering[0]).to.have.property("breaks");
920
+ expect(result.dailyClustering[0]).to.have.property("clusterMeans");
921
+ expect(result.dailyClustering[0].minPrice).to.equal(50);
922
+ expect(result.dailyClustering[0].maxPrice).to.equal(100);
923
+ });
924
+ });
925
+
926
+ describe("createSchedule with clusterPerDay", function () {
927
+ it("should use per-day clustering by default", function () {
928
+ // Day 1: prices 50-100, Day 2: prices 150-200
929
+ const prices = [
930
+ { time: "2026-01-15T23:00:00Z", value: 50 },
931
+ { time: "2026-01-16T02:00:00Z", value: 75 },
932
+ { time: "2026-01-16T05:00:00Z", value: 100 },
933
+ { time: "2026-01-16T08:00:00Z", value: 75 },
934
+ { time: "2026-01-16T11:00:00Z", value: 50 },
935
+ { time: "2026-01-16T14:00:00Z", value: 75 },
936
+ { time: "2026-01-16T17:00:00Z", value: 100 },
937
+ { time: "2026-01-16T20:00:00Z", value: 75 },
938
+ { time: "2026-01-16T23:00:00Z", value: 150 },
939
+ { time: "2026-01-17T02:00:00Z", value: 175 },
940
+ { time: "2026-01-17T05:00:00Z", value: 200 },
941
+ { time: "2026-01-17T08:00:00Z", value: 175 },
942
+ { time: "2026-01-17T11:00:00Z", value: 150 },
943
+ { time: "2026-01-17T14:00:00Z", value: 175 },
944
+ { time: "2026-01-17T17:00:00Z", value: 200 },
945
+ { time: "2026-01-17T20:00:00Z", value: 175 },
946
+ ];
947
+
948
+ const config = {
949
+ heatLossCoefficient: 0.05,
950
+ minModeDuration: 60,
951
+ minSavingsPercent: 0,
952
+ // clusterPerDay defaults to true
953
+ };
954
+
955
+ const schedule = createSchedule(prices, 5, config);
956
+
957
+ expect(schedule[0].tuning.clusterPerDay).to.equal(true);
958
+ expect(schedule[0].tuning.clustering.method).to.equal("ckmeans-per-day");
959
+ expect(schedule[0].tuning.clustering).to.have.property("dailyClustering");
960
+ expect(schedule[0].tuning.clustering.dailyClustering).to.have.length(2);
961
+ });
962
+
963
+ it("should use global clustering when clusterPerDay is false", function () {
964
+ const prices = [
965
+ { time: "2026-01-15T23:00:00Z", value: 50 },
966
+ { time: "2026-01-16T02:00:00Z", value: 75 },
967
+ { time: "2026-01-16T05:00:00Z", value: 100 },
968
+ { time: "2026-01-16T08:00:00Z", value: 75 },
969
+ { time: "2026-01-16T11:00:00Z", value: 50 },
970
+ { time: "2026-01-16T14:00:00Z", value: 75 },
971
+ { time: "2026-01-16T17:00:00Z", value: 100 },
972
+ { time: "2026-01-16T20:00:00Z", value: 75 },
973
+ ];
974
+
975
+ const config = {
976
+ heatLossCoefficient: 0.05,
977
+ minModeDuration: 60,
978
+ minSavingsPercent: 0,
979
+ clusterPerDay: false,
980
+ };
981
+
982
+ const schedule = createSchedule(prices, 5, config);
983
+
984
+ expect(schedule[0].tuning.clusterPerDay).to.equal(false);
985
+ expect(schedule[0].tuning.clustering.method).to.equal("ckmeans");
986
+ expect(schedule[0].tuning.clustering).to.not.have.property("dailyClustering");
987
+ });
988
+
989
+ it("should find boost/coast on EACH day with per-day clustering", function () {
990
+ // This is the key test: without per-day clustering, day 1's prices
991
+ // would all be "normal" compared to day 2's higher prices.
992
+ // With per-day clustering, each day gets its own boost/coast hours.
993
+ const prices = [
994
+ // Day 1: Low price range (50-100)
995
+ { time: "2026-01-15T23:00:00Z", value: 50 }, // Cheapest on day 1
996
+ { time: "2026-01-16T02:00:00Z", value: 75 },
997
+ { time: "2026-01-16T05:00:00Z", value: 100 }, // Most expensive on day 1
998
+ { time: "2026-01-16T08:00:00Z", value: 75 },
999
+ { time: "2026-01-16T11:00:00Z", value: 50 }, // Cheapest on day 1
1000
+ { time: "2026-01-16T14:00:00Z", value: 75 },
1001
+ { time: "2026-01-16T17:00:00Z", value: 100 }, // Most expensive on day 1
1002
+ { time: "2026-01-16T20:00:00Z", value: 75 },
1003
+ // Day 2: High price range (150-200)
1004
+ { time: "2026-01-16T23:00:00Z", value: 150 }, // Cheapest on day 2
1005
+ { time: "2026-01-17T02:00:00Z", value: 175 },
1006
+ { time: "2026-01-17T05:00:00Z", value: 200 }, // Most expensive on day 2
1007
+ { time: "2026-01-17T08:00:00Z", value: 175 },
1008
+ { time: "2026-01-17T11:00:00Z", value: 150 }, // Cheapest on day 2
1009
+ { time: "2026-01-17T14:00:00Z", value: 175 },
1010
+ { time: "2026-01-17T17:00:00Z", value: 200 }, // Most expensive on day 2
1011
+ { time: "2026-01-17T20:00:00Z", value: 175 },
1012
+ ];
1013
+
1014
+ const config = {
1015
+ heatLossCoefficient: 0.02, // Well-insulated building (long coast time)
1016
+ minModeDuration: 60,
1017
+ minSavingsPercent: 0,
1018
+ clusterPerDay: true,
1019
+ };
1020
+
1021
+ const schedule = createSchedule(prices, 5, config);
1022
+
1023
+ // Count modes per day
1024
+ const day1Modes = schedule.slice(0, 8).map(s => s.mode);
1025
+ const day2Modes = schedule.slice(8, 16).map(s => s.mode);
1026
+
1027
+ // Day 1 should have some boost (at price 50) and some coast (at price 100)
1028
+ expect(day1Modes).to.include("boost");
1029
+ expect(day1Modes).to.include("coast");
1030
+
1031
+ // Day 2 should ALSO have boost (at price 150) and coast (at price 200)
1032
+ // This is the key difference from global clustering!
1033
+ expect(day2Modes).to.include("boost");
1034
+ expect(day2Modes).to.include("coast");
1035
+ });
1036
+ });
1037
+ });
874
1038
  });
@@ -24,21 +24,16 @@ describe("ps-strategy-smart-thermal node", function () {
24
24
  });
25
25
  });
26
26
 
27
- it("should output current setpoint on output 1", function (done) {
27
+ it("should output current mode on output 1", function (done) {
28
28
  const flow = [
29
29
  {
30
- id: "n1",
31
- type: "ps-strategy-smart-thermal",
32
- name: "thermal test",
33
- setpoint: 22,
34
- comfortMin: 20,
35
- comfortMax: 24,
36
- heatLossCoefficient: 0.05,
37
- peakThreshold: 20,
38
- intervalMinutes: 60,
39
- sendSchedule: true,
40
- wires: [["n2"], ["n3"]],
41
- },
30
+ id: "n1",
31
+ type: "ps-strategy-smart-thermal",
32
+ name: "thermal test",
33
+ heatLossCoefficient: 0.05,
34
+ sendSchedule: true,
35
+ wires: [["n2"], ["n3"]],
36
+ },
42
37
  { id: "n2", type: "helper" },
43
38
  { id: "n3", type: "helper" },
44
39
  ];
@@ -75,18 +70,13 @@ describe("ps-strategy-smart-thermal node", function () {
75
70
  it("should output schedule on output 2 when sendSchedule is true", function (done) {
76
71
  const flow = [
77
72
  {
78
- id: "n1",
79
- type: "ps-strategy-smart-thermal",
80
- name: "thermal test",
81
- setpoint: 22,
82
- comfortMin: 20,
83
- comfortMax: 24,
84
- heatLossCoefficient: 0.05,
85
- peakThreshold: 20,
86
- intervalMinutes: 60,
87
- sendSchedule: true,
88
- wires: [["n2"], ["n3"]],
89
- },
73
+ id: "n1",
74
+ type: "ps-strategy-smart-thermal",
75
+ name: "thermal test",
76
+ heatLossCoefficient: 0.05,
77
+ sendSchedule: true,
78
+ wires: [["n2"], ["n3"]],
79
+ },
90
80
  { id: "n2", type: "helper" },
91
81
  { id: "n3", type: "helper" },
92
82
  ];
@@ -235,14 +225,11 @@ describe("ps-strategy-smart-thermal node", function () {
235
225
  it("should ignore message not for this node", function (done) {
236
226
  const flow = [
237
227
  {
238
- id: "n1",
239
- type: "ps-strategy-smart-thermal",
240
- name: "thermal test",
241
- setpoint: 22,
242
- comfortMin: 20,
243
- comfortMax: 24,
244
- wires: [["n2"], ["n3"]],
245
- },
228
+ id: "n1",
229
+ type: "ps-strategy-smart-thermal",
230
+ name: "thermal test",
231
+ wires: [["n2"], ["n3"]],
232
+ },
246
233
  { id: "n2", type: "helper" },
247
234
  { id: "n3", type: "helper" },
248
235
  ];
@@ -274,14 +261,11 @@ describe("ps-strategy-smart-thermal node", function () {
274
261
  it("should warn when price data is missing", function (done) {
275
262
  const flow = [
276
263
  {
277
- id: "n1",
278
- type: "ps-strategy-smart-thermal",
279
- name: "thermal test",
280
- setpoint: 22,
281
- comfortMin: 20,
282
- comfortMax: 24,
283
- wires: [["n2"], ["n3"]],
284
- },
264
+ id: "n1",
265
+ type: "ps-strategy-smart-thermal",
266
+ name: "thermal test",
267
+ wires: [["n2"], ["n3"]],
268
+ },
285
269
  { id: "n2", type: "helper" },
286
270
  { id: "n3", type: "helper" },
287
271
  ];
@@ -312,14 +296,11 @@ describe("ps-strategy-smart-thermal node", function () {
312
296
  it("should warn when outdoor temperature is missing", function (done) {
313
297
  const flow = [
314
298
  {
315
- id: "n1",
316
- type: "ps-strategy-smart-thermal",
317
- name: "thermal test",
318
- setpoint: 22,
319
- comfortMin: 20,
320
- comfortMax: 24,
321
- wires: [["n2"], ["n3"]],
322
- },
299
+ id: "n1",
300
+ type: "ps-strategy-smart-thermal",
301
+ name: "thermal test",
302
+ wires: [["n2"], ["n3"]],
303
+ },
323
304
  { id: "n2", type: "helper" },
324
305
  { id: "n3", type: "helper" },
325
306
  ];
@@ -350,15 +331,12 @@ describe("ps-strategy-smart-thermal node", function () {
350
331
  it("should allow config override via message", function (done) {
351
332
  const flow = [
352
333
  {
353
- id: "n1",
354
- type: "ps-strategy-smart-thermal",
355
- name: "thermal test",
356
- setpoint: 22,
357
- comfortMin: 20,
358
- comfortMax: 24,
359
- heatLossCoefficient: 0.05,
360
- wires: [["n2"], ["n3"]],
361
- },
334
+ id: "n1",
335
+ type: "ps-strategy-smart-thermal",
336
+ name: "thermal test",
337
+ heatLossCoefficient: 0.05,
338
+ wires: [["n2"], ["n3"]],
339
+ },
362
340
  { id: "n2", type: "helper" },
363
341
  { id: "n3", type: "helper" },
364
342
  ];
package/nul DELETED
File without changes