@startuml Camera Addition Workflow skinparam sequenceMessageAlign center skinparam responseMessageBelowArrow true title Ivideon Camera Addition Workflow (New User) actor "User" as user participant "API5\n(api_concept)" as api5 participant "Device Registry\n(Router)" as registry participant "API4\n(api)" as api4 participant "MongoDB" as db participant "Ivideon Server\n/Camera Device" as device participant "Broker/Hive" as broker participant "Billing System" as billing == ЭТАП 1: Инициализация (Token Creation) == user -> api5: POST /servers\n{name, device_id, device_id_type} activate api5 api5 -> api5: Server.create() api5 -> api5: AttachmentToken.create() api5 -> db: Валидация blacklist\n(device_id) db --> api5: OK api5 -> api4: POST /users/{uid}/server_attachment/tokens activate api4 api4 -> db: INSERT attachment_tokens\n{token, expires_at, status='pending'} api4 --> api5: {token, expires_at} deactivate api4 api5 -> api5: Отправка метрики\nDeviceCreationMetric(token_creation) api5 --> user: {token, expires_at, status='pending'} deactivate api5 == ЭТАП 2: Использование токена (Token Acquisition) == device -> registry: POST /public/roster\n{login=token, mac, sn} activate registry note right Камера/сервер подключается с использованием токена end note registry -> db: Поиск токена в attachment_tokens db --> registry: {token_data, customer_cloud} registry -> api5: Редирект в customer cloud\nPOST /public/roster activate api5 api5 -> api5: AttachmentToken.acquire()\n{mac_address, serial_number} api5 -> api4: POST /public/roster activate api4 api4 -> db: Создание/обновление сервера\nservers.{uin} api4 -> db: Генерация UIN и password db --> api4: {uin, password} api4 --> api5: {uin, password} deactivate api4 api5 -> db: UPDATE attachment_tokens\nstatus='finished' api5 -> api5: EVENT: attachment_token/finished api5 --> registry: {uin, password} deactivate api5 registry --> device: {uin, password} deactivate registry note right of device Устройство сохраняет UIN и password для дальнейшей аутентификации end note == ЭТАП 3: Регистрация сервера (Server Registration) == device -> broker: Подключение с\n{uin, password} activate broker broker -> db: Проверка credentials db --> broker: OK broker -> db: UPDATE servers.{uin}\n{online=true, connected=true} broker -> api4: EVENT: server/online deactivate broker == ЭТАП 4: Обнаружение и добавление камер (Camera Discovery) == device -> api4: NOTIFICATION: new_cams\n{server_id, cameras: {...}} activate api4 api4 -> api4: roster.new_cams() api4 -> db: object_lock(server_id) api4 -> api4: _process_new_cams() note right Для каждой камеры: 1. Валидация сервера 2. Фильтрация инициализированных 3. Проставление флагов: - billing_notified = True - billing_initialized = True 4. Установка timezone end note api4 -> api4: Выбор обработчика по billver:\n- b4_new_cams()\n- b5_new_cams()\n- mts_b2b_new_cams() == ЭТАП 5: Конфигурация услуг (Service Configuration) == alt Billing v4 api4 -> api4: b4_new_cams() api4 -> api4: set_defaults_for_new_objects() api4 -> db: CREATE cam_services[cam_id]\n{archive, notifications, ...} else Billing v5 api4 -> api4: b5_new_cams() api4 -> billing: camera_tariffs.try_set_default() activate billing billing -> db: Поиск prepaid plans\n(по serial number) billing -> db: CREATE camera_plan billing --> api4: OK deactivate billing api4 -> db: CREATE cam_services[cam_id] else MTS B2B api4 -> api4: mts_b2b_new_cams() api4 -> db: Поиск неназначенной\nMTS subscription api4 -> db: Назначение тарифа api4 -> api4: LOG: mts-subscription-activated end api4 -> db: UPDATE servers.{server_id}.cameras.{cam_id}\n{name, online, billing_initialized, ...} api4 -> api4: Отправка метрики\nDeviceCreationMetric(billing_subscription) api4 -> api4: Аудит лог: device/add api4 -> api4: TDC-notifier уведомление api4 --> device: OK deactivate api4 == ЭТАП 6: Отражение в интерфейсе (API Response) == user -> api5: GET /servers/{id}?projection=cameras activate api5 api5 -> db: FIND servers.{id}.cameras db --> api5: {cameras_dict} api5 -> api5: Server.cameras property loop for each camera api5 -> api5: roster.show_camera_to_user() note right Фильтрация: - Не удалена - Есть name - billing_initialized end note api5 -> api5: Camera.from_server() end api5 --> user: [\n {id, name, owner_id, online, type, ...},\n ...\n] deactivate api5 == ЭТАП 7: Управление камерой (Operations) == user -> api5: PUT /servers/{srv}/cameras/{cam}/name\n{name: "New Name"} activate api5 api5 -> api5: Проверка прав доступа api5 -> db: UPDATE servers.{srv}.cameras.{cam}.name db --> api5: OK api5 -> broker: Отправка команды на device activate broker broker -> device: UPDATE camera name broker --> api5: ACK deactivate broker api5 -> api5: Аудит лог: camera/update api5 --> user: {id, name: "New Name", ...} deactivate api5 @enduml