File: replay-beast.py

package info (click to toggle)
dump1090-mutability 1.15~20180310.4a16df3%2Bdfsg-8
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 3,964 kB
  • sloc: ansic: 7,520; javascript: 4,359; sh: 417; python: 406; makefile: 70
file content (136 lines) | stat: -rwxr-xr-x 4,216 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/env python3

#
# Reads Beast-format input files and replays them to stdout
# (either in their original form or in a human-readable form)
# while maintaining the correct inter-message delays according
# to the timestamps contained in the input file.
#

from contextlib import closing
import time

MODE_AC = 'MODE_AC'
MODE_S_SHORT = 'MODE_S_SHORT'
MODE_S_LONG = 'MODE_S_LONG'
RADARCAPE_STATUS = 'RADARCAPE_STATUS'

def parse(buf):
    i = 0
    messages = []
    msglen = -1
    start = 0

    while i < len(buf):
        if buf[i] != 0x1a:
            i += 1
            continue

        i += 1
        if i >= len(buf):
            break

        msglen = 1 + 6
        if buf[i] == 0x31:
            msglen += 2
            msgtype = MODE_AC
        elif buf[i] == 0x32:
            msglen += 7
            msgtype = MODE_S_SHORT
        elif buf[i] == 0x33:
            msglen += 14
            msgtype = MODE_S_LONG
        elif buf[i] == 0x34:
            msglen += 14
            msgtype = RADARCAPE_STATUS
        else:
            continue

        i += 1
        msgbytes = bytearray()
        while i < len(buf) and len(msgbytes) < msglen:
            if buf[i] == 0x1a:
                i += 1
                if i >= len(buf) or buf[i] != 0x1a:
                    break

            msgbytes.append(buf[i])
            i += 1

        if len(msgbytes) == msglen:
            timestamp = (msgbytes[0] << 40) | (msgbytes[1] << 32) | (msgbytes[2] << 24) | (msgbytes[3] << 16) | (msgbytes[4] << 8) | (msgbytes[5])
            signal = msgbytes[6]
            data = msgbytes[7:]
            raw = buf[start:i]
            messages.append( (msgtype, timestamp, signal, data, raw) )
            start = i

    return (buf[start:], messages)

def replay(filename, radarcape_mode, show_mode, delay_mode):
    with closing(open(filename, 'rb')) as f:
        buf = b''
        last_timestamp = None
        last_time = None

        while True:
            more = f.read(1024)
            buf = buf + more

            buf, messages = parse(buf)
            if not messages and not more:
                break

            for msgtype, timestamp, signal, data, raw in messages:
                if delay_mode:
                    if radarcape_mode:
                        secs = timestamp >> 30
                        nanos = timestamp & 0x00003FFFFFFF
                        adj_timestamp = nanos + secs * 1000000000
                        freq = 1e9
                    else:
                        adj_timestamp = timestamp
                        freq = 12e6

                    if last_timestamp is None:
                        last_timestamp = adj_timestamp
                        last_time = time.time()
                    elif adj_timestamp > last_timestamp:
                        now = time.time()
                        sched_delta = (adj_timestamp - last_timestamp) / freq
                        delay = last_time + sched_delta - now
                        if delay > 0.010:
                            time.sleep(delay)
                        last_timestamp = adj_timestamp
                        last_time += sched_delta

                if show_mode:
                    h = ''
                    for b in data:
                        h += '{0:02X}'.format(b)
                    print("Type: {0:16s} Time: {1:06X} Signal: {2:3d} Data: {3}".format(msgtype, timestamp, signal, h))
                else:
                    sys.stdout.buffer.write(raw)
                    sys.stdout.buffer.flush()

if __name__ == '__main__':
    import sys

    radarcape_mode = False
    show_mode = False
    delay_mode = True
    for filename in sys.argv[1:]:
        if filename == '--radarcape':
            radarcape_mode = True
        elif filename == '--beast':
            radarcape_mode = False
        elif filename == '--show':
            show_mode = True
        elif filename == '--raw':
            show_mode = False
        elif filename == '--delay':
            delay_mode = True
        elif filename == '--no-delay':
            delay_mode = False
        else:
            replay(filename, radarcape_mode=radarcape_mode, show_mode=show_mode, delay_mode=delay_mode)