kopia lustrzana https://github.com/cyoung/stratux
Merge remote-tracking branch 'upstream/master' into traffic-ui
commit
3b510c146e
|
@ -31,14 +31,16 @@ case "$1" in
|
||||||
log_daemon_msg "Starting $DESC" "$NAME"
|
log_daemon_msg "Starting $DESC" "$NAME"
|
||||||
echo powersave >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
|
echo powersave >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
|
||||||
# Check if we need to run an update.
|
# Check if we need to run an update.
|
||||||
UPDATE_SCRIPT=`ls -1t /root/update*.sh | head -1`
|
if [ -e /root/update*.sh ] ; then
|
||||||
if [ -n "$UPDATE_SCRIPT" ] ; then
|
UPDATE_SCRIPT=`ls -1t /root/update*.sh | head -1`
|
||||||
# Execute the script, remove it, then reboot.
|
if [ -n "$UPDATE_SCRIPT" ] ; then
|
||||||
echo
|
# Execute the script, remove it, then reboot.
|
||||||
echo "Running update script ${UPDATE_SCRIPT}..."
|
echo
|
||||||
sh ${UPDATE_SCRIPT}
|
echo "Running update script ${UPDATE_SCRIPT}..."
|
||||||
rm -f $UPDATE_SCRIPT
|
sh ${UPDATE_SCRIPT}
|
||||||
reboot
|
rm -f $UPDATE_SCRIPT
|
||||||
|
reboot
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
start-stop-daemon --start --background --oknodo --quiet --exec "$DAEMON_SBIN" \
|
start-stop-daemon --start --background --oknodo --quiet --exec "$DAEMON_SBIN" \
|
||||||
--pidfile "$PIDFILE" --make-pidfile -- $DAEMON_OPTS >/dev/null
|
--pidfile "$PIDFILE" --make-pidfile -- $DAEMON_OPTS >/dev/null
|
||||||
|
|
|
@ -39,6 +39,10 @@ func (m *monotonic) HumanizeTime(t time.Time) string {
|
||||||
return humanize.RelTime(t, m.Time, "ago", "from now")
|
return humanize.RelTime(t, m.Time, "ago", "from now")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *monotonic) Unix() int64 {
|
||||||
|
return int64(m.Since(time.Time{}).Seconds())
|
||||||
|
}
|
||||||
|
|
||||||
func NewMonotonic() *monotonic {
|
func NewMonotonic() *monotonic {
|
||||||
t := &monotonic{Milliseconds: 0, Time: time.Time{}, ticker: time.NewTicker(50 * time.Millisecond)}
|
t := &monotonic{Milliseconds: 0, Time: time.Time{}, ticker: time.NewTicker(50 * time.Millisecond)}
|
||||||
go t.Watcher()
|
go t.Watcher()
|
||||||
|
|
63
main/sdr.go
63
main/sdr.go
|
@ -13,6 +13,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -26,12 +27,14 @@ import (
|
||||||
type UAT struct {
|
type UAT struct {
|
||||||
dev *rtl.Context
|
dev *rtl.Context
|
||||||
indexID int
|
indexID int
|
||||||
|
ppm int
|
||||||
serial string
|
serial string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ES struct {
|
type ES struct {
|
||||||
dev *rtl.Context
|
dev *rtl.Context
|
||||||
indexID int
|
indexID int
|
||||||
|
ppm int
|
||||||
serial string
|
serial string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +64,7 @@ func readToChan(fp io.ReadCloser, ch chan []byte) {
|
||||||
func (e *ES) read() {
|
func (e *ES) read() {
|
||||||
defer es_wg.Done()
|
defer es_wg.Done()
|
||||||
log.Println("Entered ES read() ...")
|
log.Println("Entered ES read() ...")
|
||||||
cmd := exec.Command("/usr/bin/dump1090", "--net", "--device-index", strconv.Itoa(e.indexID))
|
cmd := exec.Command("/usr/bin/dump1090", "--net", "--device-index", strconv.Itoa(e.indexID), "--ppm", strconv.Itoa(e.ppm))
|
||||||
stdout, _ := cmd.StdoutPipe()
|
stdout, _ := cmd.StdoutPipe()
|
||||||
stderr, _ := cmd.StderrPipe()
|
stderr, _ := cmd.StderrPipe()
|
||||||
|
|
||||||
|
@ -124,12 +127,33 @@ func (u *UAT) read() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getPPM(serial string) int {
|
||||||
|
r, err := regexp.Compile("str?a?t?u?x:\\d+:?(-?\\d*)");
|
||||||
|
if err != nil {
|
||||||
|
return globalSettings.PPM
|
||||||
|
}
|
||||||
|
|
||||||
|
arr := r.FindStringSubmatch(serial);
|
||||||
|
if arr == nil {
|
||||||
|
return globalSettings.PPM
|
||||||
|
}
|
||||||
|
|
||||||
|
if ppm, err := strconv.Atoi(arr[1]); err != nil {
|
||||||
|
return globalSettings.PPM
|
||||||
|
} else {
|
||||||
|
return ppm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (e *ES) sdrConfig() (err error) {
|
func (e *ES) sdrConfig() (err error) {
|
||||||
|
e.ppm = getPPM(e.serial)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UAT) sdrConfig() (err error) {
|
func (u *UAT) sdrConfig() (err error) {
|
||||||
log.Printf("===== UAT Device name: %s =====\n", rtl.GetDeviceName(u.indexID))
|
log.Printf("===== UAT Device name: %s =====\n", rtl.GetDeviceName(u.indexID))
|
||||||
|
u.ppm = getPPM(u.serial)
|
||||||
|
|
||||||
if u.dev, err = rtl.Open(u.indexID); err != nil {
|
if u.dev, err = rtl.Open(u.indexID); err != nil {
|
||||||
log.Printf("\tUAT Open Failed...\n")
|
log.Printf("\tUAT Open Failed...\n")
|
||||||
return
|
return
|
||||||
|
@ -223,13 +247,13 @@ func (u *UAT) sdrConfig() (err error) {
|
||||||
//---------- Get/Set Freq Correction ----------
|
//---------- Get/Set Freq Correction ----------
|
||||||
freqCorr := u.dev.GetFreqCorrection()
|
freqCorr := u.dev.GetFreqCorrection()
|
||||||
log.Printf("\tGetFreqCorrection: %d\n", freqCorr)
|
log.Printf("\tGetFreqCorrection: %d\n", freqCorr)
|
||||||
err = u.dev.SetFreqCorrection(globalSettings.PPM)
|
err = u.dev.SetFreqCorrection(u.ppm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
u.dev.Close()
|
u.dev.Close()
|
||||||
log.Printf("\tSetFreqCorrection %d Failed, error: %s\n", globalSettings.PPM, err)
|
log.Printf("\tSetFreqCorrection %d Failed, error: %s\n", u.ppm, err)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
log.Printf("\tSetFreqCorrection %d Successful\n", globalSettings.PPM)
|
log.Printf("\tSetFreqCorrection %d Successful\n", u.ppm)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -297,6 +321,19 @@ func sdrKill() {
|
||||||
|
|
||||||
// Watch for config/device changes.
|
// Watch for config/device changes.
|
||||||
func sdrWatcher() {
|
func sdrWatcher() {
|
||||||
|
var doSkip bool
|
||||||
|
rES, err := regexp.Compile("str?a?t?u?x:1090")
|
||||||
|
if err != nil {
|
||||||
|
rES = nil
|
||||||
|
log.Println("failed to compile ES regexp because %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
rUAT, err := regexp.Compile("str?a?t?u?x:978")
|
||||||
|
if err != nil {
|
||||||
|
rUAT = nil
|
||||||
|
log.Println("failed to compile UAT regexp because %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
if sdrShutdown {
|
if sdrShutdown {
|
||||||
|
@ -365,7 +402,14 @@ func sdrWatcher() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
serial = ""
|
serial = ""
|
||||||
}
|
}
|
||||||
if strings.Compare(serial, "stratux:1090") != 0 {
|
|
||||||
|
if (rES == nil) {
|
||||||
|
doSkip = rES.MatchString(serial)
|
||||||
|
} else {
|
||||||
|
doSkip = strings.Compare(serial, "stratux:1090") == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if !doSkip {
|
||||||
UATDev = &UAT{indexID: id, serial: serial}
|
UATDev = &UAT{indexID: id, serial: serial}
|
||||||
if err := UATDev.sdrConfig(); err != nil {
|
if err := UATDev.sdrConfig(); err != nil {
|
||||||
log.Printf("UATDev = &UAT{indexID: id} failed: %s\n", err)
|
log.Printf("UATDev = &UAT{indexID: id} failed: %s\n", err)
|
||||||
|
@ -407,7 +451,14 @@ func sdrWatcher() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
serial = ""
|
serial = ""
|
||||||
}
|
}
|
||||||
if strings.Compare(serial, "stratux:978") != 0 {
|
|
||||||
|
if (rUAT == nil) {
|
||||||
|
doSkip = rUAT.MatchString(serial)
|
||||||
|
} else {
|
||||||
|
doSkip = strings.Compare(serial, "stratux:978") == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if !doSkip {
|
||||||
ESDev = &ES{indexID: id, serial: serial}
|
ESDev = &ES{indexID: id, serial: serial}
|
||||||
if err := ESDev.sdrConfig(); err != nil {
|
if err := ESDev.sdrConfig(); err != nil {
|
||||||
log.Printf("ESDev = &ES{indexID: id} failed: %s\n", err)
|
log.Printf("ESDev = &ES{indexID: id} failed: %s\n", err)
|
||||||
|
|
|
@ -32,6 +32,10 @@ func main() {
|
||||||
|
|
||||||
x := strings.Split(buf, ",")
|
x := strings.Split(buf, ",")
|
||||||
|
|
||||||
|
if len(x) < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
uatMsg, err := uatparse.New(x[1])
|
uatMsg, err := uatparse.New(x[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// fmt.Printf("err %s\n", err.Error())
|
// fmt.Printf("err %s\n", err.Error())
|
||||||
|
|
|
@ -199,6 +199,24 @@
|
||||||
padding: 1px 2px 1px 3px;
|
padding: 1px 2px 1px 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fake-btn {
|
||||||
|
background-color:#ccc;
|
||||||
|
margin-bottom:0;
|
||||||
|
font-weight:400;
|
||||||
|
text-align:center;
|
||||||
|
vertical-align:middle;
|
||||||
|
cursor:pointer;
|
||||||
|
border:1px solid transparent;
|
||||||
|
white-space:nowrap;
|
||||||
|
padding: 6px 12px;
|
||||||
|
line-height: 1.43;
|
||||||
|
border-radius:4px;
|
||||||
|
}
|
||||||
|
.fake-btn-block {
|
||||||
|
display:inline-block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ***************************************************************************
|
/* ***************************************************************************
|
||||||
everything below this comment represents tweeks to the mobile-angular-uis CSS
|
everything below this comment represents tweeks to the mobile-angular-uis CSS
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
angular.module('appControllers').controller('LogsCtrl', LogsCtrl); // get the main module contollers set
|
angular.module('appControllers').controller('LogsCtrl', LogsCtrl); // get the main module contollers set
|
||||||
LogsCtrl.$inject = ['$scope', '$http']; // Inject my dependencies
|
LogsCtrl.$inject = ['$scope', '$state', '$http']; // Inject my dependencies
|
||||||
|
|
||||||
// create our controller function with all necessary logic
|
// create our controller function with all necessary logic
|
||||||
function LogsCtrl($scope, $http) {
|
function LogsCtrl($scope, $state, $http) {
|
||||||
$scope.userAgent = navigator.userAgent;
|
$scope.$parent.helppage = 'plates/logs-help.html';
|
||||||
|
|
||||||
|
// just a couple environment variables that may bve useful for dev/debugging but otherwise not significant
|
||||||
|
$scope.userAgent = navigator.userAgent;
|
||||||
$scope.deviceViewport = 'screen = ' + window.screen.width + ' x ' + window.screen.height;
|
$scope.deviceViewport = 'screen = ' + window.screen.width + ' x ' + window.screen.height;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,8 @@ function SettingsCtrl($rootScope, $scope, $state, $http) {
|
||||||
for (i = 0; i < toggles.length; i++) {
|
for (i = 0; i < toggles.length; i++) {
|
||||||
settings[toggles[i]] = undefined;
|
settings[toggles[i]] = undefined;
|
||||||
}
|
}
|
||||||
|
$scope.update_files = '';
|
||||||
|
|
||||||
function loadSettings(data) {
|
function loadSettings(data) {
|
||||||
settings = angular.fromJson(data);
|
settings = angular.fromJson(data);
|
||||||
// consider using angular.extend()
|
// consider using angular.extend()
|
||||||
|
@ -39,7 +40,6 @@ function SettingsCtrl($rootScope, $scope, $state, $http) {
|
||||||
for (i = 0; i < toggles.length; i++) {
|
for (i = 0; i < toggles.length; i++) {
|
||||||
settings[toggles[i]] = false;
|
settings[toggles[i]] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ function SettingsCtrl($rootScope, $scope, $state, $http) {
|
||||||
setSettings(angular.toJson(newsettings));
|
setSettings(angular.toJson(newsettings));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.updatewatchlist = function () {
|
$scope.updatewatchlist = function () {
|
||||||
if ($scope.WatchList !== settings["WatchList"]) {
|
if ($scope.WatchList !== settings["WatchList"]) {
|
||||||
settings["WatchList"] = $scope.WatchList.toUpperCase();
|
settings["WatchList"] = $scope.WatchList.toUpperCase();
|
||||||
|
@ -118,14 +118,38 @@ function SettingsCtrl($rootScope, $scope, $state, $http) {
|
||||||
$http.post('/reboot');
|
$http.post('/reboot');
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.uploadFile = function(files) {
|
$scope.setUploadFile = function (files) {
|
||||||
|
$scope.update_files = files;
|
||||||
|
$scope.$apply();
|
||||||
|
}
|
||||||
|
$scope.resetUploadFile = function () {
|
||||||
|
$scope.update_files = '';
|
||||||
|
$scope.$apply();
|
||||||
|
}
|
||||||
|
$scope.uploadFile = function () {
|
||||||
var fd = new FormData();
|
var fd = new FormData();
|
||||||
//Take the first selected file
|
//Take the first selected file
|
||||||
fd.append("update_file", files[0]);
|
var file = $scope.update_files[0];
|
||||||
|
// check for empty string
|
||||||
|
if (file === undefined || file === null) {
|
||||||
|
alert ("update file not selected")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var filename = file.name;
|
||||||
|
// check for expected file naming convention
|
||||||
|
var re = /^update.*\.sh$/;
|
||||||
|
if (!re.exec(filename)) {
|
||||||
|
alert ("file does not appear to be an update")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd.append("update_file", file);
|
||||||
|
|
||||||
$http.post("/updateUpload", fd, {
|
$http.post("/updateUpload", fd, {
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
headers: {'Content-Type': undefined },
|
headers: {
|
||||||
|
'Content-Type': undefined
|
||||||
|
},
|
||||||
transformRequest: angular.identity
|
transformRequest: angular.identity
|
||||||
}).success(function (data) {
|
}).success(function (data) {
|
||||||
alert("success. wait 60 seconds and refresh home page to verify new version.");
|
alert("success. wait 60 seconds and refresh home page to verify new version.");
|
||||||
|
@ -135,4 +159,4 @@ function SettingsCtrl($rootScope, $scope, $state, $http) {
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
|
@ -0,0 +1,5 @@
|
||||||
|
<div class="section text-left help-page">
|
||||||
|
<p>The <strong>Logs</strong> page provides basic access to teh replay logs and system logs generated on the Stratux device.</p>
|
||||||
|
<p></p>
|
||||||
|
<p class="text-warning">NOTE: It is the intent that minimal log processing be done to enalbve users to see recent activity from the logs. However, this is a lower value to the current project and has been prioritized accordingly.</p>
|
||||||
|
</div>
|
|
@ -7,14 +7,14 @@
|
||||||
<i class="fa fa-cloud feature-icon text-primary"></i>
|
<i class="fa fa-cloud feature-icon text-primary"></i>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a href="../logs/stratux.log">stratux.log</a>
|
<a target="_blank" href="../logs/stratux.log">stratux.log</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a href="../logs/stratux/">SDR, AHRS, and GPS logs</a>
|
<a target="_blank" href="../logs/stratux/">SDR, AHRS, and GPS logs</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
(Enable device logging on "Settings" page)
|
(Enable device logging on "Settings" page)
|
||||||
</dib>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
|
|
|
@ -50,8 +50,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="panel-group col-sm-6">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">Configuration</div>
|
<div class="panel-heading">Configuration</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
|
@ -80,44 +83,36 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="panel-group col-sm-6">
|
<div class="panel-group col-sm-6">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">Shutdown</div>
|
<div class="panel-heading">Commands</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div class="form-group">
|
<!-- Upload. Temporary. -->
|
||||||
<div class="col-xs-5">
|
<div class="col-xs-12">
|
||||||
<button ui-turn-on="modalShutdown">Shutdown</button>
|
<span ng-show="update_files == ''">
|
||||||
|
<span style="position:relative; overflow: hidden;">
|
||||||
|
<span class="fake-btn fake-btn-block">Click to select System Update file</span>
|
||||||
|
<input style="opacity:0.0; position: absolute; top: 0; right: 0;" class="col-xs-12" type="file" name="update_file" onchange="angular.element(this).scope().setUploadFile(this.files)"/>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span ng-hide="update_files == ''">
|
||||||
|
<button class="btn btn-block" onclick="angular.element(this).scope().uploadFile()">Install {{update_files[0].name}}</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group reset-flow">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<button class="btn btn-primary btn-block" ui-turn-on="modalReboot">Reboot</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group reset-flow">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<button class="btn btn-primary btn-block"ui-turn-on="modalShutdown">Shutdown</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-group col-sm-6">
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<div class="panel-heading">Reboot</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="col-xs-5">
|
|
||||||
<button ui-turn-on="modalReboot">Reboot</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Upload. Temporary. -->
|
|
||||||
<div class="panel-group col-sm-6">
|
|
||||||
<div class="panel panel-default">
|
|
||||||
<div class="panel-heading">Update</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="col-xs-5">
|
|
||||||
<input class="col-xs-7" type="file" name="update_file" onChange="angular.element(this).scope().uploadFile(this.files)"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue