]> git.basschouten.com Git - openhab-addons.git/commitdiff
[miio] Allow for quantity Type (#8756)
authorMarcel <marcelrv@users.noreply.github.com>
Mon, 9 Nov 2020 16:39:50 +0000 (17:39 +0100)
committerGitHub <noreply@github.com>
Mon, 9 Nov 2020 16:39:50 +0000 (08:39 -0800)
* [miio] Allow for quantity Type in the basic handler

This extends the miio:basic handler with the option to define channels
with QuantityType e.g. to use number:temperature

* [miio] add missing breaks

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/MiIoQuantiyTypes.java [new file with mode: 0644]
bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/MiIoBasicChannel.java
bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoBasicHandler.java
bundles/org.openhab.binding.miio/src/main/resources/OH-INF/thing/commonChannels.xml
bundles/org.openhab.binding.miio/src/main/resources/database/chuangmi.plug.v3fw.json
bundles/org.openhab.binding.miio/src/main/resources/database/zhimi.heater.za1.json

index fdcff1a3e78250b3c76d8c5421f30b92b567a138..ccb3ecb0c9eef9e018b15cf3945b64d135dbd8b9 100644 (file)
@@ -3122,13 +3122,13 @@ e.g. `smarthome:send actionCommand 'upd_timer["1498595904821", "on"]'` would ena
 | Channel          | Type    | Description                         | Comment    |
 |------------------|---------|-------------------------------------|------------|
 | power            | Switch  | Power                               |            |
-| target_temperature | Number  | Target Temperature                  |            |
+| target_temperature | Number:Temperature | Target Temperature                  |            |
 | brightness       | Number  | Brightness                          |            |
 | buzzer           | Switch  | Buzzer Status                       |            |
 | relative_humidity | Number  | Relative Humidity                   |            |
 | childlock        | Switch  | Child Lock                          |            |
 | HWSwitch         | Switch  | HW Switch                           |            |
-| temperature      | Number  | Temperature                         |            |
+| temperature      | Number:Temperature | Temperature                         |            |
 | usedhours        | Number  | Run Time                            |            |
 
 
@@ -6429,13 +6429,13 @@ note: Autogenerated example. Replace the id (heater) in the channel with your ow
 ```java
 Group G_heater "Zhimi Heater" <status>
 Switch power "Power" (G_heater) {channel="miio:basic:heater:power"}
-Number target_temperature "Target Temperature" (G_heater) {channel="miio:basic:heater:target_temperature"}
+Number:Temperature target_temperature "Target Temperature" (G_heater) {channel="miio:basic:heater:target_temperature"}
 Number brightness "Brightness" (G_heater) {channel="miio:basic:heater:brightness"}
 Switch buzzer "Buzzer Status" (G_heater) {channel="miio:basic:heater:buzzer"}
 Number relative_humidity "Relative Humidity" (G_heater) {channel="miio:basic:heater:relative_humidity"}
 Switch childlock "Child Lock" (G_heater) {channel="miio:basic:heater:childlock"}
 Switch HWSwitch "HW Switch" (G_heater) {channel="miio:basic:heater:HWSwitch"}
-Number temperature "Temperature" (G_heater) {channel="miio:basic:heater:temperature"}
+Number:Temperature temperature "Temperature" (G_heater) {channel="miio:basic:heater:temperature"}
 Number usedhours "Run Time" (G_heater) {channel="miio:basic:heater:usedhours"}
 ```
 
diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoQuantiyTypes.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoQuantiyTypes.java
new file mode 100644 (file)
index 0000000..303c62b
--- /dev/null
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2010-2020 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 java.util.Arrays;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import javax.measure.Unit;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.library.unit.ImperialUnits;
+import org.openhab.core.library.unit.SIUnits;
+import org.openhab.core.library.unit.SmartHomeUnits;
+
+/**
+ * Enum of the units used in the miio protocol
+ * Used to find the right {@link javax.measure.Unit} given the string of the unit
+ *
+ * @author Marcel Verpaalen - Initial contribution
+ */
+@NonNullByDefault
+public enum MiIoQuantiyTypes {
+
+    CELCIUS(SIUnits.CELSIUS),
+    FAHRENHEIT(ImperialUnits.FAHRENHEIT),
+    SECOND(SmartHomeUnits.SECOND),
+    MINUTE(SmartHomeUnits.MINUTE),
+    HOUR(SmartHomeUnits.HOUR),
+    AMPERE(SmartHomeUnits.AMPERE),
+    WATT(SmartHomeUnits.WATT);
+
+    private final Unit<?> unit;
+
+    private static Map<String, Unit<?>> stringMap = Arrays.stream(values())
+            .collect(Collectors.toMap(Enum::toString, MiIoQuantiyTypes::getUnit));
+
+    private MiIoQuantiyTypes(Unit<?> unit) {
+        this.unit = unit;
+    }
+
+    public Unit<?> getUnit() {
+        return unit;
+    }
+
+    public static @Nullable Unit<?> get(String unitName) {
+        return stringMap.get(unitName.toUpperCase());
+    }
+}
index 27b1bf52dae4ae7a47401aa12401362011abb9ec..89994ec66cf68e89b17c6338eac136803d396230 100644 (file)
@@ -53,6 +53,9 @@ public class MiIoBasicChannel {
     @SerializedName("type")
     @Expose
     private @Nullable String type;
+    @SerializedName("unit")
+    @Expose
+    private @Nullable String unit;
     @SerializedName("refresh")
     @Expose
     private @Nullable Boolean refresh;
@@ -155,6 +158,15 @@ public class MiIoBasicChannel {
         this.type = type;
     }
 
+    public String getUnit() {
+        final @Nullable String unit = this.unit;
+        return unit != null ? unit : "";
+    }
+
+    public void setUnit(String unit) {
+        this.unit = unit;
+    }
+
     public Boolean getRefresh() {
         final @Nullable Boolean rf = refresh;
         return rf != null && rf.booleanValue() && !getProperty().isEmpty();
index ee6422b33f20e219081944005cf59c58fc90b35d..63f1929da7f9df1d0f0e5ad1b9362474771c41b8 100644 (file)
@@ -23,11 +23,15 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
+import javax.measure.Unit;
+import javax.measure.format.ParserException;
+
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.miio.internal.MiIoBindingConfiguration;
 import org.openhab.binding.miio.internal.MiIoCommand;
 import org.openhab.binding.miio.internal.MiIoCryptoException;
+import org.openhab.binding.miio.internal.MiIoQuantiyTypes;
 import org.openhab.binding.miio.internal.MiIoSendCommand;
 import org.openhab.binding.miio.internal.Utils;
 import org.openhab.binding.miio.internal.basic.ActionConditions;
@@ -44,7 +48,10 @@ import org.openhab.core.library.types.DecimalType;
 import org.openhab.core.library.types.HSBType;
 import org.openhab.core.library.types.OnOffType;
 import org.openhab.core.library.types.PercentType;
+import org.openhab.core.library.types.QuantityType;
 import org.openhab.core.library.types.StringType;
+import org.openhab.core.library.unit.SIUnits;
+import org.openhab.core.library.unit.SmartHomeUnits;
 import org.openhab.core.thing.Channel;
 import org.openhab.core.thing.ChannelUID;
 import org.openhab.core.thing.Thing;
@@ -105,7 +112,8 @@ public class MiIoBasicHandler extends MiIoAbstractHandler {
     }
 
     @Override
-    public void handleCommand(ChannelUID channelUID, Command command) {
+    public void handleCommand(ChannelUID channelUID, Command receivedCommand) {
+        Command command = receivedCommand;
         if (command == RefreshType.REFRESH) {
             if (updateDataCache.isExpired()) {
                 logger.debug("Refreshing {}", channelUID);
@@ -119,7 +127,7 @@ public class MiIoBasicHandler extends MiIoAbstractHandler {
             cmds.put(sendCommand(command.toString()), command.toString());
             return;
         }
-        logger.debug("Locating action for channel '{}': '{}'", channelUID.getId(), command);
+        logger.debug("Locating action for {} channel '{}': '{}'", getThing().getUID(), channelUID.getId(), command);
         if (!actions.isEmpty()) {
             if (actions.containsKey(channelUID)) {
                 int valuePos = 0;
@@ -137,6 +145,25 @@ public class MiIoBasicHandler extends MiIoAbstractHandler {
                     }
                     String cmd = action.getCommand();
                     CommandParameterType paramType = action.getparameterType();
+                    if (command instanceof QuantityType) {
+                        QuantityType<?> qtc = null;
+                        try {
+                            if (!miIoBasicChannel.getUnit().isBlank()) {
+                                Unit<?> unit = MiIoQuantiyTypes.get(miIoBasicChannel.getUnit());
+                                if (unit != null) {
+                                    qtc = ((QuantityType<?>) command).toUnit(unit);
+                                }
+                            }
+                        } catch (ParserException e) {
+                            // swallow
+                        }
+                        if (qtc != null) {
+                            command = new DecimalType(qtc.toBigDecimal());
+                        } else {
+                            logger.debug("Could not convert QuantityType to '{}'", miIoBasicChannel.getUnit());
+                            command = new DecimalType(((QuantityType<?>) command).toBigDecimal());
+                        }
+                    }
                     if (paramType == CommandParameterType.COLOR) {
                         if (command instanceof HSBType) {
                             HSBType hsb = (HSBType) command;
@@ -505,9 +532,10 @@ public class MiIoBasicHandler extends MiIoAbstractHandler {
             val = transformed;
         }
         try {
-            switch (basicChannel.getType().toLowerCase()) {
+            String[] chType = basicChannel.getType().toLowerCase().split(":");
+            switch (chType[0]) {
                 case "number":
-                    updateState(basicChannel.getChannel(), new DecimalType(val.getAsBigDecimal()));
+                    quantityTypeUpdate(basicChannel, val, chType.length > 1 ? chType[1] : "");
                     break;
                 case "dimmer":
                     updateState(basicChannel.getChannel(), new PercentType(val.getAsBigDecimal()));
@@ -534,6 +562,39 @@ public class MiIoBasicHandler extends MiIoAbstractHandler {
         }
     }
 
+    private void quantityTypeUpdate(MiIoBasicChannel basicChannel, JsonElement val, String type) {
+        if (!basicChannel.getUnit().isBlank()) {
+            Unit<?> unit = MiIoQuantiyTypes.get(basicChannel.getUnit());
+            if (unit != null) {
+                logger.debug("'{}' channel '{}' has unit '{}' with symbol '{}'.", getThing().getUID(),
+                        basicChannel.getChannel(), basicChannel.getUnit(), unit);
+                updateState(basicChannel.getChannel(), new QuantityType<>(val.getAsBigDecimal(), unit));
+            } else {
+                logger.debug("Unit '{}' used by '{}' channel '{}' is not found.. using default unit.",
+                        getThing().getUID(), basicChannel.getUnit(), basicChannel.getChannel());
+            }
+        }
+        // if no unit is provided or unit not found use default units, these units have so far been seen for miio
+        // devices
+        switch (type.toLowerCase()) {
+            case "temperature":
+                updateState(basicChannel.getChannel(), new QuantityType<>(val.getAsBigDecimal(), SIUnits.CELSIUS));
+                break;
+            case "electriccurrent":
+                updateState(basicChannel.getChannel(),
+                        new QuantityType<>(val.getAsBigDecimal(), SmartHomeUnits.AMPERE));
+                break;
+            case "energy":
+                updateState(basicChannel.getChannel(), new QuantityType<>(val.getAsBigDecimal(), SmartHomeUnits.WATT));
+                break;
+            case "time":
+                updateState(basicChannel.getChannel(), new QuantityType<>(val.getAsBigDecimal(), SmartHomeUnits.HOUR));
+                break;
+            default:
+                updateState(basicChannel.getChannel(), new DecimalType(val.getAsBigDecimal()));
+        }
+    }
+
     @Override
     public void onMessageReceived(MiIoSendCommand response) {
         super.onMessageReceived(response);
index 8a8ce289b5b4db1274a1782978b1824fb50addcf..27cbfcbbb55cd58fdd5d95437d56eaf12f7404de 100644 (file)
                <label>Temperature</label>
                <state pattern="%.1f" readOnly="true"/>
        </channel-type>
+       <channel-type id="temperatureC">
+               <item-type>Number:Temperature</item-type>
+               <label>Temperature</label>
+               <state readOnly="true" pattern="%.1f %unit%"/>
+       </channel-type>
        <channel-type id="humidity">
                <item-type>Number</item-type>
                <label>Humidity</label>
index c3e5f63084655a154d928c644b108db9c623574d..3db10fc8ca0fefb6264bce1028a6af83e20def64 100644 (file)
@@ -42,8 +42,9 @@
                                "property": "temperature",
                                "friendlyName": "Temperature",
                                "channel": "temperature",
-                               "channelType": "temperature",
-                               "type": "Number",
+                               "channelType": "temperatureC",
+                               "unit": "CELCIUS",
+                               "type": "Number:Temperature",
                                "refresh": true,
                                "ChannelGroup": "",
                                "actions": []
index fb20b97dafd070a6929f89d56195d519c3befd6b..a37fb2e727f165043b34d7a18a6dcdafe0132aaa 100644 (file)
@@ -24,7 +24,8 @@
                                "property": "target_temperature",
                                "friendlyName": "Target Temperature",
                                "channel": "target_temperature",
-                               "type": "Number",
+                               "type": "Number:Temperature",
+                               "channelType": "temperatureC",
                                "refresh": true,
                                "actions": [
                                        {
                                "property": "temperature",
                                "friendlyName": "Temperature",
                                "channel": "temperature",
-                               "channelType": "temperature",
-                               "type": "Number",
+                               "channelType": "temperatureC",
+                               "type": "Number:Temperature",
                                "refresh": true,
                                "actions": []
                        },