package config import ( "bytes" "encoding/json" "fmt" "io" "text/tabwriter" "time" "git.cryptic.systems/fh-trier/go-flucky/pkg/sensor" "git.cryptic.systems/fh-trier/go-flucky/pkg/types" "github.com/satori/go.uuid" ) // FluckyConfig dasd type FluckyConfig struct { Device *types.Device `json:"device"` Sensors []*types.Sensor `json:"sensors"` Remotes []*Remote `json:"remotes"` } // AddSensor add a new sensor func (fc *FluckyConfig) AddSensor(sensor *types.Sensor) error { // check if sensorID is a valid UUID string if !validUUID.MatchString(sensor.SensorID) { sensor.SensorID = uuid.NewV4().String() } // check if sensor name and sensor uuid already exists for _, s := range fc.Sensors { if s.SensorName == sensor.SensorName { return fmt.Errorf("Sensor %v already exists", s.SensorName) } if s.SensorID == sensor.SensorID { return fmt.Errorf("Sensor %v with UUID %v already exists", s.SensorName, s.SensorID) } if *sensor.WireID != "" && *s.WireID == *sensor.WireID { return fmt.Errorf("Sensor with 1wire-id %v already exists as %v", *s.WireID, s.SensorName) } } // check if sensor has a valid device id if sensor.DeviceID != fc.Device.DeviceID { sensor.DeviceID = fc.Device.DeviceID } // overwrite creation date sensor.CreationDate = time.Now() //TODO: check if wire sensor exists in /dev/bus/w1/devices // check fc.Sensors = append(fc.Sensors, sensor) return nil } // AddRemote add a new remote address func (fc *FluckyConfig) AddRemote(remote *Remote) error { // check if remoteID is a valid UUID string if !validUUID.MatchString(remote.RemoteID) { remote.RemoteID = uuid.NewV4().String() } // check if remote name or remiteid already exists for _, r := range fc.Remotes { if r.Name == remote.Name { return fmt.Errorf("Remote %v -> %v already exists", r.Name, r.Address) } if r.RemoteID == remote.RemoteID { return fmt.Errorf("Remote %v with UUID %v already exists", r.Name, r.RemoteID) } } fc.Remotes = append(fc.Remotes, remote) return nil } // DisableRemote disables a remote address by its name or its unique UUID func (fc *FluckyConfig) DisableRemote(nameOrUUID string) error { found := false for _, remote := range fc.Remotes { // disable sensor matched after name if !validUUID.MatchString(nameOrUUID) && remote.Name == nameOrUUID { remote.Enabled = false found = true break } // remove machted uuid if validUUID.MatchString(nameOrUUID) && remote.RemoteID == nameOrUUID { remote.Enabled = false found = true break } } if !found { return fmt.Errorf("Can not found remote name %v", nameOrUUID) } return nil } // DisableSensor disables a sensor by its name or its unique UUID func (fc *FluckyConfig) DisableSensor(nameOrUUID string) error { found := false for _, sensor := range fc.Sensors { // disable sensor matched after name if !validUUID.MatchString(nameOrUUID) && sensor.SensorName == nameOrUUID { sensor.SensorEnabled = false found = true break } // remove machted uuid if validUUID.MatchString(nameOrUUID) && sensor.SensorID == nameOrUUID { sensor.SensorEnabled = false found = true break } } if !found { return fmt.Errorf("Can not found sensor %v", nameOrUUID) } return nil } // EnableRemote enable a remote address by its name or its unique UUID func (fc *FluckyConfig) EnableRemote(nameOrUUID string) error { found := false for _, remote := range fc.Remotes { // disable sensor matched after name if !validUUID.MatchString(nameOrUUID) && remote.Name == nameOrUUID { remote.Enabled = true found = true break } // remove machted uuid if validUUID.MatchString(nameOrUUID) && remote.RemoteID == nameOrUUID { remote.Enabled = true found = true break } } if !found { return fmt.Errorf("Can not found sensor %v", nameOrUUID) } return nil } // EnableSensor enables a sensor by its name or its unique UUID func (fc *FluckyConfig) EnableSensor(nameOrUUID string) error { found := false for _, sensor := range fc.Sensors { // disable sensor matched after name if !validUUID.MatchString(nameOrUUID) && sensor.SensorName == nameOrUUID { sensor.SensorEnabled = true found = true break } // remove machted uuid if validUUID.MatchString(nameOrUUID) && sensor.SensorID == nameOrUUID { sensor.SensorEnabled = true found = true break } } if !found { return fmt.Errorf("Can not found sensor %v", nameOrUUID) } return nil } func (fc *FluckyConfig) GetHumiditySensors() []sensor.HumiditySensor { hs := []sensor.HumiditySensor{} for _, s := range fc.Sensors { switch s.SensorModel { case types.DHT11: hs = append(hs, &sensor.DHT11Sensor{ Sensor: s, }) case types.DHT22: hs = append(hs, &sensor.DHT22Sensor{ Sensor: s, }) } } return hs } func (fc *FluckyConfig) GetTemperatureSensors() ([]sensor.TemperatureSensor, error) { ts := []sensor.TemperatureSensor{} for _, s := range fc.Sensors { // skip disabled sensors if !s.SensorEnabled { continue } switch s.SensorModel { case types.DHT11: ts = append(ts, &sensor.DHT11Sensor{ Sensor: s, }) case types.DHT22: ts = append(ts, &sensor.DHT22Sensor{ Sensor: s, }) case types.DS18B20: ts = append(ts, &sensor.DS18B20{ Sensor: s, }) default: return nil, fmt.Errorf("Sensor Model %v is not a valid sensor model. Please remove the sensor named %v", s.SensorModel, s.Name()) } } return ts, nil } // JSONDecoder decode a JSON string from a reader into a struct func (fc *FluckyConfig) JSONDecoder(r io.Reader) error { jsonDecoder := json.NewDecoder(r) if err := jsonDecoder.Decode(&fc); err != nil { return fmt.Errorf("Can not unmarshal JSON: %v", err) } return nil } // JSONWriter needs a writer to write the struct into JSON string func (fc *FluckyConfig) JSONWriter(w io.Writer) error { encoder := json.NewEncoder(w) encoder.SetIndent("", " ") err := encoder.Encode(&fc) if err != nil { return fmt.Errorf("Error in encoding struct to json: %v", err) } return nil } // PrintRemotes displays a list with all configured remote addresses func (fc *FluckyConfig) PrintRemotes(w io.Writer) error { tw := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0) fmt.Fprint(tw, "name\taddress\tenabled\tregistered\n") for _, remote := range fc.Remotes { fmt.Fprintf(tw, "%v\t%v\t%v\t%v\n", remote.Name, remote.Address, remote.Enabled, remote.Registered) } tw.Flush() return nil } // PrintSensors displays a list with all configured sensors func (fc *FluckyConfig) PrintSensors(w io.Writer) error { // declar tabwriter tw := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0) fmt.Fprint(tw, "name\tlocation\ttype\twire-id\tgpio\tenabled\n") for _, sensor := range fc.Sensors { fmt.Fprintf(tw, "%v\t%v\t%v\t%v\t%v\t%v\n", sensor.SensorName, sensor.SensorLocation, sensor.SensorModel, *sensor.WireID, *sensor.GPIONumber, sensor.SensorEnabled) } tw.Flush() return nil } // RemoveSensor deletes a sensor by its name or its unique UUID func (fc *FluckyConfig) RemoveSensor(nameOrUUID string) error { for i, sensor := range fc.Sensors { // remove machted name if !validUUID.MatchString(nameOrUUID) && sensor.SensorName == nameOrUUID { fc.Sensors = append(fc.Sensors[:i], fc.Sensors[i+1:]...) return nil } // remove machted uuid if validUUID.MatchString(nameOrUUID) && sensor.SensorID == nameOrUUID { fc.Sensors = append(fc.Sensors[:i], fc.Sensors[i+1:]...) return nil } } return fmt.Errorf("Can not find sensor %v", nameOrUUID) } // RemoveRemote deletes a remote address by its name or its unique UUID func (fc *FluckyConfig) RemoveRemote(nameOrUUID string) error { found := false for i, remote := range fc.Remotes { // remove machted name if !validUUID.MatchString(nameOrUUID) && remote.Name == nameOrUUID { fc.Remotes = append(fc.Remotes[:i], fc.Remotes[i+1:]...) found = true } // remove machted uuid if validUUID.MatchString(nameOrUUID) && remote.RemoteID == nameOrUUID { fc.Remotes = append(fc.Remotes[:i], fc.Remotes[i+1:]...) found = true } } if !found { return fmt.Errorf("Can not find remote %v", nameOrUUID) } return nil } // RenameSensor renames a sensor identified by the name or the UUID func (fc *FluckyConfig) RenameSensor(oldName, newName string) error { for _, sensor := range fc.Sensors { if sensor.SensorName == oldName || sensor.SensorID == oldName { sensor.SensorName = newName return nil } } return fmt.Errorf("Could not find sensor %v to replace into ", oldName) } // RenameRemote renames a remote address identified by the name or the UUID func (fc *FluckyConfig) RenameRemote(oldName, newName string) error { for _, remote := range fc.Remotes { if remote.Name == oldName || remote.RemoteID == oldName { remote.Name = newName return nil } } return fmt.Errorf("Could not find remote name %v to replace into %v", oldName, newName) } // ToJSON returns the struct as JSON string func (fc *FluckyConfig) ToJSON() (string, error) { var b bytes.Buffer err := fc.JSONWriter(&b) if err != nil { return "", err } return b.String(), nil }