fix: sync and fetch temperatures

changes:
- add sync command to synchronize device sensor information with remote
  servers
- fix fetch functions to get temperatures
This commit is contained in:
Markus Pesch 2018-11-29 16:06:39 +01:00
parent 99ff511117
commit f8e829d3d2
Signed by: volker.raschek
GPG Key ID: 852BCC170D81A982
13 changed files with 291 additions and 122 deletions

4
Gopkg.lock generated
View File

@ -3,11 +3,11 @@
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:7753db8f0bb46d1196ca6d01c52397b96de630975857bcdca0af62a5f107f588" digest = "1:ab8875db0749c2b2d147b0d250b73e45a2a722da4dd3664729ac207f1e6dcf9c"
name = "git.cryptic.systems/fh-trier/go-flucky-server" name = "git.cryptic.systems/fh-trier/go-flucky-server"
packages = ["pkg/types"] packages = ["pkg/types"]
pruneopts = "UT" pruneopts = "UT"
revision = "75118080be43f6e26d2701094ca86c23d9364a92" revision = "09990bcc64b4c240c53c0e98c03add895c1902c1"
[[projects]] [[projects]]
digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be" digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be"

View File

@ -4,6 +4,7 @@ import (
"git.cryptic.systems/fh-trier/go-flucky/cmd/config" "git.cryptic.systems/fh-trier/go-flucky/cmd/config"
"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/cmd/sensor" "git.cryptic.systems/fh-trier/go-flucky/cmd/sensor"
"git.cryptic.systems/fh-trier/go-flucky/cmd/temperature"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -23,7 +24,7 @@ func Execute(version string) {
config.InitCmd(rootCmd, configDir) config.InitCmd(rootCmd, configDir)
remote.InitCmd(rootCmd, configDir) remote.InitCmd(rootCmd, configDir)
sensor.InitCmd(rootCmd, configDir) sensor.InitCmd(rootCmd, configDir)
//temperature.InitCmd(rootCmd, configDir) temperature.InitCmd(rootCmd, configDir)
rootCmd.Execute() rootCmd.Execute()
} }

View File

