From f8e829d3d26a639780a9d1b1d1a1354743f2090c Mon Sep 17 00:00:00 2001 From: Markus Pesch Date: Thu, 29 Nov 2018 16:06:39 +0100 Subject: [PATCH] fix: sync and fetch temperatures changes: - add sync command to synchronize device sensor information with remote servers - fix fetch functions to get temperatures --- Gopkg.lock | 4 +- cmd/cmd.go | 3 +- cmd/config/config.go | 1 + cmd/remote/register.go | 26 ----- cmd/remote/sync.go | 26 +++++ cmd/sensor/add.go | 2 +- cmd/sensor/sync.go | 26 +++++ pkg/httpcall/remote.go | 75 +++++++++--- pkg/httpcall/sensor.go | 107 ++++++++++++++++++ pkg/sensor/sensor.go | 53 ++++----- pkg/temperature/temperature.go | 38 +++---- pkg/types/types.go | 19 ++-- .../go-flucky-server/pkg/types/types.go | 33 +++--- 13 files changed, 291 insertions(+), 122 deletions(-) delete mode 100644 cmd/remote/register.go create mode 100644 cmd/remote/sync.go create mode 100644 cmd/sensor/sync.go create mode 100644 pkg/httpcall/sensor.go diff --git a/Gopkg.lock b/Gopkg.lock index 008e003..8ee2cb1 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -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" diff --git a/cmd/cmd.go b/cmd/cmd.go index a83ffa9..452f462 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -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() } diff --git a/cmd/config/config.go b/cmd/config/config.go index d0fb624..f9136d6 100644 --- a/cmd/config/config.go +++ b/cmd/config/config.go @@ -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) diff --git a/cmd/remote/register.go b/cmd/remote/register.go deleted file mode 100644 index 16a6e47..0000000 --- a/cmd/remote/register.go +++ /dev/null @@ -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") -} diff --git a/cmd/remote/sync.go b/cmd/remote/sync.go new file mode 100644 index 0000000..ba336a3 --- /dev/null +++ b/cmd/remote/sync.go @@ -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") +} diff --git a/cmd/sensor/add.go b/cmd/sensor/add.go index 3898378..f53fe98 100644 --- a/cmd/sensor/add.go +++ b/cmd/sensor/add.go @@ -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) } }, diff --git a/cmd/sensor/sync.go b/cmd/sensor/sync.go new file mode 100644 index 0000000..861f8d6 --- /dev/null +++ b/cmd/sensor/sync.go @@ -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") +} diff --git a/pkg/httpcall/remote.go b/pkg/httpcall/remote.go index 341bcea..c7fdeab 100644 --- a/pkg/httpcall/remote.go +++ b/pkg/httpcall/remote.go @@ -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 } diff --git a/pkg/httpcall/sensor.go b/pkg/httpcall/sensor.go new file mode 100644 index 0000000..d964751 --- /dev/null +++ b/pkg/httpcall/sensor.go @@ -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 +} diff --git a/pkg/sensor/sensor.go b/pkg/sensor/sensor.go index 1270aac..665dd4c 100644 --- a/pkg/sensor/sensor.go +++ b/pkg/sensor/sensor.go @@ -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 } } diff --git a/pkg/temperature/temperature.go b/pkg/temperature/temperature.go index df84de3..889608c 100644 --- a/pkg/temperature/temperature.go +++ b/pkg/temperature/temperature.go @@ -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) diff --git a/pkg/types/types.go b/pkg/types/types.go index 842ce37..0098333 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -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"` -} diff --git a/vendor/git.cryptic.systems/fh-trier/go-flucky-server/pkg/types/types.go b/vendor/git.cryptic.systems/fh-trier/go-flucky-server/pkg/types/types.go index 1199078..8aee04b 100644 --- a/vendor/git.cryptic.systems/fh-trier/go-flucky-server/pkg/types/types.go +++ b/vendor/git.cryptic.systems/fh-trier/go-flucky-server/pkg/types/types.go @@ -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