Base de client ReachRS fonctionnelle
This commit is contained in:
parent
267017bdc1
commit
cd27332c4f
16
Makefile
16
Makefile
|
@ -2,21 +2,25 @@ export GO111MODULE := on
|
||||||
|
|
||||||
build: bin/server
|
build: bin/server
|
||||||
|
|
||||||
bin/server: vendor
|
bin/server:
|
||||||
CGO_ENABLED=0 go build -v -o ./bin/server ./cmd/server
|
CGO_ENABLED=0 go build -mod=vendor -v -o ./bin/server ./cmd/server
|
||||||
|
|
||||||
watch:
|
watch:
|
||||||
modd
|
modd
|
||||||
|
|
||||||
test:
|
test: tidy
|
||||||
go test -v ./...
|
GO111MODULE=off go clean -testcache
|
||||||
|
go test -mod=vendor -v ./...
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
PATH=$(PATH):./bin/gometalinter gometalinter -e '.*/pkg/mod' --vendor ./...
|
PATH=$(PATH):./bin/gometalinter gometalinter -e '.*/pkg/mod' --vendor ./...
|
||||||
|
|
||||||
vendor:
|
tidy:
|
||||||
go mod tidy
|
go mod tidy
|
||||||
|
|
||||||
|
vendor: tidy
|
||||||
|
go mod vendor
|
||||||
|
|
||||||
install-devtools: vendor
|
install-devtools: vendor
|
||||||
# Install modd
|
# Install modd
|
||||||
GO111MODULE=off go get -u github.com/cortesi/modd/cmd/modd
|
GO111MODULE=off go get -u github.com/cortesi/modd/cmd/modd
|
||||||
|
@ -27,4 +31,4 @@ clean:
|
||||||
rm -rf ./bin
|
rm -rf ./bin
|
||||||
go clean -i -x -r -modcache
|
go clean -i -x -r -modcache
|
||||||
|
|
||||||
.PHONY: test clean generate vendor install-devtools lint watch
|
.PHONY: test clean generate vendor install-devtools lint watch tidy
|
|
@ -0,0 +1,14 @@
|
||||||
|
# Débugger la communication websocket avec ReachView
|
||||||
|
|
||||||
|
|
||||||
|
## Intercepter les connexions sur le module ReachRS
|
||||||
|
|
||||||
|
Il est possible d'intercepter et logger les communications sur la connexion websocket de ReachView.
|
||||||
|
|
||||||
|
Pour ce faire, se connecter en SSH sur le module ReachRS et lancer la commande:
|
||||||
|
|
||||||
|
```
|
||||||
|
tcpdump -nl -w - -i wlan0 -c 500 port 80|strings
|
||||||
|
```
|
||||||
|
|
||||||
|
## Intercepter les connexions sortantes depuis la machine de test
|
3
go.mod
3
go.mod
|
@ -1,9 +1,12 @@
|
||||||
module forge.cadoles.com/Pyxis/orion
|
module forge.cadoles.com/Pyxis/orion
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
forge.cadoles.com/Pyxis/golang-socketio v0.0.0-20180918160219-85050e6154f1
|
||||||
github.com/caarlos0/env v3.3.0+incompatible
|
github.com/caarlos0/env v3.3.0+incompatible
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/go-chi/chi v3.3.3+incompatible
|
github.com/go-chi/chi v3.3.3+incompatible
|
||||||
|
github.com/gorilla/websocket v1.4.0 // indirect
|
||||||
|
github.com/pkg/errors v0.8.0
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/stretchr/testify v1.2.2 // indirect
|
github.com/stretchr/testify v1.2.2 // indirect
|
||||||
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3 // indirect
|
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3 // indirect
|
||||||
|
|
6
go.sum
6
go.sum
|
@ -1,9 +1,15 @@
|
||||||
|
forge.cadoles.com/Pyxis/golang-socketio v0.0.0-20180918160219-85050e6154f1 h1:T/50zBZ+rLp9q7ntXpkKkiLBp5h8J5BnrHO6dbZUNqo=
|
||||||
|
forge.cadoles.com/Pyxis/golang-socketio v0.0.0-20180918160219-85050e6154f1/go.mod h1:I6kYOFWNkFlNeQLI7ZqfTRz4NdPHZxX0Bzizmzgchs0=
|
||||||
github.com/caarlos0/env v3.3.0+incompatible h1:jCfY0ilpzC2FFViyZyDKCxKybDESTwaR+ebh8zm6AOE=
|
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/caarlos0/env v3.3.0+incompatible/go.mod h1:tdCsowwCzMLdkqRYDlHpZCp2UooDD3MspDBjZ2AD02Y=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/go-chi/chi v3.3.3+incompatible h1:KHkmBEMNkwKuK4FdQL7N2wOeB9jnIx7jR5wsuSBEFI8=
|
github.com/go-chi/chi v3.3.3+incompatible h1:KHkmBEMNkwKuK4FdQL7N2wOeB9jnIx7jR5wsuSBEFI8=
|
||||||
github.com/go-chi/chi v3.3.3+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
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/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=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||||
|
|
|
@ -0,0 +1,823 @@
|
||||||
|
/**
|
||||||
|
* ReachView code is placed under the GPL license.
|
||||||
|
* Written by Egor Fedorov (egor.fedorov@emlid.com) and Danil Kramorov (danil.kramorov@emlid.com)
|
||||||
|
* Copyright (c) 2015-2018, Emlid Limited
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* If you are interested in using ReachView code as a part of a
|
||||||
|
* closed source project, please contact Emlid Limited (info@emlid.com).
|
||||||
|
*
|
||||||
|
* This file is part of ReachView.
|
||||||
|
*
|
||||||
|
* ReachView is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* ReachView is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with ReachView. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
requirejs(['socket', 'bootstrap_select'], function (io, bootstrap_select) {
|
||||||
|
var lostConnectionNoty;
|
||||||
|
var addConnectionNoty;
|
||||||
|
var removeConnetctionNoty;
|
||||||
|
var emptyRequiredModal = false;
|
||||||
|
var incorrectSymbolsNumber = false;
|
||||||
|
var incorrectSymbols = false;
|
||||||
|
var syncInterval;
|
||||||
|
var new_network = {};
|
||||||
|
var to_append = '';
|
||||||
|
|
||||||
|
var testPass = false;
|
||||||
|
var wifiPass = false;
|
||||||
|
var timePass = false;
|
||||||
|
var receiverPass = false;
|
||||||
|
var updatePass = false;
|
||||||
|
|
||||||
|
var currentVersion = false;
|
||||||
|
var availableReceiverVersion = false;
|
||||||
|
var availableVersion = false;
|
||||||
|
var opkgResult = false;
|
||||||
|
var receiverLocked = false;
|
||||||
|
|
||||||
|
var device = '';
|
||||||
|
var preventLostConnectionNoty = false;
|
||||||
|
|
||||||
|
var disconnect_msg = 'Lost connection with Reach. Please check your network, then try refreshing the page.';
|
||||||
|
|
||||||
|
$('.bootstrap-select').selectpicker();
|
||||||
|
$('.styled, .multiselect-container input').uniform({ radioClass: 'choice' });
|
||||||
|
|
||||||
|
$(document).on('click', '#create_new_network', function () {
|
||||||
|
$(this).parents('.modal-content').find('.required_field:visible').each(function () {
|
||||||
|
if ($.trim($(this).val()) === '') {
|
||||||
|
emptyRequiredModal = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($('#new_network_pass:visible').length !== 0) {
|
||||||
|
if ($('#new_network_pass').val().length < 8) {
|
||||||
|
incorrectSymbolsNumber = true;
|
||||||
|
} else {
|
||||||
|
incorrectSymbolsNumber = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
incorrectSymbolsNumber = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emptyRequiredModal) {
|
||||||
|
$(this).parents('.modal-content').find('.required_field:visible')
|
||||||
|
.filter(function () { return $.trim($(this).val()) === ''; }).css('border', '1px solid red');
|
||||||
|
$(this).parents('.modal-content').find('.required_field')
|
||||||
|
.filter(function () { return $.trim($(this).val()) !== ''; }).css('border', '1px solid #ddd');
|
||||||
|
|
||||||
|
emptyRequiredModal = false;
|
||||||
|
} else {
|
||||||
|
$(this).parents('.modal-content').find('.required_field').css('border', '1px solid #ddd');
|
||||||
|
|
||||||
|
if (incorrectSymbols) {
|
||||||
|
$('.modal_add_warning').text('Incorrect symbols. Use only a-z, 1-9 characters.');
|
||||||
|
} else if (incorrectSymbolsNumber) {
|
||||||
|
$('.modal_add_warning').text('Password should contain at least 8 characters');
|
||||||
|
} else {
|
||||||
|
new_network['ssid'] = $('#new_network_name').val();
|
||||||
|
new_network['password'] = $('#new_network_pass').val();
|
||||||
|
new_network['security'] = $('#security_select').val();
|
||||||
|
new_network['identity'] = $('#new_network_identity').val();
|
||||||
|
|
||||||
|
$('#modal_network').modal('hide');
|
||||||
|
|
||||||
|
socket.emit('add new network', new_network);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('change', '#security_select', function () {
|
||||||
|
$('#new_network_identity').removeClass('required_field');
|
||||||
|
$('#new_network_identity').parents('.form-group').css('display', 'none');
|
||||||
|
|
||||||
|
$('#new_network_pass').addClass('required_field');
|
||||||
|
$('#new_network_pass').parents('.form-group').css('display', 'block');
|
||||||
|
$('#uniform-show_pass').parents('.form-group').css('display', 'block');
|
||||||
|
|
||||||
|
if ($(this).val() === 'open') {
|
||||||
|
$('#new_network_pass').removeClass('required_field');
|
||||||
|
$('#new_network_pass').parents('.form-group').css('display', 'none');
|
||||||
|
$('#uniform-show_pass').parents('.form-group').css('display', 'none');
|
||||||
|
} else if ($(this).val() == 'wpaeap') {
|
||||||
|
$('#new_network_identity').addClass('required_field');
|
||||||
|
$('#new_network_identity').parents('.form-group').css('display', 'block');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#modal_network').on('show.bs.modal', function () {
|
||||||
|
$('#new_network_name').val('');
|
||||||
|
$('#new_network_pass').val('');
|
||||||
|
$('#new_network_pass').attr('type', 'password');
|
||||||
|
$('#new_network_identity').val('');
|
||||||
|
$('#security_select').val('wpa-psk');
|
||||||
|
$('#security_select').selectpicker('refresh');
|
||||||
|
$('#show_pass').attr('checked', false);
|
||||||
|
$('#show_pass').parent().removeClass('checked');
|
||||||
|
$('.modal_add_warning').text('');
|
||||||
|
|
||||||
|
$('#security_select').change();
|
||||||
|
|
||||||
|
$('#modal_network input').css('border', '1px solid #ddd');
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('change', '#show_pass', function () {
|
||||||
|
if ($(this).is(':checked')) {
|
||||||
|
$('#new_network_pass').attr('type', 'text');
|
||||||
|
} else {
|
||||||
|
$('#new_network_pass').attr('type', 'password');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '#added_wi-fi li', function () {
|
||||||
|
if (!$(this).hasClass('connected_wi-fi_network')) {
|
||||||
|
$('#modal_saved_connect .network_title').text($(this).find('.wi-fi_title').text());
|
||||||
|
$('#modal_saved_connect .network_mac').text('Security: ' + $(this).find('.wi-fi_security').val());
|
||||||
|
$('#modal_saved_connect').modal('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '#connected_wi-fi li', function () {
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '#connect_network', function () {
|
||||||
|
var ssid_to_connect = $('#modal_saved_connect .network_title').text();
|
||||||
|
disconnect_msg = 'Reach is connecting to another network. Switch to ' + ssid_to_connect + ' to continue.';
|
||||||
|
|
||||||
|
socket.emit('connect to network', ssid_to_connect);
|
||||||
|
|
||||||
|
$('#modal_saved_connect').modal('hide');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '#forget_network', function () {
|
||||||
|
var ssid_to_remove = $('#modal_saved_connect .network_title').text();
|
||||||
|
socket.emit('remove network', ssid_to_remove);
|
||||||
|
|
||||||
|
$('#modal_saved_connect').modal('hide');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.update_reachview').on('click', function () {
|
||||||
|
if (!$(this).hasClass('disabled')) {
|
||||||
|
receiverPass = true;
|
||||||
|
|
||||||
|
socket.emit('upgrade reachview');
|
||||||
|
$('.current_version').text('Updating...');
|
||||||
|
$('.update_status').html('<i class="icon-spinner2 spinner text-warning"></i>');
|
||||||
|
$('.row_try_skip').css('display', 'none');
|
||||||
|
$('.skip_update_btn').css('display', 'none');
|
||||||
|
$('.update_reachview').addClass('disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.skip_update, .skip_update_btn').on('click', function () {
|
||||||
|
receiverPass = true;
|
||||||
|
|
||||||
|
socket.emit('skip update');
|
||||||
|
|
||||||
|
$('.update_status').html('<i class="icon-checkmark3 text-success"></i>');
|
||||||
|
$('.update_anchor:not(.collapsed)').click();
|
||||||
|
$('.row_try_skip').css('display', 'none');
|
||||||
|
$('.skip_update_btn').css('display', 'none');
|
||||||
|
|
||||||
|
updatePass = true;
|
||||||
|
|
||||||
|
if (updatePass && receiverPass && timePass && wifiPass && testPass) {
|
||||||
|
$('.to_app').removeClass('disabled');
|
||||||
|
} else {
|
||||||
|
$('.to_app').addClass('disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.try_again').on('click', function () {
|
||||||
|
receiverPass = true;
|
||||||
|
|
||||||
|
$('.row_try_skip').css('display', 'none');
|
||||||
|
|
||||||
|
currentVersion = false;
|
||||||
|
|
||||||
|
socket.emit('get reachview version');
|
||||||
|
$('.current_version').text('Getting current version...');
|
||||||
|
$('.update_status').html('<i class="icon-spinner2 spinner text-warning"></i>');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.to_app').on('click', function () {
|
||||||
|
if (!$(this).hasClass('disabled')) {
|
||||||
|
disconnect_msg = 'Reach is rebooting and has been disconnected from this network.';
|
||||||
|
|
||||||
|
noty({
|
||||||
|
width: 200,
|
||||||
|
text: 'Reboot will start in 3...',
|
||||||
|
type: 'information',
|
||||||
|
dismissQueue: true,
|
||||||
|
timeout: 3000,
|
||||||
|
closeWith: false,
|
||||||
|
layout: 'topRight',
|
||||||
|
callback: {
|
||||||
|
onClose: function () {
|
||||||
|
if (device === 'ReachM+' || device === 'ReachRS+') {
|
||||||
|
preventLostConnectionNoty = true;
|
||||||
|
$('#modal_mender_guide').modal({ backdrop: 'static', keyboard: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('reboot now');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(function () { $('.noty_text').text('Reboot will start in 2...'); }, 1000);
|
||||||
|
setTimeout(function () { $('.noty_text').text('Reboot will start in 1...'); }, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// SocketIO namespace:
|
||||||
|
socket = io();
|
||||||
|
|
||||||
|
socket.on('add network results', function (msg) {
|
||||||
|
if (msg) {
|
||||||
|
socket.emit('get saved wifi networks');
|
||||||
|
} else {
|
||||||
|
addConnectionNoty = noty({
|
||||||
|
width: 200,
|
||||||
|
text: 'Failed to add a new Wi-Fi connection',
|
||||||
|
type: 'error',
|
||||||
|
dismissQueue: true,
|
||||||
|
timeout: 4000,
|
||||||
|
closeWith: ['click'],
|
||||||
|
layout: 'topRight'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('remove network results', function (msg) {
|
||||||
|
if (msg) {
|
||||||
|
socket.emit('get saved wifi networks');
|
||||||
|
} else {
|
||||||
|
removeConnetctionNoty = noty({
|
||||||
|
width: 200,
|
||||||
|
text: 'Failed to remove network',
|
||||||
|
type: 'error',
|
||||||
|
dismissQueue: true,
|
||||||
|
timeout: 4000,
|
||||||
|
closeWith: ['click'],
|
||||||
|
layout: 'topRight'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// say hello on connect
|
||||||
|
socket.on('connect', function () {
|
||||||
|
socket.emit('browser connected', {data: 'I\'m connected'});
|
||||||
|
|
||||||
|
if (typeof lostConnectionNoty !== 'undefined') {
|
||||||
|
lostConnectionNoty.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('reconnect', function () {
|
||||||
|
$('.disconnect_overlay').fadeOut();
|
||||||
|
$('body').css('position', 'relative');
|
||||||
|
|
||||||
|
$(window).resize();
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('disconnect', function () {
|
||||||
|
if (preventLostConnectionNoty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.disconnect_overlay').fadeIn();
|
||||||
|
$('body').css('position', 'fixed');
|
||||||
|
|
||||||
|
lostConnectionNoty = noty({
|
||||||
|
width: 200,
|
||||||
|
text: disconnect_msg,
|
||||||
|
type: 'error',
|
||||||
|
dismissQueue: true,
|
||||||
|
timeout: false,
|
||||||
|
closeWith: false,
|
||||||
|
layout: 'topRight',
|
||||||
|
callback: {
|
||||||
|
onClose: function () {
|
||||||
|
$('.disconnect_overlay').fadeOut();
|
||||||
|
$('body').css('position', 'relative');
|
||||||
|
|
||||||
|
noty({
|
||||||
|
width: 200,
|
||||||
|
text: 'Reach reconnected!',
|
||||||
|
type: 'success',
|
||||||
|
dismissQueue: true,
|
||||||
|
closeWith: false,
|
||||||
|
timeout: 3000,
|
||||||
|
layout: 'topRight'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('connect_error', function () {
|
||||||
|
console.clear();
|
||||||
|
console.warn('Lost connection with sockets');
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.emit('get test results');
|
||||||
|
|
||||||
|
socket.on('reachview upgrade status', function (msg) {
|
||||||
|
if (!receiverPass) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.row_try_skip').css('display', 'none');
|
||||||
|
$('.skip_update_btn').css('display', 'none');
|
||||||
|
|
||||||
|
if (!$('.update_status i').hasClass('icon-spinner2')) {
|
||||||
|
$('.update_status').html('<i class="icon-spinner2 spinner text-warning"></i>');
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.available_version').css('display', 'none');
|
||||||
|
$('.update_reachview').addClass('disabled');
|
||||||
|
$('.coords_progress').css('display', 'block');
|
||||||
|
|
||||||
|
if (msg['active']) {
|
||||||
|
$('.current_version').text(msg['state'] + ' ' + msg['package'] + ' (' + msg['version'] + ')');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg['state'] === 'Downloading') {
|
||||||
|
$('.coords_progress .progress-bar').removeClass('progress-bar-striped active');
|
||||||
|
$('.coords_progress .progress-bar').css('width', msg['percentage'] + '%');
|
||||||
|
|
||||||
|
if (parseInt(msg['percentage']) > 30) {
|
||||||
|
$('.coords_progress .progress-bar span').text(msg['percentage'] + '%');
|
||||||
|
} else {
|
||||||
|
$('.coords_progress .progress-bar span').text('');
|
||||||
|
}
|
||||||
|
} else if (msg['state'] === 'Installing') {
|
||||||
|
$('.coords_progress .progress-bar').css('width', '100%');
|
||||||
|
$('.coords_progress .progress-bar span').text('');
|
||||||
|
$('.coords_progress .progress-bar').addClass('progress-bar-striped active');
|
||||||
|
} else if (msg['state'] === 'Finished') {
|
||||||
|
$('.coords_progress').css('display', 'none');
|
||||||
|
currentVersion = false;
|
||||||
|
|
||||||
|
socket.emit('get reachview version');
|
||||||
|
|
||||||
|
$('.update_status').html('<i class="icon-checkmark3 text-success"></i>');
|
||||||
|
$('.update_reachview').css('display', 'none');
|
||||||
|
$('.available_version').css('display', 'none');
|
||||||
|
|
||||||
|
updatePass = true;
|
||||||
|
|
||||||
|
if (updatePass && receiverPass && timePass && wifiPass && testPass) {
|
||||||
|
$('.to_app').removeClass('disabled');
|
||||||
|
} else {
|
||||||
|
$('.to_app').addClass('disabled');
|
||||||
|
}
|
||||||
|
} else if (msg['state'] === 'Failed') {
|
||||||
|
$('.coords_progress').css('display', 'none');
|
||||||
|
$('.update_status').html('<i class="icon-cross2 text-danger-400"></i>');
|
||||||
|
|
||||||
|
$('.coords_progress .progress-bar').css('width', '0%');
|
||||||
|
$('.coords_progress .progress-bar span').text('');
|
||||||
|
|
||||||
|
if (msg['locked']) {
|
||||||
|
$('.current_version').html('Update system is used by another process. Please try again later.');
|
||||||
|
} else {
|
||||||
|
$('.current_version').html('Failed to perform update.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.skip_update_btn').css('display', 'inline-block');
|
||||||
|
$('.update_reachview').css('display', 'block');
|
||||||
|
$('.update_reachview').removeClass('disabled');
|
||||||
|
$('.update_anchor.collapsed').click();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('wifi saved networks results', function (msg) {
|
||||||
|
var connectedNetwork = false;
|
||||||
|
|
||||||
|
var to_append = '';
|
||||||
|
|
||||||
|
msg.forEach(function (key, value) {
|
||||||
|
var ssid = (key['ssid'] !== '') ? key['ssid'] : 'Unknown';
|
||||||
|
|
||||||
|
if (key['is_connected']) {
|
||||||
|
to_append += '<li class="media connected_wi-fi_network">';
|
||||||
|
$('#current_network').text(ssid);
|
||||||
|
} else {
|
||||||
|
to_append += '<li class="media">';
|
||||||
|
}
|
||||||
|
|
||||||
|
to_append += '<a href="#" class="media-link"><div class="media-body">';
|
||||||
|
to_append += '<div class="media-heading text-semibold wi-fi_title">' + ssid + '</div>';
|
||||||
|
|
||||||
|
if (key['is_connected']) {
|
||||||
|
to_append += '<span class="text-muted">Connected (' + key['ip'] + ')</span>';
|
||||||
|
connectedNetwork = true;
|
||||||
|
} else {
|
||||||
|
to_append += '<span class="text-muted">Saved</span>';
|
||||||
|
}
|
||||||
|
|
||||||
|
to_append += '<input type="hidden" class="wi-fi_mac" value="' + key['mac_address'] + '"><input type="hidden" class="wi-fi_security" value="' + key['security'] + '"></div>';
|
||||||
|
|
||||||
|
if (key['is_connected']) {
|
||||||
|
to_append += '<div class="media-right media-middle text-nowrap"><span class="text-muted wi-fi_remove"><i class="icon-link text-size-base"></i></span></div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
to_append += '</a></li>';
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#added_wi-fi').html(to_append);
|
||||||
|
$('#connected_wi-fi').html('');
|
||||||
|
$('#connected_wi-fi').append($('.connected_wi-fi_network'));
|
||||||
|
|
||||||
|
if (connectedNetwork) {
|
||||||
|
$('.wifi_status').html('<i class="icon-checkmark3 text-success"></i>');
|
||||||
|
|
||||||
|
socket.emit('get time sync status');
|
||||||
|
|
||||||
|
$('.overlay.sync_overlay').fadeOut();
|
||||||
|
$('.sync_status').html('<i class="icon-spinner2 spinner text-warning"></i>');
|
||||||
|
|
||||||
|
syncInterval = setInterval(function () { socket.emit('get time sync status'); }, 1000);
|
||||||
|
|
||||||
|
wifiPass = true;
|
||||||
|
} else {
|
||||||
|
$('.wifi_status').html('<i class="icon-circle-small text-danger-400"></i>');
|
||||||
|
$('.wi-fi_anchor.collapsed').click();
|
||||||
|
|
||||||
|
wifiPass = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('time sync status', function (msg) {
|
||||||
|
if (timePass) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg['status']) {
|
||||||
|
$('.sync_status').html('<i class="icon-checkmark3 text-success"></i>');
|
||||||
|
$('.time_sync_warning').text('Time was synchronized!');
|
||||||
|
|
||||||
|
// Receiver update
|
||||||
|
availableReceiverVersion = false;
|
||||||
|
|
||||||
|
socket.emit('is receiver upgrade available');
|
||||||
|
|
||||||
|
$('.receiver_status').html('<i class="icon-spinner2 spinner text-warning"></i>');
|
||||||
|
$('#receiver_upgrade_msg').text('Checking for receiver updates...');
|
||||||
|
$('.receiver_overlay').fadeOut();
|
||||||
|
|
||||||
|
// Reach update
|
||||||
|
// currentVersion = false;
|
||||||
|
// socket.emit('get reachview version');
|
||||||
|
// $('.current_version').text('Getting current version...');
|
||||||
|
// $('.overlay.update_overlay').fadeOut();
|
||||||
|
// $('.update_status').html('<i class="icon-spinner2 spinner text-warning"></i>');
|
||||||
|
|
||||||
|
clearInterval(syncInterval);
|
||||||
|
|
||||||
|
timePass = true;
|
||||||
|
} else {
|
||||||
|
$('.time_sync_warning').text('Check your internet connection or connect antenna.');
|
||||||
|
timePass = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('receiver upgrade available', function (msg) {
|
||||||
|
if (availableReceiverVersion || receiverLocked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg['running']) {
|
||||||
|
$('#receiver_upgrade_msg').text('Updating receiver...');
|
||||||
|
$('.receiver_status').html('<i class="icon-spinner2 spinner text-warning"></i>');
|
||||||
|
$('.update_receiver').css('display', 'inline-block');
|
||||||
|
$('.update_receiver').addClass('disabled');
|
||||||
|
$('.skip_receiver_update').css('display', 'none');
|
||||||
|
$('.receiver_progress').css('display', 'block');
|
||||||
|
$('.receiver_anchor.collapsed').click();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg['available']) {
|
||||||
|
$('.receiver_status').html('<i class="text-warning icon-circle-small"></i>');
|
||||||
|
$('#receiver_upgrade_msg').text('Receiver upgrade available');
|
||||||
|
$('.update_receiver').css('display', 'inline-block');
|
||||||
|
$('.skip_receiver_update').css('display', 'inline-block');
|
||||||
|
$('.receiver_anchor.collapsed').click();
|
||||||
|
} else {
|
||||||
|
$('.receiver_status').html('<i class="icon-checkmark3 text-success"></i>');
|
||||||
|
$('#receiver_upgrade_msg').text('No upgrades available for receiver');
|
||||||
|
|
||||||
|
$('.skip_receiver_update').trigger('click', [true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
availableReceiverVersion = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.update_receiver').on('click', function () {
|
||||||
|
if (!$(this).hasClass('disabled')) {
|
||||||
|
receiverPass = false;
|
||||||
|
|
||||||
|
socket.emit('upgrade receiver');
|
||||||
|
|
||||||
|
$('#receiver_upgrade_msg').text('Updating receiver...');
|
||||||
|
$('.receiver_status').html('<i class="icon-spinner2 spinner text-warning"></i>');
|
||||||
|
$('.update_receiver').addClass('disabled');
|
||||||
|
$('.skip_receiver_update').css('display', 'none');
|
||||||
|
$('.receiver_progress').css('display', 'block');
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.skip_receiver_update, .receiver_skip_locked').on('click', function (event, fakeClick) {
|
||||||
|
if (!$(this).hasClass('disabled')) {
|
||||||
|
$(this).css('display', 'none');
|
||||||
|
$('.receiver_status').html('<i class="icon-checkmark3 text-success"></i>');
|
||||||
|
|
||||||
|
if (!fakeClick) {
|
||||||
|
$('.receiver_anchor:not(.collapsed)').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!availableVersion && !updatePass) {
|
||||||
|
currentVersion = false;
|
||||||
|
|
||||||
|
socket.emit('get reachview version');
|
||||||
|
|
||||||
|
$('.current_version').text('Getting current version...');
|
||||||
|
$('.overlay.update_overlay').fadeOut();
|
||||||
|
$('.update_status').html('<i class="icon-spinner2 spinner text-warning"></i>');
|
||||||
|
}
|
||||||
|
|
||||||
|
receiverLocked = false;
|
||||||
|
receiverPass = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.receiver_try_again').on('click', function () {
|
||||||
|
receiverPass = false;
|
||||||
|
availableReceiverVersion = false;
|
||||||
|
|
||||||
|
socket.emit('is receiver upgrade available');
|
||||||
|
|
||||||
|
$('.receiver_status').html('<i class="icon-spinner2 spinner text-warning"></i>');
|
||||||
|
$('#receiver_upgrade_msg').text('Checking for receiver updates...');
|
||||||
|
|
||||||
|
$('.receiver_try_skip').css('display', 'none');
|
||||||
|
|
||||||
|
receiverLocked = false;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('receiver upgrade result', function (msg) {
|
||||||
|
if (receiverPass || receiverLocked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg) {
|
||||||
|
$('.update_receiver').css('display', 'none');
|
||||||
|
$('#receiver_upgrade_msg').text('Receiver updated successfully');
|
||||||
|
$('.receiver_status').html('<i class="icon-checkmark3 text-success"></i>');
|
||||||
|
|
||||||
|
$('.skip_receiver_update').trigger('click', [true]);
|
||||||
|
} else {
|
||||||
|
$('#receiver_upgrade_msg').text('Failed to perform receiver update');
|
||||||
|
$('.receiver_status').html('<i class="text-warning icon-circle-small"></i>');
|
||||||
|
$('.update_receiver').css('display', 'inline-block');
|
||||||
|
$('.skip_receiver_update').css('display', 'inline-block');
|
||||||
|
$('.receiver_anchor.collapsed').click();
|
||||||
|
$('.update_receiver').removeClass('disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.receiver_progress').css('display', 'none');
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('opkg update result', function (msg) {
|
||||||
|
if (opkgResult) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg['state'] === 'Failed') {
|
||||||
|
$('.update_status').html('<i class="icon-cross2 text-danger-400"></i>');
|
||||||
|
$('.update_anchor.collapsed').click();
|
||||||
|
|
||||||
|
if (msg['locked']) {
|
||||||
|
$('.current_version').html('Update system is used by another process. Please try again later.');
|
||||||
|
} else {
|
||||||
|
$('.current_version').html('Update server unreachable. Check your Internet connection or try again later.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.available_version').css('display', 'none');
|
||||||
|
$('.row_try_skip').css('display', 'block');
|
||||||
|
$('.update_reachview').css('display', 'none');
|
||||||
|
$('.update_anchor.collapsed').click();
|
||||||
|
}
|
||||||
|
else if (msg['state'] === 'Finished') {
|
||||||
|
opkgResult = true;
|
||||||
|
availableVersion = false;
|
||||||
|
|
||||||
|
socket.emit('is reachview upgrade available');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('update system locked', function () {
|
||||||
|
if (receiverPass) {
|
||||||
|
$('.update_anchor.collapsed').click();
|
||||||
|
$('.update_status').html('<i class="icon-cross2 text-danger-400"></i>');
|
||||||
|
|
||||||
|
$('.current_version').text('Update system is used by another process. Please try again later.');
|
||||||
|
$('.available_version').css('display', 'none');
|
||||||
|
|
||||||
|
$('.row_try_skip').css('display', 'block');
|
||||||
|
} else {
|
||||||
|
$('.receiver_anchor.collapsed').click();
|
||||||
|
$('.receiver_status').html('<i class="icon-cross2 text-danger-400"></i>');
|
||||||
|
|
||||||
|
$('#receiver_upgrade_msg').text('Update system is used by another process. Please try again later.');
|
||||||
|
$('.update_receiver').css('display', 'none');
|
||||||
|
$('.skip_receiver_update').css('display', 'none');
|
||||||
|
|
||||||
|
$('.receiver_try_skip').css('display', 'block');
|
||||||
|
|
||||||
|
receiverLocked = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('current reachview version', function (msg) {
|
||||||
|
if (currentVersion || !receiverPass) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var version = (msg['version'] != null)
|
||||||
|
? 'Current ReachView version: ' + msg['version']
|
||||||
|
: 'Could not retrieve ReachView version.';
|
||||||
|
|
||||||
|
$('.current_version').text(version);
|
||||||
|
|
||||||
|
currentVersion = true;
|
||||||
|
opkgResult = false;
|
||||||
|
|
||||||
|
socket.emit('update');
|
||||||
|
|
||||||
|
$('.available_version').css('display', 'block');
|
||||||
|
$('.available_version').text('Checking for updates...');
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('reachview upgrade version', function (msg) {
|
||||||
|
if (availableVersion || !receiverPass) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!msg['upgrade available']) {
|
||||||
|
$('.update_status').html('<i class="icon-checkmark3 text-success"></i>');
|
||||||
|
$('.update_reachview').css('display', 'none');
|
||||||
|
$('.available_version').css('display', 'none');
|
||||||
|
|
||||||
|
updatePass = true;
|
||||||
|
|
||||||
|
if (updatePass && receiverPass && timePass && wifiPass && testPass) {
|
||||||
|
$('.to_app').removeClass('disabled');
|
||||||
|
} else {
|
||||||
|
$('.to_app').addClass('disabled');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$('.available_version').css('display', 'block');
|
||||||
|
$('.available_version').text('Available version: ' + msg['available version']);
|
||||||
|
$('.update_status').html('<i class="text-warning icon-circle-small"></i>');
|
||||||
|
$('.update_reachview').css('display', 'inline-block');
|
||||||
|
$('.update_anchor.collapsed').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
availableVersion = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('test results', function (msg) {
|
||||||
|
$('.tests_status').css('display', 'none');
|
||||||
|
|
||||||
|
device = msg['device'];
|
||||||
|
|
||||||
|
if (msg['device'] === 'Reach' || msg['device'] === 'ReachM+') {
|
||||||
|
$('.ltc_test, .stc_test, .lora_test').parent().css('display', 'none');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!msg['ltc']) {
|
||||||
|
$('.tests_status').html('<i class="icon-cross2 text-danger-400"></i>');
|
||||||
|
$('.test_warning').text('Test 3 failed');
|
||||||
|
$('.test_warning').slideDown();
|
||||||
|
|
||||||
|
testPass = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!msg['stc']) {
|
||||||
|
$('.tests_status').html('<i class="icon-cross2 text-danger-400"></i>');
|
||||||
|
$('.test_warning').text('Test 4 failed');
|
||||||
|
$('.test_warning').slideDown();
|
||||||
|
|
||||||
|
testPass = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!msg['lora']) {
|
||||||
|
$('.tests_status').html('<i class="icon-cross2 text-danger-400"></i>');
|
||||||
|
$('.test_warning').text('Test 5 failed');
|
||||||
|
$('.test_warning').slideDown();
|
||||||
|
|
||||||
|
testPass = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!msg['mpu']) {
|
||||||
|
$('.tests_status').html('<i class="icon-cross2 text-danger-400"></i>');
|
||||||
|
$('.test_warning').text('Test 1 failed');
|
||||||
|
$('.test_warning').slideDown();
|
||||||
|
|
||||||
|
testPass = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!msg['u-blox']) {
|
||||||
|
$('.tests_status').html('<i class="icon-cross2 text-danger-400"></i>');
|
||||||
|
$('.test_warning').text('Test 2 failed');
|
||||||
|
$('.test_warning').slideDown();
|
||||||
|
|
||||||
|
testPass = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg['device'] === 'Reach' || msg['device'] === 'ReachM+') {
|
||||||
|
if (msg['u-blox'] && msg['mpu']) {
|
||||||
|
$('.tests_status').html('<i class="icon-checkmark3 text-success"></i>');
|
||||||
|
testPass = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (msg['u-blox'] && msg['mpu'] && msg['lora'] && msg['ltc'] && msg['stc']) {
|
||||||
|
$('.tests_status').html('<i class="icon-checkmark3 text-success"></i>');
|
||||||
|
testPass = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.tests_status').fadeIn();
|
||||||
|
|
||||||
|
if (msg['mpu']) {
|
||||||
|
$('.mpu_test').html('<i class="icon-checkmark3 text-success"></i>');
|
||||||
|
} else {
|
||||||
|
$('.mpu_test').html('<i class="icon-cross2 text-danger-400"></i>');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg['u-blox']) {
|
||||||
|
$('.u-blox_test').html('<i class="icon-checkmark3 text-success"></i>');
|
||||||
|
} else {
|
||||||
|
$('.u-blox_test').html('<i class="icon-cross2 text-danger-400"></i>');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg['lora']) {
|
||||||
|
$('.lora_test').html('<i class="icon-checkmark3 text-success"></i>');
|
||||||
|
} else {
|
||||||
|
$('.lora_test').html('<i class="icon-cross2 text-danger-400"></i>');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg['stc']) {
|
||||||
|
$('.stc_test').html('<i class="icon-checkmark3 text-success"></i>');
|
||||||
|
} else {
|
||||||
|
$('.stc_test').html('<i class="icon-cross2 text-danger-400"></i>');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg['ltc']) {
|
||||||
|
$('.ltc_test').html('<i class="icon-checkmark3 text-success"></i>');
|
||||||
|
} else {
|
||||||
|
$('.ltc_test').html('<i class="icon-cross2 text-danger-400"></i>');
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('get saved wifi networks');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,4 +1,5 @@
|
||||||
**/*.go
|
**/*.go
|
||||||
|
!**/*_test.go
|
||||||
modd.conf
|
modd.conf
|
||||||
.env
|
.env
|
||||||
Makefile {
|
Makefile {
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
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
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
package reach
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"forge.cadoles.com/Pyxis/golang-socketio"
|
||||||
|
"forge.cadoles.com/Pyxis/golang-socketio/transport"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type handshake struct {
|
||||||
|
PingInterval time.Duration `json:"pingInterval"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client is a ReachView Websocket API client
|
||||||
|
type Client struct {
|
||||||
|
opts *Options
|
||||||
|
conn *gosocketio.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect connects the client to the ReachView endpoint
|
||||||
|
// This method is not safe to call by different coroutines
|
||||||
|
func (c *Client) Connect() error {
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
transport := &transport.WebsocketTransport{
|
||||||
|
PingInterval: c.opts.PingInterval,
|
||||||
|
PingTimeout: c.opts.PingTimeout,
|
||||||
|
ReceiveTimeout: c.opts.ReceiveTimeout,
|
||||||
|
SendTimeout: c.opts.SendTimeout,
|
||||||
|
BufferSize: c.opts.BufferSize,
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.conn = conn
|
||||||
|
|
||||||
|
err = conn.On(gosocketio.OnConnection, func(h *gosocketio.Channel) {
|
||||||
|
c.logf("connected with sid '%s'", h.Id())
|
||||||
|
err = c.sendBrowserConnected()
|
||||||
|
wg.Done()
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "error while attaching to connection event")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = conn.On(gosocketio.OnError, func(h *gosocketio.Channel) {
|
||||||
|
c.logf("error")
|
||||||
|
err = errors.Errorf("an unknown error occured")
|
||||||
|
c.conn = nil
|
||||||
|
wg.Done()
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "error while attaching to error event")
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
conn.On(gosocketio.OnError, nil)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the current connection to the ReachView endpoint
|
||||||
|
func (c *Client) Close() {
|
||||||
|
if c.conn == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.conn.Close()
|
||||||
|
c.conn = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) logf(format string, args ...interface{}) {
|
||||||
|
if c.opts.Logger == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.opts.Logger.Printf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClient returns a new ReachView Websocket API client
|
||||||
|
func NewClient(opts ...OptionFunc) *Client {
|
||||||
|
options := DefaultOptions()
|
||||||
|
for _, o := range opts {
|
||||||
|
o(options)
|
||||||
|
}
|
||||||
|
return &Client{
|
||||||
|
opts: options,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package reach
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestClient(t *testing.T) {
|
||||||
|
|
||||||
|
client := NewClient(
|
||||||
|
WithStandardLogger(),
|
||||||
|
)
|
||||||
|
if err := client.Connect(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
results, err := client.TestResults()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if g, e := results.Device, "ReachRS"; g != e {
|
||||||
|
t.Errorf("results.Device: got '%s', expected '%s'", g, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package reach
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"forge.cadoles.com/Pyxis/golang-socketio"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Logger interface {
|
||||||
|
Printf(format string, args ...interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Options are ReachRS client configuration options
|
||||||
|
type Options struct {
|
||||||
|
Endpoint string
|
||||||
|
PingInterval time.Duration
|
||||||
|
PingTimeout time.Duration
|
||||||
|
ReceiveTimeout time.Duration
|
||||||
|
SendTimeout time.Duration
|
||||||
|
BufferSize int
|
||||||
|
Logger Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
type OptionFunc func(opts *Options)
|
||||||
|
|
||||||
|
func WithEndpoint(host string, port int) OptionFunc {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.Endpoint = gosocketio.GetUrl(host, port, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithPingInterval(interval time.Duration) OptionFunc {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.PingInterval = interval
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithPingTimeout(timeout time.Duration) OptionFunc {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.PingTimeout = timeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithReceiveTimeout(timeout time.Duration) OptionFunc {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.ReceiveTimeout = timeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithSendTimeout(timeout time.Duration) OptionFunc {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.SendTimeout = timeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithBufferSize(size int) OptionFunc {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.BufferSize = size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithLogger(logger Logger) OptionFunc {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.Logger = logger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithStandardLogger() OptionFunc {
|
||||||
|
return func(opts *Options) {
|
||||||
|
logger := log.New(os.Stdout, "[reachrs] ", log.LstdFlags)
|
||||||
|
opts.Logger = logger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefaultOptions() *Options {
|
||||||
|
opts := &Options{}
|
||||||
|
defaults := []OptionFunc{
|
||||||
|
WithEndpoint("192.168.42.1", 80),
|
||||||
|
WithPingInterval(30 * time.Second),
|
||||||
|
WithPingTimeout(60 * time.Second),
|
||||||
|
WithReceiveTimeout(60 * time.Second),
|
||||||
|
WithSendTimeout(60 * time.Second),
|
||||||
|
WithBufferSize(1024 * 32),
|
||||||
|
}
|
||||||
|
for _, o := range defaults {
|
||||||
|
o(opts)
|
||||||
|
}
|
||||||
|
return opts
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package reach
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"forge.cadoles.com/Pyxis/golang-socketio"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// EventProbe -
|
||||||
|
EventProbe = "probe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Probe -
|
||||||
|
func (c *Client) Probe() error {
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
c.conn.On(EventProbe, func(h *gosocketio.Channel) {
|
||||||
|
wg.Done()
|
||||||
|
c.conn.On(EventProbe, nil)
|
||||||
|
})
|
||||||
|
|
||||||
|
c.logf("sending '%s' event", EventProbe)
|
||||||
|
if err := c.conn.Emit(EventProbe, nil); err != nil {
|
||||||
|
return errors.Wrapf(err, "error while emitting '%s' event", EventProbe)
|
||||||
|
}
|
||||||
|
c.logf("'%s' event sent", EventProbe)
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package reach
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"forge.cadoles.com/Pyxis/golang-socketio"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestResults are the ReachRS module's test results
|
||||||
|
type TestResults struct {
|
||||||
|
UBlox bool `json:"u-blox"`
|
||||||
|
STC bool `json:"stc"`
|
||||||
|
MPU bool `json:"mpu"`
|
||||||
|
Device string `json:"device"`
|
||||||
|
Lora bool `json:"lora"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestResults returns the ReachRS module tests results
|
||||||
|
func (c *Client) TestResults() (*TestResults, error) {
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var results *TestResults
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
c.conn.On(EventTestResults, func(h *gosocketio.Channel, res *TestResults) {
|
||||||
|
results = res
|
||||||
|
c.conn.On(EventTestResults, nil)
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
c.logf("'%s' event sent", EventGetTestResults)
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
return results, err
|
||||||
|
|
||||||
|
}
|
Reference in New Issue