@startuml _get_all_user_cameras Sequence Diagram title Последовательность выполнения _get_all_user_cameras participant "Caller" as caller participant "_get_all_user_cameras" as main_func participant "_get_servers" as get_servers participant "MongoDB" as mongo participant "ivideon.servers" as servers_collection note over main_func Входные параметры: - user_id: int - requested_cameras: list[str] (формат: ["server1:0", "server1:1"]) - service_name: str (например: "crowd") end note caller -> main_func: _get_all_user_cameras(user_id, requested_cameras, service_name) activate main_func main_func -> main_func: cameras = {} main_func -> get_servers: _get_servers(requested_cameras) activate get_servers note over get_servers Извлекает server_ids из camera_ids: ["server1:0", "server1:1"] → ["server1", "server1"] → ["server1"] end note @startuml _get_all_user_cameras Activity Diagram title Алгоритм работы _get_all_user_cameras start note right **Входные параметры:** • user_id: int • requested_cameras: list[str] (формат: ["server1:0", "server1:1"]) • service_name: str (например: "crowd") end note :Инициализация cameras = {}; :Извлечь server_ids из requested_cameras| note right ["server1:0", "server1:1"] → ["server1"] end note :Построить MongoDB запрос: query = { 'deleted': {'$ne': True}, '_id': {'$in': server_ids} }| :Задать проекцию полей: projection = { '_id': 1, 'owner_id': 1, 'name': 1, 'cameras': 1, 'cam_services': 1, 'info': 1, 'timezone': 1 }| :Выполнить запрос к MongoDB: servers = db.ivideon().servers.find(query, projection)| partition "Обработка серверов" { :Взять следующий server; while (Есть серверы для обработки?) is (да) :server_id = server['_id']; :is_shared = server['owner_id'] != user_id; :server_build_type = server.get('info', {}).get('build_type', ''); :is_server_embedded = server_build_type.endswith('camera'); :cam_services = server.get('cam_services', {}); partition "Обработка камер сервера" { :Взять следующую камеру (camera_idx, camera_data); while (Есть камеры на сервере?) is (да) :service_info = cam_services.get(camera_idx, {}) .get(service_name, {}); if (service_info.get('active', False) == True?) then (да) :camera_id = f'{server_id}:{camera_idx}'; if (is_server_embedded?) then (да) :camera_name = server['name']; else (нет) :camera_name = camera_data.get('name'); endif :cameras[camera_id] = { 'id': camera_id, 'owner_id': server['owner_id'], 'server': server_id, 'name': camera_name, 'is_shared': is_shared, 'timezone': server.get('timezone') or server.get('timezone_default'), 'is_embedded': is_server_embedded }; else (нет) note right: Камера пропускается - сервис неактивен endif :Взять следующую камеру (camera_idx, camera_data); endwhile (нет) } :Взять следующий server; endwhile (нет) } :return cameras; stop note left **Результат:** dict[camera_id, camera_info] **Пример:** { "507f...439011:0": { "id": "507f...439011:0", "owner_id": "user123", "server": "507f...439011", "name": "Камера входа", "is_shared": false, "timezone": "Europe/Moscow", "is_embedded": false } } end note @enduml ggVG get_servers -> get_servers: requested_server_ids = [camera_id.split(':')[0] \\nfor camera_id in requested_camera_ids] get_servers -> get_servers: query = {\n 'deleted': {'$ne': True},\n '_id': {'$in': requested_server_ids}\n} get_servers -> get_servers: projection = {\n '_id': 1, 'owner_id': 1, 'name': 1,\n 'cameras': 1, 'cam_services': 1,\n 'info': 1, 'timezone': 1\n} get_servers -> mongo: db.ivideon().servers.find(query, projection) activate mongo mongo -> servers_collection: find documents activate servers_collection servers_collection -> mongo: return server documents deactivate servers_collection mongo -> get_servers: list[server_documents] deactivate mongo get_servers -> main_func: return servers_list deactivate get_servers loop for each server in servers_list main_func -> main_func: server@startuml _get_all_user_cameras Activity Diagram title Алгоритм работы _get_all_user_cameras start note right **Входные параметры:** • user_id: int • requested_cameras: list[str] (формат: ["server1:0", "server1:1"]) • service_name: str (например: "crowd") end note :Инициализация cameras = {}; :Извлечь server_ids из requested_cameras| note right ["server1:0", "server1:1"] → ["server1"] end note :Построить MongoDB запрос: query = { 'deleted': {'$ne': True}, '_id': {'$in': server_ids} }| :Задать проекцию полей: projection = { '_id': 1, 'owner_id': 1, 'name': 1, 'cameras': 1, 'cam_services': 1, 'info': 1, 'timezone': 1 }| :Выполнить запрос к MongoDB: servers = db.ivideon().servers.find(query, projection)| partition "Обработка серверов" { :Взять следующий server; while (Есть серверы для обработки?) is (да) :server_id = server['_id']; :is_shared = server['owner_id'] != user_id; :server_build_type = server.get('info', {}).get('build_type', ''); :is_server_embedded = server_build_type.endswith('camera'); :cam_services = server.get('cam_services', {}); partition "Обработка камер сервера" { :Взять следующую камеру (camera_idx, camera_data); while (Есть камеры на сервере?) is (да) :service_info = cam_services.get(camera_idx, {}) .get(service_name, {}); if (service_info.get('active', False) == True?) then (да) :camera_id = f'{server_id}:{camera_idx}'; if (is_server_embedded?) then (да) :camera_name = server['name']; else (нет) :camera_name = camera_data.get('name'); endif :cameras[camera_id] = { 'id': camera_id, 'owner_id': server['owner_id'], 'server': server_id, 'name': camera_name, 'is_shared': is_shared, 'timezone': server.get('timezone') or server.get('timezone_default'), 'is_embedded': is_server_embedded }; else (нет) note right: Камера пропускается - сервис неактивен endif :Взять следующую камеру (camera_idx, camera_data); endwhile (нет) } :Взять следующий server; endwhile (нет) } :return cameras; stop note left **Результат:** dict[camera_id, camera_info] **Пример:** { "507f...439011:0": { "id": "507f...439011:0", "owner_id": "user123", "server": "507f...439011", "name": "Камера входа", "is_shared": false, "timezone": "Europe/Moscow", "is_embedded": false } } end note @enduml ggVG_id = server['_id'] main_func -> main_func: is_shared = server['owner_id'] != user_id main_func -> main_func: server_build_type = server.get('info', {}).get('build_type', '') main_func -> main_func: is_server_embedded = server_build_type.endswith('camera') main_func -> main_func: cam_services = server.get('cam_services', {}) loop for camera_idx, camera_data in server.cameras.items() main_func -> main_func: service_info = cam_services.get(camera_idx, {})\\n .get(service_name, {}) alt service_info.get('active', False) == True main_func -> main_func: camera_id = f'{server_id}:{camera_idx}' alt is_server_embedded == True main_func -> main_func: camera_name = server['name'] else main_func -> main_func: camera_name = camera_data.get('name') end main_func -> main_func: cameras[camera_id] = {\n 'id': camera_id,\n 'owner_id': server['owner_id'],\n 'server': server_id,\n 'name': camera_name,\n 'is_shared': is_shared,\n 'timezone': server.timezone,\n 'is_embedded': is_server_embedded\n} note right Создается полная информация о камере для возврата end note else note right Камера пропускается: сервис неактивен end note end end end main_func -> caller: return cameras dict deactivate main_func note over caller Результат: dict[camera_id, camera_info] где camera_id = "server_id:camera_index" Пример: { "507f...439011:0": { "id": "507f...439011:0", "owner_id": "user123", "server": "507f...439011", "name": "Камера входа", "is_shared": false, "timezone": "Europe/Moscow", "is_embedded": false } } end note @enduml