kopia lustrzana https://github.com/cyoung/stratux
More data logger boilerplate. Add to Makefile and init in main().
rodzic
67d62184d3
commit
854b96f608
2
Makefile
2
Makefile
|
@ -14,7 +14,7 @@ all:
|
||||||
|
|
||||||
xgen_gdl90:
|
xgen_gdl90:
|
||||||
go get -t -d -v ./main ./test ./linux-mpu9150/mpu ./godump978 ./mpu6050 ./uatparse
|
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/uibroadcast.go main/monotonic.go main/datalog.go
|
||||||
|
|
||||||
xdump1090:
|
xdump1090:
|
||||||
git submodule update --init
|
git submodule update --init
|
||||||
|
|
118
main/datalog.go
118
main/datalog.go
|
@ -14,6 +14,8 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -21,7 +23,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LOG_TIMESTAMP_RESOLUTION = 50 * time.Millisecond
|
LOG_TIMESTAMP_RESOLUTION = 250 * time.Millisecond
|
||||||
)
|
)
|
||||||
|
|
||||||
type StratuxTimestamp struct {
|
type StratuxTimestamp struct {
|
||||||
|
@ -45,8 +47,10 @@ func checkTimestamp() bool {
|
||||||
if time.Since(dataLogTimestamp.StratuxClock_value) >= LOG_TIMESTAMP_RESOLUTION {
|
if time.Since(dataLogTimestamp.StratuxClock_value) >= LOG_TIMESTAMP_RESOLUTION {
|
||||||
//FIXME: mutex.
|
//FIXME: mutex.
|
||||||
dataLogTimestamp.id = 0
|
dataLogTimestamp.id = 0
|
||||||
dataLogTimestamp.StratuxClock_value = time.Now()
|
dataLogTimestamp.Time_type_preference = 0 // stratuxClock.
|
||||||
dataLogTimestamp.Time_type_preference = 0
|
dataLogTimestamp.StratuxClock_value = stratuxClock.Time
|
||||||
|
dataLogTimestamp.GPSClock_value = time.Time{}
|
||||||
|
dataLogTimestamp.PreferredTime_value = stratuxClock.Time
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -66,14 +70,6 @@ func boolMarshal(v reflect.Value) string {
|
||||||
return "0"
|
return "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
func structCanBeMarshalled(v reflect.Value) bool {
|
|
||||||
m := v.MethodByName("String")
|
|
||||||
if m.IsValid() && !m.IsNil() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func intMarshal(v reflect.Value) string {
|
func intMarshal(v reflect.Value) string {
|
||||||
return strconv.FormatInt(v.Int(), 10)
|
return strconv.FormatInt(v.Int(), 10)
|
||||||
}
|
}
|
||||||
|
@ -94,6 +90,14 @@ func notsupportedMarshal(v reflect.Value) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func structCanBeMarshalled(v reflect.Value) bool {
|
||||||
|
m := v.MethodByName("String")
|
||||||
|
if m.IsValid() && !m.IsNil() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func structMarshal(v reflect.Value) string {
|
func structMarshal(v reflect.Value) string {
|
||||||
if structCanBeMarshalled(v) {
|
if structCanBeMarshalled(v) {
|
||||||
m := v.MethodByName("String")
|
m := v.MethodByName("String")
|
||||||
|
@ -236,17 +240,41 @@ var dataLogChan chan DataLogRow
|
||||||
func dataLogWriter() {
|
func dataLogWriter() {
|
||||||
dataLogChan := make(chan DataLogRow, 10240)
|
dataLogChan := make(chan DataLogRow, 10240)
|
||||||
|
|
||||||
db, err := sql.Open("sqlite3", "./test.db")
|
// Check if we need to create a new database.
|
||||||
|
createDatabase := false
|
||||||
|
|
||||||
|
if _, err := os.Stat(dataLogFile); os.IsNotExist(err) {
|
||||||
|
createDatabase = true
|
||||||
|
log.Printf("creating new database '%s'.\n", dataLogFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := sql.Open("sqlite3", dataLogFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("sql.Open(): %s\n", err.Error())
|
log.Printf("sql.Open(): %s\n", err.Error())
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
|
// Do we need to create the database?
|
||||||
|
if createDatabase {
|
||||||
|
makeTable(dataLogTimestamp, "timestamp", db)
|
||||||
|
makeTable(mySituation, "mySituation", db)
|
||||||
|
makeTable(globalStatus, "status", db)
|
||||||
|
makeTable(globalSettings, "settings", db)
|
||||||
|
makeTable(TrafficInfo{}, "traffic", db)
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
//FIXME: measure latency from here to end of block. Messages may need to be timestamped *before* executing everything here.
|
//FIXME: measure latency from here to end of block. Messages may need to be timestamped *before* executing everything here.
|
||||||
r := <-dataLogChan
|
r := <-dataLogChan
|
||||||
if r.tbl == "mySituation" {
|
if r.tbl == "mySituation" && isGPSClockValid() {
|
||||||
//TODO: Piggyback a GPS time update from this update.
|
// Piggyback a GPS time update from this update.
|
||||||
|
if t, ok := r.data.(SituationData); ok {
|
||||||
|
dataLogTimestamp.id = 0
|
||||||
|
dataLogTimestamp.Time_type_preference = 1 // gpsClock.
|
||||||
|
dataLogTimestamp.StratuxClock_value = stratuxClock.Time
|
||||||
|
dataLogTimestamp.GPSClock_value = t.GPSTime
|
||||||
|
dataLogTimestamp.PreferredTime_value = t.GPSTime
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if our time bucket has expired or has never been entered.
|
// Check if our time bucket has expired or has never been entered.
|
||||||
|
@ -257,50 +285,22 @@ func dataLogWriter() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type SituationData struct {
|
func logSituation() {
|
||||||
// From GPS.
|
dataLogChan <- DataLogRow{tbl: "mySituation", data: mySituation}
|
||||||
LastFixSinceMidnightUTC float32
|
|
||||||
Lat float32
|
|
||||||
Lng float32
|
|
||||||
Quality uint8
|
|
||||||
HeightAboveEllipsoid float32 // GPS height above WGS84 ellipsoid, ft. This is specified by the GDL90 protocol, but most EFBs use MSL altitude instead. HAE is about 70-100 ft below GPS MSL altitude over most of the US.
|
|
||||||
GeoidSep float32 // geoid separation, ft, MSL minus HAE (used in altitude calculation)
|
|
||||||
Satellites uint16 // satellites used in solution
|
|
||||||
SatellitesTracked uint16 // satellites tracked (almanac data received)
|
|
||||||
SatellitesSeen uint16 // satellites seen (signal received)
|
|
||||||
Accuracy float32 // 95% confidence for horizontal position, meters.
|
|
||||||
NACp uint8 // NACp categories are defined in AC 20-165A
|
|
||||||
Alt float32 // Feet MSL
|
|
||||||
AccuracyVert float32 // 95% confidence for vertical position, meters
|
|
||||||
GPSVertVel float32 // GPS vertical velocity, feet per second
|
|
||||||
LastFixLocalTime time.Time
|
|
||||||
TrueCourse uint16
|
|
||||||
GroundSpeed uint16
|
|
||||||
LastGroundTrackTime time.Time
|
|
||||||
LastGPSTimeTime time.Time
|
|
||||||
LastNMEAMessage time.Time // time valid NMEA message last seen
|
|
||||||
|
|
||||||
// From BMP180 pressure sensor.
|
|
||||||
Temp float64
|
|
||||||
Pressure_alt float64
|
|
||||||
LastTempPressTime time.Time
|
|
||||||
|
|
||||||
// From MPU6050 accel/gyro.
|
|
||||||
Pitch float64
|
|
||||||
Roll float64
|
|
||||||
Gyro_heading float64
|
|
||||||
LastAttitudeTime time.Time
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func logStatus() {
|
||||||
db, err := sql.Open("sqlite3", "./test.db")
|
dataLogChan <- DataLogRow{tbl: "status", data: globalStatus}
|
||||||
if err != nil {
|
}
|
||||||
fmt.Printf("sql.Open(): %s\n", err.Error())
|
|
||||||
}
|
func logSettings() {
|
||||||
defer db.Close()
|
dataLogChan <- DataLogRow{tbl: "settings", data: globalSettings}
|
||||||
|
}
|
||||||
e := SituationData{}
|
|
||||||
//makeTable(e, "situation", db)
|
func logTraffic(ti TrafficInfo) {
|
||||||
i := insertData(e, "situation", db)
|
dataLogChan <- DataLogRow{tbl: "traffic", data: ti}
|
||||||
fmt.Printf("insert id=%d\n", i)
|
}
|
||||||
|
|
||||||
|
func initDataLog() {
|
||||||
|
go dataLogWriter()
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ const (
|
||||||
maxDatagramSize = 8192
|
maxDatagramSize = 8192
|
||||||
maxUserMsgQueueSize = 25000 // About 10MB per port per connected client.
|
maxUserMsgQueueSize = 25000 // About 10MB per port per connected client.
|
||||||
logDirectory = "/var/log/stratux"
|
logDirectory = "/var/log/stratux"
|
||||||
|
dataLogFile = "/var/log/stratux.sqlite"
|
||||||
|
|
||||||
UPLINK_BLOCK_DATA_BITS = 576
|
UPLINK_BLOCK_DATA_BITS = 576
|
||||||
UPLINK_BLOCK_BITS = (UPLINK_BLOCK_DATA_BITS + 160)
|
UPLINK_BLOCK_BITS = (UPLINK_BLOCK_DATA_BITS + 160)
|
||||||
|
@ -1361,6 +1362,8 @@ func main() {
|
||||||
globalSettings.ReplayLog = true
|
globalSettings.ReplayLog = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FIXME: Only do this if data logging is enabled.
|
||||||
|
initDataLog()
|
||||||
// Set up the replay logs. Keep these files open in any case, even if replay logging is disabled.
|
// Set up the replay logs. Keep these files open in any case, even if replay logging is disabled.
|
||||||
|
|
||||||
if uatwt, err := openReplay(uatReplayLog, !developerMode); err != nil {
|
if uatwt, err := openReplay(uatReplayLog, !developerMode); err != nil {
|
||||||
|
|
Ładowanie…
Reference in New Issue