]> git.basschouten.com Git - openhab-addons.git/blob
3589a6cdd98a56cbb0648ca01b35bae88b3fc75e
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.lutron.internal.handler;
14
15 import static org.openhab.binding.lutron.internal.LutronBindingConstants.CHANNEL_SHADELEVEL;
16
17 import java.math.BigDecimal;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.openhab.binding.lutron.internal.protocol.LutronCommandType;
21 import org.openhab.core.library.types.PercentType;
22 import org.openhab.core.library.types.StopMoveType;
23 import org.openhab.core.library.types.UpDownType;
24 import org.openhab.core.thing.Bridge;
25 import org.openhab.core.thing.ChannelUID;
26 import org.openhab.core.thing.Thing;
27 import org.openhab.core.thing.ThingStatus;
28 import org.openhab.core.thing.ThingStatusDetail;
29 import org.openhab.core.types.Command;
30 import org.openhab.core.types.RefreshType;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 /**
35  * Handler responsible for communicating with a Lutron Sivoia QS shade
36  *
37  * @author Bob Adair - Initial contribution based on Alan Tong's DimmerHandler
38  */
39 @NonNullByDefault
40 public class ShadeHandler extends LutronHandler {
41     private static final Integer ACTION_ZONELEVEL = 1;
42     private static final Integer ACTION_STARTRAISING = 2;
43     private static final Integer ACTION_STARTLOWERING = 3;
44     private static final Integer ACTION_STOP = 4;
45     private static final Integer ACTION_POSITION_UPDATE = 32; // undocumented in integration protocol guide
46     private static final Integer PARAMETER_POSITION_UPDATE = 2; // undocumented in integration protocol guide
47
48     private final Logger logger = LoggerFactory.getLogger(ShadeHandler.class);
49
50     protected int integrationId;
51
52     public ShadeHandler(Thing thing) {
53         super(thing);
54     }
55
56     @Override
57     public int getIntegrationId() {
58         return integrationId;
59     }
60
61     @Override
62     public void initialize() {
63         Number id = (Number) getThing().getConfiguration().get("integrationId");
64         if (id == null) {
65             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No integrationId");
66             return;
67         }
68         integrationId = id.intValue();
69         logger.debug("Initializing Shade handler for integration ID {}", id);
70
71         initDeviceState();
72     }
73
74     @Override
75     protected void initDeviceState() {
76         logger.debug("Initializing device state for Shade {}", getIntegrationId());
77         Bridge bridge = getBridge();
78         if (bridge == null) {
79             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No bridge configured");
80         } else if (bridge.getStatus() == ThingStatus.ONLINE) {
81             updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.NONE, "Awaiting initial response");
82             queryOutput(ACTION_ZONELEVEL); // handleUpdate() will set thing status to online when response arrives
83         } else {
84             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
85         }
86     }
87
88     @Override
89     public void channelLinked(ChannelUID channelUID) {
90         // Refresh state when new item is linked.
91         if (channelUID.getId().equals(CHANNEL_SHADELEVEL)) {
92             queryOutput(ACTION_ZONELEVEL);
93         }
94     }
95
96     @Override
97     public void handleCommand(ChannelUID channelUID, Command command) {
98         if (channelUID.getId().equals(CHANNEL_SHADELEVEL)) {
99             if (command instanceof PercentType) {
100                 int level = ((PercentType) command).intValue();
101                 output(ACTION_ZONELEVEL, level, 0);
102             } else if (command.equals(UpDownType.UP)) {
103                 output(ACTION_STARTRAISING);
104             } else if (command.equals(UpDownType.DOWN)) {
105                 output(ACTION_STARTLOWERING);
106             } else if (command.equals(StopMoveType.STOP)) {
107                 output(ACTION_STOP);
108             } else if (command instanceof RefreshType) {
109                 queryOutput(ACTION_ZONELEVEL);
110             }
111         }
112     }
113
114     @Override
115     public void handleUpdate(LutronCommandType type, String... parameters) {
116         if (type == LutronCommandType.OUTPUT && parameters.length >= 2) {
117             if (ACTION_ZONELEVEL.toString().equals(parameters[0])) {
118                 BigDecimal level = new BigDecimal(parameters[1]);
119                 if (getThing().getStatus() == ThingStatus.UNKNOWN) {
120                     updateStatus(ThingStatus.ONLINE);
121                 }
122                 logger.trace("Shade {} received zone level: {}", getIntegrationId(), level);
123                 updateState(CHANNEL_SHADELEVEL, new PercentType(level));
124             } else if (ACTION_POSITION_UPDATE.toString().equals(parameters[0])
125                     && PARAMETER_POSITION_UPDATE.toString().equals(parameters[1]) && parameters.length >= 3) {
126                 BigDecimal level = new BigDecimal(parameters[2]);
127                 logger.trace("Shade {} received position update: {}", getIntegrationId(), level);
128                 updateState(CHANNEL_SHADELEVEL, new PercentType(level));
129             }
130         }
131     }
132 }