Merge pull request #428 from AvSquirrel/uat-mutex

Additional UAT stability improvements (tower mutex, array bounds checks)
pull/436/head
cyoung 2016-05-31 08:26:50 -04:00
commit 8f310d0afc
3 zmienionych plików z 82 dodań i 60 usunięć

Wyświetl plik

@ -26,6 +26,7 @@ import (
"runtime"
"strconv"
"strings"
"sync"
"syscall"
"time"
@ -129,6 +130,7 @@ type ADSBTower struct {
}
var ADSBTowers map[string]ADSBTower // Running list of all towers seen. (lat,lng) -> ADSBTower
var ADSBTowerMutex *sync.Mutex
// Construct the CRC table. Adapted from FAA ref above.
func crcInit() {
@ -467,7 +469,8 @@ func makeStratuxStatus() []byte {
msg[26] = byte((v & 0xFF00) >> 8)
msg[27] = byte(v & 0xFF)
// Number of ADS-B towers.
// Number of ADS-B towers. Map structure is protected by ADSBTowerMutex.
ADSBTowerMutex.Lock()
num_towers := uint8(len(ADSBTowers))
msg[28] = byte(num_towers)
@ -484,7 +487,7 @@ func makeStratuxStatus() []byte {
msg = append(msg, tmp[1]) // Longitude.
msg = append(msg, tmp[2]) // Longitude.
}
ADSBTowerMutex.Unlock()
return prepareMessage(msg)
}
@ -600,7 +603,9 @@ func updateMessageStats() {
m := len(MsgLog)
UAT_messages_last_minute := uint(0)
ES_messages_last_minute := uint(0)
products_last_minute := make(map[string]uint32)
//products_last_minute := make(map[string]uint32)
ADSBTowerMutex.Lock()
// Clear out ADSBTowers stats.
for t, tinf := range ADSBTowers {
@ -614,9 +619,9 @@ func updateMessageStats() {
t = append(t, MsgLog[i])
if MsgLog[i].MessageClass == MSGCLASS_UAT {
UAT_messages_last_minute++
for _, p := range MsgLog[i].Products {
products_last_minute[getProductNameFromId(int(p))]++
}
//for _, p := range MsgLog[i].Products {
// products_last_minute[getProductNameFromId(int(p))]++
//}
if len(MsgLog[i].ADSBTowerID) > 0 { // Update tower stats.
tid := MsgLog[i].ADSBTowerID
twr := ADSBTowers[tid]
@ -635,7 +640,7 @@ func updateMessageStats() {
MsgLog = t
globalStatus.UAT_messages_last_minute = UAT_messages_last_minute
globalStatus.ES_messages_last_minute = ES_messages_last_minute
globalStatus.UAT_products_last_minute = products_last_minute
//globalStatus.UAT_products_last_minute = products_last_minute
// Update "max messages/min" counters.
if globalStatus.UAT_messages_max < UAT_messages_last_minute {
@ -655,6 +660,7 @@ func updateMessageStats() {
ADSBTowers[t] = tinf
}
ADSBTowerMutex.Unlock()
}
// Check if CPU temperature is valid. Assume <= 0 is invalid.
@ -955,14 +961,14 @@ type settings struct {
}
type status struct {
Version string
Build string
HardwareBuild string
Devices uint32
Connected_Users uint
DiskBytesFree uint64
UAT_messages_last_minute uint
UAT_products_last_minute map[string]uint32
Version string
Build string
HardwareBuild string
Devices uint32
Connected_Users uint
DiskBytesFree uint64
UAT_messages_last_minute uint
//UAT_products_last_minute map[string]uint32
UAT_messages_max uint
ES_messages_last_minute uint
ES_messages_max uint
@ -1238,6 +1244,7 @@ func main() {
log.Printf("Stratux %s (%s) starting.\n", stratuxVersion, stratuxBuild)
ADSBTowers = make(map[string]ADSBTower)
ADSBTowerMutex = &sync.Mutex{}
MsgLog = make([]msg, 0)
crcInit() // Initialize CRC16 table.

Wyświetl plik

@ -151,6 +151,8 @@ func handleSituationRequest(w http.ResponseWriter, r *http.Request) {
func handleTowersRequest(w http.ResponseWriter, r *http.Request) {
setNoCache(w)
setJSONHeaders(w)
ADSBTowerMutex.Lock()
towersJSON, err := json.Marshal(&ADSBTowers)
if err != nil {
log.Printf("Error sending tower JSON data: %s\n", err.Error())
@ -158,6 +160,7 @@ func handleTowersRequest(w http.ResponseWriter, r *http.Request) {
// for testing purposes, we can return a fixed reply
// towersJSON = []byte(`{"(38.490880,-76.135554)":{"Lat":38.49087953567505,"Lng":-76.13555431365967,"Signal_strength_last_minute":100,"Signal_strength_max":67,"Messages_last_minute":1,"Messages_total":1059},"(38.978698,-76.309276)":{"Lat":38.97869825363159,"Lng":-76.30927562713623,"Signal_strength_last_minute":495,"Signal_strength_max":32,"Messages_last_minute":45,"Messages_total":83},"(39.179285,-76.668413)":{"Lat":39.17928457260132,"Lng":-76.66841268539429,"Signal_strength_last_minute":50,"Signal_strength_max":24,"Messages_last_minute":1,"Messages_total":16},"(39.666309,-74.315300)":{"Lat":39.66630935668945,"Lng":-74.31529998779297,"Signal_strength_last_minute":9884,"Signal_strength_max":35,"Messages_last_minute":4,"Messages_total":134}}`)
fmt.Fprintf(w, "%s\n", towersJSON)
ADSBTowerMutex.Unlock()
}
// AJAX call - /getSatellites. Responds with all GNSS satellites that are being tracked, along with status information.

Wyświetl plik

@ -404,55 +404,63 @@ func (f *UATFrame) decodeAirmet() {
f.Points = points
}
case 9: // Extended Range 3D Point (AGL). p.47.
lng_raw := (int32(record_data[0]) << 11) | (int32(record_data[1]) << 3) | (int32(record_data[2]) & 0xE0 >> 5)
lat_raw := ((int32(record_data[2]) & 0x1F) << 14) | (int32(record_data[3]) << 6) | ((int32(record_data[4]) & 0xFC) >> 2)
alt_raw := ((int32(record_data[4]) & 0x03) << 8) | int32(record_data[5])
fmt.Fprintf(ioutil.Discard, "lat_raw=%d, lng_raw=%d, alt_raw=%d\n", lat_raw, lng_raw, alt_raw)
lat, lng := airmetLatLng(lat_raw, lng_raw, false)
alt := alt_raw * 100
fmt.Fprintf(ioutil.Discard, "lat=%f,lng=%f,alt=%d\n", lat, lng, alt)
fmt.Fprintf(ioutil.Discard, "coord:%f,%f\n", lat, lng)
var point GeoPoint
point.Lat = lat
point.Lon = lng
point.Alt = alt
f.Points = []GeoPoint{point}
case 7, 8: // Extended Range Circular Prism (MSL). (8 = AGL)
lng_bot_raw := (int32(record_data[0]) << 10) | (int32(record_data[1]) << 2) | (int32(record_data[2]) & 0xC0 >> 6)
lat_bot_raw := ((int32(record_data[2]) & 0x3F) << 12) | (int32(record_data[3]) << 4) | ((int32(record_data[4]) & 0xF0) >> 4)
lng_top_raw := ((int32(record_data[4]) & 0x0F) << 14) | (int32(record_data[5]) << 6) | ((int32(record_data[6]) & 0xFC) >> 2)
lat_top_raw := ((int32(record_data[6]) & 0x03) << 16) | (int32(record_data[7]) << 8) | int32(record_data[8])
alt_bot_raw := (int32(record_data[9]) & 0xFE) >> 1
alt_top_raw := ((int32(record_data[9]) & 0x01) << 6) | ((int32(record_data[10]) & 0xFC) >> 2)
r_lng_raw := ((int32(record_data[10]) & 0x03) << 7) | ((int32(record_data[11]) & 0xFE) >> 1)
r_lat_raw := ((int32(record_data[11]) & 0x01) << 8) | int32(record_data[12])
alpha := int32(record_data[13])
lat_bot, lng_bot := airmetLatLng(lat_bot_raw, lng_bot_raw, true)
lat_top, lng_top := airmetLatLng(lat_top_raw, lng_top_raw, true)
alt_bot := alt_bot_raw * 5
alt_top := alt_top_raw * 500
r_lng := float64(r_lng_raw) * float64(0.2)
r_lat := float64(r_lat_raw) * float64(0.2)
fmt.Fprintf(ioutil.Discard, "lat_bot, lng_bot = %f, %f\n", lat_bot, lng_bot)
fmt.Fprintf(ioutil.Discard, "lat_top, lng_top = %f, %f\n", lat_top, lng_top)
if geometry_overlay_options == 8 {
fmt.Fprintf(ioutil.Discard, "alt_bot, alt_top = %d AGL, %d AGL\n", alt_bot, alt_top)
if len(record_data) < 6 {
fmt.Fprintf(ioutil.Discard, "invalid data: Extended Range 3D Point. Should be 6 bytes; % seen.\n", len(record_data))
} else {
fmt.Fprintf(ioutil.Discard, "alt_bot, alt_top = %d MSL, %d MSL\n", alt_bot, alt_top)
lng_raw := (int32(record_data[0]) << 11) | (int32(record_data[1]) << 3) | (int32(record_data[2]) & 0xE0 >> 5)
lat_raw := ((int32(record_data[2]) & 0x1F) << 14) | (int32(record_data[3]) << 6) | ((int32(record_data[4]) & 0xFC) >> 2)
alt_raw := ((int32(record_data[4]) & 0x03) << 8) | int32(record_data[5])
fmt.Fprintf(ioutil.Discard, "lat_raw=%d, lng_raw=%d, alt_raw=%d\n", lat_raw, lng_raw, alt_raw)
lat, lng := airmetLatLng(lat_raw, lng_raw, false)
alt := alt_raw * 100
fmt.Fprintf(ioutil.Discard, "lat=%f,lng=%f,alt=%d\n", lat, lng, alt)
fmt.Fprintf(ioutil.Discard, "coord:%f,%f\n", lat, lng)
var point GeoPoint
point.Lat = lat
point.Lon = lng
point.Alt = alt
f.Points = []GeoPoint{point}
}
fmt.Fprintf(ioutil.Discard, "r_lng, r_lat = %f, %f\n", r_lng, r_lat)
case 7, 8: // Extended Range Circular Prism (7 = MSL, 8 = AGL)
if len(record_data) < 14 {
fmt.Fprintf(ioutil.Discard, "invalid data: Extended Range Circular Prism. Should be 14 bytes; % seen.\n", len(record_data))
} else {
fmt.Fprintf(ioutil.Discard, "alpha=%d\n", alpha)
lng_bot_raw := (int32(record_data[0]) << 10) | (int32(record_data[1]) << 2) | (int32(record_data[2]) & 0xC0 >> 6)
lat_bot_raw := ((int32(record_data[2]) & 0x3F) << 12) | (int32(record_data[3]) << 4) | ((int32(record_data[4]) & 0xF0) >> 4)
lng_top_raw := ((int32(record_data[4]) & 0x0F) << 14) | (int32(record_data[5]) << 6) | ((int32(record_data[6]) & 0xFC) >> 2)
lat_top_raw := ((int32(record_data[6]) & 0x03) << 16) | (int32(record_data[7]) << 8) | int32(record_data[8])
alt_bot_raw := (int32(record_data[9]) & 0xFE) >> 1
alt_top_raw := ((int32(record_data[9]) & 0x01) << 6) | ((int32(record_data[10]) & 0xFC) >> 2)
r_lng_raw := ((int32(record_data[10]) & 0x03) << 7) | ((int32(record_data[11]) & 0xFE) >> 1)
r_lat_raw := ((int32(record_data[11]) & 0x01) << 8) | int32(record_data[12])
alpha := int32(record_data[13])
lat_bot, lng_bot := airmetLatLng(lat_bot_raw, lng_bot_raw, true)
lat_top, lng_top := airmetLatLng(lat_top_raw, lng_top_raw, true)
alt_bot := alt_bot_raw * 5
alt_top := alt_top_raw * 500
r_lng := float64(r_lng_raw) * float64(0.2)
r_lat := float64(r_lat_raw) * float64(0.2)
fmt.Fprintf(ioutil.Discard, "lat_bot, lng_bot = %f, %f\n", lat_bot, lng_bot)
fmt.Fprintf(ioutil.Discard, "lat_top, lng_top = %f, %f\n", lat_top, lng_top)
if geometry_overlay_options == 8 {
fmt.Fprintf(ioutil.Discard, "alt_bot, alt_top = %d AGL, %d AGL\n", alt_bot, alt_top)
} else {
fmt.Fprintf(ioutil.Discard, "alt_bot, alt_top = %d MSL, %d MSL\n", alt_bot, alt_top)
}
fmt.Fprintf(ioutil.Discard, "r_lng, r_lat = %f, %f\n", r_lng, r_lat)
fmt.Fprintf(ioutil.Discard, "alpha=%d\n", alpha)
}
default:
fmt.Fprintf(ioutil.Discard, "unknown geometry: %d\n", geometry_overlay_options)
}
@ -491,6 +499,10 @@ func (u *UATMsg) DecodeUplink() error {
// position_valid := (uint32(frame[5]) & 0x01) != 0
frame := u.msg
if len(frame) < UPLINK_FRAME_DATA_BYTES {
return errors.New(fmt.Sprintf("DecodeUplink: short read (%d).", len(frame)))
}
raw_lat := (uint32(frame[0]) << 15) | (uint32(frame[1]) << 7) | (uint32(frame[2]) >> 1)
raw_lon := ((uint32(frame[2]) & 0x01) << 23) | (uint32(frame[3]) << 15) | (uint32(frame[4]) << 7) | (uint32(frame[5]) >> 1)