@blueharford/scrypted-spatial-awareness 0.4.7 → 0.5.0-beta

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/README.md CHANGED
@@ -51,6 +51,7 @@ Done! Your camera topology is configured.
51
51
  ### Visual Editor
52
52
  - **Floor Plan** - Upload image or draw with built-in tools
53
53
  - **Drag & Drop** - Place cameras, draw connections
54
+ - **Polygon Zone Drawing** - Draw custom zones (yards, driveways, patios, etc.)
54
55
  - **Live Tracking** - Watch objects move in real-time
55
56
 
56
57
  ### AI Features (optional)
@@ -58,11 +59,74 @@ Done! Your camera topology is configured.
58
59
  - **Auto-Learning** - Transit times adjust based on observations
59
60
  - **Connection Suggestions** - System suggests new camera paths
60
61
  - **Landmark Discovery** - AI identifies landmarks from footage
62
+ - **Auto-Topology Discovery** - Vision LLM analyzes camera views to build topology
61
63
 
62
64
  ### Integrations
63
65
  - **MQTT** - Home Assistant integration
64
66
  - **REST API** - Query tracked objects programmatically
65
67
 
68
+ ## Topology Configuration
69
+
70
+ The plugin uses topology data (landmarks, zones, connections) to generate meaningful alerts. Camera names are **not** used for location descriptions - only topology landmarks matter.
71
+
72
+ ### Setting Up Landmarks
73
+
74
+ For best alert quality, configure landmarks in the topology editor:
75
+
76
+ 1. **Entry/Exit Points** - Mark where people enter/exit your property
77
+ - Examples: `Driveway`, `Front Gate`, `Side Gate`, `Street`
78
+ - Set `isEntryPoint: true` or `isExitPoint: true`
79
+
80
+ 2. **Access Points** - Paths and walkways
81
+ - Examples: `Front Walkway`, `Back Path`, `Garage Door`
82
+ - Type: `access`
83
+
84
+ 3. **Zones** - Areas of your property
85
+ - Examples: `Front Yard`, `Back Yard`, `Side Yard`, `Patio`
86
+ - Type: `zone`
87
+
88
+ 4. **Structures** - Buildings and fixed features
89
+ - Examples: `Garage`, `Shed`, `Front Porch`, `Deck`
90
+ - Type: `structure`
91
+
92
+ 5. **Features** - Other notable landmarks
93
+ - Examples: `Mailbox`, `Pool`, `Garden`, `Trash Cans`
94
+ - Type: `feature`
95
+
96
+ ### Linking Landmarks to Cameras
97
+
98
+ Each camera should have `visibleLandmarks` configured - the landmarks visible in that camera's view:
99
+
100
+ ```json
101
+ {
102
+ "cameras": [{
103
+ "deviceId": "abc123",
104
+ "name": "Front Camera",
105
+ "context": {
106
+ "visibleLandmarks": ["front-door", "driveway", "mailbox"]
107
+ }
108
+ }]
109
+ }
110
+ ```
111
+
112
+ ### Example Topology
113
+
114
+ ```json
115
+ {
116
+ "landmarks": [
117
+ { "id": "driveway", "name": "Driveway", "type": "access", "isEntryPoint": true },
118
+ { "id": "front-door", "name": "Front Door", "type": "access" },
119
+ { "id": "backyard", "name": "Back Yard", "type": "zone" },
120
+ { "id": "garage", "name": "Garage", "type": "structure" }
121
+ ]
122
+ }
123
+ ```
124
+
125
+ With proper landmarks, alerts become rich and contextual:
126
+ - "Person arrived at the Driveway from Main Street"
127
+ - "Person moved from the Front Porch heading towards the Back Yard"
128
+ - "Person left the Garage towards Driveway after 2m on property - visited Driveway > Front Door > Garage"
129
+
66
130
  ## Configuration
67
131
 
68
132
  ### Settings
