125 lines
3.4 KiB
Go
125 lines
3.4 KiB
Go
package models
|
|
|
|
import (
|
|
"database/sql/driver"
|
|
"errors"
|
|
"gorm.io/gorm"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type SensorType uint
|
|
|
|
const (
|
|
Temperature SensorType = iota + 1 // to allow gorm: not null
|
|
Humidity
|
|
Pressure
|
|
Gas
|
|
CO2
|
|
)
|
|
|
|
func (s SensorType) IsValid() bool {
|
|
switch s {
|
|
case Temperature, Humidity, Pressure, Gas, CO2:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
type Position struct {
|
|
X int `json:"x"`
|
|
Y int `json:"y"`
|
|
NotNull bool `json:"-"` // to allow gorm: not null with x/y = 0
|
|
}
|
|
|
|
type Sensor struct {
|
|
ID uint `json:"id" gorm:"primaryKey"`
|
|
CreatedAt time.Time `json:"-"`
|
|
UpdatedAt time.Time `json:"-"`
|
|
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
|
Name string `json:"name" gorm:"uniqueIndex;not null;default:null"`
|
|
SensorType SensorType `json:"sensor_type" gorm:"not null;default:null"`
|
|
Position Position `json:"position" gorm:"not null;default:null"`
|
|
}
|
|
|
|
type Measurement struct {
|
|
ID uint `json:"id" gorm:"primaryKey"`
|
|
CreatedAt time.Time `json:"time"` // TODO: change to datetime2
|
|
UpdatedAt time.Time `json:"-"` // TODO: remove
|
|
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"` // TODO: remove
|
|
SensorID uint `json:"sensor_id" gorm:"<-:create;not null;default:null"`
|
|
Sensor Sensor `json:"-"`
|
|
Value float64 `json:"value" gorm:"<-:create;default:null"` // TODO on migrate set column NOT NULL
|
|
}
|
|
|
|
func (s Sensor) IsValid() bool {
|
|
return s.SensorType.IsValid()
|
|
}
|
|
|
|
func (p Position) Value() (driver.Value, error) {
|
|
return strconv.FormatInt(int64(p.X), 10) + "." + strconv.FormatInt(int64(p.Y), 10), nil
|
|
}
|
|
|
|
func (p *Position) Scan(value interface{}) error {
|
|
p.X = 0
|
|
p.Y = 0
|
|
p.NotNull = true
|
|
positionString, isString := value.(string)
|
|
if !isString {
|
|
return errors.New("invalid scan value")
|
|
}
|
|
positionArray := strings.Split(positionString, ".")
|
|
if len(positionArray) != 2 {
|
|
return errors.New("invalid string value")
|
|
}
|
|
var err error
|
|
var position int64
|
|
position, err = strconv.ParseInt(positionArray[0], 10, 32)
|
|
if err != nil {
|
|
return errors.New("invalid x value")
|
|
}
|
|
p.X = int(position)
|
|
position, err = strconv.ParseInt(positionArray[1], 10, 32)
|
|
if err != nil {
|
|
return errors.New("invalid y value")
|
|
}
|
|
p.Y = int(position)
|
|
return nil
|
|
}
|
|
|
|
// http -v POST localhost:8080/sensors name="sensor_$RANDOM" sensor_type:=1 position:='{"x":1, "y":2}'
|
|
// http -v POST localhost:8080/sensors name="sensor_$RANDOM" sensor_type:=2
|
|
func (m Model) AddSensor(sensor Sensor) (uint, error) {
|
|
sensor.ID = 0
|
|
sensor.Position.NotNull = true
|
|
if !sensor.SensorType.IsValid() {
|
|
return 0, errors.New("invalid sensor type")
|
|
}
|
|
result := m.app.Db().Create(&sensor)
|
|
return sensor.ID, result.Error
|
|
}
|
|
|
|
func (m Model) UpdateSensor(sensor Sensor, txSensor Sensor, tx *gorm.DB) (uint, error) {
|
|
sensor.ID = txSensor.ID
|
|
sensor.Position.NotNull = true
|
|
if !sensor.SensorType.IsValid() {
|
|
return 0, errors.New("invalid sensor type")
|
|
}
|
|
result := tx.Updates(&sensor)
|
|
return sensor.ID, result.Error
|
|
}
|
|
|
|
// http -v POST localhost:8080/measurements sensor_id:=3 value:=32
|
|
// http -v GET localhost:8080/measurements/3
|
|
func (m Model) AddMeasurement(measurement Measurement) (uint, error) {
|
|
measurement.ID = 0
|
|
err := m.app.Db().First(&Sensor{}, measurement.SensorID).Error
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
result := m.app.Db().Create(&measurement)
|
|
return measurement.ID, result.Error
|
|
}
|