package iotLog import ( "IotAdmin/core/sdk/config" "IotAdmin/core/tools/writer" iotStruct "IotAdmin/iot/struct" "encoding/json" "fmt" "log" "os" "path/filepath" "strings" "time" ) func init() { mp = make(map[string]*writer.FileWriter) } // LogData 记录数据日志 func LogData(data *iotStruct.CollectData, cfg *iotStruct.ReportConfig, dataStr *string) { output := getWrite(data) logData := &iotStruct.LogData{ Time: time.Now().Format("20060102150400"), No: data.SlaveConfig.No, Data: *data, ReportHost: cfg.Host, ReportProtocol: cfg.Protocol, ReportMn: cfg.MN, ReportUser: cfg.User, ReportPwd: cfg.Pwd, ReportStr: *dataStr, } str, err := json.Marshal(logData) if err != nil { log.Printf("Report Log Marshal error: %s \r\n", err.Error()) return } _, err = output.Write(str) if err != nil { log.Printf("Report Log Write error: %s \r\n", err.Error()) return } _, err = output.Write([]byte("\r\n")) } var mp map[string]*writer.FileWriter func getWrite(data *iotStruct.CollectData) *writer.FileWriter { path := getDataLogPath() path += strings.ReplaceAll(data.SlaveConfig.No, "_", "/") var output *writer.FileWriter var ok bool if output, ok = mp[path]; !ok { var err error output, err = writer.NewFileWriter( writer.WithPath(path), // 不切割文件 writer.WithCap(0), writer.WithSuffix("data"), writer.WithTimeFormat("2006010215"), ) if err != nil { log.Printf("Report Log setup error: %s \r\n", err.Error()) } mp[path] = output } return output } func getDataLogPath() string { path := config.ApplicationConfig.DataLogFile if path == "" { path = "./_data/iot/" } else if path[len(path)-1] != '/' { path += "/" } return path } func GetLastData(sn string) (*iotStruct.LogData, error) { path := getDataLogPath() path += strings.ReplaceAll(sn, "_", "/") dirPath := path latestFilePath, err := getLatestFilePath(dirPath) if err != nil { return nil, err } bytes, err := os.ReadFile(latestFilePath) if err != nil { return nil, err } str := string(bytes) arr := strings.Split(str, "\r\n") if len(arr) < 1 { return nil, fmt.Errorf("数据为空") } dataStr := arr[len(arr)-1] if dataStr == "" { return nil, fmt.Errorf("未采集到数据或数据解析失败") } data := &iotStruct.LogData{} if err = json.Unmarshal([]byte(dataStr), data); err != nil { return nil, err } return data, nil } // getLatestFilePath 返回给定目录中最新被修改的文件的路径。 // 如果目录不存在或者不是一个目录,或者发生任何错误,函数将返回相应的错误信息。 func getLatestFilePath(dirPath string) (string, error) { // 判断目录是否存在 info, err := os.Stat(dirPath) if err != nil { if os.IsNotExist(err) { return "", fmt.Errorf("目录 %s 不存在", dirPath) } return "", fmt.Errorf("获取目录信息失败: %w", err) } if !info.IsDir() { return "", fmt.Errorf("%s 不是目录", dirPath) } // 查找目录下最新修改的文件 var latestModTime time.Time var latestFilePath string files, err := os.ReadDir(dirPath) // 更新为使用os.ReadDir代替ioutil.ReadDir if err != nil { return "", fmt.Errorf("读取目录失败: %w", err) } for _, f := range files { file, err := f.Info() if err != nil { return "", fmt.Errorf("获取文件信息失败: %w", err) } if !file.Mode().IsRegular() { continue // 跳过非普通文件(如目录、符号链接等) } fileModTime := file.ModTime() if fileModTime.After(latestModTime) { latestModTime = fileModTime latestFilePath = filepath.Join(dirPath, file.Name()) } } // 确保找到的文件是有效的普通文件 fileInfo, err := os.Stat(latestFilePath) if err != nil { return "", fmt.Errorf("获取文件信息失败: %s: %w", latestFilePath, err) } if !fileInfo.Mode().IsRegular() { return "", fmt.Errorf("%s 不是普通文件", latestFilePath) } return latestFilePath, nil }