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]]
branch = "master"
digest = "1:7753db8f0bb46d1196ca6d01c52397b96de630975857bcdca0af62a5f107f588"
digest = "1:ab8875db0749c2b2d147b0d250b73e45a2a722da4dd3664729ac207f1e6dcf9c"
name = "git.cryptic.systems/fh-trier/go-flucky-server"
packages = ["pkg/types"]
pruneopts = "UT"
revision = "75118080be43f6e26d2701094ca86c23d9364a92"
revision = "09990bcc64b4c240c53c0e98c03add895c1902c1"
[[projects]]
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/remote"
"git.cryptic.systems/fh-trier/go-flucky/cmd/sensor"
"git.cryptic.systems/fh-trier/go-flucky/cmd/temperature"
"github.com/spf13/cobra"
)
@ -23,7 +24,7 @@ func Execute(version string) {
config.InitCmd(rootCmd, configDir)
remote.InitCmd(rootCmd, configDir)
sensor.InitCmd(rootCmd, configDir)
//temperature.InitCmd(rootCmd, configDir)
temperature.InitCmd(rootCmd, configDir)
rootCmd.Execute()
}

View File

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

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 (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"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"
)
// RegisterDevice ..
func RegisterDevice(configDir string, force bool) error {
con, err := config.Read(configDir)
// SyncDevice ..
func SyncDevice(configDir string, force bool) error {
// read config
cnf, err := config.Read(configDir)
if err != nil {
return err
}
device := new(stypes.Device)
device.DeviceID = con.DeviceID
// define array of devices
device := types.Device{
DeviceID: cnf.DeviceID,
DeviceLocation: &cnf.DeviceLocation,
DeviceName: &cnf.DeviceName,
DeviceLastContact: time.Now(),
CreationDate: time.Now(),
}
var buffer bytes.Buffer
device.EncodeToJSON(&buffer)
// encode to json
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 {
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 {
return err
}
@ -38,18 +56,47 @@ func RegisterDevice(configDir string, force bool) error {
}
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 {
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("Invalid HTTP-Statuscode - expected 200, got %d - can not read response body: %v", resp.StatusCode, err)
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("Invalid HTTP-Statuscode - expected 200, got %d: %v", resp.StatusCode, string(b))
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(con, configDir); err != nil {
if err := config.Write(cnf, configDir); err != nil {
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"
"git.cryptic.systems/fh-trier/go-flucky/pkg/config"
"git.cryptic.systems/fh-trier/go-flucky/pkg/types"
)
// 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
cnf, err := config.Read(configDir)
@ -24,17 +23,15 @@ func Add(sensorName, sensorLocation, sensorType, wireID, gpioNumber *string, wir
return err
}
s := &types.Sensor{
Enabled: enabled,
RemoteSensor: &stypes.Sensor{
SensorID: uuid.NewV4().String(),
SensorName: sensorName,
SensorLocation: sensorLocation,
GPIONumber: gpioNumber,
SensorType: sensorType,
DeviceID: cnf.DeviceID,
CreationDate: time.Now(),
},
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
@ -50,7 +47,7 @@ func Add(sensorName, sensorLocation, sensorType, wireID, gpioNumber *string, wir
return fmt.Errorf("Sensor %v already exists", *wireID)
}
s.RemoteSensor.WireID = wireID
s.WireID = wireID
}
// check if sensor is redundant
@ -80,9 +77,9 @@ func Enable(sensorName string, configDir string) error {
// search after duplicate remote_names
var found bool
for _, sensor := range cnf.Sensors {
if *sensor.RemoteSensor.SensorName == sensorName ||
sensor.RemoteSensor.SensorID == sensorName {
sensor.Enabled = true
if *sensor.SensorName == sensorName ||
sensor.SensorID == sensorName {
*sensor.SensorEnabled = true
found = true
break
}
@ -110,9 +107,9 @@ func Disable(sensorName string, configDir string) error {
// search after duplicate remote_names
var found bool
for _, sensor := range cnf.Sensors {
if *sensor.RemoteSensor.SensorName == sensorName ||
sensor.RemoteSensor.SensorID == sensorName {
sensor.Enabled = false
if *sensor.SensorName == sensorName ||
sensor.SensorID == sensorName {
*sensor.SensorEnabled = false
found = true
break
}
@ -148,9 +145,9 @@ func Print(w io.Writer, configDir string, quiet bool) error {
for _, sensor := range cnf.Sensors {
if quiet {
fmt.Fprintf(tw, "%v\n", sensor.RemoteSensor.SensorID)
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.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
for _, sensor := range cnf.Sensors {
if *sensor.RemoteSensor.SensorName == sensorName ||
sensor.RemoteSensor.SensorID == sensorName {
if *sensor.SensorName == sensorName ||
sensor.SensorID == sensorName {
cnf.Sensors = append(cnf.Sensors[:j], cnf.Sensors[j+1:]...)
if j > 0 {
@ -197,9 +194,9 @@ func exists(wirePath, sensorID string) bool {
}
// 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 {
if *sensor.RemoteSensor.WireID == wireID {
if *sensor.WireID == wireID {
return true
}
}
@ -208,9 +205,9 @@ func isWireIDRedundant(wireID string, sensors []*types.Sensor) bool {
}
// 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 {
if *sensor.RemoteSensor.SensorName == sensorName {
if *sensor.SensorName == sensorName {
return true
}
}

View File

@ -10,7 +10,6 @@ import (
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/types"
"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")
} else {
numOfSensors := len(cnf.TemperatureSensors)
numOfSensors := len(cnf.Sensors)
for _, temperatureSensor := range cnf.TemperatureSensors {
for _, sensor := range cnf.Sensors {
switch {
case temperatureSensor.Name != "" && numOfSensors <= 1:
sensorNames = append(sensorNames, temperatureSensor.Name)
case temperatureSensor.Name == "" && numOfSensors <= 1:
sensorNames = append(sensorNames, temperatureSensor.ID)
case temperatureSensor.Name != "" && numOfSensors > 1:
fmt.Fprintf(tw, "%v\t", temperatureSensor.Name)
sensorNames = append(sensorNames, temperatureSensor.Name)
case sensor.SensorName != nil && numOfSensors <= 1:
sensorNames = append(sensorNames, *sensor.SensorName)
case sensor.SensorName == nil && numOfSensors <= 1:
sensorNames = append(sensorNames, sensor.SensorID)
case sensor.SensorName != nil && numOfSensors > 1:
fmt.Fprintf(tw, "%v\t", *sensor.SensorName)
sensorNames = append(sensorNames, *sensor.SensorName)
break
case temperatureSensor.Name == "" && numOfSensors > 1:
sensorNames = append(sensorNames, temperatureSensor.ID)
fmt.Fprintf(tw, "%v\t", temperatureSensor.ID)
case sensor.SensorName == nil && numOfSensors > 1:
sensorNames = append(sensorNames, sensor.SensorID)
fmt.Fprintf(tw, "%v\t", sensor.SensorID)
break
}
}
@ -212,11 +211,11 @@ func getTemperatures(sensorNames []string, configDir string) ([]*stypes.Temperat
}
// search after sensor
var foundSensors []*types.WireSensor
var foundSensors []*stypes.Sensor
var sensorFound bool
for _, configSensor := range cnf.TemperatureSensors {
for _, configSensor := range cnf.Sensors {
for _, sensorName := range sensorNames {
if configSensor.ID == sensorName || configSensor.Name == sensorName {
if configSensor.SensorID == sensorName || *configSensor.SensorName == sensorName {
foundSensors = append(foundSensors, configSensor)
sensorFound = true
}
@ -228,17 +227,16 @@ func getTemperatures(sensorNames []string, configDir string) ([]*stypes.Temperat
}
for _, foundSensor := range foundSensors {
t, err := ds18b20.Temperature(foundSensor.ID)
t, err := ds18b20.Temperature(*foundSensor.WireID)
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{
TemperatureID: uuid.NewV4().String(),
TemperatureValue: t,
SensorID: foundSensor.ID,
SensorID: foundSensor.SensorID,
TemperatureDate: time.Now(),
DeviceID: cnf.DeviceID,
}
temperatures = append(temperatures, temperature)

View File

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

View File

@ -7,18 +7,13 @@ import (
"time"
)
// TypeObject ...
type TypeObject interface {
EncodeToJSON(w io.Writer) error
DecodeFromJSON(r io.Reader) error
}
// Device ...
type Device struct {
DeviceID string `json:"device_id"`
DeviceName *string `json:"device_name"`
DeviceLocation *string `json:"device_location"`
CreationDate time.Time `json:"creation_date"`
DeviceID string `json:"device_id"`
DeviceName *string `json:"device_name"`
DeviceLocation *string `json:"device_location"`
DeviceLastContact time.Time `json:"device_last_contact"`
CreationDate time.Time `json:"creation_date"`
}
// EncodeToJSON needs a writer to write the struct into json string
@ -72,14 +67,16 @@ func (h *Humidity) DecodeFromJSON(r io.Reader) error {
// Sensor ...
type Sensor struct {
SensorID string `json:"sensor_id"`
SensorName *string `json:"sensor_name"`
SensorLocation *string `json:"sensor_location"`
WireID *string `json:"wire_id"`
GPIONumber *string `json:"gpio_number"`
SensorType *string `json:"sensor_type"`
DeviceID string `json:"device_id"`
CreationDate time.Time `json:"creation_date"`
SensorID string `json:"sensor_id"`
SensorName *string `json:"sensor_name"`
SensorLocation *string `json:"sensor_location"`
WireID *string `json:"wire_id"`
GPIONumber *string `json:"gpio_number"`
SensorType *string `json:"sensor_type"`
SensorEnabled *bool `json:"sensor_enabled"`
SensorLastContact time.Time `json:"sensor_last_contact"`
DeviceID string `json:"device_id"`
CreationDate time.Time `json:"creation_date"`
}
// EncodeToJSON needs a writer to write the struct into json string