summaryrefslogtreecommitdiff
path: root/ADSBDecoder/main.swift
blob: a346fbb78d7eb97a8c72e2ab879c9059db17be0d (plain) (blame)
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
//
//  main.swift
//  ADSBDecoder
//
//  Created by Jacky Jack on 28/05/2024.
//

import Foundation
import ArgumentParser
import RegexBuilder
import SQLite3

//return true if file excists
func checkIfFileExists(_ fname: String) -> Bool {
    let fm = FileManager.default
    if fm.fileExists(atPath: fname) {
        return true
    }
    return false
}

//get current run directory
func getCurrentDirPath() -> String {
    return Process().currentDirectoryPath
}

struct CommandLineArgs: ParsableCommand {
    @Option(name: .shortAndLong) var inputfile: String
    @Flag(name: .shortAndLong) var debug:Bool = false
    @Flag(name: .shortAndLong) var version:Bool = false
    @Flag(name: .shortAndLong) var show_stats:Bool = false
}

let args = CommandLineArgs.parseOrExit()

let fileUrl = URL(fileURLWithPath:args.inputfile)
print("File location [\(fileUrl.absoluteString)]")

//check if file excists
if (checkIfFileExists(fileUrl.path) == false) {
    print("Supplied path \(fileUrl.path) doesnt exists")
    exit(1)
}

//load the file with adsb data
var adsb_source = ""
do {
    adsb_source = try String(contentsOfFile: fileUrl.path)
    print("Loaded \(adsb_source.count) bytes")
} catch {
    print("Couldn't load text from a file \(fileUrl.path)")
    exit(1)
}



let matchADSBLong = Regex {
    Anchor.startOfLine
    "*"
    
        Repeat(
            CharacterClass(
                ("a"..."f"),
                ("0"..."9")
            )
            ,count:28)
    
    ";"
}

let matchADSBShort = Regex {
    Anchor.startOfLine
    "*"
    Repeat(
        CharacterClass(
            ("a"..."f"),
            ("0"..."9")
        )
        ,count:14)
    ";"
}

//gather stats
var q_df = QueryDF()
var q_dftc = QueryDF17TC()
var q_decoded = QueryDecodedMessages()
var q_df17_decoded = QueryDF17TC_decoded()

//track all airplanes
var tracker = AirPlaneTracker()

//parse line by line
var count_messages=0
for line in adsb_source.components(separatedBy: .newlines) {
    var found=false
    //print("\(cnt) \(line)")
    count_messages += 1
    if let tokenMatch = try matchADSBLong.prefixMatch(in: line) {
        //print("\(String(tokenMatch.output))")
        found = true
        let str = String(tokenMatch.output)
        let startIndex = str.index(str.startIndex, offsetBy: 1)
        let endIndex = str.index(str.endIndex, offsetBy: -2)
        let decoder = Decoder(String(str[startIndex...endIndex]))
        if decoder.DataFormat == 17 {
            if let d17 = decoder.getDataFormat17() {
                //print(d17)
                q_dftc.addTC(d17.TypeCode)
                q_decoded.addDecoded()
                if (d17.TypeCode == 4) {
                    if let indentification = d17.messageIdentification {
                        tracker.addDF17Indentification(d17.AddressAnnounced, indentification.ICAOName)
                    }
                    q_df17_decoded.addDecoded(4)
                } else if (d17.TypeCode >= 9 && d17.TypeCode <= 18) {
                    if let airbornposition = d17.messageAirbornPositon {
                        tracker.addDF17AirBornPosition(
                            d17.AddressAnnounced,
                            airbornposition.Latitude,
                            airbornposition.Longitude,
                            airbornposition.Altitude,
                            airbornposition.CPRFormat == 0
                        )
                        if let position = tracker.getPosition(d17.AddressAnnounced) {
                            print("position: \(position)")
                        }
                    }
                    q_df17_decoded.addDecoded(d17.TypeCode)
                } else {
                    q_df17_decoded.addUndecode(d17.TypeCode)
                }
            }
        } else {
            q_decoded.addUndecoded()
        }
        q_df.addDF(decoder.DataFormat)
    };
    
    if let tokenMatch = try matchADSBShort.prefixMatch(in: line) {
        print("\(tokenMatch.output)")
        found = true
        
        q_decoded.addUndecoded()
    };
    
    if (found == false) {
        print("Unknown adsb data line \(line)")
    }
    
    
}


if args.show_stats {
    print("----STAT----")
    //q_df.showStat()
    print(q_df)
    print(q_dftc)
    print(q_decoded)
    print(q_df17_decoded)
    tracker.printAllICAOnames()
    
    print("Total message:\(count_messages)")
}