-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathheating-period.js
165 lines (149 loc) · 4.19 KB
/
heating-period.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/**
* Spot price optimizer, HeatingPeriod class.
*
* Copyright Markus Sipilä 2024. Published under Eclipse Public Licence v 2.0.
*/
class HeatingPeriod {
/**
* Constructor.
*
* @param HeatingCalculator heatingCalculator
* HeatingCalculator service
* @param ZonedDateTime start
* Start of the heating period.
* @param ZonedDateTime end
* End of the heating period.
* @param Item forecastItem
* Foreacast Item
* @param array heatCurve
* Array of temperature-hours pairs, representing the heat curve.
* @param float flexDefault
* Default flexibility of the heating need, between 0 and 1 (0% - 100%).
* @param float flexThreshold
* Flexibility will be set to 100% when the heating need is below this threshold.
*/
constructor(heatingCalculator, start, end, forecastItem, heatCurve, flexDefault, flexThreshold) {
this.heatingCalculator = heatingCalculator;
this.start = start;
this.end = end;
this.duration = time.Duration.between(start, end);
this.forecastItem = forecastItem;
this.heatCurve = heatCurve;
this.flexDefault = flexDefault;
this.flexThreshold = flexThreshold;
// Check that weather forecast is available.
if (!this.validateForecast()) {
return null;
}
// If forecast duration is not 24H, scale the heating need.
const multiplier = this.duration.seconds() / time.Duration.parse('PT24H').seconds();
this.avgTemp = this.forecastItem.persistence.averageBetween(this.start, this.end).numericState;
this.heatingNeed = this.heatingCalculator.calculateHeatingHoursLinear(this.heatCurve, this.avgTemp, multiplier);
// Set default flexibility for this period.
this.flexibility = (this.heatingNeed < this.flexThreshold) ? 1.0 : this.flexDefault;
}
/**
* Sets the heating need for the heating period.
*
* @param float heatingNeed
*/
setHeatingNeed(heatingNeed) {
this.heatingNeed = heatingNeed;
this.flexibility = (this.heatingNeed < this.flexThreshold) ? 1.0 : this.flexDefault;
}
/**
* Sets the flexibility to a new value.
*
* @param float flexibility.
*/
setFlexibility(flexibility) {
this.flexibility = flexibility;
}
/**
* Returns heating period start.
*
* @return ZonedDateTime
*/
getStart() {
return this.start;
}
/**
* Returns heating period end.
*
* @return ZonedDateTime
*/
getEnd() {
return this.end;
}
/**
* Returns heating period average temperature.
*
* @return float
*/
getAvgTemp() {
if (this.avgTemp === null) {
return null;
}
return parseFloat(this.avgTemp);
}
/**
* Returns heating need for the heating period, in hours.
*
* @return float
*/
getHeatingNeed() {
if (this.heatingNeed === null) {
return null;
}
return parseFloat(this.heatingNeed);
}
/**
* Returns the non-flexible heating need for the heating period, in hours.
*
* @return float
*/
getNonFlexNeed() {
if (this.heatingNeed === null) {
return null;
}
let need = (1-this.flexibility) * this.heatingNeed;
return parseFloat(need);
}
/**
* Returns the flexible heating need for the heating period, in hours.
*
* @return float
*/
getFlexNeed() {
let need = this.flexibility * this.heatingNeed;
return parseFloat(need);
}
/**
* Validates that forecast data exists for this period.
*/
validateForecast() {
const points = this.forecastItem.persistence.countBetween(this.start, this.end);
if (points < this.duration.toHours()) {
console.error('heating-calculator.js: Not enough forecast data available!');
return false;
}
return true;
}
/**
* Returns textual representation of the heating period.
*
* @return string
*/
toString() {
if (this.avgTemp === null || this.heatingNeed === null) {
return "heating-period.js: Heating need could not be calculated!"
}
return `heating-period.js: ${this.start}: temperature ${this.getAvgTemp().toFixed(2)}, heating hours ${this.getHeatingNeed().toFixed(2)}, flexibility: ${this.flexibility}`;
}
}
/**
* Exports.
*/
module.exports = {
HeatingPeriod
}