iobroker.poolcontrol 1.2.0 → 1.2.1

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 (66) hide show
  1. package/README.md +285 -292
  2. package/admin/i18n/de/translations.json +158 -4
  3. package/admin/i18n/en/translations.json +161 -3
  4. package/admin/i18n/es/translations.json +158 -4
  5. package/admin/i18n/fr/translations.json +158 -4
  6. package/admin/i18n/it/translations.json +158 -4
  7. package/admin/i18n/nl/translations.json +158 -4
  8. package/admin/i18n/pl/translations.json +158 -4
  9. package/admin/i18n/pt/translations.json +158 -4
  10. package/admin/i18n/ru/translations.json +158 -4
  11. package/admin/i18n/uk/translations.json +158 -4
  12. package/admin/i18n/zh-cn/translations.json +158 -4
  13. package/admin/jsonConfig.json +180 -602
  14. package/io-package.json +107 -100
  15. package/lib/helpers/actuatorsHelper.js +6 -8
  16. package/lib/helpers/aiChemistryHelpHelper.js +7 -7
  17. package/lib/helpers/aiForecastHelper.js +21 -21
  18. package/lib/helpers/aiHelper.js +53 -63
  19. package/lib/helpers/consumptionHelper.js +23 -25
  20. package/lib/helpers/controlHelper.js +24 -24
  21. package/lib/helpers/controlHelper2.js +17 -17
  22. package/lib/helpers/debugLogHelper.js +12 -14
  23. package/lib/helpers/frostHelper.js +6 -6
  24. package/lib/helpers/heatHelper.js +14 -14
  25. package/lib/helpers/infoHelper.js +2 -2
  26. package/lib/helpers/migrationHelper.js +16 -16
  27. package/lib/helpers/photovoltaicHelper.js +28 -28
  28. package/lib/helpers/pumpHelper.js +16 -18
  29. package/lib/helpers/pumpHelper2.js +8 -10
  30. package/lib/helpers/pumpHelper3.js +9 -9
  31. package/lib/helpers/pumpHelper4.js +9 -9
  32. package/lib/helpers/pumpSpeedHelper.js +6 -6
  33. package/lib/helpers/runtimeHelper.js +14 -14
  34. package/lib/helpers/solarHelper.js +9 -9
  35. package/lib/helpers/speechHelper.js +13 -15
  36. package/lib/helpers/speechTextHelper.js +13 -13
  37. package/lib/helpers/statisticsHelper.js +9 -9
  38. package/lib/helpers/statisticsHelperMonth.js +15 -15
  39. package/lib/helpers/statisticsHelperWeek.js +11 -11
  40. package/lib/helpers/statusHelper.js +9 -9
  41. package/lib/helpers/temperatureHelper.js +9 -11
  42. package/lib/helpers/timeHelper.js +7 -9
  43. package/lib/stateDefinitions/actuatorsStates.js +19 -19
  44. package/lib/stateDefinitions/aiChemistryHelpStates.js +59 -28
  45. package/lib/stateDefinitions/aiStates.js +119 -31
  46. package/lib/stateDefinitions/consumptionStates.js +20 -14
  47. package/lib/stateDefinitions/controlStates.js +90 -37
  48. package/lib/stateDefinitions/debugLogStates.js +28 -13
  49. package/lib/stateDefinitions/generalStates.js +4 -4
  50. package/lib/stateDefinitions/heatStates.js +21 -21
  51. package/lib/stateDefinitions/infoStates.js +11 -5
  52. package/lib/stateDefinitions/photovoltaicStates.js +52 -24
  53. package/lib/stateDefinitions/pumpSpeedStates.js +11 -11
  54. package/lib/stateDefinitions/pumpStates.js +24 -15
  55. package/lib/stateDefinitions/pumpStates2.js +22 -10
  56. package/lib/stateDefinitions/pumpStates3.js +63 -24
  57. package/lib/stateDefinitions/pumpStates4.js +62 -32
  58. package/lib/stateDefinitions/runtimeStates.js +10 -10
  59. package/lib/stateDefinitions/solarStates.js +9 -9
  60. package/lib/stateDefinitions/speechStates.js +24 -21
  61. package/lib/stateDefinitions/statisticsStates.js +107 -29
  62. package/lib/stateDefinitions/statusStates.js +14 -12
  63. package/lib/stateDefinitions/temperatureStates.js +18 -12
  64. package/lib/stateDefinitions/timeStates.js +5 -5
  65. package/main.js +38 -0
  66. package/package.json +7 -8
