hoffmation-base 3.8.0 → 4.0.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 (127) hide show
  1. package/lib/devices/dachs/dachs.d.ts +79 -2
  2. package/lib/devices/dachs/dachs.js +214 -18
  3. package/lib/devices/devices.d.ts +36 -1
  4. package/lib/devices/devices.js +64 -0
  5. package/lib/devices/jsObject/jsObjectEnergyManager.d.ts +16 -1
  6. package/lib/devices/jsObject/jsObjectEnergyManager.js +23 -0
  7. package/lib/devices/victron/victron-device.d.ts +83 -1
  8. package/lib/devices/victron/victron-device.js +151 -2
  9. package/lib/devices/victron/victron-morning-release.d.ts +16 -0
  10. package/lib/devices/victron/victron-morning-release.js +2 -0
  11. package/lib/enums/DeviceCapability.d.ts +1 -0
  12. package/lib/enums/DeviceCapability.js +1 -0
  13. package/lib/interfaces/baseDevices/iAirQualityCollector.d.ts +2 -1
  14. package/lib/interfaces/baseDevices/iAirQualityReadings.d.ts +50 -0
  15. package/lib/interfaces/baseDevices/iAirQualityReadings.js +2 -0
  16. package/lib/interfaces/baseDevices/iAirQualitySensor.d.ts +1 -54
  17. package/lib/interfaces/baseDevices/iAirQualitySensor.js +0 -5
  18. package/lib/interfaces/baseDevices/iEnergyManager.d.ts +43 -0
  19. package/lib/interfaces/baseDevices/iHumidityCollector.d.ts +0 -1
  20. package/lib/interfaces/baseDevices/iHumidityCollector.js +0 -2
  21. package/lib/interfaces/baseDevices/iTemperatureCollector.d.ts +0 -1
  22. package/lib/interfaces/baseDevices/iTemperatureCollector.js +0 -2
  23. package/lib/interfaces/baseDevices/index.d.ts +4 -0
  24. package/lib/interfaces/baseDevices/index.js +4 -0
  25. package/lib/interfaces/baseDevices/undefinedAirQualityValue.d.ts +4 -0
  26. package/lib/interfaces/baseDevices/undefinedAirQualityValue.js +7 -0
  27. package/lib/interfaces/baseDevices/undefinedHumidityValue.d.ts +4 -0
  28. package/lib/interfaces/baseDevices/undefinedHumidityValue.js +7 -0
  29. package/lib/interfaces/baseDevices/undefinedTempValue.d.ts +4 -0
  30. package/lib/interfaces/baseDevices/undefinedTempValue.js +7 -0
  31. package/lib/interfaces/dachs/KeyListEntity.d.ts +0 -5
  32. package/lib/interfaces/dachs/KeyListEntityResponse.d.ts +6 -0
  33. package/lib/interfaces/dachs/KeyListEntityResponse.js +2 -0
  34. package/lib/interfaces/dachs/index.d.ts +1 -0
  35. package/lib/interfaces/dachs/index.js +1 -0
  36. package/lib/interfaces/deviceSettings/iDachsDeviceSettings.d.ts +15 -0
  37. package/lib/interfaces/iActuatorStateSample.d.ts +13 -0
  38. package/lib/interfaces/iActuatorStateSample.js +2 -0
  39. package/lib/interfaces/iBatteryLevelSample.d.ts +13 -0
  40. package/lib/interfaces/iBatteryLevelSample.js +2 -0
  41. package/lib/interfaces/iConsumptionWindowSample.d.ts +26 -0
  42. package/lib/interfaces/iConsumptionWindowSample.js +2 -0
  43. package/lib/interfaces/iDachsHistoryGateResult.d.ts +29 -0
  44. package/lib/interfaces/iDachsHistoryGateResult.js +2 -0
  45. package/lib/interfaces/iEnergyHistoryBasis.d.ts +26 -0
  46. package/lib/interfaces/iEnergyHistoryBasis.js +2 -0
  47. package/lib/interfaces/iEnergyHistoryEstimate.d.ts +21 -0
  48. package/lib/interfaces/iEnergyHistoryEstimate.js +2 -0
  49. package/lib/interfaces/iEnergyHistoryFeatures.d.ts +21 -0
  50. package/lib/interfaces/iEnergyHistoryFeatures.js +2 -0
  51. package/lib/interfaces/iEnergyHistoryModel.d.ts +21 -0
  52. package/lib/interfaces/iEnergyHistoryModel.js +2 -0
  53. package/lib/interfaces/iEnergyHistoryOptions.d.ts +29 -0
  54. package/lib/interfaces/iEnergyHistoryOptions.js +2 -0
  55. package/lib/interfaces/iEnergyHistoryOutlook.d.ts +41 -0
  56. package/lib/interfaces/iEnergyHistoryOutlook.js +2 -0
  57. package/lib/interfaces/iEnergyHistorySample.d.ts +19 -0
  58. package/lib/interfaces/iEnergyHistorySample.js +2 -0
  59. package/lib/interfaces/iFossilGeneratorRun.d.ts +22 -0
  60. package/lib/interfaces/iFossilGeneratorRun.js +2 -0
  61. package/lib/interfaces/iFossilGeneratorSource.d.ts +21 -0
  62. package/lib/interfaces/iFossilGeneratorSource.js +2 -0
  63. package/lib/interfaces/iMorningReserveVerdict.d.ts +38 -0
  64. package/lib/interfaces/iMorningReserveVerdict.js +2 -0
  65. package/lib/interfaces/iPersist.d.ts +51 -0
  66. package/lib/interfaces/iProjectedSocBand.d.ts +7 -0
  67. package/lib/interfaces/iProjectedSocBand.js +2 -0
  68. package/lib/interfaces/iWeatherDaySummary.d.ts +21 -0
  69. package/lib/interfaces/iWeatherDaySummary.js +2 -0
  70. package/lib/interfaces/index.d.ts +16 -0
  71. package/lib/interfaces/index.js +16 -0
  72. package/lib/services/dbo/actuator-state-row.d.ts +14 -0
  73. package/lib/services/dbo/actuator-state-row.js +2 -0
  74. package/lib/services/dbo/battery-level-row.d.ts +16 -0
  75. package/lib/services/dbo/battery-level-row.js +2 -0
  76. package/lib/services/dbo/energy-consumption-row.d.ts +16 -0
  77. package/lib/services/dbo/energy-consumption-row.js +2 -0
  78. package/lib/services/dbo/postgreSqlPersist.d.ts +48 -1
  79. package/lib/services/dbo/postgreSqlPersist.js +298 -28
  80. package/lib/services/dbo/weather-day-summary-row.d.ts +18 -0
  81. package/lib/services/dbo/weather-day-summary-row.js +2 -0
  82. package/lib/services/energy/energy-history-service.d.ts +168 -0
  83. package/lib/services/energy/energy-history-service.js +499 -0
  84. package/lib/services/energy/index.d.ts +1 -0
  85. package/lib/services/energy/index.js +17 -0
  86. package/lib/services/energy/plant-energy-dials.d.ts +22 -0
  87. package/lib/services/energy/plant-energy-dials.js +2 -0
  88. package/lib/services/https-service.d.ts +48 -2
  89. package/lib/services/https-service.js +136 -10
  90. package/lib/services/index.d.ts +1 -0
  91. package/lib/services/index.js +1 -0
  92. package/lib/services/time-callback-service.d.ts +12 -0
  93. package/lib/services/time-callback-service.js +16 -2
  94. package/lib/services/weather/index.d.ts +1 -0
  95. package/lib/services/weather/index.js +1 -0
  96. package/lib/services/weather/open-weather-day-summary.d.ts +21 -0
  97. package/lib/services/weather/open-weather-day-summary.js +2 -0
  98. package/lib/services/weather/weather-day-summary-fetcher.d.ts +6 -0
  99. package/lib/services/weather/weather-day-summary-fetcher.js +2 -0
  100. package/lib/services/weather/weather-history-backfill.d.ts +88 -0
  101. package/lib/services/weather/weather-history-backfill.js +228 -0
  102. package/lib/services/weather/weather-service.js +29 -4
  103. package/lib/settings-service-instance.js +5 -2
  104. package/lib/settingsObjects/deviceSettings/dachsSettings.d.ts +6 -0
  105. package/lib/settingsObjects/deviceSettings/dachsSettings.js +14 -1
  106. package/lib/settingsObjects/deviceSettings/victronDeviceSettings.d.ts +116 -0
  107. package/lib/settingsObjects/deviceSettings/victronDeviceSettings.js +150 -5
  108. package/lib/tsconfig.tsbuildinfo +1 -1
  109. package/lib/utils/dayMs.d.ts +7 -0
  110. package/lib/utils/dayMs.js +10 -0
  111. package/lib/utils/energy-history-dials.d.ts +19 -0
  112. package/lib/utils/energy-history-dials.js +2 -0
  113. package/lib/utils/energy-history-utils.d.ts +143 -0
  114. package/lib/utils/energy-history-utils.js +470 -0
  115. package/lib/utils/energy-manager-utils.d.ts +123 -1
  116. package/lib/utils/energy-manager-utils.js +226 -0
  117. package/lib/utils/index.d.ts +4 -0
  118. package/lib/utils/index.js +4 -0
  119. package/lib/utils/model-shadow.d.ts +61 -0
  120. package/lib/utils/model-shadow.js +83 -0
  121. package/lib/utils/morning-reserve-dials.d.ts +21 -0
  122. package/lib/utils/morning-reserve-dials.js +2 -0
  123. package/lib/utils/morning-verdict.d.ts +5 -0
  124. package/lib/utils/morning-verdict.js +2 -0
  125. package/lib/utils/utils.d.ts +0 -1
  126. package/lib/utils/utils.js +5 -5
  127. package/package.json +3 -2
