package Connection; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.image.BufferedImage; import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.text.NumberFormat; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFormattedTextField; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.text.NumberFormatter; import api.AddOn; import classes.AbstractCanvasObject; import classes.GroupNode; import classes.HolonElement; import classes.HolonObject; import ui.controller.Control; import ui.view.Console; /** * Easy Connection via Http Request. Repeat Request with a delay. * * @author tom * */ public class ConnectPhysical implements AddOn{ //Holeg private Control control; //Gui private JPanel content = new JPanel(); private Console console; private JLabel rotorLabel; private JLabel houseLabel; private boolean onlyOnChange = false; // Future future; private boolean lessInformation = false; private int delay = 1000; JLabel warningLabel; public enum HolonObjectStatus{ Connected , NotSelected, ObjectDeleted } public class PhysicalLinkWrapper{ public HolonObject hObject; public HolonObjectStatus status; public String postAddress; PhysicalLinkWrapper(HolonObject hObject, HolonObjectStatus status, String postAddress){ this.hObject = hObject; this.status = status; this.postAddress = postAddress; } } //Object to look at PhysicalLinkWrapper rotor = new PhysicalLinkWrapper(null, HolonObjectStatus.NotSelected, "/rotor/"); //Because House is special PhysicalLinkWrapper house = new PhysicalLinkWrapper(null, HolonObjectStatus.NotSelected, "notUsed"); String room1Address = "/room1/"; String room2Address = "/room2/"; //the keywords are for the sepreation in 2 rooms String room1Keyword = "room1"; String room2Keyword = "room2"; //OnChange int oldValueRotor = -1; int oldValueRoom1 = -1; int oldValueRoom2 = -1; public static void main(String[] args) { JFrame newFrame = new JFrame("exampleWindow"); ConnectPhysical instance = new ConnectPhysical(); newFrame.setContentPane(instance.getPanel()); newFrame.pack(); newFrame.setVisible(true); newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public ConnectPhysical() { content.setLayout(new BorderLayout()); console = new Console(); JScrollPane scrollPane = new JScrollPane(console); JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, createOptionPanel() , scrollPane); splitPane.setResizeWeight(0.0); content.add(splitPane, BorderLayout.CENTER); content.setPreferredSize(new Dimension(800,800)); } private Component createOptionPanel() { JPanel optionPanel = new JPanel(new BorderLayout()); JScrollPane scrollPane = new JScrollPane(createParameterPanel()); scrollPane.setBorder(BorderFactory.createTitledBorder("Settings")); optionPanel.add(scrollPane, BorderLayout.CENTER); optionPanel.add(createButtonPanel(), BorderLayout.PAGE_END); return optionPanel; } private Component createParameterPanel() { JPanel parameterPanel = new JPanel(null); parameterPanel.setPreferredSize(new Dimension(510,300)); JLabel lessInformationLabel = new JLabel("Less information in Console:"); lessInformationLabel.setBounds(200, 180, 200, 20); parameterPanel.add(lessInformationLabel); JCheckBox lessInformationCheckBox = new JCheckBox(); lessInformationCheckBox.setSelected(false); lessInformationCheckBox.setBounds(400, 180, 25, 20); lessInformationCheckBox.addActionListener(actionEvent -> { lessInformation = lessInformationCheckBox.isSelected(); }); parameterPanel.add(lessInformationCheckBox); JLabel onlyOnChangeLabel = new JLabel("OnlyOnChange:"); onlyOnChangeLabel.setBounds(200, 240, 200, 20); parameterPanel.add(onlyOnChangeLabel); JCheckBox onlyOnChangeCheckBox = new JCheckBox(); onlyOnChangeCheckBox.setSelected(false); onlyOnChangeCheckBox.setBounds(400, 240, 25, 20); onlyOnChangeCheckBox.addActionListener(actionEvent -> { onlyOnChange = onlyOnChangeCheckBox.isSelected(); }); parameterPanel.add(onlyOnChangeCheckBox); JLabel delayLabel = new JLabel("Delay:"); delayLabel.setBounds(200, 210, 50, 20); parameterPanel.add(delayLabel); JLabel delayUnitLabel = new JLabel("[ms]"); delayUnitLabel.setBounds(300, 210, 50, 20); parameterPanel.add(delayUnitLabel); warningLabel = new JLabel(stringToHtml(stringWithColor("You need to Stop and Run again to affect delay change.", "red"))); warningLabel.setBounds(200, 280, 400, 20); warningLabel.setVisible(false); parameterPanel.add(warningLabel); //Integer formatter NumberFormat format = NumberFormat.getIntegerInstance(); format.setGroupingUsed(false); format.setParseIntegerOnly(true); NumberFormatter integerFormatter = new NumberFormatter(format); integerFormatter.setMinimum(0); integerFormatter.setCommitsOnValidEdit(true); JFormattedTextField delayTextField = new JFormattedTextField(integerFormatter); delayTextField.setValue(delay); delayTextField.setToolTipText("Only positive Integer."); delayTextField.addPropertyChangeListener(actionEvent -> { delay = Integer.parseInt(delayTextField.getValue().toString()); if(future != null && !future.isCancelled()) { console.println("You need to Stop and Run again to affect this change."); warningLabel.setVisible(true); } }); delayTextField.setBounds(250, 210, 50, 20); parameterPanel.add(delayTextField); rotorLabel = new JLabel(stringToHtml("Rotor Status: " + statusToString(rotor.status))); rotorLabel.setBounds(200, 60, 220, 30); parameterPanel.add(rotorLabel); houseLabel = new JLabel(stringToHtml("House Status: " + statusToString(house.status))); houseLabel.setBounds(200, 90, 220, 30); parameterPanel.add(houseLabel); JLabel keywordsLabel = new JLabel("Room Seperation Keywords: " + room1Keyword + " " + room2Keyword); keywordsLabel.setBounds(200, 120, 320, 30); parameterPanel.add(keywordsLabel); JLabel keywordsHintLabel = new JLabel("HolonElements with a name that contains the Keyword count."); keywordsHintLabel.setBounds(200, 135, 450, 30); parameterPanel.add(keywordsHintLabel); JButton selectRotorButton = new JButton("Select"); selectRotorButton.setBounds(420,65, 90, 20); selectRotorButton.addActionListener(actionEvent -> this.selectGroupNode(rotor)); parameterPanel.add(selectRotorButton); JButton selectRoom1Button = new JButton("Select"); selectRoom1Button.setBounds(420,95, 90, 20); selectRoom1Button.addActionListener(actionEvent -> this.selectGroupNode(house)); parameterPanel.add(selectRoom1Button); return parameterPanel; } private String stringToHtml(String string) { return "" + string + ""; } private String statusToString(HolonObjectStatus status) { switch(status) { case Connected: return stringWithColor("Connected", "green"); case NotSelected: return stringWithColor("Not selected", "red"); case ObjectDeleted: return stringWithColor("Object deleted", "red"); default: return ""; } } private String stringWithColor(String string, String color) { return "" + string + ""; } private void updateStatusLabels() { rotorLabel.setText(stringToHtml("Rotor Status: " + statusToString(rotor.status))); houseLabel.setText(stringToHtml("House Status: " + statusToString(house.status))); } private Component createButtonPanel() { JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); JButton clearButton = new JButton("Clear Console"); clearButton.addActionListener(actionEvent -> console.clear()); buttonPanel.add(clearButton); JButton stopButton = new JButton("Stop"); stopButton.addActionListener(actionEvent -> stop()); buttonPanel.add(stopButton); JButton runButton = new JButton("Run"); runButton.addActionListener(actionEvent -> initSchedule()); buttonPanel.add(runButton); return buttonPanel; } private void stop() { if(future!= null) { if(future.isCancelled()) { console.println("Is cancelled."); } else { future.cancel(true); console.println("Stopped sending Requests on localhost:2019 ..."); } } else { console.println("Not started jet."); } } private void initSchedule() { if(future != null && !future.isCancelled()) { console.println("Is running."); return; } warningLabel.setVisible(false); console.println("Starting sending Requests on localhost:2019"); final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); final Runnable beeper = new Runnable() { //RepeatedMethod public void run() { if(lessInformation)console.print("."); checkWrapper(rotor); checkWrapperHouseSpecial(house); } private void checkWrapper(PhysicalLinkWrapper wrapper) { if(wrapper.status == HolonObjectStatus.Connected) checkConnected(wrapper); else if(!lessInformation)console.println(wrapper.postAddress +" is not connected."); } private void checkConnected(PhysicalLinkWrapper wrapper) { if(wrapper.hObject == null) { wrapper.status = HolonObjectStatus.ObjectDeleted; updateStatusLabels(); return; } if(wrapper.hObject.getNumberOfElements() > 0) { //OnlyForRotor int value = Math.round(((float)wrapper.hObject.getNumberOfActiveElements()/(float) wrapper.hObject.getNumberOfElements())*(float) 100); if(onlyOnChange) { if(oldValueRotor != value) { sendRequest(wrapper.postAddress, value); oldValueRotor = value; } }else { sendRequest(wrapper.postAddress, value); } }else { if(onlyOnChange) { if(oldValueRotor != 0) { sendRequest(wrapper.postAddress, 0); oldValueRotor = 0; } }else { sendRequest(wrapper.postAddress, 0); } } } private void sendRequest(String postAddress, int value) { if(!lessInformation)console.println("Send " + "http://localhost:2019" + postAddress + value); doHttpUrlConnectionAction("http://localhost:2019" + postAddress + value); } /** * Send A Request to a URL. * * @param desiredUrl * @return */ private void doHttpUrlConnectionAction(String desiredUrl) { URL url = null; // create the HttpURLConnection try { url = new URL(desiredUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // just want to do an HTTP GET here connection.setRequestMethod("GET"); connection.getResponseCode(); // give it 15 seconds to respond connection.setReadTimeout(1000); connection.connect(); } catch (MalformedURLException e) { console.println("MalformedURLException"); e.printStackTrace(); } catch (IOException e) { console.println("IOException: Connection refused"); e.printStackTrace(); } } private void checkWrapperHouseSpecial(PhysicalLinkWrapper house) { if(!(house.status == HolonObjectStatus.Connected)) { if(!lessInformation)console.println("House" + " is not connected."); return; } //House is Connected if(house.hObject == null) { house.status = HolonObjectStatus.ObjectDeleted; updateStatusLabels(); return; } //House exist List elementsOfRoom1 = house.hObject.getElements().stream().filter(ele -> ele.getEleName().contains(room1Keyword)).collect(Collectors.toList()); List elementsOfRoom2 = house.hObject.getElements().stream().filter(ele -> ele.getEleName().contains(room2Keyword)).collect(Collectors.toList()); if(elementsOfRoom1.isEmpty()){ if(onlyOnChange) { if(oldValueRoom1 != 0) { sendRequest(room1Address, 0); oldValueRoom1 = 0; } }else { sendRequest(room1Address, 0); } } else{ int value = Math.round(((float)elementsOfRoom1.stream().filter(ele -> ele.isActive()).count()/(float) elementsOfRoom1.size())*(float) 100); if(onlyOnChange) { if(oldValueRoom1 != value) { sendRequest(room1Address, value); oldValueRoom1 = value; } }else { sendRequest(room1Address, value); } } if(elementsOfRoom2.isEmpty()){ if(onlyOnChange) { if(oldValueRoom2 != 0) { sendRequest(room2Address, 0); oldValueRoom2 = 0; } }else { sendRequest(room2Address, 0); } } else{ int value = Math.round(((float)elementsOfRoom2.stream().filter(ele -> ele.isActive()).count()/(float) elementsOfRoom2.size())*(float) 100); if(onlyOnChange) { if(oldValueRoom2 != value) { sendRequest(room2Address, value); oldValueRoom2 = value; } }else { sendRequest(room2Address, value); } } } }; future = executorService.scheduleAtFixedRate(beeper, 0, delay, TimeUnit.MILLISECONDS); } private void addObjectToList(List listToSearch, List listToAdd){ for (AbstractCanvasObject aCps : listToSearch) { if (aCps instanceof HolonObject) listToAdd.add((HolonObject) aCps); else if(aCps instanceof GroupNode) { addObjectToList(((GroupNode)aCps).getNodes(),listToAdd); } } } //SelectGroupNode private void selectGroupNode(PhysicalLinkWrapper wrapper) { List holonObjectList = new ArrayList(); addObjectToList(control.getModel().getObjectsOnCanvas(),holonObjectList); Object[] possibilities = holonObjectList.stream().map(aCps -> new Handle(aCps)).toArray(); @SuppressWarnings("unchecked") Handle selected = (Handle) JOptionPane.showInputDialog(content, "Select HolonObject:", "HolonObject?", JOptionPane.OK_OPTION,new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)) , possibilities, ""); if(selected != null) { console.println("Selected: " + selected); wrapper.hObject = selected.object; wrapper.status = HolonObjectStatus.Connected; updateStatusLabels(); } } private class Handle{ public T object; Handle(T object){ this.object = object; } public String toString() { return object.toString(); } } @Override public JPanel getPanel() { return content; } @Override public void setController(Control control) { this.control = control; } }