Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package de.stefanwndelmann.zy1270logger; import com.fazecast.jSerialComm.SerialPort; import java.awt.BorderLayout; import java.awt.GridBagConstraints; import java.io.FileWriter; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JFileChooser; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.DefaultTableModel; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.DateAxis; import org.jfree.chart.axis.DateTickMarkPosition; import org.jfree.data.time.Millisecond; import org.jfree.data.time.TimeSeries; import org.jfree.data.time.TimeSeriesCollection; /** * * @author swendelmann */ public class ZY1270LoggerMain extends javax.swing.JFrame { //Serial SerialPort chosenPort; Thread portThread; //JFreeChart TimeSeries voltageSeries; TimeSeries ampSeries; TimeSeries wattSeries; TimeSeriesCollection dataset; JFreeChart chart; ChartPanel chartPanel; /** * Creates new form ZY1270LoggerMain */ public ZY1270LoggerMain() { initComponents(); initJFreeChart(); SerialPort[] portNames = SerialPort.getCommPorts(); for (int i = 0; i < portNames.length; i++) { portList.addItem(portNames[i].getSystemPortName()); } } private void initJFreeChart() { voltageSeries = new TimeSeries("Voltage"); ampSeries = new TimeSeries("Amps"); wattSeries = new TimeSeries("Watt"); dataset = new TimeSeriesCollection(voltageSeries); dataset.addSeries(ampSeries); dataset.addSeries(wattSeries); chart = ChartFactory.createTimeSeriesChart("Live Data", "Time", "U/I/P", dataset); DateAxis axis = (DateAxis) chart.getXYPlot().getDomainAxis(); axis.setTickMarkPosition(DateTickMarkPosition.START); axis.setDateFormatOverride(new SimpleDateFormat("HH:mm:ss.SSS")); chart.setAntiAlias(true); chart.setTextAntiAlias(true); chartPanel = new ChartPanel(chart); jFreeChartPanel.add(chartPanel, BorderLayout.CENTER); } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { jLabel1 = new javax.swing.JLabel(); portList = new javax.swing.JComboBox<>(); connectButton = new javax.swing.JButton(); jLabel2 = new javax.swing.JLabel(); jFreeChartPanel = new javax.swing.JPanel(); jScrollPane1 = new javax.swing.JScrollPane(); resultTable = new javax.swing.JTable(); saveCSVButton = new javax.swing.JButton(); clearButton = new javax.swing.JButton(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setTitle("ZY1270 Logger by Stefan Wendelmann"); setMinimumSize(new java.awt.Dimension(800, 600)); jLabel1.setText("Select Serial Port"); portList.setModel(new javax.swing.DefaultComboBoxModel<>()); portList.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { portListActionPerformed(evt); } }); connectButton.setText("Connect"); connectButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { connectButtonActionPerformed(evt); } }); jLabel2.setText("Live Data"); jFreeChartPanel.setBackground(new java.awt.Color(102, 255, 51)); jFreeChartPanel.addComponentListener(new java.awt.event.ComponentAdapter() { public void componentResized(java.awt.event.ComponentEvent evt) { jFreeChartPanelComponentResized(evt); } }); jFreeChartPanel.setLayout(new java.awt.BorderLayout()); resultTable.setModel(new javax.swing.table.DefaultTableModel(new Object[][] { }, new String[] { "Timestamp", "Volt", "Amp", "Watt" }) { Class[] types = new Class[] { java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class }; public Class getColumnClass(int columnIndex) { return types[columnIndex]; } }); jScrollPane1.setViewportView(resultTable); saveCSVButton.setText("Save as CSV"); saveCSVButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { saveCSVButtonActionPerformed(evt); } }); clearButton.setText("Clear"); clearButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { clearButtonActionPerformed(evt); } }); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jFreeChartPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup().addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup().addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(portList, javax.swing.GroupLayout.PREFERRED_SIZE, 167, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent( connectButton, javax.swing.GroupLayout.PREFERRED_SIZE, 84, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(jLabel2) .addGroup(layout.createSequentialGroup() .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 572, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(saveCSVButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(clearButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) .addContainerGap(23, Short.MAX_VALUE))); layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup().addContainerGap().addGroup(layout .createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE).addComponent(jLabel1) .addComponent(portList, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(connectButton)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(jLabel2) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 111, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jFreeChartPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 374, Short.MAX_VALUE)) .addGroup(layout.createSequentialGroup().addComponent(saveCSVButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(clearButton).addGap(0, 0, Short.MAX_VALUE))))); pack(); }// </editor-fold>//GEN-END:initComponents private void portListActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_portListActionPerformed // TODO add your handling code here: }//GEN-LAST:event_portListActionPerformed private void connectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectButtonActionPerformed if (connectButton.getText().equals("Connect")) { // attempt to connect to the serial port chosenPort = SerialPort.getCommPort(portList.getSelectedItem().toString()); chosenPort.setComPortTimeouts(SerialPort.TIMEOUT_SCANNER, 0, 0); if (chosenPort.openPort()) { connectButton.setText("Disconnect"); portList.setEnabled(false); } portThread = new Thread() { @Override public void run() { Scanner scanner = new Scanner(chosenPort.getInputStream()); try { Thread.currentThread().setName("Port Reader"); while (true) { while (scanner.hasNextLine()) { try { String line = scanner.nextLine(); ZY1270Data data = ZY1270Data.parseString(line, new Date()); ((DefaultTableModel) resultTable.getModel()).addRow(data.getRowFormat()); java.awt.EventQueue.invokeLater(new Runnable() { public void run() { resultTable.scrollRectToVisible( resultTable.getCellRect(resultTable.getRowCount() - 1, resultTable.getColumnCount(), true)); } }); ampSeries.add(new Millisecond(data.getTimestamp()), data.getAmp()); voltageSeries.add(new Millisecond(data.getTimestamp()), data.getVoltage()); wattSeries.add(new Millisecond(data.getTimestamp()), data.getWatt()); } catch (Exception e) { } } Thread.sleep(1); } } catch (Exception e) { } finally { scanner.close(); } } }; portThread.start(); } else { // disconnect from the serial port new Thread() { @Override public void run() { while (!portThread.isInterrupted()) { portThread.interrupt(); } chosenPort.closePort(); portList.setEnabled(true); connectButton.setText("Connect"); } }.start(); } }//GEN-LAST:event_connectButtonActionPerformed private void jFreeChartPanelComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_jFreeChartPanelComponentResized // chartPanel .setPreferredSize(new java.awt.Dimension(jFreeChartPanel.getWidth(), jFreeChartPanel.getHeight())); chartPanel.setSize(new java.awt.Dimension(jFreeChartPanel.getWidth(), jFreeChartPanel.getHeight())); jFreeChartPanel.validate(); }//GEN-LAST:event_jFreeChartPanelComponentResized private void clearButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clearButtonActionPerformed // TODO add your handling code here: resultTable.setModel(new javax.swing.table.DefaultTableModel(new Object[][] {}, new String[] { "Timestamp", "Volt", "Amp", "Watt" }) { Class[] types = new Class[] { java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class }; public Class getColumnClass(int columnIndex) { return types[columnIndex]; } }); ampSeries.clear(); wattSeries.clear(); voltageSeries.clear(); }//GEN-LAST:event_clearButtonActionPerformed private void saveCSVButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveCSVButtonActionPerformed // TODO add your handling code here: String data = getCSVData(); JFileChooser chooser = new JFileChooser(); chooser.setFileFilter(new FileNameExtensionFilter("CSV Files", "csv")); int retrival = chooser.showSaveDialog(null); if (retrival == JFileChooser.APPROVE_OPTION) { try (FileWriter fw = new FileWriter(chooser.getSelectedFile() + ".csv")) { fw.write(data); } catch (IOException ex) { Logger.getLogger(ZY1270LoggerMain.class.getName()).log(Level.SEVERE, null, ex); } } }//GEN-LAST:event_saveCSVButtonActionPerformed /** * Reads the Data from the JTable and returns it as a CSV String. * * @return */ private String getCSVData() { DefaultTableModel dtm = (DefaultTableModel) resultTable.getModel(); int nRow = dtm.getRowCount(), nCol = dtm.getColumnCount(); String data = ""; for (int i = 0; i < nCol; i++) { data += dtm.getColumnName(i) + ";"; } data = data.substring(0, data.length() - 1) + "\n"; for (int i = 0; i < nRow; i++) { for (int j = 0; j < nCol; j++) { data += dtm.getValueAt(i, j) + ";"; } data = data.substring(0, data.length() - 1) + "\n"; } return data; } /** * @param args the command line arguments */ public static void main(String args[]) { /* Set the Nimbus look and feel */ //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) "> /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel. * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html */ try { for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { if ("Windows".equals(info.getName())) { javax.swing.UIManager.setLookAndFeel(info.getClassName()); break; } } } catch (ClassNotFoundException ex) { java.util.logging.Logger.getLogger(ZY1270LoggerMain.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } catch (InstantiationException ex) { java.util.logging.Logger.getLogger(ZY1270LoggerMain.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } catch (IllegalAccessException ex) { java.util.logging.Logger.getLogger(ZY1270LoggerMain.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } catch (javax.swing.UnsupportedLookAndFeelException ex) { java.util.logging.Logger.getLogger(ZY1270LoggerMain.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } //</editor-fold> /* Create and display the form */ java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new ZY1270LoggerMain().setVisible(true); } }); } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton clearButton; private javax.swing.JButton connectButton; private javax.swing.JPanel jFreeChartPanel; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JComboBox<String> portList; private javax.swing.JTable resultTable; private javax.swing.JButton saveCSVButton; // End of variables declaration//GEN-END:variables }