@@ -1,8 +1,58 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VictronDeviceSettings = void 0;
4
+ exports.acceptedShare = acceptedShare;
5
+ exports.reportImpossibleWindow = reportImpossibleWindow;
4
6
  const deviceSettings_1 = require("./deviceSettings");
5
7
  const utils_1 = require("../../utils");
8
+ const logging_1 = require("../../logging");
9
+ const enums_1 = require("../../enums");
10
+ /**
11
+ * Takes over a setting that has to lie between 0 and 1, or keeps the value in force and reports the refusal.
12
+ *
13
+ * Kept rather than clamped, and that is the whole decision: 90 written for "90 percent" clamps to 1 and turns
14
+ * a dial nobody touched to its extreme - a coverage demanding every single reading of a day, a quantile at
15
+ * the maximum of the sample, a conversion factor that loses nothing at all. Each of those is a plausible
16
+ * looking number, and a plausible looking number is exactly the one an operator never goes looking for. The
17
+ * value in force is the documented default, the refused input is named in the log, and no unusable input
18
+ * quietly becomes a different plant.
19
+ *
20
+ * Deliberately loud rather than thrown: a settings file is read at startup, and one mistyped share must not
21
+ * cost the whole installation its automation.
22
+ *
23
+ * Lives here rather than on the settings base class only because of how this change was cut; it is shared by
24
+ * every settings class that carries a share and belongs next to them.
25
+ * @param name - The setting, so the log line names what was refused
26
+ * @param value - What was handed in, or undefined when the caller set nothing
27
+ * @param current - The value in force, kept whenever the input is unusable
28
+ * @returns - The value to use from now on
29
+ */
30
+ function acceptedShare(name, value, current) {
31
+ if (value === undefined) {
32
+ return current;
33
+ }
34
+ if (!Number.isFinite(value) || value < 0 || value > 1) {
35
+ logging_1.ServerLogService.writeLog(enums_1.LogLevel.Warn, `Settings: ${name} of ${value} lies outside 0..1 --> refused, ${current} stays in force`);
36
+ return current;
37
+ }
38
+ return value;
39
+ }
40
+ /**
41
+ * Reports a history window shorter than the number of days the fit demands before it produces anything.
42
+ *
43
+ * Reported rather than corrected: which of the two numbers the operator meant cannot be told from here, and
44
+ * the combination is not dangerous - the fit simply never yields a band and the decision falls back to the
45
+ * rung that needs no history. Only nobody would ever see why it never got past that rung.
46
+ * @param windowDays - The length of the sliding window in days
47
+ * @param minimumDays - How many usable days the fit demands
48
+ */
49
+ function reportImpossibleWindow(windowDays, minimumDays) {
50
+ if (windowDays >= minimumDays) {
51
+ return;
52
+ }
53
+ logging_1.ServerLogService.writeLog(enums_1.LogLevel.Warn, `Settings: historyWindowDays of ${windowDays} is shorter than historyMinimumDays of ${minimumDays} ` +
54
+ '--> the fit can never gather enough days and no band will be produced');
55
+ }
6
56
  class VictronDeviceSettings extends deviceSettings_1.DeviceSettings {
7
57
  constructor() {
8
58
  super(...arguments);
@@ -53,6 +103,91 @@ class VictronDeviceSettings extends deviceSettings_1.DeviceSettings {
53
103
  * @default 10000
54
104
  */
55
105
  this.batteryCapacityWattage = 10000;
106
+ /**
107
+ * The share of the expected consumption readings a recorded day has to carry before its window sum is
108
+ * counted at all, between 0 and 1.
109
+ *
110
+ * A dial of the plant rather than of whoever reads its history: an incompletely covered night adds up to
111
+ * too little, therefore looks like a frugal night, pulls the quantile down and makes the resulting bound
112
+ * too optimistic - and two readers who disagree about what counts as a covered day of the same plant would
113
+ * be answering about two different plants. Deliberately strict, because a bound that is too optimistic
114
+ * suppresses, and a wrong suppression has no way back: the morning is simply below the reserve by then.
115
+ * @default 0.9
116
+ */
117
+ this.historyMinimumDayCoverage = 0.9;
118
+ /**
119
+ * The quantile of the recorded consumption windows a model free bound is calculated with, between 0 and 1.
120
+ * An upper quantile rather than the median, because the bound has to hold on a heavy night and not on half
121
+ * of them.
122
+ * @default 0.9
123
+ */
124
+ this.historyConsumptionQuantile = 0.9;
125
+ /**
126
+ * How many usable consumption window sums are needed before that quantile means anything at all.
127
+ *
128
+ * An upper quantile of one night is that night, and of two nights it sits all but on their maximum - so a
129
+ * single quiet night would yield a high bound and a suppression with nothing behind it. Deliberately its
130
+ * own number rather than a shared minimum with the day count a model fit needs: that one protects the
131
+ * stability of a fit, this one protects the meaning of a quantile.
132
+ * @default 10
133
+ */
134
+ this.historyMinimumConsumptionDays = 10;
135
+ /**
136
+ * The state of charge in percent the coming morning's low is expected to stay above.
137
+ *
138
+ * A property of the battery and therefore stated once, here: "how low may the morning get" is the same
139
+ * question whichever device asks it, and two numbers for one battery would let a plant judge one and the
140
+ * same morning twice. Where consumers legitimately differ is how sure they want to be before they act, and
141
+ * that is the split between the verdicts that need no model and the ones that do - see
142
+ * {@link iMorningReserveVerdict.measured}, not a second reserve.
143
+ *
144
+ * It is also the threshold the model shadow measures against, and a shadow whose sample is split across two
145
+ * thresholds measures nothing - see {@link ModelShadow}.
146
+ * @default 20
147
+ */
148
+ this.minimumMorningSocReserve = 20;
149
+ /**
150
+ * Below this many remaining sun hours no further photovoltaic yield is expected to change the coming
151
+ * morning.
152
+ *
153
+ * Plant wide next to the reserve, because it describes this installation's photovoltaic rather than whoever
154
+ * asks: the last half hour before sunset yields the same nothing for every consumer.
155
+ * @default 0.5
156
+ */
157
+ this.noSunThresholdHours = 0.5;
158
+ /**
159
+ * The length of the sliding window in days the history is read and fitted from. Older days describe a
160
+ * differently grown installation and are deliberately left out.
161
+ *
162
+ * Stated once for the whole plant, here, because it says how much of the recorded data is telling enough to
163
+ * answer with - a property of that data and not of whoever asks. Every consumer of the history asks the
164
+ * same question, and a second window meant a second read and a second paid backfill of the same days.
165
+ *
166
+ * The default is a starting point, not a finding: it has not been established against recorded data. In the
167
+ * back test the estimate gets monotonically worse the longer the window is, and a window of sixty days
168
+ * already scores worse than the trivial threshold rule. Treat this value as unproven until a run against
169
+ * the recorded history has produced a number.
170
+ * @default 90
171
+ */
172
+ this.historyWindowDays = 90;
173
+ /**
174
+ * How many usable historical days are needed before the weights are fitted at all. Below this number no
175
+ * band is produced at all and every consumer falls back to what needs no history.
176
+ *
177
+ * Plant wide for the same reason {@link historyWindowDays} is: how much evidence makes a fit meaningful is a
178
+ * property of the recorded data.
179
+ * @default 15
180
+ */
181
+ this.historyMinimumDays = 15;
182
+ /**
183
+ * How many standard deviations of the residuals each band edge lies away from the point estimate.
184
+ *
185
+ * Plant wide, because the band is part of the answer rather than of the judgement made on it. A consumer
186
+ * that one day wants edges of its own width reads {@link iEnergyHistoryOutlook.residualSigma} and forms
187
+ * them; it does not fit a second model.
188
+ * @default 1.0
189
+ */
190
+ this.historyBandSigma = 1.0;
56
191
  /**
57
192
  * The normal base consumption of the house in wattage
58
193
  * @default 600
@@ -73,7 +208,7 @@ class VictronDeviceSettings extends deviceSettings_1.DeviceSettings {
73
208
  this.excessEnergyTurnOffThreshold = 50;
74
209
  }
75
210
  fromPartialObject(data) {
76
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
211
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
77
212
  this.maxBatteryLoadWattage = (_a = data.maxBatteryLoadWattage) !== null && _a !== void 0 ? _a : this.maxBatteryLoadWattage;
78
213
  this.batteryReportingInterval = (_b = data.batteryReportingInterval) !== null && _b !== void 0 ? _b : this.batteryReportingInterval;
79
214
  this.hasBattery = (_c = data.hasBattery) !== null && _c !== void 0 ? _c : this.hasBattery;
@@ -86,10 +221,20 @@ class VictronDeviceSettings extends deviceSettings_1.DeviceSettings {
86
221
  (_h = data.minimumTransientTimeAcBatteryLevel) !== null && _h !== void 0 ? _h : this.minimumTransientTimeAcBatteryLevel;
87
222
  this.minimumDayTimeAcBatteryLevel = (_j = data.minimumDayTimeAcBatteryLevel) !== null && _j !== void 0 ? _j : this.minimumDayTimeAcBatteryLevel;
88
223
  this.batteryCapacityWattage = (_k = data.batteryCapacityWattage) !== null && _k !== void 0 ? _k : this.batteryCapacityWattage;
89
- this.normalBaseConsumptionWattage = (_l = data.normalBaseConsumptionWattage) !== null && _l !== void 0 ? _l : this.normalBaseConsumptionWattage;
90
- this.maximumBatteryDischargeWattage = (_m = data.maximumBatteryDischargeWattage) !== null && _m !== void 0 ? _m : this.maximumBatteryDischargeWattage;
91
- this.excessEnergyTurnOnThreshold = (_o = data.excessEnergyTurnOnThreshold) !== null && _o !== void 0 ? _o : this.excessEnergyTurnOnThreshold;
92
- this.excessEnergyTurnOffThreshold = (_p = data.excessEnergyTurnOffThreshold) !== null && _p !== void 0 ? _p : this.excessEnergyTurnOffThreshold;
224
+ this.historyMinimumDayCoverage = acceptedShare('historyMinimumDayCoverage', data.historyMinimumDayCoverage, this.historyMinimumDayCoverage);
225
+ this.historyConsumptionQuantile = acceptedShare('historyConsumptionQuantile', data.historyConsumptionQuantile, this.historyConsumptionQuantile);
226
+ this.historyMinimumConsumptionDays = (_l = data.historyMinimumConsumptionDays) !== null && _l !== void 0 ? _l : this.historyMinimumConsumptionDays;
227
+ this.minimumMorningSocReserve = (_m = data.minimumMorningSocReserve) !== null && _m !== void 0 ? _m : this.minimumMorningSocReserve;
228
+ this.noSunThresholdHours = (_o = data.noSunThresholdHours) !== null && _o !== void 0 ? _o : this.noSunThresholdHours;
229
+ this.historyWindowDays = (_p = data.historyWindowDays) !== null && _p !== void 0 ? _p : this.historyWindowDays;
230
+ this.historyMinimumDays = (_q = data.historyMinimumDays) !== null && _q !== void 0 ? _q : this.historyMinimumDays;
231
+ this.historyBandSigma = (_r = data.historyBandSigma) !== null && _r !== void 0 ? _r : this.historyBandSigma;
232
+ this.normalBaseConsumptionWattage = (_s = data.normalBaseConsumptionWattage) !== null && _s !== void 0 ? _s : this.normalBaseConsumptionWattage;
233
+ this.maximumBatteryDischargeWattage = (_t = data.maximumBatteryDischargeWattage) !== null && _t !== void 0 ? _t : this.maximumBatteryDischargeWattage;
234
+ this.excessEnergyTurnOnThreshold = (_u = data.excessEnergyTurnOnThreshold) !== null && _u !== void 0 ? _u : this.excessEnergyTurnOnThreshold;
235
+ this.excessEnergyTurnOffThreshold = (_v = data.excessEnergyTurnOffThreshold) !== null && _v !== void 0 ? _v : this.excessEnergyTurnOffThreshold;
236
+ // After both are taken over, because the two only contradict each other as a pair.
237
+ reportImpossibleWindow(this.historyWindowDays, this.historyMinimumDays);
93
238
  super.fromPartialObject(data);
94
239
  }
95
240
  toJSON() {