package services import ( "database/sql" "time" ) type SensorValuesService struct { ctx *Context } type sensorValue struct { Timestamp int64 `json:"timestamp"` Value float64 `json:"value"` } func min(a, b int64) int64 { if a < b { return a } return b } func (s *SensorValuesService) Push(sensorId int64, value float64) (int64, error) { res, err := s.ctx.DB.Exec("INSERT INTO sensor_values (timestamp, sensor_id, value) VALUES (?, ?, ?)", time.Now().Unix(), sensorId, value) if err != nil { return 0, err } return res.LastInsertId() } func (s *SensorValuesService) GetList(sensorId int64, from int64, to int64) ([]sensorValue, error) { intervalSize := to - from batchSize := intervalSize if intervalSize > 100*24*60 { batchSize = 24 * 60 } values := make([]sensorValue, 0) current := from for current < to { nextValue := min(to, current+batchSize) batchValues, err := s.getValueItems(sensorId, current, nextValue) if err != nil { return nil, err } sum := 0.0 for _, item := range batchValues { sum += item.Value } values = append(values, sensorValue{Timestamp: int64((nextValue + current) / 2.0), Value: sum / float64(len(batchValues))}) current += batchSize } return values, nil } func (s *SensorValuesService) GetLatest(sensorId int64, to int64) (*sensorValue, error) { var value = sensorValue{} row := s.ctx.DB.QueryRow("SELECT timestamp, value FROM sensor_values WHERE sensor_id = ? AND timestamp < ? ORDER BY timestamp DESC LIMIT 1", sensorId, to) err := row.Scan(&value.Timestamp, &value.Value) if err != nil { return nil, err } return &value, nil } func (s *SensorValuesService) getValueItems(sensorId int64, from int64, to int64) ([]sensorValue, error) { values := make([]sensorValue, 0) rows, err := s.ctx.DB.Query("SELECT timestamp, value FROM sensor_values WHERE sensor_id = ? AND timestamp > ? AND timestamp < ? ORDER BY timestamp ASC", sensorId, from, to) if err != nil { if err == sql.ErrNoRows { return values, nil } return nil, err } defer rows.Close() for rows.Next() { item := sensorValue{} err := rows.Scan(&item.Timestamp, &item.Value) if err != nil { return nil, err } values = append(values, item) } err = rows.Err() if err != nil { return nil, err } return values, nil }