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) }