From 0ec7b2f9afdfc2f866ff9525dffe939eb4ff8bc0 Mon Sep 17 00:00:00 2001 From: "robert@savagehomeautomation.com" Date: Sat, 9 Feb 2013 20:36:35 -0600 Subject: [PATCH] * Added support for a GpioController.shutdown() method to cleanup terminate all Pi4J threads and executors. https://github.com/Pi4J/pi4j/issues/9 * Added support for a user-definable ExecutorServiceFactory to allow user program to provide the implementation for executor service instances and managed thread pools. https://github.com/Pi4J/pi4j/issues/10 * Fixed 'java.util.concurrent.RejectedExecutionException' issue where there were not enough default thread in the pool for concurrent tasks. https://github.com/Pi4J/pi4j/issues/31 * Fixed issue where SerialDataMonitorThread was not shutting down on program exit. https://github.com/Pi4J/pi4j/issues/33 * Fixed issue where hard-float ABI was not detected properly when using Oracle JDK 8 early access edition. https://github.com/Pi4J/pi4j/issues/26 --- README.md | 14 ++- .../java/com/pi4j/io/gpio/GpioController.java | 2 + .../java/com/pi4j/io/gpio/GpioFactory.java | 30 ++++++ .../pi4j/io/gpio/GpioPinDigitalOutput.java | 8 +- .../java/com/pi4j/io/gpio/GpioProvider.java | 3 +- .../com/pi4j/io/gpio/GpioProviderBase.java | 18 ++++ .../pi4j/io/gpio/impl/GpioControllerImpl.java | 91 +++++++++++++------ .../impl/GpioEventMonitorExecutorImpl.java | 10 +- .../com/pi4j/io/gpio/impl/GpioPinImpl.java | 16 ++-- .../gpio/impl/GpioScheduledExecutorImpl.java | 38 +++----- .../main/java/com/pi4j/io/serial/Serial.java | 4 + .../serial/impl/SerialDataMonitorThread.java | 2 +- .../com/pi4j/io/serial/impl/SerialImpl.java | 36 +++++++- .../com/pi4j/util/NativeLibraryLoader.java | 2 +- .../src/main/java/BlinkGpioExample.java | 31 ++++--- .../main/java/BlinkTriggerGpioExample.java | 16 ++-- .../src/main/java/ControlGpioExample.java | 15 +-- .../src/main/java/CylonGpioExample.java | 23 +++-- .../src/main/java/FrequencyGpioExample.java | 15 +-- pi4j-example/src/main/java/LcdExample.java | 20 ++-- .../src/main/java/ListenGpioExample.java | 20 ++-- .../main/java/ListenMultipleGpioExample.java | 75 +++++++-------- .../src/main/java/MCP23017GpioExample.java | 30 +++--- .../main/java/MultipurposePinGpioExample.java | 24 ++--- .../src/main/java/OlimexGpioExample.java | 47 +++++----- .../src/main/java/PCF8574GpioExample.java | 31 +++---- pi4j-example/src/main/java/SerialExample.java | 20 ++-- .../src/main/java/ShutdownGpioExample.java | 20 ++-- .../main/java/StepperMotorGpioExample.java | 12 ++- .../src/main/java/SystemInfoExample.java | 8 +- .../src/main/java/TriggerGpioExample.java | 24 ++--- .../src/main/java/UsageGpioExample.java | 21 +++-- .../src/main/java/WiringPiGpioExample.java | 29 ++---- .../java/WiringPiGpioInterruptExample.java | 50 +++++----- .../src/main/java/WiringPiLcdExample.java | 10 +- .../src/main/java/WiringPiSerialExample.java | 29 +++--- .../src/main/java/WiringPiSoftPWMExample.java | 19 ++-- .../extension/mcp/MCP23008GpioProvider.java | 10 +- .../extension/mcp/MCP23017GpioProvider.java | 8 ++ .../olimex/OlimexAVRIOGpioProvider.java | 12 +++ .../extension/pcf/PCF8574GpioProvider.java | 8 ++ 41 files changed, 512 insertions(+), 389 deletions(-) diff --git a/README.md b/README.md index 56ddd027e..f92f51e93 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Copyright (C) 2012 Pi4J ## IN DEVELOPMENT -2013-01-07 :: 0.0.5-SNAPSHOT +2013-02-09 :: 0.0.5-SNAPSHOT * Added support for PCF8574 GpioProvider * Added sample code for using PCF8574 GpioProvider @@ -56,6 +56,18 @@ Copyright (C) 2012 Pi4J * Added LCD component interface * Added GPIO based 4/8 bit LCD display component implementation and sample program. * Added GPIO based 4/8 bit LCD WiringPi example program + * Added support for a GpioController.shutdown() method to cleanup terminate all Pi4J threads and executors. + https://github.com/Pi4J/pi4j/issues/9 + * Added support for a user-definable ExecutorServiceFactory to allow user program to provide the implementation + for executor service instances and managed thread pools. + https://github.com/Pi4J/pi4j/issues/10 + * Fixed 'java.util.concurrent.RejectedExecutionException' issue where there were not + enough default thread in the pool for concurrent tasks. + https://github.com/Pi4J/pi4j/issues/31 + * Fixed issue where SerialDataMonitorThread was not shutting down on program exit. + https://github.com/Pi4J/pi4j/issues/33 + * Fixed issue where hard-float ABI was not detected properly when using Oracle JDK 8 early access edition. + https://github.com/Pi4J/pi4j/issues/26 ## RELEASES diff --git a/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioController.java b/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioController.java index 059dc223c..bfcba62be 100644 --- a/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioController.java +++ b/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioController.java @@ -145,4 +145,6 @@ public interface GpioController { Collection getProvisionedPins(); void unprovisionPin(GpioPin... pin); + boolean isShutdown(); + void shutdown(); } diff --git a/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioFactory.java b/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioFactory.java index 643fb3de1..de8b20577 100644 --- a/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioFactory.java +++ b/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioFactory.java @@ -28,6 +28,8 @@ */ +import com.pi4j.concurrent.DefaultExecutorServiceFactory; +import com.pi4j.concurrent.ExecutorServiceFactory; import com.pi4j.io.gpio.impl.GpioControllerImpl; /** @@ -59,6 +61,9 @@ public class GpioFactory { // we only allow a single default provider to exists private static GpioProvider provider = null; + + // we only allow a single default scheduled executor service factory to exists + private static ExecutorServiceFactory executorServiceFactory = null; // private constructor private GpioFactory() { @@ -110,4 +115,29 @@ public static void setDefaultProvider(GpioProvider provider) { GpioFactory.provider = provider; } + + /** + *

Return instance of {@link ExecutorServiceFactory}.

+ *

Note: .

