func main() { Log.Printf("reading file '%s' (dumpPos=%v)", fFilename, fDumpPos) h := histogram.Histogram{ ValMin: 0, ValMax: 80, NumBuckets: 80, } _ = h if osFile, err := os.Open(fFilename); err != nil { Log.Fatal(err) } else { scanner := bufio.NewScanner(osFile) // os.File implements io.Reader for scanner.Scan() { m := adsb.Msg{} text := scanner.Text() if err := m.FromSBS1(text); err != nil { Log.Fatal(err) break } if fDumpPos { if m.HasPosition() { fmt.Printf("\"%.5f,%.5f\"\n", m.Position.Lat, m.Position.Long) } } else { Log.Print(m) } } if err := scanner.Err(); err != nil { Log.Fatal(err) } } }
// Load all the messages, and sort into a single time-ordered stream. func file2msgs(filename string) []adsb.Msg { file, err := os.Open(filename) if err != nil { log.Fatal(err) } defer file.Close() msgs := []adsb.Msg{} scanner := bufio.NewScanner(file) for scanner.Scan() { if err := scanner.Err(); err != nil { log.Fatal(err) } msg := adsb.Msg{} if err := msg.FromSBS1(scanner.Text()); err != nil { log.Fatal("Bad parse '%s'\n%v\n", scanner.Text(), err) } // We drop the useless "111" fields, so this doesn't work. Maybe add them in, for ToSBS1 ? //if msg.ToSBS1() != scanner.Text() { // log.Fatalf("parse/print fail\nread: %s\ngen : %s\n", scanner.Text(), msg.ToSBS1()) //} msgs = append(msgs, msg) } return msgs }
func msgs(sbs string) (ret []adsb.Msg) { scanner := bufio.NewScanner(strings.NewReader(sbs)) for scanner.Scan() { m := adsb.Msg{} text := scanner.Text() if err := m.FromSBS1(text); err != nil { panic(err) } m.GeneratedTimestampUTC = time.Now() // Fake this out ret = append(ret, m) } return }
// Parse up the SBS strings, and then pretend we've fleshed them out with data into CompositeMsgs func msgs(sbsText string) (ret []*adsb.CompositeMsg) { scanner := bufio.NewScanner(strings.NewReader(sbsText)) for scanner.Scan() { if text := scanner.Text(); text != "" { m := adsb.Msg{} if err := m.FromSBS1(text); err != nil { panic(err) } cm := adsb.CompositeMsg{Msg: m} ret = append(ret, &cm) } } return }
func TestAgeOutQuietSenders(t *testing.T) { mb := NewMsgBuffer() messages := msgs(maybeAddSBS) for _, msg := range messages { mb.Add(&msg) } unrelatedMsg := adsb.Msg{} if err := unrelatedMsg.FromSBS1(unrelatedSBS); err != nil { panic(err) } // Pluck out the (only) sender ID, reset its clock into the past var id adsb.IcaoId for k, _ := range mb.Senders { id = k } // Rig time - just before the age out window offset := -1*mb.MaxQuietTime - 5 mb.Senders[id].LastSeen = mb.Senders[id].LastSeen.Add(offset) mb.Add(&unrelatedMsg) // Send a message, to trigger ageout if len(mb.Senders) != 1 { t.Errorf("aged out too soon ?") } // Rig time - just after the age out window. And reset the sweep time. mb.Senders[id].LastSeen = mb.Senders[id].LastSeen.Add(time.Duration(-10) * time.Second) mb.lastAgeOut = mb.lastAgeOut.Add(time.Second * time.Duration(-5)) mb.Add(&unrelatedMsg) // Send a message, to trigger ageout if len(mb.Senders) != 0 { t.Errorf("aged out, but still present") } _ = fmt.Sprintf("%s", mb) }
// readMsgFromSocket will pull basestation (and extended basestation) // formatted messages from the socket, and send them down the channel. // It will retry the connection on failure. func readMsgFromSocket(wg *sync.WaitGroup, hostport string, msgChan chan<- *adsb.Msg) { nTimeMismatches := 0 lastBackoff := time.Second wg.Add(1) outerLoop: for { if weAreDone() { break } // outer conn, err := net.Dial("tcp", hostport) if err != nil { Log.Printf("connect '%s': err %s; trying again in %s ...", hostport, err, lastBackoff*2) time.Sleep(lastBackoff) if lastBackoff < time.Minute*5 { lastBackoff *= 2 } continue } lastBackoff = time.Second Log.Printf("connected to '%s'", hostport) // a net.Conn implements io.Reader scanner := bufio.NewScanner(conn) for scanner.Scan() { // This can block indefinitely ... if weAreDone() { break outerLoop } if err := scanner.Err(); err != nil { Log.Printf("killing connection, scanner err: %v\n", err) conn.Close() break // inner } msg := adsb.Msg{} text := scanner.Text() if err := msg.FromSBS1(text); err != nil { Log.Printf("killing connection, SBS input:%q, parse fail: %v", text, err) break // inner } // If there is significant clock skew, we should bail. But, it seems // that sometimes we pick up stale data from dump1090; so wait to see // if it passes. offset := time.Since(msg.GeneratedTimestampUTC) if offset > time.Minute*30 || offset < time.Minute*-30 { nTimeMismatches++ if nTimeMismatches < 100 { continue // do not process this message } else { Log.Fatalf("100 bad msgs; set -timeloc ?\nNow = %s\nmsg = %s\n", time.Now(), msg.GeneratedTimestampUTC) } } // If the message is flagged as one we should mask, honor that if msg.IsMasked() { continue } msgChan <- &msg } } wg.Done() Log.Printf(" ---- readMsgFromSocket, clean shutdown\n") }