@@ -108,6 +172,98 @@ Base URL: `/endpoint/@blueharford/scrypted-spatial-awareness`
108
172
  | `/api/training/apply` | POST | Apply results to topology |
109
173
  | `/api/training/status` | GET | Current training status |
110
174
 
175
+ ### Discovery API
176
+
177
+ | Endpoint | Method | Description |
178
+ |----------|--------|-------------|
179
+ | `/api/discovery/scan` | POST | Run full discovery scan |
180
+ | `/api/discovery/status` | GET | Current discovery status |
181
+ | `/api/discovery/suggestions` | GET | Pending suggestions |
182
+ | `/api/discovery/camera/{id}` | GET | Analyze single camera |
183
+
184
+ ## Auto-Topology Discovery
185
+
186
+ The plugin can automatically analyze camera views using a vision-capable LLM to discover landmarks, zones, and camera connections.
187
+
188
+ ### How It Works
189
+
190
+ 1. **Capture Snapshots** - System takes a picture from each camera
191
+ 2. **Scene Analysis** - Vision LLM identifies landmarks, zones, and edges in each view
192
+ 3. **Cross-Camera Correlation** - LLM correlates findings across cameras to identify shared landmarks and connections
193
+ 4. **Suggestions** - Discoveries are presented as suggestions you can accept or reject
194
+
195
+ ### Using Discovery
196
+
197
+ **Manual Scan:**
198
+ 1. Open the topology editor (`/ui/editor`)
199
+ 2. Find the "Auto-Discovery" section in the sidebar
200
+ 3. Click "Scan Now"
201
+ 4. Review and accept/reject suggestions
202
+
203
+ **Automatic Scan:**
204
+ - Set `Auto-Discovery Interval (hours)` in plugin settings
205
+ - System will periodically scan and generate suggestions
206
+ - Set to 0 to disable automatic scanning
207
+
208
+ ### Discovery Settings
209
+
210
+ | Setting | Default | Description |
211
+ |---------|---------|-------------|
212
+ | Auto-Discovery Interval | 0 (disabled) | Hours between automatic scans (0 = disabled) |
213
+ | Min Landmark Confidence | 0.6 | Minimum confidence for landmark suggestions |
214
+ | Min Connection Confidence | 0.5 | Minimum confidence for connection suggestions |
215
+ | Auto-Accept Threshold | 0.85 | Auto-accept suggestions above this confidence |
216
+
217
+ > **Rate Limiting Note:** If you set the interval to less than 1 hour, a warning will appear in the discovery status. Frequent scans can consume significant LLM API quota and may be rate-limited by your provider.
218
+
219
+ ### Requirements
220
+
221
+ - **Vision-capable LLM** - Install @scrypted/llm with a vision model (OpenAI GPT-4V, Claude, etc.)
222
+ - **Camera access** - Plugin needs camera.takePicture() capability
223
+
224
+ ### What Gets Discovered
225
+
226
+ - **Landmarks**: Doors, gates, mailbox, garage, structures, fences
227
+ - **Zones**: Front yard, driveway, patio, street, walkways
228
+ - **Connections**: Suggested camera paths with transit time estimates
229
+ - **Edges**: What's visible at frame boundaries (for correlation)
230
+
231
+ ## Zone Drawing
232
+
233
+ The visual editor includes a polygon zone drawing tool for marking areas on your floor plan.
234
+
235
+ ### How to Draw Zones
236
+
237
+ 1. Click the **Draw Zone** button in the toolbar (green)
238
+ 2. Enter a zone name and select the type (yard, driveway, patio, etc.)
239
+ 3. Click **Start Drawing**
240
+ 4. Click on the canvas to add polygon points
241
+ 5. **Double-click** or press **Enter** to finish the zone
242
+ 6. Press **Escape** to cancel, **Backspace** to undo last point
243
+
244
+ ### Zone Types
245
+
246
+ | Type | Color | Description |
247
+ |------|-------|-------------|
248
+ | Yard | Green | Front yard, backyard, side yard |
249
+ | Driveway | Gray | Driveway, parking area |
250
+ | Street | Dark Gray | Street, sidewalk |
251
+ | Patio | Orange | Patio, deck |
252
+ | Walkway | Brown | Walkways, paths |
253
+ | Parking | Light Gray | Parking lot, parking space |
254
+ | Garden | Light Green | Garden, landscaped area |
255
+ | Pool | Blue | Pool area |
256
+ | Garage | Medium Gray | Garage area |
257
+ | Entrance | Pink | Entry areas |
258
+ | Custom | Purple | Custom zone type |
259
+
260
+ ### Using Zones
261
+
262
+ - Click on a zone to select it and edit its properties
263
+ - Zones are color-coded by type for easy identification
264
+ - Zones help provide context for object movement descriptions
265
+ - Auto-Discovery can suggest zones based on camera analysis
266
+
111
267
  ## MQTT Topics
