package busmodels import ( "device-manage/common/log" model "device-manage/common/mqttcli/flatbuffer/models" "device-manage/pkg/ws" tools "device-manage/tools" "encoding/json" "fmt" "time" "github.com/muesli/cache2go" ) /* DeviceSn 设备序列号 TimerFinishType 定时结束类型 */ const ( cacheName = "devicetimer" ) type DeviceTimer struct { DeviceSn string `json:"deviceSn" gorm:"size:128;"` } func DeviceTimerSetup() { cache := cache2go.Cache(cacheName) // cache2go supports a few handy callbacks and loading mechanisms. cache.SetAboutToDeleteItemCallback(func(e *cache2go.CacheItem) { fmt.Println("Deleting:", e.Key(), e.Data().(*DeviceTimer).DeviceSn, e.CreatedOn()) //todo delete media source fmt.Println(e.LifeSpan().Seconds()) fmt.Println(e.CreatedOn().Unix()) fmt.Println(time.Now().Unix()) //要区分手动删除设备和超时删除设备. 超时删除要更新数据库, if time.Now().Unix()-e.CreatedOn().Unix() >= int64(e.LifeSpan().Seconds()) { fmt.Println("heartbeat timeout device offline:", e.Data().(*DeviceTimer).DeviceSn) var dev BusDevice dev.DeviceSn = e.Data().(*DeviceTimer).DeviceSn dev, _ = dev.GetDeviceByDeviceSn() devId := dev.DeviceId dev.DeviceId = 0 dev.Status = DeviceStatusOffline dev.OnlineTime = DeviceInitTime if _, err := dev.UpdateByMap(devId); err != nil { log.Info(err) } devArry, _ := json.Marshal(dev) ws.WebsocketManager.SendAll(devArry) } else { fmt.Println("手动删除缓存.") } }) initDevices() } //启动时, 初始化检查当前设备状态,如果历史上设备在线,给设备重新添加超时,检测设备是否离线. func initDevices() { var dev BusDevice var devtimer DeviceTimer devs, err := dev.GetOnlineDevices() if err != nil { return } for _, devInfo := range devs { devtimer.DeviceSn = devInfo.DeviceSn devtimer.AddDevice() fmt.Println("init device:", devInfo.DeviceSn) } } //查询缓存是否存在. func (e *DeviceTimer) GetDevice() error { //添加数据 cache := cache2go.Cache(cacheName) res, err := cache.Value(e.DeviceSn) if err == nil { fmt.Println("Found Device in cache:", res.Data().(*DeviceTimer).DeviceSn) } else { fmt.Println("Error retrieving value from cache:", err) return err } return nil } func (e *DeviceTimer) AddDevice() (err error) { //添加数据 cache := cache2go.Cache(cacheName) //如果有先清除历史 if cache.Exists(e.DeviceSn) { cache.Delete(e.DeviceSn) } //添加 超时时间 cache.Add(e.DeviceSn, 3*time.Minute, e) return nil } //delete device func (e *DeviceTimer) DeleteDevice() (err error) { cache := cache2go.Cache(cacheName) if _, err := cache.Delete(e.DeviceSn); err != nil { return err } fmt.Println("delete device:", e.DeviceSn) return nil } //设备在线心跳,更新设备信息 func DevicesHeartBeat(devInfo *model.Heartbeat) { var err error var dev BusDevice var devtimer DeviceTimer dev.DeviceSn = devInfo.Serial //设备不存在, 设备上线也直接抛弃数据,不能接入系统. if !dev.IsExist() { return } //history db data dbDevice, _ := dev.Get() dev.DeviceIp = devInfo.DeviceIp dev.ServerIp = devInfo.ServerIp dev.Status = devInfo.Status dev.Gps = devInfo.Gps dev.Nettype = devInfo.Nettype dev.DeviceType = devInfo.Devtype //设备存在,有两种状态, a. 已经注册状态 b. 未注册状态 //先判断当前设备是否已经完成注册 //a. 设备未注册, 先进行设备注册,在更新设备状态信息 time := time.Now() if !dev.IsRegist() { dev.DeviceName = devInfo.Serial dev.Status = DeviceStatusOnline dev.IsRegister = 1 dev.RegisterTime = time dev.OnlineTime = DeviceInitTime dev.TotallTime = DeviceInitTime dev.LastTime = time if _, err = dev.Update(dbDevice.DeviceId); err != nil { log.Info(dev.DeviceSn + " error") return } fmt.Println("device register.") } else { //deviceInfo.TotallTime //b. 设备已注册, 更新设备状态信息 //设备状态又分为 status:1 在线 status:0 离线. //1. 设备在线信息上报. if dev.Status == DeviceStatusOnline { devtimer.DeviceSn = dbDevice.DeviceSn devtimer.AddDevice() dev.LastTime = time //设备在线又分为设备启动首次上线(history last status:0)和正常在线(history last status:1). //设备上一次在线 if dbDevice.Status == DeviceStatusOnline { updateTime := dev.LastTime.Unix() - dbDevice.LastTime.Unix() //当前在线时间加上最近一次更新的时间长度(当前LastTime减去历史LastTime的时间差) dev.OnlineTime = tools.TimeStamp2Time(tools.Time2TimeStamp(dbDevice.OnlineTime) + int(updateTime)) //历史在线总时间加上最近一次更新时间长度(当前LastTime减去历史LastTime的时间差) dev.TotallTime = tools.TimeStamp2Time(tools.Time2TimeStamp(dbDevice.TotallTime) + int(updateTime)) } else { //设备上一次离线 dev.OnlineTime = DeviceInitTime } if _, err = dev.Update(dbDevice.DeviceId); err != nil { log.Info(dev.DeviceSn + " error") return } dev, _ := json.Marshal(dev) ws.WebsocketManager.SendAll(dev) } //使用cache2go, 设备主动报离线暂时处理不了, 先只做超时离线. /* else { //设备主动上报离线. dev.Status = 0 dev.OnlineTime = "00:00:00" if _, err = dev.Update(dbDevice.DeviceId); err != nil { log.Info(dev.DeviceSn + " error") return } } */ } //1. 设备存在,设备上线完成注册 /* //todo get device log for _, devid := range IDS { fmt.Println(devid) dev.DeviceId = devid if devInfo, err = dev.Get(); err != nil { continue } if devInfo.Status > 0 { if _, ok := mqtthandler.MqttClientList[devInfo.ServerIp]; ok { mqtthandler.MqttClientList[devInfo.ServerIp].Reboot(devInfo.DeviceSn, "") } } else { log.Info("cmd reboot offline [%s]", devInfo.DeviceSn) } } */ //app.OK(c, "", "重启成功.") }