# 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"
  }
}
```
