@apocaliss92/scrypted-advanced-notifier 4.8.37 → 4.8.38

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/dist/plugin.zip CHANGED
Binary file
@@ -0,0 +1,184 @@
1
+ # Migrazione da Webhook HTTP a Socket SDK con interfaceDescriptors
2
+
3
+ Piano per esporre i metodi Events App via **interfaceDescriptors** (come [@scrypted/llm](https://github.com/scryptedapp/llm)), eliminando le chiamate REST e usando solo la socket SDK.
4
+
5
+ ---
6
+
7
+ ## 1. Come funziona interfaceDescriptors (LLM plugin)
8
+
9
+ Dal [package.json dell'LLM](https://github.com/scryptedapp/llm/blob/main/package.json):
10
+
11
+ ```json
12
+ {
13
+ "scrypted": {
14
+ "interfaces": ["DeviceProvider", "UserDatabase", ...],
15
+ "interfaceDescriptors": {
16
+ "UserDatabase": {
17
+ "name": "UserDatabase",
18
+ "methods": ["openDatabase"],
19
+ "properties": []
20
+ }
21
+ }
22
+ }
23
+ }
24
+ ```
25
+
26
+ - **interfaceDescriptors** dichiara interfacce custom con metodi e proprietà
27
+ - Il server Scrypted usa questi descrittori per esporre i metodi via RPC sulla socket
28
+ - Il client può chiamare `device.openDatabase()` invece di fare HTTP
29
+
30
+ ---
31
+
32
+ ## 2. Metodi Events App da esporre (handleEventsAppRequest)
33
+
34
+ | apimethod | payload | Note |
35
+ |-----------|---------|------|
36
+ | GetConfigs | — | |
37
+ | GetCamerasStatus | — | |
38
+ | GetEvents | fromDate, tillDate, limit, offset, sources, cameras, detectionClasses, eventSource, filter, groupingRange | |
39
+ | GetVideoclips | fromDate, tillDate, limit, offset, cameras, detectionClasses | |
40
+ | GetCameraDayData | deviceId, day | |
41
+ | GetClusteredDayData | deviceId, days, bucketMs, enabledClasses, classFilter | |
42
+ | GetClusterEvents | clusterId, deviceId, startMs, endMs | |
43
+ | GetArtifacts | deviceId, day | |
44
+ | GetLatestRuleArtifacts | deviceId, limit | |
45
+ | RemoteLog | level, message | |
46
+
47
+ ---
48
+
49
+ ## 3. Modifiche al plugin advanced-notifier
50
+
51
+ ### 3.1 package.json — aggiungere interfaceDescriptors
52
+
53
+ ```json
54
+ {
55
+ "scrypted": {
56
+ "interfaces": ["Settings", "DeviceProvider", "MixinProvider", "HttpRequestHandler", "Videoclips", "LauncherApplication", "PushHandler"],
57
+ "interfaceDescriptors": {
58
+ "EventsAppApi": {
59
+ "name": "EventsAppApi",
60
+ "methods": [
61
+ "getConfigs",
62
+ "getCamerasStatus",
63
+ "getEvents",
64
+ "getVideoclips",
65
+ "getCameraDayData",
66
+ "getClusteredDayData",
67
+ "getClusterEvents",
68
+ "getArtifacts",
69
+ "getLatestRuleArtifacts",
70
+ "remoteLog"
71
+ ],
72
+ "properties": []
73
+ }
74
+ }
75
+ }
76
+ }
77
+ ```
78
+
79
+ ### 3.2 utils.ts — costante interfaccia
80
+
81
+ ```ts
82
+ export const EVENTS_APP_API_INTERFACE = "EventsAppApi";
83
+ ```
84
+
85
+ ### 3.3 main.ts — aggiungere interfaccia al data fetcher
86
+
87
+ In `onDeviceDiscovered` per DATA_FETCHER_NATIVE_ID:
88
+
89
+ ```ts
90
+ interfaces: [
91
+ ScryptedInterface.VideoClips,
92
+ ScryptedInterface.EventRecorder,
93
+ ScryptedInterface.Settings,
94
+ EVENTS_APP_API_INTERFACE, // <-- aggiungere
95
+ ],
96
+ ```
97
+
98
+ ### 3.4 dataFetcher.ts — implementare EventsAppApi
99
+
100
+ La classe `AdvancedNotifierDataFetcher` deve implementare i metodi pubblici che mappano 1:1 con gli apimethod. Esempio:
101
+
102
+ ```ts
103
+ // EventsAppApi interface
104
+ async getConfigs(): Promise<{ cameras: ...; enabledDetectionSources: string[] }> {
105
+ const { statusCode, body } = await this.handleEventsAppRequest('GetConfigs', {});
106
+ if (statusCode !== 200) throw new Error(JSON.stringify(body));
107
+ return body as any;
108
+ }
109
+ async getCamerasStatus(): Promise<CamerasStatusResponse> { ... }
110
+ async getEvents(payload: GetEventsPayload): Promise<GetEventsResponse> { ... }
111
+ // ... etc
112
+ ```
113
+
114
+ Oppure, più pulito: estrarre la logica da `handleEventsAppRequest` in metodi dedicati e far sì che `handleEventsAppRequest` li chiami, così si evita duplicazione.
115
+
116
+ ---
117
+
118
+ ## 4. Come il server Scrypted gestisce interfaceDescriptors
119
+
120
+ Il server Scrypted (koush/scrypted) legge `interfaceDescriptors` dal `package.json` del plugin. Quando un device dichiara un'interfaccia in `interfaces`, il server:
121
+
122
+ 1. Verifica che l'interfaccia sia in `interfaceDescriptors` (per interfacce custom)
123
+ 2. Espone i metodi via RPC sulla socket Engine.IO
124
+ 3. Il client `@scrypted/client` può chiamare `device.getConfigs()` e la chiamata viene serializzata e inviata via socket
125
+
126
+ Non serve modificare il server: il supporto è già presente. Il client deve solo usare `client.systemManager.getDeviceById(deviceId)` e chiamare i metodi sull'oggetto restituito.
127
+
128
+ ---
129
+
130
+ ## 5. Modifiche al client (camstack / scrypted-an-frontend)
131
+
132
+ ### 5.1 Trovare il device Events App
133
+
134
+ Il device "Advanced notifier data fetcher" ha tipo `API` e implementa `EventsAppApi`. Per ottenere il suo ID:
135
+
136
+ ```ts
137
+ const state = client.systemManager.getSystemState();
138
+ const eventsAppDeviceId = Object.entries(state).find(
139
+ ([_, d]) => (d as any)?.interfaces?.includes?.('EventsAppApi')
140
+ )?.[0];
141
+ ```
142
+
143
+ Oppure cercare per nome/tipo se lo stato lo espone.
144
+
145
+ ### 5.2 Sostituire fetch con chiamate SDK
146
+
147
+ **Prima (HTTP):**
148
+ ```ts
149
+ const res = await fetch(`${baseUrl}/eventsApp`, {
150
+ method: 'POST',
151
+ body: JSON.stringify({ apimethod: 'GetClusteredDayData', payload: { deviceId, days, bucketMs } }),
152
+ headers: { 'Content-Type': 'application/json', Authorization: getAuthHeader(auth) },
153
+ });
154
+ const data = await res.json();
155
+ ```
156
+
157
+ **Dopo (Socket):**
158
+ ```ts
159
+ const client = await getScryptedClient(auth);
160
+ const device = client.systemManager.getDeviceById(eventsAppDeviceId) as EventsAppApi;
161
+ const data = await device.getClusteredDayData({ deviceId, days, bucketMs });
162
+ ```
163
+
164
+ ### 5.3 Cosa resta su HTTP
165
+
166
+ - **URL di immagini/thumbnail/video**: usati in `<Image src={url} />` e `<Video source={{ uri }} />` — devono restare URL HTTP. Il plugin continua a servire `/eventThumbnail/...`, `/eventImage/...`, `/eventVideoclip/...` via HttpRequestHandler.
167
+ - **Autenticazione**: la socket SDK usa già le credenziali del client (login con username/password). Non serve più Basic auth per le chiamate dati.
168
+
169
+ ---
170
+
171
+ ## 6. Ordine di implementazione
172
+
173
+ 1. **Plugin**: aggiungere `interfaceDescriptors` e `EVENTS_APP_API_INTERFACE`, implementare i metodi su `AdvancedNotifierDataFetcher`
174
+ 2. **Mantenere HttpRequestHandler**: per `apimethod` POST a `/eventsApp` — opzionale durante la transizione (fallback)
175
+ 3. **Client**: creare `eventsAppSdk.ts` che usa la socket; `eventsAppApi.ts` può passare a usare l'SDK quando il client è connesso
176
+ 4. **Rimuovere** le chiamate fetch a `/eventsApp` dal client una volta validato l'SDK
177
+
178
+ ---
179
+
180
+ ## 7. Riferimenti
181
+
182
+ - [LLM plugin package.json](https://github.com/scryptedapp/llm/blob/main/package.json) — esempio interfaceDescriptors
183
+ - [Scrypted Developer Docs](https://developer.scrypted.app/) — interfacce e plugin
184
+ - [@scrypted/client](https://www.npmjs.com/package/@scrypted/client) — SDK client con socket
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": "4.8.37",
8
+ "version": "4.8.38",
9
9
  "scripts": {
10
10
  "scrypted-setup-project": "scrypted-setup-project",
11
11
  "prescrypted-setup-project": "scrypted-package-json",
@@ -49,9 +49,31 @@
49
49
  "HttpRequestHandler",
50
50
  "Videoclips",
51
51
  "LauncherApplication",
52
- "PushHandler"
52
+ "PushHandler",
53
+ "EventsAppApi"
53
54
  ],
54
- "pluginDependencies": []
55
+ "pluginDependencies": [],
56
+ "interfaceDescriptors": {
57
+ "EventsAppApi": {
58
+ "name": "EventsAppApi",
59
+ "methods": [
60
+ "getConfigs",
61
+ "getCamerasStatus",
62
+ "getEvents",
63
+ "getVideoclips",
64
+ "getCameraDayData",
65
+ "getClusteredDayData",
66
+ "getClusterEvents",
67
+ "getArtifacts",
68
+ "getLatestRuleArtifacts",
69
+ "remoteLog",
70
+ "getAsset",
71
+ "getVideoClipThumbnailData",
72
+ "getVideoClipData"
73
+ ],
74
+ "properties": []
75
+ }
76
+ }
55
77
  },
56
78
  "dependencies": {
57
79
  "@scrypted/common": "file:../scrypted/common",
@@ -69,4 +91,4 @@
69
91
  "@types/lodash": "^4.17.12",
70
92
  "@types/node": "^20.11.0"
71
93
  }
72
- }
94
+ }