data.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package iotLog
  2. import (
  3. "IotAdmin/core/sdk/config"
  4. "IotAdmin/core/tools/writer"
  5. iotStruct "IotAdmin/iot/struct"
  6. "encoding/json"
  7. "fmt"
  8. "log"
  9. "os"
  10. "path/filepath"
  11. "strings"
  12. "time"
  13. )
  14. func init() {
  15. mp = make(map[string]*writer.FileWriter)
  16. }
  17. // LogData 记录数据日志
  18. func LogData(data *iotStruct.CollectData, cfg *iotStruct.ReportConfig, dataStr *string) {
  19. output := getWrite(data)
  20. logData := &iotStruct.LogData{
  21. Time: time.Now().Format("20060102150400"),
  22. No: data.SlaveConfig.No,
  23. Data: *data,
  24. ReportHost: cfg.Host,
  25. ReportProtocol: cfg.Protocol,
  26. ReportMn: cfg.MN,
  27. ReportUser: cfg.User,
  28. ReportPwd: cfg.Pwd,
  29. ReportStr: *dataStr,
  30. }
  31. str, err := json.Marshal(logData)
  32. if err != nil {
  33. log.Printf("Report Log Marshal error: %s \r\n", err.Error())
  34. return
  35. }
  36. _, err = output.Write(str)
  37. if err != nil {
  38. log.Printf("Report Log Write error: %s \r\n", err.Error())
  39. return
  40. }
  41. _, err = output.Write([]byte("\r\n"))
  42. }
  43. var mp map[string]*writer.FileWriter
  44. func getWrite(data *iotStruct.CollectData) *writer.FileWriter {
  45. path := getDataLogPath()
  46. path += strings.ReplaceAll(data.SlaveConfig.No, "_", "/")
  47. var output *writer.FileWriter
  48. var ok bool
  49. if output, ok = mp[path]; !ok {
  50. var err error
  51. output, err = writer.NewFileWriter(
  52. writer.WithPath(path),
  53. // 不切割文件
  54. writer.WithCap(0),
  55. writer.WithSuffix("data"),
  56. writer.WithTimeFormat("2006010215"),
  57. )
  58. if err != nil {
  59. log.Printf("Report Log setup error: %s \r\n", err.Error())
  60. }
  61. mp[path] = output
  62. }
  63. return output
  64. }
  65. func getDataLogPath() string {
  66. path := config.ApplicationConfig.DataLogFile
  67. if path == "" {
  68. path = "./_data/iot/"
  69. } else if path[len(path)-1] != '/' {
  70. path += "/"
  71. }
  72. return path
  73. }
  74. func GetLastData(sn string) (*iotStruct.LogData, error) {
  75. path := getDataLogPath()
  76. path += strings.ReplaceAll(sn, "_", "/")
  77. dirPath := path
  78. latestFilePath, err := getLatestFilePath(dirPath)
  79. if err != nil {
  80. return nil, err
  81. }
  82. bytes, err := os.ReadFile(latestFilePath)
  83. if err != nil {
  84. return nil, err
  85. }
  86. str := string(bytes)
  87. arr := strings.Split(str, "\r\n")
  88. if len(arr) < 1 {
  89. return nil, fmt.Errorf("数据为空")
  90. }
  91. dataStr := arr[len(arr)-1]
  92. if dataStr == "" {
  93. return nil, fmt.Errorf("未采集到数据或数据解析失败")
  94. }
  95. data := &iotStruct.LogData{}
  96. if err = json.Unmarshal([]byte(dataStr), data); err != nil {
  97. return nil, err
  98. }
  99. return data, nil
  100. }
  101. // getLatestFilePath 返回给定目录中最新被修改的文件的路径。
  102. // 如果目录不存在或者不是一个目录,或者发生任何错误,函数将返回相应的错误信息。
  103. func getLatestFilePath(dirPath string) (string, error) {
  104. // 判断目录是否存在
  105. info, err := os.Stat(dirPath)
  106. if err != nil {
  107. if os.IsNotExist(err) {
  108. return "", fmt.Errorf("目录 %s 不存在", dirPath)
  109. }
  110. return "", fmt.Errorf("获取目录信息失败: %w", err)
  111. }
  112. if !info.IsDir() {
  113. return "", fmt.Errorf("%s 不是目录", dirPath)
  114. }
  115. // 查找目录下最新修改的文件
  116. var latestModTime time.Time
  117. var latestFilePath string
  118. files, err := os.ReadDir(dirPath) // 更新为使用os.ReadDir代替ioutil.ReadDir
  119. if err != nil {
  120. return "", fmt.Errorf("读取目录失败: %w", err)
  121. }
  122. for _, f := range files {
  123. file, err := f.Info()
  124. if err != nil {
  125. return "", fmt.Errorf("获取文件信息失败: %w", err)
  126. }
  127. if !file.Mode().IsRegular() {
  128. continue // 跳过非普通文件(如目录、符号链接等)
  129. }
  130. fileModTime := file.ModTime()
  131. if fileModTime.After(latestModTime) {
  132. latestModTime = fileModTime
  133. latestFilePath = filepath.Join(dirPath, file.Name())
  134. }
  135. }
  136. // 确保找到的文件是有效的普通文件
  137. fileInfo, err := os.Stat(latestFilePath)
  138. if err != nil {
  139. return "", fmt.Errorf("获取文件信息失败: %s: %w", latestFilePath, err)
  140. }
  141. if !fileInfo.Mode().IsRegular() {
  142. return "", fmt.Errorf("%s 不是普通文件", latestFilePath)
  143. }
  144. return latestFilePath, nil
  145. }