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