From a02be787ee8170740c06e7d8bc84f76df2f009c3 Mon Sep 17 00:00:00 2001 From: Nils Bauer <15706595+nils-bauer@users.noreply.github.com> Date: Sun, 3 Jan 2021 08:38:22 +0100 Subject: [PATCH] [gpio] GPIO Binding initial contribution (#1334) * Added GPIO support Signed-off-by: Nils Bauer --- CODEOWNERS | 1 + bom/openhab-addons/pom.xml | 5 + bundles/org.openhab.binding.gpio/NOTICE | 20 ++++ bundles/org.openhab.binding.gpio/README.md | 88 ++++++++++++++ bundles/org.openhab.binding.gpio/pom.xml | 25 ++++ .../src/main/feature/feature.xml | 23 ++++ .../gpio/internal/GPIOBindingConstants.java | 47 ++++++++ .../gpio/internal/GPIOHandlerFactory.java | 56 +++++++++ .../gpio/internal/NoGpioIdException.java | 25 ++++ .../configuration/GPIOConfiguration.java | 35 ++++++ .../configuration/GPIOInputConfiguration.java | 28 +++++ .../GPIOOutputConfiguration.java | 25 ++++ .../configuration/PigpioConfiguration.java | 35 ++++++ .../gpio/internal/handler/ChannelHandler.java | 28 +++++ .../handler/PigpioDigitalInputHandler.java | 88 ++++++++++++++ .../handler/PigpioDigitalOutputHandler.java | 85 ++++++++++++++ .../internal/handler/PigpioRemoteHandler.java | 111 ++++++++++++++++++ .../main/resources/OH-INF/binding/binding.xml | 10 ++ .../resources/OH-INF/thing/pigpio-remote.xml | 72 ++++++++++++ bundles/pom.xml | 1 + 20 files changed, 808 insertions(+) create mode 100644 bundles/org.openhab.binding.gpio/NOTICE create mode 100644 bundles/org.openhab.binding.gpio/README.md create mode 100644 bundles/org.openhab.binding.gpio/pom.xml create mode 100644 bundles/org.openhab.binding.gpio/src/main/feature/feature.xml create mode 100644 bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/GPIOBindingConstants.java create mode 100644 bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/GPIOHandlerFactory.java create mode 100644 bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/NoGpioIdException.java create mode 100644 bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/GPIOConfiguration.java create mode 100644 bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/GPIOInputConfiguration.java create mode 100644 bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/GPIOOutputConfiguration.java create mode 100644 bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/PigpioConfiguration.java create mode 100644 bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/ChannelHandler.java create mode 100644 bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/PigpioDigitalInputHandler.java create mode 100644 bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/PigpioDigitalOutputHandler.java create mode 100644 bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/PigpioRemoteHandler.java create mode 100644 bundles/org.openhab.binding.gpio/src/main/resources/OH-INF/binding/binding.xml create mode 100644 bundles/org.openhab.binding.gpio/src/main/resources/OH-INF/thing/pigpio-remote.xml diff --git a/CODEOWNERS b/CODEOWNERS index 5a0d8c6b0..363278450 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -84,6 +84,7 @@ /bundles/org.openhab.binding.generacmobilelink/ @digitaldan /bundles/org.openhab.binding.globalcache/ @mhilbush /bundles/org.openhab.binding.goecharger/ @SamuelBrucksch +/bundles/org.openhab.binding.gpio/ @nils-bauer /bundles/org.openhab.binding.gpstracker/ @gbicskei /bundles/org.openhab.binding.gree/ @markus7017 /bundles/org.openhab.binding.groheondus/ @FlorianSW diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml index c31c6713e..b3039866c 100644 --- a/bom/openhab-addons/pom.xml +++ b/bom/openhab-addons/pom.xml @@ -406,6 +406,11 @@ org.openhab.binding.goecharger ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.gpio + ${project.version} + org.openhab.addons.bundles org.openhab.binding.gpstracker diff --git a/bundles/org.openhab.binding.gpio/NOTICE b/bundles/org.openhab.binding.gpio/NOTICE new file mode 100644 index 000000000..f3f5da627 --- /dev/null +++ b/bundles/org.openhab.binding.gpio/NOTICE @@ -0,0 +1,20 @@ +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab-addons + +== Third-party Content + +jpigpio +* License: Apache License 2.0 +* Project: https://github.com/Xeli/jpigpio +* Source: https://github.com/Xeli/jpigpio diff --git a/bundles/org.openhab.binding.gpio/README.md b/bundles/org.openhab.binding.gpio/README.md new file mode 100644 index 000000000..e935a735f --- /dev/null +++ b/bundles/org.openhab.binding.gpio/README.md @@ -0,0 +1,88 @@ +# GPIO Binding + +This binding adds GPIO support via the pigpio daemon to openhab. +It requires the pigpio (http://abyz.me.uk/rpi/pigpio/) to be running on the pi that should be controlled. + +## Supported Things + +### pigpio-remote + +This thing represents a remote pigpio instance running as daemon on a raspberry pi. + +## Thing Configuration + +### Pigpio Remote (`pigpio-remote`) + +On a raspberry (or a compatible device) you have to install pigpio: + +``` +sudo apt-get install pigpiod +sudo raspi-config +``` + +-> Interfacing Options --> Remote GPIO --> YES --> OK --> Finish + +``` +sudo systemctl enable pigpiod +sudo systemctl start pigpiod +``` + +Set `host` to the address of the pi and the `port` to the port of pigpio (default: 8888). + +## Channels + +### Pigpio Remote + +| channel | type | description | +|-----------------------|--------|---------------------------------| +| pigpio-digital-input | Switch | Read-only value of the gpio pin | +| pigpio-digital-output | Switch | Controls the gpio pin | + +### GPIO digital input channel + +Set the number of the pin in `gpioId`. +If you want to invert the value, set `invert` to true. +To prevent incorrect change events, you can adjust the `debouncingTime`. + +### GPIO digital output channel + +Set the number of the pin in `gpioId`. +If you want to invert the value, set `invert` to true. + +## Full Example + + +demo.things: + +``` +Thing gpio:pigpio-remote:sample-pi-1 "Sample-Pi 1" [host="192.168.2.36", port=8888] { + Channels: + Type pigpio-digital-input : sample-input-1 [ gpioId=10] + Type pigpio-digital-input : sample-input-2 [ gpioId=14, invert=true] + Type pigpio-digital-output : sample-output-1 [ gpioId=3] +} + +Thing gpio:pigpio-remote:sample-pi-2 "Sample-Pi 2" [host="192.168.2.37", port=8888] { + Channels: + Type pigpio-digital-input : sample-input-3 [ gpioId=16, debouncingTime=20] + Type pigpio-digital-input : sample-input-4 [ gpioId=17, invert=true, debouncingTime=5] + Type pigpio-digital-output : sample-output-2 [ gpioId=4, invert=true] +} +``` + +demo.items: + +``` +Switch SampleInput1 {channel="gpio:pigpio-remote:sample-pi-1:sample-input-1"} +Switch SampleOutput1 {channel="gpio:pigpio-remote:sample-pi-1:sample-output-1"} +``` + +demo.sitemap: + +``` +sitemap demo label="Main Menu" +{ + Switch item=SampleInput1 + Switch item=SampleOutput1 +} +``` diff --git a/bundles/org.openhab.binding.gpio/pom.xml b/bundles/org.openhab.binding.gpio/pom.xml new file mode 100644 index 000000000..b373ac8d1 --- /dev/null +++ b/bundles/org.openhab.binding.gpio/pom.xml @@ -0,0 +1,25 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 3.1.0-SNAPSHOT + + + org.openhab.binding.gpio + + openHAB Add-ons :: Bundles :: gpio Binding + + + + eu.xeli + jpigpio_2.12 + 0.1.0 + compile + + + diff --git a/bundles/org.openhab.binding.gpio/src/main/feature/feature.xml b/bundles/org.openhab.binding.gpio/src/main/feature/feature.xml new file mode 100644 index 000000000..153fb4074 --- /dev/null +++ b/bundles/org.openhab.binding.gpio/src/main/feature/feature.xml @@ -0,0 +1,23 @@ + + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.gpio/${project.version} + + diff --git a/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/GPIOBindingConstants.java b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/GPIOBindingConstants.java new file mode 100644 index 000000000..8d6ea6578 --- /dev/null +++ b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/GPIOBindingConstants.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.gpio.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.type.ChannelTypeUID; + +/** + * The {@link gpioBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Nils Bauer - Initial contribution + */ +@NonNullByDefault +public class GPIOBindingConstants { + + private static final String BINDING_ID = "gpio"; + + public static final ThingTypeUID THING_TYPE_PIGPIO_REMOTE_THING = new ThingTypeUID(BINDING_ID, "pigpio-remote"); + + // List of all Thing Type UIDs + public static final ChannelTypeUID CHANNEL_TYPE_DIGITAL_INPUT = new ChannelTypeUID(BINDING_ID, + "pigpio-digital-input"); + public static final ChannelTypeUID CHANNEL_TYPE_DIGITAL_OUTPUT = new ChannelTypeUID(BINDING_ID, + "pigpio-digital-output"); + + // Thing config properties + public static final String HOST = "host"; + public static final String PORT = "port"; + public static final String INVERT = "invert"; + public static final String DEBOUNCING_TIME = "debouncing_time"; + public static final String STRICT_DEBOUNCING = "debouncing_strict"; + + // GPIO config properties + public static final String GPIO_ID = "gpioId"; +} diff --git a/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/GPIOHandlerFactory.java b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/GPIOHandlerFactory.java new file mode 100644 index 000000000..0c9443b82 --- /dev/null +++ b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/GPIOHandlerFactory.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.gpio.internal; + +import static org.openhab.binding.gpio.internal.GPIOBindingConstants.THING_TYPE_PIGPIO_REMOTE_THING; + +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.gpio.internal.handler.PigpioRemoteHandler; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.binding.BaseThingHandlerFactory; +import org.openhab.core.thing.binding.ThingHandler; +import org.openhab.core.thing.binding.ThingHandlerFactory; +import org.osgi.service.component.annotations.Component; + +/** + * The {@link gpioHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Nils Bauer - Initial contribution + */ +@NonNullByDefault +@Component(configurationPid = "binding.gpio", service = ThingHandlerFactory.class) +public class GPIOHandlerFactory extends BaseThingHandlerFactory { + + private static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_PIGPIO_REMOTE_THING); + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (thingTypeUID.equals(THING_TYPE_PIGPIO_REMOTE_THING)) { + return new PigpioRemoteHandler(thing); + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/NoGpioIdException.java b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/NoGpioIdException.java new file mode 100644 index 000000000..ca87db553 --- /dev/null +++ b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/NoGpioIdException.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.gpio.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Is thrown when no gpio id is provided + * + * @author Nils Bauer - Initial contribution + */ +@NonNullByDefault +public class NoGpioIdException extends Exception { + private static final long serialVersionUID = -1281107134439928767L; +} diff --git a/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/GPIOConfiguration.java b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/GPIOConfiguration.java new file mode 100644 index 000000000..663eac800 --- /dev/null +++ b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/GPIOConfiguration.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.gpio.internal.configuration; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link GPIOConfiguration} class contains fields mapping thing configuration parameters. + * + * @author Nils Bauer - Initial contribution + */ +@NonNullByDefault +public class GPIOConfiguration { + + /** + * The id of the gpio pin. + */ + public @Nullable Integer gpioId; + + /** + * Should the input/output be inverted? + */ + public boolean invert = false; +} diff --git a/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/GPIOInputConfiguration.java b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/GPIOInputConfiguration.java new file mode 100644 index 000000000..ef1a91153 --- /dev/null +++ b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/GPIOInputConfiguration.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.gpio.internal.configuration; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link GPIOInputConfiguration} class contains fields mapping thing configuration parameters. + * + * @author Nils Bauer - Initial contribution + */ +@NonNullByDefault +public class GPIOInputConfiguration extends GPIOConfiguration { + /** + * Time in ms to double check if value hasn't changed + */ + public int debouncingTime = 10; +} diff --git a/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/GPIOOutputConfiguration.java b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/GPIOOutputConfiguration.java new file mode 100644 index 000000000..263546a2f --- /dev/null +++ b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/GPIOOutputConfiguration.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.gpio.internal.configuration; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link GPIOOutputConfiguration} class contains fields mapping thing configuration parameters. + * + * @author Nils Bauer - Initial contribution + */ +@NonNullByDefault +public class GPIOOutputConfiguration extends GPIOConfiguration { + +} diff --git a/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/PigpioConfiguration.java b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/PigpioConfiguration.java new file mode 100644 index 000000000..86a971359 --- /dev/null +++ b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/PigpioConfiguration.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.gpio.internal.configuration; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link PigpioConfiguration} class contains fields mapping thing configuration parameters. + * + * @author Nils Bauer - Initial contribution + */ +@NonNullByDefault +public class PigpioConfiguration { + + /** + * Network address of the raspberry pi + */ + public @Nullable String host; + + /** + * Port of pigpio on the remote raspberry pi + */ + public int port = 8888; +} diff --git a/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/ChannelHandler.java b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/ChannelHandler.java new file mode 100644 index 000000000..c00f7f428 --- /dev/null +++ b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/ChannelHandler.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.gpio.internal.handler; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.types.Command; + +/** + * The {@link ChannelHandler} provides an interface for different pin + * configuration handlers + * + * @author Jan N. Klug - Initial contribution + */ +@NonNullByDefault +public interface ChannelHandler { + + void handleCommand(Command command); +} diff --git a/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/PigpioDigitalInputHandler.java b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/PigpioDigitalInputHandler.java new file mode 100644 index 000000000..06abc8fba --- /dev/null +++ b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/PigpioDigitalInputHandler.java @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.gpio.internal.handler; + +import java.util.Date; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.gpio.internal.NoGpioIdException; +import org.openhab.binding.gpio.internal.configuration.GPIOInputConfiguration; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.types.Command; +import org.openhab.core.types.RefreshType; +import org.openhab.core.types.State; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import eu.xeli.jpigpio.GPIO; +import eu.xeli.jpigpio.JPigpio; +import eu.xeli.jpigpio.PigpioException; + +/** + * Thing Handler for digital GPIO inputs. + * + * @author Nils Bauer - Initial contribution + * @author Jan N. Klug - Channel redesign + */ +@NonNullByDefault +public class PigpioDigitalInputHandler implements ChannelHandler { + + private final Logger logger = LoggerFactory.getLogger(PigpioDigitalInputHandler.class); + private Date lastChanged = new Date(); + + private final GPIOInputConfiguration configuration; + private final GPIO gpio; + private final Consumer updateStatus; + + public PigpioDigitalInputHandler(GPIOInputConfiguration configuration, JPigpio jPigpio, + ScheduledExecutorService scheduler, Consumer updateStatus) + throws PigpioException, NoGpioIdException { + this.configuration = configuration; + this.updateStatus = updateStatus; + Integer gpioId = configuration.gpioId; + if (gpioId == null) { + throw new NoGpioIdException(); + } + gpio = new GPIO(jPigpio, gpioId, 1); + jPigpio.gpioSetAlertFunc(gpio.getPin(), (gpio, level, tick) -> { + lastChanged = new Date(); + Date thisChange = new Date(); + scheduler.schedule(() -> afterDebounce(thisChange), configuration.debouncingTime, TimeUnit.MILLISECONDS); + }); + } + + private void afterDebounce(Date thisChange) { + try { + // Check if value changed over time + if (!thisChange.before(lastChanged)) { + updateStatus.accept(OnOffType.from(configuration.invert != gpio.getValue())); + } + } catch (PigpioException e) { + logger.warn("Unknown pigpio exception", e); + } + } + + @Override + public void handleCommand(Command command) { + if (command instanceof RefreshType) { + try { + updateStatus.accept(OnOffType.from(configuration.invert != gpio.getValue())); + } catch (PigpioException e) { + logger.warn("Unknown pigpio exception while handling Refresh", e); + } + } + } +} diff --git a/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/PigpioDigitalOutputHandler.java b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/PigpioDigitalOutputHandler.java new file mode 100644 index 000000000..d0ef7993c --- /dev/null +++ b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/PigpioDigitalOutputHandler.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.gpio.internal.handler; + +import java.util.function.Consumer; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.gpio.internal.NoGpioIdException; +import org.openhab.binding.gpio.internal.configuration.GPIOOutputConfiguration; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.types.Command; +import org.openhab.core.types.RefreshType; +import org.openhab.core.types.State; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import eu.xeli.jpigpio.GPIO; +import eu.xeli.jpigpio.JPigpio; +import eu.xeli.jpigpio.PigpioException; + +/** + * Thing Handler for digital GPIO outputs. + * + * @author Nils Bauer - Initial contribution + * @author Jan N. Klug - Channel redesign + */ +@NonNullByDefault +public class PigpioDigitalOutputHandler implements ChannelHandler { + + /** The logger. */ + private final Logger logger = LoggerFactory.getLogger(PigpioDigitalOutputHandler.class); + + private final GPIOOutputConfiguration configuration; + private final GPIO gpio; + private final Consumer updateStatus; + + /** + * Constructor for PigpioDigitalOutputHandler + * + * @param configuration The channel configuration + * @param jPigpio The jPigpio instance + * @param updateStatus Is called when the state should be changed + * + * @throws PigpioException Can be thrown by Pigpio + * @throws NoGpioIdException Is thrown when no gpioId is defined + */ + public PigpioDigitalOutputHandler(GPIOOutputConfiguration configuration, JPigpio jPigpio, + Consumer updateStatus) throws PigpioException, NoGpioIdException { + this.configuration = configuration; + this.updateStatus = updateStatus; + Integer gpioId = configuration.gpioId; + if (gpioId == null) { + throw new NoGpioIdException(); + } + this.gpio = new GPIO(jPigpio, gpioId, 0); + } + + @Override + public void handleCommand(Command command) { + if (command instanceof RefreshType) { + try { + updateStatus.accept(OnOffType.from(configuration.invert != gpio.getValue())); + } catch (PigpioException e) { + logger.warn("Unknown pigpio exception while handling Refresh", e); + } + } + if (command instanceof OnOffType) { + try { + gpio.setValue(configuration.invert != (OnOffType.ON.equals(command))); + } catch (PigpioException e) { + logger.warn("An error occured while changing the gpio value: {}", e.getMessage()); + } + } + } +} diff --git a/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/PigpioRemoteHandler.java b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/PigpioRemoteHandler.java new file mode 100644 index 000000000..2880fe845 --- /dev/null +++ b/bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/PigpioRemoteHandler.java @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.gpio.internal.handler; + +import static org.openhab.binding.gpio.internal.GPIOBindingConstants.CHANNEL_TYPE_DIGITAL_INPUT; +import static org.openhab.binding.gpio.internal.GPIOBindingConstants.CHANNEL_TYPE_DIGITAL_OUTPUT; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.gpio.internal.NoGpioIdException; +import org.openhab.binding.gpio.internal.configuration.GPIOInputConfiguration; +import org.openhab.binding.gpio.internal.configuration.GPIOOutputConfiguration; +import org.openhab.binding.gpio.internal.configuration.PigpioConfiguration; +import org.openhab.core.thing.*; +import org.openhab.core.thing.binding.BaseThingHandler; +import org.openhab.core.thing.type.ChannelTypeUID; +import org.openhab.core.types.Command; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import eu.xeli.jpigpio.JPigpio; +import eu.xeli.jpigpio.PigpioException; +import eu.xeli.jpigpio.PigpioSocket; + +/** + * Remote pigpio Handler + * + * This bridge is used to control remote pigpio instances. + * + * @author Nils Bauer - Initial contribution + * @author Jan N. Klug - Channel redesign + */ +@NonNullByDefault +public class PigpioRemoteHandler extends BaseThingHandler { + private final Logger logger = LoggerFactory.getLogger(PigpioRemoteHandler.class); + private final Map channelHandlers = new HashMap<>(); + + /** + * Instantiates a new pigpio remote bridge handler. + * + * @param thing the thing + */ + public PigpioRemoteHandler(Thing thing) { + super(thing); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + ChannelHandler channelHandler = channelHandlers.get(channelUID); + if (channelHandler != null) { + channelHandler.handleCommand(command); + } + } + + @Override + public void initialize() { + PigpioConfiguration config = getConfigAs(PigpioConfiguration.class); + String host = config.host; + int port = config.port; + JPigpio jPigpio; + if (host == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, + "Cannot connect to PiGPIO Service on remote raspberry. IP address not set."); + return; + } + try { + jPigpio = new PigpioSocket(host, port); + updateStatus(ThingStatus.ONLINE); + } catch (PigpioException e) { + if (e.getErrorCode() == PigpioException.PI_BAD_SOCKET_PORT) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, "Port out of range"); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, + e.getLocalizedMessage()); + } + return; + } + thing.getChannels().forEach(channel -> { + ChannelUID channelUID = channel.getUID(); + ChannelTypeUID type = channel.getChannelTypeUID(); + try { + if (CHANNEL_TYPE_DIGITAL_INPUT.equals(type)) { + GPIOInputConfiguration configuration = channel.getConfiguration().as(GPIOInputConfiguration.class); + channelHandlers.put(channelUID, new PigpioDigitalInputHandler(configuration, jPigpio, scheduler, + state -> updateState(channelUID.getId(), state))); + } else if (CHANNEL_TYPE_DIGITAL_OUTPUT.equals(type)) { + GPIOOutputConfiguration configuration = channel.getConfiguration() + .as(GPIOOutputConfiguration.class); + channelHandlers.put(channelUID, new PigpioDigitalOutputHandler(configuration, jPigpio, + state -> updateState(channelUID.getId(), state))); + } + } catch (PigpioException e) { + logger.warn("Failed to initialize {}: {}", channelUID, e.getMessage()); + } catch (NoGpioIdException e) { + logger.warn("Failed to initialize {}: GpioId is not set", channelUID); + } + }); + } +} diff --git a/bundles/org.openhab.binding.gpio/src/main/resources/OH-INF/binding/binding.xml b/bundles/org.openhab.binding.gpio/src/main/resources/OH-INF/binding/binding.xml new file mode 100644 index 000000000..4012c123a --- /dev/null +++ b/bundles/org.openhab.binding.gpio/src/main/resources/OH-INF/binding/binding.xml @@ -0,0 +1,10 @@ + + + + GPIO Binding + Adds GPIO support to openHAB. + Nils Bauer + + diff --git a/bundles/org.openhab.binding.gpio/src/main/resources/OH-INF/thing/pigpio-remote.xml b/bundles/org.openhab.binding.gpio/src/main/resources/OH-INF/thing/pigpio-remote.xml new file mode 100644 index 000000000..3dbda62f1 --- /dev/null +++ b/bundles/org.openhab.binding.gpio/src/main/resources/OH-INF/thing/pigpio-remote.xml @@ -0,0 +1,72 @@ + + + + + + + The remote pigpio thing represents a remote raspberry pi with pigpio installed. Pins are channels. + + + Raspberry Pi Foundation + + + + + network_address + + Network address of the Raspberry Pi. + + + port + + Port of pigpio on the remote Raspberry Pi. + 8888 + + + + + + Switch + + Get digital state of a GPIO Pin + + + + + + GPIO pin to use as input + + + false + + + + time + + Time in ms to double check if value hasn't changed + 10 + true + + + + + + Switch + + Set digital state of a GPIO Pin + + + + GPIO pin to use as output + + + false + + + + + + diff --git a/bundles/pom.xml b/bundles/pom.xml index 2645a4149..394835617 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -114,6 +114,7 @@ org.openhab.binding.gce org.openhab.binding.generacmobilelink org.openhab.binding.goecharger + org.openhab.binding.gpio org.openhab.binding.globalcache org.openhab.binding.gpstracker org.openhab.binding.gree