package logfile import ( "encoding/json" "fmt" "io/ioutil" "log" "os" "path/filepath" "strconv" "time" "github.com/go-flucky/flucky/pkg/types" ) type jsonLogfile struct { logfile string } func (jl *jsonLogfile) Append(compression bool, measuredValues []types.MeasuredValue) error { allMeasuredValues, err := jl.Read() if err != nil { return err } allMeasuredValues = append(allMeasuredValues, measuredValues...) err = jl.Write(allMeasuredValues) if err != nil { return err } return nil } func (jl *jsonLogfile) Read() ([]types.MeasuredValue, error) { if _, err := os.Stat(jl.logfile); os.IsNotExist(err) { return nil, fmt.Errorf("%v: %v", errorLogfileNotFound, jl.logfile) } unmarshaledMeasuredValues := make([]interface{}, 0) bytes, err := ioutil.ReadFile(jl.logfile) if err != nil { return nil, fmt.Errorf("%v %v: %v", errorLogfileRead, jl.logfile, err) } err = json.Unmarshal(bytes, &unmarshaledMeasuredValues) if err != nil { return nil, fmt.Errorf("%v %v: %v", errorLogfileUnmarshal, jl.logfile, err) } measuredValues := make([]types.MeasuredValue, 0) for _, unmarshaledMeasuredValue := range unmarshaledMeasuredValues { mappedMeasuredValue, ok := unmarshaledMeasuredValue.(map[string]interface{}) if !ok { log.Println("Can not parse into map") continue } if _, ok := mappedMeasuredValue["temperature_id"]; ok { temperature, err := jl.transformTemperature(mappedMeasuredValue) if err != nil { log.Printf("Can not unmarshal temperature from map: %v", err) continue } measuredValues = append(measuredValues, temperature) } if _, ok := mappedMeasuredValue["humidity_id"]; ok { humidity, err := jl.transformHumidity(mappedMeasuredValue) if err != nil { log.Printf("Can not unmarshal humidity from map: %v", err) continue } measuredValues = append(measuredValues, humidity) } } return measuredValues, nil } func (jl *jsonLogfile) transformHumidity(mappedMeasuredValue map[string]interface{}) (types.MeasuredValue, error) { humidity := &types.Humidity{ HumidityID: mappedMeasuredValue["humidity_id"].(string), SensorID: mappedMeasuredValue["sensor_id"].(string), CreationDate: nil, UpdateDate: nil, } humidityValue, err := strconv.ParseFloat(mappedMeasuredValue["humidity_value"].(string), 64) if err != nil { return nil, fmt.Errorf("%v for humidity value. HumidityID %v: %v", errorParseFloat, mappedMeasuredValue["humidity_id"].(string), err) } humidity.HumidityValue = humidityValue humidityFromDate, err := time.Parse(timeFormat, mappedMeasuredValue["humidity_from_date"].(string)) if err != nil { return nil, fmt.Errorf("%v for humidity from date. HumidityID %v: %v", errorParseTime, mappedMeasuredValue["humidity_id"].(string), err) } humidity.HumidityFromDate = humidityFromDate humidityTillDate, err := time.Parse(timeFormat, mappedMeasuredValue["humidity_till_date"].(string)) if err != nil { return nil, fmt.Errorf("%v for humidity till date. HumidityID %v: %v", errorParseTime, mappedMeasuredValue["humidity_id"].(string), err) } humidity.HumidityTillDate = humidityTillDate if mappedMeasuredValue["creation_date"] != nil { creationDate, err := time.Parse(timeFormat, mappedMeasuredValue["creation_date"].(string)) if err != nil { return nil, fmt.Errorf("%v for creation date. HumidityID %v: %v", errorParseTime, mappedMeasuredValue["humidity_id"].(string), err) } humidity.CreationDate = &creationDate } if mappedMeasuredValue["update_date"] != nil { updateDate, err := time.Parse(timeFormat, mappedMeasuredValue["update_date"].(string)) if err != nil { return nil, fmt.Errorf("%v for update date. HumidityID %v: %v", errorParseTime, mappedMeasuredValue["humidity_id"].(string), err) } humidity.UpdateDate = &updateDate } return humidity, nil } func (jl *jsonLogfile) transformTemperature(mappedMeasuredValue map[string]interface{}) (types.MeasuredValue, error) { temperature := &types.Temperature{ TemperatureID: mappedMeasuredValue["temperature_id"].(string), SensorID: mappedMeasuredValue["sensor_id"].(string), CreationDate: nil, UpdateDate: nil, } temperatureValue, err := strconv.ParseFloat(mappedMeasuredValue["temperature_value"].(string), 64) if err != nil { return nil, fmt.Errorf("%v for temperature value. TemperatureID %v: %v", errorParseFloat, mappedMeasuredValue["temperature_id"].(string), err) } temperature.TemperatureValue = temperatureValue temperatureFromDate, err := time.Parse(timeFormat, mappedMeasuredValue["temperature_from_date"].(string)) if err != nil { return nil, fmt.Errorf("%v for temperature from date. TemperatureID %v: %v", errorParseTime, mappedMeasuredValue["temperature_id"].(string), err) } temperature.TemperatureFromDate = temperatureFromDate temperatureTillDate, err := time.Parse(timeFormat, mappedMeasuredValue["temperature_till_date"].(string)) if err != nil { return nil, fmt.Errorf("%v for temperature till date. TemperatureID %v: %v", errorParseTime, mappedMeasuredValue["temperature_id"].(string), err) } temperature.TemperatureTillDate = temperatureTillDate if mappedMeasuredValue["creation_date"] != nil { creationDate, err := time.Parse(timeFormat, mappedMeasuredValue["creation_date"].(string)) if err != nil { return nil, fmt.Errorf("%v for creation date. TemperatureID %v: %v", errorParseTime, mappedMeasuredValue["temperature_id"].(string), err) } temperature.CreationDate = &creationDate } if mappedMeasuredValue["update_date"] != nil { updateDate, err := time.Parse(timeFormat, mappedMeasuredValue["update_date"].(string)) if err != nil { return nil, fmt.Errorf("%v for update date. TemperatureID %v: %v", errorParseTime, mappedMeasuredValue["temperature_id"].(string), err) } temperature.UpdateDate = &updateDate } return temperature, nil } func (jl *jsonLogfile) Write(measuredValues []types.MeasuredValue) error { if _, err := os.Stat(filepath.Dir(jl.logfile)); os.IsNotExist(err) { if err := os.MkdirAll(filepath.Dir(jl.logfile), 755); err != nil { return fmt.Errorf("Directory for the logfile can not be created: %v", err) } } f, err := os.Create(jl.logfile) if err != nil { return fmt.Errorf("%v %v: %v", errorLogfileCreate, jl.logfile, err) } jsonEncoder := json.NewEncoder(f) jsonEncoder.SetIndent("", " ") err = jsonEncoder.Encode(measuredValues) if err != nil { return fmt.Errorf("%v %v: %v", errorLogfileEncode, jl.logfile, err) } return nil }