feat(pkg/db): postgres database
This commit is contained in:
		| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/go-flucky/flucky/pkg/internal/format" | ||||
| 	"github.com/go-flucky/flucky/pkg/rgbled" | ||||
| 	"github.com/go-flucky/flucky/pkg/sensor" | ||||
|  | ||||
| @@ -101,7 +102,7 @@ func (c *Configuration) AddSensor(sensor *types.Sensor) error { | ||||
| 	} | ||||
|  | ||||
| 	// overwrite creation date | ||||
| 	sensor.CreationDate = time.Now() | ||||
| 	sensor.CreationDate = format.FormatedTime() | ||||
|  | ||||
| 	//TODO: check if wire sensor exists in /dev/bus/w1/devices | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/go-flucky/flucky/pkg/config" | ||||
| 	"github.com/go-flucky/flucky/pkg/db" | ||||
| 	"github.com/go-flucky/flucky/pkg/logfile" | ||||
| 	"github.com/go-flucky/flucky/pkg/logger" | ||||
| 	"github.com/go-flucky/flucky/pkg/rgbled" | ||||
| @@ -15,6 +16,14 @@ import ( | ||||
| 	"github.com/go-flucky/flucky/pkg/types" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	postgresHost     = "markus-pc.trier.cryptic.systems" | ||||
| 	postgresPort     = "5432" | ||||
| 	postgresDatabase = "postgres" | ||||
| 	postgresUser     = "postgres" | ||||
| 	postgresPassword = "postgres" | ||||
| ) | ||||
|  | ||||
| // Start the daemon | ||||
| func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compression bool, round float64, logger logger.Logger) { | ||||
|  | ||||
| @@ -67,7 +76,9 @@ func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compress | ||||
| 				logger.Error("Can not turn on blue info light: %v", err) | ||||
| 			} | ||||
|  | ||||
| 			err = logfile.Append(measuredValuesLogfile, compression, round, measuredValuesCache) | ||||
| 			// err = logfile.Append(measuredValuesLogfile, compression, round, measuredValuesCache) | ||||
|  | ||||
| 			postgres, err := db.New(db.DBOTypePostgres, postgresHost, postgresPort, postgresDatabase, postgresUser, postgresPassword) | ||||
| 			if err != nil { | ||||
|  | ||||
| 				err = rgbled.Error(rgbLEDs) | ||||
| @@ -76,8 +87,22 @@ func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compress | ||||
| 				} | ||||
|  | ||||
| 				cancel() | ||||
| 				logger.Fatal("Can not save temperatures: %v", err) | ||||
| 				logger.Error("Can not open database connection: %v", err) | ||||
| 			} | ||||
|  | ||||
| 			postgresCtx := context.Background() | ||||
| 			err = postgres.InsertMeasuredValues(postgresCtx, measuredValuesCache) | ||||
| 			if err != nil { | ||||
|  | ||||
| 				err = rgbled.Error(rgbLEDs) | ||||
| 				if err != nil { | ||||
| 					logger.Error("Can not turn on red info light: %v", err) | ||||
| 				} | ||||
|  | ||||
| 				cancel() | ||||
| 				logger.Error("Can not save caches measured values in database: %v", err) | ||||
| 			} | ||||
|  | ||||
| 			measuredValuesCache = make([]*types.MeasuredValue, 0) | ||||
|  | ||||
| 		case measuredValues, _ := <-measuredValuesChannel: | ||||
|   | ||||
							
								
								
									
										36
									
								
								pkg/db/db.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								pkg/db/db.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| package db | ||||
|  | ||||
| import ( | ||||
| 	"database/sql" | ||||
| 	"fmt" | ||||
|  | ||||
| 	_ "github.com/lib/pq" | ||||
| ) | ||||
|  | ||||
| type DBOType string | ||||
|  | ||||
| func (dboType DBOType) String() string { | ||||
| 	return string(dboType) | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	DBOTypePostgres DBOType = "postgres" | ||||
| 	DBOTypeOracle           = "oracle" | ||||
| ) | ||||
|  | ||||
| func New(dboType DBOType, host string, port string, database string, user string, password string) (Database, error) { | ||||
| 	connStr := fmt.Sprintf("%v://%v:%v@%v:%v/%v?sslmode=disable", dboType.String(), user, password, host, port, database) | ||||
| 	newDBO, err := sql.Open(dboType.String(), connStr) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	switch dboType { | ||||
| 	case "postgres": | ||||
| 		return &Postgres{ | ||||
| 			dbo: newDBO, | ||||
| 		}, nil | ||||
| 	default: | ||||
| 		return nil, fmt.Errorf("Unknown Database Type") | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										16
									
								
								pkg/db/errors.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								pkg/db/errors.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| package db | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	errorBeginTransaction         = errors.New("Can not start new transaction") | ||||
| 	errorRowNotFound              = errors.New("Can not find row by given ID") | ||||
| 	errorPrepareStatement         = errors.New("Can not prepare sql statement") | ||||
| 	errorRollbackTransaction      = errors.New("Can not rollback transaction") | ||||
| 	errorScanRow                  = errors.New("Can not scan row") | ||||
| 	errorStatementExecute         = errors.New("Can not execute statement") | ||||
| 	errorStatementQuery           = errors.New("Can not query statement") | ||||
| 	errorUnknownMeasuredValueType = errors.New("Unknown measured value type") | ||||
| ) | ||||
							
								
								
									
										39
									
								
								pkg/db/interfaces.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								pkg/db/interfaces.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| package db | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/go-flucky/flucky/pkg/types" | ||||
| ) | ||||
|  | ||||
| type Database interface { | ||||
|  | ||||
| 	// Close DB Connction | ||||
| 	Close() error | ||||
|  | ||||
| 	// Delete | ||||
| 	DeleteDevices(ctx context.Context, devices []*types.Device) error | ||||
| 	DeleteMeasuredValues(ctx context.Context, measuredValues []*types.MeasuredValue) error | ||||
| 	DeleteSensors(ctx context.Context, sensors []*types.Sensor) error | ||||
|  | ||||
| 	// Insert | ||||
| 	InsertDevices(ctx context.Context, devices []*types.Device) error | ||||
| 	InsertMeasuredValues(ctx context.Context, measuredValues []*types.MeasuredValue) error | ||||
| 	InsertSensors(ctx context.Context, sensors []*types.Sensor) error | ||||
|  | ||||
| 	// Select | ||||
| 	SelectDeviceByID(ctx context.Context, id string) (*types.Device, error) | ||||
| 	SelectHumidities(ctx context.Context) ([]*types.MeasuredValue, error) | ||||
| 	SelectHumidityByID(ctx context.Context, id string) (*types.MeasuredValue, error) | ||||
| 	SelectMeasuredValuesByIDAndType(ctx context.Context, id string, valueType types.MeasuredValueType) (*types.MeasuredValue, error) | ||||
| 	SelectPressures(ctx context.Context) ([]*types.MeasuredValue, error) | ||||
| 	SelectPressureByID(ctx context.Context, id string) (*types.MeasuredValue, error) | ||||
| 	SelectSensorByID(ctx context.Context, id string) (*types.Sensor, error) | ||||
| 	SelectTemperatures(ctx context.Context) ([]*types.MeasuredValue, error) | ||||
| 	SelectTemperatureByID(ctx context.Context, id string) (*types.MeasuredValue, error) | ||||
|  | ||||
| 	// Update | ||||
| 	UpdateDevices(ctx context.Context, devices []*types.Device) error | ||||
| 	UpdateMeasuredValues(ctx context.Context, measuredValues []*types.MeasuredValue) error | ||||
| 	UpdateSensors(ctx context.Context, sensots []*types.Sensor) error | ||||
| } | ||||
							
								
								
									
										410
									
								
								pkg/db/postgres.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										410
									
								
								pkg/db/postgres.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,410 @@ | ||||
