]> git.basschouten.com Git - openhab-addons.git/commitdiff
[gpio] GPIO Binding initial contribution (#1334)
authorNils Bauer <15706595+nils-bauer@users.noreply.github.com>
Sun, 3 Jan 2021 07:38:22 +0000 (08:38 +0100)
committerGitHub <noreply@github.com>
Sun, 3 Jan 2021 07:38:22 +0000 (08:38 +0100)
* Added GPIO support

Signed-off-by: Nils Bauer <nbauer@niba.tech>
20 files changed:
CODEOWNERS
bom/openhab-addons/pom.xml
bundles/org.openhab.binding.gpio/NOTICE [new file with mode: 0644]
bundles/org.openhab.binding.gpio/README.md [new file with mode: 0644]
bundles/org.openhab.binding.gpio/pom.xml [new file with mode: 0644]
bundles/org.openhab.binding.gpio/src/main/feature/feature.xml [new file with mode: 0644]
bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/GPIOBindingConstants.java [new file with mode: 0644]
bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/GPIOHandlerFactory.java [new file with mode: 0644]
bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/NoGpioIdException.java [new file with mode: 0644]
bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/GPIOConfiguration.java [new file with mode: 0644]
bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/GPIOInputConfiguration.java [new file with mode: 0644]
bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/GPIOOutputConfiguration.java [new file with mode: 0644]
bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/configuration/PigpioConfiguration.java [new file with mode: 0644]
bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/ChannelHandler.java [new file with mode: 0644]
bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/PigpioDigitalInputHandler.java [new file with mode: 0644]
bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/PigpioDigitalOutputHandler.java [new file with mode: 0644]
bundles/org.openhab.binding.gpio/src/main/java/org/openhab/binding/gpio/internal/handler/PigpioRemoteHandler.java [new file with mode: 0644]
bundles/org.openhab.binding.gpio/src/main/resources/OH-INF/binding/binding.xml [new file with mode: 0644]
bundles/org.openhab.binding.gpio/src/main/resources/OH-INF/thing/pigpio-remote.xml [new file with mode: 0644]
bundles/pom.xml

index 5a0d8c6b0c7d363f57364fb9150a4ff28523470c..363278450ac177f479a35b5f8dda3fdc67d78adc 100644 (file)
@@ -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
index c31c6713e944cacce6e5a8a21ac98e56101591ea..b3039866c6cffc6cf85ccc6b3b759136b98a9709 100644 (file)
       <artifactId>org.openhab.binding.goecharger</artifactId>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.openhab.addons.bundles</groupId>
+      <artifactId>org.openhab.binding.gpio</artifactId>
+      <version>${project.version}</version>
+    </dependency>
     <dependency>
       <groupId>org.openhab.addons.bundles</groupId>
       <artifactId>org.openhab.binding.gpstracker</artifactId>
diff --git a/bundles/org.openhab.binding.gpio/NOTICE b/bundles/org.openhab.binding.gpio/NOTICE
new file mode 100644 (file)
index 0000000..f3f5da6
--- /dev/null
@@ -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 (file)
index 0000000..e935a73
--- /dev/null
@@ -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 (file)
index 0000000..b373ac8
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.openhab.addons.bundles</groupId>
+    <artifactId>org.openhab.addons.reactor.bundles</artifactId>
+    <version>3.1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>org.openhab.binding.gpio</artifactId>
+
+  <name>openHAB Add-ons :: Bundles :: gpio Binding</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>eu.xeli</groupId>
+      <artifactId>jpigpio_2.12</artifactId>
+      <version>0.1.0</version>
+      <scope>compile</scope>
+    </dependency>
+  </dependencies>
+</project>
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 (file)
index 0000000..153fb40
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+       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
+
+-->
+<features name="org.openhab.binding.gpio-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
+       <repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
+
+       <feature name="openhab-binding-gpio" description="GPIO Binding" version="${project.version}">
+               <feature>openhab-runtime-base</feature>
+               <bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.gpio/${project.version}</bundle>
+       </feature>
+</features>
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 (file)
index 0000000..8d6ea65
--- /dev/null
@@ -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 (file)
index 0000000..0c9443b
--- /dev/null
@@ -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<ThingTypeUID> 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 (file)
index 0000000..ca87db5
--- /dev/null
@@ -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 (file)
index 0000000..663eac8
--- /dev/null
@@ -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 (file)
index 0000000..ef1a911
--- /dev/null
@@ -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 (file)
index 0000000..263546a
--- /dev/null
@@ -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 (file)
index 0000000..86a9713
--- /dev/null
@@ -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 (file)
index 0000000..c00f7f4
--- /dev/null
@@ -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 (file)
index 0000000..06abc8f
--- /dev/null
@@ -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<State> updateStatus;
+
+    public PigpioDigitalInputHandler(GPIOInputConfiguration configuration, JPigpio jPigpio,
+            ScheduledExecutorService scheduler, Consumer<State> 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 (file)
index 0000000..d0ef799
--- /dev/null
@@ -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<State> 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<State> 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 (file)
index 0000000..2880fe8
--- /dev/null
@@ -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<ChannelUID, ChannelHandler> 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 (file)
index 0000000..4012c12
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<binding:binding id="gpio" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
+       xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
+
+       <name>GPIO Binding</name>
+       <description>Adds GPIO support to openHAB.</description>
+       <author>Nils Bauer</author>
+
+</binding:binding>
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 (file)
index 0000000..3dbda62
--- /dev/null
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<thing:thing-descriptions bindingId="gpio"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
+       xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
+
+       <!-- PiGPIO Thing -->
+       <thing-type id="pigpio-remote" extensible="pigpio-digital-input,pigpio-digital-output">
+               <label>Pigpio Remote</label>
+               <description>The remote pigpio thing represents a remote raspberry pi with pigpio installed. Pins are channels.</description>
+
+               <properties>
+                       <property name="vendor">Raspberry Pi Foundation</property>
+               </properties>
+
+               <config-description>
+                       <parameter name="host" type="text">
+                               <context>network_address</context>
+                               <label>Network Address</label>
+                               <description>Network address of the Raspberry Pi.</description>
+                       </parameter>
+                       <parameter name="port" type="integer" min="0" max="65535">
+                               <context>port</context>
+                               <label>Port</label>
+                               <description>Port of pigpio on the remote Raspberry Pi.</description>
+                               <default>8888</default>
+                       </parameter>
+               </config-description>
+       </thing-type>
+
+       <channel-type id="pigpio-digital-input">
+               <item-type>Switch</item-type>
+               <label>GPIO Digital Input</label>
+               <description>Get digital state of a GPIO Pin</description>
+               <state readOnly="true"/>
+
+               <config-description>
+                       <parameter name="gpioId" type="integer" required="true">
+                               <label>GPIO Pin</label>
+                               <description>GPIO pin to use as input</description>
+                       </parameter>
+                       <parameter name="invert" type="boolean">
+                               <default>false</default>
+                               <label>Invert</label>
+                       </parameter>
+                       <parameter name="debouncingTime" type="integer" min="0">
+                               <context>time</context>
+                               <label>Delay Time</label>
+                               <description>Time in ms to double check if value hasn't changed</description>
+                               <default>10</default>
+                               <advanced>true</advanced>
+                       </parameter>
+               </config-description>
+       </channel-type>
+
+       <channel-type id="pigpio-digital-output">
+               <item-type>Switch</item-type>
+               <label>GPIO Digital Output</label>
+               <description>Set digital state of a GPIO Pin</description>
+               <config-description>
+                       <parameter name="gpioId" type="integer" required="true">
+                               <label>GPIO Pin</label>
+                               <description>GPIO pin to use as output</description>
+                       </parameter>
+                       <parameter name="invert" type="boolean">
+                               <default>false</default>
+                               <label>Invert</label>
+                       </parameter>
+               </config-description>
+       </channel-type>
+
+</thing:thing-descriptions>
index 2645a4149d1b3e34b55993cad9fd9b2918698fbc..394835617a4c72a93dd183697a0a1c6c36e19fe4 100644 (file)
     <module>org.openhab.binding.gce</module>
     <module>org.openhab.binding.generacmobilelink</module>
     <module>org.openhab.binding.goecharger</module>
+    <module>org.openhab.binding.gpio</module>
     <module>org.openhab.binding.globalcache</module>
     <module>org.openhab.binding.gpstracker</module>
     <module>org.openhab.binding.gree</module>