Merge pull request #427 from uavionix/master

Initial
pull/470/head^2
cyoung 2016-05-26 23:15:41 -04:00
commit 3843350432
13 zmienionych plików z 327 dodań i 10 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) -p 4 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 main/datalog.go main/equations.go
go build $(BUILDINFO) -p 4 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 main/datalog.go main/equations.go
xdump1090:
git submodule update --init

Wyświetl plik

@ -0,0 +1,6 @@
# uAvionix Ping Mavlink
ATTRS{idProduct}=="74f0", ATTRS{idVendor}=="0403", RUN+="/sbin/modprobe -q ftdi_sio" RUN+="/bin/sh -c 'echo 0403 74f0 > /sys/bus/usb-serial/drivers/ftdi_sio/new_id'", OWNER="root", MODE="0666", SYMLINK+="ping"
# uAvionix Ping Raw
ATTRS{idProduct}=="74f1", ATTRS{idVendor}=="0403", RUN+="/sbin/modprobe -q ftdi_sio" RUN+="/bin/sh -c 'echo 0403 74f1 > /sys/bus/usb-serial/drivers/ftdi_sio/new_id'", OWNER="root", MODE="0666", SYMLINK+="ping"

Wyświetl plik

@ -50,6 +50,8 @@ cp -f interfaces mnt/etc/network/interfaces
#custom hostapd start script
cp stratux-wifi.sh mnt/usr/sbin/
chmod 755 mnt/usr/sbin/stratux-wifi.sh
#ping udev
cp -f 99-uavionix.rules mnt/etc/udev/rules.d
#isc-dhcp-server config
cp -f isc-dhcp-server mnt/etc/default/isc-dhcp-server

Wyświetl plik

