kopia lustrzana https://github.com/cyoung/stratux
First cut of uAvionix Ping changes
rodzic
796d0a2632
commit
91fd133271
2
Makefile
2
Makefile
|
@ -14,7 +14,7 @@ all:
|
|||
|
||||
xgen_gdl90:
|
||||
go get -t -d -v ./main ./test ./linux-mpu9150/mpu ./godump978 ./mpu6050 ./uatparse
|
||||
go build $(BUILDINFO) main/gen_gdl90.go main/traffic.go main/ry835ai.go main/network.go main/managementinterface.go main/sdr.go main/uibroadcast.go main/monotonic.go
|
||||
go build $(BUILDINFO) main/gen_gdl90.go main/traffic.go main/ry835ai.go main/network.go main/managementinterface.go main/sdr.go main/ping.go main/uibroadcast.go main/monotonic.go
|
||||
|
||||
xdump1090:
|
||||
git submodule update --init
|
||||
|
|
|
@ -885,6 +885,9 @@ func parseInput(buf string) ([]byte, uint16) {
|
|||
|
||||
if isUplink && msglen == UPLINK_FRAME_DATA_BYTES {
|
||||
msgtype = MSGTYPE_UPLINK
|
||||
} else if msglen == 48 {
|
||||
// With Reed Solomon appended
|
||||
msgtype = MSGTYPE_LONG_REPORT
|
||||
} else if msglen == 34 {
|
||||
msgtype = MSGTYPE_LONG_REPORT
|
||||
} else if msglen == 18 {
|
||||
|
@ -1019,6 +1022,7 @@ func getProductNameFromId(product_id int) string {
|
|||
type settings struct {
|
||||
UAT_Enabled bool
|
||||
ES_Enabled bool
|
||||
Ping_Enabled bool
|
||||
GPS_Enabled bool
|
||||
NetworkOutputs []networkConnection
|
||||
AHRS_Enabled bool
|
||||
|
@ -1039,6 +1043,7 @@ type status struct {
|
|||
UAT_messages_max uint
|
||||
ES_messages_last_minute uint
|
||||
ES_messages_max uint
|
||||
Ping_connected bool
|
||||
GPS_satellites_locked uint16
|
||||
GPS_satellites_seen uint16
|
||||
GPS_satellites_tracked uint16
|
||||
|
@ -1277,6 +1282,7 @@ func closeReplayLogs() {
|
|||
func gracefulShutdown() {
|
||||
// Shut down SDRs.
|
||||
sdrKill()
|
||||
pingKill()
|
||||
//TODO: Any other graceful shutdown functions.
|
||||
closeReplayLogs()
|
||||
os.Exit(1)
|
||||
|
@ -1331,6 +1337,7 @@ func main() {
|
|||
crcInit() // Initialize CRC16 table.
|
||||
|
||||
sdrInit()
|
||||
pingInit()
|
||||
initTraffic()
|
||||
|
||||
globalStatus.Version = stratuxVersion
|
||||
|
|
|
@ -198,6 +198,8 @@ func handleSettingsSetRequest(w http.ResponseWriter, r *http.Request) {
|
|||
globalSettings.UAT_Enabled = val.(bool)
|
||||
case "ES_Enabled":
|
||||
globalSettings.ES_Enabled = val.(bool)
|
||||
case "Ping_Enabled":
|
||||
globalSettings.Ping_Enabled = val.(bool)
|
||||
case "GPS_Enabled":
|
||||
globalSettings.GPS_Enabled = val.(bool)
|
||||
case "AHRS_Enabled":
|
||||
|
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
Copyright (c) 2016 uAvionix
|
||||
Distributable under the terms of The "BSD New"" License
|
||||
that can be found in the LICENSE file, herein included
|
||||
as part of this header.
|
||||
|
||||
ping.go: uAvionix Ping ADS-B monitoring and management.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"strings"
|
||||
"log"
|
||||
"os"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"net"
|
||||
"os/exec"
|
||||
|
||||
"github.com/tarm/serial"
|
||||
)
|
||||
|
||||
// Ping device data
|
||||
var pingSerialConfig *serial.Config
|
||||
var pingSerialPort *serial.Port
|
||||
var pingWG *sync.WaitGroup
|
||||
var closeCh chan int
|
||||
|
||||
func initPingSerial() bool {
|
||||
var device string
|
||||
baudrate := int(2000000)
|
||||
|
||||
log.Printf("Configuring Ping ADS-B\n")
|
||||
|
||||
if _, err := os.Stat("/dev/ttyUSB0"); err == nil {
|
||||
device = "/dev/ttyUSB0"
|
||||
} else if _, err := os.Stat("/dev/ping"); err == nil {
|
||||
device = "/dev/ping"
|
||||
} else {
|
||||
log.Printf("No suitable device found.\n")
|
||||
return false
|
||||
}
|
||||
log.Printf("Using %s for Ping\n", device)
|
||||
|
||||
// Open port
|
||||
//pingSerialConfig = &serial.Config{Name: device, Baud: baudrate, ReadTimeout: time.Millisecond * 2500}
|
||||
pingSerialConfig = &serial.Config{Name: device, Baud: baudrate}
|
||||
p, err := serial.OpenPort(pingSerialConfig)
|
||||
if err != nil {
|
||||
log.Printf("Error opening serial port: %s\n", err.Error())
|
||||
return false
|
||||
}
|
||||
log.Printf("Ping opened serial port")
|
||||
|
||||
// No device configuration is needed, we should be ready
|
||||
|
||||
pingSerialPort = p
|
||||
return true
|
||||
}
|
||||
|
||||
func pingNetworkRepeater() {
|
||||
defer pingWG.Done()
|
||||
log.Println("Entered Ping network repeater ...")
|
||||
cmd := exec.Command("/usr/bin/dump1090", "--net-only")
|
||||
stdout, _ := cmd.StdoutPipe()
|
||||
stderr, _ := cmd.StderrPipe()
|
||||
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
log.Printf("Error executing /usr/bin/dump1090: %s\n", err)
|
||||
// don't return immediately, use the proper shutdown procedure
|
||||
shutdownPing = true
|
||||
for {
|
||||
select {
|
||||
case <-closeCh:
|
||||
return
|
||||
default:
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("Executed /usr/bin/dump1090 successfully...")
|
||||
|
||||
scanStdout := bufio.NewScanner(stdout)
|
||||
scanStderr := bufio.NewScanner(stderr)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-closeCh:
|
||||
log.Println("Ping network repeater: shutdown msg received, calling cmd.Process.Kill() ...")
|
||||
err := cmd.Process.Kill()
|
||||
if err != nil {
|
||||
log.Printf("\t couldn't kill dump1090: %s\n", err)
|
||||
} else {
|
||||
cmd.Wait()
|
||||
log.Println("\t kill successful...")
|
||||
}
|
||||
return
|
||||
default:
|
||||
for scanStdout.Scan() {
|
||||
replayLog(scanStdout.Text(), MSGCLASS_DUMP1090)
|
||||
}
|
||||
if err := scanStdout.Err(); err != nil {
|
||||
log.Printf("scanStdout error: %s\n", err)
|
||||
}
|
||||
|
||||
for scanStderr.Scan() {
|
||||
replayLog(scanStderr.Text(), MSGCLASS_DUMP1090)
|
||||
if shutdownES != true {
|
||||
shutdownES = true
|
||||
}
|
||||
}
|
||||
if err := scanStderr.Err(); err != nil {
|
||||
log.Printf("scanStderr error: %s\n", err)
|
||||
}
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var dump1090Connection net.Conn = nil
|
||||
var connectionError error
|
||||
|
||||
func pingNetworkConnection() {
|
||||
// Send to dump1090 on port 30001
|
||||
dump1090Addr := "127.0.0.1:30001"
|
||||
dump1090Connection, connectionError = net.Dial("tcp", dump1090Addr)
|
||||
// RCB monitoir for connection failure and redial
|
||||
}
|
||||
|
||||
func pingSerialReader() {
|
||||
//defer pingWG.Done()
|
||||
defer pingSerialPort.Close()
|
||||
// RCB TODO channel control for terminate
|
||||
|
||||
log.Printf("Starting Ping serial reader")
|
||||
|
||||
scanner := bufio.NewScanner(pingSerialPort)
|
||||
for scanner.Scan() && globalStatus.Ping_connected && globalSettings.Ping_Enabled {
|
||||
s := scanner.Text()
|
||||
// Trimspace removes newlines as well as whitespace
|
||||
s = strings.TrimSpace(s)
|
||||
logString := fmt.Sprintf("Print received: %s", s);
|
||||
log.Println(logString)
|
||||
if s[0] == '*' {
|
||||
// 1090ES report
|
||||
//replayLog(s, MSGCLASS_DUMP1090);
|
||||
if dump1090Connection != nil {
|
||||
dump1090Connection.Write([]byte(s + "\r\n"))
|
||||
log.Println("Relaying 1090ES message")
|
||||
}
|
||||
} else {
|
||||
// UAT report
|
||||
o, msgtype := parseInput(s)
|
||||
if o != nil && msgtype != 0 {
|
||||
logString = fmt.Sprintf("Relaying message, type=%d", msgtype)
|
||||
log.Println(logString)
|
||||
relayMessage(msgtype, o)
|
||||
} else if (o == nil) {
|
||||
log.Println("Not relaying message, o == nil")
|
||||
} else {
|
||||
log.Println("Not relaying message, msgtype == 0")
|
||||
}
|
||||
}
|
||||
}
|
||||
globalStatus.Ping_connected = false
|
||||
log.Printf("Exiting Ping serial reader")
|
||||
return
|
||||
}
|
||||
|
||||
func pingShutdown() {
|
||||
log.Println("Entered Ping shutdown() ...")
|
||||
//close(closeCh)
|
||||
//log.Println("Ping shutdown(): calling pingWG.Wait() ...")
|
||||
//pingWG.Wait() // Wait for the goroutine to shutdown
|
||||
//log.Println("Ping shutdown(): pingWG.Wait() returned...")
|
||||
// RCB TODO FINISH
|
||||
globalStatus.Ping_connected = false
|
||||
}
|
||||
|
||||
func pingKill() {
|
||||
// Send signal to shutdown to pingWatcher().
|
||||
shutdownPing = true
|
||||
// Spin until device has been de-initialized.
|
||||
for globalStatus.Ping_connected != false {
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
// to keep our sync primitives synchronized, only exit a read
|
||||
// method's goroutine via the close flag channel check, to
|
||||
// include catastrophic dongle failures
|
||||
var shutdownPing bool
|
||||
|
||||
// Watch for config/device changes.
|
||||
func pingWatcher() {
|
||||
prevPingEnabled := false
|
||||
|
||||
for {
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
// true when a serial call fails
|
||||
if shutdownPing {
|
||||
pingShutdown()
|
||||
shutdownPing = false
|
||||
}
|
||||
|
||||
if prevPingEnabled == globalSettings.Ping_Enabled {
|
||||
continue
|
||||
}
|
||||
|
||||
// Global settings have changed, reconfig
|
||||
if globalSettings.Ping_Enabled && !globalStatus.Ping_connected {
|
||||
globalStatus.Ping_connected = initPingSerial()
|
||||
count := 0
|
||||
if globalStatus.Ping_connected {
|
||||
//pingWG.Add(1)
|
||||
go pingNetworkRepeater()
|
||||
go pingNetworkConnection()
|
||||
go pingSerialReader()
|
||||
// Emulate SDR count
|
||||
count = 2
|
||||
}
|
||||
atomic.StoreUint32(&globalStatus.Devices, uint32(count))
|
||||
} else if !globalSettings.Ping_Enabled {
|
||||
pingShutdown()
|
||||
}
|
||||
|
||||
prevPingEnabled = globalSettings.Ping_Enabled
|
||||
}
|
||||
}
|
||||
|
||||
func pingInit() {
|
||||
go pingWatcher()
|
||||
}
|
|
@ -536,7 +536,7 @@ func parseDownlinkReport(s string, signalLevel int) {
|
|||
|
||||
func esListen() {
|
||||
for {
|
||||
if !globalSettings.ES_Enabled {
|
||||
if !globalSettings.ES_Enabled && !globalSettings.Ping_Enabled {
|
||||
time.Sleep(1 * time.Second) // Don't do much unless ES is actually enabled.
|
||||
continue
|
||||
}
|
||||
|
@ -547,15 +547,15 @@ func esListen() {
|
|||
continue
|
||||
}
|
||||
rdr := bufio.NewReader(inConn)
|
||||
for globalSettings.ES_Enabled {
|
||||
//log.Printf("ES enabled. Ready to read next message from dump1090\n")
|
||||
for globalSettings.ES_Enabled || globalSettings.Ping_Enabled {
|
||||
log.Printf("ES enabled. Ready to read next message from dump1090\n")
|
||||
buf, err := rdr.ReadString('\n')
|
||||
//log.Printf("String read from dump1090\n")
|
||||
log.Printf("String read from dump1090\n")
|
||||
if err != nil { // Must have disconnected?
|
||||
break
|
||||
}
|
||||
buf = strings.Trim(buf, "\r\n")
|
||||
//log.Printf("%s\n", buf)
|
||||
log.Printf("%s\n", buf)
|
||||
replayLog(buf, MSGCLASS_ES) // Log the raw message to nnnn-ES.log
|
||||
|
||||
var newTi *dump1090Data
|
||||
|
@ -585,9 +585,9 @@ func esListen() {
|
|||
// Retrieve previous information on this ICAO code.
|
||||
if val, ok := traffic[icao]; ok { // if we've already seen it, copy it in to do updates
|
||||
ti = val
|
||||
//log.Printf("Existing target %X imported for ES update\n", icao)
|
||||
log.Printf("Existing target %X imported for ES update\n", icao)
|
||||
} else {
|
||||
//log.Printf("New target %X created for ES update\n",newTi.Icao_addr)
|
||||
log.Printf("New target %X created for ES update\n",newTi.Icao_addr)
|
||||
ti.Last_seen = stratuxClock.Time // need to initialize to current stratuxClock so it doesn't get cut before we have a chance to populate a position message
|
||||
ti.Icao_addr = icao
|
||||
ti.ExtrapolatedPosition = false
|
||||
|
@ -597,7 +597,6 @@ func esListen() {
|
|||
|
||||
// generate human readable summary of message types for debug
|
||||
// TO-DO: Use for ES message statistics?
|
||||
/*
|
||||
var s1 string
|
||||
if newTi.DF == 17 {
|
||||
s1 = "ADS-B"
|
||||
|
@ -625,8 +624,7 @@ func esListen() {
|
|||
if newTi.DF == 16 {
|
||||
s1 = "Long Air-Air Surv."
|
||||
}
|
||||
*/
|
||||
//log.Printf("Mode S message from icao=%X, DF=%02d, CA=%02d, TC=%02d (%s)\n", ti.Icao_addr, newTi.DF, newTi.CA, newTi.TypeCode, s1)
|
||||
log.Printf("Mode S message from icao=%X, DF=%02d, CA=%02d, TC=%02d (%s)\n", ti.Icao_addr, newTi.DF, newTi.CA, newTi.TypeCode, s1)
|
||||
|
||||
// Altitude will be sent by dump1090 for ES ADS-B/TIS-B (DF=17 and DF=18)
|
||||
// and Mode S messages (DF=0, DF = 4, and DF = 20).
|
||||
|
|
|
@ -115,6 +115,7 @@ Stratux makes available a webserver to retrieve statistics which may be useful t
|
|||
{
|
||||
"UAT_Enabled": true,
|
||||
"ES_Enabled": false,
|
||||
"Ping_Enabled": false,
|
||||
"GPS_Enabled": true,
|
||||
"NetworkOutputs": [
|
||||
{
|
||||
|
@ -177,4 +178,4 @@ Subsequent update (2837120 = 2B4A80 reports a newer position, altitude increased
|
|||
|
||||
```json
|
||||
{"Icao_addr":2837120,"OnGround":false,"Lat":42.193336,"Lng":-83.92136,"Position_valid":true,"Alt":3400,"Track":9,"Speed":92,"Speed_valid":true,"Vvel":0,"Tail":"","Last_seen":"2015-12-22T21:29:22.252914555Z","Last_source":2}
|
||||
```
|
||||
```
|
||||
|
|
|
@ -6,7 +6,7 @@ function SettingsCtrl($rootScope, $scope, $state, $http) {
|
|||
|
||||
$scope.$parent.helppage = 'plates/settings-help.html';
|
||||
|
||||
var toggles = ['UAT_Enabled', 'ES_Enabled', 'GPS_Enabled', 'AHRS_Enabled', 'DEBUG', 'ReplayLog']; // DEBUG is 'DspTrafficSrc'
|
||||
var toggles = ['UAT_Enabled', 'ES_Enabled', 'Ping_Enabled', 'GPS_Enabled', 'AHRS_Enabled', 'DEBUG', 'ReplayLog']; // DEBUG is 'DspTrafficSrc'
|
||||
var settings = {};
|
||||
for (i = 0; i < toggles.length; i++) {
|
||||
settings[toggles[i]] = undefined;
|
||||
|
@ -19,6 +19,7 @@ function SettingsCtrl($rootScope, $scope, $state, $http) {
|
|||
$scope.rawSettings = angular.toJson(data, true);
|
||||
$scope.UAT_Enabled = settings.UAT_Enabled;
|
||||
$scope.ES_Enabled = settings.ES_Enabled;
|
||||
$scope.Ping_Enabled = settings.Ping_Enabled;
|
||||
$scope.GPS_Enabled = settings.GPS_Enabled;
|
||||
$scope.AHRS_Enabled = settings.AHRS_Enabled;
|
||||
$scope.PowerSave = settings.PowerSave
|
||||
|
@ -159,4 +160,4 @@ function SettingsCtrl($rootScope, $scope, $state, $http) {
|
|||
});
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -97,6 +97,11 @@ function StatusCtrl($rootScope, $scope, $state, $http, $interval) {
|
|||
settings = angular.fromJson(response.data);
|
||||
$scope.visible_uat = settings.UAT_Enabled;
|
||||
$scope.visible_es = settings.ES_Enabled;
|
||||
$scope.visible_ping = settings.Ping_Enabled;
|
||||
if (settings.Ping_Enabled) {
|
||||
$scope.visible_uat = true;
|
||||
$scope.visible_es = true;
|
||||
}
|
||||
$scope.visible_gps = settings.GPS_Enabled;
|
||||
$scope.visible_ahrs = settings.AHRS_Enabled;
|
||||
}, function (response) {
|
||||
|
|
|
@ -16,6 +16,12 @@
|
|||
<ui-switch ng-model='ES_Enabled' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">Ping ADS-B</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='Ping_Enabled' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">GPS</label>
|
||||
<div class="col-xs-5">
|
||||
|
|
Ładowanie…
Reference in New Issue