Newer
Older
IoTP / src / main / java / info / istlab / IoTP / MqttWindow.java
@motoki miura motoki miura on 8 Apr 2024 11 KB v0.51 mqtt
package info.istlab.IoTP;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

public class MqttWindow extends JFrame implements ActionListener, WindowListener, MqttCallback, Runnable, KeyListener {
    static MqttWindow theMqttWindow;
    JTextField jtf;
    JTextArea jta;
    Thread thread;

    JTextField brokerjtf;
    JTextField brokerportjtf;
    JTextField topicjtf;
    JButton connectB;
    MqttSubscriber subscriber;

    public static MqttWindow create() {
        if (theMqttWindow != null)
            return theMqttWindow;
        else
            theMqttWindow = new MqttWindow();
        return theMqttWindow;
    }

    public static void main(String[] args) {
        new MqttWindow();
    }

    public MqttWindow() {
        super("MQTT TestApp");

        brokerjtf = new JTextField("mqtt.istlab.info", 30);
        brokerjtf.addKeyListener(this);
        // brokerjtf = new JTextField("10.104.91.19", 30);
        brokerportjtf = new JTextField("1883", 10);
        brokerportjtf.addKeyListener(this);
        topicjtf = new JTextField("+");
        topicjtf.addKeyListener(this);
        connectB = new JButton("Connect");
        connectB.addKeyListener(this);
        connectB.addActionListener(e -> connect(e));

        JPanel settingP = new JPanel();
        settingP.setLayout(new BoxLayout(settingP, BoxLayout.Y_AXIS));
        JPanel v01p = new JPanel(new BorderLayout());
        v01p.setBorder(BorderFactory
                .createTitledBorder("Broker ( ex. mqtt.istlab.info ) and port ( ex. 1883 )"));
        v01p.add(brokerjtf, BorderLayout.CENTER);
        v01p.add(brokerportjtf, BorderLayout.EAST);
        settingP.add(v01p);
        JPanel v02p = new JPanel(new BorderLayout());
        v02p.setBorder(BorderFactory.createTitledBorder("Topic ( ex. jikken | jikken/A1han | jikken/+ )"));
        v02p.add(topicjtf);
        v02p.add(connectB, BorderLayout.EAST);
        settingP.add(v02p);

        jtf = new JTextField("(ここをクリックして、入力して、Enterを押すと、publishします)");
        jtf.addKeyListener(this);
        jtf.setForeground(Color.GRAY);
        jtf.addFocusListener(new FocusListener() {
            @Override
            public void focusGained(FocusEvent e) {
                if (jtf.getText().equals("(ここをクリックして、入力して、Enterを押すと、publishします)")) {
                    jtf.setText("");
                    jtf.setForeground(Color.BLACK);
                }
            }

            @Override
            public void focusLost(FocusEvent e) {
                if (jtf.getText().isEmpty()) {
                    jtf.setForeground(Color.GRAY);
                    jtf.setText("(ここをクリックして、入力して、Enterを押すと、publishします)");
                }
            }
        });
        jtf.setBackground(new Color(210, 255, 255));
        // settingP.add(jtf);

        getContentPane().add(settingP, BorderLayout.NORTH);
        jta = new JTextArea();
        jta.addKeyListener(this);
        jta.setBackground(Color.lightGray);
        getContentPane().add(new JScrollPane(jta), BorderLayout.CENTER);

        JPanel v03p = new JPanel(new BorderLayout());
        v03p.setBorder(BorderFactory.createTitledBorder("Publish to the topic (未接続でもTopicが指定されていれば送信できます)"));
        v03p.add(jtf);

        getContentPane().add(v03p, BorderLayout.SOUTH);
        // compileB = new JButton("compile");
        // compileB.addActionListener(e -> {
        // compile(e.getActionCommand());
        // });
        // getContentPane().add(compileB, BorderLayout.SOUTH);

        setSize(600, 500);
        setLocation(centerOfScreen(getSize()));
        setVisible(true);
        setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        jtf.addActionListener(this);
        addWindowListener(this); // Xをおしたらserial closeする
        addKeyListener(this);

        // フォーカスをあえて外す
        // jta.requestFocus();
        appendToJTA("まだ接続していません。Topicを設定してConnectをおしてください。\n");
    }

    @Override
    public void run() {
        subscriber = new MqttSubscriber(brokerjtf.getText(), brokerportjtf.getText(), topicjtf.getText(), this);
        jta.setBackground(Color.YELLOW);
        appendToJTA("Try Connecting to broker : tcp://" + brokerjtf.getText() + ":" + brokerportjtf.getText() + "\n");
        try {
            subscriber.subscribe();
        } catch (MqttException | InterruptedException e1) {
            e1.printStackTrace();
            appendToJTA("接続できませんでした。\n");
            jta.setBackground(Color.magenta);
            thread = null;
            subscriber = null;
            return;
        }
        appendToJTA("Connected.\n");
        jta.setBackground(Color.white);
        topicjtf.setEditable(false);
        connectB.setText("Disconnect");
    }

