├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── csharp └── example1 │ ├── .gitignore │ ├── README.md │ ├── example1.cs │ ├── example1.csproj │ ├── example1.sln │ └── output.txt ├── java ├── example1 │ ├── README.md │ ├── SSL_Client_gson.java │ └── output.txt ├── example2 │ ├── README.md │ ├── SSL_Client_json_simple.java │ └── output.txt └── example3 │ ├── README.md │ ├── pom.xml │ └── src │ └── main │ └── java │ └── com │ └── flightaware │ └── firehose │ └── examples │ └── Example3.java ├── perl └── example1 │ ├── README.md │ ├── example1.pl │ └── output.txt ├── php ├── example1 │ ├── README.md │ └── example1.php └── example2 │ ├── README.md │ └── example2.php ├── python └── example1 │ ├── README.md │ ├── example1.py │ └── output.txt └── tcl └── example1 ├── README.md └── example1.tcl /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | *.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | *.sln merge=binary 26 | *.csproj merge=binary 27 | *.vbproj merge=binary 28 | *.vcxproj merge=binary 29 | *.vcproj merge=binary 30 | *.dbproj merge=binary 31 | *.fsproj merge=binary 32 | *.lsproj merge=binary 33 | *.wixproj merge=binary 34 | *.modelproj merge=binary 35 | *.sqlproj merge=binary 36 | *.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | target/ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2017, FlightAware LLC 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following 12 | disclaimer in the documentation and/or other materials provided 13 | with the distribution. 14 | 15 | * Neither the name of the FlightAware LLC nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # firehose_examples 2 | Example programs that demonstrate how to use the FlightAware Firehose service 3 | 4 | For more information about Firehose, please visit: https://flightaware.com/commercial/firehose/ 5 | -------------------------------------------------------------------------------- /csharp/example1/.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | bin 3 | obj 4 | -------------------------------------------------------------------------------- /csharp/example1/README.md: -------------------------------------------------------------------------------- 1 | Requirements 2 | ------------ 3 | 4 | This example was tested against .NET Core 3.1 under Visual Studio 2019 on Windows 10. It has also been tested against the .NET Core 3.1 SDK Docker Linux container: `mcr.microsoft.com/dotnet/core/sdk:3.1` 5 | 6 | Parsing JSON in C# can be done using .NET Framework Classes or by downloading a third party library. 7 | 8 | There are plenty of libraries to choose from http://www.json.org/ 9 | 10 | For this example we are going to use System.Text.Json, which is included with .NET Core 3.0 and higher, however it can also be downloaded from NuGet for certain other .NET Framework versions. 11 | 12 | 13 | What to change 14 | -------------- 15 | 16 | Substitute your actual username and API key in the initiation_command. 17 | 18 | Change/remove limit on the number of messages received. 19 | 20 | 21 | Running the example 22 | ------------------- 23 | Visual Studio or SharpDeveloper offer IDE that make development and testing easier. 24 | 25 | Alternatively, you can run commands (Win32): 26 | 27 | Compile: 28 | 29 | dotnet build example1.csproj 30 | 31 | Run: 32 | 33 | example1 34 | 35 | 36 | -------------------------------------------------------------------------------- /csharp/example1/example1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Collections; 4 | using System.Net; 5 | using System.Net.Security; 6 | using System.Net.Sockets; 7 | using System.Security.Authentication; 8 | using System.Text; 9 | using System.Security.Cryptography.X509Certificates; 10 | using System.IO; 11 | using System.IO.Compression; 12 | using System.Text.Json; // requires .NET Core 3.0 or higher, or the NuGet package 13 | 14 | namespace SSLClient 15 | { 16 | 17 | public class FlightObject 18 | { 19 | 20 | public String type { get; set; } 21 | public String ident { get; set; } 22 | public String air_ground { get; set; } 23 | public String alt { get; set; } 24 | public String clock { get; set; } 25 | public String id { get; set; } 26 | public String gs { get; set; } 27 | public String heading { get; set; } 28 | public String lat { get; set; } 29 | public String lon { get; set; } 30 | public String reg { get; set; } 31 | public String squawk { get; set; } 32 | public String updateType { get; set; } 33 | 34 | 35 | public String toString() 36 | { 37 | String result; 38 | // format result into 2 columns, left justify data, min 10 chars col space 39 | result = String.Format(" {0,-10} {1,-10}\n {2,-10} {3,-10}\n {4,-10} {5,-10}\n" + 40 | " {6,-10} {7,-10}\n {8,-10} {9,-10}\n {10,-10} {11,-10}\n" + 41 | " {12,-10} {13,-10}\n {14,-10} {15,-10}\n {16,-10} {17,-10}\n" + 42 | " {18,-10} {19,-10}\n {20,-10} {21,-10}\n {22,-10} {23,-10}\n" + 43 | " {24,-10} {25,-10}\n", 44 | "type", type, 45 | "ident", ident, 46 | "airground", air_ground, 47 | "alt", alt, 48 | "clock", clock, 49 | "id", id, 50 | "gs", gs, 51 | "heading", heading, 52 | "lat", lat, 53 | "lon", lon, 54 | "reg", reg, 55 | "squawk", squawk, 56 | "updateType", updateType 57 | ); 58 | return result; 59 | } 60 | } 61 | 62 | 63 | public class SSLClient 64 | { 65 | public static String username = "XXXXXXXX"; 66 | public static String apikey = "XXXXXXXXXXXXXXXXXXXX"; 67 | public static Boolean useCompression = true; 68 | public static String initiation_command = "live username " + username + " password " + apikey + 69 | (useCompression ? " compression deflate" : "") + "\n"; 70 | 71 | // The following method is invoked by the RemoteCertificateValidationDelegate 72 | // prevent communication with unauthenticated server 73 | public static bool ValidateServerCertificate( 74 | object sender, 75 | X509Certificate certificate, 76 | X509Chain chain, 77 | SslPolicyErrors sslPolicyErrors) 78 | { 79 | if (sslPolicyErrors == SslPolicyErrors.None) 80 | { 81 | // authenticated 82 | return true; 83 | } 84 | 85 | Console.WriteLine("Certificate error: {0}", sslPolicyErrors); 86 | // Do not allow this client to communicate with unauthenticated servers. 87 | return false; 88 | } 89 | public static void RunClient(string machineName, string serverName) 90 | { 91 | // Create a TCP/IP client socket. 92 | TcpClient client = new TcpClient(machineName, 1501); 93 | 94 | // Create ssl stream to read data 95 | SslStream sslStream = new SslStream( 96 | client.GetStream(), 97 | true, 98 | new RemoteCertificateValidationCallback(ValidateServerCertificate), 99 | null); 100 | try 101 | { 102 | // require at least TLS 1.2 (this enumeration exists starting in .NET 4.5) 103 | // (older platforms use:) var sslProtocols = (SslProtocols)0x00000C00; 104 | var sslProtocols = SslProtocols.Tls12; 105 | 106 | // server name must match name on the server certificate. 107 | sslStream.AuthenticateAsClient(serverName, null, sslProtocols, true); 108 | Console.WriteLine("sslStream AuthenticateAsClient completed."); 109 | } 110 | catch (AuthenticationException e) 111 | { 112 | Console.WriteLine("Exception: {0}", e.Message); 113 | if (e.InnerException != null) 114 | { 115 | Console.WriteLine("Inner exception: {0}", e.InnerException.Message); 116 | } 117 | Console.WriteLine("Authentication failed - closing the connection."); 118 | client.Close(); 119 | return; 120 | } 121 | 122 | // Send initiation command to the server. 123 | // Encode to a byte array. 124 | Console.WriteLine(initiation_command); 125 | byte[] messsage = Encoding.UTF8.GetBytes(initiation_command + "\n"); 126 | sslStream.Write(messsage); 127 | sslStream.Flush(); 128 | 129 | //read from server, print to console: 130 | StreamReader sr; 131 | if (useCompression) 132 | { 133 | sr = new StreamReader(new DeflateStream(sslStream, CompressionMode.Decompress)); 134 | } 135 | else 136 | { 137 | sr = new StreamReader(sslStream); 138 | } 139 | int limit = 1000; 140 | while (limit > 0) 141 | { 142 | string line; 143 | if (useCompression) 144 | { 145 | line = sr.ReadLineAsync().Result; 146 | } 147 | else 148 | { 149 | line = sr.ReadLine(); 150 | } 151 | 152 | if (line == null) 153 | { 154 | limit = 0; 155 | } 156 | else 157 | { 158 | Console.WriteLine(" Received: " + line); 159 | parse(line); 160 | limit--; 161 | } 162 | 163 | } 164 | 165 | // Close the client connection. 166 | sr.Close(); 167 | client.Close(); 168 | Console.WriteLine("Client closed."); 169 | } 170 | 171 | public static void parse(string mes) 172 | { 173 | FlightObject flight = JsonSerializer.Deserialize(mes); 174 | Console.WriteLine(" --------------- Message ------------------ \n"); 175 | Console.WriteLine(flight.toString()); 176 | Console.WriteLine(" ------------------------------------------ \n"); 177 | } 178 | 179 | public static int Main(string[] args) 180 | { 181 | 182 | // machineName is the host running the server application. 183 | String machineName = "firehose.flightaware.com"; 184 | String serverCertificateName = machineName; 185 | 186 | //connect, read data 187 | SSLClient.RunClient(machineName, serverCertificateName); 188 | 189 | Console.WriteLine(" Hit Enter to end ..."); 190 | Console.Read(); 191 | return 0; 192 | } 193 | } 194 | } -------------------------------------------------------------------------------- /csharp/example1/example1.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /csharp/example1/example1.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "example1", "example1.csproj", "{BC13EC46-377C-4231-A444-4371C75ED2BE}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {BC13EC46-377C-4231-A444-4371C75ED2BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {BC13EC46-377C-4231-A444-4371C75ED2BE}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {BC13EC46-377C-4231-A444-4371C75ED2BE}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {BC13EC46-377C-4231-A444-4371C75ED2BE}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {A9A0FEBC-C912-4C9E-B899-C7C59600211E} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /csharp/example1/output.txt: -------------------------------------------------------------------------------- 1 | 2 | sslStream AuthenticateAsClient completed. 3 | Received: {"type":"position","ident":"AAL363","air_ground":"A","alt":"37200"," 4 | lock":"1417488737","id":"AAL363-1417242628-airline-0282","gs":"374","heading":" 5 | 79","lat":"42.81940","lon":"-83.97197","reg":"N930NN","updateType":"A"} 6 | 7 | ------------------- Message ---------------------- 8 | 9 | type position 10 | ident AAL363 11 | airground A 12 | alt 37200 13 | clock 1417488737 14 | id AAL363-1417242628-airline-0282 15 | gs 374 16 | heading 279 17 | lat 42.81940 18 | lon -83.97197 19 | reg N930NN 20 | squawk 21 | updateType A 22 | 23 | ------------------------------------------------- 24 | 25 | Received: {"type":"position","ident":"AWE798","air_ground":"A","alt":"37000"," 26 | lock":"1417488736","id":"AWE798-1417242974-airline-0052","gs":"545","heading":" 27 | 2","lat":"43.14862","lon":"-68.63178","reg":"N206UW","updateType":"A"} 28 | 29 | ------------------- Message ---------------------- 30 | 31 | type position 32 | ident AWE798 33 | airground A 34 | alt 37000 35 | clock 1417488736 36 | id AWE798-1417242974-airline-0052 37 | gs 545 38 | heading 42 39 | lat 43.14862 40 | lon -68.63178 41 | reg N206UW 42 | squawk 43 | updateType A 44 | 45 | ------------------------------------------------- 46 | -------------------------------------------------------------------------------- /java/example1/README.md: -------------------------------------------------------------------------------- 1 | Requirements 2 | ------------ 3 | 4 | * Java SE 8 5 | * JSON parsing library 6 | 7 | Depending on Java platform used, there may or may not be a standard JSON parsing library. 8 | However, there are plenty of libraries to choose from http://www.json.org/ 9 | 10 | This example uses the google-gson library. Download google-gson library from https://github.com/google/gson 11 | 12 | 13 | What to change 14 | -------------- 15 | 16 | Substitute your actual username and API key in the initiation_command. 17 | 18 | Change/remove limit on the number of messages received. 19 | 20 | 21 | 22 | Running the example 23 | ------------------- 24 | Eclipse or NetBeans IDE could make development and testing easier. 25 | 26 | Alternatively you can run commands such as (Win32): 27 | 28 | Compile: 29 | 30 | javac -classpath "xxx\gson-2.8.6.jar" SSL_Client_gson.java 31 | 32 | Run: 33 | 34 | java -classpath "xxx\gson-2.8.6.jar;." SSL_Client_gson 35 | -------------------------------------------------------------------------------- /java/example1/SSL_Client_gson.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.IOException; 3 | import java.io.InputStream; 4 | import java.io.InputStreamReader; 5 | import java.io.OutputStreamWriter; 6 | import javax.net.ssl.*; 7 | import com.google.gson.Gson; 8 | 9 | public class SSL_Client_gson { 10 | 11 | // substitute your own username and password 12 | private static String initiation_command = "live username XXXXXXXX password XXXXXXXXXXXXXXXXXXXX"; 13 | private SSLSocket ssl_socket; 14 | private static final boolean useCompression = false; 15 | 16 | public static void main(String[] args) { 17 | String machineName = "firehose.flightaware.com"; 18 | RunClient(machineName); 19 | System.out.println(" Thank you for using FlightAware ... bye now"); 20 | } 21 | 22 | private class FlightObject { 23 | 24 | //define here all fields of interest from the received messages 25 | public String type; 26 | public String ident; 27 | public String air_ground; 28 | public String alt; 29 | public String clock; 30 | public String id; 31 | public String gs; 32 | public String heading; 33 | public String lat; 34 | public String lon; 35 | public String reg; 36 | public String squawk; 37 | public String updateType; 38 | 39 | @Override 40 | public String toString() { 41 | String result; 42 | //if any field is missing in the received message, 43 | //for eg if "squawk" is missing then squawk value will be null! 44 | //format as a table left justified, 10 chars min width 45 | result = String.format("%-10s %-10s\n %-10s %-10s\n %-10s %-10s\n " 46 | + "%-10s %-10s\n %-10s %-10s\n %-10s %-10s\n " 47 | + "%-10s %-10s\n %-10s %-10s\n %-10s %-10s\n " 48 | + "%-10s %-10s\n %-10s %-10s\n %-10s %-10s\n " 49 | + "%-10s %-10s\n", 50 | "type", type, 51 | "ident", ident, 52 | "airground", air_ground, 53 | "alt", alt, 54 | "clock", clock, 55 | "id", id, 56 | "gs", gs, 57 | "heading", heading, 58 | "lat", lat, 59 | "lon", lon, 60 | "reg", reg, 61 | "squawk", squawk, 62 | "updateType", updateType 63 | ); 64 | return result; 65 | } 66 | } 67 | 68 | public static void RunClient(String machineName) { 69 | System.out.println(" Running Client"); 70 | try { 71 | SSLSocket ssl_socket; 72 | ssl_socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(machineName, 1501); 73 | // enable certifcate validation: 74 | SSLParameters sslParams = new SSLParameters(); 75 | sslParams.setEndpointIdentificationAlgorithm("HTTPS"); 76 | sslParams.setProtocols(new String[] {"TLSv1.2"}); 77 | ssl_socket.setSSLParameters(sslParams); 78 | 79 | if (useCompression) { 80 | initiation_command += " compression gzip"; 81 | } 82 | 83 | initiation_command += "\n"; 84 | 85 | //send your initiation command 86 | OutputStreamWriter writer = new OutputStreamWriter(ssl_socket.getOutputStream(), "UTF8"); 87 | writer.write(initiation_command); 88 | writer.flush(); 89 | 90 | InputStream inputStream = ssl_socket.getInputStream(); 91 | if (useCompression) { 92 | inputStream = new java.util.zip.GZIPInputStream(inputStream); 93 | } 94 | 95 | // read messages from FlightAware 96 | BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); 97 | Gson gson = new Gson(); 98 | String message = null; 99 | int limit = 10; //limit number messages for testing 100 | while (limit > 0 && (message = reader.readLine()) != null) { 101 | System.out.println("msg: " + message); 102 | //parse message with gson 103 | System.out.printf("---------------- Parsing ---------------------\n"); 104 | FlightObject flight = gson.fromJson(message, FlightObject.class); 105 | System.out.println(flight); 106 | System.out.println("---------------------------------------------\n"); 107 | limit--; 108 | } 109 | 110 | //done, close everything 111 | writer.close(); 112 | reader.close(); 113 | inputStream.close(); 114 | ssl_socket.close(); 115 | 116 | } catch (IOException e) { 117 | e.printStackTrace(); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /java/example1/output.txt: -------------------------------------------------------------------------------- 1 | 2 | Running Client 3 | msg: {"type":"position","ident":"TFR52","air_ground":"A","alt":"7000","clock":"1440101019","id":"TFR52-1440084510-fds-0000:0","gs":"319","heading":"286","hexid":"C81E1C","lat":"-16.61007","lon":"145.81540","reg":"ZKTLE","squawk":"6025","updateType":"A","altChange":"C"} 4 | 5 | --------- Parsing Results -------- 6 | type position 7 | ident TFR52 8 | airground A 9 | alt 7000 10 | clock 1440101019 11 | id TFR52-1440084510-fds-0000:0 12 | gs 319 13 | heading 286 14 | lat -16.61007 15 | lon 145.81540 16 | reg ZKTLE 17 | squawk 6025 18 | updateType A 19 | --------------------------------- 20 | 21 | msg: {"type":"position","ident":"TFR52","air_ground":"A","alt":"7000","clock":"1440101019","id":"TFR52-1440084510-fds-0000","gs":"319","heading":"286","hexid":"C81E1C","lat":"-16.61007","lon":"145.81540","reg":"ZKTLE","squawk":"6025","updateType":"A","altChange":" "} 22 | 23 | --------- Parsing Results -------- 24 | type position 25 | ident TFR52 26 | airground A 27 | alt 7000 28 | clock 1440101019 29 | id TFR52-1440084510-fds-0000 30 | gs 319 31 | heading 286 32 | lat -16.61007 33 | lon 145.81540 34 | reg ZKTLE 35 | squawk 6025 36 | updateType A 37 | --------------------------------- 38 | 39 | -------------------------------------------------------------------------------- /java/example2/README.md: -------------------------------------------------------------------------------- 1 | Requirements 2 | ------------ 3 | 4 | * Java SE 8 5 | * JSON parsing library 6 | 7 | Depending on Java platform used, there may or may not be a standard JSON parsing library. 8 | However, there are plenty of libraries to choose from http://www.json.org/ 9 | 10 | This example uses Json-simple "a simple lightweight Java toolkit for 11 | JSON". Download Json-simple library from https://github.com/fangyidong/json-simple 12 | 13 | 14 | What to change 15 | -------------- 16 | 17 | Substitute your actual username and API key in the initiation_command. 18 | 19 | Change/remove limit on the number of messages received. 20 | 21 | 22 | 23 | Running the example 24 | ------------------- 25 | 26 | Eclipse or NetBeans IDE could make development and testing easier. 27 | 28 | Alternatively you can run commands such as (Win32): 29 | 30 | Compile: 31 | 32 | javac -classpath "xxx\json-simple-1.1.1.jar" SSL_Client_json_simple.java 33 | 34 | Run: 35 | 36 | java -classpath "xxx\json-simple-1.1.1.jar;." SSL_Client_json_simple 37 | 38 | -------------------------------------------------------------------------------- /java/example2/SSL_Client_json_simple.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.IOException; 3 | import java.io.InputStream; 4 | import java.io.InputStreamReader; 5 | import java.io.OutputStreamWriter; 6 | import javax.net.ssl.*; 7 | import org.json.simple.JSONObject; 8 | import org.json.simple.parser.JSONParser; 9 | import org.json.simple.parser.ParseException; 10 | 11 | public class SSL_Client_json_simple { 12 | 13 | // substitute your own username and password 14 | private static String initiation_command = "live username XXXXXXXX password XXXXXXXXXXXXXXXXXXXX"; 15 | private static final boolean useCompression = false; 16 | private SSLSocket ssl_socket; 17 | 18 | public static void main(String[] args) { 19 | String machineName = "firehose.flightaware.com"; 20 | RunClient(machineName); 21 | System.out.println(" Thank you for using FlightAware ... bye now"); 22 | } 23 | 24 | private static void RunClient(String machineName) { 25 | System.out.println(" Running Client"); 26 | try { 27 | SSLSocket ssl_socket; 28 | ssl_socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(machineName, 1501); 29 | // enable certifcate validation: 30 | SSLParameters sslParams = new SSLParameters(); 31 | sslParams.setEndpointIdentificationAlgorithm("HTTPS"); 32 | sslParams.setProtocols(new String[] {"TLSv1.2"}); 33 | ssl_socket.setSSLParameters(sslParams); 34 | 35 | if (useCompression) { 36 | initiation_command += " compression gzip"; 37 | } 38 | 39 | initiation_command += "\n"; 40 | 41 | //send your initiation command 42 | OutputStreamWriter writer = new OutputStreamWriter(ssl_socket.getOutputStream(), "UTF8"); 43 | writer.write(initiation_command); 44 | writer.flush(); 45 | 46 | InputStream inputStream = ssl_socket.getInputStream(); 47 | if (useCompression) { 48 | inputStream = new java.util.zip.GZIPInputStream(inputStream); 49 | } 50 | 51 | // read messages from FlightAware 52 | BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); 53 | String message = null; 54 | int limit = 5; //limit number messages for testing 55 | while (limit > 0 && (message = reader.readLine()) != null) { 56 | System.out.println("msg: " + message + "\n"); 57 | parse_json(message); 58 | limit--; 59 | } 60 | 61 | //done, close everything 62 | writer.close(); 63 | reader.close(); 64 | inputStream.close(); 65 | ssl_socket.close(); 66 | 67 | } catch (IOException e) { 68 | e.printStackTrace(); 69 | } 70 | } 71 | 72 | public static void parse_json(String message) { 73 | //using JSON.simple: Java toolkit for JSON 74 | JSONParser jsonParser = new JSONParser(); 75 | JSONObject jsonObject; 76 | try { 77 | // parse message from json to JSONObject 78 | jsonObject = (JSONObject) jsonParser.parse(message); 79 | 80 | // retrieve values of interest associated with the keys 81 | // for alternative ways to retrieve data checks http://www.json.org/javadoc/org/json/JSONObject.html 82 | String type = (String) jsonObject.get("type"); 83 | String ident = (String) jsonObject.get("ident"); 84 | String air_ground = (String) jsonObject.get("air_ground"); 85 | String alt = (String) jsonObject.get("alt"); 86 | String clock = (String) jsonObject.get("clock"); 87 | String id = (String) jsonObject.get("id"); 88 | String gs = (String) jsonObject.get("gs"); 89 | String heading = (String) jsonObject.get("heading"); 90 | String lat = (String) jsonObject.get("lat"); 91 | String lon = (String) jsonObject.get("lon"); 92 | String reg = (String) jsonObject.get("reg"); 93 | String squawk = (String) jsonObject.get("squawk"); 94 | String updateType = (String) jsonObject.get("updateType"); 95 | // if any field is missing, for eg if "squawk" is missing then squawk value will be null! 96 | 97 | // print values from above 98 | System.out.println("--------- Parsing Results --------"); 99 | System.out.println(String.format(" %-10s %-10s\n " 100 | + "%-10s %-10s\n %-10s %-10s\n %-10s %-10s\n " 101 | + "%-10s %-10s\n %-10s %-10s\n %-10s %-10s\n " 102 | + "%-10s %-10s\n %-10s %-10s\n %-10s %-10s\n " 103 | + "%-10s %-10s\n %-10s %-10s\n %-10s %-10s ", 104 | "type", type, 105 | "ident", ident, 106 | "airground", air_ground, 107 | "alt", alt, 108 | "clock", clock, 109 | "id", id, 110 | "gs", gs, 111 | "heading", heading, 112 | "lat", lat, 113 | "lon", lon, 114 | "reg", reg, 115 | "squawk", squawk, 116 | "updateType", updateType 117 | )); 118 | System.out.println("---------------------------------\n"); 119 | 120 | } catch (ParseException e) { 121 | e.printStackTrace(); 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /java/example2/output.txt: -------------------------------------------------------------------------------- 1 | Running Client 2 | msg: {"type":"position","ident":"VOI423","air_ground":"A","alt":"7400","clock":"1440096358","id":"VOI423-1439922000-schedule-0001","gs":"184","heading":"295","hexid":"0D081C","lat":"20.54741","lon":"-103.36899","updateType":"A","altChange":"C"} 3 | 4 | --------- Parsing Results -------- 5 | type position 6 | ident VOI423 7 | airground A 8 | alt 7400 9 | clock 1440096358 10 | id VOI423-1439922000-schedule-0001 11 | gs 184 12 | heading 295 13 | lat 20.54741 14 | lon -103.36899 15 | reg null 16 | squawk null 17 | updateType A 18 | --------------------------------- 19 | 20 | msg: {"type":"position","ident":"N317SW","air_ground":"A","alt":"5600","clock":"1440096358","id":"N317SW-1440095950-adhoc-0","gs":"169","heading":"62","hexid":"A36277","lat":"41.58961","lon":"-92.50894","reg":"N317SW","squawk":"1200","updateType":"A","altChange":"C"} 21 | 22 | --------- Parsing Results -------- 23 | type position 24 | ident N317SW 25 | airground A 26 | alt 5600 27 | clock 1440096358 28 | id N317SW-1440095950-adhoc-0 29 | gs 169 30 | heading 62 31 | lat 41.58961 32 | lon -92.50894 33 | reg N317SW 34 | squawk 1200 35 | updateType A 36 | --------------------------------- 37 | -------------------------------------------------------------------------------- /java/example3/README.md: -------------------------------------------------------------------------------- 1 | Example3 2 | 3 | Read the FlightAware Firehose stream and aggregate the departure and arrival messages. Collect the departures and 4 | arrivals in a hashmap. 5 | Every 30 seconds print the state of the hashmap as CSV to standard out. 6 | 7 | This program can be compiled and run with Apache Maven. It can also be imported into IntelliJ as a Maven project. 8 | 9 | This program uses Googles JSON parser for de-serializing JSON into Java objects. -------------------------------------------------------------------------------- /java/example3/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | com.flightaware.firehose.examples 4 | example3 5 | 1.0.0-SNAPSHOT 6 | 2008 7 | 8 | 9 | 10 | com.google.code.gson 11 | gson 12 | 2.8.9 13 | 14 | 15 | 16 | 17 | src/main/java 18 | src/test/java 19 | 20 | 21 | org.apache.maven.plugins 22 | maven-surefire-plugin 23 | 2.7 24 | 25 | true 26 | 27 | 28 | 29 | org.codehaus.mojo 30 | exec-maven-plugin 31 | 1.2.1 32 | 33 | 34 | verify 35 | 36 | java 37 | 38 | 39 | com.flightaware.firehose.examples.Example3 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /java/example3/src/main/java/com/flightaware/firehose/examples/Example3.java: -------------------------------------------------------------------------------- 1 | package com.flightaware.firehose.examples; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.io.OutputStreamWriter; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.concurrent.TimeUnit; 11 | import javax.net.ssl.*; 12 | import com.google.gson.Gson; 13 | 14 | class FlightObject { 15 | 16 | //define here all fields of interest from the received messages 17 | String id; 18 | String type; 19 | String ident; 20 | String orig; 21 | String dest; 22 | String aat; // actual arrival time 23 | String adt; // actual departure time 24 | String reg; 25 | 26 | @Override 27 | public String toString() { 28 | return "FlightObject{" + 29 | "id='" + id + '\'' + 30 | ", type='" + type + '\'' + 31 | ", ident='" + ident + '\'' + 32 | ", orig='" + orig + '\'' + 33 | ", dest='" + dest + '\'' + 34 | ", aat='" + aat + '\'' + 35 | ", adt='" + adt + '\'' + 36 | ", reg='" + reg + '\'' + 37 | '}'; 38 | } 39 | } 40 | 41 | class Flight { 42 | FlightObject departure; 43 | FlightObject arrival; 44 | 45 | @Override 46 | public String toString() { 47 | String id = ""; 48 | String ident = ""; 49 | String orig = ""; 50 | String dest = ""; 51 | String adt = ""; 52 | String aat = ""; 53 | 54 | // Handle all cases where null can be present 55 | if (departure != null) { 56 | orig = departure.orig; 57 | adt = departure.adt; 58 | ident = departure.ident; 59 | id = departure.id; 60 | } 61 | 62 | if (arrival != null) { 63 | ident = arrival.ident; 64 | dest = arrival.dest; 65 | aat = arrival.aat; 66 | id = arrival.id; 67 | } 68 | 69 | if (id == null) { 70 | throw new RuntimeException("id cannot be null " + departure.toString() + " " + arrival.toString()); 71 | } 72 | if (ident == null) ident = ""; 73 | if (orig == null) orig = ""; 74 | if (dest == null) dest = ""; 75 | if (adt == null) adt = ""; 76 | if (aat == null) aat = ""; 77 | 78 | return String.format("%s,%s,%s,%s,%s,%s", 79 | id, orig, dest, ident, adt, aat); 80 | } 81 | } 82 | 83 | /* 84 | * Aggregate all of the departure and arrival messages into a single object. 85 | * Join the messages based on the id key. 86 | * 87 | * Since we join the feed in the past, we will have arrivals without departures. 88 | */ 89 | public class Example3 { 90 | 91 | // Our flight board state is saved in a HashMap in RAM 92 | // The key is the id field, the flight id FA generates. 93 | private static final Map flights = new HashMap(); 94 | 95 | // GZIP the data on the network wire 96 | private static final boolean useCompression = false; 97 | 98 | // 99 | // Either pass the username and API access token on the command line or 100 | // set properties 101 | // 102 | // You can run with maven using the target verify to run the program. 103 | // Fill in your username and API key 104 | // 105 | // mvn -Dfirehose.username=##### -Dfirehose.password=###### verify 106 | // 107 | public static void main(String[] args) { 108 | String machineName = "firehose.flightaware.com"; 109 | if (args.length != 2) { 110 | RunClient(machineName, System.getProperty("firehose.username"), System.getProperty("firehose.password")); 111 | } else { 112 | RunClient(machineName, args[0], args[1]); 113 | } 114 | System.out.println(" Thank you for using FlightAware ... bye now"); 115 | } 116 | 117 | /* 118 | * Print out the hash map as CSV 119 | */ 120 | private static void PrintBoard() { 121 | long now = System.currentTimeMillis(); 122 | now = TimeUnit.SECONDS.convert(now, TimeUnit.MILLISECONDS); 123 | for (Flight flight : flights.values()) { 124 | System.out.println(now + "," + flight.toString()); 125 | } 126 | } 127 | 128 | private static void RunClient(String machineName, String username, String password) { 129 | // Request data from 3 days ago 130 | // It can take awhile to catch up, but this insures we get all the departures 131 | // 3 days is a bit conservative 132 | long startTime = System.currentTimeMillis(); 133 | startTime = TimeUnit.SECONDS.convert(startTime, TimeUnit.MILLISECONDS); 134 | startTime = startTime - TimeUnit.DAYS.toSeconds(3L); 135 | 136 | // Initiate data stream 137 | String initiation_command = String.format("pitr " + startTime + " username %s password %s", username, password); 138 | try { 139 | SSLSocket ssl_socket; 140 | ssl_socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(machineName, 1501); 141 | SSLParameters sslParams = new SSLParameters(); 142 | sslParams.setEndpointIdentificationAlgorithm("HTTPS"); 143 | sslParams.setProtocols(new String[] {"TLSv1.2"}); 144 | ssl_socket.setSSLParameters(sslParams); 145 | 146 | if (useCompression) { 147 | initiation_command += " compression gzip"; 148 | } 149 | 150 | initiation_command += "\n"; 151 | 152 | //send your initiation command 153 | OutputStreamWriter writer = new OutputStreamWriter(ssl_socket.getOutputStream(), "UTF8"); 154 | writer.write(initiation_command); 155 | writer.flush(); 156 | 157 | InputStream inputStream = ssl_socket.getInputStream(); 158 | if (useCompression) { 159 | inputStream = new java.util.zip.GZIPInputStream(inputStream); 160 | } 161 | 162 | // read messages from FlightAware 163 | BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); 164 | Gson gson = new Gson(); 165 | String message; 166 | long start = System.currentTimeMillis(); 167 | while ((message = reader.readLine()) != null) { 168 | // Parse the JSON with Googles GSON 169 | // Any missing fields will be null 170 | FlightObject flight = gson.fromJson(message, FlightObject.class); 171 | // Filter by message type 172 | if (flight.type.equals("arrival") || flight.type.equals("departure")) { 173 | // Get last value from map 174 | Flight f = flights.get(flight.id); 175 | if (f == null) { 176 | // Add a value to map 177 | f = new Flight(); 178 | flights.put(flight.id, f); 179 | } 180 | // Update either the arrival or departure 181 | if (flight.type.equals("arrival")) { 182 | f.arrival = flight; 183 | } else { 184 | f.departure = flight; 185 | } 186 | // Every 30 seconds print out the collection 187 | long now = System.currentTimeMillis(); 188 | if (now - start > TimeUnit.SECONDS.toMillis(30)) { 189 | start = now; 190 | PrintBoard(); 191 | } 192 | } 193 | } 194 | 195 | //done, close everything 196 | writer.close(); 197 | reader.close(); 198 | inputStream.close(); 199 | ssl_socket.close(); 200 | 201 | } catch (IOException e) { 202 | e.printStackTrace(); 203 | } 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /perl/example1/README.md: -------------------------------------------------------------------------------- 1 | Requirements 2 | ------------ 3 | * Perl 5 4 | * IO::Socket::SSL 5 | * Net::SSLeay 6 | 7 | You can download Perl from https://www.perl.org/. You may need to also 8 | install the perl modules that are referenced, by using the cpan 9 | utility. Please note that Perl 6 is not compatible with this example. 10 | 11 | If using a Debian system, you can use the following installation command: 12 | 13 | sudo apt-get install libnet-ssleay-perl libio-socket-ssl-perl 14 | 15 | 16 | What to change 17 | -------------- 18 | Substitute your actual username and API key in the variables at the top of the program. 19 | 20 | Change/remove count on the number of messages received. 21 | 22 | 23 | Run commands 24 | ------------ 25 | 26 | perl example1.pl 27 | 28 | -------------------------------------------------------------------------------- /perl/example1/example1.pl: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/perl 2 | 3 | use strict; 4 | use IO::Socket::SSL; 5 | use JSON::PP; 6 | use Compress::Zlib; 7 | use Data::Dumper; 8 | 9 | my $username = 'XXXXXXXXXX'; 10 | my $apikey = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; 11 | my $compression = 0; 12 | 13 | # Open the TLS socket connection to FlightAware. 14 | my $sock = IO::Socket::SSL->new( 15 | PeerHost => 'firehose-test.flightaware.com', 16 | PeerPort => 1501, 17 | SSL_version => 'TLSv1_2') or die $!; 18 | print "Connected!\n"; 19 | 20 | # Send the initiation command to the uncompressed socket. 21 | my $initcmd = "live version 7.0 user $username password $apikey events \"flifo position\""; 22 | if ($compression) { 23 | $initcmd .= " compression compress"; 24 | } 25 | binmode $sock; 26 | print $sock "$initcmd\n"; 27 | 28 | # Activate compression, if requested. 29 | my $zsock; 30 | if ($compression) { 31 | $zsock = inflateInit() 32 | or die "Could not initiate inflate\n"; 33 | } else { 34 | $zsock = $sock; 35 | } 36 | 37 | # Main loop, reading lines of JSON from the server. 38 | my $i = 1; 39 | my $buffer = ""; 40 | while (1) { 41 | #print "LINE $i\n"; 42 | #print "LINE $i: ", $line, "\n"; 43 | 44 | my $line = ""; 45 | my $data_available = 1; 46 | 47 | if ($compression) { 48 | if (index($buffer, "\n") == -1) { 49 | $data_available = read($sock, $line, 8192); 50 | (my $output, my $status) = $zsock->inflate($line); 51 | $line = $output; 52 | 53 | $buffer = $buffer . $line; 54 | } 55 | 56 | my $rawline = ""; 57 | my $newline_index = index($buffer, "\n"); 58 | 59 | if ($newline_index != -1) { 60 | $rawline = substr($buffer, 0, $newline_index); 61 | $buffer = substr($buffer, $newline_index + 1); 62 | } 63 | 64 | $line = $rawline 65 | 66 | } else { 67 | $line = $sock->getline(); 68 | if(!defined($line)) { 69 | $data_available = 0; 70 | } 71 | } 72 | 73 | if ($line ne "") { 74 | my $data = eval { decode_json $line }; 75 | die "Failed to decode JSON: $line" if !defined($data) || $@; 76 | 77 | print "LINE $i\n" . Dumper($data); 78 | 79 | last if ($i++ >= 1000); 80 | } 81 | 82 | last if (!$data_available); 83 | 84 | } 85 | close $sock; 86 | 87 | print "All done.\n"; 88 | -------------------------------------------------------------------------------- /perl/example1/output.txt: -------------------------------------------------------------------------------- 1 | Connected! 2 | LINE 1 3 | $VAR1 = { 4 | 'fdt' => '1473423300', 5 | 'type' => 'flightplan', 6 | 'status' => 'S', 7 | 'dest' => 'EDDB', 8 | 'facility_name' => 'Airline', 9 | 'ete' => '6600', 10 | 'eta' => '1473429900', 11 | 'aircrafttype' => 'A319', 12 | 'ident' => 'EZY6237', 13 | 'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9', 14 | 'pitr' => '1473380220', 15 | 'speed' => '363', 16 | 'orig' => 'EGGD', 17 | 'edt' => '1473423300', 18 | 'id' => 'EZY6237-1473226541-airline-0394' 19 | }; 20 | LINE 2 21 | $VAR1 = { 22 | 'ete' => '3720', 23 | 'reg' => 'N8696E', 24 | 'eta' => '1473377100', 25 | 'waypoints' => [ 26 | { 27 | 'lon' => '-87.75', 28 | 'lat' => '41.79' 29 | }, 30 | { 31 | 'lon' => '-87.84', 32 | 'lat' => '41.79' 33 | }, 34 | { 35 | 'lat' => '41.79', 36 | 'lon' => '-87.87' 37 | }, 38 | { 39 | 'lat' => '39.48', 40 | 'lon' => '-94.59' 41 | }, 42 | { 43 | 'lon' => '-94.71', 44 | 'lat' => '39.3' 45 | } 46 | ], 47 | 'dest' => 'KMCI', 48 | 'facility_name' => 'Airline', 49 | 'speed' => '467', 50 | 'orig' => 'KMDW', 51 | 'route' => 'KMDW./.VORIN041016..QUANE..BQS.BQS4.KMCI/2326', 52 | 'edt' => '1473373380', 53 | 'ident' => 'SWA3002', 54 | 'pitr' => '1473380220', 55 | 'aircrafttype' => 'B738', 56 | 'status' => 'Z', 57 | 'type' => 'flightplan', 58 | 'fdt' => '1473373200', 59 | 'alt' => '2700', 60 | 'id' => 'SWA3002-1473140159-airline-0252', 61 | 'hexid' => 'ABF375', 62 | 'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9' 63 | }; 64 | LINE 3 65 | $VAR1 = { 66 | 'edt' => '1473468300', 67 | 'speed' => '391', 68 | 'orig' => 'KPIT', 69 | 'pitr' => '1473380220', 70 | 'ident' => 'FFT1093', 71 | 'eta' => '1473484200', 72 | 'reg' => 'N216FR', 73 | 'ete' => '15900', 74 | 'dest' => 'KLAS', 75 | 'facility_name' => 'Airline', 76 | 'id' => 'FFT1093-1473226201-airline-0321', 77 | 'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9', 78 | 'aircrafttype' => 'A320', 79 | 'fdt' => '1473468300', 80 | 'type' => 'flightplan', 81 | 'status' => 'S' 82 | }; 83 | LINE 4 84 | $VAR1 = { 85 | 'dest' => 'EGCC', 86 | 'facility_name' => 'Airline', 87 | 'type' => 'flightplan', 88 | 'fdt' => '1473449100', 89 | 'status' => 'S', 90 | 'eta' => '1473460200', 91 | 'aircrafttype' => 'B738', 92 | 'ete' => '10500', 93 | 'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9', 94 | 'pitr' => '1473380220', 95 | 'ident' => 'RYR8895', 96 | 'id' => 'RYR8895-1473226211-airline-0419', 97 | 'edt' => '1473449700', 98 | 'speed' => '384', 99 | 'orig' => 'LIBR' 100 | }; 101 | LINE 5 102 | $VAR1 = { 103 | 'ident' => 'JAI364', 104 | 'lon' => '73.26817', 105 | 'pitr' => '1473380220', 106 | 'gs' => '461', 107 | 'lat' => '19.72847', 108 | 'facility_name' => 'FlightAware ADS-B', 109 | 'reg' => 'VTJBL', 110 | 'updateType' => 'A', 111 | 'heading' => '344', 112 | 'facility_hash' => 'b4a580edcf3c4ba4302ce4aa6e3b36af39b1259f', 113 | 'air_ground' => 'A', 114 | 'altChange' => 'C', 115 | 'clock' => '1473380210', 116 | 'hexid' => '800547', 117 | 'id' => 'JAI364-1473225942-airline-0283', 118 | 'type' => 'position', 119 | 'squawk' => '0302', 120 | 'alt' => '26900' 121 | }; 122 | LINE 6 123 | $VAR1 = { 124 | 'type' => 'flightplan', 125 | 'fdt' => '1473394500', 126 | 'status' => 'S', 127 | 'dest' => 'RPLL', 128 | 'facility_name' => 'Airline', 129 | 'ete' => '2700', 130 | 'aircrafttype' => 'A320', 131 | 'eta' => '1473397800', 132 | 'ident' => 'CEB326', 133 | 'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9', 134 | 'pitr' => '1473380220', 135 | 'speed' => '165', 136 | 'orig' => 'RPLP', 137 | 'edt' => '1473395100', 138 | 'id' => 'CEB326-1473221700-schedule-0000' 139 | }; 140 | LINE 7 141 | $VAR1 = { 142 | 'pitr' => '1473380220', 143 | 'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9', 144 | 'ident' => 'ICE440', 145 | 'edt' => '1473408600', 146 | 'id' => 'ICE440-1473235200-schedule-0000', 147 | 'speed' => '346', 148 | 'orig' => 'BIKF', 149 | 'dest' => 'EGCC', 150 | 'facility_name' => 'Airline', 151 | 'status' => 'S', 152 | 'type' => 'flightplan', 153 | 'fdt' => '1473408000', 154 | 'aircrafttype' => 'B752', 155 | 'eta' => '1473416700', 156 | 'ete' => '8100' 157 | }; 158 | LINE 8 159 | $VAR1 = { 160 | 'type' => 'flightplan', 161 | 'fdt' => '1473451500', 162 | 'status' => 'S', 163 | 'facility_name' => 'Airline', 164 | 'dest' => 'EGCC', 165 | 'ete' => '8400', 166 | 'eta' => '1473460500', 167 | 'aircrafttype' => 'B738', 168 | 'ident' => 'RYR7545', 169 | 'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9', 170 | 'pitr' => '1473380220', 171 | 'speed' => '320', 172 | 'orig' => 'LEBL', 173 | 'id' => 'RYR7545-1473226211-airline-0350', 174 | 'edt' => '1473452100' 175 | }; 176 | LINE 9 177 | $VAR1 = { 178 | 'reg' => 'N132EV', 179 | 'eta' => '1473383940', 180 | 'ete' => '3900', 181 | 'dest' => 'KDTW', 182 | 'facility_name' => 'Airline', 183 | 'waypoints' => [ 184 | { 185 | 'lat' => '40', 186 | 'lon' => '-82.89' 187 | }, 188 | { 189 | 'lon' => '-82.86', 190 | 'lat' => '40.05' 191 | }, 192 | { 193 | 'lat' => '40.11', 194 | 'lon' => '-82.81' 195 | }, 196 | { 197 | 'lat' => '42.1', 198 | 'lon' => '-83.23' 199 | }, 200 | { 201 | 'lat' => '42.11', 202 | 'lon' => '-83.25' 203 | }, 204 | { 205 | 'lat' => '42.17', 206 | 'lon' => '-83.31' 207 | }, 208 | { 209 | 'lon' => '-83.35', 210 | 'lat' => '42.21' 211 | } 212 | ], 213 | 'edt' => '1473380040', 214 | 'orig' => 'KCMH', 215 | 'speed' => '431', 216 | 'route' => 'KCMH..GIVES..DJB.GEMNI4.KDTW/0032', 217 | 'pitr' => '1473380220', 218 | 'ident' => 'ASQ5180', 219 | 'aircrafttype' => 'CRJ9', 220 | 'alt' => '25000', 221 | 'status' => 'F', 222 | 'fdt' => '1473379020', 223 | 'type' => 'flightplan', 224 | 'id' => 'ASQ5180-1473139757-airline-0499', 225 | 'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9' 226 | }; 227 | LINE 10 228 | $VAR1 = { 229 | 'ident' => 'RYR4051', 230 | 'facility_hash' => 'fb69318716f52e9c266ef4ad76ceffb6b42c9ce9', 231 | 'pitr' => '1473380220', 232 | 'orig' => 'LPFR', 233 | 'speed' => '379', 234 | 'id' => 'RYR4051-1473226208-airline-0472', 235 | 'edt' => '1473437700', 236 | 'fdt' => '1473437100', 237 | 'type' => 'flightplan', 238 | 'status' => 'S', 239 | 'facility_name' => 'Airline', 240 | 'dest' => 'EGCC', 241 | 'ete' => '9600', 242 | 'aircrafttype' => 'B738', 243 | 'eta' => '1473447300' 244 | }; 245 | All done. 246 | -------------------------------------------------------------------------------- /php/example1/README.md: -------------------------------------------------------------------------------- 1 | Requirements 2 | ------------ 3 | 4 | * PHP 5 5 | 6 | You can download PHP from https://www.php.net/. You may need to also install the PHP extensionis that are referenced. 7 | 8 | On FreeBSD systems, you can use the following installation command: 9 | pkg install php56 php56-openssl php56-zlib php56-json 10 | 11 | If you are going to use this for live, low volume compression, please use example2 instead. This example is good for all other situations 12 | 13 | What to change 14 | -------------- 15 | 16 | Substitute your actual username and API key in the variables at the top of the program. 17 | 18 | Change/remove count on the number of messages received. 19 | 20 | 21 | 22 | Run commands 23 | ------------ 24 | 25 | php example1.php 26 | 27 | -------------------------------------------------------------------------------- /php/example1/example1.php: -------------------------------------------------------------------------------- 1 | = 10) { 52 | break; 53 | } 54 | } 55 | fclose($fp); 56 | echo "All done.\n"; 57 | 58 | ?> 59 | -------------------------------------------------------------------------------- /php/example2/README.md: -------------------------------------------------------------------------------- 1 | Requirements 2 | ------------ 3 | 4 | * PHP 5 5 | 6 | You can download PHP from https://www.php.net/. You may need to also install the PHP extensionis that are referenced. 7 | 8 | On FreeBSD systems, you can use the following installation command: 9 | pkg install php56 php56-openssl php56-zlib php56-json 10 | 11 | This example is better for live, low volume compression. Please use example1 if you are using this for anything other than that. 12 | 13 | What to change 14 | -------------- 15 | 16 | Substitute your actual username and API key in the variables at the top of the program. 17 | 18 | Change/remove count on the number of messages received. 19 | 20 | 21 | 22 | Run commands 23 | ------------ 24 | 25 | php example1.php 26 | 27 | -------------------------------------------------------------------------------- /php/example2/example2.php: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/php 2 | sock = $sock; 19 | if (!stream_filter_append($this->sock, 'zlib.inflate', STREAM_FILTER_READ)) { 20 | echo "Error appending filter.\n"; 21 | exit(1); 22 | } 23 | 24 | stream_set_blocking($this->sock, 0); 25 | } 26 | 27 | public function readline() { 28 | $newline = strpos($this->buffer, "\n"); 29 | while (($newline == false)) { 30 | $socket_stream = fgets($this->sock); 31 | 32 | if($socket_stream !== false) { 33 | $this->buffer .= $socket_stream; 34 | $newline = strpos($this->buffer, "\n"); 35 | } 36 | } 37 | 38 | $rawline = substr($this->buffer, 0, $newline + 1); 39 | $this->buffer = substr($this->buffer, $newline + 1); 40 | return $rawline; 41 | } 42 | } 43 | 44 | // Open the TLS socket connection to FlightAware. 45 | $fp = fsockopen("tcp://firehose.flightaware.com", 1501, $errno, $errstr, 30); 46 | if (!$fp) { 47 | echo "Error connecting ($errno): $errstr\n"; 48 | exit(1); 49 | } 50 | if (!stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT)) { 51 | echo "Error negotiating TLS\n"; 52 | fclose($fp); 53 | exit(1); 54 | } 55 | echo "Connected!\n"; 56 | 57 | // Send the initiation command to the uncompressed socket. 58 | $initcmd = "live version 7.0 user $username password $apikey events \"flifo position\""; 59 | if ($compression) { 60 | $initcmd .= " compression deflate"; 61 | } 62 | fwrite($fp, "$initcmd\n"); 63 | 64 | // Apply a decompression filter, if requested. 65 | if ($compression) { 66 | $inflate = new InflateStream($fp); 67 | } 68 | 69 | 70 | 71 | // Main loop, reading lines of JSON from the server. 72 | $i = 1; 73 | 74 | while ($i < 10000) { 75 | 76 | if ($compression) { 77 | $buffer = $inflate->readline(); 78 | } else { 79 | $buffer = fgets($fp); 80 | } 81 | 82 | if ($buffer == false) { 83 | break; 84 | } 85 | 86 | echo "LINE $i\n"; 87 | 88 | $data = json_decode($buffer); 89 | echo $buffer; 90 | if (json_last_error() !== JSON_ERROR_NONE) { 91 | echo "Error: invalid json.\n"; 92 | echo $buffer; 93 | break; 94 | } 95 | 96 | $i += 1; 97 | } 98 | fclose($fp); 99 | echo "All done.\n"; 100 | 101 | ?> 102 | -------------------------------------------------------------------------------- /python/example1/README.md: -------------------------------------------------------------------------------- 1 | Requirements 2 | ------------ 3 | 4 | * Python 3 5 | 6 | You can download python from https://www.python.org/downloads/. Please note that older versions of Python 2 are no longer recommended for use. 7 | 8 | 9 | What to change 10 | -------------- 11 | Substitute your actual username and API key in the variables at the top of the program. 12 | 13 | Change/remove count on the number of messages received. 14 | 15 | Conversely, there are several IDEs for Python such as PyCharm that may make development and testing easier. 16 | 17 | 18 | Running the example 19 | ------------------- 20 | 21 | Run commands: 22 | 23 | python3 example1.py 24 | 25 | -------------------------------------------------------------------------------- /python/example1/example1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import json, socket, ssl, sys, time, zlib 4 | 5 | 6 | username = "XXXXXXXXXX" 7 | apikey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" 8 | compression = None # set to "deflate", "decompress", or "gzip" to enable compression 9 | servername = "firehose.flightaware.com" 10 | 11 | 12 | class InflateStream: 13 | "A wrapper for a socket carrying compressed data that does streaming decompression" 14 | 15 | def __init__(self, sock, mode): 16 | self.sock = sock 17 | self._buf = bytearray() 18 | self._eof = False 19 | if mode == 'deflate': # no header, raw deflate stream 20 | self._z = zlib.decompressobj(-zlib.MAX_WBITS) 21 | elif mode == 'compress': # zlib header 22 | self._z = zlib.decompressobj(zlib.MAX_WBITS) 23 | elif mode == 'gzip': # gzip header 24 | self._z = zlib.decompressobj(16 | zlib.MAX_WBITS) 25 | else: 26 | raise ValueError('unrecognized compression mode') 27 | 28 | def _fill(self): 29 | rawdata = self.sock.recv(8192) 30 | if len(rawdata) == 0: 31 | self._buf += self._z.flush() 32 | self._eof = True 33 | else: 34 | self._buf += self._z.decompress(rawdata) 35 | 36 | def readline(self): 37 | newline = self._buf.find(b'\n') 38 | while newline < 0 and not self._eof: 39 | self._fill() 40 | newline = self._buf.find(b'\n') 41 | 42 | if newline >= 0: 43 | rawline = self._buf[:newline+1] 44 | del self._buf[:newline+1] 45 | return rawline.decode('ascii') 46 | 47 | # EOF 48 | return '' 49 | 50 | 51 | # function to parse JSON data: 52 | def parse_json( str ): 53 | try: 54 | # parse all data into dictionary decoded: 55 | decoded = json.loads(str) 56 | print(decoded) 57 | 58 | # compute the latency of this message: 59 | clocknow = time.time() 60 | diff = clocknow - int(decoded['pitr']) 61 | print("diff = {0:.2f} s\n".format(diff)) 62 | except (ValueError, KeyError, TypeError): 63 | print("JSON format error: ", sys.exc_info()[0]) 64 | print(str) 65 | #print(traceback.format_exc()) 66 | return; 67 | 68 | # Create socket 69 | sock = socket.socket(socket.AF_INET) 70 | # Create a SSL context with the recommended security settings for client sockets, including automatic certificate verification 71 | context = ssl.create_default_context() 72 | # the folowing line requires Python 3.7+ and OpenSSL 1.1.0g+ to specify minimum_version 73 | context.minimum_version = ssl.TLSVersion.TLSv1_2 74 | 75 | ssl_sock = context.wrap_socket(sock, server_hostname = servername) 76 | print("Connecting...") 77 | ssl_sock.connect((servername, 1501)) 78 | print("Connection succeeded") 79 | 80 | # build the initiation command: 81 | initiation_command = "live username {} password {}".format(username, apikey) 82 | if compression is not None: 83 | initiation_command += " compression " + compression 84 | 85 | # send initialization command to server: 86 | initiation_command += "\n" 87 | if sys.version_info[0] >= 3: 88 | ssl_sock.write(bytes(initiation_command, 'UTF-8')) 89 | else: 90 | ssl_sock.write(initiation_command) 91 | 92 | # return a file object associated with the socket 93 | if compression is not None: 94 | file = InflateStream(sock = ssl_sock, mode = compression) 95 | else: 96 | file = ssl_sock.makefile('r') 97 | 98 | # use "while True" for no limit in messages received 99 | count = 10 100 | while (count > 0): 101 | try : 102 | # read line from file: 103 | inline = file.readline() 104 | if inline == '': 105 | # EOF 106 | break 107 | 108 | # print(inline) 109 | 110 | # parse the line 111 | parse_json(inline) 112 | count = count - 1 113 | except socket.error as e: 114 | print('Connection fail', e) 115 | print(traceback.format_exc()) 116 | 117 | # wait for user input to end 118 | # input("\n Press Enter to exit..."); 119 | # close the SSLSocket, will also close the underlying socket 120 | ssl_sock.close() 121 | 122 | -------------------------------------------------------------------------------- /python/example1/output.txt: -------------------------------------------------------------------------------- 1 | Connecting... 2 | Connection succeeded 3 | {u'synthetic': u'1', u'adt': u'1527787251', u'ident': u'BLOCKED', u'facility_name': u'FlightAware ADS-B', u'pitr': u'1527787259', u'reg': u'BLOCKED', u'facility_hash': u'5F108B0455C84B6A', u'aircrafttype': u'P28A', u'type': u'departure', u'id': u'BLOCKED-1527787251-adhoc-0', u'orig': u'KFXE'} 4 | diff = 5.03 s 5 | 6 | {u'status': u'A', u'ident': u'BLOCKED', u'aircrafttype': u'P28A', u'speed': u'0', u'facility_name': u'FlightAware ADS-B', u'pitr': u'1527787259', u'reg': u'BLOCKED', u'facility_hash': u'5F108B0455C84B6A', u'fdt': u'1527787251', u'edt': u'1527787251', u'type': u'flightplan', u'id': u'BLOCKED-1527787251-adhoc-0', u'orig': u'KFXE'} 7 | diff = 5.03 s 8 | 9 | {u'status': u'A', u'ident': u'BLOCKED', u'aircrafttype': u'P28A', u'speed': u'0', u'facility_name': u'FlightAware Estimated', u'pitr': u'1527787259', u'hexid': u'BLOCKED', u'reg': u'BLOCKED', u'facility_hash': u'202769E5419AED2', u'fdt': u'1527787251', u'edt': u'1527787251', u'type': u'flightplan', u'id': u'BLOCKED-1527787251-adhoc-0', u'orig': u'KFXE'} 10 | diff = 5.03 s 11 | 12 | {u'reg': u'BLOCKED', u'lon': u'-80.15525', u'ident': u'BLOCKED', u'gs': u'110', u'clock': u'1527787251', u'altChange': u' ', u'facility_name': u'FlightAware ADS-B', u'pitr': u'1527787259', u'air_ground': u'A', u'hexid': u'BLOCKED', u'heading': u'322', u'facility_hash': u'5F108B0455C84B6A', u'aircrafttype': u'P28A', u'updateType': u'A', u'lat': u'26.21999', u'alt': u'825', u'type': u'position', u'id': u'BLOCKED-1527787251-adhoc-0'} 13 | diff = 5.03 s 14 | 15 | {u'reg': u'HSLTS', u'lon': u'101.30915', u'ident': u'TLM929', u'gs': u'479', u'clock': u'1527787251', u'altChange': u' ', u'facility_name': u'FlightAware ADS-B', u'pitr': u'1527787259', u'air_ground': u'A', u'hexid': u'883293', u'heading': u'207', u'facility_hash': u'4AF6A75430228056', u'squawk': u'5070', u'updateType': u'A', u'lat': u'15.73000', u'alt': u'34000', u'type': u'position', u'id': u'TLM929-1527571549-airline-0440'} 16 | diff = 5.03 s 17 | 18 | {u'lon': u'-92.98694', u'ident': u'N944TT', u'gs': u'125', u'clock': u'1527787242', u'dest': u'KADS', u'altChange': u' ', u'facility_name': u'Houston Center', u'pitr': u'1527787259', u'air_ground': u'A', u'heading': u'278', u'facility_hash': u'6CD7605BCF54E38C', u'updateType': u'Z', u'lat': u'30.96806', u'alt': u'10000', u'type': u'position', u'id': u'N944TT-1527777676-3-0-9', u'orig': u'KNEW'} 19 | diff = 5.03 s 20 | 21 | {u'reg': u'N987HP', u'lon': u'-118.49237', u'ident': u'N987HP', u'gs': u'122', u'clock': u'1527787252', u'altChange': u' ', u'facility_name': u'FlightAware ADS-B', u'pitr': u'1527787259', u'air_ground': u'A', u'hexid': u'ADC5E2', u'heading': u'177', u'facility_hash': u'81C113504F8CAC1A', u'aircrafttype': u'CL30', u'updateType': u'A', u'lat': u'34.23221', u'alt': u'1225', u'type': u'position', u'id': u'N987HP-1527735771-dlad-5743947'} 22 | diff = 5.03 s 23 | 24 | {u'status': u'A', u'speed': u'445', u'ident': u'HGT3572', u'edt': u'1527785040', u'dest': u'KSJC', u'route': u'KHIO.BERNI3.FAMUK.Q3.FOWND..CHBLI.BRIXX2.KSJC/1829', u'facility_name': u'Oakland Center', u'pitr': u'1527787259', u'hexid': u'A471AC', u'reg': u'N386AZ', u'eta': u'1527789942', u'fdt': u'1527785100', u'aircrafttype': u'E45X', u'ete': u'4902', u'waypoints': [{u'lat': 45.54, u'lon': -122.95}, {u'lat': 45.45, u'lon': -122.98}, {u'lat': 45.42, u'lon': -122.99}, {u'lat': 45.42, u'lon': -122.99}, {u'lat': 45.4, u'lon': -123.0}, {u'lat': 45.37, u'lon': -123.01}, {u'lat': 45.33, u'lon': -123.02}, {u'lat': 45.31, u'lon': -123.04}, {u'lat': 45.29, u'lon': -123.06}, {u'lat': 45.2, u'lon': -123.14}, {u'lat': 45.17, u'lon': -123.17}, {u'lat': 45.12, u'lon': -123.21}, {u'lat': 45.01, u'lon': -123.19}, {u'lat': 44.9, u'lon': -123.18}, {u'lat': 44.79, u'lon': -123.17}, {u'lat': 44.74, u'lon': -123.16}, {u'lat': 44.54, u'lon': -123.14}, {u'lat': 44.5, u'lon': -123.14}, {u'lat': 44.35, u'lon': -123.13}, {u'lat': 44.2, u'lon': -123.12}, {u'lat': 44.15, u'lon': -123.12}, {u'lat': 44.12, u'lon': -123.12}, {u'lat': 43.88, u'lon': -123.11}, {u'lat': 43.8, u'lon': -123.11}, {u'lat': 43.64, u'lon': -123.11}, {u'lat': 43.5, u'lon': -123.1}, {u'lat': 43.45, u'lon': -123.1}, {u'lat': 42.48, u'lon': -123.07}, {u'lat': 42.31, u'lon': -123.06}, {u'lat': 41.34, u'lon': -123.03}, {u'lat': 41.33, u'lon': -123.03}, {u'lat': 39.1, u'lon': -122.96}, {u'lat': 39.04, u'lon': -122.92}, {u'lat': 38.84, u'lon': -122.76}, {u'lat': 38.77, u'lon': -122.7}, {u'lat': 38.59, u'lon': -122.56}, {u'lat': 38.56, u'lon': -122.54}, {u'lat': 38.49, u'lon': -122.54}, {u'lat': 38.43, u'lon': -122.53}, {u'lat': 38.19, u'lon': -122.53}, {u'lat': 38.17, u'lon': -122.53}, {u'lat': 38.13, u'lon': -122.52}, {u'lat': 38.06, u'lon': -122.52}, {u'lat': 37.94, u'lon': -122.51}, {u'lat': 37.93, u'lon': -122.51}, {u'lat': 37.84, u'lon': -122.51}, {u'lat': 37.73, u'lon': -122.5}, {u'lat': 37.7, u'lon': -122.46}, {u'lat': 37.69, u'lon': -122.45}, {u'lat': 37.62, u'lon': -122.37}, {u'lat': 37.61, u'lon': -122.37}, {u'lat': 37.6, u'lon': -122.37}, {u'lat': 37.55, u'lon': -122.34}, {u'lat': 37.49, u'lon': -122.31}, {u'lat': 37.48, u'lon': -122.3}, {u'lat': 37.46, u'lon': -122.29}, {u'lat': 37.39, u'lon': -122.26}, {u'lat': 37.35, u'lon': -122.24}, {u'lat': 37.29, u'lon': -122.2}, {u'lat': 37.25, u'lon': -122.15}, {u'lat': 37.25, u'lon': -122.15}, {u'lat': 37.23, u'lon': -122.11}, {u'lat': 37.21, u'lon': -122.05}, {u'lat': 37.2, u'lon': -122.02}, {u'lat': 37.21, u'lon': -122.02}, {u'lat': 37.29, u'lon': -121.97}, {u'lat': 37.36, u'lon': -121.93}, {u'lat': 37.36, u'lon': -121.93}], u'alt': u'33000', u'type': u'flightplan', u'id': u'HGT3572-1527774326-1-5-122', u'facility_hash': u'844BE52BA37B3ADD', u'orig': u'KHIO'} 25 | diff = 5.03 s 26 | 27 | {u'reg': u'FHBAP', u'lon': u'3.23969', u'ident': u'AAF707', u'gs': u'435', u'clock': u'1527787253', u'altChange': u' ', u'facility_name': u'FlightAware ADS-B', u'pitr': u'1527787259', u'air_ground': u'A', u'hexid': u'39840F', u'heading': u'190', u'facility_hash': u'D9BA883A5213DBFD', u'squawk': u'4050', u'updateType': u'A', u'lat': u'38.74957', u'alt': u'39050', u'type': u'position', u'id': u'AAF707-1527571553-airline-0496'} 28 | diff = 5.03 s 29 | 30 | {u'status': u'S', u'speed': u'455', u'ident': u'AAL2448', u'edt': u'1527864540', u'dest': u'KJFK', u'route': u'KSAN.ZZOOO2.IPL.J18.SJN..KA33U..KA36W..KA39Y..KK42A..KK45C..KK48E..BUM..KK54K..KI57O..ROD..DJB..JHW.J70.LVZ.LENDY6.KJFK', u'facility_name': u'', u'pitr': u'1527787259', u'waypoints': [{u'lat': 32.73, u'lon': -117.19}, {u'lat': 32.75, u'lon': -117.28}, {u'lat': 32.73, u'lon': -117.27}, {u'lat': 32.68, u'lon': -117.26}, {u'lat': 32.66, u'lon': -117.25}, {u'lat': 32.64, u'lon': -117.25}, {u'lat': 32.63, u'lon': -117.25}, {u'lat': 32.63, u'lon': -117.22}, {u'lat': 32.63, u'lon': -117.19}, {u'lat': 32.61, u'lon': -116.99}, {u'lat': 32.6, u'lon': -116.92}, {u'lat': 32.63, u'lon': -116.8}, {u'lat': 32.63, u'lon': -116.8}, {u'lat': 32.63, u'lon': -116.77}, {u'lat': 32.63, u'lon': -116.76}, {u'lat': 32.63, u'lon': -116.76}, {u'lat': 32.64, u'lon': -116.72}, {u'lat': 32.64, u'lon': -116.65}, {u'lat': 32.65, u'lon': -116.58}, {u'lat': 32.65, u'lon': -116.55}, {u'lat': 32.66, u'lon': -116.51}, {u'lat': 32.67, u'lon': -116.41}, {u'lat': 32.68, u'lon': -116.26}, {u'lat': 32.69, u'lon': -116.18}, {u'lat': 32.7, u'lon': -116.03}, {u'lat': 32.71, u'lon': -115.94}, {u'lat': 32.72, u'lon': -115.85}, {u'lat': 32.73, u'lon': -115.71}, {u'lat': 32.73, u'lon': -115.67}, {u'lat': 32.75, u'lon': -115.51}, {u'lat': 32.75, u'lon': -115.27}, {u'lat': 32.77, u'lon': -114.6}, {u'lat': 32.77, u'lon': -114.07}, {u'lat': 32.78, u'lon': -114.0}, {u'lat': 32.78, u'lon': -113.97}, {u'lat': 32.82, u'lon': -113.69}, {u'lat': 32.96, u'lon': -112.67}, {u'lat': 33.43, u'lon': -111.97}, {u'lat': 33.54, u'lon': -111.67}, {u'lat': 33.69, u'lon': -111.27}, {u'lat': 33.84, u'lon': -110.84}, {u'lat': 34.01, u'lon': -110.35}, {u'lat': 34.26, u'lon': -109.63}, {u'lat': 34.35, u'lon': -109.37}, {u'lat': 34.42, u'lon': -109.14}, {u'lat': 34.78, u'lon': -108.15}, {u'lat': 35.12, u'lon': -107.14}, {u'lat': 35.29, u'lon': -106.63}, {u'lat': 35.5, u'lon': -106.0}, {u'lat': 35.64, u'lon': -105.44}, {u'lat': 36.0, u'lon': -104.0}, {u'lat': 36.02, u'lon': -103.92}, {u'lat': 36.08, u'lon': -103.68}, {u'lat': 36.5, u'lon': -102.0}, {u'lat': 36.55, u'lon': -101.79}, {u'lat': 36.84, u'lon': -100.67}, {u'lat': 37.0, u'lon': -100.0}, {u'lat': 37.02, u'lon': -99.94}, {u'lat': 37.5, u'lon': -98.0}, {u'lat': 37.56, u'lon': -97.78}, {u'lat': 38.0, u'lon': -96.0}, {u'lat': 38.25, u'lon': -94.59}, {u'lat': 38.27, u'lon': -94.49}, {u'lat': 38.41, u'lon': -93.7}, {u'lat': 38.81, u'lon': -91.32}, {u'lat': 39.0, u'lon': -90.0}, {u'lat': 39.02, u'lon': -89.85}, {u'lat': 39.12, u'lon': -89.11}, {u'lat': 39.16, u'lon': -88.86}, {u'lat': 39.25, u'lon': -88.12}, {u'lat': 39.41, u'lon': -86.81}, {u'lat': 39.5, u'lon': -86.0}, {u'lat': 39.79, u'lon': -85.3}, {u'lat': 40.29, u'lon': -84.04}, {u'lat': 40.68, u'lon': -83.37}, {u'lat': 41.36, u'lon': -82.16}, {u'lat': 41.7, u'lon': -80.95}, {u'lat': 42.19, u'lon': -79.12}, {u'lat': 41.87, u'lon': -77.85}, {u'lat': 41.79, u'lon': -77.55}, {u'lat': 41.77, u'lon': -77.49}, {u'lat': 41.68, u'lon': -77.15}, {u'lat': 41.55, u'lon': -76.67}, {u'lat': 41.53, u'lon': -76.6}, {u'lat': 41.39, u'lon': -76.11}, {u'lat': 41.36, u'lon': -76.01}, {u'lat': 41.31, u'lon': -75.83}, {u'lat': 41.31, u'lon': -75.82}, {u'lat': 41.27, u'lon': -75.69}, {u'lat': 41.26, u'lon': -75.64}, {u'lat': 41.21, u'lon': -75.51}, {u'lat': 41.19, u'lon': -75.44}, {u'lat': 41.15, u'lon': -75.33}, {u'lat': 41.14, u'lon': -75.29}, {u'lat': 41.1, u'lon': -75.17}, {u'lat': 41.08, u'lon': -75.12}, {u'lat': 41.07, u'lon': -75.09}, {u'lat': 41.06, u'lon': -75.05}, {u'lat': 41.03, u'lon': -74.97}, {u'lat': 41.02, u'lon': -74.93}, {u'lat': 41.01, u'lon': -74.92}, {u'lat': 41.0, u'lon': -74.9}, {u'lat': 41.0, u'lon': -74.87}, {u'lat': 41.0, u'lon': -74.86}, {u'lat': 40.99, u'lon': -74.84}, {u'lat': 40.99, u'lon': -74.77}, {u'lat': 40.98, u'lon': -74.73}, {u'lat': 40.97, u'lon': -74.67}, {u'lat': 40.97, u'lon': -74.66}, {u'lat': 40.95, u'lon': -74.44}, {u'lat': 40.94, u'lon': -74.35}, {u'lat': 40.93, u'lon': -74.23}, {u'lat': 40.92, u'lon': -74.16}, {u'lat': 40.91, u'lon': -74.14}, {u'lat': 40.91, u'lon': -74.12}, {u'lat': 40.86, u'lon': -74.02}, {u'lat': 40.83, u'lon': -73.97}, {u'lat': 40.81, u'lon': -73.92}, {u'lat': 40.8, u'lon': -73.91}, {u'lat': 40.79, u'lon': -73.88}, {u'lat': 40.78, u'lon': -73.87}, {u'lat': 40.71, u'lon': -73.83}, {u'lat': 40.71, u'lon': -73.82}, {u'lat': 40.64, u'lon': -73.78}], u'reg': u'N955AN', u'eta': u'1527881306', u'fdt': u'1527864900', u'aircrafttype': u'B738', u'ete': u'16766', u'alt': u'35000', u'type': u'flightplan', u'id': u'AAL2448-1527657976-airline-0584', u'facility_hash': u'81E755935A704D47', u'orig': u'KSAN'} 31 | diff = 5.03 s 32 | 33 | -------------------------------------------------------------------------------- /tcl/example1/README.md: -------------------------------------------------------------------------------- 1 | Requirements 2 | ------------ 3 | 4 | * Tcl 8.6 5 | * yajl-tcl package 6 | * tclTLS package 7 | 8 | You can download Tcl from https://www.tcl.tk/. You may need to also install the Tcl packagees that are referenced. 9 | The yajl-tcl package can be downloaded from https://github.com/flightaware/yajl-tcl/releases 10 | The tcltls package can be downloaded from https://core.tcl.tk/tcltls/wiki/Download 11 | 12 | On FreeBSD systems, you can use the command: 13 | pkg install tcl86 yajl-tcl tcltls 14 | 15 | 16 | What to change 17 | -------------- 18 | 19 | Substitute your actual username and API key in the variables at the top of the program. 20 | 21 | Change/remove count on the number of messages received. 22 | 23 | 24 | Run commands 25 | ------------ 26 | 27 | tclsh example1.tcl 28 | -------------------------------------------------------------------------------- /tcl/example1/example1.tcl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tclsh 2 | 3 | package require tls 4 | package require yajltcl 5 | package require zlib 6 | 7 | set username "XXXXXXXXXXXXXXXXX" 8 | set apikey "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" 9 | 10 | set hostname "firehose.flightaware.com" 11 | set compression 0 12 | 13 | 14 | 15 | # Open the TLS socket connection to FlightAware. 16 | set sock [tls::socket -ssl2 0 -ssl3 0 -tls1 0 -tls1.1 0 -tls1.2 1 $hostname 1501] 17 | puts "Connected!" 18 | 19 | # Send the initiation command to the server. 20 | set initcmd "live version 7.0 user $username password $apikey events {flifo position}" 21 | if {$compression} { 22 | append initcmd " compression deflate" 23 | } 24 | 25 | puts $sock "$initcmd" 26 | flush $sock 27 | 28 | # Activate compression, if requested. 29 | if {$compression} { 30 | zlib push inflate $sock 31 | } 32 | 33 | # Main loop, reading lines of JSON from the server. 34 | set linecount 1 35 | while {$linecount < 10000} { 36 | if {[catch {set getResult [gets $sock line]} catchResult] == 1} { 37 | puts "Failed to get line from socket: $catchResult" 38 | break 39 | } elseif {$getResult < 0} { 40 | puts "Reached end of socket." 41 | break 42 | } 43 | 44 | puts "Line #$linecount" 45 | array unset data 46 | if {[catch { 47 | array set data [::yajl::json2dict $line] 48 | } catchResult] == 1} { 49 | puts "Failed to parse message: $line" 50 | break 51 | } 52 | parray data 53 | puts "========" 54 | 55 | incr linecount 56 | } 57 | close $sock 58 | 59 | puts "" 60 | --------------------------------------------------------------------------------