package nvcs import ( "container/list" "fmt" "time" "gat1400Exchange/config" "gat1400Exchange/models" "gat1400Exchange/pkg/logger" ) type simpleCache struct { data *list.List expiration time.Duration } func newCache(expiration time.Duration) *simpleCache { return &simpleCache{ data: list.New(), expiration: expiration, } } // 存储数据到缓存中 func (c *simpleCache) store(data ElevatorRunData) { var floorChanged = true // 取RFID楼层 if config.RFIDConf.ReadFloor && gRFIDFloor != data.Floor { if data.RunState == RunStop { logger.Warn("A floor error has occurred rfid epc %s, nvcs floor %s", gRFIDFloor, data.Floor) } data.Floor = gRFIDFloor } if data.Floor == "" { return } lastData := c.data.Back() // 如果楼层相同,并且数据在1秒内,则忽略 if lastData != nil { if lastData.Value.(ElevatorRunData).Floor == data.Floor { floorChanged = false if lastData.Value.(ElevatorRunData).Timestamp == data.Timestamp { return } } } c.data.PushBack(data) if !floorChanged { return } // 数据库保存一份 var d = models.Positions{ DeviceId: data.Device, Pos: data.Floor, RunDir: data.RunState, CreateTime: time.Now().Unix(), TimeString: time.Now().Format("2006-01-02 15:04:05"), } err := d.Save() if err != nil { logger.Warn("Device position update error:%s", err.Error()) } // 写OSD var runStateStr string if config.NVCSConf.RunState { if data.RunState == RunUp { runStateStr = "上" } else if data.RunState == RunDown { runStateStr = "下" } } // 设置osd 格式 "1F上 固 枪" if config.NVCSConf.OSD != "" { floorText := fmt.Sprintf("%s%s %s", data.Floor, runStateStr, config.NVCSConf.OSD) // 调用hik api 将文字添加到osd的左下角 err = addFloorToOSD(floorText) if err != nil { logger.Warn("%s", err.Error()) } } } // 删除过期数据 func (c *simpleCache) cleanExpired() { now := time.Now() // 从队列头部开始检查是否有过期数据 for c.data.Len() > 0 { elem := c.data.Front() // 获取队列头部的元素 item := elem.Value.(ElevatorRunData) if now.Sub(time.Unix(item.Timestamp, 0)) > c.expiration { // 如果数据已经过期,则从队列中删除 c.data.Remove(elem) } else { // 因为数据按时间顺序存储,遇到不过期的数据后就可以停止检查 break } } } func (c *simpleCache) getPositionByTime(timestamp int64) (runData ElevatorRunData) { node := c.data.Back() // 从链表尾部开始 for node != nil { if data, ok := node.Value.(ElevatorRunData); ok { if data.Timestamp >= timestamp { runData = data node = node.Prev() // 向前移动节点 } else { break } } else { break } } return } func (c *simpleCache) getMovePosition(timestamp int64, floor string) (runData ElevatorRunData) { logger.Debug("getMovePosition") node := c.data.Back() // 从链表末尾开始 // 找到最近的符合时间戳的节点 for node != nil { if data, ok := node.Value.(ElevatorRunData); ok { if data.Timestamp >= timestamp { node = node.Prev() // 向前移动节点 } else { break } } else { break } } // 如果找到的节点的时间戳符合要求,继续检查楼层 if node != nil { if current, ok := node.Value.(ElevatorRunData); ok && current.Timestamp >= timestamp { for node != nil { if nextNode := node.Next(); nextNode != nil { logger.Debug("next node %v", nextNode.Value.(ElevatorRunData)) if nextData, ok := nextNode.Value.(ElevatorRunData); ok { if nextData.Floor == floor { node = nextNode // 向前移动节点 } else { break } } } else { break } } // 如果找到的楼层与目标楼层不同,返回该数据 if current.Floor != floor { runData = current } } } return }