jcan2.SimpleSerial.java Source code

Java tutorial

Introduction

Here is the source code for jcan2.SimpleSerial.java

Source

/*
 * 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 jcan2;

import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JProgressBar;
import javax.swing.JTextArea;
import jssc.SerialPort;
import jssc.SerialPortException;
import jssc.SerialPortList;
import org.json.JSONException;
import org.json.JSONObject;

/**
 *
 * @author Micha
 */
public class SimpleSerial {
    private String serialPortName = "Error - no Port found";
    private static final boolean SERIAL_DEBUG = false;
    private static final int MAX_DATA_PER_IMPORT = 20;
    private static final int WAIT_MS = 50; //time to wait for the device to respond
    private static final int WAIT_MS_POINTS = WAIT_MS + 10 * MAX_DATA_PER_IMPORT; //time to wait for the device to respond
    //Test: 100ms = 15 points
    //security factor 200% --> time_ms = 15 ms per point
    private boolean deviceConnected = false;
    private String currentPortName;

    public SimpleSerial() {
        super();
    }

    public String getPortName() {
        return serialPortName;
    }

    public int searchDevicePort() throws InterruptedException {
        String[] portNames = SerialPortList.getPortNames();
        if (SERIAL_DEBUG)
            BeMapEditor.mainWindow.append("\nFound ports: " + Arrays.toString(portNames));
        int portNumber = -1;
        for (int i = 0; i < portNames.length; i++) {

            currentPortName = portNames[i];

            ExecutorService executor = Executors.newSingleThreadExecutor();
            Future<String> future = executor.submit(new PortSearchTask());

            try {
                String returnPort = future.get(3, TimeUnit.SECONDS);
                if (!"NULL".equals(returnPort)) {
                    portNumber = i;
                    i = portNames.length; //quit loop
                }

            } catch (ExecutionException ex) {
                Logger.getLogger(SimpleSerial.class.getName()).log(Level.SEVERE, null, ex);
            } catch (TimeoutException ex) {
                Logger.getLogger(SimpleSerial.class.getName()).log(Level.SEVERE, null, ex);
                if (SERIAL_DEBUG)
                    BeMapEditor.mainWindow.append("\nOpening port " + currentPortName + " has timed out");
            }

            executor.shutdownNow();
        }
        if (portNumber < 0) {
            deviceConnected = false;
            return 0;
        } else {
            serialPortName = portNames[portNumber];
            deviceConnected = true;
            if (SERIAL_DEBUG)
                BeMapEditor.mainWindow.append("\nDevice detected on port " + serialPortName);
            return 1; //success
        }
    }

    public boolean deviceConnected() {
        return deviceConnected;
    }