112
268
 
113
269
  Base: `scrypted/spatial-awareness`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blueharford/scrypted-spatial-awareness",
3
- "version": "0.4.7",
3
+ "version": "0.5.0-beta",
4
4
  "description": "Cross-camera object tracking for Scrypted NVR with spatial awareness",
5
5
  "author": "Joshua Seidel <blueharford>",
6
6
  "license": "Apache-2.0",
@@ -46,7 +46,24 @@ export class ObjectCorrelator {
46
46
  }
47
47
  }
48
48
 
49
- if (candidates.length === 0) return null;
49
+ if (candidates.length === 0) {
50
+ // No candidates above threshold - try to find best match with relaxed criteria
51
+ // This helps when there's only one object of this class active
52
+ const sameClassObjects = activeObjects.filter(
53
+ o => o.className === sighting.detection.className
54
+ );
55
+
56
+ if (sameClassObjects.length === 1) {
57
+ // Only one object of this class - likely the same one
58
+ const candidate = await this.evaluateCandidate(sameClassObjects[0], sighting);
59
+ // Accept with lower threshold if timing is reasonable
60
+ if (candidate.confidence >= 0.3 && candidate.factors.timing > 0) {
61
+ return candidate;
62
+ }
63
+ }
64
+
65
+ return null;
66
+ }
50
67
 
51
68
  // Sort by confidence (highest first)
52
69
  candidates.sort((a, b) => b.confidence - a.confidence);
@@ -137,15 +154,23 @@ export class ObjectCorrelator {
137
154
 
138
155
  if (!connection) {
139
156
  // No defined connection - still allow correlation based on reasonable timing
140
- // Allow up to 2 minutes transit between any cameras
141
- const MAX_UNCHARTED_TRANSIT = 120000; // 2 minutes
157
+ // Allow up to 5 minutes transit between any cameras (property could be large)
158
+ const MAX_UNCHARTED_TRANSIT = 300000; // 5 minutes
142
159
  if (transitTime > 0 && transitTime < MAX_UNCHARTED_TRANSIT) {
143
160
  // Score based on how reasonable the timing is
144
- // Shorter transits are more likely to be the same object
145
- const timingScore = Math.max(0.3, 1 - (transitTime / MAX_UNCHARTED_TRANSIT));
146
- return timingScore;
161
+ // Give higher base score for reasonable transits (encourages matching)
162
+ if (transitTime < 60000) {
163
+ // Under 1 minute - very likely same object
164
+ return 0.9;
165
+ } else if (transitTime < 120000) {
166
+ // Under 2 minutes - probably same object
167
+ return 0.7;
168
+ } else {
169
+ // 2-5 minutes - possible but less certain
170
+ return Math.max(0.4, 0.7 - (transitTime - 120000) / 180000 * 0.3);
171
+ }
147
172
  }
148
- return 0.2;
173
+ return 0.3; // Even long transits get some credit
149
174
  }
150
175
  const { min, typical, max } = connection.transitTime;
151
176