@@ -20,43 +20,67 @@
20
20
  * @param {ioBroker.Adapter} adapter - Instanz des ioBroker-Adapters
21
21
  */
22
22
  async function createStatisticsStates(adapter) {
23
- adapter.log.debug('statisticsStates: Initialisierung der Temperaturstatistiken gestartet.');
23
+ adapter.log.debug('statisticsStates: Temperature statistics initialization started.');
24
24
 
25
25
  // Oberstruktur
26
26
  await adapter.setObjectNotExistsAsync('analytics', {
27
27
  type: 'channel',
28
- common: { name: 'Analysen & Auswertungen (Statistik, Historie, Berichte)' },
28
+ common: {
29
+ name: {
30
+ de: 'Analysen & Auswertungen (Statistik, Historie, Berichte)',
31
+ en: 'Analytics & insights (statistics, history, reports)',
32
+ },
33
+ },
29
34
  native: {},
30
35
  });
31
36
 
32
37
  await adapter.setObjectNotExistsAsync('analytics.statistics', {
33
38
  type: 'channel',
34
- common: { name: 'Statistische Auswertungen' },
39
+ common: {
40
+ name: {
41
+ de: 'Statistische Auswertungen',
42
+ en: 'Statistical evaluations',
43
+ },
44
+ },
35
45
  native: {},
36
46
  });
37
47
 
38
48
  await adapter.setObjectNotExistsAsync('analytics.statistics.temperature', {
39
49
  type: 'channel',
40
- common: { name: 'Temperaturstatistik' },
50
+ common: {
51
+ name: {
52
+ de: 'Temperaturstatistik',
53
+ en: 'Temperature statistics',
54
+ },
55
+ },
41
56
  native: {},
42
57
  });
43
58
 
44
59
  // -------------------------------------------------------------
45
60
  // 🔹 TAGESSTATISTIK
46
61
  // -------------------------------------------------------------
47
- await _createTemperatureStatsGroup(adapter, 'today', 'Tagesstatistik (Temperaturen)');
62
+ await _createTemperatureStatsGroup(adapter, 'today', {
63
+ de: 'Tagesstatistik (Temperaturen)',
64
+ en: 'Daily statistics (temperatures)',
65
+ });
48
66
 
49
67
  // -------------------------------------------------------------
50
68
  // 🔹 WOCHENSTATISTIK
51
69
  // -------------------------------------------------------------
52
- await _createTemperatureStatsGroup(adapter, 'week', 'Wochenstatistik (Temperaturen)');
70
+ await _createTemperatureStatsGroup(adapter, 'week', {
71
+ de: 'Wochenstatistik (Temperaturen)',
72
+ en: 'Weekly statistics (temperatures)',
73
+ });
53
74
 
54
75
  // -------------------------------------------------------------
55
76
  // 🔹 MONATSSTATISTIK (NEU)
56
77
  // -------------------------------------------------------------
57
- await _createTemperatureStatsGroup(adapter, 'month', 'Monatsstatistik (Temperaturen)');
78
+ await _createTemperatureStatsGroup(adapter, 'month', {
79
+ de: 'Monatsstatistik (Temperaturen)',
80
+ en: 'Monthly statistics (temperatures)',
81
+ });
58
82
 
59
- adapter.log.debug('statisticsStates: Tages-, Wochen- und Monatsstatistik (Temperatur) erfolgreich angelegt.');
83
+ adapter.log.debug('statisticsStates: Daily, weekly and monthly temperature statistics created successfully.');
60
84
  }
61
85
 
62
86
  /**
@@ -64,7 +88,7 @@ async function createStatisticsStates(adapter) {
64
88
  *
65
89
  * @param {ioBroker.Adapter} adapter - Aktive ioBroker-Adapterinstanz
66
90
  * @param {string} periodId - z. B. "today", "week" oder "month"
67
- * @param {string} displayName - Anzeigename im Objektbaum
91
+ * @param {{de: string, en: string}} displayName - Anzeigename im Objektbaum (DE/EN)
68
92
  */
