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

com.pi4j.io.gpio.GpioProviderBase Maven / Gradle / Ivy

Go to download

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;
    }    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy