]> git.basschouten.com Git - openhab-addons.git/blob
eb9a44d5eeef1f200d1b2497b4d78fc9cc5ad193
[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.mihome.internal.handler;
14
15 import static org.openhab.binding.mihome.internal.XiaomiGatewayBindingConstants.*;
16
17 import org.openhab.binding.mihome.internal.ColorUtil;
18 import org.openhab.core.library.types.DecimalType;
19 import org.openhab.core.library.types.HSBType;
20 import org.openhab.core.library.types.OnOffType;
21 import org.openhab.core.library.types.PercentType;
22 import org.openhab.core.thing.ChannelUID;
23 import org.openhab.core.thing.Thing;
24 import org.openhab.core.types.Command;
25 import org.openhab.core.types.State;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 import com.google.gson.JsonObject;
30
31 /**
32  * @author Patrick Boos - Initial contribution
33  * @author Dieter Schmidt - Refactor & sound
34  */
35 public class XiaomiActorGatewayHandler extends XiaomiActorBaseHandler {
36
37     private static final int COLOR_TEMPERATURE_MAX = 6500;
38     private static final int COLOR_TEMPERATURE_MIN = 1700;
39
40     private static final int DEFAULT_BRIGTHNESS_PCENT = 100;
41     private static final int DEFAULT_VOLUME_PCENT = 50;
42     private static final int DEFAULT_COLOR = 0xffffff;
43
44     private static final String RGB = "rgb";
45     private static final String ILLUMINATION = "illumination";
46     private static final String MID = "mid";
47     private static final String VOL = "vol";
48
49     private Integer lastBrigthness;
50     private Integer lastVolume;
51     private Integer lastColor;
52
53     private final Logger logger = LoggerFactory.getLogger(XiaomiActorGatewayHandler.class);
54
55     public XiaomiActorGatewayHandler(Thing thing) {
56         super(thing);
57         lastBrigthness = DEFAULT_BRIGTHNESS_PCENT;
58         lastVolume = DEFAULT_VOLUME_PCENT;
59         lastColor = DEFAULT_COLOR;
60     }
61
62     @Override
63     void execute(ChannelUID channelUID, Command command) {
64         switch (channelUID.getId()) {
65             case CHANNEL_BRIGHTNESS:
66                 if (command instanceof PercentType) {
67                     int newBright = ((PercentType) command).intValue();
68                     if (lastBrigthness != newBright) {
69                         lastBrigthness = newBright;
70                         logger.debug("Set brigthness to {}", lastBrigthness);
71                         writeBridgeLightColor(lastColor, lastBrigthness);
72                     } else {
73                         logger.debug("Do not send this command, value {} already set", newBright);
74                     }
75                     return;
76                 } else if (command instanceof OnOffType) {
77                     writeBridgeLightColor(lastColor, command == OnOffType.ON ? lastBrigthness : 0);
78                     return;
79                 }
80                 break;
81             case CHANNEL_COLOR:
82                 if (command instanceof HSBType) {
83                     lastColor = ((HSBType) command).getRGB() & 0xffffff;
84                     writeBridgeLightColor(lastColor, lastBrigthness);
85                     return;
86                 }
87                 break;
88             case CHANNEL_COLOR_TEMPERATURE:
89                 if (command instanceof PercentType) {
90                     PercentType colorTemperature = (PercentType) command;
91                     int kelvin = (COLOR_TEMPERATURE_MAX - COLOR_TEMPERATURE_MIN) / 100 * colorTemperature.intValue()
92                             + COLOR_TEMPERATURE_MIN;
93                     int color = ColorUtil.getRGBFromK(kelvin);
94                     writeBridgeLightColor(color, lastBrigthness);
95                     updateState(CHANNEL_COLOR,
96                             HSBType.fromRGB((color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff));
97                     return;
98                 }
99                 break;
100             case CHANNEL_GATEWAY_SOUND:
101                 if (command instanceof DecimalType) {
102                     writeBridgeRingtone(((DecimalType) command).intValue(), lastVolume);
103                     updateState(CHANNEL_GATEWAY_SOUND_SWITCH, OnOffType.ON);
104                     return;
105                 }
106                 break;
107             case CHANNEL_GATEWAY_SOUND_SWITCH:
108                 if (command instanceof OnOffType) {
109                     if (((OnOffType) command) == OnOffType.OFF) {
110                         stopRingtone();
111                     }
112                     return;
113                 }
114                 break;
115             case CHANNEL_GATEWAY_VOLUME:
116                 if (command instanceof DecimalType) {
117                     updateLastVolume((DecimalType) command);
118                 }
119                 return;
120         }
121         // Only gets here, if no condition was met
122         logger.warn("Can't handle command {} on channel {}", command, channelUID);
123     }
124
125     private void updateLastVolume(DecimalType newVolume) {
126         lastVolume = newVolume.intValue();
127         logger.debug("Changed volume to {}", lastVolume);
128     }
129
130     @Override
131     public void handleUpdate(ChannelUID channelUID, State newState) {
132         logger.debug("Update {} for channel {} received", newState, channelUID);
133         switch (channelUID.getId()) {
134             case CHANNEL_BRIGHTNESS:
135                 if (newState instanceof PercentType) {
136                     lastBrigthness = ((PercentType) newState).intValue();
137                 }
138                 break;
139             case CHANNEL_COLOR:
140                 if (newState instanceof HSBType) {
141                     lastColor = ((HSBType) newState).getRGB();
142                 }
143                 break;
144             case CHANNEL_GATEWAY_VOLUME:
145                 if (newState instanceof DecimalType) {
146                     updateLastVolume((DecimalType) newState);
147                 }
148                 break;
149         }
150     }
151
152     @Override
153     void parseReport(JsonObject data) {
154         parseDefault(data);
155     }
156
157     @Override
158     void parseHeartbeat(JsonObject data) {
159         parseDefault(data);
160     }
161
162     @Override
163     void parseReadAck(JsonObject data) {
164         parseDefault(data);
165     }
166
167     @Override
168     void parseWriteAck(JsonObject data) {
169         parseDefault(data);
170     }
171
172     @Override
173     void parseDefault(JsonObject data) {
174         if (data.has(RGB)) {
175             long rgb = data.get(RGB).getAsLong();
176             updateState(CHANNEL_BRIGHTNESS, new PercentType((int) (((rgb >> 24) & 0xff))));
177             updateState(CHANNEL_COLOR,
178                     HSBType.fromRGB((int) (rgb >> 16) & 0xff, (int) (rgb >> 8) & 0xff, (int) rgb & 0xff));
179         }
180         if (data.has(ILLUMINATION)) {
181             int illu = data.get(ILLUMINATION).getAsInt();
182             updateState(CHANNEL_ILLUMINATION, new DecimalType(illu));
183         }
184     }
185
186     private void writeBridgeLightColor(int color, int brightness) {
187         long brightnessInt = brightness << 24;
188         writeBridgeLightColor((color & 0xffffff) | brightnessInt & 0xff000000);
189     }
190
191     private void writeBridgeLightColor(long color) {
192         getXiaomiBridgeHandler().writeToBridge(new String[] { RGB }, new Object[] { color });
193     }
194
195     /**
196      * Play ringtone on Xiaomi Gateway
197      * 0 - 8, 10 - 13, 20 - 29 -- ringtones that come with the system)
198      * > 10001 -- user-defined ringtones
199      *
200      * @param ringtoneId
201      */
202     private void writeBridgeRingtone(int ringtoneId, int volume) {
203         getXiaomiBridgeHandler().writeToBridge(new String[] { MID, VOL }, new Object[] { ringtoneId, volume });
204     }
205
206     /**
207      * Stop playing ringtone on Xiaomi Gateway
208      * by setting "mid" parameter to 10000
209      */
210     private void stopRingtone() {
211         getXiaomiBridgeHandler().writeToBridge(new String[] { MID }, new Object[] { 10000 });
212     }
213 }