| package db | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"database/sql" | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/go-flucky/flucky/pkg/types" | ||||
| 	_ "github.com/lib/pq" | ||||
| ) | ||||
|  | ||||
| type Postgres struct { | ||||
| 	dbo *sql.DB | ||||
| } | ||||
|  | ||||
| func (p *Postgres) Close() error { | ||||
| 	return p.Close() | ||||
| } | ||||
|  | ||||
| func (p *Postgres) DeleteDevices(ctx context.Context, devices []*types.Device) error { | ||||
| 	query := string(MustAsset("pkg/db/sql/psql/deleteDevice.sql")) | ||||
|  | ||||
| 	stmt, err := p.dbo.PrepareContext(ctx, query) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("%v: %v", errorPrepareStatement, err) | ||||
| 	} | ||||
| 	defer stmt.Close() | ||||
|  | ||||
| 	for _, device := range devices { | ||||
| 		_, err := stmt.ExecContext(ctx, &device.DeviceID) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("%v: %v", errorStatementExecute, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) DeleteSensors(ctx context.Context, sensors []*types.Sensor) error { | ||||
| 	query := string(MustAsset("pkg/db/sql/psql/deleteSensor.sql")) | ||||
|  | ||||
| 	stmt, err := p.dbo.PrepareContext(ctx, query) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("%v: %v", errorPrepareStatement, err) | ||||
| 	} | ||||
| 	defer stmt.Close() | ||||
|  | ||||
| 	for _, sensor := range sensors { | ||||
| 		_, err := stmt.ExecContext(ctx, &sensor.SensorID) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("%v: %v", errorStatementExecute, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) DeleteMeasuredValues(ctx context.Context, measuredValues []*types.MeasuredValue) error { | ||||
|  | ||||
| 	deleteMeasuredValue := func(ctx context.Context, query string, measuredValues []*types.MeasuredValue) error { | ||||
| 		stmt, err := p.dbo.PrepareContext(ctx, query) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("%v: %v", errorPrepareStatement, err) | ||||
| 		} | ||||
| 		defer stmt.Close() | ||||
|  | ||||
| 		for _, measuredValue := range measuredValues { | ||||
| 			_, err := stmt.ExecContext(ctx, &measuredValue.ID) | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("%v: %v", errorStatementExecute, err) | ||||
| 			} | ||||
| 		} | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	sortedMeasuredValueTypes := make(map[types.MeasuredValueType][]*types.MeasuredValue) | ||||
| 	for _, measuredValue := range measuredValues { | ||||
| 		if _, ok := sortedMeasuredValueTypes[measuredValue.ValueType]; !ok { | ||||
| 			sortedMeasuredValueTypes[measuredValue.ValueType] = make([]*types.MeasuredValue, 0) | ||||
| 		} | ||||
| 		sortedMeasuredValueTypes[measuredValue.ValueType] = append(sortedMeasuredValueTypes[measuredValue.ValueType], measuredValue) | ||||
| 	} | ||||
|  | ||||
| 	for measuredValueType, sortedMeasuredValues := range sortedMeasuredValueTypes { | ||||
| 		switch measuredValueType { | ||||
| 		case types.MeasuredValueTypeHumidity: | ||||
| 			if err := deleteMeasuredValue(ctx, string(MustAsset("pkg/db/sql/psql/deleteHumidity.sql")), sortedMeasuredValues); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		case types.MeasuredValueTypePressure: | ||||
| 			if err := deleteMeasuredValue(ctx, string(MustAsset("pkg/db/sql/psql/deletePressure.sql")), sortedMeasuredValues); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		case types.MeasuredValueTypeTemperature: | ||||
| 			if err := deleteMeasuredValue(ctx, string(MustAsset("pkg/db/sql/psql/deleteTemperature.sql")), sortedMeasuredValues); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) InsertDevices(ctx context.Context, devices []*types.Device) error { | ||||
|  | ||||
| 	query := string(MustAsset("pkg/db/sql/psql/insertDevice.sql")) | ||||
|  | ||||
| 	stmt, err := p.dbo.PrepareContext(ctx, query) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("%v: %v", errorPrepareStatement, err) | ||||
| 	} | ||||
| 	defer stmt.Close() | ||||
|  | ||||
| 	for _, device := range devices { | ||||
| 		_, err := stmt.ExecContext(ctx, &device.DeviceID, &device.DeviceName, &device.DeviceLocation, &device.CreationDate) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("%v: %v", errorStatementExecute, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) InsertMeasuredValues(ctx context.Context, measuredValues []*types.MeasuredValue) error { | ||||
|  | ||||
| 	sortedMeasuredValueTypes := make(map[types.MeasuredValueType][]*types.MeasuredValue) | ||||
|  | ||||
| 	for _, measuredValue := range measuredValues { | ||||
| 		if _, ok := sortedMeasuredValueTypes[measuredValue.ValueType]; !ok { | ||||
| 			sortedMeasuredValueTypes[measuredValue.ValueType] = make([]*types.MeasuredValue, 0) | ||||
| 		} | ||||
| 		sortedMeasuredValueTypes[measuredValue.ValueType] = append(sortedMeasuredValueTypes[measuredValue.ValueType], measuredValue) | ||||
| 	} | ||||
|  | ||||
| 	for measuredValueType, sortedMeasuredValues := range sortedMeasuredValueTypes { | ||||
| 		switch measuredValueType { | ||||
| 		case types.MeasuredValueTypeHumidity: | ||||
| 			if err := p.insertHumidity(ctx, sortedMeasuredValues); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		case types.MeasuredValueTypePressure: | ||||
| 			if err := p.insertPressure(ctx, sortedMeasuredValues); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		case types.MeasuredValueTypeTemperature: | ||||
| 			if err := p.insertTemperature(ctx, sortedMeasuredValues); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) insertHumidity(ctx context.Context, measuredValues []*types.MeasuredValue) error { | ||||
|  | ||||
| 	query := string(MustAsset("pkg/db/sql/psql/insertHumidity.sql")) | ||||
|  | ||||
| 	stmt, err := p.dbo.PrepareContext(ctx, query) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("%v: %v", errorPrepareStatement, err) | ||||
| 	} | ||||
| 	defer stmt.Close() | ||||
|  | ||||
| 	for _, measuredValue := range measuredValues { | ||||
|  | ||||
| 		if measuredValue.ValueType != types.MeasuredValueTypeHumidity { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		_, err := stmt.ExecContext(ctx, &measuredValue.ID, &measuredValue.Value, &measuredValue.FromDate, &measuredValue.TillDate, &measuredValue.SensorID, &measuredValue.CreationDate, &measuredValue.UpdateDate) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("%v: %v", errorStatementExecute, err) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) insertPressure(ctx context.Context, measuredValues []*types.MeasuredValue) error { | ||||
|  | ||||
| 	query := string(MustAsset("pkg/db/sql/psql/insertPressure.sql")) | ||||
|  | ||||
| 	stmt, err := p.dbo.PrepareContext(ctx, query) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("%v: %v", errorPrepareStatement, err) | ||||
| 	} | ||||
| 	defer stmt.Close() | ||||
|  | ||||
| 	for _, measuredValue := range measuredValues { | ||||
|  | ||||
| 		if measuredValue.ValueType != types.MeasuredValueTypePressure { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		_, err := stmt.ExecContext(ctx, &measuredValue.ID, &measuredValue.Value, &measuredValue.FromDate, &measuredValue.TillDate, &measuredValue.SensorID, &measuredValue.CreationDate, &measuredValue.UpdateDate) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("%v: %v", errorStatementExecute, err) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) insertTemperature(ctx context.Context, measuredValues []*types.MeasuredValue) error { | ||||
|  | ||||
| 	query := string(MustAsset("pkg/db/sql/psql/insertTemperature.sql")) | ||||
|  | ||||
| 	stmt, err := p.dbo.PrepareContext(ctx, query) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("%v: %v", errorPrepareStatement, err) | ||||
| 	} | ||||
| 	defer stmt.Close() | ||||
|  | ||||
| 	for _, measuredValue := range measuredValues { | ||||
|  | ||||
| 		if measuredValue.ValueType != types.MeasuredValueTypeTemperature { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		_, err := stmt.ExecContext(ctx, &measuredValue.ID, &measuredValue.Value, &measuredValue.FromDate, &measuredValue.TillDate, &measuredValue.SensorID, &measuredValue.CreationDate, &measuredValue.UpdateDate) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("%v: %v", errorStatementExecute, err) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) InsertSensors(ctx context.Context, sensors []*types.Sensor) error { | ||||
|  | ||||
| 	query := string(MustAsset("pkg/db/sql/psql/insertSensor.sql")) | ||||
|  | ||||
| 	stmt, err := p.dbo.PrepareContext(ctx, query) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("%v: %v", errorPrepareStatement, err) | ||||
| 	} | ||||
| 	defer stmt.Close() | ||||
|  | ||||
| 	for _, sensor := range sensors { | ||||
|  | ||||
| 		_, err := stmt.ExecContext(ctx, &sensor.SensorID, &sensor.SensorName, &sensor.SensorLocation, &sensor.WireID, &sensor.I2CBus, &sensor.I2CAddress, &sensor.GPIONumber, &sensor.SensorModel, &sensor.SensorEnabled, &sensor.DeviceID, &sensor.CreationDate) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("%v: %v", errorStatementExecute, err) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) SelectDeviceByID(ctx context.Context, id string) (*types.Device, error) { | ||||
| 	query := string(MustAsset("pkg/db/sql/psql/selectDeviceByID.sql")) | ||||
|  | ||||
| 	stmt, err := p.dbo.PrepareContext(ctx, query) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("%v: %v", errorPrepareStatement, err) | ||||
| 	} | ||||
|  | ||||
| 	row := stmt.QueryRowContext(ctx, id) | ||||
| 	if row == nil { | ||||
| 		return nil, errorRowNotFound | ||||
| 	} | ||||
|  | ||||
| 	device := new(types.Device) | ||||
| 	err = row.Scan(&device.DeviceID, &device.DeviceName, &device.DeviceLocation, &device.CreationDate) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("%v: %v", errorScanRow, err) | ||||
| 	} | ||||
|  | ||||
| 	return device, nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) SelectMeasuredValuesByIDAndType(ctx context.Context, id string, valueType types.MeasuredValueType) (*types.MeasuredValue, error) { | ||||
| 	switch valueType { | ||||
| 	case types.MeasuredValueTypeHumidity: | ||||
| 		return p.SelectHumidityByID(ctx, id) | ||||
| 	case types.MeasuredValueTypePressure: | ||||
| 		return p.SelectPressureByID(ctx, id) | ||||
| 	case types.MeasuredValueTypeTemperature: | ||||
| 		return p.SelectTemperatureByID(ctx, id) | ||||
| 	default: | ||||
| 		return nil, fmt.Errorf("%v: %v", errorUnknownMeasuredValueType, valueType) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (p *Postgres) SelectHumidities(ctx context.Context) ([]*types.MeasuredValue, error) { | ||||
| 	queryFile := "pkg/db/sql/psql/selectHumidities.sql" | ||||
| 	measuredValues, err := p.selectMeasuredValues(ctx, types.MeasuredValueTypeHumidity, queryFile, nil) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return measuredValues, nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) SelectHumidityByID(ctx context.Context, id string) (*types.MeasuredValue, error) { | ||||
| 	queryFile := "pkg/db/sql/psql/selectHumidityByID.sql" | ||||
| 	args := []interface{}{id} | ||||
| 	measuredValues, err := p.selectMeasuredValues(ctx, types.MeasuredValueTypeHumidity, queryFile, args) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if len(measuredValues) == 0 { | ||||
| 		return nil, fmt.Errorf("%v: %v", errorRowNotFound, id) | ||||
| 	} | ||||
|  | ||||
| 	return measuredValues[0], nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) SelectPressures(ctx context.Context) ([]*types.MeasuredValue, error) { | ||||
| 	queryFile := "pkg/db/sql/psql/selectPressures.sql" | ||||
| 	measuredValues, err := p.selectMeasuredValues(ctx, types.MeasuredValueTypePressure, queryFile, nil) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return measuredValues, nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) SelectPressureByID(ctx context.Context, id string) (*types.MeasuredValue, error) { | ||||
| 	queryFile := "pkg/db/sql/psql/selectPressureByID.sql" | ||||
| 	args := []interface{}{id} | ||||
| 	measuredValues, err := p.selectMeasuredValues(ctx, types.MeasuredValueTypePressure, queryFile, args) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if len(measuredValues) == 0 { | ||||
| 		return nil, fmt.Errorf("%v: %v", errorRowNotFound, id) | ||||
| 	} | ||||
|  | ||||
| 	return measuredValues[0], nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) SelectSensorByID(ctx context.Context, id string) (*types.Sensor, error) { | ||||
| 	query := string(MustAsset("pkg/db/sql/psql/selectSensorByID.sql")) | ||||
|  | ||||
| 	stmt, err := p.dbo.PrepareContext(ctx, query) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("%v: %v", errorPrepareStatement, err) | ||||
| 	} | ||||
|  | ||||
| 	row := stmt.QueryRowContext(ctx, id) | ||||
| 	if row == nil { | ||||
| 		return nil, errorRowNotFound | ||||
| 	} | ||||
|  | ||||
| 	sensor := new(types.Sensor) | ||||
| 	err = row.Scan(&sensor.SensorID, &sensor.SensorName, &sensor.SensorLocation, &sensor.WireID, &sensor.I2CBus, &sensor.I2CAddress, &sensor.GPIONumber, &sensor.SensorModel, &sensor.SensorEnabled, &sensor.DeviceID, &sensor.CreationDate) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("%v: %v", errorScanRow, err) | ||||
| 	} | ||||
|  | ||||
| 	return sensor, nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) SelectTemperatures(ctx context.Context) ([]*types.MeasuredValue, error) { | ||||
| 	queryFile := "pkg/db/sql/psql/selectTemperatures.sql" | ||||
| 	measuredValues, err := p.selectMeasuredValues(ctx, types.MeasuredValueTypeTemperature, queryFile, nil) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return measuredValues, nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) SelectTemperatureByID(ctx context.Context, id string) (*types.MeasuredValue, error) { | ||||
| 	queryFile := "pkg/db/sql/psql/selectTemperatureByID.sql" | ||||
| 	args := []interface{}{id} | ||||
| 	measuredValues, err := p.selectMeasuredValues(ctx, types.MeasuredValueTypeTemperature, queryFile, args) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if len(measuredValues) == 0 { | ||||
| 		return nil, fmt.Errorf("%v: %v", errorRowNotFound, id) | ||||
| 	} | ||||
|  | ||||
| 	return measuredValues[0], nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) selectMeasuredValues(ctx context.Context, measuredValueType types.MeasuredValueType, queryFile string, queryArgs []interface{}) ([]*types.MeasuredValue, error) { | ||||
| 	query := string(MustAsset(queryFile)) | ||||
|  | ||||
| 	stmt, err := p.dbo.PrepareContext(ctx, query) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("%v: %v", errorPrepareStatement, err) | ||||
| 	} | ||||
|  | ||||
| 	rows, err := stmt.QueryContext(ctx, queryArgs...) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("%v: %v", errorStatementQuery, err) | ||||
| 	} | ||||
|  | ||||
| 	measuredValues := make([]*types.MeasuredValue, 0) | ||||
| 	for rows.Next() { | ||||
| 		measuredValue := new(types.MeasuredValue) | ||||
| 		measuredValue.ValueType = measuredValueType | ||||
| 		rows.Scan(&measuredValue.ID, &measuredValue.Value, &measuredValue.FromDate, &measuredValue.TillDate, &measuredValue.SensorID, &measuredValue.CreationDate, &measuredValue.UpdateDate) | ||||
| 		measuredValues = append(measuredValues, measuredValue) | ||||
| 	} | ||||
|  | ||||
| 	return measuredValues, nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) UpdateDevices(ctx context.Context, devices []*types.Device) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) UpdateMeasuredValues(ctx context.Context, measuredValues []*types.MeasuredValue) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (p *Postgres) UpdateSensors(ctx context.Context, sensots []*types.Sensor) error { | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										273
									
								
								pkg/db/postgres_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										273
									
								
								pkg/db/postgres_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,273 @@ | ||||
| package db_test | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/go-flucky/flucky/pkg/db" | ||||
| 	"github.com/go-flucky/flucky/pkg/types" | ||||
| 	"github.com/go-flucky/flucky/test/goldenfiles" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| ) | ||||
|  | ||||
| type test struct { | ||||
| 	Name string | ||||
| 	Test func(*testing.T) | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	database db.Database | ||||
|  | ||||
| 	postgresContainerImage string = "docker.io/postgres/postgres" | ||||
| 	postgresHost           string = "localhost" | ||||
| 	postgresPort           string = "5432" | ||||
| 	postgresUser           string = "postgres" | ||||
| 	postgresPassword       string = "postgres" | ||||
| 	postgresDatabase       string = "postgres" | ||||
|  | ||||
| 	goldenDevicesFilePath        string = "test/goldenfiles/json/goldenDevices.json" | ||||
| 	goldenSensorsFilePath        string = "test/goldenfiles/json/goldenSensors.json" | ||||
| 	goldenMeasuredValuesFilePath string = "test/goldenfiles/json/goldenMeasuredValues.json" | ||||
| 	goldenPressuresFilePath      string = "test/goldenfiles/json/goldenPressures.json" | ||||
| 	goldenHumiditiesFilePath     string = "test/goldenfiles/json/goldenHumidities.json" | ||||
| 	goldenTemperaturesFilePath   string = "test/goldenfiles/json/goldenTemperatures.json" | ||||
|  | ||||
| 	goldenDevices        []*types.Device | ||||
| 	goldenSensors        []*types.Sensor | ||||
| 	goldenMeasuredValues []*types.MeasuredValue | ||||
| 	goldenPressures      []*types.MeasuredValue | ||||
| 	goldenHumidites      []*types.MeasuredValue | ||||
| 	goldenTemperatures   []*types.MeasuredValue | ||||
| ) | ||||
|  | ||||
| func load(t *testing.T) { | ||||
| 	require := require.New(t) | ||||
|  | ||||
| 	d, err := goldenfiles.GetGoldenDevices(goldenDevicesFilePath) | ||||
| 	require.NoError(err) | ||||
| 	goldenDevices = d | ||||
|  | ||||
| 	s, err := goldenfiles.GetGoldenSensors(goldenSensorsFilePath) | ||||
| 	require.NoError(err) | ||||
| 	goldenSensors = s | ||||
|  | ||||
| 	hum, err := goldenfiles.GetGoldenMeasuredValues(goldenHumiditiesFilePath) | ||||
| 	require.NoError(err) | ||||
| 	goldenHumidites = hum | ||||
|  | ||||
| 	mv, err := goldenfiles.GetGoldenMeasuredValues(goldenMeasuredValuesFilePath) | ||||
| 	require.NoError(err) | ||||
| 	goldenMeasuredValues = mv | ||||
|  | ||||
| 	pres, err := goldenfiles.GetGoldenMeasuredValues(goldenPressuresFilePath) | ||||
| 	require.NoError(err) | ||||
| 	goldenPressures = pres | ||||
|  | ||||
| 	temp, err := goldenfiles.GetGoldenMeasuredValues(goldenTemperaturesFilePath) | ||||
| 	require.NoError(err) | ||||
| 	goldenTemperatures = temp | ||||
|  | ||||
| } | ||||
|  | ||||
| func TestPostgres(t *testing.T) { | ||||
| 	require := require.New(t) | ||||
|  | ||||
| 	load(t) | ||||
|  | ||||
| 	db, err := db.New(db.DBOTypePostgres, postgresHost, postgresPort, postgresDatabase, postgresUser, postgresPassword) | ||||
| 	database = db | ||||
| 	require.Nil(err) | ||||
|  | ||||
| 	tests := []*test{ | ||||
| 		&test{ | ||||
| 			Name: "insertDevices", | ||||
| 			Test: testInsertDevices, | ||||
| 		}, | ||||
| 		&test{ | ||||
| 			Name: "insertSensors", | ||||
| 			Test: testInsertSensors, | ||||
| 		}, | ||||
| 		&test{ | ||||
| 			Name: "insertHumidity", | ||||
| 			Test: testInsertHumidity, | ||||
| 		}, | ||||
| 		&test{ | ||||
| 			Name: "insertPressure", | ||||
| 			Test: testInsertPressure, | ||||
| 		}, | ||||
| 		&test{ | ||||
| 			Name: "insertTemperatures", | ||||
| 			Test: testInsertTemperatures, | ||||
| 		}, | ||||
| 		&test{ | ||||
| 			Name: "deleteHumidities", | ||||
| 			Test: testDeleteHumidity, | ||||
| 		}, | ||||
| 		&test{ | ||||
| 			Name: "deletePressures", | ||||
| 			Test: testDeletePressures, | ||||
| 		}, | ||||
| 		&test{ | ||||
| 			Name: "deleteTemperatures", | ||||
| 			Test: testDeleteTemperatures, | ||||
| 		}, | ||||
| 		&test{ | ||||
| 			Name: "insertMeasuredValues", | ||||
| 			Test: testInsertMeasuredValues, | ||||
| 		}, | ||||
| 		&test{ | ||||
| 			Name: "deleteMeasuredValues", | ||||
| 			Test: testDeleteMeasuredValues, | ||||
| 		}, | ||||
| 		&test{ | ||||
| 			Name: "deleteSensors", | ||||
| 			Test: testDeleteSensors, | ||||
| 		}, | ||||
| 		&test{ | ||||
| 			Name: "deleteDevices", | ||||
| 			Test: testDeleteDevices, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range tests { | ||||
| 		t.Run(test.Name, test.Test) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func testInsertDevices(t *testing.T) { | ||||
| 	require := require.New(t) | ||||
| 	ctx := context.Background() | ||||
| 	err := database.InsertDevices(ctx, goldenDevices) | ||||
| 	require.NoError(err) | ||||
| 	for _, goldenDevice := range goldenDevices { | ||||
| 		testDevice, err := database.SelectDeviceByID(ctx, goldenDevice.DeviceID) | ||||
| 		require.NoError(err) | ||||
| 		goldenfiles.CompareMeasuredValues(t, goldenDevice, testDevice) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func testInsertSensors(t *testing.T) { | ||||
| 	require := require.New(t) | ||||
| 	ctx := context.Background() | ||||
| 	err := database.InsertSensors(ctx, goldenSensors) | ||||
| 	require.NoError(err) | ||||
| 	for _, goldenSensor := range goldenSensors { | ||||
| 		testSensor, err := database.SelectSensorByID(ctx, goldenSensor.SensorID) | ||||
| 		require.NoError(err) | ||||
| 		goldenfiles.CompareMeasuredValues(t, goldenSensor, testSensor) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func testInsertHumidity(t *testing.T) { | ||||
| 	require := require.New(t) | ||||
| 	ctx := context.Background() | ||||
| 	err := database.InsertMeasuredValues(ctx, goldenHumidites) | ||||
| 	require.NoError(err) | ||||
| 	for _, goldenHumidity := range goldenHumidites { | ||||
| 		testHumidity, err := database.SelectHumidityByID(ctx, goldenHumidity.ID) | ||||
| 		require.NoError(err) | ||||
| 		goldenfiles.CompareMeasuredValues(t, []*types.MeasuredValue{testHumidity}, []*types.MeasuredValue{testHumidity}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func testInsertMeasuredValues(t *testing.T) { | ||||
| 	require := require.New(t) | ||||
| 	ctx := context.Background() | ||||
| 	err := database.InsertMeasuredValues(ctx, goldenMeasuredValues) | ||||
| 	require.NoError(err) | ||||
| 	for _, goldenMeasuredValue := range goldenMeasuredValues { | ||||
| 		testMeasuredValue, err := database.SelectMeasuredValuesByIDAndType(ctx, goldenMeasuredValue.ID, goldenMeasuredValue.ValueType) | ||||
| 		require.NoError(err) | ||||
| 		goldenfiles.CompareMeasuredValues(t, []*types.MeasuredValue{goldenMeasuredValue}, []*types.MeasuredValue{testMeasuredValue}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func testInsertPressure(t *testing.T) { | ||||
| 	require := require.New(t) | ||||
| 	ctx := context.Background() | ||||
| 	err := database.InsertMeasuredValues(ctx, goldenPressures) | ||||
| 	require.NoError(err) | ||||
| 	for _, goldenPressure := range goldenPressures { | ||||
| 		testPressure, err := database.SelectPressureByID(ctx, goldenPressure.ID) | ||||
| 		require.NoError(err) | ||||
| 		goldenfiles.CompareMeasuredValues(t, []*types.MeasuredValue{testPressure}, []*types.MeasuredValue{testPressure}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func testInsertTemperatures(t *testing.T) { | ||||
| 	require := require.New(t) | ||||
| 	ctx := context.Background() | ||||
| 	err := database.InsertMeasuredValues(ctx, goldenTemperatures) | ||||
| 	require.NoError(err) | ||||
| 	for _, goldenTemperature := range goldenTemperatures { | ||||
| 		testTemperature, err := database.SelectTemperatureByID(ctx, goldenTemperature.ID) | ||||
| 		require.NoError(err) | ||||
| 		goldenfiles.CompareMeasuredValues(t, []*types.MeasuredValue{goldenTemperature}, []*types.MeasuredValue{testTemperature}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func testDeleteDevices(t *testing.T) { | ||||
| 	require := require.New(t) | ||||
| 	ctx := context.Background() | ||||
| 	err := database.DeleteDevices(ctx, goldenDevices) | ||||
| 	require.NoError(err) | ||||
| 	for _, goldenDevice := range goldenDevices { | ||||
| 		_, err := database.SelectDeviceByID(ctx, goldenDevice.DeviceID) | ||||
| 		require.Error(err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func testDeleteSensors(t *testing.T) { | ||||
| 	require := require.New(t) | ||||
| 	ctx := context.Background() | ||||
| 	err := database.DeleteSensors(ctx, goldenSensors) | ||||
| 	require.NoError(err) | ||||
| 	for _, goldenSensor := range goldenSensors { | ||||
| 		_, err := database.SelectDeviceByID(ctx, goldenSensor.SensorID) | ||||
| 		require.Error(err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func testDeleteHumidity(t *testing.T) { | ||||
| 	require := require.New(t) | ||||
| 	ctx := context.Background() | ||||
| 	err := database.DeleteMeasuredValues(ctx, goldenHumidites) | ||||
| 	require.NoError(err) | ||||
| 	for _, goldenHumidity := range goldenHumidites { | ||||
| 		_, err := database.SelectHumidityByID(ctx, goldenHumidity.ID) | ||||
| 		require.Error(err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func testDeleteMeasuredValues(t *testing.T) { | ||||
| 	require := require.New(t) | ||||
| 	ctx := context.Background() | ||||
| 	err := database.DeleteMeasuredValues(ctx, goldenMeasuredValues) | ||||
| 	require.NoError(err) | ||||
| 	for _, goldenMeasuredValue := range goldenMeasuredValues { | ||||
| 		_, err := database.SelectPressureByID(ctx, goldenMeasuredValue.ID) | ||||
| 		require.Error(err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func testDeletePressures(t *testing.T) { | ||||
| 	require := require.New(t) | ||||
| 	ctx := context.Background() | ||||
| 	err := database.DeleteMeasuredValues(ctx, goldenPressures) | ||||
| 	require.NoError(err) | ||||
| 	for _, goldenPressure := range goldenPressures { | ||||
| 		_, err := database.SelectPressureByID(ctx, goldenPressure.ID) | ||||
| 		require.Error(err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func testDeleteTemperatures(t *testing.T) { | ||||
| 	require := require.New(t) | ||||
| 	ctx := context.Background() | ||||
| 	err := database.DeleteMeasuredValues(ctx, goldenTemperatures) | ||||
| 	require.NoError(err) | ||||
| 	for _, goldenTemperature := range goldenTemperatures { | ||||
| 		_, err := database.SelectTemperatureByID(ctx, goldenTemperature.ID) | ||||
| 		require.Error(err) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										2
									
								
								pkg/db/sql/psql/deleteDevice.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								pkg/db/sql/psql/deleteDevice.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| DELETE FROM devices | ||||
| WHERE device_id = $1; | ||||
							
								
								
									
										2
									
								
								pkg/db/sql/psql/deleteHumidity.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								pkg/db/sql/psql/deleteHumidity.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| DELETE FROM humidities | ||||
| WHERE humidity_id = $1; | ||||
							
								
								
									
										2
									
								
								pkg/db/sql/psql/deletePressure.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								pkg/db/sql/psql/deletePressure.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| DELETE FROM pressures | ||||
| WHERE pressure_id = $1; | ||||
							
								
								
									
										2
									
								
								pkg/db/sql/psql/deleteSensor.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								pkg/db/sql/psql/deleteSensor.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| DELETE FROM sensors | ||||
| WHERE sensor_id = $1; | ||||
							
								
								
									
										2
									
								
								pkg/db/sql/psql/deleteTemperature.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								pkg/db/sql/psql/deleteTemperature.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| DELETE FROM temperatures | ||||
| WHERE temperature_id = $1; | ||||
							
								
								
									
										7
									
								
								pkg/db/sql/psql/insertDevice.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								pkg/db/sql/psql/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/db/sql/psql/insertHumidity.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								pkg/db/sql/psql/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/db/sql/psql/insertPressure.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								pkg/db/sql/psql/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/db/sql/psql/insertSensor.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								pkg/db/sql/psql/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/db/sql/psql/insertTemperature.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								pkg/db/sql/psql/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); | ||||
							
								
								
									
										146
									
								
								pkg/db/sql/psql/schema.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								pkg/db/sql/psql/schema.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,146 @@ | ||||
| DROP TABLE IF EXISTS devices CASCADE; | ||||
| DROP TABLE IF EXISTS sensors CASCADE; | ||||
| DROP TABLE IF EXISTS humidities CASCADE; | ||||
| DROP TABLE IF EXISTS pressures CASCADE; | ||||
| DROP TABLE IF EXISTS temperatures CASCADE; | ||||
|  | ||||
|  | ||||
| -- +----------------------------------------+ | ||||
| -- |                  TABLES                | | ||||
| -- +----------------------------------------+ | ||||
| CREATE TABLE IF NOT EXISTS devices( | ||||
|   device_id               CHAR(36)                                                CONSTRAINT pk_devices PRIMARY KEY, | ||||
|   device_name             VARCHAR(32)                                             NOT NULL, | ||||
|   device_location         VARCHAR(32), | ||||
|   device_last_contact     TIMESTAMP WITH TIME ZONE    DEFAULT CURRENT_TIMESTAMP   NOT NULL, | ||||
|   creation_date           TIMESTAMP WITH TIME ZONE    DEFAULT CURRENT_TIMESTAMP | ||||
| ); | ||||
|  | ||||
| CREATE TABLE IF NOT EXISTS sensors ( | ||||
|   sensor_id               CHAR(36)                                                CONSTRAINT pk_sensors PRIMARY KEY, | ||||
|   sensor_name             VARCHAR(32)                                             NOT NULL, | ||||
|   sensor_location         VARCHAR(32)                                             NOT NULL, | ||||
|   wire_id                 VARCHAR(15), | ||||
|   i2c_bus                 VARCHAR(255), | ||||
|   i2c_address             VARCHAR(12), | ||||
|   gpio_number             VARCHAR(6), | ||||
|   sensor_model            VARCHAR(16)                                             NOT NULL, | ||||
|   sensor_enabled          BOOLEAN                     DEFAULT TRUE                NOT NULL, | ||||
|   sensor_last_contact     TIMESTAMP WITH TIME ZONE    DEFAULT CURRENT_TIMESTAMP   NOT NULL, | ||||
|   device_id               CHAR(36), | ||||
|   creation_date           TIMESTAMP WITH TIME ZONE    DEFAULT CURRENT_TIMESTAMP   NOT NULL | ||||
| ); | ||||
|  | ||||
| CREATE TABLE IF NOT EXISTS humidities ( | ||||
|   humidity_id             CHAR(36)                                                CONSTRAINT pk_humidities PRIMARY KEY, | ||||
|   humidity_value          NUMERIC(9,3)                                            NOT NULL, | ||||
|   humidity_from_date      TIMESTAMP WITH TIME ZONE                                NOT NULL, | ||||
|   humidity_till_date      TIMESTAMP WITH TIME ZONE, | ||||
|   sensor_id               CHAR(36), | ||||
|   creation_date           TIMESTAMP WITH TIME ZONE    DEFAULT CURRENT_TIMESTAMP   NOT NULL, | ||||
|   update_date             TIMESTAMP WITH TIME ZONE | ||||
| ); | ||||
|  | ||||
| CREATE TABLE IF NOT EXISTS pressures ( | ||||
|   pressure_id             CHAR(36)                                                CONSTRAINT pk_pressures PRIMARY KEY, | ||||
|   pressure_value          NUMERIC(10,3)                                           NOT NULL, | ||||
|   pressure_from_date      TIMESTAMP WITH TIME ZONE                                NOT NULL, | ||||
|   pressure_till_date      TIMESTAMP WITH TIME ZONE, | ||||
|   sensor_id               CHAR(36), | ||||
|   creation_date           TIMESTAMP WITH TIME ZONE    DEFAULT CURRENT_TIMESTAMP   NOT NULL, | ||||
|   update_date             TIMESTAMP WITH TIME ZONE | ||||
| ); | ||||
|  | ||||
| CREATE TABLE IF NOT EXISTS temperatures ( | ||||
|   temperature_id          CHAR(36)                                                CONSTRAINT pk_temperatures PRIMARY KEY, | ||||
|   temperature_value       NUMERIC(5,3)                                            NOT NULL, | ||||
|   temperature_from_date   TIMESTAMP WITH TIME ZONE                                NOT NULL, | ||||
|   temperature_till_date   TIMESTAMP WITH TIME ZONE, | ||||
|   sensor_id               CHAR(36), | ||||
|   creation_date           TIMESTAMP WITH TIME ZONE    DEFAULT CURRENT_TIMESTAMP   NOT NULL, | ||||
|   update_date             TIMESTAMP WITH TIME ZONE | ||||
| ); | ||||
|  | ||||
| -- +----------------------------------------+ | ||||
| -- |               FOREIGN-KEYS             | | ||||
| -- +----------------------------------------+ | ||||
| ALTER TABLE sensors | ||||
| ADD FOREIGN KEY (device_id) | ||||
| REFERENCES devices(device_id) | ||||
| ON DELETE CASCADE | ||||
| ON UPDATE CASCADE; | ||||
|  | ||||
| ALTER TABLE humidities | ||||
| ADD FOREIGN KEY (sensor_id) | ||||
| REFERENCES sensors(sensor_id) | ||||
| ON DELETE CASCADE | ||||
| ON UPDATE CASCADE; | ||||
|  | ||||
| ALTER TABLE pressures | ||||
| ADD FOREIGN KEY (sensor_id) | ||||
| REFERENCES sensors(sensor_id) | ||||
| ON DELETE CASCADE | ||||
| ON UPDATE CASCADE; | ||||
|  | ||||
| ALTER TABLE temperatures | ||||
| ADD FOREIGN KEY (sensor_id) | ||||
| REFERENCES sensors(sensor_id) | ||||
| ON DELETE CASCADE | ||||
| ON UPDATE CASCADE; | ||||
|  | ||||
| -- +----------------------------------------+ | ||||
| -- |            Trigger-Functions           | | ||||
| -- +----------------------------------------+ | ||||
| CREATE OR REPLACE FUNCTION device_last_contact() | ||||
|   RETURNS trigger AS | ||||
| $BODY$ | ||||
| BEGIN | ||||
|  UPDATE devices | ||||
|  SET device_last_contact = CURRENT_TIMESTAMP | ||||
|  WHERE device_id = NEW.device_id; | ||||
|  RETURN NEW; | ||||
| END; | ||||
| $BODY$ LANGUAGE plpgsql; | ||||
|  | ||||
| CREATE OR REPLACE FUNCTION sensor_last_contact() | ||||
|   RETURNS trigger AS | ||||
| $BODY$ | ||||
| BEGIN | ||||
|  UPDATE sensors | ||||
|  SET sensor_last_contact = CURRENT_TIMESTAMP, | ||||
|      sensor_enabled = true | ||||
|  WHERE sensor_id = NEW.sensor_id; | ||||
|  RETURN NEW; | ||||
| END; | ||||
| $BODY$ LANGUAGE plpgsql; | ||||
|  | ||||
| -- +----------------------------------------+ | ||||
| -- |                  Trigger               | | ||||
| -- +----------------------------------------+ | ||||
| DROP TRIGGER IF EXISTS ai_humidities ON humidities; | ||||
| DROP TRIGGER IF EXISTS ai_pressure ON pressures; | ||||
| DROP TRIGGER IF EXISTS ai_temperatures ON temperatures; | ||||
|  | ||||
| CREATE TRIGGER au_sensors | ||||
|   AFTER UPDATE | ||||
|   ON sensors | ||||
|   FOR EACH ROW | ||||
|   EXECUTE PROCEDURE device_last_contact(); | ||||
|  | ||||
| CREATE TRIGGER ai_humidities | ||||
|   AFTER INSERT | ||||
|   ON humidities | ||||
|   FOR EACH ROW | ||||
|   EXECUTE PROCEDURE sensor_last_contact(); | ||||
|  | ||||
| CREATE TRIGGER ai_pressures | ||||
|   AFTER INSERT | ||||
|   ON pressures | ||||
|   FOR EACH ROW | ||||
|   EXECUTE PROCEDURE sensor_last_contact(); | ||||
|  | ||||
| CREATE TRIGGER ai_temperatures | ||||
|   AFTER INSERT | ||||
|   ON temperatures | ||||
|   FOR EACH ROW | ||||
|   EXECUTE PROCEDURE sensor_last_contact(); | ||||
							
								
								
									
										8
									
								
								pkg/db/sql/psql/selectDeviceByID.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								pkg/db/sql/psql/selectDeviceByID.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| SELECT | ||||
|   device_id, | ||||
|   device_name, | ||||
|   device_location, | ||||
|   creation_date | ||||
| FROM | ||||
|   devices | ||||
| WHERE device_id = $1; | ||||
							
								
								
									
										10
									
								
								pkg/db/sql/psql/selectHumidities.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								pkg/db/sql/psql/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/db/sql/psql/selectHumidityByID.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								pkg/db/sql/psql/selectHumidityByID.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/db/sql/psql/selectPressureByID.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								pkg/db/sql/psql/selectPressureByID.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/db/sql/psql/selectPressures.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								pkg/db/sql/psql/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/db/sql/psql/selectSensorByID.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								pkg/db/sql/psql/selectSensorByID.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; | ||||
							
								
								
									
										12
									
								
								pkg/db/sql/psql/selectTemperatureByID.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								pkg/db/sql/psql/selectTemperatureByID.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/db/sql/psql/selectTemperatures.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								pkg/db/sql/psql/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; | ||||
							
								
								
									
										23
									
								
								pkg/internal/format/format.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								pkg/internal/format/format.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| package format | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"math" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	errorPraseTime = errors.New("Can not parse time") | ||||
|  | ||||
| 	TimeFormat = "2006-01-02T15:04:05.999999Z07:00" | ||||
| ) | ||||
|  | ||||
| // FormatedTime returns a current timestamp without nano seconds. Postgres | ||||
| // currently does not support nanoseconds which is automatically include into | ||||
| // the go time object | ||||
| func FormatedTime() time.Time { | ||||
| 	t := time.Now() | ||||
| 	l, _ := time.LoadLocation("Europe/Berlin") | ||||
| 	return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), int(math.Round(float64(t.Nanosecond())/1000000)*1000000), l) | ||||
|  | ||||
| } | ||||
| @@ -7,6 +7,7 @@ import ( | ||||
| 	"strconv" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/go-flucky/flucky/pkg/internal/format" | ||||
| 	"github.com/go-flucky/flucky/pkg/types" | ||||
| ) | ||||
|  | ||||
| @@ -50,7 +51,7 @@ func (cl *csvLogfile) Read() ([]*types.MeasuredValue, error) { | ||||
| 		// Times | ||||
| 		times := make([]time.Time, 0) | ||||
| 		for _, i := range []int{3, 4} { | ||||
| 			time, err := time.Parse(timeFormat, record[i]) | ||||
| 			time, err := time.Parse(format.TimeFormat, record[i]) | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("%v %v: %v", errorParseTime, record[i], err) | ||||
| 			} | ||||
| @@ -67,14 +68,14 @@ func (cl *csvLogfile) Read() ([]*types.MeasuredValue, error) { | ||||
| 		} | ||||
|  | ||||
| 		// Creation date | ||||
| 		creationDate, err := time.Parse(timeFormat, record[6]) | ||||
| 		creationDate, err := time.Parse(format.TimeFormat, record[6]) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("%v %v: %v", errorParseTime, record[6], err) | ||||
| 		} | ||||
| 		measuredValue.CreationDate = &creationDate | ||||
| 		measuredValue.CreationDate = creationDate | ||||
|  | ||||
| 		if record[7] != "null" { | ||||
| 			updateDate, err := time.Parse(timeFormat, record[7]) | ||||
| 			updateDate, err := time.Parse(format.TimeFormat, record[7]) | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("%v %v: %v", errorParseTime, record[7], err) | ||||
| 			} | ||||
| @@ -106,19 +107,15 @@ func (cl *csvLogfile) Write(measuredValues []*types.MeasuredValue) error { | ||||
| 			measuredValue.ID, | ||||
| 			fmt.Sprintf("%v", measuredValue.ValueType), | ||||
| 			fmt.Sprintf("%v", measuredValue.Value), | ||||
| 			measuredValue.FromDate.Format(timeFormat), | ||||
| 			measuredValue.TillDate.Format(timeFormat), | ||||
| 			measuredValue.FromDate.Format(format.TimeFormat), | ||||
| 			measuredValue.TillDate.Format(format.TimeFormat), | ||||
| 			measuredValue.SensorID, | ||||
| 		} | ||||
|  | ||||
| 		if measuredValue.CreationDate != nil { | ||||
| 			record = append(record, measuredValue.CreationDate.Format(timeFormat)) | ||||
| 		} else { | ||||
| 			record = append(record, "null") | ||||
| 		} | ||||
| 		record = append(record, measuredValue.CreationDate.Format(format.TimeFormat)) | ||||
|  | ||||
| 		if measuredValue.UpdateDate != nil { | ||||
| 			record = append(record, measuredValue.UpdateDate.Format(timeFormat)) | ||||
| 			record = append(record, measuredValue.UpdateDate.Format(format.TimeFormat)) | ||||
| 		} else { | ||||
| 			record = append(record, "null") | ||||
| 		} | ||||
|   | ||||
| @@ -2,25 +2,27 @@ package logfile | ||||
|  | ||||
| import "errors" | ||||
|  | ||||
| var errorLogfileCreate = errors.New("Can not create logfile") | ||||
| var errorLogfileDecode = errors.New("Can not decode from reader") | ||||
| var errorLogfileEncode = errors.New("Can not encode from writer") | ||||
| var errorLogfileMarshal = errors.New("Can not marshal values") | ||||
| var errorLogfileNotFound = errors.New("Can not find logfile") | ||||
| var errorLogfileOpen = errors.New("Can not open logfile") | ||||
| var errorLogfileRead = errors.New("Can not read from given reader") | ||||
| var errorLogfileUnmarshal = errors.New("Can not unmarshal values") | ||||
| var errorLogfileWrite = errors.New("Can not write with given writer") | ||||
| var ( | ||||
| 	errorLogfileCreate    = errors.New("Can not create logfile") | ||||
| 	errorLogfileDecode    = errors.New("Can not decode from reader") | ||||
| 	errorLogfileEncode    = errors.New("Can not encode from writer") | ||||
| 	errorLogfileMarshal   = errors.New("Can not marshal values") | ||||
| 	errorLogfileNotFound  = errors.New("Can not find logfile") | ||||
| 	errorLogfileOpen      = errors.New("Can not open logfile") | ||||
| 	errorLogfileRead      = errors.New("Can not read from given reader") | ||||
| 	errorLogfileUnmarshal = errors.New("Can not unmarshal values") | ||||
| 	errorLogfileWrite     = errors.New("Can not write with given writer") | ||||
|  | ||||
| var errorParseFloat = errors.New("Can not parse float") | ||||
| var errorParseMeasurementUnit = errors.New("Can not parse mesaurement unit") | ||||
| var errorParseTime = errors.New("Can not parse time") | ||||
| 	errorParseFloat           = errors.New("Can not parse float") | ||||
| 	errorParseMeasurementUnit = errors.New("Can not parse mesaurement unit") | ||||
| 	errorParseTime            = errors.New("Can not parse time") | ||||
|  | ||||
| var errorNoValidHumidityID = errors.New("No valid humidity id detected or available") | ||||
| var errorNoValidMesuredValue = errors.New("No mesured value detected or available") | ||||
| var errorNoValidSensorID = errors.New("No sensor id detected or available") | ||||
| var errorNoValidTemperatureID = errors.New("No valid temperature id detected or available") | ||||
| var errorNoValidTime = errors.New("No time detected or available") | ||||
| var errorNoValidTimePeriods = errors.New("No valid time periods") | ||||
| 	errorNoValidHumidityID    = errors.New("No valid humidity id detected or available") | ||||
| 	errorNoValidMesuredValue  = errors.New("No mesured value detected or available") | ||||
| 	errorNoValidSensorID      = errors.New("No sensor id detected or available") | ||||
| 	errorNoValidTemperatureID = errors.New("No valid temperature id detected or available") | ||||
| 	errorNoValidTime          = errors.New("No time detected or available") | ||||
| 	errorNoValidTimePeriods   = errors.New("No valid time periods") | ||||
|  | ||||
| var errorTypeSwitch = errors.New("Can not detect type via type switch") | ||||
| 	errorTypeSwitch = errors.New("Can not detect type via type switch") | ||||
| ) | ||||
|   | ||||
| @@ -4,13 +4,12 @@ import ( | ||||
| 	"math" | ||||
| 	"path/filepath" | ||||
| 	"sort" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/go-flucky/flucky/pkg/internal/format" | ||||
| 	"github.com/go-flucky/flucky/pkg/types" | ||||
| ) | ||||
|  | ||||
| // var validUUID = regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$") | ||||
| var timeFormat = "2006-01-02T15:04:05.999999Z07:00" | ||||
|  | ||||
| // Append adds an array of several measured values to a logfile | ||||
| func Append(logfile Logfile, compression bool, round float64, measuredValues []*types.MeasuredValue) error { | ||||
| @@ -56,7 +55,7 @@ func Compression(measuredValues []*types.MeasuredValue) []*types.MeasuredValue { | ||||
| 		return measuredValues[i].FromDate.Before(measuredValues[j].TillDate) | ||||
| 	}) | ||||
|  | ||||
| 	now := time.Now() | ||||
| 	now := format.FormatedTime() | ||||
|  | ||||
| 	for _, measuredValue := range measuredValues { | ||||
| 		if _, ok := lastMeasuredValuesBySensors[measuredValue.SensorID]; !ok { | ||||
| @@ -124,11 +123,10 @@ func New(logfile string) Logfile { | ||||
|  | ||||
| } | ||||
|  | ||||
| func writeCreationDate(measuredValues []*types.MeasuredValue) { | ||||
| 	now := time.Now() | ||||
| func writeCreationDate(measuredValues []*types.MeasuredValue) error { | ||||
| 	for _, measuredValue := range measuredValues { | ||||
| 		if measuredValue.CreationDate == nil { | ||||
| 			measuredValue.CreationDate = &now | ||||
| 		} | ||||
| 		now := format.FormatedTime() | ||||
| 		measuredValue.CreationDate = now | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -5,11 +5,11 @@ import ( | ||||
| 	"fmt" | ||||
| 	"log" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/d2r2/go-bsbmp" | ||||
| 	"github.com/d2r2/go-i2c" | ||||
| 	"github.com/d2r2/go-logger" | ||||
| 	"github.com/go-flucky/flucky/pkg/internal/format" | ||||
| 	"github.com/go-flucky/flucky/pkg/types" | ||||
| 	uuid "github.com/satori/go.uuid" | ||||
| ) | ||||
| @@ -67,24 +67,24 @@ func (s *BME280) Read() ([]*types.MeasuredValue, error) { | ||||
| 			ID:        uuid.NewV4().String(), | ||||
| 			Value:     float64(humidityValue), | ||||
| 			ValueType: types.MeasuredValueTypeHumidity, | ||||
| 			FromDate:  time.Now(), | ||||
| 			TillDate:  time.Now(), | ||||
| 			FromDate:  format.FormatedTime(), | ||||
| 			TillDate:  format.FormatedTime(), | ||||
| 			SensorID:  s.SensorID, | ||||
| 		}, | ||||
| 		&types.MeasuredValue{ | ||||
| 			ID:        uuid.NewV4().String(), | ||||
| 			Value:     float64(pressureValue), | ||||
| 			ValueType: types.MeasuredValueTypePressure, | ||||
| 			FromDate:  time.Now(), | ||||
| 			TillDate:  time.Now(), | ||||
| 			FromDate:  format.FormatedTime(), | ||||
| 			TillDate:  format.FormatedTime(), | ||||
| 			SensorID:  s.SensorID, | ||||
| 		}, | ||||
| 		&types.MeasuredValue{ | ||||
| 			ID:        uuid.NewV4().String(), | ||||
| 			Value:     float64(temperatureValue), | ||||
| 			ValueType: types.MeasuredValueTypeTemperature, | ||||
| 			FromDate:  time.Now(), | ||||
| 			TillDate:  time.Now(), | ||||
| 			FromDate:  format.FormatedTime(), | ||||
| 			TillDate:  format.FormatedTime(), | ||||
| 			SensorID:  s.SensorID, | ||||
| 		}, | ||||
| 	} | ||||
|   | ||||
| @@ -4,8 +4,8 @@ import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/go-flucky/flucky/pkg/internal/format" | ||||
| 	"github.com/go-flucky/flucky/pkg/types" | ||||
| 	"github.com/go-flucky/go-dht" | ||||
| 	uuid "github.com/satori/go.uuid" | ||||
| @@ -49,16 +49,16 @@ func (s *DHT11) Read() ([]*types.MeasuredValue, error) { | ||||
| 			ID:        uuid.NewV4().String(), | ||||
| 			Value:     float64(humidityValue), | ||||
| 			ValueType: types.MeasuredValueTypeHumidity, | ||||
| 			FromDate:  time.Now(), | ||||
| 			TillDate:  time.Now(), | ||||
| 			FromDate:  format.FormatedTime(), | ||||
| 			TillDate:  format.FormatedTime(), | ||||
| 			SensorID:  s.SensorID, | ||||
| 		}, | ||||
| 		&types.MeasuredValue{ | ||||
| 			ID:        uuid.NewV4().String(), | ||||
| 			Value:     float64(temperatureValue), | ||||
| 			ValueType: types.MeasuredValueTypeTemperature, | ||||
| 			FromDate:  time.Now(), | ||||
| 			TillDate:  time.Now(), | ||||
| 			FromDate:  format.FormatedTime(), | ||||
| 			TillDate:  format.FormatedTime(), | ||||
| 			SensorID:  s.SensorID, | ||||
| 		}, | ||||
| 	} | ||||
|   | ||||
| @@ -4,8 +4,8 @@ import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/go-flucky/flucky/pkg/internal/format" | ||||
| 	"github.com/go-flucky/flucky/pkg/types" | ||||
| 	"github.com/go-flucky/go-dht" | ||||
| 	uuid "github.com/satori/go.uuid" | ||||
| @@ -49,16 +49,16 @@ func (s *DHT22) Read() ([]*types.MeasuredValue, error) { | ||||
| 			ID:        uuid.NewV4().String(), | ||||
| 			Value:     float64(humidityValue), | ||||
| 			ValueType: types.MeasuredValueTypeHumidity, | ||||
| 			FromDate:  time.Now(), | ||||
| 			TillDate:  time.Now(), | ||||
| 			FromDate:  format.FormatedTime(), | ||||
| 			TillDate:  format.FormatedTime(), | ||||
| 			SensorID:  s.SensorID, | ||||
| 		}, | ||||
| 		&types.MeasuredValue{ | ||||
| 			ID:        uuid.NewV4().String(), | ||||
| 			Value:     float64(temperatureValue), | ||||
| 			ValueType: types.MeasuredValueTypeTemperature, | ||||
| 			FromDate:  time.Now(), | ||||
| 			TillDate:  time.Now(), | ||||
| 			FromDate:  format.FormatedTime(), | ||||
| 			TillDate:  format.FormatedTime(), | ||||
| 			SensorID:  s.SensorID, | ||||
| 		}, | ||||
| 	} | ||||
|   | ||||
| @@ -8,8 +8,8 @@ import ( | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/go-flucky/flucky/pkg/internal/format" | ||||
| 	"github.com/go-flucky/flucky/pkg/types" | ||||
| 	uuid "github.com/satori/go.uuid" | ||||
| ) | ||||
| @@ -55,8 +55,8 @@ func (s *DS18B20) Read() ([]*types.MeasuredValue, error) { | ||||
| 			ID:        uuid.NewV4().String(), | ||||
| 			Value:     float64(temperatureValue), | ||||
| 			ValueType: types.MeasuredValueTypeTemperature, | ||||
| 			FromDate:  time.Now(), | ||||
| 			TillDate:  time.Now(), | ||||
| 			FromDate:  format.FormatedTime(), | ||||
| 			TillDate:  format.FormatedTime(), | ||||
| 			SensorID:  s.SensorID, | ||||
| 		}, | ||||
| 	} | ||||
|   | ||||
| @@ -4,10 +4,10 @@ import "time" | ||||
|  | ||||
| // Device ... | ||||
| type Device struct { | ||||
| 	DeviceID          string    `json:"device_id" xml:"device_id"` | ||||
| 	DeviceName        string    `json:"device_name" xml:"device_name"` | ||||
| 	DeviceLocation    *string   `json:"device_location" xml:"device_location"` | ||||
| 	DeviceLastContact time.Time `json:"device_last_contact" xml:"device_last_contact"` | ||||
| 	Logfile           string    `json:"logfile" xml:"logfile"` | ||||
| 	CreationDate      time.Time `json:"creation_date" xml:"creation_date"` | ||||
| 	DeviceID          string     `json:"device_id" xml:"device_id"` | ||||
| 	DeviceName        string     `json:"device_name" xml:"device_name"` | ||||
| 	DeviceLocation    *string    `json:"device_location" xml:"device_location"` | ||||
| 	DeviceLastContact *time.Time `json:"device_last_contact" xml:"device_last_contact"` | ||||
| 	Logfile           string     `json:"logfile" xml:"logfile"` | ||||
| 	CreationDate      time.Time  `json:"creation_date" xml:"creation_date"` | ||||
| } | ||||
|   | ||||
| @@ -12,7 +12,7 @@ type MeasuredValue struct { | ||||
| 	FromDate     time.Time         `json:"from_date" xml:"from_date"` | ||||
| 	TillDate     time.Time         `json:"till_date" xml:"till_date"` | ||||
| 	SensorID     string            `json:"sensor_id" xml:"sensor_id"` | ||||
| 	CreationDate *time.Time        `json:"creation_date" xml:"creation_date"` | ||||
| 	CreationDate time.Time         `json:"creation_date" xml:"creation_date"` | ||||
| 	UpdateDate   *time.Time        `json:"update_date" xml:"update_date"` | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -18,7 +18,7 @@ type Sensor struct { | ||||
| 	GPIONumber        *GPIO       `json:"gpio_number" xml:"gpio_number"` | ||||
| 	SensorModel       SensorModel `json:"sensor_model" xml:"sensor_model"` | ||||
| 	SensorEnabled     bool        `json:"sensor_enabled" xml:"sensor_enabled"` | ||||
| 	SensorLastContact time.Time   `json:"sensor_last_contact" xml:"sensor_last_contact"` | ||||
| 	SensorLastContact *time.Time  `json:"sensor_last_contact" xml:"sensor_last_contact"` | ||||
| 	DeviceID          string      `json:"device_id" xml:"device_id"` | ||||
| 	CreationDate      time.Time   `json:"creation_date" xml:"creation_date"` | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user