First cut of uAvionix Ping changes

pull/427/head
Ryan C. Braun 2016-04-20 08:59:55 +00:00
rodzic 796d0a2632
commit 91fd133271
9 zmienionych plików z 275 dodań i 14 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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":

241
main/ping.go 100644
Wyświetl plik

@ -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()
}

Wyświetl plik

@ -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).

Wyświetl plik

@ -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}
```
```

Wyświetl plik

@ -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) {
});
};
};
};

Wyświetl plik

@ -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) {

Wyświetl plik

@ -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">