fix: implement repository pkg
This commit is contained in:
parent
fb916c94ae
commit
8f1c7b10f7
22
Makefile
22
Makefile
@ -105,7 +105,7 @@ all: ${EXECUTABLE_TARGETS}
|
|||||||
|
|
||||||
# darwin os
|
# darwin os
|
||||||
bin/darwin/386/${EXECUTABLE}: bindata
|
bin/darwin/386/${EXECUTABLE}: bindata
|
||||||
CGO_ENABLED=0 \
|
CGO_ENABLED=1 \
|
||||||
GOOS=darwin \
|
GOOS=darwin \
|
||||||
GOARCH=386 \
|
GOARCH=386 \
|
||||||
GOPROXY=${GOPROXY} \
|
GOPROXY=${GOPROXY} \
|
||||||
@ -113,7 +113,7 @@ bin/darwin/386/${EXECUTABLE}: bindata
|
|||||||
go build -ldflags "-X main.version=${VERSION:v%=%}" -o ${@}
|
go build -ldflags "-X main.version=${VERSION:v%=%}" -o ${@}
|
||||||
|
|
||||||
bin/darwin/amd64/${EXECUTABLE}: bindata
|
bin/darwin/amd64/${EXECUTABLE}: bindata
|
||||||
CGO_ENABLED=0 \
|
CGO_ENABLED=1 \
|
||||||
GOOS=darwin \
|
GOOS=darwin \
|
||||||
GOARCH=amd64 \
|
GOARCH=amd64 \
|
||||||
GOPROXY=${GOPROXY} \
|
GOPROXY=${GOPROXY} \
|
||||||
@ -122,7 +122,7 @@ bin/darwin/amd64/${EXECUTABLE}: bindata
|
|||||||
|
|
||||||
# freebsd os
|
# freebsd os
|
||||||
bin/freebsd/amd64/${EXECUTABLE}: bindata
|
bin/freebsd/amd64/${EXECUTABLE}: bindata
|
||||||
CGO_ENABLED=0 \
|
CGO_ENABLED=1 \
|
||||||
GOOS=freebsd \
|
GOOS=freebsd \
|
||||||
GOARCH=amd64 \
|
GOARCH=amd64 \
|
||||||
GOPROXY=${GOPROXY} \
|
GOPROXY=${GOPROXY} \
|
||||||
@ -131,7 +131,7 @@ bin/freebsd/amd64/${EXECUTABLE}: bindata
|
|||||||
|
|
||||||
# linux os
|
# linux os
|
||||||
bin/linux/386/${EXECUTABLE}: bindata
|
bin/linux/386/${EXECUTABLE}: bindata
|
||||||
CGO_ENABLED=0 \
|
CGO_ENABLED=1 \
|
||||||
GOOS=linux \
|
GOOS=linux \
|
||||||
GOARCH=386 \
|
GOARCH=386 \
|
||||||
GOPROXY=${GOPROXY} \
|
GOPROXY=${GOPROXY} \
|
||||||
@ -139,7 +139,7 @@ bin/linux/386/${EXECUTABLE}: bindata
|
|||||||
go build -ldflags "-X main.version=${VERSION:v%=%}" -o ${@}
|
go build -ldflags "-X main.version=${VERSION:v%=%}" -o ${@}
|
||||||
|
|
||||||
bin/linux/amd64/${EXECUTABLE}: bindata
|
bin/linux/amd64/${EXECUTABLE}: bindata
|
||||||
CGO_ENABLED=0 \
|
CGO_ENABLED=1 \
|
||||||
GOOS=linux \
|
GOOS=linux \
|
||||||
GOARCH=amd64 \
|
GOARCH=amd64 \
|
||||||
GOPROXY=${GOPROXY} \
|
GOPROXY=${GOPROXY} \
|
||||||
@ -147,7 +147,7 @@ bin/linux/amd64/${EXECUTABLE}: bindata
|
|||||||
go build -ldflags "-X main.version=${VERSION:v%=%}" -o ${@}
|
go build -ldflags "-X main.version=${VERSION:v%=%}" -o ${@}
|
||||||
|
|
||||||
bin/linux/arm/5/${EXECUTABLE}: bindata
|
bin/linux/arm/5/${EXECUTABLE}: bindata
|
||||||
CGO_ENABLED=0 \
|
CGO_ENABLED=1 \
|
||||||
GOOS=linux \
|
GOOS=linux \
|
||||||
GOARCH=arm \
|
GOARCH=arm \
|
||||||
GOARM=5 \
|
GOARM=5 \
|
||||||
@ -156,7 +156,7 @@ bin/linux/arm/5/${EXECUTABLE}: bindata
|
|||||||
go build -ldflags "-X main.version=${VERSION:v%=%}" -o ${@}
|
go build -ldflags "-X main.version=${VERSION:v%=%}" -o ${@}
|
||||||
|
|
||||||
bin/linux/arm/7/${EXECUTABLE}: bindata
|
bin/linux/arm/7/${EXECUTABLE}: bindata
|
||||||
CGO_ENABLED=0 \
|
CGO_ENABLED=1 \
|
||||||
GOOS=linux \
|
GOOS=linux \
|
||||||
GOARCH=arm \
|
GOARCH=arm \
|
||||||
GOARM=7 \
|
GOARM=7 \
|
||||||
@ -165,7 +165,7 @@ bin/linux/arm/7/${EXECUTABLE}: bindata
|
|||||||
go build -ldflags "-X main.version=${VERSION:v%=%}" -o ${@}
|
go build -ldflags "-X main.version=${VERSION:v%=%}" -o ${@}
|
||||||
|
|
||||||
bin/tmp/${EXECUTABLE}: bindata
|
bin/tmp/${EXECUTABLE}: bindata
|
||||||
CGO_ENABLED=0 \
|
CGO_ENABLED=1 \
|
||||||
GOPROXY=${GOPROXY} \
|
GOPROXY=${GOPROXY} \
|
||||||
GOPRIVATE=${GOPRIVATE} \
|
GOPRIVATE=${GOPRIVATE} \
|
||||||
go build -ldflags "-X main.version=${VERSION:v%=%}" -o ${@}
|
go build -ldflags "-X main.version=${VERSION:v%=%}" -o ${@}
|
||||||
@ -173,13 +173,13 @@ bin/tmp/${EXECUTABLE}: bindata
|
|||||||
# GO-BINDATA
|
# GO-BINDATA
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
BINDATA_TARGETS := \
|
BINDATA_TARGETS := \
|
||||||
pkg/storage/bindataSQL.go \
|
pkg/repository/db/bindataSQL.go \
|
||||||
|
|
||||||
PHONY+=bindata
|
PHONY+=bindata
|
||||||
bindata: clean ${BINDATA_TARGETS}
|
bindata: clean ${BINDATA_TARGETS}
|
||||||
|
|
||||||
pkg/storage/bindataSQL.go:
|
pkg/repository/db/bindataSQL.go:
|
||||||
go-bindata -pkg storage -o ./pkg/storage/bindataSQL.go pkg/storage/postgres/***
|
go-bindata -pkg db -o ./pkg/repository/db/bindataSQL.go pkg/repository/db/postgres/*** pkg/repository/db/sqlite3/***
|
||||||
|
|
||||||
# TEST
|
# TEST
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
@ -83,7 +83,7 @@ func preRunError(cmd *cobra.Command, args []string) error {
|
|||||||
Name: hostname,
|
Name: hostname,
|
||||||
CreationDate: postgresTimeStamp,
|
CreationDate: postgresTimeStamp,
|
||||||
},
|
},
|
||||||
StorageEndpoint: "file:/var/log/flucky/sqlite.db?cache=shared&mode=memory",
|
StorageEndpoint: "sqlite3:///var/log/flucky/sqlite.db?cache=shared&mode=memory&FKSupport=True",
|
||||||
}
|
}
|
||||||
|
|
||||||
err = config.Write(&cnf, configFile)
|
err = config.Write(&cnf, configFile)
|
||||||
|
@ -2,13 +2,16 @@ package sensor
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
uuid "github.com/satori/go.uuid"
|
uuid "github.com/satori/go.uuid"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/volker-raschek/flucky/pkg/cli"
|
"github.com/volker-raschek/flucky/pkg/cli"
|
||||||
"github.com/volker-raschek/flucky/pkg/config"
|
"github.com/volker-raschek/flucky/pkg/config"
|
||||||
|
"github.com/volker-raschek/flucky/pkg/repository"
|
||||||
"github.com/volker-raschek/flucky/pkg/types"
|
"github.com/volker-raschek/flucky/pkg/types"
|
||||||
|
"github.com/volker-raschek/go-logger/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitCmd initialize all sensor subcommands
|
// InitCmd initialize all sensor subcommands
|
||||||
@ -39,7 +42,7 @@ flucky sensor add --i2c-bus 1 --i2c-address 0x76 wetter-station BME280`,
|
|||||||
disableSensorCmd := &cobra.Command{
|
disableSensorCmd := &cobra.Command{
|
||||||
Use: "disable",
|
Use: "disable",
|
||||||
Short: "Disable Sensor",
|
Short: "Disable Sensor",
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
Example: "flucky sensor disable outdoor",
|
Example: "flucky sensor disable outdoor",
|
||||||
RunE: disableSensor,
|
RunE: disableSensor,
|
||||||
}
|
}
|
||||||
@ -48,7 +51,7 @@ flucky sensor add --i2c-bus 1 --i2c-address 0x76 wetter-station BME280`,
|
|||||||
Use: "enable",
|
Use: "enable",
|
||||||
Short: "Enable Sensor",
|
Short: "Enable Sensor",
|
||||||
Example: "flucky sensor enable outdoor",
|
Example: "flucky sensor enable outdoor",
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
RunE: enableSensor,
|
RunE: enableSensor,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,10 +67,9 @@ flucky sensor add --i2c-bus 1 --i2c-address 0x76 wetter-station BME280`,
|
|||||||
Short: "Remove Sensor",
|
Short: "Remove Sensor",
|
||||||
Aliases: []string{"rm"},
|
Aliases: []string{"rm"},
|
||||||
Example: "flucky sensor remove outdoor",
|
Example: "flucky sensor remove outdoor",
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
RunE: removeSensor,
|
RunE: removeSensor,
|
||||||
}
|
}
|
||||||
removeSensorCmd.Flags().Bool("definitive", true, "Remove the sensor definitive from the backend")
|
|
||||||
|
|
||||||
renameSensorCmd := &cobra.Command{
|
renameSensorCmd := &cobra.Command{
|
||||||
Use: "rename",
|
Use: "rename",
|
||||||
@ -162,17 +164,34 @@ func addSensor(cmd *cobra.Command, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
storageEndpoint, err := url.Parse(cnf.StorageEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// loglevel, err := cmd.Flags().GetString("loglevel")
|
||||||
|
// if err != nil {
|
||||||
|
// return fmt.Errorf("No loglevel defined")
|
||||||
|
// }
|
||||||
|
|
||||||
|
flogger := logger.NewDefaultLogger(logger.LogLevelDebug)
|
||||||
|
|
||||||
|
repo, err := repository.New(storageEndpoint, flogger)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// add sensor entry to list
|
// add sensor entry to list
|
||||||
err = cnf.AddSensor(sensor)
|
err = repo.AddSensors(sensor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// save new configuration
|
// save new configuration
|
||||||
err = config.Write(cnf, configFile)
|
// err = config.Write(cnf, configFile)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -189,17 +208,24 @@ func disableSensor(cmd *cobra.Command, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cnf.DisableSensor(args[0])
|
storageEndpoint, err := url.Parse(cnf.StorageEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = config.Write(cnf, configFile)
|
// loglevel, err := cmd.Flags().GetString("loglevel")
|
||||||
|
// if err != nil {
|
||||||
|
// return fmt.Errorf("No loglevel defined")
|
||||||
|
// }
|
||||||
|
|
||||||
|
flogger := logger.NewDefaultLogger(logger.LogLevelDebug)
|
||||||
|
|
||||||
|
repo, err := repository.New(storageEndpoint, flogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return repo.DisableSensorsByNames(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func enableSensor(cmd *cobra.Command, args []string) error {
|
func enableSensor(cmd *cobra.Command, args []string) error {
|
||||||
@ -214,16 +240,24 @@ func enableSensor(cmd *cobra.Command, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cnf.EnableSensor(args[0])
|
storageEndpoint, err := url.Parse(cnf.StorageEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = config.Write(cnf, configFile)
|
// loglevel, err := cmd.Flags().GetString("loglevel")
|
||||||
|
// if err != nil {
|
||||||
|
// return fmt.Errorf("No loglevel defined")
|
||||||
|
// }
|
||||||
|
|
||||||
|
flogger := logger.NewDefaultLogger(logger.LogLevelDebug)
|
||||||
|
|
||||||
|
repo, err := repository.New(storageEndpoint, flogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
return repo.EnableSensorsByNames(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func listSensors(cmd *cobra.Command, args []string) error {
|
func listSensors(cmd *cobra.Command, args []string) error {
|
||||||
@ -238,12 +272,30 @@ func listSensors(cmd *cobra.Command, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cli.PrintSensors(cnf, os.Stdout)
|
storageEndpoint, err := url.Parse(cnf.StorageEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = config.Write(cnf, configFile)
|
// loglevel, err := cmd.Flags().GetString("loglevel")
|
||||||
|
// if err != nil {
|
||||||
|
// return fmt.Errorf("No loglevel defined")
|
||||||
|
// }
|
||||||
|
|
||||||
|
flogger := logger.NewDefaultLogger(logger.LogLevelDebug)
|
||||||
|
|
||||||
|
repo, err := repository.New(storageEndpoint, flogger)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// add sensor entry to list
|
||||||
|
sensors, err := repo.GetSensors()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = cli.PrintSensors(sensors, os.Stdout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -258,27 +310,29 @@ func removeSensor(cmd *cobra.Command, args []string) error {
|
|||||||
return fmt.Errorf("No config file defined")
|
return fmt.Errorf("No config file defined")
|
||||||
}
|
}
|
||||||
|
|
||||||
definitive, err := cmd.Flags().GetBool("definitive")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("No config file defined")
|
|
||||||
}
|
|
||||||
|
|
||||||
cnf, err := config.Read(configFile)
|
cnf, err := config.Read(configFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cnf.RemoveSensor(args[0], definitive)
|
storageEndpoint, err := url.Parse(cnf.StorageEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = config.Write(cnf, configFile)
|
// loglevel, err := cmd.Flags().GetString("loglevel")
|
||||||
|
// if err != nil {
|
||||||
|
// return fmt.Errorf("No loglevel defined")
|
||||||
|
// }
|
||||||
|
|
||||||
|
flogger := logger.NewDefaultLogger(logger.LogLevelDebug)
|
||||||
|
|
||||||
|
repo, err := repository.New(storageEndpoint, flogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return repo.RemoveSensorsByNames(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renameSensor(cmd *cobra.Command, args []string) error {
|
func renameSensor(cmd *cobra.Command, args []string) error {
|
||||||
@ -293,15 +347,22 @@ func renameSensor(cmd *cobra.Command, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cnf.RenameSensor(args[0], args[1])
|
storageEndpoint, err := url.Parse(cnf.StorageEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = config.Write(cnf, configFile)
|
// loglevel, err := cmd.Flags().GetString("loglevel")
|
||||||
|
// if err != nil {
|
||||||
|
// return fmt.Errorf("No loglevel defined")
|
||||||
|
// }
|
||||||
|
|
||||||
|
flogger := logger.NewDefaultLogger(logger.LogLevelDebug)
|
||||||
|
|
||||||
|
repo, err := repository.New(storageEndpoint, flogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return repo.RenameSensors(args[0], args[1])
|
||||||
}
|
}
|
||||||
|
1
go.mod
1
go.mod
@ -9,6 +9,7 @@ require (
|
|||||||
github.com/d2r2/go-logger v0.0.0-20181221090742-9998a510495e
|
github.com/d2r2/go-logger v0.0.0-20181221090742-9998a510495e
|
||||||
github.com/go-flucky/go-dht v0.1.1
|
github.com/go-flucky/go-dht v0.1.1
|
||||||
github.com/lib/pq v1.4.0
|
github.com/lib/pq v1.4.0
|
||||||
|
github.com/mattn/go-sqlite3 v1.10.0
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/spf13/cobra v1.0.0
|
github.com/spf13/cobra v1.0.0
|
||||||
github.com/stretchr/testify v1.5.1
|
github.com/stretchr/testify v1.5.1
|
||||||
|
5
go.sum
5
go.sum
@ -70,6 +70,11 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|||||||
github.com/lib/pq v1.4.0 h1:TmtCFbH+Aw0AixwyttznSMQDgbR5Yed/Gg6S8Funrhc=
|
github.com/lib/pq v1.4.0 h1:TmtCFbH+Aw0AixwyttznSMQDgbR5Yed/Gg6S8Funrhc=
|
||||||
github.com/lib/pq v1.4.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.4.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
|
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
|
||||||
|
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
|
github.com/mattn/go-sqlite3 v1.13.0 h1:LnJI81JidiW9r7pS/hXe6cFeO5EXNq7KbfvoJLRI69c=
|
||||||
|
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
|
||||||
|
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
@ -5,18 +5,18 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/volker-raschek/flucky/pkg/config"
|
"github.com/volker-raschek/flucky/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PrintSensors displays a list with all configured sensors
|
// PrintSensors displays a list with all configured sensors
|
||||||
func PrintSensors(cnf *config.Config, w io.Writer) error {
|
func PrintSensors(sensors []*types.Sensor, w io.Writer) error {
|
||||||
|
|
||||||
// declar tabwriter
|
// declar tabwriter
|
||||||
tw := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0)
|
tw := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0)
|
||||||
|
|
||||||
fmt.Fprint(tw, "name\tlocation\ttype\twire-id\ti2c-bus\ti2c-address\tgpio\ttick-duration\tenabled\n")
|
fmt.Fprint(tw, "name\tlocation\ttype\twire-id\ti2c-bus\ti2c-address\tgpio\ttick-duration\tenabled\n")
|
||||||
|
|
||||||
for _, sensor := range cnf.Sensors {
|
for _, sensor := range sensors {
|
||||||
fmt.Fprintf(tw, "%v\t%v\t%v\t", sensor.Name, sensor.Location, sensor.Model)
|
fmt.Fprintf(tw, "%v\t%v\t%v\t", sensor.Name, sensor.Location, sensor.Model)
|
||||||
|
|
||||||
if sensor.WireID != nil {
|
if sensor.WireID != nil {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -10,7 +9,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/volker-raschek/flucky/pkg/internal/format"
|
"github.com/volker-raschek/flucky/pkg/internal/format"
|
||||||
"github.com/volker-raschek/flucky/pkg/storage"
|
|
||||||
|
|
||||||
uuid "github.com/satori/go.uuid"
|
uuid "github.com/satori/go.uuid"
|
||||||
"github.com/volker-raschek/flucky/pkg/types"
|
"github.com/volker-raschek/flucky/pkg/types"
|
||||||
@ -159,12 +157,7 @@ func (cnf *Config) GetSensorByID(id string) *types.Sensor {
|
|||||||
// RemoveSensor deletes a sensor by its name or its unique UUID, If definitive
|
// RemoveSensor deletes a sensor by its name or its unique UUID, If definitive
|
||||||
// is set to true, the sensor will not only be removed in the configuration file
|
// is set to true, the sensor will not only be removed in the configuration file
|
||||||
// but also in the backend.
|
// but also in the backend.
|
||||||
func (cnf *Config) RemoveSensor(name string, definitive bool) error {
|
func (cnf *Config) RemoveSensor(name string) error {
|
||||||
|
|
||||||
backend, err := storage.New(cnf.StorageEndpoint, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, sensor := range cnf.Sensors {
|
for i, sensor := range cnf.Sensors {
|
||||||
// remove machted name
|
// remove machted name
|
||||||
@ -172,13 +165,6 @@ func (cnf *Config) RemoveSensor(name string, definitive bool) error {
|
|||||||
sensor.Name == name {
|
sensor.Name == name {
|
||||||
cnf.Sensors = append(cnf.Sensors[:i], cnf.Sensors[i+1:]...)
|
cnf.Sensors = append(cnf.Sensors[:i], cnf.Sensors[i+1:]...)
|
||||||
|
|
||||||
if definitive {
|
|
||||||
err = backend.RemoveSensorByName(context.Background(), name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// remove machted uuid
|
// remove machted uuid
|
||||||
@ -186,13 +172,6 @@ func (cnf *Config) RemoveSensor(name string, definitive bool) error {
|
|||||||
sensor.ID == name {
|
sensor.ID == name {
|
||||||
cnf.Sensors = append(cnf.Sensors[:i], cnf.Sensors[i+1:]...)
|
cnf.Sensors = append(cnf.Sensors[:i], cnf.Sensors[i+1:]...)
|
||||||
|
|
||||||
if definitive {
|
|
||||||
err = backend.RemoveSensorByID(context.Background(), name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,14 @@ package daemon
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/volker-raschek/flucky/pkg/config"
|
"github.com/volker-raschek/flucky/pkg/config"
|
||||||
|
"github.com/volker-raschek/flucky/pkg/repository/db"
|
||||||
"github.com/volker-raschek/flucky/pkg/sensor"
|
"github.com/volker-raschek/flucky/pkg/sensor"
|
||||||
"github.com/volker-raschek/flucky/pkg/storage"
|
|
||||||
"github.com/volker-raschek/flucky/pkg/types"
|
"github.com/volker-raschek/flucky/pkg/types"
|
||||||
"github.com/volker-raschek/go-logger/pkg/logger"
|
"github.com/volker-raschek/go-logger/pkg/logger"
|
||||||
)
|
)
|
||||||
@ -31,7 +32,12 @@ func Start(cnf *config.Config, flogger logger.Logger) error {
|
|||||||
measuredValueChannel := make(chan *types.MeasuredValue, 0)
|
measuredValueChannel := make(chan *types.MeasuredValue, 0)
|
||||||
|
|
||||||
// load storage endpoint
|
// load storage endpoint
|
||||||
storageEndpoint, err := storage.New(cnf.StorageEndpoint, flogger)
|
storageEndpointURL, err := url.Parse(cnf.StorageEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
backend, err := db.New(storageEndpointURL, flogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -43,18 +49,18 @@ func Start(cnf *config.Config, flogger logger.Logger) error {
|
|||||||
parentCtx := context.Background()
|
parentCtx := context.Background()
|
||||||
|
|
||||||
// Insert device if not exist
|
// Insert device if not exist
|
||||||
device, _ := storageEndpoint.SelectDevice(parentCtx, cnf.Device.ID)
|
device, _ := backend.SelectDevice(parentCtx, cnf.Device.ID)
|
||||||
if device == nil {
|
if device == nil {
|
||||||
if err := storageEndpoint.InsertDevice(parentCtx, cnf.Device); err != nil {
|
if err := backend.InsertDevices(parentCtx, cnf.Device); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert sensors if not exist
|
// Insert sensors if not exist
|
||||||
for _, cnfSensor := range cnf.Sensors {
|
for _, cnfSensor := range cnf.Sensors {
|
||||||
sensor, _ := storageEndpoint.SelectSensor(parentCtx, cnfSensor.ID)
|
sensor, _ := backend.SelectSensor(parentCtx, cnfSensor.ID)
|
||||||
if sensor == nil {
|
if sensor == nil {
|
||||||
if err := storageEndpoint.InsertSensor(parentCtx, cnfSensor); err != nil {
|
if err := backend.InsertSensors(parentCtx, cnfSensor); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,7 +97,7 @@ func Start(cnf *config.Config, flogger logger.Logger) error {
|
|||||||
|
|
||||||
if cap(measuredValues) == len(measuredValues) {
|
if cap(measuredValues) == len(measuredValues) {
|
||||||
flogger.Debug("Flush cache")
|
flogger.Debug("Flush cache")
|
||||||
err := storageEndpoint.InsertMeasuredValues(ctx, measuredValues)
|
err := backend.InsertMeasuredValues(ctx, measuredValues...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flogger.Error("%v", err)
|
flogger.Error("%v", err)
|
||||||
}
|
}
|
||||||
@ -102,7 +108,7 @@ func Start(cnf *config.Config, flogger logger.Logger) error {
|
|||||||
cancel()
|
cancel()
|
||||||
close(measuredValueChannel)
|
close(measuredValueChannel)
|
||||||
|
|
||||||
err := storageEndpoint.InsertMeasuredValues(ctx, measuredValues)
|
err := backend.InsertMeasuredValues(ctx, measuredValues...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flogger.Error("%v", err)
|
flogger.Error("%v", err)
|
||||||
}
|
}
|
||||||
@ -110,6 +116,4 @@ func Start(cnf *config.Config, flogger logger.Logger) error {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
118
pkg/repository/db/db.go
Normal file
118
pkg/repository/db/db.go
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/volker-raschek/flucky/pkg/types"
|
||||||
|
"github.com/volker-raschek/go-logger/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Database is a general interface for a storage endpoint
|
||||||
|
type Database interface {
|
||||||
|
DeleteDevices(ctx context.Context, deviceIDs ...string) error
|
||||||
|
DeleteSensors(ctx context.Context, sensorIDs ...string) error
|
||||||
|
InsertDevices(ctx context.Context, devices ...*types.Device) error
|
||||||
|
InsertMeasuredValues(ctx context.Context, measuredValues ...*types.MeasuredValue) error
|
||||||
|
InsertSensors(ctx context.Context, sensors ...*types.Sensor) error
|
||||||
|
Scheme(ctx context.Context) error
|
||||||
|
SelectDevice(ctx context.Context, deviceID string) (*types.Device, error)
|
||||||
|
SelectDevices(ctx context.Context) ([]*types.Device, error)
|
||||||
|
SelectHumidity(ctx context.Context, id string) (*types.MeasuredValue, error)
|
||||||
|
SelectHumidities(ctx context.Context) ([]*types.MeasuredValue, error)
|
||||||
|
SelectPressure(ctx context.Context, id string) (*types.MeasuredValue, error)
|
||||||
|
SelectPressures(ctx context.Context) ([]*types.MeasuredValue, error)
|
||||||
|
SelectSensor(ctx context.Context, sensorID string) (*types.Sensor, error)
|
||||||
|
SelectSensors(ctx context.Context) ([]*types.Sensor, error)
|
||||||
|
SelectTemperature(ctx context.Context, id string) (*types.MeasuredValue, error)
|
||||||
|
SelectTemperatures(ctx context.Context) ([]*types.MeasuredValue, error)
|
||||||
|
UpdateDevices(ctx context.Context, devices ...*types.Device) error
|
||||||
|
UpdateSensors(ctx context.Context, sensors ...*types.Sensor) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new storage provider
|
||||||
|
func New(storageEndpoint *url.URL, flogger logger.Logger) (Database, error) {
|
||||||
|
|
||||||
|
// Check of nil pointer
|
||||||
|
for _, parameter := range []interface{}{
|
||||||
|
storageEndpoint,
|
||||||
|
flogger,
|
||||||
|
} {
|
||||||
|
if parameter == nil {
|
||||||
|
return nil, fmt.Errorf("Parameter does not be nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load Queryfiles
|
||||||
|
queries := make(map[string]string, 0)
|
||||||
|
for _, asset := range AssetNames() {
|
||||||
|
if !strings.Contains(asset, storageEndpoint.Scheme) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := Asset(asset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
queryFile := filepath.Base(asset)
|
||||||
|
|
||||||
|
queries[queryFile] = string(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
database Database
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
switch storageEndpoint.Scheme {
|
||||||
|
// case "postgres":
|
||||||
|
// // postgres://[user]:[password]@[host]:[port]/[path]?[query]
|
||||||
|
// newDBO, err := sql.Open(storageEndpoint.Scheme, storageEndpoint.String())
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return &Postgres{
|
||||||
|
// dbo: newDBO,
|
||||||
|
// flogger: flogger,
|
||||||
|
// }, nil
|
||||||
|
|
||||||
|
case "sqlite3":
|
||||||
|
|
||||||
|
if _, err := os.Stat(filepath.Dir(storageEndpoint.Path)); os.IsNotExist(err) {
|
||||||
|
err := os.MkdirAll(filepath.Dir(storageEndpoint.Path), 0755)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sqlite3:///[path]?[query] flucky dsn
|
||||||
|
// file:///[path]?[query] sql-lib dsn
|
||||||
|
newDBO, err := sql.Open(storageEndpoint.Scheme, fmt.Sprintf("file://%v?%v", storageEndpoint.Path, storageEndpoint.RawQuery))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
database = &SQLite{
|
||||||
|
dbo: newDBO,
|
||||||
|
flogger: flogger,
|
||||||
|
queries: queries,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("Unsupported database scheme: %v", storageEndpoint.Scheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = database.Scheme(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return database, nil
|
||||||
|
|
||||||
|
}
|
@ -1,28 +1,17 @@
|
|||||||
package storage
|
package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
|
|
||||||
"github.com/volker-raschek/flucky/pkg/types"
|
"github.com/volker-raschek/flucky/pkg/types"
|
||||||
"github.com/volker-raschek/go-logger/pkg/logger"
|
"github.com/volker-raschek/go-logger/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Storage is a general interface for a storage endpoint
|
|
||||||
type Storage interface {
|
|
||||||
InsertDevice(ctx context.Context, device *types.Device) error
|
|
||||||
InsertMeasuredValues(ctx context.Context, measuredValues []*types.MeasuredValue) error
|
|
||||||
InsertSensor(ctx context.Context, sensor *types.Sensor) error
|
|
||||||
RemoveSensorByID(ctx context.Context, sensorID string) error
|
|
||||||
RemoveSensorByName(ctx context.Context, sensorName string) error
|
|
||||||
SelectDevice(ctx context.Context, id string) (*types.Device, error)
|
|
||||||
SelectSensor(ctx context.Context, id string) (*types.Sensor, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
postgresAssetPath = "pkg/storage/postgres"
|
postgresAssetPath = "pkg/storage/postgres"
|
||||||
)
|
)
|
||||||
@ -33,8 +22,70 @@ type Postgres struct {
|
|||||||
flogger logger.Logger
|
flogger logger.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsertDevice into the database
|
// DeleteDevices from the database
|
||||||
func (postgres *Postgres) InsertDevice(ctx context.Context, device *types.Device) error {
|
func (postgres *Postgres) DeleteDevices(ctx context.Context, deviceIDs ...string) error {
|
||||||
|
asset := filepath.Join(postgresAssetPath, "deleteDevice.sql")
|
||||||
|
queryBytes, err := Asset(asset)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to load asset %v: %v", asset, err)
|
||||||
|
}
|
||||||
|
query := string(queryBytes)
|
||||||
|
|
||||||
|
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt, err := tx.Prepare(query)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to prepare statement: %v", err)
|
||||||
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
|
||||||
|
for _, deviceID := range deviceIDs {
|
||||||
|
_, err = stmt.Exec(deviceID)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteSensors from the database
|
||||||
|
func (postgres *Postgres) DeleteSensors(ctx context.Context, sensorIDs ...string) error {
|
||||||
|
asset := filepath.Join(postgresAssetPath, "deleteSensor.sql")
|
||||||
|
queryBytes, err := Asset(asset)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to load asset %v: %v", asset, err)
|
||||||
|
}
|
||||||
|
query := string(queryBytes)
|
||||||
|
|
||||||
|
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt, err := tx.Prepare(query)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to prepare statement: %v", err)
|
||||||
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
|
||||||
|
for _, sensorID := range sensorIDs {
|
||||||
|
_, err = stmt.Exec(sensorID)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
// InsertDevices into the database
|
||||||
|
func (postgres *Postgres) InsertDevices(ctx context.Context, devices ...*types.Device) error {
|
||||||
asset := filepath.Join(postgresAssetPath, "insertDevice.sql")
|
asset := filepath.Join(postgresAssetPath, "insertDevice.sql")
|
||||||
queryBytes, err := Asset(asset)
|
queryBytes, err := Asset(asset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -53,17 +104,19 @@ func (postgres *Postgres) InsertDevice(ctx context.Context, device *types.Device
|
|||||||
}
|
}
|
||||||
defer stmt.Close()
|
defer stmt.Close()
|
||||||
|
|
||||||
|
for _, device := range devices {
|
||||||
_, err = stmt.Exec(&device.ID, &device.Name, &device.Location, &device.CreationDate)
|
_, err = stmt.Exec(&device.ID, &device.Name, &device.Location, &device.CreationDate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
return fmt.Errorf("Failed to execute statement: %v", err)
|
return fmt.Errorf("Failed to execute statement: %v", err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return tx.Commit()
|
return tx.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsertMeasuredValues into the database
|
// InsertMeasuredValues into the database
|
||||||
func (postgres *Postgres) InsertMeasuredValues(ctx context.Context, measuredValues []*types.MeasuredValue) error {
|
func (postgres *Postgres) InsertMeasuredValues(ctx context.Context, measuredValues ...*types.MeasuredValue) error {
|
||||||
splittedMeasuredValues := make(map[string][]*types.MeasuredValue, 0)
|
splittedMeasuredValues := make(map[string][]*types.MeasuredValue, 0)
|
||||||
|
|
||||||
for _, measuredValue := range measuredValues {
|
for _, measuredValue := range measuredValues {
|
||||||
@ -127,8 +180,8 @@ func (postgres *Postgres) InsertMeasuredValues(ctx context.Context, measuredValu
|
|||||||
return tx.Commit()
|
return tx.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsertSensor into the database
|
// InsertSensors into the database
|
||||||
func (postgres *Postgres) InsertSensor(ctx context.Context, sensor *types.Sensor) error {
|
func (postgres *Postgres) InsertSensors(ctx context.Context, sensors ...*types.Sensor) error {
|
||||||
asset := filepath.Join(postgresAssetPath, "insertSensor.sql")
|
asset := filepath.Join(postgresAssetPath, "insertSensor.sql")
|
||||||
queryBytes, err := Asset(asset)
|
queryBytes, err := Asset(asset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -147,68 +200,12 @@ func (postgres *Postgres) InsertSensor(ctx context.Context, sensor *types.Sensor
|
|||||||
}
|
}
|
||||||
defer stmt.Close()
|
defer stmt.Close()
|
||||||
|
|
||||||
|
for _, sensor := range sensors {
|
||||||
_, err = stmt.Exec(&sensor.ID, &sensor.Name, &sensor.Location, &sensor.WireID, &sensor.I2CBus, &sensor.I2CAddress, &sensor.GPIONumber, &sensor.Model, &sensor.Enabled, &sensor.DeviceID, &sensor.CreationDate)
|
_, err = stmt.Exec(&sensor.ID, &sensor.Name, &sensor.Location, &sensor.WireID, &sensor.I2CBus, &sensor.I2CAddress, &sensor.GPIONumber, &sensor.Model, &sensor.Enabled, &sensor.DeviceID, &sensor.CreationDate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
return fmt.Errorf("Failed to execute statement: %v", err)
|
return fmt.Errorf("Failed to execute statement: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return tx.Commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveSensorByID from the database
|
|
||||||
func (postgres *Postgres) RemoveSensorByID(ctx context.Context, sensorID string) error {
|
|
||||||
asset := filepath.Join(postgresAssetPath, "removeSensorByID.sql")
|
|
||||||
queryBytes, err := Asset(asset)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Failed to load asset %v: %v", asset, err)
|
|
||||||
}
|
|
||||||
query := string(queryBytes)
|
|
||||||
|
|
||||||
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Failed to begin new transaction: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt, err := tx.Prepare(query)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Failed to prepare statement: %v", err)
|
|
||||||
}
|
|
||||||
defer stmt.Close()
|
|
||||||
|
|
||||||
_, err = stmt.Exec(sensorID)
|
|
||||||
if err != nil {
|
|
||||||
tx.Rollback()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return tx.Commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveSensorByName from the database
|
|
||||||
func (postgres *Postgres) RemoveSensorByName(ctx context.Context, sensorID string) error {
|
|
||||||
asset := filepath.Join(postgresAssetPath, "removeSensorByName.sql")
|
|
||||||
queryBytes, err := Asset(asset)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Failed to load asset %v: %v", asset, err)
|
|
||||||
}
|
|
||||||
query := string(queryBytes)
|
|
||||||
|
|
||||||
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Failed to begin new transaction: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt, err := tx.Prepare(query)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Failed to prepare statement: %v", err)
|
|
||||||
}
|
|
||||||
defer stmt.Close()
|
|
||||||
|
|
||||||
_, err = stmt.Exec(sensorID)
|
|
||||||
if err != nil {
|
|
||||||
tx.Rollback()
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return tx.Commit()
|
return tx.Commit()
|
||||||
@ -216,7 +213,7 @@ func (postgres *Postgres) RemoveSensorByName(ctx context.Context, sensorID strin
|
|||||||
|
|
||||||
// SelectDevice from database
|
// SelectDevice from database
|
||||||
func (postgres *Postgres) SelectDevice(ctx context.Context, id string) (*types.Device, error) {
|
func (postgres *Postgres) SelectDevice(ctx context.Context, id string) (*types.Device, error) {
|
||||||
asset := filepath.Join(postgresAssetPath, "selectDeviceByID.sql")
|
asset := filepath.Join(postgresAssetPath, "selectDevice.sql")
|
||||||
queryBytes, err := Asset(asset)
|
queryBytes, err := Asset(asset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Failed to load asset %v: %v", asset, err)
|
return nil, fmt.Errorf("Failed to load asset %v: %v", asset, err)
|
||||||
@ -242,12 +239,60 @@ func (postgres *Postgres) SelectDevice(ctx context.Context, id string) (*types.D
|
|||||||
return nil, fmt.Errorf("Failed to scan row: %v", err)
|
return nil, fmt.Errorf("Failed to scan row: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to commit transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
return device, nil
|
return device, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SelectDevices from the database
|
||||||
|
func (postgres *Postgres) SelectDevices(ctx context.Context) ([]*types.Device, error) {
|
||||||
|
asset := filepath.Join(postgresAssetPath, "selectDevices.sql")
|
||||||
|
queryBytes, err := Asset(asset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to load asset %v: %v", asset, err)
|
||||||
|
}
|
||||||
|
query := string(queryBytes)
|
||||||
|
|
||||||
|
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt, err := tx.Prepare(query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to prepare statement: %v", err)
|
||||||
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
|
||||||
|
rows, err := stmt.Query()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to query statement: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
devices := make([]*types.Device, 0)
|
||||||
|
for rows.Next() {
|
||||||
|
device := new(types.Device)
|
||||||
|
err = rows.Scan(&device.ID, &device.Name, &device.Location, &device.CreationDate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to scan row: %v", err)
|
||||||
|
}
|
||||||
|
devices = append(devices, device)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to commit transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return devices, nil
|
||||||
|
}
|
||||||
|
|
||||||
// SelectSensor from database
|
// SelectSensor from database
|
||||||
func (postgres *Postgres) SelectSensor(ctx context.Context, id string) (*types.Sensor, error) {
|
func (postgres *Postgres) SelectSensor(ctx context.Context, id string) (*types.Sensor, error) {
|
||||||
asset := filepath.Join(postgresAssetPath, "selectSensorByID.sql")
|
asset := filepath.Join(postgresAssetPath, "selectSensor.sql")
|
||||||
queryBytes, err := Asset(asset)
|
queryBytes, err := Asset(asset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Failed to load asset %v: %v", asset, err)
|
return nil, fmt.Errorf("Failed to load asset %v: %v", asset, err)
|
||||||
@ -273,28 +318,63 @@ func (postgres *Postgres) SelectSensor(ctx context.Context, id string) (*types.S
|
|||||||
return nil, fmt.Errorf("Failed to scan row: %v", err)
|
return nil, fmt.Errorf("Failed to scan row: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to commit transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
return sensor, nil
|
return sensor, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new storage provider
|
// SelectSensors from the database
|
||||||
func New(storageEndpoint string, flogger logger.Logger) (Storage, error) {
|
func (postgres *Postgres) SelectSensors(ctx context.Context) ([]*types.Sensor, error) {
|
||||||
storageEndpointURL, err := url.Parse(storageEndpoint)
|
asset := filepath.Join(postgresAssetPath, "selectSensors.sql")
|
||||||
|
queryBytes, err := Asset(asset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("Failed to load asset %v: %v", asset, err)
|
||||||
|
}
|
||||||
|
query := string(queryBytes)
|
||||||
|
|
||||||
|
tx, err := postgres.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch storageEndpointURL.Scheme {
|
stmt, err := tx.Prepare(query)
|
||||||
case "postgres":
|
|
||||||
newDBO, err := sql.Open(storageEndpointURL.Scheme, storageEndpointURL.String())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("Failed to prepare statement: %v", err)
|
||||||
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
|
||||||
|
rows, err := stmt.Query()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to query statement: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Postgres{
|
sensors := make([]*types.Sensor, 0)
|
||||||
dbo: newDBO,
|
for rows.Next() {
|
||||||
flogger: flogger,
|
sensor := new(types.Sensor)
|
||||||
}, nil
|
err = rows.Scan(&sensor.ID, &sensor.Name, &sensor.Location, &sensor.WireID, &sensor.I2CBus, &sensor.I2CAddress, &sensor.GPIONumber, &sensor.Model, &sensor.Enabled, &sensor.DeviceID, &sensor.CreationDate)
|
||||||
default:
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Unsupported database scheme: %v", storageEndpointURL.Scheme)
|
return nil, fmt.Errorf("Failed to scan row: %v", err)
|
||||||
}
|
}
|
||||||
|
sensors = append(sensors, sensor)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to commit transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sensors, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateDevices updates a device in the database
|
||||||
|
func (postgres *Postgres) UpdateDevices(ctx context.Context, devices ...*types.Device) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateSensors updates a sensor in the database
|
||||||
|
func (postgres *Postgres) UpdateSensors(ctx context.Context, sensor ...*types.Sensor) error {
|
||||||
|
return nil
|
||||||
}
|
}
|
2
pkg/repository/db/postgres/deleteDevice.sql
Normal file
2
pkg/repository/db/postgres/deleteDevice.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
DELETE FROM sensors
|
||||||
|
WHERE device_id = $1;
|
7
pkg/repository/db/postgres/selectDevices.sql
Normal file
7
pkg/repository/db/postgres/selectDevices.sql
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
SELECT
|
||||||
|
device_id,
|
||||||
|
device_name,
|
||||||
|
device_location,
|
||||||
|
creation_date
|
||||||
|
FROM
|
||||||
|
devices;
|
14
pkg/repository/db/postgres/selectSensors.sql
Normal file
14
pkg/repository/db/postgres/selectSensors.sql
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
SELECT
|
||||||
|
sensor_id,
|
||||||
|
sensor_name,
|
||||||
|
sensor_location,
|
||||||
|
wire_id,
|
||||||
|
i2c_bus,
|
||||||
|
i2c_address,
|
||||||
|
gpio_number,
|
||||||
|
sensor_model,
|
||||||
|
sensor_enabled,
|
||||||
|
device_id,
|
||||||
|
creation_date
|
||||||
|
FROM
|
||||||
|
sensors;
|
8
pkg/repository/db/postgres/updateDevice.sql
Normal file
8
pkg/repository/db/postgres/updateDevice.sql
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
UPDATE device
|
||||||
|
SET
|
||||||
|
device_id = $1,
|
||||||
|
device_name = $2,
|
||||||
|
device_location = $3,
|
||||||
|
creation_date = $4
|
||||||
|
WHERE
|
||||||
|
device_id = $5,
|
15
pkg/repository/db/postgres/updateSensor.sql
Normal file
15
pkg/repository/db/postgres/updateSensor.sql
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
UPDATE sensors
|
||||||
|
SET
|
||||||
|
sensor_id = $1,
|
||||||
|
sensor_name = $2,
|
||||||
|
sensor_location = $3,
|
||||||
|
wire_id = $4,
|
||||||
|
i2c_bus = $5,
|
||||||
|
i2c_address = $6,
|
||||||
|
gpio_number = $7,
|
||||||
|
sensor_model = $8,
|
||||||
|
sensor_enabled = $9,
|
||||||
|
device_id = $10,
|
||||||
|
creation_date = $11
|
||||||
|
WHERE
|
||||||
|
sensor_id = $12;
|
723
pkg/repository/db/sqlite.go
Normal file
723
pkg/repository/db/sqlite.go
Normal file
@ -0,0 +1,723 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
"github.com/volker-raschek/flucky/pkg/types"
|
||||||
|
"github.com/volker-raschek/go-logger/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
sqliteAssetPath = "pkg/storage/sqlite"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SQLite implementation
|
||||||
|
type SQLite struct {
|
||||||
|
dbo *sql.DB
|
||||||
|
flogger logger.Logger
|
||||||
|
queries map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteDevices from the database
|
||||||
|
func (sqlite *SQLite) DeleteDevices(ctx context.Context, deviceIDs ...string) error {
|
||||||
|
queryFile := "deleteDevice.sql"
|
||||||
|
query, present := sqlite.queries[queryFile]
|
||||||
|
if !present {
|
||||||
|
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt, err := tx.Prepare(query)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to prepare statement: %v", err)
|
||||||
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
|
||||||
|
for _, deviceID := range deviceIDs {
|
||||||
|
_, err = stmt.Exec(deviceID)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteSensors from the database
|
||||||
|
func (sqlite *SQLite) DeleteSensors(ctx context.Context, sensorIDs ...string) error {
|
||||||
|
queryFile := "deleteSensor.sql"
|
||||||
|
query, present := sqlite.queries[queryFile]
|
||||||
|
if !present {
|
||||||
|
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt, err := tx.Prepare(query)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to prepare statement: %v", err)
|
||||||
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
|
||||||
|
for _, sensorID := range sensorIDs {
|
||||||
|
_, err = stmt.Exec(sensorID)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
// InsertDevices into the database
|
||||||
|
func (sqlite *SQLite) InsertDevices(ctx context.Context, devices ...*types.Device) error {
|
||||||
|
queryFile := "insertDevice.sql"
|
||||||
|
query, present := sqlite.queries[queryFile]
|
||||||
|
if !present {
|
||||||
|
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt, err := tx.Prepare(query)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to prepare statement: %v", err)
|
||||||
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
|
||||||
|
for _, device := range devices {
|
||||||
|
_, err = stmt.Exec(&device.ID, &device.Name, &device.Location, &device.CreationDate)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return fmt.Errorf("Failed to execute statement: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
// InsertMeasuredValues into the database
|
||||||
|
func (sqlite *SQLite) InsertMeasuredValues(ctx context.Context, measuredValues ...*types.MeasuredValue) error {
|
||||||
|
splittedMeasuredValues := make(map[string][]*types.MeasuredValue, 0)
|
||||||
|
|
||||||
|
for _, measuredValue := range measuredValues {
|
||||||
|
if _, ok := splittedMeasuredValues[measuredValue.ValueType]; !ok {
|
||||||
|
splittedMeasuredValues[measuredValue.ValueType] = make([]*types.MeasuredValue, 0)
|
||||||
|
}
|
||||||
|
splittedMeasuredValues[measuredValue.ValueType] = append(splittedMeasuredValues[measuredValue.ValueType], measuredValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// General insert function
|
||||||
|
insert := func(tx *sql.Tx, queryFile string, measuredValues []*types.MeasuredValue) error {
|
||||||
|
query, present := sqlite.queries[queryFile]
|
||||||
|
if !present {
|
||||||
|
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt, err := tx.Prepare(query)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to prepare statement: %v", err)
|
||||||
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
|
||||||
|
for _, measuredValue := range measuredValues {
|
||||||
|
_, err := stmt.Exec(
|
||||||
|
&measuredValue.ID,
|
||||||
|
&measuredValue.Value,
|
||||||
|
&measuredValue.FromDate,
|
||||||
|
&measuredValue.TillDate,
|
||||||
|
&measuredValue.SensorID,
|
||||||
|
&measuredValue.CreationDate,
|
||||||
|
&measuredValue.UpdateDate,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to execute statement: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for measuredValueType, measuredValues := range splittedMeasuredValues {
|
||||||
|
var queryFile string
|
||||||
|
|
||||||
|
switch measuredValueType {
|
||||||
|
case "humidity":
|
||||||
|
queryFile = "insertHumidity.sql"
|
||||||
|
case "pressure":
|
||||||
|
queryFile = "insertPressure.sql"
|
||||||
|
case "temperature":
|
||||||
|
queryFile = "insertTemperature.sql"
|
||||||
|
default:
|
||||||
|
tx.Rollback()
|
||||||
|
return fmt.Errorf("Measured value type %v not supported", measuredValueType)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := insert(tx, queryFile, measuredValues)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
// InsertSensors into the database
|
||||||
|
func (sqlite *SQLite) InsertSensors(ctx context.Context, sensors ...*types.Sensor) error {
|
||||||
|
queryFile := "insertSensor.sql"
|
||||||
|
query, present := sqlite.queries[queryFile]
|
||||||
|
if !present {
|
||||||
|
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt, err := tx.Prepare(query)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to prepare statement: %v", err)
|
||||||
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
|
||||||
|
for _, sensor := range sensors {
|
||||||
|
_, err = stmt.Exec(
|
||||||
|
&sensor.ID,
|
||||||
|
&sensor.Name,
|
||||||
|
&sensor.Location,
|
||||||
|
&sensor.WireID,
|
||||||
|
&sensor.I2CBus,
|
||||||
|
&sensor.I2CAddress,
|
||||||
|
&sensor.GPIONumber,
|
||||||
|
&sensor.Model,
|
||||||
|
&sensor.Enabled,
|
||||||
|
&sensor.DeviceID,
|
||||||
|
&sensor.CreationDate,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return fmt.Errorf("Failed to execute statement: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scheme creates all required tables if not exist
|
||||||
|
func (sqlite *SQLite) Scheme(ctx context.Context) error {
|
||||||
|
for _, query := range []string{
|
||||||
|
sqlite.queries["createTableDevices.sql"],
|
||||||
|
sqlite.queries["createTableSensors.sql"],
|
||||||
|
sqlite.queries["createTableHumidites.sql"],
|
||||||
|
sqlite.queries["createTablePressures.sql"],
|
||||||
|
sqlite.queries["createTableTemperatures.sql"],
|
||||||
|
} {
|
||||||
|
_, err := sqlite.dbo.ExecContext(ctx, query)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectDevice from database
|
||||||
|
func (sqlite *SQLite) SelectDevice(ctx context.Context, id string) (*types.Device, error) {
|
||||||
|
queryFile := "selectDevice.sql"
|
||||||
|
query, present := sqlite.queries[queryFile]
|
||||||
|
if !present {
|
||||||
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
devices, err := sqlite.selectDevices(tx, query, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return devices[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectDevices from the database
|
||||||
|
func (sqlite *SQLite) SelectDevices(ctx context.Context) ([]*types.Device, error) {
|
||||||
|
queryFile := "selectDevices.sql"
|
||||||
|
query, present := sqlite.queries[queryFile]
|
||||||
|
if !present {
|
||||||
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
devices, err := sqlite.selectDevices(tx, query, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to commit transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return devices, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sqlite *SQLite) selectDevices(tx *sql.Tx, query string, args ...interface{}) ([]*types.Device, error) {
|
||||||
|
stmt, err := tx.Prepare(query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to prepare statement: %v", err)
|
||||||
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
|
||||||
|
rows, err := stmt.Query()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to query statement: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
devices := make([]*types.Device, 0)
|
||||||
|
for rows.Next() {
|
||||||
|
device := new(types.Device)
|
||||||
|
err = rows.Scan(
|
||||||
|
&device.ID,
|
||||||
|
&device.Name,
|
||||||
|
&device.Location,
|
||||||
|
&device.CreationDate,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to scan row: %v", err)
|
||||||
|
}
|
||||||
|
devices = append(devices, device)
|
||||||
|
}
|
||||||
|
|
||||||
|
return devices, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectHumidity returns humidity from the database
|
||||||
|
func (sqlite *SQLite) SelectHumidity(ctx context.Context, id string) (*types.MeasuredValue, error) {
|
||||||
|
queryFile := "selectHumidity.sql"
|
||||||
|
query, present := sqlite.queries[queryFile]
|
||||||
|
if !present {
|
||||||
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
measuredValues, err := sqlite.selectMeasuredValue(tx, query, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if measuredValues == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, measuredValue := range measuredValues {
|
||||||
|
measuredValue.ValueType = "humidity"
|
||||||
|
}
|
||||||
|
|
||||||
|
return measuredValues[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectHumidities returns humidities from the database
|
||||||
|
func (sqlite *SQLite) SelectHumidities(ctx context.Context) ([]*types.MeasuredValue, error) {
|
||||||
|
queryFile := "selectHumidities.sql"
|
||||||
|
query, present := sqlite.queries[queryFile]
|
||||||
|
if !present {
|
||||||
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
measuredValues, err := sqlite.selectMeasuredValue(tx, query, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, measuredValue := range measuredValues {
|
||||||
|
measuredValue.ValueType = "humidity"
|
||||||
|
}
|
||||||
|
|
||||||
|
return measuredValues, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sqlite *SQLite) selectMeasuredValue(tx *sql.Tx, query string, args ...interface{}) ([]*types.MeasuredValue, error) {
|
||||||
|
stmt, err := tx.Prepare(query)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
|
||||||
|
rows, err := stmt.Query(args...)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
measuredValues := make([]*types.MeasuredValue, 0)
|
||||||
|
for rows.Next() {
|
||||||
|
measuredValues := new(types.MeasuredValue)
|
||||||
|
err := rows.Scan(
|
||||||
|
&measuredValues.ID,
|
||||||
|
&measuredValues.Value,
|
||||||
|
&measuredValues.FromDate,
|
||||||
|
&measuredValues.TillDate,
|
||||||
|
&measuredValues.SensorID,
|
||||||
|
&measuredValues.CreationDate,
|
||||||
|
&measuredValues.UpdateDate,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return measuredValues, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectPressure returns pressure from the database
|
||||||
|
func (sqlite *SQLite) SelectPressure(ctx context.Context, id string) (*types.MeasuredValue, error) {
|
||||||
|
queryFile := "selectPressure.sql"
|
||||||
|
query, present := sqlite.queries[queryFile]
|
||||||
|
if !present {
|
||||||
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
measuredValues, err := sqlite.selectMeasuredValue(tx, query, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if measuredValues == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, measuredValue := range measuredValues {
|
||||||
|
measuredValue.ValueType = "pressure"
|
||||||
|
}
|
||||||
|
|
||||||
|
return measuredValues[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectPressures returns pressure from the database
|
||||||
|
func (sqlite *SQLite) SelectPressures(ctx context.Context) ([]*types.MeasuredValue, error) {
|
||||||
|
queryFile := "selectPressures.sql"
|
||||||
|
query, present := sqlite.queries[queryFile]
|
||||||
|
if !present {
|
||||||
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
measuredValues, err := sqlite.selectMeasuredValue(tx, query, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, measuredValue := range measuredValues {
|
||||||
|
measuredValue.ValueType = "pressure"
|
||||||
|
}
|
||||||
|
|
||||||
|
return measuredValues, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectSensor from database
|
||||||
|
func (sqlite *SQLite) SelectSensor(ctx context.Context, id string) (*types.Sensor, error) {
|
||||||
|
queryFile := "selectSensor.sql"
|
||||||
|
query, present := sqlite.queries[queryFile]
|
||||||
|
if !present {
|
||||||
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sensors, err := sqlite.selectSensors(tx, query, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to commit transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sensors[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectSensors from the database
|
||||||
|
func (sqlite *SQLite) SelectSensors(ctx context.Context) ([]*types.Sensor, error) {
|
||||||
|
queryFile := "selectSensors.sql"
|
||||||
|
query, present := sqlite.queries[queryFile]
|
||||||
|
if !present {
|
||||||
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to begin new transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sensors, err := sqlite.selectSensors(tx, query, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to commit transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sensors, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sqlite *SQLite) selectSensors(tx *sql.Tx, query string, args ...interface{}) ([]*types.Sensor, error) {
|
||||||
|
stmt, err := tx.Prepare(query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to prepare statement: %v", err)
|
||||||
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
|
||||||
|
rows, err := stmt.Query()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to query statement: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sensors := make([]*types.Sensor, 0)
|
||||||
|
for rows.Next() {
|
||||||
|
sensor := new(types.Sensor)
|
||||||
|
err = rows.Scan(
|
||||||
|
&sensor.ID,
|
||||||
|
&sensor.Name,
|
||||||
|
&sensor.Location,
|
||||||
|
&sensor.WireID,
|
||||||
|
&sensor.I2CBus,
|
||||||
|
&sensor.I2CAddress,
|
||||||
|
&sensor.GPIONumber,
|
||||||
|
&sensor.Model,
|
||||||
|
&sensor.Enabled,
|
||||||
|
&sensor.DeviceID,
|
||||||
|
&sensor.CreationDate,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to scan row: %v", err)
|
||||||
|
}
|
||||||
|
sensors = append(sensors, sensor)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sensors, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectTemperature returns temperatures from the database
|
||||||
|
func (sqlite *SQLite) SelectTemperature(ctx context.Context, id string) (*types.MeasuredValue, error) {
|
||||||
|
queryFile := "selectTemperature.sql"
|
||||||
|
query, present := sqlite.queries[queryFile]
|
||||||
|
if !present {
|
||||||
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
measuredValues, err := sqlite.selectMeasuredValue(tx, query, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if measuredValues == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, measuredValue := range measuredValues {
|
||||||
|
measuredValue.ValueType = "temperatures"
|
||||||
|
}
|
||||||
|
|
||||||
|
return measuredValues[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectTemperatures returns temperatures from the database
|
||||||
|
func (sqlite *SQLite) SelectTemperatures(ctx context.Context) ([]*types.MeasuredValue, error) {
|
||||||
|
queryFile := "selectTemperatures.sql"
|
||||||
|
query, present := sqlite.queries[queryFile]
|
||||||
|
if !present {
|
||||||
|
return nil, fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
measuredValues, err := sqlite.selectMeasuredValue(tx, query, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, measuredValue := range measuredValues {
|
||||||
|
measuredValue.ValueType = "temperatures"
|
||||||
|
}
|
||||||
|
|
||||||
|
return measuredValues, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateDevices updates a device in the database
|
||||||
|
func (sqlite *SQLite) UpdateDevices(ctx context.Context, devices ...*types.Device) error {
|
||||||
|
queryFile := "updateDevice.sql"
|
||||||
|
query, present := sqlite.queries[queryFile]
|
||||||
|
if !present {
|
||||||
|
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt, err := tx.Prepare(query)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
|
||||||
|
for _, device := range devices {
|
||||||
|
_, err := stmt.Exec(
|
||||||
|
&device.Name,
|
||||||
|
&device.Location,
|
||||||
|
&device.CreationDate,
|
||||||
|
&device.ID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateSensors updates a sensor in the database
|
||||||
|
func (sqlite *SQLite) UpdateSensors(ctx context.Context, sensors ...*types.Sensor) error {
|
||||||
|
queryFile := "updateSensor.sql"
|
||||||
|
query, present := sqlite.queries[queryFile]
|
||||||
|
if !present {
|
||||||
|
return fmt.Errorf("SQLite-Backend: File %v not found", queryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := sqlite.dbo.BeginTx(ctx, &sql.TxOptions{ReadOnly: false})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt, err := tx.Prepare(query)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
|
||||||
|
for _, sensor := range sensors {
|
||||||
|
_, err := stmt.Exec(
|
||||||
|
&sensor.Name,
|
||||||
|
&sensor.Location,
|
||||||
|
&sensor.WireID,
|
||||||
|
&sensor.I2CBus,
|
||||||
|
&sensor.I2CAddress,
|
||||||
|
&sensor.GPIONumber,
|
||||||
|
&sensor.Model,
|
||||||
|
&sensor.Enabled,
|
||||||
|
&sensor.DeviceID,
|
||||||
|
&sensor.CreationDate,
|
||||||
|
&sensor.ID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.Commit()
|
||||||
|
}
|
6
pkg/repository/db/sqlite3/createTableDevices.sql
Normal file
6
pkg/repository/db/sqlite3/createTableDevices.sql
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS devices (
|
||||||
|
device_id CHAR(37) PRIMARY KEY,
|
||||||
|
device_name VARCHAR(64) NOT NULL,
|
||||||
|
device_location VARCHAR(64),
|
||||||
|
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
|
||||||
|
);
|
10
pkg/repository/db/sqlite3/createTableHumidities.sql
Normal file
10
pkg/repository/db/sqlite3/createTableHumidities.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS humidities (
|
||||||
|
humidity_id CHAR(37) PRIMARY KEY,
|
||||||
|
humidity_value NUMERIC(10,3) NOT NULL,
|
||||||
|
humidity_from_date TIMESTAMP NOT NULL,
|
||||||
|
humidity_till_date TIMESTAMP,
|
||||||
|
sensor_id CHAR(37) NOT NULL,
|
||||||
|
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||||
|
update_date TIMESTAMP,
|
||||||
|
FOREIGN KEY(sensor_id) REFERENCES sensors(sensor_id)
|
||||||
|
);
|
10
pkg/repository/db/sqlite3/createTablePressures.sql
Normal file
10
pkg/repository/db/sqlite3/createTablePressures.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS pressures (
|
||||||
|
pressure_id CHAR(37) PRIMARY KEY,
|
||||||
|
pressure_value NUMERIC(10,3) NOT NULL,
|
||||||
|
pressure_from_date TIMESTAMP NOT NULL,
|
||||||
|
pressure_till_date TIMESTAMP,
|
||||||
|
sensor_id CHAR(37) NOT NULL,
|
||||||
|
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||||
|
update_date TIMESTAMP,
|
||||||
|
FOREIGN KEY(sensor_id) REFERENCES sensors(sensor_id)
|
||||||
|
);
|
14
pkg/repository/db/sqlite3/createTableSensors.sql
Normal file
14
pkg/repository/db/sqlite3/createTableSensors.sql
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS sensors (
|
||||||
|
sensor_id CHAR(37) PRIMARY KEY,
|
||||||
|
sensor_name VARCHAR(64) NOT NULL,
|
||||||
|
sensor_location VARCHAR(64),
|
||||||
|
wire_id VARCHAR(64),
|
||||||
|
i2c_bus VARCHAR(255),
|
||||||
|
i2c_address VARCHAR(12),
|
||||||
|
gpio_number VARCHAR(6),
|
||||||
|
sensor_model VARCHAR(16) NOT NULL,
|
||||||
|
sensor_enabled INTEGER(1) DEFAULT 1 NOT NULL,
|
||||||
|
device_id CHAR(37) NOT NULL,
|
||||||
|
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY(device_id) REFERENCES devices(device_id)
|
||||||
|
);
|
10
pkg/repository/db/sqlite3/createTableTemperatures.sql
Normal file
10
pkg/repository/db/sqlite3/createTableTemperatures.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS temperatures (
|
||||||
|
temperature_id CHAR(37) PRIMARY KEY,
|
||||||
|
temperature_value NUMERIC(10,3) NOT NULL,
|
||||||
|
temperature_from_date TIMESTAMP NOT NULL,
|
||||||
|
temperature_till_date TIMESTAMP,
|
||||||
|
sensor_id CHAR(37) NOT NULL,
|
||||||
|
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||||
|
update_date TIMESTAMP,
|
||||||
|
FOREIGN KEY(sensor_id) REFERENCES sensors(sensor_id)
|
||||||
|
);
|
2
pkg/repository/db/sqlite3/deleteDevice.sql
Normal file
2
pkg/repository/db/sqlite3/deleteDevice.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
DELETE FROM sensors
|
||||||
|
WHERE device_id = $1;
|
2
pkg/repository/db/sqlite3/deleteSensor.sql
Normal file
2
pkg/repository/db/sqlite3/deleteSensor.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
DELETE FROM sensors
|
||||||
|
WHERE sensor_id = $1;
|
7
pkg/repository/db/sqlite3/insertDevice.sql
Normal file
7
pkg/repository/db/sqlite3/insertDevice.sql
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
INSERT INTO devices (
|
||||||
|
device_id,
|
||||||
|
device_name,
|
||||||
|
device_location,
|
||||||
|
creation_date
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4);
|
10
pkg/repository/db/sqlite3/insertHumidity.sql
Normal file
10
pkg/repository/db/sqlite3/insertHumidity.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
INSERT INTO humidities (
|
||||||
|
humidity_id,
|
||||||
|
humidity_value,
|
||||||
|
humidity_from_date,
|
||||||
|
humidity_till_date,
|
||||||
|
sensor_id,
|
||||||
|
creation_date,
|
||||||
|
update_date
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, $7);
|
10
pkg/repository/db/sqlite3/insertPressure.sql
Normal file
10
pkg/repository/db/sqlite3/insertPressure.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
INSERT INTO pressures (
|
||||||
|
pressure_id,
|
||||||
|
pressure_value,
|
||||||
|
pressure_from_date,
|
||||||
|
pressure_till_date,
|
||||||
|
sensor_id,
|
||||||
|
creation_date,
|
||||||
|
update_date
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, $7);
|
14
pkg/repository/db/sqlite3/insertSensor.sql
Normal file
14
pkg/repository/db/sqlite3/insertSensor.sql
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
INSERT INTO sensors (
|
||||||
|
sensor_id,
|
||||||
|
sensor_name,
|
||||||
|
sensor_location,
|
||||||
|
wire_id,
|
||||||
|
i2c_bus,
|
||||||
|
i2c_address,
|
||||||
|
gpio_number,
|
||||||
|
sensor_model,
|
||||||
|
sensor_enabled,
|
||||||
|
device_id,
|
||||||
|
creation_date
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);
|
10
pkg/repository/db/sqlite3/insertTemperature.sql
Normal file
10
pkg/repository/db/sqlite3/insertTemperature.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
INSERT INTO temperatures (
|
||||||
|
temperature_id,
|
||||||
|
temperature_value,
|
||||||
|
temperature_from_date,
|
||||||
|
temperature_till_date,
|
||||||
|
sensor_id,
|
||||||
|
creation_date,
|
||||||
|
update_date
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, $7);
|
8
pkg/repository/db/sqlite3/selectDevice.sql
Normal file
8
pkg/repository/db/sqlite3/selectDevice.sql
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
SELECT
|
||||||
|
device_id,
|
||||||
|
device_name,
|
||||||
|
device_location,
|
||||||
|
creation_date
|
||||||
|
FROM
|
||||||
|
devices
|
||||||
|
WHERE device_id = $1;
|
7
pkg/repository/db/sqlite3/selectDevices.sql
Normal file
7
pkg/repository/db/sqlite3/selectDevices.sql
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
SELECT
|
||||||
|
device_id,
|
||||||
|
device_name,
|
||||||
|
device_location,
|
||||||
|
creation_date
|
||||||
|
FROM
|
||||||
|
devices;
|
10
pkg/repository/db/sqlite3/selectHumidities.sql
Normal file
10
pkg/repository/db/sqlite3/selectHumidities.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
SELECT
|
||||||
|
humidity_id,
|
||||||
|
humidity_value,
|
||||||
|
humidity_from_date,
|
||||||
|
humidity_till_date,
|
||||||
|
sensor_id,
|
||||||
|
creation_date,
|
||||||
|
update_date
|
||||||
|
FROM
|
||||||
|
humidities
|
12
pkg/repository/db/sqlite3/selectHumidity.sql
Normal file
12
pkg/repository/db/sqlite3/selectHumidity.sql
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
SELECT
|
||||||
|
humidity_id,
|
||||||
|
humidity_value,
|
||||||
|
humidity_from_date,
|
||||||
|
humidity_till_date,
|
||||||
|
sensor_id,
|
||||||
|
creation_date,
|
||||||
|
update_date
|
||||||
|
FROM
|
||||||
|
humidities
|
||||||
|
WHERE
|
||||||
|
humidity_id = $1
|
12
pkg/repository/db/sqlite3/selectPressure.sql
Normal file
12
pkg/repository/db/sqlite3/selectPressure.sql
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
SELECT
|
||||||
|
pressure_id,
|
||||||
|
pressure_value,
|
||||||
|
pressure_from_date,
|
||||||
|
pressure_till_date,
|
||||||
|
sensor_id,
|
||||||
|
creation_date,
|
||||||
|
update_date
|
||||||
|
FROM
|
||||||
|
pressures
|
||||||
|
WHERE
|
||||||
|
pressure_id = $1
|
10
pkg/repository/db/sqlite3/selectPressures.sql
Normal file
10
pkg/repository/db/sqlite3/selectPressures.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
SELECT
|
||||||
|
pressure_id,
|
||||||
|
pressure_value,
|
||||||
|
pressure_from_date,
|
||||||
|
pressure_till_date,
|
||||||
|
sensor_id,
|
||||||
|
creation_date,
|
||||||
|
update_date
|
||||||
|
FROM
|
||||||
|
pressures
|
16
pkg/repository/db/sqlite3/selectSensor.sql
Normal file
16
pkg/repository/db/sqlite3/selectSensor.sql
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
SELECT
|
||||||
|
sensor_id,
|
||||||
|
sensor_name,
|
||||||
|
sensor_location,
|
||||||
|
wire_id,
|
||||||
|
i2c_bus,
|
||||||
|
i2c_address,
|
||||||
|
gpio_number,
|
||||||
|
sensor_model,
|
||||||
|
sensor_enabled,
|
||||||
|
device_id,
|
||||||
|
creation_date
|
||||||
|
FROM
|
||||||
|
sensors
|
||||||
|
WHERE
|
||||||
|
sensor_id = $1;
|
14
pkg/repository/db/sqlite3/selectSensors.sql
Normal file
14
pkg/repository/db/sqlite3/selectSensors.sql
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
SELECT
|
||||||
|
sensor_id,
|
||||||
|
sensor_name,
|
||||||
|
sensor_location,
|
||||||
|
wire_id,
|
||||||
|
i2c_bus,
|
||||||
|
i2c_address,
|
||||||
|
gpio_number,
|
||||||
|
sensor_model,
|
||||||
|
sensor_enabled,
|
||||||
|
device_id,
|
||||||
|
creation_date
|
||||||
|
FROM
|
||||||
|
sensors;
|
12
pkg/repository/db/sqlite3/selectTemperature.sql
Normal file
12
pkg/repository/db/sqlite3/selectTemperature.sql
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
SELECT
|
||||||
|
temperature_id,
|
||||||
|
temperature_value,
|
||||||
|
temperature_from_date,
|
||||||
|
temperature_till_date,
|
||||||
|
sensor_id,
|
||||||
|
creation_date,
|
||||||
|
update_date
|
||||||
|
FROM
|
||||||
|
temperatures
|
||||||
|
WHERE
|
||||||
|
temperature_id = $1
|
10
pkg/repository/db/sqlite3/selectTemperatures.sql
Normal file
10
pkg/repository/db/sqlite3/selectTemperatures.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
SELECT
|
||||||
|
temperature_id,
|
||||||
|
temperature_value,
|
||||||
|
temperature_from_date,
|
||||||
|
temperature_till_date,
|
||||||
|
sensor_id,
|
||||||
|
creation_date,
|
||||||
|
update_date
|
||||||
|
FROM
|
||||||
|
temperatures
|
7
pkg/repository/db/sqlite3/updateDevice.sql
Normal file
7
pkg/repository/db/sqlite3/updateDevice.sql
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
UPDATE device
|
||||||
|
SET
|
||||||
|
device_name = $1,
|
||||||
|
device_location = $2,
|
||||||
|
creation_date = $3
|
||||||
|
WHERE
|
||||||
|
device_id = $4,
|
14
pkg/repository/db/sqlite3/updateSensor.sql
Normal file
14
pkg/repository/db/sqlite3/updateSensor.sql
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
UPDATE sensors
|
||||||
|
SET
|
||||||
|
sensor_name = $1,
|
||||||
|
sensor_location = $2,
|
||||||
|
wire_id = $3,
|
||||||
|
i2c_bus = $4,
|
||||||
|
i2c_address = $5,
|
||||||
|
gpio_number = $6,
|
||||||
|
sensor_model = $7,
|
||||||
|
sensor_enabled = $8,
|
||||||
|
device_id = $9,
|
||||||
|
creation_date = $10
|
||||||
|
WHERE
|
||||||
|
sensor_id = $11;
|
189
pkg/repository/repository.go
Normal file
189
pkg/repository/repository.go
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
package repository
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/volker-raschek/flucky/pkg/repository/db"
|
||||||
|
"github.com/volker-raschek/flucky/pkg/types"
|
||||||
|
"github.com/volker-raschek/go-logger/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Repository represent a repository where all devices, sensors and measured
|
||||||
|
// values are stored.
|
||||||
|
type Repository struct {
|
||||||
|
database db.Database
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddDevices to the repository
|
||||||
|
func (repo *Repository) AddDevices(devices ...*types.Device) error {
|
||||||
|
return repo.database.InsertDevices(context.Background(), devices...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMeasuredValues to the repository
|
||||||
|
func (repo *Repository) AddMeasuredValues(measuredValues ...*types.MeasuredValue) error {
|
||||||
|
return repo.database.InsertMeasuredValues(context.Background(), measuredValues...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSensors to the repository
|
||||||
|
func (repo *Repository) AddSensors(sensors ...*types.Sensor) error {
|
||||||
|
return repo.database.InsertSensors(context.Background(), sensors...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisableSensorsByNames disable all sensors which match bei their name
|
||||||
|
func (repo *Repository) DisableSensorsByNames(sensorNames ...string) error {
|
||||||
|
sensors, err := repo.GetSensors()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
matchedSensors := make([]*types.Sensor, 0)
|
||||||
|
for _, sensor := range sensors {
|
||||||
|
for _, sensorName := range sensorNames {
|
||||||
|
if strings.Compare(sensor.Name, sensorName) == 0 {
|
||||||
|
sensor.Enabled = false
|
||||||
|
matchedSensors = append(matchedSensors, sensor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return repo.UpdateSensors(matchedSensors...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnableSensorsByNames enable all sensors which match bei their name
|
||||||
|
func (repo *Repository) EnableSensorsByNames(sensorNames ...string) error {
|
||||||
|
sensors, err := repo.GetSensors()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
matchedSensors := make([]*types.Sensor, 0)
|
||||||
|
for _, sensor := range sensors {
|
||||||
|
for _, sensorName := range sensorNames {
|
||||||
|
if strings.Compare(sensor.Name, sensorName) == 0 {
|
||||||
|
sensor.Enabled = true
|
||||||
|
matchedSensors = append(matchedSensors, sensor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return repo.UpdateSensors(matchedSensors...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDevice returns a device by his id. If no device has been found, the
|
||||||
|
// function returns nil.
|
||||||
|
func (repo *Repository) GetDevice(deviceID string) (*types.Device, error) {
|
||||||
|
return repo.database.SelectDevice(context.Background(), deviceID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDevices returns all devices. If no devices has been found, the function
|
||||||
|
// returns nil.
|
||||||
|
func (repo *Repository) GetDevices() ([]*types.Device, error) {
|
||||||
|
return repo.database.SelectDevices(context.Background())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSensor returns a sensor by his id. If no sensor has been found, the
|
||||||
|
// function returns nil.
|
||||||
|
func (repo *Repository) GetSensor(sensorID string) (*types.Sensor, error) {
|
||||||
|
return repo.database.SelectSensor(context.Background(), sensorID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSensors returns all sensors. If no sensors has been found, the function
|
||||||
|
// returns nil.
|
||||||
|
func (repo *Repository) GetSensors() ([]*types.Sensor, error) {
|
||||||
|
return repo.database.SelectSensors(context.Background())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSensorsByDeviceID returns all sensors by a device id. If no sensor has
|
||||||
|
// been found by the id, the function returns nil.
|
||||||
|
func (repo *Repository) GetSensorsByDeviceID(deviceID string) ([]*types.Sensor, error) {
|
||||||
|
cachedSensors := make([]*types.Sensor, 0)
|
||||||
|
sensors, err := repo.GetSensors()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, sensor := range sensors {
|
||||||
|
if strings.Compare(sensor.DeviceID, deviceID) == 0 {
|
||||||
|
cachedSensors = append(cachedSensors, sensor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sensors, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveDevices removes devices by their ids from the repository. Additional
|
||||||
|
// all sensors and measured values, which are in relation with the device
|
||||||
|
// respectively the sensors will also be deleted.
|
||||||
|
func (repo *Repository) RemoveDevices(deviceIDs ...string) error {
|
||||||
|
return repo.database.DeleteDevices(context.Background(), deviceIDs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenameSensors all sensors which match by their current name to the new name
|
||||||
|
func (repo *Repository) RenameSensors(oldName string, newName string) error {
|
||||||
|
sensors, err := repo.GetSensors()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
matchedSensors := make([]*types.Sensor, 0)
|
||||||
|
for _, sensor := range sensors {
|
||||||
|
if strings.Compare(sensor.Name, oldName) == 0 {
|
||||||
|
sensor.Name = newName
|
||||||
|
matchedSensors = append(matchedSensors, sensor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return repo.UpdateSensors(matchedSensors...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveSensors removes sensors by their ids from the repository. Additional
|
||||||
|
// all measured values, which are in relation with the sensor will also be
|
||||||
|
// deleted.
|
||||||
|
func (repo *Repository) RemoveSensors(sensorIDs ...string) error {
|
||||||
|
return repo.database.DeleteSensors(context.Background(), sensorIDs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveSensorsByNames removes all sensors which match bei their name
|
||||||
|
func (repo *Repository) RemoveSensorsByNames(sensorNames ...string) error {
|
||||||
|
sensors, err := repo.GetSensors()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
matchedSensorIDs := make([]string, 0)
|
||||||
|
for _, sensor := range sensors {
|
||||||
|
for _, sensorName := range sensorNames {
|
||||||
|
if strings.Compare(sensor.Name, sensorName) == 0 {
|
||||||
|
matchedSensorIDs = append(matchedSensorIDs, sensor.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return repo.RemoveSensors(matchedSensorIDs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateDevices update devices which are stored into the repository by their
|
||||||
|
// id. The id of the device can not be updated.
|
||||||
|
func (repo *Repository) UpdateDevices(devices ...*types.Device) error {
|
||||||
|
return repo.database.UpdateDevices(context.Background(), devices...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateSensors update sensors which are stored into the repository by their
|
||||||
|
// id. The id of the sensor can not be updated.
|
||||||
|
func (repo *Repository) UpdateSensors(sensors ...*types.Sensor) error {
|
||||||
|
return repo.database.UpdateSensors(context.Background(), sensors...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new repository based on the storageEndpoint
|
||||||
|
func New(storageEndpoint *url.URL, flogger logger.Logger) (*Repository, error) {
|
||||||
|
database, err := db.New(storageEndpoint, flogger)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Repository{
|
||||||
|
database: database,
|
||||||
|
}, nil
|
||||||
|
}
|
@ -1,2 +0,0 @@
|
|||||||
DELETE FROM sensors
|
|
||||||
WHERE sensor_name = $1;
|
|
Loading…
Reference in New Issue
Block a user