# 采集器设置与连接验证 ## 背景 控制台现在把“数据源目录”和“采集器配置”拆开: - `/datasources` - 展示所有数据源,包括内置和自定义。 - 点击名称只打开信息抽屉。 - 负责查看状态、触发采集和查看采集中任务。 - `/settings?tab=collector_credentials` - 显示为“采集器设置”。 - 负责 endpoint、请求头、基础参数和凭证配置。 - 所有采集器都提供连接按钮,用于健康检查。 这样做是为了减少首次使用时的认知分裂:接口地址、请求头、凭证和自定义源配置都属于“采集器设置”,而不是散落在数据源列表和系统设置多个入口里。 ## 用户侧规则 连接状态不是前端样式状态,而是由后端根据配置 checksum 和已验证记录判断。 一个内置采集器被视为“已连接”需要满足任一条件: - 当前配置已经成功采集过数据。 - 当前配置点击过连接按钮,并且后端验证成功。 如果 endpoint、请求头、基础配置或凭证指纹相对上次验证成功时发生变化,状态会回到“需要重新连接”。 ## 前端入口 ### 数据源目录 文件: - [DataSources.tsx](/home/ray/dev/linkong/planet/frontend/src/pages/DataSources/DataSources.tsx) - [index.css](/home/ray/dev/linkong/planet/frontend/src/index.css) 当前行为: - 内置数据源和自定义数据源合并为 `UnifiedDataSource` 列表。 - 表格只保留查看、采集和状态类操作。 - 名称点击打开只读抽屉。 - 抽屉中展示: - 是否内置 - 是否启用 - 模块、优先级、频率 - endpoint - 请求头 - 基础配置 - 是否需要凭证 - 有任务运行时,顶部进度区显示 `采集中 N` 可点击标签。 - 点击 `采集中 N` 打开任务列表弹窗,显示各任务进度。 `data-source-bulk-toolbar__running-pill` 是“采集中”标签的样式入口。它和其他状态标签同排,但通过 hover、箭头和蓝色描边表达可交互性。 ### 采集器设置 文件: - [Settings.tsx](/home/ray/dev/linkong/planet/frontend/src/pages/Settings/Settings.tsx) 当前行为: - `collector_credentials` tab 展示为“采集器设置”。 - 下拉框列出所有内置采集器。 - 下拉框右侧只有一个插头图标按钮,用于健康检查。 - 下拉框下方用状态标签展示: - `需要凭证` / `无需凭证` - 模块 - `启用` / `禁用` - `未检查` / `可用` / `不可用` - 是否覆盖 endpoint - 需要凭证的采集器把凭证卡片放在基础配置上方。 - 不需要凭证的采集器只显示基础配置。 连接按钮使用内联 Tabler 风格插头图标,来源语义对应 `plug-connected`,避免继续使用刷新图标表达连接动作。 ## 后端接口 ### 数据源配置列表 ```http GET /api/v1/datasources/configs/all ``` 返回 YAML 默认数据源和数据库覆盖配置的合并结果。该路由必须定义在 `/configs/{config_id}` 之前,否则 `all` 会被 FastAPI 当成路径参数并触发 422。 返回字段包括: - `name` - `default_url` - `endpoint` - `is_overridden` - `is_active` - `source_type` - `auth_type` - `headers` - `config` - `config_id` - `description` `config` 返回前会移除内部连接验证字段,避免前端把校验元数据当成用户配置展示。 ### 内置采集器连接状态 ```http POST /api/v1/datasources/configs/builtin/connection-status ``` 用途: - 给定一份候选配置。 - 计算 checksum。 - 判断当前配置是否已经连接。 当前前端主要通过连接按钮即时检查,不强依赖这个接口,但它是后续保存按钮置灰、页面初始化状态恢复的后端依据。 ### 内置采集器连接验证 ```http POST /api/v1/datasources/configs/builtin/connect ``` 用途: - 免费采集器直接请求 endpoint。 - 需要凭证的采集器走对应 credential provider。 - 验证成功后写入系统级连接记录。 成功返回中会带: - `success` - `connected` - `checksum` - `stage` - `message` - `response_time_ms` - `credential_provider` - `credential_source` ### BarentsWatch AIS 连接验证 ```http POST /api/v1/settings/integrations/barentswatch/connect GET /api/v1/settings/integrations/barentswatch/connectivity ``` BarentsWatch 使用独立接口,是因为它需要在保存前验证草稿凭证: - 使用草稿 `client_id` / `client_secret` 获取 token。 - 使用 token 请求 AIS endpoint。 - 连接成功后用草稿凭证指纹写入内置采集器连接记录。 ## 连接校验服务 文件: - [datasource_connectivity.py](/home/ray/dev/linkong/planet/backend/app/services/datasource_connectivity.py) 核心职责: - 计算内置采集器配置 checksum。 - 读取环境变量和 `~/.zshrc` 中的凭证。 - 判断当前配置是否已连接。 - 执行 endpoint 健康检查。 - 保存连接成功记录。 ### checksum 组成 checksum 包含: - 采集器名称 - endpoint - auth type - headers - 去掉内部校验字段后的 config - credential provider - 凭证指纹 凭证指纹使用凭证内容 hash,不把明文凭证写入连接记录。 ### 连接记录 连接成功记录写入 `SystemSetting`: ```text category = datasource_connectivity_validations ``` payload 以采集器 source 为 key: ```json { "barentswatch_vessels": { "checksum": "...", "status": "success", "validated_at": "2026-04-29T00:00:00+00:00", "status_code": 200, "credential_source": "datasource_config", "connected_by": "connection_button" } } ``` `connected_by` 当前有两个来源: - `connection_button` - 用户手动点击连接按钮。 - `collection` - 采集任务成功完成,系统自动记录当前有效配置已连通。 ### 成功采集即连接 调度器在采集成功后会调用连接记录写入逻辑: - [scheduler.py](/home/ray/dev/linkong/planet/backend/app/services/scheduler.py) 这样已有数据的采集器不会要求用户重复验证。只有当配置 checksum 变化时,才需要重新点击连接。 ## BarentsWatch AIS 凭证链路 文件: - [barentswatch.py](/home/ray/dev/linkong/planet/backend/app/services/barentswatch.py) - [vessel_ais.py](/home/ray/dev/linkong/planet/backend/app/services/collectors/vessel_ais.py) 解析优先级: 1. `DataSourceConfig.auth_config` 2. `DataSourceConfig.config` 3. 环境变量 4. `~/.zshrc` 支持的环境变量: ```bash export BARENTSWATCH_CLIENT_ID="..." export BARENTSWATCH_CLIENT_SECRET="..." ``` 也兼容历史拼写: ```bash export BARRENTSWATCH_CLIENT_ID="..." export BARRENTSWATCH_CLIENT_SECRET="..." ``` Token 请求规则: - Token URL:`https://id.barentswatch.no/connect/token` - `Content-Type`: `application/x-www-form-urlencoded` - Body: - `grant_type=client_credentials` - `client_id` - `client_secret` - `scope=ais` AIS 请求规则: - Endpoint 默认:`https://live.ais.barentswatch.no/v1/latest/combined` - Header:`Authorization: Bearer ` `VesselAISCollector` 不再自己读取环境变量,而是统一走 `resolve_barentswatch_config()` 和 `fetch_barentswatch_access_token()`,避免设置页、连接验证和采集器三套凭证逻辑分叉。 ## AISStream 采集器链路 文件: - [aisstream.py](/home/ray/dev/linkong/planet/backend/app/services/collectors/aisstream.py) - [vessel_ais_aggregation.py](/home/ray/dev/linkong/planet/backend/app/services/vessel_ais_aggregation.py) AISStream 使用 WebSocket 实时流,采集器只写入 `ais_raw_observations` 原始观测层,不直接覆盖最终船只展示表。聚合接口负责多源去重、字段选择和冲突记录。 配置项: - `api_key`:保存在 `DataSourceConfig.auth_config`,也可用环境变量 `AISSTREAM_API_KEY`。 - `endpoint`:默认 `wss://stream.aisstream.io/v0/stream`。 - `message_types`:默认 `PositionReport` 和 `ShipStaticData`。 - `bounding_boxes`:AISStream 格式为 `[[[lat_min, lon_min], [lat_max, lon_max]]]`,设置页提供全球、挪威 / 北海、欧洲近海、东亚、北美东西海岸 preset。 - `max_messages` 和 `receive_timeout_seconds`:控制单次批次式 WebSocket 采集窗口。 标准化规则: - `PositionReport` 主要提供位置、速度、航向和状态。 - 船名可以从 `MetaData.ShipName` 补入,即使消息体本身没有 `name`。 - 船型通常来自低频 `ShipStaticData.Type`;后端会把 AIS 数字类型码映射为 Cargo / Tanker / Passenger / Fishing / Military。 - 如果某艘船尚未收到静态消息,聚合结果的船型仍可能是 `Other`,后续由 v5 船舶资料 enrichment 补齐。 ## 凭证教程 文件: - [credential_guides.py](/home/ray/dev/linkong/planet/backend/app/services/credential_guides.py) 接口: ```http GET /api/v1/settings/credential-guides/{provider} POST /api/v1/settings/credential-guides/{provider}/generate POST /api/v1/settings/credential-guides/{provider}/reset ``` 当前支持: - `barentswatch` - `aisstream` 默认教程包含 BarentsWatch 官方 tutorial 地址: ```text https://developer.barentswatch.no/docs/tutorial ``` 如果用户点击“教程不好用”,后端会把默认 prompt 发给 AI Provider 生成新的中文教程,并保存到 `SystemSetting`: ```text category = collector_credential_guides ``` “重置”会删除自定义教程,恢复默认教程。 ## 保存规则 内置采集器配置保存时会移除内部 `connectivity_validation` 字段,避免校验状态跟用户配置混在一起。 BarentsWatch `client_secret` 保存时有特殊处理: - 输入框显示脱敏预览。 - 如果提交值仍等于脱敏预览,后端保留原 secret。 - 如果输入新值,才替换 secret。 - 不再提供单独“清除当前 secret”复选框。 ## 测试覆盖 相关测试: - [test_vessels.py](/home/ray/dev/linkong/planet/backend/tests/test_vessels.py) 新增覆盖: - 能从 `~/.zshrc` 解析 BarentsWatch 凭证。 - 环境变量为空时,`resolve_barentswatch_config()` 能回退到 `~/.zshrc`。 - 船只数据转换和 GeoJSON 输出保持兼容。 ## 当前 Provider 覆盖 当前已经支持的凭证 provider: - `barentswatch` - `spacetrack` 其他 `requires_credentials=true` 的采集器如果还没有 provider,会返回“凭证链路尚未接入”,前端显示 `不可用`。