001package com.pi4j.io.gpio.impl; 002 003/* 004 * #%L 005 * ********************************************************************** 006 * ORGANIZATION : Pi4J 007 * PROJECT : Pi4J :: Java Library (Core) 008 * FILENAME : GpioEventMonitorExecutorImpl.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 032import com.pi4j.io.gpio.GpioFactory; 033import com.pi4j.io.gpio.GpioPinDigitalInput; 034import com.pi4j.io.gpio.GpioPinInput; 035import com.pi4j.io.gpio.PinState; 036import com.pi4j.io.gpio.event.PinDigitalStateChangeEvent; 037import com.pi4j.io.gpio.event.PinEvent; 038import com.pi4j.io.gpio.event.PinEventType; 039import com.pi4j.io.gpio.event.PinListener; 040import com.pi4j.io.gpio.tasks.impl.GpioEventDebounceTaskImpl; 041import com.pi4j.io.gpio.tasks.impl.GpioEventDispatchTaskImpl; 042 043import java.util.concurrent.ExecutorService; 044import java.util.concurrent.ScheduledExecutorService; 045import java.util.concurrent.ScheduledFuture; 046import java.util.concurrent.TimeUnit; 047 048public class GpioEventMonitorExecutorImpl implements PinListener { 049 050 private final GpioPinInput pin; 051 private static ExecutorService executor; 052 private static ScheduledExecutorService scheduledExecutor; 053 private ScheduledFuture<?> debounceFuture = null; 054 055 public GpioEventMonitorExecutorImpl(GpioPinInput pin) { 056 this.pin = pin; 057 executor = GpioFactory.getExecutorServiceFactory().getGpioEventExecutorService(); 058 scheduledExecutor = GpioFactory.getExecutorServiceFactory().getScheduledExecutorService(); 059 } 060 061 @Override 062 public void handlePinEvent(PinEvent event) { 063 064 // for digital input pins, we need to enforce pin debounce event suppression 065 if(pin instanceof GpioPinDigitalInput && event.getEventType() == PinEventType.DIGITAL_STATE_CHANGE){ 066 067 // cast to the digital input pin interface, get the current state from 068 // the event, and determine the debounce interval for this pin state 069 GpioPinDigitalInput dip = (GpioPinDigitalInput)pin; 070 PinState state = ((PinDigitalStateChangeEvent) event).getState(); 071 int pinDebounceForState = dip.getDebounce(state); 072 073 // if the pin has a debounce delay configured for this pin state, 074 // then we will need to use the pin debounce logic to defer pin events 075 if(pinDebounceForState > 0) { 076 // if no existing debounce future task exists or no future task is still busy, then 077 // create a new debounce future task and schedule it based on the debounce 078 // interval defined for the current pin state 079 if (debounceFuture == null || debounceFuture.isDone()) { 080 debounceFuture = scheduledExecutor.schedule( 081 new GpioEventDebounceTaskImpl(dip, state), pinDebounceForState, TimeUnit.MILLISECONDS); 082 } else { 083 // if an existing debounce future task exists and is still busy, 084 // then exit this method effectively suppressing the current pin event 085 return; 086 } 087 } 088 } 089 090 // add a new pin event notification to the thread pool for *immediate* execution 091 executor.execute(new GpioEventDispatchTaskImpl(pin, event)); 092 } 093}