From d764aca98f297a8086395878ef26e9ff73688862 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sun, 28 Mar 2021 19:12:38 -0400 Subject: [PATCH 1/5] Basic data sending --- src/uorocketry/basestation/Main.java | 5 +- src/uorocketry/basestation/StateButton.java | 54 +++++++++++++++++++++ src/uorocketry/basestation/Window.java | 45 ++++++++++++++--- 3 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 src/uorocketry/basestation/StateButton.java diff --git a/src/uorocketry/basestation/Main.java b/src/uorocketry/basestation/Main.java index 6902188..23dc8c0 100644 --- a/src/uorocketry/basestation/Main.java +++ b/src/uorocketry/basestation/Main.java @@ -21,7 +21,6 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -824,9 +823,9 @@ public void actionPerformed(ActionEvent e) { updateUI(); } } else if (e.getSource() == window.hideComSelectorButton) { - window.sidePanel.setVisible(!window.sidePanel.isVisible()); + window.comPanelParent.setVisible(!window.comPanelParent.isVisible()); - if (window.sidePanel.isVisible()) { + if (window.comPanelParent.isVisible()) { window.hideComSelectorButton.setText("Hide Com Selector"); } else { window.hideComSelectorButton.setText("Show Com Selector"); diff --git a/src/uorocketry/basestation/StateButton.java b/src/uorocketry/basestation/StateButton.java new file mode 100644 index 0000000..a6ba6b3 --- /dev/null +++ b/src/uorocketry/basestation/StateButton.java @@ -0,0 +1,54 @@ +package uorocketry.basestation; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + +import javax.swing.JButton; + +import com.fazecast.jSerialComm.SerialPort; + +/** + * DOES NOT support multiple data sources + * (Hardcoded, fixable) + * + * @author Ajay + * + */ +public class StateButton implements ActionListener { + + // Always zero for now + private static final int TABLE_INDEX = 0; + + String name; + /** What data to send */ + byte[] data; + /** Which state means this button has been complete */ + int stateNumber; + + JButton button; + + private List activeSerialPorts; + + public StateButton(List activeSerialPorts, String name, String data, int stateNumber) { + this.activeSerialPorts = activeSerialPorts; + + this.name = name; + this.data = data.getBytes(); + this.stateNumber = stateNumber; + + button = new JButton(name); + button.addActionListener(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource() == button) { + SerialPort serialPort = activeSerialPorts.get(TABLE_INDEX); + if (serialPort != null) { + serialPort.writeBytes(data, data.length); + } + } + } + +} diff --git a/src/uorocketry/basestation/Window.java b/src/uorocketry/basestation/Window.java index 408a1c6..0e2f0a1 100644 --- a/src/uorocketry/basestation/Window.java +++ b/src/uorocketry/basestation/Window.java @@ -29,6 +29,8 @@ import javax.swing.UnsupportedLookAndFeelException; import javax.swing.border.LineBorder; +import org.json.JSONArray; +import org.json.JSONException; import org.json.JSONObject; import javax.swing.border.TitledBorder; import javax.swing.JSplitPane; @@ -72,12 +74,16 @@ public class Window extends JFrame { JButton latestButton; JLabel savingToLabel; - private List comPanels = new ArrayList<>(); - List> comSelectors = new ArrayList<>(); - List comConnectionSuccessLabels = new ArrayList<>(); - - Vector comSelectorData = new Vector(); public JPanel sidePanel; + public JPanel comPanelParent; + private List comPanels = new ArrayList<>(); + public List> comSelectors = new ArrayList<>(); + public List comConnectionSuccessLabels = new ArrayList<>(); + + public JPanel stateSendingPanel; + private List stateButtons = new ArrayList<>(); + private List statePanels = new ArrayList<>(); + private List> stateSelectors = new ArrayList<>(); JPanel centerChartPanel; @@ -235,12 +241,37 @@ public Window(Main main) { sidePanel = new JPanel(); getContentPane().add(sidePanel, BorderLayout.EAST); - sidePanel.setLayout(new GridLayout(2, 1, 0, 0)); + sidePanel.setLayout(new BorderLayout()); + + comPanelParent = new JPanel(); + sidePanel.add(comPanelParent, BorderLayout.SOUTH); + comPanelParent.setLayout(new GridLayout(2, 1, 0, 0)); for (int i = 0; i < Main.dataSourceCount; i++) { addComSelectorPanel(); } + try { + JSONArray array = main.config.getJSONArray("states"); + + if (array.length() > 0) { + stateSendingPanel = new JPanel(); + sidePanel.add(stateSendingPanel, BorderLayout.NORTH); + stateSendingPanel.setLayout(new BoxLayout(stateSendingPanel, BoxLayout.Y_AXIS)); + } + + for (int i = 0; i < array.length(); i++) { + JSONObject object = array.getJSONObject(i); + StateButton stateButton = new StateButton(main.activeSerialPorts, object.getString("name"), object.getString("data"), object.getInt("stateNumber")); + + stateSendingPanel.add(stateButton.button); + } + + } catch (JSONException e) { + // No states then + stateSendingPanel.setVisible(false); + } + centerChartPanel = new JPanel(); splitPane.setRightComponent(centerChartPanel); @@ -318,7 +349,7 @@ public void addComSelectorPanel() { comConnectionSuccessLabel.setOpaque(true); comPanel.add(comConnectionSuccessLabel); - sidePanel.add(comPanel); + comPanelParent.add(comPanel); comPanels.add(comPanel); comSelectors.add(comSelector); From 88125e302da54368cdcad8f0881b36bae562295f Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Wed, 31 Mar 2021 22:30:56 -0400 Subject: [PATCH 2/5] Add all states --- .gitignore | 4 ++++ src/uorocketry/basestation/StateButton.java | 16 +++++++++++++++- src/uorocketry/basestation/Window.java | 5 ++--- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 6cb8850..a973871 100644 --- a/.gitignore +++ b/.gitignore @@ -111,3 +111,7 @@ data build builds +# Intellij +.idea +BaseStation.iml + diff --git a/src/uorocketry/basestation/StateButton.java b/src/uorocketry/basestation/StateButton.java index a6ba6b3..9274b1f 100644 --- a/src/uorocketry/basestation/StateButton.java +++ b/src/uorocketry/basestation/StateButton.java @@ -1,10 +1,14 @@ package uorocketry.basestation; +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.List; +import javax.swing.BorderFactory; import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.border.LineBorder; import com.fazecast.jSerialComm.SerialPort; @@ -26,7 +30,8 @@ public class StateButton implements ActionListener { /** Which state means this button has been complete */ int stateNumber; - JButton button; + private JButton button; + private JPanel border; private List activeSerialPorts; @@ -39,6 +44,11 @@ public StateButton(List activeSerialPorts, String name, String data, button = new JButton(name); button.addActionListener(this); + button.setFont(new Font("Arial", Font.PLAIN, 20)); + + border = new JPanel(); + border.setBorder(BorderFactory.createTitledBorder(name)); + border.add(button); } @Override @@ -50,5 +60,9 @@ public void actionPerformed(ActionEvent e) { } } } + + public JPanel getPanel() { + return border; + } } diff --git a/src/uorocketry/basestation/Window.java b/src/uorocketry/basestation/Window.java index 0e2f0a1..79840f1 100644 --- a/src/uorocketry/basestation/Window.java +++ b/src/uorocketry/basestation/Window.java @@ -82,8 +82,6 @@ public class Window extends JFrame { public JPanel stateSendingPanel; private List stateButtons = new ArrayList<>(); - private List statePanels = new ArrayList<>(); - private List> stateSelectors = new ArrayList<>(); JPanel centerChartPanel; @@ -264,7 +262,8 @@ public Window(Main main) { JSONObject object = array.getJSONObject(i); StateButton stateButton = new StateButton(main.activeSerialPorts, object.getString("name"), object.getString("data"), object.getInt("stateNumber")); - stateSendingPanel.add(stateButton.button); + stateSendingPanel.add(stateButton.getPanel()); + stateButtons.add(stateButton); } } catch (JSONException e) { From 72985199f48a3fae6c202c8e7ba0935a54c07a89 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Fri, 2 Apr 2021 23:51:48 -0400 Subject: [PATCH 3/5] Add highlighting to state buttons --- src/uorocketry/basestation/Data.java | 4 +- src/uorocketry/basestation/Helper.java | 29 +++++++++++++ src/uorocketry/basestation/Main.java | 9 ++++ src/uorocketry/basestation/StateButton.java | 46 ++++++++++++++++----- src/uorocketry/basestation/Window.java | 10 +++-- 5 files changed, 81 insertions(+), 17 deletions(-) create mode 100644 src/uorocketry/basestation/Helper.java diff --git a/src/uorocketry/basestation/Data.java b/src/uorocketry/basestation/Data.java index dabe401..c81ebbf 100644 --- a/src/uorocketry/basestation/Data.java +++ b/src/uorocketry/basestation/Data.java @@ -81,12 +81,12 @@ public float getDecimalValue() { } } - public long getDecimalLong() { + public long getLongValue() { switch (type) { case LONG: return dataLong; default: - return getDecimalLong(); + return (long) getDecimalValue(); } } diff --git a/src/uorocketry/basestation/Helper.java b/src/uorocketry/basestation/Helper.java new file mode 100644 index 0000000..9cb4a2c --- /dev/null +++ b/src/uorocketry/basestation/Helper.java @@ -0,0 +1,29 @@ +package uorocketry.basestation; + +import org.json.JSONArray; + +public class Helper { + + /** + * + * @param array + * @return + */ + public static int[] toIntArray(JSONArray array) { + int[] result = new int[array.length()]; + + for (int i = 0; i < array.length(); i++) { + result[i] = array.getInt(i); + } + + return result; + } + + public static boolean arrayIncludes(int[] array, int value) { + for (int i = 0; i < array.length; i++) { + if (array[i] == value) return true; + } + + return false; + } +} diff --git a/src/uorocketry/basestation/Main.java b/src/uorocketry/basestation/Main.java index 23dc8c0..f52cc72 100644 --- a/src/uorocketry/basestation/Main.java +++ b/src/uorocketry/basestation/Main.java @@ -436,6 +436,15 @@ private void updateUIInternal() { } else { setTableToError(i, window.dataTables.get(i)); } + + if (window.stateButtons.size() > i) { + try { + int stateIndex = config.getJSONArray("datasets").getJSONObject(i).getInt("stateIndex"); + for (StateButton stateButton: window.stateButtons.get(i)) { + stateButton.stateChanged((int) currentDataHandler.data[stateIndex].getDecimalValue()); + } + } catch (JSONException e) {} + } } if (googleEarth) { diff --git a/src/uorocketry/basestation/StateButton.java b/src/uorocketry/basestation/StateButton.java index 9274b1f..e7dbf02 100644 --- a/src/uorocketry/basestation/StateButton.java +++ b/src/uorocketry/basestation/StateButton.java @@ -1,6 +1,7 @@ package uorocketry.basestation; -import java.awt.*; +import java.awt.Color; +import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.List; @@ -8,7 +9,9 @@ import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JPanel; -import javax.swing.border.LineBorder; +import javax.swing.border.Border; + +import org.json.JSONArray; import com.fazecast.jSerialComm.SerialPort; @@ -24,31 +27,40 @@ public class StateButton implements ActionListener { // Always zero for now private static final int TABLE_INDEX = 0; + private static final Color AVAILABLE_COLOR = new Color(0, 33, 115); + private static final Color SUCCESS_COLOR = new Color(3, 176, 0); + private static final Color INACTIVE_COLOR = new Color(79, 79, 79); + String name; /** What data to send */ byte[] data; - /** Which state means this button has been complete */ - int stateNumber; + /** Which states can this action be completed from */ + int[] availableStates; + /** Which states means this button has been complete */ + int[] successStates; private JButton button; - private JPanel border; + private JPanel borderPanel; + private Border defaultButtonBorder; private List activeSerialPorts; - public StateButton(List activeSerialPorts, String name, String data, int stateNumber) { + public StateButton(List activeSerialPorts, String name, String data, JSONArray successStates, JSONArray availableStates) { this.activeSerialPorts = activeSerialPorts; this.name = name; this.data = data.getBytes(); - this.stateNumber = stateNumber; + this.successStates = Helper.toIntArray(successStates); + this.availableStates = Helper.toIntArray(availableStates); button = new JButton(name); button.addActionListener(this); button.setFont(new Font("Arial", Font.PLAIN, 20)); + defaultButtonBorder = button.getBorder(); - border = new JPanel(); - border.setBorder(BorderFactory.createTitledBorder(name)); - border.add(button); + borderPanel = new JPanel(); + borderPanel.setBorder(BorderFactory.createTitledBorder(name)); + borderPanel.add(button); } @Override @@ -61,8 +73,20 @@ public void actionPerformed(ActionEvent e) { } } + public void stateChanged(int newState) { + if (Helper.arrayIncludes(availableStates, newState)) { + button.setForeground(AVAILABLE_COLOR); + } else if (Helper.arrayIncludes(successStates, newState)) { + button.setForeground(SUCCESS_COLOR); + + } else { + button.setForeground(INACTIVE_COLOR); + + } + } + public JPanel getPanel() { - return border; + return borderPanel; } } diff --git a/src/uorocketry/basestation/Window.java b/src/uorocketry/basestation/Window.java index 79840f1..d1b2eed 100644 --- a/src/uorocketry/basestation/Window.java +++ b/src/uorocketry/basestation/Window.java @@ -81,7 +81,7 @@ public class Window extends JFrame { public List comConnectionSuccessLabels = new ArrayList<>(); public JPanel stateSendingPanel; - private List stateButtons = new ArrayList<>(); + public List> stateButtons = new ArrayList<>(); JPanel centerChartPanel; @@ -258,14 +258,16 @@ public Window(Main main) { stateSendingPanel.setLayout(new BoxLayout(stateSendingPanel, BoxLayout.Y_AXIS)); } + List buttons = new ArrayList(array.length()); + stateButtons.add(buttons); + for (int i = 0; i < array.length(); i++) { JSONObject object = array.getJSONObject(i); - StateButton stateButton = new StateButton(main.activeSerialPorts, object.getString("name"), object.getString("data"), object.getInt("stateNumber")); + StateButton stateButton = new StateButton(main.activeSerialPorts, object.getString("name"), object.getString("data"), object.getJSONArray("successStates"), object.getJSONArray("availableStates")); stateSendingPanel.add(stateButton.getPanel()); - stateButtons.add(stateButton); + buttons.add(stateButton); } - } catch (JSONException e) { // No states then stateSendingPanel.setVisible(false); From 4cd12f66a9676d6ca96ec585aa7c30f7945233e5 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sat, 3 Apr 2021 13:35:49 -0400 Subject: [PATCH 4/5] Add dynamic state names --- src/uorocketry/basestation/DataHandler.java | 44 +++++---------------- src/uorocketry/basestation/Main.java | 5 +-- 2 files changed, 11 insertions(+), 38 deletions(-) diff --git a/src/uorocketry/basestation/DataHandler.java b/src/uorocketry/basestation/DataHandler.java index 467a972..ddafdce 100644 --- a/src/uorocketry/basestation/DataHandler.java +++ b/src/uorocketry/basestation/DataHandler.java @@ -38,8 +38,11 @@ public class DataHandler { */ int tableIndex = 0; - public DataHandler(int tableIndex) { + private JSONObject datasetConfig; + + public DataHandler(int tableIndex, JSONObject datasetConfig) { this.tableIndex = tableIndex; + this.datasetConfig = datasetConfig; this.data = new Data[Main.dataLength.get(tableIndex)]; @@ -59,37 +62,8 @@ public void updateTableUIWithData(JTable table, String[] labels) { String dataText = data[i].getFormattedString(); if (hiddenDataTypes.contains(types[i])) dataText = "Hidden Data"; - // Hardcode for now TODO: Move this into config - if (i == data.length - 1 && labels[i].toLowerCase().contains("state")) { - switch (dataText) { - case "0": - dataText = "Init"; - break; - case "1": - dataText = "Wait For Init"; - break; - case "2": - dataText = "Wait For Launch"; - break; - case "3": - dataText = "Powered Flight"; - break; - case "4": - dataText = "Coast"; - break; - case "5": - dataText = "Descent Phase 1"; - break; - case "6": - dataText = "Descent Phase 2"; - break; - case "7": - dataText = "Ground"; - break; - case "8": - dataText = "Max States"; - break; - } + if (i == data.length - 1 && datasetConfig.getInt("stateIndex") == i) { + dataText = datasetConfig.getJSONArray("states").getString((int) data[i].getDecimalValue()); } // Set data @@ -97,14 +71,14 @@ public void updateTableUIWithData(JTable table, String[] labels) { } } - public boolean set(int index, String currentData, JSONObject dataset) { + public boolean set(int index, String currentData) { // Check for special cases first boolean isFormattedCoordinate = false; boolean isTimestamp = false; try { - isTimestamp = dataset.getInt("timestampIndex") == index; + isTimestamp = datasetConfig.getInt("timestampIndex") == index; - JSONObject coordinateIndexes = dataset.getJSONObject("coordinateIndexes"); + JSONObject coordinateIndexes = datasetConfig.getJSONObject("coordinateIndexes"); isFormattedCoordinate = coordinateIndexes.has("formattedCoordinates") && coordinateIndexes.getBoolean("formattedCoordinates") && (coordinateIndexes.getInt("latitude") == index || coordinateIndexes.getInt("longitude") == index); diff --git a/src/uorocketry/basestation/Main.java b/src/uorocketry/basestation/Main.java index f52cc72..79f5753 100644 --- a/src/uorocketry/basestation/Main.java +++ b/src/uorocketry/basestation/Main.java @@ -641,7 +641,7 @@ public void loadSimulationData(int index, String fileName) { } public DataHandler parseData(String data, int tableIndex) { - DataHandler dataHandler = new DataHandler(tableIndex); + DataHandler dataHandler = new DataHandler(tableIndex, config.getJSONArray("datasets").getJSONObject(tableIndex)); // Clear out the b' ' stuff added that is only meant for the radio to see data = data.replaceAll("b'|\\\\r\\\\n'", ""); @@ -666,9 +666,8 @@ public DataHandler parseData(String data, int tableIndex) { } } catch (NumberFormatException | JSONException e) {} - JSONArray dataSets = config.getJSONArray("datasets"); for (int i = 0; i < splitData.length; i++) { - if (!dataHandler.set(i, splitData[i], dataSets.getJSONObject(tableIndex))) { + if (!dataHandler.set(i, splitData[i])) { System.err.println("Failed to set data handler"); // Parsing failed From 6b46ca50d3010ae16c4444177a3fc71d7c738b0b Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sat, 10 Apr 2021 01:09:54 -0400 Subject: [PATCH 5/5] Change config schema --- src/uorocketry/basestation/Window.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uorocketry/basestation/Window.java b/src/uorocketry/basestation/Window.java index d1b2eed..e91a710 100644 --- a/src/uorocketry/basestation/Window.java +++ b/src/uorocketry/basestation/Window.java @@ -250,7 +250,7 @@ public Window(Main main) { } try { - JSONArray array = main.config.getJSONArray("states"); + JSONArray array = main.config.getJSONArray("stateEvents"); if (array.length() > 0) { stateSendingPanel = new JPanel();