Skip to content

Commit 99f5a3d

Browse files
committed
implement support for thing actions
So far only transition time for color channels is supported Signed-off-by: Thomas Weißschuh <[email protected]>
1 parent 1600cfd commit 99f5a3d

11 files changed

+144
-23
lines changed

org.openhab.binding.zigbee/META-INF/MANIFEST.MF

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Import-Package: com.thoughtworks.xstream,
3030
javax.measure.quantity,
3131
org.apache.commons.io,
3232
org.eclipse.jdt.annotation;resolution:=optional,
33+
org.eclipse.smarthome.automation.annotation,
3334
org.eclipse.smarthome.config.core,
3435
org.eclipse.smarthome.config.discovery,
3536
org.eclipse.smarthome.core.common.registry,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.openhab.binding.zigbee.action;
2+
3+
import java.util.Map;
4+
import java.util.Optional;
5+
6+
public class ZigBeeThingActionParameter<T> {
7+
private final String name;
8+
private final Class<T> klazz;
9+
10+
public ZigBeeThingActionParameter(Class<T> klazz, String name) {
11+
this.klazz = klazz;
12+
this.name = name;
13+
}
14+
15+
public String getName() {
16+
return name;
17+
}
18+
19+
public Optional<T> getFromMap(Map<String, Object> params) {
20+
if (!params.containsKey(name)) {
21+
return Optional.empty();
22+
}
23+
return Optional.of(klazz.cast(params.get(name)));
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package org.openhab.binding.zigbee.action;
2+
3+
public class ZigBeeThingActionParameters {
4+
public static final ZigBeeThingActionParameter<Integer> TRANSITION_TIME =
5+
new ZigBeeThingActionParameter<>(Integer.class, "transitionTime");
6+
}

org.openhab.binding.zigbee/src/main/java/org/openhab/binding/zigbee/converter/ZigBeeBaseChannelConverter.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ public void handleRefresh() {
234234
*
235235
* @param command the {@link Command} to send
236236
*/
237-
public void handleCommand(final Command command) {
237+
public void handleCommand(final Command command, final Map<String, Object> params) {
238238
// Overridable if a channel can be commanded
239239
}
240240

org.openhab.binding.zigbee/src/main/java/org/openhab/binding/zigbee/handler/ZigBeeThingHandler.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import org.openhab.binding.zigbee.converter.ZigBeeBaseChannelConverter;
5757
import org.openhab.binding.zigbee.discovery.ZigBeeNodePropertyDiscoverer;
5858
import org.openhab.binding.zigbee.internal.ZigBeeDeviceConfigHandler;
59+
import org.openhab.binding.zigbee.internal.ZigbeeThingActions;
5960
import org.openhab.binding.zigbee.internal.converter.ZigBeeChannelConverterFactory;
6061
import org.openhab.binding.zigbee.internal.converter.config.ZclClusterConfigFactory;
6162
import org.openhab.binding.zigbee.internal.converter.config.ZclClusterConfigHandler;
@@ -590,8 +591,13 @@ public void handleConfigurationUpdate(Map<String, Object> configurationParameter
590591
updateConfiguration(configuration);
591592
}
592593

594+
593595
@Override
594596
public void handleCommand(final ChannelUID channelUID, final Command command) {
597+
handleCommand(channelUID, command, Collections.emptyMap());
598+
}
599+
600+
public void handleCommand(final ChannelUID channelUID, final Command command, final Map<String, Object> params) {
595601
logger.debug("{}: Command for channel {} --> {} [{}]", nodeIeeeAddress, channelUID, command,
596602
command.getClass().getSimpleName());
597603

@@ -616,7 +622,7 @@ public void run() {
616622
if (command == RefreshType.REFRESH) {
617623
handler.handleRefresh();
618624
} else {
619-
handler.handleCommand(command);
625+
handler.handleCommand(command, params);
620626
}
621627
} catch (Exception e) {
622628
logger.debug("{}: Exception sending command to channel {}", nodeIeeeAddress, channelUID, e);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package org.openhab.binding.zigbee.internal;
2+
3+
import org.eclipse.jdt.annotation.NonNullByDefault;
4+
import org.eclipse.smarthome.automation.annotation.ActionInput;
5+
import org.eclipse.smarthome.automation.annotation.RuleAction;
6+
import org.eclipse.smarthome.core.thing.ChannelUID;
7+
import org.eclipse.smarthome.core.thing.binding.ThingActions;
8+
import org.eclipse.smarthome.core.thing.binding.ThingActionsScope;
9+
import org.eclipse.smarthome.core.thing.binding.ThingHandler;
10+
import org.eclipse.smarthome.core.types.Command;
11+
import org.openhab.binding.zigbee.action.ZigBeeThingActionParameter;
12+
import org.openhab.binding.zigbee.handler.ZigBeeThingHandler;
13+
14+
import java.util.HashMap;
15+
import java.util.Map;
16+
17+
@ThingActionsScope(name="zigbee")
18+
@NonNullByDefault
19+
public class ZigbeeThingActions implements ThingActions {
20+
private ZigBeeThingHandler handler;
21+
22+
@Override
23+
public void setThingHandler(ThingHandler handler) {
24+
this.handler = (ZigBeeThingHandler) handler;
25+
}
26+
27+
@Override
28+
public ThingHandler getThingHandler() {
29+
return handler;
30+
}
31+
32+
@RuleAction(label = "sendCommand")
33+
public void sendCommand(
34+
@ActionInput(name = "channelId") String channelId,
35+
@ActionInput(name = "command") Command command,
36+
@ActionInput(name = "params") Map<String, Object> params
37+
) {
38+
ChannelUID channel = new ChannelUID(handler.getThing().getUID(), channelId);
39+
handleCommand(channel, command, params);
40+
}
41+
42+
private void handleCommand(ChannelUID channel, Command command, Map<String, Object> params) {
43+
handler.handleCommand(channel, command, params);
44+
}
45+
46+
@RuleAction(label = "buildCommand")
47+
public CommandBuilder buildCommand(
48+
@ActionInput(name = "channelId") String channelId,
49+
@ActionInput(name = "command") Command command
50+
) {
51+
ChannelUID channel = new ChannelUID(handler.getThing().getUID(), channelId);
52+
return new CommandBuilder(this, channel, command);
53+
}
54+
55+
public static class CommandBuilder {
56+
private final ZigbeeThingActions actions;
57+
private final ChannelUID channel;
58+
private final Command command;
59+
private final Map<String, Object> params = new HashMap<>();
60+
61+
private CommandBuilder(ZigbeeThingActions actions, ChannelUID channel, Command command) {
62+
this.actions = actions;
63+
this.channel = channel;
64+
this.command = command;
65+
}
66+
67+
public <T> CommandBuilder with(ZigBeeThingActionParameter<T> parameter, T value) {
68+
params.put(parameter.getName(), value);
69+
return this;
70+
}
71+
72+
public void send() {
73+
actions.handleCommand(channel, command, params);
74+
}
75+
}
76+
}

org.openhab.binding.zigbee/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeConverterColorColor.java

+18-16
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.eclipse.smarthome.core.types.Command;
2929
import org.eclipse.smarthome.core.types.UnDefType;
3030
import org.openhab.binding.zigbee.ZigBeeBindingConstants;
31+
import org.openhab.binding.zigbee.action.ZigBeeThingActionParameters;
3132
import org.openhab.binding.zigbee.converter.ZigBeeBaseChannelConverter;
3233
import org.openhab.binding.zigbee.internal.converter.config.ZclLevelControlConfig;
3334
import org.slf4j.Logger;
@@ -244,12 +245,12 @@ public void handleRefresh() {
244245
}
245246
}
246247

247-
private void changeOnOff(OnOffType onoff) throws InterruptedException, ExecutionException {
248+
private void changeOnOff(OnOffType onoff, int transitionTime) throws InterruptedException, ExecutionException {
248249
boolean on = onoff == OnOffType.ON;
249250
PercentType brightness = on ? PercentType.HUNDRED : PercentType.ZERO;
250251

251252
if (clusterLevelControl != null) {
252-
changeBrightness(brightness);
253+
changeBrightness(brightness, transitionTime);
253254
return;
254255
}
255256

@@ -269,10 +270,10 @@ private void changeOnOff(OnOffType onoff) throws InterruptedException, Execution
269270
}
270271
}
271272

272-
private void changeBrightness(PercentType brightness) throws InterruptedException, ExecutionException {
273+
private void changeBrightness(PercentType brightness, int transitionTime) throws InterruptedException, ExecutionException {
273274
if (clusterLevelControl == null) {
274275
if (clusterOnOff != null) {
275-
changeOnOff(brightness.intValue() == 0 ? OnOffType.OFF : OnOffType.ON);
276+
changeOnOff(brightness.intValue() == 0 ? OnOffType.OFF : OnOffType.ON, transitionTime);
276277
} else {
277278
logger.warn("{}: ignoring brightness command", endpoint.getIeeeAddress());
278279
}
@@ -289,25 +290,25 @@ private void changeBrightness(PercentType brightness) throws InterruptedExceptio
289290
if (brightness.equals(PercentType.ZERO)) {
290291
clusterOnOff.offCommand();
291292
} else {
292-
clusterLevelControl.moveToLevelWithOnOffCommand(level, configLevelControl.getDefaultTransitionTime())
293+
clusterLevelControl.moveToLevelWithOnOffCommand(level, transitionTime)
293294
.get();
294295
}
295296
} else {
296-
clusterLevelControl.moveToLevelCommand(level, configLevelControl.getDefaultTransitionTime()).get();
297+
clusterLevelControl.moveToLevelCommand(level, transitionTime).get();
297298
}
298299
}
299300

300-
private void changeColorHueSaturation(HSBType color) throws InterruptedException, ExecutionException {
301+
private void changeColorHueSaturation(HSBType color, int transitionTime) throws InterruptedException, ExecutionException {
301302
HSBType oldHSB = currentHSB;
302303
currentHSB = new HSBType(color.getHue(), color.getSaturation(), oldHSB.getBrightness());
303304
int hue = (int) (color.getHue().floatValue() * 254.0f / 360.0f + 0.5f);
304305
int saturation = percentToLevel(color.getSaturation());
305306

306307
clusterColorControl
307-
.moveToHueAndSaturationCommand(hue, saturation, configLevelControl.getDefaultTransitionTime()).get();
308+
.moveToHueAndSaturationCommand(hue, saturation, transitionTime).get();
308309
}
309310

310-
private void changeColorXY(HSBType color) throws InterruptedException, ExecutionException {
311+
private void changeColorXY(HSBType color, int transitionTime) throws InterruptedException, ExecutionException {
311312
PercentType xy[] = color.toXY();
312313

313314
HSBType oldHSB = currentHSB;
@@ -318,11 +319,12 @@ private void changeColorXY(HSBType color) throws InterruptedException, Execution
318319
int x = (int) (xy[0].floatValue() / 100.0f * 65536.0f + 0.5f); // up to 65279
319320
int y = (int) (xy[1].floatValue() / 100.0f * 65536.0f + 0.5f); // up to 65279
320321

321-
clusterColorControl.moveToColorCommand(x, y, configLevelControl.getDefaultTransitionTime()).get();
322+
clusterColorControl.moveToColorCommand(x, y, transitionTime).get();
322323
}
323324

324325
@Override
325-
public void handleCommand(final Command command) {
326+
public void handleCommand(final Command command, final Map<String, Object> params) {
327+
int transitionTime = ZigBeeThingActionParameters.TRANSITION_TIME.getFromMap(params).orElseGet(configLevelControl::getDefaultTransitionTime);
326328
try {
327329
if (command instanceof HSBType) {
328330
HSBType current = currentHSB;
@@ -339,23 +341,23 @@ public void handleCommand(final Command command) {
339341
}
340342

341343
if (brightness.intValue() != currentHSB.getBrightness().intValue()) {
342-
changeBrightness(brightness);
344+
changeBrightness(brightness, transitionTime);
343345
if (changeColor && delayedColorChange) {
344346
Thread.sleep(1100);
345347
}
346348
}
347349

348350
if (changeColor) {
349351
if (supportsHue) {
350-
changeColorHueSaturation(color);
352+
changeColorHueSaturation(color, transitionTime);
351353
} else {
352-
changeColorXY(color);
354+
changeColorXY(color, transitionTime);
353355
}
354356
}
355357
} else if (command instanceof PercentType) {
356-
changeBrightness((PercentType) command);
358+
changeBrightness((PercentType) command, transitionTime);
357359
} else if (command instanceof OnOffType) {
358-
changeOnOff((OnOffType) command);
360+
changeOnOff((OnOffType) command, transitionTime);
359361
}
360362
} catch (InterruptedException | ExecutionException e) {
361363
logger.warn("{}: Exception processing command", endpoint.getIeeeAddress(), e);

org.openhab.binding.zigbee/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeConverterColorTemperature.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*/
99
package org.openhab.binding.zigbee.internal.converter;
1010

11+
import java.util.Map;
1112
import java.util.concurrent.ExecutionException;
1213

1314
import org.eclipse.smarthome.core.library.types.OnOffType;
@@ -18,6 +19,7 @@
1819
import org.eclipse.smarthome.core.types.Command;
1920
import org.eclipse.smarthome.core.types.UnDefType;
2021
import org.openhab.binding.zigbee.ZigBeeBindingConstants;
22+
import org.openhab.binding.zigbee.action.ZigBeeThingActionParameters;
2123
import org.openhab.binding.zigbee.converter.ZigBeeBaseChannelConverter;
2224
import org.slf4j.Logger;
2325
import org.slf4j.LoggerFactory;
@@ -105,7 +107,8 @@ public void handleRefresh() {
105107
}
106108

107109
@Override
108-
public void handleCommand(final Command command) {
110+
public void handleCommand(final Command command, final Map<String, Object> params) {
111+
int transitionTime = ZigBeeThingActionParameters.TRANSITION_TIME.getFromMap(params).orElse(10);
109112
PercentType colorTemperaturePercentage = PercentType.ZERO;
110113
if (command instanceof PercentType) {
111114
colorTemperaturePercentage = (PercentType) command;
@@ -114,7 +117,7 @@ public void handleCommand(final Command command) {
114117
return;
115118
}
116119

117-
clusterColorControl.moveToColorTemperatureCommand(percentToMired(colorTemperaturePercentage), 10);
120+
clusterColorControl.moveToColorTemperatureCommand(percentToMired(colorTemperaturePercentage), transitionTime);
118121
}
119122

120123
@Override

org.openhab.binding.zigbee/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeConverterDoorLock.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*/
99
package org.openhab.binding.zigbee.internal.converter;
1010

11+
import java.util.Map;
1112
import java.util.concurrent.ExecutionException;
1213

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

8384
@Override
84-
public void handleCommand(final Command command) {
85+
public void handleCommand(final Command command, final Map<String, Object> params) {
8586
if (command == OnOffType.ON) {
8687
cluster.lockDoorCommand(new ByteArray(new byte[0]));
8788
} else {

org.openhab.binding.zigbee/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeConverterSwitchLevel.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public void handleRefresh() {
132132
}
133133

134134
@Override
135-
public void handleCommand(final Command command) {
135+
public void handleCommand(final Command command, final Map<String, Object> params) {
136136
if (command instanceof OnOffType) {
137137
handleOnOffCommand((OnOffType) command);
138138
} else if (command instanceof PercentType) {

org.openhab.binding.zigbee/src/main/java/org/openhab/binding/zigbee/internal/converter/ZigBeeConverterSwitchOnoff.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*/
99
package org.openhab.binding.zigbee.internal.converter;
1010

11+
import java.util.Map;
1112
import java.util.concurrent.ExecutionException;
1213

1314
import org.eclipse.smarthome.core.library.types.OnOffType;
@@ -133,7 +134,7 @@ public void handleRefresh() {
133134
}
134135

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

0 commit comments

Comments
 (0)