diff --git a/circle.yml b/circle.yml index e5c23521..925e7573 100644 --- a/circle.yml +++ b/circle.yml @@ -18,6 +18,3 @@ deployment: branch: master commands: - yes | ssh -i ~/.ssh/id_updates.stratux.me stratux-updates@updates.stratux.me "touch queue/`git log -n 1 --pretty=%H`" - branch: ahrs_dev - commands: - - yes | ssh -i ~/.ssh/id_updates.stratux.me stratux-updates@updates.stratux.me "touch queue/`git log -n 1 --pretty=%H`" diff --git a/image/hostapd_manager.sh b/image/hostapd_manager.sh index bc23253d..fa95cb32 100644 --- a/image/hostapd_manager.sh +++ b/image/hostapd_manager.sh @@ -274,6 +274,10 @@ do fi fi + if [ $OPT_P != false ]; then + OPT_E=$OPT_P + fi + if [ $OPT_E != false ]; then echo "${MAGENTA}Adding WPA encryption with passphrase: ${YELLOW}$OPT_E ${MAGENTA}to $i...${WHITE}" if grep -q "^#auth_algs=" ${i}; then diff --git a/main/fancontrol.go b/main/fancontrol.go index 3369242c..efdde267 100644 --- a/main/fancontrol.go +++ b/main/fancontrol.go @@ -69,6 +69,8 @@ func fanControl(pwmDutyMin int, pin int, tempTarget float32) { }) pwmDuty := 0 + delay := time.NewTicker(delaySeconds * time.Second) + for { if temp > (tempTarget + hysteresis) { pwmDuty = iMax(iMin(pwmDutyMax, pwmDuty+1), pwmDutyMin) @@ -80,7 +82,7 @@ func fanControl(pwmDutyMin int, pin int, tempTarget float32) { } //log.Println(temp, " ", pwmDuty) C.pwmWrite(cPin, C.int(pwmDuty)) - time.Sleep(delaySeconds * time.Second) + <-delay.C } // Default to "ON". @@ -158,7 +160,7 @@ func (service *Service) Manage() (string, error) { } // Accept a client connection and collect it in a channel -func acceptConnection(listener net.Listener, listen chan<- net.Conn) { +func acceptConnection(listener net.Listener, listen chan net.Conn) { for { conn, err := listener.Accept() if err != nil { @@ -169,6 +171,7 @@ func acceptConnection(listener net.Listener, listen chan<- net.Conn) { } func handleClient(client net.Conn) { + defer client.Close() for { buf := make([]byte, 4096) numbytes, err := client.Read(buf) diff --git a/main/sdr.go b/main/sdr.go index d352277c..d303414f 100644 --- a/main/sdr.go +++ b/main/sdr.go @@ -10,6 +10,7 @@ package main import ( + "fmt" "log" "os/exec" "regexp" @@ -17,6 +18,7 @@ import ( "strings" "sync" "sync/atomic" + "syscall" "time" "../godump978" @@ -471,7 +473,21 @@ func sdrWatcher() { prevUATEnabled := false prevESEnabled := false - time.Sleep(90 * time.Second) + // Get the system (RPi) uptime. + info := syscall.Sysinfo_t{} + err := syscall.Sysinfo(&info) + if err == nil { + // Got system uptime. Delay if and only if the system uptime is less than 120 seconds. This should be plenty of time + // for the RPi to come up and start Stratux. Keeps the delay from happening if the daemon is auto-restarted from systemd. + if info.Uptime < 120 { + time.Sleep(90 * time.Second) + } else if globalSettings.DeveloperMode { + // Throw a "critical error" if developer mode is enabled. Alerts the developer that the daemon was restarted (possibly) + // unexpectedly. + daemonRestartedErr := fmt.Errorf("System uptime %d seconds. Daemon restarted.\n") + addSystemError(daemonRestartedErr) + } + } for { time.Sleep(1 * time.Second) diff --git a/notes/app-vendor-integration.md b/notes/app-vendor-integration.md index d3234fcb..b69ade30 100644 --- a/notes/app-vendor-integration.md +++ b/notes/app-vendor-integration.md @@ -15,8 +15,9 @@ In order of preference: 1. Look for `0xCC` (or `0x5358`) GDL90 heartbeat message. This is sent at the same time as the GDL90 heartbeat (0x00) message. 2. Look for Wi-Fi network that **starts with** "stratux". 3. Detect 192.168.10.0/24 Wi-Fi connection, verify stratux status with JSON response from ws://192.168.10.1/status. +4. Use the the second [stratux status](http://hiltonsoftware.com/stratux/StratuxStatusMessage-V104.pdf) message. -See main/gen_gdl90.go:makeStratuxHeartbeat() for heartbeat format. +See main/gen_gdl90.go:makeStratuxHeartbeat() for heartbeat (#1) format. ### Sleep mode @@ -93,18 +94,52 @@ Stratux makes available a webserver to retrieve statistics which may be useful t ```javascript { - "Version": "v0.5b1", // Software version. - "Devices": 0, // Number of radios connected. - "Connected_Users": 1, // Number of WiFi devices connected. - "UAT_messages_last_minute": 0, // UAT messages received in last minute. - "UAT_messages_max": 17949, // Max UAT messages received in a minute (since last reboot). - "ES_messages_last_minute": 0, // 1090ES messages received in last minute. - "ES_messages_max": 0, // Max 1090ES messages received in a minute (since last reboot). - "GPS_satellites_locked": 0, // Number of GPS satellites used in last GPS lock. - "GPS_connected": true, // GPS unit connected and functioning. - "GPS_solution": "", // "DGPS (WAAS)", "3D GPS", "N/A", or "" when GPS not connected/enabled. - "Uptime": 227068, // Device uptime (in milliseconds). - "CPUTemp": 42.236 // CPU temperature (in ÂșC). + "Version": "v1.4r2", + "Build": "ebd6b9bf5049aa5bb31c345c1eaa39648bc219a2", + "HardwareBuild": "", + "Devices": 1, + "Connected_Users": 0, + "DiskBytesFree": 60625375232, + "UAT_messages_last_minute": 0, + "UAT_messages_max": 0, + "ES_messages_last_minute": 0, + "ES_messages_max": 0, + "UAT_traffic_targets_tracking": 0, + "ES_traffic_targets_tracking": 0, + "Ping_connected": false, + "GPS_satellites_locked": 5, + "GPS_satellites_seen": 7, + "GPS_satellites_tracked": 9, + "GPS_position_accuracy": 10.2, + "GPS_connected": true, + "GPS_solution": "GPS + SBAS (WAAS)", + "GPS_detected_type": 55, + "Uptime": 323020, + "UptimeClock": "0001-01-01T00:05:23.02Z", + "CPUTemp": 47.774, + "CPULoad": "", + "NetworkDataMessagesSent": 0, + "NetworkDataMessagesSentNonqueueable": 0, + "NetworkDataBytesSent": 0, + "NetworkDataBytesSentNonqueueable": 0, + "NetworkDataMessagesSentLastSec": 0, + "NetworkDataMessagesSentNonqueueableLastSec": 0, + "NetworkDataBytesSentLastSec": 0, + "NetworkDataBytesSentNonqueueableLastSec": 0, + "UAT_METAR_total": 0, + "UAT_TAF_total": 0, + "UAT_NEXRAD_total": 0, + "UAT_SIGMET_total": 0, + "UAT_PIREP_total": 0, + "UAT_NOTAM_total": 0, + "UAT_OTHER_total": 0, + "Errors": [ + + ], + "Logfile_Size": 34487043, + "AHRS_LogFiles_Size": 0, + "BMPConnected": true, + "IMUConnected": true } ``` @@ -116,27 +151,53 @@ Stratux makes available a webserver to retrieve statistics which may be useful t "ES_Enabled": false, "Ping_Enabled": false, "GPS_Enabled": true, + "BMP_Sensor_Enabled": true, + "IMU_Sensor_Enabled": true, "NetworkOutputs": [ { "Conn": null, "Ip": "", "Port": 4000, - "Capability": 5 - }, - { - "Conn": null, - "Ip": "", - "Port": 49002, - "Capability": 2 + "Capability": 5, + "MessageQueueLen": 0, + "LastUnreachable": "0001-01-01T00:00:00Z", + "SleepFlag": false, + "FFCrippled": false } ], + "SerialOutputs": null, + "DisplayTrafficSource": false, "DEBUG": false, - "ReplayLog": true, + "ReplayLog": false, + "AHRSLog": false, + "IMUMapping": [ + -1, + 0 + ], + "SensorQuaternion": [ + 0.0068582877312501, + 0.0067230280142738, + 0.7140806859355, + -0.69999752767998 + ], + "C": [ + -0.019065523239845, + -0.99225684377575, + -0.019766228217414 + ], + "D": [ + -2.7707754753258, + 5.544145023957, + -1.890621662038 + ], "PPM": 0, "OwnshipModeS": "F00000", "WatchList": "", "DeveloperMode": false, - "StaticIps": [] + "GLimits": "", + "StaticIps": [ + + ] } ``` * `http://192.168.10.1/setSettings` - set device settings. Use an HTTP POST of JSON content in the format given above - posting only the fields containing the settings to be modified. @@ -145,22 +206,45 @@ Stratux makes available a webserver to retrieve statistics which may be useful t ```json { - "Lat": 39.108533, - "Lng": -76.770862, - "Satellites": 7, - "Accuracy": 5.88, - "NACp": 10, - "Alt": 170.10767, - "LastFixLocalTime": "2015-12-18T23:47:06.015563066Z", - "TrueCourse": 0, - "GroundSpeed": 0, - "LastGroundTrackTime": "0001-01-01T00:00:00Z", - "Temp": 6553, - "Pressure_alt": 231.27980834234, - "Pitch": -0.006116937627108, - "Roll": -0.026442866350631, - "Gyro_heading": 45.844213419776, - "LastAttitudeTime": "2015-12-18T23:47:06.774039623Z" + "GPSLastFixSinceMidnightUTC": 67337.6, + "GPSLatitude": 39.108533, + "GPSLongitude": -76.770862, + "GPSFixQuality": 2, + "GPSHeightAboveEllipsoid": 115.51, + "GPSGeoidSep": -17.523, + "GPSSatellites": 5, + "GPSSatellitesTracked": 11, + "GPSSatellitesSeen": 8, + "GPSHorizontalAccuracy": 10.2, + "GPSNACp": 9, + "GPSAltitudeMSL": 170.10767, + "GPSVerticalAccuracy": 8, + "GPSVerticalSpeed": -0.6135171, + "GPSLastFixLocalTime": "0001-01-01T00:06:44.24Z", + "GPSTrueCourse": 0, + "GPSTurnRate": 0, + "GPSGroundSpeed": 0.77598433056951, + "GPSLastGroundTrackTime": "0001-01-01T00:06:44.24Z", + "GPSTime": "2017-09-26T18:42:17Z", + "GPSLastGPSTimeStratuxTime": "0001-01-01T00:06:43.65Z", + "GPSLastValidNMEAMessageTime": "0001-01-01T00:06:44.24Z", + "GPSLastValidNMEAMessage": "$PUBX,04,184426.00,260917,240266.00,1968,18,-177618,-952.368,21*1A", + "GPSPositionSampleRate": 0, + "BaroTemperature": 37.02, + "BaroPressureAltitude": 153.32, + "BaroVerticalSpeed": 1.3123479, + "BaroLastMeasurementTime": "0001-01-01T00:06:44.23Z", + "AHRSPitch": -0.97934145732801, + "AHRSRoll": -2.2013729217108, + "AHRSGyroHeading": 187741.08073052, + "AHRSMagHeading": 3276.7, + "AHRSSlipSkid": 0.52267604604907, + "AHRSTurnRate": 3276.7, + "AHRSGLoad": 0.99847599584255, + "AHRSGLoadMin": 0.99815989027411, + "AHRSGLoadMax": 1.0043409597397, + "AHRSLastAttitudeTime": "0001-01-01T00:06:44.28Z", + "AHRSStatus": 7 } ``` diff --git a/test/maxgap.go b/test/maxgap.go index e4b64203..73beec9f 100644 --- a/test/maxgap.go +++ b/test/maxgap.go @@ -1,27 +1,25 @@ package main - import ( "fmt" -// "time" + // "time" "../uatparse" - "os" "bufio" + "gonum.org/v1/plot" + "gonum.org/v1/plot/plotter" + "gonum.org/v1/plot/plotutil" + "gonum.org/v1/plot/vg" + "os" + "sort" + "strconv" "strings" "unicode" - "strconv" - "github.com/gonum/plot" - "github.com/gonum/plot/plotter" - "github.com/gonum/plot/plotutil" - "github.com/gonum/plot/vg" - "sort" ) const ( UPLINK_FRAME_DATA_BYTES = 432 ) - /* From AC 00-45G [http://www.faa.gov/documentLibrary/media/Advisory_Circular/AC_00-45G_CHG_1-2.pdf] @@ -51,29 +49,28 @@ Winds Aloft 12 hours 10 minutes */ -func append_metars(rawUplinkMessage string, curMetars []string) []string { +func append_metars(rawUplinkMessage string, curMetars []string) []string { ret := curMetars uatMsg, err := uatparse.New(rawUplinkMessage) if err != nil { return ret } -//fmt.Printf("*************************\n") + //fmt.Printf("*************************\n") metars, _ := uatMsg.GetTextReports() for _, v := range metars { -//fmt.Printf("EE: %s\n", v) + //fmt.Printf("EE: %s\n", v) vSplit := strings.Split(v, " ") if vSplit[0] != "METAR" || len(vSplit) < 3 { // Only looking for METARs. continue } ret = append(ret, v) } -//fmt.Printf("=========================\n") - + //fmt.Printf("=========================\n") + return ret } - /* Average number of METARs received for an airport for which you first received a METAR in the first 5 minutes, over 10 minutes. Divided by two. */ @@ -97,7 +94,7 @@ func metar_qos_one_period(a, b []string) float64 { ret += float64(num) } if len(numMetarByIdent) > 0 { - ret = ret / float64(2 * len(numMetarByIdent)) + ret = ret / float64(2*len(numMetarByIdent)) } return ret } @@ -124,7 +121,7 @@ func main() { if err != nil { break } - buf = strings.TrimFunc(buf, func(r rune) bool {return unicode.IsControl(r)}) + buf = strings.TrimFunc(buf, func(r rune) bool { return unicode.IsControl(r) }) linesplit := strings.Split(buf, ",") if len(linesplit) < 2 { // Blank line or invalid. continue @@ -132,9 +129,9 @@ func main() { if linesplit[0] == "START" { // Reset ticker, new start. //TODO: Support multiple sessions. // Reset the counters, new session. -// qos = make(map[uint]float64) -// curWindowMetars = make([]string, 0) -// curWindow = 0 + // qos = make(map[uint]float64) + // curWindowMetars = make([]string, 0) + // curWindow = 0 windowOffset = curWindow } else { // If it's not "START", then it's a tick count. i, err := strconv.ParseInt(linesplit[0], 10, 64) @@ -145,17 +142,17 @@ func main() { // Window number in current session. wnum := int64(i / (5 * 60 * 1000000000)) -// fmt.Printf("%d\n", curWindow) - if wnum + windowOffset != curWindow { // Switched over. + // fmt.Printf("%d\n", curWindow) + if wnum+windowOffset != curWindow { // Switched over. curWindow = wnum + windowOffset - beforeLastWindowMetars, ok := metarsByWindow[curWindow - 2] - lastWindowMetars, ok2 := metarsByWindow[curWindow - 1] + beforeLastWindowMetars, ok := metarsByWindow[curWindow-2] + lastWindowMetars, ok2 := metarsByWindow[curWindow-1] if ok && ok2 { - // fmt.Printf("%v\n\n\nheyy\n\n%v\n", beforeLastWindowMetars, lastWindowMetars) - qos[curWindow - 1] = metar_qos_one_period(beforeLastWindowMetars, lastWindowMetars) - fmt.Printf("qos=%f\n", qos[curWindow - 1]) - delete(metarsByWindow, curWindow - 2) - delete(metarsByWindow, curWindow - 1) + // fmt.Printf("%v\n\n\nheyy\n\n%v\n", beforeLastWindowMetars, lastWindowMetars) + qos[curWindow-1] = metar_qos_one_period(beforeLastWindowMetars, lastWindowMetars) + fmt.Printf("qos=%f\n", qos[curWindow-1]) + delete(metarsByWindow, curWindow-2) + delete(metarsByWindow, curWindow-1) } } metarsByWindow[curWindow] = append_metars(linesplit[1], metarsByWindow[curWindow]) @@ -180,7 +177,7 @@ func main() { pts := make(plotter.XYs, len(qos)) i := 0 - for _,k := range keys { + for _, k := range keys { v := qos[int64(k)] fmt.Printf("%d, %f\n", k, v) pts[i].X = float64(k) @@ -192,7 +189,7 @@ func main() { if err != nil { panic(err) } - if err := p.Save(4 * vg.Inch, 4 * vg.Inch, "qos.png"); err != nil { + if err := p.Save(4*vg.Inch, 4*vg.Inch, "qos.png"); err != nil { panic(err) } } diff --git a/test/packetrate b/test/packetrate deleted file mode 100755 index 30236f4e..00000000 Binary files a/test/packetrate and /dev/null differ diff --git a/test/packetrate.go b/test/packetrate.go index d286adac..22d2f10c 100644 --- a/test/packetrate.go +++ b/test/packetrate.go @@ -1,19 +1,18 @@ package main - import ( "fmt" -// "time" - "os" + // "time" "bufio" + "gonum.org/v1/plot" + "gonum.org/v1/plot/plotter" + "gonum.org/v1/plot/plotutil" + "gonum.org/v1/plot/vg" + "os" + "sort" + "strconv" "strings" "unicode" - "strconv" - "github.com/gonum/plot" - "github.com/gonum/plot/plotter" - "github.com/gonum/plot/plotutil" - "github.com/gonum/plot/vg" - "sort" ) func main() { @@ -37,7 +36,7 @@ func main() { if err != nil { break } - buf = strings.TrimFunc(buf, func(r rune) bool {return unicode.IsControl(r)}) + buf = strings.TrimFunc(buf, func(r rune) bool { return unicode.IsControl(r) }) linesplit := strings.Split(buf, ",") if len(linesplit) < 2 { // Blank line or invalid. continue @@ -53,10 +52,10 @@ func main() { // Window number in current session. wnum := int64(i / (60 * 1000000000)) -// fmt.Printf("%d\n", curWindow) - if wnum + windowOffset != curWindow { // Switched over. + // fmt.Printf("%d\n", curWindow) + if wnum+windowOffset != curWindow { // Switched over. curWindow = wnum + windowOffset - fmt.Printf("ppm=%d\n", ppm[curWindow - 1]) + fmt.Printf("ppm=%d\n", ppm[curWindow-1]) } ppm[curWindow]++ } @@ -80,7 +79,7 @@ func main() { pts := make(plotter.XYs, len(ppm)) i := 0 - for _,k := range keys { + for _, k := range keys { v := ppm[int64(k)] fmt.Printf("%d, %d\n", k, v) pts[i].X = float64(k) @@ -92,7 +91,7 @@ func main() { if err != nil { panic(err) } - if err := p.Save(4 * vg.Inch, 4 * vg.Inch, "ppm.png"); err != nil { + if err := p.Save(4*vg.Inch, 4*vg.Inch, "ppm.png"); err != nil { panic(err) } -} \ No newline at end of file +}