alarm_add.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. package monitor
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "github.com/jinzhu/gorm"
  7. "smart-alarm/consts"
  8. "smart-alarm/errors"
  9. "smart-alarm/model"
  10. "smart-alarm/pb"
  11. "smart-alarm/pb/v1"
  12. "smart-alarm/utils"
  13. "strings"
  14. "time"
  15. "github.com/jaryhe/gopkgs/database"
  16. "github.com/jaryhe/gopkgs/logger"
  17. "go.uber.org/zap"
  18. )
  19. var DeviceTypeMap = map[uint32]string {
  20. 5:"扬尘设备",
  21. 1:"塔吊设备",
  22. 2:"门禁设备",
  23. 4:"升降机设备",
  24. }
  25. // 解析时间
  26. func parseTime(str string) time.Time {
  27. layOut := "2006-01-02 15:04:05"
  28. if strings.Contains(str, ":") == false && strings.Contains(str, "-") == false {
  29. layOut = "20060102150405"
  30. } else if strings.Contains(str, "T") {
  31. layOut = "2006-01-02T15:04:05"
  32. }
  33. loc, _ := time.LoadLocation("Local")
  34. t, err := time.ParseInLocation(layOut, str, loc)
  35. if err != nil {
  36. return time.Now()
  37. }
  38. return t
  39. }
  40. func TaskAdd(db *gorm.DB, reason string, projectId int64) (int64, error) {
  41. project := model.ProjectInfo{}
  42. where := map[string]interface{}{
  43. "ID": projectId,
  44. }
  45. err := project.Find(db, where)
  46. if err != nil && err != gorm.ErrRecordNotFound {
  47. return 0, errors.DataBaseError
  48. }
  49. if project.ID == 0 {
  50. return 0, errors.ProjectNotExistError
  51. }
  52. finishDate := time.Now().Add(4 * 24 * time.Hour)
  53. finishDate = time.Date(finishDate.Year(), finishDate.Month(), finishDate.Day(), 0, 0, 0, 0, finishDate.Location())
  54. now := time.Now()
  55. p := model.TaskProcessingInfo{
  56. Code: project.Code,
  57. ProjectID: projectId,
  58. TaskName: reason,
  59. TaskDesc: reason,
  60. AssignmentDate: now,
  61. FinishDate: finishDate,
  62. TaskType: 3,
  63. Status: 1,
  64. }
  65. pipe := model.TaskPipeline{
  66. PipeType: model.PipelineCreate,
  67. PipeTime: now.Format("2006-01-02 15:04:05"),
  68. Person: "",
  69. Desc: p.TaskDesc,
  70. Img: p.TaskImg,
  71. ApproveStatus: false,
  72. }
  73. if pipe.Img == "" {
  74. pipe.Img = "[]"
  75. }
  76. pipeArray := []model.TaskPipeline{pipe}
  77. pipeBytes, _ := json.Marshal(pipeArray)
  78. p.Pipeline = string(pipeBytes)
  79. for i := 0; i < 10; i++ {
  80. p.TaskID = fmt.Sprintf("%s%s", time.Now().Format("20060102"), utils.GenerateRandomStr(8, "char"))
  81. err = p.Insert(db)
  82. if err != nil {
  83. if strings.Contains(strings.ToLower(err.Error()), "duplicate") {
  84. time.Sleep(200 * time.Microsecond)
  85. continue
  86. }
  87. return 0, errors.DataBaseError
  88. }
  89. break
  90. }
  91. if err != nil {
  92. return 0, errors.DataBaseError
  93. }
  94. return p.ID, nil
  95. }
  96. // 存储告警信息
  97. func WriteAlarm(req *v1.AlarmAddRequest) (bool, error) {
  98. alarm := &model.TAlarm{
  99. ProjectId: req.ProjectId,
  100. Sn: req.Sn,
  101. AlarmCode: req.AlarmCode,
  102. AlarmReason: req.AlarmReason,
  103. IsHandle: false,
  104. Time: req.Date,
  105. DeviceCode: uint32(req.DeviceCode),
  106. }
  107. p := &model.TAlarm{}
  108. where := map[string]interface{}{
  109. "SN": req.Sn,
  110. "AlarmCode": req.AlarmCode,
  111. "IsHandle": false,
  112. "DeviceCode": req.DeviceCode,
  113. }
  114. // 分布式锁,政府端处理告警同样需加分布式锁
  115. key := fmt.Sprintf("%s-%s-%d", req.Sn, req.AlarmCode, req.DeviceCode)
  116. ok, err := utils.RedisLock(key, 500, 10)
  117. if err != nil {
  118. return false, err
  119. }
  120. if !ok {
  121. return false, errors.SystemError
  122. }
  123. defer utils.RedisUnlock(key)
  124. err = p.Query(database.DB(), where)
  125. if err != nil && err != gorm.ErrRecordNotFound {
  126. return false, err
  127. }
  128. ret := false
  129. if p.Id == 0 {
  130. db := database.DB().Begin()
  131. alarm.First = true
  132. taskId := int64(0)
  133. var err error
  134. if alarm.First && DeviceTypeMap[alarm.DeviceCode]!= "" {
  135. alarmReason := fmt.Sprintf("%s%s于%s%s ", DeviceTypeMap[alarm.DeviceCode],alarm.Sn, alarm.Time, alarm.AlarmReason)
  136. taskId, err = TaskAdd(db, alarmReason, alarm.ProjectId)
  137. if err != nil {
  138. db.Rollback()
  139. return false, err
  140. }
  141. }
  142. alarm.TaskID = taskId
  143. err = alarm.Insert(db)
  144. if err != nil {
  145. return false, err
  146. }
  147. db.Commit()
  148. ret = true
  149. }
  150. return ret, nil
  151. /*projectIdStr := strconv.Itoa(int(req.ProjectId))
  152. tags := map[string]string{"sn": req.Sn, "project_id": projectIdStr, "alarm_code": req.AlarmCode}
  153. fields := map[string]interface{}{
  154. "alarm_reason": req.AlarmReason,
  155. "is_handled": false,
  156. }
  157. return model.WriteAlarmData(tags, fields, t, req.ProjectId)*/
  158. }
  159. func sendAlarm(ctx context.Context, req *v1.AlarmAddRequest, contacts []model.TAlarmContact) {
  160. for _, contact := range contacts {
  161. fmt.Println("send to notify:", contact.Phone, contact.Email)
  162. name := req.DeviceName
  163. if name == "" {
  164. name = req.Sn
  165. }
  166. deviceName := name
  167. rpcReq := &v1.SendAlarmRequest{
  168. PhoneNumber: contact.Phone,
  169. Email: contact.Email,
  170. DeviceName: deviceName,
  171. AlarmReason: req.AlarmReason,
  172. AlarmTime: req.Date,
  173. }
  174. _, err := pb.ThirdParty.SendAlarm(ctx, rpcReq)
  175. if err != nil {
  176. reqByte, _ := json.Marshal(*rpcReq)
  177. logger.Error("rpc",
  178. zap.String("call", "pb.ThirdParty.SendAlarm"),
  179. zap.String("params", string(reqByte)),
  180. zap.String("error", err.Error()))
  181. }
  182. }
  183. }
  184. // 处理告警
  185. func HandlAlarm(ctx context.Context, req *v1.AlarmAddRequest, rule *model.TAlarmRule, contact []model.TAlarmContact) {
  186. // 1 获取本地告警记录
  187. statistics := utils.GetAlarmStatistics(req.Sn, req.AlarmCode)
  188. // 重置统计数据
  189. defer utils.SetAlarmStatistics(req.Sn, req.AlarmCode, statistics)
  190. timeNow := time.Now().Unix()
  191. // 判断是否在连续时间范围内
  192. // 第一次获取
  193. if statistics.Timestamp == 0 {
  194. statistics.Timestamp = timeNow
  195. }
  196. // 发送过,判断是否超过发送间隔
  197. if statistics.IsSend {
  198. // 超过发送间隔
  199. if (timeNow - statistics.Timestamp) > int64(rule.SilencePeriod*60) {
  200. statistics.IsSend = false
  201. statistics.Timestamp = timeNow
  202. } else {
  203. // 在发送间隔内不再发送
  204. return
  205. }
  206. }
  207. // 不在一个周期内,重置告警重新计算
  208. if (timeNow - statistics.Timestamp) > int64(rule.ContinuePeriod*60) {
  209. // 重置统计数据
  210. statistics.Timestamp = timeNow
  211. statistics.AlarmCount = 1
  212. return
  213. } else {
  214. // 统计数据加1
  215. statistics.AlarmCount++
  216. }
  217. // 达到告警次数
  218. if statistics.AlarmCount >= rule.AlarmCount {
  219. sendAlarm(ctx, req, contact)
  220. // 重置统计数据
  221. statistics.Timestamp = timeNow
  222. statistics.AlarmCount = 0
  223. statistics.IsSend = true
  224. }
  225. }
  226. // 添加告警
  227. func AlarmAdd(ctx context.Context, req *v1.AlarmAddRequest) (reply *v1.AlarmAddReply, err error) {
  228. reply = &v1.AlarmAddReply{}
  229. if req.Sn == "" || req.ProjectId <= 0 || req.AlarmReason == "" {
  230. return nil, errors.ParamsError
  231. }
  232. req.Date = parseTime(req.Date).Format(consts.TimeSecondLayOut)
  233. // 如果是离线状态
  234. if req.AlarmCode == consts.DeviceOfflineCode {
  235. req.AlarmReason = "离线"
  236. }
  237. // 获取告警联系人
  238. contact := utils.GetAlarmContact(req.ProjectId)
  239. /*
  240. if contact != nil {
  241. // 如果是离线告警不需要检查告警规则
  242. if req.AlarmCode == consts.DeviceOfflineCode {
  243. sendAlarm(ctx, req, contact)
  244. } else {
  245. // 获取告警规则
  246. rule := utils.GetAlarmRule(req.ProjectId, req.Sn)
  247. if rule != nil {
  248. HandlAlarm(ctx, req, rule, contact)
  249. }
  250. }
  251. }*/
  252. isNewRecord, _ := WriteAlarm(req)
  253. if contact != nil {
  254. if isNewRecord {
  255. sendAlarm(ctx, req, contact)
  256. }
  257. }
  258. return reply, nil
  259. }