@ -10,6 +10,7 @@ var configDir string
var configCmd = &cobra.Command{ var configCmd = &cobra.Command{
Use: "config", Use: "config",
Short: "Manage Configuration", Short: "Manage Configuration",
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if args[0] == "device.name" { if args[0] == "device.name" {
config.DeviceName(args[1], configDir) config.DeviceName(args[1], configDir)

View File

@ -1,26 +0,0 @@
package remote
import (
"log"
"git.cryptic.systems/fh-trier/go-flucky/pkg/httpcall"
"github.com/spf13/cobra"
)
var force bool
var registerRemoteCmd = &cobra.Command{
Use: "register",
Short: "register on remote servers",
Run: func(cmd *cobra.Command, args []string) {
if err := httpcall.RegisterDevice(configDir, force); err != nil {
log.Fatal(err)
}
},
}
func init() {
remoteCmd.AddCommand(registerRemoteCmd)
registerRemoteCmd.Flags().BoolVarP(&force, "force", "f", false, "Force register on a remote server")
}

26
cmd/remote/sync.go Normal file
View File

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

View File

@ -15,7 +15,7 @@ var addSensorCmd = &cobra.Command{
Short: "Add Sensor", Short: "Add Sensor",
Args: cobra.ExactArgs(3), Args: cobra.ExactArgs(3),
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if err := sensor.Add(&args[0], &sensorLocation, &args[1], &wireID, &args[2], wirePath, configDir, enabled); err != nil { if err := sensor.Add(&args[0], &sensorLocation, &args[1], &wireID, &args[2], wirePath, configDir, &enabled); err != nil {
log.Fatal(err) log.Fatal(err)
} }
}, },

26
cmd/sensor/sync.go Normal file
View File

@ -0,0 +1,26 @@
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",
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,31 +2,49 @@ package httpcall
import ( import (
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log"
"net/http" "net/http"
"time"
stypes "git.cryptic.systems/fh-trier/go-flucky-server/pkg/types" "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/config"
) )
// RegisterDevice .. // SyncDevice ..
func RegisterDevice(configDir string, force bool) error { func SyncDevice(configDir string, force bool) error {
con, err := config.Read(configDir)
// read config
cnf, err := config.Read(configDir)
if err != nil { if err != nil {
return err return err
} }
device := new(stypes.Device) // define array of devices
device.DeviceID = con.DeviceID device := types.Device{
DeviceID: cnf.DeviceID,
DeviceLocation: &cnf.DeviceLocation,
DeviceName: &cnf.DeviceName,
DeviceLastContact: time.Now(),
CreationDate: time.Now(),
}
var buffer bytes.Buffer // encode to json
device.EncodeToJSON(&buffer) deviceAsBytes, err := json.Marshal(device)
if err != nil {
return err
}
for _, remote := range con.Remotes { deviceAsReader := bytes.NewReader(deviceAsBytes)
// send array of devices to remote links
for _, remote := range cnf.Remotes {
if !remote.Registered || force { if !remote.Registered || force {
requestURL := fmt.Sprintf("%s%s", remote.Address, "/devices")
req, err := http.NewRequest("POST", requestURL, &buffer) requestURL := fmt.Sprintf("%v/devices/%v", remote.Address, cnf.DeviceID)
req, err := http.NewRequest("PUT", requestURL, deviceAsReader)
if err != nil { if err != nil {
return err return err
} }
@ -38,18 +56,47 @@ func RegisterDevice(configDir string, force bool) error {
} }
defer resp.Body.Close() defer resp.Body.Close()
log.Println(resp.StatusCode)
// 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, deviceAsReader)
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 { if resp.StatusCode < 200 || resp.StatusCode > 299 {
b, err := ioutil.ReadAll(resp.Body) b, err := ioutil.ReadAll(resp.Body)
if err != nil { 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("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("Invalid HTTP-Statuscode - expected 200, got %d: %v", resp.StatusCode, string(b)) 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 remote.Registered = true
} }
} }
if err := config.Write(con, configDir); err != nil { if err := config.Write(cnf, configDir); err != nil {
return err return err
} }

107
pkg/httpcall/sensor.go Normal file
View File

@ -0,0 +1,107 @@
package httpcall
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
stypes "git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
"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
}
// PostSensors ...
func PostSensors(sensors []*stypes.Sensor, 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(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

@ -12,11 +12,10 @@ import (
stypes "git.cryptic.systems/fh-trier/go-flucky-server/pkg/types" 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/config"
"git.cryptic.systems/fh-trier/go-flucky/pkg/types"
) )
// Add ... // Add ...
func Add(sensorName, sensorLocation, sensorType, wireID, gpioNumber *string, wirePath, configDir string, enabled bool) error { func Add(sensorName, sensorLocation, sensorType, wireID, gpioNumber *string, wirePath, configDir string, enabled *bool) error {
// read cnf file // read cnf file
cnf, err := config.Read(configDir) cnf, err := config.Read(configDir)
@ -24,17 +23,15 @@ func Add(sensorName, sensorLocation, sensorType, wireID, gpioNumber *string, wir
return err return err
} }
s := &types.Sensor{ s := &stypes.Sensor{
Enabled: enabled,
RemoteSensor: &stypes.Sensor{
SensorID: uuid.NewV4().String(), SensorID: uuid.NewV4().String(),
SensorName: sensorName, SensorName: sensorName,
SensorLocation: sensorLocation, SensorLocation: sensorLocation,
GPIONumber: gpioNumber, GPIONumber: gpioNumber,
SensorType: sensorType, SensorType: sensorType,
SensorEnabled: enabled,
DeviceID: cnf.DeviceID, DeviceID: cnf.DeviceID,
CreationDate: time.Now(), CreationDate: time.Now(),
},
} }
// If the new sensor is a wire sensor // If the new sensor is a wire sensor
@ -50,7 +47,7 @@ func Add(sensorName, sensorLocation, sensorType, wireID, gpioNumber *string, wir
return fmt.Errorf("Sensor %v already exists", *wireID) return fmt.Errorf("Sensor %v already exists", *wireID)
} }
s.RemoteSensor.WireID = wireID s.WireID = wireID
} }
// check if sensor is redundant // check if sensor is redundant
@ -80,9 +77,9 @@ func Enable(sensorName string, configDir string) error {
// search after duplicate remote_names // search after duplicate remote_names
var found bool var found bool
for _, sensor := range cnf.Sensors { for _, sensor := range cnf.Sensors {
if *sensor.RemoteSensor.SensorName == sensorName || if *sensor.SensorName == sensorName ||
sensor.RemoteSensor.SensorID == sensorName { sensor.SensorID == sensorName {
sensor.Enabled = true *sensor.SensorEnabled = true
found = true found = true
break break
} }
@ -110,9 +107,9 @@ func Disable(sensorName string, configDir string) error {
// search after duplicate remote_names // search after duplicate remote_names
var found bool var found bool
for _, sensor := range cnf.Sensors { for _, sensor := range cnf.Sensors {
if *sensor.RemoteSensor.SensorName == sensorName || if *sensor.SensorName == sensorName ||
sensor.RemoteSensor.SensorID == sensorName { sensor.SensorID == sensorName {
sensor.Enabled = false *sensor.SensorEnabled = false
found = true found = true
break break
} }
@ -148,9 +145,9 @@ func Print(w io.Writer, configDir string, quiet bool) error {
for _, sensor := range cnf.Sensors { for _, sensor := range cnf.Sensors {
if quiet { if quiet {
fmt.Fprintf(tw, "%v\n", sensor.RemoteSensor.SensorID) fmt.Fprintf(tw, "%v\n", sensor.SensorID)
} else { } else {
fmt.Fprintf(tw, "%v\t%v\t%v\t%v\t%v\t%v\t%v\n", sensor.RemoteSensor.SensorID, *sensor.RemoteSensor.SensorName, *sensor.RemoteSensor.SensorLocation, *sensor.RemoteSensor.SensorType, *sensor.RemoteSensor.WireID, *sensor.RemoteSensor.GPIONumber, sensor.Enabled) 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)
} }
} }
@ -169,8 +166,8 @@ func Remove(sensorName, configDir string) error {
var j int var j int
for _, sensor := range cnf.Sensors { for _, sensor := range cnf.Sensors {
if *sensor.RemoteSensor.SensorName == sensorName || if *sensor.SensorName == sensorName ||
sensor.RemoteSensor.SensorID == sensorName { sensor.SensorID == sensorName {
cnf.Sensors = append(cnf.Sensors[:j], cnf.Sensors[j+1:]...) cnf.Sensors = append(cnf.Sensors[:j], cnf.Sensors[j+1:]...)
if j > 0 { if j > 0 {
@ -197,9 +194,9 @@ func exists(wirePath, sensorID string) bool {
} }
// isWireIDRedundant returns a boolean if the sensor id redundant // isWireIDRedundant returns a boolean if the sensor id redundant
func isWireIDRedundant(wireID string, sensors []*types.Sensor) bool { func isWireIDRedundant(wireID string, sensors []*stypes.Sensor) bool {
for _, sensor := range sensors { for _, sensor := range sensors {
if *sensor.RemoteSensor.WireID == wireID { if *sensor.WireID == wireID {
return true return true
} }
} }
@ -208,9 +205,9 @@ func isWireIDRedundant(wireID string, sensors []*types.Sensor) bool {
} }
// isSensorNameRedundant returns a boolean if the sensor name redundant // isSensorNameRedundant returns a boolean if the sensor name redundant
func isSensorNameRedundant(sensorName string, sensors []*types.Sensor) bool { func isSensorNameRedundant(sensorName string, sensors []*stypes.Sensor) bool {
for _, sensor := range sensors { for _, sensor := range sensors {
if *sensor.RemoteSensor.SensorName == sensorName { if *sensor.SensorName == sensorName {
return true return true
} }
} }

View File

@ -10,7 +10,6 @@ import (
stypes "git.cryptic.systems/fh-trier/go-flucky-server/pkg/types" stypes "git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
"git.cryptic.systems/fh-trier/go-flucky/pkg/logs" "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" "git.cryptic.systems/fh-trier/go-flucky/pkg/config"
@ -42,21 +41,21 @@ func Get(argSensorNames []string, writeLogfiles, push bool, configDir string, w
} }
fmt.Fprint(tw, "\n") fmt.Fprint(tw, "\n")
} else { } else {
numOfSensors := len(cnf.TemperatureSensors) numOfSensors := len(cnf.Sensors)
for _, temperatureSensor := range cnf.TemperatureSensors { for _, sensor := range cnf.Sensors {
switch { switch {
case temperatureSensor.Name != "" && numOfSensors <= 1: case sensor.SensorName != nil && numOfSensors <= 1:
sensorNames = append(sensorNames, temperatureSensor.Name) sensorNames = append(sensorNames, *sensor.SensorName)
case temperatureSensor.Name == "" && numOfSensors <= 1: case sensor.SensorName == nil && numOfSensors <= 1:
sensorNames = append(sensorNames, temperatureSensor.ID) sensorNames = append(sensorNames, sensor.SensorID)
case temperatureSensor.Name != "" && numOfSensors > 1: case sensor.SensorName != nil && numOfSensors > 1:
fmt.Fprintf(tw, "%v\t", temperatureSensor.Name) fmt.Fprintf(tw, "%v\t", *sensor.SensorName)
sensorNames = append(sensorNames, temperatureSensor.Name) sensorNames = append(sensorNames, *sensor.SensorName)
break break
case temperatureSensor.Name == "" && numOfSensors > 1: case sensor.SensorName == nil && numOfSensors > 1:
sensorNames = append(sensorNames, temperatureSensor.ID) sensorNames = append(sensorNames, sensor.SensorID)
fmt.Fprintf(tw, "%v\t", temperatureSensor.ID) fmt.Fprintf(tw, "%v\t", sensor.SensorID)
break break
} }
} }
@ -212,11 +211,11 @@ func getTemperatures(sensorNames []string, configDir string) ([]*stypes.Temperat
} }
// search after sensor // search after sensor
var foundSensors []*types.WireSensor var foundSensors []*stypes.Sensor
var sensorFound bool var sensorFound bool
for _, configSensor := range cnf.TemperatureSensors { for _, configSensor := range cnf.Sensors {
for _, sensorName := range sensorNames { for _, sensorName := range sensorNames {
if configSensor.ID == sensorName || configSensor.Name == sensorName { if configSensor.SensorID == sensorName || *configSensor.SensorName == sensorName {
foundSensors = append(foundSensors, configSensor) foundSensors = append(foundSensors, configSensor)
sensorFound = true sensorFound = true
} }
@ -228,17 +227,16 @@ func getTemperatures(sensorNames []string, configDir string) ([]*stypes.Temperat
} }
for _, foundSensor := range foundSensors { for _, foundSensor := range foundSensors {
t, err := ds18b20.Temperature(foundSensor.ID) t, err := ds18b20.Temperature(*foundSensor.WireID)
if err != nil { if err != nil {
return []*stypes.Temperature{}, fmt.Errorf("Can not read temperature from sensor %v: %v", foundSensor.ID, err) return []*stypes.Temperature{}, fmt.Errorf("Can not read temperature from sensor %v: %v", foundSensor.SensorID, err)
} }
temperature := &stypes.Temperature{ temperature := &stypes.Temperature{
TemperatureID: uuid.NewV4().String(), TemperatureID: uuid.NewV4().String(),
TemperatureValue: t, TemperatureValue: t,
SensorID: foundSensor.ID, SensorID: foundSensor.SensorID,
TemperatureDate: time.Now(), TemperatureDate: time.Now(),
DeviceID: cnf.DeviceID,
} }
temperatures = append(temperatures, temperature) temperatures = append(temperatures, temperature)

View File

@ -16,7 +16,7 @@ type Config struct {
TemperatureLogfile string `json:"temperature_logfile"` TemperatureLogfile string `json:"temperature_logfile"`
HumidityLogfile string `json:"humiditiy_logfile"` HumidityLogfile string `json:"humiditiy_logfile"`
Remotes []*Remote `json:"remotes"` Remotes []*Remote `json:"remotes"`
Sensors []*Sensor `json:"sensors"` Sensors []*stypes.Sensor `json:"sensors"`
} }
func (c *Config) ToJSON() (string, error) { func (c *Config) ToJSON() (string, error) {
@ -56,8 +56,3 @@ type Remote struct {
Registered bool `json:"remote_registered"` Registered bool `json:"remote_registered"`
Enabled bool `json:"remote_enabled"` Enabled bool `json:"remote_enabled"`
} }
type Sensor struct {
RemoteSensor *stypes.Sensor `json:"sensor"`
Enabled bool `json:"sensor_enabled"`
}

View File

@ -7,17 +7,12 @@ import (
"time" "time"
) )
// TypeObject ...
type TypeObject interface {
EncodeToJSON(w io.Writer) error
DecodeFromJSON(r io.Reader) error
}
// Device ... // Device ...
type Device struct { type Device struct {
DeviceID string `json:"device_id"` DeviceID string `json:"device_id"`
DeviceName *string `json:"device_name"` DeviceName *string `json:"device_name"`
DeviceLocation *string `json:"device_location"` DeviceLocation *string `json:"device_location"`
DeviceLastContact time.Time `json:"device_last_contact"`
CreationDate time.Time `json:"creation_date"` CreationDate time.Time `json:"creation_date"`
} }
@ -78,6 +73,8 @@ type Sensor struct {
WireID *string `json:"wire_id"` WireID *string `json:"wire_id"`
GPIONumber *string `json:"gpio_number"` GPIONumber *string `json:"gpio_number"`
SensorType *string `json:"sensor_type"` SensorType *string `json:"sensor_type"`
SensorEnabled *bool `json:"sensor_enabled"`
SensorLastContact time.Time `json:"sensor_last_contact"`
DeviceID string `json:"device_id"` DeviceID string `json:"device_id"`
CreationDate time.Time `json:"creation_date"` CreationDate time.Time `json:"creation_date"`
} }