001package com.pi4j.wiringpi; 002 003/* 004 * #%L 005 * ********************************************************************** 006 * ORGANIZATION : Pi4J 007 * PROJECT : Pi4J :: Java Library (Core) 008 * FILENAME : GpioInterrupt.java 009 * 010 * This file is part of the Pi4J project. More information about 011 * this project can be found here: https://www.pi4j.com/ 012 * ********************************************************************** 013 * %% 014 * Copyright (C) 2012 - 2021 Pi4J 015 * %% 016 * This program is free software: you can redistribute it and/or modify 017 * it under the terms of the GNU Lesser General Public License as 018 * published by the Free Software Foundation, either version 3 of the 019 * License, or (at your option) any later version. 020 * 021 * This program is distributed in the hope that it will be useful, 022 * but WITHOUT ANY WARRANTY; without even the implied warranty of 023 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 024 * GNU General Lesser Public License for more details. 025 * 026 * You should have received a copy of the GNU General Lesser Public 027 * License along with this program. If not, see 028 * <http://www.gnu.org/licenses/lgpl-3.0.html>. 029 * #L% 030 */ 031 032 033import com.pi4j.util.NativeLibraryLoader; 034 035import java.util.Vector; 036 037/** 038 * <p> 039 * This class provides static methods to configure the native Pi4J library to listen to GPIO 040 * interrupts and invoke callbacks into this class. Additionally, this class provides a listener 041 * registration allowing Java consumers to subscribe to GPIO pin state changes. 042 * </p> 043 * 044 * <p> 045 * Before using the Pi4J library, you need to ensure that the Java VM in configured with access to 046 * the following system libraries: 047 * <ul> 048 * <li>pi4j</li> 049 * <li>wiringPi</li> 050 * </ul> 051 * <blockquote> This library depends on the wiringPi native system library.</br> (developed by 052 * Gordon Henderson @ <a href="http://wiringpi.com/">http://wiringpi.com/</a>) 053 * </blockquote> 054 * </p> 055 * 056 * @see <a href="https://www.pi4j.com/">https://www.pi4j.com/</a> 057 * @author Robert Savage (<a 058 * href="http://www.savagehomeautomation.com">http://www.savagehomeautomation.com</a>) 059 */ 060public class GpioInterrupt { 061 062 private static Vector<GpioInterruptListener> listeners = new Vector<>(); 063 private Object lock; 064 065 // private constructor 066 private GpioInterrupt() { 067 // forbid object construction 068 } 069 070 static { 071 // Load the platform library 072 NativeLibraryLoader.load("libpi4j.so", "pi4j"); 073 } 074 075 /** 076 * <p> 077 * This method is used to instruct the native code to setup a monitoring thread to monitor 078 * interrupts that represent changes to the selected GPIO pin. 079 * </p> 080 * 081 * <p> 082 * <b>The GPIO pin must first be exported before it can be monitored.</b> 083 * </p> 084 * 085 * @param pin GPIO pin number (not header pin number; not wiringPi pin number) 086 * @return A return value of a negative number represents an error. A return value of '0' 087 * represents success and that the GPIO pin is already being monitored. A return value 088 * of '1' represents success and that a new monitoring thread was created to handle the 089 * requested GPIO pin number. 090 */ 091 public static native int enablePinStateChangeCallback(int pin); 092 093 /** 094 * <p> 095 * This method is used to instruct the native code to stop the monitoring thread monitoring 096 * interrupts on the selected GPIO pin. 097 * </p> 098 * 099 * @param pin GPIO pin number (not header pin number; not wiringPi pin number) 100 101 * @return A return value of a negative number represents an error. A return value of '0' 102 * represents success and that no existing monitor was previously running. A return 103 * value of '1' represents success and that an existing monitoring thread was stopped 104 * for the requested GPIO pin number. 105 */ 106 public static native int disablePinStateChangeCallback(int pin); 107 108 /** 109 * <p> 110 * This method is provided as the callback handler for the Pi4J native library to invoke when a 111 * GPIO interrupt is detected. This method should not be called from any Java consumers. (Thus 112 * is is marked as a private method.) 113 * </p> 114 * 115 * @param pin GPIO pin number (not header pin number; not wiringPi pin number) 116 * @param state New GPIO pin state. 117 */ 118 @SuppressWarnings("unchecked") 119 private static void pinStateChangeCallback(int pin, boolean state) { 120 121 Vector<GpioInterruptListener> listenersClone; 122 listenersClone = (Vector<GpioInterruptListener>) listeners.clone(); 123 124 for (int i = 0; i < listenersClone.size(); i++) { 125 GpioInterruptListener listener = listenersClone.elementAt(i); 126 if(listener != null) { 127 GpioInterruptEvent event = new GpioInterruptEvent(listener, pin, state); 128 listener.pinStateChange(event); 129 } 130 } 131 132 //System.out.println("GPIO PIN [" + pin + "] = " + state); 133 } 134 135 /** 136 * <p> 137 * Java consumer code can all this method to register itself as a listener for pin state 138 * changes. 139 * </p> 140 * 141 * @see com.pi4j.wiringpi.GpioInterruptListener 142 * @see com.pi4j.wiringpi.GpioInterruptEvent 143 * 144 * @param listener A class instance that implements the GpioInterruptListener interface. 145 */ 146 public static synchronized void addListener(GpioInterruptListener listener) { 147 if (!listeners.contains(listener)) { 148 listeners.addElement(listener); 149 } 150 } 151 152 /** 153 * <p> 154 * Java consumer code can all this method to unregister itself as a listener for pin state 155 * changes. 156 * </p> 157 * 158 * @see com.pi4j.wiringpi.GpioInterruptListener 159 * @see com.pi4j.wiringpi.GpioInterruptEvent 160 * 161 * @param listener A class instance that implements the GpioInterruptListener interface. 162 */ 163 public static synchronized void removeListener(GpioInterruptListener listener) { 164 if (listeners.contains(listener)) { 165 listeners.removeElement(listener); 166 } 167 } 168 169 170 /** 171 * <p> 172 * Returns true if the listener is already registered for event callbacks. 173 * </p> 174 * 175 * @see com.pi4j.wiringpi.GpioInterruptListener 176 * @see com.pi4j.wiringpi.GpioInterruptEvent 177 * 178 * @param listener A class instance that implements the GpioInterruptListener interface. 179 */ 180 public static synchronized boolean hasListener(GpioInterruptListener listener) { 181 return listeners.contains(listener); 182 } 183}