package main import ( "runtime/debug" "strconv" "sync" "time" "github.com/sirupsen/logrus" "lc/common/models" "lc/common/util" ) // DeviceAlarmId 开关灯,离线,上线事件 var DeviceAlarmId = "device_alarm_id" var _EventMgrOnce sync.Once var _EventMgrSingle *EventMgr func GetEventMgr() *EventMgr { _EventMgrOnce.Do(func() { _EventMgrSingle = &EventMgr{ EventQueue: util.NewQueue(10000), MapAlarm: make(map[string]int64), MapLampEvent: make(map[string]int64), } }) return _EventMgrSingle } type EventObject struct { ID string EventType models.EventType Time time.Time Value float64 } type EventMgr struct { EventQueue *util.MlQueue MapAlarm map[string]int64 MapLampEvent map[string]int64 } func (o *EventMgr) PushEvent(eo *EventObject) { if eo.ID == "" { logrus.Debugf("事件的设备ID为空:%s", string(debug.Stack())) } o.EventQueue.Put(eo) } func (o *EventMgr) Handler(args ...interface{}) interface{} { defer func() { if err := recover(); err != nil { gopool.Add(o.Handler, args) logrus.Errorf("EventMgr.Handler发生异常:%s", string(debug.Stack())) } }() for { msg, ok, _ := o.EventQueue.Get() if !ok { time.Sleep(200 * time.Millisecond) continue } eo, ok := msg.(*EventObject) if !ok { continue } //事件保存 o.SaveEventObject(eo) //在线离线告警处理 if eo.EventType == models.ET_ONLINE || eo.EventType == models.ET_OFFLINE { o.CheckOffLine(eo) } else if eo.EventType == models.ET_ONLAMP || eo.EventType == models.ET_OFFLAMP { o.CheckLampOnOff(eo) } } } func (o *EventMgr) SaveEventObject(eo *EventObject) { oo := models.DeviceEvents{DID: eo.ID, EType: eo.EventType, Time: eo.Time} if err := models.G_db.Create(&oo).Error; err != nil { logrus.Errorf("设备[%s]事件入库失败:%s", eo.ID, err.Error()) } } func (o *EventMgr) CheckOffLine(eo *EventObject) { if eo.EventType == models.ET_ONLINE { //上线事件 ai, ok := o.MapAlarm[eo.ID] if !ok { if str, err := redisCltRawData.HGet(DeviceAlarmId, eo.ID).Result(); err == nil { if id, err := strconv.Atoi(str); err == nil { ai = int64(id) } } } if ai > 0 { oo := models.DeviceAlarm{ID: ai, TEnd: eo.Time, EValue: float32(0)} if err := oo.Update(); err != nil { logrus.Errorf("更新告警[%d]信息失败:%s", ai, err.Error()) } delete(o.MapAlarm, eo.ID) if err := redisCltRawData.HDel(DeviceAlarmId, eo.ID).Err(); err != nil { logrus.Errorf("更新告警[%d]信息失败:%s", ai, err.Error()) } } } else if eo.EventType == models.ET_OFFLINE { //掉线事件 oo := models.DeviceAlarm{ DID: eo.ID, TStart: eo.Time, Threshold: 0, SValue: 0, Content: "离线", AlarmType: 0, Level: 2, //设备离线为严重告警 } if err := models.G_db.Create(&oo).Error; err != nil { logrus.Errorf("告警信息[%v]入库失败:%s", eo, err.Error()) } else { o.MapAlarm[eo.ID] = oo.ID if err := redisCltRawData.HSet(DeviceAlarmId, eo.ID, oo.ID).Err(); err != nil { logrus.Errorf("设备[%s]告警数据[%d]缓存失败:%s", eo.ID, oo.ID, err.Error()) } } } } func (o *EventMgr) CheckLampOnOff(eo *EventObject) { if eo.EventType == models.ET_OFFLAMP { //关灯事件 RID, ok := o.MapLampEvent[eo.ID] if !ok { if str, err := redisCltRawData.HGet(LampEventId, eo.ID).Result(); err == nil { if id, err := strconv.Atoi(str); err == nil { RID = int64(id) } } } if RID > 0 { oo := models.DeviceLampEvents{ ID: uint(RID), DID: eo.ID, TEnd: eo.Time, } if err := oo.Update(); err != nil { logrus.Errorf("灯控[%s]关灯数据[ID=%d]入库失败:%s", eo.ID, RID, err.Error()) } delete(o.MapLampEvent, eo.ID) if err := oo.Split(); err != nil { logrus.Errorf("分割开灯事件[%d]失败:%s", oo.ID, err.Error()) } if err := redisCltRawData.HDel(LampEventId, eo.ID).Err(); err != nil { logrus.Errorf("灯控[%s]关灯数据[ID=%d]删除失败:%s", eo.ID, RID, err.Error()) } } } else if eo.EventType == models.ET_ONLAMP { //开灯事件 oo := models.DeviceLampEvents{ DID: eo.ID, TStart: eo.Time, Brightness: uint8(eo.Value), } if err := models.G_db.Create(&oo).Error; err != nil { logrus.Errorf("灯控[%s]开灯数据入库失败:%s", eo.ID, err.Error()) } else { o.MapLampEvent[eo.ID] = int64(oo.ID) if err := redisCltRawData.HSet(LampEventId, eo.ID, oo.ID).Err(); err != nil { logrus.Errorf("灯控[%s]开灯数据[ID=%d]缓存失败:%s", eo.ID, oo.ID, err.Error()) } } } }