@apocaliss92/scrypted-advanced-notifier 5.0.1 → 5.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,10 @@
1
1
  <details>
2
2
  <summary>Changelog</summary>
3
3
 
4
+ ### 5.0.2
5
+
6
+ Native HA component now available. Follow docs on page https://advanced-notifier-docs.zentik.app/docs/advanced-notifier/discovery for how to install and configure it
7
+
4
8
  ### 5.0.0
5
9
  Finally An app is completed. It's called CamStack and it's available on testflight and as pwa on the scrypted local istance. Also available on https://camstack.zentik.app
6
10
  New docs is up on https://advanced-notifier-docs.zentik.app/docs/advanced-notifier
@@ -0,0 +1,186 @@
1
+ # Advanced Notifier — Piano di Miglioramento
2
+
3
+ ## Panoramica Codebase
4
+
5
+ | File | LOC | Problema |
6
+ |------|-----|----------|
7
+ | cameraMixin.ts | 6,669 | God class: 43+ metodi, 8 responsabilità, 13 metodi >100 LOC |
8
+ | utils.ts | 6,631 | God file: 120+ export, settings/rules/text/notifier mischiati |
9
+ | main.ts | 5,910 | God class: HTTP/MQTT/FS/DB/media/HA in un unico file |
10
+ | mqtt-utils.ts | 2,719 | 5 subscribe fn e 5 setup fn quasi identiche |
11
+
12
+ ---
13
+
14
+ ## 1. Memory Leak — Priorità CRITICA
15
+
16
+ ### 1.1 Cache embedding senza limiti (main.ts)
17
+ - `imageEmbeddingCache: Record<string, Buffer>` — mai pulita
18
+ - `textEmbeddingCache: Record<string, Buffer>` — mai pulita
19
+ - **Fix:** Implementare LRU con max ~100 entry, o Map con TTL
20
+
21
+ ### 1.2 State maps mai potate (cameraMixin.ts)
22
+ - `detectionIdEventIdMap` — cresce a ogni detection, mai pulita
23
+ - `objectIdLastReport` — per object ID, senza TTL
24
+ - `audioRuleSamples` — array `{timestamp, dBs}[]` per regola, mai trimmati
25
+ - `occupancyState` — contiene `b64Image` per regola, mai rilasciate
26
+ - `snoozeUntilDic` — entry mai rimosse
27
+ - `clipGenerationTimeout` — se la regola viene rimossa, il timeout resta
28
+ - **Fix:** TTL-based cleanup periodico (ogni 5 min), trim audioRuleSamples a max 1000 entry
29
+
30
+ ### 1.3 Doppio caching immagine
31
+ - `lastFrame: Buffer` + `lastB64Image: string` — stessa immagine in due formati (~33% overhead)
32
+ - **Fix:** Tenere solo `lastB64Image`, decodificare on-demand se serve Buffer
33
+
34
+ ### 1.4 State non pulite su device removal (main.ts)
35
+ - `cameraStates` — entry mai rimosse su releaseMixin
36
+ - `lastCameraAutodiscoveryMap` — entry per camera mai rimosse
37
+ - **Fix:** Pulire in `releaseMixin()`
38
+
39
+ ### 1.5 release() incompleto (cameraMixin.ts)
40
+ - `release()` pulisce listener/interval ma NON: occupancyState, audioRuleSamples, detectionIdEventIdMap, maps vari
41
+ - **Fix:** Aggiungere cleanup completo in release()
42
+
43
+ ---
44
+
45
+ ## 2. Complessità Metodi — Priorità ALTA
46
+
47
+ ### 2.1 Metodi >200 LOC da spezzare
48
+
49
+ | Metodo | LOC | Dove | Estrarre in |
50
+ |--------|-----|------|-------------|
51
+ | `onRequest()` | ~1,300 | main.ts | `HttpRouter` class con handler separati per route |
52
+ | `manualCheckOccupancyRule()` | ~853 | cameraMixin.ts | `OccupancyChecker.evaluate()` |
53
+ | `onRestart()` | ~745 | cameraMixin.ts | Separare occupancy check da restart logic |
54
+ | `startCheckInterval()` | ~580 | cameraMixin.ts | `enableRules()`, `setupMqtt()`, `scheduleMaintenance()` |
55
+ | `getDetectionRulesSettings()` | ~500 | utils.ts | `SettingsBuilder` class |
56
+ | `executeDetection()` | ~497 | cameraMixin.ts | `DetectionExecutor.run()` |
57
+ | `processDetections()` | ~460 | cameraMixin.ts | `acquireImage()`, `reportDetections()`, `matchRules()`, `storeData()` |
58
+
59
+ ### 2.2 processDetections() — Pipeline
60
+ Attualmente è un metodo monolitico. Dovrebbe diventare una pipeline:
61
+ ```
62
+ 1. acquireDetectionImage(detect, eventSource) → {b64Image, image, imageSource}
63
+ 2. reportBasicDetections(candidates, b64Image) → void (MQTT side-effect)
64
+ 3. matchAndTriggerRules(candidates, image) → MatchRule[]
65
+ 4. storeDetectionData(candidates, b64Image, eventSource) → void (FS side-effect)
66
+ ```
67
+
68
+ ---
69
+
70
+ ## 3. Duplicazione Codice — Priorità ALTA
71
+
72
+ ### 3.1 mqtt-utils.ts — 5 subscribe fn identiche
73
+ `subscribeToPluginMqttTopics`, `subscribeToAlarmSystemMqttTopics`, `subscribeToCameraMqttTopics`, `subscribeToNotifierMqttTopics`, `subscribeToSensorMqttTopics` — stesso pattern:
74
+ ```
75
+ check mqttClient → getEntities → for each → getMqttTopics → subscribe → check payload → callback → publish
76
+ ```
77
+ **Fix:** Creare `MqttSubscriptionBuilder`:
78
+ ```typescript
79
+ new MqttSubscriptionBuilder(mqttClient)
80
+ .addSwitch('recording', switchRecordingCb)
81
+ .addSwitch('snapshots', switchSnapshotsCb)
82
+ .subscribe()
83
+ ```
84
+
85
+ ### 3.2 mqtt-utils.ts — 5 setup/autodiscovery fn simili
86
+ `setupPluginAutodiscovery`, `setupAlarmSystemAutodiscovery`, `setupCameraAutodiscovery`, `setupNotifierAutodiscovery`, `setupSensorAutodiscovery`
87
+ **Fix:** Estrarre template comune `setupEntityAutodiscovery(type, entities, mqttClient)`
88
+
89
+ ### 3.3 utils.ts — 6 pattern rules identici
90
+ `getDetectionRules`, `getDeviceOccupancyRules`, `getDeviceTimelapseRules`, `getDeviceAudioRules`, `getRecordingRules`, `getDevicePatrolRules` — tutti:
91
+ ```
92
+ storage.getItem() → safeParseJson() → loop/filter → return {availableRules, allowedRules}
93
+ ```
94
+ **Fix:** `createRuleProcessor(ruleType, storageKey, parser)` factory
95
+
96
+ ### 3.4 cameraMixin.ts — switch subscribe duplicati (righe 1376-1435)
97
+ 5 blocchi `if (switchXyzCb)` identici per rebroadcast, recording, snapshots, privacy, notifications
98
+ **Fix:** Usa il `MqttSubscriptionBuilder` del punto 3.1
99
+
100
+ ---
101
+
102
+ ## 4. Estrazione Moduli — Priorità MEDIA
103
+
104
+ ### 4.1 Da cameraMixin.ts (6,669 LOC → ~5 file)
105
+
106
+ | Modulo | Responsabilità | LOC stimato |
107
+ |--------|----------------|-------------|
108
+ | `DetectionProcessor` | processDetections, executeDetection, checkRuleMatches | ~1,200 |
109
+ | `OccupancyChecker` | checkOccupancyData, manualCheckOccupancyRule | ~1,000 |
110
+ | `RecordingManager` | startRecording, stopRecording, getVideoClips | ~500 |
111
+ | `AudioAnalyzer` | startAudioAnalyzer, audio level, audio classification | ~400 |
112
+ | `DecoderManager` | initDecoderStream, startDecoder, stopDecoder, cleanup | ~300 |
113
+
114
+ ### 4.2 Da main.ts (5,910 LOC → ~4 file)
115
+
116
+ | Modulo | Responsabilità | LOC stimato |
117
+ |--------|----------------|-------------|
118
+ | `HttpRouter` | onRequest, route matching, SPA serving | ~1,500 |
119
+ | `FilesystemStorage` | getFsPaths, getRulePaths, store*, clear* | ~800 |
120
+ | `MediaGenerator` | generateTimelapse, generateVideoclip, generateGif | ~400 |
121
+ | `QueueProcessor` | dbWriteQueue, clearVideoclipsQueue, autodiscoveryQueue | ~300 |
122
+
123
+ ### 4.3 Da utils.ts (6,631 LOC → ~3 file)
124
+
125
+ | Modulo | Responsabilità | LOC stimato |
126
+ |--------|----------------|-------------|
127
+ | `ruleUtils.ts` | Tutti i rule getter, rule parsing, rule keys | ~2,000 |
128
+ | `settingsUtils.ts` | getTextSettings, getMixinBaseSettings, getRuleSettings | ~2,500 |
129
+ | `textUtils.ts` | Template text, i18n keys, text rendering | ~500 |
130
+
131
+ ---
132
+
133
+ ## 5. Anti-pattern da Correggere — Priorità BASSA
134
+
135
+ ### 5.1 Fire-and-forget promises
136
+ ```typescript
137
+ setupPluginAutodiscovery({...}).catch(logger.error); // no retry
138
+ publishPluginValues({...}).catch(logger.error); // silently fails
139
+ ```
140
+ **Fix:** Implementare retry con backoff per operazioni critiche
141
+
142
+ ### 5.2 Nested callback in notifyDetectionEvent
143
+ ```typescript
144
+ const executeNotify = async (props) => { ... }
145
+ checkIfClipRequired({ cb: executeNotify, ... })
146
+ ```
147
+ **Fix:** Linearizzare con async/await: `const clipRequired = await checkIfClipRequired(); if (clipRequired) await executeNotify();`
148
+
149
+ ### 5.3 getBasicMqttEntities() non memoizzato
150
+ Crea 25+ entity definitions da zero a ogni chiamata.
151
+ **Fix:** Memoizzare a livello modulo (le entity non cambiano a runtime)
152
+
153
+ ### 5.4 audioLabels hardcoded (285 righe)
154
+ Array da 285 righe in detectionClasses.ts
155
+ **Fix:** Spostare in file JSON esterno
156
+
157
+ ---
158
+
159
+ ## Ordine di Esecuzione Consigliato
160
+
161
+ ### Fase 1 — Memory (impatto immediato su stabilità)
162
+ - [ ] 1.1 LRU su embedding cache
163
+ - [ ] 1.2 TTL cleanup su state maps cameraMixin
164
+ - [ ] 1.3 Rimuovere lastFrame, tenere solo lastB64Image
165
+ - [ ] 1.4 Cleanup in releaseMixin()
166
+ - [ ] 1.5 Completare release()
167
+
168
+ ### Fase 2 — Duplicazione (riduce LOC, facilita manutenzione)
169
+ - [ ] 3.1 MqttSubscriptionBuilder
170
+ - [ ] 3.3 createRuleProcessor factory
171
+ - [ ] 3.2 Template autodiscovery comune
172
+
173
+ ### Fase 3 — Estrazione moduli (architettura)
174
+ - [ ] 4.1 DetectionProcessor da cameraMixin
175
+ - [ ] 4.1 OccupancyChecker da cameraMixin
176
+ - [ ] 4.2 HttpRouter da main.ts
177
+ - [ ] 4.3 ruleUtils.ts e settingsUtils.ts da utils.ts
178
+
179
+ ### Fase 4 — Complessità metodi
180
+ - [ ] 2.2 Pipeline processDetections
181
+ - [ ] 2.1 Spezzare metodi >200 LOC
182
+
183
+ ### Fase 5 — Cleanup
184
+ - [ ] 5.1 Retry su promise critiche
185
+ - [ ] 5.2 Linearizzare callback
186
+ - [ ] 5.3 Memoizzare getBasicMqttEntities
package/dist/plugin.zip CHANGED
Binary file
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "type": "git",
6
6
  "url": "https://github.com/apocaliss92/scrypted-advanced-notifier"
7
7
  },
8
- "version": "5.0.1",
8
+ "version": "5.0.2",
9
9
  "scripts": {
10
10
  "docs:dev": "cd docs && npm run dev",
11
11
  "docs:build": "cd docs && npm run build",