2019-02-17 17:23:59 +00:00
|
|
|
package config
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"text/tabwriter"
|
2019-02-24 21:46:36 +00:00
|
|
|
"time"
|
2019-02-17 17:23:59 +00:00
|
|
|
|
2019-02-24 21:46:36 +00:00
|
|
|
"git.cryptic.systems/fh-trier/go-flucky/pkg/sensor"
|
2019-02-17 17:23:59 +00:00
|
|
|
|
2019-02-24 21:46:36 +00:00
|
|
|
"git.cryptic.systems/fh-trier/go-flucky/pkg/types"
|
|
|
|
"github.com/satori/go.uuid"
|
2019-02-17 17:23:59 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// FluckyConfig dasd
|
|
|
|
type FluckyConfig struct {
|
2019-02-22 12:08:58 +00:00
|
|
|
Device *types.Device `json:"device"`
|
2019-02-17 17:23:59 +00:00
|
|
|
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 {
|
2019-02-22 12:08:58 +00:00
|
|
|
return fmt.Errorf("Sensor %v with UUID %v already exists", s.SensorName, s.SensorID)
|
|
|
|
}
|
|
|
|
|
2019-02-24 21:46:36 +00:00
|
|
|
if *sensor.WireID != "" &&
|
|
|
|
*s.WireID == *sensor.WireID {
|
|
|
|
return fmt.Errorf("Sensor with 1wire-id %v already exists as %v", *s.WireID, s.SensorName)
|
2019-02-17 17:23:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-24 21:46:36 +00:00
|
|
|
// 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
|
2019-02-17 17:23:59 +00:00
|
|
|
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 {
|
2019-02-22 12:08:58 +00:00
|
|
|
return fmt.Errorf("Can not found remote name %v", nameOrUUID)
|
2019-02-17 17:23:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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) &&
|
2019-02-24 21:46:36 +00:00
|
|
|
sensor.SensorName == nameOrUUID {
|
|
|
|
sensor.SensorEnabled = false
|
2019-02-17 17:23:59 +00:00
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove machted uuid
|
|
|
|
if validUUID.MatchString(nameOrUUID) &&
|
|
|
|
sensor.SensorID == nameOrUUID {
|
2019-02-24 21:46:36 +00:00
|
|
|
sensor.SensorEnabled = false
|
2019-02-17 17:23:59 +00:00
|
|
|
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) &&
|
2019-02-24 21:46:36 +00:00
|
|
|
sensor.SensorName == nameOrUUID {
|
|
|
|
sensor.SensorEnabled = true
|
2019-02-17 17:23:59 +00:00
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove machted uuid
|
|
|
|
if validUUID.MatchString(nameOrUUID) &&
|
|
|
|
sensor.SensorID == nameOrUUID {
|
2019-02-24 21:46:36 +00:00
|
|
|
sensor.SensorEnabled = true
|
2019-02-17 17:23:59 +00:00
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !found {
|
|
|
|
return fmt.Errorf("Can not found sensor %v", nameOrUUID)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-02-24 21:46:36 +00:00
|
|
|
func (fc *FluckyConfig) GetHumiditySensors() []sensor.HumiditySensor {
|
|
|
|
hs := []sensor.HumiditySensor{}
|
|
|
|
// for _, s := range fc.Sensors {
|
|
|
|
// switch s.SensorType {
|
|
|
|
// case "DHT11":
|
|
|
|
// hs = append(hs, sensor.DHT11Sensor{
|
|
|
|
// Sensor: s,
|
|
|
|
// })
|
|
|
|
// case "DHT22":
|
|
|
|
// hs = append(hs, sensor.DHT22Sensor{
|
|
|
|
// Sensor: s,
|
|
|
|
// })
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
return hs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fc *FluckyConfig) GetTemperatureSensors() []sensor.TemperatureSensor {
|
|
|
|
ts := []sensor.TemperatureSensor{}
|
|
|
|
|
|
|
|
for _, s := range fc.Sensors {
|
|
|
|
switch s.SensorType {
|
|
|
|
case "DHT11":
|
|
|
|
ts = append(ts, &sensor.DHT11Sensor{
|
|
|
|
Sensor: s,
|
|
|
|
})
|
|
|
|
case "DHT22":
|
|
|
|
ts = append(ts, &sensor.DHT22Sensor{
|
|
|
|
Sensor: s,
|
|
|
|
})
|
|
|
|
case "DS18B20":
|
|
|
|
ts = append(ts, &sensor.DS18B20{
|
|
|
|
Sensor: s,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ts
|
|
|
|
}
|
|
|
|
|
2019-02-17 17:23:59 +00:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2019-02-22 12:08:58 +00:00
|
|
|
// PrintRemotes displays a list with all configured remote addresses
|
2019-02-17 17:23:59 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2019-02-22 12:08:58 +00:00
|
|
|
// 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)
|
|
|
|
|
2019-02-24 21:46:36 +00:00
|
|
|
fmt.Fprint(tw, "name\tlocation\ttype\twire-id\tgpio\tenabled\n")
|
2019-02-22 12:08:58 +00:00
|
|
|
|
|
|
|
for _, sensor := range fc.Sensors {
|
2019-02-24 21:46:36 +00:00
|
|
|
fmt.Fprintf(tw, "%v\t%v\t%v\t%v\t%v\t%v\n", sensor.SensorName, sensor.SensorLocation, sensor.SensorType, *sensor.WireID, *sensor.GPIONumber, sensor.SensorEnabled)
|
2019-02-22 12:08:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tw.Flush()
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-02-17 17:23:59 +00:00
|
|
|
// RemoveSensor deletes a sensor by its name or its unique UUID
|
|
|
|
func (fc *FluckyConfig) RemoveSensor(nameOrUUID string) error {
|
|
|
|
found := false
|
|
|
|
|
|
|
|
for i, sensor := range fc.Sensors {
|
|
|
|
|
|
|
|
// remove machted name
|
|
|
|
if !validUUID.MatchString(nameOrUUID) &&
|
2019-02-24 21:46:36 +00:00
|
|
|
sensor.SensorName == nameOrUUID {
|
2019-02-17 17:23:59 +00:00
|
|
|
fc.Sensors = append(fc.Sensors[:i], fc.Sensors[i+1:]...)
|
|
|
|
found = true
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove machted uuid
|
|
|
|
if validUUID.MatchString(nameOrUUID) &&
|
|
|
|
sensor.SensorID == nameOrUUID {
|
|
|
|
fc.Sensors = append(fc.Sensors[:i], fc.Sensors[i+1:]...)
|
|
|
|
found = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !found {
|
2019-02-24 21:46:36 +00:00
|
|
|
return fmt.Errorf("Can not find sensor %v", nameOrUUID)
|
2019-02-17 17:23:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|