release: bump version to 0.43.0

This commit is contained in:
linkong
2026-04-28 16:10:17 +08:00
parent 1cd2dab0ee
commit ac69d5d354
69 changed files with 6954 additions and 1141 deletions

View File

@@ -0,0 +1,272 @@
# 实时船只监控系统 — 实施计划
**状态**:规划中
**创建日期**2026-04-27
**优先数据源**BarentsWatch免费→ AISHub / MarineTrafficTODO付费
## 已确认决策
| 项目 | 决策 |
|-----|------|
| 数据源 | BarentsWatch 先行AISHub / MarineTraffic TODO |
| 船只规模 | BarentsWatch 阶段全部显示;全球数据接入后按需加船型过滤(默认 Cargo + Tanker + Passenger |
| 更新频率 | 准实时:前端 5 分钟轮询,后端 Collector 每分钟拉取写库 |
| 历史轨迹 | 保留(`vessel_position` 表保留 24h后期按需扩展 |
| 推送方式 | HTTP 轮询(不用 WebSocket换实时数据源后再评估升级 |
---
## 一、技术背景
船只通过 AIS自动识别系统每 210 秒广播位置、航速、航向、目的地等信息。全球约 50 万艘持证船只在线,实时数据通过以下方式获取:
| 来源类型 | 典型服务 | 覆盖范围 | 成本 | 状态 |
|---------|---------|---------|------|------|
| **BarentsWatch Open API** | live.ais.barentswatch.no | 挪威海域实时 | 完全免费 | **当前使用** |
| **AISHub** | aishub.net | 全球实时 | 免费/小额 | TODO付费接入 |
| **MarineTraffic API** | marinetraffic.com | 全球实时 | $50$500/月 | TODO评估 tier |
| **VesselFinder API** | vesselfinder.com | 全球实时 | $50$300/月 | TODO备选 |
| **自建 SDR 接收** | RTL-SDR + AIS-catcher | 仅本地 3050km | 硬件 $30 | 不考虑 |
| **NOAA 历史数据** | Marine Cadastre | 美国近海历史 | 免费 | 可用于冷启动 |
### BarentsWatch API
- 端点:`https://live.ais.barentswatch.no/v1/latest/combined`
- 无需注册,直接 GET返回挪威近海 20005000 艘船只 JSON
- 字段mmsi, lat, lon, sog, cog, heading, nav_status, name, vessel_type, flag
- 刷新频率:数据约 3060s 更新一次,可随意轮询
### TODO付费数据源接入
- [ ] 评估 AISHub 订阅(全球覆盖,约 $30/月),接入全球实时流
- [ ] 评估 MarineTraffic API tier对比 AISHub 数据质量与成本
- [ ] 实现多数据源适配器,通过 `datasource_config` 切换
- [ ] 真实高频 AIS 稳定接入后,评估将 `vessel_position` 迁移为 TimescaleDB hypertable保留 Postgres 原生分区作为备选)
---
## 二、实施计划
### Phase 0 — 数据源验证与链路打通12 天)
- 接入 BarentsWatch Open API验证数据格式与字段
- 构建全球 mock 数据生成器(用于前端渲染压测,补充 BarentsWatch 的地域限制)
- 确认前端可渲染船只点,整条链路走通
### Phase 1 — 后端基础设施34 天)
#### 1.1 数据库 Schema
```sql
-- 船只静态信息(每 6h 刷新一次)
CREATE TABLE vessel_static (
mmsi BIGINT PRIMARY KEY,
name VARCHAR(128),
callsign VARCHAR(16),
vessel_type SMALLINT,
vessel_type_name VARCHAR(64),
flag VARCHAR(4), -- ISO 国家码
length FLOAT,
width FLOAT,
draught FLOAT,
imo BIGINT,
updated_at TIMESTAMPTZ
);
-- 船只实时位置(高频写入,保留 24h 轨迹)
CREATE TABLE vessel_position (
id BIGSERIAL PRIMARY KEY,
mmsi BIGINT NOT NULL,
lat FLOAT NOT NULL,
lon FLOAT NOT NULL,
sog FLOAT, -- Speed over ground
cog FLOAT, -- Course over ground
heading SMALLINT, -- 真北航向
nav_status SMALLINT, -- 0=航行 1=锚泊 5=停靠 ...
received_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_vessel_pos_mmsi_time ON vessel_position(mmsi, received_at DESC);
CREATE INDEX idx_vessel_pos_time ON vessel_position(received_at DESC);
-- 最新位置物化视图(地图渲染主数据源,避免全表扫描)
CREATE MATERIALIZED VIEW vessel_latest AS
SELECT DISTINCT ON (mmsi)
vp.*, vs.name, vs.vessel_type_name, vs.flag, vs.length
FROM vessel_position vp
LEFT JOIN vessel_static vs USING (mmsi)
ORDER BY mmsi, received_at DESC;
CREATE UNIQUE INDEX ON vessel_latest(mmsi);
```
> 后期如需完整历史轨迹查询,迁移 `vessel_position` 到 TimescaleDB 或按天分区。
#### 1.2 CollectorVesselAISCollector
文件:`backend/app/services/collectors/vessel_ais.py`
- 继承 `BaseCollector`,注册到 `collector_registry`
- 轮询间隔3060s由数据源限速决定
- 支持多数据源切换,通过 `datasource_config` 配置 URL + API Key
- 写入逻辑upsert `vessel_latest`append `vessel_position`
- 接入现有调度系统(`scheduler.py`
#### 1.3 API 端点
```
GET /api/v1/visualization/geo/vessels
?bbox=lon_min,lat_min,lon_max,lat_max # 视口裁剪
?type=cargo,tanker,passenger # 船型过滤
?limit=5000
→ GeoJSON FeatureCollectionPoint
GET /api/v1/visualization/vessels/{mmsi} # 单船详情
GET /api/v1/visualization/vessels/{mmsi}/track # 历史轨迹(默认 6h
?hours=6
→ GeoJSON LineString
```
GeoJSON Feature 格式:
```json
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [lon, lat] },
"properties": {
"mmsi": 123456789,
"name": "EVER GIVEN",
"vessel_type": 70,
"vessel_type_name": "Cargo",
"flag": "PA",
"sog": 12.4,
"cog": 247.0,
"heading": 245,
"nav_status": 0,
"length": 400,
"received_at": "2026-04-27T10:00:00Z"
}
}
```
#### 1.4 更新机制
**HTTP 轮询**(不使用 WebSocket
- 前端 `setInterval(fetchVessels, 5 * 60 * 1000)` 定期拉取最新快照
- 后端 Collector 每 60s 从 BarentsWatch 拉取并写库,`vessel_latest` 物化视图随时可查
- WebSocket 留给告警/事件驱动场景BGP、系统通知不混入周期性位置刷新
- 换用 AISHub / MarineTraffic 实时流后,届时再评估是否升级为 WebSocket delta push
---
### Phase 2 — 前端渲染34 天)
文件:`frontend/public/earth/js/vessels.js`
#### 2.1 渲染方案
参考现有卫星系统(`satellites.js`)的 InstancedMesh 模式:
- `THREE.InstancedMesh`:每个实例 = 一艘船,矩阵包含位置 + 旋转(朝向 COG
- 行进船:三角箭头图标,朝向 COG 方向
- 静止/锚泊船:圆点图标
- SVG 图标输出到 `frontend/public/earth/assets/icons/vessel-arrow.svg``vessel-dot.svg`
#### 2.2 船型颜色规范
| 船型 | 颜色 |
|-----|------|
| 货轮 Cargo | `#4A90D9` 蓝 |
| 油轮 Tanker | `#E85D04` 橙红 |
| 客船 Passenger | `#06D6A0` 绿 |
| 渔船 Fishing | `#FFD166` 黄 |
| 军舰 Military | `#73797E` 灰 |
| 其他 | `#9B9B9B` 浅灰 |
| 锚泊/停靠 | 降低饱和度 0.4x |
#### 2.3 LOD相机距离细节层次
| 相机距离 | 渲染策略 |
|---------|---------|
| > 400 | 仅渲染 top 1000 艘(按数据新鲜度 + 船型优先级) |
| 200400 | 渲染 top 5000 艘 |
| < 200 | 渲染当前视口 bbox 内全部船只 |
前端根据相机位置动态计算 bbox附加到 API 请求中。
#### 2.4 图层集成
接入现有图层系统,新增"船只"图层项,支持:
- 图层开/关,状态持久化
- 子过滤(按船型选择显示哪类,可在图例或设置面板中配置)
- 与海缆、BGP、卫星层级共存renderOrder 待定,参考现有层级文档)
#### 2.5 Info Card
复用 `showInfoCard` 机制,点击船只弹出:
```
EVER GIVEN 🚢
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
MMSI 123456789
IMO 9811000
旗帜 巴拿马 🇵🇦
船型 散货轮
当前航速 12.4 kn
航向 247°
状态 航行中
目的地 ROTTERDAM
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[ 查看轨迹 ] [ MarineTraffic ↗ ]
```
#### 2.6 轨迹可视化
点击"查看轨迹" → 请求 `/vessels/{mmsi}/track` → 用 `THREE.CatmullRomCurve3` 渲染插值轨迹线,风格与海缆一致。
---
### Phase 3 — 功能完善23 天)
| 功能 | 说明 |
|-----|------|
| **船只搜索** | 接入现有搜索面板,按名称 / MMSI 搜索 |
| **统计 HUD** | 显示当前在线船只数、各类型分布 |
| **密度热图** | 超低 zoom 时切换为 hex-bin 热力图(避免点云爆炸) |
| **港口标注** | 加载 WorldPorts 数据集,显示主要港口标记 |
| **关键水道监控** | 马六甲、霍尔木兹、苏伊士等高亮 + 流量统计 |
---
### Phase 4 — 性能与生产化23 天)
- `vessel_position` 按天分区7 天自动清理
- TODO真实数据量达到百万级/日后,将 `vessel_position` 升级为 TimescaleDB hypertable配置 retention policy 与压缩策略
- GeoJSON endpoint 用 Redis 缓存 15s
- 若需 bbox 精确查询,引入 PostGIS `geography` + `ST_DWithin`
- InstancedMesh + frustum culling目标 5 万船只 60fps
---
## 三、工作量估算
| Phase | 内容 | 估计时间 |
|-------|-----|---------|
| Phase 0 | 数据源验证、mock | 12 天 |
| Phase 1 | 后端 Schema + Collector + API | 34 天 |
| Phase 2 | 前端渲染InstancedMesh + 图层 + Info Card | 34 天 |
| Phase 3 | 搜索 + 统计 + 轨迹 | 23 天 |
| Phase 4 | 性能优化 + 生产数据源接入 | 23 天 |
| **合计** | | **约 23 周** |
---
## 四、参考资料
- BarentsWatch AIS API 文档https://www.barentswatch.no/en/developer/ais-api/
- MarineTraffic APIhttps://www.marinetraffic.com/en/ais-api-services
- AISHubhttps://www.aishub.net/api
- AIS 导航状态码ITU-R M.1371-5
- 船型编码vessel_typeITU/IMO AIS Message 5 Type and Cargo
- WorldPorts 数据集https://msi.nga.mil/Publications/WPI