Overview

IoT with Java 8 and TinkerForge – 003

No Comments

Today we are going to dive further into IoT. The focus is on the DualButton-Bricklet of TinkerForge. How can we communicate bidirectionally? What are the possibilities of interaction with the electronics? All this will be the preperation for further manual
elements.

We are used to the fact that we can have skin contact to the electronics. To be more precise: finger contact. The DualButton-Bricklet provides the possibility to send manual impulses which can be processed on the Java side. But also the way back to the bricklet
is possible. Today we are going to look at this more closely.

The DualButton-Bricklet
=======================
The DualButton-Bricklet can be linked to the MasterBrick like the others. This way we have two push buttons. Both buttons have a blue implemented LED. The current state of the button (pressed/not pressed) and the LED (on/off) can be read all the time.
Those states can also be set programmatically.

Usage of the Buttons
====================
The linking of the DualButton-Bricklet can also be achieved through the configuration of the encapsulating instance of the element and the implementation of the ActionListener (!kursiv) within which we get the values. Because of the two
seperate buttons on the bricklet there are basically two states “pressed” and “released”. Both states are represented by 0 for “released” and 1 for “pressed”. Similar to the previous articles we are going to put the bricklet and the ActionListener
in a seperate class which implements the interface Runnable . This class is called Worker .

public class Worker implements Runnable{
    @Override
    public void run() {
        try {
            ipcon.connect(host, port);
            final BrickletDualButton.StateChangedListener changedListener
                    = (buttonL, buttonR, ledL, ledR) -> runLater(() -> {
 
                if (buttonL == BrickletDualButton.BUTTON_STATE_PRESSED) {
                    setMsg("Left button pressed");
                    activateLeftButton();
                }
                if (buttonL == BrickletDualButton.BUTTON_STATE_RELEASED) {
                    setMsg("Left button released");
                }
                if (buttonR == BrickletDualButton.BUTTON_STATE_PRESSED) {
                    setMsg("Right button pressed");
                    activateRightButton();
                }
                if (buttonR == BrickletDualButton.BUTTON_STATE_RELEASED) {
                    setMsg("Right button released");
                }
            });
 
            db.addStateChangedListener(changedListener);
            db.setLEDState(LED_STATE_ON, LED_STATE_ON );
 
        } catch (IOException
                | AlreadyConnectedException
                | TimeoutException
                | NotConnectedException e) {
            e.printStackTrace();
        }
    }
 
    private void setMsg(String msg) {
        tx.setText(msg.concat(newline).concat(tx.getText()));
    }
}

Within the ActionListener we again get the required values. In our case we get always both states of the buttons. If only the pressed-state is relevant we can easily check and interact on the individual state like shown in listing 1.
If you want to know when the taster has been released you also have to remember the last state change. This way you can get the difference over the timestamp. At first we set the state of both LEDs once to active/illuminated.
In our example both methods activateRightButton() and activateLeftButton() of the class worker have been moved to the class ButtonMaster . The only reason for this is that both methods (listing2) can be reused in another location.

private void activateRightButton() {
    try {
        db.setLEDState(LED_STATE_OFF, LED_STATE_ON);
        bL.setText("InActive");
        bR.setText("Active");
    } catch (TimeoutException | NotConnectedException e) {
        e.printStackTrace();
    }
}
 
private void activateLeftButton() {
    try {
        db.setLEDState(LED_STATE_ON, LED_STATE_OFF);
        bL.setText("Active");
        bR.setText("InActive");
 
    } catch (TimeoutException | NotConnectedException e) {
        e.printStackTrace();
    }
}

Within these methods the state of each LED is set on the one hand, on the other hand the text of both JavaFX buttons is set inverted (active/inActive). This way pressing a button is not just shown through the LEDs but also with the text of the two Buttons in
the JavaFX GUI. This way we have shown the path from the hardware to the GUI. But how does it go from JavaFX to the button?

Linking to JavaFX
=================

The linking of both buttons to JavaFX can basically be achieved the same way as in the articles before. Remember: The basic principal is that the JavaFX application is started out of a thread. The latter configures the element and adds the ActionListener in the run()-method (!kursiv). Important is that the parts which are updating JavaFX-GUI elements have to be encapsulated in Platform.runLater(). The call is then quite easy:

