diff --git a/internal/gateway/models.go b/internal/gateway/models.go index 1fd859b..3bd8618 100644 --- a/internal/gateway/models.go +++ b/internal/gateway/models.go @@ -3,6 +3,7 @@ package gateway import ( "encoding/json" + "strconv" "strings" ) @@ -24,6 +25,27 @@ func (b *FlexBool) UnmarshalJSON(data []byte) error { return nil } +// FlexInt 灵活整数类型 +// 与 FlexBool 同理,Gateway 部分设备返回 int 字段时使用字符串(如 "30")而非 JSON number。 +type FlexInt int + +// UnmarshalJSON 实现 json.Unmarshaler 接口 +// 支持:30, "30", null +func (i *FlexInt) UnmarshalJSON(data []byte) error { + raw := strings.Trim(string(data), "\"") + if raw == "" || raw == "null" { + *i = 0 + return nil + } + n, err := strconv.Atoi(raw) + if err != nil { + *i = 0 + return nil + } + *i = FlexInt(n) + return nil +} + // GatewayResponse 是 Gateway API 的通用响应结构 type GatewayResponse struct { Code int `json:"code" description:"业务状态码(200 = 成功)"` @@ -173,17 +195,17 @@ type SyncDeviceInfoResp struct { WifiEnabled FlexBool `json:"wifi_enabled" description:"WiFi开关状态"` SwitchMode string `json:"switch_mode" description:"切卡模式:0=自动,1=手动"` RSSI string `json:"rssi" description:"接收信号强度"` - BatteryLevel *int `json:"battery_level" description:"电池电量百分比(无电池时为null)"` - OnlineStatus int `json:"online_status" description:"在线状态:1=在线,2=离线"` + BatteryLevel *FlexInt `json:"battery_level" description:"电池电量百分比(无电池时为null)"` + OnlineStatus FlexInt `json:"online_status" description:"在线状态:1=在线,2=离线"` LastUpdateTime string `json:"last_update_time" description:"设备信息最后更新时间(ISO 8601)"` LastOnlineTime string `json:"last_online_time" description:"设备最后在线时间(ISO 8601)"` RunTime string `json:"run_time" description:"本次开机运行时间(秒)"` DailyUsage string `json:"daily_usage" description:"日使用流量(字节)"` // 信号相关(D-10 补全) - Rsrp int `json:"rsrp" description:"参考信号接收功率(dBm)"` - Rsrq int `json:"rsrq" description:"参考信号接收质量(dB)"` - Sinr int `json:"sinr" description:"信噪比(dB)"` + Rsrp FlexInt `json:"rsrp" description:"参考信号接收功率(dBm)"` + Rsrq FlexInt `json:"rsrq" description:"参考信号接收质量(dB)"` + Sinr FlexInt `json:"sinr" description:"信噪比(dB)"` // WiFi 相关(D-10 补全) WifiPassword string `json:"wifi_password" description:"WiFi密码"` @@ -194,14 +216,14 @@ type SyncDeviceInfoResp struct { LANIP string `json:"lan_ip" description:"局域网网关IP地址"` // 连接相关(D-10 补全) - MaxClients int `json:"max_clients" description:"最大连接客户端数"` - ConnectTime string `json:"connect_time" description:"设备本次联网时间(秒)"` + MaxClients FlexInt `json:"max_clients" description:"最大连接客户端数"` + ConnectTime string `json:"connect_time" description:"设备本次联网时间(秒)"` // 设备属性(D-10 补全) - Status int `json:"status" description:"设备状态:1=正常,0=禁用"` - IMSI string `json:"imsi" description:"IMSI用户标识码"` - ULStats string `json:"ul_stats" description:"本次开机上传流量(字节)"` - DLStats string `json:"dl_stats" description:"本次开机下载流量(字节)"` - LimitSpeed int `json:"limit_speed" description:"限速速率(KB/s)"` - SyncInterval int `json:"sync_interval" description:"信息上报周期(秒)"` + Status FlexInt `json:"status" description:"设备状态:1=正常,0=禁用"` + IMSI string `json:"imsi" description:"IMSI用户标识码"` + ULStats string `json:"ul_stats" description:"本次开机上传流量(字节)"` + DLStats string `json:"dl_stats" description:"本次开机下载流量(字节)"` + LimitSpeed FlexInt `json:"limit_speed" description:"限速速率(KB/s)"` + SyncInterval FlexInt `json:"sync_interval" description:"信息上报周期(秒)"` } diff --git a/internal/service/asset/service.go b/internal/service/asset/service.go index 21a3653..e6f2a2b 100644 --- a/internal/service/asset/service.go +++ b/internal/service/asset/service.go @@ -363,15 +363,15 @@ func (s *Service) fetchDeviceGatewayInfo(ctx context.Context, deviceID uint) *dt // 使用指针字段,未赋值的字段保持 nil(omitempty) func mapSyncRespToDeviceGatewayInfo(r *gateway.SyncDeviceInfoResp) *dto.DeviceGatewayInfo { info := &dto.DeviceGatewayInfo{ - OnlineStatus: &r.OnlineStatus, + OnlineStatus: flexIntPtr(r.OnlineStatus), RunTime: strPtr(r.RunTime), ConnectTime: strPtr(r.ConnectTime), LastOnlineTime: strPtr(r.LastOnlineTime), LastUpdateTime: strPtr(r.LastUpdateTime), - Rsrp: &r.Rsrp, - Rsrq: &r.Rsrq, + Rsrp: flexIntPtr(r.Rsrp), + Rsrq: flexIntPtr(r.Rsrq), Rssi: strPtr(r.RSSI), - Sinr: &r.Sinr, + Sinr: flexIntPtr(r.Sinr), SSID: strPtr(r.SSID), WifiEnabled: flexBoolPtr(r.WifiEnabled), WifiPassword: strPtr(r.WifiPassword), @@ -382,21 +382,22 @@ func mapSyncRespToDeviceGatewayInfo(r *gateway.SyncDeviceInfoResp) *dto.DeviceGa DailyUsage: strPtr(r.DailyUsage), DLStats: strPtr(r.DLStats), ULStats: strPtr(r.ULStats), - LimitSpeed: &r.LimitSpeed, + LimitSpeed: flexIntPtr(r.LimitSpeed), CurrentIccid: strPtr(r.CurrentIccid), - MaxClients: &r.MaxClients, + MaxClients: flexIntPtr(r.MaxClients), SoftwareVersion: strPtr(r.SoftwareVersion), SwitchMode: strPtr(r.SwitchMode), - SyncInterval: &r.SyncInterval, + SyncInterval: flexIntPtr(r.SyncInterval), DeviceID: strPtr(r.DeviceID), DeviceName: strPtr(r.DeviceName), DeviceType: strPtr(r.DeviceType), IMEI: strPtr(r.IMEI), IMSI: strPtr(r.IMSI), - Status: &r.Status, + Status: flexIntPtr(r.Status), } if r.BatteryLevel != nil { - info.BatteryLevel = r.BatteryLevel + n := int(*r.BatteryLevel) + info.BatteryLevel = &n } return info } @@ -415,6 +416,11 @@ func flexBoolPtr(fb gateway.FlexBool) *bool { return &b } +func flexIntPtr(fi gateway.FlexInt) *int { + n := int(fi) + return &n +} + // Refresh 刷新资产数据(调网关同步) func (s *Service) Refresh(ctx context.Context, assetType string, id uint) (*dto.AssetRealtimeStatusResponse, error) { switch assetType { @@ -505,7 +511,7 @@ func (s *Service) updateDeviceFromSyncInfo(ctx context.Context, deviceID uint, r // 更新设备 5 个存储字段 updates := map[string]any{ - "online_status": resp.OnlineStatus, + "online_status": int(resp.OnlineStatus), "software_version": resp.SoftwareVersion, "switch_mode": resp.SwitchMode, "last_gateway_sync_at": now,