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"
|
||||
echo powersave >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
|
||||
# Check if we need to run an update.
|
||||
UPDATE_SCRIPT=`ls -1t /root/update*.sh | head -1`
|
||||
if [ -n "$UPDATE_SCRIPT" ] ; then
|
||||
# Execute the script, remove it, then reboot.
|
||||
echo
|
||||
echo "Running update script ${UPDATE_SCRIPT}..."
|
||||
sh ${UPDATE_SCRIPT}
|
||||
rm -f $UPDATE_SCRIPT
|
||||
reboot
|
||||
if [ -e /root/update*.sh ] ; then
|
||||
UPDATE_SCRIPT=`ls -1t /root/update*.sh | head -1`
|
||||
if [ -n "$UPDATE_SCRIPT" ] ; then
|
||||
# Execute the script, remove it, then reboot.
|
||||
echo
|
||||
echo "Running update script ${UPDATE_SCRIPT}..."
|
||||
sh ${UPDATE_SCRIPT}
|
||||
rm -f $UPDATE_SCRIPT
|
||||
reboot
|
||||
fi
|
||||
fi
|
||||
start-stop-daemon --start --background --oknodo --quiet --exec "$DAEMON_SBIN" \
|
||||
--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")
|
||||
}
|
||||
|
||||
func (m *monotonic) Unix() int64 {
|
||||
return int64(m.Since(time.Time{}).Seconds())
|
||||
}
|
||||
|
||||
func NewMonotonic() *monotonic {
|
||||
t := &monotonic{Milliseconds: 0, Time: time.Time{}, ticker: time.NewTicker(50 * time.Millisecond)}
|
||||
go t.Watcher()
|
||||
|
|
63
main/sdr.go
63
main/sdr.go
|
@ -13,6 +13,7 @@ import (
|
|||
"io"
|
||||
"log"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -26,12 +27,14 @@ import (
|
|||
type UAT struct {
|
||||
dev *rtl.Context
|
||||
indexID int
|
||||
ppm int
|
||||
serial string
|
||||
}
|
||||
|
||||
type ES struct {
|
||||
dev *rtl.Context
|
||||
indexID int
|
||||
ppm int
|
||||
serial string
|
||||
}
|
||||
|
||||
|
@ -61,7 +64,7 @@ func readToChan(fp io.ReadCloser, ch chan []byte) {
|
|||
func (e *ES) read() {
|
||||
defer es_wg.Done()
|
||||
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()
|
||||
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) {
|
||||
e.ppm = getPPM(e.serial)
|
||||
return
|
||||
}
|
||||
|
||||
func (u *UAT) sdrConfig() (err error) {
|
||||
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 {
|
||||
log.Printf("\tUAT Open Failed...\n")
|
||||
return
|
||||
|
@ -223,13 +247,13 @@ func (u *UAT) sdrConfig() (err error) {
|
|||
//---------- Get/Set Freq Correction ----------
|
||||
freqCorr := u.dev.GetFreqCorrection()
|
||||
log.Printf("\tGetFreqCorrection: %d\n", freqCorr)
|
||||
err = u.dev.SetFreqCorrection(globalSettings.PPM)
|
||||
err = u.dev.SetFreqCorrection(u.ppm)
|
||||
if err != nil {
|
||||
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
|
||||
} else {
|
||||
log.Printf("\tSetFreqCorrection %d Successful\n", globalSettings.PPM)
|
||||
log.Printf("\tSetFreqCorrection %d Successful\n", u.ppm)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -297,6 +321,19 @@ func sdrKill() {
|
|||
|
||||
// Watch for config/device changes.
|
||||
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 {
|
||||
time.Sleep(1 * time.Second)
|
||||
if sdrShutdown {
|
||||
|
@ -365,7 +402,14 @@ func sdrWatcher() {
|
|||
if err != nil {
|
||||
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}
|
||||
if err := UATDev.sdrConfig(); err != nil {
|
||||
log.Printf("UATDev = &UAT{indexID: id} failed: %s\n", err)
|
||||
|
@ -407,7 +451,14 @@ func sdrWatcher() {
|
|||
if err != nil {
|
||||
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}
|
||||
if err := ESDev.sdrConfig(); err != nil {
|
||||
log.Printf("ESDev = &ES{indexID: id} failed: %s\n", err)
|
||||
|
|
|
@ -32,6 +32,10 @@ func main() {
|
|||
|
||||
x := strings.Split(buf, ",")
|
||||
|
||||
if len(x) < 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
uatMsg, err := uatparse.New(x[1])
|
||||
if err != nil {
|
||||
// fmt.Printf("err %s\n", err.Error())
|
||||
|
|
|
@ -199,6 +199,24 @@
|
|||
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
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
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
|
||||
function LogsCtrl($scope, $http) {
|
||||
$scope.userAgent = navigator.userAgent;
|
||||
function LogsCtrl($scope, $state, $http) {
|
||||
$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;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ function SettingsCtrl($rootScope, $scope, $state, $http) {
|
|||
for (i = 0; i < toggles.length; i++) {
|
||||
settings[toggles[i]] = undefined;
|
||||
}
|
||||
|
||||
$scope.update_files = '';
|
||||
|
||||
function loadSettings(data) {
|
||||
settings = angular.fromJson(data);
|
||||
// consider using angular.extend()
|
||||
|
@ -39,7 +40,6 @@ function SettingsCtrl($rootScope, $scope, $state, $http) {
|
|||
for (i = 0; i < toggles.length; i++) {
|
||||
settings[toggles[i]] = false;
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -88,7 +88,7 @@ function SettingsCtrl($rootScope, $scope, $state, $http) {
|
|||
setSettings(angular.toJson(newsettings));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
$scope.updatewatchlist = function () {
|
||||
if ($scope.WatchList !== settings["WatchList"]) {
|
||||
settings["WatchList"] = $scope.WatchList.toUpperCase();
|
||||
|
@ -118,14 +118,38 @@ function SettingsCtrl($rootScope, $scope, $state, $http) {
|
|||
$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();
|
||||
//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, {
|
||||
withCredentials: true,
|
||||
headers: {'Content-Type': undefined },
|
||||
headers: {
|
||||
'Content-Type': undefined
|
||||
},
|
||||
transformRequest: angular.identity
|
||||
}).success(function (data) {
|
||||
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>
|
||||
</div>
|
||||
<div>
|
||||
<a href="../logs/stratux.log">stratux.log</a>
|
||||
<a target="_blank" href="../logs/stratux.log">stratux.log</a>
|
||||
</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>
|
||||
(Enable device logging on "Settings" page)
|
||||
</dib>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
|
|
|
@ -50,8 +50,11 @@
|
|||
</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-heading">Configuration</div>
|
||||
<div class="panel-body">
|
||||
|
@ -80,44 +83,36 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-group col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Shutdown</div>
|
||||
<div class="panel-heading">Commands</div>
|
||||
<div class="panel-body">
|
||||
<div class="form-group">
|
||||
<div class="col-xs-5">
|
||||
<button ui-turn-on="modalShutdown">Shutdown</button>
|
||||
<!-- Upload. Temporary. -->
|
||||
<div class="col-xs-12">
|
||||
<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 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>
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue