| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490 |
- package service
- import (
- "encoding/json"
- "errors"
- "fmt"
- "math"
- "rtzh_elec_temperature/datachannel"
- "rtzh_elec_temperature/enum"
- "rtzh_elec_temperature/global"
- "rtzh_elec_temperature/logger"
- "rtzh_elec_temperature/models/bo"
- "rtzh_elec_temperature/mqtt"
- "rtzh_elec_temperature/rtelec_app_public_lib/models"
- "rtzh_elec_temperature/tools"
- "strconv"
- "strings"
- "sync"
- "time"
- "github.com/astaxie/beego/orm"
- "git.rtzhtech.cn/iss/public-lib/model"
- "git.rtzhtech.cn/iss/public-lib/dto"
- "github.com/spf13/cast"
- "git.rtzhtech.cn/iss/public-lib/logic"
- )
- //公共平台告警服务,提供告警策略的维护以及告警判断、触发等
- type AlarmService struct {
- BaseService
- }
- //发送告警消息
- type AlarmMessage struct {
- Eventid int64 `json:"eventid"`
- Eventtype int `json:"eventtype"`
- Eventdesc string `json:"eventdesc"`
- Strategyid int64 `json:"strategyid"`
- Timestamp int64 `json:"timestamp"`
- Mid string `json:"mid"`
- }
- type AlarmRelation struct {
- Alarmlevel int `json:"alarmlevel"`
- Mpid int64 `json:"mpid"`
- Deviceid int64 `json:"deviceid"`
- Attrname string `json:"attrname"`
- Alarmtype int `json:"alarmtype"`
- Uplimit float64 `json:"uplimit"`
- Dnlimit float64 `json:"dnlimit"`
- Dio float64 `json:"dio"`
- Diffvalue float64 `json:"diffvalue"`
- Relation int `json:"relation"`
- Strategyid int64 `json:"strategyid"`
- Strategyname string `json:"strategyname"`
- Positionname string `json:"positionname"`
- }
- type Alarm_List struct {
- Id int `json:"id"`
- Strategyid int64 `json:"strategyid,string"`
- Strategyname string `json:"strategyname"`
- Alarmlevel int `json:"alarmlevel"`
- Create_at string `json:"create_at"`
- Update_at string `json:"update_at"`
- Nickname string `json:"nickname"`
- }
- type Alarm_Total struct {
- Recordcount int
- }
- //设备测点最后一次的采集值及告警信息
- //map_key:deviceid_attrname_strategyid
- //map_value:alertstatus
- var DeviceAttrLastInfo = sync.Map{}
- var beforeAlarmState = sync.Map{}
- //告警策略定义列表
- var strategyDefList = []AlarmRelation{}
- var strategyDefListLock = sync.Mutex{}
- //重新加载告警策略到缓存中
- func (t *AlarmService) ReloadAlarmList() {
- strategyDefListLock.Lock()
- strategyDefList = []AlarmRelation{}
- alarmObject := logic.NewAlarmStrategyLogic()
- var sqlCommandText = "select alarmlevel,b.mpid,alarmtype,uplimit,dnlimit,dio,diffvalue,relation,b.strategyid,a.strategyname,c.attrname,c.deviceid,c.positionname " +
- fmt.Sprintf("from alarm_strategy a inner join alarm_relation b on a.strategyid=b.strategyid inner join dev_mpinfo c on b.mpid=c.mpid where a.appid=%s", RtelecManageApp().RegAppID)
- //log.Println(sqlCommandText)
- err := alarmObject.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &strategyDefList)
- if err != nil {
- logger.Logger.Error(err)
- }
- logger.Logger.Println(fmt.Sprintf("====初始化告警策略:%+v", strategyDefList))
- strategyDefListLock.Unlock()
- }
- //从告警策略列表中根据测点名称查找定义的策略。返回该策略下定义的所有规则
- func (t *AlarmService) FindstrategyDefByAttrname(deviceid int64, attrname string) map[int64][]AlarmRelation {
- strategyDefListLock.Lock()
- result := map[int64][]AlarmRelation{}
- strategyids := map[int64]string{}
- //根据属性名获取包含该属性的策略ID
- for _, row := range strategyDefList {
- if row.Attrname == attrname && row.Deviceid == deviceid {
- strategyids[row.Strategyid] = "1"
- }
- }
- if len(strategyids) > 0 {
- for id, _ := range strategyids {
- //获取该策略下的所有规则列表
- tmpLst := []AlarmRelation{}
- for _, row := range strategyDefList {
- if row.Strategyid == id {
- tmpLst = append(tmpLst, row)
- }
- }
- result[id] = tmpLst
- }
- }
- strategyDefListLock.Unlock()
- return result
- }
- //告警策略列表
- func (t *AlarmService) AlarmList(levle, pageIndex, pageSize int, name string) (map[string]interface{}, error) {
- l := logic.NewAlarmStrategyLogic()
- var list []Alarm_List
- sqlCommandText := "select a.id,strategyid,a.strategyname,a.alarmlevel,a.create_at,a.update_at,b.nickname from alarm_strategy a inner join sys_app b on a.appid=b.appid "
- totalSql := "select count(1) recordcount from alarm_strategy a inner join sys_app b on a.appid=b.appid "
- var sqlCondition []string
- sqlCondition = append(sqlCondition, fmt.Sprintf("a.appid=%s", RtelecManageApp().RegAppID))
- if name != "" {
- sqlCondition = append(sqlCondition, fmt.Sprintf("strategyname like '%%%s%%'", name))
- }
- if levle > 0 {
- sqlCondition = append(sqlCondition, fmt.Sprintf("alarmlevel=%d", levle))
- }
- if len(sqlCondition) > 0 {
- sqlCommandText += " where " + strings.Join(sqlCondition, " and ")
- totalSql += " where " + strings.Join(sqlCondition, " and ")
- }
- sqlCommandText += fmt.Sprintf(" order by id desc limit %d,%d", (pageIndex-1)*pageSize, pageSize)
- err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &list)
- var total Alarm_Total
- if err == nil {
- l.SvcCtx.AlarmStrategy.Base.Raw(totalSql, &total)
- }
- return map[string]interface{}{"list": list, "total": total.Recordcount}, err
- }
- //告警数据列表列表
- func (t *AlarmService) AlarmDataList(appId, startDate, endDate int, area string, alarmType, alarmLevel, pageIndex, pageSize int) (map[string]interface{}, error) {
- l := logic.NewAlarmStrategyLogic()
- type AlarmData struct {
- Id int `json:"id"`
- Eventid int64 `json:"eventid,string"`
- Eventdesc string `json:"eventdesc"`
- Eventtype string `json:"eventtype"`
- Alarmdate string `json:"alarmdate"`
- Confirm string `json:"confirm"`
- Level string `json:"level"`
- Confirmtime string `json:"confirmtime"`
- Result string `json:"result"`
- Create_at string `json:"create_at"`
- Zonename string `json:"zonename"`
- }
- sqlCommandText := "select distinct a.id,a.eventid,eventdesc,case eventtype when 1 then '测点告警' when 2 then '系统告警' when 3 then '告警复归' end eventtype,date_format(from_unixtime(timestamp),'%Y-%m-%d %H:%i:%s') alarmdate,case confirm when 1 then '未确认' when 2 then '已确认' else '' end confirm,case when confirm!=2 then null else date_format(confirmtime,'%Y-%m-%d %H:%i:%s') end confirmtime,result,date_format(a.create_at,'%Y-%m-%d %H:%i:%s') create_at,b.strategyname," +
- " case b.alarmlevel when 1 then '预警' when 2 then '一般' when 3 then '严重' when 4 then '危急' end level,c.zonename " +
- fmt.Sprintf("from alarm_event a inner join (select a.strategyid,strategyname,max(mpid) mpid,alarmtype,alarmlevel from alarm_strategy a inner join alarm_relation b on a.strategyid=b.strategyid where appid=%d GROUP BY a.strategyid) b on a.strategyid=b.strategyid left join (select * from dev_mpinfo where appid=%d) c on b.mpid=c.mpid ", appId, appId)
- //查询条件结果会重复
- totalSql := "select count(1) recordcount " + fmt.Sprintf("from alarm_event a inner join (select a.strategyid,strategyname,max(mpid) mpid,alarmtype,alarmlevel from alarm_strategy a inner join alarm_relation b on a.strategyid=b.strategyid where appid=%d GROUP BY a.strategyid) b on a.strategyid=b.strategyid left join (select * from dev_mpinfo where appid=%d) c on b.mpid=c.mpid ", appId, appId)
- var sqlCondition []string
- if area != "" {
- sqlCondition = append(sqlCondition, fmt.Sprintf("c.zonename like '%%%s%%'", area))
- }
- if alarmLevel > 0 {
- sqlCondition = append(sqlCondition, fmt.Sprintf("b.alarmlevel=%d", alarmLevel))
- }
- if alarmType > 0 {
- sqlCondition = append(sqlCondition, fmt.Sprintf("eventtype=%d", alarmType))
- }
- if startDate > 0 && endDate > 0 {
- sqlCondition = append(sqlCondition, fmt.Sprintf("timestamp between %d and %d", startDate, endDate))
- } else if startDate > 0 {
- sqlCondition = append(sqlCondition, fmt.Sprintf("timestamp>=%d", startDate))
- } else if endDate > 0 {
- sqlCondition = append(sqlCondition, fmt.Sprintf("timestamp<=%d", endDate))
- }
- if len(sqlCondition) > 0 {
- sqlCommandText += " where " + strings.Join(sqlCondition, " and ")
- totalSql += " where " + strings.Join(sqlCondition, " and ")
- }
- sqlCommandText += fmt.Sprintf(" order by a.id desc limit %d,%d", (pageIndex-1)*pageSize, pageSize)
- var list []AlarmData
- err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &list)
- var total Alarm_Total
- if err == nil {
- l.SvcCtx.AlarmStrategy.Base.Raw(totalSql, &total)
- }
- if len(list) == 0 {
- return map[string]interface{}{"list": []interface{}{}, "total": total.Recordcount}, err
- } else {
- return map[string]interface{}{"list": list, "total": total.Recordcount}, err
- }
- }
- //首页异常设备
- func (t *AlarmService) AlarmHome(modelid string, limit int) (interface{}, error) {
- if limit == 0 {
- limit = 50
- }
- var sqlCommandText string
- l := logic.NewAlarmStrategyLogic()
- type AlarmData struct {
- Eventid int64 `json:"eventid,string"`
- Alarmdata string `json:"alarmdata"`
- Zonename string `json:"zonename"`
- Positionname string `json:"positionname"`
- Devicename string `json:"devicename"`
- Mpname string `json:"mpname"`
- Eventdesc string `json:"eventdesc"`
- }
- appid := RtelecManageApp().RegAppID
- if len(modelid) > 0 {
- sqlCommandText = "select distinct alarm.id eventid,alarm.eventdesc,date_format(from_unixtime(timestamp),'%Y-%m-%d %H:%i:%s') alarmdata,zonename,positionname,device.modelid,device.mpname,devicename " +
- "from (select a.id,a.eventdesc,a.timestamp,b.mpid from alarm_event a inner join alarm_relation b on a.strategyid=b.strategyid where a.eventtype=1 and a.subeventid=0 and a.appid=" + appid + " order by a.create_at desc) alarm " +
- fmt.Sprintf(" inner join (select a.appid,devicename,zonename,positionname,b.mpname,a.modelid,mpid from dev_devinfo a inner join dev_mpinfo b on a.deviceid=b.deviceid where a.appid=%d) device on alarm.mpid=device.mpid where device.appid=%d and device.modelid in %s", appid, appid, modelid)
- } else {
- sqlCommandText = "select distinct alarm.id eventid,alarm.eventdesc,date_format(from_unixtime(timestamp),'%Y-%m-%d %H:%i:%s') alarmdata,zonename,positionname,device.modelid,device.mpname,devicename " +
- "from (select a.id,a.eventdesc,a.timestamp,b.mpid from alarm_event a inner join alarm_relation b on a.strategyid=b.strategyid where a.eventtype=1 and a.subeventid=0 and a.appid=" + appid + " order by a.create_at desc) alarm " +
- fmt.Sprintf(" inner join (select a.appid,devicename,zonename,positionname,b.mpname,a.modelid,mpid from dev_devinfo a inner join dev_mpinfo b on a.deviceid=b.deviceid where a.appid=%d) device on alarm.mpid=device.mpid where device.appid=%d", appid, appid)
- }
- sqlCommandText += fmt.Sprintf(" order by timestamp desc limit %d", limit)
- var list []AlarmData
- err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &list)
- return list, err
- }
- //添加或修改策略信息
- func (t *AlarmService) EditAlarm(parameter *dto.AddAlarmStrategyRes, relationData []map[string]interface{}) error {
- l := logic.NewAlarmStrategyLogic()
- var isAdd = false
- if parameter.Strategyid == 0 {
- isAdd = true
- parameter.Strategyid = new(logic.ToolsLogic).GetOnlyId(int64(parameter.Appid))
- }
- count, err := t.CheckAlarmName(parameter.Strategyname, parameter.Appid)
- if isAdd {
- if err == nil && count > 0 {
- return errors.New(fmt.Sprintf("已存在策略名称(%s)", parameter.Strategyname))
- }
- } else {
- if err == nil && count > 1 {
- return errors.New(fmt.Sprintf("已存在策略名称(%s)", parameter.Strategyname))
- }
- }
- //判断是否有测点关联
- if len(relationData) > 0 {
- var Relations []*model.AlarmRelation
- for _, row := range relationData {
- var RelationField model.AlarmRelation
- relaceId := tools.IsEmpty(row["id"])
- if relaceId == "" {
- RelationField.ID = 0
- } else {
- relationid, _ := strconv.Atoi(relaceId)
- RelationField.ID = int32(relationid)
- }
- RelationField.Alarmtype = int32(row["alarmtype"].(float64))
- RelationField.Strategyid = parameter.Strategyid
- RelationField.Mpid, _ = strconv.ParseInt(row["mpid"].(string), 10, 64)
- if row["uplimit"] != nil {
- RelationField.Uplimit = row["uplimit"].(float64)
- RelationField.Dnlimit = row["dnlimit"].(float64)
- }
- if row["dio"] != nil {
- RelationField.Dio = int32(row["dio"].(float64))
- }
- if row["diffvalue"] != nil {
- RelationField.Diffvalue = row["diffvalue"].(float64)
- }
- RelationField.Relation = int32(row["relation"].(float64))
- Relations = append(Relations, &RelationField)
- }
- parameter.Relation = Relations
- }
- var edit_err error
- if isAdd {
- edit_err = l.AddAlarmStrategy(parameter)
- if edit_err == nil {
- new(LogService).SaveLog(fmt.Sprintf("创建告警策略[%s]成功", parameter.Strategyname))
- }
- } else {
- edit_err = l.ModifyAlarmStrategy(parameter)
- if edit_err == nil {
- new(LogService).SaveLog(fmt.Sprintf("编辑告警策略[%s]成功", parameter.Strategyname))
- }
- }
- if edit_err == nil {
- go t.ReloadAlarmList()
- } else {
- new(LogService).SaveLog(fmt.Sprintf("告警策略[%s]操作失败:%s", parameter.Strategyname, edit_err.Error()))
- }
- return edit_err
- }
- func (t *AlarmService) DeleteAlarm(strategyId int64) error {
- l := logic.NewAlarmEventLogic()
- do := l.SvcCtx.AlarmEvent
- _, err := do.Where(do.Strategyid.Eq(strategyId)).Delete()
- if err != nil {
- new(LogService).SaveLog(fmt.Sprintf("删除告警策略[策略ID:%d]失败:%s", strategyId, err.Error()))
- logger.Logger.Error(err)
- return err
- }
- l1 := logic.NewAlarmStrategyLogic()
- err = l1.DelAlarmStrategy(strategyId)
- if err != nil {
- new(LogService).SaveLog(fmt.Sprintf("删除告警策略[策略ID:%d]失败:%s", strategyId, err.Error()))
- logger.Logger.Error(err)
- return err
- }
- new(LogService).SaveLog(fmt.Sprintf("删除告警策略[策略ID:%d]成功", strategyId))
- go t.ReloadAlarmList()
- return err
- }
- //判断是否已存在条件
- func (t *AlarmService) CheckAlarmName(name string, appId int32) (int64, error) {
- var parameter dto.GetAlarmStrategyReq
- parameter.AppId = appId
- parameter.StrategyName = name
- l := logic.NewAlarmStrategyLogic()
- return l.GetAlarmStrategyCount(¶meter)
- }
- //告警数据列表列表
- func (t *AlarmService) AlarmConfirm(Id int32, eventid int64, content string) error {
- l := logic.NewAlarmEventLogic()
- err := l.SetAlarmEvent(Id, time.Now(), content)
- context := fmt.Sprintf("告警事件Id(%d),确认告警内容(%s)", Id, content)
- if err == nil {
- o := orm.NewOrm()
- o.Raw("update alarm_his set confirm=2,confirmtime=now(),result=? where eventid=?", content, eventid).Exec()
- new(LogService).SaveLog("确定告警事件成功!参数值:" + string(context))
- } else {
- new(LogService).SaveLog("确定告警事件失败!参数值:" + string(context) + ",失败原因:" + err.Error())
- }
- return err
- }
- //告警策略详细
- func (t *AlarmService) AlarmDetail(strategyId int64) (interface{}, error) {
- l := logic.NewAlarmStrategyLogic()
- type AlarmBasic struct {
- Id int `json:"id"`
- Strategyid int64 `json:"strategyid,string"`
- Appid int `json:"appid"`
- Strategyname string `json:"strategyname"`
- Alarmlevel string `json:"alarmlevel"`
- }
- var basic AlarmBasic
- var sqlCommandText = fmt.Sprintf("select * from alarm_strategy where strategyid=%d", strategyId)
- err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &basic)
- type relaction struct {
- Id int `json:"id"`
- Strategyid int64 `json:"strategyid,string"`
- Mpid int64 `json:"mpid,string"`
- Mpname string `json:"mpname"`
- Alarmtype int `json:"alarmtype"`
- Uplimit float64 `json:"uplimit"`
- Dnlimit float64 `json:"dnlimit"`
- Dio int `json:"dio"`
- Diffvalue float64 `json:"diffvalue"`
- Relation int `json:"relation"`
- CreateAt string `json:"create_at"`
- CpdateAt string `json:"cpdate_at"`
- }
- var detail []relaction
- sqlCommandText = fmt.Sprintf("select a.*,b.mpname from alarm_relation a,dev_mpinfo b where a.mpid=b.mpid and a.strategyid=%d", strategyId)
- //fmt.Println("==========sql====", sqlCommandText)
- if err == nil {
- _ = l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &detail)
- }
- return map[string]interface{}{"basic": basic, "detail": detail}, err
- }
- func (t *AlarmService) Search(deviceId int, attrName string) ([]AlarmRelation, error) {
- alarmObject := logic.NewAlarmStrategyLogic()
- var Relation []AlarmRelation
- var sqlCommandText = "select alarmlevel,b.mpid,alarmtype,uplimit,dnlimit,dio,diffvalue,relation,b.strategyid,c.attrname,c.deviceid,c.positionname " +
- fmt.Sprintf("from alarm_strategy a inner join alarm_relation b on a.strategyid=b.strategyid inner join dev_mpinfo c on b.mpid=c.mpid where c.attrname='%s' and c.deviceid=%d and a.appid=%s", attrName, deviceId, RtelecManageApp().RegAppID)
- //log.Println(sqlCommandText)
- err := alarmObject.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &Relation)
- if err != nil {
- logger.Logger.Error(err)
- }
- return Relation, err
- }
- //处理告警事件表
- func (t *AlarmService) HandleAlarmEvent(field *HistoryService) {
- alramSettingService := AlarmSettingService{}
- alarmTacticsService := AlarmTactics{}
- alarmInfoService := AlarmInfoService{}
- var deviceId = int64(field.Model.Deviceid)
- var devicename = field.Model.Devicename
- var receivTime = field.Model.Date
- //log.Println(fmt.Sprintf("接收到新状态值:%v", field))
- //mpid, err := strconv.ParseInt(fmt.Sprint(field.Model.Mpid), 10, 64)
- for attrName, attrValue := range field.AttrInfo {
- // 设备返回来的数据
- // 需要根据attrname去获取mpid
- mpinfo := new(DeviceService).DeviceMpInfo(int32(deviceId))
- row := mpinfo[attrName]
- if len(row) == 0 || len(attrName) == 0 {
- continue
- }
- mpid, err := strconv.ParseInt(tools.IsEmpty(row["mpid"]), 10, 64)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("*******mpid 转化出错 is:%s.", err.Error()))
- }
- curValue, err := strconv.ParseFloat(fmt.Sprint(attrValue), 64)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- curValue, _ = strconv.ParseFloat(global.NullNumber, 64)
- }
- // 如果报警的测点在黑名单中则不处理
- flag := alramSettingService.MpInBlackList(deviceId, mpid)
- if flag {
- return
- }
- // 首先判断这个设备的这个测点是否有绝对值告警策略,如果有则判断是否满足告警条件,如果满足告警条件则写入告警历史表t_base_alarm_his
- // 先获取当前设备当前测点的独立配置信息,如果没有独立配置信息则使用标准的告警策略
- // 先读取绝对值告警独立配置
- aloneAbss := alarmTacticsService.GetAloneAttrAbs(deviceId, mpid)
- if len(aloneAbss) > 0 {
- for _, abs := range aloneAbss {
- // 检查告警是否是当前测点的持续的告警,持续告警不做处理
- flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 1)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- }
- if flag {
- return
- }
- // 获取当前点的数值
- value, err := strconv.ParseFloat(fmt.Sprint(abs["threshold"]), 64)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- f := fmt.Sprint(abs["operation_symbol"])
- var alarmObj models.T_base_alarm_his
- alarmDesc := fmt.Sprintf("触发绝对值告警规则【%s】,", abs["strategy_name"])
- alarm_type := 1
- strategyid, err := strconv.ParseInt(fmt.Sprint(abs["alarm_id"]), 10, 64)
- alarm_level, err := strconv.ParseInt(fmt.Sprint(abs["alarm_level"]), 10, 64)
- alarmObj.Alarm_type = alarm_type
- alarmObj.Alarm_level = int(alarm_level)
- alarmObj.Deviceid = deviceId
- alarmObj.Devicename = devicename
- alarmObj.Confirm = 0
- alarmObj.Confirmtime = ""
- alarmObj.Mpid = mpid
- alarmObj.Mpname = tools.IsEmpty(row["mpname"])
- alarmObj.Is_reset = 0
- alarmObj.Strategyid = strategyid
- alarmObj.Alarm_value = float32(curValue)
- alarmObj.Create_at = tools.NowTime()
- switch f {
- case "=":
- if curValue == value {
- // 添加一条报警记录
- alarmDesc += fmt.Sprintf("采集值%s阈值【%f】", f, value)
- alarmObj.Alarm_desc = alarmDesc
- newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- t.sendWSMessage("alarm", newid, alarmObj)
- }
- case "<":
- if curValue <= value {
- // 添加一条报警记录
- alarmDesc += fmt.Sprintf("采集值%s阈值【%f】", f, value)
- alarmObj.Alarm_desc = alarmDesc
- newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- t.sendWSMessage("alarm", newid, alarmObj)
- }
- case ">":
- if curValue >= value {
- // 添加一条报警记录
- alarmDesc += fmt.Sprintf("采集值%s阈值【%f】", f, value)
- alarmObj.Alarm_desc = alarmDesc
- newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- t.sendWSMessage("alarm", newid, alarmObj)
- }
- case "!=":
- if curValue != value {
- // 添加一条报警记录
- alarmDesc += fmt.Sprintf("采集值%s阈值【%f】", f, value)
- alarmObj.Alarm_desc = alarmDesc
- newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- t.sendWSMessage("alarm", newid, alarmObj)
- }
- }
- // 如果都没有触发告警规则,那进行复归操作
- // 复归操作首先查询告警历史表中相同设备相同测点,状态为未复归的记录
- // 再设置复归状态为“复归”
- flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 1)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- if flag {
- //开始复归操作
- o := orm.NewOrm()
- updid := int64(0)
- hasRow := []orm.Params{}
- o.Raw("select id from t_base_alarm_his where alarm_type=1 and deviceid=? and mpid=?", deviceId, mpid).Values(&hasRow)
- if len(hasRow) > 0 {
- updid, _ = strconv.ParseInt(tools.IsEmpty(hasRow[0]["id"]), 10, 64)
- } else {
- return
- }
- var resetSql = "update t_base_alarm_his set is_reset=1 where id=?"
- res, err := o.Raw(resetSql, updid).Exec()
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", resetSql, []interface{}{updid}))
- new(bo.SystemLog).Fail(enum.AuditType_alarmdata,
- enum.LogType_Update,
- enum.OptEventType_Bus,
- enum.OptEventLevel_Hight,
- fmt.Sprintf("复归告警信息失败:%s,deviceId:%s,mpid:%s", err.Error(), deviceId, mpid),
- map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
- )
- } else {
- num, _ := res.RowsAffected()
- if num > 0 {
- //推送复归信息到前端
- t.sendWSMessage("reset", updid, models.T_base_alarm_his{
- Deviceid: deviceId,
- Mpid: mpid,
- Is_reset: 1,
- })
- new(bo.SystemLog).Success(enum.AuditType_alarmdata,
- enum.LogType_Update,
- enum.OptEventType_Bus,
- enum.OptEventLevel_Hight,
- fmt.Sprintf("复归告警信息成功,deviceId:%s,mpid:%s", deviceId, mpid),
- map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
- )
- }
- }
- }
- }
- } else {
- abss := alarmTacticsService.GetAttrAbs(attrName)
- // 如果有多个绝对值告警
- if len(abss) > 0 {
- for _, abs := range abss {
- // 检查告警是否是当前测点的持续的告警,持续告警不做处理
- flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 1)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- }
- if flag {
- return
- }
- value, err := strconv.ParseFloat(fmt.Sprint(abs["threshold"]), 64)
- if err != nil {
- logger.Logger.Error(err)
- logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- f := fmt.Sprint(abs["operation_symbol"])
- var alarmObj models.T_base_alarm_his
- alarmDesc := fmt.Sprintf("触发绝对值告警规则【%s】,", abs["strategy_name"])
- alarm_type := 1
- strategyid, err := strconv.ParseInt(fmt.Sprint(abs["id"]), 10, 64)
- alarm_level, err := strconv.ParseInt(fmt.Sprint(abs["alarm_level"]), 10, 64)
- alarmObj.Alarm_type = alarm_type
- alarmObj.Alarm_level = int(alarm_level)
- alarmObj.Deviceid = deviceId
- alarmObj.Devicename = devicename
- alarmObj.Confirm = 0
- alarmObj.Confirmtime = ""
- alarmObj.Mpid = mpid
- alarmObj.Mpname = tools.IsEmpty(row["mpname"])
- alarmObj.Is_reset = 0
- alarmObj.Strategyid = strategyid
- alarmObj.Alarm_value = float32(curValue)
- alarmObj.Create_at = tools.NowTime()
- switch f {
- case "=":
- if curValue == value {
- // 添加一条报警记录
- alarmDesc += fmt.Sprintf("采集值%s阈值【%f】", f, value)
- alarmObj.Alarm_desc = alarmDesc
- newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
- if err != nil {
- logger.Logger.Error(err)
- logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- t.sendWSMessage("alarm", newid, alarmObj)
- }
- case "<":
- if curValue <= value {
- // 添加一条报警记录
- alarmDesc += fmt.Sprintf("采集值%s阈值【%f】", f, value)
- alarmObj.Alarm_desc = alarmDesc
- newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
- if err != nil {
- logger.Logger.Error(err)
- logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- t.sendWSMessage("alarm", newid, alarmObj)
- }
- case ">":
- if curValue >= value {
- // 添加一条报警记录
- alarmDesc += fmt.Sprintf("采集值%s阈值【%f】", f, value)
- alarmObj.Alarm_desc = alarmDesc
- newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
- if err != nil {
- logger.Logger.Error(err)
- logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- t.sendWSMessage("alarm", newid, alarmObj)
- }
- case "!=":
- if curValue != value {
- // 添加一条报警记录
- alarmDesc += fmt.Sprintf("采集值%s阈值【%f】", f, value)
- alarmObj.Alarm_desc = alarmDesc
- newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
- if err != nil {
- logger.Logger.Error(err)
- logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- t.sendWSMessage("alarm", newid, alarmObj)
- }
- }
- // 如果都没有触发告警规则,那进行复归操作
- // 复归操作首先查询告警历史表中相同设备相同测点,状态为未复归的记录
- // 再设置复归状态为“复归”
- flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 1)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- if flag {
- //开始复归操作
- o := orm.NewOrm()
- updid := int64(0)
- hasRow := []orm.Params{}
- o.Raw("select id from t_base_alarm_his where alarm_type=1 and deviceid=? and mpid=?", deviceId, mpid).Values(&hasRow)
- if len(hasRow) > 0 {
- updid, _ = strconv.ParseInt(tools.IsEmpty(hasRow[0]["id"]), 10, 64)
- } else {
- return
- }
- var resetSql = "update t_base_alarm_his set is_reset=1 where id=?"
- res, err := o.Raw(resetSql, updid).Exec()
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", resetSql, []interface{}{updid}))
- new(bo.SystemLog).Fail(enum.AuditType_alarmdata,
- enum.LogType_Update,
- enum.OptEventType_Bus,
- enum.OptEventLevel_Hight,
- fmt.Sprintf("复归告警信息失败:%s,deviceId:%s,mpid:%s", err.Error(), deviceId, mpid),
- map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
- )
- } else {
- num, _ := res.RowsAffected()
- if num > 0 {
- //推送复归信息到前端
- t.sendWSMessage("reset", updid, models.T_base_alarm_his{
- Deviceid: deviceId,
- Mpid: mpid,
- Is_reset: 1,
- })
- new(bo.SystemLog).Success(enum.AuditType_alarmdata,
- enum.LogType_Update,
- enum.OptEventType_Bus,
- enum.OptEventLevel_Hight,
- fmt.Sprintf("复归告警信息成功,deviceId:%s,mpid:%s", deviceId, mpid),
- map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
- )
- }
- }
- }
- }
- }
- }
- // 第二判断这个设备的这个测点是否有升温告警策略,如果有则判断是否满足告警条件,如果满足告警条件则写入告警历史表t_base_alarm_his
- // 先读取升温告警独立配置
- aloneRises := alarmTacticsService.GetAloneAttrRise(deviceId, mpid)
- if len(aloneRises) > 0 {
- for _, rise := range aloneRises {
- // 检查告警是否是当前测点的持续的告警,持续告警不做处理
- flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 2)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- }
- if flag {
- return
- }
- // 配置里面的值
- value, err := strconv.ParseFloat(fmt.Sprint(rise["scope"]), 64)
- if err != nil {
- logger.Logger.Error(err)
- logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- upcycle, err := strconv.ParseInt(tools.IsEmpty(rise["upcycle"]), 10, 64)
- var alarmObj models.T_base_alarm_his
- alarmDesc := fmt.Sprintf("触发升温告警规则【%s】,", rise["strategy_name"])
- alarm_type := 2
- strategyid, err := strconv.ParseInt(fmt.Sprint(rise["alarm_id"]), 10, 64)
- if err != nil {
- logger.Logger.Error(err)
- logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- alarm_level, err := strconv.ParseInt(fmt.Sprint(rise["alarm_level"]), 10, 64)
- if err != nil {
- logger.Logger.Error(err)
- logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- alarmObj.Alarm_type = alarm_type
- alarmObj.Alarm_level = int(alarm_level)
- alarmObj.Deviceid = deviceId
- alarmObj.Devicename = devicename
- alarmObj.Confirm = 0
- alarmObj.Confirmtime = ""
- alarmObj.Mpid = mpid
- alarmObj.Mpname = tools.IsEmpty(row["mpname"])
- alarmObj.Is_reset = 0
- alarmObj.Strategyid = strategyid
- alarmObj.Alarm_value = float32(curValue)
- alarmObj.Alarm_desc = alarmDesc
- // 上升周期(分钟)内,温度升高超过温升范围,则需要报警
- // 需要读取当前测点最后一条数据推送记录进行对比
- nearBy, err := alarmInfoService.GetNearByUpcycle(deviceId, attrName, int(upcycle), receivTime)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- if nearBy != nil {
- // curValue数据返回的值,value配置中的上升范围
- nearItem, err := strconv.ParseFloat(fmt.Sprint(nearBy[attrName]), 64) // 历史数据中最接近现在的一条数据
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- //如果当前的数据大于等于周期之前的数据值+设置的范围值,则认为超出了范围,需要报警
- if curValue >= (value + nearItem) {
- newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
- if err != nil {
- logger.Logger.Error(err)
- logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- t.sendWSMessage("alarm", newid, alarmObj)
- }
- }
- }
- // 如果都没有触发告警规则,那进行复归操作
- // 复归操作首先查询告警历史表中相同设备相同测点,状态为未复归的记录
- // 再设置复归状态为“复归”
- flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 2)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- if flag {
- //开始复归操作
- o := orm.NewOrm()
- updid := int64(0)
- hasRow := []orm.Params{}
- o.Raw("select id from t_base_alarm_his where alarm_type=2 and deviceid=? and mpid=?", deviceId, mpid).Values(&hasRow)
- if len(hasRow) > 0 {
- updid, _ = strconv.ParseInt(tools.IsEmpty(hasRow[0]["id"]), 10, 64)
- } else {
- return
- }
- var resetSql = "update t_base_alarm_his set is_reset=1 where id=?"
- res, err := o.Raw(resetSql, updid).Exec()
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", resetSql, []interface{}{updid}))
- new(bo.SystemLog).Fail(enum.AuditType_alarmdata,
- enum.LogType_Update,
- enum.OptEventType_Bus,
- enum.OptEventLevel_Hight,
- fmt.Sprintf("复归告警信息失败:%s,deviceId:%s,mpid:%s", err.Error(), deviceId, mpid),
- map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
- )
- } else {
- num, _ := res.RowsAffected()
- if num > 0 {
- //推送复归信息到前端
- t.sendWSMessage("reset", updid, models.T_base_alarm_his{
- Deviceid: deviceId,
- Mpid: mpid,
- Is_reset: 1,
- })
- new(bo.SystemLog).Success(enum.AuditType_alarmdata,
- enum.LogType_Update,
- enum.OptEventType_Bus,
- enum.OptEventLevel_Hight,
- fmt.Sprintf("复归告警信息成功,deviceId:%s,mpid:%s", deviceId, mpid),
- map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
- )
- }
- }
- }
- } else {
- // 没有独立的配置则读取标准配置
- rises := alarmTacticsService.GetAttrRise(attrName)
- if len(rises) > 0 {
- for _, rise := range rises {
- // 检查告警是否是当前测点的持续的告警,持续告警不做处理
- flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 2)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- }
- if flag {
- return
- }
- value, err := strconv.ParseFloat(fmt.Sprint(rise["scope"]), 64)
- if err != nil {
- logger.Logger.Error(err)
- logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- upcycle, err := strconv.ParseInt(tools.IsEmpty(rise["upcycle"]), 10, 64)
- var alarmObj models.T_base_alarm_his
- alarmDesc := fmt.Sprintf("触发升温告警规则【%s】,", rise["strategy_name"])
- alarm_type := 2
- strategyid, err := strconv.ParseInt(fmt.Sprint(rise["id"]), 10, 64)
- if err != nil {
- logger.Logger.Error(err)
- logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- alarm_level, err := strconv.ParseInt(fmt.Sprint(rise["alarm_level"]), 10, 64)
- if err != nil {
- logger.Logger.Error(err)
- logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- alarmObj.Alarm_type = alarm_type
- alarmObj.Alarm_level = int(alarm_level)
- alarmObj.Deviceid = deviceId
- alarmObj.Devicename = devicename
- alarmObj.Confirm = 0
- alarmObj.Confirmtime = ""
- alarmObj.Mpid = mpid
- alarmObj.Mpname = tools.IsEmpty(row["mpname"])
- alarmObj.Is_reset = 0
- alarmObj.Strategyid = strategyid
- alarmObj.Alarm_value = float32(curValue)
- alarmObj.Alarm_desc = alarmDesc
- alarmObj.Create_at = tools.NowTime()
- // 上升周期(分钟)内,温度升高超过温升范围,则需要报警
- // 需要读取当前测点上升周期的最后一条数据推送记录进行对比
- nearBy, err := alarmInfoService.GetNearByUpcycle(deviceId, attrName, int(upcycle), receivTime)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- if nearBy != nil {
- // curValue数据返回的值,value配置中的上升范围
- nearItem, err := strconv.ParseFloat(fmt.Sprint(nearBy[attrName]), 64) // 历史数据中最接近现在的一条数据
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- //如果当前的数据大于等于周期之前的数据值+设置的范围值,则认为超出了范围,需要报警
- if curValue >= (value + nearItem) {
- newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
- if err != nil {
- logger.Logger.Error(err)
- logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- t.sendWSMessage("alarm", newid, alarmObj)
- }
- }
- }
- // 如果都没有触发告警规则,那进行复归操作
- // 复归操作首先查询告警历史表中相同设备相同测点,状态为未复归的记录
- // 再设置复归状态为“复归”
- flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 2)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- if flag {
- //开始复归操作
- o := orm.NewOrm()
- updid := int64(0)
- hasRow := []orm.Params{}
- o.Raw("select id from t_base_alarm_his where alarm_type=2 and deviceid=? and mpid=?", deviceId, mpid).Values(&hasRow)
- if len(hasRow) > 0 {
- updid, _ = strconv.ParseInt(tools.IsEmpty(hasRow[0]["id"]), 10, 64)
- } else {
- return
- }
- var resetSql = "update t_base_alarm_his set is_reset=1 where id=?"
- res, err := o.Raw(resetSql, updid).Exec()
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", resetSql, []interface{}{updid}))
- new(bo.SystemLog).Fail(enum.AuditType_alarmdata,
- enum.LogType_Update,
- enum.OptEventType_Bus,
- enum.OptEventLevel_Hight,
- fmt.Sprintf("复归告警信息失败:%s,deviceId:%s,mpid:%s", err.Error(), deviceId, mpid),
- map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
- )
- } else {
- num, _ := res.RowsAffected()
- if num > 0 {
- //推送复归信息到前端
- t.sendWSMessage("reset", updid, models.T_base_alarm_his{
- Deviceid: deviceId,
- Mpid: mpid,
- Is_reset: 1,
- })
- new(bo.SystemLog).Success(enum.AuditType_alarmdata,
- enum.LogType_Update,
- enum.OptEventType_Bus,
- enum.OptEventLevel_Hight,
- fmt.Sprintf("复归告警信息成功,deviceId:%s,mpid:%s", deviceId, mpid),
- map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
- )
- }
- }
- }
- }
- }
- // 第三判断是否在分组里面
- flag, err = new(MpinfoService).MpidInGroup(mpid)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- // 如果在分组里面需要根据deviceid把所有分组找出来
- if flag {
- // 检查告警是否是当前测点的持续的告警,持续告警不做处理
- flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 3)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- }
- if flag {
- return
- }
- var alarmObj models.T_base_alarm_his
- alarmObj.Alarm_type = 3
- alarmObj.Deviceid = deviceId
- alarmObj.Devicename = devicename
- alarmObj.Confirm = 0
- alarmObj.Confirmtime = ""
- alarmObj.Is_reset = 0
- alarmObj.Alarm_value = float32(curValue)
- alarmObj.Create_at = tools.NowTime()
- groupList, err := new(MpinfoService).GroupList(int32(deviceId))
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- for _, row := range groupList {
- groupid, err := strconv.ParseInt(tools.IsEmpty(row["groupid"]), 10, 64)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- t.HandleAlarmUnbalance(groupid, alarmObj, field.AttrInfo)
- }
- // 如果都没有触发告警规则,那进行复归操作
- // 复归操作首先查询告警历史表中相同设备相同测点,状态为未复归的记录
- // 再设置复归状态为“复归”
- flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 3)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return
- }
- if flag {
- //开始复归操作
- o := orm.NewOrm()
- updid := int64(0)
- hasRow := []orm.Params{}
- o.Raw("select id from t_base_alarm_his where alarm_type=3 and deviceid=? and mpid=?", deviceId, mpid).Values(&hasRow)
- if len(hasRow) > 0 {
- updid, _ = strconv.ParseInt(tools.IsEmpty(hasRow[0]["id"]), 10, 64)
- } else {
- return
- }
- var resetSql = "update t_base_alarm_his set is_reset=1 where id=?"
- res, err := o.Raw(resetSql, updid).Exec()
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", resetSql, []interface{}{updid}))
- new(bo.SystemLog).Fail(enum.AuditType_alarmdata,
- enum.LogType_Update,
- enum.OptEventType_Bus,
- enum.OptEventLevel_Hight,
- fmt.Sprintf("复归告警信息失败:%s,deviceId:%s,mpid:%s", err.Error(), deviceId, mpid),
- map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
- )
- } else {
- num, _ := res.RowsAffected()
- if num > 0 {
- //推送复归信息到前端
- t.sendWSMessage("reset", updid, models.T_base_alarm_his{
- Deviceid: deviceId,
- Mpid: mpid,
- Is_reset: 1,
- })
- new(bo.SystemLog).Success(enum.AuditType_alarmdata,
- enum.LogType_Update,
- enum.OptEventType_Bus,
- enum.OptEventLevel_Hight,
- fmt.Sprintf("复归告警信息成功,deviceId:%s,mpid:%s", deviceId, mpid),
- map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
- )
- }
- }
- }
- }
- }
- }
- // 根据测点分组id获取该分组下的所有测点id
- // 然后应用所有温度不平衡下的所有策略
- func (t AlarmService) HandleAlarmUnbalance(groupId int64, alarmObj models.T_base_alarm_his, attrInfo map[string]interface{}) error {
- db := orm.NewOrm()
- var sqlCommandText = "select * from t_data_mp_group where groupid=?"
- source := []orm.Params{}
- _, err := db.Raw(sqlCommandText, groupId).Values(&source)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return err
- }
- unBalanceList := new(AlarmTactics).GetUnbalanceList()
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return err
- }
- currtValueSourceList := []interface{}{}
- currtValueTargtList := []interface{}{}
- for _, s := range source {
- currtValue := tools.IsEmpty(attrInfo[tools.IsEmpty(s["attrname"])]) //返回分组的测点在当前采集数据中对应的值
- currtValueSourceList = append(currtValueSourceList, currtValue)
- currtValueTargtList = append(currtValueTargtList, currtValue)
- }
- for _, balance := range unBalanceList {
- for index, row := range currtValueSourceList {
- a, err := strconv.ParseFloat(tools.IsEmpty(row), 64)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return err
- }
- for _, item := range currtValueTargtList {
- op := tools.IsEmpty(balance["operation_symbol"])
- strategyid, err := strconv.ParseInt(tools.IsEmpty(balance["id"]), 10, 64)
- alarm_level, err := strconv.ParseInt(tools.IsEmpty(balance["alarm_level"]), 10, 64)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return err
- }
- threshold, err := strconv.ParseFloat(tools.IsEmpty(balance["threshold"]), 64)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return err
- }
- b, err := strconv.ParseFloat(tools.IsEmpty(item), 64)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return err
- }
- flag := t.CompareAbs(op, a, b, threshold)
- // 如果满足触发条件则添加一个告警数据
- if flag {
- // 添加一个告警信息
- alarmObj.Mpid = groupId
- alarmObj.Mpname = tools.IsEmpty(balance["strategy_name"])
- alarmObj.Alarm_level = int(alarm_level)
- alarmObj.Strategyid = strategyid
- alarmObj.Alarm_desc = fmt.Sprintf("触发温度不平衡告警规则【%s】,", balance["strategy_name"])
- newid, err := new(AlarmInfoService).InsertAlarmInfo(alarmObj)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
- return err
- }
- t.sendWSMessage("alarm", newid, alarmObj)
- }
- currtValueTargtList = append(currtValueTargtList[:index], currtValueTargtList[index+1:]...)
- }
- }
- }
- return nil
- }
- // a和b之差的绝对值和不平衡里面的值进行operation比较
- func (t *AlarmService) CompareAbs(op string, a float64, b float64, threshold float64) bool {
- // 如果a和b之差的绝对值和不平衡里面的值进行operation比较
- switch op {
- case ">":
- if math.Abs(a-b) > threshold {
- return true
- }
- case "<":
- if math.Abs(a-b) < threshold {
- return true
- }
- case "=":
- if math.Abs(a-b) == threshold {
- return true
- }
- default:
- return false
- }
- return false
- }
- func (t *AlarmService) HandleAlarmEvent2(field *HistoryService) {
- var deviceId = int64(field.Model.Deviceid)
- //log.Println(fmt.Sprintf("接收到新状态值:%v", field))
- for attrName, attrValue := range field.AttrInfo {
- curValue := cast.ToFloat64(attrValue)
- eventId := int64(0)
- //relation, _ := search(deviceId, attrName)
- strategyLst := t.FindstrategyDefByAttrname(deviceId, attrName)
- //log.Println(fmt.Sprintf("设备%d及属性%s的策略配置:%+v", deviceId, attrName, strategyLst))
- if len(strategyLst) == 0 {
- continue
- } else {
- for strategyid, relation := range strategyLst {
- strategyname := ""
- alertstatus := 0 //策略当前告警状态:默认告警状态
- alarmLevel := 1 //告警级别,1 预警,2 一般,3 严重,4 危急
- positionname := "" //告警设备位置
- mpid := int64(0) //当前测点ID
- //前置测点运算关系,默认为无 1-与,2-或,3-无
- preRelation := 0
- //前置测点告警状态运算结果
- preAlertStatus := false
- for _, record := range relation {
- var alarmState = false // 当前测点规则是否告警
- //log.Println(fmt.Sprintf("当前测点规则:%+v 当前状态值:%d", record, attrValue))
- key := fmt.Sprintf("%d_%s_%d", record.Deviceid, record.Attrname, strategyid)
- if record.Deviceid == deviceId && record.Attrname == attrName {
- switch record.Alarmtype {
- case 1: //阈值告警
- if curValue <= record.Dnlimit || curValue >= record.Uplimit { //小于下限或者大于上限触发告警条件
- alarmState = true
- }
- case 2: //开关量告警
- if record.Dio == curValue { //触发告警条件
- alarmState = true
- }
- case 3: //差值告警
- var diffen, err = t.GetDiff(record.Mpid)
- if err == nil {
- if math.Abs(cast.ToFloat64(diffen)-curValue) > record.Diffvalue { //触发告警条件
- alarmState = true
- }
- }
- }
- //缓存当前设备及测点的告警状态
- DeviceAttrLastInfo.Store(key, alarmState)
- } else {
- //判断是否缓存了该设备和测点的告警状态,未缓存时默认为无告警
- v, has := DeviceAttrLastInfo.Load(key)
- if has {
- alarmState = v.(bool)
- }
- }
- if preRelation == 0 {
- //第一个测点规则,没有前置测点时
- preAlertStatus = alarmState
- } else {
- if preRelation == 1 {
- //"与"关系
- preAlertStatus = alarmState && preAlertStatus
- } else if preRelation == 2 {
- //"或"关系
- preAlertStatus = alarmState || preAlertStatus
- }
- }
- //log.Printf(fmt.Sprintf("本次告警状态:%v 策略告警状态%v", alarmState, preAlertStatus))
- //当前告警测点信息
- alarmLevel = record.Alarmlevel
- mpid = record.Mpid
- strategyname = record.Strategyname
- preRelation = record.Relation
- if record.Relation == 3 {
- //运算关系:多测点间告警关系。1-与,2-或,3-无
- break
- }
- }
- if preAlertStatus {
- alertstatus = 1
- } else {
- alertstatus = 0
- }
- //该策略最后一次告警状态信息
- tmpData, has := beforeAlarmState.Load(strategyid)
- var beforeAlram = false
- var beforeEventId = int64(0)
- if !has {
- beforeAlram, beforeEventId = t.GetBeforeAlarmState(tools.IsEmpty(strategyid))
- } else {
- //从缓存中获取策略告警信息
- tmpData1 := tmpData.(map[string]interface{})
- beforeAlram = tmpData1["state"].(bool)
- beforeEventId = tmpData1["eventid"].(int64)
- }
- //log.Println("=====%d====%v===%d", alertstatus, beforeAlram, beforeEventId)
- //策略当前告警状态:0 无告警 1 触发告警 2 告警复归
- if alertstatus == 0 && !beforeAlram {
- //无告警,不做处理
- continue
- }
- if alertstatus == 1 && beforeAlram {
- //持续告警,不做处理
- continue
- }
- eventId = new(logic.ToolsLogic).GetOnlyId(cast.ToInt64(RtelecManageApp().RegAppID))
- desc := t.AlarmDesc(mpid)
- shortDesc := desc
- var eventtype int32 = 0
- if alertstatus == 1 && !beforeAlram {
- eventtype = 1
- desc += fmt.Sprintf("状态值(%d)触发告警策略[%s]", int(curValue), strategyname)
- //在写iss库的同时,写本地库的alarm_his表
- lerr := t.AddLocalAlarmEvent(eventId, shortDesc, eventtype, strategyid, int32(alarmLevel), positionname, int(deviceId))
- if lerr != nil {
- logger.Logger.Error(lerr)
- continue
- }
- tmpData := map[string]interface{}{"state": true, "eventid": eventId}
- beforeAlarmState.Store(strategyid, tmpData)
- } else if alertstatus == 0 && beforeAlram {
- eventtype = 3
- desc += fmt.Sprintf("状态值(%d)已恢复正常,告警复归", int(curValue))
- tmpData := map[string]interface{}{"state": false, "eventid": int64(0)}
- beforeAlarmState.Store(strategyid, tmpData)
- }
- //log.Printf(fmt.Sprintf("本次告警描述:%s", desc))
- err := t.AddAlarmEvent(eventId, desc, eventtype, strategyid, int32(alarmLevel), beforeEventId)
- if err == nil {
- //添加告警成功后发送消息到前端
- //向websocket通道中发送数据让前端接收
- go func() {
- var message = make(map[string]interface{})
- message["content"] = field.Model.Devicename
- message["time"] = tools.NowTime()
- message["region"] = positionname
- message["msg_type"] = 0
- datachannel.SendDataQueue <- message
- }()
- //向中台发送消息
- var parameter AlarmMessage
- parameter.Eventid = eventId
- parameter.Eventtype = 0
- parameter.Eventdesc = desc
- parameter.Timestamp = time.Now().Local().Unix()
- parameter.Mid = tools.GetUid()
- parameter.Strategyid = strategyid
- t.SendAlertMessage(parameter)
- } else {
- logger.Logger.Error("告警信息写入失败:" + err.Error())
- }
- }
- }
- }
- }
- // 添加本地告警事件
- func (t *AlarmService) AddLocalAlarmEvent(eventid int64, eventdesc string, eventtype int32, strategyId int64, alarmlevel int32, position string, deviceid int) error {
- db := orm.NewOrm()
- rs, dberr := new(DeviceService).GetDeviceActionPoint(deviceid)
- var modelid int
- var positionname string
- if dberr == nil && len(rs) > 0 {
- modelid = rs[0].Modelid
- }
- descs := strings.Split(eventdesc, ",")
- for i := 0; i < len(descs); i++ {
- if i == 0 || i == (len(descs)-1) {
- continue
- }
- positionname = positionname + tools.IsEmpty(descs[i]) + ","
- }
- positionname = positionname[0 : len(positionname)-1]
- var sqlCommandText = "insert into alarm_his(eventid,eventdesc,eventtype,timestamp,strategyid,appid,alarmlevel,modelid,position)values(?,?,?,?,?,?,?,?,?);"
- var sqlParamber = []interface{}{eventid, positionname, eventtype, time.Now().Unix(), strategyId, RtelecManageApp().RegAppID, alarmlevel, modelid, position}
- _, err := db.Raw(sqlCommandText, sqlParamber).Exec()
- if err != nil {
- logger.Logger.Println("告警事件写入本地数据库出现错误:")
- logger.Logger.Error(err)
- }
- return err
- }
- //根据测点id(mpid)获得描述
- func (t *AlarmService) AlarmDesc(Mpid int64) string {
- var eventdesc = ""
- mpInfo := logic.NewMpInfoLogic()
- type Mpfield struct {
- Eventdesc string `json:"eventdesc"`
- }
- var list []Mpfield
- var sqlCommandText = fmt.Sprintf("select concat(c.name,',区域:',a.zonename,',位置:',a.positionname,',测点:',a.mpname) eventdesc from dev_mpinfo a inner join dev_devinfo b on a.deviceid=b.deviceid inner join sys_station c on b.stationid=c.stationid where mpid=%d", Mpid)
- err := mpInfo.SvcCtx.DevMpinfo.Base.Raw(sqlCommandText, &list)
- if err == nil && len(list) > 0 {
- eventdesc = list[0].Eventdesc + ","
- }
- return eventdesc
- }
- //发送消息
- func (t *AlarmService) SendAlertMessage(msg AlarmMessage) error {
- var parameter = make(map[string]interface{})
- parameter["token"] = RtelecManageApp().AppToken
- parameter["eventid"] = msg.Eventid
- parameter["eventtype"] = msg.Eventtype
- parameter["eventdesc"] = msg.Eventdesc
- parameter["strategyid"] = msg.Strategyid
- parameter["timestamp"] = time.Now().Unix()
- parameter["mid"] = msg.Mid
- /*//mqtt消息中的message数据处理
- var para = make(map[string]interface{})
- para["eventid"] = msg.Eventid
- para["eventtype"] = msg.Eventtype
- para["eventdesc"] = msg.Eventdesc
- para["strategyid"] = msg.Strategyid
- para["timestamp"] = time.Now().Unix()
- para["mid"] = msg.Mid
- Message, _ := json.Marshal(para)
- message, _ := common.Encrypt(Message, configure.AppConfigure.PassWord)
- parameter["message"] = message*/
- messageContent, _ := json.Marshal(parameter)
- mqtt.PublishMessage(global.Rtelec_Topics["alarm_info"], string(messageContent))
- return nil
- }
- //添加告警事件记录
- func (t *AlarmService) AddAlarmEvent(eventid int64, eventdesc string, eventtype int32, strategyId int64, alarmlevel int32, beforeEventId int64) error {
- l := logic.NewAlarmEventLogic()
- appid := RtelecManageApp().RegAppID
- parameter := model.AlarmEvent{}
- parameter.Eventid = eventid
- parameter.Eventdesc = eventdesc
- parameter.Eventtype = eventtype
- parameter.Timestamp = time.Now().Unix()
- parameter.Strategyid = strategyId
- parameter.Alarmlevel = int32(alarmlevel)
- parameter.Appid = cast.ToInt32(appid)
- parameter.Subeventid = beforeEventId
- oldRow := model.AlarmEvent{}
- oldRow.Eventid = beforeEventId
- oldRow.Subeventid = eventid
- err := l.ModifyAlarmEvent(&oldRow, "subeventid")
- if err != nil {
- logger.Logger.Error(err)
- }
- return l.AddAlarmEvent(¶meter)
- }
- //获取设备上次状态
- func (t *AlarmService) GetBeforeState(deviceId int, attrName string) float64 {
- var state = -1
- o := orm.NewOrm()
- var sqlCommandText = "select val from dev_history where attrname=? and deviceid=? order by id desc limit 1"
- var sqlParameter = []interface{}{attrName, deviceId}
- var table []orm.Params
- _, err := o.Raw(sqlCommandText, sqlParameter).Values(&table)
- if err == nil && len(table) > 0 {
- state, _ = strconv.Atoi(table[0]["val"].(string))
- }
- return float64(state)
- }
- //获取测点上次报警状态
- //true:已报警,下次不处理
- //false:未报警或已复归,下次需处理
- func (t *AlarmService) GetBeforeAlarmState(strategyid string) (bool, int64) {
- mpInfo := logic.NewMpInfoLogic()
- //获取告警事件表中告警策略最近的一条纪录
- //根据这个纪录的eventtype来判断。如果没有纪录或者eventtype是3,那么上次的状态为复归了。下次需要写事件表。
- //如果eventtype不为3,那么上次状态为确认了。下次不需要写事件表
- var sqlCommandText = "select eventtype,eventid from alarm_event where strategyid=" + strategyid + " order by id desc limit 1"
- // var table []orm.Params
- type tabledd struct {
- Eventtype int `json:"eventtype"`
- Eventid int64
- }
- var tablesd []tabledd
- err := mpInfo.SvcCtx.AlarmEvent.Base.Raw(sqlCommandText, &tablesd)
- if err == nil {
- if len(tablesd) == 0 {
- return false, 0
- } else if "3" == tools.IsEmpty(tablesd[0].Eventtype) {
- return false, 0
- }
- }
- return true, tablesd[0].Eventid
- }
- //差值告警,获取本次数据与上一次历史数据的差值
- func (t *AlarmService) GetDiff(mpid interface{}) (float64, error) {
- var k = tools.IsEmpty(mpid)
- o := orm.NewOrm()
- var sqlCommandText = "select val from dev_history where mpid=? order by id desc limit 1"
- var sqlParameter = []interface{}{k}
- var table []orm.Params
- _, err := o.Raw(sqlCommandText, sqlParameter).Values(&table)
- if err == nil && len(table) > 0 {
- return cast.ToFloat64((table[0]["val"])), nil
- }
- return cast.ToFloat64(0), err
- }
- //向前端推送告警信息
- //optype:操作类型。alarm:新的告警 reset:告警复归
- func (t *AlarmService) sendWSMessage(optype string, alarmid int64, alarmObj models.T_base_alarm_his) {
- //推送复归信息到前端
- msg := map[string]interface{}{
- "alarm_id": tools.IsEmpty(alarmid),
- "device_id": tools.IsEmpty(alarmObj.Deviceid),
- "mp_id": tools.IsEmpty(alarmObj.Mpid),
- "is_reset": 0,
- }
- if optype == "alarm" {
- msg["alarm_desc"] = alarmObj.Alarm_desc
- msg["device_name"] = alarmObj.Devicename
- msg["mp_name"] = alarmObj.Mpname
- msg["create_at"] = alarmObj.Create_at
- msg["alarm_level"] = alarmObj.Alarm_level
- } else {
- msg["is_reset"] = 1
- }
- datachannel.SendDataQueue <- map[string]interface{}{
- "topic": global.Topic_DeviceAlarmPublish,
- "data": msg,
- }
- }
|