From a2d1c675d7dfec2c7a4bd39c51769367e1f45247 Mon Sep 17 00:00:00 2001 From: William Petit Date: Wed, 19 Sep 2018 13:00:08 +0200 Subject: [PATCH] WiFi networks management API --- Makefile | 2 +- go.mod | 2 +- go.sum | 4 +- modd.conf | 1 + reach/test_results.go | 23 +-- .../{client_test.go => test_results_test.go} | 2 +- reach/wifi_networks.go | 148 ++++++++++++++++++ reach/wifi_networks_test.go | 75 +++++++++ 8 files changed, 241 insertions(+), 16 deletions(-) rename reach/{client_test.go => test_results_test.go} (89%) create mode 100644 reach/wifi_networks.go create mode 100644 reach/wifi_networks_test.go diff --git a/Makefile b/Makefile index 09fb3c9..8660d7b 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ test: tidy go test -mod=vendor -v ./... lint: - @PATH=$(PATH):./bin/gometalinter gometalinter -e '.*/pkg/mod' -e ".*/go/src" --vendor ./... + @PATH=$(PATH):./bin/gometalinter gometalinter -e '.*/pkg/mod' -e ".*/go/src" --vendor $(LINT_ARGS) ./... tidy: go mod tidy diff --git a/go.mod b/go.mod index a351cfb..08eb7a8 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module forge.cadoles.com/Pyxis/orion require ( - forge.cadoles.com/Pyxis/golang-socketio v0.0.0-20180919081902-52a9157a070d + forge.cadoles.com/Pyxis/golang-socketio v0.0.0-20180919100209-bb857ced6b95 github.com/caarlos0/env v3.3.0+incompatible github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-chi/chi v3.3.3+incompatible diff --git a/go.sum b/go.sum index bff80fd..4749ce9 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -forge.cadoles.com/Pyxis/golang-socketio v0.0.0-20180919081902-52a9157a070d h1:gkJw6IeJ+A/EVw48eUnZwbK36fBlDrfB5lNyEPAltLQ= -forge.cadoles.com/Pyxis/golang-socketio v0.0.0-20180919081902-52a9157a070d/go.mod h1:I6kYOFWNkFlNeQLI7ZqfTRz4NdPHZxX0Bzizmzgchs0= +forge.cadoles.com/Pyxis/golang-socketio v0.0.0-20180919100209-bb857ced6b95 h1:o3G5+9RjczCK1xAYFaRMknk1kY9Ule6PNfiW6N6hEpg= +forge.cadoles.com/Pyxis/golang-socketio v0.0.0-20180919100209-bb857ced6b95/go.mod h1:I6kYOFWNkFlNeQLI7ZqfTRz4NdPHZxX0Bzizmzgchs0= github.com/caarlos0/env v3.3.0+incompatible h1:jCfY0ilpzC2FFViyZyDKCxKybDESTwaR+ebh8zm6AOE= github.com/caarlos0/env v3.3.0+incompatible/go.mod h1:tdCsowwCzMLdkqRYDlHpZCp2UooDD3MspDBjZ2AD02Y= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= diff --git a/modd.conf b/modd.conf index fba3af3..b69c775 100644 --- a/modd.conf +++ b/modd.conf @@ -11,6 +11,7 @@ Makefile { **/*.go modd.conf Makefile { + prep: make lint LINT_ARGS=--fast prep: make test } diff --git a/reach/test_results.go b/reach/test_results.go index 2ceb7bb..7a721f2 100644 --- a/reach/test_results.go +++ b/reach/test_results.go @@ -8,10 +8,8 @@ import ( ) const ( - // EventGetTestResults is a request for the ReachRS module's test results - EventGetTestResults = "get test results" - // EventTestResults is the response of the EventGetTestResults request - EventTestResults = "test results" + eventGetTestResults = "get test results" + eventTestResults = "test results" ) // TestResults are the ReachRS module's test results @@ -32,17 +30,20 @@ func (c *Client) TestResults() (*TestResults, error) { wg.Add(1) - c.conn.On(EventTestResults, func(h *gosocketio.Channel, res *TestResults) { + err = c.conn.On(eventTestResults, func(h *gosocketio.Channel, res *TestResults) { results = res - c.conn.On(EventTestResults, nil) + c.conn.Off(eventTestResults) wg.Done() }) - - c.logf("sending '%s' event", EventGetTestResults) - if err = c.conn.Emit(EventGetTestResults, nil); err != nil { - return nil, errors.Wrapf(err, "error while emitting '%s' event", EventGetTestResults) + if err != nil { + return nil, errors.Wrapf(err, "error while binding to '%s' event", eventTestResults) } - c.logf("'%s' event sent", EventGetTestResults) + + c.logf("sending '%s' event", eventGetTestResults) + if err = c.conn.Emit(eventGetTestResults, nil); err != nil { + return nil, errors.Wrapf(err, "error while emitting '%s' event", eventGetTestResults) + } + c.logf("'%s' event sent", eventGetTestResults) wg.Wait() diff --git a/reach/client_test.go b/reach/test_results_test.go similarity index 89% rename from reach/client_test.go rename to reach/test_results_test.go index 658b98e..5dbcf29 100644 --- a/reach/client_test.go +++ b/reach/test_results_test.go @@ -4,7 +4,7 @@ import ( "testing" ) -func TestClient(t *testing.T) { +func TestClientTestResults(t *testing.T) { client := NewClient( WithStandardLogger(), diff --git a/reach/wifi_networks.go b/reach/wifi_networks.go new file mode 100644 index 0000000..ce8f2f2 --- /dev/null +++ b/reach/wifi_networks.go @@ -0,0 +1,148 @@ +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 ( + // SecurityWPAPSK WPA-PSK wifi network + SecurityWPAPSK WifiSecurity = "wpa-psk" + // SecurityOpen Open wifi network + SecurityOpen WifiSecurity = "open" +) + +// WifiNetwork is a ReachRS module's saved wifi network +// Raw messages examples: +// [{"ssid":"Cadoles","password":"...","security":"wpa-psk","identity":""}] +// [{"is_visible":false,"connected":false,"ssid":"Cadoles","security":"wpa-psk","is_connected":false,"is_added":true}]] +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"` +} + +// SavedWifiNetworks returns the ReachRS module saved wifi networks +func (c *Client) SavedWifiNetworks() ([]*WifiNetwork, error) { + + var err error + var wifiNetworks []*WifiNetwork + var wg sync.WaitGroup + + wg.Add(1) + + err = c.conn.On(eventSavedWifiNetworkResults, func(h *gosocketio.Channel, wn []*WifiNetwork) { + wifiNetworks = wn + c.conn.Off(eventSavedWifiNetworkResults) + wg.Done() + }) + if err != nil { + return nil, errors.Wrapf(err, "error while binding to '%s' event", eventSavedWifiNetworkResults) + } + + c.logf("sending '%s' event", eventGetSavedWifiNetworks) + if err = c.conn.Emit(eventGetSavedWifiNetworks, nil); err != nil { + return nil, errors.Wrapf(err, "error while emitting '%s' event", eventGetSavedWifiNetworks) + } + c.logf("'%s' event sent", eventGetSavedWifiNetworks) + + wg.Wait() + + return wifiNetworks, err + +} + +// AddWifiNetwork asks the ReachRS module to save the given wifi network informations +func (c *Client) AddWifiNetwork(ssid string, security WifiSecurity, password string) (bool, error) { + + var err error + var wg sync.WaitGroup + var done bool + + wg.Add(1) + + err = c.conn.On(eventAddWifiNetworkResults, func(h *gosocketio.Channel, d bool) { + done = d + c.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, + } + + c.logf("sending '%s' event", eventAddWifiNetwork) + if err = c.conn.Emit(eventAddWifiNetwork, wn); err != nil { + return false, errors.Wrapf(err, "error while emitting '%s' event", eventAddWifiNetwork) + } + c.logf("'%s' event sent", eventAddWifiNetwork) + + wg.Wait() + + return done, err + +} + +// RemoveWifiNetwork asks the ReachRS module to remove the given WiFi network +func (c *Client) RemoveWifiNetwork(ssid string) (bool, error) { + + var err error + var wg sync.WaitGroup + var done bool + + wg.Add(1) + + err = c.conn.On(eventRemoveWifiNetworkResults, func(h *gosocketio.Channel, d bool) { + done = d + c.conn.Off(eventRemoveWifiNetworkResults) + wg.Done() + }) + if err != nil { + return false, errors.Wrapf(err, "error while binding to '%s' event", eventRemoveWifiNetworkResults) + } + + c.logf("sending '%s' event", eventRemoveWifiNetwork) + if err := c.conn.Emit(eventRemoveWifiNetwork, ssid); err != nil { + return false, errors.Wrapf(err, "error while emitting '%s' event", eventRemoveWifiNetwork) + } + c.logf("'%s' event sent", eventRemoveWifiNetwork) + + wg.Wait() + + return done, nil + +} + +// ConnectToWifiNetwork asks the ReachRS module to connect to the given WiFi network +func (c *Client) ConnectToWifiNetwork(ssid string) error { + c.logf("sending '%s' event", eventConnectToNetwork) + if err := c.conn.Emit(eventConnectToNetwork, ssid); err != nil { + return errors.Wrapf(err, "error while emitting '%s' event", eventConnectToNetwork) + } + c.logf("'%s' event sent", eventConnectToNetwork) + return nil +} diff --git a/reach/wifi_networks_test.go b/reach/wifi_networks_test.go new file mode 100644 index 0000000..667e669 --- /dev/null +++ b/reach/wifi_networks_test.go @@ -0,0 +1,75 @@ +package reach + +import ( + "fmt" + "math/rand" + "testing" +) + +func TestClientSavedWiFiNetworks(t *testing.T) { + + client := NewClient( + WithStandardLogger(), + ) + if err := client.Connect(); err != nil { + t.Fatal(err) + } + + _, err := client.SavedWifiNetworks() + if err != nil { + t.Error(err) + } + + defer client.Close() + +} + +func TestClientCRUDWiFiNetwork(t *testing.T) { + + client := NewClient( + WithStandardLogger(), + ) + if err := client.Connect(); err != nil { + t.Fatal(err) + } + + ssid := fmt.Sprintf("wifi_test_%d", rand.Uint32()) + + done, err := client.AddWifiNetwork(ssid, SecurityOpen, "") + if err != nil { + t.Error(err) + } + + if g, e := done, true; g != e { + t.Errorf("AddWifiNetwork() -> done: got '%v', expected '%v'", g, e) + } + + networks, err := client.SavedWifiNetworks() + if err != nil { + t.Error(err) + } + + found := false + for _, n := range networks { + if n.SSID == ssid { + found = true + break + } + } + + if g, e := found, true; g != e { + t.Errorf("wifi network '%s' should exists", ssid) + } + + done, err = client.RemoveWifiNetwork(ssid) + if err != nil { + t.Error(err) + } + + if g, e := done, true; g != e { + t.Errorf("RemoveWifiNetwork() -> done: got '%v', expected '%v'", g, e) + } + + defer client.Close() + +}