@blueharford/scrypted-spatial-awareness 0.6.19 → 0.6.21

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/out/plugin.zip CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blueharford/scrypted-spatial-awareness",
3
- "version": "0.6.19",
3
+ "version": "0.6.21",
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",
package/src/main.ts CHANGED
@@ -1062,18 +1062,24 @@ export class SpatialAwarenessPlugin extends ScryptedDeviceBase
1062
1062
  if (request.method === 'GET') {
1063
1063
  const topologyJson = this.storage.getItem('topology');
1064
1064
  const topology = topologyJson ? JSON.parse(topologyJson) : createEmptyTopology();
1065
+ this.console.log(`[Topology API] GET - drawnZones: ${topology.drawnZones?.length || 0}`);
1065
1066
  response.send(JSON.stringify(topology), {
1066
1067
  headers: { 'Content-Type': 'application/json' },
1067
1068
  });
1068
1069
  } else if (request.method === 'PUT' || request.method === 'POST') {
1069
1070
  try {
1070
1071
  const topology = JSON.parse(request.body!) as CameraTopology;
1072
+ this.console.log(`[Topology API] PUT received - drawnZones: ${topology.drawnZones?.length || 0}`);
1073
+ if (topology.drawnZones?.length) {
1074
+ this.console.log(`[Topology API] Zone names: ${topology.drawnZones.map(z => z.name).join(', ')}`);
1075
+ }
1071
1076
  this.storage.setItem('topology', JSON.stringify(topology));
1072
1077
  await this.startTrackingEngine(topology);
1073
1078
  response.send(JSON.stringify({ success: true }), {
1074
1079
  headers: { 'Content-Type': 'application/json' },
1075
1080
  });
1076
1081
  } catch (e) {
1082
+ this.console.error(`[Topology API] PUT error:`, e);
1077
1083
  response.send(JSON.stringify({ error: 'Invalid topology JSON' }), {
1078
1084
  code: 400,
1079
1085
  headers: { 'Content-Type': 'application/json' },
@@ -167,6 +167,8 @@ export const EDITOR_HTML = `<!DOCTYPE html>
167
167
  <button class="btn" id="tool-wall" onclick="setTool('wall')">Draw Wall</button>
168
168
  <button class="btn" id="tool-room" onclick="setTool('room')">Draw Room</button>
169
169
  <button class="btn" id="tool-zone" onclick="setTool('zone')" style="background: #2e7d32;">Draw Zone</button>
170
+ <button class="btn" id="finish-zone-btn" onclick="finishZoneDrawing()" style="background: #1976d2; display: none;">Finish Zone</button>
171
+ <button class="btn" id="cancel-zone-btn" onclick="cancelZoneDrawing()" style="background: #dc2626; display: none;">Cancel Zone</button>
170
172
  <button class="btn" id="tool-camera" onclick="setTool('camera')">Place Camera</button>
171
173
  <button class="btn" id="tool-landmark" onclick="setTool('landmark')">Place Landmark</button>
172
174
  <button class="btn" id="tool-connect" onclick="setTool('connect')">Connect</button>
@@ -404,6 +406,8 @@ export const EDITOR_HTML = `<!DOCTYPE html>
404
406
  let zoneDrawingMode = false;
405
407
  let currentZonePoints = [];
406
408
  let pendingZoneConfig = null;
409
+ let lastClickTime = 0;
410
+ const DOUBLE_CLICK_THRESHOLD = 400; // ms
407
411
 
408
412
  // Zone colors by type
409
413
  const ZONE_COLORS = {
@@ -1609,9 +1613,11 @@ export const EDITOR_HTML = `<!DOCTYPE html>
1609
1613
  // Zone list
1610
1614
  const zoneList = document.getElementById('zone-list');
1611
1615
  const zones = topology.drawnZones || [];
1616
+ console.log('[updateUI] Zone list update - topology.drawnZones:', zones.length, 'zones');
1612
1617
  if (zones.length === 0) {
1613
1618
  zoneList.innerHTML = '<div class="zone-item" style="color: #666; text-align: center; cursor: default; padding: 8px;">No zones drawn</div>';
1614
1619
  } else {
1620
+ console.log('[updateUI] Rendering', zones.length, 'zones:', zones.map(z => z.name).join(', '));
1615
1621
  zoneList.innerHTML = zones.map(z => {
1616
1622
  const color = ZONE_STROKE_COLORS[z.type] || ZONE_STROKE_COLORS.custom;
1617
1623
  return '<div class="camera-item ' + (selectedItem?.type === 'zone' && selectedItem?.id === z.id ? 'selected' : '') + '" onclick="selectZone(\\'' + z.id + '\\')" style="border-left: 3px solid ' + color + ';"><div class="camera-name">' + z.name + '</div><div class="camera-info">' + z.type + ' | ' + z.polygon.length + ' points</div></div>';
@@ -1754,9 +1760,14 @@ export const EDITOR_HTML = `<!DOCTYPE html>
1754
1760
  pendingZoneConfig = { name, type, description };
1755
1761
  zoneDrawingMode = true;
1756
1762
  currentZonePoints = [];
1763
+ lastClickTime = 0;
1757
1764
  closeModal('add-zone-modal');
1758
- setStatus('Zone drawing mode - click to add points, double-click to finish', 'warning');
1765
+ setStatus('Zone drawing mode - click to add points, click Finish Zone when done', 'warning');
1766
+ // Show zone drawing buttons
1767
+ document.getElementById('finish-zone-btn').style.display = 'inline-block';
1768
+ document.getElementById('cancel-zone-btn').style.display = 'inline-block';
1759
1769
  render();
1770
+ console.log('[Zone] Drawing mode started for:', name);
1760
1771
  }
1761
1772
 
1762
1773
  function cancelZoneDrawing() {
@@ -1764,9 +1775,13 @@ export const EDITOR_HTML = `<!DOCTYPE html>
1764
1775
  currentZonePoints = [];
1765
1776
  pendingZoneConfig = null;
1766
1777
  closeModal('add-zone-modal');
1778
+ // Hide zone drawing buttons
1779
+ document.getElementById('finish-zone-btn').style.display = 'none';
1780
+ document.getElementById('cancel-zone-btn').style.display = 'none';
1767
1781
  setTool('select');
1768
1782
  setStatus('Zone drawing cancelled', 'success');
1769
1783
  render();
1784
+ console.log('[Zone] Drawing mode cancelled');
1770
1785
  }
1771
1786
 
1772
1787
  function finishZoneDrawing() {
@@ -1801,6 +1816,10 @@ export const EDITOR_HTML = `<!DOCTYPE html>
1801
1816
  currentZonePoints = [];
1802
1817
  pendingZoneConfig = null;
1803
1818
 
1819
+ // Hide zone drawing buttons
1820
+ document.getElementById('finish-zone-btn').style.display = 'none';
1821
+ document.getElementById('cancel-zone-btn').style.display = 'none';
1822
+
1804
1823
  setTool('select');
1805
1824
  updateUI();
1806
1825
  render();
@@ -1902,9 +1921,21 @@ export const EDITOR_HTML = `<!DOCTYPE html>
1902
1921
 
1903
1922
  // Handle zone drawing mode separately
1904
1923
  if (zoneDrawingMode) {
1924
+ const now = Date.now();
1925
+ const timeSinceLastClick = now - lastClickTime;
1926
+ lastClickTime = now;
1927
+
1928
+ // If this is the second click of a double-click, don't add a point
1929
+ // The dblclick event will handle finishing the zone
1930
+ if (timeSinceLastClick < DOUBLE_CLICK_THRESHOLD && currentZonePoints.length >= 3) {
1931
+ console.log('[Zone] Double-click detected, skipping point addition');
1932
+ return;
1933
+ }
1934
+
1905
1935
  currentZonePoints.push({ x, y });
1936
+ console.log('[Zone] Added point', currentZonePoints.length, 'at', x, y);
1906
1937
  render();
1907
- setStatus('Point ' + currentZonePoints.length + ' added. ' + (currentZonePoints.length < 3 ? 'Need at least 3 points.' : 'Double-click or Enter to finish.'), 'warning');
1938
+ setStatus('Point ' + currentZonePoints.length + ' added. ' + (currentZonePoints.length < 3 ? 'Need at least 3 points.' : 'Click Finish Zone to complete.'), 'warning');
1908
1939
  return;
1909
1940
  }
1910
1941
 
@@ -1962,7 +1993,9 @@ export const EDITOR_HTML = `<!DOCTYPE html>
1962
1993
 
1963
1994
  // Double-click to finish zone drawing
1964
1995
  canvas.addEventListener('dblclick', (e) => {
1996
+ console.log('[Zone] dblclick event, zoneDrawingMode:', zoneDrawingMode, 'points:', currentZonePoints.length);
1965
1997
  if (zoneDrawingMode && currentZonePoints.length >= 3) {
1998
+ console.log('[Zone] Calling finishZoneDrawing from dblclick');
1966
1999
  finishZoneDrawing();
1967
2000
  }
1968
2001
  });