iobroker.schlueter-thermostat 0.2.2 → 0.2.4
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.
- package/README.md +8 -0
- package/io-package.json +27 -1
- package/main.js +68 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -222,6 +222,14 @@ Enable **debug log level** to see cloud communication.
|
|
|
222
222
|
Placeholder for the next version (at the beginning of the line):
|
|
223
223
|
### **WORK IN PROGRESS**
|
|
224
224
|
-->
|
|
225
|
+
### 0.2.4 (2026-01-28)
|
|
226
|
+
|
|
227
|
+
- (patricknitsch) Change Format of Times
|
|
228
|
+
|
|
229
|
+
### 0.2.3 (2026-01-28)
|
|
230
|
+
|
|
231
|
+
- (patricknitsch) Catch wrong values for Temperature and Regulation Mode
|
|
232
|
+
|
|
225
233
|
### 0.2.2 (2026-01-28)
|
|
226
234
|
|
|
227
235
|
- (patricknitsch) Update setStates for ComfortMode
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "schlueter-thermostat",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.4",
|
|
5
5
|
"news": {
|
|
6
|
+
"0.2.4": {
|
|
7
|
+
"en": "Change Format of Times",
|
|
8
|
+
"de": "Format der Zeiten ändern",
|
|
9
|
+
"ru": "Изменение формата времени",
|
|
10
|
+
"pt": "Mudar o Formato dos Tempos",
|
|
11
|
+
"nl": "Formaat van tijden wijzigen",
|
|
12
|
+
"fr": "Modification du format des temps",
|
|
13
|
+
"it": "Cambia il formato dei tempi",
|
|
14
|
+
"es": "Formato de cambio de tiempos",
|
|
15
|
+
"pl": "Zmień format Times",
|
|
16
|
+
"uk": "Змінення форматів часу",
|
|
17
|
+
"zh-cn": "更改时间格式"
|
|
18
|
+
},
|
|
19
|
+
"0.2.3": {
|
|
20
|
+
"en": "Catch wrong values for Temperature and Regulation Mode",
|
|
21
|
+
"de": "Falsche Werte für Temperatur und Regelungsmodus einfangen",
|
|
22
|
+
"ru": "Улавливать неправильные значения температуры и режима регулирования",
|
|
23
|
+
"pt": "Valores errados de captura para a temperatura e o modo de regulação",
|
|
24
|
+
"nl": "Verkeerde vangwaarden voor temperatuur- en regelmodus",
|
|
25
|
+
"fr": "Capturer des valeurs erronées en mode température et régulation",
|
|
26
|
+
"it": "Cattura valori errati per la modalità Temperatura e Regolamento",
|
|
27
|
+
"es": "Obtener valores incorrectos para el modo de temperatura y regulación",
|
|
28
|
+
"pl": "Nieprawidłowe wartości połowu dla trybu temperatury i regulacji",
|
|
29
|
+
"uk": "Випадкові значення для режиму температури та регулювання",
|
|
30
|
+
"zh-cn": "获取温度和调节模式的错误值"
|
|
31
|
+
},
|
|
6
32
|
"0.2.2": {
|
|
7
33
|
"en": "Update setStates for ComfortMode\nMore Debugging",
|
|
8
34
|
"de": "Update setStates für ComfortMode\nMehr Debugging",
|
package/main.js
CHANGED
|
@@ -466,6 +466,8 @@ class SchlueterThermostat extends utils.Adapter {
|
|
|
466
466
|
unit: '°C',
|
|
467
467
|
read: true,
|
|
468
468
|
write: true,
|
|
469
|
+
min: 12,
|
|
470
|
+
max: 35,
|
|
469
471
|
});
|
|
470
472
|
await ensureState(`${devId}.setpoint.comfortSet`, {
|
|
471
473
|
name: 'Set comfort setpoint',
|
|
@@ -474,14 +476,17 @@ class SchlueterThermostat extends utils.Adapter {
|
|
|
474
476
|
unit: '°C',
|
|
475
477
|
read: true,
|
|
476
478
|
write: true,
|
|
479
|
+
min: 12,
|
|
480
|
+
max: 35,
|
|
477
481
|
});
|
|
478
482
|
await ensureState(`${devId}.regulationModeSet`, {
|
|
479
483
|
name: 'Set regulation mode',
|
|
480
484
|
type: 'number',
|
|
481
485
|
role: 'level',
|
|
482
486
|
read: true,
|
|
483
|
-
max: 9,
|
|
484
487
|
write: true,
|
|
488
|
+
min: 0,
|
|
489
|
+
max: 9,
|
|
485
490
|
});
|
|
486
491
|
|
|
487
492
|
await this.safeSetObjectNotExists(`${devId}.endTime`, {
|
|
@@ -580,6 +585,8 @@ class SchlueterThermostat extends utils.Adapter {
|
|
|
580
585
|
unit: '°C',
|
|
581
586
|
read: true,
|
|
582
587
|
write: true,
|
|
588
|
+
min: 12,
|
|
589
|
+
max: 35,
|
|
583
590
|
});
|
|
584
591
|
|
|
585
592
|
await this.safeSetObjectNotExists(`${devId}.schedule`, {
|
|
@@ -623,8 +630,8 @@ class SchlueterThermostat extends utils.Adapter {
|
|
|
623
630
|
this.safeSetState(`${devId}.regulationMode`, { val: mode, ack: true });
|
|
624
631
|
this.safeSetState(`${devId}.regulationModeSet`, { val: mode, ack: true });
|
|
625
632
|
|
|
626
|
-
const comfortEnd =
|
|
627
|
-
const boostEnd =
|
|
633
|
+
const comfortEnd = this._formatIsoNoMsNoZ(t?.ComfortEndTime || '');
|
|
634
|
+
const boostEnd = this._formatIsoNoMsNoZ(t?.BoostEndTime || '');
|
|
628
635
|
if (comfortEnd) {
|
|
629
636
|
this.safeSetState(`${devId}.endTime.comfort`, comfortEnd, true);
|
|
630
637
|
this.safeSetState(`${devId}.endTime.comfortSet`, comfortEnd, true);
|
|
@@ -773,7 +780,7 @@ class SchlueterThermostat extends utils.Adapter {
|
|
|
773
780
|
// ============================================================================
|
|
774
781
|
|
|
775
782
|
_nowPlusMinutesIso(minutes) {
|
|
776
|
-
return new Date(Date.now() + minutes * 60 * 1000)
|
|
783
|
+
return this._formatIsoNoMsNoZ(new Date(Date.now() + minutes * 60 * 1000));
|
|
777
784
|
}
|
|
778
785
|
|
|
779
786
|
_parseIsoOrMinutes(value, defaultMinutes) {
|
|
@@ -787,14 +794,41 @@ class SchlueterThermostat extends utils.Adapter {
|
|
|
787
794
|
return this._nowPlusMinutesIso(asNum);
|
|
788
795
|
}
|
|
789
796
|
|
|
797
|
+
// ISO-like string
|
|
790
798
|
const d = new Date(v);
|
|
791
799
|
if (!Number.isNaN(d.getTime())) {
|
|
792
|
-
return
|
|
800
|
+
return this._formatIsoNoMsNoZ(d); // NEW
|
|
793
801
|
}
|
|
794
802
|
|
|
795
803
|
return this._nowPlusMinutesIso(defaultMinutes);
|
|
796
804
|
}
|
|
797
805
|
|
|
806
|
+
_formatIsoNoMsNoZ(value) {
|
|
807
|
+
// Accept Date or string, return "YYYY-MM-DDTHH:mm:ss"
|
|
808
|
+
if (!value) {
|
|
809
|
+
return '';
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
let d;
|
|
813
|
+
if (value instanceof Date) {
|
|
814
|
+
d = value;
|
|
815
|
+
} else {
|
|
816
|
+
d = new Date(String(value));
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
if (Number.isNaN(d.getTime())) {
|
|
820
|
+
// If it already looks like "YYYY-MM-DDTHH:mm:ss(.sss)?Z?" just strip
|
|
821
|
+
return String(value)
|
|
822
|
+
.trim()
|
|
823
|
+
.replace(/\.\d{3}Z$/, '')
|
|
824
|
+
.replace(/Z$/, '')
|
|
825
|
+
.replace(/\.\d{3}$/, '');
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
// toISOString() => "YYYY-MM-DDTHH:mm:ss.sssZ"
|
|
829
|
+
return d.toISOString().replace(/\.\d{3}Z$/, '');
|
|
830
|
+
}
|
|
831
|
+
|
|
798
832
|
async _getSerialFromObject(groupId, thermostatId) {
|
|
799
833
|
const oid = `groups.${safeId(groupId)}.thermostats.${safeId(thermostatId)}`;
|
|
800
834
|
const obj = await this.safeGetObject(oid);
|
|
@@ -841,8 +875,13 @@ class SchlueterThermostat extends utils.Adapter {
|
|
|
841
875
|
|
|
842
876
|
const thermostatName = this.thermostatNameCache[thermostatId] || `Thermostat ${thermostatId}`;
|
|
843
877
|
|
|
844
|
-
const comfortEndTime = this.
|
|
845
|
-
|
|
878
|
+
const comfortEndTime = this._formatIsoNoMsNoZ(
|
|
879
|
+
this.thermostatComfortEnd[thermostatId] || this._nowPlusMinutesIso(120),
|
|
880
|
+
);
|
|
881
|
+
|
|
882
|
+
const boostEndTime = this._formatIsoNoMsNoZ(
|
|
883
|
+
this.thermostatBoostEnd[thermostatId] || this._nowPlusMinutesIso(60),
|
|
884
|
+
);
|
|
846
885
|
|
|
847
886
|
const baseUpdate = {
|
|
848
887
|
ThermostatName: thermostatName,
|
|
@@ -857,10 +896,15 @@ class SchlueterThermostat extends utils.Adapter {
|
|
|
857
896
|
};
|
|
858
897
|
|
|
859
898
|
const devPrefix = `groups.${safeId(groupId)}.thermostats.${safeId(thermostatId)}`;
|
|
899
|
+
const clamp = (n, min, max) => Math.min(max, Math.max(min, n));
|
|
860
900
|
|
|
861
901
|
try {
|
|
862
902
|
if (sub === 'setpoint.manualSet') {
|
|
863
|
-
|
|
903
|
+
let tempC = Number(state.val);
|
|
904
|
+
if (!Number.isFinite(tempC)) {
|
|
905
|
+
throw new Error('Invalid temperature');
|
|
906
|
+
}
|
|
907
|
+
tempC = clamp(tempC, 12, 35);
|
|
864
908
|
this.log.debug(`Write: UpdateThermostat serial=${serial} (ManualModeSetpoint=${tempC}C)`);
|
|
865
909
|
await client.updateThermostat(serial, {
|
|
866
910
|
...baseUpdate,
|
|
@@ -869,7 +913,11 @@ class SchlueterThermostat extends utils.Adapter {
|
|
|
869
913
|
});
|
|
870
914
|
this.safeSetState(id, { val: tempC, ack: true });
|
|
871
915
|
} else if (sub === 'setpoint.comfortSet') {
|
|
872
|
-
|
|
916
|
+
let tempC = Number(state.val);
|
|
917
|
+
if (!Number.isFinite(tempC)) {
|
|
918
|
+
throw new Error('Invalid temperature');
|
|
919
|
+
}
|
|
920
|
+
tempC = clamp(tempC, 12, 35);
|
|
873
921
|
const comfortToSend = this._nowPlusMinutesIso(180);
|
|
874
922
|
this.log.debug(
|
|
875
923
|
`Write: UpdateThermostat serial=${serial} (ComfortSetpoint=${tempC}C) (ComfortEndTime=${comfortToSend})`,
|
|
@@ -884,8 +932,12 @@ class SchlueterThermostat extends utils.Adapter {
|
|
|
884
932
|
this.safeSetState(`${devPrefix}.endTime.comfortSet`, comfortToSend, true);
|
|
885
933
|
this.safeSetState(id, { val: tempC, ack: true });
|
|
886
934
|
} else if (sub === 'regulationModeSet') {
|
|
887
|
-
|
|
888
|
-
|
|
935
|
+
let mode = Number(state.val);
|
|
936
|
+
if (!Number.isFinite(mode)) {
|
|
937
|
+
throw new Error('Invalid regulation mode');
|
|
938
|
+
}
|
|
939
|
+
mode = Math.trunc(mode);
|
|
940
|
+
mode = clamp(mode, 0, 9);
|
|
889
941
|
if (mode === 8) {
|
|
890
942
|
const boostToSend = this._nowPlusMinutesIso(180);
|
|
891
943
|
this.log.debug(`Write: Boost mode=8 serial=${serial} BoostEndTime=${boostToSend}`);
|
|
@@ -958,7 +1010,11 @@ class SchlueterThermostat extends utils.Adapter {
|
|
|
958
1010
|
this.safeSetState(id, { val: endIso, ack: true });
|
|
959
1011
|
this.safeSetState(`${devPrefix}.vacation.end`, { val: endIso, ack: true });
|
|
960
1012
|
} else if (sub === 'vacation.temperatureSet') {
|
|
961
|
-
|
|
1013
|
+
let tempC = Number(state.val);
|
|
1014
|
+
if (!Number.isFinite(tempC)) {
|
|
1015
|
+
throw new Error('Invalid temperature');
|
|
1016
|
+
}
|
|
1017
|
+
tempC = clamp(tempC, 12, 35); // NEW
|
|
962
1018
|
this.log.debug(`Write: UpdateThermostat serial=${serial} (VacationTemperature=${tempC}C)`);
|
|
963
1019
|
|
|
964
1020
|
const tempNum = cToNum(tempC);
|