]> git.basschouten.com Git - openhab-addons.git/blob
5a6511153adaaeea8a77eebf1959868ef321445e
[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) {
66                     int newBright = ((PercentType) command).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) {
82                     lastColor = ((HSBType) command).getRGB() & 0xffffff;
83                     writeBridgeLightColor(lastColor, lastBrigthness);
84                     return;
85                 }
86                 break;
87             case CHANNEL_COLOR_TEMPERATURE:
88                 if (command instanceof PercentType) {
89                     PercentType colorTemperature = (PercentType) command;
90                     int kelvin = (COLOR_TEMPERATURE_MAX - COLOR_TEMPERATURE_MIN) / 100 * colorTemperature.intValue()
91                             + COLOR_TEMPERATURE_MIN;
92                     int color = ColorUtil.getRGBFromK(kelvin);
93                     writeBridgeLightColor(color, lastBrigthness);
94                     updateState(CHANNEL_COLOR,
95                             HSBType.fromRGB((color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff));
96                     return;
97                 }
98                 break;
99             case CHANNEL_GATEWAY_SOUND:
100                 if (command instanceof DecimalType) {
101                     writeBridgeRingtone(((DecimalType) command).intValue(), lastVolume);
102                     updateState(CHANNEL_GATEWAY_SOUND_SWITCH, OnOffType.ON);
103                     return;
104                 }
105                 break;
106             case CHANNEL_GATEWAY_SOUND_SWITCH:
107                 if (command instanceof OnOffType) {
108                     if (((OnOffType) command) == OnOffType.OFF) {
109                         stopRingtone();
110                     }
111                     return;
112                 }
113                 break;
114             case CHANNEL_GATEWAY_VOLUME:
115                 if (command instanceof DecimalType) {
116                     updateLastVolume((DecimalType) command);
117                 }
118                 return;
119         }
120         // Only gets here, if no condition was met
121         logger.warn("Can't handle command {} on channel {}", command, channelUID);
122     }
123
124     private void updateLastVolume(DecimalType newVolume) {
125         lastVolume = newVolume.intValue();
126         logger.debug("Changed volume to {}", lastVolume);
127     }
128
129     @Override
130     void parseReport(JsonObject data) {
131         parseDefault(data);
132     }
133
134     @Override
135     void parseHeartbeat(JsonObject data) {
136         parseDefault(data);
137     }
138
139     @Override
140     void parseReadAck(JsonObject data) {
141         parseDefault(data);
142     }
143
144     @Override
145     void parseWriteAck(JsonObject data) {
146         parseDefault(data);
147     }
148
149     @Override
150     void parseDefault(JsonObject data) {
151         if (data.has(RGB)) {
152             long rgb = data.get(RGB).getAsLong();
153             updateState(CHANNEL_BRIGHTNESS, new PercentType((int) (((rgb >> 24) & 0xff))));
154             updateState(CHANNEL_COLOR,
155                     HSBType.fromRGB((int) (rgb >> 16) & 0xff, (int) (rgb >> 8) & 0xff, (int) rgb & 0xff));
156         }
157         if (data.has(ILLUMINATION)) {
158             int illu = data.get(ILLUMINATION).getAsInt();
159             updateState(CHANNEL_ILLUMINATION, new DecimalType(illu));
160         }
161     }
162
163     private void writeBridgeLightColor(int color, int brightness) {
164         long brightnessInt = brightness << 24;
165         writeBridgeLightColor((color & 0xffffff) | brightnessInt & 0xff000000);
166     }
167
168     private void writeBridgeLightColor(long color) {
169         getXiaomiBridgeHandler().writeToBridge(new String[] { RGB }, new Object[] { color });
170     }
171
172     /**
173      * Play ringtone on Xiaomi Gateway
174      * 0 - 8, 10 - 13, 20 - 29 -- ringtones that come with the system)
175      * > 10001 -- user-defined ringtones
176      *
177      * @param ringtoneId
178      */
179     private void writeBridgeRingtone(int ringtoneId, int volume) {
180         getXiaomiBridgeHandler().writeToBridge(new String[] { MID, VOL }, new Object[] { ringtoneId, volume });
181     }
182
183     /**
184      * Stop playing ringtone on Xiaomi Gateway
185      * by setting "mid" parameter to 10000
186      */
187     private void stopRingtone() {
188         getXiaomiBridgeHandler().writeToBridge(new String[] { MID }, new Object[] { 10000 });
189     }
190 }