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

7.5 KiB

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 消息

订阅:

{
  "action": "subscribe",
  "channels": ["updates", "alarms"]
}

更新:

{
  "type": "update",
  "data": {
    "source": "top500",
    "action": "add",
    "payload": { ... }
  }
}

告警:

{
  "type": "alarm",
  "data": {
    "severity": "high",
    "message": "数据采集失败",
    "source": "peeringdb_ixp"
  }
}