alarm_service.go 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490
  1. package service
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "math"
  7. "rtzh_elec_temperature/datachannel"
  8. "rtzh_elec_temperature/enum"
  9. "rtzh_elec_temperature/global"
  10. "rtzh_elec_temperature/logger"
  11. "rtzh_elec_temperature/models/bo"
  12. "rtzh_elec_temperature/mqtt"
  13. "rtzh_elec_temperature/rtelec_app_public_lib/models"
  14. "rtzh_elec_temperature/tools"
  15. "strconv"
  16. "strings"
  17. "sync"
  18. "time"
  19. "github.com/astaxie/beego/orm"
  20. "git.rtzhtech.cn/iss/public-lib/model"
  21. "git.rtzhtech.cn/iss/public-lib/dto"
  22. "github.com/spf13/cast"
  23. "git.rtzhtech.cn/iss/public-lib/logic"
  24. )
  25. //公共平台告警服务,提供告警策略的维护以及告警判断、触发等
  26. type AlarmService struct {
  27. BaseService
  28. }
  29. //发送告警消息
  30. type AlarmMessage struct {
  31. Eventid int64 `json:"eventid"`
  32. Eventtype int `json:"eventtype"`
  33. Eventdesc string `json:"eventdesc"`
  34. Strategyid int64 `json:"strategyid"`
  35. Timestamp int64 `json:"timestamp"`
  36. Mid string `json:"mid"`
  37. }
  38. type AlarmRelation struct {
  39. Alarmlevel int `json:"alarmlevel"`
  40. Mpid int64 `json:"mpid"`
  41. Deviceid int64 `json:"deviceid"`
  42. Attrname string `json:"attrname"`
  43. Alarmtype int `json:"alarmtype"`
  44. Uplimit float64 `json:"uplimit"`
  45. Dnlimit float64 `json:"dnlimit"`
  46. Dio float64 `json:"dio"`
  47. Diffvalue float64 `json:"diffvalue"`
  48. Relation int `json:"relation"`
  49. Strategyid int64 `json:"strategyid"`
  50. Strategyname string `json:"strategyname"`
  51. Positionname string `json:"positionname"`
  52. }
  53. type Alarm_List struct {
  54. Id int `json:"id"`
  55. Strategyid int64 `json:"strategyid,string"`
  56. Strategyname string `json:"strategyname"`
  57. Alarmlevel int `json:"alarmlevel"`
  58. Create_at string `json:"create_at"`
  59. Update_at string `json:"update_at"`
  60. Nickname string `json:"nickname"`
  61. }
  62. type Alarm_Total struct {
  63. Recordcount int
  64. }
  65. //设备测点最后一次的采集值及告警信息
  66. //map_key:deviceid_attrname_strategyid
  67. //map_value:alertstatus
  68. var DeviceAttrLastInfo = sync.Map{}
  69. var beforeAlarmState = sync.Map{}
  70. //告警策略定义列表
  71. var strategyDefList = []AlarmRelation{}
  72. var strategyDefListLock = sync.Mutex{}
  73. //重新加载告警策略到缓存中
  74. func (t *AlarmService) ReloadAlarmList() {
  75. strategyDefListLock.Lock()
  76. strategyDefList = []AlarmRelation{}
  77. alarmObject := logic.NewAlarmStrategyLogic()
  78. var sqlCommandText = "select alarmlevel,b.mpid,alarmtype,uplimit,dnlimit,dio,diffvalue,relation,b.strategyid,a.strategyname,c.attrname,c.deviceid,c.positionname " +
  79. 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)
  80. //log.Println(sqlCommandText)
  81. err := alarmObject.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &strategyDefList)
  82. if err != nil {
  83. logger.Logger.Error(err)
  84. }
  85. logger.Logger.Println(fmt.Sprintf("====初始化告警策略:%+v", strategyDefList))
  86. strategyDefListLock.Unlock()
  87. }
  88. //从告警策略列表中根据测点名称查找定义的策略。返回该策略下定义的所有规则
  89. func (t *AlarmService) FindstrategyDefByAttrname(deviceid int64, attrname string) map[int64][]AlarmRelation {
  90. strategyDefListLock.Lock()
  91. result := map[int64][]AlarmRelation{}
  92. strategyids := map[int64]string{}
  93. //根据属性名获取包含该属性的策略ID
  94. for _, row := range strategyDefList {
  95. if row.Attrname == attrname && row.Deviceid == deviceid {
  96. strategyids[row.Strategyid] = "1"
  97. }
  98. }
  99. if len(strategyids) > 0 {
  100. for id, _ := range strategyids {
  101. //获取该策略下的所有规则列表
  102. tmpLst := []AlarmRelation{}
  103. for _, row := range strategyDefList {
  104. if row.Strategyid == id {
  105. tmpLst = append(tmpLst, row)
  106. }
  107. }
  108. result[id] = tmpLst
  109. }
  110. }
  111. strategyDefListLock.Unlock()
  112. return result
  113. }
  114. //告警策略列表
  115. func (t *AlarmService) AlarmList(levle, pageIndex, pageSize int, name string) (map[string]interface{}, error) {
  116. l := logic.NewAlarmStrategyLogic()
  117. var list []Alarm_List
  118. 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 "
  119. totalSql := "select count(1) recordcount from alarm_strategy a inner join sys_app b on a.appid=b.appid "
  120. var sqlCondition []string
  121. sqlCondition = append(sqlCondition, fmt.Sprintf("a.appid=%s", RtelecManageApp().RegAppID))
  122. if name != "" {
  123. sqlCondition = append(sqlCondition, fmt.Sprintf("strategyname like '%%%s%%'", name))
  124. }
  125. if levle > 0 {
  126. sqlCondition = append(sqlCondition, fmt.Sprintf("alarmlevel=%d", levle))
  127. }
  128. if len(sqlCondition) > 0 {
  129. sqlCommandText += " where " + strings.Join(sqlCondition, " and ")
  130. totalSql += " where " + strings.Join(sqlCondition, " and ")
  131. }
  132. sqlCommandText += fmt.Sprintf(" order by id desc limit %d,%d", (pageIndex-1)*pageSize, pageSize)
  133. err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &list)
  134. var total Alarm_Total
  135. if err == nil {
  136. l.SvcCtx.AlarmStrategy.Base.Raw(totalSql, &total)
  137. }
  138. return map[string]interface{}{"list": list, "total": total.Recordcount}, err
  139. }
  140. //告警数据列表列表
  141. func (t *AlarmService) AlarmDataList(appId, startDate, endDate int, area string, alarmType, alarmLevel, pageIndex, pageSize int) (map[string]interface{}, error) {
  142. l := logic.NewAlarmStrategyLogic()
  143. type AlarmData struct {
  144. Id int `json:"id"`
  145. Eventid int64 `json:"eventid,string"`
  146. Eventdesc string `json:"eventdesc"`
  147. Eventtype string `json:"eventtype"`
  148. Alarmdate string `json:"alarmdate"`
  149. Confirm string `json:"confirm"`
  150. Level string `json:"level"`
  151. Confirmtime string `json:"confirmtime"`
  152. Result string `json:"result"`
  153. Create_at string `json:"create_at"`
  154. Zonename string `json:"zonename"`
  155. }
  156. 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," +
  157. " case b.alarmlevel when 1 then '预警' when 2 then '一般' when 3 then '严重' when 4 then '危急' end level,c.zonename " +
  158. 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)
  159. //查询条件结果会重复
  160. 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)
  161. var sqlCondition []string
  162. if area != "" {
  163. sqlCondition = append(sqlCondition, fmt.Sprintf("c.zonename like '%%%s%%'", area))
  164. }
  165. if alarmLevel > 0 {
  166. sqlCondition = append(sqlCondition, fmt.Sprintf("b.alarmlevel=%d", alarmLevel))
  167. }
  168. if alarmType > 0 {
  169. sqlCondition = append(sqlCondition, fmt.Sprintf("eventtype=%d", alarmType))
  170. }
  171. if startDate > 0 && endDate > 0 {
  172. sqlCondition = append(sqlCondition, fmt.Sprintf("timestamp between %d and %d", startDate, endDate))
  173. } else if startDate > 0 {
  174. sqlCondition = append(sqlCondition, fmt.Sprintf("timestamp>=%d", startDate))
  175. } else if endDate > 0 {
  176. sqlCondition = append(sqlCondition, fmt.Sprintf("timestamp<=%d", endDate))
  177. }
  178. if len(sqlCondition) > 0 {
  179. sqlCommandText += " where " + strings.Join(sqlCondition, " and ")
  180. totalSql += " where " + strings.Join(sqlCondition, " and ")
  181. }
  182. sqlCommandText += fmt.Sprintf(" order by a.id desc limit %d,%d", (pageIndex-1)*pageSize, pageSize)
  183. var list []AlarmData
  184. err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &list)
  185. var total Alarm_Total
  186. if err == nil {
  187. l.SvcCtx.AlarmStrategy.Base.Raw(totalSql, &total)
  188. }
  189. if len(list) == 0 {
  190. return map[string]interface{}{"list": []interface{}{}, "total": total.Recordcount}, err
  191. } else {
  192. return map[string]interface{}{"list": list, "total": total.Recordcount}, err
  193. }
  194. }
  195. //首页异常设备
  196. func (t *AlarmService) AlarmHome(modelid string, limit int) (interface{}, error) {
  197. if limit == 0 {
  198. limit = 50
  199. }
  200. var sqlCommandText string
  201. l := logic.NewAlarmStrategyLogic()
  202. type AlarmData struct {
  203. Eventid int64 `json:"eventid,string"`
  204. Alarmdata string `json:"alarmdata"`
  205. Zonename string `json:"zonename"`
  206. Positionname string `json:"positionname"`
  207. Devicename string `json:"devicename"`
  208. Mpname string `json:"mpname"`
  209. Eventdesc string `json:"eventdesc"`
  210. }
  211. appid := RtelecManageApp().RegAppID
  212. if len(modelid) > 0 {
  213. 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 " +
  214. "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 " +
  215. 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)
  216. } else {
  217. 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 " +
  218. "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 " +
  219. 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)
  220. }
  221. sqlCommandText += fmt.Sprintf(" order by timestamp desc limit %d", limit)
  222. var list []AlarmData
  223. err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &list)
  224. return list, err
  225. }
  226. //添加或修改策略信息
  227. func (t *AlarmService) EditAlarm(parameter *dto.AddAlarmStrategyRes, relationData []map[string]interface{}) error {
  228. l := logic.NewAlarmStrategyLogic()
  229. var isAdd = false
  230. if parameter.Strategyid == 0 {
  231. isAdd = true
  232. parameter.Strategyid = new(logic.ToolsLogic).GetOnlyId(int64(parameter.Appid))
  233. }
  234. count, err := t.CheckAlarmName(parameter.Strategyname, parameter.Appid)
  235. if isAdd {
  236. if err == nil && count > 0 {
  237. return errors.New(fmt.Sprintf("已存在策略名称(%s)", parameter.Strategyname))
  238. }
  239. } else {
  240. if err == nil && count > 1 {
  241. return errors.New(fmt.Sprintf("已存在策略名称(%s)", parameter.Strategyname))
  242. }
  243. }
  244. //判断是否有测点关联
  245. if len(relationData) > 0 {
  246. var Relations []*model.AlarmRelation
  247. for _, row := range relationData {
  248. var RelationField model.AlarmRelation
  249. relaceId := tools.IsEmpty(row["id"])
  250. if relaceId == "" {
  251. RelationField.ID = 0
  252. } else {
  253. relationid, _ := strconv.Atoi(relaceId)
  254. RelationField.ID = int32(relationid)
  255. }
  256. RelationField.Alarmtype = int32(row["alarmtype"].(float64))
  257. RelationField.Strategyid = parameter.Strategyid
  258. RelationField.Mpid, _ = strconv.ParseInt(row["mpid"].(string), 10, 64)
  259. if row["uplimit"] != nil {
  260. RelationField.Uplimit = row["uplimit"].(float64)
  261. RelationField.Dnlimit = row["dnlimit"].(float64)
  262. }
  263. if row["dio"] != nil {
  264. RelationField.Dio = int32(row["dio"].(float64))
  265. }
  266. if row["diffvalue"] != nil {
  267. RelationField.Diffvalue = row["diffvalue"].(float64)
  268. }
  269. RelationField.Relation = int32(row["relation"].(float64))
  270. Relations = append(Relations, &RelationField)
  271. }
  272. parameter.Relation = Relations
  273. }
  274. var edit_err error
  275. if isAdd {
  276. edit_err = l.AddAlarmStrategy(parameter)
  277. if edit_err == nil {
  278. new(LogService).SaveLog(fmt.Sprintf("创建告警策略[%s]成功", parameter.Strategyname))
  279. }
  280. } else {
  281. edit_err = l.ModifyAlarmStrategy(parameter)
  282. if edit_err == nil {
  283. new(LogService).SaveLog(fmt.Sprintf("编辑告警策略[%s]成功", parameter.Strategyname))
  284. }
  285. }
  286. if edit_err == nil {
  287. go t.ReloadAlarmList()
  288. } else {
  289. new(LogService).SaveLog(fmt.Sprintf("告警策略[%s]操作失败:%s", parameter.Strategyname, edit_err.Error()))
  290. }
  291. return edit_err
  292. }
  293. func (t *AlarmService) DeleteAlarm(strategyId int64) error {
  294. l := logic.NewAlarmEventLogic()
  295. do := l.SvcCtx.AlarmEvent
  296. _, err := do.Where(do.Strategyid.Eq(strategyId)).Delete()
  297. if err != nil {
  298. new(LogService).SaveLog(fmt.Sprintf("删除告警策略[策略ID:%d]失败:%s", strategyId, err.Error()))
  299. logger.Logger.Error(err)
  300. return err
  301. }
  302. l1 := logic.NewAlarmStrategyLogic()
  303. err = l1.DelAlarmStrategy(strategyId)
  304. if err != nil {
  305. new(LogService).SaveLog(fmt.Sprintf("删除告警策略[策略ID:%d]失败:%s", strategyId, err.Error()))
  306. logger.Logger.Error(err)
  307. return err
  308. }
  309. new(LogService).SaveLog(fmt.Sprintf("删除告警策略[策略ID:%d]成功", strategyId))
  310. go t.ReloadAlarmList()
  311. return err
  312. }
  313. //判断是否已存在条件
  314. func (t *AlarmService) CheckAlarmName(name string, appId int32) (int64, error) {
  315. var parameter dto.GetAlarmStrategyReq
  316. parameter.AppId = appId
  317. parameter.StrategyName = name
  318. l := logic.NewAlarmStrategyLogic()
  319. return l.GetAlarmStrategyCount(&parameter)
  320. }
  321. //告警数据列表列表
  322. func (t *AlarmService) AlarmConfirm(Id int32, eventid int64, content string) error {
  323. l := logic.NewAlarmEventLogic()
  324. err := l.SetAlarmEvent(Id, time.Now(), content)
  325. context := fmt.Sprintf("告警事件Id(%d),确认告警内容(%s)", Id, content)
  326. if err == nil {
  327. o := orm.NewOrm()
  328. o.Raw("update alarm_his set confirm=2,confirmtime=now(),result=? where eventid=?", content, eventid).Exec()
  329. new(LogService).SaveLog("确定告警事件成功!参数值:" + string(context))
  330. } else {
  331. new(LogService).SaveLog("确定告警事件失败!参数值:" + string(context) + ",失败原因:" + err.Error())
  332. }
  333. return err
  334. }
  335. //告警策略详细
  336. func (t *AlarmService) AlarmDetail(strategyId int64) (interface{}, error) {
  337. l := logic.NewAlarmStrategyLogic()
  338. type AlarmBasic struct {
  339. Id int `json:"id"`
  340. Strategyid int64 `json:"strategyid,string"`
  341. Appid int `json:"appid"`
  342. Strategyname string `json:"strategyname"`
  343. Alarmlevel string `json:"alarmlevel"`
  344. }
  345. var basic AlarmBasic
  346. var sqlCommandText = fmt.Sprintf("select * from alarm_strategy where strategyid=%d", strategyId)
  347. err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &basic)
  348. type relaction struct {
  349. Id int `json:"id"`
  350. Strategyid int64 `json:"strategyid,string"`
  351. Mpid int64 `json:"mpid,string"`
  352. Mpname string `json:"mpname"`
  353. Alarmtype int `json:"alarmtype"`
  354. Uplimit float64 `json:"uplimit"`
  355. Dnlimit float64 `json:"dnlimit"`
  356. Dio int `json:"dio"`
  357. Diffvalue float64 `json:"diffvalue"`
  358. Relation int `json:"relation"`
  359. CreateAt string `json:"create_at"`
  360. CpdateAt string `json:"cpdate_at"`
  361. }
  362. var detail []relaction
  363. sqlCommandText = fmt.Sprintf("select a.*,b.mpname from alarm_relation a,dev_mpinfo b where a.mpid=b.mpid and a.strategyid=%d", strategyId)
  364. //fmt.Println("==========sql====", sqlCommandText)
  365. if err == nil {
  366. _ = l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &detail)
  367. }
  368. return map[string]interface{}{"basic": basic, "detail": detail}, err
  369. }
  370. func (t *AlarmService) Search(deviceId int, attrName string) ([]AlarmRelation, error) {
  371. alarmObject := logic.NewAlarmStrategyLogic()
  372. var Relation []AlarmRelation
  373. var sqlCommandText = "select alarmlevel,b.mpid,alarmtype,uplimit,dnlimit,dio,diffvalue,relation,b.strategyid,c.attrname,c.deviceid,c.positionname " +
  374. 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)
  375. //log.Println(sqlCommandText)
  376. err := alarmObject.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &Relation)
  377. if err != nil {
  378. logger.Logger.Error(err)
  379. }
  380. return Relation, err
  381. }
  382. //处理告警事件表
  383. func (t *AlarmService) HandleAlarmEvent(field *HistoryService) {
  384. alramSettingService := AlarmSettingService{}
  385. alarmTacticsService := AlarmTactics{}
  386. alarmInfoService := AlarmInfoService{}
  387. var deviceId = int64(field.Model.Deviceid)
  388. var devicename = field.Model.Devicename
  389. var receivTime = field.Model.Date
  390. //log.Println(fmt.Sprintf("接收到新状态值:%v", field))
  391. //mpid, err := strconv.ParseInt(fmt.Sprint(field.Model.Mpid), 10, 64)
  392. for attrName, attrValue := range field.AttrInfo {
  393. // 设备返回来的数据
  394. // 需要根据attrname去获取mpid
  395. mpinfo := new(DeviceService).DeviceMpInfo(int32(deviceId))
  396. row := mpinfo[attrName]
  397. if len(row) == 0 || len(attrName) == 0 {
  398. continue
  399. }
  400. mpid, err := strconv.ParseInt(tools.IsEmpty(row["mpid"]), 10, 64)
  401. if err != nil {
  402. logger.Logger.Error(err, fmt.Sprintf("*******mpid 转化出错 is:%s.", err.Error()))
  403. }
  404. curValue, err := strconv.ParseFloat(fmt.Sprint(attrValue), 64)
  405. if err != nil {
  406. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  407. curValue, _ = strconv.ParseFloat(global.NullNumber, 64)
  408. }
  409. // 如果报警的测点在黑名单中则不处理
  410. flag := alramSettingService.MpInBlackList(deviceId, mpid)
  411. if flag {
  412. return
  413. }
  414. // 首先判断这个设备的这个测点是否有绝对值告警策略,如果有则判断是否满足告警条件,如果满足告警条件则写入告警历史表t_base_alarm_his
  415. // 先获取当前设备当前测点的独立配置信息,如果没有独立配置信息则使用标准的告警策略
  416. // 先读取绝对值告警独立配置
  417. aloneAbss := alarmTacticsService.GetAloneAttrAbs(deviceId, mpid)
  418. if len(aloneAbss) > 0 {
  419. for _, abs := range aloneAbss {
  420. // 检查告警是否是当前测点的持续的告警,持续告警不做处理
  421. flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 1)
  422. if err != nil {
  423. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  424. }
  425. if flag {
  426. return
  427. }
  428. // 获取当前点的数值
  429. value, err := strconv.ParseFloat(fmt.Sprint(abs["threshold"]), 64)
  430. if err != nil {
  431. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  432. return
  433. }
  434. f := fmt.Sprint(abs["operation_symbol"])
  435. var alarmObj models.T_base_alarm_his
  436. alarmDesc := fmt.Sprintf("触发绝对值告警规则【%s】,", abs["strategy_name"])
  437. alarm_type := 1
  438. strategyid, err := strconv.ParseInt(fmt.Sprint(abs["alarm_id"]), 10, 64)
  439. alarm_level, err := strconv.ParseInt(fmt.Sprint(abs["alarm_level"]), 10, 64)
  440. alarmObj.Alarm_type = alarm_type
  441. alarmObj.Alarm_level = int(alarm_level)
  442. alarmObj.Deviceid = deviceId
  443. alarmObj.Devicename = devicename
  444. alarmObj.Confirm = 0
  445. alarmObj.Confirmtime = ""
  446. alarmObj.Mpid = mpid
  447. alarmObj.Mpname = tools.IsEmpty(row["mpname"])
  448. alarmObj.Is_reset = 0
  449. alarmObj.Strategyid = strategyid
  450. alarmObj.Alarm_value = float32(curValue)
  451. alarmObj.Create_at = tools.NowTime()
  452. switch f {
  453. case "=":
  454. if curValue == value {
  455. // 添加一条报警记录
  456. alarmDesc += fmt.Sprintf("采集值%s阈值【%f】", f, value)
  457. alarmObj.Alarm_desc = alarmDesc
  458. newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
  459. if err != nil {
  460. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  461. return
  462. }
  463. t.sendWSMessage("alarm", newid, alarmObj)
  464. }
  465. case "<":
  466. if curValue <= value {
  467. // 添加一条报警记录
  468. alarmDesc += fmt.Sprintf("采集值%s阈值【%f】", f, value)
  469. alarmObj.Alarm_desc = alarmDesc
  470. newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
  471. if err != nil {
  472. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  473. return
  474. }
  475. t.sendWSMessage("alarm", newid, alarmObj)
  476. }
  477. case ">":
  478. if curValue >= value {
  479. // 添加一条报警记录
  480. alarmDesc += fmt.Sprintf("采集值%s阈值【%f】", f, value)
  481. alarmObj.Alarm_desc = alarmDesc
  482. newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
  483. if err != nil {
  484. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  485. return
  486. }
  487. t.sendWSMessage("alarm", newid, alarmObj)
  488. }
  489. case "!=":
  490. if curValue != value {
  491. // 添加一条报警记录
  492. alarmDesc += fmt.Sprintf("采集值%s阈值【%f】", f, value)
  493. alarmObj.Alarm_desc = alarmDesc
  494. newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
  495. if err != nil {
  496. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  497. return
  498. }
  499. t.sendWSMessage("alarm", newid, alarmObj)
  500. }
  501. }
  502. // 如果都没有触发告警规则,那进行复归操作
  503. // 复归操作首先查询告警历史表中相同设备相同测点,状态为未复归的记录
  504. // 再设置复归状态为“复归”
  505. flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 1)
  506. if err != nil {
  507. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  508. return
  509. }
  510. if flag {
  511. //开始复归操作
  512. o := orm.NewOrm()
  513. updid := int64(0)
  514. hasRow := []orm.Params{}
  515. o.Raw("select id from t_base_alarm_his where alarm_type=1 and deviceid=? and mpid=?", deviceId, mpid).Values(&hasRow)
  516. if len(hasRow) > 0 {
  517. updid, _ = strconv.ParseInt(tools.IsEmpty(hasRow[0]["id"]), 10, 64)
  518. } else {
  519. return
  520. }
  521. var resetSql = "update t_base_alarm_his set is_reset=1 where id=?"
  522. res, err := o.Raw(resetSql, updid).Exec()
  523. if err != nil {
  524. logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", resetSql, []interface{}{updid}))
  525. new(bo.SystemLog).Fail(enum.AuditType_alarmdata,
  526. enum.LogType_Update,
  527. enum.OptEventType_Bus,
  528. enum.OptEventLevel_Hight,
  529. fmt.Sprintf("复归告警信息失败:%s,deviceId:%s,mpid:%s", err.Error(), deviceId, mpid),
  530. map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
  531. )
  532. } else {
  533. num, _ := res.RowsAffected()
  534. if num > 0 {
  535. //推送复归信息到前端
  536. t.sendWSMessage("reset", updid, models.T_base_alarm_his{
  537. Deviceid: deviceId,
  538. Mpid: mpid,
  539. Is_reset: 1,
  540. })
  541. new(bo.SystemLog).Success(enum.AuditType_alarmdata,
  542. enum.LogType_Update,
  543. enum.OptEventType_Bus,
  544. enum.OptEventLevel_Hight,
  545. fmt.Sprintf("复归告警信息成功,deviceId:%s,mpid:%s", deviceId, mpid),
  546. map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
  547. )
  548. }
  549. }
  550. }
  551. }
  552. } else {
  553. abss := alarmTacticsService.GetAttrAbs(attrName)
  554. // 如果有多个绝对值告警
  555. if len(abss) > 0 {
  556. for _, abs := range abss {
  557. // 检查告警是否是当前测点的持续的告警,持续告警不做处理
  558. flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 1)
  559. if err != nil {
  560. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  561. }
  562. if flag {
  563. return
  564. }
  565. value, err := strconv.ParseFloat(fmt.Sprint(abs["threshold"]), 64)
  566. if err != nil {
  567. logger.Logger.Error(err)
  568. logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
  569. return
  570. }
  571. f := fmt.Sprint(abs["operation_symbol"])
  572. var alarmObj models.T_base_alarm_his
  573. alarmDesc := fmt.Sprintf("触发绝对值告警规则【%s】,", abs["strategy_name"])
  574. alarm_type := 1
  575. strategyid, err := strconv.ParseInt(fmt.Sprint(abs["id"]), 10, 64)
  576. alarm_level, err := strconv.ParseInt(fmt.Sprint(abs["alarm_level"]), 10, 64)
  577. alarmObj.Alarm_type = alarm_type
  578. alarmObj.Alarm_level = int(alarm_level)
  579. alarmObj.Deviceid = deviceId
  580. alarmObj.Devicename = devicename
  581. alarmObj.Confirm = 0
  582. alarmObj.Confirmtime = ""
  583. alarmObj.Mpid = mpid
  584. alarmObj.Mpname = tools.IsEmpty(row["mpname"])
  585. alarmObj.Is_reset = 0
  586. alarmObj.Strategyid = strategyid
  587. alarmObj.Alarm_value = float32(curValue)
  588. alarmObj.Create_at = tools.NowTime()
  589. switch f {
  590. case "=":
  591. if curValue == value {
  592. // 添加一条报警记录
  593. alarmDesc += fmt.Sprintf("采集值%s阈值【%f】", f, value)
  594. alarmObj.Alarm_desc = alarmDesc
  595. newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
  596. if err != nil {
  597. logger.Logger.Error(err)
  598. logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
  599. return
  600. }
  601. t.sendWSMessage("alarm", newid, alarmObj)
  602. }
  603. case "<":
  604. if curValue <= value {
  605. // 添加一条报警记录
  606. alarmDesc += fmt.Sprintf("采集值%s阈值【%f】", f, value)
  607. alarmObj.Alarm_desc = alarmDesc
  608. newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
  609. if err != nil {
  610. logger.Logger.Error(err)
  611. logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
  612. return
  613. }
  614. t.sendWSMessage("alarm", newid, alarmObj)
  615. }
  616. case ">":
  617. if curValue >= value {
  618. // 添加一条报警记录
  619. alarmDesc += fmt.Sprintf("采集值%s阈值【%f】", f, value)
  620. alarmObj.Alarm_desc = alarmDesc
  621. newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
  622. if err != nil {
  623. logger.Logger.Error(err)
  624. logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
  625. return
  626. }
  627. t.sendWSMessage("alarm", newid, alarmObj)
  628. }
  629. case "!=":
  630. if curValue != value {
  631. // 添加一条报警记录
  632. alarmDesc += fmt.Sprintf("采集值%s阈值【%f】", f, value)
  633. alarmObj.Alarm_desc = alarmDesc
  634. newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
  635. if err != nil {
  636. logger.Logger.Error(err)
  637. logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
  638. return
  639. }
  640. t.sendWSMessage("alarm", newid, alarmObj)
  641. }
  642. }
  643. // 如果都没有触发告警规则,那进行复归操作
  644. // 复归操作首先查询告警历史表中相同设备相同测点,状态为未复归的记录
  645. // 再设置复归状态为“复归”
  646. flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 1)
  647. if err != nil {
  648. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  649. return
  650. }
  651. if flag {
  652. //开始复归操作
  653. o := orm.NewOrm()
  654. updid := int64(0)
  655. hasRow := []orm.Params{}
  656. o.Raw("select id from t_base_alarm_his where alarm_type=1 and deviceid=? and mpid=?", deviceId, mpid).Values(&hasRow)
  657. if len(hasRow) > 0 {
  658. updid, _ = strconv.ParseInt(tools.IsEmpty(hasRow[0]["id"]), 10, 64)
  659. } else {
  660. return
  661. }
  662. var resetSql = "update t_base_alarm_his set is_reset=1 where id=?"
  663. res, err := o.Raw(resetSql, updid).Exec()
  664. if err != nil {
  665. logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", resetSql, []interface{}{updid}))
  666. new(bo.SystemLog).Fail(enum.AuditType_alarmdata,
  667. enum.LogType_Update,
  668. enum.OptEventType_Bus,
  669. enum.OptEventLevel_Hight,
  670. fmt.Sprintf("复归告警信息失败:%s,deviceId:%s,mpid:%s", err.Error(), deviceId, mpid),
  671. map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
  672. )
  673. } else {
  674. num, _ := res.RowsAffected()
  675. if num > 0 {
  676. //推送复归信息到前端
  677. t.sendWSMessage("reset", updid, models.T_base_alarm_his{
  678. Deviceid: deviceId,
  679. Mpid: mpid,
  680. Is_reset: 1,
  681. })
  682. new(bo.SystemLog).Success(enum.AuditType_alarmdata,
  683. enum.LogType_Update,
  684. enum.OptEventType_Bus,
  685. enum.OptEventLevel_Hight,
  686. fmt.Sprintf("复归告警信息成功,deviceId:%s,mpid:%s", deviceId, mpid),
  687. map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
  688. )
  689. }
  690. }
  691. }
  692. }
  693. }
  694. }
  695. // 第二判断这个设备的这个测点是否有升温告警策略,如果有则判断是否满足告警条件,如果满足告警条件则写入告警历史表t_base_alarm_his
  696. // 先读取升温告警独立配置
  697. aloneRises := alarmTacticsService.GetAloneAttrRise(deviceId, mpid)
  698. if len(aloneRises) > 0 {
  699. for _, rise := range aloneRises {
  700. // 检查告警是否是当前测点的持续的告警,持续告警不做处理
  701. flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 2)
  702. if err != nil {
  703. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  704. }
  705. if flag {
  706. return
  707. }
  708. // 配置里面的值
  709. value, err := strconv.ParseFloat(fmt.Sprint(rise["scope"]), 64)
  710. if err != nil {
  711. logger.Logger.Error(err)
  712. logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
  713. return
  714. }
  715. upcycle, err := strconv.ParseInt(tools.IsEmpty(rise["upcycle"]), 10, 64)
  716. var alarmObj models.T_base_alarm_his
  717. alarmDesc := fmt.Sprintf("触发升温告警规则【%s】,", rise["strategy_name"])
  718. alarm_type := 2
  719. strategyid, err := strconv.ParseInt(fmt.Sprint(rise["alarm_id"]), 10, 64)
  720. if err != nil {
  721. logger.Logger.Error(err)
  722. logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
  723. return
  724. }
  725. alarm_level, err := strconv.ParseInt(fmt.Sprint(rise["alarm_level"]), 10, 64)
  726. if err != nil {
  727. logger.Logger.Error(err)
  728. logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
  729. return
  730. }
  731. alarmObj.Alarm_type = alarm_type
  732. alarmObj.Alarm_level = int(alarm_level)
  733. alarmObj.Deviceid = deviceId
  734. alarmObj.Devicename = devicename
  735. alarmObj.Confirm = 0
  736. alarmObj.Confirmtime = ""
  737. alarmObj.Mpid = mpid
  738. alarmObj.Mpname = tools.IsEmpty(row["mpname"])
  739. alarmObj.Is_reset = 0
  740. alarmObj.Strategyid = strategyid
  741. alarmObj.Alarm_value = float32(curValue)
  742. alarmObj.Alarm_desc = alarmDesc
  743. // 上升周期(分钟)内,温度升高超过温升范围,则需要报警
  744. // 需要读取当前测点最后一条数据推送记录进行对比
  745. nearBy, err := alarmInfoService.GetNearByUpcycle(deviceId, attrName, int(upcycle), receivTime)
  746. if err != nil {
  747. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  748. return
  749. }
  750. if nearBy != nil {
  751. // curValue数据返回的值,value配置中的上升范围
  752. nearItem, err := strconv.ParseFloat(fmt.Sprint(nearBy[attrName]), 64) // 历史数据中最接近现在的一条数据
  753. if err != nil {
  754. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  755. return
  756. }
  757. //如果当前的数据大于等于周期之前的数据值+设置的范围值,则认为超出了范围,需要报警
  758. if curValue >= (value + nearItem) {
  759. newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
  760. if err != nil {
  761. logger.Logger.Error(err)
  762. logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
  763. return
  764. }
  765. t.sendWSMessage("alarm", newid, alarmObj)
  766. }
  767. }
  768. }
  769. // 如果都没有触发告警规则,那进行复归操作
  770. // 复归操作首先查询告警历史表中相同设备相同测点,状态为未复归的记录
  771. // 再设置复归状态为“复归”
  772. flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 2)
  773. if err != nil {
  774. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  775. return
  776. }
  777. if flag {
  778. //开始复归操作
  779. o := orm.NewOrm()
  780. updid := int64(0)
  781. hasRow := []orm.Params{}
  782. o.Raw("select id from t_base_alarm_his where alarm_type=2 and deviceid=? and mpid=?", deviceId, mpid).Values(&hasRow)
  783. if len(hasRow) > 0 {
  784. updid, _ = strconv.ParseInt(tools.IsEmpty(hasRow[0]["id"]), 10, 64)
  785. } else {
  786. return
  787. }
  788. var resetSql = "update t_base_alarm_his set is_reset=1 where id=?"
  789. res, err := o.Raw(resetSql, updid).Exec()
  790. if err != nil {
  791. logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", resetSql, []interface{}{updid}))
  792. new(bo.SystemLog).Fail(enum.AuditType_alarmdata,
  793. enum.LogType_Update,
  794. enum.OptEventType_Bus,
  795. enum.OptEventLevel_Hight,
  796. fmt.Sprintf("复归告警信息失败:%s,deviceId:%s,mpid:%s", err.Error(), deviceId, mpid),
  797. map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
  798. )
  799. } else {
  800. num, _ := res.RowsAffected()
  801. if num > 0 {
  802. //推送复归信息到前端
  803. t.sendWSMessage("reset", updid, models.T_base_alarm_his{
  804. Deviceid: deviceId,
  805. Mpid: mpid,
  806. Is_reset: 1,
  807. })
  808. new(bo.SystemLog).Success(enum.AuditType_alarmdata,
  809. enum.LogType_Update,
  810. enum.OptEventType_Bus,
  811. enum.OptEventLevel_Hight,
  812. fmt.Sprintf("复归告警信息成功,deviceId:%s,mpid:%s", deviceId, mpid),
  813. map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
  814. )
  815. }
  816. }
  817. }
  818. } else {
  819. // 没有独立的配置则读取标准配置
  820. rises := alarmTacticsService.GetAttrRise(attrName)
  821. if len(rises) > 0 {
  822. for _, rise := range rises {
  823. // 检查告警是否是当前测点的持续的告警,持续告警不做处理
  824. flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 2)
  825. if err != nil {
  826. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  827. }
  828. if flag {
  829. return
  830. }
  831. value, err := strconv.ParseFloat(fmt.Sprint(rise["scope"]), 64)
  832. if err != nil {
  833. logger.Logger.Error(err)
  834. logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
  835. return
  836. }
  837. upcycle, err := strconv.ParseInt(tools.IsEmpty(rise["upcycle"]), 10, 64)
  838. var alarmObj models.T_base_alarm_his
  839. alarmDesc := fmt.Sprintf("触发升温告警规则【%s】,", rise["strategy_name"])
  840. alarm_type := 2
  841. strategyid, err := strconv.ParseInt(fmt.Sprint(rise["id"]), 10, 64)
  842. if err != nil {
  843. logger.Logger.Error(err)
  844. logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
  845. return
  846. }
  847. alarm_level, err := strconv.ParseInt(fmt.Sprint(rise["alarm_level"]), 10, 64)
  848. if err != nil {
  849. logger.Logger.Error(err)
  850. logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
  851. return
  852. }
  853. alarmObj.Alarm_type = alarm_type
  854. alarmObj.Alarm_level = int(alarm_level)
  855. alarmObj.Deviceid = deviceId
  856. alarmObj.Devicename = devicename
  857. alarmObj.Confirm = 0
  858. alarmObj.Confirmtime = ""
  859. alarmObj.Mpid = mpid
  860. alarmObj.Mpname = tools.IsEmpty(row["mpname"])
  861. alarmObj.Is_reset = 0
  862. alarmObj.Strategyid = strategyid
  863. alarmObj.Alarm_value = float32(curValue)
  864. alarmObj.Alarm_desc = alarmDesc
  865. alarmObj.Create_at = tools.NowTime()
  866. // 上升周期(分钟)内,温度升高超过温升范围,则需要报警
  867. // 需要读取当前测点上升周期的最后一条数据推送记录进行对比
  868. nearBy, err := alarmInfoService.GetNearByUpcycle(deviceId, attrName, int(upcycle), receivTime)
  869. if err != nil {
  870. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  871. return
  872. }
  873. if nearBy != nil {
  874. // curValue数据返回的值,value配置中的上升范围
  875. nearItem, err := strconv.ParseFloat(fmt.Sprint(nearBy[attrName]), 64) // 历史数据中最接近现在的一条数据
  876. if err != nil {
  877. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  878. return
  879. }
  880. //如果当前的数据大于等于周期之前的数据值+设置的范围值,则认为超出了范围,需要报警
  881. if curValue >= (value + nearItem) {
  882. newid, err := alarmInfoService.InsertAlarmInfo(alarmObj)
  883. if err != nil {
  884. logger.Logger.Error(err)
  885. logger.Logger.Println(fmt.Sprintf("****************Error is:%s.", err.Error()))
  886. return
  887. }
  888. t.sendWSMessage("alarm", newid, alarmObj)
  889. }
  890. }
  891. }
  892. // 如果都没有触发告警规则,那进行复归操作
  893. // 复归操作首先查询告警历史表中相同设备相同测点,状态为未复归的记录
  894. // 再设置复归状态为“复归”
  895. flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 2)
  896. if err != nil {
  897. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  898. return
  899. }
  900. if flag {
  901. //开始复归操作
  902. o := orm.NewOrm()
  903. updid := int64(0)
  904. hasRow := []orm.Params{}
  905. o.Raw("select id from t_base_alarm_his where alarm_type=2 and deviceid=? and mpid=?", deviceId, mpid).Values(&hasRow)
  906. if len(hasRow) > 0 {
  907. updid, _ = strconv.ParseInt(tools.IsEmpty(hasRow[0]["id"]), 10, 64)
  908. } else {
  909. return
  910. }
  911. var resetSql = "update t_base_alarm_his set is_reset=1 where id=?"
  912. res, err := o.Raw(resetSql, updid).Exec()
  913. if err != nil {
  914. logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", resetSql, []interface{}{updid}))
  915. new(bo.SystemLog).Fail(enum.AuditType_alarmdata,
  916. enum.LogType_Update,
  917. enum.OptEventType_Bus,
  918. enum.OptEventLevel_Hight,
  919. fmt.Sprintf("复归告警信息失败:%s,deviceId:%s,mpid:%s", err.Error(), deviceId, mpid),
  920. map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
  921. )
  922. } else {
  923. num, _ := res.RowsAffected()
  924. if num > 0 {
  925. //推送复归信息到前端
  926. t.sendWSMessage("reset", updid, models.T_base_alarm_his{
  927. Deviceid: deviceId,
  928. Mpid: mpid,
  929. Is_reset: 1,
  930. })
  931. new(bo.SystemLog).Success(enum.AuditType_alarmdata,
  932. enum.LogType_Update,
  933. enum.OptEventType_Bus,
  934. enum.OptEventLevel_Hight,
  935. fmt.Sprintf("复归告警信息成功,deviceId:%s,mpid:%s", deviceId, mpid),
  936. map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
  937. )
  938. }
  939. }
  940. }
  941. }
  942. }
  943. // 第三判断是否在分组里面
  944. flag, err = new(MpinfoService).MpidInGroup(mpid)
  945. if err != nil {
  946. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  947. return
  948. }
  949. // 如果在分组里面需要根据deviceid把所有分组找出来
  950. if flag {
  951. // 检查告警是否是当前测点的持续的告警,持续告警不做处理
  952. flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 3)
  953. if err != nil {
  954. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  955. }
  956. if flag {
  957. return
  958. }
  959. var alarmObj models.T_base_alarm_his
  960. alarmObj.Alarm_type = 3
  961. alarmObj.Deviceid = deviceId
  962. alarmObj.Devicename = devicename
  963. alarmObj.Confirm = 0
  964. alarmObj.Confirmtime = ""
  965. alarmObj.Is_reset = 0
  966. alarmObj.Alarm_value = float32(curValue)
  967. alarmObj.Create_at = tools.NowTime()
  968. groupList, err := new(MpinfoService).GroupList(int32(deviceId))
  969. if err != nil {
  970. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  971. return
  972. }
  973. for _, row := range groupList {
  974. groupid, err := strconv.ParseInt(tools.IsEmpty(row["groupid"]), 10, 64)
  975. if err != nil {
  976. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  977. return
  978. }
  979. t.HandleAlarmUnbalance(groupid, alarmObj, field.AttrInfo)
  980. }
  981. // 如果都没有触发告警规则,那进行复归操作
  982. // 复归操作首先查询告警历史表中相同设备相同测点,状态为未复归的记录
  983. // 再设置复归状态为“复归”
  984. flag, err = alarmInfoService.IsExsitInAlarmHis(deviceId, mpid, 3)
  985. if err != nil {
  986. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  987. return
  988. }
  989. if flag {
  990. //开始复归操作
  991. o := orm.NewOrm()
  992. updid := int64(0)
  993. hasRow := []orm.Params{}
  994. o.Raw("select id from t_base_alarm_his where alarm_type=3 and deviceid=? and mpid=?", deviceId, mpid).Values(&hasRow)
  995. if len(hasRow) > 0 {
  996. updid, _ = strconv.ParseInt(tools.IsEmpty(hasRow[0]["id"]), 10, 64)
  997. } else {
  998. return
  999. }
  1000. var resetSql = "update t_base_alarm_his set is_reset=1 where id=?"
  1001. res, err := o.Raw(resetSql, updid).Exec()
  1002. if err != nil {
  1003. logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", resetSql, []interface{}{updid}))
  1004. new(bo.SystemLog).Fail(enum.AuditType_alarmdata,
  1005. enum.LogType_Update,
  1006. enum.OptEventType_Bus,
  1007. enum.OptEventLevel_Hight,
  1008. fmt.Sprintf("复归告警信息失败:%s,deviceId:%s,mpid:%s", err.Error(), deviceId, mpid),
  1009. map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
  1010. )
  1011. } else {
  1012. num, _ := res.RowsAffected()
  1013. if num > 0 {
  1014. //推送复归信息到前端
  1015. t.sendWSMessage("reset", updid, models.T_base_alarm_his{
  1016. Deviceid: deviceId,
  1017. Mpid: mpid,
  1018. Is_reset: 1,
  1019. })
  1020. new(bo.SystemLog).Success(enum.AuditType_alarmdata,
  1021. enum.LogType_Update,
  1022. enum.OptEventType_Bus,
  1023. enum.OptEventLevel_Hight,
  1024. fmt.Sprintf("复归告警信息成功,deviceId:%s,mpid:%s", deviceId, mpid),
  1025. map[string]interface{}{"name": t.UserInfo.Usrname, "ip": t.UserInfo.Ip},
  1026. )
  1027. }
  1028. }
  1029. }
  1030. }
  1031. }
  1032. }
  1033. // 根据测点分组id获取该分组下的所有测点id
  1034. // 然后应用所有温度不平衡下的所有策略
  1035. func (t AlarmService) HandleAlarmUnbalance(groupId int64, alarmObj models.T_base_alarm_his, attrInfo map[string]interface{}) error {
  1036. db := orm.NewOrm()
  1037. var sqlCommandText = "select * from t_data_mp_group where groupid=?"
  1038. source := []orm.Params{}
  1039. _, err := db.Raw(sqlCommandText, groupId).Values(&source)
  1040. if err != nil {
  1041. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  1042. return err
  1043. }
  1044. unBalanceList := new(AlarmTactics).GetUnbalanceList()
  1045. if err != nil {
  1046. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  1047. return err
  1048. }
  1049. currtValueSourceList := []interface{}{}
  1050. currtValueTargtList := []interface{}{}
  1051. for _, s := range source {
  1052. currtValue := tools.IsEmpty(attrInfo[tools.IsEmpty(s["attrname"])]) //返回分组的测点在当前采集数据中对应的值
  1053. currtValueSourceList = append(currtValueSourceList, currtValue)
  1054. currtValueTargtList = append(currtValueTargtList, currtValue)
  1055. }
  1056. for _, balance := range unBalanceList {
  1057. for index, row := range currtValueSourceList {
  1058. a, err := strconv.ParseFloat(tools.IsEmpty(row), 64)
  1059. if err != nil {
  1060. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  1061. return err
  1062. }
  1063. for _, item := range currtValueTargtList {
  1064. op := tools.IsEmpty(balance["operation_symbol"])
  1065. strategyid, err := strconv.ParseInt(tools.IsEmpty(balance["id"]), 10, 64)
  1066. alarm_level, err := strconv.ParseInt(tools.IsEmpty(balance["alarm_level"]), 10, 64)
  1067. if err != nil {
  1068. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  1069. return err
  1070. }
  1071. threshold, err := strconv.ParseFloat(tools.IsEmpty(balance["threshold"]), 64)
  1072. if err != nil {
  1073. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  1074. return err
  1075. }
  1076. b, err := strconv.ParseFloat(tools.IsEmpty(item), 64)
  1077. if err != nil {
  1078. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  1079. return err
  1080. }
  1081. flag := t.CompareAbs(op, a, b, threshold)
  1082. // 如果满足触发条件则添加一个告警数据
  1083. if flag {
  1084. // 添加一个告警信息
  1085. alarmObj.Mpid = groupId
  1086. alarmObj.Mpname = tools.IsEmpty(balance["strategy_name"])
  1087. alarmObj.Alarm_level = int(alarm_level)
  1088. alarmObj.Strategyid = strategyid
  1089. alarmObj.Alarm_desc = fmt.Sprintf("触发温度不平衡告警规则【%s】,", balance["strategy_name"])
  1090. newid, err := new(AlarmInfoService).InsertAlarmInfo(alarmObj)
  1091. if err != nil {
  1092. logger.Logger.Error(err, fmt.Sprintf("****************Error is:%s.", err.Error()))
  1093. return err
  1094. }
  1095. t.sendWSMessage("alarm", newid, alarmObj)
  1096. }
  1097. currtValueTargtList = append(currtValueTargtList[:index], currtValueTargtList[index+1:]...)
  1098. }
  1099. }
  1100. }
  1101. return nil
  1102. }
  1103. // a和b之差的绝对值和不平衡里面的值进行operation比较
  1104. func (t *AlarmService) CompareAbs(op string, a float64, b float64, threshold float64) bool {
  1105. // 如果a和b之差的绝对值和不平衡里面的值进行operation比较
  1106. switch op {
  1107. case ">":
  1108. if math.Abs(a-b) > threshold {
  1109. return true
  1110. }
  1111. case "<":
  1112. if math.Abs(a-b) < threshold {
  1113. return true
  1114. }
  1115. case "=":
  1116. if math.Abs(a-b) == threshold {
  1117. return true
  1118. }
  1119. default:
  1120. return false
  1121. }
  1122. return false
  1123. }
  1124. func (t *AlarmService) HandleAlarmEvent2(field *HistoryService) {
  1125. var deviceId = int64(field.Model.Deviceid)
  1126. //log.Println(fmt.Sprintf("接收到新状态值:%v", field))
  1127. for attrName, attrValue := range field.AttrInfo {
  1128. curValue := cast.ToFloat64(attrValue)
  1129. eventId := int64(0)
  1130. //relation, _ := search(deviceId, attrName)
  1131. strategyLst := t.FindstrategyDefByAttrname(deviceId, attrName)
  1132. //log.Println(fmt.Sprintf("设备%d及属性%s的策略配置:%+v", deviceId, attrName, strategyLst))
  1133. if len(strategyLst) == 0 {
  1134. continue
  1135. } else {
  1136. for strategyid, relation := range strategyLst {
  1137. strategyname := ""
  1138. alertstatus := 0 //策略当前告警状态:默认告警状态
  1139. alarmLevel := 1 //告警级别,1 预警,2 一般,3 严重,4 危急
  1140. positionname := "" //告警设备位置
  1141. mpid := int64(0) //当前测点ID
  1142. //前置测点运算关系,默认为无 1-与,2-或,3-无
  1143. preRelation := 0
  1144. //前置测点告警状态运算结果
  1145. preAlertStatus := false
  1146. for _, record := range relation {
  1147. var alarmState = false // 当前测点规则是否告警
  1148. //log.Println(fmt.Sprintf("当前测点规则:%+v 当前状态值:%d", record, attrValue))
  1149. key := fmt.Sprintf("%d_%s_%d", record.Deviceid, record.Attrname, strategyid)
  1150. if record.Deviceid == deviceId && record.Attrname == attrName {
  1151. switch record.Alarmtype {
  1152. case 1: //阈值告警
  1153. if curValue <= record.Dnlimit || curValue >= record.Uplimit { //小于下限或者大于上限触发告警条件
  1154. alarmState = true
  1155. }
  1156. case 2: //开关量告警
  1157. if record.Dio == curValue { //触发告警条件
  1158. alarmState = true
  1159. }
  1160. case 3: //差值告警
  1161. var diffen, err = t.GetDiff(record.Mpid)
  1162. if err == nil {
  1163. if math.Abs(cast.ToFloat64(diffen)-curValue) > record.Diffvalue { //触发告警条件
  1164. alarmState = true
  1165. }
  1166. }
  1167. }
  1168. //缓存当前设备及测点的告警状态
  1169. DeviceAttrLastInfo.Store(key, alarmState)
  1170. } else {
  1171. //判断是否缓存了该设备和测点的告警状态,未缓存时默认为无告警
  1172. v, has := DeviceAttrLastInfo.Load(key)
  1173. if has {
  1174. alarmState = v.(bool)
  1175. }
  1176. }
  1177. if preRelation == 0 {
  1178. //第一个测点规则,没有前置测点时
  1179. preAlertStatus = alarmState
  1180. } else {
  1181. if preRelation == 1 {
  1182. //"与"关系
  1183. preAlertStatus = alarmState && preAlertStatus
  1184. } else if preRelation == 2 {
  1185. //"或"关系
  1186. preAlertStatus = alarmState || preAlertStatus
  1187. }
  1188. }
  1189. //log.Printf(fmt.Sprintf("本次告警状态:%v 策略告警状态%v", alarmState, preAlertStatus))
  1190. //当前告警测点信息
  1191. alarmLevel = record.Alarmlevel
  1192. mpid = record.Mpid
  1193. strategyname = record.Strategyname
  1194. preRelation = record.Relation
  1195. if record.Relation == 3 {
  1196. //运算关系:多测点间告警关系。1-与,2-或,3-无
  1197. break
  1198. }
  1199. }
  1200. if preAlertStatus {
  1201. alertstatus = 1
  1202. } else {
  1203. alertstatus = 0
  1204. }
  1205. //该策略最后一次告警状态信息
  1206. tmpData, has := beforeAlarmState.Load(strategyid)
  1207. var beforeAlram = false
  1208. var beforeEventId = int64(0)
  1209. if !has {
  1210. beforeAlram, beforeEventId = t.GetBeforeAlarmState(tools.IsEmpty(strategyid))
  1211. } else {
  1212. //从缓存中获取策略告警信息
  1213. tmpData1 := tmpData.(map[string]interface{})
  1214. beforeAlram = tmpData1["state"].(bool)
  1215. beforeEventId = tmpData1["eventid"].(int64)
  1216. }
  1217. //log.Println("=====%d====%v===%d", alertstatus, beforeAlram, beforeEventId)
  1218. //策略当前告警状态:0 无告警 1 触发告警 2 告警复归
  1219. if alertstatus == 0 && !beforeAlram {
  1220. //无告警,不做处理
  1221. continue
  1222. }
  1223. if alertstatus == 1 && beforeAlram {
  1224. //持续告警,不做处理
  1225. continue
  1226. }
  1227. eventId = new(logic.ToolsLogic).GetOnlyId(cast.ToInt64(RtelecManageApp().RegAppID))
  1228. desc := t.AlarmDesc(mpid)
  1229. shortDesc := desc
  1230. var eventtype int32 = 0
  1231. if alertstatus == 1 && !beforeAlram {
  1232. eventtype = 1
  1233. desc += fmt.Sprintf("状态值(%d)触发告警策略[%s]", int(curValue), strategyname)
  1234. //在写iss库的同时,写本地库的alarm_his表
  1235. lerr := t.AddLocalAlarmEvent(eventId, shortDesc, eventtype, strategyid, int32(alarmLevel), positionname, int(deviceId))
  1236. if lerr != nil {
  1237. logger.Logger.Error(lerr)
  1238. continue
  1239. }
  1240. tmpData := map[string]interface{}{"state": true, "eventid": eventId}
  1241. beforeAlarmState.Store(strategyid, tmpData)
  1242. } else if alertstatus == 0 && beforeAlram {
  1243. eventtype = 3
  1244. desc += fmt.Sprintf("状态值(%d)已恢复正常,告警复归", int(curValue))
  1245. tmpData := map[string]interface{}{"state": false, "eventid": int64(0)}
  1246. beforeAlarmState.Store(strategyid, tmpData)
  1247. }
  1248. //log.Printf(fmt.Sprintf("本次告警描述:%s", desc))
  1249. err := t.AddAlarmEvent(eventId, desc, eventtype, strategyid, int32(alarmLevel), beforeEventId)
  1250. if err == nil {
  1251. //添加告警成功后发送消息到前端
  1252. //向websocket通道中发送数据让前端接收
  1253. go func() {
  1254. var message = make(map[string]interface{})
  1255. message["content"] = field.Model.Devicename
  1256. message["time"] = tools.NowTime()
  1257. message["region"] = positionname
  1258. message["msg_type"] = 0
  1259. datachannel.SendDataQueue <- message
  1260. }()
  1261. //向中台发送消息
  1262. var parameter AlarmMessage
  1263. parameter.Eventid = eventId
  1264. parameter.Eventtype = 0
  1265. parameter.Eventdesc = desc
  1266. parameter.Timestamp = time.Now().Local().Unix()
  1267. parameter.Mid = tools.GetUid()
  1268. parameter.Strategyid = strategyid
  1269. t.SendAlertMessage(parameter)
  1270. } else {
  1271. logger.Logger.Error("告警信息写入失败:" + err.Error())
  1272. }
  1273. }
  1274. }
  1275. }
  1276. }
  1277. // 添加本地告警事件
  1278. func (t *AlarmService) AddLocalAlarmEvent(eventid int64, eventdesc string, eventtype int32, strategyId int64, alarmlevel int32, position string, deviceid int) error {
  1279. db := orm.NewOrm()
  1280. rs, dberr := new(DeviceService).GetDeviceActionPoint(deviceid)
  1281. var modelid int
  1282. var positionname string
  1283. if dberr == nil && len(rs) > 0 {
  1284. modelid = rs[0].Modelid
  1285. }
  1286. descs := strings.Split(eventdesc, ",")
  1287. for i := 0; i < len(descs); i++ {
  1288. if i == 0 || i == (len(descs)-1) {
  1289. continue
  1290. }
  1291. positionname = positionname + tools.IsEmpty(descs[i]) + ","
  1292. }
  1293. positionname = positionname[0 : len(positionname)-1]
  1294. var sqlCommandText = "insert into alarm_his(eventid,eventdesc,eventtype,timestamp,strategyid,appid,alarmlevel,modelid,position)values(?,?,?,?,?,?,?,?,?);"
  1295. var sqlParamber = []interface{}{eventid, positionname, eventtype, time.Now().Unix(), strategyId, RtelecManageApp().RegAppID, alarmlevel, modelid, position}
  1296. _, err := db.Raw(sqlCommandText, sqlParamber).Exec()
  1297. if err != nil {
  1298. logger.Logger.Println("告警事件写入本地数据库出现错误:")
  1299. logger.Logger.Error(err)
  1300. }
  1301. return err
  1302. }
  1303. //根据测点id(mpid)获得描述
  1304. func (t *AlarmService) AlarmDesc(Mpid int64) string {
  1305. var eventdesc = ""
  1306. mpInfo := logic.NewMpInfoLogic()
  1307. type Mpfield struct {
  1308. Eventdesc string `json:"eventdesc"`
  1309. }
  1310. var list []Mpfield
  1311. 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)
  1312. err := mpInfo.SvcCtx.DevMpinfo.Base.Raw(sqlCommandText, &list)
  1313. if err == nil && len(list) > 0 {
  1314. eventdesc = list[0].Eventdesc + ","
  1315. }
  1316. return eventdesc
  1317. }
  1318. //发送消息
  1319. func (t *AlarmService) SendAlertMessage(msg AlarmMessage) error {
  1320. var parameter = make(map[string]interface{})
  1321. parameter["token"] = RtelecManageApp().AppToken
  1322. parameter["eventid"] = msg.Eventid
  1323. parameter["eventtype"] = msg.Eventtype
  1324. parameter["eventdesc"] = msg.Eventdesc
  1325. parameter["strategyid"] = msg.Strategyid
  1326. parameter["timestamp"] = time.Now().Unix()
  1327. parameter["mid"] = msg.Mid
  1328. /*//mqtt消息中的message数据处理
  1329. var para = make(map[string]interface{})
  1330. para["eventid"] = msg.Eventid
  1331. para["eventtype"] = msg.Eventtype
  1332. para["eventdesc"] = msg.Eventdesc
  1333. para["strategyid"] = msg.Strategyid
  1334. para["timestamp"] = time.Now().Unix()
  1335. para["mid"] = msg.Mid
  1336. Message, _ := json.Marshal(para)
  1337. message, _ := common.Encrypt(Message, configure.AppConfigure.PassWord)
  1338. parameter["message"] = message*/
  1339. messageContent, _ := json.Marshal(parameter)
  1340. mqtt.PublishMessage(global.Rtelec_Topics["alarm_info"], string(messageContent))
  1341. return nil
  1342. }
  1343. //添加告警事件记录
  1344. func (t *AlarmService) AddAlarmEvent(eventid int64, eventdesc string, eventtype int32, strategyId int64, alarmlevel int32, beforeEventId int64) error {
  1345. l := logic.NewAlarmEventLogic()
  1346. appid := RtelecManageApp().RegAppID
  1347. parameter := model.AlarmEvent{}
  1348. parameter.Eventid = eventid
  1349. parameter.Eventdesc = eventdesc
  1350. parameter.Eventtype = eventtype
  1351. parameter.Timestamp = time.Now().Unix()
  1352. parameter.Strategyid = strategyId
  1353. parameter.Alarmlevel = int32(alarmlevel)
  1354. parameter.Appid = cast.ToInt32(appid)
  1355. parameter.Subeventid = beforeEventId
  1356. oldRow := model.AlarmEvent{}
  1357. oldRow.Eventid = beforeEventId
  1358. oldRow.Subeventid = eventid
  1359. err := l.ModifyAlarmEvent(&oldRow, "subeventid")
  1360. if err != nil {
  1361. logger.Logger.Error(err)
  1362. }
  1363. return l.AddAlarmEvent(&parameter)
  1364. }
  1365. //获取设备上次状态
  1366. func (t *AlarmService) GetBeforeState(deviceId int, attrName string) float64 {
  1367. var state = -1
  1368. o := orm.NewOrm()
  1369. var sqlCommandText = "select val from dev_history where attrname=? and deviceid=? order by id desc limit 1"
  1370. var sqlParameter = []interface{}{attrName, deviceId}
  1371. var table []orm.Params
  1372. _, err := o.Raw(sqlCommandText, sqlParameter).Values(&table)
  1373. if err == nil && len(table) > 0 {
  1374. state, _ = strconv.Atoi(table[0]["val"].(string))
  1375. }
  1376. return float64(state)
  1377. }
  1378. //获取测点上次报警状态
  1379. //true:已报警,下次不处理
  1380. //false:未报警或已复归,下次需处理
  1381. func (t *AlarmService) GetBeforeAlarmState(strategyid string) (bool, int64) {
  1382. mpInfo := logic.NewMpInfoLogic()
  1383. //获取告警事件表中告警策略最近的一条纪录
  1384. //根据这个纪录的eventtype来判断。如果没有纪录或者eventtype是3,那么上次的状态为复归了。下次需要写事件表。
  1385. //如果eventtype不为3,那么上次状态为确认了。下次不需要写事件表
  1386. var sqlCommandText = "select eventtype,eventid from alarm_event where strategyid=" + strategyid + " order by id desc limit 1"
  1387. // var table []orm.Params
  1388. type tabledd struct {
  1389. Eventtype int `json:"eventtype"`
  1390. Eventid int64
  1391. }
  1392. var tablesd []tabledd
  1393. err := mpInfo.SvcCtx.AlarmEvent.Base.Raw(sqlCommandText, &tablesd)
  1394. if err == nil {
  1395. if len(tablesd) == 0 {
  1396. return false, 0
  1397. } else if "3" == tools.IsEmpty(tablesd[0].Eventtype) {
  1398. return false, 0
  1399. }
  1400. }
  1401. return true, tablesd[0].Eventid
  1402. }
  1403. //差值告警,获取本次数据与上一次历史数据的差值
  1404. func (t *AlarmService) GetDiff(mpid interface{}) (float64, error) {
  1405. var k = tools.IsEmpty(mpid)
  1406. o := orm.NewOrm()
  1407. var sqlCommandText = "select val from dev_history where mpid=? order by id desc limit 1"
  1408. var sqlParameter = []interface{}{k}
  1409. var table []orm.Params
  1410. _, err := o.Raw(sqlCommandText, sqlParameter).Values(&table)
  1411. if err == nil && len(table) > 0 {
  1412. return cast.ToFloat64((table[0]["val"])), nil
  1413. }
  1414. return cast.ToFloat64(0), err
  1415. }
  1416. //向前端推送告警信息
  1417. //optype:操作类型。alarm:新的告警 reset:告警复归
  1418. func (t *AlarmService) sendWSMessage(optype string, alarmid int64, alarmObj models.T_base_alarm_his) {
  1419. //推送复归信息到前端
  1420. msg := map[string]interface{}{
  1421. "alarm_id": tools.IsEmpty(alarmid),
  1422. "device_id": tools.IsEmpty(alarmObj.Deviceid),
  1423. "mp_id": tools.IsEmpty(alarmObj.Mpid),
  1424. "is_reset": 0,
  1425. }
  1426. if optype == "alarm" {
  1427. msg["alarm_desc"] = alarmObj.Alarm_desc
  1428. msg["device_name"] = alarmObj.Devicename
  1429. msg["mp_name"] = alarmObj.Mpname
  1430. msg["create_at"] = alarmObj.Create_at
  1431. msg["alarm_level"] = alarmObj.Alarm_level
  1432. } else {
  1433. msg["is_reset"] = 1
  1434. }
  1435. datachannel.SendDataQueue <- map[string]interface{}{
  1436. "topic": global.Topic_DeviceAlarmPublish,
  1437. "data": msg,
  1438. }
  1439. }