package ws2 import ( "encoding/json" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/util/gconv" "github.com/gorilla/websocket" "github.com/tiger1103/gfast/v3/api/constant" "log" "time" ) // 获取实时、状态等心跳包的请求 func SendHeartbeat(conn *websocket.Conn) { activeDevicesMessage := map[string]string{ "act": "ma_get_active_devices", } conn.WriteJSON(activeDevicesMessage) } // 定时任务 func SendHeartbeatTime(Conn *websocket.Conn) { // 使用匿名函数创建一个定时器,每隔60秒执行一次 ticker := time.NewTicker(60 * time.Second) defer ticker.Stop() for { select { case <-ticker.C: SendHeartbeat(Conn) } } } // Response 包含从服务器获取的设备数据 type LocationAndHeart struct { Cmd string `json:"cmd"` Status bool `json:"status"` Message string `json:"msg"` Data []DeviceData `json:"data"` MsgCode string `json:"msg_code"` } // UserInfo 包含有关用户的信息 type UserInfo struct { UserID string `json:"user_id" dc:"用户id"` CAVersion string `json:"ca_ver"` DeviceID string `json:"device_id" dc:"设备id"` Mobile string `json:"mobile"` SIM string `json:"sim"` CTime string `json:"c_time" dc:"创建时间"` CALastLoginTime string `json:"ca_last_login_time"` UserName string `json:"user_name" dc:"用户名字"` UserImg string `json:"user_img"` Department string `json:"department"` Role string `json:"role"` FID string `json:"f_id"` CapType string `json:"cap_type"` B1 string `json:"b1"` B2 string `json:"b2"` SOSHeight string `json:"sos_height"` CUserID string `json:"c_user_id"` VoicePkg string `json:"voice_pkg"` AppVersion string `json:"app_version"` Headset string `json:"headset"` UploadVideoNum string `json:"upload_video_num"` NotUploadedVideos string `json:"notuploaded_video_count"` GID string `json:"g_id"` SIPID int `json:"sip_id"` } // LocationInfo 包含有关位置信息的数据 type LocationInfo struct { Act string `json:"act"` BatteryLevel string `json:"bat_l" dc:"电量百分比"` BatteryVoltage string `json:"bat_v" dc:"电池电压"` Charging string `json:"charging"` GPS string `json:"gps"` GPSLevel string `json:"gps_level"` InUse string `json:"in_use"` IsWorn string `json:"is_weared"` NetStrength string `json:"net_strenth"` NetType string `json:"net_type"` NotUploadedVideos string `json:"notuploaded_video_count"` OnlineType string `json:"online_type"` PhoneNumber string `json:"phoneNumber"` RailStatus string `json:"rail_status"` SIMDataNum string `json:"sim_data_num"` SIMStatus string `json:"sim_status"` TCardStatus string `json:"tcard_status"` TempData string `json:"tempdata"` UserID string `json:"user_id"` XPoint string `json:"x_point"` YPoint string `json:"y_point"` CTime int64 `json:"ctime"` CapType string `json:"cap_type"` } // DeviceData 包含用户信息和位置信息 type DeviceData struct { UserInfo UserInfo `json:"user_info"` LocationInfo LocationInfo `json:"location_info"` } // 处理收到的心跳和实时数据信息 func HandleLocation(jsonString string) { var response LocationAndHeart // 解析 JSON 字符串到结构体 err := json.Unmarshal([]byte(jsonString), &response) if err != nil { log.Fatal("Error decoding JSON to struct:", err) } var IsLowBattery int // 用来跟踪当前活跃的设备编号 activeDevices := make(map[string]bool) // 获取当前时间,格式化为 YYYY-MM-DD currentTime := time.Now() todayDate := currentTime.Format("2006-01-02") for _, v := range response.Data { // 标记此设备ID为活跃 activeDevices[v.UserInfo.DeviceID] = true // 将 Unix 时间戳(秒)转换为 time.Time 类型 createTime := time.Unix(gconv.Int64(v.UserInfo.CTime), 0) // 判断电量是否低于20%,如果是,则标记为低电量 if gconv.Int(v.LocationInfo.BatteryLevel) <= constant.BatteryLevel { IsLowBattery = 1 } // 检查数据库中是否存在该设备 IfExists, _ := g.Model("device_video_hat").Where("dev_num", v.UserInfo.DeviceID).Count() if IfExists == 0 { // 如果设备不存在,则插入新设备数据(不包括设备名称) devHat := g.Map{ "dev_num": v.UserInfo.DeviceID, "status": v.LocationInfo.InUse, "uid": v.UserInfo.UserID, "battery_level": v.LocationInfo.BatteryLevel, "is_low_battery": IsLowBattery, "create_time": createTime, "longitude": v.LocationInfo.XPoint, "latitude": v.LocationInfo.YPoint, "sip_id": v.UserInfo.SIPID, } g.Model("device_video_hat").Data(devHat).Save() } else { // 更新已存在的设备数据 updateData := g.Map{ "status": v.LocationInfo.InUse, "uid": v.UserInfo.UserID, "battery_level": v.LocationInfo.BatteryLevel, "is_low_battery": IsLowBattery, "create_time": createTime, "longitude": v.LocationInfo.XPoint, "latitude": v.LocationInfo.YPoint, "sip_id": v.UserInfo.SIPID, } g.Model("device_video_hat").Data(updateData).Where("dev_num", v.UserInfo.DeviceID).Update() } // 检查 device_data_time 表是否已有当天的记录 count, err := g.Model("device_data_time").Where("dev_num = ? AND data_time = ?", v.UserInfo.DeviceID, todayDate).Count() if err != nil { log.Println("Error checking device_data_time:", err) continue } if count == 0 { // 如果没有记录,则插入新数据 g.Model("device_data_time").Data(g.Map{ "dev_num": v.UserInfo.DeviceID, "data_time": todayDate, }).Insert() } } // 从数据库中检索所有设备 var allDevices []struct{ DevNum string } err = g.Model("device_video_hat").Fields("dev_num AS DevNum").Scan(&allDevices) if err != nil { log.Fatal("Error retrieving all devices:", err) } // 为不活跃的设备设置状态为0 for _, device := range allDevices { if _, isActive := activeDevices[device.DevNum]; !isActive { g.Model("device_video_hat").Data(g.Map{"status": 0}).Where("dev_num", device.DevNum).Update() } } }