package storage import ( "fmt" "math/rand" "net/url" "strconv" "time" "github.com/google/uuid" ) type SensorValueType string const ( Temperature SensorValueType = "temperature" Pressure SensorValueType = "pressure" Humidity SensorValueType = "humidity" Co2Level SensorValueType = "co2level" ) func GetSensorValueTypes() []SensorValueType { return []SensorValueType{Temperature, Pressure, Humidity, Co2Level} } //WeatherStorage interface for different storage-implementations of weather data type WeatherStorage interface { Save(WeatherData) error GetData(*WeatherQuery) ([]*WeatherData, error) Close() error } type SensorRegistry interface { RegisterSensorByName(string) (*WeatherSensor, error) ExistSensor(*WeatherSensor) (bool, error) ResolveSensorById(uuid.UUID) (*WeatherSensor, error) GetSensors() ([]*WeatherSensor, error) Close() error } //WeatherData type type WeatherData struct { Values map[SensorValueType]float64 SensorId uuid.UUID `json:"sensorId"` TimeStamp time.Time `json:"timestamp"` } func (data *WeatherData) OnlyQueriedValues(query *WeatherQuery) *WeatherData { for _, sensorValueType := range GetSensorValueTypes() { if !query.Values[sensorValueType] { delete(data.Values, sensorValueType) } } return data } func (data *WeatherData) ToStringMap() map[string]string { mappedData := map[string]string{ "sensorId": data.SensorId.String(), "timeStamp": data.TimeStamp.String(), } for sensorValueType, value := range data.Values { mappedData[string(sensorValueType)] = strconv.FormatFloat(value, 'f', -1, 64) } return mappedData } func GetOnlyQueriedFields(dataPoints []*WeatherData, query *WeatherQuery) []map[string]string { var result []map[string]string for _, data := range dataPoints { result = append(result, data.OnlyQueriedValues(query).ToStringMap()) } return result } //WeatherSensor is the data for a new Sensorregistration type WeatherSensor struct { Name string Id uuid.UUID Location string Longitude float64 Latitude float64 } type WeatherQuery struct { Start time.Time End time.Time SensorId uuid.UUID Values map[SensorValueType]bool } func (query *WeatherQuery) Init() { query.Start = time.Now().Add(-1 * time.Hour * 24 * 14) query.End = time.Now() query.SensorId = uuid.Nil query.Values = make(map[SensorValueType]bool) for _, sensorValueType := range GetSensorValueTypes() { query.Values[sensorValueType] = true } } func ParseFromUrlQuery(query url.Values) (*WeatherQuery, error) { result := new(WeatherQuery) result.Init() start := query.Get("start") end := query.Get("end") if len(start) != 0 { if tval, err := time.Parse(time.RFC3339, start); err == nil { result.Start = tval } else if err != nil { fmt.Println(err) return nil, err } } if len(end) != 0 { if tval, err := time.Parse(time.RFC3339, end); err == nil { result.End = tval } else if err != nil { fmt.Println(err) return nil, err } } for _, sensorValueType := range GetSensorValueTypes() { queryParam := query.Get(string(sensorValueType)) if bval, err := strconv.ParseBool(queryParam); err == nil { result.Values[sensorValueType] = bval } } return result, nil } //NewRandomWeatherData creates random WeatherData with given Location func NewRandomWeatherData(sensorId uuid.UUID) WeatherData { rand.Seed(time.Now().UnixNano()) var data WeatherData data.Values[Humidity] = rand.Float64() * 100 data.Values[Pressure] = rand.Float64()*80 + 960 data.Values[Temperature] = rand.Float64()*40 - 5 data.Values[Co2Level] = rand.Float64()*50 + 375 data.SensorId = sensorId data.TimeStamp = time.Now() return data }