All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.diozero.api.SmoothedInputDevice Maven / Gradle / Ivy

There is a newer version: 1.4.0
Show newest version
package com.diozero.api;

/*
 * #%L
 * Organisation: diozero
 * Project:      Device I/O Zero - Core
 * Filename:     SmoothedInputDevice.java  
 * 
 * This file is part of the diozero project. More information about this project
 * can be found at http://www.diozero.com/
 * %%
 * Copyright (C) 2016 - 2020 diozero
 * %%
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * #L%
 */

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;

import com.diozero.internal.provider.GpioDeviceFactoryInterface;
import com.diozero.util.DeviceFactoryHelper;
import com.diozero.util.DioZeroScheduler;
import com.diozero.util.RuntimeIOException;

/**
 * 

* Represents a generic input device which takes its value from the number of * active events over a specific time period. *

* *

* This class extends {@link com.diozero.api.WaitableDigitalInputDevice * WaitableDigitalInputDevice} with a queue which is added to whenever the input device * is active. The number of the active events in the queue is compared to a * threshold which is used to determine the state of the 'active' property. *

* *

* Any active events over the specified eventAge are removed by a background * thread. *

* *

* This class is intended for use with devices which exhibit "twitchy" behaviour * (such as certain motion sensors). *

*/ public class SmoothedInputDevice extends WaitableDigitalInputDevice { private int threshold; private int eventAge; private int eventDetectPeriod; private Queue queue; /** * @param gpio * GPIO to which the device is connected. * @param pud * Pull up/down configuration, values: NONE, PULL_UP, PULL_DOWN. * @param threshold * The value above which the device will be considered "on". * @param eventAge * The time in milliseconds to keep active events in the queue. * @param eventDetectPeriod * How frequently to check for events. * @throws RuntimeIOException * if an I/O error occurs */ public SmoothedInputDevice(int gpio, GpioPullUpDown pud, int threshold, int eventAge, int eventDetectPeriod) throws RuntimeIOException { this(DeviceFactoryHelper.getNativeDeviceFactory(), gpio, pud, threshold, eventAge, eventDetectPeriod); } /** * @param deviceFactory * Device factory to use to provision this device. * @param gpio * GPIO to which the device is connected. * @param pud * Pull up/down configuration, values: NONE, PULL_UP, PULL_DOWN. * @param threshold * The value above which the device will be considered "on". * @param eventAge * The time in milliseconds to keep active events in the queue. * @param eventDetectPeriod * How frequently to check for events. * @throws RuntimeIOException * if an I/O error occurs */ public SmoothedInputDevice(GpioDeviceFactoryInterface deviceFactory, int gpio, GpioPullUpDown pud, int threshold, int eventAge, int eventDetectPeriod) throws RuntimeIOException { super(deviceFactory, gpio, pud, pud == GpioPullUpDown.PULL_UP ? GpioEventTrigger.FALLING : GpioEventTrigger.RISING); this.threshold = threshold; this.eventAge = eventAge; this.eventDetectPeriod = eventDetectPeriod; queue = new LinkedList<>(); DioZeroScheduler.getDaemonInstance().scheduleAtFixedRate(new EventDetection(), eventDetectPeriod, eventDetectPeriod, TimeUnit.MILLISECONDS); } @Override public void valueChanged(DigitalInputEvent event) { event.setActiveHigh(activeHigh); if (event.isActive()) { synchronized (queue) { queue.add(Long.valueOf(event.getEpochTime())); } } } private class EventDetection implements Runnable { private Predicate removePredicate; private long now; private boolean active; EventDetection() { removePredicate = time -> time.longValue() < (now - eventAge); } @Override public void run() { long nano_time = System.nanoTime(); now = System.currentTimeMillis(); synchronized (queue) { // Purge any old events queue.removeIf(removePredicate); // Check if the number of events exceeds the threshold if (queue.size() > threshold) { if (! active) { SmoothedInputDevice.super.valueChanged(new DigitalInputEvent(gpio, now, nano_time, activeHigh)); active = true; } // If an event is fired clear the queue of all events queue.clear(); } else if (active) { SmoothedInputDevice.super.valueChanged(new DigitalInputEvent(gpio, now, nano_time, !activeHigh)); active = false; } } } } /** * If the number of on events younger than eventAge exceeds this amount, * then 'isActive' will return 'True'. * * @return event threshold */ public int getThreshold() { return threshold; } /** * Set the threshold value in terms of number of on events within the * specified time period that will trigger an on event to any listeners. * * @param threshold * New threshold value. */ public void setThreshold(int threshold) { this.threshold = threshold; } /** * The time in milliseconds to keep items in the queue. * * @return The event age (milliseconds). */ public int getEventAge() { return eventAge; } /** * Set the event age (milliseconds). * * @param eventAge * New event age value (milliseconds). */ public void setEventAge(int eventAge) { this.eventAge = eventAge; } /** * How frequently (in milliseconds) to check the state of the queue. * * @return The event detection period (milliseconds) */ public int getEventDetectPeriod() { return eventDetectPeriod; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy