package de.gurkengewuerz.serialinterface; import gnu.io.CommPortIdentifier; import gnu.io.SerialPort; import gnu.io.SerialPortEvent; import org.pmw.tinylog.Logger; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.util.ArrayList; import java.util.Hashtable; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * Created by gurkengewuerz.de on 08.01.2018. */ public class SerialGUI { private JTabbedPane tabbedPane1; private JButton refreshButton; private JTextField a0000TextField; private JTextArea debugArea; private JButton sendButton; private JTextField txText; private JTextField a8652TextField; private JButton connectButton; private JButton startServerButton; public JPanel mainPanel; private JList comPorts; private JSlider kmhSlider; private JSpinner fuelSpinner; private JSlider rpmSlider; private JCheckBox rTurnSignalCheckBox; private JCheckBox lTurnSignalCheckBox; private JCheckBox handbrakeCheckBox; private JCheckBox fogBeamCheckBox; private JCheckBox highBeamCheckBox; private JCheckBox seatBeltCheckBox; private JCheckBox lowVoltageCheckBox; private JCheckBox waterTempCheckBox; private JCheckBox ABSCheckBox; private JCheckBox tirePressureCheckBox; private JCheckBox backlightCheckBox; private JButton updateButton; private JCheckBox offroadCheckBox; private JCheckBox oilPressureCheckBox; private JCheckBox openDoorsCheckBox; private JCheckBox kupplungCheckBox; private JCheckBox checkLampCheckBox; private JCheckBox openTrunkCheckBox; private JLabel rpmCounter; private JLabel kmhCounter; private JPanel simulatorPanel; private SerialPort serialPort; private BufferedReader input; private OutputStream output; private static final int TIME_OUT = 2000; private static final int BAUDRATE = 115200; // ~ 14 kByte pro Sekunde private DashboardStatus status; private ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(); /* TODO: Klasse für Ansteuerung TODO: WebServer TODO: Update Simulation Panel if Class for contol gets updated! (Live View) */ public SerialGUI() { status = new DashboardStatus(); Logger.info(String.join(",", listPorts())); refreshPortList(); SpinnerModel sm = new SpinnerNumberModel(100, 0, 100, 5); fuelSpinner.setModel(sm); Hashtable labelsKMH = new Hashtable(); labelsKMH.put(0, new JLabel("0 km/h")); labelsKMH.put(40, new JLabel("40 km/h")); labelsKMH.put(80, new JLabel("80 km/h")); labelsKMH.put(120, new JLabel("120 km/h")); labelsKMH.put(160, new JLabel("160 km/h")); labelsKMH.put(200, new JLabel("200 km/h")); labelsKMH.put(240, new JLabel("240 km/h")); kmhSlider.setLabelTable(labelsKMH); kmhSlider.addChangeListener(evt -> { JSlider slider = (JSlider) evt.getSource(); if (!slider.getValueIsAdjusting()) { int value = slider.getValue(); kmhCounter.setText(value + " km/h"); } }); Hashtable labelsRPM = new Hashtable(); labelsRPM.put(0, new JLabel("0")); labelsRPM.put(1000, new JLabel("1k")); labelsRPM.put(2000, new JLabel("2k")); labelsRPM.put(3000, new JLabel("3k")); labelsRPM.put(4000, new JLabel("4k")); labelsRPM.put(5000, new JLabel("5k")); labelsRPM.put(6000, new JLabel("6k")); labelsRPM.put(7000, new JLabel("7k")); labelsRPM.put(8000, new JLabel("8k")); rpmSlider.setLabelTable(labelsRPM); rpmSlider.addChangeListener(evt -> { JSlider slider = (JSlider) evt.getSource(); if (!slider.getValueIsAdjusting()) { int value = slider.getValue(); rpmCounter.setText("RPM: " + value); } }); refreshButton.addActionListener(e -> { refreshPortList(); comPorts.grabFocus(); }); connectButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (serialPort == null) { try { if (comPorts.getSelectedIndex() < 0) { errorBox("Please select a COM Port!", "No port selected"); return; } CommPortIdentifier portId = getPortIDbyString((String) comPorts.getSelectedValue()); if (portId == null) { errorBox("An invalid port is selected!\nIs the port still connected?", "Invalid port selected"); refreshPortList(); return; } // open serial port, and use class name for the appName. serialPort = (SerialPort) portId.open(this.getClass().getName(), TIME_OUT); // set port parameters serialPort.setSerialPortParams(BAUDRATE, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); // open the streams input = new BufferedReader(new InputStreamReader(serialPort.getInputStream())); output = serialPort.getOutputStream(); ses.scheduleAtFixedRate(() -> write(status.generateJSON()), 5 * 1000, 10, TimeUnit.MILLISECONDS); // add event listeners serialPort.addEventListener(oEvent -> { if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) { try { String inputLine = input.readLine(); debugArea.append(inputLine + "\n"); debugArea.setCaretPosition(debugArea.getDocument().getLength()); } catch (Exception ex) { //Logger.error(ex); } } }); serialPort.notifyOnDataAvailable(true); refreshButton.setEnabled(false); comPorts.setEnabled(false); startServerButton.setEnabled(true); connectButton.setText("Disconnect"); } catch (Exception ex) { Logger.error(ex); } } else { close(); serialPort = null; refreshButton.setEnabled(true); comPorts.setEnabled(true); startServerButton.setEnabled(false); connectButton.setText("Connect"); ses.shutdown(); // TODO: Stop Server } } }); sendButton.addActionListener(e -> { write(txText.getText()); txText.setText(""); }); updateButton.addActionListener(e -> { status.setRpm(rpmSlider.getValue()); status.setKmh(kmhSlider.getValue()); status.setFuel((Integer) fuelSpinner.getValue()); status.setFogbeam(fogBeamCheckBox.isSelected()); status.setHighbeam(highBeamCheckBox.isSelected()); status.setHandbrake(handbrakeCheckBox.isSelected()); status.setAbs(ABSCheckBox.isSelected()); status.setOil_pressure(oilPressureCheckBox.isSelected()); status.setTire_pressure(tirePressureCheckBox.isSelected()); status.setKupplung(kupplungCheckBox.isSelected()); status.setTrunk(openTrunkCheckBox.isSelected()); status.setBacklight(backlightCheckBox.isSelected()); status.setL_turn_signal(lTurnSignalCheckBox.isSelected()); status.setR_turn_signal(rTurnSignalCheckBox.isSelected()); status.setOffroad(offroadCheckBox.isSelected()); status.setWater_temp(waterTempCheckBox.isSelected()); status.setSeat_belt(seatBeltCheckBox.isSelected()); status.setBattery(lowVoltageCheckBox.isSelected()); status.setCheck_lamp(checkLampCheckBox.isSelected()); status.setDoors(openDoorsCheckBox.isSelected()); Logger.info(status.generateJSON()); Logger.info(status.generateJSON().getBytes().length); }); } public void write(String payload) { if (serialPort != null) { try { output.write(payload.getBytes()); output.flush(); } catch (IOException e) { Logger.error(e); } } } public synchronized void close() { if (serialPort != null) { serialPort.removeEventListener(); serialPort.close(); } } private void refreshPortList() { DefaultListModel model = new DefaultListModel<>(); comPorts.setModel(model); listPorts().forEach(model::addElement); } private CommPortIdentifier getPortIDbyString(String port) { CommPortIdentifier portID = null; java.util.Enumeration portEnum = CommPortIdentifier.getPortIdentifiers(); while (portEnum.hasMoreElements()) { CommPortIdentifier portIdentifier = portEnum.nextElement(); if (portIdentifier.getName().equals(port)) { portID = portIdentifier; break; } } return portID; } private ArrayList listPorts() { ArrayList ports = new ArrayList<>(); java.util.Enumeration portEnum = CommPortIdentifier.getPortIdentifiers(); while (portEnum.hasMoreElements()) { CommPortIdentifier portIdentifier = portEnum.nextElement(); if (portIdentifier.getPortType() == CommPortIdentifier.PORT_SERIAL) ports.add(portIdentifier.getName()); } return ports; } public static void infoBox(String infoMessage, String titleBar) { JOptionPane.showMessageDialog(null, infoMessage, "INFO: " + titleBar, JOptionPane.INFORMATION_MESSAGE); } public static void errorBox(String errorMessage, String titleBar) { JOptionPane.showMessageDialog(null, errorMessage, "ERROR: " + titleBar, JOptionPane.ERROR_MESSAGE); } }