From 7239e81418672ab4a87d87f7aa6ff0dd0d7fae38 Mon Sep 17 00:00:00 2001 From: Jim Jacobsen Date: Sun, 23 Oct 2016 23:38:13 -0500 Subject: [PATCH 01/22] Initial support for NEXRAD data, added support for JSON types --- main/gen_gdl90.go | 33 +++++++--- main/managementinterface.go | 36 +++++++++++ main/traffic.go | 1 + uatparse/uatparse.go | 126 +++++++++++++++++++++++++++++++++++- 4 files changed, 187 insertions(+), 9 deletions(-) mode change 100644 => 100755 main/managementinterface.go mode change 100644 => 100755 main/traffic.go mode change 100644 => 100755 uatparse/uatparse.go diff --git a/main/gen_gdl90.go b/main/gen_gdl90.go index 6daedc97..f4fedaed 100755 --- a/main/gen_gdl90.go +++ b/main/gen_gdl90.go @@ -745,10 +745,15 @@ type WeatherMessage struct { Time string Data string LocaltimeReceived time.Time + Ticks int64 + TowerLon float64 + TowerLat float64 + TisId byte + } // Send update to connected websockets. -func registerADSBTextMessageReceived(msg string) { +func registerADSBTextMessageReceived(msg string, uatMsg *uatparse.UATMsg) { x := strings.Split(msg, " ") if len(x) < 5 { return @@ -768,13 +773,25 @@ func registerADSBTextMessageReceived(msg string) { if x[0] == "PIREP" { globalStatus.UAT_PIREP_total++ } - - wm.Type = x[0] - wm.Location = x[1] - wm.Time = x[2] - wm.Data = strings.Join(x[3:], " ") + if x[0] == "NEXRAD" { + log.Printf("registerADSBTextMessageReceived: %s\n",msg) + wm.Type = x[0] + wm.Data = strings.Join(x[1:], " ") + wm.Location = "NEXRAD" + wm.Time = "NONE" + } else { + wm.Type = x[0] + wm.Location = x[1] + wm.Time = x[2] + wm.Data = strings.Join(x[3:], " ") + } wm.LocaltimeReceived = stratuxClock.Time - + wm.TowerLon = uatMsg.Lon + wm.TowerLat = uatMsg.Lat +// now := time.Now() +// Year := time.Year() + uatTime := time.Date(2016, time.Month(uatMsg.Frames[0].FISB_month),int(uatMsg.Frames[0].FISB_day), int(uatMsg.Frames[0].FISB_hours), int(uatMsg.Frames[0].FISB_minutes), int(uatMsg.Frames[0].FISB_seconds), 0, time.UTC) + wm.Ticks = uatTime.UnixNano() / 1000000 wmJSON, _ := json.Marshal(&wm) // Send to weatherUpdate channel for any connected clients. @@ -895,7 +912,7 @@ func parseInput(buf string) ([]byte, uint16) { // Get all of the text reports. textReports, _ := uatMsg.GetTextReports() for _, r := range textReports { - registerADSBTextMessageReceived(r) + registerADSBTextMessageReceived(r, uatMsg) } thisMsg.uatMsg = uatMsg } diff --git a/main/managementinterface.go b/main/managementinterface.go old mode 100644 new mode 100755 index 290a10b3..cdd035fa --- a/main/managementinterface.go +++ b/main/managementinterface.go @@ -57,6 +57,35 @@ func handleWeatherWS(conn *websocket.Conn) { } } +func handleJsonIo(conn *websocket.Conn) { + trafficMutex.Lock() + for _, traf := range traffic { + if !traf.Position_valid { // Don't send unless a valid position exists. + continue + } + trafficJSON, _ := json.Marshal(&traf) + conn.Write(trafficJSON) + } + // Subscribe the socket to receive updates. + trafficUpdate.AddSocket(conn) + weatherUpdate.AddSocket(conn) + + trafficMutex.Unlock() + + // Connection closes when function returns. Since uibroadcast is writing and we don't need to read anything (for now), just keep it busy. + for { + buf := make([]byte, 1024) + _, err := conn.Read(buf) + if err != nil { + break + } + if buf[0] != 0 { // Dummy. + continue + } + time.Sleep(1 * time.Second) + } +} + // Works just as weather updates do. func handleTrafficWS(conn *websocket.Conn) { @@ -512,6 +541,13 @@ func managementInterface() { s.ServeHTTP(w, req) }) + http.HandleFunc("/jsonio", + func(w http.ResponseWriter, req *http.Request) { + s := websocket.Server{ + Handler: websocket.Handler(handleJsonIo)} + s.ServeHTTP(w, req) + }) + http.HandleFunc("/getStatus", handleStatusRequest) http.HandleFunc("/getSituation", handleSituationRequest) http.HandleFunc("/getTowers", handleTowersRequest) diff --git a/main/traffic.go b/main/traffic.go old mode 100644 new mode 100755 index 26addc3d..e7c4e216 --- a/main/traffic.go +++ b/main/traffic.go @@ -75,6 +75,7 @@ const ( ) type TrafficInfo struct { + Type string // Icao_addr uint32 Reg string // Registration. Calculated from Icao_addr for civil aircraft of US registry. Tail string // Callsign. Transmitted by aircraft. diff --git a/uatparse/uatparse.go b/uatparse/uatparse.go old mode 100644 new mode 100755 index 6dc2e985..6197bc92 --- a/uatparse/uatparse.go +++ b/uatparse/uatparse.go @@ -4,11 +4,13 @@ import ( "encoding/hex" "errors" "fmt" + "log" "io/ioutil" "strconv" "strings" ) +var elementIdentifier byte const ( UPLINK_BLOCK_DATA_BITS = 576 UPLINK_BLOCK_BITS = (UPLINK_BLOCK_DATA_BITS + 160) @@ -24,7 +26,9 @@ const ( // assume 6 byte frames: 2 header bytes, 4 byte payload // (TIS-B heartbeat with one address, or empty FIS-B APDU) UPLINK_MAX_INFO_FRAMES = (424 / 6) - + COLS_PER_BIN = 32 + ROWS_PER_BIN = 4 + dlac_alpha = "\x03ABCDEFGHIJKLMNOPQRSTUVWXYZ\x1A\t\x1E\n| !\"#$%&'()*+,-./0123456789:;<=>?" ) @@ -187,6 +191,123 @@ func formatDLACData(p string) []string { return ret } +func (f *UATFrame) decodeNexradFrame() { + ret := make([]string, 0) + builder := make([]string, 0) + + if len(f.FISB_data) < int(f.FISB_length) { + return + } + mEmpty := make([]int32, 1) + mData := make([]int32, COLS_PER_BIN * ROWS_PER_BIN) + elementIdentifier := f.FISB_data[0] & 0x80 + mBlock := uint32(f.FISB_data[0] & 0x0f) << 16 + mBlock = mBlock | uint32(f.FISB_data[1]) << 8 + mBlock = mBlock | uint32(f.FISB_data[2]) + index := 3 + // Make 32 * 4 array + if elementIdentifier != 0 { + // Clear the array + for c:=0; c < (COLS_PER_BIN * ROWS_PER_BIN); c++ { + mData[c] = 0 + } + j := 0 + for index < int(f.FISB_length) { + numberOfBins := ((f.FISB_data[index] & 0xf8) >> 3) + 1 + for i:=0; i < int(numberOfBins); i++ { + if j >= int(COLS_PER_BIN*ROWS_PER_BIN) { + return + } + mData[j] = int32(f.FISB_data[index] & 0x07) + j++ + } + index++ + } + } else { + bitmapLen := int32(f.FISB_data[index] & 0x0f) + // Start with 1 element + + mEmpty[0] = int32(mBlock) + if (f.FISB_data[index] & 0x10) != 0 { + mEmpty = append(mEmpty, int32(mBlock+1)) + } + if (f.FISB_data[index] & 0x20) != 0 { + mEmpty = append(mEmpty, int32(mBlock+2)) + } + if (f.FISB_data[index] & 0x30) != 0 { + mEmpty = append(mEmpty, int32(mBlock+3)) + } + if (f.FISB_data[index] & 0x40) != 0 { + mEmpty = append(mEmpty, int32(mBlock+4)) + } + for i:=1; i Date: Mon, 24 Oct 2016 15:22:57 -0400 Subject: [PATCH 02/22] Formatting. --- main/gen_gdl90.go | 15 ++++---- main/managementinterface.go | 2 +- main/traffic.go | 2 +- uatparse/uatparse.go | 77 +++++++++++++++++++------------------ 4 files changed, 48 insertions(+), 48 deletions(-) diff --git a/main/gen_gdl90.go b/main/gen_gdl90.go index f4fedaed..8f297cd1 100755 --- a/main/gen_gdl90.go +++ b/main/gen_gdl90.go @@ -745,11 +745,10 @@ type WeatherMessage struct { Time string Data string LocaltimeReceived time.Time - Ticks int64 - TowerLon float64 - TowerLat float64 + Ticks int64 + TowerLon float64 + TowerLat float64 TisId byte - } // Send update to connected websockets. @@ -774,7 +773,7 @@ func registerADSBTextMessageReceived(msg string, uatMsg *uatparse.UATMsg) { globalStatus.UAT_PIREP_total++ } if x[0] == "NEXRAD" { - log.Printf("registerADSBTextMessageReceived: %s\n",msg) + log.Printf("registerADSBTextMessageReceived: %s\n", msg) wm.Type = x[0] wm.Data = strings.Join(x[1:], " ") wm.Location = "NEXRAD" @@ -788,9 +787,9 @@ func registerADSBTextMessageReceived(msg string, uatMsg *uatparse.UATMsg) { wm.LocaltimeReceived = stratuxClock.Time wm.TowerLon = uatMsg.Lon wm.TowerLat = uatMsg.Lat -// now := time.Now() -// Year := time.Year() - uatTime := time.Date(2016, time.Month(uatMsg.Frames[0].FISB_month),int(uatMsg.Frames[0].FISB_day), int(uatMsg.Frames[0].FISB_hours), int(uatMsg.Frames[0].FISB_minutes), int(uatMsg.Frames[0].FISB_seconds), 0, time.UTC) + // now := time.Now() + // Year := time.Year() + uatTime := time.Date(2016, time.Month(uatMsg.Frames[0].FISB_month), int(uatMsg.Frames[0].FISB_day), int(uatMsg.Frames[0].FISB_hours), int(uatMsg.Frames[0].FISB_minutes), int(uatMsg.Frames[0].FISB_seconds), 0, time.UTC) wm.Ticks = uatTime.UnixNano() / 1000000 wmJSON, _ := json.Marshal(&wm) diff --git a/main/managementinterface.go b/main/managementinterface.go index cdd035fa..78f7a57b 100755 --- a/main/managementinterface.go +++ b/main/managementinterface.go @@ -69,7 +69,7 @@ func handleJsonIo(conn *websocket.Conn) { // Subscribe the socket to receive updates. trafficUpdate.AddSocket(conn) weatherUpdate.AddSocket(conn) - + trafficMutex.Unlock() // Connection closes when function returns. Since uibroadcast is writing and we don't need to read anything (for now), just keep it busy. diff --git a/main/traffic.go b/main/traffic.go index e7c4e216..dd2e23b8 100755 --- a/main/traffic.go +++ b/main/traffic.go @@ -75,7 +75,7 @@ const ( ) type TrafficInfo struct { - Type string // + Type string // Icao_addr uint32 Reg string // Registration. Calculated from Icao_addr for civil aircraft of US registry. Tail string // Callsign. Transmitted by aircraft. diff --git a/uatparse/uatparse.go b/uatparse/uatparse.go index 6197bc92..c5d743da 100755 --- a/uatparse/uatparse.go +++ b/uatparse/uatparse.go @@ -4,13 +4,14 @@ import ( "encoding/hex" "errors" "fmt" - "log" "io/ioutil" + "log" "strconv" "strings" ) var elementIdentifier byte + const ( UPLINK_BLOCK_DATA_BITS = 576 UPLINK_BLOCK_BITS = (UPLINK_BLOCK_DATA_BITS + 160) @@ -26,9 +27,9 @@ const ( // assume 6 byte frames: 2 header bytes, 4 byte payload // (TIS-B heartbeat with one address, or empty FIS-B APDU) UPLINK_MAX_INFO_FRAMES = (424 / 6) - COLS_PER_BIN = 32 - ROWS_PER_BIN = 4 - + COLS_PER_BIN = 32 + ROWS_PER_BIN = 4 + dlac_alpha = "\x03ABCDEFGHIJKLMNOPQRSTUVWXYZ\x1A\t\x1E\n| !\"#$%&'()*+,-./0123456789:;<=>?" ) @@ -194,27 +195,27 @@ func formatDLACData(p string) []string { func (f *UATFrame) decodeNexradFrame() { ret := make([]string, 0) builder := make([]string, 0) - + if len(f.FISB_data) < int(f.FISB_length) { return } mEmpty := make([]int32, 1) - mData := make([]int32, COLS_PER_BIN * ROWS_PER_BIN) + mData := make([]int32, COLS_PER_BIN*ROWS_PER_BIN) elementIdentifier := f.FISB_data[0] & 0x80 - mBlock := uint32(f.FISB_data[0] & 0x0f) << 16 - mBlock = mBlock | uint32(f.FISB_data[1]) << 8 + mBlock := uint32(f.FISB_data[0]&0x0f) << 16 + mBlock = mBlock | uint32(f.FISB_data[1])<<8 mBlock = mBlock | uint32(f.FISB_data[2]) index := 3 // Make 32 * 4 array if elementIdentifier != 0 { // Clear the array - for c:=0; c < (COLS_PER_BIN * ROWS_PER_BIN); c++ { + for c := 0; c < (COLS_PER_BIN * ROWS_PER_BIN); c++ { mData[c] = 0 } j := 0 for index < int(f.FISB_length) { numberOfBins := ((f.FISB_data[index] & 0xf8) >> 3) + 1 - for i:=0; i < int(numberOfBins); i++ { + for i := 0; i < int(numberOfBins); i++ { if j >= int(COLS_PER_BIN*ROWS_PER_BIN) { return } @@ -226,7 +227,7 @@ func (f *UATFrame) decodeNexradFrame() { } else { bitmapLen := int32(f.FISB_data[index] & 0x0f) // Start with 1 element - + mEmpty[0] = int32(mBlock) if (f.FISB_data[index] & 0x10) != 0 { mEmpty = append(mEmpty, int32(mBlock+1)) @@ -240,69 +241,69 @@ func (f *UATFrame) decodeNexradFrame() { if (f.FISB_data[index] & 0x40) != 0 { mEmpty = append(mEmpty, int32(mBlock+4)) } - for i:=1; i Date: Mon, 24 Oct 2016 15:27:48 -0400 Subject: [PATCH 03/22] Formatting. --- main/gen_gdl90.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main/gen_gdl90.go b/main/gen_gdl90.go index 8f297cd1..bff8ec1c 100755 --- a/main/gen_gdl90.go +++ b/main/gen_gdl90.go @@ -746,9 +746,8 @@ type WeatherMessage struct { Data string LocaltimeReceived time.Time Ticks int64 - TowerLon float64 TowerLat float64 - TisId byte + TowerLon float64 } // Send update to connected websockets. From 27206c0751348f92e3a1b7dc5235b4511edda6cb Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Mon, 24 Oct 2016 15:28:44 -0400 Subject: [PATCH 04/22] Formatting. --- main/traffic.go | 1 - 1 file changed, 1 deletion(-) diff --git a/main/traffic.go b/main/traffic.go index dd2e23b8..26addc3d 100755 --- a/main/traffic.go +++ b/main/traffic.go @@ -75,7 +75,6 @@ const ( ) type TrafficInfo struct { - Type string // Icao_addr uint32 Reg string // Registration. Calculated from Icao_addr for civil aircraft of US registry. Tail string // Callsign. Transmitted by aircraft. From 504d97ec7a73a44d80069e74ca34170dd1718ea4 Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Mon, 24 Oct 2016 15:36:54 -0400 Subject: [PATCH 05/22] Add SendJSON() to uibroadcaster. --- main/uibroadcast.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/main/uibroadcast.go b/main/uibroadcast.go index 500e2afa..b7d45ab1 100644 --- a/main/uibroadcast.go +++ b/main/uibroadcast.go @@ -11,6 +11,7 @@ package main import ( + "encoding/json" "golang.org/x/net/websocket" "sync" "time" @@ -36,6 +37,11 @@ func (u *uibroadcaster) Send(msg []byte) { u.messages <- msg } +func (u *uibroadcaster) SendJSON(i interface{}) { + j, _ := json.Marshal(&i) + u.Send(j) +} + func (u *uibroadcaster) AddSocket(sock *websocket.Conn) { u.sockets_mu.Lock() u.sockets = append(u.sockets, sock) From a949bda34f560f9d079e7731473da8ac044f66be Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Mon, 24 Oct 2016 15:38:05 -0400 Subject: [PATCH 06/22] Add mySituation uibroadcast. --- main/managementinterface.go | 4 ++++ main/ry835ai.go | 11 ++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/main/managementinterface.go b/main/managementinterface.go index 78f7a57b..f5102e87 100755 --- a/main/managementinterface.go +++ b/main/managementinterface.go @@ -36,6 +36,9 @@ type SettingMessage struct { var weatherUpdate *uibroadcaster var trafficUpdate *uibroadcaster +// Situation updates channel. +var situationUpdate *uibroadcaster + /* The /weather websocket starts off by sending the current buffer of weather messages, then sends updates as they are received. */ @@ -511,6 +514,7 @@ func viewLogs(w http.ResponseWriter, r *http.Request) { func managementInterface() { weatherUpdate = NewUIBroadcaster() trafficUpdate = NewUIBroadcaster() + situationUpdate = NewUIBroadcaster() http.HandleFunc("/", defaultServer) http.Handle("/logs/", http.StripPrefix("/logs/", http.FileServer(http.Dir("/var/log")))) diff --git a/main/ry835ai.go b/main/ry835ai.go index 715740bb..5343b52e 100644 --- a/main/ry835ai.go +++ b/main/ry835ai.go @@ -456,6 +456,15 @@ func calculateNACp(accuracy float32) uint8 { return ret } +/* + registerSituationUpdate(). + Called whenever there is a change in mySituation. +*/ +func registerSituationUpdate() { + logSituation() + situationUpdate.SendJSON(mySituation) +} + /* processNMEALine parses NMEA-0183 formatted strings against several message types. @@ -472,7 +481,7 @@ func processNMEALine(l string) (sentenceUsed bool) { defer func() { if sentenceUsed || globalSettings.DEBUG { - logSituation() + registerSituationUpdate() } mySituation.mu_GPS.Unlock() }() From f5ebf4c43d335be2a9b829f9eb03b0f37c666e02 Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Mon, 24 Oct 2016 15:40:30 -0400 Subject: [PATCH 07/22] Use uibroadcast.SendJSON(). --- main/gen_gdl90.go | 3 +-- main/traffic.go | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/main/gen_gdl90.go b/main/gen_gdl90.go index bff8ec1c..3b34e98d 100755 --- a/main/gen_gdl90.go +++ b/main/gen_gdl90.go @@ -790,10 +790,9 @@ func registerADSBTextMessageReceived(msg string, uatMsg *uatparse.UATMsg) { // Year := time.Year() uatTime := time.Date(2016, time.Month(uatMsg.Frames[0].FISB_month), int(uatMsg.Frames[0].FISB_day), int(uatMsg.Frames[0].FISB_hours), int(uatMsg.Frames[0].FISB_minutes), int(uatMsg.Frames[0].FISB_seconds), 0, time.UTC) wm.Ticks = uatTime.UnixNano() / 1000000 - wmJSON, _ := json.Marshal(&wm) // Send to weatherUpdate channel for any connected clients. - weatherUpdate.Send(wmJSON) + weatherUpdate.SendJSON(wm) } func UpdateUATStats(ProductID uint32) { diff --git a/main/traffic.go b/main/traffic.go index 26addc3d..61a187ac 100755 --- a/main/traffic.go +++ b/main/traffic.go @@ -207,8 +207,7 @@ func sendTrafficUpdates() { traffic[icao] = ti // write the updated ti back to the map //log.Printf("Traffic age of %X is %f seconds\n",icao,ti.Age) if ti.Age > 2 { // if nothing polls an inactive ti, it won't push to the webUI, and its Age won't update. - tiJSON, _ := json.Marshal(&ti) - trafficUpdate.Send(tiJSON) + trafficUpdate.SendJSON(ti) } if ti.Position_valid && ti.Age < 6 { // ... but don't pass stale data to the EFB. TO-DO: Coast old traffic? Need to determine how FF, WingX, etc deal with stale targets. logTraffic(ti) // only add to the SQLite log if it's not stale @@ -235,8 +234,7 @@ func registerTrafficUpdate(ti TrafficInfo) { return } */ // Send all traffic to the websocket and let JS sort it out. This will provide user indication of why they see 1000 ES messages and no traffic. - tiJSON, _ := json.Marshal(&ti) - trafficUpdate.Send(tiJSON) + trafficUpdate.SendJSON(ti) } func makeTrafficReportMsg(ti TrafficInfo) []byte { From 386be11b8c934202ddd363f6d27cb8a12299fd13 Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Mon, 24 Oct 2016 16:05:30 -0400 Subject: [PATCH 08/22] Subscribe /jsonio socket for situation updates. --- main/managementinterface.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main/managementinterface.go b/main/managementinterface.go index f5102e87..f4645814 100755 --- a/main/managementinterface.go +++ b/main/managementinterface.go @@ -72,6 +72,7 @@ func handleJsonIo(conn *websocket.Conn) { // Subscribe the socket to receive updates. trafficUpdate.AddSocket(conn) weatherUpdate.AddSocket(conn) + situationUpdate.AddSocket(conn) trafficMutex.Unlock() From b829e2228a21e2d17f5826d292dec6bd34f65f56 Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Mon, 24 Oct 2016 16:12:18 -0400 Subject: [PATCH 09/22] Replaced NEXRAD processing. --- uatparse/nexrad.go | 147 +++++++++++++++++++++++++++++++++++++++++++ uatparse/uatparse.go | 124 +----------------------------------- 2 files changed, 150 insertions(+), 121 deletions(-) create mode 100644 uatparse/nexrad.go diff --git a/uatparse/nexrad.go b/uatparse/nexrad.go new file mode 100644 index 00000000..07a34491 --- /dev/null +++ b/uatparse/nexrad.go @@ -0,0 +1,147 @@ +package uatparse + +import () + +const ( + BLOCK_WIDTH = float64(48.0 / 60.0) + WIDE_BLOCK_WIDTH = float64(96.0 / 60.0) + BLOCK_HEIGHT = float64(4.0 / 60.0) + BLOCK_THRESHOLD = 405000 + BLOCKS_PER_RING = 450 +) + +type NEXRADBlock struct { + radar_type uint32 + scale int + latNorth float64 + lonWest float64 + height float64 + width float64 + intensity []uint8 // Really only 4-bit values. +} + +func block_location(block_num int, ns_flag bool, scale_factor int) (float64, float64, float64, float64) { + var realScale float64 + if scale_factor == 1 { + realScale = float64(5.0) + } else if scale_factor == 2 { + realScale = float64(9.0) + } else { + realScale = float64(1.0) + } + + if block_num >= BLOCK_THRESHOLD { + block_num = block_num & ^1 + } + + raw_lat := float64(BLOCK_HEIGHT * float64(int(float64(block_num)/float64(BLOCKS_PER_RING)))) + raw_lon := float64(block_num%BLOCKS_PER_RING) * BLOCK_WIDTH + + var lonSize float64 + if block_num >= BLOCK_THRESHOLD { + lonSize = WIDE_BLOCK_WIDTH * realScale + } else { + lonSize = BLOCK_WIDTH * realScale + } + + latSize := BLOCK_HEIGHT * realScale + + if ns_flag { // Southern hemisphere. + raw_lat = 0 - raw_lat + } else { + raw_lat = raw_lat + BLOCK_HEIGHT + } + + if raw_lon > 180.0 { + raw_lon = raw_lon - 360.0 + } + + return raw_lat, raw_lon, latSize, lonSize + +} + +func (f *UATFrame) decodeNexradFrame() { + if len(f.FISB_data) < 4 { // Short read. + return + } + + rle_flag := (uint32(f.FISB_data[0]) & 0x80) != 0 + ns_flag := (uint32(f.FISB_data[0]) & 0x40) != 0 + block_num := ((int(f.FISB_data[0]) & 0x0f) << 16) | (int(f.FISB_data[1]) << 8) | (int(f.FISB_data[2])) + scale_factor := (int(f.FISB_data[0]) & 0x30) >> 4 + + if rle_flag { // Single bin, RLE encoded. + lat, lon, h, w := block_location(block_num, ns_flag, scale_factor) + var tmp NEXRADBlock + tmp.radar_type = f.Product_id + tmp.scale = scale_factor + tmp.latNorth = lat + tmp.lonWest = lon + tmp.height = h + tmp.width = w + tmp.intensity = make([]uint8, 0) + + intensityData := f.FISB_data[3:] + for _, v := range intensityData { + intensity := uint8(v) & 0x7 + runlength := (uint8(v) >> 3) + 1 + for runlength > 0 { + tmp.intensity = append(tmp.intensity, intensity) + runlength-- + } + } + f.NEXRAD = []NEXRADBlock{tmp} + } else { + var row_start int + var row_size int + if block_num >= 405000 { + row_start = block_num - ((block_num - 405000) % 225) + row_size = 225 + } else { + row_start = block_num - (block_num % 450) + row_size = 450 + } + + row_offset := block_num - row_start + + L := int(f.FISB_data[3] & 15) + + if len(f.FISB_data) < L+3 { // Short read. + return + } + + for i := 0; i < L; i++ { + var bb int + if i == 0 { + bb = (int(f.FISB_data[3]) & 0xF0) | 0x08 + } else { + bb = int(f.FISB_data[i+3]) + } + + for j := 0; j < 8; j++ { + if bb&(1<?" ) @@ -66,6 +62,9 @@ type UATFrame struct { RecordFormat uint8 ReportStart string ReportEnd string + + // For NEXRAD. + NEXRAD []NEXRADBlock } type UATMsg struct { @@ -192,123 +191,6 @@ func formatDLACData(p string) []string { return ret } -func (f *UATFrame) decodeNexradFrame() { - ret := make([]string, 0) - builder := make([]string, 0) - - if len(f.FISB_data) < int(f.FISB_length) { - return - } - mEmpty := make([]int32, 1) - mData := make([]int32, COLS_PER_BIN*ROWS_PER_BIN) - elementIdentifier := f.FISB_data[0] & 0x80 - mBlock := uint32(f.FISB_data[0]&0x0f) << 16 - mBlock = mBlock | uint32(f.FISB_data[1])<<8 - mBlock = mBlock | uint32(f.FISB_data[2]) - index := 3 - // Make 32 * 4 array - if elementIdentifier != 0 { - // Clear the array - for c := 0; c < (COLS_PER_BIN * ROWS_PER_BIN); c++ { - mData[c] = 0 - } - j := 0 - for index < int(f.FISB_length) { - numberOfBins := ((f.FISB_data[index] & 0xf8) >> 3) + 1 - for i := 0; i < int(numberOfBins); i++ { - if j >= int(COLS_PER_BIN*ROWS_PER_BIN) { - return - } - mData[j] = int32(f.FISB_data[index] & 0x07) - j++ - } - index++ - } - } else { - bitmapLen := int32(f.FISB_data[index] & 0x0f) - // Start with 1 element - - mEmpty[0] = int32(mBlock) - if (f.FISB_data[index] & 0x10) != 0 { - mEmpty = append(mEmpty, int32(mBlock+1)) - } - if (f.FISB_data[index] & 0x20) != 0 { - mEmpty = append(mEmpty, int32(mBlock+2)) - } - if (f.FISB_data[index] & 0x30) != 0 { - mEmpty = append(mEmpty, int32(mBlock+3)) - } - if (f.FISB_data[index] & 0x40) != 0 { - mEmpty = append(mEmpty, int32(mBlock+4)) - } - for i := 1; i < int(bitmapLen); i++ { - if (f.FISB_data[index+i] & 0x01) != 0 { - mEmpty = append(mEmpty, int32(mBlock+uint32(i)*8-3)) - } - if (f.FISB_data[index+i] & 0x02) != 0 { - mEmpty = append(mEmpty, int32(mBlock+uint32(i)*8-2)) - } - if (f.FISB_data[index+i] & 0x04) != 0 { - mEmpty = append(mEmpty, int32(mBlock+uint32(i)*8-1)) - } - if (f.FISB_data[index+i] & 0x08) != 0 { - mEmpty = append(mEmpty, int32(mBlock+uint32(i)*8-0)) - } - if (f.FISB_data[index+i] & 0x10) != 0 { - mEmpty = append(mEmpty, int32(mBlock+uint32(i)*8+1)) - } - if (f.FISB_data[index+i] & 0x20) != 0 { - mEmpty = append(mEmpty, int32(mBlock+uint32(i)*8+2)) - } - if (f.FISB_data[index+i] & 0x40) != 0 { - mEmpty = append(mEmpty, int32(mBlock+uint32(i)*8+3)) - } - if (f.FISB_data[index+i] & 0x80) != 0 { - mEmpty = append(mEmpty, int32(mBlock+uint32(i)*8+4)) - } - } - } - log.Printf("NEXRAD: elementIdentifier %d mBlock %d\n", elementIdentifier, mBlock) - log.Printf("NEXRAD: mEmpty %d mData %d\n", mEmpty, mData) - // field 1 - NEXRAD - builder = append(builder, "NEXRAD") - // CONUS - if f.Product_id == 63 { - builder = append(builder, "0") - } else { - builder = append(builder, "1") - } - // Field 3 block - builder = append(builder, fmt.Sprintf("%d", mBlock)) - // Field 4 Columns - builder = append(builder, fmt.Sprintf("%d", COLS_PER_BIN)) - // Field 5 Rows - builder = append(builder, fmt.Sprintf("%d", ROWS_PER_BIN)) - if elementIdentifier != 0 { - builder = append(builder, "1") - bin := "" - for br := range mData { - bin = bin + fmt.Sprintf("%d,", mData[br]) - } - if bin[len(bin)-1] == ',' { - bin = bin[0 : len(bin)-1] - } - builder = append(builder, bin) - } else { - builder = append(builder, "0") - bin2 := "" - for be := range mEmpty { - bin2 = bin2 + fmt.Sprintf("%d,", mEmpty[be]) - } - if bin2[len(bin2)-1] == ',' { - bin2 = bin2[0 : len(bin2)-1] - } - builder = append(builder, bin2) - } - ret = append(ret, fmt.Sprintf(strings.Join(builder, " "))) - f.Text_data = ret -} - // Whole frame contents is DLAC encoded text. func (f *UATFrame) decodeTextFrame() { if len(f.FISB_data) < int(f.FISB_length) { From e0b123e426e0924f2526dafce9f9e77f35088c03 Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Mon, 24 Oct 2016 16:52:27 -0400 Subject: [PATCH 10/22] Fixes. --- uatparse/nexrad.go | 2 +- uatparse/uatparse.go | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/uatparse/nexrad.go b/uatparse/nexrad.go index 07a34491..d0a2bb93 100644 --- a/uatparse/nexrad.go +++ b/uatparse/nexrad.go @@ -143,5 +143,5 @@ func (f *UATFrame) decodeNexradFrame() { } } } - return ret + } diff --git a/uatparse/uatparse.go b/uatparse/uatparse.go index 400f1c21..59755522 100755 --- a/uatparse/uatparse.go +++ b/uatparse/uatparse.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "io/ioutil" - "log" "strconv" "strings" ) From 76e71bd6e53c608b302386172f453ee6a8d54d6e Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Mon, 24 Oct 2016 17:14:06 -0400 Subject: [PATCH 11/22] Make NEXRADBlock fields exportable. --- uatparse/nexrad.go | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/uatparse/nexrad.go b/uatparse/nexrad.go index d0a2bb93..57b53dbe 100644 --- a/uatparse/nexrad.go +++ b/uatparse/nexrad.go @@ -11,13 +11,13 @@ const ( ) type NEXRADBlock struct { - radar_type uint32 - scale int - latNorth float64 - lonWest float64 - height float64 - width float64 - intensity []uint8 // Really only 4-bit values. + Radar_Type uint32 + Scale int + LatNorth float64 + LonWest float64 + Height float64 + Width float64 + Intensity []uint8 // Really only 4-bit values. } func block_location(block_num int, ns_flag bool, scale_factor int) (float64, float64, float64, float64) { @@ -73,20 +73,20 @@ func (f *UATFrame) decodeNexradFrame() { if rle_flag { // Single bin, RLE encoded. lat, lon, h, w := block_location(block_num, ns_flag, scale_factor) var tmp NEXRADBlock - tmp.radar_type = f.Product_id - tmp.scale = scale_factor - tmp.latNorth = lat - tmp.lonWest = lon - tmp.height = h - tmp.width = w - tmp.intensity = make([]uint8, 0) + tmp.Radar_Type = f.Product_id + tmp.Scale = scale_factor + tmp.LatNorth = lat + tmp.LonWest = lon + tmp.Height = h + tmp.Width = w + tmp.Intensity = make([]uint8, 0) intensityData := f.FISB_data[3:] for _, v := range intensityData { intensity := uint8(v) & 0x7 runlength := (uint8(v) >> 3) + 1 for runlength > 0 { - tmp.intensity = append(tmp.intensity, intensity) + tmp.Intensity = append(tmp.Intensity, intensity) runlength-- } } @@ -124,19 +124,19 @@ func (f *UATFrame) decodeNexradFrame() { bn := row_start + row_x lat, lon, h, w := block_location(bn, ns_flag, scale_factor) var tmp NEXRADBlock - tmp.radar_type = f.Product_id - tmp.scale = scale_factor - tmp.latNorth = lat - tmp.lonWest = lon - tmp.height = h - tmp.width = w - tmp.intensity = make([]uint8, 0) + tmp.Radar_Type = f.Product_id + tmp.Scale = scale_factor + tmp.LatNorth = lat + tmp.LonWest = lon + tmp.Height = h + tmp.Width = w + tmp.Intensity = make([]uint8, 0) for k := 0; k < 128; k++ { z := uint8(0) if f.Product_id == 64 { z = 1 } - tmp.intensity = append(tmp.intensity, z) + tmp.Intensity = append(tmp.Intensity, z) } f.NEXRAD = append(f.NEXRAD, tmp) } From 73d7cdbe1dc3f0d41ab288fe5dad72945dc5d3b6 Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Mon, 24 Oct 2016 17:28:57 -0400 Subject: [PATCH 12/22] weatherRawUpdate uibroadcast - send UATFrame as received. --- main/gen_gdl90.go | 26 +++++--------------------- main/managementinterface.go | 6 +++++- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/main/gen_gdl90.go b/main/gen_gdl90.go index 3b34e98d..971e5d76 100755 --- a/main/gen_gdl90.go +++ b/main/gen_gdl90.go @@ -745,9 +745,6 @@ type WeatherMessage struct { Time string Data string LocaltimeReceived time.Time - Ticks int64 - TowerLat float64 - TowerLon float64 } // Send update to connected websockets. @@ -771,25 +768,11 @@ func registerADSBTextMessageReceived(msg string, uatMsg *uatparse.UATMsg) { if x[0] == "PIREP" { globalStatus.UAT_PIREP_total++ } - if x[0] == "NEXRAD" { - log.Printf("registerADSBTextMessageReceived: %s\n", msg) - wm.Type = x[0] - wm.Data = strings.Join(x[1:], " ") - wm.Location = "NEXRAD" - wm.Time = "NONE" - } else { - wm.Type = x[0] - wm.Location = x[1] - wm.Time = x[2] - wm.Data = strings.Join(x[3:], " ") - } + wm.Type = x[0] + wm.Location = x[1] + wm.Time = x[2] + wm.Data = strings.Join(x[3:], " ") wm.LocaltimeReceived = stratuxClock.Time - wm.TowerLon = uatMsg.Lon - wm.TowerLat = uatMsg.Lat - // now := time.Now() - // Year := time.Year() - uatTime := time.Date(2016, time.Month(uatMsg.Frames[0].FISB_month), int(uatMsg.Frames[0].FISB_day), int(uatMsg.Frames[0].FISB_hours), int(uatMsg.Frames[0].FISB_minutes), int(uatMsg.Frames[0].FISB_seconds), 0, time.UTC) - wm.Ticks = uatTime.UnixNano() / 1000000 // Send to weatherUpdate channel for any connected clients. weatherUpdate.SendJSON(wm) @@ -905,6 +888,7 @@ func parseInput(buf string) ([]byte, uint16) { for _, f := range uatMsg.Frames { thisMsg.Products = append(thisMsg.Products, f.Product_id) UpdateUATStats(f.Product_id) + weatherRawUpdate.SendJSON(f) } // Get all of the text reports. textReports, _ := uatMsg.GetTextReports() diff --git a/main/managementinterface.go b/main/managementinterface.go index f4645814..9c94449d 100755 --- a/main/managementinterface.go +++ b/main/managementinterface.go @@ -39,6 +39,9 @@ var trafficUpdate *uibroadcaster // Situation updates channel. var situationUpdate *uibroadcaster +// Raw weather (UATFrame packet stream) update channel. +var weatherRawUpdate *uibroadcaster + /* The /weather websocket starts off by sending the current buffer of weather messages, then sends updates as they are received. */ @@ -71,7 +74,7 @@ func handleJsonIo(conn *websocket.Conn) { } // Subscribe the socket to receive updates. trafficUpdate.AddSocket(conn) - weatherUpdate.AddSocket(conn) + weatherRawUpdate.AddSocket(conn) situationUpdate.AddSocket(conn) trafficMutex.Unlock() @@ -516,6 +519,7 @@ func managementInterface() { weatherUpdate = NewUIBroadcaster() trafficUpdate = NewUIBroadcaster() situationUpdate = NewUIBroadcaster() + weatherRawUpdate = NewUIBroadcaster() http.HandleFunc("/", defaultServer) http.Handle("/logs/", http.StripPrefix("/logs/", http.FileServer(http.Dir("/var/log")))) From 33e9cb0b44c64360022cc20cd25e93255a400e10 Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Mon, 24 Oct 2016 21:32:42 -0400 Subject: [PATCH 13/22] Change Intensity encoding. --- uatparse/nexrad.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/uatparse/nexrad.go b/uatparse/nexrad.go index 57b53dbe..453955aa 100644 --- a/uatparse/nexrad.go +++ b/uatparse/nexrad.go @@ -17,7 +17,7 @@ type NEXRADBlock struct { LonWest float64 Height float64 Width float64 - Intensity []uint8 // Really only 4-bit values. + Intensity []uint16 // Really only 4-bit values, but using this as a hack for the JSON encoding. } func block_location(block_num int, ns_flag bool, scale_factor int) (float64, float64, float64, float64) { @@ -79,12 +79,12 @@ func (f *UATFrame) decodeNexradFrame() { tmp.LonWest = lon tmp.Height = h tmp.Width = w - tmp.Intensity = make([]uint8, 0) + tmp.Intensity = make([]uint16, 0) intensityData := f.FISB_data[3:] for _, v := range intensityData { - intensity := uint8(v) & 0x7 - runlength := (uint8(v) >> 3) + 1 + intensity := uint16(v) & 0x7 + runlength := (uint16(v) >> 3) + 1 for runlength > 0 { tmp.Intensity = append(tmp.Intensity, intensity) runlength-- @@ -130,9 +130,9 @@ func (f *UATFrame) decodeNexradFrame() { tmp.LonWest = lon tmp.Height = h tmp.Width = w - tmp.Intensity = make([]uint8, 0) + tmp.Intensity = make([]uint16, 0) for k := 0; k < 128; k++ { - z := uint8(0) + z := uint16(0) if f.Product_id == 64 { z = 1 } From e742ff0712eaad43036d53ef5ac5bf3a088905dd Mon Sep 17 00:00:00 2001 From: Jim Jacobsen Date: Thu, 17 Nov 2016 06:01:39 +0000 Subject: [PATCH 14/22] Add colors for wind, taf and pirep weather reports --- web/css/main.css | 15 +++++++++++++++ web/plates/weather.html | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) mode change 100755 => 100644 web/plates/weather.html diff --git a/web/css/main.css b/web/css/main.css index 80cec4f9..84aaf56a 100644 --- a/web/css/main.css +++ b/web/css/main.css @@ -131,6 +131,21 @@ content: "\f1d9"; } +.report_TAF { + background-color: cornsilk; + color: black; +} + +.report_PIREP { + background-color: gainsboro; + color: black; +} + +.report_WINDS { + background-color: lavender; + color: black; +} + .flight_condition_VFR { background-color: forestgreen; color: white; diff --git a/web/plates/weather.html b/web/plates/weather.html old mode 100755 new mode 100644 index 5ee5f0a8..b658c405 --- a/web/plates/weather.html +++ b/web/plates/weather.html @@ -29,7 +29,7 @@
{{weather.location}} - {{weather.type}} + {{weather.type}} {{weather.time}}
@@ -62,7 +62,7 @@
{{weather.location}} - {{weather.type}} + {{weather.type}} {{weather.time}}
From c5b18b79d9f1a7deffd5a85e5198823819486fea Mon Sep 17 00:00:00 2001 From: Jim Jacobsen Date: Thu, 17 Nov 2016 06:58:36 +0000 Subject: [PATCH 15/22] More churching up, looks good --- web/css/main.css | 8 ++++++++ web/maui/css/mobile-angular-ui-base.css | 12 ++++++++++++ web/plates/weather.html | 14 ++++++++++---- 3 files changed, 30 insertions(+), 4 deletions(-) mode change 100755 => 100644 web/maui/css/mobile-angular-ui-base.css diff --git a/web/css/main.css b/web/css/main.css index 84aaf56a..bfb7cec9 100644 --- a/web/css/main.css +++ b/web/css/main.css @@ -132,36 +132,44 @@ } .report_TAF { + border-radius: 5px; background-color: cornsilk; color: black; } .report_PIREP { + border-radius: 5px; background-color: gainsboro; color: black; } .report_WINDS { + border-radius: 5px; background-color: lavender; color: black; } .flight_condition_VFR { + border-radius: 5px; background-color: forestgreen; color: white; } .flight_condition_MVFR { + left-border: 120px; + border-radius: 5px; background-color: blue; color: white; } .flight_condition_IFR { + border-radius: 5px; background-color: crimson; color: white; } .flight_condition_LIFR { + border-radius: 5px; background-color: darkorchid; color: white; } diff --git a/web/maui/css/mobile-angular-ui-base.css b/web/maui/css/mobile-angular-ui-base.css old mode 100755 new mode 100644 index 35c2f579..67a8ffcf --- a/web/maui/css/mobile-angular-ui-base.css +++ b/web/maui/css/mobile-angular-ui-base.css @@ -6373,50 +6373,62 @@ a.label:focus { .label-default { background-color: #777777; + border-radius: 5px; } .label-default[href]:focus { background-color: #5e5e5e; + border-radius: 5px; } .label-primary { background-color: #007aff; + border-radius: 5px; } .label-primary[href]:focus { background-color: #0062cc; + border-radius: 5px; } .label-success { background-color: #4cd964; + border-radius: 5px; } .label-success[href]:focus { background-color: #2ac845; + border-radius: 5px; } .label-info { background-color: #34aadc; + border-radius: 5px; } .label-info[href]:focus { background-color: #218ebd; + border-radius: 5px; } .label-warning { background-color: #ffcc00; + border-radius: 5px; } .label-warning[href]:focus { background-color: #cca300; + border-radius: 5px; } .label-danger { background-color: #ff3b30; + border-radius: 5px; } .label-danger[href]:focus { background-color: #fc0d00; + border-radius: 5px; } .badge { diff --git a/web/plates/weather.html b/web/plates/weather.html index b658c405..7ed0de22 100644 --- a/web/plates/weather.html +++ b/web/plates/weather.html @@ -29,8 +29,11 @@
{{weather.location}} - {{weather.type}} - {{weather.time}} + +
{{weather.type}}
+
+   + {{weather.time}}
{{weather.data}} @@ -62,8 +65,11 @@
{{weather.location}} - {{weather.type}} - {{weather.time}} + +
{{weather.type}}
+
+   + {{weather.time}}
{{weather.data}} From 3a5a5e5048c826151a9dbf5dc89654e935e3cb37 Mon Sep 17 00:00:00 2001 From: Jim Jacobsen Date: Thu, 17 Nov 2016 07:09:18 +0000 Subject: [PATCH 16/22] GDL90 JSON interface stratux changes --- main/managementinterface.go | 26 ++++++++++++++++++++++++++ main/network.go | 15 +++++++++++++++ 2 files changed, 41 insertions(+) mode change 100755 => 100644 main/network.go diff --git a/main/managementinterface.go b/main/managementinterface.go index 290a10b3..d774b6c7 100644 --- a/main/managementinterface.go +++ b/main/managementinterface.go @@ -35,6 +35,25 @@ type SettingMessage struct { // Weather updates channel. var weatherUpdate *uibroadcaster var trafficUpdate *uibroadcaster +var gdl90Update *uibroadcaster + +func handleGdl90WS(conn *websocket.Conn) { + // Subscribe the socket to receive updates. + gdl90Update.AddSocket(conn) + + // Connection closes when function returns. Since uibroadcast is writing and we don't need to read anything (for now), just keep it busy. + for { + buf := make([]byte, 1024) + _, err := conn.Read(buf) + if err != nil { + break + } + if buf[0] != 0 { // Dummy. + continue + } + time.Sleep(1 * time.Second) + } +} /* The /weather websocket starts off by sending the current buffer of weather messages, then sends updates as they are received. @@ -482,11 +501,18 @@ func viewLogs(w http.ResponseWriter, r *http.Request) { func managementInterface() { weatherUpdate = NewUIBroadcaster() trafficUpdate = NewUIBroadcaster() + gdl90Update = NewUIBroadcaster() http.HandleFunc("/", defaultServer) http.Handle("/logs/", http.StripPrefix("/logs/", http.FileServer(http.Dir("/var/log")))) http.HandleFunc("/view_logs/", viewLogs) + http.HandleFunc("/gdl90", + func(w http.ResponseWriter, req *http.Request) { + s := websocket.Server{ + Handler: websocket.Handler(handleGdl90WS)} + s.ServeHTTP(w, req) + }) http.HandleFunc("/status", func(w http.ResponseWriter, req *http.Request) { s := websocket.Server{ diff --git a/main/network.go b/main/network.go old mode 100755 new mode 100644 index 17fe3f5e..adcb9fa7 --- a/main/network.go +++ b/main/network.go @@ -143,6 +143,7 @@ func sendToAllConnectedClients(msg networkMessage) { if (msg.msgType & NETWORK_GDL90_STANDARD) != 0 { // It's a GDL90 message. Send to serial output channel (which may or may not cause something to happen). serialOutputChan <- msg.msg + networkGDL90Chan <- msg.msg } netMutex.Lock() @@ -192,6 +193,18 @@ func sendToAllConnectedClients(msg networkMessage) { } var serialOutputChan chan []byte +var networkGDL90Chan chan []byte + +func networkOutWatcher() { + //ticker := time.NewTicker(10 * time.Second) + //var nmsg gdl90NetMessage + for { + select { + case ch := <-networkGDL90Chan: + gdl90Update.SendJSON(ch) + } + } +} // Monitor serial output channel, send to serial port. func serialOutWatcher() { @@ -603,6 +616,7 @@ func ffMonitor() { func initNetwork() { messageQueue = make(chan networkMessage, 1024) // Buffered channel, 1024 messages. serialOutputChan = make(chan []byte, 1024) // Buffered channel, 1024 GDL90 messages. + networkGDL90Chan = make(chan []byte, 1024) outSockets = make(map[string]networkConnection) pingResponse = make(map[string]time.Time) netMutex = &sync.Mutex{} @@ -612,4 +626,5 @@ func initNetwork() { go sleepMonitor() go networkStatsCounter() go serialOutWatcher() + go networkOutWatcher() } From 2b3d06eafa881a734f198402c79dfcf0e7154247 Mon Sep 17 00:00:00 2001 From: Jim Jacobsen Date: Thu, 17 Nov 2016 07:25:36 +0000 Subject: [PATCH 17/22] Fixed JSON call --- main/network.go | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/main/network.go b/main/network.go index adcb9fa7..25c8966a 100644 --- a/main/network.go +++ b/main/network.go @@ -143,7 +143,7 @@ func sendToAllConnectedClients(msg networkMessage) { if (msg.msgType & NETWORK_GDL90_STANDARD) != 0 { // It's a GDL90 message. Send to serial output channel (which may or may not cause something to happen). serialOutputChan <- msg.msg - networkGDL90Chan <- msg.msg + networkGDL90Chan <- msg.msg } netMutex.Lock() @@ -196,14 +196,15 @@ var serialOutputChan chan []byte var networkGDL90Chan chan []byte func networkOutWatcher() { - //ticker := time.NewTicker(10 * time.Second) - //var nmsg gdl90NetMessage - for { - select { - case ch := <-networkGDL90Chan: - gdl90Update.SendJSON(ch) - } - } + //ticker := time.NewTicker(10 * time.Second) + //var nmsg gdl90NetMessage + for { + select { + case ch := <-networkGDL90Chan: + gdlJSON, _ := json.Marshal(ch) + gdl90Update.Send(gdlJSON) + } + } } // Monitor serial output channel, send to serial port. @@ -616,7 +617,7 @@ func ffMonitor() { func initNetwork() { messageQueue = make(chan networkMessage, 1024) // Buffered channel, 1024 messages. serialOutputChan = make(chan []byte, 1024) // Buffered channel, 1024 GDL90 messages. - networkGDL90Chan = make(chan []byte, 1024) + networkGDL90Chan = make(chan []byte, 1024) outSockets = make(map[string]networkConnection) pingResponse = make(map[string]time.Time) netMutex = &sync.Mutex{} From 7a801c6a0660f47419891e5115a08c56a46fed69 Mon Sep 17 00:00:00 2001 From: Jim Jacobsen Date: Thu, 17 Nov 2016 07:41:10 +0000 Subject: [PATCH 18/22] oops again --- main/network.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main/network.go b/main/network.go index 25c8966a..1fe8ea45 100644 --- a/main/network.go +++ b/main/network.go @@ -15,6 +15,7 @@ import ( "golang.org/x/net/icmp" "golang.org/x/net/ipv4" "io/ioutil" + "encoding/json" "log" "math" "math/rand" From 2691fe714c23e1337cd7efcdd46b88759e8fa2ba Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Thu, 17 Nov 2016 10:53:39 -0500 Subject: [PATCH 19/22] Remove debug code. #525. --- web/css/main.css | 1 - 1 file changed, 1 deletion(-) diff --git a/web/css/main.css b/web/css/main.css index bfb7cec9..b2963f15 100644 --- a/web/css/main.css +++ b/web/css/main.css @@ -156,7 +156,6 @@ } .flight_condition_MVFR { - left-border: 120px; border-radius: 5px; background-color: blue; color: white; From b30f7094dcfc5874bdaebf2836fccd02475bacb1 Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Thu, 17 Nov 2016 10:54:30 -0500 Subject: [PATCH 20/22] Formatting. #525. --- web/css/main.css | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/web/css/main.css b/web/css/main.css index b2963f15..5ab603b2 100644 --- a/web/css/main.css +++ b/web/css/main.css @@ -5,22 +5,22 @@ .modal { } .vertical-alignment-helper { - display:table; - height: 100%; - width: 75%; + display:table; + height: 100%; + width: 75%; } .vertical-align-center { - /* To center vertically */ - display: table-cell; - vertical-align: middle; + /* To center vertically */ + display: table-cell; + vertical-align: middle; } .modal-content { - /* Bootstrap sets the size of the modal in the modal-dialog class, we need to inherit it */ - width:inherit; - height:inherit; - /* To center horizontally */ - margin: 0 auto; + /* Bootstrap sets the size of the modal in the modal-dialog class, we need to inherit it */ + width:inherit; + height:inherit; + /* To center horizontally */ + margin: 0 auto; } .traffic-page {} @@ -132,43 +132,43 @@ } .report_TAF { - border-radius: 5px; + border-radius: 5px; background-color: cornsilk; color: black; } .report_PIREP { - border-radius: 5px; + border-radius: 5px; background-color: gainsboro; color: black; } .report_WINDS { - border-radius: 5px; + border-radius: 5px; background-color: lavender; color: black; } .flight_condition_VFR { - border-radius: 5px; + border-radius: 5px; background-color: forestgreen; color: white; } .flight_condition_MVFR { - border-radius: 5px; + border-radius: 5px; background-color: blue; color: white; } .flight_condition_IFR { - border-radius: 5px; + border-radius: 5px; background-color: crimson; color: white; } .flight_condition_LIFR { - border-radius: 5px; + border-radius: 5px; background-color: darkorchid; color: white; } From 57e7c6d0a923fa71296839a5be15b0ce521f4bfe Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Thu, 17 Nov 2016 12:43:47 -0500 Subject: [PATCH 21/22] Formatting. #526. --- main/managementinterface.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main/managementinterface.go b/main/managementinterface.go index a82142b2..6aa28f82 100755 --- a/main/managementinterface.go +++ b/main/managementinterface.go @@ -37,7 +37,7 @@ var weatherUpdate *uibroadcaster var trafficUpdate *uibroadcaster var gdl90Update *uibroadcaster -func handleGdl90WS(conn *websocket.Conn) { +func handleGDL90WS(conn *websocket.Conn) { // Subscribe the socket to receive updates. gdl90Update.AddSocket(conn) @@ -539,7 +539,7 @@ func managementInterface() { trafficUpdate = NewUIBroadcaster() situationUpdate = NewUIBroadcaster() weatherRawUpdate = NewUIBroadcaster() - gdl90Update = NewUIBroadcaster() + gdl90Update = NewUIBroadcaster() http.HandleFunc("/", defaultServer) http.Handle("/logs/", http.StripPrefix("/logs/", http.FileServer(http.Dir("/var/log")))) @@ -548,7 +548,7 @@ func managementInterface() { http.HandleFunc("/gdl90", func(w http.ResponseWriter, req *http.Request) { s := websocket.Server{ - Handler: websocket.Handler(handleGdl90WS)} + Handler: websocket.Handler(handleGDL90WS)} s.ServeHTTP(w, req) }) http.HandleFunc("/status", From 564bf93c633845ef9a9cc4dd62a730946fcf2fe6 Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Thu, 17 Nov 2016 12:46:48 -0500 Subject: [PATCH 22/22] Cleanup. #526. --- main/network.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/main/network.go b/main/network.go index 1fe8ea45..06db05b1 100644 --- a/main/network.go +++ b/main/network.go @@ -15,7 +15,6 @@ import ( "golang.org/x/net/icmp" "golang.org/x/net/ipv4" "io/ioutil" - "encoding/json" "log" "math" "math/rand" @@ -197,14 +196,9 @@ var serialOutputChan chan []byte var networkGDL90Chan chan []byte func networkOutWatcher() { - //ticker := time.NewTicker(10 * time.Second) - //var nmsg gdl90NetMessage for { - select { - case ch := <-networkGDL90Chan: - gdlJSON, _ := json.Marshal(ch) - gdl90Update.Send(gdlJSON) - } + ch := <-networkGDL90Chan + gdl90Update.SendJSON(ch) } }