[nikobus] added option to set rollershutter position (#11548)
Signed-off-by: Boris Krivonog boris.krivonog@inova.si Signed-off-by: Boris Krivonog <boris.krivonog@inova.si>
This commit is contained in:
parent
666214749b
commit
edafc1970b
|
@ -14,6 +14,7 @@ package org.openhab.binding.nikobus.internal.handler;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
@ -22,6 +23,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.nikobus.internal.utils.Utils;
|
import org.openhab.binding.nikobus.internal.utils.Utils;
|
||||||
|
import org.openhab.core.library.types.DecimalType;
|
||||||
import org.openhab.core.library.types.OnOffType;
|
import org.openhab.core.library.types.OnOffType;
|
||||||
import org.openhab.core.library.types.PercentType;
|
import org.openhab.core.library.types.PercentType;
|
||||||
import org.openhab.core.library.types.StopMoveType;
|
import org.openhab.core.library.types.StopMoveType;
|
||||||
|
@ -45,7 +47,6 @@ import org.slf4j.LoggerFactory;
|
||||||
public class NikobusRollershutterModuleHandler extends NikobusModuleHandler {
|
public class NikobusRollershutterModuleHandler extends NikobusModuleHandler {
|
||||||
private final Logger logger = LoggerFactory.getLogger(NikobusRollershutterModuleHandler.class);
|
private final Logger logger = LoggerFactory.getLogger(NikobusRollershutterModuleHandler.class);
|
||||||
private final List<PositionEstimator> positionEstimators = new CopyOnWriteArrayList<>();
|
private final List<PositionEstimator> positionEstimators = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
private final Map<String, DirectionConfiguration> directionConfigurations = new ConcurrentHashMap<>();
|
private final Map<String, DirectionConfiguration> directionConfigurations = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public NikobusRollershutterModuleHandler(Thing thing) {
|
public NikobusRollershutterModuleHandler(Thing thing) {
|
||||||
|
@ -77,8 +78,65 @@ public class NikobusRollershutterModuleHandler extends NikobusModuleHandler {
|
||||||
logger.debug("Position estimators for {} = {}", thing.getUID(), positionEstimators);
|
logger.debug("Position estimators for {} = {}", thing.getUID(), positionEstimators);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
positionEstimators.forEach(PositionEstimator::destroy);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int valueFromCommand(String channelId, Command command) {
|
protected int valueFromCommand(String channelId, Command command) {
|
||||||
|
Optional<PositionEstimator> positionEstimator = getPositionEstimator(channelId);
|
||||||
|
if (command instanceof DecimalType) {
|
||||||
|
return positionEstimator.map(estimator -> {
|
||||||
|
return estimator.processSetPosition(((DecimalType) command).intValue());
|
||||||
|
}).orElseThrow(() -> {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Received position request but no estimation configured for channel " + channelId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
int result = convertCommandToValue(channelId, command);
|
||||||
|
positionEstimator.ifPresent(PositionEstimator::cancelStopMovement);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected State stateFromValue(String channelId, int value) {
|
||||||
|
if (value == 0x00) {
|
||||||
|
return OnOffType.OFF;
|
||||||
|
}
|
||||||
|
DirectionConfiguration configuration = getDirectionConfiguration(channelId);
|
||||||
|
if (value == configuration.up) {
|
||||||
|
return UpDownType.UP;
|
||||||
|
}
|
||||||
|
if (value == configuration.down) {
|
||||||
|
return UpDownType.DOWN;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unexpected value " + value + " received");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateState(ChannelUID channelUID, State state) {
|
||||||
|
logger.debug("updateState {} {}", channelUID, state);
|
||||||
|
|
||||||
|
getPositionEstimator(channelUID.getId()).ifPresentOrElse(estimator -> {
|
||||||
|
if (state == UpDownType.UP) {
|
||||||
|
estimator.start(-1);
|
||||||
|
} else if (state == UpDownType.DOWN) {
|
||||||
|
estimator.start(1);
|
||||||
|
} else if (state == OnOffType.OFF) {
|
||||||
|
estimator.stop();
|
||||||
|
} else {
|
||||||
|
logger.debug("Unexpected state update '{}' for '{}'", state, channelUID);
|
||||||
|
}
|
||||||
|
}, () -> super.updateState(channelUID, state));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateState(ChannelUID channelUID, int percent) {
|
||||||
|
super.updateState(channelUID, new PercentType(percent));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int convertCommandToValue(String channelId, Command command) {
|
||||||
if (command == StopMoveType.STOP) {
|
if (command == StopMoveType.STOP) {
|
||||||
return 0x00;
|
return 0x00;
|
||||||
}
|
}
|
||||||
|
@ -91,43 +149,9 @@ public class NikobusRollershutterModuleHandler extends NikobusModuleHandler {
|
||||||
throw new IllegalArgumentException("Command '" + command + "' not supported");
|
throw new IllegalArgumentException("Command '" + command + "' not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private Optional<PositionEstimator> getPositionEstimator(String channelId) {
|
||||||
protected State stateFromValue(String channelId, int value) {
|
return positionEstimators.stream().filter(estimator -> channelId.equals(estimator.getChannelUID().getId()))
|
||||||
if (value == 0x00) {
|
.findFirst();
|
||||||
return OnOffType.OFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
DirectionConfiguration configuration = getDirectionConfiguration(channelId);
|
|
||||||
if (value == configuration.up) {
|
|
||||||
return UpDownType.UP;
|
|
||||||
}
|
|
||||||
if (value == configuration.down) {
|
|
||||||
return UpDownType.DOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Unexpected value " + value + " received");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void updateState(ChannelUID channelUID, State state) {
|
|
||||||
logger.debug("updateState {} {}", channelUID, state);
|
|
||||||
|
|
||||||
positionEstimators.stream().filter(estimator -> channelUID.equals(estimator.getChannelUID())).findFirst()
|
|
||||||
.ifPresentOrElse(estimator -> {
|
|
||||||
if (state == UpDownType.UP) {
|
|
||||||
estimator.start(-1);
|
|
||||||
} else if (state == UpDownType.DOWN) {
|
|
||||||
estimator.start(1);
|
|
||||||
} else if (state == OnOffType.OFF) {
|
|
||||||
estimator.stop();
|
|
||||||
} else {
|
|
||||||
logger.debug("Unexpected state update '{}' for '{}'", state, channelUID);
|
|
||||||
}
|
|
||||||
}, () -> super.updateState(channelUID, state));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateState(ChannelUID channelUID, int percent) {
|
|
||||||
super.updateState(channelUID, new PercentType(percent));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private DirectionConfiguration getDirectionConfiguration(String channelId) {
|
private DirectionConfiguration getDirectionConfiguration(String channelId) {
|
||||||
|
@ -154,6 +178,7 @@ public class NikobusRollershutterModuleHandler extends NikobusModuleHandler {
|
||||||
private long startTimeMillis = 0;
|
private long startTimeMillis = 0;
|
||||||
private int direction = 0;
|
private int direction = 0;
|
||||||
private @Nullable Future<?> updateEstimateFuture;
|
private @Nullable Future<?> updateEstimateFuture;
|
||||||
|
private @Nullable Future<?> stopMovementFuture;
|
||||||
|
|
||||||
PositionEstimator(ChannelUID channelUID, PositionEstimatorConfig config) {
|
PositionEstimator(ChannelUID channelUID, PositionEstimatorConfig config) {
|
||||||
this.channelUID = channelUID;
|
this.channelUID = channelUID;
|
||||||
|
@ -167,6 +192,12 @@ public class NikobusRollershutterModuleHandler extends NikobusModuleHandler {
|
||||||
return channelUID;
|
return channelUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void destroy() {
|
||||||
|
Utils.cancel(updateEstimateFuture);
|
||||||
|
updateEstimateFuture = null;
|
||||||
|
cancelStopMovement();
|
||||||
|
}
|
||||||
|
|
||||||
public void start(int direction) {
|
public void start(int direction) {
|
||||||
stop();
|
stop();
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
|
@ -191,6 +222,41 @@ public class NikobusRollershutterModuleHandler extends NikobusModuleHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int processSetPosition(int percent) {
|
||||||
|
if (percent < 0 || percent > 100) {
|
||||||
|
throw new IllegalArgumentException("Position % out of range - expecting [0, 100] but got " + percent
|
||||||
|
+ " for " + channelUID.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelStopMovement();
|
||||||
|
|
||||||
|
int newPosition = (int) ((double) percent * (double) durationInMillis / 100.0 + 0.5);
|
||||||
|
int delta = position - newPosition;
|
||||||
|
|
||||||
|
logger.debug("Position set command {} for {}: delta = {}, current pos: {}, new position: {}", percent,
|
||||||
|
channelUID, delta, position, newPosition);
|
||||||
|
|
||||||
|
if (delta == 0) {
|
||||||
|
return convertCommandToValue(channelUID.getId(), StopMoveType.STOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
int time = Math.abs(delta);
|
||||||
|
if (percent == 0 || percent == 100) {
|
||||||
|
time += 5000; // Make sure we get to completely open/closed position.
|
||||||
|
}
|
||||||
|
|
||||||
|
stopMovementFuture = scheduler.schedule(() -> {
|
||||||
|
handleCommand(channelUID, StopMoveType.STOP);
|
||||||
|
}, time, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
return convertCommandToValue(channelUID.getId(), delta > 0 ? UpDownType.UP : UpDownType.DOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelStopMovement() {
|
||||||
|
Utils.cancel(stopMovementFuture);
|
||||||
|
stopMovementFuture = null;
|
||||||
|
}
|
||||||
|
|
||||||
private void updateEstimate() {
|
private void updateEstimate() {
|
||||||
int direction;
|
int direction;
|
||||||
int ellapsedMillis;
|
int ellapsedMillis;
|
||||||
|
|
Loading…
Reference in New Issue