fix(pkg/sensor): reduce interface functions for better error handling
This commit is contained in:
parent
ca4269fff8
commit
95fb1f6745
@ -5,13 +5,12 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/go-flucky/flucky/pkg/storage"
|
|
||||||
"github.com/go-flucky/flucky/pkg/types"
|
|
||||||
|
|
||||||
"github.com/go-flucky/flucky/pkg/cli"
|
"github.com/go-flucky/flucky/pkg/cli"
|
||||||
"github.com/go-flucky/flucky/pkg/config"
|
"github.com/go-flucky/flucky/pkg/config"
|
||||||
"github.com/go-flucky/flucky/pkg/rgbled"
|
"github.com/go-flucky/flucky/pkg/rgbled"
|
||||||
"github.com/go-flucky/flucky/pkg/sensor"
|
"github.com/go-flucky/flucky/pkg/sensor"
|
||||||
|
"github.com/go-flucky/flucky/pkg/storage"
|
||||||
|
"github.com/go-flucky/flucky/pkg/types"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -45,9 +44,8 @@ var readHumidityCmd = &cobra.Command{
|
|||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
measuredValues, err := sensor.Read(sensors, types.MeasuredValueTypeTemperature)
|
||||||
measuredValues, err := sensor.Read(ctx, sensors)
|
if err := rgbled.Run(rgbLEDs); err != nil {
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,6 +59,8 @@ var readHumidityCmd = &cobra.Command{
|
|||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
err = storage.Write(ctx, measuredValues, storageEndpoint)
|
err = storage.Write(ctx, measuredValues, storageEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
|
@ -45,14 +45,11 @@ var readPressureCmd = &cobra.Command{
|
|||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
measuredValues, err := sensor.Read(sensors, types.MeasuredValueTypePressure)
|
||||||
measuredValues, err := sensor.Read(ctx, sensors)
|
if err := rgbled.Run(rgbLEDs); err != nil {
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
measuredValues = types.SelectMeasuredValues(types.MeasuredValueTypePressure, measuredValues)
|
|
||||||
|
|
||||||
cli.PrintMeasuredValues(measuredValues, cnf, os.Stdout)
|
cli.PrintMeasuredValues(measuredValues, cnf, os.Stdout)
|
||||||
|
|
||||||
if logs {
|
if logs {
|
||||||
@ -61,6 +58,8 @@ var readPressureCmd = &cobra.Command{
|
|||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
err = storage.Write(ctx, measuredValues, storageEndpoint)
|
err = storage.Write(ctx, measuredValues, storageEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
|
@ -6,12 +6,12 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/go-flucky/flucky/pkg/storage"
|
|
||||||
"github.com/go-flucky/flucky/pkg/types"
|
|
||||||
|
|
||||||
"github.com/go-flucky/flucky/pkg/cli"
|
"github.com/go-flucky/flucky/pkg/cli"
|
||||||
"github.com/go-flucky/flucky/pkg/config"
|
"github.com/go-flucky/flucky/pkg/config"
|
||||||
|
"github.com/go-flucky/flucky/pkg/rgbled"
|
||||||
"github.com/go-flucky/flucky/pkg/sensor"
|
"github.com/go-flucky/flucky/pkg/sensor"
|
||||||
|
"github.com/go-flucky/flucky/pkg/storage"
|
||||||
|
"github.com/go-flucky/flucky/pkg/types"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,36 +39,33 @@ var readTemperatureCmd = &cobra.Command{
|
|||||||
log.Fatalln("No sensors found, specified or configured")
|
log.Fatalln("No sensors found, specified or configured")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
rgbLEDs := cnf.GetRGBLEDs(config.ENABLED)
|
||||||
measuredValues, err := sensor.Read(ctx, sensors)
|
if err := rgbled.Run(rgbLEDs); err != nil {
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
storage.Round(measuredValues, round)
|
measuredValues, err := sensor.Read(sensors, types.MeasuredValueTypeTemperature)
|
||||||
|
if err := rgbled.Run(rgbLEDs); err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
|
||||||
measuredValues = types.SelectMeasuredValues(types.MeasuredValueTypeTemperature, measuredValues)
|
|
||||||
|
|
||||||
// print temperatures on stdout
|
|
||||||
cli.PrintMeasuredValues(measuredValues, cnf, os.Stdout)
|
cli.PrintMeasuredValues(measuredValues, cnf, os.Stdout)
|
||||||
|
|
||||||
// Save the new measured values, if desired
|
|
||||||
if logs {
|
if logs {
|
||||||
|
|
||||||
if compression {
|
|
||||||
measuredValues = storage.Compression(measuredValues)
|
|
||||||
}
|
|
||||||
|
|
||||||
storageEndpoint, err := cnf.GetStorageEndpointURL()
|
storageEndpoint, err := cnf.GetStorageEndpointURL()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
err = storage.Write(ctx, measuredValues, storageEndpoint)
|
err = storage.Write(ctx, measuredValues, storageEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rgbled.Off(rgbLEDs)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package daemon
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
@ -59,8 +60,49 @@ func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compress
|
|||||||
measuredValuesCache := make([]*types.MeasuredValue, 0)
|
measuredValuesCache := make([]*types.MeasuredValue, 0)
|
||||||
// measuredValuesLogfile := logfile.New(cnf.Logfile)
|
// measuredValuesLogfile := logfile.New(cnf.Logfile)
|
||||||
|
|
||||||
// Producer
|
// Init semaphoreChannel
|
||||||
go sensor.ReadContinuously(ctx, cnf.GetSensors(config.ENABLED), measuredValueChannel, errorChannel)
|
semaphoreChannels := make(map[string]chan struct{})
|
||||||
|
for _, sensor := range cnf.GetSensors(config.ENABLED) {
|
||||||
|
semaphoreChannels[sensor.ID()] = make(chan struct{}, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start producers
|
||||||
|
for _, s := range cnf.GetSensors(config.ENABLED) {
|
||||||
|
|
||||||
|
// start go routine for each sensor
|
||||||
|
go func(sensor sensor.Sensor) {
|
||||||
|
// run forever
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
errorChannel <- fmt.Errorf("Closed context: %v", ctx.Err().Error())
|
||||||
|
return
|
||||||
|
case <-semaphoreChannels[sensor.ID()]:
|
||||||
|
measuredValues, err := sensor.Read()
|
||||||
|
if err != nil {
|
||||||
|
errorChannel <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, measmeasuredValue := range measuredValues {
|
||||||
|
measuredValueChannel <- measmeasuredValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(s)
|
||||||
|
|
||||||
|
// start ticker for each sensor
|
||||||
|
go func(sensor sensor.Sensor) {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
errorChannel <- fmt.Errorf("Closed context: %v", ctx.Err().Error())
|
||||||
|
return
|
||||||
|
case <-sensor.Ticker().C:
|
||||||
|
semaphoreChannels[sensor.ID()] <- struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(s)
|
||||||
|
}
|
||||||
|
|
||||||
// Distributor
|
// Distributor
|
||||||
//measuredValueChannels := distribute.MeasuredValues(ctx, 5, measuredValueChannel)
|
//measuredValueChannels := distribute.MeasuredValues(ctx, 5, measuredValueChannel)
|
||||||
@ -105,7 +147,11 @@ func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compress
|
|||||||
|
|
||||||
measuredValuesCache = make([]*types.MeasuredValue, 0)
|
measuredValuesCache = make([]*types.MeasuredValue, 0)
|
||||||
|
|
||||||
case measuredValue, _ := <-measuredValueChannel:
|
case measuredValue, open := <-measuredValueChannel:
|
||||||
|
if !open {
|
||||||
|
errorChannel <- fmt.Errorf("MeasuredValue channel closed")
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
measuredValuesCache = append(measuredValuesCache, measuredValue)
|
measuredValuesCache = append(measuredValuesCache, measuredValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/d2r2/go-bsbmp"
|
"github.com/d2r2/go-bsbmp"
|
||||||
"github.com/d2r2/go-i2c"
|
"github.com/d2r2/go-i2c"
|
||||||
@ -19,9 +20,8 @@ type BME280 struct {
|
|||||||
*types.Sensor
|
*types.Sensor
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSensorModel returns the sensor model
|
func (s *BME280) ID() string {
|
||||||
func (s *BME280) GetSensorModel() types.SensorModel {
|
return s.SensorID
|
||||||
return s.Sensor.SensorModel
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read measured values
|
// Read measured values
|
||||||
@ -124,3 +124,12 @@ func (s *BME280) ReadContinously(ctx context.Context, measuredValueChannel chan<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ticker returns a new ticker, which tick every when the sensor should be read
|
||||||
|
func (s *BME280) Ticker() *time.Ticker {
|
||||||
|
duration, err := time.ParseDuration(s.TickDuration)
|
||||||
|
if err != nil {
|
||||||
|
duration = time.Minute
|
||||||
|
}
|
||||||
|
return time.NewTicker(duration)
|
||||||
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/go-flucky/flucky/pkg/internal/format"
|
"github.com/go-flucky/flucky/pkg/internal/format"
|
||||||
"github.com/go-flucky/flucky/pkg/types"
|
"github.com/go-flucky/flucky/pkg/types"
|
||||||
@ -16,9 +17,8 @@ type DHT11 struct {
|
|||||||
*types.Sensor
|
*types.Sensor
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSensorModel returns the sensor model
|
func (s *DHT11) ID() string {
|
||||||
func (s *DHT11) GetSensorModel() types.SensorModel {
|
return s.SensorID
|
||||||
return s.Sensor.SensorModel
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read measured values
|
// Read measured values
|
||||||
@ -98,3 +98,12 @@ func (s *DHT11) ReadContinously(ctx context.Context, measuredValueChannel chan<-
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ticker returns a new ticker, which tick every when the sensor should be read
|
||||||
|
func (s *DHT11) Ticker() *time.Ticker {
|
||||||
|
duration, err := time.ParseDuration(s.TickDuration)
|
||||||
|
if err != nil {
|
||||||
|
duration = time.Minute
|
||||||
|
}
|
||||||
|
return time.NewTicker(duration)
|
||||||
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/go-flucky/flucky/pkg/internal/format"
|
"github.com/go-flucky/flucky/pkg/internal/format"
|
||||||
"github.com/go-flucky/flucky/pkg/types"
|
"github.com/go-flucky/flucky/pkg/types"
|
||||||
@ -16,9 +17,8 @@ type DHT22 struct {
|
|||||||
*types.Sensor
|
*types.Sensor
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSensorModel returns the sensor model
|
func (s *DHT22) ID() string {
|
||||||
func (s *DHT22) GetSensorModel() types.SensorModel {
|
return s.SensorID
|
||||||
return s.Sensor.SensorModel
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read measured values
|
// Read measured values
|
||||||
@ -98,3 +98,12 @@ func (s *DHT22) ReadContinously(ctx context.Context, measuredValueChannel chan<-
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ticker returns a new ticker, which tick every when the sensor should be read
|
||||||
|
func (s *DHT22) Ticker() *time.Ticker {
|
||||||
|
duration, err := time.ParseDuration(s.TickDuration)
|
||||||
|
if err != nil {
|
||||||
|
duration = time.Minute
|
||||||
|
}
|
||||||
|
return time.NewTicker(duration)
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/go-flucky/flucky/pkg/internal/format"
|
"github.com/go-flucky/flucky/pkg/internal/format"
|
||||||
"github.com/go-flucky/flucky/pkg/types"
|
"github.com/go-flucky/flucky/pkg/types"
|
||||||
@ -19,9 +20,8 @@ type DS18B20 struct {
|
|||||||
*types.Sensor
|
*types.Sensor
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSensorModel returns the sensor model
|
func (s *DS18B20) ID() string {
|
||||||
func (s *DS18B20) GetSensorModel() types.SensorModel {
|
return s.SensorID
|
||||||
return s.Sensor.SensorModel
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read measured values
|
// Read measured values
|
||||||
@ -40,12 +40,12 @@ func (s *DS18B20) Read() ([]*types.MeasuredValue, error) {
|
|||||||
|
|
||||||
i := strings.LastIndex(raw, "t=")
|
i := strings.LastIndex(raw, "t=")
|
||||||
if i == -1 {
|
if i == -1 {
|
||||||
return nil, ErrReadSensor
|
return nil, errorReadData
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := strconv.ParseFloat(raw[i+2:len(raw)-1], 64)
|
c, err := strconv.ParseFloat(raw[i+2:len(raw)-1], 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ErrParseData
|
return nil, errorParseData
|
||||||
}
|
}
|
||||||
|
|
||||||
temperatureValue := c / 1000
|
temperatureValue := c / 1000
|
||||||
@ -97,3 +97,12 @@ func (s *DS18B20) ReadContinously(ctx context.Context, measuredValueChannel chan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ticker returns a new ticker, which tick every when the sensor should be read
|
||||||
|
func (s *DS18B20) Ticker() *time.Ticker {
|
||||||
|
duration, err := time.ParseDuration(s.TickDuration)
|
||||||
|
if err != nil {
|
||||||
|
duration = time.Minute
|
||||||
|
}
|
||||||
|
return time.NewTicker(duration)
|
||||||
|
}
|
||||||
|
@ -4,5 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrParseData = errors.New("Can not parse data")
|
var (
|
||||||
var ErrReadSensor = errors.New("Can not read data from Sensor")
|
errorParseData = errors.New("Failed to parse data")
|
||||||
|
errorReadData = errors.New("Failed to read data from sensor")
|
||||||
|
)
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
package sensor
|
package sensor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/go-flucky/flucky/pkg/types"
|
"github.com/go-flucky/flucky/pkg/types"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Sensor interface {
|
type Sensor interface {
|
||||||
GetSensorModel() types.SensorModel
|
ID() string
|
||||||
Read() ([]*types.MeasuredValue, error)
|
Read() ([]*types.MeasuredValue, error)
|
||||||
ReadChannel(measuredValueChannel chan<- *types.MeasuredValue, errorChannel chan<- error, wg *sync.WaitGroup)
|
Ticker() *time.Ticker
|
||||||
ReadContinously(ctx context.Context, measuredValueChannel chan<- *types.MeasuredValue, errorChannel chan<- error)
|
|
||||||
}
|
}
|
||||||
|
@ -1,58 +1,46 @@
|
|||||||
package sensor
|
package sensor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/go-flucky/flucky/pkg/internal/collect"
|
|
||||||
"github.com/go-flucky/flucky/pkg/internal/prittyprint"
|
|
||||||
|
|
||||||
"github.com/go-flucky/flucky/pkg/types"
|
"github.com/go-flucky/flucky/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Read measured values from sensors
|
func Read(sensors []Sensor, measuredValueType types.MeasuredValueType) ([]*types.MeasuredValue, error) {
|
||||||
func Read(ctx context.Context, sensors []Sensor) ([]*types.MeasuredValue, error) {
|
|
||||||
|
|
||||||
measuredValueChannel := make(chan *types.MeasuredValue, len(sensors))
|
type result struct {
|
||||||
errorChannel := make(chan error, len(sensors))
|
measuredValues []*types.MeasuredValue
|
||||||
|
err error
|
||||||
ReadChannel(ctx, sensors, measuredValueChannel, errorChannel)
|
|
||||||
|
|
||||||
errors := collect.Errors(errorChannel)
|
|
||||||
if len(errors) > 0 {
|
|
||||||
return nil, prittyprint.FormatErrors(errors)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
measuredValues := collect.MeasuredValues(measuredValueChannel)
|
resultChannel := make(chan *result, len(sensors))
|
||||||
|
|
||||||
return measuredValues, nil
|
// producers
|
||||||
}
|
// read measured values
|
||||||
|
for _, s := range sensors {
|
||||||
// ReadChannel reads the measured values from sensors and writes them to a
|
go func(s Sensor) {
|
||||||
// channel.
|
measuredValues, err := s.Read()
|
||||||
func ReadChannel(ctx context.Context, sensors []Sensor, measuredValueChannel chan<- *types.MeasuredValue, errorChannel chan<- error) {
|
resultChannel <- &result{
|
||||||
|
measuredValues: measuredValues,
|
||||||
wg := new(sync.WaitGroup)
|
err: err,
|
||||||
wg.Add(len(sensors))
|
}
|
||||||
|
}(s)
|
||||||
for _, sensor := range sensors {
|
|
||||||
go sensor.ReadChannel(measuredValueChannel, errorChannel, wg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
// consumer
|
||||||
}
|
measuredValues := make([]*types.MeasuredValue, 0)
|
||||||
|
counter := len(sensors)
|
||||||
// ReadContinuously reads the measured values continously from sensors and writes
|
|
||||||
// them to a channel.
|
|
||||||
func ReadContinuously(ctx context.Context, sensors []Sensor, measuredValueChannel chan<- *types.MeasuredValue, errorChannel chan<- error) {
|
|
||||||
for {
|
for {
|
||||||
|
if counter == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case result := <-resultChannel:
|
||||||
errorChannel <- fmt.Errorf("Context closed: %v", ctx.Err())
|
counter--
|
||||||
return
|
if result.err != nil {
|
||||||
default:
|
return nil, result.err
|
||||||
ReadChannel(ctx, sensors, measuredValueChannel, errorChannel)
|
}
|
||||||
|
measuredValues = append(measuredValues, result.measuredValues...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return types.SelectMeasuredValues(measuredValueType, measuredValues), nil
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ type Sensor struct {
|
|||||||
SensorModel SensorModel `json:"sensor_model" xml:"sensor_model"`
|
SensorModel SensorModel `json:"sensor_model" xml:"sensor_model"`
|
||||||
SensorEnabled bool `json:"sensor_enabled" xml:"sensor_enabled"`
|
SensorEnabled bool `json:"sensor_enabled" xml:"sensor_enabled"`
|
||||||
SensorLastContact *time.Time `json:"sensor_last_contact" xml:"sensor_last_contact"`
|
SensorLastContact *time.Time `json:"sensor_last_contact" xml:"sensor_last_contact"`
|
||||||
|
TickDuration string `json:"sensor_tick_duration" xml:"sensor_tick_duration"`
|
||||||
DeviceID string `json:"device_id" xml:"device_id"`
|
DeviceID string `json:"device_id" xml:"device_id"`
|
||||||
CreationDate time.Time `json:"creation_date" xml:"creation_date"`
|
CreationDate time.Time `json:"creation_date" xml:"creation_date"`
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user