iobroker.data-solectrus 0.2.9 → 0.3.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0 - 2026-02-03
4
+
5
+ ### BREAKING CHANGES
6
+
7
+ - **Diagnostics state reorganization**: States moved to hierarchical structure for better organization
8
+ - `info.itemsConfigured` → `info.diagnostics.itemsTotal`
9
+ - `info.itemsEnabled` → `info.itemsActive`
10
+ - `info.evalTimeMs` → `info.lastRunMs`
11
+ - `info.timeBudgetMs` → `info.diagnostics.evalBudgetMs`
12
+ - `info.skippedItems` → `info.diagnostics.evalSkipped`
13
+ - Old flat timing states → `info.diagnostics.timing.*`
14
+ - **Note**: Existing visualizations and scripts need to be updated to use new state paths
15
+
16
+ ### Added
17
+
18
+ - New hierarchical state structure with `info.diagnostics.*` and `info.diagnostics.timing.*` channels
19
+ - Enhanced timing diagnostics:
20
+ - Active vs sleeping source detection (30s threshold)
21
+ - `info.diagnostics.timing.sourcesActive` and `sourcesSleeping`
22
+ - Newest/oldest source tracking with IDs and age metrics
23
+ - `info.diagnostics.timing.newestAgeMs`, `newestId`, `oldestAgeMs`, `oldestId`
24
+ - Separate gap calculations for all sources vs active sources only
25
+ - `info.diagnostics.timing.gapActiveMs` and `gapActiveOk`
26
+
27
+ ### Changed
28
+
29
+ - Improved state organization: all timing-related states now grouped under `info.diagnostics.timing.*`
30
+ - Better state naming for clarity (e.g., `lastRunMs` instead of `evalTimeMs`)
31
+
3
32
  ## 0.2.9 - 2026-02-03
4
33
 
5
34
  ### Added
package/README.md CHANGED
@@ -71,18 +71,30 @@ Direktlinks (Auswahl):
71
71
  Unter `data-solectrus.0.info.*` werden Status/Diagnosewerte gepflegt:
72
72
 
73
73
  - `info.status`: `starting`, `ok`, `no_items_enabled`
