fwh_eventAlarmLog.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. package fwh_pro
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "fwh-toolbox-server/config"
  7. "fwh-toolbox-server/domain"
  8. "net/url"
  9. "strconv"
  10. "time"
  11. "go.uber.org/zap"
  12. )
  13. type EventAlarmType int
  14. const (
  15. All EventAlarmType = iota // 0
  16. Event // 1
  17. Alarm // 2
  18. )
  19. type EventAlarmListResponse struct {
  20. Code int `json:"code"`
  21. Message string `json:"message"`
  22. Result []domain.EventAlarmItem `json:"result"`
  23. Success bool `json:"success"`
  24. Total uint `json:"total"`
  25. }
  26. // 查询事件事件日志
  27. func queryEventAndAlarmLog(sn string, params url.Values) ([]byte, error) {
  28. token := getLoginToken()
  29. userId, _ := getUserId(token)
  30. // 构造 query 参数
  31. params.Add("userId", strconv.Itoa(userId))
  32. params.Add("searchName", sn)
  33. params.Add("timeType", strconv.Itoa(1)) // 0-通讯时间;1-设备时间
  34. params.Add("pageSize", strconv.FormatUint(REQ_PAGE_SIZE, 10))
  35. params.Add("pageNum", strconv.Itoa(1))
  36. params.Add("land", "ZH_CN")
  37. reqUrl := fmt.Sprintf("https://%s/hes-gateway/manage/iotDeviceRunLogs", config.FWH_ENERGY)
  38. response, err := FwhHttpGet(reqUrl, params)
  39. if err != nil {
  40. return nil, err
  41. }
  42. return response.Body, nil
  43. }
  44. // 查询所有事件告警
  45. // startTime&endTime 格式 YYYY-MM-DD HH:mm:SS
  46. func queryAllEventAlarm(sn, startTime, endTime string) ([]byte, error) {
  47. // 构造 query 参数
  48. params := url.Values{}
  49. params.Add("startTime", startTime)
  50. params.Add("endTime", endTime)
  51. return queryEventAndAlarmLog(sn, params)
  52. }
  53. // 查询事件日志
  54. // startTime&endTime 格式 YYYY-MM-DD HH:mm:SS
  55. func queryEventLog(sn, startTime, endTime string) ([]byte, error) {
  56. // 构造 query 参数
  57. params := url.Values{}
  58. params.Add("logType", strconv.Itoa(0))
  59. params.Add("startTime", startTime)
  60. params.Add("endTime", endTime)
  61. return queryEventAndAlarmLog(sn, params)
  62. }
  63. // 查询告警日志
  64. // startTime&endTime 格式 YYYY-MM-DD HH:mm:SS
  65. // alarmCode - 支持多个code,用‘,’隔开,“”代表查询所有
  66. func queryAlarmLog(sn, startTime, endTime, alarmCode string) ([]byte, error) {
  67. // 构造 query 参数
  68. params := url.Values{}
  69. params.Add("logType", strconv.Itoa(1))
  70. params.Add("alarmCode", alarmCode)
  71. params.Add("startTime", startTime)
  72. params.Add("endTime", endTime)
  73. return queryEventAndAlarmLog(sn, params)
  74. }
  75. // 查询实时告警
  76. func queryRealtimeAlarm(sn string) ([]byte, error) {
  77. // 构造 query 参数
  78. params := url.Values{}
  79. params.Add("logType", strconv.Itoa(2))
  80. return queryEventAndAlarmLog(sn, params)
  81. }
  82. func queryEventOrAlarmListOnePage(sn string, startTime, endTime time.Time, t EventAlarmType) ([]domain.EventAlarmItem, error) {
  83. // 三次请求尝试
  84. for i := 0; i < 3; i++ {
  85. eventLogRes, err := queryEventOrAlarmListOnePageExec(sn, startTime, endTime, t)
  86. if err != nil {
  87. zap.L().Warn("queryEventOrAlarmListOnePageExec failed and retry", zap.String("err", err.Error()))
  88. continue
  89. }
  90. if eventLogRes.Code == 401 {
  91. // TODO 尝试重新登录
  92. return nil, errors.New("certification expired")
  93. }
  94. if eventLogRes.Code != 200 {
  95. // return nil, fmt.Errorf("查询失败 code: %d, message: %s", eventLogRes.Code, eventLogRes.Message)
  96. zap.L().Warn("queryEventOrAlarmListOnePage 查询失败 retry", zap.Int("code", eventLogRes.Code), zap.String("msg", eventLogRes.Message))
  97. time.Sleep(time.Second * 5)
  98. continue
  99. }
  100. return eventLogRes.Result, nil
  101. }
  102. return nil, errors.New("retry failed")
  103. }
  104. func queryEventOrAlarmListOnePageExec(sn string, startTime, endTime time.Time, t EventAlarmType) (*EventAlarmListResponse, error) {
  105. startTimeStr := startTime.Format(time.DateTime)
  106. endTimeStr := endTime.Format(time.DateTime)
  107. // TEST
  108. fmt.Printf("startTime = %s\n", startTimeStr)
  109. fmt.Printf("endTime = %s\n", endTimeStr)
  110. var resByte []byte
  111. var err error
  112. switch t {
  113. case Event:
  114. resByte, err = queryEventLog(sn, startTimeStr, endTimeStr)
  115. case Alarm:
  116. resByte, err = queryAlarmLog(sn, startTimeStr, endTimeStr, "")
  117. default:
  118. resByte, err = queryAllEventAlarm(sn, startTimeStr, endTimeStr)
  119. }
  120. if err != nil {
  121. return nil, err
  122. }
  123. var eventLogRes EventAlarmListResponse
  124. // 反序列化(unmarshal)
  125. jsonErr := json.Unmarshal(resByte, &eventLogRes)
  126. if jsonErr != nil {
  127. return nil, jsonErr
  128. }
  129. return &eventLogRes, nil
  130. }
  131. // 从FWH获取事件或告警log数据
  132. func QueryEventOrAlarmListOnTimeRange(sn string, startTime, endTime time.Time, t EventAlarmType) ([]domain.EventAlarmItem, error) {
  133. // 保证 startTime <= endTime
  134. if startTime.After(endTime) {
  135. return nil, errors.New("startTime > endTime")
  136. }
  137. // 按天拆分时间段
  138. var periods []struct{ Start, End time.Time }
  139. currTime := startTime
  140. for currTime.Before(endTime) {
  141. // 当天结束时间
  142. dayEnd := time.Date(currTime.Year(), currTime.Month(), currTime.Day(), 23, 59, 59, 0, currTime.Location())
  143. // 如果当天结束大于 endTime,使用 endTime
  144. if dayEnd.After(endTime) {
  145. dayEnd = endTime
  146. }
  147. periods = append(periods, struct{ Start, End time.Time }{Start: currTime, End: dayEnd})
  148. // 下一天开始
  149. currTime = dayEnd.Add(time.Second).Truncate(24 * time.Hour)
  150. currTime = time.Date(currTime.Year(), currTime.Month(), currTime.Day(), 0, 0, 0, 0, currTime.Location())
  151. }
  152. // 按天查询
  153. var eventLogList []domain.EventAlarmItem
  154. for _, period := range periods {
  155. var eventLogRes []domain.EventAlarmItem = nil
  156. periodEndTime := period.End
  157. // 检查数据是否超过1000(单次查询上限)
  158. for {
  159. var err error
  160. eventLogRes, err = queryEventOrAlarmListOnePage(sn, period.Start, periodEndTime, t)
  161. if err != nil {
  162. return nil, err
  163. }
  164. eventLogList = append(eventLogList, eventLogRes...)
  165. // 判断是否未查完
  166. if len(eventLogRes) < int(REQ_PAGE_SIZE) {
  167. // 请求完成,退出
  168. break
  169. }
  170. // 跳转时间段,再次请求
  171. // 提取最后一条数据的设备时间
  172. periodEndTime, err = time.Parse(time.DateTime, eventLogRes[len(eventLogRes)-1].LogTime)
  173. if err != nil {
  174. return nil, err
  175. }
  176. }
  177. }
  178. return eventLogList, nil
  179. }
  180. // 查询快照信息
  181. // logTime 格式 YYYY-MM-DD
  182. func queryAlarmSnapshotInfo(sn, logTime string, page int) ([]byte, error) {
  183. // 构造 query 参数
  184. params := url.Values{}
  185. params.Add("logTime", logTime)
  186. params.Add("linkId", sn)
  187. params.Add("pageSize", strconv.FormatUint(REQ_PAGE_SIZE, 10))
  188. params.Add("pageNum", strconv.Itoa(page))
  189. params.Add("land", "ZH_CN")
  190. reqUrl := fmt.Sprintf("https://%s/hes-gateway/manage/selectAlarmSnapshotList", config.FWH_ENERGY)
  191. response, err := FwhHttpGet(reqUrl, params)
  192. if err != nil {
  193. return nil, err
  194. }
  195. return response.Body, nil
  196. }
  197. func QueryAlarmSnapshotInfo(sn, logTime string) ([]domain.AlarmSnapshotInfo, error) {
  198. var page int = 1
  199. var infoList []domain.AlarmSnapshotInfo
  200. for {
  201. // 查询告警快照数据
  202. resByte, err := queryAlarmSnapshotInfo(sn, logTime, page)
  203. if err != nil {
  204. return nil, fmt.Errorf("[QueryAlarmSnapshotInfo] %s", err.Error())
  205. }
  206. var alarmSnapshotRes domain.FwhPageResponse[[]domain.AlarmSnapshotInfo]
  207. // 反序列化(unmarshal)
  208. jsonErr := json.Unmarshal(resByte, &alarmSnapshotRes)
  209. if jsonErr != nil {
  210. return nil, fmt.Errorf("[QueryAlarmSnapshotInfo] %s", jsonErr)
  211. }
  212. if alarmSnapshotRes.Code != 200 {
  213. return nil, fmt.Errorf("[QueryAlarmSnapshotInfo] 查询失败 code: %d, message: %s", alarmSnapshotRes.Code, alarmSnapshotRes.Message)
  214. }
  215. if alarmSnapshotRes.Total > 10000 {
  216. return nil, fmt.Errorf("[QueryAlarmSnapshotInfo] 数据超过10000条")
  217. }
  218. infoList = append(infoList, alarmSnapshotRes.Result...)
  219. if alarmSnapshotRes.Total <= uint64(page*int(REQ_PAGE_SIZE)) {
  220. break
  221. }
  222. page++
  223. }
  224. return infoList, nil
  225. }