    private void connect(ActionEvent e) {
        if (e.getActionCommand().equals("Connect")) {
            if (thread != null) {
                JOptionPane.showMessageDialog(this, "まだ接続試行中です...");
                return;
            }
            thread = new Thread(this);
            thread.start();
        } else if (e.getActionCommand().equals("Disconnect")) {
            try {
                subscriber.unsubscribe();
            } catch (MqttException | InterruptedException e1) {
                e1.printStackTrace();
            } finally {
                subscriber = null;
                appendToJTA("Disconnected.\n");
                jta.setBackground(Color.gray);
                topicjtf.setEditable(true);
            }
            connectB.setText("Connect");
            thread = null;
        }
    }

    void appendToJTA(String s) {
        if (jta == null)
            return;
        jta.append(s);
        int len = jta.getDocument().getLength();
        if (jta.getSelectedText() == null)
            jta.setCaretPosition(len);
    }

    // ここで、画面中心にウィンドウ表示するため、いろいろ計算する
    public static Point centerOfScreen(Dimension winSize) {
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        return new Point((screenSize.width - winSize.width) / 2, (screenSize.height - winSize.height) / 2);
    }

    // ここで、画面中心にウィンドウ表示するため、いろいろ計算する
    public static Point leftOfScreen(Dimension winSize) {
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        return new Point(10, (screenSize.height - winSize.height) / 2);
    }

    /**
     * 送信(publish)する
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        String message = e.getActionCommand();
        // System.out.println(action);
        try {
            if (message.length() > 0) {
                // Topic name check
                String topic = topicjtf.getText();
                if (topic.contains("#") || topic.contains("+")) {
                    appendToJTA("Publishするとき、Topic にワイルドカード文字 #+ を含めることはできません。");
                    return;
                }
                MqttPublisher publisher = new MqttPublisher(brokerjtf.getText(),
                        topicjtf.getText());
                publisher.publish(message);
            }

        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }

    // /**
    // * 再接続用(つかっていない)
    // */
    // @Override
    // public void run() {
    // appendToJTA("(Waiting to reconnect.)\n");
    // try {
    // Thread.sleep(10000);
    // } catch (InterruptedException e) {
    // }
    // while (thread != null) {
    // if (!sp.openPort()) {
    // System.out.println("Unable to open the port.");
    // return;
    // } else {
    // thread = null;
    // appendToJTA("Reconnected.\n");
    // }
    // try {
    // Thread.sleep(2000);
    // } catch (InterruptedException e) {
    // }

    // }
    // }

    private void closeWin() {
        if (subscriber != null) {
            try {
                subscriber.unsubscribe();
            } catch (MqttException | InterruptedException e1) {
                e1.printStackTrace();
            } finally {
                subscriber = null;
                appendToJTA("Disconnected.\n");
                jta.setBackground(Color.gray);
            }
        }
        MqttWindow.theMqttWindow = null;
        connectB.setText("Connect");
        if (Launcher.theapp == null || !Launcher.theapp.isVisible())
            System.exit(0);
        else {
            setVisible(false);
            dispose();
        }
    }

    @Override
    public void windowOpened(WindowEvent e) {
    }

    @Override
    public void windowClosing(WindowEvent e) {
        closeWin();
    }

    @Override
    public void windowClosed(WindowEvent e) {
        closeWin();
    }

    @Override
    public void windowIconified(WindowEvent e) {
    }

    @Override
    public void windowDeiconified(WindowEvent e) {
    }

    @Override
    public void windowActivated(WindowEvent e) {
    }

    @Override
    public void windowDeactivated(WindowEvent e) {
    }

    /**
     * MQTTブローカーとの接続を失った時に呼び出される.
     */
    @Override
    public void connectionLost(Throwable cause) {
        System.out.println("Connection lost");
        System.exit(1);
    }

    /**
     * メッセージを受信したときに呼び出される.
     */
    @Override
    public void messageArrived(String topic, MqttMessage message) throws MqttException {
        // System.out.println("Message arrived");
        appendToJTA("Topic : " + topic + "  Message: " + new String(message.getPayload()) + "\n");
        // recieveTime = new Timestamp(System.currentTimeMillis());
        // MqttThread.recieveData = new String(message.getPayload());
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        throw new UnsupportedOperationException("Unimplemented method 'deliveryComplete'");
    }


    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (e.isControlDown() || e.isAltDown() || e.isAltGraphDown() || e.isMetaDown()) {
            if (e.getKeyCode() == 87) { // W
                closeWin();
            }
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }


}