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