2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.mihome.internal.handler;
15 import static org.openhab.binding.mihome.internal.XiaomiGatewayBindingConstants.*;
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;
28 import com.google.gson.JsonObject;
31 * @author Patrick Boos - Initial contribution
32 * @author Dieter Schmidt - Refactor & sound
34 public class XiaomiActorGatewayHandler extends XiaomiActorBaseHandler {
36 private static final int COLOR_TEMPERATURE_MAX = 6500;
37 private static final int COLOR_TEMPERATURE_MIN = 1700;
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;
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";
48 private Integer lastBrigthness;
49 private Integer lastVolume;
50 private Integer lastColor;
52 private final Logger logger = LoggerFactory.getLogger(XiaomiActorGatewayHandler.class);
54 public XiaomiActorGatewayHandler(Thing thing) {
56 lastBrigthness = DEFAULT_BRIGTHNESS_PCENT;
57 lastVolume = DEFAULT_VOLUME_PCENT;
58 lastColor = DEFAULT_COLOR;
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);
72 logger.debug("Do not send this command, value {} already set", newBright);
75 } else if (command instanceof OnOffType) {
76 writeBridgeLightColor(lastColor, command == OnOffType.ON ? lastBrigthness : 0);
81 if (command instanceof HSBType hsbCommand) {
82 lastColor = hsbCommand.getRGB() & 0xffffff;
83 writeBridgeLightColor(lastColor, lastBrigthness);
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));
98 case CHANNEL_GATEWAY_SOUND:
99 if (command instanceof DecimalType decimalCommand) {
100 writeBridgeRingtone(decimalCommand.intValue(), lastVolume);
101 updateState(CHANNEL_GATEWAY_SOUND_SWITCH, OnOffType.ON);
105 case CHANNEL_GATEWAY_SOUND_SWITCH:
106 if (command instanceof OnOffType onOffCommand) {
107 if (onOffCommand == OnOffType.OFF) {
113 case CHANNEL_GATEWAY_VOLUME:
114 if (command instanceof DecimalType decimalCommand) {
115 updateLastVolume(decimalCommand);
119 // Only gets here, if no condition was met
120 logger.warn("Can't handle command {} on channel {}", command, channelUID);
123 private void updateLastVolume(DecimalType newVolume) {
124 lastVolume = newVolume.intValue();
125 logger.debug("Changed volume to {}", lastVolume);
129 void parseReport(JsonObject data) {
134 void parseHeartbeat(JsonObject data) {
139 void parseReadAck(JsonObject data) {
144 void parseWriteAck(JsonObject data) {
149 void parseDefault(JsonObject data) {
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));
156 if (data.has(ILLUMINATION)) {
157 int illu = data.get(ILLUMINATION).getAsInt();
158 updateState(CHANNEL_ILLUMINATION, new DecimalType(illu));
162 private void writeBridgeLightColor(int color, int brightness) {
163 long brightnessInt = brightness << 24;
164 writeBridgeLightColor((color & 0xffffff) | brightnessInt & 0xff000000);
167 private void writeBridgeLightColor(long color) {
168 getXiaomiBridgeHandler().writeToBridge(new String[] { RGB }, new Object[] { color });
172 * Play ringtone on Xiaomi Gateway
173 * 0 - 8, 10 - 13, 20 - 29 -- ringtones that come with the system)
174 * > 10001 -- user-defined ringtones
178 private void writeBridgeRingtone(int ringtoneId, int volume) {
179 getXiaomiBridgeHandler().writeToBridge(new String[] { MID, VOL }, new Object[] { ringtoneId, volume });
183 * Stop playing ringtone on Xiaomi Gateway
184 * by setting "mid" parameter to 10000
186 private void stopRingtone() {
187 getXiaomiBridgeHandler().writeToBridge(new String[] { MID }, new Object[] { 10000 });