public class ButtonMaster extends Application {
    private static final String host = "localhost";
    private static final int port = 4223;
    private static final String UID = "j5K";
    public static String newline = System.getProperty("line.separator");
 
    private final IPConnection ipcon = new IPConnection();
    private final BrickletDualButton db 
        = new BrickletDualButton(UID, ipcon);
 
    public static void main(String[] args) {
        launch(args);
    }
 
    public Button bL;
    public Button bR;
 
    public TextArea tx;
 
    @Override
    public void start(Stage stage) {
        stage.setTitle("Button TinkerForge Sample");
 
        final VBox vBox = new VBox();
        setAnchorZero(vBox);
        final HBox hBox = new HBox();
        setAnchorZero(hBox);
        bL = new Button("LED links");
        bR = new Button("LED rechts");
 
        setAnchorZero(bL);
        setAnchorZero(bR);
 
        bL.setOnAction(actionEvent -> activateLeftButton());
        bR.setOnAction(actionEvent -> activateRightButton());
 
        hBox.getChildren().add(bL);
        hBox.getChildren().add(bR);
 
        vBox.getChildren().add(hBox);
 
        tx = new TextArea();
        vBox.getChildren().add(tx);
 
 
        Scene scene = new Scene(vBox);
        stage.setScene(scene);
 
        runLater(new Worker());
 
        stage.show();
 
    }
 
    private void setAnchorZero(final Node node) {
        AnchorPane.setBottomAnchor(node, 0.0);
        AnchorPane.setLeftAnchor(node, 0.0);
        AnchorPane.setRightAnchor(node, 0.0);
        AnchorPane.setTopAnchor(node, 0.0);
    }
 
 
    public class Worker implements Runnable {
        @Override
        public void run() {
            try {
                ipcon.connect(host, port);
 
                db.addStateChangedListener(
                  (buttonL, buttonR, ledL, ledR) -> runLater(() -> {
                    if (buttonL == BUTTON_STATE_PRESSED) {
                        setMsg("Left button pressed");
                        activateLeftButton();
                    }
                    if (buttonL == BUTTON_STATE_RELEASED) {
                        setMsg("Left button released");
                    }
                    if (buttonR == BUTTON_STATE_PRESSED) {
                        setMsg("Right button pressed");
                        activateRightButton();
                    }
                    if (buttonR == BUTTON_STATE_RELEASED) {
                        setMsg("Right button released");
                    }
                }));
                db.setLEDState(LED_STATE_ON, LED_STATE_ON);
            } catch (IOException
                    | AlreadyConnectedException
                    | TimeoutException
                    | NotConnectedException e) {
                e.printStackTrace();
            }
        }
        private void setMsg(String msg) {
            tx.setText(msg.concat(newline).concat(tx.getText()));
        }
    }
 
    private void activateRightButton() {
        try {
            db.setLEDState(LED_STATE_OFF, LED_STATE_ON);
            bL.setText("InActive");
            bR.setText("Active");
        } catch (TimeoutException | NotConnectedException e) {
            e.printStackTrace();
        }
    }
 
    private void activateLeftButton() {
        try {
            db.setLEDState(LED_STATE_ON, LED_STATE_OFF);
            bL.setText("Active");
            bR.setText("InActive");
        } catch (TimeoutException | NotConnectedException e) {
            e.printStackTrace();
        }
    }
}

Now we show the way from the JavaFX-Buttons to the hardware. When pushing one of the two software buttons the corresponding LED is activated. The only thing that is required for that is the call of the intended method activate(Left/Right)Button().
Now we have a flow of the GUI to the hardware and back. Here we have to note that the pushing of the software Button does not move the physical button. You can see the full JavaFX application in listing3.

Conclusion
==========
With the DualButton-Bricklet for the first time we have the possibility to start manually software processes via mechanical button. We are going to show in detail in the next articles what you can realize with that. Until then: Stay tuned and happy coding.

The source code to this article can be found under
https://bitbucket.org/rapidpm/jaxenter.de-0012-iot-tinkerforge .
For people who are interested in more complex examples I recommend the following
https://bitbucket.org/rapidpm/modules .

Comment

Your email address will not be published. Required fields are marked *