Skip to content

Commit

Permalink
implement support for thing actions
Browse files Browse the repository at this point in the history
So far only transition time for color channels is supported

Signed-off-by: Thomas Weißschuh <[email protected]>
  • Loading branch information
t-8ch committed Feb 22, 2019
1 parent c3c9e08 commit db1281a
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 24 deletions.
1 change: 1 addition & 0 deletions org.openhab.binding.zigbee/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Import-Package: com.thoughtworks.xstream,
javax.measure.quantity,
org.apache.commons.io,
org.eclipse.jdt.annotation;resolution:=optional,
org.eclipse.smarthome.automation.annotation;resolution:=optional,
org.eclipse.smarthome.config.core,
org.eclipse.smarthome.config.discovery,
org.eclipse.smarthome.core.common.registry,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.openhab.binding.zigbee.action;

import java.util.Map;
import java.util.Optional;

public class ZigBeeThingActionParameter<T> {
private final String name;
private final Class<T> klazz;

public ZigBeeThingActionParameter(Class<T> klazz, String name) {
this.klazz = klazz;
this.name = name;
}

public String getName() {
return name;
}

public Optional<T> getFromMap(Map<String, Object> params) {
if (!params.containsKey(name)) {
return Optional.empty();
}
return Optional.of(klazz.cast(params.get(name)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.openhab.binding.zigbee.action;

public class ZigBeeThingActionParameters {
public static final ZigBeeThingActionParameter<Integer> TRANSITION_TIME =
new ZigBeeThingActionParameter<>(Integer.class, "transitionTime");
}
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ public void handleRefresh() {
*
* @param command the {@link Command} to send
*/
public void handleCommand(final Command command) {
public void handleCommand(final Command command, final Map<String, Object> params) {
// Overridable if a channel can be commanded
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/*
* Copyright (c) 2010-2018 by the respective copyright holders.
*
* All rights reserved. This program and the accompanying materials
Expand Down Expand Up @@ -42,6 +42,7 @@
import org.eclipse.smarthome.core.thing.ThingStatusDetail;
import org.eclipse.smarthome.core.thing.ThingStatusInfo;
import org.eclipse.smarthome.core.thing.binding.BaseThingHandler;
import org.eclipse.smarthome.core.thing.binding.ThingHandlerService;
import org.eclipse.smarthome.core.thing.binding.builder.ThingBuilder;
import org.eclipse.smarthome.core.thing.binding.firmware.Firmware;
import org.eclipse.smarthome.core.thing.binding.firmware.FirmwareUpdateHandler;
Expand All @@ -57,6 +58,7 @@
import org.openhab.binding.zigbee.converter.ZigBeeChannelConverterFactory;
import org.openhab.binding.zigbee.discovery.ZigBeeNodePropertyDiscoverer;
import org.openhab.binding.zigbee.internal.ZigBeeDeviceConfigHandler;
import org.openhab.binding.zigbee.internal.ZigbeeThingActions;
import org.openhab.binding.zigbee.internal.converter.config.ZclClusterConfigFactory;
import org.openhab.binding.zigbee.internal.converter.config.ZclClusterConfigHandler;
import org.openhab.binding.zigbee.internal.converter.config.ZclReportingConfig;
Expand Down Expand Up @@ -595,8 +597,13 @@ public void handleConfigurationUpdate(Map<String, Object> configurationParameter
updateConfiguration(configuration);
}


@Override
public void handleCommand(final ChannelUID channelUID, final Command command) {
handleCommand(channelUID, command, Collections.emptyMap());
}

public void handleCommand(final ChannelUID channelUID, final Command command, final Map<String, Object> params) {
logger.debug("{}: Command for channel {} --> {} [{}]", nodeIeeeAddress, channelUID, command,
command.getClass().getSimpleName());

Expand All @@ -621,7 +628,7 @@ public void run() {
if (command == RefreshType.REFRESH) {
handler.handleRefresh();
} else {
handler.handleCommand(command);
handler.handleCommand(command, params);
}
} catch (Exception e) {
logger.debug("{}: Exception sending command to channel {}", nodeIeeeAddress, channelUID, e);
Expand Down Expand Up @@ -907,4 +914,9 @@ public boolean isUpdateExecutable() {
// Always allow the firmware to be updated
return true;
}

@Override
public Collection<Class<? extends ThingHandlerService>> getServices() {
return Collections.singleton(ZigbeeThingActions.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package org.openhab.binding.zigbee.internal;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.smarthome.automation.annotation.ActionInput;
import org.eclipse.smarthome.automation.annotation.RuleAction;
import org.eclipse.smarthome.core.thing.ChannelUID;
import org.eclipse.smarthome.core.thing.binding.ThingActions;
import org.eclipse.smarthome.core.thing.binding.ThingActionsScope;
import org.eclipse.smarthome.core.thing.binding.ThingHandler;
import org.eclipse.smarthome.core.types.Command;
import org.openhab.binding.zigbee.action.ZigBeeThingActionParameter;
import org.openhab.binding.zigbee.handler.ZigBeeThingHandler;

import java.util.HashMap;
import java.util.Map;

@ThingActionsScope(name="zigbee")
@NonNullByDefault
public class ZigbeeThingActions implements ThingActions {
private ZigBeeThingHandler handler;

@Override
public void setThingHandler(ThingHandler handler) {
this.handler = (ZigBeeThingHandler) handler;
}

@Override
public ThingHandler getThingHandler() {
return handler;
}

@RuleAction(label = "sendCommand")
public void sendCommand(
@ActionInput(name = "channelId") String channelId,
@ActionInput(name = "command") Command command,
@ActionInput(name = "params") Map<String, Object> params
) {
ChannelUID channel = new ChannelUID(handler.getThing().getUID(), channelId);
handleCommand(channel, command, params);
}

private void handleCommand(ChannelUID channel, Command command, Map<String, Object> params) {
handler.handleCommand(channel, command, params);
}

@RuleAction(label = "buildCommand")
public CommandBuilder buildCommand(
@ActionInput(name = "channelId") String channelId,
@ActionInput(name = "command") Command command
) {
ChannelUID channel = new ChannelUID(handler.getThing().getUID(), channelId);
return new CommandBuilder(this, channel, command);
}

public static class CommandBuilder {
private final ZigbeeThingActions actions;
private final ChannelUID channel;
private final Command command;
private final Map<String, Object> params = new HashMap<>();

private CommandBuilder(ZigbeeThingActions actions, ChannelUID channel, Command command) {
this.actions = actions;
this.channel = channel;
this.command = command;
}

public <T> CommandBuilder with(ZigBeeThingActionParameter<T> parameter, T value) {
params.put(parameter.getName(), value);
return this;
}

public void send() {
actions.handleCommand(channel, command, params);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.smarthome.core.types.Command;
import org.eclipse.smarthome.core.types.UnDefType;
import org.openhab.binding.zigbee.ZigBeeBindingConstants;
import org.openhab.binding.zigbee.action.ZigBeeThingActionParameters;
import org.openhab.binding.zigbee.converter.ZigBeeBaseChannelConverter;
import org.openhab.binding.zigbee.internal.converter.config.ZclLevelControlConfig;
import org.slf4j.Logger;
Expand Down Expand Up @@ -246,14 +247,14 @@ public void handleRefresh() {
clusterColorControl.getColorMode(0);
}

private void changeOnOff(OnOffType onoff) throws InterruptedException, ExecutionException {
private void changeOnOff(OnOffType onoff, int transitionTime) throws InterruptedException, ExecutionException {
boolean on = onoff == OnOffType.ON;

if (clusterOnOff == null) {
if (clusterLevelControl == null) {
logger.warn("{}: ignoring on/off command", endpoint.getIeeeAddress());
} else {
changeBrightness(on ? PercentType.HUNDRED : PercentType.ZERO);
changeBrightness(on ? PercentType.HUNDRED : PercentType.ZERO, transitionTime);
}
return;
}
Expand All @@ -265,12 +266,12 @@ private void changeOnOff(OnOffType onoff) throws InterruptedException, Execution
}
}

private void changeBrightness(PercentType brightness) throws InterruptedException, ExecutionException {
private void changeBrightness(PercentType brightness, int transitionTime) throws InterruptedException, ExecutionException {
if (clusterLevelControl == null) {
if (clusterOnOff == null) {
logger.warn("{}: ignoring brightness command", endpoint.getIeeeAddress());
} else {
changeOnOff(brightness.intValue() == 0 ? OnOffType.OFF : OnOffType.ON);
changeOnOff(brightness.intValue() == 0 ? OnOffType.OFF : OnOffType.ON, transitionTime);
}
return;
}
Expand All @@ -281,55 +282,56 @@ private void changeBrightness(PercentType brightness) throws InterruptedExceptio
if (brightness.equals(PercentType.ZERO)) {
clusterOnOff.offCommand();
} else {
clusterLevelControl.moveToLevelWithOnOffCommand(level, configLevelControl.getDefaultTransitionTime())
clusterLevelControl.moveToLevelWithOnOffCommand(level, transitionTime)
.get();
}
} else {
clusterLevelControl.moveToLevelCommand(level, configLevelControl.getDefaultTransitionTime()).get();
clusterLevelControl.moveToLevelCommand(level, transitionTime).get();
}
}

private void changeColorHueSaturation(HSBType color) throws InterruptedException, ExecutionException {
private void changeColorHueSaturation(HSBType color, int transitionTime) throws InterruptedException, ExecutionException {
int hue = (int) (color.getHue().floatValue() * 254.0f / 360.0f + 0.5f);
int saturation = percentToLevel(color.getSaturation());

clusterColorControl
.moveToHueAndSaturationCommand(hue, saturation, configLevelControl.getDefaultTransitionTime()).get();
.moveToHueAndSaturationCommand(hue, saturation, transitionTime).get();
}

private void changeColorXY(HSBType color) throws InterruptedException, ExecutionException {
private void changeColorXY(HSBType color, int transitionTime) throws InterruptedException, ExecutionException {
PercentType xy[] = color.toXY();

logger.debug("{}: Change Color HSV ({}, {}, {}) -> XY ({}, {})", endpoint.getIeeeAddress(), color.getHue(),
color.getSaturation(), color.getBrightness(), xy[0], xy[1]);
int x = (int) (xy[0].floatValue() / 100.0f * 65536.0f + 0.5f); // up to 65279
int y = (int) (xy[1].floatValue() / 100.0f * 65536.0f + 0.5f); // up to 65279

clusterColorControl.moveToColorCommand(x, y, configLevelControl.getDefaultTransitionTime()).get();
clusterColorControl.moveToColorCommand(x, y, transitionTime).get();
}

@Override
public void handleCommand(final Command command) {
public void handleCommand(final Command command, final Map<String, Object> params) {
int transitionTime = ZigBeeThingActionParameters.TRANSITION_TIME.getFromMap(params).orElseGet(configLevelControl::getDefaultTransitionTime);
try {
if (command instanceof HSBType) {
HSBType color = (HSBType) command;
PercentType brightness = color.getBrightness();

changeBrightness(brightness);
changeBrightness(brightness, transitionTime);

if (delayedColorChange && brightness.intValue() != lastHSB.getBrightness().intValue()) {
Thread.sleep(1100);
}

if (supportsHue) {
changeColorHueSaturation(color);
changeColorHueSaturation(color, transitionTime);
} else {
changeColorXY(color);
changeColorXY(color, transitionTime);
}
} else if (command instanceof PercentType) {
changeBrightness((PercentType) command);
changeBrightness((PercentType) command, transitionTime);
} else if (command instanceof OnOffType) {
changeOnOff((OnOffType) command);
changeOnOff((OnOffType) command, transitionTime);
}
} catch (InterruptedException | ExecutionException e) {
logger.warn("{}: Exception processing command", endpoint.getIeeeAddress(), e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/
package org.openhab.binding.zigbee.internal.converter;

import java.util.Map;
import java.util.concurrent.ExecutionException;

import org.eclipse.smarthome.core.library.types.OnOffType;
Expand All @@ -18,6 +19,7 @@
import org.eclipse.smarthome.core.types.Command;
import org.eclipse.smarthome.core.types.UnDefType;
import org.openhab.binding.zigbee.ZigBeeBindingConstants;
import org.openhab.binding.zigbee.action.ZigBeeThingActionParameters;
import org.openhab.binding.zigbee.converter.ZigBeeBaseChannelConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -105,7 +107,8 @@ public void handleRefresh() {
}

@Override
public void handleCommand(final Command command) {
public void handleCommand(final Command command, final Map<String, Object> params) {
int transitionTime = ZigBeeThingActionParameters.TRANSITION_TIME.getFromMap(params).orElse(10);
PercentType colorTemperaturePercentage = PercentType.ZERO;
if (command instanceof PercentType) {
colorTemperaturePercentage = (PercentType) command;
Expand All @@ -114,7 +117,7 @@ public void handleCommand(final Command command) {
return;
}

clusterColorControl.moveToColorTemperatureCommand(percentToMired(colorTemperaturePercentage), 10);
clusterColorControl.moveToColorTemperatureCommand(percentToMired(colorTemperaturePercentage), transitionTime);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/
package org.openhab.binding.zigbee.internal.converter;

import java.util.Map;
import java.util.concurrent.ExecutionException;

import org.eclipse.smarthome.core.library.types.OnOffType;
Expand Down Expand Up @@ -81,7 +82,7 @@ public void handleRefresh() {
}

@Override
public void handleCommand(final Command command) {
public void handleCommand(final Command command, final Map<String, Object> params) {
if (command == OnOffType.ON) {
cluster.lockDoorCommand(new ByteArray(new byte[0]));
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public void handleRefresh() {
}

@Override
public void handleCommand(final Command command) {
public void handleCommand(final Command command, final Map<String, Object> params) {
if (command instanceof OnOffType) {
handleOnOffCommand((OnOffType) command);
} else if (command instanceof PercentType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
package org.openhab.binding.zigbee.internal.converter;

import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ExecutionException;

import org.eclipse.smarthome.core.library.types.OnOffType;
Expand Down Expand Up @@ -147,7 +148,7 @@ public void handleRefresh() {
}

@Override
public void handleCommand(final Command command) {
public void handleCommand(final Command command, Map<String, Object> params) {
if (clusterOnOffServer == null) {
logger.warn("{}: OnOff converter is not linked to a server and cannot accept commands",
endpoint.getIeeeAddress());
Expand Down

0 comments on commit db1281a

Please sign in to comment.