kopia lustrzana https://github.com/cyoung/stratux
Merge pull request #428 from AvSquirrel/uat-mutex
Additional UAT stability improvements (tower mutex, array bounds checks)pull/436/head
commit
8f310d0afc
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
Ładowanie…
Reference in New Issue