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
66 private static JsonElement addBrightToHSV(JsonElement rgbValue, @Nullable Map<String, Object> deviceVariables)
67 throws ClassCastException, IllegalStateException {
69 if (deviceVariables != null) {
70 JsonElement lastBright = (JsonElement) deviceVariables.getOrDefault("bright", new JsonPrimitive(100));
71 bright = lastBright.getAsInt();
73 if (rgbValue.isJsonPrimitive()
74 && (rgbValue.getAsJsonPrimitive().isNumber() || rgbValue.getAsString().matches("^[0-9]+$"))) {
75 Color rgb = new Color(rgbValue.getAsInt());
76 HSBType hsb = HSBType.fromRGB(rgb.getRed(), rgb.getGreen(), rgb.getBlue());
77 hsb = new HSBType(hsb.getHue(), hsb.getSaturation(), new PercentType(bright));
78 return new JsonPrimitive(hsb.toFullString());
83 public static JsonElement deviceDataTab(JsonElement deviceLog, @Nullable Map<String, Object> deviceVariables)
84 throws ClassCastException, IllegalStateException {
85 if (!deviceLog.isJsonObject() && !deviceLog.isJsonPrimitive()) {
88 JsonObject deviceLogJsonObj = deviceLog.isJsonObject() ? deviceLog.getAsJsonObject()
89 : (JsonObject) JsonParser.parseString(deviceLog.getAsString());
90 JsonArray resultLog = new JsonArray();
91 if (deviceLogJsonObj.has("data") && deviceLogJsonObj.get("data").isJsonArray()) {
92 for (JsonElement element : deviceLogJsonObj.get("data").getAsJsonArray()) {
93 if (element.isJsonObject()) {
94 JsonObject dataObject = element.getAsJsonObject();
95 if (dataObject.has("value")) {
96 String value = dataObject.get("value").getAsString();
97 JsonElement val = JsonParser.parseString(value);
98 if (val.isJsonArray()) {
99 resultLog.add(JsonParser.parseString(val.getAsString()));
110 private static JsonElement secondsToHours(JsonElement seconds) throws ClassCastException {
111 double value = seconds.getAsDouble() / 3600;
112 return new JsonPrimitive(value);
115 private static JsonElement yeelightSceneConversion(JsonElement intValue)
116 throws ClassCastException, IllegalStateException {
117 switch (intValue.getAsInt()) {
119 return new JsonPrimitive("color");
121 return new JsonPrimitive("hsv");
123 return new JsonPrimitive("ct");
125 return new JsonPrimitive("nightlight");
126 case 5: // don't know the number for colorflow...
127 return new JsonPrimitive("cf");
128 case 6: // don't know the number for auto_delay_off, or if it is even in the properties visible...
129 return new JsonPrimitive("auto_delay_off");
131 return new JsonPrimitive("unknown");
135 private static JsonElement divideTen(JsonElement value10) throws ClassCastException, IllegalStateException {
136 double value = value10.getAsDouble() / 10.0;
137 return new JsonPrimitive(value);
140 private static JsonElement divideHundred(JsonElement value10) throws ClassCastException, IllegalStateException {
141 double value = value10.getAsDouble() / 100.0;
142 return new JsonPrimitive(value);
145 private static JsonElement tankLevel(JsonElement value12) throws ClassCastException, IllegalStateException {
146 // 127 without water tank. 120 = 100% water
147 if (value12.getAsInt() == 127) {
148 return new JsonPrimitive(-1);
150 double value = value12.getAsDouble();
151 return new JsonPrimitive(value / 1.2);
156 * Returns the deviceId element value from the Json response. If not found, returns the input
158 * @param responseValue
159 * @param deviceVariables containing the deviceId
162 private static JsonElement getDidElement(JsonElement responseValue, Map<String, Object> deviceVariables) {
163 String did = (String) deviceVariables.get("deviceId");
165 return getJsonElement(did, responseValue);
167 LOGGER.debug("deviceId not Found, no conversion");
168 return responseValue;
172 * Returns the element from the Json response. If not found, returns the input
174 * @param element to be found
175 * @param responseValue
178 private static JsonElement getJsonElement(String element, JsonElement responseValue) {
180 if (responseValue.isJsonPrimitive() || responseValue.isJsonObject()) {
181 JsonElement jsonElement = responseValue.isJsonObject() ? responseValue
182 : JsonParser.parseString(responseValue.getAsString());
183 if (jsonElement.isJsonObject()) {
184 JsonObject value = jsonElement.getAsJsonObject();
185 if (value.has(element)) {
186 return value.get(element);
190 } catch (JsonParseException e) {
193 LOGGER.debug("JsonElement '{}' not found in '{}'", element, responseValue);
194 return responseValue;
197 public static JsonElement execute(String transformation, JsonElement value, Map<String, Object> deviceVariables) {
199 if (transformation.toUpperCase().startsWith("GETJSONELEMENT")) {
200 if (transformation.length() > 15) {
201 return getJsonElement(transformation.substring(15), value);
203 LOGGER.info("Transformation {} missing element. Returning '{}'", transformation, value.toString());
206 switch (transformation.toUpperCase()) {
207 case "YEELIGHTSCENEID":
208 return yeelightSceneConversion(value);
209 case "SECONDSTOHOURS":
210 return secondsToHours(value);
212 return divideTen(value);
214 return divideHundred(value);
216 return tankLevel(value);
217 case "ADDBRIGHTTOHSV":
218 return addBrightToHSV(value, deviceVariables);
220 return bRGBtoHSV(value);
221 case "DEVICEDATATAB":
222 return deviceDataTab(value, deviceVariables);
223 case "GETDIDELEMENT":
224 return getDidElement(value, deviceVariables);
226 LOGGER.debug("Transformation {} not found. Returning '{}'", transformation, value.toString());
229 } catch (ClassCastException | IllegalStateException e) {
230 LOGGER.debug("Transformation {} failed. Returning '{}'", transformation, value.toString());