All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.wshackle.crcl4java.motoman.ui.MotomanCrclServerJPanel Maven / Gradle / Ivy

There is a newer version: 1.8
Show newest version
/*
 * This software is public domain software, however it is preferred
 * that the following disclaimers be attached.
 * Software Copywrite/Warranty Disclaimer
 * 
 * This software was developed at the National Institute of Standards and
 * Technology by employees of the Federal Government in the course of their
 * official duties. Pursuant to title 17 Section 105 of the United States
 * Code this software is not subject to copyright protection and is in the
 * public domain.
 * 
 * This software is experimental. NIST assumes no responsibility whatsoever 
 * for its use by other parties, and makes no guarantees, expressed or 
 * implied, about its quality, reliability, or any other characteristic. 
 * We would appreciate acknowledgement if the software is used. 
 * This software can be redistributed and/or modified freely provided 
 * that any derivative works bear some notice that they are derived from it, 
 * and any modified versions bear some notice that they have been modified.
 * 
 *  See http://www.copyright.gov/title17/92chap1.html#105
 * 
 */
package com.github.wshackle.crcl4java.motoman.ui;

import com.github.wshackle.crcl4java.motoman.MotoPlusConnection;
import com.github.wshackle.crcl4java.motoman.MotomanCrclServer;
import crcl.utils.CRCLServerSocket;
import crcl.utils.CRCLSocket;
import crcl.utils.PropertiesUtils;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Properties;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author shackle
 */
public class MotomanCrclServerJPanel extends javax.swing.JPanel {

    /**
     * Creates new form MotomanCrclServerJPanel
     */
    public MotomanCrclServerJPanel() {
        initComponents();
    }

    /**
     * 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")
    // //GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        telnetJPanel1 = new com.github.wshackle.crcl4java.motoman.ui.TelnetJPanel();
        jPanel2 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jTextFieldCrclPort = new javax.swing.JTextField();
        jLabel2 = new javax.swing.JLabel();
        jTextFieldMotoplusHost = new javax.swing.JTextField();
        jCheckBoxConnect = new javax.swing.JCheckBox();
        jLabel3 = new javax.swing.JLabel();
        jTextFieldMotoplusPort = new javax.swing.JTextField();
        jCheckBoxDebug = new javax.swing.JCheckBox();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTextAreaErrLog = new javax.swing.JTextArea();

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Telnet"));

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(telnetJPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(telnetJPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 206, Short.MAX_VALUE))
        );

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("CRCL"));

        jLabel1.setText("CRCL Port:");

        jTextFieldCrclPort.setText("64444");

        jLabel2.setText("Motoman Motoplus TCP Host:");

        jTextFieldMotoplusHost.setText("192.168.1.33");

        jCheckBoxConnect.setText("Connected");
        jCheckBoxConnect.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jCheckBoxConnectActionPerformed(evt);
            }
        });

        jLabel3.setText("Port:");

        jTextFieldMotoplusPort.setText("12222  ");

        jCheckBoxDebug.setText("Debug");
        jCheckBoxDebug.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jCheckBoxDebugActionPerformed(evt);
            }
        });

        jTextAreaErrLog.setColumns(20);
        jTextAreaErrLog.setRows(5);
        jScrollPane1.setViewportView(jTextAreaErrLog);

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addComponent(jCheckBoxDebug)
                .addGap(0, 0, Short.MAX_VALUE))
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(jPanel2Layout.createSequentialGroup()
                                .addComponent(jLabel1)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jTextFieldCrclPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(jCheckBoxConnect))
                            .addGroup(jPanel2Layout.createSequentialGroup()
                                .addComponent(jLabel2)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jTextFieldMotoplusHost, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jLabel3)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jTextFieldMotoplusPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(0, 0, Short.MAX_VALUE))))
                    .addComponent(jScrollPane1))
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(jTextFieldCrclPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jCheckBoxConnect))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(jTextFieldMotoplusHost, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel3)
                    .addComponent(jTextFieldMotoplusPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 136, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jCheckBoxDebug)
                .addContainerGap())
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
    }// //GEN-END:initComponents

    private MotomanCrclServer motomanCrclServer = null;
    private int motomanPort = MotomanCrclServer.DEFAULT_MOTOMAN_PORT;
    private int crclPort = CRCLSocket.DEFAULT_PORT;
    private String motomanHost = MotomanCrclServer.DEFAULT_MOTOMAN_HOST;
    private Thread crclThread = null;

    private int connectTimeoutMillis = 2000;

    /**
     * Get the value of connectTimeoutMillis
     *
     * @return the value of connectTimeoutMillis
     */
    public int getConnectTimeoutMillis() {
        return connectTimeoutMillis;
    }