74
- - `info.itemsConfigured`, `info.itemsEnabled`
75
- - `info.lastError`
76
- - `info.lastRun`, `info.evalTimeMs`
77
- - `info.timeBudgetMs`, `info.skippedItems`
78
-
79
- Timing/Sync-Diagnose (hilft bei kurzzeitig „unplausiblen“ Kombinationen, wenn Quellen zeitversetzt updaten):
80
-
81
- - `info.inputTsGapMs`: Differenz zwischen ältestem und neuestem Input-Timestamp (ms) der im Tick genutzten Quellen
82
- - `info.inputTsGapOk`: `true/false` basierend auf einem konservativen Threshold
83
- - `info.inputTsGapThresholdMs`: verwendeter Threshold (ms)
84
- - `info.inputTsSources`: Anzahl Inputs mit Timestamp
85
- - `info.inputTsMissing`: Anzahl Inputs ohne Timestamp
74
+ - `info.itemsActive`: Anzahl aktiver Items
75
+ - `info.lastError`: Letzter Fehler
76
+ - `info.lastRun`: Zeitstempel des letzten Ticks (ISO)
77
+ - `info.lastRunMs`: Dauer des letzten Ticks (ms)
78
+
79
+ Unter `info.diagnostics.*` liegen erweiterte Diagnose-Informationen:
80
+
81
+ - `info.diagnostics.itemsTotal`: Gesamtzahl konfigurierter Items
82
+ - `info.diagnostics.evalBudgetMs`: Verfügbares Zeitbudget pro Tick (ms)
83
+ - `info.diagnostics.evalSkipped`: Anzahl übersprungener Items (bei Budget-Überschreitung)
84
+
85
+ Unter `info.diagnostics.timing.*` finden sich detaillierte Timing-Analysen (hilft bei kurzzeitig „unplausiblen" Kombinationen, wenn Quellen zeitversetzt updaten):
86
+
87
+ - `info.diagnostics.timing.gapMs`: Zeitdifferenz zwischen ältestem und neuestem Source-Timestamp (alle Quellen)
88
+ - `info.diagnostics.timing.gapOk`: `true/false` basierend auf Threshold
89
+ - `info.diagnostics.timing.gapActiveMs`: Zeitdifferenz nur für aktive Quellen (< 30s alt)
90
+ - `info.diagnostics.timing.gapActiveOk`: `true/false` für aktive Quellen
91
+ - `info.diagnostics.timing.newestAgeMs`: Alter der neuesten Quelle (ms)
92
+ - `info.diagnostics.timing.newestId`: State-ID der neuesten Quelle
93
+ - `info.diagnostics.timing.oldestAgeMs`: Alter der ältesten Quelle (ms)
94
+ - `info.diagnostics.timing.oldestId`: State-ID der ältesten Quelle
95
+ - `info.diagnostics.timing.sources`: Anzahl Quellen mit Timestamp
96
+ - `info.diagnostics.timing.sourcesActive`: Anzahl aktiver Quellen (< 30s alt)
97
+ - `info.diagnostics.timing.sourcesSleeping`: Anzahl inaktiver Quellen (≥ 30s alt)
86
98
 
87
99
  Zusätzlich gibt es per Item Diagnose-States unter `data-solectrus.0.items.<outputId>.*`:
88
100
 
package/io-package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "data-solectrus",
4
- "version": "0.2.9",
4
+ "version": "0.3.0",
5
5
  "title": "Data-SOLECTRUS",
6
6
  "icon": "data-solectrus.png",
7
7
  "extIcon": "https://raw.githubusercontent.com/Felliglanz/ioBroker.data-solectrus/main/admin/data-solectrus.png",
@@ -30,6 +30,10 @@
30
30
  "license": "MIT",
31
31
  "readme": "https://github.com/Felliglanz/ioBroker.data-solectrus/blob/main/README.md",
32
32
  "news": {
33
+ "0.3.0": {
34
+ "en": "BREAKING: Restructured diagnostics states with hierarchical organization. Enhanced timing analytics.",
35
+ "de": "BREAKING: Diagnose-States neu strukturiert mit hierarchischer Organisation. Erweiterte Timing-Analysen."
36
+ },
33
37
  "0.2.9": {
34
38
  "en": "Added package metadata (repository, bugs, homepage) and .npmignore",
35
39
  "de": "Package-Metadaten (repository, bugs, homepage) und .npmignore hinzugefügt"
@@ -145,6 +145,7 @@ async function ensureItemInfoStatesForCompiled(adapter, compiled) {
145
145
  }
146
146
 
147
147
  async function createInfoStates(adapter) {
148
+ // === info.* (top-level status states) ===
148
149
  await adapter.setObjectNotExistsAsync('info.status', {
149
150
  type: 'state',
150
151
  common: {
@@ -157,10 +158,10 @@ async function createInfoStates(adapter) {
157
158
  native: {},
158
159
  });
159
160
 
160
- await adapter.setObjectNotExistsAsync('info.itemsConfigured', {
161
+ await adapter.setObjectNotExistsAsync('info.itemsActive', {
161
162
  type: 'state',
162
163
  common: {
163
- name: 'Configured items',
164
+ name: 'Active items',
164
165
  type: 'number',
165
166
  role: 'value',
166
167
  read: true,
@@ -169,84 +170,123 @@ async function createInfoStates(adapter) {
169
170
  native: {},
170
171
  });
171
172
 
172
- await adapter.setObjectNotExistsAsync('info.itemsEnabled', {
173
+ await adapter.setObjectNotExistsAsync('info.lastError', {
173
174
  type: 'state',
174
175
  common: {
175
- name: 'Enabled items',
176
- type: 'number',
177
- role: 'value',
176
+ name: 'Last error',
177
+ type: 'string',
178
+ role: 'text',
178
179
  read: true,
179
180
  write: false,
180
181
  },
181
182
  native: {},
182
183
  });
183
184
 
184
- await adapter.setObjectNotExistsAsync('info.lastError', {
185
+ await adapter.setObjectNotExistsAsync('info.lastRun', {
185
186
  type: 'state',
186
187
  common: {
187
- name: 'Last Error',
188
+ name: 'Last run',
188
189
  type: 'string',
189
- role: 'text',
190
+ role: 'date',
190
191
  read: true,
191
192
  write: false,
192
193
  },
193
194
  native: {},
194
195
  });
195
196
 
196
- await adapter.setObjectNotExistsAsync('info.lastRun', {
197
+ await adapter.setObjectNotExistsAsync('info.lastRunMs', {
197
198
  type: 'state',
198
199
  common: {
199
- name: 'Last Run',
200
- type: 'string',
201
- role: 'date',
200
+ name: 'Last run duration',
201
+ type: 'number',
202
+ role: 'value',
203
+ unit: 'ms',
202
204
  read: true,
203
205
  write: false,
204
206
  },
205
207
  native: {},
206
208
  });
207
209
 
208
- await adapter.setObjectNotExistsAsync('info.evalTimeMs', {
210
+ // === info.diagnostics.* (diagnostics channel) ===
211
+ await adapter.setObjectNotExistsAsync('info.diagnostics', {
212
+ type: 'channel',
213
+ common: { name: 'diagnostics' },
214
+ native: {},
215
+ });
216
+
217
+ await adapter.setObjectNotExistsAsync('info.diagnostics.evalBudgetMs', {
209
218
  type: 'state',
210
219
  common: {
211
- name: 'Evaluation time (ms)',
220
+ name: 'Evaluation budget',
212
221
  type: 'number',
213
222
  role: 'value',
223
+ unit: 'ms',
214
224
  read: true,
215
225
  write: false,
216
226
  },
217
227
  native: {},
218
228
  });
219
229
 
220
- await adapter.setObjectNotExistsAsync('info.timeBudgetMs', {
230
+ await adapter.setObjectNotExistsAsync('info.diagnostics.evalSkipped', {
221
231
  type: 'state',
222
232
  common: {
223
- name: 'Tick time budget (ms)',
233
+ name: 'Skipped items (last tick)',
224
234
  type: 'number',
225
235
  role: 'value',
226
- unit: 'ms',
227
236
  read: true,
228
237
  write: false,
229
238
  },
230
239
  native: {},
231
240
  });
232
241
 
233
- await adapter.setObjectNotExistsAsync('info.skippedItems', {
242
+ await adapter.setObjectNotExistsAsync('info.diagnostics.itemsTotal', {
234
243
  type: 'state',
235
244
  common: {
236
- name: 'Skipped items (last tick)',
245
+ name: 'Total configured items',
246
+ type: 'number',
247
+ role: 'value',
248
+ read: true,
249
+ write: false,
250
+ },
251
+ native: {},
252
+ });
253
+
254
+ // === info.diagnostics.timing.* (timing sub-channel) ===
255
+ await adapter.setObjectNotExistsAsync('info.diagnostics.timing', {
256
+ type: 'channel',
257
+ common: { name: 'timing' },
258
+ native: {},
259
+ });
260
+
261
+ await adapter.setObjectNotExistsAsync('info.diagnostics.timing.gapMs', {
262
+ type: 'state',
263
+ common: {
264
+ name: 'Timestamp gap (all sources)',
237
265
  type: 'number',
238
266
  role: 'value',
267
+ unit: 'ms',
268
+ read: true,
269
+ write: false,
270
+ },
271
+ native: {},
272
+ });
273
+
274
+ await adapter.setObjectNotExistsAsync('info.diagnostics.timing.gapOk', {
275
+ type: 'state',
276
+ common: {
277
+ name: 'Timestamp gap OK',
278
+ type: 'boolean',
279
+ role: 'indicator',
239
280
  read: true,
240
281
  write: false,
241
282
  },
242
283
  native: {},
243
284
  });
244
285
 
245
- // Input timestamp skew diagnostics (helps spot timing/cache issues when combining many sources).
246
- await adapter.setObjectNotExistsAsync('info.inputTsGapMs', {
286
+ await adapter.setObjectNotExistsAsync('info.diagnostics.timing.gapActiveMs', {
247
287
  type: 'state',
248
288
  common: {
249
- name: 'Input timestamp gap (ms)',
289
+ name: 'Timestamp gap (active sources)',
250
290
  type: 'number',
251
291
  role: 'value',
252
292
  unit: 'ms',
@@ -256,10 +296,10 @@ async function createInfoStates(adapter) {
256
296
  native: {},
257
297
  });
258
298
 
259
- await adapter.setObjectNotExistsAsync('info.inputTsGapOk', {
299
+ await adapter.setObjectNotExistsAsync('info.diagnostics.timing.gapActiveOk', {
260
300
  type: 'state',
261
301
  common: {
262
- name: 'Input timestamp gap OK',
302
+ name: 'Timestamp gap (active) OK',
263
303
  type: 'boolean',
264
304
  role: 'indicator',
265
305
  read: true,
@@ -268,10 +308,35 @@ async function createInfoStates(adapter) {
268
308
  native: {},
269
309
  });
270
310
 
271
- await adapter.setObjectNotExistsAsync('info.inputTsGapThresholdMs', {
311
+ await adapter.setObjectNotExistsAsync('info.diagnostics.timing.newestAgeMs', {
312
+ type: 'state',
313
+ common: {
314
+ name: 'Newest source age',
315
+ type: 'number',
316
+ role: 'value',
317
+ unit: 'ms',
318
+ read: true,
319
+ write: false,
320
+ },
321
+ native: {},
322
+ });
323
+
324
+ await adapter.setObjectNotExistsAsync('info.diagnostics.timing.newestId', {
325
+ type: 'state',
326
+ common: {
327
+ name: 'Newest source ID',
328
+ type: 'string',
329
+ role: 'text',
330
+ read: true,
331
+ write: false,
332
+ },
333
+ native: {},
334
+ });
335
+
336
+ await adapter.setObjectNotExistsAsync('info.diagnostics.timing.oldestAgeMs', {
272
337
  type: 'state',
273
338
  common: {
274
- name: 'Input timestamp gap OK threshold (ms)',
339
+ name: 'Oldest source age',
275
340
  type: 'number',
276
341
  role: 'value',
277
342
  unit: 'ms',
@@ -281,10 +346,34 @@ async function createInfoStates(adapter) {
281
346
  native: {},
282
347
  });
283
348
 
284
- await adapter.setObjectNotExistsAsync('info.inputTsSources', {
349
+ await adapter.setObjectNotExistsAsync('info.diagnostics.timing.oldestId', {
350
+ type: 'state',
351
+ common: {
352
+ name: 'Oldest source ID',
353
+ type: 'string',
354
+ role: 'text',
355
+ read: true,
356
+ write: false,
357
+ },
358
+ native: {},
359
+ });
360
+
361
+ await adapter.setObjectNotExistsAsync('info.diagnostics.timing.sources', {
362
+ type: 'state',
363
+ common: {
364
+ name: 'Sources with timestamps',
365
+ type: 'number',
366
+ role: 'value',
367
+ read: true,
368
+ write: false,
369
+ },
370
+ native: {},
371
+ });
372
+
373
+ await adapter.setObjectNotExistsAsync('info.diagnostics.timing.sourcesActive', {
285
374
  type: 'state',
286
375
  common: {
287
- name: 'Inputs with timestamps (last tick)',
376
+ name: 'Active sources',
288
377
  type: 'number',
289
378
  role: 'value',
290
379
  read: true,
@@ -293,10 +382,10 @@ async function createInfoStates(adapter) {
293
382
  native: {},
294
383
  });
295
384
 
296
- await adapter.setObjectNotExistsAsync('info.inputTsMissing', {
385
+ await adapter.setObjectNotExistsAsync('info.diagnostics.timing.sourcesSleeping', {
297
386
  type: 'state',
298
387
  common: {
299
- name: 'Inputs missing timestamps (last tick)',
388
+ name: 'Sleeping sources',
300
389
  type: 'number',
301
390
  role: 'value',
302
391
  read: true,
@@ -305,19 +394,26 @@ async function createInfoStates(adapter) {
305
394
  native: {},
306
395
  });
307
396
 
397
+ // Initialize all states with default values
308
398
  await adapter.setStateAsync('info.status', 'starting', true);
309
- await adapter.setStateAsync('info.itemsConfigured', 0, true);
310
- await adapter.setStateAsync('info.itemsEnabled', 0, true);
399
+ await adapter.setStateAsync('info.itemsActive', 0, true);
311
400
  await adapter.setStateAsync('info.lastError', '', true);
312
401
  await adapter.setStateAsync('info.lastRun', '', true);
313
- await adapter.setStateAsync('info.evalTimeMs', 0, true);
314
- await adapter.setStateAsync('info.timeBudgetMs', 0, true);
315
- await adapter.setStateAsync('info.skippedItems', 0, true);
316
- await adapter.setStateAsync('info.inputTsGapMs', 0, true);
317
- await adapter.setStateAsync('info.inputTsGapOk', true, true);
318
- await adapter.setStateAsync('info.inputTsGapThresholdMs', 0, true);
319
- await adapter.setStateAsync('info.inputTsSources', 0, true);
320
- await adapter.setStateAsync('info.inputTsMissing', 0, true);
402
+ await adapter.setStateAsync('info.lastRunMs', 0, true);
403
+ await adapter.setStateAsync('info.diagnostics.evalBudgetMs', 0, true);
404
+ await adapter.setStateAsync('info.diagnostics.evalSkipped', 0, true);
405
+ await adapter.setStateAsync('info.diagnostics.itemsTotal', 0, true);
406
+ await adapter.setStateAsync('info.diagnostics.timing.gapMs', 0, true);
407
+ await adapter.setStateAsync('info.diagnostics.timing.gapOk', true, true);
408
+ await adapter.setStateAsync('info.diagnostics.timing.gapActiveMs', 0, true);
409
+ await adapter.setStateAsync('info.diagnostics.timing.gapActiveOk', true, true);
410
+ await adapter.setStateAsync('info.diagnostics.timing.newestAgeMs', 0, true);
411
+ await adapter.setStateAsync('info.diagnostics.timing.newestId', '', true);
412
+ await adapter.setStateAsync('info.diagnostics.timing.oldestAgeMs', 0, true);
413
+ await adapter.setStateAsync('info.diagnostics.timing.oldestId', '', true);
414
+ await adapter.setStateAsync('info.diagnostics.timing.sources', 0, true);
415
+ await adapter.setStateAsync('info.diagnostics.timing.sourcesActive', 0, true);
416
+ await adapter.setStateAsync('info.diagnostics.timing.sourcesSleeping', 0, true);
321
417
  }
322
418
 
323
419
  module.exports = {
@@ -60,11 +60,11 @@ async function runTick(adapter) {
60
60
 
61
61
  // Keep status in sync even if config changes without a restart
62
62
  try {
63
- await adapter.setStateAsync('info.itemsConfigured', items.filter(it => it && typeof it === 'object').length, true);
64
- await adapter.setStateAsync('info.itemsEnabled', enabledItems.length, true);
63
+ await adapter.setStateAsync('info.diagnostics.itemsTotal', items.filter(it => it && typeof it === 'object').length, true);
64
+ await adapter.setStateAsync('info.itemsActive', enabledItems.length, true);
65
65
  await adapter.setStateAsync('info.status', enabledItems.length ? 'ok' : 'no_items_enabled', true);
66
- await adapter.setStateAsync('info.timeBudgetMs', timeBudgetMs, true);
67
- await adapter.setStateAsync('info.skippedItems', 0, true);
66
+ await adapter.setStateAsync('info.diagnostics.evalBudgetMs', timeBudgetMs, true);
67
+ await adapter.setStateAsync('info.diagnostics.evalSkipped', 0, true);
68
68
  } catch {
69
69
  // ignore
70
70
  }
@@ -84,33 +84,83 @@ async function runTick(adapter) {
84
84
  }
85
85
  adapter.currentSnapshot = snapshot;
86
86
 
87
- // Publish input timestamp skew diagnostics.
87
+ // Publish comprehensive timing diagnostics.
88
88
  // This helps explain "impossible" transient combinations when snapshot is off or sources update slightly offset.
89
89
  try {
90
90
  const ids = snapshot && typeof snapshot.keys === 'function' ? Array.from(snapshot.keys()) : [];
91
+ const now = Date.now();
92
+ const sleepThresholdMs = 30000; // Sources not updated in 30s are considered "sleeping"
93
+
91
94
  let minTs = Infinity;
92
95
  let maxTs = -Infinity;
96
+ let minActiveTs = Infinity;
97
+ let maxActiveTs = -Infinity;
98
+ let newestTs = -Infinity;
99
+ let oldestTs = Infinity;
100
+ let newestId = '';
101
+ let oldestId = '';
93
102
  let withTs = 0;
103
+ let activeSources = 0;
104
+ let sleepingSources = 0;
94
105
  let total = 0;
106
+
95
107
  for (const id of ids) {
96
108
  if (!id) continue;
97
109
  total++;
98
110
  const ts = adapter.cacheTs.get(id);
99
111
  if (typeof ts !== 'number' || !Number.isFinite(ts)) continue;
112
+
100
113
  withTs++;
114
+ const age = now - ts;
115
+ const isActive = age < sleepThresholdMs;
116
+
117
+ // Track overall min/max timestamps
101
118
  if (ts < minTs) minTs = ts;
102
119
  if (ts > maxTs) maxTs = ts;
120
+
121
+ // Track active sources min/max
122
+ if (isActive) {
123
+ activeSources++;
124
+ if (ts < minActiveTs) minActiveTs = ts;
125
+ if (ts > maxActiveTs) maxActiveTs = ts;
126
+ } else {
127
+ sleepingSources++;
128
+ }
129
+
130
+ // Track newest (most recent)
131
+ if (ts > newestTs) {
132
+ newestTs = ts;
133
+ newestId = id;
134
+ }
135
+
136
+ // Track oldest (least recent)
137
+ if (ts < oldestTs) {
138
+ oldestTs = ts;
139
+ oldestId = id;
140
+ }
103
141
  }
142
+
104
143
  const gapMs = withTs >= 2 ? Math.max(0, Math.round(maxTs - minTs)) : 0;
144
+ const gapActiveMs = activeSources >= 2 ? Math.max(0, Math.round(maxActiveTs - minActiveTs)) : 0;
105
145
  const intervalMs = getTickIntervalMs(adapter);
106
146
  const thresholdMs = Math.max(200, Math.min(5000, Math.floor(intervalMs * 0.2)));
107
- const ok = withTs <= 1 ? true : gapMs <= thresholdMs;
147
+ const gapOk = withTs <= 1 ? true : gapMs <= thresholdMs;
148
+ const gapActiveOk = activeSources <= 1 ? true : gapActiveMs <= thresholdMs;
149
+ const newestAgeMs = newestTs > -Infinity ? Math.max(0, now - newestTs) : 0;
150
+ const oldestAgeMs = oldestTs < Infinity ? Math.max(0, now - oldestTs) : 0;
108
151
 
109
- await adapter.setStateAsync('info.inputTsGapMs', gapMs, true);
110
- await adapter.setStateAsync('info.inputTsGapOk', ok, true);
111
- await adapter.setStateAsync('info.inputTsGapThresholdMs', thresholdMs, true);
112
- await adapter.setStateAsync('info.inputTsSources', withTs, true);
113
- await adapter.setStateAsync('info.inputTsMissing', Math.max(0, total - withTs), true);
152
+ // Write all timing diagnostics
153
+ await adapter.setStateAsync('info.diagnostics.timing.gapMs', gapMs, true);
154
+ await adapter.setStateAsync('info.diagnostics.timing.gapOk', gapOk, true);
155
+ await adapter.setStateAsync('info.diagnostics.timing.gapActiveMs', gapActiveMs, true);
156
+ await adapter.setStateAsync('info.diagnostics.timing.gapActiveOk', gapActiveOk, true);
157
+ await adapter.setStateAsync('info.diagnostics.timing.newestAgeMs', newestAgeMs, true);
158
+ await adapter.setStateAsync('info.diagnostics.timing.newestId', newestId, true);
159
+ await adapter.setStateAsync('info.diagnostics.timing.oldestAgeMs', oldestAgeMs, true);
160
+ await adapter.setStateAsync('info.diagnostics.timing.oldestId', oldestId, true);
161
+ await adapter.setStateAsync('info.diagnostics.timing.sources', withTs, true);
162
+ await adapter.setStateAsync('info.diagnostics.timing.sourcesActive', activeSources, true);
163
+ await adapter.setStateAsync('info.diagnostics.timing.sourcesSleeping', sleepingSources, true);
114
164
  } catch {
115
165
  // ignore
116
166
  }
@@ -194,9 +244,9 @@ async function runTick(adapter) {
194
244
  adapter.currentSnapshot = null;
195
245
 
196
246
  try {
197
- await adapter.setStateAsync('info.skippedItems', skippedItems, true);
247
+ await adapter.setStateAsync('info.diagnostics.evalSkipped', skippedItems, true);
198
248
  await adapter.setStateAsync('info.lastRun', new Date().toISOString(), true);
199
- await adapter.setStateAsync('info.evalTimeMs', Date.now() - start, true);
249
+ await adapter.setStateAsync('info.lastRunMs', Date.now() - start, true);
200
250
  } catch {
201
251
  // ignore
202
252
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.data-solectrus",
3
- "version": "0.2.9",
3
+ "version": "0.3.0",
4
4
  "description": "ioBroker adapter to compute/mirror PV & consumption values for SOLECTRUS dashboards",
5
5
  "author": "Sven",
6
6
  "main": "main.js",