feat(03.1-01): 建立设备实时 Gateway 调用链路,替换 mock 数据

- GetRealtimeStatus() device case 新增 Gateway sync-info 实时调用(IMEI/SN 优先,gatewayClient nil 安全)
- 新增 mapSyncRespToDeviceGatewayInfo() 将 SyncDeviceInfoResp 映射为 B 端 DeviceGatewayInfo DTO
- 新增 strPtr() 辅助函数(空字符串→nil,防止 JSON 出现大量空字符串字段)
- client_asset.go 删除 buildMockDeviceRealtime(),改为调用 assetService.GetRealtimeStatus() 获取真实数据
- 新增 mapDeviceGatewayInfoToClientInfo() 将 B 端 DeviceGatewayInfo 映射为 C 端 DeviceRealtimeInfo
- Gateway 调用失败时 DeviceRealtime 返回 null,不阻断主流程
This commit is contained in:
2026-03-28 13:21:02 +08:00
parent 3b54850f1b
commit a202b2da8a
2 changed files with 154 additions and 41 deletions

View File

@@ -185,9 +185,15 @@ func (h *ClientAssetHandler) GetAssetInfo(c *fiber.Ctx) error {
BoundDeviceName: resolved.Asset.BoundDeviceName,
}
// TODO: Gateway 同步接口对接后,替换为真实设备实时数据
// 调用服务层获取设备实时 Gateway 数据per D-11
// Gateway 失败时 DeviceRealtime 为 null不阻断主流程per D-06
if resp.AssetType == "device" {
resp.DeviceRealtime = buildMockDeviceRealtime()
realtimeResp, realtimeErr := h.assetService.GetRealtimeStatus(
c.UserContext(), "device", resp.AssetID,
)
if realtimeErr == nil && realtimeResp.DeviceRealtime != nil {
resp.DeviceRealtime = mapDeviceGatewayInfoToClientInfo(realtimeResp.DeviceRealtime)
}
}
return response.Success(c, resp)
@@ -592,44 +598,76 @@ func packageStatusName(status int) string {
}
}
// buildMockDeviceRealtime 构建设备实时状态假数据
// TODO: Gateway 同步接口对接后移除此函数,改为调用 Gateway 接口获取真实数据
func buildMockDeviceRealtime() *dto.DeviceRealtimeInfo {
onlineStatus := int64(1)
batteryLevel := int64(85)
deviceStatus := int64(1)
runTime := "3600"
connectTime := "3500"
rsrp := int64(-80)
rsrq := int64(-10)
rssi := "-65"
sinr := int64(15)
ssid := "JunHong-WiFi"
wifiEnabled := true
wifiPassword := "12345678"
ipAddress := "192.168.1.1"
lanIP := "192.168.1.1"
dailyUsage := "0"
maxClients := int64(32)
switchMode := 0
return &dto.DeviceRealtimeInfo{
OnlineStatus: &onlineStatus,
BatteryLevel: &batteryLevel,
Status: &deviceStatus,
RunTime: &runTime,
ConnectTime: &connectTime,
Rsrp: &rsrp,
Rsrq: &rsrq,
Rssi: &rssi,
Sinr: &sinr,
SSID: &ssid,
WifiEnabled: &wifiEnabled,
WifiPassword: &wifiPassword,
IPAddress: &ipAddress,
LANIP: &lanIP,
DailyUsage: &dailyUsage,
MaxClients: &maxClients,
SwitchMode: &switchMode,
// mapDeviceGatewayInfoToClientInfo 将 B 端 DeviceGatewayInfo 映射为 C 端 DeviceRealtimeInfo
// B 端和 C 端结构独立通过映射函数转换per D-08
func mapDeviceGatewayInfoToClientInfo(g *dto.DeviceGatewayInfo) *dto.DeviceRealtimeInfo {
if g == nil {
return nil
}
info := &dto.DeviceRealtimeInfo{}
if g.OnlineStatus != nil {
v := int64(*g.OnlineStatus)
info.OnlineStatus = &v
}
if g.BatteryLevel != nil {
v := int64(*g.BatteryLevel)
info.BatteryLevel = &v
}
if g.Status != nil {
v := int64(*g.Status)
info.Status = &v
}
info.RunTime = g.RunTime
info.ConnectTime = g.ConnectTime
info.LastOnlineTime = g.LastOnlineTime
info.LastUpdateTime = g.LastUpdateTime
if g.Rsrp != nil {
v := int64(*g.Rsrp)
info.Rsrp = &v
}
if g.Rsrq != nil {
v := int64(*g.Rsrq)
info.Rsrq = &v
}
info.Rssi = g.Rssi
if g.Sinr != nil {
v := int64(*g.Sinr)
info.Sinr = &v
}
info.SSID = g.SSID
info.WifiEnabled = g.WifiEnabled
info.WifiPassword = g.WifiPassword
info.IPAddress = g.IPAddress
info.WANIP = g.WANIP
info.LANIP = g.LANIP
info.MACAddress = g.MACAddress
info.DailyUsage = g.DailyUsage
info.DLStats = g.DLStats
info.ULStats = g.ULStats
if g.LimitSpeed != nil {
v := int64(*g.LimitSpeed)
info.LimitSpeed = &v
}
info.CurrentIccid = g.CurrentIccid
if g.MaxClients != nil {
v := int64(*g.MaxClients)
info.MaxClients = &v
}
info.SoftwareVersion = g.SoftwareVersion
if g.SwitchMode != nil {
// SwitchMode 在 B 端为字符串("0"/"1"C 端为整型0/1需解析转换
if n, convErr := strconv.Atoi(*g.SwitchMode); convErr == nil {
info.SwitchMode = &n
}
}
if g.SyncInterval != nil {
v := int64(*g.SyncInterval)
info.SyncInterval = &v
}
info.DeviceID = g.DeviceID
info.DeviceName = g.DeviceName
info.DeviceType = g.DeviceType
info.Imei = g.IMEI
info.Imsi = g.IMSI
return info
}