refactor: config and remote pkg

This commit is contained in:
Markus Pesch 2019-02-22 13:08:58 +01:00
parent c437127531
commit d6f41b8105
Signed by: volker.raschek
GPG Key ID: 852BCC170D81A982
29 changed files with 247 additions and 1292 deletions

View File

@ -1,7 +1,14 @@
package cmd package cmd
import ( import (
"fmt"
"os"
"git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
"git.cryptic.systems/fh-trier/go-flucky/cmd/remote" "git.cryptic.systems/fh-trier/go-flucky/cmd/remote"
"git.cryptic.systems/fh-trier/go-flucky/pkg/config"
uuid "github.com/satori/go.uuid"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -10,6 +17,30 @@ var cfg string
var rootCmd = &cobra.Command{ var rootCmd = &cobra.Command{
Use: "flucky", Use: "flucky",
Short: "Read from sensors", Short: "Read from sensors",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
// check if config file exists
if _, err := os.Stat(cfg); os.IsNotExist(err) {
hostname, err := os.Hostname()
if err != nil {
return fmt.Errorf("Can not locate the hostname: %v", err)
}
fc := config.FluckyConfig{
Device: &types.Device{
DeviceID: uuid.NewV4().String(),
DeviceName: &hostname,
},
}
err = config.Write(&fc, cfg)
if err != nil {
return err
}
}
return nil
},
} }
// Execute a // Execute a
@ -20,7 +51,7 @@ func Execute(version string) {
// humidity.InitCmd(rootCmd, configDir) // humidity.InitCmd(rootCmd, configDir)
remote.InitCmd(rootCmd, cfg) remote.InitCmd(rootCmd, cfg)
// sensor.InitCmd(rootCmd, configDir) // sensor.InitCmd(rootCmd, cfg)
// temperature.InitCmd(rootCmd, configDir) // temperature.InitCmd(rootCmd, configDir)
rootCmd.Execute() rootCmd.Execute()

View File

@ -10,9 +10,10 @@ import (
var enabled bool var enabled bool
var addRemoteCmd = &cobra.Command{ var addRemoteCmd = &cobra.Command{
Use: "add", Use: "add",
Short: "Add Remove Server", Short: "Add Remote Server",
Args: cobra.ExactArgs(2), Args: cobra.ExactArgs(2),
Example: "flucky remote add origin https://example.local",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// read configuration // read configuration

View File

@ -8,9 +8,10 @@ import (
) )
var disableRemoteCmd = &cobra.Command{ var disableRemoteCmd = &cobra.Command{
Use: "disable", Use: "disable",
Short: "Disable Remove Server", Short: "Disable Remove Server",
Args: cobra.ExactArgs(1), Args: cobra.ExactArgs(1),
Example: "flucky remote disable origin",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// read configuration // read configuration

View File

@ -8,9 +8,10 @@ import (
) )
var enableRemoteCmd = &cobra.Command{ var enableRemoteCmd = &cobra.Command{
Use: "enable", Use: "enable",
Short: "Enable Remove Server", Short: "Enable Remove Server",
Args: cobra.ExactArgs(1), Args: cobra.ExactArgs(1),
Example: "flucky remote enable origin",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// read configuration // read configuration

View File

@ -11,9 +11,10 @@ import (
var quiet bool var quiet bool
var listRemoteCmd = &cobra.Command{ var listRemoteCmd = &cobra.Command{
Use: "list", Use: "ls",
Short: "List Remove Servers", Short: "List Remove Servers",
Aliases: []string{"ls"}, Aliases: []string{"list"},
Example: "flucky remote ls",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// read configuration // read configuration

View File

@ -12,6 +12,7 @@ var rmRemoteCmd = &cobra.Command{
Short: "Remove Remote Server", Short: "Remove Remote Server",
Aliases: []string{"remove"}, Aliases: []string{"remove"},
Args: cobra.ExactArgs(1), Args: cobra.ExactArgs(1),
Example: "flucky remote rm origin",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// read configuration // read configuration

View File

@ -1,6 +1,8 @@
package sensor package sensor
import ( import (
"fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -8,12 +10,10 @@ var enabled bool
var sensorLocation, wireID, wirePath string var sensorLocation, wireID, wirePath string
var addSensorCmd = &cobra.Command{ var addSensorCmd = &cobra.Command{
Use: "add", Use: "add",
Short: "Add Sensor", Short: "Add Sensor",
Args: cobra.ExactArgs(3), Args: cobra.ExactArgs(3),
Run: func(cmd *cobra.Command, args []string) { Example: fmt.Sprintf("flucky sensor add indoor dht11 14\nflucky sensor add --wire-id 28-011432f0bb3d outdoor ds18b20 14"),
},
} }
func init() { func init() {

View File

@ -1,24 +1,24 @@
package sensor package sensor
import ( // import (
"log" // "log"
"git.cryptic.systems/fh-trier/go-flucky/pkg/sensor" // "git.cryptic.systems/fh-trier/go-flucky/pkg/sensor"
"github.com/spf13/cobra" // "github.com/spf13/cobra"
) // )
var disableSensorCmd = &cobra.Command{ // var disableSensorCmd = &cobra.Command{
Use: "disable", // Use: "disable",
Short: "Disable Sensor", // Short: "Disable Sensor",
Args: cobra.ExactArgs(1), // Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) { // Run: func(cmd *cobra.Command, args []string) {
if err := sensor.Disable(args[0], configDir); err != nil { // if err := sensor.Disable(args[0], configDir); err != nil {
log.Fatal(err) // log.Fatal(err)
} // }
}, // },
} // }
func init() { // func init() {
sensorCmd.AddCommand(disableSensorCmd) // sensorCmd.AddCommand(disableSensorCmd)
} // }

View File

@ -1,24 +1,24 @@
package sensor package sensor
import ( // import (
"log" // "log"
"git.cryptic.systems/fh-trier/go-flucky/pkg/sensor" // "git.cryptic.systems/fh-trier/go-flucky/pkg/sensor"
"github.com/spf13/cobra" // "github.com/spf13/cobra"
) // )
var enableSensorCmd = &cobra.Command{ // var enableSensorCmd = &cobra.Command{
Use: "enable", // Use: "enable",
Short: "Enable Sensor", // Short: "Enable Sensor",
Args: cobra.ExactArgs(1), // Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) { // Run: func(cmd *cobra.Command, args []string) {
if err := sensor.Enable(args[0], configDir); err != nil { // if err := sensor.Enable(args[0], configDir); err != nil {
log.Fatal(err) // log.Fatal(err)
} // }
}, // },
} // }
func init() { // func init() {
sensorCmd.AddCommand(enableSensorCmd) // sensorCmd.AddCommand(enableSensorCmd)
} // }

View File

@ -1,29 +1,29 @@
package sensor package sensor
import ( // import (
"log" // "log"
"os" // "os"
"git.cryptic.systems/fh-trier/go-flucky/pkg/sensor" // "git.cryptic.systems/fh-trier/go-flucky/pkg/sensor"
"github.com/spf13/cobra" // "github.com/spf13/cobra"
) // )
var quiet bool // var quiet bool
var listSensorCmd = &cobra.Command{ // var listSensorCmd = &cobra.Command{
Use: "ls", // Use: "ls",
Short: "List Sensors", // Short: "List Sensors",
Aliases: []string{"list"}, // Aliases: []string{"list"},
Run: func(cmd *cobra.Command, args []string) { // Run: func(cmd *cobra.Command, args []string) {
if err := sensor.Print(os.Stdout, configDir, quiet); err != nil { // if err := sensor.Print(os.Stdout, configDir, quiet); err != nil {
log.Fatal(err) // log.Fatal(err)
} // }
}, // },
//28-01143277168e // //28-01143277168e
} // }
func init() { // func init() {
sensorCmd.AddCommand(listSensorCmd) // sensorCmd.AddCommand(listSensorCmd)
listSensorCmd.Flags().BoolVarP(&quiet, "quiet", "q", false, "List only sensor id's") // listSensorCmd.Flags().BoolVarP(&quiet, "quiet", "q", false, "List only sensor id's")
} // }

View File

@ -1,24 +1,24 @@
package sensor package sensor
import ( // import (
"log" // "log"
"git.cryptic.systems/fh-trier/go-flucky/pkg/sensor" // "git.cryptic.systems/fh-trier/go-flucky/pkg/sensor"
"github.com/spf13/cobra" // "github.com/spf13/cobra"
) // )
var rmSensorCmd = &cobra.Command{ // var rmSensorCmd = &cobra.Command{
Use: "rm", // Use: "rm",
Short: "Remove Sensor", // Short: "Remove Sensor",
Aliases: []string{"remove"}, // Aliases: []string{"remove"},
Args: cobra.ExactArgs(1), // Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) { // Run: func(cmd *cobra.Command, args []string) {
if err := sensor.Remove(args[0], configDir); err != nil { // if err := sensor.Remove(args[0], configDir); err != nil {
log.Fatal(err) // log.Fatal(err)
} // }
}, // },
} // }
func init() { // func init() {
sensorCmd.AddCommand(rmSensorCmd) // sensorCmd.AddCommand(rmSensorCmd)
} // }

View File

@ -4,16 +4,16 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
var configDir string var cfg string
var sensorCmd = &cobra.Command{ var sensorCmd = &cobra.Command{
Use: "sensor", Use: "sensor",
Short: "Manage Sensors", Short: "Manage Sensors",
} }
// Execute a // InitCmd da
func InitCmd(cmd *cobra.Command, cnf string) { func InitCmd(cmd *cobra.Command, config string) {
configDir = cnf cfg = config
cmd.AddCommand(sensorCmd) cmd.AddCommand(sensorCmd)

View File

@ -1,27 +0,0 @@
package sensor
import (
"log"
"git.cryptic.systems/fh-trier/go-flucky/pkg/httpcall"
"github.com/spf13/cobra"
)
var force bool
var syncSensorCmd = &cobra.Command{
Use: "sync",
Short: "Synchronise Sensors with Remote Servers",
Aliases: []string{"synchronize"},
Run: func(cmd *cobra.Command, args []string) {
if err := httpcall.SyncSensors(configDir, force); err != nil {
log.Fatal(err)
}
},
}
func init() {
sensorCmd.AddCommand(syncSensorCmd)
syncSensorCmd.Flags().BoolVarP(&force, "force", "f", false, "Include disabled remote links")
}

View File

@ -2,33 +2,12 @@ package config
import ( import (
"fmt" "fmt"
"io"
"os" "os"
"regexp" "regexp"
"git.cryptic.systems/fh-trier/go-flucky-server/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}$") var validUUID = regexp.MustCompile("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$")
type Config interface {
AddSensor(sensor *types.Sensor) error
AddRemote(remote *Remote) error
DisableRemote(nameOrUUID string) error
DisableSensor(nameOrUUID string) error
EnableRemote(nameOrUUID string) error
EnableSensor(nameOrUUID string) error
GetDevice() *Device
GetRemotes() []*Remote
GetSensors() []*types.Sensor
JSONDecoder(r io.Reader) error
JSONWriter(w io.Writer) error
RemoveSensor(nameOrUUID string) error
RemoveRemote(nameOrUUID string) error
SetDevice(device *Device)
ToJSON() (string, error)
}
// Read the configuration file // Read the configuration file
func Read(configFile string) (*FluckyConfig, error) { func Read(configFile string) (*FluckyConfig, error) {
@ -50,7 +29,7 @@ func Read(configFile string) (*FluckyConfig, error) {
} }
// Write the configuration into a file, specified by the configuration filepath // Write the configuration into a file, specified by the configuration filepath
func Write(cfg Config, configFile string) error { func Write(cfg *FluckyConfig, configFile string) error {
f, err := os.Create(configFile) f, err := os.Create(configFile)
if err != nil { if err != nil {

View File

@ -1,7 +0,0 @@
package config
type Device struct {
DeviceID string `json:"device_id"`
DeviceName string `json:"device_name"`
DeviceLocation string `json:"device_location"`
}

View File

@ -14,7 +14,7 @@ import (
// FluckyConfig dasd // FluckyConfig dasd
type FluckyConfig struct { type FluckyConfig struct {
Device *Device `json:"device"` Device *types.Device `json:"device"`
Sensors []*types.Sensor `json:"sensors"` Sensors []*types.Sensor `json:"sensors"`
Remotes []*Remote `json:"remotes"` Remotes []*Remote `json:"remotes"`
} }
@ -34,7 +34,12 @@ func (fc *FluckyConfig) AddSensor(sensor *types.Sensor) error {
} }
if s.SensorID == sensor.SensorID { if s.SensorID == sensor.SensorID {
return fmt.Errorf("Remote %v with UUID %v already exists", s.SensorName, s.SensorID) return fmt.Errorf("Sensor %v with UUID %v already exists", s.SensorName, s.SensorID)
}
if sensor.WireID != nil &&
s.WireID == sensor.WireID {
return fmt.Errorf("Sensor with 1wire-id %v already exists as %v", s.WireID, s.SensorName)
} }
} }
@ -91,7 +96,7 @@ func (fc *FluckyConfig) DisableRemote(nameOrUUID string) error {
} }
if !found { if !found {
return fmt.Errorf("Can not found sensor %v", nameOrUUID) return fmt.Errorf("Can not found remote name %v", nameOrUUID)
} }
return nil return nil
@ -187,21 +192,6 @@ func (fc *FluckyConfig) EnableSensor(nameOrUUID string) error {
return nil return nil
} }
// GetDevice returns device informations
func (fc *FluckyConfig) GetDevice() *Device {
return fc.Device
}
// GetRemotes returns an array if remote struct poniter
func (fc *FluckyConfig) GetRemotes() []*Remote {
return fc.Remotes
}
// GetSensors returns an array if remote struct poniter
func (fc *FluckyConfig) GetSensors() []*types.Sensor {
return fc.Sensors
}
// JSONDecoder decode a JSON string from a reader into a struct // JSONDecoder decode a JSON string from a reader into a struct
func (fc *FluckyConfig) JSONDecoder(r io.Reader) error { func (fc *FluckyConfig) JSONDecoder(r io.Reader) error {
jsonDecoder := json.NewDecoder(r) jsonDecoder := json.NewDecoder(r)
@ -222,6 +212,7 @@ func (fc *FluckyConfig) JSONWriter(w io.Writer) error {
return nil return nil
} }
// PrintRemotes displays a list with all configured remote addresses
func (fc *FluckyConfig) PrintRemotes(w io.Writer) error { func (fc *FluckyConfig) PrintRemotes(w io.Writer) error {
tw := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0) tw := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0)
@ -237,6 +228,23 @@ func (fc *FluckyConfig) PrintRemotes(w io.Writer) error {
return nil 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, "id\tname\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\t%v\n", sensor.SensorID, *sensor.SensorName, *sensor.SensorLocation, *sensor.SensorType, *sensor.WireID, *sensor.GPIONumber, *sensor.SensorEnabled)
}
tw.Flush()
return nil
}
// RemoveSensor deletes a sensor by its name or its unique UUID // RemoveSensor deletes a sensor by its name or its unique UUID
func (fc *FluckyConfig) RemoveSensor(nameOrUUID string) error { func (fc *FluckyConfig) RemoveSensor(nameOrUUID string) error {
found := false found := false
@ -295,11 +303,6 @@ func (fc *FluckyConfig) RemoveRemote(nameOrUUID string) error {
return nil return nil
} }
// SetDevice informations, like device name or device location
func (fc *FluckyConfig) SetDevice(device *Device) {
fc.Device = device
}
// ToJSON returns the struct as JSON string // ToJSON returns the struct as JSON string
func (fc *FluckyConfig) ToJSON() (string, error) { func (fc *FluckyConfig) ToJSON() (string, error) {
var b bytes.Buffer var b bytes.Buffer

View File

@ -1,5 +1,7 @@
package config package config
import "git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
// Remote ... // Remote ...
type Remote struct { type Remote struct {
RemoteID string `json:"remote_id"` RemoteID string `json:"remote_id"`
@ -8,3 +10,19 @@ type Remote struct {
Registered bool `json:"remote_registered"` Registered bool `json:"remote_registered"`
Enabled bool `json:"remote_enabled"` Enabled bool `json:"remote_enabled"`
} }
func (r *Remote) AddSensor(s *types.Sensor) error {
return nil
}
func (r *Remote) RegisterDevice(d *types.Device) error {
return nil
}
func (r *Remote) RemoveSensor(s *types.Sensor) error {
return nil
}
func (r *Remote) UnregisterDevice(d *types.Device) error {
return nil
}

View File

@ -1,114 +0,0 @@
package httpcall
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
"git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
"git.cryptic.systems/fh-trier/go-flucky/pkg/config"
)
// SyncDevice ..
func SyncDevice(configDir string, force bool) error {
// read config
cnf, err := config.Read(configDir)
if err != nil {
return err
}
jsonBuffer := bytes.Buffer{}
// define array of devices
device := types.Device{
DeviceID: cnf.DeviceID,
DeviceLocation: &cnf.DeviceLocation,
DeviceName: &cnf.DeviceName,
DeviceLastContact: time.Now(),
CreationDate: time.Now(),
}
// encode to json
encoder := json.NewEncoder(&jsonBuffer)
if err != nil {
return err
}
if err = encoder.Encode(device); err != nil {
return fmt.Errorf("Can not encode device to json: %v", err)
}
log.Println(jsonBuffer.String())
// send array of devices to remote links
for _, remote := range cnf.Remotes {
if !remote.Registered || force {
requestURL := fmt.Sprintf("%v/devices/%v", remote.Address, cnf.DeviceID)
req, err := http.NewRequest("PUT", requestURL, &jsonBuffer)
if err != nil {
return err
}
client := http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
// if resource does not exxists, create a new one
if resp.StatusCode == 404 {
log.Println("test")
requestURL := fmt.Sprintf("%v/devices", remote.Address)
req, err := http.NewRequest("POST", requestURL, &jsonBuffer)
if err != nil {
return err
}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode > 299 {
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("Can not create a new device on %v - Invalid HTTP-Statuscode, expected 200, got %d - Can not read response body: %v", remote.Name, resp.StatusCode, err)
}
return fmt.Errorf("Can not create a new device on %v - Invalid HTTP-Statuscode, expected 200, got %d: %v", remote.Name, resp.StatusCode, string(b))
}
}
if resp.StatusCode < 200 || resp.StatusCode > 299 {
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("Can not update device on %v - Invalid HTTP-Statuscode, expected 200, got %d - Can not read response body: %v", remote.Name, resp.StatusCode, err)
}
return fmt.Errorf("Can not update device on %v - Invalid HTTP-Statuscode, expected 200, got %d: %v", remote.Name, resp.StatusCode, string(b))
}
remote.Registered = true
}
}
if err := config.Write(cnf, configDir); err != nil {
return err
}
return nil
}
// UnregisterDevice ...
func UnregisterDevice(configDir string) error {
return nil
}

View File

@ -1,60 +0,0 @@
package httpcall
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"git.cryptic.systems/fh-trier/go-flucky/pkg/config"
)
// SyncSensors ..
func SyncSensors(configDir string, force bool) error {
// read config
cnf, err := config.Read(configDir)
if err != nil {
return err
}
// send array of sensors to remote links
for _, remote := range cnf.Remotes {
if remote.Enabled || force {
// encode to json
sensorsAsBytes, err := json.Marshal(cnf.Sensors)
if err != nil {
return err
}
sensorsAsReader := bytes.NewReader(sensorsAsBytes)
requestURL := fmt.Sprintf("%v/sensors", remote.Address)
req, err := http.NewRequest("PUT", requestURL, sensorsAsReader)
if err != nil {
return err
}
client := http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode > 299 {
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("Invalid HTTP-Statuscode - expected 200, got %d - can not read response body: %v", resp.StatusCode, err)
}
return fmt.Errorf("Invalid HTTP-Statuscode - expected 200, got %d: %v", resp.StatusCode, string(b))
}
}
}
return nil
}

View File

@ -1,78 +0,0 @@
package httpcall
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"math"
"net/http"
"git.cryptic.systems/fh-trier/go-flucky/pkg/config"
stypes "git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
)
// SendTemperatures remote servers
func SendTemperatures(temperatures []*stypes.Temperature, configDir string) error {
cnf, err := config.Read(configDir)
if err != nil {
return err
}
// split temperatures in blocks to reduce server data size in single request
blockSize := 500
temperatureBlocks := make(map[int][]*stypes.Temperature)
length := int(math.Ceil(float64(len(temperatures)) / float64(blockSize)))
for i := 0; i < length; i++ {
start := i * blockSize
end := (i + 1) * blockSize
if end > len(temperatures) {
end = len(temperatures)
}
temperatureBlocks[i] = temperatures[start:end]
}
for _, remote := range cnf.Remotes {
if remote.Enabled {
for _, temperatureBlock := range temperatureBlocks {
temperaturesAsBytes, err := json.Marshal(temperatureBlock)
if err != nil {
return fmt.Errorf("Can not marshal temperatures to JSON: %v", err)
}
temperaturesAsReader := bytes.NewReader(temperaturesAsBytes)
requestURL := fmt.Sprintf("%s%s", remote.Address, "/temperatures")
req, err := http.NewRequest("POST", requestURL, temperaturesAsReader)
if err != nil {
return err
}
client := http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode > 299 {
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("Invalid HTTP-Statuscode - expected 200, got %d - can not read response body: %v", resp.StatusCode, err)
}
return fmt.Errorf("Invalid HTTP-Statuscode - expected 200, got %d: %v", resp.StatusCode, string(b))
}
}
}
}
return nil
}

View File

@ -1,30 +0,0 @@
package humidity
import (
"fmt"
dht "github.com/MichaelS11/go-dht"
)
func Get() error {
err := dht.HostInit()
if err != nil {
return fmt.Errorf("HostInit error: %v", err)
}
dht, err := dht.NewDHT("GPIO19", dht.Celsius, "dht11")
if err != nil {
return fmt.Errorf("NewDHT error: %v", err)
}
humidity, temperature, err := dht.ReadRetry(10)
if err != nil {
return fmt.Errorf("Read error: %v", err)
}
fmt.Printf("humidity: %v\n", humidity)
fmt.Printf("temperature: %v\n", temperature)
return nil
}

View File

@ -1 +0,0 @@
package logs

View File

@ -1,170 +0,0 @@
package logs
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"text/tabwriter"
stypes "git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
"git.cryptic.systems/fh-trier/go-flucky/pkg/config"
"git.cryptic.systems/fh-trier/go-flucky/pkg/types"
)
// AppendTemperature write a given array of temperatures to a logfile
func AppendTemperature(temperatures []*stypes.Temperature, cnf *types.Config) error {
tLog, err := ReadTemperatures(cnf)
if err != nil {
return err
}
tLog = append(tLog, temperatures...)
err = WriteTemperatures(tLog, cnf)
if err != nil {
return err
}
return nil
}
// FlushTemperatures ...
func FlushTemperatures(cnf *types.Config) error {
if err := ioutil.WriteFile(cnf.TemperatureLogfile, []byte(""), 0644); err != nil {
return err
}
return nil
}
// ListTemperatures ...
func ListTemperatures(configDir string, w io.Writer) error {
cnf, err := config.Read(configDir)
if err != nil {
return err
}
temperatures, err := ReadTemperatures(cnf)
if err != nil {
return err
}
// tabwriter
tw := tabwriter.NewWriter(w, 0, 0, 5, ' ', 0)
sensors := []*stypes.Sensor{}
// find all sensors which matched with one of the configuration file
for _, temperature := range temperatures {
for _, cnfSensor := range cnf.Sensors {
if temperature.SensorID == cnfSensor.SensorID {
var found bool
for _, sensor := range sensors {
if temperature.SensorID == sensor.SensorID {
found = true
}
}
if !found {
sensors = append(sensors, cnfSensor)
}
}
}
}
// sort temperature values to every sensor
orderedTemperatures := make(map[string][]*stypes.Temperature)
for _, temperature := range temperatures {
orderedTemperatures[temperature.SensorID] = append(orderedTemperatures[temperature.SensorID], temperature)
}
// print headline
fmt.Fprint(tw, "\t")
for _, sensor := range sensors {
fmt.Fprintf(tw, "%v\t", sensor.ReadableSensorName())
}
if len(sensors) > 0 {
fmt.Fprint(tw, "\n")
}
// find max length
maxLength := 0
for _, orderedTemperature := range orderedTemperatures {
if len(orderedTemperature) > maxLength {
maxLength = len(orderedTemperature)
}
}
// print body
for i := 0; i < maxLength; i++ {
fmt.Fprintf(tw, "%v\t", i)
for _, sensor := range sensors {
if len(orderedTemperatures[sensor.SensorID]) > i {
fmt.Fprintf(tw, "%3.3f (%v)\t", orderedTemperatures[sensor.SensorID][i].TemperatureValue, orderedTemperatures[sensor.SensorID][i].TemperatureDate.Format("2006-01-02 15:04:05"))
} else {
fmt.Fprint(tw, "\t")
}
}
fmt.Fprint(tw, "\n")
}
tw.Flush()
return nil
}
// ReadTemperatures ...
func ReadTemperatures(cnf *types.Config) ([]*stypes.Temperature, error) {
logPath := filepath.Dir(cnf.TemperatureLogfile)
// create log dir if not exist
if _, err := os.Stat(cnf.TemperatureLogfile); os.IsNotExist(err) {
if _, err := os.Stat(logPath); os.IsNotExist(err) {
err := os.MkdirAll(logPath, os.ModePerm)
if err != nil {
return nil, fmt.Errorf("Can not create directory: %v", err)
}
}
if err := FlushTemperatures(cnf); err != nil {
return nil, err
}
}
// open config file
jsonFile, err := os.Open(cnf.TemperatureLogfile)
if err != nil {
return nil, fmt.Errorf("Can not open file %v: %v", cnf.TemperatureLogfile, err)
}
defer jsonFile.Close()
bytes, err := ioutil.ReadAll(jsonFile)
if err != nil {
return nil, fmt.Errorf("Can not read jsonfile %v: %v", cnf.TemperatureLogfile, err)
}
temperatures := []*stypes.Temperature{}
json.Unmarshal(bytes, &temperatures)
return temperatures, nil
}
// WriteTemperatures ...
func WriteTemperatures(temperatures []*stypes.Temperature, cnf *types.Config) error {
bytes, err := json.Marshal(temperatures)
if err != nil {
return err
}
if err := ioutil.WriteFile(cnf.TemperatureLogfile, bytes, 0644); err != nil {
return err
}
return nil
}

View File

@ -1,157 +0,0 @@
package remote
// import (
// "fmt"
// "io"
// "text/tabwriter"
// "git.cryptic.systems/fh-trier/go-flucky/pkg/config"
// )
// func Add(remote *types.Remote, configDir string) error {
// configuration, err := config.Read(configDir)
// if err != nil {
// return err
// }
// // search after duplicate remote_names
// for _, r := range configuration.Remotes {
// if r.Name == remote.Name {
// return fmt.Errorf("Remote-Name %v already exists", remote.Name)
// }
// }
// configuration.Remotes = append(configuration.Remotes, remote)
// if err := config.Write(configuration, configDir); err != nil {
// return err
// }
// return nil
// }
// // Enable a remote link
// func Enable(remoteName string, configDir string) error {
// cnf, err := config.Read(configDir)
// if err != nil {
// return err
// }
// // search after duplicate remote_names
// var found bool
// for _, r := range cnf.Remotes {
// if r.Name == remoteName {
// r.Enabled = true
// found = true
// }
// }
// if !found {
// return fmt.Errorf("Can not find remote %v", remoteName)
// }
// if err := config.Write(cnf, configDir); err != nil {
// return err
// }
// return nil
// }
// // Disable a remote link
// func Disable(remoteName string, configDir string) error {
// cnf, err := config.Read(configDir)
// if err != nil {
// return err
// }
// // search after duplicate remote_names
// var found bool
// for _, r := range cnf.Remotes {
// if r.Name == remoteName {
// r.Enabled = false
// found = true
// }
// }
// if !found {
// return fmt.Errorf("Can not find remote %v", remoteName)
// }
// if err := config.Write(cnf, configDir); err != nil {
// return err
// }
// return nil
// }
// func Print(w io.Writer, configDir string, quiet bool) error {
// configuration, err := config.Read(configDir)
// if err != nil {
// return err
// }
// tw := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0)
// if !quiet {
// fmt.Fprint(tw, "name\taddress\tenabled\tregistered\n")
// }
// for _, remote := range configuration.Remotes {
// if quiet {
// fmt.Fprintf(tw, "%v\n", remote.Name)
// } else {
// fmt.Fprintf(tw, "%v\t%v\t%v\t%v\n", remote.Name, remote.Address, remote.Enabled, remote.Registered)
// }
// }
// tw.Flush()
// return nil
// }
// func Remove(name string, configDir string) error {
// con, err := config.Read(configDir)
// if err != nil {
// return err
// }
// var j int
// for _, remote := range con.Remotes {
// if remote.Name == name {
// con.Remotes = append(con.Remotes[:j], con.Remotes[j+1:]...)
// if j > 0 {
// j = j - 1
// }
// continue
// }
// j++
// }
// if err := config.Write(con, configDir); err != nil {
// return err
// }
// return nil
// }
// func RemoveAll(configDir string) error {
// con, err := config.Read(configDir)
// if err != nil {
// return err
// }
// con.Remotes = nil
// if err := config.Write(con, configDir); err != nil {
// return err
// }
// return nil
// }

16
pkg/sensor/dht11.go Normal file
View File

@ -0,0 +1,16 @@
package sensor
import (
"log"
"git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
)
type DHT11Sensor struct {
*types.Sensor
}
func (s *DHT11Sensor) Read() (interface{}, error) {
log.Println("DHT11 Read Method not yet implemented")
return nil, nil
}

16
pkg/sensor/dht22.go Normal file
View File

@ -0,0 +1,16 @@
package sensor
import (
"log"
"git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
)
type DHT22Sensor struct {
*types.Sensor
}
func (s *DHT22Sensor) Read() (interface{}, error) {
log.Println("DHT22 Read Method not yet implemented")
return nil, nil
}

32
pkg/sensor/ds18b20.go Normal file
View File

@ -0,0 +1,32 @@
package sensor
import (
"fmt"
"time"
"git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
uuid "github.com/satori/go.uuid"
"github.com/yryz/ds18b20"
)
type DS18B20 struct {
*types.Sensor
}
func (s *DS18B20) Read() (interface{}, error) {
t, err := ds18b20.Temperature(*s.WireID)
if err != nil {
return nil, fmt.Errorf("Can not read from Sensor %v (UUID: %v, Wire-ID: %v): %v", s.SensorName, s.SensorID, s.WireID, err)
}
temperature := &types.Temperature{
TemperatureID: uuid.NewV4().String(),
TemperatureValue: t,
TemperatureDate: time.Now(),
SensorID: s.SensorID,
}
return temperature, nil
}

View File

@ -1,216 +1,7 @@
package sensor package sensor
import ( type Sensor interface {
"fmt" Read() (interface{}, error)
"io"
"os"
"path/filepath"
"text/tabwriter"
"time"
"github.com/satori/go.uuid"
stypes "git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
"git.cryptic.systems/fh-trier/go-flucky/pkg/config"
)
// Add ...
func Add(sensorName, sensorLocation, sensorType, wireID, gpioNumber *string, wirePath, configDir string, enabled *bool) error {
// read cnf file
cnf, err := config.Read(configDir)
if err != nil {
return err
}
s := &stypes.Sensor{
SensorID: uuid.NewV4().String(),
SensorName: sensorName,
SensorLocation: sensorLocation,
GPIONumber: gpioNumber,
SensorType: sensorType,
SensorEnabled: enabled,
DeviceID: cnf.DeviceID,
CreationDate: time.Now(),
}
// If the new sensor is a wire sensor
if wireID != nil {
// check if sensor exists
if !exists(wirePath, *wireID) {
return fmt.Errorf("Can not find sensor: %v", filepath.Join(wirePath, *wireID))
}
// check if sensor is redundant
if isWireIDRedundant(*wireID, cnf.Sensors) {
return fmt.Errorf("Sensor %v already exists", *wireID)
}
s.WireID = wireID
}
// check if sensor is redundant
if isSensorNameRedundant(*sensorName, cnf.Sensors) {
return fmt.Errorf("Sensor %v already exists", *sensorName)
}
// append sensor to list
cnf.Sensors = append(cnf.Sensors, s)
// write cnf file
if err := config.Write(cnf, configDir); err != nil {
return err
}
return nil
} }
// Enable a remote link // func ReadTemperatures
func Enable(sensorName string, configDir string) error {
cnf, err := config.Read(configDir)
if err != nil {
return err
}
// search after duplicate remote_names
var found bool
for _, sensor := range cnf.Sensors {
if *sensor.SensorName == sensorName ||
sensor.SensorID == sensorName {
*sensor.SensorEnabled = true
found = true
break
}
}
if !found {
return fmt.Errorf("Can not find sensor %v", sensorName)
}
if err := config.Write(cnf, configDir); err != nil {
return err
}
return nil
}
// Disable a remote link
func Disable(sensorName string, configDir string) error {
cnf, err := config.Read(configDir)
if err != nil {
return err
}
// search after duplicate remote_names
var found bool
for _, sensor := range cnf.Sensors {
if *sensor.SensorName == sensorName ||
sensor.SensorID == sensorName {
*sensor.SensorEnabled = false
found = true
break
}
}
if !found {
return fmt.Errorf("Can not find sensor %v", sensorName)
}
if err := config.Write(cnf, configDir); err != nil {
return err
}
return nil
}
// Print a list with the given writer w over all temperature sensors
func Print(w io.Writer, configDir string, quiet bool) error {
// read cnf file
cnf, err := config.Read(configDir)
if err != nil {
return err
}
// declar tabwriter
tw := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0)
// headline
if !quiet {
fmt.Fprint(tw, "id\tname\tlocation\ttype\twire-id\tgpio\tenabled\n")
}
for _, sensor := range cnf.Sensors {
if quiet {
fmt.Fprintf(tw, "%v\n", sensor.SensorID)
} else {
fmt.Fprintf(tw, "%v\t%v\t%v\t%v\t%v\t%v\t%v\n", sensor.SensorID, *sensor.SensorName, *sensor.SensorLocation, *sensor.SensorType, *sensor.WireID, *sensor.GPIONumber, *sensor.SensorEnabled)
}
}
tw.Flush()
return nil
}
// Remove a sensor
func Remove(sensorName, configDir string) error {
cnf, err := config.Read(configDir)
if err != nil {
return err
}
var j int
for _, sensor := range cnf.Sensors {
if *sensor.SensorName == sensorName ||
sensor.SensorID == sensorName {
cnf.Sensors = append(cnf.Sensors[:j], cnf.Sensors[j+1:]...)
if j > 0 {
j = j - 1
}
continue
}
j++
}
if err := config.Write(cnf, configDir); err != nil {
return err
}
return nil
}
func exists(wirePath, sensorID string) bool {
sensorPath := filepath.Join(wirePath, sensorID)
if _, err := os.Stat(sensorPath); os.IsNotExist(err) {
return false
}
return true
}
// isWireIDRedundant returns a boolean if the sensor id redundant
func isWireIDRedundant(wireID string, sensors []*stypes.Sensor) bool {
for _, sensor := range sensors {
if *sensor.WireID == wireID {
return true
}
}
return false
}
// isSensorNameRedundant returns a boolean if the sensor name redundant
func isSensorNameRedundant(sensorName string, sensors []*stypes.Sensor) bool {
for _, sensor := range sensors {
if *sensor.SensorName == sensorName {
return true
}
}
return false
}

View File

@ -1,292 +0,0 @@
package temperature
import (
"fmt"
"io"
"os"
"os/signal"
"syscall"
"text/tabwriter"
"time"
stypes "git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
"git.cryptic.systems/fh-trier/go-flucky/pkg/httpcall"
"git.cryptic.systems/fh-trier/go-flucky/pkg/logs"
"git.cryptic.systems/fh-trier/go-flucky/pkg/types"
"git.cryptic.systems/fh-trier/go-flucky/pkg/config"
uuid "github.com/satori/go.uuid"
"github.com/yryz/ds18b20"
)
var temperatureLog = "temperature.log"
// Get ...
func Get(sensorNames []string, push bool, configDir string, w io.Writer) error {
// get cnf
cnf, err := config.Read(configDir)
if err != nil {
return err
}
// get sensors
sensors, err := getSensors(sensorNames, cnf)
if err != nil {
return err
}
// get temperatures
temperatures, err := getTemperatures(sensors)
if err != nil {
return err
}
tw := tabwriter.NewWriter(w, 0, 0, 5, ' ', 0)
// headlines
for _, sensor := range sensors {
if sensor.SensorName != nil && *sensor.SensorName != "" {
fmt.Fprintf(tw, "%v\t", *sensor.SensorName)
} else {
fmt.Fprintf(tw, "%v\t", sensor.SensorID)
}
}
fmt.Fprint(tw, "\n")
// body
for _, temperature := range temperatures {
fmt.Fprintf(tw, "%v\t", temperature.TemperatureValue)
}
fmt.Fprint(tw, "\n")
tw.Flush()
// write logfiles or push
if !push {
if err := logs.AppendTemperature(temperatures, cnf); err != nil {
return err
}
} else {
if err := httpcall.SendTemperatures(temperatures, configDir); err != nil {
return err
}
}
return nil
}
// Fetch ...
func Fetch(sensorNames []string, push bool, configDir string) error {
// get cnf
cnf, err := config.Read(configDir)
if err != nil {
return err
}
// get sensors
sensors, err := getSensors(sensorNames, cnf)
if err != nil {
return err
}
// get temperatures
temperatures, err := getTemperatures(sensors)
if err != nil {
return err
}
// write logfiles or push
if !push {
if err := logs.AppendTemperature(temperatures, cnf); err != nil {
return err
}
} else {
if err := httpcall.SendTemperatures(temperatures, configDir); err != nil {
return err
}
}
return nil
}
// Follow ...
func Follow(sensorNames []string, push bool, configDir string, w io.Writer) error {
// get cnf
cnf, err := config.Read(configDir)
if err != nil {
return err
}
// get sensors
sensors, err := getSensors(sensorNames, cnf)
if err != nil {
return err
}
tw := tabwriter.NewWriter(w, 0, 0, 5, ' ', 0)
// headlines
for _, sensor := range sensors {
if sensor.SensorName != nil && *sensor.SensorName != "" {
fmt.Fprintf(tw, "%v\t", *sensor.SensorName)
} else {
fmt.Fprintf(tw, "%v\t", sensor.SensorID)
}
}
fmt.Fprint(tw, "\n")
// body
temperatures := []*stypes.Temperature{}
ticker := time.NewTicker(1 * time.Second)
// TODO: create channel for own sensor
go func() {
for {
select {
case _, more := <-ticker.C:
if !more {
return
}
// get temperatures from sensors and write them into writer
t, err := getTemperatures(sensors)
// TODO: get error back over channel
if err != nil {
return
}
// append temperatures to temperature list
temperatures = append(temperatures, t...)
for _, temperature := range t {
fmt.Fprintf(tw, "%3.3f\t", temperature.TemperatureValue)
}
fmt.Fprint(tw, "\n")
// flush writer
tw.Flush()
}
}
}()
signalChannel := make(chan os.Signal)
signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM)
sig := <-signalChannel
fmt.Printf("Got signal %s, initiating shutdown\n", sig)
ticker.Stop()
// write logfiles or push
if !push {
if err := logs.AppendTemperature(temperatures, cnf); err != nil {
return err
}
} else {
if err := httpcall.SendTemperatures(temperatures, configDir); err != nil {
return err
}
}
return nil
}
// Push ...
func Push(configDir string) error {
// get cnf
cnf, err := config.Read(configDir)
if err != nil {
return err
}
temperatures, err := logs.ReadTemperatures(cnf)
if err != nil {
return err
}
if err := httpcall.SendTemperatures(temperatures, configDir); err != nil {
return err
}
if err := logs.FlushTemperatures(cnf); err != nil {
return err
}
return nil
}
func getTemperatures(sensors []*stypes.Sensor) ([]*stypes.Temperature, error) {
temperatures := []*stypes.Temperature{}
for _, sensor := range sensors {
t, err := ds18b20.Temperature(*sensor.WireID)
if err != nil {
return []*stypes.Temperature{}, fmt.Errorf("Can not read temperature from sensor %v: %v", sensor.SensorID, err)
}
temperature := &stypes.Temperature{
TemperatureID: uuid.NewV4().String(),
TemperatureValue: t,
TemperatureDate: time.Now(),
SensorID: sensor.SensorID,
CreationDate: time.Now(),
}
temperatures = append(temperatures, temperature)
}
return temperatures, nil
}
func getSensors(sensorNames []string, cnf *types.Config) ([]*stypes.Sensor, error) {
sensors := []*stypes.Sensor{}
if len(sensorNames) > 0 {
for _, sensorName := range sensorNames {
for _, sensor := range cnf.Sensors {
if sensorName == *sensor.SensorName && *sensor.SensorEnabled ||
sensorName == sensor.SensorID && *sensor.SensorEnabled ||
sensorName == *sensor.WireID && *sensor.SensorEnabled {
sensors = append(sensors, sensor)
}
}
}
} else {
for _, sensor := range cnf.Sensors {
if *sensor.SensorEnabled {
sensors = append(sensors, sensor)
}
}
}
if len(sensors) == 0 {
return nil, fmt.Errorf("No matched Sensors. Check if your sensor is configured or enabled")
}
// check if sensor exists in cnf and has a wire id
for _, filterdSensor := range sensors {
if filterdSensor.WireID == nil || *filterdSensor.WireID == "" {
return nil, fmt.Errorf("Sensor %v has no wire id", filterdSensor.SensorID)
}
var found bool
for _, cnfSensor := range cnf.Sensors {
if filterdSensor.SensorID == cnfSensor.SensorID {
found = true
}
}
if !found {
return nil, fmt.Errorf("Can not found sensor %v in config", filterdSensor.SensorID)
}
}
return sensors, nil
}