/*
* Copyright (c) 2014, Jens Deters
* http://www.jensd.de
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package de.jensd.raspi.adapter;
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalMultipurpose;
import com.pi4j.io.gpio.PinMode;
import com.pi4j.io.gpio.PinPullResistance;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;
import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent;
import com.pi4j.io.gpio.event.GpioPinListenerDigital;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.util.Duration;
/*
*
* @author Jens Deters
*/
public class GpioAdapter {
private GpioController gpio;
private GpioPinDigitalMultipurpose pin0;
private GpioPinDigitalMultipurpose pin1;
private GpioPinDigitalMultipurpose pin2;
private GpioPinDigitalMultipurpose pin3;
private GpioPinDigitalMultipurpose pin4;
private GpioPinDigitalMultipurpose pin5;
private GpioPinDigitalMultipurpose pin6;
private GpioPinDigitalMultipurpose pin7;
private ObjectProperty<PinMode> gpio0ModeProperty;
private ObjectProperty<PinMode> gpio1ModeProperty;
private ObjectProperty<PinMode> gpio2ModeProperty;
private ObjectProperty<PinMode> gpio3ModeProperty;
private ObjectProperty<PinMode> gpio4ModeProperty;
private ObjectProperty<PinMode> gpio5ModeProperty;
private ObjectProperty<PinMode> gpio6ModeProperty;
private ObjectProperty<PinMode> gpio7ModeProperty;
private BooleanProperty gpio0StateProperty;
private BooleanProperty gpio1StateProperty;
private BooleanProperty gpio2StateProperty;
private BooleanProperty gpio3StateProperty;
private BooleanProperty gpio4StateProperty;
private BooleanProperty gpio5StateProperty;
private BooleanProperty gpio6StateProperty;
private BooleanProperty gpio7StateProperty;
private BooleanProperty connectedProperty;
private Timeline testTimeline;
private GpioPinDigitalMultipurpose[] pins;
private BooleanProperty[] stateProperties;
private ObjectProperty<PinMode>[] modeProperties;
private final static Logger LOGGER = Logger.getLogger(GpioAdapter.class.getName());
public GpioAdapter() {
init();
}
private void init() {
connectedProperty = new SimpleBooleanProperty(Boolean.FALSE);
gpio0StateProperty = new SimpleBooleanProperty(Boolean.FALSE);
gpio1StateProperty = new SimpleBooleanProperty(Boolean.FALSE);
gpio2StateProperty = new SimpleBooleanProperty(Boolean.FALSE);
gpio3StateProperty = new SimpleBooleanProperty(Boolean.FALSE);
gpio4StateProperty = new SimpleBooleanProperty(Boolean.FALSE);
gpio5StateProperty = new SimpleBooleanProperty(Boolean.FALSE);
gpio6StateProperty = new SimpleBooleanProperty(Boolean.FALSE);
gpio7StateProperty = new SimpleBooleanProperty(Boolean.FALSE);
stateProperties = new BooleanProperty[]{gpio0StateProperty,
gpio1StateProperty,
gpio2StateProperty,
gpio3StateProperty,
gpio4StateProperty,
gpio5StateProperty,
gpio6StateProperty,
gpio7StateProperty
};
gpio0ModeProperty = new SimpleObjectProperty<>(PinMode.DIGITAL_OUTPUT);
gpio1ModeProperty = new SimpleObjectProperty<>(PinMode.DIGITAL_OUTPUT);
gpio2ModeProperty = new SimpleObjectProperty<>(PinMode.DIGITAL_OUTPUT);
gpio3ModeProperty = new SimpleObjectProperty<>(PinMode.DIGITAL_OUTPUT);
gpio4ModeProperty = new SimpleObjectProperty<>(PinMode.DIGITAL_OUTPUT);
gpio5ModeProperty = new SimpleObjectProperty<>(PinMode.DIGITAL_OUTPUT);
gpio6ModeProperty = new SimpleObjectProperty<>(PinMode.DIGITAL_OUTPUT);
gpio7ModeProperty = new SimpleObjectProperty<>(PinMode.DIGITAL_OUTPUT);
modeProperties = new ObjectProperty[]{
gpio0ModeProperty,
gpio1ModeProperty,
gpio2ModeProperty,
gpio3ModeProperty,
gpio4ModeProperty,
gpio5ModeProperty,
gpio6ModeProperty,
gpio7ModeProperty
};
}
private ChangeListener<Boolean> createPinStatePropertyListener(final GpioPinDigitalMultipurpose pin) {
return (ObservableValue<? extends Boolean> ov, Boolean oldValue, Boolean newValue) -> {
LOGGER.log(Level.INFO, "pinPropertyChanged: {0} {1}", new Object[]{pin.getName(), newValue});
if (pin.getMode() != PinMode.DIGITAL_INPUT) {
if (newValue) {
pin.high();
} else {
pin.low();
}
}
};
}
private void addGpioInputListener(final GpioPinDigitalMultipurpose pin, final BooleanProperty gpioStateProperty) {
pin.addListener((GpioPinListenerDigital) new GpioPinListenerDigital() {
@Override
public void handleGpioPinDigitalStateChangeEvent(final GpioPinDigitalStateChangeEvent event) {
LOGGER.log(Level.INFO, "pinstateChanged: {0} {1}", new Object[]{pin.getName(), event.getState()});
Platform.runLater(() -> {
gpioStateProperty.set(event.getState().
isHigh());
});
}
});
}
/*
* -------------------------- ACTIONS --------------------------
*/
public void connect() {
LOGGER.log(Level.INFO, "connect...");
gpio = GpioFactory.getInstance();
pin0 = gpio.provisionDigitalMultipurposePin(RaspiPin.GPIO_00, gpio0ModeProperty.get(), PinPullResistance.PULL_DOWN);
pin1 = gpio.provisionDigitalMultipurposePin(RaspiPin.GPIO_01, gpio1ModeProperty.get(), PinPullResistance.PULL_DOWN);
pin2 = gpio.provisionDigitalMultipurposePin(RaspiPin.GPIO_02, gpio2ModeProperty.get(), PinPullResistance.PULL_DOWN);
pin3 = gpio.provisionDigitalMultipurposePin(RaspiPin.GPIO_03, gpio3ModeProperty.get(), PinPullResistance.PULL_DOWN);
pin4 = gpio.provisionDigitalMultipurposePin(RaspiPin.GPIO_04, gpio4ModeProperty.get(), PinPullResistance.PULL_DOWN);
pin5 = gpio.provisionDigitalMultipurposePin(RaspiPin.GPIO_05, gpio5ModeProperty.get(), PinPullResistance.PULL_DOWN);
pin6 = gpio.provisionDigitalMultipurposePin(RaspiPin.GPIO_06, gpio6ModeProperty.get(), PinPullResistance.PULL_DOWN);
pin7 = gpio.provisionDigitalMultipurposePin(RaspiPin.GPIO_07, gpio7ModeProperty.get(), PinPullResistance.PULL_DOWN);
pins = new GpioPinDigitalMultipurpose[]{
pin0, pin1, pin2, pin3, pin4, pin5, pin6, pin7
};
gpio.setShutdownOptions(true, PinState.LOW, pins);
gpio0StateProperty.addListener(createPinStatePropertyListener(pin0));
addGpioInputListener(pin0, gpio0StateProperty);
addGpioInputListener(pin1, gpio1StateProperty);
addGpioInputListener(pin2, gpio2StateProperty);
addGpioInputListener(pin3, gpio3StateProperty);
addGpioInputListener(pin4, gpio4StateProperty);
addGpioInputListener(pin5, gpio5StateProperty);
addGpioInputListener(pin6, gpio6StateProperty);
addGpioInputListener(pin7, gpio7StateProperty);
gpio1StateProperty.addListener(createPinStatePropertyListener(pin1));
gpio2StateProperty.addListener(createPinStatePropertyListener(pin2));
gpio3StateProperty.addListener(createPinStatePropertyListener(pin3));
gpio4StateProperty.addListener(createPinStatePropertyListener(pin4));
gpio5StateProperty.addListener(createPinStatePropertyListener(pin5));
gpio6StateProperty.addListener(createPinStatePropertyListener(pin6));
gpio7StateProperty.addListener(createPinStatePropertyListener(pin7));
reset();
setConnectedPropertyValue(Boolean.TRUE);
LOGGER.log(Level.INFO, "connected.");
}
public void setOnAllPins() {
LOGGER.log(Level.INFO, "setOnAllPins()");
for (int i = 0; i <= 7; i++) {
stateProperties[i].setValue(Boolean.TRUE);
}
}
public void setAllPinsLow() {
LOGGER.log(Level.INFO, "setOffAllPins()");
for (int i = 0; i <= 7; i++) {
stateProperties[i].setValue(Boolean.FALSE);
}
}
public void disconnect() {
LOGGER.log(Level.INFO, "disconnect()");
if (gpio != null) {
gpio.shutdown();
}
setConnectedPropertyValue(Boolean.FALSE);
}
public void resetIOModes() {
LOGGER.log(Level.INFO, "resetIOModes()");
for (int i = 0; i <= 7; i++) {
setGpioMode(i, PinMode.DIGITAL_OUTPUT);
}
}
public void reset() {
LOGGER.log(Level.INFO, "reset()");
if (testTimeline != null) {
testTimeline.stop();
}
setAllPinsLow();
resetIOModes();
}
public void connectTest() {
LOGGER.log(Level.INFO, "connectTest()");
if (testTimeline != null) {
testTimeline.stop();
}
reset();
testTimeline = new Timeline(new KeyFrame(Duration.seconds(1), (ActionEvent event) -> {
setOnAllPins();
}), new KeyFrame(Duration.seconds(0.1), (ActionEvent event) -> {
setAllPinsLow();
}));
testTimeline.play();
}
public void test(double millis) {
LOGGER.log(Level.INFO, "test()");
reset();
testTimeline = new Timeline(new KeyFrame(Duration.millis(millis), (ActionEvent event) -> {
gpio0StateProperty.setValue(Boolean.TRUE);
}), new KeyFrame(Duration.millis(millis * 2), (ActionEvent event) -> {
gpio1StateProperty.setValue(Boolean.TRUE);
}), new KeyFrame(Duration.millis(millis * 3), (ActionEvent event) -> {
gpio2StateProperty.setValue(Boolean.TRUE);
}), new KeyFrame(Duration.millis(millis * 4), (ActionEvent event) -> {
gpio3StateProperty.setValue(Boolean.TRUE);
}), new KeyFrame(Duration.millis(millis * 5), (ActionEvent event) -> {
gpio4StateProperty.setValue(Boolean.TRUE);
}), new KeyFrame(Duration.millis(millis * 6), (ActionEvent event) -> {
gpio5StateProperty.setValue(Boolean.TRUE);
}), new KeyFrame(Duration.millis(millis * 7), (ActionEvent event) -> {
gpio6StateProperty.setValue(Boolean.TRUE);
}), new KeyFrame(Duration.millis(millis * 8), (ActionEvent event) -> {
gpio7StateProperty.setValue(Boolean.TRUE);
}));
testTimeline.play();
}
/*
* -------------------------- PROPERTY METHODS --------------------------
*/
public void setGpioStateValue(int pinNumber, Boolean state) {
stateProperties[pinNumber].setValue(state);
}
public void setGpioMode(int pinNumber, PinMode mode) {
modeProperties[pinNumber].setValue(mode);
if (isConnected()) {
pins[pinNumber].setMode(mode);
if (PinMode.DIGITAL_OUTPUT.equals(mode)) {
pins[pinNumber].setState(PinState.LOW);
}
}
}
public void setConnectedPropertyValue(Boolean connected) {
this.connectedProperty.setValue(connected);
}
public boolean isConnected() {
return connectedProperty.get();
}
public BooleanProperty connectedProperty() {
return connectedProperty;
}
public BooleanProperty gpio0StateProperty() {
return gpio0StateProperty;
}
public BooleanProperty gpio1StateProperty() {
return gpio1StateProperty;
}
public BooleanProperty gpio2StateProperty() {
return gpio2StateProperty;
}
public BooleanProperty gpio3StateProperty() {
return gpio3StateProperty;
}
public BooleanProperty gpio4StateProperty() {
return gpio4StateProperty;
}
public BooleanProperty gpio5StateProperty() {
return gpio5StateProperty;
}
public BooleanProperty gpio6StateProperty() {
return gpio6StateProperty;
}
public BooleanProperty gpio7StateProperty() {
return gpio7StateProperty;
}
public ObjectProperty<PinMode> gpio0ModeProperty() {
return gpio0ModeProperty;
}
public ObjectProperty<PinMode> gpio1ModeProperty() {
return gpio1ModeProperty;
}
public ObjectProperty<PinMode> gpio2ModeProperty() {
return gpio2ModeProperty;
}
public ObjectProperty<PinMode> gpio3ModeProperty() {
return gpio3ModeProperty;
}
public ObjectProperty<PinMode> gpio4ModeProperty() {
return gpio4ModeProperty;
}
public ObjectProperty<PinMode> gpio5ModeProperty() {
return gpio5ModeProperty;
}
public ObjectProperty<PinMode> gpio6ModeProperty() {
return gpio6ModeProperty;
}
public ObjectProperty<PinMode> gpio7ModeProperty() {
return gpio7ModeProperty;
}
}