iobroker.anomaly-detection 0.1.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/LICENSE +21 -0
- package/README.md +323 -0
- package/admin/anomaly-detection-icon.png +0 -0
- package/admin/anomaly-detection.png +0 -0
- package/admin/i18n/de.json +32 -0
- package/admin/i18n/en.json +32 -0
- package/admin/i18n/es.json +32 -0
- package/admin/i18n/fr.json +32 -0
- package/admin/i18n/it.json +32 -0
- package/admin/i18n/nl.json +32 -0
- package/admin/i18n/pl.json +32 -0
- package/admin/i18n/pt.json +32 -0
- package/admin/i18n/ru.json +32 -0
- package/admin/i18n/uk.json +32 -0
- package/admin/i18n/zh-cn.json +32 -0
- package/admin/jsonConfig.json +220 -0
- package/build/lib/advanced-detectors.js +149 -0
- package/build/lib/advanced-detectors.js.map +7 -0
- package/build/lib/context-value.js +42 -0
- package/build/lib/context-value.js.map +7 -0
- package/build/lib/detectors.js +76 -0
- package/build/lib/detectors.js.map +7 -0
- package/build/lib/history-provider.js +58 -0
- package/build/lib/history-provider.js.map +7 -0
- package/build/lib/history-source-resolver.js +109 -0
- package/build/lib/history-source-resolver.js.map +7 -0
- package/build/lib/model/contextual-model.js +98 -0
- package/build/lib/model/contextual-model.js.map +7 -0
- package/build/lib/model/statistics.js +78 -0
- package/build/lib/model/statistics.js.map +7 -0
- package/build/lib/model/temporal-model.js +98 -0
- package/build/lib/model/temporal-model.js.map +7 -0
- package/build/lib/scoring.js +57 -0
- package/build/lib/scoring.js.map +7 -0
- package/build/lib/source-cleanup.js +58 -0
- package/build/lib/source-cleanup.js.map +7 -0
- package/build/lib/source-monitor.js +348 -0
- package/build/lib/source-monitor.js.map +7 -0
- package/build/main.js +589 -0
- package/build/main.js.map +7 -0
- package/io-package.json +95 -0
- package/package.json +105 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/main.ts"],
|
|
4
|
+
"sourcesContent": ["/* Created with @iobroker/create-adapter v3.1.5 */\nimport * as utils from \"@iobroker/adapter-core\";\nimport { sanitizeHistory, type HistoryProvider } from \"./lib/history-provider\";\nimport { HistorySourceResolver, selectHistorySource, type HistorySource } from \"./lib/history-source-resolver\";\nimport { cleanupStaleSources } from \"./lib/source-cleanup\";\nimport { SourceMonitor, parseStoredModel, type ObservationResult, type SourceSettings } from \"./lib/source-monitor\";\nimport { createContextPart } from \"./lib/context-value\";\n\nconst MODEL_STATE_ID = \"models\";\nconst PERSIST_DELAY_MS = 30_000;\nconst HISTORY_TIMEOUT_MS = 30_000;\nconst HISTORY_CONCURRENCY = 2;\ninterface ConfiguredSource extends SourceSettings {\n\tname: string;\n}\n\nclass IoBrokerHistoryProvider implements HistoryProvider {\n\tpublic constructor(\n\t\tprivate readonly adapter: ioBroker.Adapter,\n\t\tprivate readonly instance: string,\n\t) {}\n\n\tpublic async getHistory(sourceId: string, start: number, end: number, limit: number): Promise<unknown> {\n\t\tconst response = await this.adapter.sendToAsync(this.instance, \"getHistory\", {\n\t\t\tid: sourceId,\n\t\t\toptions: { start, end, aggregate: \"none\", count: limit, returnNewestEntries: false },\n\t\t});\n\t\treturn response;\n\t}\n}\n\nclass AnomalyDetection extends utils.Adapter {\n\tprivate readonly monitors = new Map<string, SourceMonitor>();\n\tprivate readonly sourceIds = new Map<string, string>();\n\tprivate readonly sources = new Map<string, ConfiguredSource>();\n\tprivate readonly invalidValueWarnings = new Set<string>();\n\tprivate readonly invalidHistoryConfigurationWarnings = new Set<string>();\n\tprivate readonly contextValues = new Map<string, Map<string, ioBroker.StateValue>>();\n\tprivate readonly contextSources = new Map<string, Set<string>>();\n\tprivate readonly contextCategories = new Map<string, Set<string>>();\n\tprivate readonly contextWarnings = new Set<string>();\n\tprivate readonly historySourceResolver = new HistorySourceResolver(this);\n\tprivate persistTimer: ioBroker.Timeout | undefined;\n\n\tpublic constructor(options: Partial<utils.AdapterOptions> = {}) {\n\t\tsuper({ ...options, name: \"anomaly-detection\" });\n\t\tthis.on(\"ready\", this.onReady.bind(this));\n\t\tthis.on(\"stateChange\", this.onStateChange.bind(this));\n\t\tthis.on(\"message\", this.onMessage.bind(this));\n\t\tthis.on(\"unload\", this.onUnload.bind(this));\n\t}\n\n\tprivate async onReady(): Promise<void> {\n\t\tawait this.ensureModelState();\n\t\tconst persistedValue = (await this.getStateAsync(MODEL_STATE_ID))?.val;\n\t\tlet stored = parseStoredModel(persistedValue);\n\t\tif (\n\t\t\ttypeof persistedValue === \"string\" &&\n\t\t\tpersistedValue !== \"\" &&\n\t\t\tpersistedValue !== \"{}\" &&\n\t\t\tObject.keys(stored).length === 0\n\t\t) {\n\t\t\tthis.log.warn(\"Ignoring corrupt or incompatible persisted anomaly models\");\n\t\t}\n\t\tconst configuredSourceIds = new Set(\n\t\t\t(this.config.sources ?? []).flatMap(source => (source.id?.trim() ? [source.id.trim()] : [])),\n\t\t);\n\t\tstored = await this.cleanupStaleSources(configuredSourceIds, stored);\n\t\tconst configuredIds = new Set<string>();\n\t\tconst bootstrapTasks: Array<() => Promise<void>> = [];\n\t\tfor (const source of this.config.sources ?? []) {\n\t\t\tif (!source.enabled || !source.id?.trim()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst id = source.id.trim();\n\t\t\tif (configuredIds.has(id)) {\n\t\t\t\tthis.log.warn(`Ignoring duplicate configured source state: ${id}`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconfiguredIds.add(id);\n\t\t\tconst object = await this.getForeignObjectAsync(id);\n\t\t\tif (!object) {\n\t\t\t\tthis.log.warn(`Configured source state does not exist yet: ${id}`);\n\t\t\t} else if (object.type !== \"state\" || object.common.type !== \"number\") {\n\t\t\t\tthis.log.warn(`Configured source is not a numerical state: ${id}`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst safeId = this.createSourceId(id);\n\t\t\tthis.sourceIds.set(id, safeId);\n\t\t\tconst monitor = new SourceMonitor(source, stored[safeId]);\n\t\t\tthis.monitors.set(id, monitor);\n\t\t\tthis.sources.set(safeId, source);\n\t\t\tawait this.registerContexts(id, source);\n\t\t\tawait this.ensureSourceObjects(safeId, source, object?.common.unit);\n\t\t\tthis.subscribeForeignStates(id);\n\t\t\tif (this.shouldBootstrap(source, monitor)) {\n\t\t\t\tbootstrapTasks.push(() => this.bootstrapSource(id, safeId, source, monitor));\n\t\t\t}\n\t\t}\n\t\tthis.subscribeStates(\"sources.*.retrain\");\n\t\tawait this.runWithConcurrency(bootstrapTasks, HISTORY_CONCURRENCY);\n\t\tthis.log.info(`Monitoring ${this.monitors.size} numerical state${this.monitors.size === 1 ? \"\" : \"s\"}`);\n\t}\n\n\tprivate onStateChange(id: string, state: ioBroker.State | null | undefined): void {\n\t\tif (!state) {\n\t\t\treturn;\n\t\t}\n\t\tfor (const sourceId of this.contextSources.get(id) ?? []) {\n\t\t\tthis.contextValues.get(sourceId)?.set(id, state.val);\n\t\t}\n\t\tconst retrainMatch = id.match(/sources\\.([^.]+)\\.retrain$/);\n\t\tif (retrainMatch && state.ack === false && state.val === true) {\n\t\t\tconst safeId = retrainMatch[1];\n\t\t\tconst sourceId = [...this.sourceIds].find(([, value]) => value === safeId)?.[0];\n\t\t\tconst source = this.sources.get(safeId);\n\t\t\tconst monitor = sourceId ? this.monitors.get(sourceId) : undefined;\n\t\t\tif (sourceId && source && monitor) {\n\t\t\t\tvoid this.retrainSource(sourceId, safeId, source, monitor);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tconst monitor = this.monitors.get(id);\n\t\tconst safeId = this.sourceIds.get(id);\n\t\tif (monitor && safeId) {\n\t\t\tvoid this.processState(id, safeId, monitor, state);\n\t\t}\n\t}\n\n\tprivate onMessage(message: ioBroker.Message): void {\n\t\tif (!message.callback) {\n\t\t\treturn;\n\t\t}\n\t\tif (message.command === \"getHistoryProviders\") {\n\t\t\tvoid this.replyWithHistoryProviders(message);\n\t\t}\n\t}\n\n\tprivate async replyWithHistoryProviders(message: ioBroker.Message): Promise<void> {\n\t\tconst sourceId = typeof message.message?.sourceId === \"string\" ? message.message.sourceId.trim() : \"\";\n\t\tconst sources = await this.historySourcesForAdmin(sourceId);\n\t\tthis.sendTo(\n\t\t\tmessage.from,\n\t\t\tmessage.command,\n\t\t\tsources.map(source => ({ value: source.instanceId, label: source.instanceId })),\n\t\t\tmessage.callback,\n\t\t);\n\t}\n\n\tprivate async historySourcesForAdmin(sourceId: string): Promise<HistorySource[]> {\n\t\tif (!sourceId) {\n\t\t\treturn [];\n\t\t}\n\t\ttry {\n\t\t\treturn await this.historySourceResolver.resolve(sourceId);\n\t\t} catch (error) {\n\t\t\tthis.log.warn(`Could not resolve history sources for ${sourceId}: ${(error as Error).message}`);\n\t\t\treturn [];\n\t\t}\n\t}\n\n\tprivate async processState(\n\t\tid: string,\n\t\tsafeId: string,\n\t\tmonitor: SourceMonitor,\n\t\tstate: ioBroker.State,\n\t): Promise<void> {\n\t\ttry {\n\t\t\tconst result = monitor.observe(\n\t\t\t\tstate.val,\n\t\t\t\ttypeof state.ts === \"number\" ? state.ts : Date.now(),\n\t\t\t\tthis.contextKey(id),\n\t\t\t);\n\t\t\tif (!result) {\n\t\t\t\tif (!this.invalidValueWarnings.has(id)) {\n\t\t\t\t\tthis.invalidValueWarnings.add(id);\n\t\t\t\t\tthis.log.warn(`Ignoring invalid non-numerical value from ${id}`);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.invalidValueWarnings.delete(id);\n\t\t\tawait this.writeResult(safeId, result);\n\t\t\tthis.schedulePersistence();\n\t\t} catch (error) {\n\t\t\tthis.log.error(`Could not process source state ${id}: ${(error as Error).message}`);\n\t\t}\n\t}\n\n\tprivate async registerContexts(sourceId: string, source: ConfiguredSource): Promise<void> {\n\t\tif (!source.enableContext) {\n\t\t\treturn;\n\t\t}\n\t\tif ((source.contextStates?.length ?? 0) > 3) {\n\t\t\tthis.warnContext(`Only the first 3 context states are used for ${sourceId}`);\n\t\t}\n\t\tfor (const context of (source.contextStates ?? []).filter(item => item.id?.trim()).slice(0, 3)) {\n\t\t\tconst id = context.id.trim();\n\t\t\tlet sources = this.contextSources.get(id);\n\t\t\tif (!sources) {\n\t\t\t\tsources = new Set();\n\t\t\t\tthis.contextSources.set(id, sources);\n\t\t\t\tthis.subscribeForeignStates(id);\n\t\t\t}\n\t\t\tsources.add(sourceId);\n\t\t\tconst state = await this.getForeignStateAsync(id);\n\t\t\tif (state) {\n\t\t\t\tlet values = this.contextValues.get(sourceId);\n\t\t\t\tif (!values) {\n\t\t\t\t\tvalues = new Map();\n\t\t\t\t\tthis.contextValues.set(sourceId, values);\n\t\t\t\t}\n\t\t\t\tvalues.set(id, state.val);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate contextKey(sourceId: string): string | undefined {\n\t\tconst safeId = this.sourceIds.get(sourceId);\n\t\tconst source = safeId ? this.sources.get(safeId) : undefined;\n\t\tif (!source?.enableContext) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst values = this.contextValues.get(sourceId);\n\t\tconst parts = (source.contextStates ?? [])\n\t\t\t.filter(item => item.id?.trim())\n\t\t\t.slice(0, 3)\n\t\t\t.map(context => {\n\t\t\t\tconst value = values?.get(context.id.trim());\n\t\t\t\tif (typeof value === \"string\" && value.trim() && value.length <= 96) {\n\t\t\t\t\tconst categoryKey = `${sourceId}\\u0000${context.id}`;\n\t\t\t\t\tlet categories = this.contextCategories.get(categoryKey);\n\t\t\t\t\tif (!categories) {\n\t\t\t\t\t\tcategories = new Set();\n\t\t\t\t\t\tthis.contextCategories.set(categoryKey, categories);\n\t\t\t\t\t}\n\t\t\t\t\tif (!categories.has(value) && categories.size >= 16) {\n\t\t\t\t\t\tthis.warnContext(`Ignoring additional categorical values for ${context.id}; limit is 16`);\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\t\t\t\t\tcategories.add(value);\n\t\t\t\t}\n\t\t\t\treturn createContextPart(context.id, value, context.bucketWidth);\n\t\t\t});\n\t\treturn parts.length > 0 && parts.every(Boolean) ? parts.join(\"|\") : undefined;\n\t}\n\n\tprivate warnContext(message: string): void {\n\t\tif (!this.contextWarnings.has(message)) {\n\t\t\tthis.contextWarnings.add(message);\n\t\t\tthis.log.warn(message);\n\t\t}\n\t}\n\n\tprivate async ensureModelState(): Promise<void> {\n\t\tawait this.setObjectNotExistsAsync(MODEL_STATE_ID, {\n\t\t\ttype: \"state\",\n\t\t\tcommon: { name: \"Persisted models\", type: \"string\", role: \"json\", read: true, write: false, def: \"\" },\n\t\t\tnative: {},\n\t\t});\n\t}\n\n\tprivate async cleanupStaleSources(\n\t\tconfiguredSourceIds: ReadonlySet<string>,\n\t\tstoredModels: ReturnType<typeof parseStoredModel>,\n\t): Promise<ReturnType<typeof parseStoredModel>> {\n\t\ttry {\n\t\t\tconst result = await cleanupStaleSources(\n\t\t\t\t{\n\t\t\t\t\tlistGeneratedSourceDevices: async () => {\n\t\t\t\t\t\tconst devices = await this.getForeignObjectsAsync(`${this.namespace}.sources.*`, \"device\");\n\t\t\t\t\t\treturn Object.entries(devices).map(([id, device]) => ({\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\tsourceId: typeof device.native?.sourceId === \"string\" ? device.native.sourceId : undefined,\n\t\t\t\t\t\t}));\n\t\t\t\t\t},\n\t\t\t\t\tdeleteGeneratedSourceTree: relativeId => this.delObjectAsync(relativeId, { recursive: true }),\n\t\t\t\t},\n\t\t\t\tthis.namespace,\n\t\t\t\tconfiguredSourceIds,\n\t\t\t\tstoredModels,\n\t\t\t\tthis.createSourceId.bind(this),\n\t\t\t);\n\t\t\tif (result.modelsChanged) {\n\t\t\t\tawait this.setStateAsync(MODEL_STATE_ID, { val: JSON.stringify(result.models), ack: true });\n\t\t\t}\n\t\t\tfor (const sourceId of result.removedSourceIds) {\n\t\t\t\tthis.log.info(`Removed generated anomaly objects and model for deleted source: ${sourceId}`);\n\t\t\t}\n\t\t\treturn result.models;\n\t\t} catch (error) {\n\t\t\tthis.log.error(`Could not clean up stale monitored sources: ${(error as Error).message}`);\n\t\t\treturn storedModels;\n\t\t}\n\t}\n\n\tprivate async ensureSourceObjects(safeId: string, source: ConfiguredSource, unit?: string): Promise<void> {\n\t\tconst base = `sources.${safeId}`;\n\t\tawait this.setObjectNotExistsAsync(base, {\n\t\t\ttype: \"device\",\n\t\t\tcommon: { name: source.name || source.id },\n\t\t\tnative: { sourceId: source.id },\n\t\t});\n\t\tawait this.setObjectNotExistsAsync(`${base}.analysis`, {\n\t\t\ttype: \"channel\",\n\t\t\tcommon: { name: \"Anomaly analysis\" },\n\t\t\tnative: {},\n\t\t});\n\t\tconst numberState = (\n\t\t\tname: string,\n\t\t\trole: string,\n\t\t\textra: Partial<ioBroker.StateCommon> = {},\n\t\t): ioBroker.SettableObject => ({\n\t\t\ttype: \"state\",\n\t\t\tcommon: { name, type: \"number\", role, read: true, write: false, ...extra },\n\t\t\tnative: {},\n\t\t});\n\t\tawait this.setObjectNotExistsAsync(\n\t\t\t`${base}.analysis.actual`,\n\t\t\tnumberState(\"Actual value\", \"value\", unit ? { unit } : {}),\n\t\t);\n\t\tawait this.setObjectNotExistsAsync(\n\t\t\t`${base}.analysis.expected`,\n\t\t\tnumberState(\"Expected value\", \"value\", unit ? { unit } : {}),\n\t\t);\n\t\tawait this.setObjectNotExistsAsync(\n\t\t\t`${base}.analysis.deviation`,\n\t\t\tnumberState(\"Deviation\", \"value\", unit ? { unit } : {}),\n\t\t);\n\t\tawait this.setObjectNotExistsAsync(\n\t\t\t`${base}.analysis.score`,\n\t\t\tnumberState(\"Anomaly score\", \"value\", { min: 0, max: 100, unit: \"%\" }),\n\t\t);\n\t\tawait this.setObjectNotExistsAsync(\n\t\t\t`${base}.analysis.sampleCount`,\n\t\t\tnumberState(\"Learned sample count\", \"value\"),\n\t\t);\n\t\tawait this.setObjectNotExistsAsync(`${base}.analysis.baselineScope`, {\n\t\t\ttype: \"state\",\n\t\t\tcommon: { name: \"Active baseline scope\", type: \"string\", role: \"info.status\", read: true, write: false },\n\t\t\tnative: {},\n\t\t});\n\t\tawait this.setObjectNotExistsAsync(`${base}.analysis.activeContext`, {\n\t\t\ttype: \"state\",\n\t\t\tcommon: { name: \"Active context\", type: \"string\", role: \"text\", read: true, write: false },\n\t\t\tnative: {},\n\t\t});\n\t\tawait this.setObjectNotExistsAsync(\n\t\t\t`${base}.analysis.baselineSampleCount`,\n\t\t\tnumberState(\"Active baseline sample count\", \"value\"),\n\t\t);\n\t\tawait this.setObjectNotExistsAsync(\n\t\t\t`${base}.analysis.contextSampleCount`,\n\t\t\tnumberState(\"Active context sample count\", \"value\"),\n\t\t);\n\t\tawait this.setObjectNotExistsAsync(`${base}.analysis.detected`, {\n\t\t\ttype: \"state\",\n\t\t\tcommon: {\n\t\t\t\tname: \"Persistent anomaly detected\",\n\t\t\t\ttype: \"boolean\",\n\t\t\t\trole: \"indicator\",\n\t\t\t\tread: true,\n\t\t\t\twrite: false,\n\t\t\t\tdef: false,\n\t\t\t},\n\t\t\tnative: {},\n\t\t});\n\t\tawait this.setObjectNotExistsAsync(`${base}.analysis.status`, {\n\t\t\ttype: \"state\",\n\t\t\tcommon: { name: \"Model status\", type: \"string\", role: \"info.status\", read: true, write: false },\n\t\t\tnative: {},\n\t\t});\n\t\tawait this.setObjectNotExistsAsync(`${base}.analysis.reason`, {\n\t\t\ttype: \"state\",\n\t\t\tcommon: { name: \"Anomaly reason\", type: \"string\", role: \"text\", read: true, write: false },\n\t\t\tnative: {},\n\t\t});\n\t\tawait this.setObjectNotExistsAsync(`${base}.analysis.lastAnomaly`, {\n\t\t\ttype: \"state\",\n\t\t\tcommon: { name: \"Last high-score anomaly\", type: \"string\", role: \"date\", read: true, write: false },\n\t\t\tnative: {},\n\t\t});\n\t\tawait this.setObjectNotExistsAsync(`${base}.retrain`, {\n\t\t\ttype: \"state\",\n\t\t\tcommon: { name: \"Retrain model\", type: \"boolean\", role: \"button\", read: false, write: true, def: false },\n\t\t\tnative: {},\n\t\t});\n\t\tawait this.setObjectNotExistsAsync(`${base}.analysis.bootstrapStatus`, {\n\t\t\ttype: \"state\",\n\t\t\tcommon: {\n\t\t\t\tname: \"Historical bootstrap status\",\n\t\t\t\ttype: \"string\",\n\t\t\t\trole: \"info.status\",\n\t\t\t\tread: true,\n\t\t\t\twrite: false,\n\t\t\t},\n\t\t\tnative: {},\n\t\t});\n\t}\n\n\tprivate shouldBootstrap(source: ConfiguredSource, monitor: SourceMonitor): boolean {\n\t\treturn (\n\t\t\tsource.initialTraining === \"history\" &&\n\t\t\t!!source.historyInstance?.trim() &&\n\t\t\t(!monitor.hasSufficientData || !monitor.bootstrapMatches(this.bootstrapConfigKey(source)))\n\t\t);\n\t}\n\n\tprivate async bootstrapSource(\n\t\tsourceId: string,\n\t\tsafeId: string,\n\t\tsource: ConfiguredSource,\n\t\tmonitor: SourceMonitor,\n\t): Promise<void> {\n\t\tconst providerName = source.historyInstance!.trim();\n\t\tconst end = Date.now();\n\t\tconst start = end - Math.max(7, source.trainingDays ?? 30) * 24 * 60 * 60 * 1000;\n\t\tawait this.setStateAsync(`sources.${safeId}.analysis.status`, { val: \"importingHistory\", ack: true });\n\t\tawait this.setStateAsync(`sources.${safeId}.analysis.bootstrapStatus`, {\n\t\t\tval: \"Importing historical data\",\n\t\t\tack: true,\n\t\t});\n\t\ttry {\n\t\t\tconst historySource = await this.resolveConfiguredHistorySource(sourceId, providerName);\n\t\t\tawait this.setStateAsync(`sources.${safeId}.analysis.bootstrapStatus`, {\n\t\t\t\tval: `Importing history from ${historySource.sourceId} via ${providerName}`,\n\t\t\t\tack: true,\n\t\t\t});\n\t\t\tconst provider = new IoBrokerHistoryProvider(this, providerName);\n\t\t\tconst raw = await this.withHistoryTimeout(\n\t\t\t\tprovider.getHistory(historySource.sourceId, start, end, source.maxHistorySamples ?? 1000),\n\t\t\t);\n\t\t\tconst samples = sanitizeHistory(raw, source.maxHistorySamples ?? 1000);\n\t\t\tif (samples.length === 0) {\n\t\t\t\tthrow new Error(\"History provider returned no valid samples\");\n\t\t\t}\n\t\t\tmonitor.reset();\n\t\t\tconst imported = monitor.bootstrapFromHistory(\n\t\t\t\tsamples,\n\t\t\t\tproviderName,\n\t\t\t\thistorySource.sourceId,\n\t\t\t\tstart,\n\t\t\t\tend,\n\t\t\t\tthis.bootstrapConfigKey(source),\n\t\t\t);\n\t\t\tif (imported === 0) {\n\t\t\t\tthrow new Error(\"No usable samples remained after historical outlier filtering\");\n\t\t\t}\n\t\t\tawait this.persistModels();\n\t\t\tawait this.setStateAsync(`sources.${safeId}.analysis.sampleCount`, { val: monitor.sampleCount, ack: true });\n\t\t\tconst status =\n\t\t\t\tmonitor.hasSufficientData && (source.autoStartMonitoringAfterImport ?? true)\n\t\t\t\t\t? \"monitoring\"\n\t\t\t\t\t: \"learning\";\n\t\t\tawait this.setStateAsync(`sources.${safeId}.analysis.status`, { val: status, ack: true });\n\t\t\tawait this.setStateAsync(`sources.${safeId}.analysis.bootstrapStatus`, {\n\t\t\t\tval: `Historical training completed (${imported} samples)`,\n\t\t\t\tack: true,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthis.log.warn(`Historical bootstrap failed for ${sourceId}: ${(error as Error).message}`);\n\t\t\tawait this.persistModels();\n\t\t\tawait this.setStateAsync(`sources.${safeId}.analysis.status`, {\n\t\t\t\tval: monitor.hasSufficientData ? \"monitoring\" : \"learning\",\n\t\t\t\tack: true,\n\t\t\t});\n\t\t\tawait this.setStateAsync(`sources.${safeId}.analysis.bootstrapStatus`, {\n\t\t\t\tval: \"Insufficient historical data, continuing live learning\",\n\t\t\t\tack: true,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async resolveConfiguredHistorySource(sourceId: string, instanceId: string): Promise<HistorySource> {\n\t\ttry {\n\t\t\treturn selectHistorySource(sourceId, instanceId, await this.historySourceResolver.resolve(sourceId));\n\t\t} catch (error) {\n\t\t\tthis.warnInvalidHistoryConfiguration((error as Error).message);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate warnInvalidHistoryConfiguration(message: string): void {\n\t\tif (!this.invalidHistoryConfigurationWarnings.has(message)) {\n\t\t\tthis.invalidHistoryConfigurationWarnings.add(message);\n\t\t\tthis.log.warn(message);\n\t\t}\n\t}\n\n\tprivate async retrainSource(\n\t\tsourceId: string,\n\t\tsafeId: string,\n\t\tsource: ConfiguredSource,\n\t\tmonitor: SourceMonitor,\n\t): Promise<void> {\n\t\ttry {\n\t\t\tmonitor.reset();\n\t\t\tif (source.initialTraining === \"history\" && source.historyInstance?.trim()) {\n\t\t\t\tawait this.bootstrapSource(sourceId, safeId, source, monitor);\n\t\t\t} else {\n\t\t\t\tawait this.setStateAsync(`sources.${safeId}.analysis.status`, { val: \"learning\", ack: true });\n\t\t\t\tawait this.setStateAsync(`sources.${safeId}.analysis.bootstrapStatus`, {\n\t\t\t\t\tval: \"Model reset; learning live values\",\n\t\t\t\t\tack: true,\n\t\t\t\t});\n\t\t\t\tawait this.persistModels();\n\t\t\t}\n\t\t} finally {\n\t\t\tawait this.setStateAsync(`sources.${safeId}.retrain`, { val: false, ack: true });\n\t\t}\n\t}\n\n\tprivate async runWithConcurrency(tasks: Array<() => Promise<void>>, concurrency: number): Promise<void> {\n\t\tconst queue = [...tasks];\n\t\tawait Promise.all(\n\t\t\tArray.from({ length: Math.min(concurrency, queue.length) }, async () => {\n\t\t\t\twhile (queue.length) {\n\t\t\t\t\tawait queue.shift()!();\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t}\n\n\tprivate async withHistoryTimeout<T>(operation: Promise<T>): Promise<T> {\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\tconst timer = this.setTimeout(() => reject(new Error(\"History request timed out\")), HISTORY_TIMEOUT_MS);\n\t\t\toperation.then(\n\t\t\t\tvalue => {\n\t\t\t\t\tthis.clearTimeout(timer);\n\t\t\t\t\tresolve(value);\n\t\t\t\t},\n\t\t\t\terror => {\n\t\t\t\t\tthis.clearTimeout(timer);\n\t\t\t\t\treject(error instanceof Error ? error : new Error(String(error)));\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate bootstrapConfigKey(source: ConfiguredSource): string {\n\t\treturn JSON.stringify({\n\t\t\tprovider: source.historyInstance?.trim(),\n\t\t\tdays: source.trainingDays ?? 30,\n\t\t\tlimit: source.maxHistorySamples ?? 1000,\n\t\t});\n\t}\n\n\tprivate async writeResult(safeId: string, result: ObservationResult): Promise<void> {\n\t\tconst base = `sources.${safeId}.analysis`;\n\t\tconst values: Record<string, ioBroker.StateValue> = {\n\t\t\tactual: result.actual,\n\t\t\tscore: result.score,\n\t\t\tdetected: result.detected,\n\t\t\tstatus: result.status,\n\t\t\treason: result.reason,\n\t\t\tsampleCount: result.sampleCount,\n\t\t\tbaselineScope: result.baselineScope,\n\t\t\tactiveContext: result.activeContext,\n\t\t\tbaselineSampleCount: result.baselineSampleCount,\n\t\t\tcontextSampleCount: result.contextSampleCount,\n\t\t};\n\t\tvalues.expected = result.expected ?? null;\n\t\tvalues.deviation = result.deviation ?? null;\n\t\tif (result.lastAnomaly !== undefined) {\n\t\t\tvalues.lastAnomaly = new Date(result.lastAnomaly).toISOString();\n\t\t}\n\t\tawait Promise.all(\n\t\t\tObject.entries(values).map(([key, value]) =>\n\t\t\t\tthis.setStateAsync(`${base}.${key}`, { val: value, ack: true }),\n\t\t\t),\n\t\t);\n\t}\n\n\tprivate schedulePersistence(): void {\n\t\tif (this.persistTimer) {\n\t\t\treturn;\n\t\t}\n\t\tthis.persistTimer = this.setTimeout(() => {\n\t\t\tthis.persistTimer = undefined;\n\t\t\tvoid this.persistModels();\n\t\t}, PERSIST_DELAY_MS);\n\t}\n\n\tprivate async persistModels(): Promise<void> {\n\t\ttry {\n\t\t\tconst models = Object.fromEntries(\n\t\t\t\t[...this.monitors].map(([sourceId, monitor]) => [\n\t\t\t\t\tthis.sourceIds.get(sourceId)!,\n\t\t\t\t\t{ ...monitor.toJSON(), configuredSourceId: sourceId },\n\t\t\t\t]),\n\t\t\t);\n\t\t\tawait this.setStateAsync(MODEL_STATE_ID, { val: JSON.stringify(models), ack: true });\n\t\t} catch (error) {\n\t\t\tthis.log.error(`Could not persist anomaly models: ${(error as Error).message}`);\n\t\t}\n\t}\n\n\tprivate createSourceId(sourceId: string): string {\n\t\tconst normalized =\n\t\t\tsourceId\n\t\t\t\t.replace(/[^A-Za-z0-9_-]+/g, \"_\")\n\t\t\t\t.replace(/^_+|_+$/g, \"\")\n\t\t\t\t.slice(0, 48) || \"source\";\n\t\tconst hash = [...sourceId]\n\t\t\t.reduce((value, character) => (value * 31 + character.charCodeAt(0)) >>> 0, 0)\n\t\t\t.toString(36);\n\t\treturn `${normalized}_${hash}`;\n\t}\n\n\tprivate onUnload(callback: () => void): void {\n\t\tif (this.persistTimer) {\n\t\t\tthis.clearTimeout(this.persistTimer);\n\t\t}\n\t\tvoid this.persistModels().finally(callback);\n\t}\n}\n\nif (require.main !== module) {\n\tmodule.exports = (options: Partial<utils.AdapterOptions> | undefined) => new AnomalyDetection(options);\n} else {\n\t(() => new AnomalyDetection())();\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["_a", "safeId", "monitor"]
|
|
7
|
+
}
|
package/io-package.json
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"common": {
|
|
3
|
+
"name": "anomaly-detection",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"news": {
|
|
6
|
+
"0.1.0": {
|
|
7
|
+
"en": "initial release",
|
|
8
|
+
"de": "Erstveröffentlichung",
|
|
9
|
+
"ru": "Начальная версия",
|
|
10
|
+
"pt": "lançamento inicial",
|
|
11
|
+
"nl": "Eerste uitgave",
|
|
12
|
+
"fr": "Première version",
|
|
13
|
+
"it": "Versione iniziale",
|
|
14
|
+
"es": "Versión inicial",
|
|
15
|
+
"pl": "Pierwsze wydanie",
|
|
16
|
+
"uk": "Початкова версія",
|
|
17
|
+
"zh-cn": "首次出版"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"titleLang": {
|
|
21
|
+
"en": "Anomaly Detection",
|
|
22
|
+
"de": "Anomalieerkennung",
|
|
23
|
+
"ru": "Обнаружение аномалий",
|
|
24
|
+
"pt": "Detecção de anomalias",
|
|
25
|
+
"nl": "Anomaliedetectie",
|
|
26
|
+
"fr": "Détection des anomalies",
|
|
27
|
+
"it": "Rilevamento anomalie",
|
|
28
|
+
"es": "Detección de anomalías",
|
|
29
|
+
"pl": "Wykrywanie anomalii",
|
|
30
|
+
"uk": "Виявлення аномалії",
|
|
31
|
+
"zh-cn": "异常检测"
|
|
32
|
+
},
|
|
33
|
+
"desc": {
|
|
34
|
+
"en": "Learns normal behavior of numerical ioBroker states and detects statistical anomalies.",
|
|
35
|
+
"de": "Erlernt das normale Verhalten numerischer ioBroker-Zustände und erkennt statistische Anomalien.",
|
|
36
|
+
"ru": "Изучает нормальное поведение числовых состояний ioBroker и обнаруживает статистические аномалии.",
|
|
37
|
+
"pt": "Aprende o comportamento normal dos estados numéricos do ioBroker e detecta anomalias estatísticas.",
|
|
38
|
+
"nl": "Leert normaal gedrag van numerieke ioBroker-statussen en detecteert statistische afwijkingen.",
|
|
39
|
+
"fr": "Apprend le comportement normal des états numériques d’ioBroker et détecte les anomalies statistiques.",
|
|
40
|
+
"it": "Apprende il comportamento normale degli stati numerici di ioBroker e rileva anomalie statistiche.",
|
|
41
|
+
"es": "Aprende el comportamiento normal de los estados numéricos de ioBroker y detecta anomalías estadísticas.",
|
|
42
|
+
"pl": "Uczy się normalnego zachowania numerycznych stanów ioBrokera i wykrywa anomalie statystyczne.",
|
|
43
|
+
"uk": "Вивчає нормальну поведінку числових станів ioBroker і виявляє статистичні аномалії.",
|
|
44
|
+
"zh-cn": "了解数字 ioBroker 状态的正常行为并检测统计异常。"
|
|
45
|
+
},
|
|
46
|
+
"authors": ["Voodoo2man <Voodoo2man@outlook.de>"],
|
|
47
|
+
"keywords": [
|
|
48
|
+
"anomaly detection",
|
|
49
|
+
"anomaly",
|
|
50
|
+
"monitoring",
|
|
51
|
+
"statistics",
|
|
52
|
+
"time series",
|
|
53
|
+
"sensor",
|
|
54
|
+
"predictive maintenance"
|
|
55
|
+
],
|
|
56
|
+
"licenseInformation": {
|
|
57
|
+
"type": "free",
|
|
58
|
+
"license": "MIT"
|
|
59
|
+
},
|
|
60
|
+
"platform": "Javascript/Node.js",
|
|
61
|
+
"icon": "anomaly-detection-icon.png",
|
|
62
|
+
"enabled": true,
|
|
63
|
+
"extIcon": "https://raw.githubusercontent.com/Voodoo2man/ioBroker.anomaly-detection/main/admin/anomaly-detection-icon.png",
|
|
64
|
+
"readme": "https://github.com/Voodoo2man/ioBroker.anomaly-detection/blob/main/README.md",
|
|
65
|
+
"loglevel": "info",
|
|
66
|
+
"tier": 3,
|
|
67
|
+
"mode": "daemon",
|
|
68
|
+
"type": "logic",
|
|
69
|
+
"compact": true,
|
|
70
|
+
"connectionType": "local",
|
|
71
|
+
"dataSource": "push",
|
|
72
|
+
"adminUI": {
|
|
73
|
+
"config": "json"
|
|
74
|
+
},
|
|
75
|
+
"messagebox": true,
|
|
76
|
+
"supportedMessages": {
|
|
77
|
+
"custom": true
|
|
78
|
+
},
|
|
79
|
+
"dependencies": [
|
|
80
|
+
{
|
|
81
|
+
"js-controller": ">=6.0.11"
|
|
82
|
+
}
|
|
83
|
+
],
|
|
84
|
+
"globalDependencies": [
|
|
85
|
+
{
|
|
86
|
+
"admin": ">=7.6.20"
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
},
|
|
90
|
+
"native": {
|
|
91
|
+
"sources": []
|
|
92
|
+
},
|
|
93
|
+
"objects": [],
|
|
94
|
+
"instanceObjects": []
|
|
95
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "iobroker.anomaly-detection",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Learns normal behavior of numerical ioBroker states and detects statistical anomalies.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Voodoo2man",
|
|
7
|
+
"email": "Voodoo2man@outlook.de"
|
|
8
|
+
},
|
|
9
|
+
"contributors": [
|
|
10
|
+
{
|
|
11
|
+
"name": "Voodoo2man"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://github.com/Voodoo2man/ioBroker.anomaly-detection",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"keywords": [
|
|
17
|
+
"ioBroker",
|
|
18
|
+
"anomaly detection",
|
|
19
|
+
"anomaly",
|
|
20
|
+
"monitoring",
|
|
21
|
+
"statistics",
|
|
22
|
+
"time series",
|
|
23
|
+
"sensor",
|
|
24
|
+
"predictive maintenance"
|
|
25
|
+
],
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/Voodoo2man/ioBroker.anomaly-detection.git"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">= 22"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@iobroker/adapter-core": "^3.4.3"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@alcalzone/release-script": "^5.2.1",
|
|
38
|
+
"@alcalzone/release-script-plugin-iobroker": "^5.2.0",
|
|
39
|
+
"@alcalzone/release-script-plugin-license": "^5.2.2",
|
|
40
|
+
"@alcalzone/release-script-plugin-manual-review": "^5.2.0",
|
|
41
|
+
"@iobroker/adapter-dev": "^1.5.0",
|
|
42
|
+
"@iobroker/dev-server": "^0.8.0",
|
|
43
|
+
"@iobroker/eslint-config": "^2.3.4",
|
|
44
|
+
"@iobroker/testing": "^6.0.0",
|
|
45
|
+
"@tsconfig/node22": "^22.0.2",
|
|
46
|
+
"@types/iobroker": "npm:@iobroker/types@^7.2.2",
|
|
47
|
+
"@types/node": "^22.0.0",
|
|
48
|
+
"nyc": "^18.0.0",
|
|
49
|
+
"rimraf": "^6.1.3",
|
|
50
|
+
"source-map-support": "^0.5.21",
|
|
51
|
+
"ts-node": "^10.9.2",
|
|
52
|
+
"typescript": "~5.9.3"
|
|
53
|
+
},
|
|
54
|
+
"main": "build/main.js",
|
|
55
|
+
"files": [
|
|
56
|
+
"admin{,/!(src)/**}/!(tsconfig|tsconfig.*|.eslintrc).{json,json5}",
|
|
57
|
+
"admin{,/!(src)/**}/*.{html,css,png,svg,jpg,js}",
|
|
58
|
+
"build/",
|
|
59
|
+
"www/",
|
|
60
|
+
"io-package.json",
|
|
61
|
+
"LICENSE"
|
|
62
|
+
],
|
|
63
|
+
"scripts": {
|
|
64
|
+
"prebuild": "rimraf build",
|
|
65
|
+
"build": "build-adapter ts",
|
|
66
|
+
"watch": "build-adapter ts --watch",
|
|
67
|
+
"prebuild:ts": "rimraf build",
|
|
68
|
+
"build:ts": "build-adapter ts",
|
|
69
|
+
"watch:ts": "build-adapter ts --watch",
|
|
70
|
+
"test:ts": "mocha --config test/mocharc.custom.json src/**/*.test.ts",
|
|
71
|
+
"test:package": "mocha test/package --exit",
|
|
72
|
+
"test:integration": "mocha test/integration --exit",
|
|
73
|
+
"test": "npm run test:ts && npm run test:package",
|
|
74
|
+
"check": "tsc --noEmit",
|
|
75
|
+
"coverage": "nyc npm run test:ts",
|
|
76
|
+
"lint": "eslint -c eslint.config.mjs .",
|
|
77
|
+
"translate": "translate-adapter",
|
|
78
|
+
"release": "release-script",
|
|
79
|
+
"dev-server": "dev-server"
|
|
80
|
+
},
|
|
81
|
+
"nyc": {
|
|
82
|
+
"include": [
|
|
83
|
+
"src/**/*.ts"
|
|
84
|
+
],
|
|
85
|
+
"exclude": [
|
|
86
|
+
"src/**/*.test.ts"
|
|
87
|
+
],
|
|
88
|
+
"extension": [
|
|
89
|
+
".ts"
|
|
90
|
+
],
|
|
91
|
+
"require": [
|
|
92
|
+
"ts-node/register"
|
|
93
|
+
],
|
|
94
|
+
"reporter": [
|
|
95
|
+
"text-summary",
|
|
96
|
+
"html"
|
|
97
|
+
],
|
|
98
|
+
"sourceMap": true,
|
|
99
|
+
"instrument": true
|
|
100
|
+
},
|
|
101
|
+
"bugs": {
|
|
102
|
+
"url": "https://github.com/Voodoo2man/ioBroker.anomaly-detection/issues"
|
|
103
|
+
},
|
|
104
|
+
"readmeFilename": "README.md"
|
|
105
|
+
}
|