+ * + * @return Return a new GpioController impl instance. + */ + public static ExecutorServiceFactory getExecutorServiceFactory() { + // if an executor service provider factory has not been created, then create a new default instance + if (executorServiceFactory == null) { + executorServiceFactory = new DefaultExecutorServiceFactory(); + } + // return the provider instance + return executorServiceFactory; + } + + /** + * Sets default {@link ExecutorServiceFactory}. + * + * @param executor service factory instance + */ + public static void setExecutorServiceFactory(ExecutorServiceFactory executorServiceFactory) { + // set the default factory instance + GpioFactory.executorServiceFactory = executorServiceFactory; + } } diff --git a/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioPinDigitalOutput.java b/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioPinDigitalOutput.java index f5cd547cf..7f77af1ac 100644 --- a/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioPinDigitalOutput.java +++ b/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioPinDigitalOutput.java @@ -40,10 +40,10 @@ public interface GpioPinDigitalOutput extends GpioPinDigital, GpioPinOutput { void high(); void low(); void toggle(); - void blink(long delay); - void blink(long delay, PinState blinkState); - void blink(long delay, long duration); - void blink(long delay, long duration, PinState blinkState); + Future blink(long delay); + Future blink(long delay, PinState blinkState); + Future blink(long delay, long duration); + Future blink(long delay, long duration, PinState blinkState); Future pulse(long duration); Future pulse(long duration, boolean blocking); Future pulse(long duration, PinState pulseState); diff --git a/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioProvider.java b/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioProvider.java index eed5386c8..34ed4f753 100644 --- a/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioProvider.java +++ b/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioProvider.java @@ -64,5 +64,6 @@ public interface GpioProvider { void removeListener(Pin pin, PinListener listener); void removeAllListeners(); - void shutdown(); + void shutdown(); + boolean isShutdown(); } diff --git a/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioProviderBase.java b/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioProviderBase.java index 0d7b3a037..a9cc26935 100644 --- a/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioProviderBase.java +++ b/pi4j-core/src/main/java/com/pi4j/io/gpio/GpioProviderBase.java @@ -53,6 +53,7 @@ public abstract class GpioProviderBase implements GpioProvider { protected final Map> listeners = new ConcurrentHashMap>(); protected final Map cache = new ConcurrentHashMap(); + protected boolean isshutdown = false; @Override public boolean hasPin(Pin pin) { @@ -311,5 +312,22 @@ protected void dispatchPinAnalogValueChangeEvent(Pin pin, double value) { @Override public void shutdown() { + + // prevent reentrant invocation + if(isShutdown()) + return; + + // set shutdown tracking state variable + isshutdown = true; } + + /** + * This method returns TRUE if the GPIO provider has been shutdown. + * + * @return shutdown state + */ + @Override + public boolean isShutdown(){ + return isshutdown; + } } diff --git a/pi4j-core/src/main/java/com/pi4j/io/gpio/impl/GpioControllerImpl.java b/pi4j-core/src/main/java/com/pi4j/io/gpio/impl/GpioControllerImpl.java index caa2d0d0f..1f8a11fee 100644 --- a/pi4j-core/src/main/java/com/pi4j/io/gpio/impl/GpioControllerImpl.java +++ b/pi4j-core/src/main/java/com/pi4j/io/gpio/impl/GpioControllerImpl.java @@ -57,6 +57,7 @@ public class GpioControllerImpl implements GpioController { private final List pins = Collections.synchronizedList(new ArrayList()); private final GpioProvider defaultProvider; + private boolean isshutdown = false; /** * Default Constructor @@ -886,35 +887,73 @@ public void setShutdownOptions(Boolean unexport, PinState state, PinPullResistan */ private class ShutdownHook extends Thread { public void run() { - // shutdown executor services - GpioScheduledExecutorImpl.shutdown(); - GpioEventMonitorExecutorImpl.shutdown(); + // perform shutdown + shutdown(); + } + } + + /** + * This method returns TRUE if the GPIO controller has been shutdown. + * + * @return shutdown state + */ + @Override + public boolean isShutdown(){ + return isshutdown; + } + + + /** + * This method can be called to forcefully shutdown all GPIO controller + * monitoring, listening, and task threads/executors. + */ + @Override + public synchronized void shutdown() + { + // prevent reentrant invocation + if(isShutdown()) + return; + + // shutdown all executor services + // + // NOTE: we are not permitted to access the shutdown() method of the individual + // executor services, we must perform the shutdown with the factory + GpioFactory.getExecutorServiceFactory().shutdown(); + + // shutdown explicit configured GPIO pins + for (GpioPin pin : pins) { - // shutdown explicit configured GPIO pins - for (GpioPin pin : pins) { - GpioPinShutdown shutdownOptions = pin.getShutdownOptions(); - if (shutdownOptions != null) { - // get shutdown option configuration - PinState state = shutdownOptions.getState(); - PinMode mode = shutdownOptions.getMode(); - PinPullResistance resistance = shutdownOptions.getPullResistor(); - Boolean unexport = shutdownOptions.getUnexport(); - - // perform shutdown actions - if ((state != null) && (pin instanceof GpioPinDigitalOutput)) { - ((GpioPinDigitalOutput)pin).setState(state); - } - if (resistance != null) { - pin.setPullResistance(resistance); - } - if (mode != null) { - pin.setMode(mode); - } - if (unexport != null && unexport == Boolean.TRUE) { - pin.unexport(); - } + // perform a shutdown on the GPIO provider for this pin + if(!pin.getProvider().isShutdown()){ + pin.getProvider().shutdown(); + } + + // perform the shutdown options if configured for the pin + GpioPinShutdown shutdownOptions = pin.getShutdownOptions(); + if (shutdownOptions != null) { + // get shutdown option configuration + PinState state = shutdownOptions.getState(); + PinMode mode = shutdownOptions.getMode(); + PinPullResistance resistance = shutdownOptions.getPullResistor(); + Boolean unexport = shutdownOptions.getUnexport(); + + // perform shutdown actions + if ((state != null) && (pin instanceof GpioPinDigitalOutput)) { + ((GpioPinDigitalOutput)pin).setState(state); + } + if (resistance != null) { + pin.setPullResistance(resistance); + } + if (mode != null) { + pin.setMode(mode); + } + if (unexport != null && unexport == Boolean.TRUE) { + pin.unexport(); } } } + + // set is shutdown tracking variable + isshutdown = true; } } diff --git a/pi4j-core/src/main/java/com/pi4j/io/gpio/impl/GpioEventMonitorExecutorImpl.java b/pi4j-core/src/main/java/com/pi4j/io/gpio/impl/GpioEventMonitorExecutorImpl.java index 334c78030..671e2ed48 100644 --- a/pi4j-core/src/main/java/com/pi4j/io/gpio/impl/GpioEventMonitorExecutorImpl.java +++ b/pi4j-core/src/main/java/com/pi4j/io/gpio/impl/GpioEventMonitorExecutorImpl.java @@ -27,7 +27,7 @@ */ import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +import com.pi4j.io.gpio.GpioFactory; import com.pi4j.io.gpio.GpioPinInput; import com.pi4j.io.gpio.event.PinEvent; import com.pi4j.io.gpio.event.PinListener; @@ -40,17 +40,11 @@ public class GpioEventMonitorExecutorImpl implements PinListener { public GpioEventMonitorExecutorImpl(GpioPinInput pin) { this.pin = pin; - executor = Executors.newSingleThreadExecutor(); + executor = GpioFactory.getExecutorServiceFactory().newSingleThreadExecutorService(); } @Override public void handlePinEvent(PinEvent event) { executor.execute(new GpioEventDispatchTaskImpl(pin, event)); } - - public synchronized static void shutdown() { - if (executor != null && !executor.isShutdown()) { - executor.shutdownNow(); - } - } } diff --git a/pi4j-core/src/main/java/com/pi4j/io/gpio/impl/GpioPinImpl.java b/pi4j-core/src/main/java/com/pi4j/io/gpio/impl/GpioPinImpl.java index 5ce509791..64102e554 100644 --- a/pi4j-core/src/main/java/com/pi4j/io/gpio/impl/GpioPinImpl.java +++ b/pi4j-core/src/main/java/com/pi4j/io/gpio/impl/GpioPinImpl.java @@ -226,25 +226,25 @@ public void toggle() { } @Override - public void blink(long delay) { - blink(delay, PinState.HIGH); + public Future blink(long delay) { + return blink(delay, PinState.HIGH); } @Override - public void blink(long delay, PinState blinkState) { + public Future blink(long delay, PinState blinkState) { // NOTE: a value of 0 milliseconds will stop the blinking - blink(delay, 0, blinkState); + return blink(delay, 0, blinkState); } @Override - public void blink(long delay, long duration) { - blink(delay, duration, PinState.HIGH); + public Future blink(long delay, long duration) { + return blink(delay, duration, PinState.HIGH); } @Override - public void blink(long delay, long duration, PinState blinkState) { + public Future blink(long delay, long duration, PinState blinkState) { // NOTE: a value of 0 milliseconds will stop the blinking - GpioScheduledExecutorImpl.blink(this, delay, duration, blinkState); + return GpioScheduledExecutorImpl.blink(this, delay, duration, blinkState); } @Override diff --git a/pi4j-core/src/main/java/com/pi4j/io/gpio/impl/GpioScheduledExecutorImpl.java b/pi4j-core/src/main/java/com/pi4j/io/gpio/impl/GpioScheduledExecutorImpl.java index 7eefa76da..95bc90c15 100644 --- a/pi4j-core/src/main/java/com/pi4j/io/gpio/impl/GpioScheduledExecutorImpl.java +++ b/pi4j-core/src/main/java/com/pi4j/io/gpio/impl/GpioScheduledExecutorImpl.java @@ -31,13 +31,13 @@ import java.util.ArrayList; import java.util.Map.Entry; import java.util.concurrent.Callable; -import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.ConcurrentHashMap; +import com.pi4j.io.gpio.GpioFactory; import com.pi4j.io.gpio.GpioPinDigitalOutput; import com.pi4j.io.gpio.PinState; import com.pi4j.io.gpio.tasks.impl.GpioBlinkStopTaskImpl; @@ -50,8 +50,8 @@ public class GpioScheduledExecutorImpl { private static ScheduledExecutorService scheduledExecutorService; private synchronized static void init(GpioPinDigitalOutput pin) { - if (scheduledExecutorService == null || scheduledExecutorService.isShutdown()) { - scheduledExecutorService = Executors.newScheduledThreadPool(5); + if (scheduledExecutorService == null) { + scheduledExecutorService = GpioFactory.getExecutorServiceFactory().getScheduledExecutorService(); } // determine if any existing future tasks are already scheduled for this pin @@ -97,12 +97,6 @@ public Object call() throws Exception { } } } - - // shutdown service when tasks are complete - if (pinTaskQueue.isEmpty()) { - scheduledExecutorService.shutdown(); - } - return null; } }, delay, TimeUnit.MILLISECONDS); @@ -141,16 +135,11 @@ public synchronized static Future pulse(GpioPinDigitalOutput pin, long durati createCleanupTask(duration + 500); } - // shutdown service when tasks are complete - if (pinTaskQueue.isEmpty()) { - scheduledExecutorService.shutdown(); - } - // return future task return scheduledFuture; } - public synchronized static void blink(GpioPinDigitalOutput pin, long delay, long duration, PinState blinkState) { + public synchronized static Future blink(GpioPinDigitalOutput pin, long delay, long duration, PinState blinkState) { // perform the initial startup and cleanup for this pin init(pin); @@ -185,18 +174,13 @@ public synchronized static void blink(GpioPinDigitalOutput pin, long delay, long // create future task to clean up completed tasks createCleanupTask(duration + 500); - } - } - - // shutdown service when tasks are complete - if (pinTaskQueue.isEmpty()) { - scheduledExecutorService.shutdown(); + } + + // return future task + return scheduledFutureBlinkTask; } + + // no future task when a delay time has not been specified + return null; } - - public synchronized static void shutdown() { - if (scheduledExecutorService != null && !scheduledExecutorService.isShutdown()) { - scheduledExecutorService.shutdownNow(); - } - } } diff --git a/pi4j-core/src/main/java/com/pi4j/io/serial/Serial.java b/pi4j-core/src/main/java/com/pi4j/io/serial/Serial.java index a66c2bd69..b32297834 100644 --- a/pi4j-core/src/main/java/com/pi4j/io/serial/Serial.java +++ b/pi4j-core/src/main/java/com/pi4j/io/serial/Serial.java @@ -201,4 +201,8 @@ public interface Serial { * @param listener A class instance that implements the SerialListener interface. */ void removeListener(SerialDataListener... listener); + + + boolean isShutdown(); + void shutdown(); } diff --git a/pi4j-core/src/main/java/com/pi4j/io/serial/impl/SerialDataMonitorThread.java b/pi4j-core/src/main/java/com/pi4j/io/serial/impl/SerialDataMonitorThread.java index 4ccc0894d..f0a2279d3 100644 --- a/pi4j-core/src/main/java/com/pi4j/io/serial/impl/SerialDataMonitorThread.java +++ b/pi4j-core/src/main/java/com/pi4j/io/serial/impl/SerialDataMonitorThread.java @@ -84,7 +84,7 @@ public SerialDataMonitorThread(Serial serial, CopyOnWriteArrayList listeners = new CopyOnWriteArrayList(); - private SerialDataMonitorThread monitor; + protected int fileDescriptor = -1; + protected final CopyOnWriteArrayList listeners = new CopyOnWriteArrayList(); + protected SerialDataMonitorThread monitor; + protected boolean isshutdown = false; /** * This method is call to open a serial port for communication. @@ -265,8 +266,35 @@ public synchronized void removeListener(SerialDataListener... listener) { // if there are not more listeners, then exit and destroy // the monitor thread now if (listeners.isEmpty() && monitor != null) { - monitor.exit(); + monitor.shutdown(); monitor = null; } } + + /** + * This method returns TRUE if the serial interface has been shutdown. + * + * @return shutdown state + */ + @Override + public boolean isShutdown(){ + return isshutdown; + } + + + /** + * This method can be called to forcefully shutdown all + * serial data monitoring threads. + */ + @Override + public synchronized void shutdown() + { + // prevent reentrant invocation + if(isShutdown()) + return; + + // shutdown monitoring thread + if(monitor != null) + monitor.shutdown(); + } } diff --git a/pi4j-core/src/main/java/com/pi4j/util/NativeLibraryLoader.java b/pi4j-core/src/main/java/com/pi4j/util/NativeLibraryLoader.java index 995b00c9a..4760aae9a 100644 --- a/pi4j-core/src/main/java/com/pi4j/util/NativeLibraryLoader.java +++ b/pi4j-core/src/main/java/com/pi4j/util/NativeLibraryLoader.java @@ -165,7 +165,7 @@ public static synchronized void load(String libraryName, String fileName) { loadLibraryFromResource(resourceUrl, libraryName, fileName); // debug - logger.info("Library [" + libraryName + "] loaded successfully using embedded resource file: [" + resourceUrl.toString() + "]"); + logger.fine("Library [" + libraryName + "] loaded successfully using embedded resource file: [" + resourceUrl.toString() + "]"); } catch(Exception|UnsatisfiedLinkError ex) { diff --git a/pi4j-example/src/main/java/BlinkGpioExample.java b/pi4j-example/src/main/java/BlinkGpioExample.java index e15a01172..539d364ed 100644 --- a/pi4j-example/src/main/java/BlinkGpioExample.java +++ b/pi4j-example/src/main/java/BlinkGpioExample.java @@ -45,10 +45,10 @@ * * @author Robert Savage */ -public class BlinkGpioExample -{ - public static void main(String[] args) throws InterruptedException - { +public class BlinkGpioExample { + + public static void main(String[] args) throws InterruptedException { + System.out.println("<--Pi4J--> GPIO Blink Example ... started."); // create gpio controller @@ -62,16 +62,16 @@ public static void main(String[] args) throws InterruptedException final GpioPinDigitalInput myButton = gpio.provisionDigitalInputPin(RaspiPin.GPIO_02, PinPullResistance.PULL_DOWN); // create and register gpio pin listener - myButton.addListener(new GpioPinListenerDigital() - { + myButton.addListener(new GpioPinListenerDigital() { @Override - public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) - { + public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) { // when button is pressed, speed up the blink rate on LED #2 - if(event.getState().isHigh()) - led2.blink(200); - else - led2.blink(1000); + if(event.getState().isHigh()){ + led2.blink(200); + } + else{ + led2.blink(1000); + } } }); @@ -85,10 +85,13 @@ public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent System.out.println(" ... PRESS TO STOP THE PROGRAM."); // keep program running until user aborts (CTRL-C) - for (;;) - { + for (;;) { Thread.sleep(500); } + + // stop all GPIO activity/threads + // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks) + // gpio.shutdown(); <--- implement this method call if you wish to terminate the Pi4J GPIO controller } } diff --git a/pi4j-example/src/main/java/BlinkTriggerGpioExample.java b/pi4j-example/src/main/java/BlinkTriggerGpioExample.java index 7ec48cbe3..31c05323e 100644 --- a/pi4j-example/src/main/java/BlinkTriggerGpioExample.java +++ b/pi4j-example/src/main/java/BlinkTriggerGpioExample.java @@ -28,7 +28,6 @@ * #L% */ - import com.pi4j.io.gpio.GpioController; import com.pi4j.io.gpio.GpioFactory; import com.pi4j.io.gpio.GpioPinDigitalInput; @@ -44,10 +43,10 @@ * * @author Robert Savage */ -public class BlinkTriggerGpioExample -{ - public static void main(String[] args) throws InterruptedException - { +public class BlinkTriggerGpioExample { + + public static void main(String[] args) throws InterruptedException { + System.out.println("<--Pi4J--> GPIO Blink Trigger Example ... started."); // create gpio controller @@ -69,10 +68,13 @@ public static void main(String[] args) throws InterruptedException myButton.addTrigger(new GpioBlinkStopStateTrigger(PinState.LOW, myLed)); // keep program running until user aborts (CTRL-C) - for (;;) - { + for (;;) { Thread.sleep(500); } + + // stop all GPIO activity/threads by shutting down the GPIO controller + // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks) + // gpio.shutdown(); <--- implement this method call if you wish to terminate the Pi4J GPIO controller } } // END SNIPPET: blink-trigger-gpio-snippet diff --git a/pi4j-example/src/main/java/ControlGpioExample.java b/pi4j-example/src/main/java/ControlGpioExample.java index 12b6306e8..acf341c3b 100644 --- a/pi4j-example/src/main/java/ControlGpioExample.java +++ b/pi4j-example/src/main/java/ControlGpioExample.java @@ -1,6 +1,5 @@ // START SNIPPET: control-gpio-snippet - /* * #%L * ********************************************************************** @@ -40,10 +39,10 @@ * * @author Robert Savage */ -public class ControlGpioExample -{ - public static void main(String[] args) throws InterruptedException - { +public class ControlGpioExample { + + public static void main(String[] args) throws InterruptedException { + System.out.println("<--Pi4J--> GPIO Control Example ... started."); // create gpio controller @@ -75,7 +74,11 @@ public static void main(String[] args) throws InterruptedException // turn on gpio pin #01 for 1 second and then off System.out.println("--> GPIO state should be: ON for only 1 second"); - pin.pulse(1000); + pin.pulse(1000, true); // set second argument to 'true' use a blocking call + + // stop all GPIO activity/threads by shutting down the GPIO controller + // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks) + gpio.shutdown(); } } //END SNIPPET: control-gpio-snippet diff --git a/pi4j-example/src/main/java/CylonGpioExample.java b/pi4j-example/src/main/java/CylonGpioExample.java index d24525a11..c03ef67d2 100644 --- a/pi4j-example/src/main/java/CylonGpioExample.java +++ b/pi4j-example/src/main/java/CylonGpioExample.java @@ -41,10 +41,10 @@ * * @author Robert Savage */ -public class CylonGpioExample -{ - public static void main(String[] args) throws InterruptedException - { +public class CylonGpioExample { + + public static void main(String[] args) throws InterruptedException { + System.out.println("<--Pi4J--> GPIO Cylon Example ... started."); // create gpio controller @@ -65,20 +65,23 @@ public static void main(String[] args) throws InterruptedException // set shutdown options on all pins gpio.setShutdownOptions(true, PinState.LOW, pins); - while(true) - { - for(int index = 0; index <= 6; index++) - { + // infinite loop + while(true) { + + for(int index = 0; index <= 6; index++) { pins[index].pulse(50); Thread.sleep(50); } - for(int index = 6; index >= 0; index--) - { + for(int index = 6; index >= 0; index--) { pins[index].pulse(50); Thread.sleep(50); } } + + // stop all GPIO activity/threads by shutting down the GPIO controller + // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks) + // gpio.shutdown(); <--- implement this method call if you wish to terminate the Pi4J GPIO controller } } //END SNIPPET: cylon-gpio-snippet diff --git a/pi4j-example/src/main/java/FrequencyGpioExample.java b/pi4j-example/src/main/java/FrequencyGpioExample.java index 966a7001c..872c344da 100644 --- a/pi4j-example/src/main/java/FrequencyGpioExample.java +++ b/pi4j-example/src/main/java/FrequencyGpioExample.java @@ -42,10 +42,10 @@ * * @author Robert Savage */ -public class FrequencyGpioExample -{ - public static void main(String[] args) - { +public class FrequencyGpioExample { + + public static void main(String[] args) { + System.out.println("<--Pi4J--> GPIO Frequency Example ... started."); // create gpio controller @@ -55,11 +55,14 @@ public static void main(String[] args) final GpioPinDigitalOutput pin = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_01, PinState.LOW); // continuous loop - while(true) - { + while(true) { pin.setState(true); pin.setState(false); } + + // stop all GPIO activity/threads by shutting down the GPIO controller + // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks) + // gpio.shutdown(); <--- implement this method call if you wish to terminate the Pi4J GPIO controller } } //END SNIPPET: frequency-gpio-snippet diff --git a/pi4j-example/src/main/java/LcdExample.java b/pi4j-example/src/main/java/LcdExample.java index 91ac2ece5..e44f4d548 100644 --- a/pi4j-example/src/main/java/LcdExample.java +++ b/pi4j-example/src/main/java/LcdExample.java @@ -48,6 +48,7 @@ public class LcdExample { public final static int LCD_BITS = 4; public static void main(String args[]) throws InterruptedException { + System.out.println("<--Pi4J--> GPIO 4 bit LCD example program"); // create gpio controller @@ -67,8 +68,8 @@ public static void main(String args[]) throws InterruptedException { final GpioPinDigitalInput myButtons[] = { gpio.provisionDigitalInputPin(RaspiPin.GPIO_13, "B1", PinPullResistance.PULL_UP), gpio.provisionDigitalInputPin(RaspiPin.GPIO_07, "B2", PinPullResistance.PULL_UP), - gpio.provisionDigitalInputPin(RaspiPin.GPIO_12, "B3", PinPullResistance.PULL_UP), - gpio.provisionDigitalInputPin(RaspiPin.GPIO_04, "B4", PinPullResistance.PULL_UP) + gpio.provisionDigitalInputPin(RaspiPin.GPIO_04, "B3", PinPullResistance.PULL_UP), + gpio.provisionDigitalInputPin(RaspiPin.GPIO_12, "B4", PinPullResistance.PULL_UP) }; // create and register gpio pin listener @@ -106,15 +107,13 @@ public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent lcd.write(LCD_ROW_2, "----------------"); // single character data replacement - for(int index = 0; index < lcd.getColumnCount(); index++) - { + for(int index = 0; index < lcd.getColumnCount(); index++) { lcd.write(LCD_ROW_2, index, ">"); if(index > 0) lcd.write(LCD_ROW_2, index - 1, "-"); Thread.sleep(300); } - for(int index = lcd.getColumnCount()-1; index >= 0 ; index--) - { + for(int index = lcd.getColumnCount()-1; index >= 0 ; index--) { lcd.write(LCD_ROW_2, index, "<"); if(index < lcd.getColumnCount()-1) lcd.write(LCD_ROW_2, index + 1, "-"); @@ -150,12 +149,17 @@ public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss"); // update time - while(true){ + while(true) { // write time to line 2 on LCD - if(gpio.isHigh(myButtons)) + if(gpio.isHigh(myButtons)) { lcd.writeln(LCD_ROW_2, formatter.format(new Date()), LCDTextAlignment.ALIGN_CENTER); + } Thread.sleep(1000); } + + // stop all GPIO activity/threads by shutting down the GPIO controller + // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks) + // gpio.shutdown(); <--- implement this method call if you wish to terminate the Pi4J GPIO controller } } diff --git a/pi4j-example/src/main/java/ListenGpioExample.java b/pi4j-example/src/main/java/ListenGpioExample.java index 77fd41659..86156addb 100644 --- a/pi4j-example/src/main/java/ListenGpioExample.java +++ b/pi4j-example/src/main/java/ListenGpioExample.java @@ -42,10 +42,9 @@ * * @author Robert Savage */ -public class ListenGpioExample -{ - public static void main(String args[]) throws InterruptedException - { +public class ListenGpioExample { + + public static void main(String args[]) throws InterruptedException { System.out.println("<--Pi4J--> GPIO Listen Example ... started."); // create gpio controller @@ -55,11 +54,9 @@ public static void main(String args[]) throws InterruptedException final GpioPinDigitalInput myButton = gpio.provisionDigitalInputPin(RaspiPin.GPIO_02, PinPullResistance.PULL_DOWN); // create and register gpio pin listener - myButton.addListener(new GpioPinListenerDigital() - { + myButton.addListener(new GpioPinListenerDigital() { @Override - public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) - { + public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) { // display pin state on console System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState()); } @@ -69,10 +66,13 @@ public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent System.out.println(" ... complete the GPIO #02 circuit and see the listener feedback here in the console."); // keep program running until user aborts (CTRL-C) - for (;;) - { + for (;;) { Thread.sleep(500); } + + // stop all GPIO activity/threads by shutting down the GPIO controller + // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks) + // gpio.shutdown(); <--- implement this method call if you wish to terminate the Pi4J GPIO controller } } diff --git a/pi4j-example/src/main/java/ListenMultipleGpioExample.java b/pi4j-example/src/main/java/ListenMultipleGpioExample.java index 3a5406fc4..7179e6172 100644 --- a/pi4j-example/src/main/java/ListenMultipleGpioExample.java +++ b/pi4j-example/src/main/java/ListenMultipleGpioExample.java @@ -28,13 +28,11 @@ * #L% */ - import com.pi4j.io.gpio.GpioController; import com.pi4j.io.gpio.GpioFactory; import com.pi4j.io.gpio.GpioPinDigitalInput; import com.pi4j.io.gpio.PinPullResistance; import com.pi4j.io.gpio.RaspiPin; -import com.pi4j.io.gpio.event.GpioPinListener; import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent; import com.pi4j.io.gpio.event.GpioPinListenerDigital; @@ -44,61 +42,50 @@ * * @author Robert Savage */ -public class ListenMultipleGpioExample -{ - public static void main(String args[]) throws InterruptedException - { +public class ListenMultipleGpioExample { + + public static void main(String args[]) throws InterruptedException { + System.out.println("<--Pi4J--> GPIO Listen Example ... started."); - // create gpio controller + // create GPIO controller final GpioController gpio = GpioFactory.getInstance(); - // provision gpio pin #02 as an input pin with its internal pull down resistor enabled - GpioPinDigitalInput myButton0 = gpio.provisionDigitalInputPin(RaspiPin.GPIO_00, PinPullResistance.PULL_DOWN); - GpioPinDigitalInput myButton1 = gpio.provisionDigitalInputPin(RaspiPin.GPIO_01, PinPullResistance.PULL_DOWN); - GpioPinDigitalInput myButton2 = gpio.provisionDigitalInputPin(RaspiPin.GPIO_02, PinPullResistance.PULL_DOWN); - GpioPinDigitalInput myButton3 = gpio.provisionDigitalInputPin(RaspiPin.GPIO_03, PinPullResistance.PULL_DOWN); - GpioPinDigitalInput myButton4 = gpio.provisionDigitalInputPin(RaspiPin.GPIO_04, PinPullResistance.PULL_DOWN); - GpioPinDigitalInput myButton5 = gpio.provisionDigitalInputPin(RaspiPin.GPIO_05, PinPullResistance.PULL_DOWN); - GpioPinDigitalInput myButton6 = gpio.provisionDigitalInputPin(RaspiPin.GPIO_06, PinPullResistance.PULL_DOWN); - GpioPinDigitalInput myButton7 = gpio.provisionDigitalInputPin(RaspiPin.GPIO_07, PinPullResistance.PULL_DOWN); + // create GPIO listener + GpioPinListenerDigital listener = new GpioPinListenerDigital() { + @Override + public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) { + // display pin state on console + System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState()); + } + }; + + // provision gpio input pins with its internal pull down resistor enabled + GpioPinDigitalInput[] pins = { + gpio.provisionDigitalInputPin(RaspiPin.GPIO_00, PinPullResistance.PULL_DOWN), + gpio.provisionDigitalInputPin(RaspiPin.GPIO_01, PinPullResistance.PULL_DOWN), + gpio.provisionDigitalInputPin(RaspiPin.GPIO_02, PinPullResistance.PULL_DOWN), + gpio.provisionDigitalInputPin(RaspiPin.GPIO_03, PinPullResistance.PULL_DOWN), + gpio.provisionDigitalInputPin(RaspiPin.GPIO_04, PinPullResistance.PULL_DOWN), + gpio.provisionDigitalInputPin(RaspiPin.GPIO_05, PinPullResistance.PULL_DOWN), + gpio.provisionDigitalInputPin(RaspiPin.GPIO_06, PinPullResistance.PULL_DOWN), + gpio.provisionDigitalInputPin(RaspiPin.GPIO_07, PinPullResistance.PULL_DOWN) + }; // create and register gpio pin listener - myButton0.addListener(new GpioExampleMultiListener()); - myButton1.addListener(new GpioExampleMultiListener()); - myButton2.addListener(new GpioExampleMultiListener()); - myButton3.addListener(new GpioExampleMultiListener()); - myButton4.addListener(new GpioExampleMultiListener()); - myButton5.addListener(new GpioExampleMultiListener()); - myButton6.addListener(new GpioExampleMultiListener()); - myButton7.addListener(new GpioExampleMultiListener()); + gpio.addListener(listener, pins); System.out.println(" ... complete the GPIO #02 circuit and see the listener feedback here in the console."); // keep program running until user aborts (CTRL-C) - for (;;) - { + for (;;) { Thread.sleep(500); } + + // stop all GPIO activity/threads by shutting down the GPIO controller + // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks) + // gpio.shutdown(); <--- implement this method call if you wish to terminate the Pi4J GPIO controller } } -/** - * This class implements the GPIO listener interface - * with the callback method for event notifications - * when GPIO pin states change. - * - * @see GpioPinListener - * @author Robert Savage - */ -class GpioExampleMultiListener implements GpioPinListenerDigital -{ - @Override - public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) - { - // display pin state on console - System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " - + event.getState()); - } -} // END SNIPPET: listen-multi-gpio-snippet diff --git a/pi4j-example/src/main/java/MCP23017GpioExample.java b/pi4j-example/src/main/java/MCP23017GpioExample.java index 1a5c95a9c..fa4491c18 100644 --- a/pi4j-example/src/main/java/MCP23017GpioExample.java +++ b/pi4j-example/src/main/java/MCP23017GpioExample.java @@ -61,21 +61,20 @@ * * @author Robert Savage */ -public class MCP23017GpioExample -{ - public static void main(String args[]) throws InterruptedException, IOException - { +public class MCP23017GpioExample { + + public static void main(String args[]) throws InterruptedException, IOException { + System.out.println("<--Pi4J--> MCP23017 GPIO Example ... started."); // create gpio controller final GpioController gpio = GpioFactory.getInstance(); // create custom MCP23017 GPIO provider - final MCP23017GpioProvider gpioProvider = new MCP23017GpioProvider(I2CBus.BUS_0, 0x21); + final MCP23017GpioProvider gpioProvider = new MCP23017GpioProvider(I2CBus.BUS_1, 0x21); // provision gpio input pins from MCP23017 - GpioPinDigitalInput myInputs[] = - { + GpioPinDigitalInput myInputs[] = { gpio.provisionDigitalInputPin(gpioProvider, MCP23017Pin.GPIO_A0, "MyInput-A0", PinPullResistance.PULL_UP), gpio.provisionDigitalInputPin(gpioProvider, MCP23017Pin.GPIO_A1, "MyInput-A1", PinPullResistance.PULL_UP), gpio.provisionDigitalInputPin(gpioProvider, MCP23017Pin.GPIO_A2, "MyInput-A2", PinPullResistance.PULL_UP), @@ -87,11 +86,9 @@ public static void main(String args[]) throws InterruptedException, IOException }; // create and register gpio pin listener - gpio.addListener(new GpioPinListenerDigital() - { + gpio.addListener(new GpioPinListenerDigital() { @Override - public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) - { + public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) { // display pin state on console System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState()); @@ -99,8 +96,7 @@ public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent }, myInputs); // provision gpio output pins and make sure they are all LOW at startup - GpioPinDigitalOutput myOutputs[] = - { + GpioPinDigitalOutput myOutputs[] = { gpio.provisionDigitalOutputPin(gpioProvider, MCP23017Pin.GPIO_B0, "MyOutput-B0", PinState.LOW), gpio.provisionDigitalOutputPin(gpioProvider, MCP23017Pin.GPIO_B1, "MyOutput-B1", PinState.LOW), gpio.provisionDigitalOutputPin(gpioProvider, MCP23017Pin.GPIO_B2, "MyOutput-B2", PinState.LOW), @@ -112,16 +108,16 @@ public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent }; // keep program running for 20 seconds - for (int count = 0; count < 10; count++) - { + for (int count = 0; count < 10; count++) { gpio.setState(true, myOutputs); Thread.sleep(1000); gpio.setState(false, myOutputs); Thread.sleep(1000); } - // shutdown the GPIO provider - gpioProvider.shutdown(); + // stop all GPIO activity/threads by shutting down the GPIO controller + // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks) + gpio.shutdown(); } } diff --git a/pi4j-example/src/main/java/MultipurposePinGpioExample.java b/pi4j-example/src/main/java/MultipurposePinGpioExample.java index b14451bec..5d3290609 100644 --- a/pi4j-example/src/main/java/MultipurposePinGpioExample.java +++ b/pi4j-example/src/main/java/MultipurposePinGpioExample.java @@ -39,10 +39,10 @@ * * @author Robert Savage */ -public class MultipurposePinGpioExample -{ - public static void main(String args[]) throws InterruptedException - { +public class MultipurposePinGpioExample { + + public static void main(String args[]) throws InterruptedException { + System.out.println("<--Pi4J--> GPIO Multipurpose Pin Example ... started."); // create gpio controller @@ -53,22 +53,18 @@ public static void main(String args[]) throws InterruptedException final GpioPinDigitalMultipurpose pin = gpio.provisionDigitalMultipurposePin(RaspiPin.GPIO_02, PinMode.DIGITAL_INPUT, PinPullResistance.PULL_DOWN); // create and register gpio pin listener - pin.addListener(new GpioPinListenerDigital() - { + pin.addListener(new GpioPinListenerDigital() { @Override - public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) - { + public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) { // display pin state on console System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState()); - } - + } }); System.out.println(" ... complete the GPIO #02 circuit and see the listener feedback here in the console."); // keep program running until user aborts (CTRL-C) - for (;;) - { + for (;;) { Thread.sleep(5000); // here we want to control the multi-purpose GPIO pin @@ -83,5 +79,9 @@ public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent pin.setMode(PinMode.DIGITAL_INPUT); System.out.println(" --> GPIO PIN - RECONFIGURED AS INPUT PIN"); } + + // stop all GPIO activity/threads by shutting down the GPIO controller + // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks) + // gpio.shutdown(); <--- implement this method call if you wish to terminate the Pi4J GPIO controller } } diff --git a/pi4j-example/src/main/java/OlimexGpioExample.java b/pi4j-example/src/main/java/OlimexGpioExample.java index c4fffca89..80dfbc83b 100644 --- a/pi4j-example/src/main/java/OlimexGpioExample.java +++ b/pi4j-example/src/main/java/OlimexGpioExample.java @@ -64,10 +64,10 @@ * @see https://www.olimex.com/Products/AVR/Development/AVR-IO-M16/ * @author Robert Savage */ -public class OlimexGpioExample -{ - public static void main(String args[]) throws InterruptedException - { +public class OlimexGpioExample { + + public static void main(String args[]) throws InterruptedException { + System.out.println("<--Pi4J--> GPIO Listen Example ... started."); // create gpio controller @@ -82,14 +82,22 @@ public static void main(String args[]) throws InterruptedException // provision gpio input pin #01 from Olimex final GpioPinDigitalInput myInput = gpio.provisionDigitalInputPin(olimexProvider, OlimexAVRIOPin.IN_01); - // create and register gpio pin listener - GpioExampleListener listener = new GpioExampleListener(); + // create gpio pin listener + GpioPinListenerDigital listener = new GpioPinListenerDigital() { + @Override + public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) { + // display pin state on console + System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + + event.getState()); + } + }; + + // register gpio pin listener for each input pin myButton.addListener(listener); myInput.addListener(listener); // setup gpio pins #04, #05, #06 as an output pins and make sure they are all LOW at startup - GpioPinDigitalOutput myRelays[] = - { + GpioPinDigitalOutput myRelays[] = { gpio.provisionDigitalOutputPin(olimexProvider, OlimexAVRIOPin.RELAY_01, "RELAY #1", PinState.LOW), gpio.provisionDigitalOutputPin(olimexProvider, OlimexAVRIOPin.RELAY_02, "RELAY #2", PinState.LOW), gpio.provisionDigitalOutputPin(olimexProvider, OlimexAVRIOPin.RELAY_03, "RELAY #3", PinState.LOW), @@ -115,25 +123,14 @@ public static void main(String args[]) throws InterruptedException // keep program running until user aborts (CTRL-C) // or we reach 60 seconds - for (int seconds = 0; seconds < 60; seconds++) - { + for (int seconds = 0; seconds < 60; seconds++) { Thread.sleep(1000); } - // shutdown the GPIO provider - olimexProvider.shutdown(); + System.out.println(" ... exiting program."); + + // stop all GPIO activity/threads by shutting down the GPIO controller + // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks) + gpio.shutdown(); } - - - public static class GpioExampleListener implements GpioPinListenerDigital - { - @Override - public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) - { - // display pin state on console - System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " - + event.getState()); - } - } } - diff --git a/pi4j-example/src/main/java/PCF8574GpioExample.java b/pi4j-example/src/main/java/PCF8574GpioExample.java index 7e6fe55b9..9ce112bad 100644 --- a/pi4j-example/src/main/java/PCF8574GpioExample.java +++ b/pi4j-example/src/main/java/PCF8574GpioExample.java @@ -56,10 +56,10 @@ * * @author Robert Savage */ -public class PCF8574GpioExample -{ - public static void main(String args[]) throws InterruptedException, IOException - { +public class PCF8574GpioExample { + + public static void main(String args[]) throws InterruptedException, IOException { + System.out.println("<--Pi4J--> PCF8574 GPIO Example ... started."); // create gpio controller @@ -69,19 +69,16 @@ public static void main(String args[]) throws InterruptedException, IOException final PCF8574GpioProvider gpioProvider = new PCF8574GpioProvider(I2CBus.BUS_1, PCF8574GpioProvider.PCF8574A_0x3F); // provision gpio input pins from MCP23017 - GpioPinDigitalInput myInputs[] = - { + GpioPinDigitalInput myInputs[] = { gpio.provisionDigitalInputPin(gpioProvider, PCF8574Pin.GPIO_00), gpio.provisionDigitalInputPin(gpioProvider, PCF8574Pin.GPIO_01), gpio.provisionDigitalInputPin(gpioProvider, PCF8574Pin.GPIO_02) }; // create and register gpio pin listener - gpio.addListener(new GpioPinListenerDigital() - { + gpio.addListener(new GpioPinListenerDigital() { @Override - public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) - { + public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) { // display pin state on console System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState()); @@ -89,8 +86,7 @@ public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent }, myInputs); // provision gpio output pins and make sure they are all LOW at startup - GpioPinDigitalOutput myOutputs[] = - { + GpioPinDigitalOutput myOutputs[] = { gpio.provisionDigitalOutputPin(gpioProvider, PCF8574Pin.GPIO_04, PinState.LOW), gpio.provisionDigitalOutputPin(gpioProvider, PCF8574Pin.GPIO_05, PinState.LOW), gpio.provisionDigitalOutputPin(gpioProvider, PCF8574Pin.GPIO_06, PinState.LOW) @@ -100,16 +96,15 @@ public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent gpio.setShutdownOptions(true, PinState.HIGH, myOutputs); // keep program running for 20 seconds - for (int count = 0; count < 10; count++) - { + for (int count = 0; count < 10; count++) { gpio.setState(true, myOutputs); Thread.sleep(1000); gpio.setState(false, myOutputs); Thread.sleep(1000); } - // shutdown the GPIO provider - gpioProvider.shutdown(); + // stop all GPIO activity/threads by shutting down the GPIO controller + // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks) + gpio.shutdown(); } -} - +} \ No newline at end of file diff --git a/pi4j-example/src/main/java/SerialExample.java b/pi4j-example/src/main/java/SerialExample.java index f80483836..7f72e3bb5 100644 --- a/pi4j-example/src/main/java/SerialExample.java +++ b/pi4j-example/src/main/java/SerialExample.java @@ -41,10 +41,10 @@ * * @author Robert Savage */ -public class SerialExample -{ - public static void main(String args[]) throws InterruptedException - { +public class SerialExample { + + public static void main(String args[]) throws InterruptedException { + // !! ATTENTION !! // By default, the serial port is configured as a console port // for interacting with the Linux OS shell. If you want to use @@ -62,11 +62,9 @@ public static void main(String args[]) throws InterruptedException final Serial serial = SerialFactory.createInstance(); // create and register the serial data listener - serial.addListener(new SerialDataListener() - { + serial.addListener(new SerialDataListener() { @Override - public void dataReceived(SerialDataEvent event) - { + public void dataReceived(SerialDataEvent event) { // print out the data received to the console System.out.print(event.getData()); } @@ -74,15 +72,13 @@ public void dataReceived(SerialDataEvent event) // open the default serial port provided on the GPIO header int ret = serial.open(Serial.DEFAULT_COM_PORT, 38400); - if (ret == -1) - { + if (ret == -1) { System.out.println(" ==>> SERIAL SETUP FAILED"); return; } // continuous loop to keep the program running until the user terminates the program - for (;;) - { + for (;;) { // write a formatted string to the serial transmit buffer serial.write("CURRENT TIME: %s", new Date().toString()); diff --git a/pi4j-example/src/main/java/ShutdownGpioExample.java b/pi4j-example/src/main/java/ShutdownGpioExample.java index a0f4a6a7a..bf26c9f52 100644 --- a/pi4j-example/src/main/java/ShutdownGpioExample.java +++ b/pi4j-example/src/main/java/ShutdownGpioExample.java @@ -28,11 +28,9 @@ * #L% */ - - import com.pi4j.io.gpio.GpioController; import com.pi4j.io.gpio.GpioFactory; -import com.pi4j.io.gpio.GpioPin; +import com.pi4j.io.gpio.GpioPinDigitalOutput; import com.pi4j.io.gpio.PinPullResistance; import com.pi4j.io.gpio.PinState; import com.pi4j.io.gpio.RaspiPin; @@ -43,17 +41,17 @@ * * @author Robert Savage */ -public class ShutdownGpioExample -{ - public static void main(String[] args) throws InterruptedException - { +public class ShutdownGpioExample { + + public static void main(String[] args) throws InterruptedException { + System.out.println("<--Pi4J--> GPIO Shutdown Example ... started."); // create gpio controller final GpioController gpio = GpioFactory.getInstance(); // provision gpio pin #01 as an output pin and turn on - final GpioPin pin = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_01, PinState.HIGH); + final GpioPinDigitalOutput pin = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_01, PinState.HIGH); // configure the pin shutdown behavior; these settings will be // automatically applied to the pin when the application is terminated @@ -66,6 +64,12 @@ public static void main(String[] args) throws InterruptedException // wait 10 seconds Thread.sleep(10000); + + System.out.println(" .. shutting down now ..."); + + // stop all GPIO activity/threads by shutting down the GPIO controller + // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks) + gpio.shutdown(); } } //END SNIPPET: shutdown-gpio-snippet diff --git a/pi4j-example/src/main/java/StepperMotorGpioExample.java b/pi4j-example/src/main/java/StepperMotorGpioExample.java index a43894741..0fbbc9d20 100644 --- a/pi4j-example/src/main/java/StepperMotorGpioExample.java +++ b/pi4j-example/src/main/java/StepperMotorGpioExample.java @@ -38,10 +38,10 @@ * * @author Robert Savage */ -public class StepperMotorGpioExample -{ - public static void main(String[] args) throws InterruptedException - { +public class StepperMotorGpioExample { + + public static void main(String[] args) throws InterruptedException { + System.out.println("<--Pi4J--> GPIO Stepper Motor Example ... started."); // create gpio controller @@ -151,5 +151,9 @@ public static void main(String[] args) throws InterruptedException // final stop to ensure no motor activity motor.stop(); + + // stop all GPIO activity/threads by shutting down the GPIO controller + // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks) + gpio.shutdown(); } } diff --git a/pi4j-example/src/main/java/SystemInfoExample.java b/pi4j-example/src/main/java/SystemInfoExample.java index 9771a3cf9..977ec4ca1 100644 --- a/pi4j-example/src/main/java/SystemInfoExample.java +++ b/pi4j-example/src/main/java/SystemInfoExample.java @@ -40,10 +40,10 @@ * * @author Robert Savage */ -public class SystemInfoExample -{ - public static void main(String[] args) throws InterruptedException, IOException - { +public class SystemInfoExample { + + public static void main(String[] args) throws InterruptedException, IOException { + // display a few of the available system information properties System.out.println("----------------------------------------------------"); System.out.println("HARDWARE INFO"); diff --git a/pi4j-example/src/main/java/TriggerGpioExample.java b/pi4j-example/src/main/java/TriggerGpioExample.java index 3d2d34b89..9032ce3ca 100644 --- a/pi4j-example/src/main/java/TriggerGpioExample.java +++ b/pi4j-example/src/main/java/TriggerGpioExample.java @@ -48,10 +48,10 @@ * * @author Robert Savage */ -public class TriggerGpioExample -{ - public static void main(String[] args) throws InterruptedException - { +public class TriggerGpioExample { + + public static void main(String[] args) throws InterruptedException { + System.out.println("<--Pi4J--> GPIO Trigger Example ... started."); // create gpio controller @@ -64,8 +64,7 @@ public static void main(String[] args) throws InterruptedException System.out.println(" ... complete the GPIO #02 circuit and see the triggers take effect."); // setup gpio pins #04, #05, #06 as an output pins and make sure they are all LOW at startup - GpioPinDigitalOutput myLed[] = - { + GpioPinDigitalOutput myLed[] = { gpio.provisionDigitalOutputPin(RaspiPin.GPIO_04, "LED #1", PinState.LOW), gpio.provisionDigitalOutputPin(RaspiPin.GPIO_05, "LED #2", PinState.LOW), gpio.provisionDigitalOutputPin(RaspiPin.GPIO_06, "LED #3", PinState.LOW) @@ -85,20 +84,21 @@ public static void main(String[] args) throws InterruptedException // create a gpio callback trigger on gpio pin#4; when #4 changes state, perform a callback // invocation on the user defined 'Callable' class instance - myButton.addTrigger(new GpioCallbackTrigger(new Callable() - { - public Void call() throws Exception - { + myButton.addTrigger(new GpioCallbackTrigger(new Callable() { + public Void call() throws Exception { System.out.println(" --> GPIO TRIGGER CALLBACK RECEIVED "); return null; } })); // keep program running until user aborts (CTRL-C) - for (;;) - { + for (;;) { Thread.sleep(500); } + + // stop all GPIO activity/threads by shutting down the GPIO controller + // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks) + // gpio.shutdown(); <--- implement this method call if you wish to terminate the Pi4J GPIO controller } } // END SNIPPET: trigger-gpio-snippet diff --git a/pi4j-example/src/main/java/UsageGpioExample.java b/pi4j-example/src/main/java/UsageGpioExample.java index cbbfc6afb..2c86af082 100644 --- a/pi4j-example/src/main/java/UsageGpioExample.java +++ b/pi4j-example/src/main/java/UsageGpioExample.java @@ -57,10 +57,10 @@ * @author Robert Savage */ @SuppressWarnings("unused") -public class UsageGpioExample -{ - public static void main(String[] args) throws InterruptedException - { +public class UsageGpioExample { + + public static void main(String[] args) throws InterruptedException { + // START SNIPPET: usage-create-controller-snippet // create gpio controller instance final GpioController gpio = GpioFactory.getInstance(); @@ -125,18 +125,19 @@ public static void main(String[] args) throws InterruptedException // END SNIPPET: usage-trigger-snippet // keep program running until user aborts (CTRL-C) - for (;;) - { + for (;;) { Thread.sleep(500); } + + // stop all GPIO activity/threads by shutting down the GPIO controller + // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks) + // gpio.shutdown(); <--- implement this method call if you wish to terminate the Pi4J GPIO controller } //START SNIPPET: usage-listener-snippet - public static class GpioUsageExampleListener implements GpioPinListenerDigital - { + public static class GpioUsageExampleListener implements GpioPinListenerDigital { @Override - public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) - { + public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) { // display pin state on console System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState()); diff --git a/pi4j-example/src/main/java/WiringPiGpioExample.java b/pi4j-example/src/main/java/WiringPiGpioExample.java index 3f03bdb77..064566427 100644 --- a/pi4j-example/src/main/java/WiringPiGpioExample.java +++ b/pi4j-example/src/main/java/WiringPiGpioExample.java @@ -28,31 +28,24 @@ import com.pi4j.wiringpi.Gpio; import com.pi4j.wiringpi.GpioUtil; -public class WiringPiGpioExample -{ +public class WiringPiGpioExample { + // Simple sequencer data // Triplets of LED, On/Off and delay - private static final int data[] = - { 0, 1, 1, 1, 1, 1, 0, 0, 0, 2, 1, 1, 1, 0, 0, 3, 1, 1, 2, 0, 0, 4, 1, 1, 3, 0, 0, 5, 1, 1, 4, + private static final int data[] = { + 0, 1, 1, 1, 1, 1, 0, 0, 0, 2, 1, 1, 1, 0, 0, 3, 1, 1, 2, 0, 0, 4, 1, 1, 3, 0, 0, 5, 1, 1, 4, 0, 0, 6, 1, 1, 5, 0, 0, 7, 1, 1, 6, 0, 1, 7, 0, 1, - 0, 0, 1, // Extra delay - // Back again - 7, 1, 1, 6, 1, 1, 7, 0, 0, 5, 1, 1, 6, 0, 0, 4, 1, 1, 5, 0, 0, 3, 1, 1, 4, 0, 0, 2, 1, 1, 3, 0, 0, 1, 1, 1, 2, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, - 0, 0, 1, // Extra delay - 9, 9, 9, // End marker - }; - public static void main(String args[]) throws InterruptedException - { + public static void main(String args[]) throws InterruptedException { int pin; int dataPtr; int l, s, d; @@ -60,8 +53,7 @@ public static void main(String args[]) throws InterruptedException System.out.println("<--Pi4J--> GPIO test program"); // setup wiringPi - if (Gpio.wiringPiSetup() == -1) - { + if (Gpio.wiringPiSetup() == -1) { System.out.println(" ==>> GPIO SETUP FAILED"); return; } @@ -73,22 +65,19 @@ public static void main(String args[]) throws InterruptedException Gpio.pullUpDnControl(7, Gpio.PUD_DOWN); // set all other GPIO as outputs - for (pin = 0; pin < 7; ++pin) - { + for (pin = 0; pin < 7; ++pin) { // export all the GPIO pins that we will be using GpioUtil.export(pin, GpioUtil.DIRECTION_OUT); Gpio.pinMode(pin, Gpio.OUTPUT); } dataPtr = 0; - for (;;) - { + for (;;) { l = data[dataPtr++]; // LED s = data[dataPtr++]; // State d = data[dataPtr++]; // Duration (10ths) - if ((l + s + d) == 27) - { + if ((l + s + d) == 27) { dataPtr = 0; continue; } diff --git a/pi4j-example/src/main/java/WiringPiGpioInterruptExample.java b/pi4j-example/src/main/java/WiringPiGpioInterruptExample.java index 40b5ec645..73797d00e 100644 --- a/pi4j-example/src/main/java/WiringPiGpioInterruptExample.java +++ b/pi4j-example/src/main/java/WiringPiGpioInterruptExample.java @@ -31,19 +31,29 @@ import com.pi4j.wiringpi.GpioInterruptEvent; import com.pi4j.wiringpi.GpioUtil; -public class WiringPiGpioInterruptExample -{ - public static void main(String args[]) throws InterruptedException - { +public class WiringPiGpioInterruptExample { + + public static void main(String args[]) throws InterruptedException { + System.out.println("<--Pi4J--> GPIO INTERRUPT test program"); - // create test listener and add as a GPIO listener - GpioTestInterruptListener lsnr = new GpioTestInterruptListener(); - GpioInterrupt.addListener(lsnr); - + // create and add GPIO listener + GpioInterrupt.addListener(new GpioInterruptListener() { + @Override + public void pinStateChange(GpioInterruptEvent event) { + System.out.println("Raspberry Pi PIN [" + event.getPin() +"] is in STATE [" + event.getState() + "]"); + + if(event.getPin() == 7) { + Gpio.digitalWrite(6, event.getStateValue()); + } + if(event.getPin() == 0) { + Gpio.digitalWrite(5, event.getStateValue()); + } + } + }); + // setup wiring pi - if (Gpio.wiringPiSetup() == -1) - { + if (Gpio.wiringPiSetup() == -1) { System.out.println(" ==>> GPIO SETUP FAILED"); return; } @@ -73,26 +83,8 @@ public static void main(String args[]) throws InterruptedException GpioInterrupt.enablePinStateChangeCallback(7); // continuously loop to prevent program from exiting - for (;;) - { + for (;;) { Thread.sleep(5000); } } } - -class GpioTestInterruptListener implements GpioInterruptListener -{ - public void pinStateChange(GpioInterruptEvent event) - { - System.out.println("Raspberry Pi PIN [" + event.getPin() +"] is in STATE [" + event.getState() + "]"); - - if(event.getPin() == 7) - { - Gpio.digitalWrite(6, event.getStateValue()); - } - if(event.getPin() == 0) - { - Gpio.digitalWrite(5, event.getStateValue()); - } - } -} diff --git a/pi4j-example/src/main/java/WiringPiLcdExample.java b/pi4j-example/src/main/java/WiringPiLcdExample.java index ab14b0128..41d6a3a4d 100644 --- a/pi4j-example/src/main/java/WiringPiLcdExample.java +++ b/pi4j-example/src/main/java/WiringPiLcdExample.java @@ -25,6 +25,7 @@ * limitations under the License. * #L% */ +import java.io.UnsupportedEncodingException; import java.text.SimpleDateFormat; import java.util.Date; @@ -37,7 +38,7 @@ public class WiringPiLcdExample { public final static int LCD_COLUMNS = 16; public final static int LCD_BITS = 4; - public static void main(String args[]) throws InterruptedException { + public static void main(String args[]) throws InterruptedException, UnsupportedEncodingException { System.out.println("<--Pi4J--> Wiring Pi LCD test program"); // setup wiringPi @@ -73,7 +74,8 @@ public static void main(String args[]) throws InterruptedException { Thread.sleep(1000); // write line 1 to LCD - Lcd.lcdPosition (lcdHandle, 0, 0) ; + Lcd.lcdHome(lcdHandle); + //Lcd.lcdPosition (lcdHandle, 0, 0) ; Lcd.lcdPuts (lcdHandle, "The Pi4J Project") ; // write line 2 to LCD @@ -81,8 +83,8 @@ public static void main(String args[]) throws InterruptedException { Lcd.lcdPuts (lcdHandle, "----------------") ; SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss"); - - // update time + + // update time every one second while(true){ // write time to line 2 on LCD Lcd.lcdPosition (lcdHandle, 0, 1) ; diff --git a/pi4j-example/src/main/java/WiringPiSerialExample.java b/pi4j-example/src/main/java/WiringPiSerialExample.java index ff67722e1..481cf420d 100644 --- a/pi4j-example/src/main/java/WiringPiSerialExample.java +++ b/pi4j-example/src/main/java/WiringPiSerialExample.java @@ -27,35 +27,34 @@ */ import com.pi4j.wiringpi.Serial; - - -public class WiringPiSerialExample -{ +public class WiringPiSerialExample { - public static void main(String args[]) throws InterruptedException - { + public static void main(String args[]) throws InterruptedException { + System.out.println("<--Pi4J--> SERIAL test program"); + // open serial port for communication int fd = Serial.serialOpen(Serial.DEFAULT_COM_PORT, 38400); - if (fd == -1) - { + if (fd == -1) { System.out.println(" ==>> SERIAL SETUP FAILED"); return; } - - while(true) - { - Serial.serialPuts(fd, "TEST\r\n"); - int dataavail = Serial.serialDataAvail(fd); + // infinite loop + while(true) { - while(dataavail > 0) - { + // send test ASCII message + Serial.serialPuts(fd, "TEST\r\n"); + + // display data received to console + int dataavail = Serial.serialDataAvail(fd); + while(dataavail > 0) { int data = Serial.serialGetchar(fd); System.out.print((char)data); dataavail = Serial.serialDataAvail(fd); } + // wash, rinse, repeat Thread.sleep(1000); } } diff --git a/pi4j-example/src/main/java/WiringPiSoftPWMExample.java b/pi4j-example/src/main/java/WiringPiSoftPWMExample.java index 45276a7df..e49fd3e4e 100644 --- a/pi4j-example/src/main/java/WiringPiSoftPWMExample.java +++ b/pi4j-example/src/main/java/WiringPiSoftPWMExample.java @@ -1,5 +1,3 @@ - - /* * #%L * ********************************************************************** @@ -29,10 +27,10 @@ import com.pi4j.wiringpi.SoftPwm; -public class WiringPiSoftPWMExample -{ - public static void main(String[] args) throws InterruptedException - { +public class WiringPiSoftPWMExample { + + public static void main(String[] args) throws InterruptedException { + // initialize wiringPi library com.pi4j.wiringpi.Gpio.wiringPiSetup(); @@ -40,18 +38,15 @@ public static void main(String[] args) throws InterruptedException SoftPwm.softPwmCreate(1, 0, 100); // continuous loop - while (true) - { + while (true) { // fade LED to fully ON - for (int i = 0; i <= 100; i++) - { + for (int i = 0; i <= 100; i++) { SoftPwm.softPwmWrite(1, i); Thread.sleep(100); } // fade LED to fully OFF - for (int i = 100; i >= 0; i--) - { + for (int i = 100; i >= 0; i--) { SoftPwm.softPwmWrite(1, i); Thread.sleep(100); } diff --git a/pi4j-gpio-extension/src/main/java/com/pi4j/gpio/extension/mcp/MCP23008GpioProvider.java b/pi4j-gpio-extension/src/main/java/com/pi4j/gpio/extension/mcp/MCP23008GpioProvider.java index 4f3d17729..0b0dbf42b 100644 --- a/pi4j-gpio-extension/src/main/java/com/pi4j/gpio/extension/mcp/MCP23008GpioProvider.java +++ b/pi4j-gpio-extension/src/main/java/com/pi4j/gpio/extension/mcp/MCP23008GpioProvider.java @@ -262,6 +262,14 @@ public PinPullResistance getPullResistance(Pin pin) { @Override public void shutdown() { + + // prevent reentrant invocation + if(isShutdown()) + return; + + // perform shutdown login in base + super.shutdown(); + try { // if a monitor is running, then shut it down now if (monitor != null) { @@ -292,7 +300,7 @@ public GpioStateMonitor(I2CDevice device) { this.device = device; } - public void shutdown() { + public void shutdown() { shuttingDown = true; } diff --git a/pi4j-gpio-extension/src/main/java/com/pi4j/gpio/extension/mcp/MCP23017GpioProvider.java b/pi4j-gpio-extension/src/main/java/com/pi4j/gpio/extension/mcp/MCP23017GpioProvider.java index f8e4631a6..8fc5030b2 100644 --- a/pi4j-gpio-extension/src/main/java/com/pi4j/gpio/extension/mcp/MCP23017GpioProvider.java +++ b/pi4j-gpio-extension/src/main/java/com/pi4j/gpio/extension/mcp/MCP23017GpioProvider.java @@ -356,6 +356,14 @@ public PinPullResistance getPullResistance(Pin pin) { @Override public void shutdown() { + + // prevent reentrant invocation + if(isShutdown()) + return; + + // perform shutdown login in base + super.shutdown(); + try { // if a monitor is running, then shut it down now if (monitor != null) { diff --git a/pi4j-gpio-extension/src/main/java/com/pi4j/gpio/extension/olimex/OlimexAVRIOGpioProvider.java b/pi4j-gpio-extension/src/main/java/com/pi4j/gpio/extension/olimex/OlimexAVRIOGpioProvider.java index ccb564e40..4d6b889d6 100644 --- a/pi4j-gpio-extension/src/main/java/com/pi4j/gpio/extension/olimex/OlimexAVRIOGpioProvider.java +++ b/pi4j-gpio-extension/src/main/java/com/pi4j/gpio/extension/olimex/OlimexAVRIOGpioProvider.java @@ -135,15 +135,27 @@ public PinState getState(Pin pin) { @Override public void shutdown() { + + // prevent reentrant invocation + if(isShutdown()) + return; + + // perform shutdown login in base + super.shutdown(); + // if a serial processing queue is running, then shut it down now if (queue != null) { // shutdown serial data processing thread queue.shutdown(); + //queue.interrupt(); queue = null; } // close the serial port communication com.close(); + + // shutdown any serial data monitoring threads + com.shutdown(); } /** diff --git a/pi4j-gpio-extension/src/main/java/com/pi4j/gpio/extension/pcf/PCF8574GpioProvider.java b/pi4j-gpio-extension/src/main/java/com/pi4j/gpio/extension/pcf/PCF8574GpioProvider.java index 9a0c89e71..e8f48614b 100644 --- a/pi4j-gpio-extension/src/main/java/com/pi4j/gpio/extension/pcf/PCF8574GpioProvider.java +++ b/pi4j-gpio-extension/src/main/java/com/pi4j/gpio/extension/pcf/PCF8574GpioProvider.java @@ -185,6 +185,14 @@ public PinState getState(Pin pin) { @Override public void shutdown() { + + // prevent reentrant invocation + if(isShutdown()) + return; + + // perform shutdown login in base + super.shutdown(); + try { // if a monitor is running, then shut it down now if (monitor != null) {