iobroker.anomaly-detection 0.2.0 → 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.
Files changed (38) hide show
  1. package/README.de.md +276 -0
  2. package/README.md +11 -1
  3. package/admin/custom/assets/Components-n5uijLJW.js +3 -0
  4. package/admin/custom/assets/{TextField-DNFcbJCE.js → TextField-C3oAONXA.js} +1 -1
  5. package/admin/custom/assets/{_virtual_mf-localSharedImportMap___mfe_internal__AnomalyDetectionAdmin__mf_owner__1-Bn45JlGM.js → _virtual_mf-localSharedImportMap___mfe_internal__AnomalyDetectionAdmin__mf_owner__1-BA-4CH8A.js} +1 -1
  6. package/admin/custom/assets/{_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.js-CxByAkwq.js → _virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.js-D34feF1M.js} +2 -2
  7. package/admin/custom/assets/{_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare___mf_0_mui_mf_1_icons_mf_2_material__loadShare__.js-C2PcnDBz.js → _virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare___mf_0_mui_mf_1_icons_mf_2_material__loadShare__.js-gzeYEwNX.js} +2 -2
  8. package/admin/custom/assets/{_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare___mf_0_mui_mf_1_material__loadShare__.js-BWEm0L22.js → _virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare___mf_0_mui_mf_1_material__loadShare__.js-Czolif-c.js} +2 -2
  9. package/admin/custom/assets/_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-3izusDYF.js +2 -0
  10. package/admin/custom/assets/{_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__-T67sp31H.js → _virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__--NubxY40.js} +3 -3
  11. package/admin/custom/assets/{_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild___mf_0_mui_mf_1_icons_mf_2_material__prebuild__-CSf7D3Rq.js → _virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild___mf_0_mui_mf_1_icons_mf_2_material__prebuild__-BBex2Aqy.js} +1 -1
  12. package/admin/custom/assets/{_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild___mf_0_mui_mf_1_material__prebuild__-G3XIndY6.js → _virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild___mf_0_mui_mf_1_material__prebuild__-I7FRi2ux.js} +1 -1
  13. package/admin/custom/assets/{createSvgIcon-lbUx5w8b.js → createSvgIcon-CJqGdhTN.js} +1 -1
  14. package/admin/custom/assets/{hostInit-BWN-RucD.js → hostInit-LhP5RTJM.js} +1 -1
  15. package/admin/custom/assets/{index-Bs96mP5z.js → index-B7JZp1OS.js} +1 -1
  16. package/admin/custom/assets/{index-DQDnJGju.js → index-CxATVJMB.js} +1 -1
  17. package/admin/custom/assets/{mf-entry-bootstrap-0-d6d9d7a6.js → mf-entry-bootstrap-0-f129c863.js} +3 -3
  18. package/admin/custom/assets/{pendingShares-CaFFrAdb.js → pendingShares-KiQCgcgq.js} +1 -1
  19. package/admin/custom/assets/{virtualExposes-Dx4O0s8s.js → virtualExposes-CEiOyubF.js} +1 -1
  20. package/admin/custom/customComponents.js +2 -2
  21. package/admin/custom/index.html +3 -3
  22. package/admin/custom/mf-manifest.json +1 -1
  23. package/admin/custom/mf-stats.json +1 -1
  24. package/admin/i18n/de.json +5 -0
  25. package/admin/i18n/en.json +5 -0
  26. package/admin/jsonConfig.json +187 -17
  27. package/admin/jsonTab.json +7 -7
  28. package/build/lib/predictive.js +832 -0
  29. package/build/lib/predictive.js.map +7 -0
  30. package/build/lib/source-monitor.js +69 -28
  31. package/build/lib/source-monitor.js.map +2 -2
  32. package/build/main.js +512 -54
  33. package/build/main.js.map +3 -3
  34. package/io-package.json +6 -2
  35. package/package.json +105 -103
  36. package/scripts/benchmark-predictive.js +56 -0
  37. package/admin/custom/assets/Components-ClCLk8YC.js +0 -3
  38. package/admin/custom/assets/_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-D-mkyUQs.js +0 -2
