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.miio.internal.basic;
15 import java.awt.Color;
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.openhab.core.library.types.HSBType;
21 import org.openhab.core.library.types.PercentType;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
25 import com.google.gson.JsonArray;
26 import com.google.gson.JsonElement;
27 import com.google.gson.JsonObject;
28 import com.google.gson.JsonParseException;
29 import com.google.gson.JsonParser;
30 import com.google.gson.JsonPrimitive;
33 * Conversion for values
35 * @author Marcel Verpaalen - Initial contribution
38 public class Conversions {
39 private static final Logger LOGGER = LoggerFactory.getLogger(Conversions.class);
42 * Converts a RGB+brightness input to a HSV value.
45 * @param RGB + brightness value (note brightness in the first byte)
48 private static JsonElement bRGBtoHSV(JsonElement bRGB) throws ClassCastException {
49 if (bRGB.isJsonPrimitive() && bRGB.getAsJsonPrimitive().isNumber()) {
50 Color rgb = new Color(bRGB.getAsInt());
51 HSBType hsb = HSBType.fromRGB(rgb.getRed(), rgb.getGreen(), rgb.getBlue());
52 hsb = new HSBType(hsb.getHue(), hsb.getSaturation(), new PercentType(bRGB.getAsInt() >>> 24));
53 return new JsonPrimitive(hsb.toFullString());
59 * Adds the brightness info (from separate channel) to a HSV value.
63 * @param map with device variables containing the brightness info
64 * @param report brightness 0 on power off
67 private static JsonElement addBrightToHSV(JsonElement rgbValue, @Nullable Map<String, Object> deviceVariables,
68 boolean powerDependent) throws ClassCastException, IllegalStateException {
70 if (deviceVariables != null) {
71 JsonElement lastBright = (JsonElement) deviceVariables.getOrDefault("bright", new JsonPrimitive(100));
72 bright = lastBright.getAsInt();
74 String lastPower = ((JsonElement) deviceVariables.getOrDefault("power", new JsonPrimitive("on")))
76 if (lastPower.toLowerCase().contentEquals("off")) {
81 if (rgbValue.isJsonPrimitive()
82 && (rgbValue.getAsJsonPrimitive().isNumber() || rgbValue.getAsString().matches("^[0-9]+$"))) {
83 Color rgb = new Color(rgbValue.getAsInt());
84 HSBType hsb = HSBType.fromRGB(rgb.getRed(), rgb.getGreen(), rgb.getBlue());
85 hsb = new HSBType(hsb.getHue(), hsb.getSaturation(), new PercentType(bright));
86 return new JsonPrimitive(hsb.toFullString());
91 public static JsonElement deviceDataTab(JsonElement deviceLog, @Nullable Map<String, Object> deviceVariables)
92 throws ClassCastException, IllegalStateException {
93 if (!deviceLog.isJsonObject() && !deviceLog.isJsonPrimitive()) {
96 JsonObject deviceLogJsonObj = deviceLog.isJsonObject() ? deviceLog.getAsJsonObject()
97 : (JsonObject) JsonParser.parseString(deviceLog.getAsString());
98 JsonArray resultLog = new JsonArray();
99 if (deviceLogJsonObj.has("data") && deviceLogJsonObj.get("data").isJsonArray()) {
100 for (JsonElement element : deviceLogJsonObj.get("data").getAsJsonArray()) {
101 if (element.isJsonObject()) {
102 JsonObject dataObject = element.getAsJsonObject();
103 if (dataObject.has("value")) {
104 String value = dataObject.get("value").getAsString();
105 JsonElement val = JsonParser.parseString(value);
106 if (val.isJsonArray()) {
107 resultLog.add(JsonParser.parseString(val.getAsString()));
118 private static JsonElement secondsToHours(JsonElement seconds) throws ClassCastException {
119 double value = seconds.getAsDouble() / 3600;
120 return new JsonPrimitive(value);
123 private static JsonElement yeelightSceneConversion(JsonElement intValue)
124 throws ClassCastException, IllegalStateException {
125 switch (intValue.getAsInt()) {
127 return new JsonPrimitive("color");
129 return new JsonPrimitive("hsv");
131 return new JsonPrimitive("ct");
133 return new JsonPrimitive("nightlight");
134 case 5: // don't know the number for colorflow...
135 return new JsonPrimitive("cf");
136 case 6: // don't know the number for auto_delay_off, or if it is even in the properties visible...
137 return new JsonPrimitive("auto_delay_off");
139 return new JsonPrimitive("unknown");
143 private static JsonElement divideTen(JsonElement value10) throws ClassCastException, IllegalStateException {
144 double value = value10.getAsDouble() / 10.0;
145 return new JsonPrimitive(value);
148 private static JsonElement divideHundred(JsonElement value10) throws ClassCastException, IllegalStateException {
149 double value = value10.getAsDouble() / 100.0;
150 return new JsonPrimitive(value);
153 private static JsonElement tankLevel(JsonElement value12) throws ClassCastException, IllegalStateException {
154 // 127 without water tank. 120 = 100% water
155 if (value12.getAsInt() == 127) {
156 return new JsonPrimitive(-1);
158 double value = value12.getAsDouble();
159 return new JsonPrimitive(value / 1.2);
164 * Returns the deviceId element value from the Json response. If not found, returns the input
166 * @param responseValue
167 * @param deviceVariables containing the deviceId
170 private static JsonElement getDidElement(JsonElement responseValue, Map<String, Object> deviceVariables) {
171 String did = (String) deviceVariables.get("deviceId");
173 return getJsonElement(did, responseValue);
175 LOGGER.debug("deviceId not Found, no conversion");
176 return responseValue;
180 * Returns the element from the Json response. If not found, returns the input
182 * @param element to be found
183 * @param responseValue
186 private static JsonElement getJsonElement(String element, JsonElement responseValue) {
188 if (responseValue.isJsonPrimitive() || responseValue.isJsonObject()) {
189 JsonElement jsonElement = responseValue.isJsonObject() ? responseValue
190 : JsonParser.parseString(responseValue.getAsString());
191 if (jsonElement.isJsonObject()) {
192 JsonObject value = jsonElement.getAsJsonObject();
193 if (value.has(element)) {
194 return value.get(element);
198 } catch (JsonParseException e) {
201 LOGGER.debug("JsonElement '{}' not found in '{}'", element, responseValue);
202 return responseValue;
205 public static JsonElement execute(String transformation, JsonElement value, Map<String, Object> deviceVariables) {
207 if (transformation.toUpperCase().startsWith("GETJSONELEMENT")) {
208 if (transformation.length() > 15) {
209 return getJsonElement(transformation.substring(15), value);
211 LOGGER.info("Transformation {} missing element. Returning '{}'", transformation, value.toString());
214 switch (transformation.toUpperCase()) {
215 case "YEELIGHTSCENEID":
216 return yeelightSceneConversion(value);
217 case "SECONDSTOHOURS":
218 return secondsToHours(value);
220 return divideTen(value);
222 return divideHundred(value);
224 return tankLevel(value);
225 case "ADDBRIGHTTOHSV":
226 return addBrightToHSV(value, deviceVariables, false);
227 case "ADDBRIGHTTOHSVPOWER":
228 return addBrightToHSV(value, deviceVariables, true);
230 return bRGBtoHSV(value);
231 case "DEVICEDATATAB":
232 return deviceDataTab(value, deviceVariables);
233 case "GETDIDELEMENT":
234 return getDidElement(value, deviceVariables);
236 LOGGER.debug("Transformation {} not found. Returning '{}'", transformation, value.toString());
239 } catch (ClassCastException | IllegalStateException e) {
240 LOGGER.debug("Transformation {} failed. Returning '{}'", transformation, value.toString());