    public JSONObject getRealTimeData() throws InterruptedException, JSONException {
        if (!"Error - no Port found".equals(serialPortName)) {
            try {
                SerialPort serialPort = new SerialPort(serialPortName);

                serialPort.openPort();//Open serial port
                serialPort.setParams(SerialPort.BAUDRATE_9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
                        SerialPort.PARITY_NONE);//Set params. Also you can set params by this string: serialPort.setParams(9600, 8, 1, 0);

                serialPort.writeBytes("$ORRTV*11\n".getBytes());//Write data to port
                Thread.sleep(WAIT_MS * 5);
                String realTime = serialPort.readString();
                serialPort.closePort();
                int temp = 0;
                JSONObject output = new JSONObject();

                if (SERIAL_DEBUG)
                    BeMapEditor.mainWindow.append("\n" + realTime);

                //decompose the received data
                String[] lines = realTime.split("\n");

                for (int i = 0; i < lines.length; i++) {
                    String[] seperated = lines[i].split(",");
                    if (SERIAL_DEBUG)
                        BeMapEditor.mainWindow.append(seperated[0]);

                    if ("$BMRTV".equals(seperated[0])) {
                        output.put("err", 0);
                        output.put("temp", Integer.parseInt(seperated[8]) / 100.0); //temp data
                        output.put("hum", Integer.parseInt(seperated[7]) / 100.0);
                        output.put("gaz1", Integer.parseInt(seperated[5]));
                        output.put("gaz2", Integer.parseInt(seperated[6]));
                        output.put("ax", Double.parseDouble(seperated[9]));
                        output.put("ay", Double.parseDouble(seperated[10]));
                        output.put("az", Double.parseDouble(seperated[11]));

                        return output;
                    }

                }
                //error handling
                output.put("err", 1);
                return output;

            } catch (SerialPortException ex) {
                Logger.getLogger(SimpleSerial.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
        return null;
    }

    //returns the number of points stored or -1 if error
    public int importDataFromDevice(JProgressBar progressBar, JTextArea status)
            throws InterruptedException, JSONException {
        if ("Error - no Port found".equals(serialPortName))
            return -1;
        else {
            SerialPort serialPort = new SerialPort(serialPortName);

            try {
                serialPort.openPort();//Open serial port
                serialPort.setParams(SerialPort.BAUDRATE_115200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
                        SerialPort.PARITY_NONE);//Set params. Also you can set params by this string: serialPort.setParams(9600, 8, 1, 0);

                serialPort.writeBytes("$ORUSR*11\n".getBytes());//Write data to port
                Thread.sleep(WAIT_MS);
                String userString = serialPort.readString();
                int usr = decodeUserID(userString);
                if (usr > 0) {
                    BeMapEditor.mainWindow.setUsr(usr);
                    status.append("\nUser ID: " + usr);
                } else if (usr == -1) {
                    //code for getting usr id from server
                    //$ORUSR,25*11\n
                    status.append("\nError: Getting user ID from server not yet supported!");
                    BeMapEditor.mainWindow.setUsr(-1);
                } else {
                    status.append("\nError: No User ID found! Import aborted.");
                    return -1;
                }

                serialPort.writeBytes("$ORNUM*11\n".getBytes());
                Thread.sleep(WAIT_MS);
                String numberString = serialPort.readString();
                int totalNumber = decodeNbPoints(numberString);
                if (totalNumber > 0)
                    status.append("\nNumber of points to import: " + totalNumber);
                else if (totalNumber == 0) {
                    status.append("\nNo points stored to import! ");
                    return 0;
                } else {
                    status.append("\nError: Number of Points");
                    return -1;
                }

                //prepare track to import
                BeMapEditor.trackOrganiser.createNewTrack("Import");

                int nbRequests = (totalNumber / (MAX_DATA_PER_IMPORT)) + 1;
                int rest = totalNumber - (nbRequests - 1) * MAX_DATA_PER_IMPORT; //nb of points for the last request
                if (SERIAL_DEBUG)
                    BeMapEditor.mainWindow.append("\nNumber of requests necessary: " + nbRequests);
                if (SERIAL_DEBUG)
                    BeMapEditor.mainWindow.append("\nPoints resting for last request: " + rest);

                //init progress bar
                progressBar.setMaximum(nbRequests);

                for (int i = 0; i < (nbRequests - 1); i++) {
                    //import serie of points
                    int offset = i * MAX_DATA_PER_IMPORT;
                    if (importSerieOfPoints(serialPort, MAX_DATA_PER_IMPORT, offset) < 0)
                        return 0;
                    //actualize progress bar
                    progressBar.setValue(i + 1);
                }
                int final_offset = (nbRequests - 1) * MAX_DATA_PER_IMPORT;
                if (importSerieOfPoints(serialPort, rest, final_offset) < 0)
                    return 0; //import the rest of the points
                progressBar.setValue(nbRequests);

                status.append("\n" + totalNumber + " Points successfully imported");

                serialPort.writeString("$ORMEM*11\n");
                Thread.sleep(WAIT_MS);
                decodeMemoryState(serialPort.readString());

                serialPort.closePort();//Close serial port

                BeMapEditor.trackOrganiser.postImportTreatment(progressBar);
                return 1;
            } catch (SerialPortException ex) {
                return 0;//do not print error
            }
        }

    }

    public int sendDeleteRequest() {
        if ("Error - no Port found".equals(serialPortName))
            return -1;
        else {
            SerialPort serialPort = new SerialPort(serialPortName);

            try {
                serialPort.openPort();//Open serial port
                serialPort.setParams(SerialPort.BAUDRATE_9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
                        SerialPort.PARITY_NONE);//Set params. Also you can set params by this string: serialPort.setParams(9600, 8, 1, 0);
                serialPort.writeString("$ORCLR*11\n");
                serialPort.closePort();
                return 1;
            } catch (SerialPortException ex) {
                return 0;//do not print error
            }
        }
    }

    public int updateMemoryState() throws InterruptedException {
        if ("Error - no Port found".equals(serialPortName))
            return -1;
        else {
            SerialPort serialPort = new SerialPort(serialPortName);

            try {
                serialPort.openPort();//Open serial port
                serialPort.setParams(SerialPort.BAUDRATE_9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
                        SerialPort.PARITY_NONE);//Set params. Also you can set params by this string: serialPort.setParams(9600, 8, 1, 0);
                serialPort.writeString("$ORMEM*11\n");
                Thread.sleep(WAIT_MS);
                decodeMemoryState(serialPort.readString());
                serialPort.closePort();
                return 1;
            } catch (SerialPortException ex) {
                return 0;//do not print error
            }
        }
    }

    /**
     * BMCFG - config
     * @param memoryState 
     */
    private void decodeMemoryState(String memoryState) {
        //decompose the received data
        String[] lines = memoryState.split("\n");

        for (int i = 0; i < lines.length; i++) {
            if (SERIAL_DEBUG)
                BeMapEditor.mainWindow.append(lines[i] + "\n");
            String[] seperated = lines[i].split(",");
            if (SERIAL_DEBUG)
                BeMapEditor.mainWindow.append("Received: " + lines[i] + "\n");

            if ("$BMMEM".equals(seperated[0])) {
                int a = Integer.parseInt(seperated[1]);
                int b = Integer.parseInt(seperated[2]);
                int state = a / b;
                if (SERIAL_DEBUG)
                    BeMapEditor.mainWindow.append("Memory state: " + state + "\n");
                BeMapEditor.mainWindow.setBar(state);
            } else if ("$BMERR".equals(seperated[0])) {
                if (SERIAL_DEBUG)
                    BeMapEditor.mainWindow.append("Memory state error\n");
            } else if (SERIAL_DEBUG)
                BeMapEditor.mainWindow.append("Memory state error\n");

        }
    }

    private int importSerieOfPoints(SerialPort serialPort, int nb, int offset) throws InterruptedException {
        try {
            String send = "$ORGET," + offset + "," + nb + "*11\n";
            if (SERIAL_DEBUG)
                BeMapEditor.mainWindow.append("\nSent request: " + send);
            serialPort.writeBytes(send.getBytes());
            Thread.sleep(WAIT_MS_POINTS);
            String answer = serialPort.readString();
            if (SERIAL_DEBUG)
                BeMapEditor.mainWindow.append("\nAnswer: " + answer);

            if (BeMapEditor.trackOrganiser.getData().treatData(answer) == nb)
                return 1;
            else
                return 0;

        } catch (SerialPortException ex) {
            Logger.getLogger(SimpleSerial.class.getName()).log(Level.SEVERE, null, ex);
            return 0;
        }
    }

    private int decodeNbPoints(String numberString) {
        //decompose the received data
        String[] lines = numberString.split("\n");
        int nbPoints = -1;

        for (int i = 0; i < lines.length; i++) {
            String[] seperated = lines[i].split(",");

            if ("$BMNUM".equals(seperated[0])) {
                nbPoints = Integer.parseInt(seperated[1]);
                return nbPoints;
            }

        }
        return nbPoints;

    }

    //returns usr id from string or -1 if error
    private int decodeUserID(String userString) {
        //decompose the received data
        String[] lines = userString.split("\n");

        for (int i = 0; i < lines.length; i++) {
            if (SERIAL_DEBUG)
                BeMapEditor.mainWindow.append(lines[i] + "\n");
            String[] seperated = lines[i].split(",");

            if ("$BMUSR".equals(seperated[0])) {
                return Integer.parseInt(seperated[1]);
            } else if ("$BMERR".equals(seperated[0])) {
                return -1;
            }

        }
        return -1;
    }

    class PortSearchTask implements Callable<String> {
        @Override
        public String call() throws Exception {
            String port = "NULL";
            SerialPort serialPort = new SerialPort(currentPortName);
            if (SERIAL_DEBUG)
                BeMapEditor.mainWindow.append("\nOpening port " + currentPortName);

            try {
                serialPort.openPort();//Open serial port
                serialPort.setParams(SerialPort.BAUDRATE_9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
                        SerialPort.PARITY_NONE);//Set params. Also you can set params by this string: serialPort.setParams(9600, 8, 1, 0);

                serialPort.writeBytes("$ORUSR*11\n".getBytes());//Write data to port
                Thread.sleep(WAIT_MS);
                byte[] buffer = serialPort.readBytes(1);//Read 1 bytes from serial port
                if (buffer[0] == 36)
                    port = currentPortName; //success on this port when device answers with $
                else if (SERIAL_DEBUG)
                    BeMapEditor.mainWindow.append("\nError: Port found but device doesn't answer with $");
                serialPort.closePort();//Close serial port
            } catch (SerialPortException ex) {
                //do not print error
                if (SERIAL_DEBUG)
                    BeMapEditor.mainWindow.append("\nOpening port " + currentPortName + " failed");
            }

            return port;
        }
    }

}