212 lines
4.8 KiB
Go
212 lines
4.8 KiB
Go
package config
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
|
|
"time"
|
|
|
|
"github.com/volker-raschek/flucky/pkg/internal/format"
|
|
"github.com/volker-raschek/flucky/pkg/storage"
|
|
|
|
uuid "github.com/satori/go.uuid"
|
|
"github.com/volker-raschek/flucky/pkg/types"
|
|
)
|
|
|
|
var (
|
|
validUUID = regexp.MustCompile("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$")
|
|
)
|
|
|
|
// Config represent the configuration
|
|
type Config struct {
|
|
Device *types.Device `json:"device"`
|
|
Sensors []*types.Sensor `json:"sensors"`
|
|
StorageEndpoint string `json:"storage_endpoint"`
|
|
}
|
|
|
|
// AddSensor add a new sensor
|
|
func (cnf *Config) AddSensor(sensor *types.Sensor) error {
|
|
|
|
// Verify that a device is configured
|
|
if cnf.Device == nil {
|
|
return fmt.Errorf("No device configured")
|
|
}
|
|
|
|
// Define a new UUID if the current UUID is invalid
|
|
if !validUUID.MatchString(sensor.ID) {
|
|
sensor.ID = uuid.NewV4().String()
|
|
}
|
|
|
|
// Verify that the sensor has a valid name
|
|
if len(sensor.Name) <= 0 {
|
|
return fmt.Errorf("No sensor name defined")
|
|
}
|
|
|
|
// check if sensor name and sensor uuid already exists
|
|
for _, cnfSensor := range cnf.Sensors {
|
|
if cnfSensor.Name == sensor.Name ||
|
|
cnfSensor.ID == sensor.ID {
|
|
return fmt.Errorf("Sensor with same name or id already exist")
|
|
}
|
|
|
|
if cnfSensor.WireID != nil &&
|
|
sensor.WireID != nil &&
|
|
*cnfSensor.WireID == *sensor.WireID {
|
|
return fmt.Errorf("Sensor with same wire id already exist")
|
|
}
|
|
}
|
|
|
|
// check if sensor has a valid tick time
|
|
if _, err := time.ParseDuration(sensor.TickDuration); err != nil {
|
|
return fmt.Errorf("Failed to parse tick duration: %v", err)
|
|
}
|
|
|
|
// check if sensor has a valid device id
|
|
if sensor.DeviceID != cnf.Device.ID {
|
|
sensor.DeviceID = cnf.Device.ID
|
|
}
|
|
|
|
// overwrite creation date
|
|
sensor.CreationDate = format.FormatedTime()
|
|
|
|
// check if wire socket is available
|
|
if sensor.WireID != nil {
|
|
socketPath := filepath.Join("/sys/bus/w1/devices", *sensor.WireID, "/w1_slave")
|
|
if _, err := os.Stat(socketPath); os.IsNotExist(err) {
|
|
return fmt.Errorf("Wire socket not found: %v", socketPath)
|
|
}
|
|
}
|
|
|
|
cnf.Sensors = append(cnf.Sensors, sensor)
|
|
|
|
return nil
|
|
}
|
|
|
|
// DisableSensor disables a sensor by its name or its unique UUID
|
|
func (cnf *Config) DisableSensor(name string) error {
|
|
found := false
|
|
|
|
for _, sensor := range cnf.Sensors {
|
|
|
|
// disable sensor matched after name
|
|
if !validUUID.MatchString(name) &&
|
|
sensor.Name == name {
|
|
sensor.Enabled = false
|
|
found = true
|
|
break
|
|
}
|
|
|
|
// remove machted uuid
|
|
if validUUID.MatchString(name) &&
|
|
sensor.ID == name {
|
|
sensor.Enabled = false
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
return fmt.Errorf("Can not found sensor %v", name)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// EnableSensor enables a sensor by its name or its unique UUID
|
|
func (cnf *Config) EnableSensor(name string) error {
|
|
found := false
|
|
|
|
for _, sensor := range cnf.Sensors {
|
|
|
|
// disable sensor matched after name
|
|
if !validUUID.MatchString(name) &&
|
|
sensor.Name == name {
|
|
sensor.Enabled = true
|
|
found = true
|
|
break
|
|
}
|
|
|
|
// remove machted uuid
|
|
if validUUID.MatchString(name) &&
|
|
sensor.ID == name {
|
|
sensor.Enabled = true
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
return fmt.Errorf("Can not found sensor %v", name)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetSensorByID returns a sensor matched by his id. If no sensor has this id,
|
|
// the function returns nil
|
|
func (cnf *Config) GetSensorByID(id string) *types.Sensor {
|
|
for _, sensor := range cnf.Sensors {
|
|
if sensor.ID == id {
|
|
return sensor
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// 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
|
|
// but also in the backend.
|
|
func (cnf *Config) RemoveSensor(name string, definitive bool) error {
|
|
|
|
backend, err := storage.New(cnf.StorageEndpoint, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for i, sensor := range cnf.Sensors {
|
|
// remove machted name
|
|
if !validUUID.MatchString(name) &&
|
|
sensor.Name == name {
|
|
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
|
|
}
|
|
// remove machted uuid
|
|
if validUUID.MatchString(name) &&
|
|
sensor.ID == name {
|
|
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 fmt.Errorf("Can not find sensor %v", name)
|
|
}
|
|
|
|
// RenameSensor renamed a sensor
|
|
func (cnf *Config) RenameSensor(oldName string, newName string) error {
|
|
for _, cnfSensor := range cnf.Sensors {
|
|
if cnfSensor.Name == oldName {
|
|
cnfSensor.Name = newName
|
|
return nil
|
|
}
|
|
}
|
|
return fmt.Errorf("No sensor %v found", oldName)
|
|
}
|