69
93
  async function _createTemperatureStatsGroup(adapter, periodId, displayName) {
70
94
  const basePathRoot = `analytics.statistics.temperature.${periodId}`;
@@ -76,39 +100,82 @@ async function _createTemperatureStatsGroup(adapter, periodId, displayName) {
76
100
 
77
101
  // Definierte Sensoren
78
102
  const sensors = [
79
- { id: 'outside', name: 'Außentemperatur' },
80
- { id: 'ground', name: 'Bodentemperatur' },
81
- { id: 'surface', name: 'Pooloberfläche' },
82
- { id: 'flow', name: 'Vorlauf' },
83
- { id: 'return', name: 'Rücklauf' },
84
- { id: 'collector', name: 'Kollektor (Solar)' },
103
+ { id: 'outside', name: { de: 'Außentemperatur', en: 'Outside temperature' } },
104
+ { id: 'ground', name: { de: 'Bodentemperatur', en: 'Ground temperature' } },
105
+ { id: 'surface', name: { de: 'Pooloberfläche', en: 'Pool surface' } },
106
+ { id: 'flow', name: { de: 'Vorlauf', en: 'Flow' } },
107
+ { id: 'return', name: { de: 'Rücklauf', en: 'Return' } },
108
+ { id: 'collector', name: { de: 'Kollektor (Solar)', en: 'Collector (solar)' } },
85
109
  ];
86
110
 
87
111
  for (const sensor of sensors) {
88
112
  const basePath = `${basePathRoot}.${sensor.id}`;
89
113
  await adapter.setObjectNotExistsAsync(basePath, {
90
114
  type: 'channel',
91
- common: { name: `${sensor.name} (${displayName})` },
115
+ common: {
116
+ name: {
117
+ de: `${sensor.name.de} (${displayName.de})`,
118
+ en: `${sensor.name.en} (${displayName.en})`,
119
+ },
120
+ },
92
121
  native: {},
93
122
  });
94
123
 
95
124
  const stateDefs = [
96
- { id: 'temp_min', name: 'Niedrigste Temperatur', type: 'number', role: 'value.temperature', unit: '°C' },
97
- { id: 'temp_max', name: 'Höchste Temperatur', type: 'number', role: 'value.temperature', unit: '°C' },
98
- { id: 'temp_min_time', name: 'Zeitpunkt Minimum', type: 'string', role: 'value.time' },
99
- { id: 'temp_max_time', name: 'Zeitpunkt Maximum', type: 'string', role: 'value.time' },
100
- { id: 'temp_avg', name: 'Durchschnittstemperatur', type: 'number', role: 'value.temperature', unit: '°C' },
101
- { id: 'data_points_count', name: 'Anzahl Messwerte', type: 'number', role: 'value' },
102
- { id: 'last_update', name: 'Letzte Aktualisierung', type: 'string', role: 'value.time' },
125
+ {
126
+ id: 'temp_min',
127
+ name: { de: 'Niedrigste Temperatur', en: 'Lowest temperature' },
128
+ type: 'number',
129
+ role: 'value.temperature',
130
+ unit: '°C',
131
+ },
132
+ {
133
+ id: 'temp_max',
134
+ name: { de: 'Höchste Temperatur', en: 'Highest temperature' },
135
+ type: 'number',
136
+ role: 'value.temperature',
137
+ unit: '°C',
138
+ },
139
+ {
140
+ id: 'temp_min_time',
141
+ name: { de: 'Zeitpunkt Minimum', en: 'Time of minimum' },
142
+ type: 'string',
143
+ role: 'value.time',
144
+ },
145
+ {
146
+ id: 'temp_max_time',
147
+ name: { de: 'Zeitpunkt Maximum', en: 'Time of maximum' },
148
+ type: 'string',
149
+ role: 'value.time',
150
+ },
151
+ {
152
+ id: 'temp_avg',
153
+ name: { de: 'Durchschnittstemperatur', en: 'Average temperature' },
154
+ type: 'number',
155
+ role: 'value.temperature',
156
+ unit: '°C',
157
+ },
158
+ {
159
+ id: 'data_points_count',
160
+ name: { de: 'Anzahl Messwerte', en: 'Number of values' },
161
+ type: 'number',
162
+ role: 'value',
163
+ },
164
+ {
165
+ id: 'last_update',
166
+ name: { de: 'Letzte Aktualisierung', en: 'Last update' },
167
+ type: 'string',
168
+ role: 'value.time',
169
+ },
103
170
  {
104
171
  id: 'summary_json',
105
- name: `${displayName} (JSON)`,
172
+ name: { de: `${displayName.de} (JSON)`, en: `${displayName.en} (JSON)` },
106
173
  type: 'string',
107
174
  role: 'json',
108
175
  },
109
176
  {
110
177
  id: 'summary_html',
111
- name: `${displayName} (HTML)`,
178
+ name: { de: `${displayName.de} (HTML)`, en: `${displayName.en} (HTML)` },
112
179
  type: 'string',
113
180
  role: 'html',
114
181
  },
@@ -118,7 +185,7 @@ async function _createTemperatureStatsGroup(adapter, periodId, displayName) {
118
185
  if (periodId === 'today') {
119
186
  stateDefs.push({
120
187
  id: 'reset_today',
121
- name: 'Tagesstatistik zurücksetzen',
188
+ name: { de: 'Tagesstatistik zurücksetzen', en: 'Reset daily statistics' },
122
189
  type: 'boolean',
123
190
  role: 'button',
124
191
  });
@@ -146,19 +213,30 @@ async function _createTemperatureStatsGroup(adapter, periodId, displayName) {
146
213
  const outputBase = `${basePathRoot}.outputs`;
147
214
  await adapter.setObjectNotExistsAsync(outputBase, {
148
215
  type: 'channel',
149
- common: { name: 'Gesamtausgaben (alle Sensoren)' },
216
+ common: {
217
+ name: {
218
+ de: 'Gesamtausgaben (alle Sensoren)',
219
+ en: 'Overall outputs (all sensors)',
220
+ },
221
+ },
150
222
  native: {},
151
223
  });
152
224
 
153
225
  const outputs = [
154
226
  {
155
227
  id: 'summary_all_json',
156
- name: `Gesamtzusammenfassung aller Sensoren (${displayName}, JSON)`,
228
+ name: {
229
+ de: `Gesamtzusammenfassung aller Sensoren (${displayName.de}, JSON)`,
230
+ en: `Overall summary of all sensors (${displayName.en}, JSON)`,
231
+ },
157
232
  role: 'json',
158
233
  },
159
234
  {
160
235
  id: 'summary_all_html',
161
- name: `Gesamtzusammenfassung aller Sensoren (${displayName}, HTML)`,
236
+ name: {
237
+ de: `Gesamtzusammenfassung aller Sensoren (${displayName.de}, HTML)`,
238
+ en: `Overall summary of all sensors (${displayName.en}, HTML)`,
239
+ },
162
240
  role: 'html',
163
241
  },
164
242
  ];
@@ -20,7 +20,9 @@ async function createStatusStates(adapter) {
20
20
  // Root-Kanal "status"
21
21
  await adapter.setObjectNotExistsAsync('status', {
22
22
  type: 'channel',
23
- common: { name: 'Statusübersicht' },
23
+ common: {
24
+ name: { de: 'Statusübersicht', en: 'Status overview' },
25
+ },
24
26
  native: {},
25
27
  });
26
28
 
@@ -28,7 +30,7 @@ async function createStatusStates(adapter) {
28
30
  await adapter.setObjectNotExistsAsync('status.summary', {
29
31
  type: 'state',
30
32
  common: {
31
- name: 'Zusammenfassung als Text',
33
+ name: { de: 'Zusammenfassung als Text', en: 'Summary as text' },
32
34
  type: 'string',
33
35
  role: 'text',
34
36
  read: true,
@@ -43,7 +45,7 @@ async function createStatusStates(adapter) {
43
45
  await adapter.setObjectNotExistsAsync('status.overview_json', {
44
46
  type: 'state',
45
47
  common: {
46
- name: 'Übersicht als JSON',
48
+ name: { de: 'Übersicht als JSON', en: 'Overview as JSON' },
47
49
  type: 'string',
48
50
  role: 'json',
49
51
  read: true,
@@ -57,7 +59,7 @@ async function createStatusStates(adapter) {
57
59
  await adapter.setObjectNotExistsAsync('status.last_summary_update', {
58
60
  type: 'state',
59
61
  common: {
60
- name: 'Letzte Aktualisierung der Zusammenfassung',
62
+ name: { de: 'Letzte Aktualisierung der Zusammenfassung', en: 'Last summary update' },
61
63
  type: 'string',
62
64
  role: 'date',
63
65
  read: true,
@@ -71,7 +73,7 @@ async function createStatusStates(adapter) {
71
73
  await adapter.setObjectNotExistsAsync('status.pump_last_start', {
72
74
  type: 'state',
73
75
  common: {
74
- name: 'Letzter Pumpenstart',
76
+ name: { de: 'Letzter Pumpenstart', en: 'Last pump start' },
75
77
  type: 'string',
76
78
  role: 'date',
77
79
  read: true,
@@ -86,7 +88,7 @@ async function createStatusStates(adapter) {
86
88
  await adapter.setObjectNotExistsAsync('status.pump_last_stop', {
87
89
  type: 'state',
88
90
  common: {
89
- name: 'Letztes Pumpenende',
91
+ name: { de: 'Letztes Pumpenende', en: 'Last pump stop' },
90
92
  type: 'string',
91
93
  role: 'date',
92
94
  read: true,
@@ -101,7 +103,7 @@ async function createStatusStates(adapter) {
101
103
  await adapter.setObjectNotExistsAsync('status.pump_was_on_today', {
102
104
  type: 'state',
103
105
  common: {
104
- name: 'Pumpe war heute eingeschaltet',
106
+ name: { de: 'Pumpe war heute eingeschaltet', en: 'Pump was on today' },
105
107
  type: 'boolean',
106
108
  role: 'indicator',
107
109
  read: true,
@@ -116,7 +118,7 @@ async function createStatusStates(adapter) {
116
118
  await adapter.setObjectNotExistsAsync('status.pump_today_count', {
117
119
  type: 'state',
118
120
  common: {
119
- name: 'Pumpenstarts heute',
121
+ name: { de: 'Pumpenstarts heute', en: 'Pump starts today' },
120
122
  type: 'number',
121
123
  role: 'value',
122
124
  read: true,
@@ -131,7 +133,7 @@ async function createStatusStates(adapter) {
131
133
  await adapter.setObjectNotExistsAsync('status.system_ok', {
132
134
  type: 'state',
133
135
  common: {
134
- name: 'System OK',
136
+ name: { de: 'System OK', en: 'System OK' },
135
137
  type: 'boolean',
136
138
  role: 'indicator',
137
139
  read: true,
@@ -145,7 +147,7 @@ async function createStatusStates(adapter) {
145
147
  await adapter.setObjectNotExistsAsync('status.system_warning', {
146
148
  type: 'state',
147
149
  common: {
148
- name: 'System-Warnung aktiv',
150
+ name: { de: 'System-Warnung aktiv', en: 'System warning active' },
149
151
  type: 'boolean',
150
152
  role: 'indicator',
151
153
  read: true,
@@ -159,7 +161,7 @@ async function createStatusStates(adapter) {
159
161
  await adapter.setObjectNotExistsAsync('status.system_warning_text', {
160
162
  type: 'state',
161
163
  common: {
162
- name: 'Beschreibung der Systemwarnung',
164
+ name: { de: 'Beschreibung der Systemwarnung', en: 'System warning description' },
163
165
  type: 'string',
164
166
  role: 'text',
165
167
  read: true,
@@ -173,7 +175,7 @@ async function createStatusStates(adapter) {
173
175
  await adapter.setObjectNotExistsAsync('status.season_active', {
174
176
  type: 'state',
175
177
  common: {
176
- name: 'Poolsaison aktiv',
178
+ name: { de: 'Poolsaison aktiv', en: 'Pool season active' },
177
179
  type: 'boolean',
178
180
  role: 'switch',
179
181
  read: true,
@@ -24,14 +24,18 @@ async function createTemperatureStates(adapter) {
24
24
  // Root-Kanal (robustheitshalber explizit anlegen)
25
25
  await adapter.setObjectNotExistsAsync('temperature', {
26
26
  type: 'channel',
27
- common: { name: 'Temperaturverwaltung' },
27
+ common: {
28
+ name: { de: 'Temperaturverwaltung', en: 'Temperature management' },
29
+ },
28
30
  native: {},
29
31
  });
30
32
 
31
33
  // Kanal für Deltas
32
34
  await adapter.setObjectNotExistsAsync('temperature.delta', {
33
35
  type: 'channel',
34
- common: { name: 'Temperatur-Differenzen' },
36
+ common: {
37
+ name: { de: 'Temperatur-Differenzen', en: 'Temperature deltas' },
38
+ },
35
39
  native: {},
36
40
  });
37
41
 
@@ -41,7 +45,7 @@ async function createTemperatureStates(adapter) {
41
45
  await adapter.setObjectNotExistsAsync(`temperature.${sensorKey}_temp_active`, {
42
46
  type: 'state',
43
47
  common: {
44
- name: `Sensor ${label} verwenden`,
48
+ name: { de: `Sensor ${label} verwenden`, en: `Use sensor ${label}` },
45
49
  type: 'boolean',
46
50
  role: 'switch',
47
51
  read: true,
@@ -57,7 +61,7 @@ async function createTemperatureStates(adapter) {
57
61
  await adapter.setObjectNotExistsAsync(`temperature.${sensorKey}_temp_sensor`, {
58
62
  type: 'state',
59
63
  common: {
60
- name: `Objekt-ID Sensor ${label}`,
64
+ name: { de: `Objekt-ID Sensor ${label}`, en: `Object ID sensor ${label}` },
61
65
  type: 'string',
62
66
  role: 'text',
63
67
  read: true,
@@ -73,14 +77,16 @@ async function createTemperatureStates(adapter) {
73
77
  // 2) Messkanal + Werte-States
74
78
  await adapter.setObjectNotExistsAsync(`temperature.${sensorKey}`, {
75
79
  type: 'channel',
76
- common: { name: `Sensor ${label}` },
80
+ common: {
81
+ name: { de: `Sensor ${label}`, en: `Sensor ${label}` },
82
+ },
77
83
  native: {},
78
84
  });
79
85
 
80
86
  await adapter.setObjectNotExistsAsync(`temperature.${sensorKey}.current`, {
81
87
  type: 'state',
82
88
  common: {
83
- name: `Aktueller Wert Sensor ${label}`,
89
+ name: { de: `Aktueller Wert Sensor ${label}`, en: `Current value sensor ${label}` },
84
90
  type: 'number',
85
91
  role: 'value.temperature',
86
92
  unit: '°C',
@@ -93,7 +99,7 @@ async function createTemperatureStates(adapter) {
93
99
  await adapter.setObjectNotExistsAsync(`temperature.${sensorKey}.min_today`, {
94
100
  type: 'state',
95
101
  common: {
96
- name: `Tagesminimum Sensor ${label}`,
102
+ name: { de: `Tagesminimum Sensor ${label}`, en: `Daily minimum sensor ${label}` },
97
103
  type: 'number',
98
104
  role: 'value.temperature',
99
105
  unit: '°C',
@@ -107,7 +113,7 @@ async function createTemperatureStates(adapter) {
107
113
  await adapter.setObjectNotExistsAsync(`temperature.${sensorKey}.max_today`, {
108
114
  type: 'state',
109
115
  common: {
110
- name: `Tagesmaximum Sensor ${label}`,
116
+ name: { de: `Tagesmaximum Sensor ${label}`, en: `Daily maximum sensor ${label}` },
111
117
  type: 'number',
112
118
  role: 'value.temperature',
113
119
  unit: '°C',
@@ -121,7 +127,7 @@ async function createTemperatureStates(adapter) {
121
127
  await adapter.setObjectNotExistsAsync(`temperature.${sensorKey}.delta_per_hour`, {
122
128
  type: 'state',
123
129
  common: {
124
- name: `Veränderung pro Stunde Sensor ${label}`,
130
+ name: { de: `Veränderung pro Stunde Sensor ${label}`, en: `Change per hour sensor ${label}` },
125
131
  type: 'number',
126
132
  role: 'value.temperature',
127
133
  unit: '°C/h',
@@ -144,7 +150,7 @@ async function createTemperatureStates(adapter) {
144
150
  await adapter.setObjectNotExistsAsync('temperature.delta.collector_outside', {
145
151
  type: 'state',
146
152
  common: {
147
- name: 'Differenz Kollektor - Luft',
153
+ name: { de: 'Differenz Kollektor - Luft', en: 'Delta collector - air' },
148
154
  type: 'number',
149
155
  role: 'value.temperature',
150
156
  unit: '°C',
@@ -157,7 +163,7 @@ async function createTemperatureStates(adapter) {
157
163
  await adapter.setObjectNotExistsAsync('temperature.delta.surface_ground', {
158
164
  type: 'state',
159
165
  common: {
160
- name: 'Differenz Oberfläche - Grund',
166
+ name: { de: 'Differenz Oberfläche - Grund', en: 'Delta surface - ground' },
161
167
  type: 'number',
162
168
  role: 'value.temperature',
163
169
  unit: '°C',
@@ -170,7 +176,7 @@ async function createTemperatureStates(adapter) {
170
176
  await adapter.setObjectNotExistsAsync('temperature.delta.flow_return', {
171
177
  type: 'state',
172
178
  common: {
173
- name: 'Differenz Vorlauf - Rücklauf',
179
+ name: { de: 'Differenz Vorlauf - Rücklauf', en: 'Delta flow - return' },
174
180
  type: 'number',
175
181
  role: 'value.temperature',
176
182
  unit: '°C',
@@ -13,7 +13,7 @@ async function createTimeStates(adapter) {
13
13
  await adapter.setObjectNotExistsAsync('timecontrol', {
14
14
  type: 'channel',
15
15
  common: {
16
- name: 'Zeitsteuerung',
16
+ name: { de: 'Zeitsteuerung', en: 'Time control' },
17
17
  },
18
18
  native: {},
19
19
  });
@@ -23,7 +23,7 @@ async function createTimeStates(adapter) {
23
23
  await adapter.setObjectNotExistsAsync(`timecontrol.${prefix}_active`, {
24
24
  type: 'state',
25
25
  common: {
26
- name: `Zeitfenster ${label} aktiv`,
26
+ name: { de: `Zeitfenster ${label} aktiv`, en: `Time window ${label} active` },
27
27
  type: 'boolean',
28
28
  role: 'switch',
29
29
  read: true,
@@ -40,7 +40,7 @@ async function createTimeStates(adapter) {
40
40
  await adapter.setObjectNotExistsAsync(`timecontrol.${prefix}_start`, {
41
41
  type: 'state',
42
42
  common: {
43
- name: `Zeitfenster ${label} Start (HH:MM)`,
43
+ name: { de: `Zeitfenster ${label} Start (HH:MM)`, en: `Time window ${label} start (HH:MM)` },
44
44
  type: 'string',
45
45
  role: 'value.time',
46
46
  read: true,
@@ -57,7 +57,7 @@ async function createTimeStates(adapter) {
57
57
  await adapter.setObjectNotExistsAsync(`timecontrol.${prefix}_end`, {
58
58
  type: 'state',
59
59
  common: {
60
- name: `Zeitfenster ${label} Ende (HH:MM)`,
60
+ name: { de: `Zeitfenster ${label} Ende (HH:MM)`, en: `Time window ${label} end (HH:MM)` },
61
61
  type: 'string',
62
62
  role: 'value.time',
63
63
  read: true,
@@ -85,7 +85,7 @@ async function createTimeStates(adapter) {
85
85
  await adapter.setObjectNotExistsAsync(`timecontrol.${prefix}_day_${key}`, {
86
86
  type: 'state',
87
87
  common: {
88
- name: `Zeitfenster ${label} ${labelDay}`,
88
+ name: { de: `Zeitfenster ${label} ${labelDay}`, en: `Time window ${label} ${labelDay}` },
89
89
  type: 'boolean',
90
90
  role: 'switch',
91
91
  read: true,
package/main.js CHANGED
@@ -62,11 +62,32 @@ class Poolcontrol extends utils.Adapter {
62
62
  ...options,
63
63
  name: 'poolcontrol',
64
64
  });
65
+
65
66
  this.on('ready', this.onReady.bind(this));
66
67
  this.on('stateChange', this.onStateChange.bind(this));
67
68
  this.on('unload', this.onUnload.bind(this));
68
69
  }
69
70
 
71
+ // FIX: Determine whether an own state is writable (command-like). Cached for performance.
72
+ async _isWritableOwnState(id) {
73
+ this._ackWritableCache = this._ackWritableCache || new Map();
74
+
75
+ if (this._ackWritableCache.has(id)) {
76
+ return this._ackWritableCache.get(id);
77
+ }
78
+
79
+ try {
80
+ const obj = await this.getObjectAsync(id);
81
+ const isWritable = !!obj?.common?.write;
82
+ this._ackWritableCache.set(id, isWritable);
83
+ return isWritable;
84
+ } catch {
85
+ // If we cannot read the object, play safe: do NOT filter it out.
86
+ this._ackWritableCache.set(id, false);
87
+ return false;
88
+ }
89
+ }
90
+
70
91
  async onReady() {
71
92
  this.log.info('Adapter gestartet');
72
93
 
@@ -250,6 +271,23 @@ class Poolcontrol extends utils.Adapter {
250
271
  this.log.debug(`state ${id} deleted`);
251
272
  }
252
273
 
274
+ // FIX: ignore deleted states completely
275
+ if (!state) {
276
+ return;
277
+ }
278
+
279
+ const isOwnState = id.startsWith(`${this.namespace}.`);
280
+
281
+ // ACK handling guard (own states)
282
+ // - ignore ack=true for OWN writeable states (commands)
283
+ // - still allow ack=true for read-only OWN states (status/live values)
284
+ if (isOwnState && state.ack === true) {
285
+ const isWritable = await this._isWritableOwnState(id);
286
+ if (isWritable) {
287
+ return;
288
+ }
289
+ }
290
+
253
291
  // Saisonstatus manuell ändern (z.B. über VIS)
254
292
  if (id.endsWith('status.season_active') && state && state.ack === false) {
255
293
  this.log.info(`[main] Saisonstatus geändert: ${state.val}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.poolcontrol",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Steuerung & Automatisierung für den Pool (Pumpe, Heizung, Ventile, Sensoren).",
5
5
  "author": "DasBo1975 <dasbo1975@outlook.de>",
6
6
  "homepage": "https://github.com/DasBo1975/ioBroker.poolcontrol",
@@ -24,15 +24,14 @@
24
24
  "@iobroker/adapter-core": "^3.3.2"
25
25
  },
26
26
  "devDependencies": {
27
- "@alcalzone/release-script": "^4.0.0",
27
+ "@alcalzone/release-script": "^5.0.0",
28
+ "@alcalzone/release-script-plugin-iobroker": "^4.0.0",
29
+ "@alcalzone/release-script-plugin-license": "^4.0.0",
28
30
  "@iobroker/adapter-dev": "^1.5.0",
29
31
  "@iobroker/eslint-config": "^2.2.0",
30
- "@iobroker/testing": "^5.1.1",
32
+ "@iobroker/testing": "^5.2.2",
31
33
  "baseline-browser-mapping": "^2.8.32",
32
- "eslint": "^9.36.0",
33
- "prettier": "^3.6.2",
34
- "proxyquire": "^2.1.3",
35
- "release-it": "^19.0.5"
34
+ "proxyquire": "^2.1.3"
36
35
  },
37
36
  "main": "main.js",
38
37
  "files": [
@@ -51,7 +50,7 @@
51
50
  "test": "npm run test:js && npm run test:package",
52
51
  "lint": "eslint .",
53
52
  "translate": "translate-adapter",
54
- "release": "release-it"
53
+ "release": "release-script"
55
54
  },
56
55
  "bugs": {
57
56
  "url": "https://github.com/DasBo1975/ioBroker.poolcontrol/issues"