Found during the final review of #12 (detection-zone filtering). Pre-existing — not introduced by that work, and out of scope for it.
AmcrestPlugin.initCamera does this.cameras.set(camera.id, controller) (src/index.ts:335) without destroying whatever controller was already registered under that id. If both configureCameras and onCameraAdded fire for the same camera, or a camera is re-adopted without a release in between, the first controller stays alive and unreferenced.
The orphan keeps its event-stream connection, its reconnect timer and its RTSP relay running. The zone-subscription added in #15 is one more thing it holds.
Fix: destroy any existing controller for that id before replacing it.
this.cameras.get(camera.id)?.destroy();
this.cameras.set(camera.id, controller);
Found during the final review of #12 (detection-zone filtering). Pre-existing — not introduced by that work, and out of scope for it.
AmcrestPlugin.initCameradoesthis.cameras.set(camera.id, controller)(src/index.ts:335) without destroying whatever controller was already registered under that id. If bothconfigureCamerasandonCameraAddedfire for the same camera, or a camera is re-adopted without a release in between, the first controller stays alive and unreferenced.The orphan keeps its event-stream connection, its reconnect timer and its RTSP relay running. The zone-subscription added in #15 is one more thing it holds.
Fix: destroy any existing controller for that id before replacing it.