fwh_mqttLog.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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. "strings"
  11. "time"
  12. )
  13. type MqttLogListResponse struct {
  14. Code int `json:"code"`
  15. Message string `json:"message"`
  16. Result []domain.MqttLogItem `json:"result"`
  17. Success bool `json:"success"`
  18. Total uint `json:"total"`
  19. }
  20. type QueryMqttLogParam struct {
  21. SN *string
  22. CmdTypes []domain.MqttCmdType
  23. StartTime *time.Time
  24. EndTime *time.Time
  25. }
  26. // 查询站点信息
  27. func queryMqttLog(param QueryMqttLogParam) ([]byte, error) {
  28. // 构造 query 参数
  29. params := url.Values{}
  30. if param.SN != nil {
  31. params.Add("searchName", *param.SN)
  32. }
  33. if len(param.CmdTypes) > 0 {
  34. cmdTypesStr := make([]string, len(param.CmdTypes))
  35. for i, v := range param.CmdTypes {
  36. cmdTypesStr[i] = string(v) // 转成 string
  37. }
  38. params.Add("cmdTypes", strings.Join(cmdTypesStr, ","))
  39. }
  40. if param.StartTime != nil {
  41. params.Add("startTime", param.StartTime.Format(time.DateTime))
  42. }
  43. if param.EndTime != nil {
  44. params.Add("endTime", param.EndTime.Format(time.DateTime))
  45. }
  46. if param.StartTime != nil || param.EndTime != nil {
  47. params.Add("timeType", "1") // 0-通讯时间 1-设备时间时
  48. }
  49. params.Add("pageSize", strconv.FormatUint(REQ_PAGE_SIZE, 10))
  50. params.Add("pageNum", strconv.Itoa(1))
  51. params.Add("lang", "ZH_CN")
  52. reqUrl := fmt.Sprintf("https://%s/hes-gateway/manage/iotMqttCommlogs", config.FWH_ENERGY)
  53. response, err := FwhHttpGet(reqUrl, params)
  54. if err != nil {
  55. return nil, err
  56. }
  57. return response.Body, nil
  58. }
  59. func queryMqttLogListOnePage(sn string, cmdType domain.MqttCmdType, startTime, endTime time.Time) ([]domain.MqttLogItem, error) {
  60. param := QueryMqttLogParam{
  61. SN: &sn,
  62. CmdTypes: []domain.MqttCmdType{cmdType},
  63. StartTime: &startTime,
  64. EndTime: &endTime,
  65. }
  66. resByte, err := queryMqttLog(param)
  67. if err != nil {
  68. return nil, err
  69. }
  70. var mqttLogRes MqttLogListResponse
  71. // 反序列化(unmarshal)
  72. jsonErr := json.Unmarshal(resByte, &mqttLogRes)
  73. if jsonErr != nil {
  74. return nil, jsonErr
  75. }
  76. if mqttLogRes.Code == 401 {
  77. // TODO 尝试重新登录
  78. return nil, errors.New("certification expired")
  79. }
  80. // 判断是否超出可处理数据上限 10万条数据
  81. if mqttLogRes.Total > 10*10000 {
  82. return nil, fmt.Errorf("超出数据请求上限 - Total: %d (>10万)", mqttLogRes.Total)
  83. }
  84. return mqttLogRes.Result, nil
  85. }
  86. // 从FWH获取MQTT log数据
  87. func QueryMqttLogListOnTimeRange(sn string, cmdType domain.MqttCmdType, startTime, endTime time.Time) ([]domain.MqttLogItem, error) {
  88. // 保证 startTime <= endTime
  89. if startTime.After(endTime) {
  90. return nil, errors.New("startTime > endTime")
  91. }
  92. // 按天拆分时间段
  93. var periods []struct{ Start, End time.Time }
  94. currTime := startTime
  95. for currTime.Before(endTime) {
  96. // 当天结束时间
  97. dayEnd := time.Date(currTime.Year(), currTime.Month(), currTime.Day(), 23, 59, 59, 0, currTime.Location())
  98. // 如果当天结束大于 endTime,使用 endTime
  99. if dayEnd.After(endTime) {
  100. dayEnd = endTime
  101. }
  102. periods = append(periods, struct{ Start, End time.Time }{Start: currTime, End: dayEnd})
  103. // 下一天开始
  104. currTime = dayEnd.Add(time.Second).Truncate(24 * time.Hour)
  105. currTime = time.Date(currTime.Year(), currTime.Month(), currTime.Day(), 0, 0, 0, 0, currTime.Location())
  106. }
  107. // 按天查询
  108. var mqttLogList []domain.MqttLogItem
  109. for _, period := range periods {
  110. var mqttLogRes []domain.MqttLogItem = nil
  111. periodEndTime := period.End
  112. // 检查数据是否超过1000(单次查询上限)
  113. for {
  114. var err error
  115. mqttLogRes, err = queryMqttLogListOnePage(sn, cmdType, period.Start, periodEndTime)
  116. if err != nil {
  117. return nil, err
  118. }
  119. time.Sleep(time.Second) // 延时1s
  120. mqttLogList = append(mqttLogList, mqttLogRes...)
  121. // 判断是否未查完
  122. if len(mqttLogRes) < int(REQ_PAGE_SIZE) {
  123. // 请求完成,退出
  124. break
  125. }
  126. // 跳转时间段,再次请求
  127. // 提取最后一条数据的设备时间
  128. periodEndTime, err = time.Parse(time.DateTime, mqttLogRes[len(mqttLogRes)-1].LogTime)
  129. if err != nil {
  130. return nil, err
  131. }
  132. }
  133. }
  134. return mqttLogList, nil
  135. }