Fix: several bug fixes

This commit is contained in:
ziesorx 2025-09-12 22:44:27 +07:00
parent 96ecc321ec
commit 9967bff6dc
4 changed files with 112 additions and 31 deletions

View file

@ -83,6 +83,8 @@ class WebSocketHandler:
# Message handlers
self.message_handlers: Dict[str, MessageHandler] = {
"subscribe": self._handle_subscribe,
"unsubscribe": self._handle_unsubscribe,
"setSubscriptionList": self._handle_set_subscription_list,
"requestState": self._handle_request_state,
"setSessionId": self._handle_set_session,
@ -180,21 +182,21 @@ class WebSocketHandler:
is_online = self.stream_manager.is_stream_active(camera_id)
connection_info = {
"subscriptionIdentifier": stream_info.get("subscriptionIdentifier", camera_id),
"modelId": stream_info.get("modelId", 0),
"modelName": stream_info.get("modelName", "Unknown Model"),
"subscriptionIdentifier": getattr(stream_info, "subscriptionIdentifier", camera_id),
"modelId": getattr(stream_info, "modelId", 0),
"modelName": getattr(stream_info, "modelName", "Unknown Model"),
"online": is_online
}
# Add crop coordinates if available
if "cropX1" in stream_info:
connection_info["cropX1"] = stream_info["cropX1"]
if "cropY1" in stream_info:
connection_info["cropY1"] = stream_info["cropY1"]
if "cropX2" in stream_info:
connection_info["cropX2"] = stream_info["cropX2"]
if "cropY2" in stream_info:
connection_info["cropY2"] = stream_info["cropY2"]
if hasattr(stream_info, "cropX1"):
connection_info["cropX1"] = stream_info.cropX1
if hasattr(stream_info, "cropY1"):
connection_info["cropY1"] = stream_info.cropY1
if hasattr(stream_info, "cropX2"):
connection_info["cropX2"] = stream_info.cropX2
if hasattr(stream_info, "cropY2"):
connection_info["cropY2"] = stream_info.cropY2
camera_connections.append(connection_info)
@ -269,7 +271,7 @@ class WebSocketHandler:
continue
# Get model for this camera
model_id = stream_info.get("modelId")
model_id = getattr(stream_info, "modelId", None)
if not model_id:
continue
@ -413,7 +415,8 @@ class WebSocketHandler:
await self.stream_manager.stop_stream(camera_id)
self.model_manager.unload_models(camera_id)
subscription_to_camera.pop(sub_id, None)
self.session_cache.clear_session(camera_id)
# Clear cached data (SessionCacheManager handles this automatically)
# Note: clear_session method not available, cleanup happens automatically
logger.info(f"Removed subscription: {sub_id}")
# Add new subscriptions
@ -612,7 +615,7 @@ class WebSocketHandler:
) -> None:
"""Send detection result over WebSocket."""
# Get session ID for this display
subscription_id = stream_info["subscriptionIdentifier"]
subscription_id = getattr(stream_info, "subscriptionIdentifier", "")
display_id = subscription_id.split(";")[0] if ";" in subscription_id else subscription_id
session_id = self.session_ids.get(display_id)
@ -623,8 +626,8 @@ class WebSocketHandler:
"sessionId": session_id, # Required by protocol
"data": {
"detection": detection_result.to_dict(),
"modelId": stream_info["modelId"],
"modelName": stream_info["modelName"]
"modelId": getattr(stream_info, "modelId", 0),
"modelName": getattr(stream_info, "modelName", "Unknown Model")
}
}
@ -645,18 +648,18 @@ class WebSocketHandler:
"""Send camera disconnection notification."""
logger.error(f"🚨 CAMERA DISCONNECTION DETECTED: {camera_id} - sending immediate detection: null")
# Clear cached data
self.session_cache.clear_session(camera_id)
# Clear cached data (SessionCacheManager handles this automatically via cleanup)
# Note: clear_session method not available, cleanup happens automatically
# Send null detection
detection_data = {
"type": "imageDetection",
"subscriptionIdentifier": stream_info["subscriptionIdentifier"],
"subscriptionIdentifier": getattr(stream_info, "subscriptionIdentifier", ""),
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
"data": {
"detection": None,
"modelId": stream_info["modelId"],
"modelName": stream_info["modelName"]
"modelId": getattr(stream_info, "modelId", 0),
"modelName": getattr(stream_info, "modelName", "Unknown Model")
}
}
@ -672,13 +675,60 @@ class WebSocketHandler:
self.camera_monitor.mark_disconnection_notified(camera_id)
logger.info(f"📡 SENT DISCONNECTION SIGNAL - detection: null for camera {camera_id}, backend should clear session")
async def _handle_subscribe(self, data: Dict[str, Any]) -> None:
"""Handle individual subscription message."""
try:
payload = data.get("payload", {})
subscription_id = payload.get("subscriptionIdentifier")
if not subscription_id:
logger.error("Subscribe message missing subscriptionIdentifier")
return
# Convert single subscription to setSubscriptionList format
subscription_list_data = {
"type": "setSubscriptionList",
"subscriptions": [payload]
}
# Delegate to existing setSubscriptionList handler
await self._handle_set_subscription_list(subscription_list_data)
except Exception as e:
logger.error(f"Error handling subscribe: {e}")
traceback.print_exc()
async def _handle_unsubscribe(self, data: Dict[str, Any]) -> None:
"""Handle individual unsubscription message."""
try:
payload = data.get("payload", {})
subscription_id = payload.get("subscriptionIdentifier")
if not subscription_id:
logger.error("Unsubscribe message missing subscriptionIdentifier")
return
# Stop stream and clean up
camera_id = subscription_to_camera.get(subscription_id)
if camera_id:
await self.stream_manager.stop_stream(camera_id)
self.model_manager.unload_models(camera_id)
del subscription_to_camera[subscription_id]
logger.info(f"Unsubscribed from {subscription_id}")
else:
logger.warning(f"Unknown subscription ID: {subscription_id}")
except Exception as e:
logger.error(f"Error handling unsubscribe: {e}")
traceback.print_exc()
def _apply_crop(self, frame: Any, stream_info: Dict[str, Any]) -> Any:
"""Apply crop to frame if crop coordinates are specified."""
crop_coords = [
stream_info.get("cropX1"),
stream_info.get("cropY1"),
stream_info.get("cropX2"),
stream_info.get("cropY2")
getattr(stream_info, "cropX1", None),
getattr(stream_info, "cropY1", None),
getattr(stream_info, "cropX2", None),
getattr(stream_info, "cropY2", None)
]
if all(coord is not None for coord in crop_coords):