Search code examples
javaawtrobot

Passing data between class and running thread


Using code examples from stockoverflow I made a class to receive data over TCP/IP. Class code below. It is working OK and I do receive data from other PC. recPositions Map is build correctly. After transmission is finished I can display all data I received using getRecPositions()

This thread is started in other class that build simple HMI screen. Thread runs and display data received from other PC. Problem is I would like to access same data in MainWindow class (HMI) but it always show that nothing was received. Class MainWindow below (not all of it since there is lots of useless pushbuttons and so on) At the very bottom I have pushbutton that should display how many positions were recorded (elements in Map) but it always show 0. Code snippet from push button update.

System.out.println(dataServer.getRecPositions().size())

So at some point I am doing something wrong. Thread starts and runs and I can see incoming positions. At some point after I received "EOT" I display received positions stored in Map. But when I tried to display the size of Map in main window it always show 0.

/*
 * Simple data server for receiving string data from IIWA robot
 */
public class SimpleDataServer implements Runnable {

    Map<Integer, String> recPositions = new HashMap<>();
    Server1Connection oneconnection;
    ServerSocket echoServer = null;
    Socket clientSocket = null;
    int port;
    boolean reset = false;

    public SimpleDataServer( int port ) {
        this.port = port;
    }

    public void stopServer() {
        System.out.println( "Simple data server stopped" );
    }

    public void startServer() {
        // Try to open a server socket on the given port
        // Note that we can't choose a port less than 1024 if we are not
        // privileged users (root)

        try {
            echoServer = new ServerSocket(port);
        }
        catch (IOException e) {
            System.out.println(e);
        }   

        System.out.println( "Waiting for connections. Only one connection is allowed." );

        // Create a socket object from the ServerSocket to listen and accept connections.
        // Use Server1Connection to process the connection.

        while ( true ) {
            try {
                clientSocket = echoServer.accept();
                oneconnection = new Server1Connection(clientSocket, this); 
                oneconnection.run();
                if(isReset()) {
                    setReset(false);
                    System.out.println("Recording finished");
                    System.out.println("DEBUG:" + this.getRecPositions().size() + " positions recorded: " + this.getRecPositions());
                }
            }   
            catch (IOException e) {
                System.out.println(e);
            }
        }
    }

    @Override
    public void run() {
        int port = this.port;
        SimpleDataServer server = new SimpleDataServer( port );
        server.startServer();
    }

    public Map<Integer, String> getRecPositions() {
        return recPositions;
    }

    public void setRecPositions(Map<Integer, String> recPositions) {
        this.recPositions = recPositions;
    }

    public boolean isReset() {
        return reset;
    }

    public void setReset(boolean reset) {
        this.reset = reset;
    }

}

class Server1Connection {
    BufferedReader is;
    PrintStream os;
    Socket clientSocket;
    SimpleDataServer server;

    public Server1Connection(Socket clientSocket, SimpleDataServer server) {
        this.clientSocket = clientSocket;
        this.server = server;
        System.out.println( "Connection established with: " + clientSocket );
        try {
            is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            os = new PrintStream(clientSocket.getOutputStream());
        } catch (IOException e) {
            System.out.println(e);
        }
    }

    public Map<Integer, String> getPositions() {
        return server.getRecPositions();
    }

    public void run() {
        String line;    //whole line recevied
        String segment = null;  //single segment from line using comma delimiter
        List<String> stringsList;
        try {
            boolean serverStop = false;
            //server runs here
            while (true) 
            {
                line = is.readLine();
                System.out.println( "DEBUG Server Received: " + line );
                //check is string is not empty
                if (line.equals(null)) {
                    System.err.println("Empty String received");
                    break;
                }           
                stringsList = new ArrayList<String>(Arrays.asList(line.split(";")));
                if (!stringsList.isEmpty()) {
                    stringsList.set(0, stringsList.get(0).replaceAll("\\s+",""));
                    stringsList.set((stringsList.size()-1), stringsList.get(stringsList.size()-1).replaceAll("\\s+",""));

                    String lastSegment = stringsList.get((stringsList.size()-1));
                    if (lastSegment.equals("ETX") || lastSegment.equals("EOT")) {
                        switch (stringsList.get(0)) {
                        case "MSG":
                            stringsList.remove(0);
                            stringsList.remove(stringsList.size()-1);
                            System.out.println("Message: " + stringsList.toString());
                            break;
                        case "POS":
//                          for (String blah : stringsList) {
//                              System.out.println("DEBUG" + blah);
//                          }
                            iiwaPosfromString iiwaPos = new iiwaPosfromString(stringsList.get(1), stringsList.get(2));
                            System.out.println("DEBUG Position number: " + iiwaPos.posNum + " ; "  + iiwaPos.toString());
                            if (iiwaPos.getPosNum() > 0) {
                                server.getRecPositions().put(iiwaPos.getPosNum(), iiwaPos.toString());
                            }
                            break;

                        case "EOT":
                        case "EXT":
                            //ignore handled later
                            break;
                        default:
                            System.err.println("Ausgebombt!");
                            break;
                        }

                    }
                    //ETX End Of Text - dump data to screen - close current connection
                    if(lastSegment.equals("ETX")) {
                        System.out.println("End of Text received");
                        break;
                    }
                    //EOT End Of Transmission - shuts down server
                    if(lastSegment.equals("EOT")) {
                        System.out.println("End of Transmission received");
                        serverStop = true;
                        server.setReset(true);
                        break;
                    }
                    System.err.println("No correct end string!");
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    break;

                } else {
                    System.out.println("Empty String received");
                    break;
                }
            }

            System.out.println( "Connection closed." );
            is.close();
            os.close();
            clientSocket.close();

            if ( serverStop ) server.stopServer();
        } catch (IOException e) {
            System.out.println(e);
        }
    }


