From 54b0fab72106672ea1d9ca4d81d782b6bf1c6820 Mon Sep 17 00:00:00 2001 From: Ben Burwell Date: Tue, 15 Nov 2016 23:43:08 -0500 Subject: Implement data table --- src/com/benburwell/planes/data/Aircraft.java | 66 +++++++++++ src/com/benburwell/planes/data/Position.java | 46 ++++++++ .../benburwell/planes/gui/AircraftTableModel.java | 65 +++++++++++ src/com/benburwell/planes/gui/Main1090.java | 61 +++++++++-- .../benburwell/planes/sbs/AggregateDataSource.java | 31 +++++- src/com/benburwell/planes/sbs/DataSource.java | 2 + src/com/benburwell/planes/sbs/SBSPacket.java | 122 +++++++++++++++++---- src/com/benburwell/planes/sbs/TCPDataSource.java | 63 +++++++++-- 8 files changed, 413 insertions(+), 43 deletions(-) create mode 100644 src/com/benburwell/planes/data/Aircraft.java create mode 100644 src/com/benburwell/planes/data/Position.java create mode 100644 src/com/benburwell/planes/gui/AircraftTableModel.java diff --git a/src/com/benburwell/planes/data/Aircraft.java b/src/com/benburwell/planes/data/Aircraft.java new file mode 100644 index 0000000..71ee5b5 --- /dev/null +++ b/src/com/benburwell/planes/data/Aircraft.java @@ -0,0 +1,66 @@ +package com.benburwell.planes.data; + +import com.benburwell.planes.sbs.SBSPacket; + +import java.util.List; +import java.util.ArrayList; + +/** + * Created by ben on 11/15/16. + */ +public class Aircraft implements Comparable { + private final String hexIdent; + private Position currentPosition = new Position(); + private List positionHistory = new ArrayList<>(); + private String callsign = ""; + private String squawk = ""; + private long packetCount = 0; + + public Aircraft(String hexIdent) { + this.hexIdent = hexIdent; + } + + public void handleUpdate(SBSPacket packet) { + this.packetCount++; + if (packet.getAltitude() != null) { + this.currentPosition.setAltitude(packet.getAltitude()); + } + if (packet.getLatitude() != null) { + this.currentPosition.setLatitude(packet.getLatitude()); + } + if (packet.getLongitude() != null) { + this.currentPosition.setLongitude(packet.getLongitude()); + } + if (packet.getCallsign() != null && !packet.getCallsign().isEmpty()) { + this.callsign = packet.getCallsign(); + } + if (packet.getSquawk() != null && !packet.getSquawk().isEmpty()) { + this.callsign = packet.getSquawk(); + } + } + + public Position getCurrentPosition() { + return currentPosition; + } + + public String getCallsign() { + return callsign; + } + + public String getSquawk() { + return squawk; + } + + public Long getPacketCount() { + return packetCount; + } + + public String getHexIdent() { + return this.hexIdent; + } + + @Override + public int compareTo(Aircraft that) { + return this.getHexIdent().compareTo(that.getHexIdent()); + } +} diff --git a/src/com/benburwell/planes/data/Position.java b/src/com/benburwell/planes/data/Position.java new file mode 100644 index 0000000..4b37235 --- /dev/null +++ b/src/com/benburwell/planes/data/Position.java @@ -0,0 +1,46 @@ +package com.benburwell.planes.data; + +import java.util.Date; + +/** + * Created by ben on 11/15/16. + */ +public class Position { + private Date timestamp = new Date(System.currentTimeMillis()); + private Double latitude = 0.0; + private Double longitude = 0.0; + + public Date getTimestamp() { + return timestamp; + } + + public void setTimestamp(Date timestamp) { + this.timestamp = timestamp; + } + + public double getLatitude() { + return latitude; + } + + public void setLatitude(double latitude) { + this.latitude = latitude; + } + + public double getLongitude() { + return longitude; + } + + public void setLongitude(double longitude) { + this.longitude = longitude; + } + + public double getAltitude() { + return altitude; + } + + public void setAltitude(double altitude) { + this.altitude = altitude; + } + + private double altitude = 0; +} diff --git a/src/com/benburwell/planes/gui/AircraftTableModel.java b/src/com/benburwell/planes/gui/AircraftTableModel.java new file mode 100644 index 0000000..72be372 --- /dev/null +++ b/src/com/benburwell/planes/gui/AircraftTableModel.java @@ -0,0 +1,65 @@ +package com.benburwell.planes.gui; + +import com.benburwell.planes.data.Aircraft; + +import javax.swing.table.AbstractTableModel; +import java.util.Map; +import java.util.List; +import java.util.ArrayList; +import java.util.Collections; + +/** + * Created by ben on 11/15/16. + */ +public class AircraftTableModel extends AbstractTableModel { + private Map aircraftMap; + private String[] columnNames = { "Hex", "Callsign", "Squawk", "Latitude", "Longitude", "Altitude", "Packets" }; + + public AircraftTableModel(Map aircraftMap) { + this.aircraftMap = aircraftMap; + } + + @Override + public int getRowCount() { + return this.aircraftMap.keySet().size(); + } + + @Override + public int getColumnCount() { + return this.columnNames.length; + } + + @Override + public String getColumnName(int col) { + return this.columnNames[col]; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + List aircraftList = this.getAircraftList(); + Aircraft aircraft = aircraftList.get(rowIndex); + switch (columnIndex) { + case 0: + return aircraft.getHexIdent(); + case 1: + return aircraft.getCallsign(); + case 2: + return aircraft.getSquawk(); + case 3: + return aircraft.getCurrentPosition().getLatitude(); + case 4: + return aircraft.getCurrentPosition().getLongitude(); + case 5: + return aircraft.getCurrentPosition().getAltitude(); + case 6: + return aircraft.getPacketCount(); + } + return ""; + } + + private List getAircraftList() { + List aircraftList = new ArrayList<>(this.aircraftMap.values()); + Collections.sort(aircraftList); + return aircraftList; + } +} diff --git a/src/com/benburwell/planes/gui/Main1090.java b/src/com/benburwell/planes/gui/Main1090.java index 5393dc0..02ef2bf 100644 --- a/src/com/benburwell/planes/gui/Main1090.java +++ b/src/com/benburwell/planes/gui/Main1090.java @@ -5,14 +5,19 @@ package com.benburwell.planes.gui; import com.benburwell.planes.sbs.*; +import com.benburwell.planes.data.*; import java.awt.*; import javax.swing.*; import java.awt.event.ActionEvent; -import java.awt.event.KeyEvent; +import java.util.Map; +import java.util.HashMap; public class Main1090 extends JFrame { private AggregateDataSource sbsDataSource = new AggregateDataSource(); + private Map aircraftMap = new HashMap<>(); + private int currentTcpConnection = 0; + private AircraftTableModel aircraftTableModel = new AircraftTableModel(this.aircraftMap); public Main1090() { this.initUI(); @@ -21,6 +26,8 @@ public class Main1090 extends JFrame { private void initUI() { this.createMenuBar(); + this.createTable(); + this.setTitle("1090"); this.setSize(100, 100); this.setLocationRelativeTo(null); @@ -29,27 +36,67 @@ public class Main1090 extends JFrame { this.openDataSource(); } + private void createTable() { + JTable table = new JTable(this.aircraftTableModel); + table.setFillsViewportHeight(true); + JScrollPane scrollPane = new JScrollPane(table); + this.add(scrollPane); + } + private void createMenuBar() { JMenuBar menubar = new JMenuBar(); JMenu file = new JMenu("1090"); - file.setMnemonic(KeyEvent.VK_F); JMenuItem eMenuItem = new JMenuItem("Quit"); - eMenuItem.setMnemonic(KeyEvent.VK_E); - eMenuItem.setToolTipText("Exit 1090"); + JMenu data = new JMenu("Data"); + JMenuItem dataConnectItem = new JMenuItem("Connect..."); + JMenuItem dataDisconnectItem = new JMenuItem("Disconnect"); + eMenuItem.addActionListener((ActionEvent event) -> { System.exit(0); }); file.add(eMenuItem); menubar.add(file); + + dataConnectItem.addActionListener((ActionEvent event) -> { + if (this.currentTcpConnection == 0) { + this.currentTcpConnection = this.addTcpSource("10.0.0.111", 30003); + dataConnectItem.setEnabled(false); + dataDisconnectItem.setEnabled(true); + } + }); + dataDisconnectItem.addActionListener((ActionEvent event) -> { + if (this.currentTcpConnection != 0) { + this.sbsDataSource.closeSource(this.currentTcpConnection); + dataConnectItem.setEnabled(true); + dataDisconnectItem.setEnabled(false); + this.currentTcpConnection = 0; + } + }); + dataDisconnectItem.setEnabled(false); + data.add(dataConnectItem); + data.add(dataDisconnectItem); + menubar.add(data); + this.setJMenuBar(menubar); } private void openDataSource() { - System.out.println("asdfasdfasdfasdfasdf"); - this.sbsDataSource.addSource(new TCPDataSource("10.0.0.111", 30003)); this.sbsDataSource.subscribe((SBSPacket packet) -> { - System.out.println("Got message: " + packet.toString()); + if (packet.getHexIdent() != null) { + if (!this.aircraftMap.containsKey(packet.getHexIdent())) { + this.aircraftMap.put(packet.getHexIdent(), new Aircraft(packet.getHexIdent())); + } + this.aircraftMap.get(packet.getHexIdent()).handleUpdate(packet); + this.aircraftTableModel.fireTableDataChanged(); + } }); + this.sbsDataSource.open(); + } + + private int addTcpSource(String host, int port) { + TCPDataSource source = new TCPDataSource(host, port); + source.open(); + return this.sbsDataSource.addSource(source); } public static void main(String[] args) { diff --git a/src/com/benburwell/planes/sbs/AggregateDataSource.java b/src/com/benburwell/planes/sbs/AggregateDataSource.java index 08b89ea..2850404 100644 --- a/src/com/benburwell/planes/sbs/AggregateDataSource.java +++ b/src/com/benburwell/planes/sbs/AggregateDataSource.java @@ -2,22 +2,47 @@ package com.benburwell.planes.sbs; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.HashMap; /** * Created by ben on 11/15/16. */ public class AggregateDataSource implements DataSource { private List subscribers = new ArrayList<>(); + private boolean isOpen = false; + private int nextSourceNumber = 1; + private Map sources = new HashMap<>(); - public void addSource(DataSource source) { + public int addSource(DataSource source) { + int thisSourceNumber = this.nextSourceNumber++; + this.sources.put(thisSourceNumber, source); source.subscribe((SBSPacket packet) -> { - for (DataListener listener : subscribers) { - listener.handleMessage(packet); + if (isOpen) { + for (DataListener listener : subscribers) { + listener.handleMessage(packet); + } } }); + return thisSourceNumber; } public void subscribe(DataListener listener) { this.subscribers.add(listener); } + + public void open() { + this.isOpen = true; + } + + public void close() { + this.isOpen = false; + } + + public void closeSource(int sourceNumber) { + if (this.sources.containsKey(sourceNumber)) { + this.sources.get(sourceNumber).close(); + this.sources.remove(sourceNumber); + } + } } diff --git a/src/com/benburwell/planes/sbs/DataSource.java b/src/com/benburwell/planes/sbs/DataSource.java index 959e273..961c6e2 100644 --- a/src/com/benburwell/planes/sbs/DataSource.java +++ b/src/com/benburwell/planes/sbs/DataSource.java @@ -5,4 +5,6 @@ package com.benburwell.planes.sbs; */ public interface DataSource { void subscribe(DataListener listener); + void open(); + void close(); } diff --git a/src/com/benburwell/planes/sbs/SBSPacket.java b/src/com/benburwell/planes/sbs/SBSPacket.java index 0988f3a..5684803 100644 --- a/src/com/benburwell/planes/sbs/SBSPacket.java +++ b/src/com/benburwell/planes/sbs/SBSPacket.java @@ -4,35 +4,31 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; -import java.util.DoubleSummaryStatistics; /** * Created by ben on 11/15/16. */ public class SBSPacket { private MessageType messageType; - private TransmissionType transmissionType; - private String sessionId; - private String aircraftId; - private String hexIdent; - private String flightId; - private Date dateGenerated; - private Date dateLogged; - private String callsign; - private double altitude; - private double groundSpeed; - private double track; - private double latitude; - private double longitude; - private double verticalRate; - private String squawk; - private boolean alert; - private boolean emergency; - private boolean spi; - private boolean isOnGround; - - public SBSPacket() { - } + private TransmissionType transmissionType = null; + private String sessionId = null; + private String aircraftId = null; + private String hexIdent = null; + private String flightId = null; + private Date dateGenerated = null; + private Date dateLogged = null; + private String callsign = null; + private Double altitude = null; + private Double groundSpeed = null; + private Double track = null; + private Double latitude = null; + private Double longitude = null; + private Double verticalRate = null; + private String squawk = null; + private Boolean alert = null; + private Boolean emergency = null; + private Boolean spi = null; + private Boolean isOnGround = null; public SBSPacket(String packet) throws MalformedPacketException { this.parse(packet); @@ -137,4 +133,84 @@ public class SBSPacket { public String toString() { return this.messageType.name(); } + + public MessageType getMessageType() { + return messageType; + } + + public TransmissionType getTransmissionType() { + return transmissionType; + } + + public String getSessionId() { + return sessionId; + } + + public String getAircraftId() { + return aircraftId; + } + + public String getHexIdent() { + return hexIdent; + } + + public String getFlightId() { + return flightId; + } + + public Date getDateGenerated() { + return dateGenerated; + } + + public Date getDateLogged() { + return dateLogged; + } + + public String getCallsign() { + return callsign; + } + + public Double getAltitude() { + return altitude; + } + + public Double getGroundSpeed() { + return groundSpeed; + } + + public Double getTrack() { + return track; + } + + public Double getLatitude() { + return latitude; + } + + public Double getLongitude() { + return longitude; + } + + public Double getVerticalRate() { + return verticalRate; + } + + public String getSquawk() { + return squawk; + } + + public Boolean isAlert() { + return alert; + } + + public Boolean isEmergency() { + return emergency; + } + + public Boolean isSpi() { + return spi; + } + + public Boolean isOnGround() { + return isOnGround; + } } diff --git a/src/com/benburwell/planes/sbs/TCPDataSource.java b/src/com/benburwell/planes/sbs/TCPDataSource.java index 6c0e51d..2224d36 100644 --- a/src/com/benburwell/planes/sbs/TCPDataSource.java +++ b/src/com/benburwell/planes/sbs/TCPDataSource.java @@ -10,20 +10,67 @@ import java.net.*; */ public class TCPDataSource implements DataSource { private List subscribers = new ArrayList<>(); + private String host; + private int port; + private Thread clientThread = null; + private SocketClient client = null; public TCPDataSource(String host, int port) { - new Thread(() -> { + this.host = host; + this.port = port; + } + + public void subscribe(DataListener listener) { + this.subscribers.add(listener); + } + + public void open() { + this.client = new SocketClient(this.host, this.port); + this.clientThread = new Thread(this.client); + this.clientThread.start(); + } + + public void close() { + if (this.client != null) { + this.client.terminate(); + try { + this.clientThread.join(); + } catch (InterruptedException ignored) {} + } + } + + private class SocketClient implements Runnable { + private String host; + private int port; + private Socket clientSocket = null; + + public SocketClient(String host, int port) { + this.host = host; + this.port = port; + } + + public void terminate() { + if (this.clientSocket != null) { + try { + this.clientSocket.close(); + } catch (IOException e) { + System.out.println("Got exception closing socket: " + e.getMessage()); + } + } + } + + @Override + public void run() { System.out.println("Starting socket client"); - Socket clientSocket; BufferedReader socketReader; try { - clientSocket = new Socket(host, port); + this.clientSocket = new Socket(this.host, this.port); } catch (IOException e) { - System.out.println("Could not connect to " + host + " on port " + port + ": " + e.getMessage()); + System.out.println("Could not connect to " + this.host + " on port " + this.port + ": " + e.getMessage()); return; } try { - socketReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + socketReader = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream())); } catch (IOException e) { System.out.println("Could not create socket reader: " + e.getMessage()); return; @@ -47,10 +94,6 @@ public class TCPDataSource implements DataSource { System.out.println(e.getMessage()); } } - }).start(); - } - - public void subscribe(DataListener listener) { - this.subscribers.add(listener); + } } } -- cgit v1.2.3