@ -436,6 +436,11 @@ func makeStratuxStatus() []byte {
msg[13] = msg[13] | (1 << 6)
}
// Ping provides ES and UAT
if globalSettings.Ping_Enabled {
msg[13] = msg[13] | (1 << 5) | (1 << 6)
}
// Valid/Enabled: GPS Enabled portion.
if globalSettings.GPS_Enabled {
msg[13] = msg[13] | (1 << 7)
@ -834,6 +839,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 {
@ -969,6 +977,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
@ -992,6 +1001,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
@ -1197,6 +1207,7 @@ var sigs = make(chan os.Signal, 1) // Signal catch channel (shutdown).
func gracefulShutdown() {
// Shut down SDRs.
sdrKill()
pingKill()
// Shut down data logging.
if dataLogStarted {
@ -1267,6 +1278,7 @@ func main() {
crcInit() // Initialize CRC16 table.
sdrInit()
pingInit()
initTraffic()
// Read settings.

Wyświetl plik

@ -212,6 +212,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":

270
main/ping.go 100644
Wyświetl plik

@ -0,0 +1,270 @@
/*
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"
// Using forked version of tarm/serial to force Linux
// instead of posix code, allowing for higher baud rates
"github.com/uavionix/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 Ping device found.\n")
return false
}
log.Printf("Using %s for Ping\n", device)
// Open port
// No timeout specified as Ping does not heartbeat
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() {
m := Dump1090TermMessage{Text: scanStdout.Text(), Source: "stdout"}
logDump1090TermMessage(m)
}
if err := scanStdout.Err(); err != nil {
log.Printf("scanStdout error: %s\n", err)
}
for scanStderr.Scan() {
m := Dump1090TermMessage{Text: scanStderr.Text(), Source: "stderr"}
logDump1090TermMessage(m)
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 monitor 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("Ping received: %s", s);
log.Println(logString)
if s[0] == '*' {
// 1090ES report
// Ping appends a signal strength at the end of the message
// e.g. *8DC01C2860C37797E9732E555B23;ss=049D;
// Remove this before forwarding to dump1090
// We currently aren't doing anything with this information
// and need to develop a scaling equation - we're using a
// log detector for power so it should have a logarithmic
// relationship. In one example, at -25dBm input (upper limit
// of RX) we saw ~0x500. At -95dBm input (lower limit of RX)
// we saw 0x370
report := strings.Split(s, ";")
//replayLog(s, MSGCLASS_DUMP1090);
if dump1090Connection == nil {
log.Println("Starting dump1090 network connection")
pingNetworkConnection()
}
if (len(report[0]) != 0 && dump1090Connection != nil) {
dump1090Connection.Write([]byte(report[0] + ";\r\n"))
//log.Println("Relaying 1090ES message")
//logString := fmt.Sprintf("Relaying 1090ES: %s;", report[0]);
//log.Println(logString)
}
} else if (s[0] == '+' || s[0] == '-') {
// UAT report
// Ping appends a signal strength and RS bit errors corrected
// at the end of the message
// e.g. -08A5DFDF3907E982585F029B00040080105C3AB4BC5C240700A206000000000000003A13C82F96C80A63191F05FCB231;rs=1;ss=A2;
// We need to rescale the signal strength for interpretation by dump978,
// which expects a 0-1000 base 10 (linear?) scale
// RSSI is in hex and represents an int8 with -128 (0x80) representing an
// errored measurement. There will be some offset from actual due to loss
// in the path. In one example we measured 0x93 (-98) when injecting a
// -102dBm signal
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()
//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

@ -487,14 +487,18 @@ func sdrWatcher() {
// true when a ReadSync call fails
if shutdownUAT {
UATDev.shutdown()
UATDev = nil
if UATDev != nil {
UATDev.shutdown()
UATDev = nil
}
shutdownUAT = false
}
// true when we get stderr output
if shutdownES {
ESDev.shutdown()
ESDev = nil
if ESDev != nil {
ESDev.shutdown()
ESDev = nil
}
shutdownES = false
}

Wyświetl plik

@ -573,7 +573,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
}
@ -584,7 +584,7 @@ func esListen() {
continue
}
rdr := bufio.NewReader(inConn)
for globalSettings.ES_Enabled {
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")

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, $location, $window, $http) {
$scope.$parent.helppage = 'plates/settings-help.html';
var toggles = ['UAT_Enabled', 'ES_Enabled', 'GPS_Enabled', 'AHRS_Enabled', 'DisplayTrafficSource', 'DEBUG', 'ReplayLog'];
var toggles = ['UAT_Enabled', 'ES_Enabled', 'Ping_Enabled', 'GPS_Enabled', 'AHRS_Enabled', 'DisplayTrafficSource', 'DEBUG', 'ReplayLog'];
var settings = {};
for (i = 0; i < toggles.length; i++) {
settings[toggles[i]] = undefined;
@ -19,6 +19,7 @@ function SettingsCtrl($rootScope, $scope, $state, $location, $window, $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.DisplayTrafficSource = settings.DisplayTrafficSource;
@ -178,4 +179,4 @@ function SettingsCtrl($rootScope, $scope, $state, $location, $window, $http) {
});
};
};
};

Wyświetl plik

@ -44,6 +44,7 @@ function StatusCtrl($rootScope, $scope, $state, $http, $interval) {
$scope.Version = status.Version;
$scope.Build = status.Build.substr(0, 10);
$scope.Devices = status.Devices;
$scope.Ping_connected = status.Ping_connected;
$scope.Connected_Users = status.Connected_Users;
$scope.UAT_messages_last_minute = status.UAT_messages_last_minute;
// $scope.UAT_products_last_minute = JSON.stringify(status.UAT_products_last_minute);
@ -102,6 +103,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">

Wyświetl plik

@ -25,10 +25,17 @@
<strong class="col-xs-5">Recent Clients:</strong>
<span class="col-xs-7">{{Connected_Users}}</span>
</div>
</div>
<div class="row">
<div class="col-sm-6 label_adj">
<strong class="col-xs-5">SDR devices:</strong>
<span class="col-xs-7">{{Devices}}</span>
</div>
<div class="col-sm-6 label_adj" ng-class="{'section_invisible': !visible_ping}">
<strong class="col-xs-5">Ping device:</strong>
<span ng-show="Ping_connected == true" class="label label-success">Connected</span>
<span ng-hide="Ping_connected == true" class="label label-danger">Disconnected</span>
</div>
</div>
<div class="separator"></div>
<div class="row">