    public class iiwaPosfromString {
        private double posX;
        private double posY;
        private double posZ;
        private double posA;
        private double posB;
        private double posC;
        private int posNum;

        public iiwaPosfromString(String posNum, String posString) {
            List <String>stringsList = new ArrayList<String>(Arrays.asList(posString.split(" ")));
            for (int i = 0; i < stringsList.size(); i++) {
                String newElement = stringsList.get(i);
                newElement = newElement.replaceAll("[^\\d.]", "");
                stringsList.set(i, newElement);
            }
            this.setPosNum(Integer.parseInt(posNum));
            this.setPosX(Double.parseDouble(stringsList.get(1)));
            this.setPosY(Double.parseDouble(stringsList.get(2)));
            this.setPosZ(Double.parseDouble(stringsList.get(3)));
            //this is stupid and don't do that
            //from right to left, string to double, change radians to degrees, format to two decimals(string), string to double again
            this.setPosA(Double.parseDouble(String.format("%.2f",(Math.toDegrees(Double.parseDouble(stringsList.get(4)))))));
            this.setPosB(Double.parseDouble(String.format("%.2f",(Math.toDegrees(Double.parseDouble(stringsList.get(4)))))));
            this.setPosC(Double.parseDouble(String.format("%.2f",(Math.toDegrees(Double.parseDouble(stringsList.get(4)))))));
        }

        public double getPosX() {
            return posX;
        }

        public void setPosX(double posX) {
            this.posX = posX;
        }

        public double getPosY() {
            return posY;
        }

        public void setPosY(double posY) {
            this.posY = posY;
        }

        public double getPosZ() {
            return posZ;
        }

        public void setPosZ(double posZ) {
            this.posZ = posZ;
        }

        public double getPosA() {
            return posA;
        }

        public void setPosA(double posA) {
            this.posA = posA;
        }

        public double getPosB() {
            return posB;
        }

        public void setPosB(double posB) {
            this.posB = posB;
        }

        public double getPosC() {
            return posC;
        }

        public void setPosC(double posC) {
            this.posC = posC;
        }
        @Override
        public String toString() {
            return  "<" +
                    "X: " + getPosX() + ", " +
                    "Y: " + getPosY() + ", " +
                    "Z: " + getPosZ() + ", " +
                    "A: " + getPosA() + ", " +
                    "B: " + getPosB() + ", " +
                    "C: " + getPosC() +
                    ">";
        }

        public int getPosNum() {
            return posNum;
        }

        public void setPosNum(int posNum) {
            this.posNum = posNum;
        }
    }
}


public class MainWindow {

    private Thread dataServerThread;
    private SimpleDataServer dataServer;
    private XmlParserGlobalVarsRD globalVarPLC, globalVarKRC;
    private JFrame frame;
    private JTextField simpleWorkingDirStiffness;
    private JTextField simpleWorkingDirAdditionalForce;
    private JTextField simpleTravelDistance;
    private JTextField simpleTravelVelocity;
    private JTextField simpleTotalTime;
    private JTextField simpleTheoreticalDepth;
    private JTextField simpleZProgress;
    private JComboBox oscillationMode;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
        } catch (Throwable e) {
            e.printStackTrace();
        }
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    MainWindow window = new MainWindow();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public MainWindow() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {

        final JCheckBox emptyScanCycle = new JCheckBox("VRSI Scan Cycle Plain Fasteners");

        //set data server thread and start it
        dataServer = new SimpleDataServer(30008);
        dataServerThread = new Thread(dataServer);
        dataServerThread.setDaemon(true);
        dataServerThread.start();

...

        JButton pbUpdate = new JButton("UPDATE");
        pbUpdate.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                System.out.println(dataServer.getRecPositions().size()) 
            }
        });
        pbUpdate.setBounds(210, 176, 90, 28);
        frame.getContentPane().add(pbUpdate);

    }

Solution

  • I believe the issue is in your SimpleDataServer.run method. You are creating a separate instance of SimpleDataServer from WITHIN your SimpleDataServer instance. Therefore, all of the communication is taking place in an object that your MainWindow has no direct reference to. I believe your SimpleDataServer.run method should look like this:

    @Override
    public void run() {
        this.startServer();
    }