refac(pkg/types): remove deprecated prefix name of struct attributes
This commit is contained in:
parent
95fb1f6745
commit
2cd2188dcb
@ -46,8 +46,8 @@ var rootCmd = &cobra.Command{
|
||||
// Default configuration
|
||||
cnf := config.Configuration{
|
||||
Device: &types.Device{
|
||||
DeviceID: uuid.NewV4().String(),
|
||||
DeviceName: hostname,
|
||||
ID: uuid.NewV4().String(),
|
||||
Name: hostname,
|
||||
CreationDate: t,
|
||||
},
|
||||
StorageEndpoint: "file:///var/log/flucky/logfile.csv",
|
||||
|
@ -38,10 +38,10 @@ flucky sensor add --i2c-bus 1 --i2c-address 0x76 wetter-station BME280`,
|
||||
|
||||
// create new sensor struct
|
||||
sensor := &types.Sensor{
|
||||
SensorName: args[0],
|
||||
SensorModel: sensorModel,
|
||||
SensorLocation: location,
|
||||
SensorEnabled: enabled,
|
||||
Name: args[0],
|
||||
Model: sensorModel,
|
||||
Location: location,
|
||||
Enabled: enabled,
|
||||
}
|
||||
|
||||
// determine gpio port if set
|
||||
|
@ -16,12 +16,12 @@ func GetSensorsByMeasuredValues(measuredValues []*types.MeasuredValue, cnf *conf
|
||||
duplicated := false
|
||||
foundSensor := &types.Sensor{}
|
||||
for _, cnfSensor := range cnf.Sensors {
|
||||
if measuredValue.SensorID == cnfSensor.SensorID {
|
||||
if measuredValue.ID == cnfSensor.ID {
|
||||
foundSensor = cnfSensor
|
||||
|
||||
// compare if id has already been added to list
|
||||
for _, sensor := range sensors {
|
||||
if cnfSensor.SensorID == sensor.SensorID {
|
||||
if cnfSensor.ID == sensor.ID {
|
||||
duplicated = true
|
||||
break
|
||||
}
|
||||
@ -35,7 +35,7 @@ func GetSensorsByMeasuredValues(measuredValues []*types.MeasuredValue, cnf *conf
|
||||
sensors = append(sensors, foundSensor)
|
||||
continue
|
||||
} else {
|
||||
sensors = append(sensors, &types.Sensor{SensorID: measuredValue.SensorID})
|
||||
sensors = append(sensors, &types.Sensor{ID: measuredValue.ID})
|
||||
}
|
||||
}
|
||||
return sensors
|
||||
@ -72,7 +72,7 @@ func PrintSensors(cnf *config.Configuration, w io.Writer) error {
|
||||
fmt.Fprint(tw, "name\tlocation\ttype\twire-id\ti2c-bus\ti2c-address\tgpio\tenabled\n")
|
||||
|
||||
for _, sensor := range cnf.Sensors {
|
||||
fmt.Fprintf(tw, "%v\t%v\t%v\t", sensor.SensorName, sensor.SensorLocation, sensor.SensorModel)
|
||||
fmt.Fprintf(tw, "%v\t%v\t%v\t", sensor.Name, sensor.Location, sensor.Model)
|
||||
|
||||
if sensor.WireID != nil {
|
||||
fmt.Fprintf(tw, "%v\t", *sensor.WireID)
|
||||
@ -98,7 +98,7 @@ func PrintSensors(cnf *config.Configuration, w io.Writer) error {
|
||||
fmt.Fprintf(tw, "\t")
|
||||
}
|
||||
|
||||
fmt.Fprintf(tw, "%v\n", sensor.SensorEnabled)
|
||||
fmt.Fprintf(tw, "%v\n", sensor.Enabled)
|
||||
}
|
||||
|
||||
tw.Flush()
|
||||
@ -114,7 +114,7 @@ func PrintMeasuredValues(measuredValues []*types.MeasuredValue, cnf *config.Conf
|
||||
// sort measured values for every sensor
|
||||
orderedMeasuredValues := make(map[string][]*types.MeasuredValue)
|
||||
for _, measuredValue := range measuredValues {
|
||||
orderedMeasuredValues[measuredValue.SensorID] = append(orderedMeasuredValues[measuredValue.SensorID], measuredValue)
|
||||
orderedMeasuredValues[measuredValue.ID] = append(orderedMeasuredValues[measuredValue.ID], measuredValue)
|
||||
}
|
||||
|
||||
// declare tabwriter
|
||||
@ -122,7 +122,7 @@ func PrintMeasuredValues(measuredValues []*types.MeasuredValue, cnf *config.Conf
|
||||
|
||||
// headlines
|
||||
for i, sensor := range sensors {
|
||||
fmt.Fprintf(tw, "%v\t", sensor.Name())
|
||||
fmt.Fprintf(tw, "%v\t", sensor.FullName())
|
||||
if i == len(sensors)-1 {
|
||||
fmt.Fprintf(tw, "\n")
|
||||
}
|
||||
@ -139,8 +139,8 @@ func PrintMeasuredValues(measuredValues []*types.MeasuredValue, cnf *config.Conf
|
||||
// body
|
||||
for i := 0; i < maxLength; i++ {
|
||||
for _, sensor := range sensors {
|
||||
if len(orderedMeasuredValues[sensor.SensorID]) > i {
|
||||
fmt.Fprintf(tw, "%3.3f\t", orderedMeasuredValues[sensor.SensorID][i].Value)
|
||||
if len(orderedMeasuredValues[sensor.ID]) > i {
|
||||
fmt.Fprintf(tw, "%3.3f\t", orderedMeasuredValues[sensor.ID][i].Value)
|
||||
} else {
|
||||
fmt.Fprint(tw, "\t")
|
||||
}
|
||||
|
@ -43,8 +43,8 @@ func (c *Configuration) AddRGBLED(rgbLED *types.RGBLED) error {
|
||||
}
|
||||
|
||||
// check if sensor has a valid device id
|
||||
if rgbLED.DeviceID != c.Device.DeviceID {
|
||||
rgbLED.DeviceID = c.Device.DeviceID
|
||||
if rgbLED.DeviceID != c.Device.ID {
|
||||
rgbLED.DeviceID = c.Device.ID
|
||||
}
|
||||
|
||||
// overwrite creation date
|
||||
@ -59,31 +59,31 @@ func (c *Configuration) AddRGBLED(rgbLED *types.RGBLED) error {
|
||||
// AddSensor add a new sensor
|
||||
func (c *Configuration) AddSensor(sensor *types.Sensor) error {
|
||||
|
||||
// check if sensorID is a valid UUID string
|
||||
if !validUUID.MatchString(sensor.SensorID) {
|
||||
sensor.SensorID = uuid.NewV4().String()
|
||||
// check if ID is a valid UUID string
|
||||
if !validUUID.MatchString(sensor.ID) {
|
||||
sensor.ID = uuid.NewV4().String()
|
||||
}
|
||||
|
||||
// check if sensor name and sensor uuid already exists
|
||||
for _, s := range c.Sensors {
|
||||
if s.SensorName == sensor.SensorName {
|
||||
return fmt.Errorf("Sensor %v already exists", s.SensorName)
|
||||
if s.Name == sensor.Name {
|
||||
return fmt.Errorf("Sensor %v already exists", s.Name)
|
||||
}
|
||||
|
||||
if s.SensorID == sensor.SensorID {
|
||||
return fmt.Errorf("Sensor %v with UUID %v already exists", s.SensorName, s.SensorID)
|
||||
if s.ID == sensor.ID {
|
||||
return fmt.Errorf("Sensor %v with UUID %v already exists", s.Name, s.ID)
|
||||
}
|
||||
|
||||
if s.WireID != nil && sensor.WireID != nil {
|
||||
if *s.WireID == *sensor.WireID {
|
||||
return fmt.Errorf("Sensor with 1wire-id %v already exists as %v", *s.WireID, s.SensorName)
|
||||
return fmt.Errorf("Sensor with 1wire-id %v already exists as %v", *s.WireID, s.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if sensor has a valid device id
|
||||
if sensor.DeviceID != c.Device.DeviceID {
|
||||
sensor.DeviceID = c.Device.DeviceID
|
||||
if sensor.ID != c.Device.ID {
|
||||
sensor.ID = c.Device.ID
|
||||
}
|
||||
|
||||
// overwrite creation date
|
||||
@ -135,16 +135,16 @@ func (c *Configuration) DisableSensor(name string) error {
|
||||
|
||||
// disable sensor matched after name
|
||||
if !validUUID.MatchString(name) &&
|
||||
sensor.SensorName == name {
|
||||
sensor.SensorEnabled = false
|
||||
sensor.Name == name {
|
||||
sensor.Enabled = false
|
||||
found = true
|
||||
break
|
||||
}
|
||||
|
||||
// remove machted uuid
|
||||
if validUUID.MatchString(name) &&
|
||||
sensor.SensorID == name {
|
||||
sensor.SensorEnabled = false
|
||||
sensor.ID == name {
|
||||
sensor.Enabled = false
|
||||
found = true
|
||||
break
|
||||
}
|
||||
@ -195,16 +195,16 @@ func (c *Configuration) EnableSensor(name string) error {
|
||||
|
||||
// disable sensor matched after name
|
||||
if !validUUID.MatchString(name) &&
|
||||
sensor.SensorName == name {
|
||||
sensor.SensorEnabled = true
|
||||
sensor.Name == name {
|
||||
sensor.Enabled = true
|
||||
found = true
|
||||
break
|
||||
}
|
||||
|
||||
// remove machted uuid
|
||||
if validUUID.MatchString(name) &&
|
||||
sensor.SensorID == name {
|
||||
sensor.SensorEnabled = true
|
||||
sensor.ID == name {
|
||||
sensor.Enabled = true
|
||||
found = true
|
||||
break
|
||||
}
|
||||
@ -226,14 +226,14 @@ func (c *Configuration) GetHumiditySensors(option Option) []sensor.Sensor {
|
||||
switch option {
|
||||
case ENABLED:
|
||||
for _, sensor := range sensors {
|
||||
if sensor.SensorEnabled {
|
||||
if sensor.Enabled {
|
||||
cachedSensors = append(cachedSensors, sensor)
|
||||
}
|
||||
}
|
||||
return c.convertSensors(cachedSensors)
|
||||
case DISABLED:
|
||||
for _, sensor := range sensors {
|
||||
if !sensor.SensorEnabled {
|
||||
if !sensor.Enabled {
|
||||
cachedSensors = append(cachedSensors, sensor)
|
||||
}
|
||||
}
|
||||
@ -251,10 +251,10 @@ func (c *Configuration) GetHumiditySensorsByName(names []string) []sensor.Sensor
|
||||
for _, name := range names {
|
||||
for _, s := range c.getHumiditySensors() {
|
||||
switch name {
|
||||
case s.SensorID:
|
||||
configHumiditySensors[s.SensorID] = s
|
||||
case s.SensorName:
|
||||
configHumiditySensors[s.SensorID] = s
|
||||
case s.ID:
|
||||
configHumiditySensors[s.ID] = s
|
||||
case s.Name:
|
||||
configHumiditySensors[s.ID] = s
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -276,14 +276,14 @@ func (c *Configuration) GetPressureSensors(option Option) []sensor.Sensor {
|
||||
switch option {
|
||||
case ENABLED:
|
||||
for _, sensor := range sensors {
|
||||
if sensor.SensorEnabled {
|
||||
if sensor.Enabled {
|
||||
cachedSensors = append(cachedSensors, sensor)
|
||||
}
|
||||
}
|
||||
return c.convertSensors(cachedSensors)
|
||||
case DISABLED:
|
||||
for _, sensor := range sensors {
|
||||
if !sensor.SensorEnabled {
|
||||
if !sensor.Enabled {
|
||||
cachedSensors = append(cachedSensors, sensor)
|
||||
}
|
||||
}
|
||||
@ -301,10 +301,10 @@ func (c *Configuration) GetPressureSensorsByName(names []string) []sensor.Sensor
|
||||
for _, name := range names {
|
||||
for _, s := range c.getPressureSensors() {
|
||||
switch name {
|
||||
case s.SensorID:
|
||||
configPressureSensors[s.SensorID] = s
|
||||
case s.SensorName:
|
||||
configPressureSensors[s.SensorID] = s
|
||||
case s.ID:
|
||||
configPressureSensors[s.ID] = s
|
||||
case s.Name:
|
||||
configPressureSensors[s.ID] = s
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -369,14 +369,14 @@ func (c *Configuration) GetSensors(option Option) []sensor.Sensor {
|
||||
switch option {
|
||||
case ENABLED:
|
||||
for _, sensor := range c.Sensors {
|
||||
if sensor.SensorEnabled {
|
||||
if sensor.Enabled {
|
||||
cachedSensors = append(cachedSensors, sensor)
|
||||
}
|
||||
}
|
||||
return c.convertSensors(cachedSensors)
|
||||
case DISABLED:
|
||||
for _, sensor := range c.Sensors {
|
||||
if !sensor.SensorEnabled {
|
||||
if !sensor.Enabled {
|
||||
cachedSensors = append(cachedSensors, sensor)
|
||||
}
|
||||
}
|
||||
@ -404,14 +404,14 @@ func (c *Configuration) GetTemperatureSensors(option Option) []sensor.Sensor {
|
||||
switch option {
|
||||
case ENABLED:
|
||||
for _, sensor := range sensors {
|
||||
if sensor.SensorEnabled {
|
||||
if sensor.Enabled {
|
||||
cachedSensors = append(cachedSensors, sensor)
|
||||
}
|
||||
}
|
||||
return c.convertSensors(cachedSensors)
|
||||
case DISABLED:
|
||||
for _, sensor := range sensors {
|
||||
if !sensor.SensorEnabled {
|
||||
if !sensor.Enabled {
|
||||
cachedSensors = append(cachedSensors, sensor)
|
||||
}
|
||||
}
|
||||
@ -429,10 +429,10 @@ func (c *Configuration) GetTemperatureSensorsByName(names []string) []sensor.Sen
|
||||
for _, name := range names {
|
||||
for _, s := range c.getTemperatureSensors() {
|
||||
switch name {
|
||||
case s.SensorID:
|
||||
configTemperatureSensors[s.SensorID] = s
|
||||
case s.SensorName:
|
||||
configTemperatureSensors[s.SensorID] = s
|
||||
case s.ID:
|
||||
configTemperatureSensors[s.ID] = s
|
||||
case s.Name:
|
||||
configTemperatureSensors[s.ID] = s
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -469,13 +469,13 @@ func (c *Configuration) RemoveSensor(name string) error {
|
||||
for i, sensor := range c.Sensors {
|
||||
// remove machted name
|
||||
if !validUUID.MatchString(name) &&
|
||||
sensor.SensorName == name {
|
||||
sensor.Name == name {
|
||||
c.Sensors = append(c.Sensors[:i], c.Sensors[i+1:]...)
|
||||
return nil
|
||||
}
|
||||
// remove machted uuid
|
||||
if validUUID.MatchString(name) &&
|
||||
sensor.SensorID == name {
|
||||
sensor.ID == name {
|
||||
c.Sensors = append(c.Sensors[:i], c.Sensors[i+1:]...)
|
||||
return nil
|
||||
}
|
||||
@ -498,9 +498,9 @@ func (c *Configuration) RenameRGBLED(oldName, newName string) error {
|
||||
// RenameSensor renames a sensor identified by the name or the UUID
|
||||
func (c *Configuration) RenameSensor(oldName, newName string) error {
|
||||
for _, sensor := range c.Sensors {
|
||||
if sensor.SensorName == oldName ||
|
||||
sensor.SensorID == oldName {
|
||||
sensor.SensorName = newName
|
||||
if sensor.Name == oldName ||
|
||||
sensor.ID == oldName {
|
||||
sensor.Name = newName
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@ -535,7 +535,7 @@ func (c *Configuration) convertSensors(sensors []*types.Sensor) []sensor.Sensor
|
||||
cachedSensors := make([]sensor.Sensor, 0)
|
||||
|
||||
for _, s := range sensors {
|
||||
switch s.SensorModel {
|
||||
switch s.Model {
|
||||
case types.BME280:
|
||||
cachedSensors = append(cachedSensors, &sensor.BME280{
|
||||
Sensor: s,
|
||||
@ -572,7 +572,7 @@ func (c *Configuration) convertRGBLEDs(rgbLEDs []*types.RGBLED) []rgbled.RGBLED
|
||||
func (c *Configuration) getHumiditySensors() []*types.Sensor {
|
||||
humiditySensors := make([]*types.Sensor, 0)
|
||||
for _, s := range c.Sensors {
|
||||
if _, ok := humiditySensorModels[s.SensorModel]; ok {
|
||||
if _, ok := humiditySensorModels[s.Model]; ok {
|
||||
humiditySensors = append(humiditySensors, s)
|
||||
}
|
||||
}
|
||||
@ -582,7 +582,7 @@ func (c *Configuration) getHumiditySensors() []*types.Sensor {
|
||||
func (c *Configuration) getPressureSensors() []*types.Sensor {
|
||||
pressureSensors := make([]*types.Sensor, 0)
|
||||
for _, s := range c.Sensors {
|
||||
if _, ok := pressureSensorModels[s.SensorModel]; ok {
|
||||
if _, ok := pressureSensorModels[s.Model]; ok {
|
||||
pressureSensors = append(pressureSensors, s)
|
||||
}
|
||||
}
|
||||
@ -592,7 +592,7 @@ func (c *Configuration) getPressureSensors() []*types.Sensor {
|
||||
func (c *Configuration) getTemperatureSensors() []*types.Sensor {
|
||||
temperatureSensors := make([]*types.Sensor, 0)
|
||||
for _, s := range c.Sensors {
|
||||
if _, ok := temperatureSensorModels[s.SensorModel]; ok {
|
||||
if _, ok := temperatureSensorModels[s.Model]; ok {
|
||||
temperatureSensors = append(temperatureSensors, s)
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compress
|
||||
// Init semaphoreChannel
|
||||
semaphoreChannels := make(map[string]chan struct{})
|
||||
for _, sensor := range cnf.GetSensors(config.ENABLED) {
|
||||
semaphoreChannels[sensor.ID()] = make(chan struct{}, 1)
|
||||
semaphoreChannels[sensor.GetID()] = make(chan struct{}, 1)
|
||||
}
|
||||
|
||||
// Start producers
|
||||
@ -77,7 +77,7 @@ func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compress
|
||||
case <-ctx.Done():
|
||||
errorChannel <- fmt.Errorf("Closed context: %v", ctx.Err().Error())
|
||||
return
|
||||
case <-semaphoreChannels[sensor.ID()]:
|
||||
case <-semaphoreChannels[sensor.GetID()]:
|
||||
measuredValues, err := sensor.Read()
|
||||
if err != nil {
|
||||
errorChannel <- err
|
||||
@ -97,8 +97,8 @@ func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compress
|
||||
case <-ctx.Done():
|
||||
errorChannel <- fmt.Errorf("Closed context: %v", ctx.Err().Error())
|
||||
return
|
||||
case <-sensor.Ticker().C:
|
||||
semaphoreChannels[sensor.ID()] <- struct{}{}
|
||||
case <-sensor.GetTicker().C:
|
||||
semaphoreChannels[sensor.GetID()] <- struct{}{}
|
||||
}
|
||||
}
|
||||
}(s)
|
||||
@ -158,7 +158,7 @@ func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compress
|
||||
}
|
||||
|
||||
func checkDeviceInDatabase(ctx context.Context, device *types.Device, database db.Database) {
|
||||
_, err := database.SelectDeviceByID(ctx, device.DeviceID)
|
||||
_, err := database.SelectDeviceByID(ctx, device.ID)
|
||||
if err != nil {
|
||||
flogger.Debug("It's seems the current device is not registered in the database. Register the device now")
|
||||
err2 := database.InsertDevices(ctx, []*types.Device{device})
|
||||
@ -173,16 +173,16 @@ func checkDeviceInDatabase(ctx context.Context, device *types.Device, database d
|
||||
|
||||
func checkSensorsInDatabase(ctx context.Context, sensors []*types.Sensor, database db.Database) {
|
||||
for _, sensor := range sensors {
|
||||
_, err := database.SelectSensorByID(ctx, sensor.SensorID)
|
||||
_, err := database.SelectSensorByID(ctx, sensor.ID)
|
||||
if err != nil {
|
||||
flogger.Debug("It's seems the sensor %v is not registered in the database. Register the sensor now", sensor.SensorName)
|
||||
flogger.Debug("It's seems the sensor %v is not registered in the database. Register the sensor now", sensor.Name)
|
||||
err2 := database.InsertSensors(ctx, []*types.Sensor{sensor})
|
||||
if err2 != nil {
|
||||
flogger.Fatal("Can not register sensor %v into database: %v", sensor.SensorName, err2)
|
||||
flogger.Fatal("Can not register sensor %v into database: %v", sensor.Name, err2)
|
||||
}
|
||||
flogger.Debug("Sensor %v successfully registered into the database", sensor.SensorName)
|
||||
flogger.Debug("Sensor %v successfully registered into the database", sensor.Name)
|
||||
continue
|
||||
}
|
||||
flogger.Debug("Sensor %v is already registered into the database", sensor.SensorName)
|
||||
flogger.Debug("Sensor %v is already registered into the database", sensor.Name)
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
package sensor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/d2r2/go-bsbmp"
|
||||
@ -20,8 +17,18 @@ type BME280 struct {
|
||||
*types.Sensor
|
||||
}
|
||||
|
||||
func (s *BME280) ID() string {
|
||||
return s.SensorID
|
||||
// GetID returns the sensor id
|
||||
func (s *BME280) GetID() string {
|
||||
return s.ID
|
||||
}
|
||||
|
||||
// GetTicker returns a new ticker, which tick every when the sensor should be read
|
||||
func (s *BME280) GetTicker() *time.Ticker {
|
||||
duration, err := time.ParseDuration(s.TickDuration)
|
||||
if err != nil {
|
||||
duration = time.Minute
|
||||
}
|
||||
return time.NewTicker(duration)
|
||||
}
|
||||
|
||||
// Read measured values
|
||||
@ -69,7 +76,7 @@ func (s *BME280) Read() ([]*types.MeasuredValue, error) {
|
||||
ValueType: types.MeasuredValueTypeHumidity,
|
||||
FromDate: format.FormatedTime(),
|
||||
TillDate: format.FormatedTime(),
|
||||
SensorID: s.SensorID,
|
||||
SensorID: s.ID,
|
||||
},
|
||||
&types.MeasuredValue{
|
||||
ID: uuid.NewV4().String(),
|
||||
@ -77,7 +84,7 @@ func (s *BME280) Read() ([]*types.MeasuredValue, error) {
|
||||
ValueType: types.MeasuredValueTypePressure,
|
||||
FromDate: format.FormatedTime(),
|
||||
TillDate: format.FormatedTime(),
|
||||
SensorID: s.SensorID,
|
||||
SensorID: s.ID,
|
||||
},
|
||||
&types.MeasuredValue{
|
||||
ID: uuid.NewV4().String(),
|
||||
@ -85,51 +92,9 @@ func (s *BME280) Read() ([]*types.MeasuredValue, error) {
|
||||
ValueType: types.MeasuredValueTypeTemperature,
|
||||
FromDate: format.FormatedTime(),
|
||||
TillDate: format.FormatedTime(),
|
||||
SensorID: s.SensorID,
|
||||
SensorID: s.ID,
|
||||
},
|
||||
}
|
||||
|
||||
return measuredValues, nil
|
||||
}
|
||||
|
||||
// ReadChannel reads the measured values from the sensor and writes them to a
|
||||
// channel.
|
||||
func (s *BME280) ReadChannel(measuredValueChannel chan<- *types.MeasuredValue, errorChannel chan<- error, wg *sync.WaitGroup) {
|
||||
if wg != nil {
|
||||
defer wg.Done()
|
||||
}
|
||||
|
||||
measuredValues, err := s.Read()
|
||||
if err != nil {
|
||||
errorChannel <- err
|
||||
return
|
||||
}
|
||||
|
||||
for _, measuredValue := range measuredValues {
|
||||
measuredValueChannel <- measuredValue
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ReadContinously reads the measured values continously from the sensor and
|
||||
// writes them to a channel.
|
||||
func (s *BME280) ReadContinously(ctx context.Context, measuredValueChannel chan<- *types.MeasuredValue, errorChannel chan<- error) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
errorChannel <- fmt.Errorf("%v: Context closed: %v", s.SensorName, ctx.Err())
|
||||
return
|
||||
default:
|
||||
s.ReadChannel(measuredValueChannel, errorChannel, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
package sensor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-flucky/flucky/pkg/internal/format"
|
||||
@ -17,8 +15,18 @@ type DHT11 struct {
|
||||
*types.Sensor
|
||||
}
|
||||
|
||||
func (s *DHT11) ID() string {
|
||||
return s.SensorID
|
||||
// GetID returns the sensor id
|
||||
func (s *DHT11) GetID() string {
|
||||
return s.ID
|
||||
}
|
||||
|
||||
// GetTicker returns a new ticker, which tick every when the sensor should be read
|
||||
func (s *DHT11) GetTicker() *time.Ticker {
|
||||
duration, err := time.ParseDuration(s.TickDuration)
|
||||
if err != nil {
|
||||
duration = time.Minute
|
||||
}
|
||||
return time.NewTicker(duration)
|
||||
}
|
||||
|
||||
// Read measured values
|
||||
@ -51,7 +59,7 @@ func (s *DHT11) Read() ([]*types.MeasuredValue, error) {
|
||||
ValueType: types.MeasuredValueTypeHumidity,
|
||||
FromDate: format.FormatedTime(),
|
||||
TillDate: format.FormatedTime(),
|
||||
SensorID: s.SensorID,
|
||||
SensorID: s.ID,
|
||||
},
|
||||
&types.MeasuredValue{
|
||||
ID: uuid.NewV4().String(),
|
||||
@ -59,51 +67,9 @@ func (s *DHT11) Read() ([]*types.MeasuredValue, error) {
|
||||
ValueType: types.MeasuredValueTypeTemperature,
|
||||
FromDate: format.FormatedTime(),
|
||||
TillDate: format.FormatedTime(),
|
||||
SensorID: s.SensorID,
|
||||
SensorID: s.ID,
|
||||
},
|
||||
}
|
||||
|
||||
return measuredValues, nil
|
||||
}
|
||||
|
||||
// ReadChannel reads the measured values from the sensor and writes them to a
|
||||
// channel.
|
||||
func (s *DHT11) ReadChannel(measuredValueChannel chan<- *types.MeasuredValue, errorChannel chan<- error, wg *sync.WaitGroup) {
|
||||
if wg != nil {
|
||||
defer wg.Done()
|
||||
}
|
||||
|
||||
measuredValues, err := s.Read()
|
||||
if err != nil {
|
||||
errorChannel <- err
|
||||
return
|
||||
}
|
||||
|
||||
for _, measuredValue := range measuredValues {
|
||||
measuredValueChannel <- measuredValue
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ReadContinously reads the measured values continously from the sensor and
|
||||
// writes them to a channel.
|
||||
func (s *DHT11) ReadContinously(ctx context.Context, measuredValueChannel chan<- *types.MeasuredValue, errorChannel chan<- error) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
errorChannel <- fmt.Errorf("%v: Context closed: %v", s.SensorName, ctx.Err())
|
||||
return
|
||||
default:
|
||||
s.ReadChannel(measuredValueChannel, errorChannel, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
package sensor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-flucky/flucky/pkg/internal/format"
|
||||
@ -17,8 +15,18 @@ type DHT22 struct {
|
||||
*types.Sensor
|
||||
}
|
||||
|
||||
func (s *DHT22) ID() string {
|
||||
return s.SensorID
|
||||
// GetID returns the sensor id
|
||||
func (s *DHT22) GetID() string {
|
||||
return s.ID
|
||||
}
|
||||
|
||||
// GetTicker returns a new ticker, which tick every when the sensor should be read
|
||||
func (s *DHT22) GetTicker() *time.Ticker {
|
||||
duration, err := time.ParseDuration(s.TickDuration)
|
||||
if err != nil {
|
||||
duration = time.Minute
|
||||
}
|
||||
return time.NewTicker(duration)
|
||||
}
|
||||
|
||||
// Read measured values
|
||||
@ -51,7 +59,7 @@ func (s *DHT22) Read() ([]*types.MeasuredValue, error) {
|
||||
ValueType: types.MeasuredValueTypeHumidity,
|
||||
FromDate: format.FormatedTime(),
|
||||
TillDate: format.FormatedTime(),
|
||||
SensorID: s.SensorID,
|
||||
SensorID: s.ID,
|
||||
},
|
||||
&types.MeasuredValue{
|
||||
ID: uuid.NewV4().String(),
|
||||
@ -59,51 +67,9 @@ func (s *DHT22) Read() ([]*types.MeasuredValue, error) {
|
||||
ValueType: types.MeasuredValueTypeTemperature,
|
||||
FromDate: format.FormatedTime(),
|
||||
TillDate: format.FormatedTime(),
|
||||
SensorID: s.SensorID,
|
||||
SensorID: s.ID,
|
||||
},
|
||||
}
|
||||
|
||||
return measuredValues, nil
|
||||
}
|
||||
|
||||
// ReadChannel reads the measured values from the sensor and writes them to a
|
||||
// channel.
|
||||
func (s *DHT22) ReadChannel(measuredValueChannel chan<- *types.MeasuredValue, errorChannel chan<- error, wg *sync.WaitGroup) {
|
||||
if wg != nil {
|
||||
defer wg.Done()
|
||||
}
|
||||
|
||||
measuredValues, err := s.Read()
|
||||
if err != nil {
|
||||
errorChannel <- err
|
||||
return
|
||||
}
|
||||
|
||||
for _, measuredValue := range measuredValues {
|
||||
measuredValueChannel <- measuredValue
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ReadContinously reads the measured values continously from the sensor and
|
||||
// writes them to a channel.
|
||||
func (s *DHT22) ReadContinously(ctx context.Context, measuredValueChannel chan<- *types.MeasuredValue, errorChannel chan<- error) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
errorChannel <- fmt.Errorf("%v: Context closed: %v", s.SensorName, ctx.Err())
|
||||
return
|
||||
default:
|
||||
s.ReadChannel(measuredValueChannel, errorChannel, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
@ -1,13 +1,11 @@
|
||||
package sensor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-flucky/flucky/pkg/internal/format"
|
||||
@ -20,20 +18,30 @@ type DS18B20 struct {
|
||||
*types.Sensor
|
||||
}
|
||||
|
||||
func (s *DS18B20) ID() string {
|
||||
return s.SensorID
|
||||
// GetID returns the sensor id
|
||||
func (s *DS18B20) GetID() string {
|
||||
return s.ID
|
||||
}
|
||||
|
||||
// GetTicker returns a new ticker, which tick every when the sensor should be read
|
||||
func (s *DS18B20) GetTicker() *time.Ticker {
|
||||
duration, err := time.ParseDuration(s.TickDuration)
|
||||
if err != nil {
|
||||
duration = time.Minute
|
||||
}
|
||||
return time.NewTicker(duration)
|
||||
}
|
||||
|
||||
// Read measured values
|
||||
func (s *DS18B20) Read() ([]*types.MeasuredValue, error) {
|
||||
|
||||
if s.WireID == nil {
|
||||
return nil, fmt.Errorf("WireID is not specified for sensor %v", s.Name())
|
||||
return nil, fmt.Errorf("WireID is not specified for sensor %v", s.Name)
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(filepath.Join("/sys/bus/w1/devices", *s.WireID, "/w1_slave"))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Can not read data from sensor %v", s.SensorName)
|
||||
return nil, fmt.Errorf("Can not read data from sensor %v", s.Name)
|
||||
}
|
||||
|
||||
raw := string(data)
|
||||
@ -57,52 +65,9 @@ func (s *DS18B20) Read() ([]*types.MeasuredValue, error) {
|
||||
ValueType: types.MeasuredValueTypeTemperature,
|
||||
FromDate: format.FormatedTime(),
|
||||
TillDate: format.FormatedTime(),
|
||||
SensorID: s.SensorID,
|
||||
SensorID: s.ID,
|
||||
},
|
||||
}
|
||||
|
||||
return measuredValues, nil
|
||||
|
||||
}
|
||||
|
||||
// ReadChannel reads the measured values from the sensor and writes them to a
|
||||
// channel.
|
||||
func (s *DS18B20) ReadChannel(measuredValueChannel chan<- *types.MeasuredValue, errorChannel chan<- error, wg *sync.WaitGroup) {
|
||||
if wg != nil {
|
||||
defer wg.Done()
|
||||
}
|
||||
|
||||
measuredValues, err := s.Read()
|
||||
if err != nil {
|
||||
errorChannel <- err
|
||||
return
|
||||
}
|
||||
|
||||
for _, measuredValue := range measuredValues {
|
||||
measuredValueChannel <- measuredValue
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ReadContinously reads the measured values continously from the sensor and
|
||||
// writes them to a channel.
|
||||
func (s *DS18B20) ReadContinously(ctx context.Context, measuredValueChannel chan<- *types.MeasuredValue, errorChannel chan<- error) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
errorChannel <- fmt.Errorf("%v: Context closed: %v", s.SensorName, ctx.Err())
|
||||
return
|
||||
default:
|
||||
s.ReadChannel(measuredValueChannel, errorChannel, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
type Sensor interface {
|
||||
ID() string
|
||||
GetID() string
|
||||
GetTicker() *time.Ticker
|
||||
Read() ([]*types.MeasuredValue, error)
|
||||
Ticker() *time.Ticker
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ func (p *Postgres) DeleteDevices(ctx context.Context, devices []*types.Device) e
|
||||
defer stmt.Close()
|
||||
|
||||
for _, device := range devices {
|
||||
_, err := stmt.ExecContext(ctx, &device.DeviceID)
|
||||
_, err := stmt.ExecContext(ctx, &device.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v: %v", errorStatementExecute, err)
|
||||
}
|
||||
@ -143,7 +143,7 @@ func (p *Postgres) DeleteSensors(ctx context.Context, sensors []*types.Sensor) e
|
||||
defer stmt.Close()
|
||||
|
||||
for _, sensor := range sensors {
|
||||
_, err := stmt.ExecContext(ctx, &sensor.SensorID)
|
||||
_, err := stmt.ExecContext(ctx, &sensor.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v: %v", errorStatementExecute, err)
|
||||
}
|
||||
@ -238,7 +238,7 @@ func (p *Postgres) InsertDevices(ctx context.Context, devices []*types.Device) e
|
||||
defer stmt.Close()
|
||||
|
||||
for _, device := range devices {
|
||||
_, err := stmt.ExecContext(ctx, &device.DeviceID, &device.DeviceName, &device.DeviceLocation, &device.CreationDate)
|
||||
_, err := stmt.ExecContext(ctx, &device.ID, &device.Name, &device.Location, &device.CreationDate)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v: %v", errorStatementExecute, err)
|
||||
}
|
||||
@ -407,7 +407,7 @@ func (p *Postgres) InsertSensors(ctx context.Context, sensors []*types.Sensor) e
|
||||
|
||||
for _, sensor := range sensors {
|
||||
|
||||
_, err := stmt.ExecContext(ctx, &sensor.SensorID, &sensor.SensorName, &sensor.SensorLocation, &sensor.WireID, &sensor.I2CBus, &sensor.I2CAddress, &sensor.GPIONumber, &sensor.SensorModel, &sensor.SensorEnabled, &sensor.DeviceID, &sensor.CreationDate)
|
||||
_, err := stmt.ExecContext(ctx, &sensor.ID, &sensor.Name, &sensor.Location, &sensor.WireID, &sensor.I2CBus, &sensor.I2CAddress, &sensor.GPIONumber, &sensor.Model, &sensor.Enabled, &sensor.DeviceID, &sensor.CreationDate)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v: %v", errorStatementExecute, err)
|
||||
}
|
||||
@ -435,7 +435,7 @@ func (p *Postgres) SelectDeviceByID(ctx context.Context, id string) (*types.Devi
|
||||
}
|
||||
|
||||
device := new(types.Device)
|
||||
err = row.Scan(&device.DeviceID, &device.DeviceName, &device.DeviceLocation, &device.CreationDate)
|
||||
err = row.Scan(&device.ID, &device.Name, &device.Location, &device.CreationDate)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v: %v", errorScanRow, err)
|
||||
}
|
||||
@ -580,7 +580,7 @@ func (p *Postgres) SelectSensorByID(ctx context.Context, id string) (*types.Sens
|
||||
}
|
||||
|
||||
sensor := new(types.Sensor)
|
||||
err = row.Scan(&sensor.SensorID, &sensor.SensorName, &sensor.SensorLocation, &sensor.WireID, &sensor.I2CBus, &sensor.I2CAddress, &sensor.GPIONumber, &sensor.SensorModel, &sensor.SensorEnabled, &sensor.DeviceID, &sensor.CreationDate)
|
||||
err = row.Scan(&sensor.ID, &sensor.Name, &sensor.Location, &sensor.WireID, &sensor.I2CBus, &sensor.I2CAddress, &sensor.GPIONumber, &sensor.Model, &sensor.Enabled, &sensor.DeviceID, &sensor.CreationDate)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v: %v", errorScanRow, err)
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ func testInsertDevices(t *testing.T) {
|
||||
err := database.InsertDevices(ctx, goldenDevices)
|
||||
require.NoError(err)
|
||||
for _, goldenDevice := range goldenDevices {
|
||||
testDevice, err := database.SelectDeviceByID(ctx, goldenDevice.DeviceID)
|
||||
testDevice, err := database.SelectDeviceByID(ctx, goldenDevice.ID)
|
||||
require.NoError(err)
|
||||
goldenfiles.CompareMeasuredValues(t, goldenDevice, testDevice)
|
||||
}
|
||||
@ -175,7 +175,7 @@ func testInsertSensors(t *testing.T) {
|
||||
err := database.InsertSensors(ctx, goldenSensors)
|
||||
require.NoError(err)
|
||||
for _, goldenSensor := range goldenSensors {
|
||||
testSensor, err := database.SelectSensorByID(ctx, goldenSensor.SensorID)
|
||||
testSensor, err := database.SelectSensorByID(ctx, goldenSensor.ID)
|
||||
require.NoError(err)
|
||||
goldenfiles.CompareMeasuredValues(t, goldenSensor, testSensor)
|
||||
}
|
||||
@ -235,7 +235,7 @@ func testDeleteDevices(t *testing.T) {
|
||||
err := database.DeleteDevices(ctx, goldenDevices)
|
||||
require.NoError(err)
|
||||
for _, goldenDevice := range goldenDevices {
|
||||
_, err := database.SelectDeviceByID(ctx, goldenDevice.DeviceID)
|
||||
_, err := database.SelectDeviceByID(ctx, goldenDevice.ID)
|
||||
require.Error(err)
|
||||
}
|
||||
}
|
||||
@ -246,7 +246,7 @@ func testDeleteSensors(t *testing.T) {
|
||||
err := database.DeleteSensors(ctx, goldenSensors)
|
||||
require.NoError(err)
|
||||
for _, goldenSensor := range goldenSensors {
|
||||
_, err := database.SelectDeviceByID(ctx, goldenSensor.SensorID)
|
||||
_, err := database.SelectDeviceByID(ctx, goldenSensor.ID)
|
||||
require.Error(err)
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,9 @@ import "time"
|
||||
|
||||
// Device ...
|
||||
type Device struct {
|
||||
DeviceID string `json:"device_id" xml:"device_id"`
|
||||
DeviceName string `json:"device_name" xml:"device_name"`
|
||||
DeviceLocation *string `json:"device_location" xml:"device_location"`
|
||||
DeviceLastContact *time.Time `json:"device_last_contact" xml:"device_last_contact"`
|
||||
CreationDate time.Time `json:"creation_date" xml:"creation_date"`
|
||||
ID string `json:"id" xml:"id"`
|
||||
Name string `json:"name" xml:"name"`
|
||||
Location *string `json:"location" xml:"location"`
|
||||
LastContact *time.Time `json:"last_contact" xml:"last_contact"`
|
||||
CreationDate time.Time `json:"creation_date" xml:"creation_date"`
|
||||
}
|
||||
|
@ -9,19 +9,19 @@ import (
|
||||
|
||||
// Sensor ...
|
||||
type Sensor struct {
|
||||
SensorID string `json:"sensor_id" xml:"sensor_id"`
|
||||
SensorName string `json:"sensor_name" xml:"sensor_name"`
|
||||
SensorLocation string `json:"sensor_location" xml:"sensor_location"`
|
||||
WireID *string `json:"wire_id" xml:"wire_id"`
|
||||
I2CBus *int `json:"i2c_bus" xml:"i2c_bus"`
|
||||
I2CAddress *uint8 `json:"i2c_address" xml:"i2c_address"`
|
||||
GPIONumber *GPIO `json:"gpio_number" xml:"gpio_number"`
|
||||
SensorModel SensorModel `json:"sensor_model" xml:"sensor_model"`
|
||||
SensorEnabled bool `json:"sensor_enabled" xml:"sensor_enabled"`
|
||||
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"`
|
||||
CreationDate time.Time `json:"creation_date" xml:"creation_date"`
|
||||
ID string `json:"id" xml:"id"`
|
||||
Name string `json:"name" xml:"name"`
|
||||
Location string `json:"location" xml:"location"`
|
||||
WireID *string `json:"wire_id" xml:"wire_id"`
|
||||
I2CBus *int `json:"i2c_bus" xml:"i2c_bus"`
|
||||
I2CAddress *uint8 `json:"i2c_address" xml:"i2c_address"`
|
||||
GPIONumber *GPIO `json:"gpio_number" xml:"gpio_number"`
|
||||
Model SensorModel `json:"model" xml:"model"`
|
||||
Enabled bool `json:"enabled" xml:"enabled"`
|
||||
LastContact *time.Time `json:"last_contact" xml:"last_contact"`
|
||||
TickDuration string `json:"tick_duration" xml:"tick_duration"`
|
||||
DeviceID string `json:"device_id" xml:"device_id"`
|
||||
CreationDate time.Time `json:"creation_date" xml:"creation_date"`
|
||||
}
|
||||
|
||||
// JSONDecoder decodes a json into a sensor
|
||||
@ -44,14 +44,14 @@ func (s *Sensor) JSONEncoder(w io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Sensor) Name() string {
|
||||
if s.SensorName != "" {
|
||||
return s.SensorName
|
||||
func (s *Sensor) FullName() string {
|
||||
if s.Name != "" {
|
||||
return s.Name
|
||||
} else if s.WireID != nil {
|
||||
return *s.WireID
|
||||
} else if s.I2CAddress != nil &&
|
||||
s.I2CBus != nil {
|
||||
return fmt.Sprintf("%v/%v", *s.I2CBus, *s.I2CAddress)
|
||||
}
|
||||
return s.SensorID
|
||||
return s.ID
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
[
|
||||
{
|
||||
"device_id": "19343609-c363-4992-ac97-124229ced640",
|
||||
"device_name": "poseidon",
|
||||
"device_location": null,
|
||||
"device_last_contact": null,
|
||||
"id": "19343609-c363-4992-ac97-124229ced640",
|
||||
"name": "poseidon",
|
||||
"location": null,
|
||||
"last_contact": null,
|
||||
"creation_date": "2019-09-29T18:14:35.203+02:00"
|
||||
}
|
||||
]
|
@ -1,15 +1,15 @@
|
||||
[
|
||||
{
|
||||
"sensor_id": "d7fc0e1f-9d5a-45c7-bc01-e85bd1b610c6",
|
||||
"sensor_name": "wetter-station",
|
||||
"sensor_location": "",
|
||||
"id": "d7fc0e1f-9d5a-45c7-bc01-e85bd1b610c6",
|
||||
"name": "wetter-station",
|
||||
"location": "",
|
||||
"wire_id": null,
|
||||
"i2c_bus": 1,
|
||||
"i2c_address": 118,
|
||||
"gpio_number": null,
|
||||
"sensor_model": "BME280",
|
||||
"sensor_enabled": true,
|
||||
"sensor_last_contact": null,
|
||||
"model": "BME280",
|
||||
"enabled": true,
|
||||
"last_contact": null,
|
||||
"device_id": "19343609-c363-4992-ac97-124229ced640",
|
||||
"creation_date": "2019-09-29T18:14:35.207+02:00"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user