PKGBUILD/pkg/config/fluckyconfig.go

416 lines
9.6 KiB
Go

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"
uuid "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(namesOrUUIDs []string) []sensor.HumiditySensor {
hs := []sensor.HumiditySensor{}
for _, s := range fc.Sensors {
// select only named sensors
if len(namesOrUUIDs) > 0 {
found := false
for _, nameOrUUID := range namesOrUUIDs {
if nameOrUUID == s.SensorID || nameOrUUID == s.SensorName {
found = true
break
}
}
if !found {
continue
}
}
// skip disabled sensors
if !s.SensorEnabled {
continue
}
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(namesOrUUIDs []string) ([]sensor.TemperatureSensor, error) {
ts := []sensor.TemperatureSensor{}
for _, s := range fc.Sensors {
// select only named sensors
if len(namesOrUUIDs) > 0 {
found := false
for _, nameOrUUID := range namesOrUUIDs {
if nameOrUUID == s.SensorID || nameOrUUID == s.SensorName {
found = true
break
}
}
if !found {
continue
}
}
// 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
}