]> git.basschouten.com Git - openhab-addons.git/commitdiff
[rollershutterposition] Initial contribution (#13259)
authorjsjames <jeff@james-online.com>
Sun, 26 Feb 2023 21:54:27 +0000 (13:54 -0800)
committerGitHub <noreply@github.com>
Sun, 26 Feb 2023 21:54:27 +0000 (22:54 +0100)
* Initial contribution

Signed-off-by: Jeff James <jeff@james-online.com>
13 files changed:
CODEOWNERS
bom/openhab-addons/pom.xml
bundles/org.openhab.transform.rollershutterposition/NOTICE [new file with mode: 0644]
bundles/org.openhab.transform.rollershutterposition/README.md [new file with mode: 0644]
bundles/org.openhab.transform.rollershutterposition/pom.xml [new file with mode: 0644]
bundles/org.openhab.transform.rollershutterposition/src/main/feature/feature.xml [new file with mode: 0644]
bundles/org.openhab.transform.rollershutterposition/src/main/java/org/openhab/transform/rollershutterposition/internal/RollerShutterPositionConstants.java [new file with mode: 0644]
bundles/org.openhab.transform.rollershutterposition/src/main/java/org/openhab/transform/rollershutterposition/internal/RollerShutterPositionProfile.java [new file with mode: 0644]
bundles/org.openhab.transform.rollershutterposition/src/main/java/org/openhab/transform/rollershutterposition/internal/RollerShutterPositionProfileFactory.java [new file with mode: 0644]
bundles/org.openhab.transform.rollershutterposition/src/main/java/org/openhab/transform/rollershutterposition/internal/config/RollerShutterPositionConfig.java [new file with mode: 0644]
bundles/org.openhab.transform.rollershutterposition/src/main/resources/OH-INF/config/rollerShutterPosition.xml [new file with mode: 0644]
bundles/org.openhab.transform.rollershutterposition/src/main/resources/OH-INF/i18n/rollershutter.properties [new file with mode: 0644]
bundles/pom.xml

index 3aa65f284207b5c58048c17ac91133931f83f4fd..f1f204fa412cdaa9955e57b7613c2ac4846b7341 100644 (file)
 /bundles/org.openhab.transform.jsonpath/ @clinique
 /bundles/org.openhab.transform.map/ @openhab/add-ons-maintainers
 /bundles/org.openhab.transform.regex/ @openhab/add-ons-maintainers
+/bundles/org.openhab.transform.rollershutterposition/ @jsjames
 /bundles/org.openhab.transform.scale/ @clinique
 /bundles/org.openhab.transform.xpath/ @openhab/add-ons-maintainers
 /bundles/org.openhab.transform.xslt/ @openhab/add-ons-maintainers
index d446bf5b49ed9bdee0c6e9e3adf88826dd64d9e3..d74ffb2408292ad370dc75fac5ba1095a62d8ac4 100644 (file)
       <artifactId>org.openhab.transform.regex</artifactId>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.openhab.addons.bundles</groupId>
+      <artifactId>org.openhab.transform.rollershutterposition</artifactId>
+      <version>${project.version}</version>
+    </dependency>
     <dependency>
       <groupId>org.openhab.addons.bundles</groupId>
       <artifactId>org.openhab.transform.scale</artifactId>
diff --git a/bundles/org.openhab.transform.rollershutterposition/NOTICE b/bundles/org.openhab.transform.rollershutterposition/NOTICE
new file mode 100644 (file)
index 0000000..38d625e
--- /dev/null
@@ -0,0 +1,13 @@
+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
diff --git a/bundles/org.openhab.transform.rollershutterposition/README.md b/bundles/org.openhab.transform.rollershutterposition/README.md
new file mode 100644 (file)
index 0000000..dd1a0bf
--- /dev/null
@@ -0,0 +1,19 @@
+# Rollershutter Position Emulation Profile Service
+
+The Rollershutter Position emulates absolute position setting for Rollershutter devices which only support basic UP/DOWN/STOP commands.
+This allows a Rollershutter to be set to an absolution position from 0..100 even if the controller does not support this feature (i.e. Somfy controllers).
+
+The logic code used for this profile service was adapted from Tarag Gautier's JavaScript implementation VASRollershutter.js.
+By implementing as a profile, it eliminates the need for setting up a jsr233 js environment and simplifies the configuration.
+
+## Configuration
+
+To use this profile, simply include the profile on the Rollershutter item which is assigned to the Rollershutter channel.
+The parameters <uptime> and <downtime> are the time it takes for the Rollershutter to fully extend or close in seconds.
+The precision parameter can be used to specify the minimum movement that can be made.
+This is useful when latencies in the system limit prevent very small movements and will reduce the accuracy of the position estimation.
+
+```java
+Rollershutter <itemName> { channel="<channelUID>"[profile="rollershutter:position", uptime=<uptime>, downtime=<downtime>, precision=<minimun percent movement>]]}
+```
+
diff --git a/bundles/org.openhab.transform.rollershutterposition/pom.xml b/bundles/org.openhab.transform.rollershutterposition/pom.xml
new file mode 100644 (file)
index 0000000..aed1db8
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://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>4.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>org.openhab.transform.rollershutterposition</artifactId>
+
+  <name>openHAB Add-ons :: Bundles :: Transformation Service :: Roller Shutter Position</name>
+
+</project>
diff --git a/bundles/org.openhab.transform.rollershutterposition/src/main/feature/feature.xml b/bundles/org.openhab.transform.rollershutterposition/src/main/feature/feature.xml
new file mode 100644 (file)
index 0000000..f442520
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<features name="org.openhab.transform.rollershutterposition-${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-transformation-rollershutterposition" description="Roller Shutter Position Emulation" version="${project.version}">
+               <feature>openhab-runtime-base</feature>
+               <bundle start-level="75">mvn:org.openhab.addons.bundles/org.openhab.transform.rollershutterposition/${project.version}</bundle>
+       </feature>
+</features>
diff --git a/bundles/org.openhab.transform.rollershutterposition/src/main/java/org/openhab/transform/rollershutterposition/internal/RollerShutterPositionConstants.java b/bundles/org.openhab.transform.rollershutterposition/src/main/java/org/openhab/transform/rollershutterposition/internal/RollerShutterPositionConstants.java
new file mode 100644 (file)
index 0000000..b0cc6ec
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2010-2023 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.transform.rollershutterposition.internal;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.profiles.ProfileTypeUID;
+import org.openhab.core.transform.TransformationService;
+
+/**
+ * The {@link RollerShutterPositionConstants} class to define transform constants
+ * used across the whole binding.
+ *
+ * @author Jeff James - Initial contribution
+ */
+@NonNullByDefault
+public class RollerShutterPositionConstants {
+
+    // Profile Type UID
+    public static final ProfileTypeUID PROFILE_TYPE_UID = new ProfileTypeUID(
+            TransformationService.TRANSFORM_PROFILE_SCOPE, "ROLLERSHUTTERPOSITION");
+
+    // Parameters
+    public static final String UPTIME_PARAM = "uptime";
+    public static final String DOWNTIME_PARAM = "downtime";
+    public static final String PRECISION_PARAM = "precision";
+
+    public static final int POSITION_UPDATE_PERIOD_MILLISECONDS = 800;
+    public static final int DEFAULT_PRECISION = 5;
+}
diff --git a/bundles/org.openhab.transform.rollershutterposition/src/main/java/org/openhab/transform/rollershutterposition/internal/RollerShutterPositionProfile.java b/bundles/org.openhab.transform.rollershutterposition/src/main/java/org/openhab/transform/rollershutterposition/internal/RollerShutterPositionProfile.java
new file mode 100644 (file)
index 0000000..192a544
--- /dev/null
@@ -0,0 +1,282 @@
+/**
+ * Copyright (c) 2010-2023 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.transform.rollershutterposition.internal;
+
+import static org.openhab.transform.rollershutterposition.internal.RollerShutterPositionConstants.*;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.Objects;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.common.ThreadPoolManager;
+import org.openhab.core.library.types.PercentType;
+import org.openhab.core.library.types.StopMoveType;
+import org.openhab.core.library.types.UpDownType;
+import org.openhab.core.thing.profiles.ProfileCallback;
+import org.openhab.core.thing.profiles.ProfileContext;
+import org.openhab.core.thing.profiles.ProfileTypeUID;
+import org.openhab.core.thing.profiles.StateProfile;
+import org.openhab.core.types.Command;
+import org.openhab.core.types.State;
+import org.openhab.transform.rollershutterposition.internal.config.RollerShutterPositionConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Profile to implement the RollerShutterPosition ItemChannelLink
+ *
+ * @author Jeff James - Initial contribution
+ *
+ *         Core logic in this module has been heavily adapted from Tarag Gautier js script implementation
+ *         VASRollershutter.js
+ */
+@NonNullByDefault
+public class RollerShutterPositionProfile implements StateProfile {
+    private static final String PROFILE_THREADPOOL_NAME = "profile-rollershutterposition";
+    private final Logger logger = LoggerFactory.getLogger(RollerShutterPositionProfile.class);
+
+    private final ProfileCallback callback;
+    RollerShutterPositionConfig configuration;
+
+    private int position = 0; // current position of the roller shutter (assumes 0 when system starts)
+    private int targetPosition;
+    private boolean isValidConfiguration = false;
+    private Instant movingSince = Instant.MIN;
+    private UpDownType direction = UpDownType.DOWN;
+
+    private final ScheduledExecutorService scheduler = ThreadPoolManager.getScheduledPool(PROFILE_THREADPOOL_NAME);
+    protected @Nullable ScheduledFuture<?> stopTimer = null;
+    protected @Nullable ScheduledFuture<?> updateTimer = null;
+
+    public RollerShutterPositionProfile(final ProfileCallback callback, final ProfileContext context) {
+        this.callback = callback;
+        this.configuration = context.getConfiguration().as(RollerShutterPositionConfig.class);
+
+        if (configuration.uptime == 0) {
+            logger.info("Profile paramater {} must not be 0", UPTIME_PARAM);
+            return;
+        }
+
+        if (configuration.downtime == 0) {
+            configuration.downtime = configuration.uptime;
+        }
+
+        if (configuration.precision == 0) {
+            configuration.precision = DEFAULT_PRECISION;
+        }
+
+        this.isValidConfiguration = true;
+
+        logger.debug("Profile configured with '{}'='{}' ms, '{}'={} ms, '{}'={}", UPTIME_PARAM, configuration.uptime,
+                DOWNTIME_PARAM, configuration.downtime, PRECISION_PARAM, configuration.precision);
+    }
+
+    @Override
+    public ProfileTypeUID getProfileTypeUID() {
+        return PROFILE_TYPE_UID;
+    }
+
+    @Override
+    public void onCommandFromItem(Command command) {
+        logger.debug("onCommandFromItem: {}", command);
+
+        // pass through command if profile has not been configured properly
+        if (!isValidConfiguration) {
+            callback.handleCommand(command);
+            return;
+        }
+
+        if (command instanceof UpDownType) {
+            if (command == UpDownType.UP) {
+                moveTo(0);
+            } else if (command == UpDownType.DOWN) {
+                moveTo(100);
+            }
+        } else if (command instanceof StopMoveType) {
+            stop();
+        } else {
+            moveTo(((PercentType) command).intValue());
+        }
+    }
+
+    private boolean isMoving() {
+        return (!movingSince.equals(Instant.MIN));
+    }
+
+    private void moveTo(int targetPos) {
+        boolean alreadyMoving = false;
+
+        if (targetPos < 0 || targetPos > 100) {
+            logger.debug("moveTo() position is invalid: {}", targetPos);
+            return;
+        }
+
+        int curPos = currentPosition();
+        int posOffset = targetPos - curPos;
+
+        UpDownType newCmd;
+
+        if (targetPos == position && !isMoving()) {
+            logger.debug("moveTo() position already current: {}", targetPos);
+            if (targetPos == 0) { // always send command if either 0 or 100 in case it is not already in that position
+                callback.handleCommand(UpDownType.UP);
+            } else if (targetPos == 100) {
+                callback.handleCommand(UpDownType.DOWN);
+            }
+            return;
+        } else if (targetPos == 0 || targetPos == 100) {
+            logger.debug("moveTo() bounding position");
+            newCmd = targetPos == 0 ? UpDownType.UP : UpDownType.DOWN;
+        } else if (Math.abs(posOffset) < configuration.precision) {
+            callback.sendUpdate(new PercentType(position)); // update position because autoupdate will assume the
+                                                            // movement happened
+            logger.info("moveTo() is less than the precision setting of {}", configuration.precision);
+            return;
+        } else {
+            newCmd = posOffset > 0 ? UpDownType.DOWN : UpDownType.UP;
+        }
+
+        logger.debug("moveTo() targetPosition: {} from currentPosition: {}", targetPos, curPos);
+
+        long time = (long) ((Math.abs(posOffset) / 100d)
+                * (posOffset > 0 ? (double) configuration.downtime * 1000 : (double) configuration.uptime * 1000));
+        logger.debug("moveTo() computed movement offset: {} / {} / {} ms", posOffset, newCmd, time);
+
+        if (isMoving()) {
+            position = curPos; // Update "starting" position if already in motion since the last move did not finish
+
+            if (direction == newCmd) {
+                alreadyMoving = true;
+            }
+        }
+
+        this.targetPosition = targetPos;
+        this.direction = newCmd;
+        this.movingSince = Instant.now();
+
+        if (stopTimer != null) {
+            Objects.requireNonNull(stopTimer).cancel(true);
+        }
+        this.stopTimer = scheduler.schedule(stopTimeoutTask, time, TimeUnit.MILLISECONDS);
+
+        if (updateTimer != null) {
+            Objects.requireNonNull(updateTimer).cancel(true);
+        }
+        this.updateTimer = scheduler.scheduleWithFixedDelay(updateTimeoutTask, 0, POSITION_UPDATE_PERIOD_MILLISECONDS,
+                TimeUnit.MILLISECONDS);
+
+        if (!alreadyMoving) {
+            logger.debug("moveTo() sending command for movement: {}, timer set in {} ms", direction, time);
+            callback.handleCommand(direction);
+        } else {
+            logger.debug("moveTo() updating timing but already moving in right directio: {}, timer set in {} ms",
+                    direction, time);
+        }
+    }
+
+    private void stop() {
+        callback.handleCommand(StopMoveType.STOP);
+
+        this.position = currentPosition();
+        this.movingSince = Instant.MIN;
+
+        if (stopTimer != null) {
+            Objects.requireNonNull(stopTimer).cancel(true);
+            this.stopTimer = null;
+        }
+        if (updateTimer != null) {
+            Objects.requireNonNull(updateTimer).cancel(true);
+            this.updateTimer = null;
+        }
+
+        callback.sendUpdate(new PercentType(position));
+    }
+
+    private int currentPosition() {
+        if (isMoving()) {
+            logger.trace("currentPosition() while moving");
+
+            // movingSince is always set if moving
+            long millis = movingSince.until(Instant.now(), ChronoUnit.MILLIS);
+            double delta = 0;
+
+            if (direction == UpDownType.UP) {
+                delta = -(millis / (configuration.uptime * 1000)) * 100d;
+            } else {
+                delta = (millis / (configuration.downtime * 1000)) * 100d;
+            }
+
+            return (int) Math.max(0, Math.min(100, Math.round(position + delta)));
+        } else {
+            return position;
+        }
+    }
+
+    // Runnable task to time duration of the move to make
+    private Runnable stopTimeoutTask = new Runnable() {
+        @Override
+        public void run() {
+            if (targetPosition == 0 || targetPosition == 100) {
+                // Don't send stop command to re-sync position using the motor end stop
+                logger.debug("arrived at end position, not stopping for calibration");
+            } else {
+                callback.handleCommand(StopMoveType.STOP);
+                logger.debug("arrived at position, sending STOP command");
+            }
+
+            logger.trace("stopTimeoutTask() position: {}", targetPosition);
+
+            if (updateTimer != null) {
+                Objects.requireNonNull(updateTimer).cancel(true);
+                updateTimer = null;
+            }
+
+            movingSince = Instant.MIN;
+            position = targetPosition;
+            targetPosition = -1;
+            callback.sendUpdate(new PercentType(position));
+        }
+    };
+
+    // Runnable task to update the item on position while the roller shutter is moving
+    private Runnable updateTimeoutTask = new Runnable() {
+        @Override
+        public void run() {
+            if (isMoving()) {
+                int pos = currentPosition();
+                if (pos < 0 || pos > 100) {
+                    return;
+                }
+                callback.sendUpdate(new PercentType(pos));
+                logger.trace("updateTimeoutTask(): {}", pos);
+            }
+        }
+    };
+
+    @Override
+    public void onStateUpdateFromItem(State state) {
+    }
+
+    @Override
+    public void onCommandFromHandler(Command command) {
+    }
+
+    @Override
+    public void onStateUpdateFromHandler(State state) {
+    }
+}
diff --git a/bundles/org.openhab.transform.rollershutterposition/src/main/java/org/openhab/transform/rollershutterposition/internal/RollerShutterPositionProfileFactory.java b/bundles/org.openhab.transform.rollershutterposition/src/main/java/org/openhab/transform/rollershutterposition/internal/RollerShutterPositionProfileFactory.java
new file mode 100644 (file)
index 0000000..19faf86
--- /dev/null
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2010-2023 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.transform.rollershutterposition.internal;
+
+import static org.openhab.transform.rollershutterposition.internal.RollerShutterPositionConstants.PROFILE_TYPE_UID;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Locale;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.library.CoreItemFactory;
+import org.openhab.core.thing.profiles.Profile;
+import org.openhab.core.thing.profiles.ProfileCallback;
+import org.openhab.core.thing.profiles.ProfileContext;
+import org.openhab.core.thing.profiles.ProfileFactory;
+import org.openhab.core.thing.profiles.ProfileType;
+import org.openhab.core.thing.profiles.ProfileTypeBuilder;
+import org.openhab.core.thing.profiles.ProfileTypeProvider;
+import org.openhab.core.thing.profiles.ProfileTypeUID;
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * {@link RollerShutterPositionProfileFactory} Factory to create the profile
+ *
+ * @author Jeff James - Initial contribution
+ */
+@NonNullByDefault
+@Component(service = { ProfileFactory.class, ProfileTypeProvider.class })
+public class RollerShutterPositionProfileFactory implements ProfileFactory, ProfileTypeProvider {
+    @Override
+    public Collection<ProfileType> getProfileTypes(@Nullable Locale locale) {
+        return List.of(ProfileTypeBuilder.newState(PROFILE_TYPE_UID, PROFILE_TYPE_UID.getId())
+                .withSupportedItemTypes(CoreItemFactory.ROLLERSHUTTER).build());
+    }
+
+    @Override
+    public @Nullable Profile createProfile(ProfileTypeUID profileTypeUID, ProfileCallback callback,
+            ProfileContext profileContext) {
+        return new RollerShutterPositionProfile(callback, profileContext);
+    }
+
+    @Override
+    public Collection<ProfileTypeUID> getSupportedProfileTypeUIDs() {
+        return List.of(PROFILE_TYPE_UID);
+    }
+}
diff --git a/bundles/org.openhab.transform.rollershutterposition/src/main/java/org/openhab/transform/rollershutterposition/internal/config/RollerShutterPositionConfig.java b/bundles/org.openhab.transform.rollershutterposition/src/main/java/org/openhab/transform/rollershutterposition/internal/config/RollerShutterPositionConfig.java
new file mode 100644 (file)
index 0000000..f9ba83c
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2010-2023 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.transform.rollershutterposition.internal.config;
+
+import static org.openhab.transform.rollershutterposition.internal.RollerShutterPositionConstants.DEFAULT_PRECISION;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link RollerShutterPositionConfig} class contains the parameters for RollerShutterPosition
+ *
+ * @author Jeff James - initial contribution
+ *
+ */
+@NonNullByDefault
+public class RollerShutterPositionConfig {
+    public float uptime; // uptime in seconds (set by param)
+    public float downtime; // downtime in seconds (set by param)
+    public int precision = DEFAULT_PRECISION; // minimum movement
+}
diff --git a/bundles/org.openhab.transform.rollershutterposition/src/main/resources/OH-INF/config/rollerShutterPosition.xml b/bundles/org.openhab.transform.rollershutterposition/src/main/resources/OH-INF/config/rollerShutterPosition.xml
new file mode 100644 (file)
index 0000000..79fea29
--- /dev/null
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<config-description:config-descriptions
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
+       xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0 https://openhab.org/schemas/config-description-1.0.0.xsd">
+
+       <config-description uri="profile:rollershutter:position">
+               <parameter name="uptime" type="decimal" required="true">
+                       <label>Up Time</label>
+                       <description>Time it takes for roller shutter to fully open (in seconds).</description>
+                       <required>true</required>
+               </parameter>
+               <parameter name="downtime" type="decimal">
+                       <label>Down Time</label>
+                       <description>Time it takes for roller shutter to extend the full length (in seconds). Defaults to Up Time if not
+                               specified.</description>
+               </parameter>
+               <parameter name="precision" type="integer">
+                       <label>Precision</label>
+                       <description>Minimum movement (in percent) that can be requested. If the requested change is less than this amount,
+                               no action will be taken. This may be required for systems where there is a lag in the stop command and
+                               consequently
+                               it is not possible for fine control of movement. (default = 5)</description>
+                       <default>5</default>
+               </parameter>
+       </config-description>
+</config-description:config-descriptions>
diff --git a/bundles/org.openhab.transform.rollershutterposition/src/main/resources/OH-INF/i18n/rollershutter.properties b/bundles/org.openhab.transform.rollershutterposition/src/main/resources/OH-INF/i18n/rollershutter.properties
new file mode 100644 (file)
index 0000000..8ca4089
--- /dev/null
@@ -0,0 +1,6 @@
+profile.config.rollershutter.position.downtime.label = Down Time
+profile.config.rollershutter.position.downtime.description = Time it takes for roller shutter to extend the full length (in seconds). Defaults to Up Time if not specified.
+profile.config.rollershutter.position.precision.label = Precision
+profile.config.rollershutter.position.precision.description = Minimum movement (in percent) that can be requested. If the requested change is less than this amount, no action will be taken. This may be required for systems where there is a lag in the stop command and consequently it is not possible for fine control of movement. (default = 5)
+profile.config.rollershutter.position.uptime.label = Up Time
+profile.config.rollershutter.position.uptime.description = Time it takes for roller shutter to fully open (in seconds).
index 7ceb398af4889541d7b016e719d04bce285149d3..acbacfc1bec2bce0b852e08fa9751ce16fb528af 100644 (file)
@@ -39,6 +39,7 @@
     <module>org.openhab.transform.jsonpath</module>
     <module>org.openhab.transform.map</module>
     <module>org.openhab.transform.regex</module>
+    <module>org.openhab.transform.rollershutterposition</module>
     <module>org.openhab.transform.scale</module>
     <module>org.openhab.transform.xpath</module>
     <module>org.openhab.transform.xslt</module>