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 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.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 = String(t?.ComfortEndTime || '');
627
- const boostEnd = String(t?.BoostEndTime || '');
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).toISOString();
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 d.toISOString();
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.thermostatComfortEnd[thermostatId] || this._nowPlusMinutesIso(120);
845
- const boostEndTime = this.thermostatBoostEnd[thermostatId] || this._nowPlusMinutesIso(60);
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
- const tempC = Number(state.val);
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
- const tempC = Number(state.val);
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
- const mode = Number(state.val);
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
- const tempC = Number(state.val);
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.schlueter-thermostat",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "Floor heating controlled with Ditra Heat Thermostat",
5
5
  "author": {
6
6
  "name": "patricknitsch",