com.pi4j.io.gpio.GpioProviderBase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of osgi.enroute.iot.pi.provider Show documentation
Show all versions of osgi.enroute.iot.pi.provider Show documentation
This bundle wraps Pi4j (http://pi4j.com) that wraps the native code Wiring Pi (http://wiringpi.com). It wraps these libraries to make them OSGi friendly and allow them to work together with the OSGi enRoute IoT circuit library (osgi.enroute.iot.circuit). The bundle will first use Pi4J to detect on what hardware it runs. If it runs on an appropriate type, it will register a component that can be configured with Metatype. The Metatype defines a full blown configuration template for all the Pi's functions. The GPIO's are registered as components for the circuit. Regardless of the success of the configuration, this bundle will also register a GpioController service, which is the main Pi4J class.
The newest version!
package com.pi4j.io.gpio;
/*
* #%L
* **********************************************************************
* ORGANIZATION : Pi4J
* PROJECT : Pi4J :: Java Library (Core)
* FILENAME : GpioProviderBase.java
*
* This file is part of the Pi4J project. More information about
* this project can be found here: http://www.pi4j.com/
* **********************************************************************
* %%
* Copyright (C) 2012 - 2015 Pi4J
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import com.pi4j.io.gpio.event.PinAnalogValueChangeEvent;
import com.pi4j.io.gpio.event.PinDigitalStateChangeEvent;
import com.pi4j.io.gpio.event.PinListener;
import com.pi4j.io.gpio.exception.InvalidPinException;
import com.pi4j.io.gpio.exception.InvalidPinModeException;
import com.pi4j.io.gpio.exception.UnsupportedPinModeException;
import com.pi4j.io.gpio.exception.UnsupportedPinPullResistanceException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Abstract base implementation of {@link com.pi4j.io.gpio.GpioProvider}.
*
* @author Robert Savage (http://www.savagehomeautomation.com)
*/
@SuppressWarnings("unused")
public abstract class GpioProviderBase implements GpioProvider {
public abstract String getName();
protected final Map> listeners = new ConcurrentHashMap<>();
protected final Map cache = new ConcurrentHashMap<>();
protected boolean isshutdown = false;
@Override
public boolean hasPin(Pin pin) {
return (pin.getProvider().equals(getName()));
}
protected GpioProviderPinCache getPinCache(Pin pin) {
if (!cache.containsKey(pin)) {
cache.put(pin, new GpioProviderPinCache(pin));
}
return cache.get(pin);
}
@Override
public void export(Pin pin, PinMode mode, PinState defaultState) {
// export the pin and set it's mode
export(pin, mode);
// apply default state if one was provided and only if this pin is a digital output
if(defaultState != null && mode == PinMode.DIGITAL_OUTPUT) {
setState(pin, defaultState);
}
}
@Override
public void export(Pin pin, PinMode mode) {
if (!hasPin(pin)) {
throw new InvalidPinException(pin);
}
if (!pin.getSupportedPinModes().contains(mode)) {
throw new UnsupportedPinModeException(pin, mode);
}
// cache exported state
getPinCache(pin).setExported(true);
// cache mode
getPinCache(pin).setMode(mode);
}
@Override
public boolean isExported(Pin pin) {
if (!hasPin(pin)) {
throw new InvalidPinException(pin);
}
// return cached exported state
return getPinCache(pin).isExported();
}
@Override
public void unexport(Pin pin) {
if (!hasPin(pin)) {
throw new InvalidPinException(pin);
}
// cache exported state
getPinCache(pin).setExported(false);
}
@Override
public void setMode(Pin pin, PinMode mode) {
if (!pin.getSupportedPinModes().contains(mode)) {
throw new InvalidPinModeException(pin, "Invalid pin mode [" + mode.getName() + "]; pin [" + pin.getName() + "] does not support this mode.");
}
if (!pin.getSupportedPinModes().contains(mode)) {
throw new UnsupportedPinModeException(pin, mode);
}
// cache mode
getPinCache(pin).setMode(mode);
}
@Override
public PinMode getMode(Pin pin) {
if (!hasPin(pin)) {
throw new InvalidPinException(pin);
}
// return cached mode value
return getPinCache(pin).getMode();
}
@Override
public void setPullResistance(Pin pin, PinPullResistance resistance) {
if (!hasPin(pin)) {
throw new InvalidPinException(pin);
}
if (!pin.getSupportedPinPullResistance().contains(resistance)) {
throw new UnsupportedPinPullResistanceException(pin, resistance);
}
// cache resistance
getPinCache(pin).setResistance(resistance);
}
@Override
public PinPullResistance getPullResistance(Pin pin) {
if (!hasPin(pin)) {
throw new InvalidPinException(pin);
}
// return cached resistance
return getPinCache(pin).getResistance();
}
@Override
public void setState(Pin pin, PinState state) {
if (!hasPin(pin)) {
throw new InvalidPinException(pin);
}
PinMode mode = getMode(pin);
// only permit invocation on pins set to DIGITAL_OUTPUT modes
if (mode != PinMode.DIGITAL_OUTPUT) {
throw new InvalidPinModeException(pin, "Invalid pin mode on pin [" + pin.getName() + "]; cannot setState() when pin mode is [" + mode.getName() + "]");
}
// for digital output pins, we will echo the event feedback
dispatchPinDigitalStateChangeEvent(pin, state);
// cache pin state
getPinCache(pin).setState(state);
}
@Override
public PinState getState(Pin pin) {
if (!hasPin(pin)) {
throw new InvalidPinException(pin);
}
PinMode mode = getMode(pin);
// only permit invocation on pins set to DIGITAL modes
if (!PinMode.allDigital().contains(mode)) {
throw new InvalidPinModeException(pin, "Invalid pin mode on pin [" + pin.getName() + "]; cannot getState() when pin mode is [" + mode.getName() + "]");
}
// return cached pin state
return getPinCache(pin).getState();
}
@Override
public void setValue(Pin pin, double value) {
if (!hasPin(pin)) {
throw new InvalidPinException(pin);
}
PinMode mode = getMode(pin);
// only permit invocation on pins set to OUTPUT modes
if (!PinMode.allOutput().contains(mode)) {
throw new InvalidPinModeException(pin, "Invalid pin mode on pin [" + pin.getName() + "]; cannot setValue(" + value + ") when pin mode is [" + mode.getName() + "]");
}
// for digital analog pins, we will echo the event feedback
dispatchPinAnalogValueChangeEvent(pin, value);
// cache pin analog value
getPinCache(pin).setAnalogValue(value);
}
@Override
public double getValue(Pin pin) {
if (!hasPin(pin)) {
throw new InvalidPinException(pin);
}
PinMode mode = getMode(pin);
if (mode == PinMode.DIGITAL_OUTPUT) {
return getState(pin).getValue();
}
// return cached pin analog value
return getPinCache(pin).getAnalogValue();
}
@Override
public void setPwm(Pin pin, int value) {
if (!hasPin(pin)) {
throw new InvalidPinException(pin);
}
PinMode mode = getMode(pin);
if (mode != PinMode.PWM_OUTPUT) {
throw new InvalidPinModeException(pin, "Invalid pin mode [" + mode.getName() + "]; unable to setPwm(" + value + ")");
}
// cache pin PWM value
getPinCache(pin).setPwmValue(value);
}
@Override
public int getPwm(Pin pin) {
if (!hasPin(pin)) {
throw new InvalidPinException(pin);
}
// return cached pin PWM value
return getPinCache(pin).getPwmValue();
}
@Override
public void addListener(Pin pin, PinListener listener) {
synchronized (listeners) {
// create new pin listener entry if one does not already exist
if (!listeners.containsKey(pin)) {
listeners.put(pin, new ArrayList());
}
// add the listener instance to the listeners map entry
List lsnrs = listeners.get(pin);
if (!lsnrs.contains(listener)) {
lsnrs.add(listener);
}
}
}
@Override
public void removeListener(Pin pin, PinListener listener) {
synchronized (listeners) {
// lookup to pin entry in the listeners map
if (listeners.containsKey(pin)) {
// remote the listener instance from the listeners map entry if found
List lsnrs = listeners.get(pin);
if (lsnrs.contains(listener)) {
lsnrs.remove(listener);
}
// if the listener list is empty, then remove the listener pin from the map
if (lsnrs.isEmpty()) {
listeners.remove(pin);
}
}
}
}
@Override
public void removeAllListeners() {
synchronized (listeners) {
// iterate over all listener pins in the map
List pins_copy = new ArrayList<>(listeners.keySet());
for (Pin pin : pins_copy) {
if(listeners.containsKey(pin)) {
// iterate over all listener handler in the map entry
// and remove each listener handler instance
List lsnrs = listeners.get(pin);
if (!lsnrs.isEmpty()) {
List lsnrs_copy = new ArrayList<>(lsnrs);
for (int index = lsnrs_copy.size() - 1; index >= 0; index--) {
PinListener listener = lsnrs_copy.get(index);
removeListener(pin, listener);
}
}
}
}
}
}
protected void dispatchPinDigitalStateChangeEvent(Pin pin, PinState state) {
// if the pin listeners map contains this pin, then dispatch event
if (listeners.containsKey(pin)) {
// dispatch this event to all listener handlers
for (PinListener listener : listeners.get(pin)) {
listener.handlePinEvent(new PinDigitalStateChangeEvent(this, pin, state));
}
}
}
protected void dispatchPinAnalogValueChangeEvent(Pin pin, double value) {
// if the pin listeners map contains this pin, then dispatch event
if (listeners.containsKey(pin)) {
// dispatch this event to all listener handlers
for (PinListener listener : listeners.get(pin)) {
listener.handlePinEvent(new PinAnalogValueChangeEvent(this, pin, value));
}
}
}
@Override
public void shutdown() {
// prevent reentrant invocation
if(isShutdown())
return;
// remove all listeners
removeAllListeners();
// 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;
}
}