From bea49c78a90f2f5db2b639414f9820a00bf3982b Mon Sep 17 00:00:00 2001 From: William Petit Date: Fri, 20 Sep 2024 10:12:05 +0200 Subject: [PATCH] feat: use /configuration/device and replice reachview system to define antenna height See https://forge.cadoles.com/Pyxis/fieldnotes/issues/63#issuecomment-114255 --- reach/client/operations.go | 15 ++++++ reach/client/protocol/operations.go | 10 ++++ reach/client/protocol/testsuite/operations.go | 29 ++++++++++-- reach/client/protocol/v1/operations.go | 46 +++++++++++++++++++ reach/client/protocol/v2/internal.go | 10 ++++ .../client/protocol/v2/model/configuration.go | 10 +--- reach/client/protocol/v2/model/device.go | 11 +++++ reach/client/protocol/v2/operations.go | 34 ++++++++++++-- 8 files changed, 149 insertions(+), 16 deletions(-) create mode 100644 reach/client/protocol/v2/model/device.go diff --git a/reach/client/operations.go b/reach/client/operations.go index 0ef77a9..d446bd8 100644 --- a/reach/client/operations.go +++ b/reach/client/operations.go @@ -123,6 +123,21 @@ func (c *Client) SetBase(ctx context.Context, funcs ...protocol.SetBaseOptionFun return nil } +// GetBaseInfo implements protocol.Operations. +func (c *Client) GetBaseInfo(ctx context.Context) (*protocol.BaseInfo, error) { + _, ops, err := c.getProtocol(ctx) + if err != nil { + return nil, errors.WithStack(err) + } + + baseInfo, err := ops.GetBaseInfo(ctx) + if err != nil { + return nil, errors.WithStack(err) + } + + return baseInfo, nil +} + // Reboot implements protocol.Operations. func (c *Client) Reboot(ctx context.Context) error { _, ops, err := c.getProtocol(ctx) diff --git a/reach/client/protocol/operations.go b/reach/client/protocol/operations.go index dfcc4e0..72a5bae 100644 --- a/reach/client/protocol/operations.go +++ b/reach/client/protocol/operations.go @@ -2,6 +2,14 @@ package protocol import "context" +type BaseInfo struct { + Mode string + AntennaOffset float64 + Latitude float64 + Longitude float64 + Height float64 +} + type Operations interface { // Connect initiates a new connection to the ReachView service // It should be called before any other operation @@ -29,6 +37,8 @@ type Operations interface { // SetBase updates the base configuration SetBase(ctx context.Context, funcs ...SetBaseOptionFunc) error + GetBaseInfo(ctx context.Context) (*BaseInfo, error) + // Reboot restarts the module Reboot(ctx context.Context) error } diff --git a/reach/client/protocol/testsuite/operations.go b/reach/client/protocol/testsuite/operations.go index 61ac17f..9e66d75 100644 --- a/reach/client/protocol/testsuite/operations.go +++ b/reach/client/protocol/testsuite/operations.go @@ -2,6 +2,7 @@ package testsuite import ( "context" + "math" "math/rand" "os" "strconv" @@ -156,7 +157,7 @@ var testCases = []operationTestCase{ latitude := -90 + rand.Float64()*180 longitude := -180 + rand.Float64()*360 height := rand.Float64() * 1000 - antennaOffset := rand.Float64() * 2 + antennaOffset := toFixed(rand.Float64()*2, 3) opts := []protocol.SetBaseOptionFunc{ protocol.WithBaseLatitude(latitude), @@ -173,13 +174,29 @@ var testCases = []operationTestCase{ return } - config, err := ops.Configuration(ctx) + baseInfo, err := ops.GetBaseInfo(ctx) if err != nil { t.Errorf("%+v", errors.WithStack(err)) return } - t.Logf("updated configuration: %v", spew.Sdump(config)) + t.Logf("base info: %v", spew.Sdump(baseInfo)) + + if e, g := latitude, baseInfo.Latitude; e != g { + t.Errorf("baseInfo.Latitude: expected '%v', got '%v'", e, g) + } + + if e, g := longitude, baseInfo.Longitude; e != g { + t.Errorf("baseInfo.Longitude: expected '%v', got '%v'", e, g) + } + + if e, g := height, baseInfo.Height; e != g { + t.Errorf("baseInfo.Height: expected '%v', got '%v'", e, g) + } + + if e, g := antennaOffset, baseInfo.AntennaOffset; e != g { + t.Errorf("baseInfo.AntennaOffset: expected '%v', got '%v'", e, g) + } }, }, @@ -247,3 +264,9 @@ func TestOperations(t *testing.T, opsFactory OperationsFactoryFunc) { }) } } + +func toFixed(n float64, precision int) float64 { + scale := math.Pow(10, float64(precision)) + + return math.Round(n*scale) / scale +} diff --git a/reach/client/protocol/v1/operations.go b/reach/client/protocol/v1/operations.go index 2e3689e..6c1ea16 100644 --- a/reach/client/protocol/v1/operations.go +++ b/reach/client/protocol/v1/operations.go @@ -297,6 +297,52 @@ func (o *Operations) SetBase(ctx context.Context, funcs ...protocol.SetBaseOptio return nil } +// GetBaseInfo implements protocol.Operations. +func (o *Operations) GetBaseInfo(ctx context.Context) (*protocol.BaseInfo, error) { + rawConfig, err := o.Configuration(ctx) + if err != nil { + return nil, errors.WithStack(err) + } + + config := rawConfig.(*model.Configuration) + baseMode := config.BaseMode + + var baseCoordinates *model.BaseCoordinates + if baseMode != nil && baseMode.BaseCoordinates != nil { + baseCoordinates = baseMode.BaseCoordinates + } + + antennaOffset, err := strconv.ParseFloat(*baseCoordinates.AntennaOffset.Up, 64) + if err != nil { + return nil, errors.WithStack(err) + } + + latitude, err := strconv.ParseFloat(*baseCoordinates.Coordinates[0], 64) + if err != nil { + return nil, errors.WithStack(err) + } + + longitude, err := strconv.ParseFloat(*baseCoordinates.Coordinates[1], 64) + if err != nil { + return nil, errors.WithStack(err) + } + + height, err := strconv.ParseFloat(*baseCoordinates.Coordinates[2], 64) + if err != nil { + return nil, errors.WithStack(err) + } + + baseInfo := &protocol.BaseInfo{ + Mode: *config.BaseMode.BaseCoordinates.Mode, + AntennaOffset: antennaOffset, + Height: height, + Latitude: latitude, + Longitude: longitude, + } + + return baseInfo, nil +} + const ( eventGetReachViewVersion = "get reachview version" eventReachViewVersionResults = "current reachview version" diff --git a/reach/client/protocol/v2/internal.go b/reach/client/protocol/v2/internal.go index 8367bb3..4a3aa4e 100644 --- a/reach/client/protocol/v2/internal.go +++ b/reach/client/protocol/v2/internal.go @@ -116,6 +116,16 @@ func (o *Operations) PostBaseCoordinates(ctx context.Context, base *model.Base) return &updated, nil } +func (o *Operations) PostDevice(ctx context.Context, device *model.ConfigurationDevice) (*model.ConfigurationDevice, error) { + var updated model.ConfigurationDevice + + if err := o.PostJSON("/configuration/device", device, &updated); err != nil { + return nil, errors.WithStack(err) + } + + return &updated, nil +} + func (o *Operations) GetUpdater(ctx context.Context) (*model.Updater, error) { updater := &model.Updater{} if err := o.GetJSON("/updater", updater); err != nil { diff --git a/reach/client/protocol/v2/model/configuration.go b/reach/client/protocol/v2/model/configuration.go index 93a3e51..f324bc5 100644 --- a/reach/client/protocol/v2/model/configuration.go +++ b/reach/client/protocol/v2/model/configuration.go @@ -148,15 +148,7 @@ type Configuration struct { } `json:"settings,omitempty"` } `json:"base_corrections,omitempty"` } `json:"correction_input,omitempty"` - Device struct { - AntennaHeight float64 `json:"antenna_height,omitempty"` - NightMode bool `json:"night_mode,omitempty"` - OnboardingShown bool `json:"onboarding_shown,omitempty"` - PowerOnBottomConnector bool `json:"power_on_bottom_connector,omitempty"` - PrivacyPolicyAccepted bool `json:"privacy_policy_accepted,omitempty"` - Role string `json:"role,omitempty"` - UsageAnalysisAccepted bool `json:"usage_analysis_accepted,omitempty"` - } `json:"device,omitempty"` + Device ConfigurationDevice `json:"device,omitempty"` Logging struct { Logs struct { Autostart bool `json:"autostart,omitempty"` diff --git a/reach/client/protocol/v2/model/device.go b/reach/client/protocol/v2/model/device.go new file mode 100644 index 0000000..6d551e4 --- /dev/null +++ b/reach/client/protocol/v2/model/device.go @@ -0,0 +1,11 @@ +package model + +type ConfigurationDevice struct { + AntennaHeight float64 `json:"antenna_height,omitempty"` + NightMode bool `json:"night_mode,omitempty"` + OnboardingShown bool `json:"onboarding_shown,omitempty"` + PowerOnBottomConnector bool `json:"power_on_bottom_connector,omitempty"` + PrivacyPolicyAccepted bool `json:"privacy_policy_accepted,omitempty"` + Role string `json:"role,omitempty"` + UsageAnalysisAccepted bool `json:"usage_analysis_accepted,omitempty"` +} diff --git a/reach/client/protocol/v2/operations.go b/reach/client/protocol/v2/operations.go index 18ea4c5..7a8afb1 100644 --- a/reach/client/protocol/v2/operations.go +++ b/reach/client/protocol/v2/operations.go @@ -60,6 +60,8 @@ func (o *Operations) Reboot(ctx context.Context) error { return err } +const DeviceHeight = 0.134 + // SetBase implements protocol.Operations. func (o *Operations) SetBase(ctx context.Context, funcs ...protocol.SetBaseOptionFunc) error { config, err := o.GetConfiguration(ctx) @@ -96,17 +98,41 @@ func (o *Operations) SetBase(ctx context.Context, funcs ...protocol.SetBaseOptio base.Coordinates.Longitude = *opts.Longitude } - if opts.AntennaOffset != nil { - base.AntennaOffset = *opts.AntennaOffset - } - if _, err := o.PostBaseCoordinates(ctx, base); err != nil { return errors.WithStack(err) } + if opts.AntennaOffset != nil { + device := &model.ConfigurationDevice{ + AntennaHeight: *opts.AntennaOffset + DeviceHeight, + } + + if _, err := o.PostDevice(ctx, device); err != nil { + return errors.WithStack(err) + } + } + return nil } +// GetBaseInfo implements protocol.Operations. +func (o *Operations) GetBaseInfo(ctx context.Context) (*protocol.BaseInfo, error) { + config, err := o.GetConfiguration(ctx) + if err != nil { + return nil, errors.WithStack(err) + } + + baseInfo := &protocol.BaseInfo{ + Mode: config.BaseMode.BaseCoordinates.Mode, + AntennaOffset: config.BaseMode.BaseCoordinates.AntennaOffset - DeviceHeight, + Height: config.BaseMode.BaseCoordinates.Coordinates.Height, + Latitude: config.BaseMode.BaseCoordinates.Coordinates.Latitude, + Longitude: config.BaseMode.BaseCoordinates.Coordinates.Longitude, + } + + return baseInfo, nil +} + // Configuration implements protocol.Operations. func (o *Operations) Configuration(ctx context.Context) (any, error) { config, err := o.GetConfiguration(ctx)