    /**
     * Set the value of connectTimeoutMillis
     *
     * @param connectTimeoutMillis new value of connectTimeoutMillis
     */
    public void setConnectTimeoutMillis(int connectTimeoutMillis) {
        this.connectTimeoutMillis = connectTimeoutMillis;
    }

    private static Socket createSocketWithTimeout(String host, int port, int timeoutMillis) throws IOException {
        Socket socket = new Socket();
        socket.connect(new InetSocketAddress(host, port), timeoutMillis);
        return socket;
    }

    public boolean isCrclMotoplusConnected() {
        return jCheckBoxConnect.isSelected()
                && null != motomanCrclServer
                && null != crclThread
                && crclThread.isAlive()
                && motomanCrclServer.mpcConnected();
    }
    
    private final int LOG_SIZE_LIMIT = 5000;
    private void appendLog(String s) {
        jTextAreaErrLog.append(s+'\n');
        String fullString = jTextAreaErrLog.getText();
        if(fullString.length() > LOG_SIZE_LIMIT) {
            int index = Math.max(LOG_SIZE_LIMIT, fullString.indexOf('\n', LOG_SIZE_LIMIT));
            jTextAreaErrLog.setText(fullString.substring(index));
        }
    }
    
    private final Consumer logConsumer  = this::appendLog;
    
    public void connectCrclMotoplus() throws IOException {
        internalDisconnect();
        motomanCrclServer = new MotomanCrclServer(
                new CRCLServerSocket(crclPort),
                new MotoPlusConnection(createSocketWithTimeout(motomanHost, motomanPort, connectTimeoutMillis)));
        motomanCrclServer.setDebug(jCheckBoxDebug.isSelected());
        motomanCrclServer.addLogListener(logConsumer);
        crclThread = new Thread(motomanCrclServer, "motomanCrclServer");
        crclThread.start();
        if (!jCheckBoxConnect.isSelected()) {
            jCheckBoxConnect.setSelected(true);
        }
    }

    public void disconnectCrclMotoplus() {
        if (jCheckBoxConnect.isSelected()) {
            jCheckBoxConnect.setSelected(false);
        }
        internalDisconnect();
    }

