analysisSiteData.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. package jobs
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "fwh-toolbox-server/domain"
  6. "fwh-toolbox-server/repositories"
  7. "sort"
  8. "strconv"
  9. "time"
  10. "go.mongodb.org/mongo-driver/bson/primitive"
  11. "go.uber.org/zap"
  12. )
  13. type SiteDataSet struct {
  14. Log_0 []domain.MqttLogItem
  15. Log_101 []domain.MqttLogItem
  16. Log_357 []domain.MqttLogItem
  17. EventLog []domain.EventAlarmItem
  18. AlarmLog []domain.EventAlarmItem
  19. }
  20. func AnalysisSiteTimeline(id primitive.ObjectID, data SiteDataSet) error {
  21. var timelineItemList []domain.TimelineItem
  22. // 分析offline
  23. for _, log := range data.Log_0 {
  24. _, err := time.Parse(time.DateTime, log.LogTime)
  25. if err != nil {
  26. zap.L().Error("0日志时间格式错误", zap.String("time", log.LogTime))
  27. return err
  28. }
  29. timelineItem := domain.TimelineItem{
  30. Time: log.LogTime,
  31. Type: domain.TimelineOffline,
  32. }
  33. timelineItemList = append(timelineItemList, timelineItem)
  34. }
  35. // 分析online
  36. for _, log := range data.Log_101 {
  37. _, err := time.Parse(time.DateTime, log.LogTime)
  38. if err != nil {
  39. zap.L().Error("101日志时间格式错误", zap.String("time", log.LogTime))
  40. return err
  41. }
  42. timelineItem := domain.TimelineItem{
  43. Time: log.LogTime,
  44. Type: domain.TimelineOnline,
  45. }
  46. timelineItemList = append(timelineItemList, timelineItem)
  47. }
  48. // 分析套餐&模式日志
  49. scheduleDataList := make(map[uint]domain.ScheduleData)
  50. for _, log := range data.Log_357 {
  51. _, err := time.Parse(time.DateTime, log.LogTime)
  52. if err != nil {
  53. zap.L().Error("357日志时间格式错误", zap.String("time", log.LogTime))
  54. return err
  55. }
  56. var log_357 domain.MqttLogType_357
  57. err = json.Unmarshal([]byte(log.LogData), &log_357)
  58. if err != nil {
  59. zap.L().Error("357日志JSON数据格式错误", zap.String("data", log.LogData))
  60. return err
  61. }
  62. // 判断操作类型 1-增加/编辑 2-删除 3-修改当前工作序列
  63. opt := log_357.Opt
  64. var modeInfo *string
  65. var modeData *string
  66. switch opt {
  67. case 1:
  68. // 记录策略ID对应的策略信息,用于关联切换的模式
  69. if log_357.Data != nil {
  70. scheduleDataList[log_357.Data.ID] = *log_357.Data
  71. }
  72. case 2:
  73. // 删除不做处理
  74. case 3:
  75. if log_357.CurrentId != nil && *log_357.CurrentId >= 0 {
  76. val, ok := scheduleDataList[uint(*log_357.CurrentId)]
  77. if ok {
  78. modeInfo = &val.Name
  79. // 转成 JSON 字符串
  80. jsonModeData, err := json.Marshal(val)
  81. if err != nil {
  82. fmt.Println("序列化失败:", err)
  83. zap.L().Error("357日志策略信息JSON数据序列化失败", zap.String("err", err.Error()), zap.Any("data", val))
  84. } else {
  85. dataStr := string(jsonModeData)
  86. modeData = &dataStr
  87. }
  88. } else {
  89. infoStr := fmt.Sprintf("未知模式(%d)", log_357.CurrentId)
  90. modeInfo = &infoStr
  91. }
  92. }
  93. default:
  94. zap.L().Error("357日志不支持的操作类型", zap.String("opt", strconv.Itoa(log_357.Opt)))
  95. return err
  96. }
  97. timelineItem := domain.TimelineItem{
  98. Time: log.LogTime,
  99. Type: domain.TimelineModeChange,
  100. Info: modeInfo,
  101. Data: modeData,
  102. }
  103. timelineItemList = append(timelineItemList, timelineItem)
  104. }
  105. // 分析Event
  106. for _, log := range data.EventLog {
  107. _, err := time.Parse(time.DateTime, log.LogTime)
  108. if err != nil {
  109. zap.L().Error("Event日志时间格式错误", zap.String("time", log.LogTime))
  110. return err
  111. }
  112. timelineItem := domain.TimelineItem{
  113. Time: log.LogTime,
  114. Type: domain.TimelineEvent,
  115. Info: &log.LogName,
  116. }
  117. timelineItemList = append(timelineItemList, timelineItem)
  118. }
  119. // 分析Alarm
  120. for _, log := range data.AlarmLog {
  121. _, err := time.Parse(time.DateTime, log.LogTime)
  122. if err != nil {
  123. zap.L().Error("Alarm日志时间格式错误", zap.String("time", log.LogTime))
  124. return err
  125. }
  126. alarmCode := []byte(log.AlarmCode)
  127. var alarmName string
  128. if len(alarmCode) < 4 {
  129. alarmName = fmt.Sprintf("#? %s", log.LogName)
  130. } else {
  131. if alarmCode[1] == '0' {
  132. alarmName = log.LogName
  133. } else {
  134. alarmName = fmt.Sprintf("#%s %s", string(alarmCode[1]), log.LogName)
  135. }
  136. }
  137. timelineItem := domain.TimelineItem{
  138. Time: log.LogTime,
  139. Type: domain.TimelineAlarm,
  140. Info: &alarmName,
  141. }
  142. timelineItemList = append(timelineItemList, timelineItem)
  143. }
  144. // 数据时间排序
  145. timelineSlice(&timelineItemList)
  146. // 最后将时间线数据存入数据库
  147. if err := repositories.InsertSiteAnalysisTimeline(id, timelineItemList); err != nil {
  148. zap.L().Error("插入站点分析timeline数据失败", zap.String("id", id.String()))
  149. return err
  150. }
  151. return nil
  152. }
  153. func timelineSlice(list *[]domain.TimelineItem) {
  154. if list == nil {
  155. return
  156. }
  157. // 排序
  158. sort.Slice(*list, func(i, j int) bool {
  159. ti, _ := time.Parse(time.DateTime, (*list)[i].Time)
  160. tj, _ := time.Parse(time.DateTime, (*list)[j].Time)
  161. return ti.Before(tj)
  162. })
  163. }