From ba3d85f48b5aa6694cb7aad39fd81299266b592c Mon Sep 17 00:00:00 2001 From: William Petit Date: Thu, 20 Sep 2018 17:20:52 +0200 Subject: [PATCH 1/8] Create generic method to implements the request/response pattern --- go.mod | 1 + go.sum | 2 ++ reach/client.go | 29 +++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/go.mod b/go.mod index 08eb7a8..066ee89 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-chi/chi v3.3.3+incompatible github.com/gorilla/websocket v1.4.0 // indirect + github.com/mitchellh/mapstructure v1.0.0 github.com/pkg/errors v0.8.0 github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.2.2 // indirect diff --git a/go.sum b/go.sum index 4749ce9..eb81ba4 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,8 @@ github.com/go-chi/chi v3.3.3+incompatible h1:KHkmBEMNkwKuK4FdQL7N2wOeB9jnIx7jR5w github.com/go-chi/chi v3.3.3+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/mitchellh/mapstructure v1.0.0 h1:vVpGvMXJPqSDh2VYHF7gsfQj8Ncx+Xw5Y1KHeTRY+7I= +github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/reach/client.go b/reach/client.go index eef832f..742db25 100644 --- a/reach/client.go +++ b/reach/client.go @@ -5,6 +5,7 @@ import ( "forge.cadoles.com/Pyxis/golang-socketio" "forge.cadoles.com/Pyxis/golang-socketio/transport" + "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) @@ -72,6 +73,34 @@ func (c *client) Close() { c.conn = nil } +func (c *client) fetch(requestEvent string, requestData interface{}, responseEvent string, res interface{}) error { + + var err error + var wg sync.WaitGroup + + wg.Add(1) + + err = c.conn.On(responseEvent, func(_ *gosocketio.Channel, data interface{}) { + err = mapstructure.Decode(data, res) + c.conn.Off(responseEvent) + wg.Done() + }) + if err != nil { + return errors.Wrapf(err, "error while binding to '%s' event", responseEvent) + } + + c.logf("sending '%s' event", requestEvent) + if err = c.conn.Emit(requestEvent, requestData); err != nil { + return errors.Wrapf(err, "error while emitting '%s' event", requestEvent) + } + c.logf("'%s' event sent", requestEvent) + + wg.Wait() + + return err + +} + func (c *client) logf(format string, args ...interface{}) { if c.opts.Logger == nil { return From ff13693f6957cf4007c145635977f79829a16df0 Mon Sep 17 00:00:00 2001 From: William Petit Date: Thu, 20 Sep 2018 17:24:26 +0200 Subject: [PATCH 2/8] Add ReachView client --- reach/reachview.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 reach/reachview.go diff --git a/reach/reachview.go b/reach/reachview.go new file mode 100644 index 0000000..2e9fa51 --- /dev/null +++ b/reach/reachview.go @@ -0,0 +1,12 @@ +package reach + +// ReachView is a ReachRS Updater client +type ReachView struct { // nolint: golint + *client +} + +// NewReachViewClient returns a new ReachRS ReachView client +func NewReachViewClient(opts ...OptionFunc) *ReachView { + client := newClient(opts...) + return &ReachView{client} +} From e3672cc6d713813d4f1393e49f2bb14d86669793 Mon Sep 17 00:00:00 2001 From: William Petit Date: Thu, 20 Sep 2018 17:28:18 +0200 Subject: [PATCH 3/8] Add basic Configuration() method --- reach/configuration.go | 44 +++++++++++++++++++++++++++++++++++++ reach/configuration_test.go | 32 +++++++++++++++++++++++++++ reach/test.go | 5 +++++ 3 files changed, 81 insertions(+) create mode 100644 reach/configuration.go create mode 100644 reach/configuration_test.go diff --git a/reach/configuration.go b/reach/configuration.go new file mode 100644 index 0000000..b7f3fca --- /dev/null +++ b/reach/configuration.go @@ -0,0 +1,44 @@ +package reach + +const ( + eventGetConfiguration = "get configuration" + eventCurrentConfiguration = "current configuration" +) + +// Configuration is a configuration +type Configuration struct { + RTKSettings *RTKSettings `mapstructure:"rtk settings,omitempty"` +} + +// RTKSettings - +type RTKSettings struct { + GLONASSARMode string `mapstructure:"glonass ar mode"` + UpdateRate string `mapstructure:"update rate"` + ElevationMaskAngle string `mapstructure:"elevation mask angle"` + MaxHorizontalAcceleration string `mapstructure:"max horizontal acceleration"` + SNRMask string `mapstructure:"snr mask"` + GPSARMode string `mapstructure:"gps ar mode"` + PositionningMode string `mapstructure:"positioning mode"` + PositioningSystems *PositionningSystems `mapstructure:"positioning systems,omitempty"` + MaxVerticalAcceleration string `mapstructure:"max vertical acceleration"` +} + +// PositionningSystems - +type PositionningSystems struct { + GLONASS bool `json:"glonass"` + SBAS bool `json:"sbas"` + QZS bool `json:"qzs"` + QZSS bool `json:"qzss"` + Compass bool `json:"compass"` + Galileo bool `json:"galileo"` + GPS bool `json:"gps"` +} + +// Configuration fetches and return the current configuration of the ReachRS module +func (r *ReachView) Configuration() (*Configuration, error) { + configuration := &Configuration{} + if err := r.fetch(eventGetConfiguration, nil, eventCurrentConfiguration, configuration); err != nil { + return nil, err + } + return configuration, nil +} diff --git a/reach/configuration_test.go b/reach/configuration_test.go new file mode 100644 index 0000000..046a974 --- /dev/null +++ b/reach/configuration_test.go @@ -0,0 +1,32 @@ +package reach + +import ( + "testing" +) + +func TestReachViewConfiguration(t *testing.T) { + + if !*runReachViewIntegrationTests { + t.Skip("To run this test, use: go test -reachview-integration") + } + + client := NewReachViewClient( + WithStandardLogger(), + WithEndpoint(*reachHost, 80), + ) + if err := client.Connect(); err != nil { + t.Fatal(err) + } + + config, err := client.Configuration() + if err != nil { + t.Error(err) + } + + if config == nil { + t.Error("config should not be nil") + } + + defer client.Close() + +} diff --git a/reach/test.go b/reach/test.go index 5343fc6..0253f58 100644 --- a/reach/test.go +++ b/reach/test.go @@ -7,6 +7,11 @@ var runUpdaterIntegrationTests = flag.Bool( "Run the 'Updater' integration tests (in addition to the unit tests)", ) +var runReachViewIntegrationTests = flag.Bool( + "reachview-integration", false, + "Run the 'ReachView' integration tests (in addition to the unit tests)", +) + var reachHost = flag.String( "reach-host", "192.168.42.1", "The Reach module host to use in integration tests", From f67724dc3a834b9c9229b2fe977a37da32be1a6c Mon Sep 17 00:00:00 2001 From: William Petit Date: Thu, 20 Sep 2018 17:40:23 +0200 Subject: [PATCH 4/8] Add another checkpoint to ReachView.Configuration() test --- reach/configuration_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/reach/configuration_test.go b/reach/configuration_test.go index 046a974..705b290 100644 --- a/reach/configuration_test.go +++ b/reach/configuration_test.go @@ -24,7 +24,11 @@ func TestReachViewConfiguration(t *testing.T) { } if config == nil { - t.Error("config should not be nil") + t.Fatal("config should not be nil") + } + + if config.RTKSettings == nil { + t.Fatal("config.RTKSettings should not be nil") } defer client.Close() From 2c7aad91c6d60da064c1122daf675e31fccee17b Mon Sep 17 00:00:00 2001 From: William Petit Date: Thu, 20 Sep 2018 17:52:50 +0200 Subject: [PATCH 5/8] Use golangci-lint instead of gometalinter --- Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 4ba546a..891a9ce 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ +LINT_ARGS ?= ./... export GO111MODULE := on build: bin/server @@ -13,7 +14,7 @@ test: tidy go test -mod=vendor -v ./... lint: - @PATH=$(PATH):./bin/gometalinter gometalinter -e '.*/pkg/mod' -e ".*/go/src" --vendor $(LINT_ARGS) ./... + @golangci-lint run -e '.*/pkg/mod' -e ".*/go/src" --enable-all $(LINT_ARGS) tidy: go mod tidy @@ -24,8 +25,8 @@ vendor: tidy install-devtools: vendor # Install modd GO111MODULE=off go get -u github.com/cortesi/modd/cmd/modd - # Install Gometalinter - bash misc/gometalinter/install.sh -b ./bin/gometalinter + # Install golangci-lint + GO111MODULE=off go get -u github.com/golangci/golangci-lint/cmd/golangci-lint clean: rm -rf ./bin From 77a779aebe8011f35256abf9b4230b4032f29b51 Mon Sep 17 00:00:00 2001 From: William Petit Date: Thu, 20 Sep 2018 17:53:43 +0200 Subject: [PATCH 6/8] Provides a pre-commit git hook to lint Go files --- doc/prepa-dev.md | 6 ++++++ misc/git-hooks/pre-commit | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100755 misc/git-hooks/pre-commit diff --git a/doc/prepa-dev.md b/doc/prepa-dev.md index 578699f..2ae7b91 100644 --- a/doc/prepa-dev.md +++ b/doc/prepa-dev.md @@ -15,4 +15,10 @@ 2. Lancer le serveur ```shell make watch + ``` + +3. (Optionnel mais recommandé) Installer le hook Git `pre-commit` + ```shell + rm -f .git/hooks/pre-commit.sample + ln -s "$PWD/misc/git-hooks/pre-commit" .git/hooks/pre-commit ``` \ No newline at end of file diff --git a/misc/git-hooks/pre-commit b/misc/git-hooks/pre-commit new file mode 100755 index 0000000..97f1d92 --- /dev/null +++ b/misc/git-hooks/pre-commit @@ -0,0 +1,17 @@ +#!/bin/bash + +set -eo pipefail + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" +CHANGESET=$(git diff --cached --name-only --diff-filter=ACM) + +function lint_go_files { + echo "Linting modified Go files..." + ( cd "$DIR/../.." && make LINT_ARGS="--new-from-rev=HEAD~ ./..." lint ) +} + +function main { + lint_go_files +} + +main \ No newline at end of file From 6e9df8d3866b10579cf7c505e35d50a708ea351f Mon Sep 17 00:00:00 2001 From: William Petit Date: Fri, 21 Sep 2018 12:31:52 +0200 Subject: [PATCH 7/8] Refactor reach package - Rename reach package to emlid - Create generic Reach websocket client - Add 2 new subpackages 'updater' and 'reachview' to provides specific API --- emlid/browser_connected.go | 17 ++ {reach => emlid}/client.go | 55 ++++-- {reach => emlid}/option.go | 2 +- {reach => emlid}/reach.go | 4 +- emlid/reachview/client.go | 14 ++ {reach => emlid/reachview}/configuration.go | 6 +- .../reachview}/configuration_test.go | 10 +- {reach => emlid/reachview}/test.go | 7 +- emlid/updater/client.go | 15 ++ {reach => emlid/updater}/example_test.go | 16 +- emlid/updater/reachview_version.go | 19 ++ .../updater}/reachview_version_test.go | 10 +- {reach => emlid/updater}/reboot_now.go | 14 +- {reach => emlid/updater}/reboot_now_test.go | 16 +- emlid/updater/receiver_upgrade.go | 21 +++ .../updater}/receiver_upgrade_test.go | 10 +- emlid/updater/test.go | 23 +++ emlid/updater/test_results.go | 25 +++ {reach => emlid/updater}/test_results_test.go | 10 +- emlid/updater/time_sync.go | 21 +++ {reach => emlid/updater}/time_sync_test.go | 10 +- emlid/updater/update.go | 26 +++ {reach => emlid/updater}/update_test.go | 10 +- emlid/updater/wifi_networks.go | 101 +++++++++++ .../updater}/wifi_networks_test.go | 26 ++- example/updater/main.go | 38 ++-- reach/browser_connected.go | 26 --- reach/reachview.go | 12 -- reach/reachview_version.go | 49 ----- reach/receiver_upgrade.go | 49 ----- reach/test_results.go | 53 ------ reach/time_sync.go | 50 ----- reach/update.go | 55 ------ reach/updater.go | 12 -- reach/wifi_networks.go | 171 ------------------ 35 files changed, 427 insertions(+), 576 deletions(-) create mode 100644 emlid/browser_connected.go rename {reach => emlid}/client.go (57%) rename {reach => emlid}/option.go (99%) rename {reach => emlid}/reach.go (56%) create mode 100644 emlid/reachview/client.go rename {reach => emlid/reachview}/configuration.go (89%) rename {reach => emlid/reachview}/configuration_test.go (76%) rename {reach => emlid/reachview}/test.go (63%) create mode 100644 emlid/updater/client.go rename {reach => emlid/updater}/example_test.go (60%) create mode 100644 emlid/updater/reachview_version.go rename {reach => emlid/updater}/reachview_version_test.go (73%) rename {reach => emlid/updater}/reboot_now.go (52%) rename {reach => emlid/updater}/reboot_now_test.go (50%) create mode 100644 emlid/updater/receiver_upgrade.go rename {reach => emlid/updater}/receiver_upgrade_test.go (70%) create mode 100644 emlid/updater/test.go create mode 100644 emlid/updater/test_results.go rename {reach => emlid/updater}/test_results_test.go (75%) create mode 100644 emlid/updater/time_sync.go rename {reach => emlid/updater}/time_sync_test.go (68%) create mode 100644 emlid/updater/update.go rename {reach => emlid/updater}/update_test.go (68%) create mode 100644 emlid/updater/wifi_networks.go rename {reach => emlid/updater}/wifi_networks_test.go (81%) delete mode 100644 reach/browser_connected.go delete mode 100644 reach/reachview.go delete mode 100644 reach/reachview_version.go delete mode 100644 reach/receiver_upgrade.go delete mode 100644 reach/test_results.go delete mode 100644 reach/time_sync.go delete mode 100644 reach/update.go delete mode 100644 reach/updater.go delete mode 100644 reach/wifi_networks.go diff --git a/emlid/browser_connected.go b/emlid/browser_connected.go new file mode 100644 index 0000000..8f0182d --- /dev/null +++ b/emlid/browser_connected.go @@ -0,0 +1,17 @@ +package emlid + +const ( + // EventBrowserConnected is emitted after the initial connection to the + // ReachView endpoint + eventBrowserConnected = "browser connected" +) + +// sendBrowserConnected notifies the ReachView endpoint +// of a new connection. +// See misc/reachview/update_main.js line 297 +func (c *Client) sendBrowserConnected() error { + payload := map[string]string{ + "data": "I'm connected", + } + return c.Emit(eventBrowserConnected, payload) +} diff --git a/reach/client.go b/emlid/client.go similarity index 57% rename from reach/client.go rename to emlid/client.go index 742db25..093d1b4 100644 --- a/reach/client.go +++ b/emlid/client.go @@ -1,4 +1,4 @@ -package reach +package emlid import ( "sync" @@ -9,14 +9,18 @@ import ( "github.com/pkg/errors" ) -type client struct { +// Client is a ReachRS websocket API client +type Client struct { opts *Options conn *gosocketio.Client } +// EventHandler is an event handler +type EventHandler func(data interface{}) + // Connect connects the client to the ReachView endpoint // This method is not safe to call by different coroutines -func (c *client) Connect() error { +func (c *Client) Connect() error { var err error var wg sync.WaitGroup @@ -31,7 +35,7 @@ func (c *client) Connect() error { BufferSize: c.opts.BufferSize, } - c.logf("connecting to '%s'", c.opts.Endpoint) + c.Logf("connecting to '%s'", c.opts.Endpoint) conn, err := gosocketio.Dial(c.opts.Endpoint, transport) if err != nil { return errors.Wrap(err, "error while connecting to endpoint") @@ -41,7 +45,7 @@ func (c *client) Connect() error { err = conn.On(gosocketio.OnConnection, func(h *gosocketio.Channel) { conn.Off(gosocketio.OnError) - c.logf("connected with sid '%s'", h.Id()) + c.Logf("connected with sid '%s'", h.Id()) err = c.sendBrowserConnected() wg.Done() }) @@ -50,7 +54,7 @@ func (c *client) Connect() error { } err = conn.On(gosocketio.OnError, func(h *gosocketio.Channel) { - c.logf("error") + c.Logf("error") err = errors.Errorf("an unknown error occured") c.conn = nil wg.Done() @@ -65,7 +69,7 @@ func (c *client) Connect() error { } // Close closes the current connection to the ReachView endpoint -func (c *client) Close() { +func (c *Client) Close() { if c.conn == nil { return } @@ -73,7 +77,28 @@ func (c *client) Close() { c.conn = nil } -func (c *client) fetch(requestEvent string, requestData interface{}, responseEvent string, res interface{}) error { +// Emit a new event with the given data +func (c *Client) Emit(event string, data interface{}) error { + c.Logf("emit '%s' event", event) + if err := c.conn.Emit(event, data); err != nil { + return errors.Wrapf(err, "error while emitting '%s' event", event) + } + c.Logf("'%s' event sent", event) + return nil +} + +// On binds and event handler to the given event +func (c *Client) On(event string, handler interface{}) error { + return c.conn.On(event, handler) +} + +// Off remove the handler bound to the given event +func (c *Client) Off(event string) { + c.conn.Off(event) +} + +// ReqResp emits an event with the given data and waits for a response +func (c *Client) ReqResp(requestEvent string, requestData interface{}, responseEvent string, res interface{}) error { var err error var wg sync.WaitGroup @@ -89,11 +114,9 @@ func (c *client) fetch(requestEvent string, requestData interface{}, responseEve return errors.Wrapf(err, "error while binding to '%s' event", responseEvent) } - c.logf("sending '%s' event", requestEvent) - if err = c.conn.Emit(requestEvent, requestData); err != nil { - return errors.Wrapf(err, "error while emitting '%s' event", requestEvent) + if err := c.Emit(requestEvent, requestData); err != nil { + return errors.Wrapf(err, "error while emitting event '%s'", requestEvent) } - c.logf("'%s' event sent", requestEvent) wg.Wait() @@ -101,19 +124,21 @@ func (c *client) fetch(requestEvent string, requestData interface{}, responseEve } -func (c *client) logf(format string, args ...interface{}) { +// Logf logs the given message with the configured logger +func (c *Client) Logf(format string, args ...interface{}) { if c.opts.Logger == nil { return } c.opts.Logger.Printf(format, args...) } -func newClient(opts ...OptionFunc) *client { +// NewClient returns a new ReachRS websocket client +func NewClient(opts ...OptionFunc) *Client { options := DefaultOptions() for _, o := range opts { o(options) } - return &client{ + return &Client{ opts: options, } } diff --git a/reach/option.go b/emlid/option.go similarity index 99% rename from reach/option.go rename to emlid/option.go index 80a713c..bb3db33 100644 --- a/reach/option.go +++ b/emlid/option.go @@ -1,4 +1,4 @@ -package reach +package emlid import ( "log" diff --git a/reach/reach.go b/emlid/reach.go similarity index 56% rename from reach/reach.go rename to emlid/reach.go index 6a8aa41..e34172f 100644 --- a/reach/reach.go +++ b/emlid/reach.go @@ -1,4 +1,4 @@ -// Package reach is a package to configure EMLID ReachRS modules in Go. +// Package emlid is a package to configure EMLID ReachRS modules in Go. // // It aims to provide a simple interface to common ReachRS modules management operations. -package reach +package emlid diff --git a/emlid/reachview/client.go b/emlid/reachview/client.go new file mode 100644 index 0000000..62a56cc --- /dev/null +++ b/emlid/reachview/client.go @@ -0,0 +1,14 @@ +package reachview + +import "forge.cadoles.com/Pyxis/orion/emlid" + +// Client is a ReachRS Updater client +type Client struct { + *emlid.Client +} + +// NewClient returns a new ReachRS ReachView client +func NewClient(opts ...emlid.OptionFunc) *Client { + client := emlid.NewClient(opts...) + return &Client{client} +} diff --git a/reach/configuration.go b/emlid/reachview/configuration.go similarity index 89% rename from reach/configuration.go rename to emlid/reachview/configuration.go index b7f3fca..e95ef64 100644 --- a/reach/configuration.go +++ b/emlid/reachview/configuration.go @@ -1,4 +1,4 @@ -package reach +package reachview const ( eventGetConfiguration = "get configuration" @@ -35,9 +35,9 @@ type PositionningSystems struct { } // Configuration fetches and return the current configuration of the ReachRS module -func (r *ReachView) Configuration() (*Configuration, error) { +func (r *Client) Configuration() (*Configuration, error) { configuration := &Configuration{} - if err := r.fetch(eventGetConfiguration, nil, eventCurrentConfiguration, configuration); err != nil { + if err := r.ReqResp(eventGetConfiguration, nil, eventCurrentConfiguration, configuration); err != nil { return nil, err } return configuration, nil diff --git a/reach/configuration_test.go b/emlid/reachview/configuration_test.go similarity index 76% rename from reach/configuration_test.go rename to emlid/reachview/configuration_test.go index 705b290..32a7b33 100644 --- a/reach/configuration_test.go +++ b/emlid/reachview/configuration_test.go @@ -1,7 +1,9 @@ -package reach +package reachview import ( "testing" + + "forge.cadoles.com/Pyxis/orion/emlid" ) func TestReachViewConfiguration(t *testing.T) { @@ -10,9 +12,9 @@ func TestReachViewConfiguration(t *testing.T) { t.Skip("To run this test, use: go test -reachview-integration") } - client := NewReachViewClient( - WithStandardLogger(), - WithEndpoint(*reachHost, 80), + client := NewClient( + emlid.WithStandardLogger(), + emlid.WithEndpoint(*reachHost, 80), ) if err := client.Connect(); err != nil { t.Fatal(err) diff --git a/reach/test.go b/emlid/reachview/test.go similarity index 63% rename from reach/test.go rename to emlid/reachview/test.go index 0253f58..1dfa823 100644 --- a/reach/test.go +++ b/emlid/reachview/test.go @@ -1,12 +1,7 @@ -package reach +package reachview import "flag" -var runUpdaterIntegrationTests = flag.Bool( - "updater-integration", false, - "Run the 'Updater' integration tests (in addition to the unit tests)", -) - var runReachViewIntegrationTests = flag.Bool( "reachview-integration", false, "Run the 'ReachView' integration tests (in addition to the unit tests)", diff --git a/emlid/updater/client.go b/emlid/updater/client.go new file mode 100644 index 0000000..1f0397f --- /dev/null +++ b/emlid/updater/client.go @@ -0,0 +1,15 @@ +// Package updater provides an API to communicate with the ReachRS modules "Updater" application +package updater + +import "forge.cadoles.com/Pyxis/orion/emlid" + +// Client is a ReachRS Updater client +type Client struct { + *emlid.Client +} + +// NewClient returns a new ReachRS Updater client +func NewClient(opts ...emlid.OptionFunc) *Client { + client := emlid.NewClient(opts...) + return &Client{client} +} diff --git a/reach/example_test.go b/emlid/updater/example_test.go similarity index 60% rename from reach/example_test.go rename to emlid/updater/example_test.go index 2a11c08..4e4f1e9 100644 --- a/reach/example_test.go +++ b/emlid/updater/example_test.go @@ -1,13 +1,15 @@ -package reach +package updater -import "log" +import ( + "log" -// ReachRS modules provides an Updater application when reset in factory mode. -// This package provides an API to communicate with this application. -func Example_updaterClientUsage() { + "forge.cadoles.com/Pyxis/orion/emlid" +) + +func Example_usage() { // Create a new Updater client instance - updater := NewUpdaterClient( - WithEndpoint("192.168.42.1", 80), // Define the module endpoint + updater := NewClient( + emlid.WithEndpoint("192.168.42.1", 80), // Define the module endpoint ) // Connect to the ReachRS Updater endpoint diff --git a/emlid/updater/reachview_version.go b/emlid/updater/reachview_version.go new file mode 100644 index 0000000..c0640d8 --- /dev/null +++ b/emlid/updater/reachview_version.go @@ -0,0 +1,19 @@ +package updater + +const ( + eventGetReachViewVersion = "get reachview version" + eventReachViewVersionResults = "current reachview version" +) + +type reachViewVersion struct { + Version string `json:"version"` +} + +// ReachViewVersion returns the ReachRS module ReachView version +func (c *Client) ReachViewVersion() (string, error) { + res := &reachViewVersion{} + if err := c.ReqResp(eventGetReachViewVersion, nil, eventReachViewVersionResults, res); err != nil { + return "", err + } + return res.Version, nil +} diff --git a/reach/reachview_version_test.go b/emlid/updater/reachview_version_test.go similarity index 73% rename from reach/reachview_version_test.go rename to emlid/updater/reachview_version_test.go index 7dba9a8..9ae46a4 100644 --- a/reach/reachview_version_test.go +++ b/emlid/updater/reachview_version_test.go @@ -1,7 +1,9 @@ -package reach +package updater import ( "testing" + + "forge.cadoles.com/Pyxis/orion/emlid" ) func TestClientReachViewVersion(t *testing.T) { @@ -10,9 +12,9 @@ func TestClientReachViewVersion(t *testing.T) { t.Skip("To run this test, use: go test -updater-integration") } - client := NewUpdaterClient( - WithStandardLogger(), - WithEndpoint(*reachHost, 80), + client := NewClient( + emlid.WithStandardLogger(), + emlid.WithEndpoint(*reachHost, 80), ) if err := client.Connect(); err != nil { t.Fatal(err) diff --git a/reach/reboot_now.go b/emlid/updater/reboot_now.go similarity index 52% rename from reach/reboot_now.go rename to emlid/updater/reboot_now.go index 18eaaf9..3003c53 100644 --- a/reach/reboot_now.go +++ b/emlid/updater/reboot_now.go @@ -1,4 +1,4 @@ -package reach +package updater import ( "sync" @@ -12,15 +12,15 @@ const ( ) // RebootNow asks the ReachRS module to reboot now -func (u *Updater) RebootNow(waitDisconnect bool) error { +func (c *Client) RebootNow(waitDisconnect bool) error { var err error var wg sync.WaitGroup if waitDisconnect { wg.Add(1) - err = u.conn.On(gosocketio.OnDisconnection, func(h *gosocketio.Channel) { - u.conn.Off(gosocketio.OnDisconnection) + err = c.On(gosocketio.OnDisconnection, func(h *gosocketio.Channel) { + c.Off(gosocketio.OnDisconnection) wg.Done() }) if err != nil { @@ -28,11 +28,9 @@ func (u *Updater) RebootNow(waitDisconnect bool) error { } } - u.logf("sending '%s' event", eventReboot) - if err = u.conn.Emit(eventReboot, nil); err != nil { - return errors.Wrapf(err, "error while emitting '%s' event", eventReboot) + if err = c.Emit(eventReboot, nil); err != nil { + return err } - u.logf("'%s' event sent", eventReboot) if waitDisconnect { wg.Wait() diff --git a/reach/reboot_now_test.go b/emlid/updater/reboot_now_test.go similarity index 50% rename from reach/reboot_now_test.go rename to emlid/updater/reboot_now_test.go index 21bac03..d3a531a 100644 --- a/reach/reboot_now_test.go +++ b/emlid/updater/reboot_now_test.go @@ -1,18 +1,24 @@ -package reach +package updater import ( "testing" + + "forge.cadoles.com/Pyxis/orion/emlid" ) -func TestClientReboutNow(t *testing.T) { +func TestClientRebootNow(t *testing.T) { if !*runUpdaterIntegrationTests { t.Skip("To run this test, use: go test -updater-integration") } - client := NewUpdaterClient( - WithStandardLogger(), - WithEndpoint(*reachHost, 80), + if !*runRebootTest { + t.Skip("To run this test, use: go test -updater-reboot-test") + } + + client := NewClient( + emlid.WithStandardLogger(), + emlid.WithEndpoint(*reachHost, 80), ) if err := client.Connect(); err != nil { t.Fatal(err) diff --git a/emlid/updater/receiver_upgrade.go b/emlid/updater/receiver_upgrade.go new file mode 100644 index 0000000..6ceba52 --- /dev/null +++ b/emlid/updater/receiver_upgrade.go @@ -0,0 +1,21 @@ +package updater + +const ( + eventIsReceiverUpgradeAvailable = "is receiver upgrade available" + eventReceiverUpgradeAvailable = "receiver upgrade available" +) + +type receiverUpgreAvailable struct { + Available bool `json:"available"` + Running bool `json:"running"` +} + +// ReceiverUpgradeAvailable checks if an upgrade is avaialable/running for the ReachRS module +func (c *Client) ReceiverUpgradeAvailable() (bool, bool, error) { + res := &receiverUpgreAvailable{} + if err := c.ReqResp(eventIsReceiverUpgradeAvailable, nil, eventReceiverUpgradeAvailable, res); err != nil { + return false, false, err + } + c.Logf("receiver upgrade result: available: %v, running: %v", res.Available, res.Running) + return res.Available, res.Running, nil +} diff --git a/reach/receiver_upgrade_test.go b/emlid/updater/receiver_upgrade_test.go similarity index 70% rename from reach/receiver_upgrade_test.go rename to emlid/updater/receiver_upgrade_test.go index a4358d2..65913bd 100644 --- a/reach/receiver_upgrade_test.go +++ b/emlid/updater/receiver_upgrade_test.go @@ -1,7 +1,9 @@ -package reach +package updater import ( "testing" + + "forge.cadoles.com/Pyxis/orion/emlid" ) func TestClientReceiverUpgradeAvailable(t *testing.T) { @@ -10,9 +12,9 @@ func TestClientReceiverUpgradeAvailable(t *testing.T) { t.Skip("To run this test, use: go test -updater-integration") } - client := NewUpdaterClient( - WithStandardLogger(), - WithEndpoint(*reachHost, 80), + client := NewClient( + emlid.WithStandardLogger(), + emlid.WithEndpoint(*reachHost, 80), ) if err := client.Connect(); err != nil { t.Fatal(err) diff --git a/emlid/updater/test.go b/emlid/updater/test.go new file mode 100644 index 0000000..a4e27b0 --- /dev/null +++ b/emlid/updater/test.go @@ -0,0 +1,23 @@ +package updater + +import "flag" + +var runUpdaterIntegrationTests = flag.Bool( + "updater-integration", false, + "Run the 'Updater' integration tests (in addition to the unit tests)", +) + +var runRebootTest = flag.Bool( + "updater-reboot-test", false, + "Run the updater 'Reboot' test (in addition to the unit tests)", +) + +var runJoinNetworkTest = flag.Bool( + "updater-join-network-test", false, + "Run the updater 'JoinWiFiNetwork' test (in addition to the unit tests)", +) + +var reachHost = flag.String( + "reach-host", "192.168.42.1", + "The Reach module host to use in integration tests", +) diff --git a/emlid/updater/test_results.go b/emlid/updater/test_results.go new file mode 100644 index 0000000..e5342ff --- /dev/null +++ b/emlid/updater/test_results.go @@ -0,0 +1,25 @@ +package updater + +const ( + eventGetTestResults = "get test results" + eventTestResults = "test results" +) + +// TestResults are the ReachRS module's test results +// +type TestResults struct { + Device string `json:"device"` + Lora bool `json:"lora"` + MPU bool `json:"mpu"` + STC bool `json:"stc"` + UBlox bool `json:"u-blox"` +} + +// TestResults returns the ReachRS module tests results +func (c *Client) TestResults() (*TestResults, error) { + res := &TestResults{} + if err := c.ReqResp(eventGetTestResults, nil, eventTestResults, res); err != nil { + return nil, err + } + return res, nil +} diff --git a/reach/test_results_test.go b/emlid/updater/test_results_test.go similarity index 75% rename from reach/test_results_test.go rename to emlid/updater/test_results_test.go index b8691bb..57bf5a3 100644 --- a/reach/test_results_test.go +++ b/emlid/updater/test_results_test.go @@ -1,7 +1,9 @@ -package reach +package updater import ( "testing" + + "forge.cadoles.com/Pyxis/orion/emlid" ) func TestClientTestResults(t *testing.T) { @@ -10,9 +12,9 @@ func TestClientTestResults(t *testing.T) { t.Skip("To run this test, use: go test -updater-integration") } - client := NewUpdaterClient( - WithStandardLogger(), - WithEndpoint(*reachHost, 80), + client := NewClient( + emlid.WithStandardLogger(), + emlid.WithEndpoint(*reachHost, 80), ) if err := client.Connect(); err != nil { t.Fatal(err) diff --git a/emlid/updater/time_sync.go b/emlid/updater/time_sync.go new file mode 100644 index 0000000..afaefd2 --- /dev/null +++ b/emlid/updater/time_sync.go @@ -0,0 +1,21 @@ +package updater + +const ( + eventGetTimeSyncStatus = "get time sync status" + eventTimeSyncResults = "time sync status" +) + +type timeSyncStatus struct { + Status bool `json:"status"` +} + +// TimeSynced returns the ReachRS module time synchronization status. +// A true response means that the module has synchronized its clock. +func (c *Client) TimeSynced() (bool, error) { + res := &timeSyncStatus{} + if err := c.ReqResp(eventGetTimeSyncStatus, nil, eventTimeSyncResults, res); err != nil { + return false, err + } + c.Logf("time sync result: %v", res.Status) + return res.Status, nil +} diff --git a/reach/time_sync_test.go b/emlid/updater/time_sync_test.go similarity index 68% rename from reach/time_sync_test.go rename to emlid/updater/time_sync_test.go index af81b70..c625425 100644 --- a/reach/time_sync_test.go +++ b/emlid/updater/time_sync_test.go @@ -1,7 +1,9 @@ -package reach +package updater import ( "testing" + + "forge.cadoles.com/Pyxis/orion/emlid" ) func TestClientTimeSync(t *testing.T) { @@ -10,9 +12,9 @@ func TestClientTimeSync(t *testing.T) { t.Skip("To run this test, use: go test -updater-integration") } - client := NewUpdaterClient( - WithStandardLogger(), - WithEndpoint(*reachHost, 80), + client := NewClient( + emlid.WithStandardLogger(), + emlid.WithEndpoint(*reachHost, 80), ) if err := client.Connect(); err != nil { t.Fatal(err) diff --git a/emlid/updater/update.go b/emlid/updater/update.go new file mode 100644 index 0000000..3fc5b44 --- /dev/null +++ b/emlid/updater/update.go @@ -0,0 +1,26 @@ +package updater + +const ( + eventUpdate = "update" + eventOPKGUpdateResult = "opkg update result" +) + +// UpdateStatus embeds informations about update status +type UpdateStatus struct { + Active bool `json:"active"` + Locked bool `json:"locked"` + State string `json:"state"` +} + +// Update asks the ReachRS module to start an OPKG update +func (c *Client) Update() (*UpdateStatus, error) { + res := &UpdateStatus{} + if err := c.ReqResp(eventUpdate, nil, eventOPKGUpdateResult, res); err != nil { + return nil, err + } + c.Logf( + "opkg update result: active: %v, state: %v, locked: %v", + res.Active, res.State, res.Locked, + ) + return res, nil +} diff --git a/reach/update_test.go b/emlid/updater/update_test.go similarity index 68% rename from reach/update_test.go rename to emlid/updater/update_test.go index 87161e4..39aa897 100644 --- a/reach/update_test.go +++ b/emlid/updater/update_test.go @@ -1,7 +1,9 @@ -package reach +package updater import ( "testing" + + "forge.cadoles.com/Pyxis/orion/emlid" ) func TestClientOPKGUpdate(t *testing.T) { @@ -10,9 +12,9 @@ func TestClientOPKGUpdate(t *testing.T) { t.Skip("To run this test, use: go test -updater-integration") } - client := NewUpdaterClient( - WithStandardLogger(), - WithEndpoint(*reachHost, 80), + client := NewClient( + emlid.WithStandardLogger(), + emlid.WithEndpoint(*reachHost, 80), ) if err := client.Connect(); err != nil { t.Fatal(err) diff --git a/emlid/updater/wifi_networks.go b/emlid/updater/wifi_networks.go new file mode 100644 index 0000000..dbc6326 --- /dev/null +++ b/emlid/updater/wifi_networks.go @@ -0,0 +1,101 @@ +package updater + +import ( + "sync" + + "forge.cadoles.com/Pyxis/golang-socketio" + "github.com/pkg/errors" +) + +const ( + eventGetSavedWifiNetworks = "get saved wifi networks" + eventSavedWifiNetworkResults = "wifi saved networks results" + eventAddWifiNetwork = "add new network" + eventAddWifiNetworkResults = "add network results" + eventRemoveWifiNetwork = "remove network" + eventRemoveWifiNetworkResults = "remove network results" + eventConnectToNetwork = "connect to network" +) + +// WifiSecurity is a WiFi network security algorithm +type WifiSecurity string + +const ( + // SecurityWEP WEP wifi network + SecurityWEP WifiSecurity = "wep" + // SecurityWPAPSK WPA(2)-PSK wifi network + SecurityWPAPSK WifiSecurity = "wpa-psk" + // SecurityOpen Open wifi network + SecurityOpen WifiSecurity = "open" +) + +// WifiNetwork is a ReachRS module wifi network +type WifiNetwork struct { + SSID string `json:"ssid"` + Password string `json:"password"` + Security WifiSecurity `json:"security"` + Identity string `json:"identity"` + Visible bool `json:"is_visible"` + Connected bool `json:"is_connected"` + Added bool `json:"is_added"` +} + +// WifiNetworks returns the ReachRS module wifi networks +func (c *Client) WifiNetworks() ([]WifiNetwork, error) { + res := make([]WifiNetwork, 0) + if err := c.ReqResp(eventGetSavedWifiNetworks, nil, eventSavedWifiNetworkResults, &res); err != nil { + return nil, err + } + return res, nil +} + +// AddWifiNetwork asks the ReachRS module to save the given wifi network informations +func (c *Client) AddWifiNetwork(ssid string, security WifiSecurity, password string) (bool, error) { + res := false + network := &WifiNetwork{ + SSID: ssid, + Security: security, + Password: password, + } + if err := c.ReqResp(eventAddWifiNetwork, network, eventAddWifiNetworkResults, &res); err != nil { + return false, err + } + return res, nil +} + +// RemoveWifiNetwork asks the ReachRS module to remove the given WiFi network +func (c *Client) RemoveWifiNetwork(ssid string) (bool, error) { + res := false + if err := c.ReqResp(eventRemoveWifiNetwork, ssid, eventRemoveWifiNetworkResults, &res); err != nil { + return false, err + } + return res, nil +} + +// JoinWifiNetwork asks the ReachRS module to join the given WiFi network +func (c *Client) JoinWifiNetwork(ssid string, waitDisconnect bool) error { + + var err error + var wg sync.WaitGroup + + if waitDisconnect { + wg.Add(1) + err = c.On(gosocketio.OnDisconnection, func(h *gosocketio.Channel) { + c.Off(gosocketio.OnDisconnection) + wg.Done() + }) + if err != nil { + return errors.Wrapf(err, "error while binding to '%s' event", gosocketio.OnDisconnection) + } + } + + if err := c.Emit(eventConnectToNetwork, ssid); err != nil { + return errors.Wrapf(err, "error while emitting '%s' event", eventConnectToNetwork) + } + + if waitDisconnect { + wg.Wait() + } + + return nil +} diff --git a/reach/wifi_networks_test.go b/emlid/updater/wifi_networks_test.go similarity index 81% rename from reach/wifi_networks_test.go rename to emlid/updater/wifi_networks_test.go index 06ca838..134552e 100644 --- a/reach/wifi_networks_test.go +++ b/emlid/updater/wifi_networks_test.go @@ -1,10 +1,12 @@ -package reach +package updater import ( "fmt" "math/rand" "testing" "time" + + "forge.cadoles.com/Pyxis/orion/emlid" ) func TestClientSavedWiFiNetworks(t *testing.T) { @@ -13,9 +15,9 @@ func TestClientSavedWiFiNetworks(t *testing.T) { t.Skip("To run this test, use: go test -updater-integration") } - client := NewUpdaterClient( - WithStandardLogger(), - WithEndpoint(*reachHost, 80), + client := NewClient( + emlid.WithStandardLogger(), + emlid.WithEndpoint(*reachHost, 80), ) if err := client.Connect(); err != nil { t.Fatal(err) @@ -36,9 +38,9 @@ func TestClientCRUDWiFiNetwork(t *testing.T) { t.Skip("To run this test, use: go test -updater-integration") } - client := NewUpdaterClient( - WithStandardLogger(), - WithEndpoint(*reachHost, 80), + client := NewClient( + emlid.WithStandardLogger(), + emlid.WithEndpoint(*reachHost, 80), ) if err := client.Connect(); err != nil { t.Fatal(err) @@ -91,9 +93,13 @@ func TestClientWifiNetworkJoin(t *testing.T) { t.Skip("To run this test, use: go test -updater-integration") } - client := NewUpdaterClient( - WithStandardLogger(), - WithEndpoint(*reachHost, 80), + if !*runJoinNetworkTest { + t.Skip("To run this test, use: go test -updater-join-network-test") + } + + client := NewClient( + emlid.WithStandardLogger(), + emlid.WithEndpoint(*reachHost, 80), ) if err := client.Connect(); err != nil { t.Fatal(err) diff --git a/example/updater/main.go b/example/updater/main.go index 54d685a..94c5600 100644 --- a/example/updater/main.go +++ b/example/updater/main.go @@ -6,7 +6,8 @@ import ( "log" "strings" - "forge.cadoles.com/Pyxis/orion/reach" + "forge.cadoles.com/Pyxis/orion/emlid" + "forge.cadoles.com/Pyxis/orion/emlid/updater" ) const ( @@ -18,7 +19,7 @@ var ( phase = phaseConfigureWifi host = "192.168.42.1" ssid = "" - security = string(reach.SecurityWPAPSK) + security = string(updater.SecurityWPAPSK) password = "" ) @@ -51,20 +52,20 @@ func main() { } -func connect() *reach.Updater { +func connect() *updater.Client { - updater := reach.NewUpdaterClient( - reach.WithEndpoint(host, 80), + c := updater.NewClient( + emlid.WithEndpoint(host, 80), ) log.Printf("connecting to module '%s'", host) - if err := updater.Connect(); err != nil { + if err := c.Connect(); err != nil { log.Fatal(err) } log.Println("connected") - return updater + return c } @@ -74,11 +75,11 @@ func configureWifi() { log.Fatal("you must provide a WiFi SSID with the -ssid flag") } - updater := connect() - defer updater.Close() + c := connect() + defer c.Close() log.Println("checking module status") - results, err := updater.TestResults() + results, err := c.TestResults() if err != nil { log.Fatal(err) } @@ -91,7 +92,7 @@ func configureWifi() { log.Printf("adding wifi network '%s'", ssid) - done, err := updater.AddWifiNetwork(ssid, reach.WifiSecurity(security), password) + done, err := c.AddWifiNetwork(ssid, updater.WifiSecurity(security), password) if err != nil { log.Fatal(err) } @@ -101,7 +102,7 @@ func configureWifi() { } log.Println("connecting module to wifi network") - if err := updater.JoinWifiNetwork(ssid, true); err != nil { + if err := c.JoinWifiNetwork(ssid, true); err != nil { log.Fatal(err) } log.Printf("you can now switch to the wifi network and start phase '%s'", phaseUpdateThenReboot) @@ -109,25 +110,26 @@ func configureWifi() { } func updateThenReboot() { - updater := connect() - defer updater.Close() + + c := connect() + defer c.Close() log.Println("checking time sync") - synced, err := updater.TimeSynced() + synced, err := c.TimeSynced() if err != nil { log.Fatal(err) } log.Printf("time synced ? %v", synced) log.Println("checking reachview version") - version, err := updater.ReachViewVersion() + version, err := c.ReachViewVersion() if err != nil { log.Fatal(err) } log.Printf("reachview version ? '%s'", version) log.Println("checking for update") - status, err := updater.Update() + status, err := c.Update() if err != nil { log.Fatal(err) } @@ -141,7 +143,7 @@ func updateThenReboot() { } log.Println("rebooting device") - if err := updater.RebootNow(true); err != nil { + if err := c.RebootNow(true); err != nil { log.Fatal(err) } diff --git a/reach/browser_connected.go b/reach/browser_connected.go deleted file mode 100644 index a773d5b..0000000 --- a/reach/browser_connected.go +++ /dev/null @@ -1,26 +0,0 @@ -package reach - -import ( - "github.com/pkg/errors" -) - -const ( - // EventBrowserConnected is emitted after the initial connection to the - // ReachView endpoint - eventBrowserConnected = "browser connected" -) - -// sendBrowserConnected notifies the ReachView endpoint -// of a new connection. -// See misc/reachview/update_main.js line 297 -func (c *client) sendBrowserConnected() error { - payload := map[string]string{ - "data": "I'm connected", - } - c.logf("sending '%s' event", eventBrowserConnected) - if err := c.conn.Emit(eventBrowserConnected, payload); err != nil { - return errors.Wrapf(err, "error while emitting '%s' event", eventBrowserConnected) - } - c.logf("'%s' event sent", eventBrowserConnected) - return nil -} diff --git a/reach/reachview.go b/reach/reachview.go deleted file mode 100644 index 2e9fa51..0000000 --- a/reach/reachview.go +++ /dev/null @@ -1,12 +0,0 @@ -package reach - -// ReachView is a ReachRS Updater client -type ReachView struct { // nolint: golint - *client -} - -// NewReachViewClient returns a new ReachRS ReachView client -func NewReachViewClient(opts ...OptionFunc) *ReachView { - client := newClient(opts...) - return &ReachView{client} -} diff --git a/reach/reachview_version.go b/reach/reachview_version.go deleted file mode 100644 index db9b8c6..0000000 --- a/reach/reachview_version.go +++ /dev/null @@ -1,49 +0,0 @@ -package reach - -import ( - "sync" - - "forge.cadoles.com/Pyxis/golang-socketio" - "github.com/pkg/errors" -) - -const ( - eventGetReachViewVersion = "get reachview version" - eventReachViewVersionResults = "current reachview version" -) - -type reachViewVersion struct { - Version string `json:"version"` -} - -// ReachViewVersion returns the ReachRS module ReachView version -func (u *Updater) ReachViewVersion() (string, error) { - - var err error - var version string - var wg sync.WaitGroup - - wg.Add(1) - - err = u.conn.On(eventReachViewVersionResults, func(h *gosocketio.Channel, rv *reachViewVersion) { - version = rv.Version - u.conn.Off(eventReachViewVersionResults) - wg.Done() - }) - if err != nil { - return "", errors.Wrapf(err, "error while binding to '%s' event", eventReachViewVersionResults) - } - - u.logf("sending '%s' event", eventGetReachViewVersion) - if err = u.conn.Emit(eventGetReachViewVersion, nil); err != nil { - return "", errors.Wrapf(err, "error while emitting '%s' event", eventGetReachViewVersion) - } - u.logf("'%s' event sent", eventGetReachViewVersion) - - wg.Wait() - - u.logf("reachview version result: %v", version) - - return version, err - -} diff --git a/reach/receiver_upgrade.go b/reach/receiver_upgrade.go deleted file mode 100644 index 79b9630..0000000 --- a/reach/receiver_upgrade.go +++ /dev/null @@ -1,49 +0,0 @@ -package reach - -import ( - "sync" - - "forge.cadoles.com/Pyxis/golang-socketio" - "github.com/pkg/errors" -) - -const ( - eventIsReceiverUpgradeAvailable = "is receiver upgrade available" - eventReceiverUpgradeAvailable = "receiver upgrade available" -) - -type receiverUpgreAvailable struct { - Available bool `json:"available"` - Running bool `json:"running"` -} - -// ReceiverUpgradeAvailable checks if an upgrade is avaialable/running for the ReachRS module -func (u *Updater) ReceiverUpgradeAvailable() (available bool, running bool, err error) { - - var wg sync.WaitGroup - - wg.Add(1) - - err = u.conn.On(eventReceiverUpgradeAvailable, func(h *gosocketio.Channel, up *receiverUpgreAvailable) { - available = up.Available - running = up.Running - u.conn.Off(eventReceiverUpgradeAvailable) - wg.Done() - }) - if err != nil { - return false, false, errors.Wrapf(err, "error while binding to '%s' event", eventReceiverUpgradeAvailable) - } - - u.logf("sending '%s' event", eventIsReceiverUpgradeAvailable) - if err = u.conn.Emit(eventIsReceiverUpgradeAvailable, nil); err != nil { - return false, false, errors.Wrapf(err, "error while emitting '%s' event", eventIsReceiverUpgradeAvailable) - } - u.logf("'%s' event sent", eventIsReceiverUpgradeAvailable) - - wg.Wait() - - u.logf("receiver upgrade result: available: %v, running: %v", available, running) - - return available, running, err - -} diff --git a/reach/test_results.go b/reach/test_results.go deleted file mode 100644 index d7ee808..0000000 --- a/reach/test_results.go +++ /dev/null @@ -1,53 +0,0 @@ -package reach - -import ( - "sync" - - "forge.cadoles.com/Pyxis/golang-socketio" - "github.com/pkg/errors" -) - -const ( - eventGetTestResults = "get test results" - eventTestResults = "test results" -) - -// TestResults are the ReachRS module's test results -// -type TestResults struct { - Device string `json:"device"` - Lora bool `json:"lora"` - MPU bool `json:"mpu"` - STC bool `json:"stc"` - UBlox bool `json:"u-blox"` -} - -// TestResults returns the ReachRS module tests results -func (u *Updater) TestResults() (*TestResults, error) { - - var err error - var results *TestResults - var wg sync.WaitGroup - - wg.Add(1) - - err = u.conn.On(eventTestResults, func(h *gosocketio.Channel, res *TestResults) { - results = res - u.conn.Off(eventTestResults) - wg.Done() - }) - if err != nil { - return nil, errors.Wrapf(err, "error while binding to '%s' event", eventTestResults) - } - - u.logf("sending '%s' event", eventGetTestResults) - if err = u.conn.Emit(eventGetTestResults, nil); err != nil { - return nil, errors.Wrapf(err, "error while emitting '%s' event", eventGetTestResults) - } - u.logf("'%s' event sent", eventGetTestResults) - - wg.Wait() - - return results, err - -} diff --git a/reach/time_sync.go b/reach/time_sync.go deleted file mode 100644 index b4e90eb..0000000 --- a/reach/time_sync.go +++ /dev/null @@ -1,50 +0,0 @@ -package reach - -import ( - "sync" - - "forge.cadoles.com/Pyxis/golang-socketio" - "github.com/pkg/errors" -) - -const ( - eventGetTimeSyncStatus = "get time sync status" - eventTimeSyncResults = "time sync status" -) - -type timeSyncStatus struct { - Status bool `json:"status"` -} - -// TimeSynced returns the ReachRS module time synchronization status. -// A true response means that the module has synchronized its clock. -func (u *Updater) TimeSynced() (bool, error) { - - var err error - var synced bool - var wg sync.WaitGroup - - wg.Add(1) - - err = u.conn.On(eventTimeSyncResults, func(h *gosocketio.Channel, st *timeSyncStatus) { - synced = st.Status - u.conn.Off(eventTimeSyncResults) - wg.Done() - }) - if err != nil { - return false, errors.Wrapf(err, "error while binding to '%s' event", eventTimeSyncResults) - } - - u.logf("sending '%s' event", eventGetTimeSyncStatus) - if err = u.conn.Emit(eventGetTimeSyncStatus, nil); err != nil { - return false, errors.Wrapf(err, "error while emitting '%s' event", eventGetTimeSyncStatus) - } - u.logf("'%s' event sent", eventGetTimeSyncStatus) - - wg.Wait() - - u.logf("time sync result: %v", synced) - - return synced, err - -} diff --git a/reach/update.go b/reach/update.go deleted file mode 100644 index 0d8d445..0000000 --- a/reach/update.go +++ /dev/null @@ -1,55 +0,0 @@ -package reach - -import ( - "sync" - - "forge.cadoles.com/Pyxis/golang-socketio" - "github.com/pkg/errors" -) - -const ( - eventUpdate = "update" - eventOPKGUpdateResult = "opkg update result" -) - -// UpdateStatus embeds informations about update status -type UpdateStatus struct { - Active bool `json:"active"` - Locked bool `json:"locked"` - State string `json:"state"` -} - -// Update asks the ReachRS module to start an OPKG update -func (u *Updater) Update() (*UpdateStatus, error) { - - var err error - var status *UpdateStatus - var wg sync.WaitGroup - - wg.Add(1) - - err = u.conn.On(eventOPKGUpdateResult, func(h *gosocketio.Channel, st *UpdateStatus) { - status = st - u.conn.Off(eventOPKGUpdateResult) - wg.Done() - }) - if err != nil { - return nil, errors.Wrapf(err, "error while binding to '%s' event", eventOPKGUpdateResult) - } - - u.logf("sending '%s' event", eventUpdate) - if err = u.conn.Emit(eventUpdate, nil); err != nil { - return nil, errors.Wrapf(err, "error while emitting '%s' event", eventUpdate) - } - u.logf("'%s' event sent", eventUpdate) - - wg.Wait() - - u.logf( - "opkg update result: active: %v, state: %v, locked: %v", - status.Active, status.State, status.Locked, - ) - - return status, err - -} diff --git a/reach/updater.go b/reach/updater.go deleted file mode 100644 index 888790d..0000000 --- a/reach/updater.go +++ /dev/null @@ -1,12 +0,0 @@ -package reach - -// Updater is a ReachRS Updater client -type Updater struct { - *client -} - -// NewUpdaterClient returns a new ReachRS Updater client -func NewUpdaterClient(opts ...OptionFunc) *Updater { - client := newClient(opts...) - return &Updater{client} -} diff --git a/reach/wifi_networks.go b/reach/wifi_networks.go deleted file mode 100644 index eac96c0..0000000 --- a/reach/wifi_networks.go +++ /dev/null @@ -1,171 +0,0 @@ -package reach - -import ( - "sync" - - "forge.cadoles.com/Pyxis/golang-socketio" - "github.com/pkg/errors" -) - -const ( - eventGetSavedWifiNetworks = "get saved wifi networks" - eventSavedWifiNetworkResults = "wifi saved networks results" - eventAddWifiNetwork = "add new network" - eventAddWifiNetworkResults = "add network results" - eventRemoveWifiNetwork = "remove network" - eventRemoveWifiNetworkResults = "remove network results" - eventConnectToNetwork = "connect to network" -) - -// WifiSecurity is a WiFi network security algorithm -type WifiSecurity string - -const ( - // SecurityWEP WEP wifi network - SecurityWEP WifiSecurity = "wep" - // SecurityWPAPSK WPA(2)-PSK wifi network - SecurityWPAPSK WifiSecurity = "wpa-psk" - // SecurityOpen Open wifi network - SecurityOpen WifiSecurity = "open" -) - -// WifiNetwork is a ReachRS module wifi network -type WifiNetwork struct { - SSID string `json:"ssid"` - Password string `json:"password"` - Security WifiSecurity `json:"security"` - Identity string `json:"identity"` - Visible bool `json:"is_visible"` - Connected bool `json:"is_connected"` - Added bool `json:"is_added"` -} - -// WifiNetworks returns the ReachRS module wifi networks -func (u *Updater) WifiNetworks() ([]*WifiNetwork, error) { - - var err error - var wifiNetworks []*WifiNetwork - var wg sync.WaitGroup - - wg.Add(1) - - err = u.conn.On(eventSavedWifiNetworkResults, func(h *gosocketio.Channel, wn []*WifiNetwork) { - wifiNetworks = wn - u.conn.Off(eventSavedWifiNetworkResults) - wg.Done() - }) - if err != nil { - return nil, errors.Wrapf(err, "error while binding to '%s' event", eventSavedWifiNetworkResults) - } - - u.logf("sending '%s' event", eventGetSavedWifiNetworks) - if err = u.conn.Emit(eventGetSavedWifiNetworks, nil); err != nil { - return nil, errors.Wrapf(err, "error while emitting '%s' event", eventGetSavedWifiNetworks) - } - u.logf("'%s' event sent", eventGetSavedWifiNetworks) - - wg.Wait() - - return wifiNetworks, err - -} - -// AddWifiNetwork asks the ReachRS module to save the given wifi network informations -func (u *Updater) AddWifiNetwork(ssid string, security WifiSecurity, password string) (bool, error) { - - var err error - var wg sync.WaitGroup - var done bool - - wg.Add(1) - - err = u.conn.On(eventAddWifiNetworkResults, func(h *gosocketio.Channel, d bool) { - done = d - u.conn.Off(eventAddWifiNetworkResults) - wg.Done() - }) - if err != nil { - return false, errors.Wrapf(err, "error while binding to '%s' event", eventAddWifiNetworkResults) - } - - wn := &WifiNetwork{ - SSID: ssid, - Security: security, - Password: password, - } - - u.logf("sending '%s' event", eventAddWifiNetwork) - if err = u.conn.Emit(eventAddWifiNetwork, wn); err != nil { - return false, errors.Wrapf(err, "error while emitting '%s' event", eventAddWifiNetwork) - } - u.logf("'%s' event sent", eventAddWifiNetwork) - - wg.Wait() - - return done, err - -} - -// RemoveWifiNetwork asks the ReachRS module to remove the given WiFi network -func (u *Updater) RemoveWifiNetwork(ssid string) (bool, error) { - - var err error - var wg sync.WaitGroup - var done bool - - wg.Add(1) - - err = u.conn.On(eventRemoveWifiNetworkResults, func(h *gosocketio.Channel, d bool) { - done = d - u.conn.Off(eventRemoveWifiNetworkResults) - wg.Done() - }) - if err != nil { - return false, errors.Wrapf(err, "error while binding to '%s' event", eventRemoveWifiNetworkResults) - } - - u.logf("sending '%s' event", eventRemoveWifiNetwork) - if err := u.conn.Emit(eventRemoveWifiNetwork, ssid); err != nil { - return false, errors.Wrapf(err, "error while emitting '%s' event", eventRemoveWifiNetwork) - } - u.logf("'%s' event sent", eventRemoveWifiNetwork) - - wg.Wait() - - return done, nil - -} - -// JoinWifiNetwork asks the ReachRS module to join the given WiFi network -func (u *Updater) JoinWifiNetwork(ssid string, waitDisconnect bool) error { - - var err error - var wg sync.WaitGroup - - if waitDisconnect { - - wg.Add(1) - - err = u.conn.On(gosocketio.OnDisconnection, func(h *gosocketio.Channel) { - u.conn.Off(gosocketio.OnDisconnection) - wg.Done() - }) - - if err != nil { - return errors.Wrapf(err, "error while binding to '%s' event", gosocketio.OnDisconnection) - } - - } - - u.logf("sending '%s' event", eventConnectToNetwork) - if err := u.conn.Emit(eventConnectToNetwork, ssid); err != nil { - return errors.Wrapf(err, "error while emitting '%s' event", eventConnectToNetwork) - } - u.logf("'%s' event sent", eventConnectToNetwork) - - if waitDisconnect { - wg.Wait() - } - - return nil -} From 1a04caafdf9d16c8c50b7388e3268976854af66c Mon Sep 17 00:00:00 2001 From: William Petit Date: Fri, 21 Sep 2018 15:39:21 +0200 Subject: [PATCH 8/8] Implements full configuration model --- emlid/reachview/configuration.go | 29 ---- emlid/reachview/configuration_model.go | 178 +++++++++++++++++++++++++ emlid/reachview/configuration_test.go | 3 + 3 files changed, 181 insertions(+), 29 deletions(-) create mode 100644 emlid/reachview/configuration_model.go diff --git a/emlid/reachview/configuration.go b/emlid/reachview/configuration.go index e95ef64..eae57b8 100644 --- a/emlid/reachview/configuration.go +++ b/emlid/reachview/configuration.go @@ -5,35 +5,6 @@ const ( eventCurrentConfiguration = "current configuration" ) -// Configuration is a configuration -type Configuration struct { - RTKSettings *RTKSettings `mapstructure:"rtk settings,omitempty"` -} - -// RTKSettings - -type RTKSettings struct { - GLONASSARMode string `mapstructure:"glonass ar mode"` - UpdateRate string `mapstructure:"update rate"` - ElevationMaskAngle string `mapstructure:"elevation mask angle"` - MaxHorizontalAcceleration string `mapstructure:"max horizontal acceleration"` - SNRMask string `mapstructure:"snr mask"` - GPSARMode string `mapstructure:"gps ar mode"` - PositionningMode string `mapstructure:"positioning mode"` - PositioningSystems *PositionningSystems `mapstructure:"positioning systems,omitempty"` - MaxVerticalAcceleration string `mapstructure:"max vertical acceleration"` -} - -// PositionningSystems - -type PositionningSystems struct { - GLONASS bool `json:"glonass"` - SBAS bool `json:"sbas"` - QZS bool `json:"qzs"` - QZSS bool `json:"qzss"` - Compass bool `json:"compass"` - Galileo bool `json:"galileo"` - GPS bool `json:"gps"` -} - // Configuration fetches and return the current configuration of the ReachRS module func (r *Client) Configuration() (*Configuration, error) { configuration := &Configuration{} diff --git a/emlid/reachview/configuration_model.go b/emlid/reachview/configuration_model.go new file mode 100644 index 0000000..1fd72ca --- /dev/null +++ b/emlid/reachview/configuration_model.go @@ -0,0 +1,178 @@ +package reachview + +// Configuration - +type Configuration struct { + RTKSettings *RTKSettings `mapstructure:"rtk settings,omitempty"` + CorrectionInput *CorrectionInput `mapstructure:"correction input,omitempty"` + PositionOutput *PositionOutput `mapstructure:"position output,omitempty"` + BaseMode *BaseMode `mapstructure:"base mode,omitempty"` + Logging *Logging `mapstructure:"logging,omitempty"` + Bluetooth *Bluetooth `mapstructure:"bluetooth,omitempty"` + LoRa *LoRa `mapstructure:"lora,omitempty"` + Constraints *Constraints `mapstructure:"constraints,omitempty"` +} + +// RTKSettings - +type RTKSettings struct { + GLONASSARMode string `mapstructure:"glonass ar mode"` + UpdateRate string `mapstructure:"update rate"` + ElevationMaskAngle string `mapstructure:"elevation mask angle"` + MaxHorizontalAcceleration string `mapstructure:"max horizontal acceleration"` + SNRMask string `mapstructure:"snr mask"` + GPSARMode string `mapstructure:"gps ar mode"` + PositionningMode string `mapstructure:"positioning mode"` + PositioningSystems *PositionningSystems `mapstructure:"positioning systems,omitempty"` + MaxVerticalAcceleration string `mapstructure:"max vertical acceleration"` +} + +// PositionningSystems - +type PositionningSystems struct { + GLONASS bool `mapstructure:"glonass"` + SBAS bool `mapstructure:"sbas"` + QZS bool `mapstructure:"qzs"` + QZSS bool `mapstructure:"qzss"` + Compass bool `mapstructure:"compass"` + Galileo bool `mapstructure:"galileo"` + GPS bool `mapstructure:"gps"` +} + +// CorrectionInput - +type CorrectionInput struct { + Input2 *Input2 `mapstructure:"input2,omitempty"` + Input3 *Input3 `mapstructure:"input3,omitempty"` +} + +// Input - +type Input struct { + Path string `mapstructure:"path"` + Type string `mapstructure:"type"` + Enabled bool `mapstructure:"enabled"` + Format string `mapstructure:"format"` +} + +// Input2 - +type Input2 struct { + Input `mapstructure:",squash"` + SendPositionToBase string `mapstructure:"send position to base"` +} + +// Input3 - +type Input3 struct { + Input `mapstructure:",squash"` +} + +// PositionOutput - +type PositionOutput struct { + Output1 *Output `mapstructure:"output1,omitempty"` + Output2 *Output `mapstructure:"output2,omitempty"` + Output3 *Output `mapstructure:"output3,omitempty"` + Output4 *Output `mapstructure:"output4,omitempty"` +} + +// Output - +type Output struct { + Path string `mapstructure:"path"` + Type string `mapstructure:"type"` + Enabled bool `mapstructure:"enabled"` + Format string `mapstructure:"format"` +} + +// BaseMode - +type BaseMode struct { + Output *Output `mapstructure:"output,omitempty"` + BaseCoordinates *BaseCoordinates `mapstructure:"base coordinates,omitempty"` + RTCM3Messages *RTCM3Messages `mapstructure:"rtcm3 messages,omitempty"` +} + +// BaseCoordinates - +type BaseCoordinates struct { + Format string `mapstructure:"format"` + AntennaOffset *AntennaOffset `mapstructure:"antenna offset,omitempty"` + Accumulation string `mapstructure:"accumulation"` + Coordinates []string `mapstructure:"coordinates"` + Mode string `mapstructure:"mode"` +} + +// AntennaOffset - +type AntennaOffset struct { + East string `mapstructure:"east"` + North string `mapstructure:"north"` + Up string `mapstructure:"up"` +} + +// RTCM3Messages - +type RTCM3Messages struct { + // GPS L1 code and phase and ambiguities and carrier-to-noise ratio + Type1002 *RTCMMessageType `mapstructure:"1002,omitemtpy"` + // Station coordinates XYZ for antenna reference point and antenna height. + Type1006 *RTCMMessageType `mapstructure:"1006,omitemtpy"` + // Antenna serial number. + Type1008 *RTCMMessageType `mapstructure:"1008,omitemtpy"` + // GLONASS L1 code and phase and ambiguities and carrier-to-noise ratio. + Type1010 *RTCMMessageType `mapstructure:"1010,omitemtpy"` + // GPS ephemeris. + Type1019 *RTCMMessageType `mapstructure:"1019,omitemtpy"` + // GLONASS ephemeris. + Type1020 *RTCMMessageType `mapstructure:"1020,omitemtpy"` + // The type 7 Multiple Signal Message format for Europe’s Galileo system + Type1097 *RTCMMessageType `mapstructure:"1097,omitemtpy"` + // Full SBAS pseudo-ranges, carrier phases, Doppler and signal strength (high resolution) + Type1107 *RTCMMessageType `mapstructure:"1107,omitemtpy"` + // Full QZSS pseudo-ranges, carrier phases, Doppler and signal strength (high resolution) + Type1117 *RTCMMessageType `mapstructure:"1117,omitemtpy"` + // Full BeiDou pseudo-ranges, carrier phases, Doppler and signal strength (high resolution) + Type1127 *RTCMMessageType `mapstructure:"1127,omitemtpy"` +} + +// RTCMMessageType - +type RTCMMessageType struct { + Frequency string `mapstructure:"frequency"` + Enabled bool `mapstructure:"enabled"` +} + +// Logging - +type Logging struct { + Correction *LoggingService `mapstructure:"correction,omitempty"` + Interval int `mapstructure:"interval"` + Solution *LoggingService `mapstructure:"solution,omitempty"` + Raw *LoggingService `mapstructure:"raw,omitempty"` + Base *LoggingService `mapstructure:"base,omitempty"` + Overwrite bool `mapstructure:"overwrite"` +} + +// LoggingService - +type LoggingService struct { + Started bool `mapstructure:"started"` + Version string `mapstructure:"version"` + Format string `mapstructure:"format"` +} + +// Bluetooth - +type Bluetooth struct { + Enabled bool `mapstructure:"enabled"` + Discoverable bool `mapstructure:"discoverable"` + Pin int `mapstructure:"pin"` +} + +// LoRa - +type LoRa struct { + AirRate float64 `mapstructure:"air rate"` + Frequency int `mapstructure:"frequency"` + OutputPower int `mapstructure:"output power"` +} + +// Constraints - +type Constraints struct { + LoRa *LoRaConstraints `mapstructure:"lora,omitempty"` +} + +// LoRaConstraints - +type LoRaConstraints struct { + Frequency *LoRaFrequencyRange `mapstructure:"frequency,omitempty"` +} + +// LoRaFrequencyRange - +type LoRaFrequencyRange struct { + Min int `mapstructure:"min"` + Max int `mapstructure:"max"` +} diff --git a/emlid/reachview/configuration_test.go b/emlid/reachview/configuration_test.go index 32a7b33..bea31dd 100644 --- a/emlid/reachview/configuration_test.go +++ b/emlid/reachview/configuration_test.go @@ -4,6 +4,7 @@ import ( "testing" "forge.cadoles.com/Pyxis/orion/emlid" + "github.com/davecgh/go-spew/spew" ) func TestReachViewConfiguration(t *testing.T) { @@ -33,6 +34,8 @@ func TestReachViewConfiguration(t *testing.T) { t.Fatal("config.RTKSettings should not be nil") } + spew.Dump(config) + defer client.Close() }