]> git.basschouten.com Git - openhab-addons.git/commitdiff
[miio] add support for BT Gateway switch on chuangmi.plug.212a01 (#11657)
authorMarcel <marcel@verpaalen.com>
Mon, 29 Nov 2021 11:34:09 +0000 (12:34 +0100)
committerGitHub <noreply@github.com>
Mon, 29 Nov 2021 11:34:09 +0000 (12:34 +0100)
* [miio] add support for BT Gateway switch on chuangmi.plug.212a01

Signed-off-by: Marcel Verpaalen <marcel@verpaalen.com>
* [miio] improve conversion & add test for it

Signed-off-by: Marcel Verpaalen <marcel@verpaalen.com>
* [miio] add one empty string test

Signed-off-by: Marcel Verpaalen <marcel@verpaalen.com>
* [miio] remove unnessesary exceptions

Signed-off-by: Marcel Verpaalen <marcel@verpaalen.com>
* [miio] add one more test for different inputs

Signed-off-by: Marcel Verpaalen <marcel@verpaalen.com>
* [miio] typo

Signed-off-by: Marcel Verpaalen <marcel@verpaalen.com>
bundles/org.openhab.binding.miio/README.md
bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/Conversions.java
bundles/org.openhab.binding.miio/src/main/resources/database/chuangmi.plug.212a01-miot.json
bundles/org.openhab.binding.miio/src/test/java/org/openhab/binding/miio/internal/ConversionsTest.java [new file with mode: 0644]

index 66f58a5329c13311783d873e74d180ae224796b8..59695ffb2719653b8d743cc0dee099a88c33beb8 100644 (file)
@@ -187,7 +187,7 @@ Currently the miio binding supports more than 300 different models.
 | Mi Multifunction Air Monitor | miio:basic       | [cgllc.airmonitor.b1](#cgllc-airmonitor-b1) | Yes       |            |
 | Qingping Air Monitor         | miio:basic       | [cgllc.airmonitor.s1](#cgllc-airmonitor-s1) | Yes       |            |
 | Mi Universal Remote          | miio:unsupported | chuangmi.ir.v2         | No        |            |
-| Mi Smart Power Plug 2 (Wi-Fi and Bluetooth Gateway) | miio:basic       | [chuangmi.plug.212a01](#chuangmi-plug-212a01) | Yes       | Experimental support. Please report back if all channels are functional. Preferably share the debug log of property refresh and command responses |
+| Mi Smart Power Plug 2 (Wi-Fi and Bluetooth Gateway) | miio:basic       | [chuangmi.plug.212a01](#chuangmi-plug-212a01) | Yes       |            |
 | Mi Smart Plug WiFi           | miio:basic       | [chuangmi.plug.hmi205](#chuangmi-plug-hmi205) | Yes       |            |
 | Mi Smart Plug (WiFi)         | miio:basic       | [chuangmi.plug.hmi206](#chuangmi-plug-hmi206) | Yes       |            |
 | Mi Smart Wi-Fi Plug (Bluetooth Gateway) | miio:basic       | [chuangmi.plug.hmi208](#chuangmi-plug-hmi208) | Yes       |            |
@@ -694,6 +694,7 @@ Note, not all the values need to be in the json file, e.g. a subset of the param
 | countdown            | Number:Time          | Imilab Timer - Countdown                 |            |
 | task-switch          | Switch               | Imilab Timer - Task Switch               |            |
 | countdown-info       | Switch               | Imilab Timer - Countdown Info            |            |
+| bt-gw                | String               | BT Gateway                               | Value mapping `["disable"="Disable","enable"="Enable"]` |
 
 ### Mi Smart Plug WiFi (<a name="chuangmi-plug-hmi205">chuangmi.plug.hmi205</a>) Channels
 
@@ -5488,6 +5489,7 @@ Number:Time off_duration "Imilab Timer - Off Duration" (G_plug) {channel="miio:b
 Number:Time countdown "Imilab Timer - Countdown" (G_plug) {channel="miio:basic:plug:countdown"}
 Switch task_switch "Imilab Timer - Task Switch" (G_plug) {channel="miio:basic:plug:task-switch"}
 Switch countdown_info "Imilab Timer - Countdown Info" (G_plug) {channel="miio:basic:plug:countdown-info"}
+String bt_gw "BT Gateway" (G_plug) {channel="miio:basic:plug:bt-gw"}
 ```
 
 ### Mi Smart Plug WiFi (chuangmi.plug.hmi205) item file lines
index ba79c31cac9fcbad665cff8b6725db1b63063999..e20487d09a0b80e8cd5bbae8e25db29d579017c6 100644 (file)
@@ -23,6 +23,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonParser;
 import com.google.gson.JsonPrimitive;
 
 /**
@@ -121,9 +124,35 @@ public class Conversions {
         }
     }
 
+    public static JsonElement getJsonElement(String element, JsonElement responseValue) {
+        try {
+            if (responseValue.isJsonPrimitive() || responseValue.isJsonObject()) {
+                JsonElement jsonElement = responseValue.isJsonObject() ? responseValue
+                        : JsonParser.parseString(responseValue.getAsString());
+                if (jsonElement.isJsonObject()) {
+                    JsonObject value = jsonElement.getAsJsonObject();
+                    if (value.has(element)) {
+                        return value.get(element);
+                    }
+                }
+            }
+        } catch (JsonParseException e) {
+            // ignore
+        }
+        LOGGER.debug("JsonElement '{}' not found in '{}'", element, responseValue);
+        return responseValue;
+    }
+
     public static JsonElement execute(String transformation, JsonElement value,
             @Nullable Map<String, Object> deviceVariables) {
         try {
+            if (transformation.toUpperCase().startsWith("GETJSONELEMENT")) {
+                if (transformation.length() > 15) {
+                    return getJsonElement(transformation.substring(15), value);
+                } else {
+                    LOGGER.info("Transformation {} missing element. Returning '{}'", transformation, value.toString());
+                }
+            }
             switch (transformation.toUpperCase()) {
                 case "YEELIGHTSCENEID":
                     return yeelightSceneConversion(value);
index 4827ef6cd6df410759a78da7e084fbf43c2d8062..9ee47e5e69f3ef72016ec0efb54eb035ebdce203 100644 (file)
                                },
                                "refresh": true,
                                "actions": []
+                       },
+                       {
+                               "property": "",
+                               "friendlyName": "BT Gateway",
+                               "channel": "bt-gw",
+                               "type": "String",
+                               "stateDescription": {
+                                       "readOnly": false,
+                                       "options": [
+                                               {
+                                                       "value": "disable",
+                                                       "label": "Disable"
+                                               },
+                                               {
+                                                       "value": "enable",
+                                                       "label": "Enable"
+                                               }
+                                       ]
+                               },
+                               "refresh": true,
+                               "customRefreshCommand": "bt_gateway_status",
+                               "transformation": "getJsonElement-gateway_status",
+                               "actions": [
+                                       {
+                                               "command": "bt_gateway_enable",
+                                               "parameterType": "EMPTY",
+                                               "condition": {
+                                                       "name": "matchValue",
+                                                       "parameters": [
+                                                               {
+                                                                       "matchValue": "enable"
+                                                               }
+                                                       ]
+                                               }
+                                       },
+                                       {
+                                               "command": "bt_gateway_disable",
+                                               "parameterType": "EMPTY",
+                                               "condition": {
+                                                       "name": "matchValue",
+                                                       "parameters": [
+                                                               {
+                                                                       "matchValue": "disable"
+                                                               }
+                                                       ]
+                                               }
+                                       }
+                               ],
+                               "readmeComment": "Value mapping `[\"disable\"\u003d\"Disable\",\"enable\"\u003d\"Enable\"]`"
                        }
                ],
-               "experimental": true
+               "experimental": false
        }
 }
diff --git a/bundles/org.openhab.binding.miio/src/test/java/org/openhab/binding/miio/internal/ConversionsTest.java b/bundles/org.openhab.binding.miio/src/test/java/org/openhab/binding/miio/internal/ConversionsTest.java
new file mode 100644 (file)
index 0000000..2ee46a0
--- /dev/null
@@ -0,0 +1,123 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.miio.internal;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.miio.internal.basic.Conversions;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonPrimitive;
+
+/**
+ * Test case for {@link ConversionsTest}
+ *
+ * @author Marcel Verpaalen - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class ConversionsTest {
+
+    @Test
+    public void getJsonElementTest() {
+
+        Map<String, Object> deviceVariables = Collections.emptyMap();
+
+        // test invalid missing element
+        String transformation = "getJsonElement";
+        JsonElement value = new JsonPrimitive("");
+        JsonElement resp = Conversions.execute(transformation, value, deviceVariables);
+        assertNotNull(resp);
+        assertEquals(value, resp);
+
+        // test invalid missing element
+        value = new JsonPrimitive("{\"test\": \"testresponse\"}");
+        resp = Conversions.execute(transformation, value, deviceVariables);
+        assertNotNull(resp);
+        assertEquals(value, resp);
+
+        transformation = "getJsonElement-test";
+
+        // test without deviceVariables
+        resp = Conversions.execute(transformation, value, null);
+        assertNotNull(resp);
+        assertEquals(new JsonPrimitive("testresponse"), resp);
+
+        // test non json
+        value = new JsonPrimitive("some non json value");
+        resp = Conversions.execute(transformation, value, deviceVariables);
+        assertNotNull(resp);
+        assertEquals(value, resp);
+
+        // test non json empty string
+        value = new JsonPrimitive("");
+        resp = Conversions.execute(transformation, value, deviceVariables);
+        assertNotNull(resp);
+        assertEquals(value, resp);
+
+        // test input as jsonString
+        value = new JsonPrimitive("{\"test\": \"testresponse\"}");
+        resp = Conversions.execute(transformation, value, deviceVariables);
+        assertNotNull(resp);
+        assertEquals(new JsonPrimitive("testresponse"), resp);
+
+        // test input as jsonObject
+        value = JsonParser.parseString("{\"test\": \"testresponse\"}");
+        resp = Conversions.execute(transformation, value, deviceVariables);
+        assertNotNull(resp);
+        assertEquals(new JsonPrimitive("testresponse"), resp);
+
+        // test input as jsonString for a number
+        value = new JsonPrimitive("{\"test\": 3}");
+        resp = Conversions.execute(transformation, value, deviceVariables);
+        assertNotNull(resp);
+        assertEquals(new JsonPrimitive(3), resp);
+
+        // test input as jsonString for a array
+        value = new JsonPrimitive("{\"test\": []}");
+        resp = Conversions.execute(transformation, value, deviceVariables);
+        assertNotNull(resp);
+        assertEquals(new JsonArray(), resp);
+
+        // test input as jsonString for a boolean
+        value = new JsonPrimitive("{\"test\": false}");
+        resp = Conversions.execute(transformation, value, deviceVariables);
+        assertNotNull(resp);
+        assertEquals(new JsonPrimitive(false), resp);
+
+        // test input as jsonObject for a number
+        value = JsonParser.parseString("{\"test\": 3}");
+        resp = Conversions.execute(transformation, value, deviceVariables);
+        assertNotNull(resp);
+        assertEquals(new JsonPrimitive(3), resp);
+
+        // test input as jsonString for non-existing element
+        value = new JsonPrimitive("{\"nottest\": \"testresponse\"}");
+        resp = Conversions.execute(transformation, value, deviceVariables);
+        assertNotNull(resp);
+        assertEquals(value, resp);
+
+        // test input as jsonString for non-existing element
+        value = JsonParser.parseString("{\"nottest\": \"testresponse\"}");
+        resp = Conversions.execute(transformation, value, deviceVariables);
+        assertNotNull(resp);
+        assertEquals(value, resp);
+    }
+}