Files
planet/unreal/Content/Blueprints/BP_GlobeController_Spec.md
2026-03-05 11:46:58 +08:00

302 lines
7.5 KiB
Markdown

# BP_GlobeController 蓝图详细规格
## 蓝图信息
| 属性 | 值 |
|------|-----|
| 蓝图类型 | Actor |
| 父类 | `CesiumGeoreference` |
| 路径 | `Content/Blueprints/BP_GlobeController.uasset` |
## 组件列表
```
BP_GlobeController
├── CesiumGeoreference (场景根组件)
│ └── Cesium3DTileset (地球地形)
│ └── CesiumSunSky (太阳光照)
│ └── BP_DataPointManager (数据点管理器)
│ └── BP_CableManager (海缆管理器)
│ └── BP_DataFlowManager (数据流管理器)
└── CameraRig (相机支架)
```
## 变量列表
| 变量名 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| `API_URL` | String | `http://localhost:8000` | 后端 API 地址 |
| `WS_URL` | String | `ws://localhost:8000/ws` | WebSocket 地址 |
| `bAutoRotate` | Boolean | `true` | 自动旋转 |
| `RotateSpeed` | Float | `0.5` | 旋转速度 |
| `SelectedPoint` | BP_DataPoint (Weak) | `None` | 当前选中点 |
| `AllDataPoints` | Map<String, BP_DataPoint> | `Empty` | 所有数据点映射 |
| `UpdateInterval` | Float | `30.0` | 数据更新间隔(秒) |
## 事件
### Event BeginPlay
```
1. [调用] InitializeCesium()
└─ 设置 Cesium ion Token (从配置读取)
2. [调用] ConnectWebSocket()
└─ 创建 WebSocket 连接
└─ 绑定回调:
├─ OnConnected: [调用] HandleConnected()
├─ OnMessage: [调用] HandleMessage()
└─ OnError: [调用] HandleError()
3. [设置] Timer by Event
└─ 事件: UpdateAllData
└─ 时间: UpdateInterval (30秒)
```
### Event Tick
```
1. [分支] bAutoRotate == true?
├─ [是]: [调用] RotateGlobe(DeltaSeconds * RotateSpeed)
└─ [否]: 跳过
```
## 自定义事件
### InitializeCesium
```
1. [获取] Get UCesiumRuntimeSettings (来自 Project Settings)
2. [设置] Cesium ion Token
3. [调用] RefreshTileset()
```
### ConnectWebSocket
```
1. [创建] WebSocket 对象 (WS_URL)
2. [绑定] OnConnected → HandleConnected
3. [绑定] OnMessage → HandleMessage
4. [绑定] OnError → HandleError
5. [调用] Connect()
```
### HandleConnected
```
1. [打印] "WebSocket Connected!" (绿色)
2. [调用] RequestAllData()
```
### HandleMessage (String Message)
```
1. [解析] JSON Parse String → MessageData
2. [获取] MessageData["type"] → Type
3. [分支] Type
├─ "update":
│ ├─ [获取] MessageData["data"] → Data
│ ├─ [获取] Data["source"] → Source
│ ├─ [获取] Data["action"] → Action
│ └─ [调用] ProcessDataUpdate(Source, Action, Data)
├─ "alarm":
│ └─ [调用] ShowAlarm(Data)
└─ [默认]:
└─ [打印] "Unknown message type" (黄色)
```
### ProcessDataUpdate (String Source, String Action, Struct Data)
```
1. [分支] Source
├─ "top500":
│ └─ [调用] UpdateSupercomputer(Action, Data)
├─ "peeringdb_ixp":
│ └─ [调用] UpdateIXPNode(Action, Data)
├─ "peeringdb_network":
│ └─ [调用] UpdateNetworkNode(Action, Data)
├─ "telegeography_cables":
│ └─ [调用] UpdateSubmarineCable(Action, Data)
└─ [默认]:
└─ [打印] Unknown source (黄色)
```
### UpdateSupercomputer (String Action, Struct Data)
```
1. [获取] Data["id"] → PointId
2. [分支] Action
├─ "add":
│ ├─ [调用] BP_DataPointManager.CreateDataPoint(Data)
│ │ └─ 返回: NewPoint
│ ├─ [获取] NewPoint.Id → Key
│ └─ [设置] AllDataPoints[Key] = NewPoint
├─ "update":
│ ├─ [获取] AllDataPoints[PointId] → ExistingPoint
│ ├─ [分支] ExistingPoint != None
│ │ └─ [调用] ExistingPoint.UpdateData(Data)
│ └─ [否则]:
│ └─ [调用] UpdateSupercomputer("add", Data)
└─ "remove":
├─ [获取] AllDataPoints[PointId] → ExistingPoint
├─ [分支] ExistingPoint != None
│ └─ [调用] ExistingPoint.Destroy()
└─ [设置] AllDataPoints.Remove(PointId)
```
### UpdateSubmarineCable (String Action, Struct Data)
```
1. [获取] Data["id"] → CableId
2. [分支] Action
├─ "add":
│ ├─ [调用] BP_CableManager.CreateCable(Data)
│ │ └─ 返回: NewCable
│ ├─ [获取] NewCable.Id → Key
│ └─ [设置] AllCables[Key] = NewCable
├─ "update":
│ ├─ [获取] AllCables[CableId] → ExistingCable
│ └─ [分支] ExistingCable != None
│ └─ [调用] ExistingCable.UpdateData(Data)
└─ "remove":
├─ [获取] AllCables[CableId] → ExistingCable
├─ [分支] ExistingCable != None
│ └─ [调用] ExistingCable.Destroy()
└─ [设置] AllCables.Remove(CableId)
```
### UpdateAllData
```
1. [调用] HTTP Request (GET /api/v1/collected/summary)
2. [解析] JSON Response
3. [打印] "Data Updated: {Total} records"
```
### RequestAllData
```
1. [调用] HTTP Request (GET /api/v1/collected?limit=10000)
2. [解析] JSON Response → DataArray
3. [循环] For Each Data in DataArray
├─ [获取] Data["source"] → Source
└─ [调用] ProcessDataUpdate(Source, "add", Data)
```
## 辅助函数
### RotateGlobe (Float Delta)
```
1. [获取] Self.ActorRotation → CurrentRotation
2. [计算] NewRotation = CurrentRotation + (0, Delta * 10, 0)
3. [设置] Self.ActorRotation = NewRotation
```
### FocusOnPoint (BP_DataPoint Target)
```
1. [分支] Target != None
├─ [获取] Target.Location → PointLocation
├─ [获取] CameraRig.Camera → MainCamera
├─ [获取] PointLocation.Latitude → Lat
├─ [获取] PointLocation.Longitude → Lon
├─ [调用] CesiumGeoreference.SetView(Lat, Lon, 500000)
└─ [设置] SelectedPoint = Target
```
### ShowAlarm (Struct AlarmData)
```
1. [创建] Widget W_AlarmPanel
2. [设置] W_AlarmPanel.Data = AlarmData
3. [添加到视口] Add to Viewport
4. [播放动画] W_AlarmPanel.FadeIn
5. [设置计时器] 5秒后调用 HideAlarm()
```
## 接口实现
### IWebSocketCallback
```
OnConnected:
└─ [调用] HandleConnected()
OnMessage (String Message):
└─ [调用] HandleMessage(Message)
OnError (String Error):
└─ [打印] "WebSocket Error: {Error}" (红色)
OnClosed (Int32 Code, String Reason):
└─ [打印] "WebSocket Closed: {Code} - {Reason}" (黄色)
└─ [设置计时器] 5秒后调用 Reconnect()
```
## 事件调度器
| 事件调度器 | 参数 | 说明 |
|------------|------|------|
| `OnDataPointSelected` | BP_DataPoint | 数据点被选中 |
| `OnAlarmReceived` | Struct AlarmData | 收到告警 |
| `OnConnectionStatus` | Boolean | 连接状态变化 |
## 后端 API 对接
### HTTP 请求
| 操作 | 方法 | 端点 | 说明 |
|------|------|------|------|
| 获取汇总 | GET | `/api/v1/collected/summary` | 获取数据统计 |
| 获取TOP500 | GET | `/api/v1/collected?source=top500` | 获取超算数据 |
| 获取海缆 | GET | `/api/v1/collected?source=telegeography_cables` | 获取海缆数据 |
| 获取全部 | GET | `/api/v1/collected?limit=10000` | 获取所有数据 |
### WebSocket 消息
**订阅:**
```json
{
"action": "subscribe",
"channels": ["updates", "alarms"]
}
```
**更新:**
```json
{
"type": "update",
"data": {
"source": "top500",
"action": "add",
"payload": { ... }
}
}
```
**告警:**
```json
{
"type": "alarm",
"data": {
"severity": "high",
"message": "数据采集失败",
"source": "peeringdb_ixp"
}
}
```