    private void internalDisconnect() {
        if (null != motomanCrclServer) {
            motomanCrclServer.removeLogListener(logConsumer);
            try {
                motomanCrclServer.close();
            } catch (Exception ex) {
                Logger.getLogger(MotomanCrclServerJPanel.class.getName()).log(Level.SEVERE, null, ex);
            }
            motomanCrclServer = null;
        }
        if (null != crclThread) {
            if (crclThread.isAlive()) {
                System.err.println("Interrupting Motoman CRCL server thread");
                try {
                    crclThread.join(100);
                } catch (InterruptedException ex) {
                    Logger.getLogger(MotomanCrclServerJPanel.class.getName()).log(Level.SEVERE, null, ex);
                }
                if (crclThread.isAlive()) {
                    crclThread.interrupt();
                    try {
                        crclThread.join(100);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(MotomanCrclServerJPanel.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
            crclThread = null;
        }
    }
    private void jCheckBoxConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBoxConnectActionPerformed

        updateConnection();
    }//GEN-LAST:event_jCheckBoxConnectActionPerformed

    private void jCheckBoxDebugActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBoxDebugActionPerformed
        if (null != motomanCrclServer) {
            motomanCrclServer.setDebug(jCheckBoxDebug.isSelected());
        }
    }//GEN-LAST:event_jCheckBoxDebugActionPerformed

    private void updateConnection() throws NumberFormatException {
        if (this.jCheckBoxConnect.isSelected()) {
            try {
                disconnectCrclMotoplus();
                crclPort = Integer.parseInt(jTextFieldCrclPort.getText());
                motomanPort = Integer.parseInt(jTextFieldMotoplusPort.getText());
                motomanHost = jTextFieldMotoplusHost.getText();
                connectCrclMotoplus();
            } catch (IOException ex) {
                Logger.getLogger(MotomanCrclServerJPanel.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else {
            disconnectCrclMotoplus();
        }
    }

    private File propertiesFile;

    /**
     * Get the value of propertiesFile
     *
     * @return the value of propertiesFile
     */
    public File getPropertiesFile() {
        return propertiesFile;
    }

    /**
     * Set the value of propertiesFile
     *
     * @param propertiesFile new value of propertiesFile
     */
    public void setPropertiesFile(File propertiesFile) {
        this.propertiesFile = propertiesFile;
    }

    public void saveProperties() throws IOException {
        Properties props = new Properties();
        props.put(CRCL_PORT_PROPERTY_NAME, jTextFieldCrclPort.getText());
        props.put(MOTOPLUS_PORT_PROPERTY_NAME, jTextFieldMotoplusPort.getText());
        props.put(MOTOPLUS_HOST_PROPERTY_NAME, jTextFieldMotoplusHost.getText());
        props.put("debug", Boolean.toString(jCheckBoxDebug.isSelected()));

        System.out.println("MotomanCrclServerJPanel saving properties to " + propertiesFile.getCanonicalPath());
//        try (FileWriter fw = new FileWriter(propertiesFile)) {
//            props.store(fw, "");
//        }
        PropertiesUtils.saveProperties(propertiesFile, props);
    }
    private static final String MOTOPLUS_HOST_PROPERTY_NAME = "MOTOPLUS_HOST";
    private static final String MOTOPLUS_PORT_PROPERTY_NAME = "MOTOPLUS_PORT";
    private static final String CRCL_PORT_PROPERTY_NAME = "CRCL_PORT";

    public void setCrclPort(int port) {
        this.jTextFieldCrclPort.setText(Integer.toString(port));
        crclPort = Integer.parseInt(jTextFieldCrclPort.getText());
        updateConnection();
    }

    public int getCrclPort() {
        return crclPort;
    }

    public void loadProperties() throws IOException {
        Properties props = new Properties();
        System.out.println("MotomanCrclServerJPanel loading properties from " + propertiesFile.getCanonicalPath());
        try (FileReader fr = new FileReader(propertiesFile)) {
            props.load(fr);
        }
        String crclPortString = props.getProperty(CRCL_PORT_PROPERTY_NAME);
        if (null != crclPortString) {
            jTextFieldCrclPort.setText(crclPortString);
        }
        String motoplusPortString = props.getProperty(MOTOPLUS_PORT_PROPERTY_NAME);
        if (null != motoplusPortString) {
            jTextFieldMotoplusPort.setText(motoplusPortString);
        }
        String motomanHostString = props.getProperty(MOTOPLUS_HOST_PROPERTY_NAME);
        if (null != motomanHostString) {
            jTextFieldMotoplusHost.setText(motomanHostString);
        }
        crclPort = Integer.parseInt(jTextFieldCrclPort.getText());
        motomanPort = Integer.parseInt(jTextFieldMotoplusPort.getText());
        motomanHost = jTextFieldMotoplusHost.getText();
        String debugString = props.getProperty("debug");
        if(debugString != null && debugString.length() > 0 && Boolean.valueOf(debugString)) {
            jCheckBoxDebug.setSelected(true);
        }
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JCheckBox jCheckBoxConnect;
    private javax.swing.JCheckBox jCheckBoxDebug;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextArea jTextAreaErrLog;
    private javax.swing.JTextField jTextFieldCrclPort;
    private javax.swing.JTextField jTextFieldMotoplusHost;
    private javax.swing.JTextField jTextFieldMotoplusPort;
    private com.github.wshackle.crcl4java.motoman.ui.TelnetJPanel telnetJPanel1;
    // End of variables declaration//GEN-END:variables
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy