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) {
66 int newBright = ((PercentType) command).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) {
82 lastColor = ((HSBType) command).getRGB() & 0xffffff;
83 writeBridgeLightColor(lastColor, lastBrigthness);
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));
99 case CHANNEL_GATEWAY_SOUND:
100 if (command instanceof DecimalType) {
101 writeBridgeRingtone(((DecimalType) command).intValue(), lastVolume);
102 updateState(CHANNEL_GATEWAY_SOUND_SWITCH, OnOffType.ON);
106 case CHANNEL_GATEWAY_SOUND_SWITCH:
107 if (command instanceof OnOffType) {
108 if (((OnOffType) command) == OnOffType.OFF) {
114 case CHANNEL_GATEWAY_VOLUME:
115 if (command instanceof DecimalType) {
116 updateLastVolume((DecimalType) command);
120 // Only gets here, if no condition was met
121 logger.warn("Can't handle command {} on channel {}", command, channelUID);
124 private void updateLastVolume(DecimalType newVolume) {
125 lastVolume = newVolume.intValue();
126 logger.debug("Changed volume to {}", lastVolume);
130 void parseReport(JsonObject data) {
135 void parseHeartbeat(JsonObject data) {
140 void parseReadAck(JsonObject data) {
145 void parseWriteAck(JsonObject data) {
150 void parseDefault(JsonObject data) {
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));
157 if (data.has(ILLUMINATION)) {
158 int illu = data.get(ILLUMINATION).getAsInt();
159 updateState(CHANNEL_ILLUMINATION, new DecimalType(illu));
163 private void writeBridgeLightColor(int color, int brightness) {
164 long brightnessInt = brightness << 24;
165 writeBridgeLightColor((color & 0xffffff) | brightnessInt & 0xff000000);
168 private void writeBridgeLightColor(long color) {
169 getXiaomiBridgeHandler().writeToBridge(new String[] { RGB }, new Object[] { color });
173 * Play ringtone on Xiaomi Gateway
174 * 0 - 8, 10 - 13, 20 - 29 -- ringtones that come with the system)
175 * > 10001 -- user-defined ringtones
179 private void writeBridgeRingtone(int ringtoneId, int volume) {
180 getXiaomiBridgeHandler().writeToBridge(new String[] { MID, VOL }, new Object[] { ringtoneId, volume });
184 * Stop playing ringtone on Xiaomi Gateway
185 * by setting "mid" parameter to 10000
187 private void stopRingtone() {
188 getXiaomiBridgeHandler().writeToBridge(new String[] { MID }, new Object[] { 10000 });