package/README.de.md ADDED
@@ -0,0 +1,276 @@
1
+ <img src="admin/anomaly-detection.png" alt="Logo" width="400">
2
+
3
+ # ioBroker.anomaly-detection
4
+
5
+ [![NPM-Version](https://img.shields.io/npm/v/iobroker.anomaly-detection.svg)](https://www.npmjs.com/package/iobroker.anomaly-detection)
6
+
7
+ [English](README.md) · **Deutsch**
8
+
9
+ Der Adapter lernt das normale Verhalten ausgewählter numerischer ioBroker-Zustände und meldet statistisch ungewöhnliche Werte lokal.
10
+
11
+ > **Es wird keine KI verwendet.** Der Adapter nutzt weder Cloud-Dienste noch externe KI- oder Machine-Learning-APIs. Alle Bewertungen werden lokal mit deterministischen mathematischen und statistischen Verfahren berechnet, unter anderem Median, Median Absolute Deviation (MAD), Zeitbereichs-Baselines und robuste Steigungen. Bei gleichen Eingangsdaten und Einstellungen sind die Ergebnisse nachvollziehbar und reproduzierbar.
12
+
13
+ ## Funktionsweise
14
+
15
+ Starre Grenzwerte können zeit- oder betriebsabhängiges Verhalten nicht abbilden: 8 kW können morgens normal, an einem warmen Sonntag aber ungewöhnlich sein. Für jeden konfigurierten numerischen Zustand verwaltet der Adapter begrenzte, robuste Baselines. Jede eingehende Zustandsänderung wird ausgewertet; die Quellzustände werden nicht abgefragt (kein Polling).
16
+
17
+ Der Adapter kombiniert folgende deterministische Detektoren:
18
+
19
+ - **Wertabweichungen (MAD):** Erkennt Werte außerhalb des gelernten Normalbereichs, ohne dass ein einzelner Extremwert die Baseline stark verzerrt.
20
+ - **Änderungsrate:** Bewertet `Delta / vergangene Zeit` und berücksichtigt dadurch unregelmäßige Update-Abstände.
21
+ - **Festhängende Werte:** Erkennt wiederholt empfangene identische Werte, die länger als die konfigurierte Dauer anhalten. Ein fehlendes Update allein gilt niemals als festhängend.
22
+ - **Tageszeit-Kontext:** Verwendet standardmäßig Stundenbereiche und kann zusätzlich nach Wochentagen getrennt werden. Bei zu wenigen Daten greift die Hierarchie auf den Zeitbereich und anschließend auf die globale Baseline zurück.
23
+
24
+ `score` ist ein deterministischer Schweregrad von 0 bis 100. Er ist weder eine statistische Wahrscheinlichkeit noch eine Diagnose der physischen Ursache.
25
+
26
+ | Score | Bedeutung |
27
+ | --- | --- |
28
+ | 0–49 | normal |
29
+ | 50–69 | ungewöhnlich |
30
+ | 70–84 | Anomalie |
31
+ | 85–100 | starke Anomalie |
32
+
33
+ ## Mathematische Grundlagen
34
+
35
+ Der Adapter verwendet begrenzte, robuste Statistik. Er trainiert kein neuronales Netz, ruft keinen KI-Dienst auf und setzt keine konstanten Messintervalle voraus.
36
+
37
+ ### Wertabweichungen: Median und MAD
38
+
39
+ Für eine gelernte Baseline mit Werten `x₁ … xₙ` ist der erwartete Wert der Median `m = median(x₁ … xₙ)`. Die Streuung wird mit der Median Absolute Deviation berechnet:
40
+
41
+ `MAD = median(|xᵢ − m|)`
42
+
43
+ Für einen neuen Wert `x` ergibt sich der robuste z-Score:
44
+
45
+ `robuster z-Score = 0,6745 × |x − m| / MAD`
46
+
47
+ Die Option **Sensitivität** legt fest, bei welchem z-Score dieser Detektor den Wert 100 erreicht. Median und MAD werden von einzelnen Ausreißern deutlich weniger verzerrt als Mittelwert und Standardabweichung. Bei `MAD = 0` ist ein unveränderter Wert normal; ein anderer Wert gilt als starke Abweichung.
48
+
49
+ ### Änderungsrate
50
+
51
+ Für zwei aufeinanderfolgende Werte wird das tatsächliche Zeitintervall verwendet:
52
+
53
+ `Rate = (aktueller Wert − vorheriger Wert) / vergangene Sekunden`
54
+
55
+ Die Rate-Baseline wird mit derselben Median/MAD-Methode gelernt. So kann eine ungewöhnlich schnelle Änderung erkannt werden, auch wenn der absolute Endwert noch plausibel ist.
56
+
57
+ ### Festhängende Werte
58
+
59
+ Dieser Detektor ist regelbasiert. Werden identische Werte wiederholt empfangen, merkt sich der Adapter den ersten Zeitpunkt `t₀`. Ein Treffer ist erst möglich, wenn gilt:
60
+
61
+ `aktueller Zeitpunkt − t₀ ≥ konfigurierte Dauer`
62
+
63
+ Ein fehlendes Update zählt nicht als wiederholter Wert und kann daher keine Festhängend-Anomalie auslösen.
64
+
65
+ ### Tageszeit- und Wochentags-Kontext
66
+
67
+ Zeitbereiche werden aus der lokalen Tageszeit gebildet:
68
+
69
+ `Zeitbereich = floor(Minuten seit Mitternacht / Bucket-Größe)`
70
+
71
+ Mit aktivierter Wochentagsoption wird der Wochentag in den Schlüssel aufgenommen. Eine Baseline wird nur verwendet, wenn sie mindestens **Mindestanzahl gelernter Messwerte** enthält. Die Fallback-Reihenfolge lautet:
72
+
73
+ `Wochentag + Zeitbereich → Zeitbereich → globale Baseline`
74
+
75
+ ### Kontextabhängige Baseline
76
+
77
+ Kontextzustände erzeugen zusätzliche Schlüssel, zum Beispiel `pumpe.ein=true`, `modus=eco` oder `temperatur=10–15`. Numerische Kontextwerte werden in feste Intervalle eingeteilt:
78
+
79
+ `Intervallbeginn = floor(Kontextwert / Bucket-Breite) × Bucket-Breite`
80
+
81
+ Bei einer Breite von 5 gehört der Wert 12,3 zum Intervall 10–15. Ein Kontext muss mindestens die konfigurierte Mindestanzahl an Messwerten enthalten, bevor er als Baseline verwendet wird. Ein gültiger, aber noch nicht ausgereifter Kontext bleibt im Status `learning` und wird nicht mit einer fremden globalen Baseline verglichen. Fehlende oder ungültige Kontextwerte verwenden den normalen Zeit-/Global-Fallback. Kombinationen, Kategorien und Samples sind begrenzt, damit der Speicher nicht unkontrolliert wächst.
82
+
83
+ ### Dauerhafte Pegelverschiebung
84
+
85
+ Die Auswertung arbeitet mit Residuen:
86
+
87
+ `Residuum = tatsächlicher Wert − erwarteter Wert`
88
+
89
+ Der robuste Median eines begrenzten aktuellen Residuenfensters wird mit dem langfristig erwarteten Residuum verglichen und anhand der MAD-Baseline normiert. Eine Verschiebung muss bei mehreren Auswertungen in dieselbe Richtung anhalten; ein einzelner Peak wird dadurch nicht zu einem Change Point.
90
+
91
+ ### Trend
92
+
93
+ Auch der Trend wird auf Residuen berechnet, damit normale Tagesmuster zuvor abgezogen werden. Für alle gültigen Wertepaarungen wird die Steigung bestimmt:
94
+
95
+ `Steigungᵢⱼ = (Residuumⱼ − Residuumᵢ) / (Zeitstempelⱼ − Zeitstempelᵢ)`
96
+
97
+ Die finale Steigung ist der Median dieser Steigungen (robuste Theil-Sen-ähnliche Methode). Isolierte Ausreißer haben dadurch deutlich weniger Einfluss als bei einer gewöhnlichen linearen Regression. Ein Trend benötigt mindestens 12 Messwerte über mindestens sechs Stunden.
98
+
99
+ ### Kombinierter Score und Lernen
100
+
101
+ Jeder Detektor liefert einen begrenzten Score von 0 bis 100. Wert-/Kontext-, Pegelverschiebungs- und Trendsignale gelten als zusammengehörige Evidenz; nur das stärkste dieser Signale wird gewichtet, damit nichts doppelt gezählt wird. Rate- und Festhängend-Signale können unabhängig beitragen. Mehrere unabhängige starke Signale erzeugen einen kleinen begrenzten Bonus. Der Endwert wird immer auf 0–100 begrenzt.
102
+
103
+ Messwerte ab **Anomalie-Schwellenwert** werden normalerweise nicht weiter gelernt, damit ein anhaltender Fehler nicht sofort als normal gilt. Bestätigte Pegelverschiebungen sind eine Ausnahme: Ihre Werte werden schrittweise aufgenommen, damit ein legitimes neues Betriebsniveau zur neuen Baseline werden kann.
104
+
105
+ ## Konfiguration
106
+
107
+ Füge in der Tabelle **Überwachte numerische Zustände** für jede Quelle eine Zeile hinzu. Unterstützt werden nur ioBroker-Zustände mit `common.type: number`.
108
+
109
+ Die wichtigsten Standardwerte sind bewusst zurückhaltend:
110
+
111
+ - Vor der Überwachung werden standardmäßig 30 Messwerte gelernt.
112
+ - Die Sensitivität beträgt 3,5 robuste z-Scores.
113
+ - Die persistente Anomalieanzeige benötigt standardmäßig Score 70 für fünf Minuten.
114
+ - Eine Hysterese von 10 Punkten verhindert Flattern an der Schwelle.
115
+ - Der Festhängend-Detektor ist standardmäßig deaktiviert und verwendet bei Aktivierung 120 Minuten.
116
+ - Der Tageszeitkontext arbeitet standardmäßig mit 60-Minuten-Bereichen; der Wochentagskontext ist optional.
117
+
118
+ Änderungen werden nach dem Neustart des Adapters wirksam. Doppelte Quell-IDs werden nach der ersten aktivierten Zeile ignoriert. Fehlende konfigurierte Objekte bleiben abonniert, damit sie später automatisch verwendet werden können; beim Start wird eine Warnung protokolliert.
119
+
120
+ Wird eine Quelle aus der Konfiguration entfernt und der Adapter neu gestartet, löscht er den zugehörigen generierten Teilbaum unter `anomaly-detection.0.sources` sowie das gespeicherte Modell. Dabei wird die ursprüngliche Quell-ID aus den Metadaten des generierten Geräts verwendet. Eine nur vorübergehend nicht verfügbare, weiterhin konfigurierte Quelle bleibt erhalten.
121
+
122
+ ## Analyseansicht und Verlauf
123
+
124
+ Die Registerkarte **Aktuelle Anomaliebewertungen** enthält pro überwachte Quelle ein responsives, zunächst eingeklapptes Diagramm **Verlauf & Anomalien**. Der Verlauf wird erst beim Öffnen geladen. Zur Auswahl stehen **1 h**, **6 h**, **24 h** (Standard) und **7 Tage**.
125
+
126
+ Das Diagramm verwendet die Einheit des ioBroker-Zustands, zum Beispiel `W`, `%` oder `°C`, und passt seine Breite an die tatsächliche Kartenbreite an. Es zeigt:
127
+
128
+ - **Wert:** historische Messwerte aus dem konfigurierten History-Adapter.
129
+ - **Erwartungsbereich:** ein transparentes Band ausschließlich aus den zu jedem historischen Zeitpunkt gespeicherten `decisionLow`/`decisionHigh`-Grenzen. Fehlende Grenzen bleiben leer; der aktuelle Bereich wird nicht rückwirkend projiziert.
130
+ - **Kontext:** eine dezente Hervorhebung für Zeitabschnitte, deren gespeicherter Kontext zum aktuellen Kontext passt. Wenn vorhanden, werden die ioBroker-`common.name`-Namen angezeigt.
131
+ - **Anomalie:** ein rotes Dreieck nur bei historischen Bewertungen mit `detected: true`.
132
+
133
+ Beim Überfahren oder Berühren eines Punktes werden Wert und Einheit, historischer Erwartungsbereich (oder ein Hinweis, dass er nicht verfügbar ist), Status, übersetzter Grund, Score und Kontext für genau diesen Zeitpunkt angezeigt. Bei Wert-/Kontextabweichungen wird zusätzlich die konkrete Distanz oberhalb oder unterhalb des historischen Bereichs angegeben. Rate, Festhängend, Trend und Pegelverschiebung behalten ihre jeweilige Detektor-Erklärung.
134
+
135
+ ## Lernen und Persistenz
136
+
137
+ Normale Beobachtungen aktualisieren globale und zeitbasierte Baselines schrittweise. Messwerte ab dem Anomalie-Schwellenwert werden nicht gelernt. Pro Baseline werden höchstens 240 Samples und kompakte Modelldaten gespeichert; eine unbegrenzte Rohdaten-Zeitreihe wird nicht angelegt.
138
+
139
+ Alle erweiterten Detektoren sind standardmäßig deaktiviert. Kontextabhängige Erkennung kann bis zu drei boolesche, Text-/Enum- oder numerisch gebucketete Zustände getrennt lernen. Eine gültige, aber noch zu kleine Kontext-Baseline bleibt im Lernstatus. Pegelverschiebung benötigt wiederholte Evidenz; Trend benötigt mindestens 12 Residuen über sechs Stunden.
140
+
141
+ Der Adapter erkennt statistische Ungewöhnlichkeit, diagnostiziert aber keinen Gerätefehler und beweist keine Ursache. Ein History-Import trainiert nur globale, Zeit-, Wochentags- und Rate-Modelle. Kontextbaselines lernen aus Live-Werten, weil allgemeine History-Adapter beliebige Kontextzustände nicht zuverlässig zeitlich rekonstruieren können.
142
+
143
+ ## Optionen im Überblick
144
+
145
+ | Option | Zweck und Anwendung | Beispiel |
146
+ | --- | --- | --- |
147
+ | **Aktiviert** | Startet oder stoppt die Überwachung dieser Zeile. Deaktivierte Zeilen bleiben konfiguriert. | Während einer Wartung deaktivieren. |
148
+ | **Quellstatus-ID** | Numerischer ioBroker-Zustand, der bewertet wird. Über den Objekt-Picker auswählen. | `alias.0.pumpe.leistung` |
149
+ | **Name** | Lesbarer Name für das generierte Quellgerät; ändert nicht die Quell-ID. | `Gartenpumpe Leistung` |
150
+ | **Initiales Training** | Nur Live-Werte lernen oder vorhandene History importieren. | Für einen Power-Meter mit InfluxDB-History: History importieren. |
151
+ | **History-Quelle** | Kompatible, aktivierte History-Adapterinstanz für den Import. | `influxdb.0` |
152
+ | **Zeitraum des History-Trainings (Tage)** | Wie weit der Import zurückreicht. Nur repräsentative Normalzeiten auswählen. | `30` Tage |
153
+ | **Maximal importierte Proben** | Begrenzung des Imports zum Schutz von Speicher und Raspberry Pi. | `1000` |
154
+ | **Überwachung nach History-Import starten** | Startet nach ausreichendem Import direkt den Status `monitoring`. | Für eine etablierte Messreihe aktivieren. |
155
+ | **Mindestens gelernte Proben** | Mindestgröße einer vertrauenswürdigen Baseline. | `30` für häufige Leistungswerte. |
156
+ | **Zeit-Bucket-Größe (Minuten)** | Größe der Tageszeitbereiche. Kleinere Bereiche sind genauer, lernen aber langsamer. | `60` Minuten |
157
+ | **Sensitivität (robuster z-Score)** | Niedriger ist empfindlicher, höher toleranter. | Auf `5` erhöhen, wenn normale Schwankungen zu viele Meldungen erzeugen. |
158
+ | **Anomalie-Schwellenwert** | Score, ab dem eine Anomalie gespeichert und nicht mehr gelernt wird. | `70` |
159
+ | **Mindestdauer einer Anomalie (Minuten)** | Zeit, die die Schwelle überschritten sein muss, bevor `detected` dauerhaft gesetzt wird. | `5` Minuten |
160
+ | **Detektor für Wertabweichungen (MAD)** | Erkennt ungewöhnliche absolute Werte gegenüber dem gelernten Bereich. | Für Temperatur, Druck, Verbrauch und Leistung aktivieren. |
161
+ | **Detektor für Änderungsrate** | Erkennt ungewöhnlich schnelle Änderungen. | Für Durchfluss oder Füllstand aktivieren; bei normalen Lastsprüngen deaktiviert lassen. |
162
+ | **Detektor für festhängende Werte** | Erkennt wiederholt empfangene identische Werte über die konfigurierte Dauer. | Für regelmäßig wechselnde Sensoren aktivieren, nicht für lange konstante Setpoints. |
163
+ | **Dauer eines festhängenden Wertes** | Wird nur bei aktiviertem Festhängend-Detektor angezeigt; legt dessen Mindestdauer fest. | `120` Minuten |
164
+ | **Tageszeit-Kontext verwenden** | Trennt Baselines nach Tageszeit. | `60`-Minuten-Buckets für Haushaltsverbrauch. |
165
+ | **Wochentags-Kontext verwenden** | Trennt zusätzlich nach Wochentag; funktioniert zusammen mit dem Tageszeit-Kontext. | Büroverbrauch werktags gegenüber Wochenende. |
166
+ | **Kontextbezogene Erkennung aktivieren** | Lernt abhängig von bis zu drei weiteren Zuständen. | `pumpe.ein`, `modus`, Außentemperatur. |
167
+ | **Kontextzustände** | Die Zustände, die den Betriebszustand beschreiben. Boolesche und Enum-Werte benötigen keine Breite; numerische Werte verwenden Buckets. | `pumpe.ein=true`, Temperatur-Breite `5`. |
168
+ | **Dauerhafte Erkennung von Pegelverschiebungen** | Erkennt ein anhaltend verändertes Betriebsniveau. | Standby-Leistung dauerhaft von 5 W auf 12 W gestiegen. |
169
+ | **Trenderkennung aktivieren** | Erkennt langsame Aufwärts- oder Abwärtsentwicklung über Residuen. | Heizdauer steigt über mehrere Tage. |
170
+
171
+ ### Konfigurationsgrundsätze
172
+
173
+ 1. Beginne mit den Standarddetektoren und aktiviere nur Verfahren, die zum physikalischen Verhalten der überwachten Quelle passen.
174
+ 2. Aktiviere nicht jeden verfügbaren Detektor nur deshalb, weil er vorhanden ist.
175
+ 3. Füge Kontextzustände nur hinzu, wenn sie den erwarteten Wert erklären; mehr Kontext bedeutet weniger Trainingsdaten pro Kontext.
176
+ 4. Starte mit der Standardsensitivität und dem Standardschwellenwert. Erhöhe die Toleranz erst, nachdem legitime Fehlalarme beobachtet wurden.
177
+ 5. Verwende History-Training nur, wenn der ausgewählte Zeitraum den normalen Betrieb repräsentiert und nicht überwiegend bekannte Fehler- oder Installationsphasen enthält.
178
+ 6. Eine statistische Anomalie zeigt ein ungewöhnliches Verhalten relativ zu den Lerndaten. Sie beweist weder einen Gerätefehler noch dessen Ursache.
179
+
180
+ ### Einrichtung mit einem KI-Assistenten
181
+
182
+ Ein KI-Assistent kann anhand dieser README und deines Anwendungsfalls eine erste Konfiguration vorschlagen. Nenne dafür die physikalische Größe, die Bedeutung der Quelle, deren Update-Häufigkeit, relevante ioBroker-Kontextzustände, ob schnelle Änderungen oder lange konstante Phasen normal sind, ob Tages- oder Wochenmuster bestehen, ob dauerhafte Pegelverschiebungen oder langsame Trends relevant sind und ob historische Daten verfügbar sind.
183
+
184
+ KI-generierte Einstellungen sind nur ein Ausgangspunkt und müssen mit dem tatsächlichen Geräteverhalten abgeglichen werden. Der Adapter selbst bleibt deterministisch und verwendet keine KI.
185
+
186
+ Beispiel-Prompt:
187
+
188
+ > Ich möchte den elektrischen Leistungsverbrauch einer Pumpe überwachen. Der Ein-/Aus-Zustand und die Betriebsart der Pumpe sind als zusätzliche ioBroker-Zustände verfügbar. Start- und Stoppvorgänge verursachen schnelle, aber normale Leistungsänderungen. Eine dauerhafte Abweichung von der üblichen Betriebsleistung wäre relevant. Für die letzten 30 Tage liegt History in InfluxDB vor. Empfiehl mir auf Grundlage dieser README passende Einstellungen für anomaly-detection und erkläre jede Auswahl.
189
+
190
+ ### Auswahlhilfe für Detektoren
191
+
192
+ - **MAD/Wertabweichungen:** Für unerwartete Einzelwerte relativ zum gelernten Normalverhalten.
193
+ - **Änderungsrate:** Wenn ungewöhnlich schnelle Änderungen relevant sind; deaktivieren, wenn schnelle Änderungen normal sind.
194
+ - **Festhängend:** Für Sensoren, die sich regelmäßig verändern müssen; nicht für Werte, die lange legitim konstant bleiben.
195
+ - **Kontextbezogen:** Wenn ein anderer Zustand das erwartete Verhalten erklärt. Boolesche/Enum-Kontexte beschreiben Betriebsart oder Anwesenheit, numerische Kontexte zum Beispiel Außentemperatur, Ladezustand oder Last.
196
+ - **Pegelverschiebung:** Für dauerhafte Änderungen des normalen Betriebsniveaus.
197
+ - **Trend:** Für langsame Drift oder Verschlechterung; bei stark schwankenden Signalen meist deaktiviert lassen.
198
+
199
+ ### Praxisbeispiel: Pumpenleistung
200
+
201
+ Für die elektrische Leistung einer Pumpe sind zunächst **Detektor für Wertabweichungen**, **kontextbezogene Erkennung** und **dauerhafte Erkennung von Pegelverschiebungen** sinnvoll. **Detektor für Änderungsrate**, **Detektor für festhängende Werte** und **Trenderkennung** bleiben zunächst deaktiviert, weil normale Start-/Stoppvorgänge schnelle Änderungen verursachen und eine ausgeschaltete Pumpe legitim bei `0 W` stehen kann.
202
+
203
+ Als Kontext eignen sich der Ein-/Aus-Zustand und die Betriebsart. So entstehen getrennte Normalmodelle für beispielsweise Pumpe AUS, Pumpe EIN im Normalbetrieb und Pumpe EIN im Boost-Modus. Weitere Zustände nur hinzufügen, wenn sie die erwartete Leistung nachweislich erklären; zu viele Kontextzustände verteilen die Samples auf zu viele Kombinationen.
204
+
205
+ ## Optionales History-Training
206
+
207
+ Für eine Quelle **Vorhandene History importieren** auswählen und danach eine **History-Quelle** aus der Auswahlliste wählen. Die Liste enthält nur vollständige, aktivierte History-Provider wie `influxdb.0`, `history.0` oder `sql.1`, die für genau diesen Zustand aktiviert sind. Wenn keine Quelle angezeigt wird, ist für den Zustand oder sein Alias-Ziel keine kompatible History aktiviert; **Nur Live-Werte lernen** bleibt trotzdem verfügbar.
208
+
209
+ Standardmäßig werden 30 Tage und höchstens 1.000 Samples importiert. Ungültige Werte und Zeitstempel werden verworfen, doppelte Zeitstempel zusammengeführt und übergroße Ergebnismengen gleichmäßig über den gesamten Zeitraum verteilt. Offensichtliche historische Extremwerte werden vor dem Lernen robust ausgeschlossen. Große Zeitlücken erzeugen niemals eine Festhängend-Anomalie.
210
+
211
+ Ein importiertes Modell wird nach einem Neustart wiederverwendet. Eine Änderung von History-Quelle, Zeitraum oder Sample-Limit startet einen neuen Import. Bei fehlgeschlagenem oder zu kleinem Import bleibt die Quelle nutzbar und lernt live weiter. Über `sources.<sanitized-source-id>.retrain = true` kann ein Modell ausdrücklich verworfen und neu trainiert werden; der Adapter setzt den Wert anschließend mit `ack=true` auf `false` zurück.
212
+
213
+ ## Erzeugte Objekte
214
+
215
+ Für jede Quelle legt der Adapter unter folgendem Pfad eine sichere, deterministische Objekt-ID an:
216
+
217
+ `anomaly-detection.0.sources.<sanitized-source-id>.analysis`
218
+
219
+ | State | Typ/Rolle | Bedeutung |
220
+ | --- | --- | --- |
221
+ | `actual` | number / `value` | zuletzt akzeptierter Quellwert |
222
+ | `expected` | number / `value` | Median der verwendeten Baseline |
223
+ | `deviation` | number / `value` | `actual - expected` |
224
+ | `score` | number / `value` | normierter Anomalie-Score 0–100 |
225
+ | `detected` | boolean / `indicator` | persistente Anomalieanzeige |
226
+ | `status` | string / `info.status` | `insufficientData`, `learning` oder `monitoring` |
227
+ | `reason` | string / `text` | deterministische Erklärung der aktuellen Bewertung |
228
+ | `lastAnomaly` | string / `date` | Zeitpunkt der letzten hohen Bewertung |
229
+ | `sampleCount` | number / `value` | gespeicherte globale Samples, maximal 240 |
230
+ | `baselineScope` | string / `info.status` | verwendete Baseline: `context`, `time`, `global` oder `insufficient` |
231
+ | `activeContext` | string / `text` | aktueller normalisierter Kontext |
232
+ | `baselineSampleCount` | number / `value` | Samples der tatsächlich verwendeten Baseline |
233
+ | `contextSampleCount` | number / `value` | Samples im passenden Kontextmodell |
234
+ | `bootstrapStatus` | string / `info.status` | Ergebnis des optionalen History-Imports |
235
+ | `retrain` | boolean / `button` | `true` schreiben, um Quelle und Modell zurückzusetzen |
236
+
237
+ Alle vom Adapter geschriebenen Ergebnis-States verwenden `ack=true`. `retrain` ist der einzige Befehls-State und wird nach der Verarbeitung zurückgesetzt.
238
+
239
+ ## Einschränkungen und Datenschutz
240
+
241
+ Eine Anomalie bedeutet, dass ein Wert oder Verhalten relativ zu den gelernten Beobachtungen ungewöhnlich ist. Sie beweist weder einen Gerätefehler noch dessen Ursache. Ungeeignete Einstellungen, nicht repräsentative Trainingszeiträume oder sich änderndes Anlagenverhalten können Fehlalarme oder übersehene Anomalien verursachen.
242
+
243
+ Verarbeitung und Modellspeicherung erfolgen vollständig lokal in ioBroker. Kein Messwert wird an einen externen KI-, Analyse- oder Cloud-Dienst gesendet.
244
+
245
+ ## Changelog
246
+
247
+ ### 0.3.0 (2026-09-08)
248
+
249
+ - Optionale lokale Predictive-Prognosen mit persistenten Modellen und Trainingsbasen ergänzt.
250
+ - History-basiertes Initialtraining, Wiederherstellung nach Neustarts, Rolling-Retraining und die Anzeige der Trainingsquelle verbessert.
251
+ - Robustes History-Bootstrap mit segmentierten Provider-Abfragen, Coverage-Probes, Deduplizierung und adaptiver Segmentierung ergänzt.
252
+ - Erklärbarkeit und Diagnosen der Anomalieerkennung verbessert, einschließlich kontextbezogener Sample-Reichweite und Bewertungsverfügbarkeit.
253
+
254
+ ### 0.2.1 (2026-09-08)
255
+
256
+ - Aktuelle Anomaliebewertungen, erklärende Details und responsive Verlaufsdiagramme ergänzt.
257
+ - `Normal` wird als Grund für niedrige Scores angezeigt.
258
+ - Kontext-, Entscheidungsbereich- und History-Daten für die Analyseansicht erweitert.
259
+ - Absturz in der Analyseansicht behoben, wenn ein Kontextzustand `null` oder ungültig ist.
260
+
261
+ ### 0.1.1 (2026-09-07)
262
+
263
+ - Konfigurationsoberfläche, Layout und Übersetzungen verbessert.
264
+ - Detektor-Hinweise und kontextabhängige Optionsanzeige ergänzt.
265
+
266
+ ### 0.1.0 (2026-09-06)
267
+
268
+ - Lokale statistische Anomalieerkennung als MVP.
269
+ - Optionales, begrenztes History-Training.
270
+ - Auswahl aktivierter History-Quellen pro konfiguriertem Zustand.
271
+
272
+ ## Lizenz
273
+
274
+ MIT License
275
+
276
+ Copyright (c) 2026 Voodoo2man <Voodoo2man@outlook.de>
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  # ioBroker.anomaly-detection
4
4
 
5
+ [English](README.md) · **Deutsch** ([README.de.md](README.de.md))
6
+
5
7
  [![NPM version](https://img.shields.io/npm/v/iobroker.anomaly-detection.svg)](https://www.npmjs.com/package/iobroker.anomaly-detection)
6
8
 
7
9
  Learns the normal behaviour of selected numerical ioBroker states and reports statistically unusual values locally.
@@ -325,10 +327,18 @@ Processing and model storage are completely local to ioBroker. No monitored valu
325
327
 
326
328
  ## Changelog
327
329
 
328
- ### 0.2.0 (unreleased)
330
+ ### 0.3.0 (2026-09-08)
331
+
332
+ - Add optional local predictive forecasting with persistent models and training bases.
333
+ - Improve history-based initial training, restart recovery, rolling retraining, and history/live training-source reporting.
334
+ - Add robust history bootstrapping with segmented provider-limit handling, coverage probes, deduplication, and adaptive segmentation.
335
+ - Improve anomaly explainability and diagnostics, including context-aware sample scope and evaluation availability.
336
+
337
+ ### 0.2.1 (2026-09-08)
329
338
 
330
339
  - Report `Normal` as the current reason for scores below 50 instead of showing a technical detector message for a minor deviation.
331
340
  - Improve analysis charts, historical explanations, and responsive layout.
341
+ - Fix a crash in the analysis view when a context-state entry is `null` or invalid.
332
342
 
333
343
  ### 0.1.1 (2026-09-07)
334
344
 
@@ -0,0 +1,3 @@
1
+ import"../customComponents.js";import{_ as r,a as o,b as O}from"./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-3izusDYF.js";import{_ as B,a as we,b as _e,c as ae,d as se,e as Ce}from"./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare__react__loadShare__.js-B1BcPa9n.js";import{a as G,b as F,c as s,d as L,e as ie,f as R,g as me,h as ve,i as fe,j as pe,k as ye}from"./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare___mf_0_mui_mf_1_material__loadShare__.js-Czolif-c.js";import{_ as ke,a as be,b as ge}from"./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare___mf_0_mui_mf_1_icons_mf_2_material__loadShare__.js-gzeYEwNX.js";import"./vite-preload-helper-ckwbz45p.js";import"./index-wphymIgy.js";function xe(t,i=[],h={}){const u=[...t,...i].filter(b=>Number.isFinite(b));if(u.length===0)return{min:0,max:1};const a=Math.min(...u),v=Math.max(...u),l=v-a||Math.max(1,Math.abs(v)*.01),p=a-l*.05;return{min:h.floorAtZero===!1?Math.max(0,p):a>=0?0:p,max:v+l*.05}}const le={en:{"reason.normal":"The value behaves as expected.","reason.insufficient_training_data":"I am still collecting data before rating this state reliably.","reason.unexpected_value":"The current value is outside the usual range.","reason.unexpected_low":"The current value is unusually low.","reason.unexpected_high":"The current value is unusually high.","reason.context_deviation":"The current value is unusual for this context.","reason.context_low":"The current value is unusually low for this context.","reason.context_high":"The current value is unusually high for this context.","reason.unexpected_rate_change":"The value is changing unusually quickly.","reason.stuck_value":"The value has not changed for longer than expected.","reason.persistent_level_shift":"A persistent change in the normal level was detected.","reason.unusual_trend":"An unusual long-term trend was detected.","reason.multiple_detectors":"Several detectors jointly indicate unusual behavior.","status.learning":"Learning","status.normal":"Normal","status.deviating":"Conspicuous","status.anomaly":"Anomaly","status.insufficient_data":"Insufficient data","status.unavailable":"No current assessment",title:"Current anomaly assessments",refresh:"Refresh",empty:"No assessment is available yet for the configured states.",current:"Current",decisionRange:"MAD decision range",chartValue:"Value",chartExpected:"Expected range",chartAnomaly:"Anomaly",chartStatus:"Status",chartReason:"Reason",chartAssessment:"Assessment",chartDeviation:"Deviation",chartExpectedUnavailable:"Historical expected range not available","deviation.below":"below the expected range","deviation.above":"above the expected range",chartContext:"Assessment context",historicalAnomaliesOne:"%s conspicuous measurement in the selected period",historicalAnomaliesMany:"%s conspicuous measurements in the selected period",chartNoContext:"Historical context information is not available for this period.",chartNow:"Now",chartNormalExplanation:"The value is within the expected range.",chartDeviating:"Conspicuous",pendingExplanation:"The deviation is being observed and has not yet been confirmed as an anomaly.",unavailableExplanation:"No current assessment is available for this state yet.",learned:"%s of at least %s required samples learned",learnedContext:"%s of at least %s required samples learned for this state",basedOn:"Based on %s samples",predictive:"Forecast",predictive_ready:"Ready",predictive_learning:"Learning",predictive_unreliable:"Limited",predictive_error:"Error",predictive_disabled:"Forecast disabled",forecastExpectedIn:"Expected in %s",forecastHoursShort:"+%s h",forecastMinutesShort:"+%s min",forecastQualityGood:"Forecast quality: Good",forecastQualityLimited:"Forecast quality: Limited",forecastQualityPoor:"Forecast quality: Not reliable",forecastQualityUnknown:"Forecast quality: Not yet assessable",qualityGood:"Good",qualityLimited:"Limited",qualityPoor:"Not reliable",qualityUnknown:"Not yet assessable",forecastLimitedExplanation:"The forecast is currently only of limited reliability.",forecastNotReliable:"The forecast is currently not reliable.",forecastError:"The forecast could not be calculated.",forecastNow:"Now",predictiveDetails:"Technical details",model:"Model",selectedModel:"Selected model",modelLevelTrend:"Level/trend",modelSeasonal:"Cyclic",modelTimeOfDay:"Time of day profile",modelInterval:"Model interval",rawInterval:"Raw data interval",historySpan:"History span",requestedHistorySpan:"Requested history span",daysCovered:"Days covered",bucketCount:"Time buckets",bucketCoverage:"Bucket coverage",trainingSamples:"Training samples",lastTraining:"Last training",trainingSource:"Training source",bootstrapReason:"Bootstrap reason",modelVersion:"Model version",sourceHistory:"History",sourcePersisted:"Persisted model",sourceLive:"Live values",sourceMixed:"History + live values",seasonality:"Seasonality",seasonalityMode:"Mode",seasonalityOff:"Off",seasonalityAuto:"Automatic",seasonalityManual:"Manual",periodDetected:"Period detected",detectedPeriod:"Detected period",periodicityScore:"Periodicity score",peakProminence:"Peak prominence",harmonicPeaks:"Confirmed harmonic peaks",secondBestPeriod:"Second-best period",secondBestScore:"Second-best score",detrended:"Detrended before detection",acfNeighbourScores:"ACF around candidate",lowerBoundary:"At lower search boundary",completePeriods:"Complete cycles",seasonalityUsed:"Used for forecast",backtest:"Backtest",levelTrend:"Level/trend",seasonal:"Cyclic",mae:"MAE",normalizedError:"Normalized error",qualityScaleNearZero:"Low historical spread; normalized quality is limited",holdoutSamples:"Holdout samples",notAvailable:"Not available",selection:"Selection",qualityClass:"Quality class",relativeError:"Relative error",qualityScale:"Quality scale",scaleSource:"Scale source",scaleSource_iqr:"IQR",scaleSource_p95p05:"P95–P05",scaleSource_mad:"MAD",scaleSource_range:"Observed range",scaleSource_none:"None",selectionSeasonalBetter:"The cyclic model was more accurate in backtesting.",selectionLevelTrendBetter:"The level/trend model was more accurate in backtesting.",selectionNoPeriodicity:"No sufficiently stable repetition was detected.",selectionInsufficientCycles:"There are not enough complete cycles for reliable detection.",selectionInsufficientSeasonalData:"There are not enough seasonal samples yet.",selectionSeasonalityDisabled:"Seasonality is disabled for this state.",selectionManualSeasonality:"A manually configured period is being used.",selectionSeasonalBacktestFailed:"The cyclic backtest was not available.",selectionSeasonalNotBetterEnough:"The cyclic model was not sufficiently better in backtesting.",minutesShort:"min",yes:"Yes",no:"No",currentView:"Current",forecastView:"Forecast",forecastHorizon:"Forecast horizon",forecastQuality:"Model quality (MAE)",comparisonSamples:"Comparison based on %s similar samples",context:"Compared with context: %s",since:"Anomalous since %s",details:"Technical details",overall:"Overall score",baseline:"Baseline",baseline_context:"Context-based",baseline_time:"Time-based",baseline_global:"Global fallback",baseline_insufficient:"Insufficient baseline",baseline_learning:"still learning",valueDeviation:"Value deviation",contextDeviation:"Context deviation",rateDeviation:"Rate of change",stuckDetection:"Stuck-state detection",levelShift:"Persistent level shift",trendDetection:"Trend detection",samples:"samples",contextSamples:"Context samples",lastEvaluation:"Last evaluation",activeDetectors:"Active detectors",loadError:"The anomaly assessments could not be loaded.",chart:"History & anomalies",chartUnavailable:"No history data is available for this state.",chartNoBounds:"Historical decision bounds are not available for this period.",hour:"1 h",sixHours:"6 h",day:"24 h",week:"7 days"},de:{"reason.normal":"Der Wert verhält sich wie erwartet.","reason.insufficient_training_data":"Ich sammle noch Daten, bevor ich diesen Datenpunkt zuverlässig bewerten kann.","reason.unexpected_value":"Der aktuelle Wert liegt außerhalb des üblichen Bereichs.","reason.unexpected_low":"Der aktuelle Wert ist ungewöhnlich niedrig.","reason.unexpected_high":"Der aktuelle Wert ist ungewöhnlich hoch.","reason.context_deviation":"Der aktuelle Wert ist für diesen Zustand ungewöhnlich.","reason.context_low":"Der aktuelle Wert ist für diesen Zustand ungewöhnlich niedrig.","reason.context_high":"Der aktuelle Wert ist für diesen Zustand ungewöhnlich hoch.","reason.unexpected_rate_change":"Der Wert verändert sich ungewöhnlich schnell.","reason.stuck_value":"Der Wert hat sich länger als erwartet nicht verändert.","reason.persistent_level_shift":"Eine dauerhafte Veränderung des normalen Niveaus wurde erkannt.","reason.unusual_trend":"Ein ungewöhnlicher längerfristiger Trend wurde erkannt.","reason.multiple_detectors":"Mehrere Detektoren weisen gemeinsam auf ein ungewöhnliches Verhalten hin.","status.learning":"Lernt noch","status.normal":"Normal","status.deviating":"Auffällig","status.anomaly":"Anomalie","status.insufficient_data":"Zu wenig Daten","status.unavailable":"Keine aktuelle Bewertung",title:"Aktuelle Anomaliebewertungen",refresh:"Aktualisieren",empty:"Für die konfigurierten Datenpunkte liegt noch keine Bewertung vor.",current:"Aktuell",decisionRange:"Erwarteter Bereich",chartValue:"Messwert",chartExpected:"Erwarteter Bereich",chartAnomaly:"Anomalie",chartStatus:"Status",chartReason:"Grund",chartAssessment:"Bewertung",chartDeviation:"Abweichung",chartExpectedUnavailable:"Historischer erwarteter Bereich nicht verfügbar","deviation.below":"unter dem erwarteten Bereich","deviation.above":"über dem erwarteten Bereich",chartContext:"Bewertungskontext",historicalAnomaliesOne:"%s auffälliger Messpunkt im gewählten Zeitraum",historicalAnomaliesMany:"%s auffällige Messpunkte im gewählten Zeitraum",chartNoContext:"Für diesen Zeitraum sind keine historischen Kontextinformationen verfügbar.",chartNow:"Jetzt",chartNormalExplanation:"Der Wert liegt im erwarteten Bereich.",chartDeviating:"Auffällig",pendingExplanation:"Die Abweichung wird beobachtet und ist noch nicht als Anomalie bestätigt.",unavailableExplanation:"Für diesen Datenpunkt liegt noch keine aktuelle Bewertung vor.",learned:"%s von mindestens %s benötigten Messwerten gelernt",learnedContext:"%s von mindestens %s benötigten Messwerten für diesen Zustand gelernt",basedOn:"Basierend auf %s Messwerten",predictive:"Prognose",predictive_ready:"Bereit",predictive_learning:"Lernt noch",predictive_unreliable:"Eingeschränkt",predictive_error:"Fehler",predictive_disabled:"Prognose deaktiviert",forecastExpectedIn:"In %s voraussichtlich",forecastHoursShort:"+%s h",forecastMinutesShort:"+%s Min.",forecastQualityGood:"Prognosequalität: Gut",forecastQualityLimited:"Prognosequalität: Eingeschränkt",forecastQualityPoor:"Prognosequalität: Nicht zuverlässig",forecastQualityUnknown:"Prognosequalität: Noch nicht bewertbar",qualityGood:"Gut",qualityLimited:"Eingeschränkt",qualityPoor:"Nicht zuverlässig",qualityUnknown:"Noch nicht bewertbar",forecastLimitedExplanation:"Die Prognose ist derzeit nur eingeschränkt zuverlässig.",forecastNotReliable:"Die Prognose ist derzeit nicht zuverlässig.",forecastError:"Die Prognose konnte nicht berechnet werden.",forecastNow:"Jetzt",predictiveDetails:"Technische Details",model:"Modell",selectedModel:"Gewähltes Modell",modelLevelTrend:"Level/Trend",modelSeasonal:"Zyklisch",modelTimeOfDay:"Tageszeitprofil",modelInterval:"Modellintervall",rawInterval:"Rohdatenintervall",historySpan:"History-Zeitraum",requestedHistorySpan:"Angeforderter History-Zeitraum",daysCovered:"Abgedeckte Tage",bucketCount:"Zeit-Buckets",bucketCoverage:"Bucket-Abdeckung",trainingSamples:"Trainingswerte",lastTraining:"Letztes Training",trainingSource:"Trainingsquelle",bootstrapReason:"Bootstrap-Grund",modelVersion:"Modellversion",sourceHistory:"History",sourcePersisted:"Persistiertes Modell",sourceLive:"Live-Werte",sourceMixed:"History + Live-Werte",seasonality:"Saisonalität",seasonalityMode:"Modus",seasonalityOff:"Aus",seasonalityAuto:"Automatisch",seasonalityManual:"Manuell",periodDetected:"Periode erkannt",detectedPeriod:"Erkannte Periode",periodicityScore:"Periodizitätsbewertung",peakProminence:"Peak-Prominenz",harmonicPeaks:"Bestätigte harmonische Peaks",secondBestPeriod:"Zweitbeste Periode",secondBestScore:"Zweitbester Score",detrended:"Vor der Erkennung detrendet",acfNeighbourScores:"ACF um den Kandidaten",lowerBoundary:"Am unteren Suchrand",completePeriods:"Vollständige Zyklen",seasonalityUsed:"Für Prognose verwendet",backtest:"Backtest",levelTrend:"Level/Trend",seasonal:"Zyklisch",mae:"MAE",normalizedError:"Normalisierter Fehler",qualityScaleNearZero:"Sehr geringe historische Streuung; normalisierte Qualität ist eingeschränkt aussagekräftig",holdoutSamples:"Holdout-Testwerte",notAvailable:"Nicht verfügbar",selection:"Auswahl",qualityClass:"Qualitätsklasse",relativeError:"Relativer Fehler",qualityScale:"Qualitätsskala",scaleSource:"Skalenquelle",scaleSource_iqr:"IQR",scaleSource_p95p05:"P95–P05",scaleSource_mad:"MAD",scaleSource_range:"Beobachteter Wertebereich",scaleSource_none:"Keine",selectionSeasonalBetter:"Das zyklische Modell war im Backtest genauer.",selectionLevelTrendBetter:"Das Level-/Trendmodell war im Backtest genauer.",selectionNoPeriodicity:"Es wurde keine ausreichend stabile Wiederholung erkannt.",selectionInsufficientCycles:"Für eine zuverlässige Erkennung liegen noch nicht genügend vollständige Zyklen vor.",selectionInsufficientSeasonalData:"Für eine saisonale Bewertung liegen noch nicht genügend Messwerte vor.",selectionSeasonalityDisabled:"Saisonalität ist für diesen Datenpunkt deaktiviert.",selectionManualSeasonality:"Eine manuell konfigurierte Periode wird verwendet.",selectionSeasonalBacktestFailed:"Der zyklische Backtest war nicht verfügbar.",selectionSeasonalNotBetterEnough:"Das zyklische Modell war im Backtest nicht ausreichend besser.",minutesShort:"Min.",yes:"Ja",no:"Nein",currentView:"Aktuell",forecastView:"Prognose",forecastHorizon:"Prognosehorizont",forecastQuality:"Modellgüte (MAE)",comparisonSamples:"Vergleich basiert auf %s ähnlichen Messungen",context:"Verglichen mit Kontext: %s",since:"Auffällig seit %s",details:"Technische Details",overall:"Gesamtbewertung",baseline:"Baseline",baseline_context:"Kontextbezogen",baseline_time:"Zeitabhängig",baseline_global:"Globale Fallback-Baseline",baseline_insufficient:"Baseline noch nicht reif",baseline_learning:"lernt noch",valueDeviation:"Wertabweichung",contextDeviation:"Abweichung im aktuellen Kontext",rateDeviation:"Änderungsgeschwindigkeit",stuckDetection:"Festhängender Wert",levelShift:"Dauerhafte Pegelverschiebung",trendDetection:"Trenderkennung",samples:"Samples",contextSamples:"Kontext-Samples",lastEvaluation:"Letzte Bewertung",activeDetectors:"Aktive Detektoren",loadError:"Die Anomaliebewertungen konnten nicht geladen werden.",chart:"Verlauf & Anomalien",chartUnavailable:"Für diesen Datenpunkt sind keine Verlaufsdaten verfügbar.",chartNoBounds:"Für diesen Zeitraum sind keine historischen Bewertungsgrenzen verfügbar.",hour:"1 h",sixHours:"6 h",day:"24 h",week:"7 Tage"}};function Y(){return(typeof navigator<"u"?navigator.language:"en").slice(0,2).toLowerCase()}function e(t,...i){var a;let u=((a=le[Y()])==null?void 0:a[t])||le.en[t]||t;for(const v of i)u=u.replace("%s",String(v));return u}function Se(t,i){return t&&e(`reason.${t}`)||i||e("empty")}function ce(t){if(t.statusCode==="unavailable")return e("unavailableExplanation");if(t.statusCode==="normal")return e("reason.normal");if((t.reasonCode==="context_deviation"||t.reasonCode==="unexpected_value")&&t.actual!==void 0&&t.expected!==void 0){const i=t.actual<t.expected?"low":"high",h=t.reasonCode==="context_deviation"?`reason.context_${i}`:`reason.unexpected_${i}`,u=e(h);if(u!==h)return u}return Se(t.reasonCode,t.reason)}function De(t){return t?e(`baseline_${t}`):"–"}function $e(t){return t.name==="context"||t.reasonCode==="context_deviation"?e("contextDeviation"):t.name==="value"||t.reasonCode==="unexpected_value"?e("valueDeviation"):t.name==="rate"||t.reasonCode==="unexpected_rate_change"?e("rateDeviation"):t.name==="stuck"||t.reasonCode==="stuck_value"?e("stuckDetection"):t.name==="changePoint"||t.reasonCode==="persistent_level_shift"?e("levelShift"):t.name==="trend"||t.reasonCode==="unusual_trend"?e("trendDetection"):t.name}function oe(t,i){return t.split("|").map(h=>{const u=h.lastIndexOf("=");if(u<0)return h;const a=h.slice(0,u),v=h.slice(u+1),l=(i==null?void 0:i[a])||a;return v==="true"?`${l} – ${Y()==="de"?"eingeschaltet":"on"}`:v==="false"?`${l} – ${Y()==="de"?"ausgeschaltet":"off"}`:`${l}=${v}`}).join(", ")}function de(t,i,h){const u=[re(t.timestamp),`${e("chartValue")}: ${z(t.value)}${h.unit?` ${h.unit}`:""}`];if(!i)return u.join(`
2
+ `);i.decisionLow!==void 0&&i.decisionHigh!==void 0?u.push(`${e("chartExpected")}: ${z(i.decisionLow)}–${z(i.decisionHigh)}${h.unit?` ${h.unit}`:""}`):u.push(e("chartExpectedUnavailable"));const a=i.statusCode||(i.detected?"anomaly":"normal");if(u.push(`${e("chartStatus")}: ${e(`status.${a}`)}`),a!=="normal"){if(u.push(`${e("chartReason")}: ${Se(i.reasonCode)}`),(i.reasonCode==="unexpected_value"||i.reasonCode==="context_deviation")&&i.decisionLow!==void 0&&i.decisionHigh!==void 0){const l=t.value<i.decisionLow?i.decisionLow-t.value:t.value-i.decisionHigh,p=t.value<i.decisionLow?"below":"above";u.push(`${e("chartDeviation")}: ${z(l)}${h.unit?` ${h.unit}`:""} ${e(`deviation.${p}`)}`)}}else u.push(`${e("chartReason")}: ${e("chartNormalExplanation")}`);return i.score!==void 0&&u.push(`${e("chartAssessment")}: ${z(i.score)} %`),i.activeContext&&u.push(`${e("context")}: ${oe(i.activeContext,h.contextLabels)}`),u.join(`
3
+ `)}function Me({source:t,socket:i,target:h,refreshKey:u}){var x;const[a,v]=B(!1),[l,p]=B(24),[b,f]=B(),[T,S]=B(600),N=se(new Map),C=se(null);ae(()=>{if(!a||!C.current||typeof ResizeObserver>"u")return;const n=()=>{var I;const _=(I=C.current)==null?void 0:I.clientWidth;_&&_>0&&S(_)};n();const m=new ResizeObserver(n);return m.observe(C.current),()=>m.disconnect()},[a]),ae(()=>{N.current.clear(),a&&f(void 0)},[u]),ae(()=>{if(!a||!(i!=null&&i.sendTo))return;const n=N.current.get(l);if(n){f(n);return}i.sendTo(h,"chartData",{sourceId:t.id,start:Date.now()-l*36e5,end:Date.now(),limit:500}).then(m=>{N.current.set(l,m.data),f(m.data)})},[l,a,u,i,t.id,h]);const d=(b==null?void 0:b.samples)||[],D=(b==null?void 0:b.diagnostics)||[],y=d.map(n=>n.value);if(!a)return o(L,{size:"small",onClick:()=>v(!0),sx:{mt:1},children:e("chart")});if(!(b!=null&&b.available))return r(G,{sx:{mt:1},children:[o(L,{size:"small",onClick:()=>v(!1),children:e("chart")}),o(ie,{severity:"info",sx:{mt:1},children:e("chartUnavailable")})]});if(!d.length)return r(G,{sx:{mt:1},children:[o(L,{size:"small",onClick:()=>v(!1),children:e("chart")}),o(ie,{severity:"info",sx:{mt:1},children:e("chartUnavailable")})]});const c=D.filter(n=>n.timestamp>=d[0].timestamp&&n.timestamp<=d[d.length-1].timestamp),$=t.evaluation.activeContext,M=[];for(let n=0;n<c.length;n++){const m=c[n];if(!$||m.activeContext!==$)continue;const _=((x=c[n+1])==null?void 0:x.timestamp)??d[d.length-1].timestamp;M.push({start:m.timestamp,end:_})}const q=c.filter(n=>n.decisionLow!==void 0&&n.decisionHigh!==void 0),H=[];let V=!1;for(const n of c){if(n.decisionLow===void 0||n.decisionHigh===void 0){V=!0;continue}const m=H[H.length-1];V||!m||m[m.length-1].timestamp<n.timestamp-7200*1e3?(H.push([n]),V=!1):m.push(n)}const U=xe(y,q.flatMap(n=>[n.decisionLow,n.decisionHigh])),W=U.min,j=U.max,X=j-W,P=44,Z=Math.max(P+40,T-8),w=n=>P+(n-d[0].timestamp)/Math.max(1,d[d.length-1].timestamp-d[0].timestamp)*(Z-P),E=n=>84-(n-W)/X*76,ee=n=>{let m,_=Number.POSITIVE_INFINITY;for(const I of c){const J=Math.abs(I.timestamp-n);J<_&&(m=I,_=J)}return m},te=d.map(n=>`${w(n.timestamp)},${E(n.value)}`).join(" "),K=n=>new Date(n).toLocaleString(void 0,{dateStyle:l>24?"short":void 0,timeStyle:"short"}),ne=c.filter((n,m)=>m>0&&n.activeContext!==c[m-1].activeContext),Q=c.filter(n=>n.statusCode==="anomaly"||!n.statusCode&&n.detected).length,k=c.filter(n=>n.statusCode==="deviating").length;return r(G,{ref:C,sx:{mt:1,width:"100%"},children:[r(F,{direction:"row",spacing:.5,alignItems:"center",children:[o(L,{size:"small",onClick:()=>v(!1),children:e("chart")}),[[1,"hour"],[6,"sixHours"],[24,"day"],[168,"week"]].map(([n,m])=>o(L,{size:"small",variant:l===n?"contained":"text",onClick:()=>p(Number(n)),children:e(m)},String(n)))]}),r("svg",{viewBox:`0 0 ${T} 100`,width:"100%",height:"220",role:"img","aria-label":e("chart"),style:{background:"rgba(127,127,127,0.08)",marginTop:8},children:[o("line",{x1:P,y1:"8",x2:P,y2:"84",stroke:"currentColor",opacity:"0.35"}),o("line",{x1:P,y1:"84",x2:Z,y2:"84",stroke:"currentColor",opacity:"0.35"}),o("text",{x:P,y:"96",fontSize:"3",fill:"currentColor",children:K(d[0].timestamp)}),o("text",{x:Z,y:"96",textAnchor:"end",fontSize:"3",fill:"currentColor",children:K(d[d.length-1].timestamp)}),r("text",{x:"1",y:"10",fontSize:"3",fill:"currentColor",children:[z(j),t.unit?` ${t.unit}`:""]}),r("text",{x:"1",y:"84",fontSize:"3",fill:"currentColor",children:[z(W),t.unit?` ${t.unit}`:""]}),H.map((n,m)=>o(Ce.Fragment,{children:o("polygon",{fill:"#90caf9",opacity:"0.12",points:[...n.map(_=>`${w(_.timestamp)},${E(_.decisionLow)}`),...n.slice().reverse().map(_=>`${w(_.timestamp)},${E(_.decisionHigh)}`)].join(" ")})},`bounds-${m}`)),M.map(n=>o("rect",{x:w(n.start),width:Math.max(.2,w(n.end)-w(n.start)),y:"8",height:"76",fill:"#ab47bc",opacity:"0.08",children:o("title",{children:e("chartContext")})},`context-band-${n.start}`)),o("polyline",{fill:"none",stroke:"#2196f3",strokeWidth:"1.5",points:te,children:o("title",{children:e("chartValue")})}),ne.map(n=>o("line",{x1:w(n.timestamp),x2:w(n.timestamp),y1:"8",y2:"84",stroke:"#ab47bc",strokeDasharray:"1 2",opacity:"0.7",children:o("title",{children:`${e("chartContext")}: ${oe(n.activeContext,t.contextLabels)}`})},`context-${n.timestamp}`)),D.filter(n=>(n.statusCode==="anomaly"||!n.statusCode&&n.detected)&&n.timestamp>=d[0].timestamp&&n.timestamp<=d[d.length-1].timestamp).map(n=>o("polygon",{points:`${w(n.timestamp)},${E(n.actual)-2.5} ${w(n.timestamp)-2.5},${E(n.actual)+2} ${w(n.timestamp)+2.5},${E(n.actual)+2}`,fill:"#f44336",role:"img",children:o("title",{children:de({value:n.actual,timestamp:n.timestamp},n,t)})},n.timestamp)),d.map(n=>{const m=ee(n.timestamp);return o("circle",{cx:w(n.timestamp),cy:E(n.value),r:"1.2",fill:(m==null?void 0:m.statusCode)==="deviating"?"#ff9800":"#2196f3",children:o("title",{children:de(n,m,t)})},n.timestamp)}),d.length>0&&o("line",{x1:w(d[d.length-1].timestamp),x2:w(d[d.length-1].timestamp),y1:"8",y2:"84",stroke:"#fff",opacity:"0.5",children:o("title",{children:e("chartNow")})})]}),r(F,{direction:"row",spacing:2,sx:{mt:.5},children:[r(s,{variant:"caption",children:["━ ",e("chartValue")]}),q.length>0&&r(s,{variant:"caption",color:"info.main",children:["┄ ",e("chartExpected")]}),M.length>0&&r(s,{variant:"caption",color:"secondary",children:["▧ ",e("chartContext")]}),c.some(n=>n.statusCode==="anomaly"||!n.statusCode&&n.detected)&&r(s,{variant:"caption",color:"error",children:["▲ ",e("chartAnomaly")]}),k>0&&r(s,{variant:"caption",color:"warning.main",children:["● ",e("chartDeviating")]})]}),Q>0&&o(s,{variant:"caption",color:"text.secondary",sx:{display:"block",mt:.5},children:e(Q===1?"historicalAnomaliesOne":"historicalAnomaliesMany",Q)}),t.evaluation.activeContext&&M.length===0&&o(s,{variant:"caption",color:"text.secondary",children:e("chartNoContext")}),!q.length&&o(s,{variant:"caption",color:"text.secondary",children:e("chartNoBounds")})]})}function A(t){return typeof t=="number"&&Number.isFinite(t)?new Intl.NumberFormat().format(t):""}function z(t){return typeof t=="number"&&Number.isFinite(t)?new Intl.NumberFormat(void 0,{maximumFractionDigits:1}).format(t):""}function re(t){return typeof t=="number"&&Number.isFinite(t)?new Date(t).toLocaleString():""}function Ne(t){return e(`status.${t||"learning"}`)}function Ae(t){return t.statusCode==="anomaly"&&t.detected===!1?"deviating":t.statusCode||"learning"}function Te(t){return t==="anomaly"?"error":t==="deviating"?"warning":t==="normal"?"success":t==="insufficient_data"||t==="unavailable"?"warning":"default"}function Pe({source:t,socket:i,target:h,refreshKey:u}){const[a,v]=B(!1),l=t.evaluation||{},p=Ae(l),b=l.decisionLow!==void 0&&l.decisionHigh!==void 0?`${z(l.decisionLow)}–${z(l.decisionHigh)}`:void 0,f=l.relevantSampleCount??(l.baselineScope==="context"?l.contextSampleCount:l.sampleCount),T=l.relevantSampleScope??l.baselineScope,S=l.requiredSamples,N=l.relevantSampleScope??l.baselineScope,C=l.relevantSampleCount??l.baselineSampleCount,d=l.evaluationAvailable??(S!==void 0&&C!==void 0&&C>=S),D=p==="unavailable"||f===void 0?void 0:T==="context"&&S!==void 0?f>=S?e("comparisonSamples",f):e("learnedContext",f,S):S!==void 0&&f<S?e("learned",f,S):e("basedOn",f);return o(me,{variant:"outlined",sx:{height:"100%"},children:r(ve,{children:[r(F,{direction:"row",sx:{justifyContent:"space-between",alignItems:"center",gap:1},children:[o(s,{variant:"h6",component:"h2",noWrap:!0,title:t.id,children:t.name}),o(fe,{label:Ne(p),color:Te(p)})]}),o(s,{variant:"subtitle1",sx:{mt:1},children:ce(l)}),r(R,{container:!0,spacing:2,sx:{mt:.5},children:[l.actual!==void 0&&r(R,{item:!0,xs:12,sm:6,children:[o(s,{variant:"body2",color:"text.secondary",children:e("current")}),r(s,{children:[A(l.actual),t.unit?` ${t.unit}`:""]})]}),b&&r(R,{item:!0,xs:12,sm:6,children:[o(s,{variant:"body2",color:"text.secondary",children:e("decisionRange")}),r(s,{children:[b,t.unit?` ${t.unit}`:""]})]})]}),D&&o(s,{variant:"body2",color:"text.secondary",sx:{mt:1},children:D}),p==="deviating"&&o(s,{variant:"body2",sx:{mt:1},children:e("pendingExplanation")}),p==="normal"&&b&&o(s,{variant:"body2",color:"text.secondary",sx:{mt:1},children:e("chartNormalExplanation")}),l.reasonCode&&p!=="normal"&&p!=="deviating"&&o(s,{variant:"body2",sx:{mt:1},children:ce(l)}),p==="anomaly"&&l.anomalySince&&o(s,{variant:"body2",color:"text.secondary",sx:{mt:1},children:e("since",re(l.anomalySince))}),l.activeContext&&o(s,{variant:"body2",color:"text.secondary",sx:{mt:1},children:e("context",oe(l.activeContext,t.contextLabels))}),t.predictive&&t.predictive.status!=="disabled"&&r(G,{sx:{mt:1},children:[r(s,{variant:"body2",color:"text.secondary",children:[e("predictive"),": ",e(`predictive_${t.predictive.status}`)]}),t.predictive.status==="ready"&&t.predictive.points.length>0&&r(s,{variant:"body2",children:[t.predictive.points[0].value.toLocaleString()," (",t.predictive.horizonMinutes," ","min)"]})]}),o(Me,{source:t,socket:i,target:h,refreshKey:u}),o(L,{size:"small",onClick:()=>v(y=>!y),endIcon:a?o(be,{}):o(ge,{}),sx:{mt:1},"aria-expanded":a,children:e("details")}),r(pe,{in:a,children:[o(ye,{sx:{my:1}}),r(F,{spacing:.5,children:[r(s,{variant:"body2",children:[e("overall"),":"," ",l.score!==void 0?`${A(l.score)} %`:"–"]}),r(s,{variant:"body2",children:[e("baseline"),": ",De(N),!d&&` – ${e("baseline_learning")}`," (",C??0," ",e("samples"),")"]}),l.contextSampleCount!==void 0&&r(s,{variant:"body2",children:[e("contextSamples"),": ",l.contextSampleCount]}),l.lastEvaluated&&r(s,{variant:"body2",children:[e("lastEvaluation"),": ",re(l.lastEvaluated)]}),(l.detectors||[]).map(y=>r(s,{variant:"body2",children:[$e(y),": ",A(y.score)," %"]},`${y.name}-${y.reasonCode}`))]})]})]})})}function Ee(t){if(t>=60&&t%60===0){const i=t/60,h=Y()==="de"?`${i} ${i===1?"Stunde":"Stunden"}`:`${i} ${i===1?"hour":"hours"}`;return e("forecastExpectedIn",h)}return e("forecastExpectedIn",Y()==="de"?`${t} Minuten`:`${t} minutes`)}function Le(t){return t>=60&&t%60===0?e("forecastHoursShort",t/60):e("forecastMinutesShort",t)}function Be(t){return e(t==="seasonal"?"modelSeasonal":t==="timeOfDay"?"modelTimeOfDay":"modelLevelTrend")}function qe(t){return e(t==="auto"?"seasonalityAuto":t==="manual"?"seasonalityManual":"seasonalityOff")}function ue(t){if(!t)return;const i=`selection${t.split("-").map(u=>u.charAt(0).toUpperCase()+u.slice(1)).join("")}`,h=e(i);return h===i?void 0:h}function he(t){return t==="history"?e("sourceHistory"):t==="persisted"?e("sourcePersisted"):t==="live"?e("sourceLive"):t==="mixed"?e("sourceMixed"):void 0}function g(t,i=""){return Number.isFinite(t)?`${A(t)}${i}`:void 0}function ze(t){switch(t){case"iqr":return e("scaleSource_iqr");case"p95-p05":case"p95p05":case"p95_p05":return e("scaleSource_p95p05");case"mad":return e("scaleSource_mad");case"range":return e("scaleSource_range");case"none":return e("scaleSource_none");default:return e("notAvailable")}}function Fe({source:t}){var H,V,U,W,j,X,P,Z,w,E,ee,te,K,ne,Q;const i=t.predictive,[h,u]=B(!1),a=i.diagnostics,v=t.evaluation.actual,l=i.generatedAt??t.evaluation.lastEvaluated??Date.now(),p=i.points.filter(k=>Number.isFinite(k.value)),b=Number.isFinite(v)&&((H=p[0])==null?void 0:H.timestamp)!==l?[{timestamp:l,value:v},...p]:p,f=xe(b.map(k=>k.value),[],{floorAtZero:!1}),T=b.map((k,x)=>{var J;const n=((J=b[0])==null?void 0:J.timestamp)??l,m=n+i.horizonMinutes*6e4,_=m>n?Math.max(0,Math.min(280,(k.timestamp-n)/(m-n)*280)):x===0?0:280,I=112-(k.value-f.min)/Math.max(.001,f.max-f.min)*100;return`${x?"L":"M"}${_.toFixed(1)},${I.toFixed(1)}`}).join(" "),S=p.at(-1),N=((V=a==null?void 0:a.model)==null?void 0:V.selectedType)??i.selectedModelType,C=((U=a==null?void 0:a.model)==null?void 0:U.selectionReason)??i.selectionReason,d=a==null?void 0:a.quality,D=i.qualityClass??((W=d==null?void 0:d.qualityClassification)==null?void 0:W.class)??"unknown",y=(i.status==="ready"||i.status==="unreliable")&&b.length>0,c=a==null?void 0:a.seasonality,$=Number.isFinite(c==null?void 0:c.periodicityScore)?(c==null?void 0:c.periodicityScore)*100:void 0,M=i.status!=="disabled",q=(k,x)=>{const n=x!=null&&x.available&&Number.isFinite(x.mae)?`${e("mae")} ${A(x.mae)}${x!=null&&x.available&&Number.isFinite(x.normalizedError)?` · ${e("normalizedError")} ${A(x.normalizedError*100)} %`:""}`:e("notAvailable");return r(F,{spacing:.25,sx:{minWidth:0},children:[r(s,{variant:"body2",sx:{overflowWrap:"anywhere"},children:[k,": ",n]}),(x==null?void 0:x.qualityScaleNearZero)&&o(s,{variant:"body2",color:"text.secondary",sx:{overflowWrap:"anywhere"},children:e("qualityScaleNearZero")})]})};return o(me,{variant:"outlined",sx:{height:"100%"},children:r(ve,{sx:{height:"100%",display:"flex",flexDirection:"column"},children:[r(F,{direction:"row",sx:{justifyContent:"space-between",alignItems:"flex-start",gap:1},children:[o(s,{variant:"h6",sx:{fontWeight:600},children:t.name}),o(fe,{label:e(`predictive_${i.status}`),color:i.status==="ready"?"success":i.status==="disabled"?"default":"warning",size:"small"})]}),Number.isFinite(v)&&r(s,{variant:"body2",sx:{mt:1},children:[e("current"),": ",A(v),t.unit?` ${t.unit}`:""]}),i.status==="learning"&&o(s,{variant:"body2",sx:{mt:1},children:e("learned",i.trainingSampleCount,i.minimumTrainingSamples??t.evaluation.requiredSamples??0)}),(i.status==="ready"||i.status==="unreliable")&&S&&r(O,{children:[o(s,{variant:"body2",sx:{mt:1},children:Ee(i.horizonMinutes)}),r(s,{variant:"body1",sx:{fontWeight:500},children:[A(S.value),t.unit?` ${t.unit}`:""]}),o(s,{variant:"body2",sx:{mt:1},children:e(D==="good"?"forecastQualityGood":D==="limited"?"forecastQualityLimited":D==="poor"?"forecastQualityPoor":"forecastQualityUnknown")})]}),i.status==="error"&&o(s,{variant:"body2",sx:{mt:1},children:e("forecastError")}),y?o(O,{children:r("svg",{viewBox:"0 0 280 140",width:"100%",height:"160",role:"img","aria-label":e("predictive"),children:[o("text",{x:"0",y:"136",fontSize:"11",fill:"currentColor",children:e("forecastNow")}),o("text",{x:"280",y:"136",textAnchor:"end",fontSize:"11",fill:"currentColor",children:Le(i.horizonMinutes)}),Number.isFinite(v)&&o("circle",{cx:"0",cy:112-(v-f.min)/Math.max(.001,f.max-f.min)*100,r:"3",fill:"currentColor"}),o("path",{d:T,fill:"none",stroke:"currentColor",strokeWidth:"2",strokeDasharray:"6 4"})]})}):null,M&&r(O,{children:[o(G,{sx:{flexGrow:1,minHeight:8}}),o(L,{size:"small",onClick:()=>u(k=>!k),endIcon:h?o(be,{}):o(ge,{}),sx:{mt:1},"aria-expanded":h,children:e("predictiveDetails")}),r(pe,{in:h,children:[o(ye,{sx:{my:1}}),r(F,{spacing:.5,children:[o(s,{variant:"subtitle2",children:e("model")}),N&&r(s,{variant:"body2",children:[e("selectedModel"),": ",Be(N)]}),Number.isFinite((j=a==null?void 0:a.model)==null?void 0:j.algorithmVersion)&&r(s,{variant:"body2",children:[e("modelVersion"),": ",(X=a==null?void 0:a.model)==null?void 0:X.algorithmVersion]}),g((P=a==null?void 0:a.model)==null?void 0:P.intervalMinutes,` ${e("minutesShort")}`)&&r(s,{variant:"body2",children:[e("modelInterval"),":"," ",g((Z=a==null?void 0:a.model)==null?void 0:Z.intervalMinutes,` ${e("minutesShort")}`)]}),r(s,{variant:"body2",children:[e("trainingSamples"),": ",i.trainingSampleCount]}),he(i.trainingSource)&&r(s,{variant:"body2",children:[e("trainingSource"),": ",he(i.trainingSource)]}),g((w=a==null?void 0:a.model)==null?void 0:w.rawIntervalMinutes,` ${e("minutesShort")}`)&&r(s,{variant:"body2",children:[e("rawInterval"),":"," ",g((E=a==null?void 0:a.model)==null?void 0:E.rawIntervalMinutes,` ${e("minutesShort")}`)]}),g((ee=a==null?void 0:a.model)==null?void 0:ee.historySpanMinutes,` ${e("minutesShort")}`)&&r(s,{variant:"body2",children:[e("historySpan"),":"," ",g((te=a==null?void 0:a.model)==null?void 0:te.historySpanMinutes,` ${e("minutesShort")}`)]}),g((K=a==null?void 0:a.model)==null?void 0:K.requestedHistorySpanMinutes,` ${e("minutesShort")}`)&&r(s,{variant:"body2",children:[e("requestedHistorySpan"),":"," ",g(a.model.requestedHistorySpanMinutes,` ${e("minutesShort")}`)]}),((ne=a==null?void 0:a.model)==null?void 0:ne.timeOfDayAvailable)!==void 0&&r(O,{children:[r(s,{variant:"body2",children:[e("modelTimeOfDay"),":"," ",a.model.timeOfDayAvailable?e("yes"):e("no")]}),g(a.model.timeOfDayDaysCovered,` ${e("daysCovered")}`)&&r(s,{variant:"body2",children:[e("daysCovered"),": ",a.model.timeOfDayDaysCovered]}),g(a.model.timeOfDayBucketCount,` ${e("bucketCount")}`)&&r(s,{variant:"body2",children:[e("bucketCount"),": ",a.model.timeOfDayBucketCount]}),g(a.model.timeOfDayBucketCoverage!==void 0?a.model.timeOfDayBucketCoverage*100:void 0," %")&&r(s,{variant:"body2",children:[e("bucketCoverage"),":"," ",g((a.model.timeOfDayBucketCoverage??0)*100," %")]})]}),((Q=a==null?void 0:a.model)==null?void 0:Q.lastTrainingAt)&&r(s,{variant:"body2",children:[e("lastTraining"),": ",re(a.model.lastTrainingAt)]}),c&&r(O,{children:[o(s,{variant:"subtitle2",sx:{mt:1},children:e("seasonality")}),r(s,{variant:"body2",children:[e("seasonalityMode"),": ",qe(c.mode)]}),c.periodicityDetected!==void 0&&r(s,{variant:"body2",children:[e("periodDetected"),":"," ",c.periodicityDetected?e("yes"):e("no")]}),g(c.detectedPeriodMinutes,` ${e("minutesShort")}`)&&r(s,{variant:"body2",children:[e("detectedPeriod"),": ca."," ",g(c.detectedPeriodMinutes,` ${e("minutesShort")}`)]}),g($," %")&&r(s,{variant:"body2",children:[e("periodicityScore"),": ",g($," %")]}),g(c.peakProminence!==void 0?c.peakProminence*100:void 0," %")&&r(s,{variant:"body2",children:[e("peakProminence"),":"," ",g((c.peakProminence??0)*100," %")]}),c.harmonicPeaks!==void 0&&r(s,{variant:"body2",children:[e("harmonicPeaks"),": ",c.harmonicPeaks]}),g(c.secondBestPeriodMinutes,` ${e("minutesShort")}`)&&r(s,{variant:"body2",children:[e("secondBestPeriod"),":"," ",g(c.secondBestPeriodMinutes,` ${e("minutesShort")}`)]}),g(c.secondBestPeriodicityScore!==void 0?c.secondBestPeriodicityScore*100:void 0," %")&&r(s,{variant:"body2",children:[e("secondBestScore"),":"," ",g((c.secondBestPeriodicityScore??0)*100," %")]}),c.candidateScores&&r(s,{variant:"body2",children:[e("acfNeighbourScores"),":"," ",Object.entries(c.candidateScores).map(([k,x])=>`${k} ${A(x*100)} %`).join(" · ")]}),c.atLowerBoundary!==void 0&&r(s,{variant:"body2",children:[e("lowerBoundary"),": ",c.atLowerBoundary?e("yes"):e("no")]}),Number.isFinite(c.completePeriods)&&r(s,{variant:"body2",children:[e("completePeriods"),": ",c.completePeriods]}),c.used!==void 0&&r(s,{variant:"body2",children:[e("seasonalityUsed"),": ",c.used?e("yes"):e("no")]})]}),d&&r(O,{children:[d.qualityClassification&&r(O,{children:[r(s,{variant:"body2",children:[e("qualityClass"),":"," ",e(d.qualityClassification.class==="good"?"qualityGood":d.qualityClassification.class==="limited"?"qualityLimited":d.qualityClassification.class==="poor"?"qualityPoor":"qualityUnknown")]}),Number.isFinite(d.qualityClassification.relativeError)&&r(s,{variant:"body2",children:[e("relativeError"),":"," ",A(d.qualityClassification.relativeError*100)," ","%"]}),Number.isFinite(d.qualityClassification.scale)&&r(s,{variant:"body2",children:[e("qualityScale"),":"," ",A(d.qualityClassification.scale)]}),r(s,{variant:"body2",children:[e("scaleSource"),":"," ",ze(d.qualityClassification.scaleSource)]})]}),o(s,{variant:"subtitle2",sx:{mt:1},children:e("backtest")}),q(e("levelTrend"),d.levelTrend),q(e("seasonal"),d.seasonal),q(e("modelTimeOfDay"),d.timeOfDay),d.holdoutSamples!==void 0&&r(s,{variant:"body2",children:[e("holdoutSamples"),": ",d.holdoutSamples]})]}),ue(C)&&r(s,{variant:"body2",sx:{mt:1},children:[e("selection"),": ",ue(C)]})]})]})]})]})})}function He(t){var N,C,d,D;const[i,h]=B(((N=t.data)==null?void 0:N.sources)||[]),[u,a]=B(),[v,l]=B(0),[p,b]=B("current"),f=t.socket||((C=t.oContext)==null?void 0:C.socket),T=we(()=>{var $,M;const y=t.adapterName||(($=t.oContext)==null?void 0:$.adapterName)||"anomaly-detection",c=t.instance??((M=t.oContext)==null?void 0:M.instance)??0;return String(c).includes(".")?String(c):`${y}.${c}`},[t.adapterName,t.instance,(d=t.oContext)==null?void 0:d.adapterName,(D=t.oContext)==null?void 0:D.instance]),S=_e(async()=>{var y,c;if(!(f!=null&&f.sendTo)){h(((y=t.data)==null?void 0:y.sources)||[]);return}try{l(q=>q+1);const $=await f.sendTo(T,"tab",{}),M=(c=$==null?void 0:$.data)==null?void 0:c.sources;Array.isArray(M)?(h(M),a(void 0)):a(e("loadError"))}catch{a(e("loadError"))}},[f,t.data,T]);return ae(()=>{S()},[S]),r(G,{sx:{p:2},children:[r(F,{direction:"row",sx:{mb:2,justifyContent:"space-between",alignItems:"center"},children:[o(s,{variant:"h5",component:"h1",children:e("title")}),o(L,{onClick:S,startIcon:o(ke,{}),"aria-label":e("refresh"),children:e("refresh")})]}),r(F,{direction:"row",spacing:1,sx:{mb:2},children:[o(L,{variant:p==="current"?"contained":"text",onClick:()=>b("current"),children:e("currentView")}),o(L,{variant:p==="forecast"?"contained":"text",onClick:()=>b("forecast"),children:e("forecastView")})]}),u&&o(ie,{severity:"error",sx:{mb:2},children:e("loadError")}),p==="forecast"?o(R,{container:!0,spacing:2,children:i.map(y=>({...y,predictive:y.predictive??{status:"disabled",horizonMinutes:0,points:[],trainingSampleCount:0}})).map(y=>o(R,{item:!0,xs:12,md:6,xl:4,children:o(Fe,{source:y})},y.id))}):i.length===0?o(ie,{severity:"info",children:e("empty")}):o(R,{container:!0,spacing:2,children:i.map(y=>o(R,{item:!0,xs:12,md:6,xl:4,children:o(Pe,{source:y,socket:f,target:T,refreshKey:v})},y.id))})]})}const Ge={AnomalyDashboard:He};export{He as AnomalyDashboard,Ge as default};
@@ -1,4 +1,4 @@
1
- import{g as pi}from"./_commonjsHelpers-D6-XlEtG.js";import{ag as fr,ah as ui,T as vr,ai as xn,aj as fi,ak as vi,al as mi,am as gi,k as hi,an as bi,ao as yi,ap as xi,Y as mr,f as z,B as fo,aq as qo,ae as Ci,m as J,H as Z,I as nt,P as gt,a4 as Cn,j as ot,K as F,L as at,i as A,M as gr,A as hr,R as Vt,u as Go,V as Si}from"./createSvgIcon-lbUx5w8b.js";import{j as te,d as U,n as Sn,t as wi,c as ht,R as br,b as St,a as ae,_ as wt,h as kt,v as Pi,i as ke,e as Zt,l as Tt,g as se,f as q,m as Oe,k as le}from"./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare__react__loadShare__.js-B1BcPa9n.js";import{a as R,_ as Pt}from"./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-D-mkyUQs.js";import{b as to,c as Ii}from"./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare__react_mf_2_dom__loadShare__.js-Ds3-Yu4l.js";var yr={exports:{}},it={};/** @license React v16.13.1
1
+ import{g as pi}from"./_commonjsHelpers-D6-XlEtG.js";import{ag as fr,ah as ui,T as vr,ai as xn,aj as fi,ak as vi,al as mi,am as gi,k as hi,an as bi,ao as yi,ap as xi,Y as mr,f as z,B as fo,aq as qo,ae as Ci,m as J,H as Z,I as nt,P as gt,a4 as Cn,j as ot,K as F,L as at,i as A,M as gr,A as hr,R as Vt,u as Go,V as Si}from"./createSvgIcon-CJqGdhTN.js";import{j as te,d as U,n as Sn,t as wi,c as ht,R as br,b as St,a as ae,_ as wt,h as kt,v as Pi,i as ke,e as Zt,l as Tt,g as se,f as q,m as Oe,k as le}from"./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare__react__loadShare__.js-B1BcPa9n.js";import{a as R,_ as Pt}from"./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-3izusDYF.js";import{b as to,c as Ii}from"./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__loadShare__react_mf_2_dom__loadShare__.js-Ds3-Yu4l.js";var yr={exports:{}},it={};/** @license React v16.13.1
2
2
  * react-is.production.min.js
3
3
  *
4
4
  * Copyright (c) Facebook, Inc. and its affiliates.
@@ -1 +1 @@
1
- import{_ as a}from"./vite-preload-helper-ckwbz45p.js";import"./index-wphymIgy.js";const o=r=>{let t=r;for(let e=0;e<5;e++){const u=t==null?void 0:t.default;if(!u||typeof u!="object"||Object.keys(u).length===0)break;const l=Object.keys(t).filter(s=>s!=="default").map(s=>t[s]);if(l.length>0&&l.some(s=>s!==void 0))break;t=u}return t},n={react:async()=>await a(()=>import("./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild__react__prebuild__-Cta2Ac0K.js"),[]),"react/jsx-runtime":async()=>await a(()=>import("./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild__react_mf_1_jsx_mf_2_runtime__prebuild__-BKVK5lr0.js"),[]),"react-dom":async()=>await a(()=>import("./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild__react_mf_2_dom__prebuild__-ab5OrS0v.js"),[]),"@iobroker/json-config":async()=>await a(()=>import("./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__-T67sp31H.js"),[]),"@mui/material":async()=>await a(()=>import("./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild___mf_0_mui_mf_1_material__prebuild__-G3XIndY6.js"),[]),"@mui/icons-material":async()=>await a(()=>import("./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild___mf_0_mui_mf_1_icons_mf_2_material__prebuild__-CSf7D3Rq.js"),[])},i={react:{name:"react",version:"18.3.1",scope:["default"],loaded:!1,materialize:!0,eager:!1,from:"AnomalyDetectionAdmin",canLiveRebind:!0,async get(){i.react.loaded=!0;const{react:r}=n,t=await r(),e=o({...t});return e.__esModule!==!0&&Object.defineProperty(e,"__esModule",{value:!0,enumerable:!1}),function(){return e}},shareConfig:{singleton:!0,requiredVersion:"*",strictVersion:!1,eager:!1}},"react/jsx-runtime":{name:"react/jsx-runtime",version:"18.3.1",scope:["default"],loaded:!1,materialize:!0,eager:!1,from:"AnomalyDetectionAdmin",canLiveRebind:!0,async get(){i["react/jsx-runtime"].loaded=!0;const{"react/jsx-runtime":r}=n,t=await r(),e=o({...t});return e.__esModule!==!0&&Object.defineProperty(e,"__esModule",{value:!0,enumerable:!1}),function(){return e}},shareConfig:{singleton:!0,requiredVersion:"*",strictVersion:!1,eager:!1}},"react-dom":{name:"react-dom",version:"18.3.1",scope:["default"],loaded:!1,materialize:!0,eager:!1,from:"AnomalyDetectionAdmin",canLiveRebind:!0,async get(){i["react-dom"].loaded=!0;const{"react-dom":r}=n,t=await r(),e=o({...t});return e.__esModule!==!0&&Object.defineProperty(e,"__esModule",{value:!0,enumerable:!1}),function(){return e}},shareConfig:{singleton:!0,requiredVersion:"*",strictVersion:!1,eager:!1}},"@iobroker/json-config":{name:"@iobroker/json-config",version:"8.0.2",scope:["default"],loaded:!1,materialize:!0,eager:!1,from:"AnomalyDetectionAdmin",canLiveRebind:!0,async get(){i["@iobroker/json-config"].loaded=!0;const{"@iobroker/json-config":r}=n,t=await r(),e=o({...t});return e.__esModule!==!0&&Object.defineProperty(e,"__esModule",{value:!0,enumerable:!1}),function(){return e}},shareConfig:{singleton:!0,requiredVersion:"*",strictVersion:!1,eager:!1}},"@mui/material":{name:"@mui/material",version:"6.5.0",scope:["default"],loaded:!1,materialize:!0,eager:!1,from:"AnomalyDetectionAdmin",canLiveRebind:!0,async get(){i["@mui/material"].loaded=!0;const{"@mui/material":r}=n,t=await r(),e=o({...t});return e.__esModule!==!0&&Object.defineProperty(e,"__esModule",{value:!0,enumerable:!1}),function(){return e}},shareConfig:{singleton:!0,requiredVersion:"*",strictVersion:!1,eager:!1}},"@mui/icons-material":{name:"@mui/icons-material",version:"6.5.0",scope:["default"],loaded:!1,materialize:!0,eager:!1,from:"AnomalyDetectionAdmin",canLiveRebind:!0,async get(){i["@mui/icons-material"].loaded=!0;const{"@mui/icons-material":r}=n,t=await r(),e=o({...t});return e.__esModule!==!0&&Object.defineProperty(e,"__esModule",{value:!0,enumerable:!1}),function(){return e}},shareConfig:{singleton:!0,requiredVersion:"*",strictVersion:!1,eager:!1}}},d=[];export{d as usedRemotes,i as usedShared};
1
+ import{_ as a}from"./vite-preload-helper-ckwbz45p.js";import"./index-wphymIgy.js";const o=r=>{let t=r;for(let e=0;e<5;e++){const u=t==null?void 0:t.default;if(!u||typeof u!="object"||Object.keys(u).length===0)break;const l=Object.keys(t).filter(s=>s!=="default").map(s=>t[s]);if(l.length>0&&l.some(s=>s!==void 0))break;t=u}return t},n={react:async()=>await a(()=>import("./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild__react__prebuild__-Cta2Ac0K.js"),[]),"react/jsx-runtime":async()=>await a(()=>import("./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild__react_mf_1_jsx_mf_2_runtime__prebuild__-BKVK5lr0.js"),[]),"react-dom":async()=>await a(()=>import("./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild__react_mf_2_dom__prebuild__-ab5OrS0v.js"),[]),"@iobroker/json-config":async()=>await a(()=>import("./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__--NubxY40.js"),[]),"@mui/material":async()=>await a(()=>import("./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild___mf_0_mui_mf_1_material__prebuild__-I7FRi2ux.js"),[]),"@mui/icons-material":async()=>await a(()=>import("./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild___mf_0_mui_mf_1_icons_mf_2_material__prebuild__-BBex2Aqy.js"),[])},i={react:{name:"react",version:"18.3.1",scope:["default"],loaded:!1,materialize:!0,eager:!1,from:"AnomalyDetectionAdmin",canLiveRebind:!0,async get(){i.react.loaded=!0;const{react:r}=n,t=await r(),e=o({...t});return e.__esModule!==!0&&Object.defineProperty(e,"__esModule",{value:!0,enumerable:!1}),function(){return e}},shareConfig:{singleton:!0,requiredVersion:"*",strictVersion:!1,eager:!1}},"react/jsx-runtime":{name:"react/jsx-runtime",version:"18.3.1",scope:["default"],loaded:!1,materialize:!0,eager:!1,from:"AnomalyDetectionAdmin",canLiveRebind:!0,async get(){i["react/jsx-runtime"].loaded=!0;const{"react/jsx-runtime":r}=n,t=await r(),e=o({...t});return e.__esModule!==!0&&Object.defineProperty(e,"__esModule",{value:!0,enumerable:!1}),function(){return e}},shareConfig:{singleton:!0,requiredVersion:"*",strictVersion:!1,eager:!1}},"react-dom":{name:"react-dom",version:"18.3.1",scope:["default"],loaded:!1,materialize:!0,eager:!1,from:"AnomalyDetectionAdmin",canLiveRebind:!0,async get(){i["react-dom"].loaded=!0;const{"react-dom":r}=n,t=await r(),e=o({...t});return e.__esModule!==!0&&Object.defineProperty(e,"__esModule",{value:!0,enumerable:!1}),function(){return e}},shareConfig:{singleton:!0,requiredVersion:"*",strictVersion:!1,eager:!1}},"@iobroker/json-config":{name:"@iobroker/json-config",version:"8.0.2",scope:["default"],loaded:!1,materialize:!0,eager:!1,from:"AnomalyDetectionAdmin",canLiveRebind:!0,async get(){i["@iobroker/json-config"].loaded=!0;const{"@iobroker/json-config":r}=n,t=await r(),e=o({...t});return e.__esModule!==!0&&Object.defineProperty(e,"__esModule",{value:!0,enumerable:!1}),function(){return e}},shareConfig:{singleton:!0,requiredVersion:"*",strictVersion:!1,eager:!1}},"@mui/material":{name:"@mui/material",version:"6.5.0",scope:["default"],loaded:!1,materialize:!0,eager:!1,from:"AnomalyDetectionAdmin",canLiveRebind:!0,async get(){i["@mui/material"].loaded=!0;const{"@mui/material":r}=n,t=await r(),e=o({...t});return e.__esModule!==!0&&Object.defineProperty(e,"__esModule",{value:!0,enumerable:!1}),function(){return e}},shareConfig:{singleton:!0,requiredVersion:"*",strictVersion:!1,eager:!1}},"@mui/icons-material":{name:"@mui/icons-material",version:"6.5.0",scope:["default"],loaded:!1,materialize:!0,eager:!1,from:"AnomalyDetectionAdmin",canLiveRebind:!0,async get(){i["@mui/icons-material"].loaded=!0;const{"@mui/icons-material":r}=n,t=await r(),e=o({...t});return e.__esModule!==!0&&Object.defineProperty(e,"__esModule",{value:!0,enumerable:!1}),function(){return e}},shareConfig:{singleton:!0,requiredVersion:"*",strictVersion:!1,eager:!1}}},d=[];export{d as usedRemotes,i as usedShared};
@@ -1,2 +1,2 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/_commonjsHelpers-D6-XlEtG.js","assets/createSvgIcon-lbUx5w8b.js","assets/TextField-DNFcbJCE.js","assets/index-wphymIgy.js"])))=>i.map(i=>d[i]);
2
- import{_ as O}from"./vite-preload-helper-ckwbz45p.js";function v(e,n){for(var o=0;o<n.length;o++){const t=n[o];if(typeof t!="string"&&!Array.isArray(t)){for(const r in t)if(r!=="default"&&!(r in e)){const a=Object.getOwnPropertyDescriptor(t,r);a&&Object.defineProperty(e,r,a.get?a:{enumerable:!0,get:()=>t[r]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}const h="__mf_init__virtual:mf:__mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__mf_v__runtimeInit__mf_v__.js__";let c=globalThis[h];if(!c){let e,n;const o=new Promise((t,r)=>{e=t,n=r});c=globalThis[h]={initPromise:o,initResolve:e,initReject:n}}const P=c.initPromise,_="__mf_module_cache__";globalThis[_]||={share:{},remote:{}};globalThis[_].share||={};globalThis[_].remote||={};const i=globalThis[_],C=e=>{const n=i.pendingShareLoads||=[];n.push(e);const o=()=>{const t=n.indexOf(e);t!==-1&&n.splice(t,1)};return e.then(o,o),e};for(const e of Object.keys(i.share))if(e.startsWith("default:")){const n=e.slice(8);i.share[n]===void 0&&(i.share[n]=i.share[e])}else if(!e.includes(":")){const n="default:"+e;i.share[n]===void 0&&(i.share[n]=i.share[e])}const b=(e,n)=>{const o=e[n.canonical];if(o!==void 0)return o;const t=n.aliases||[];for(const r of t){if(!Object.prototype.hasOwnProperty.call(e,r))continue;const a=e[r];if(a!==void 0)return e[n.canonical]=a,a}},u=Symbol.for("module-federation.shared-cache-listeners"),k=e=>{let n=e[u];return n===void 0&&(n=Object.create(null),Object.defineProperty(e,u,{value:n,enumerable:!1,configurable:!1,writable:!1})),n},w=(e,n,o)=>{const t=k(e);(t[n.canonical]||=new Set).add(o)},m=Symbol.for("module-federation.shared-cache-owners"),A=e=>{let n=e[m];return n===void 0&&(n=Object.create(null),Object.defineProperty(e,m,{value:n,enumerable:!1,configurable:!1,writable:!1})),n},T=(e,n,o,t)=>{var s;e[n.canonical]=o;const r=n.aliases||[];for(const f of r)Object.defineProperty(e,f,{value:o,enumerable:!0,configurable:!0,writable:!0});e[m],A(e)[n.canonical]=t;const a=(s=e[u])==null?void 0:s[n.canonical];if(a)for(const f of a)f(o);return o},L=e=>{const n=(()=>{let o=e;for(let t=0;t<5;t++){const r=o==null?void 0:o.default;if(!r||typeof r!="object")break;const a=Object.keys(o).filter(s=>s!=="default").map(s=>o[s]);if(a.length>0&&a.some(s=>s!==void 0))break;o=r}return o})();return n&&Object.getPrototypeOf(n)===null?Object.assign({},n):n};let g,y,j,p,S;const d=e=>{y=e.JsonConfig,j=e.JsonConfigComponent,p=e.ConfigPanel,S=e.ConfigGeneric,g=e.default??e};w(i.share,{canonical:"default:@iobroker/json-config"},d);let l=b(i.share,{canonical:"default:@iobroker/json-config",aliases:["@iobroker/json-config"]});l===void 0?C(P.then(()=>{if(l=b(i.share,{canonical:"default:@iobroker/json-config",aliases:["@iobroker/json-config"]}),l!==void 0){d(l);return}return O(()=>import("./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__-T67sp31H.js"),__vite__mapDeps([0,1,2,3])).then(e=>{l=L(e),T(i.share,{canonical:"default:@iobroker/json-config",aliases:["@iobroker/json-config"]},l,"AnomalyDetectionAdmin")})})):d(l);const x=l,D=v({__proto__:null,get ConfigGeneric(){return S},get ConfigPanel(){return p},get JsonConfig(){return y},get JsonConfigComponent(){return j},get default(){return g}},[x]);export{D as _};
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/_commonjsHelpers-D6-XlEtG.js","assets/createSvgIcon-CJqGdhTN.js","assets/TextField-C3oAONXA.js","assets/index-wphymIgy.js"])))=>i.map(i=>d[i]);
2
+ import{_ as O}from"./vite-preload-helper-ckwbz45p.js";function v(e,n){for(var o=0;o<n.length;o++){const t=n[o];if(typeof t!="string"&&!Array.isArray(t)){for(const r in t)if(r!=="default"&&!(r in e)){const a=Object.getOwnPropertyDescriptor(t,r);a&&Object.defineProperty(e,r,a.get?a:{enumerable:!0,get:()=>t[r]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}const h="__mf_init__virtual:mf:__mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__mf_v__runtimeInit__mf_v__.js__";let c=globalThis[h];if(!c){let e,n;const o=new Promise((t,r)=>{e=t,n=r});c=globalThis[h]={initPromise:o,initResolve:e,initReject:n}}const P=c.initPromise,_="__mf_module_cache__";globalThis[_]||={share:{},remote:{}};globalThis[_].share||={};globalThis[_].remote||={};const i=globalThis[_],C=e=>{const n=i.pendingShareLoads||=[];n.push(e);const o=()=>{const t=n.indexOf(e);t!==-1&&n.splice(t,1)};return e.then(o,o),e};for(const e of Object.keys(i.share))if(e.startsWith("default:")){const n=e.slice(8);i.share[n]===void 0&&(i.share[n]=i.share[e])}else if(!e.includes(":")){const n="default:"+e;i.share[n]===void 0&&(i.share[n]=i.share[e])}const b=(e,n)=>{const o=e[n.canonical];if(o!==void 0)return o;const t=n.aliases||[];for(const r of t){if(!Object.prototype.hasOwnProperty.call(e,r))continue;const a=e[r];if(a!==void 0)return e[n.canonical]=a,a}},u=Symbol.for("module-federation.shared-cache-listeners"),k=e=>{let n=e[u];return n===void 0&&(n=Object.create(null),Object.defineProperty(e,u,{value:n,enumerable:!1,configurable:!1,writable:!1})),n},w=(e,n,o)=>{const t=k(e);(t[n.canonical]||=new Set).add(o)},m=Symbol.for("module-federation.shared-cache-owners"),A=e=>{let n=e[m];return n===void 0&&(n=Object.create(null),Object.defineProperty(e,m,{value:n,enumerable:!1,configurable:!1,writable:!1})),n},T=(e,n,o,t)=>{var s;e[n.canonical]=o;const r=n.aliases||[];for(const f of r)Object.defineProperty(e,f,{value:o,enumerable:!0,configurable:!0,writable:!0});e[m],A(e)[n.canonical]=t;const a=(s=e[u])==null?void 0:s[n.canonical];if(a)for(const f of a)f(o);return o},L=e=>{const n=(()=>{let o=e;for(let t=0;t<5;t++){const r=o==null?void 0:o.default;if(!r||typeof r!="object")break;const a=Object.keys(o).filter(s=>s!=="default").map(s=>o[s]);if(a.length>0&&a.some(s=>s!==void 0))break;o=r}return o})();return n&&Object.getPrototypeOf(n)===null?Object.assign({},n):n};let g,y,j,p,S;const d=e=>{y=e.JsonConfig,j=e.JsonConfigComponent,p=e.ConfigPanel,S=e.ConfigGeneric,g=e.default??e};w(i.share,{canonical:"default:@iobroker/json-config"},d);let l=b(i.share,{canonical:"default:@iobroker/json-config",aliases:["@iobroker/json-config"]});l===void 0?C(P.then(()=>{if(l=b(i.share,{canonical:"default:@iobroker/json-config",aliases:["@iobroker/json-config"]}),l!==void 0){d(l);return}return O(()=>import("./_virtual_mf___mfe_internal__AnomalyDetectionAdmin__mf_owner__65673490305404__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__--NubxY40.js"),__vite__mapDeps([0,1,2,3])).then(e=>{l=L(e),T(i.share,{canonical:"default:@iobroker/json-config",aliases:["@iobroker/json-config"]},l,"AnomalyDetectionAdmin")})})):d(l);const x=l,D=v({__proto__:null,get ConfigGeneric(){return S},get ConfigPanel(){return p},get JsonConfig(){return y},get JsonConfigComponent(){return j},get default(){return g}},[x]);export{D as _};