195 lines
6.4 KiB
Go
195 lines
6.4 KiB
Go
|
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()
|
|||
|
}
|
|||
|
}
|
|||
|
}
|