]> git.basschouten.com Git - openhab-addons.git/commitdiff
[daikin] Add support for Alira X (#14108)
authorlsiepel <leosiepel@gmail.com>
Thu, 29 Dec 2022 17:41:17 +0000 (18:41 +0100)
committerGitHub <noreply@github.com>
Thu, 29 Dec 2022 17:41:17 +0000 (18:41 +0100)
* Add support for Alira X
* Fix checkstyle
* Move changes AirbaseControlInfo =>  ControlInfo
* Send seperated values conditionally

Signed-off-by: lsiepel <leosiepel@gmail.com>
bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/ControlInfo.java
bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/InfoParser.java
bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseControlInfo.java
bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseModelInfo.java
bundles/org.openhab.binding.daikin/src/test/java/org/openhab/binding/daikin/internal/api/ControlInfoTest.java [new file with mode: 0644]

index 629994ef7cb090b329415341e0a49af69951f82b..9dbc1f6c712031a2fe9a45bf4699528488ebee81 100644 (file)
@@ -46,6 +46,7 @@ public class ControlInfo {
     /* Not supported by all units. Sets the target humidity for dehumidifying. */
     public Optional<Integer> targetHumidity = Optional.empty();
     public AdvancedMode advancedMode = AdvancedMode.UNKNOWN;
+    public boolean separatedDirectionParams = false;
 
     private ControlInfo() {
     }
@@ -63,8 +64,22 @@ public class ControlInfo {
         info.temp = Optional.ofNullable(responseMap.get("stemp")).flatMap(value -> InfoParser.parseDouble(value));
         info.fanSpeed = Optional.ofNullable(responseMap.get("f_rate")).map(value -> FanSpeed.fromValue(value))
                 .orElse(FanSpeed.AUTO);
-        info.fanMovement = Optional.ofNullable(responseMap.get("f_dir")).flatMap(value -> InfoParser.parseInt(value))
-                .map(value -> FanMovement.fromValue(value)).orElse(FanMovement.STOPPED);
+        // determine if device has combined direction (f_dir) or separated directions (f_dir_ud/f_dir_lr)
+        if (response.contains("f_dir=")) {
+            info.fanMovement = Optional.ofNullable(responseMap.get("f_dir"))
+                    .flatMap(value -> InfoParser.parseInt(value)).map(value -> FanMovement.fromValue(value))
+                    .orElse(FanMovement.STOPPED);
+        } else {
+            info.separatedDirectionParams = true;
+            String ud = responseMap.get("f_dir_ud");
+            String lr = responseMap.get("f_dir_lr");
+            if (ud != null && lr != null) {
+                info.fanMovement = parseFanMovement(ud, lr);
+            } else {
+                info.fanMovement = FanMovement.UNKNOWN;
+            }
+        }
+
         info.targetHumidity = Optional.ofNullable(responseMap.get("shum")).flatMap(value -> InfoParser.parseInt(value));
 
         info.advancedMode = Optional.ofNullable(responseMap.get("adv")).map(value -> AdvancedMode.fromValue(value))
@@ -77,7 +92,16 @@ public class ControlInfo {
         params.put("pow", power ? "1" : "0");
         params.put("mode", Integer.toString(mode.getValue()));
         params.put("f_rate", fanSpeed.getValue());
-        params.put("f_dir", Integer.toString(fanMovement.getValue()));
+        if (separatedDirectionParams) {
+            params.put("f_dir_lr",
+                    fanMovement == FanMovement.VERTICAL || fanMovement == FanMovement.VERTICAL_AND_HORIZONTAL ? "S"
+                            : "0");
+            params.put("f_dir_ud",
+                    fanMovement == FanMovement.HORIZONTAL || fanMovement == FanMovement.VERTICAL_AND_HORIZONTAL ? "S"
+                            : "0");
+        } else {
+            params.put("f_dir", Integer.toString(fanMovement.getValue()));
+        }
         params.put("stemp", temp.orElse(20.0).toString());
         params.put("shum", targetHumidity.map(value -> value.toString()).orElse(""));
 
@@ -87,4 +111,21 @@ public class ControlInfo {
     public SpecialMode getSpecialMode() {
         return SpecialMode.fromAdvancedMode(advancedMode);
     }
+
+    /*
+     * This method combines different direction parameters to one.
+     * 
+     * @param ud up/ down value S or 0
+     * 
+     * @param lr left/ right value S or 0
+     * 
+     * @return combined value based on {@link FanMovement} enum
+     */
+    public static FanMovement parseFanMovement(String ud, String lr) {
+        if ("S".equals(ud)) {
+            return "S".equals(lr) ? FanMovement.VERTICAL_AND_HORIZONTAL : FanMovement.VERTICAL;
+        } else {
+            return "S".equals(lr) ? FanMovement.HORIZONTAL : FanMovement.STOPPED;
+        }
+    }
 }
index f8da25502e03621471dfcffa949af5101347aec8..59e04d1c8bec18798595aae402395e6a915821b2 100644 (file)
@@ -33,7 +33,7 @@ import org.slf4j.LoggerFactory;
  */
 @NonNullByDefault
 public class InfoParser {
-    private static final Logger logger = LoggerFactory.getLogger(InfoParser.class);
+    private static final Logger LOGGER = LoggerFactory.getLogger(InfoParser.class);
 
     private InfoParser() {
     }
@@ -92,7 +92,7 @@ public class InfoParser {
         try {
             return URLDecoder.decode(value, StandardCharsets.UTF_8.toString());
         } catch (UnsupportedEncodingException e) {
-            logger.warn("Unsupported encoding error in '{}'", value, e);
+            LOGGER.warn("Unsupported encoding error in '{}'", value, e);
             return value;
         }
     }
index 68f4484ffd0d1188986e9ad51c3e6ba6398429f9..4c740a140b6b5fe0b510bc69ab3715b635b3209f 100644 (file)
@@ -59,11 +59,11 @@ public class AirbaseControlInfo {
         info.mode = Optional.ofNullable(responseMap.get("mode")).flatMap(value -> InfoParser.parseInt(value))
                 .map(value -> AirbaseMode.fromValue(value)).orElse(AirbaseMode.AUTO);
         info.temp = Optional.ofNullable(responseMap.get("stemp")).flatMap(value -> InfoParser.parseDouble(value));
-        int f_rate = Optional.ofNullable(responseMap.get("f_rate")).flatMap(value -> InfoParser.parseInt(value))
+        int fRate = Optional.ofNullable(responseMap.get("f_rate")).flatMap(value -> InfoParser.parseInt(value))
                 .orElse(1);
-        boolean f_auto = "1".equals(responseMap.getOrDefault("f_auto", "0"));
-        boolean f_airside = "1".equals(responseMap.getOrDefault("f_airside", "0"));
-        info.fanSpeed = AirbaseFanSpeed.fromValue(f_rate, f_auto, f_airside);
+        boolean fAuto = "1".equals(responseMap.getOrDefault("f_auto", "0"));
+        boolean fAirside = "1".equals(responseMap.getOrDefault("f_airside", "0"));
+        info.fanSpeed = AirbaseFanSpeed.fromValue(fRate, fAuto, fAirside);
         info.fanMovement = Optional.ofNullable(responseMap.get("f_dir")).flatMap(value -> InfoParser.parseInt(value))
                 .map(value -> AirbaseFanMovement.fromValue(value)).orElse(AirbaseFanMovement.STOPPED);
         info.targetHumidity = Optional.ofNullable(responseMap.get("shum")).flatMap(value -> InfoParser.parseInt(value));
index 9c35be9ec151a9c6b9b0d6a2169eee6e3de45281..b08a4335c51ef84c9ab55d7bbce07cde9d6b73b1 100644 (file)
@@ -35,7 +35,7 @@ public class AirbaseModelInfo {
     public String ret = "";
     public int zonespresent;
     public int commonzone;
-    public int frate_steps; // fan rate steps
+    public int fRateSteps; // fan rate steps
     public EnumSet<AirbaseFeature> features;
 
     private AirbaseModelInfo() {
@@ -53,7 +53,7 @@ public class AirbaseModelInfo {
                 .orElse(0);
         info.commonzone = Optional.ofNullable(responseMap.get("en_common_zone"))
                 .flatMap(value -> InfoParser.parseInt(value)).orElse(0);
-        info.frate_steps = Optional.ofNullable(responseMap.get("frate_steps"))
+        info.fRateSteps = Optional.ofNullable(responseMap.get("frate_steps"))
                 .flatMap(value -> InfoParser.parseInt(value)).orElse(1);
         for (AirbaseFeature f : AirbaseFeature.values()) {
             if ("1".equals(responseMap.get(f.getValue()))) {
diff --git a/bundles/org.openhab.binding.daikin/src/test/java/org/openhab/binding/daikin/internal/api/ControlInfoTest.java b/bundles/org.openhab.binding.daikin/src/test/java/org/openhab/binding/daikin/internal/api/ControlInfoTest.java
new file mode 100644 (file)
index 0000000..e630d7e
--- /dev/null
@@ -0,0 +1,133 @@
+/**
+ * Copyright (c) 2010-2022 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.daikin.internal.api;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.IOException;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.daikin.internal.api.Enums.FanMovement;
+
+/**
+ * This class provides tests for deconz lights
+ *
+ * @author Leo Siepel - Initial contribution
+ *
+ */
+
+@NonNullByDefault
+public class ControlInfoTest {
+
+    @BeforeEach
+    public void initialize() {
+    }
+
+    @Test
+    public void separateUpAndDown() {
+        // arrange
+        String incomingMessage = "ret=OK,pow=0,mode=3,stemp=21.0,shum=0,adv=13,dt1=21.0,dt2=M,dt3=21.0,dt4=25.0,dh1=0,dh2=0,dh3=0,dh4=0,dhh=0,alert=16,f_rate=3,dfr1=A,dfr2=A,dfr3=3,dfr4=A,dfr6=A,dfrh=0,f_dir_ud=S,f_dir_lr=0,ndfd1=00,ndfd2=00,ndfd3=S0,ndfd4=00,ndfd6=00,ndfdh=00";
+
+        // act
+        ControlInfo info = ControlInfo.parse(incomingMessage);
+
+        // assert
+        assertEquals(FanMovement.VERTICAL, info.fanMovement);
+    }
+
+    @Test
+    public void separateLeftAndRightTest() {
+        // arrange
+        String incomingMessage = "ret=OK,pow=0,mode=3,stemp=21.0,shum=0,adv=13,dt1=21.0,dt2=M,dt3=21.0,dt4=25.0,dh1=0,dh2=0,dh3=0,dh4=0,dhh=0,alert=16,f_rate=3,dfr1=A,dfr2=A,dfr3=3,dfr4=A,dfr6=A,dfrh=0,f_dir_ud=0,f_dir_lr=S,ndfd1=00,ndfd2=00,ndfd3=0S,ndfd4=00,ndfd6=00,ndfdh=00";
+
+        // act
+        ControlInfo info = ControlInfo.parse(incomingMessage);
+
+        // assert
+        assertEquals(FanMovement.HORIZONTAL, info.fanMovement);
+    }
+
+    @Test
+    public void separateStoppedTest() {
+        // arrange
+        String incomingMessage = "ret=OK,pow=0,mode=3,stemp=21.0,shum=0,adv=13,dt1=21.0,dt2=M,dt3=21.0,dt4=25.0,dh1=0,dh2=0,dh3=0,dh4=0,dhh=0,alert=16,f_rate=3,dfr1=A,dfr2=A,dfr3=3,dfr4=A,dfr6=A,dfrh=0,f_dir_ud=0,f_dir_lr=0,ndfd1=00,ndfd2=00,ndfd3=00,ndfd4=00,ndfd6=00,ndfdh=00";
+
+        // act
+        ControlInfo info = ControlInfo.parse(incomingMessage);
+
+        // assert
+        assertEquals(FanMovement.STOPPED, info.fanMovement);
+    }
+
+    @Test
+    public void separateTwoDimensionalTest() {
+        // arrange
+        String incomingMessage = "ret=OK,pow=0,mode=3,stemp=21.0,shum=0,adv=13,dt1=21.0,dt2=M,dt3=21.0,dt4=25.0,dh1=0,dh2=0,dh3=0,dh4=0,dhh=0,alert=16,f_rate=3,dfr1=A,dfr2=A,dfr3=3,dfr4=A,dfr6=A,dfrh=0,f_dir_ud=S,f_dir_lr=S,ndfd1=00,ndfd2=00,ndfd3=SS,ndfd4=00,ndfd6=00,ndfdh=00";
+
+        // act
+        ControlInfo info = ControlInfo.parse(incomingMessage);
+
+        // assert
+        assertEquals(FanMovement.VERTICAL_AND_HORIZONTAL, info.fanMovement);
+    }
+
+    @Test
+    public void combinedUpAndDown() {
+        // arrange
+        String incomingMessage = "ret=OK,pow=0,mode=3,stemp=21.0,shum=0,adv=13,dt1=21.0,dt2=M,dt3=21.0,dt4=25.0,dh1=0,dh2=0,dh3=0,dh4=0,dhh=0,alert=16,f_rate=3,dfr1=A,dfr2=A,dfr3=3,dfr4=A,dfr6=A,dfrh=0,f_dir=1,ndfd1=00,ndfd2=00,ndfd3=S0,ndfd4=00,ndfd6=00,ndfdh=00";
+
+        // act
+        ControlInfo info = ControlInfo.parse(incomingMessage);
+
+        // assert
+        assertEquals(FanMovement.VERTICAL, info.fanMovement);
+    }
+
+    @Test
+    public void combinedLeftAndRightTest() throws IOException {
+        // arrange
+        String incomingMessage = "ret=OK,pow=0,mode=3,stemp=21.0,shum=0,adv=13,dt1=21.0,dt2=M,dt3=21.0,dt4=25.0,dh1=0,dh2=0,dh3=0,dh4=0,dhh=0,alert=16,f_rate=3,dfr1=A,dfr2=A,dfr3=3,dfr4=A,dfr6=A,dfrh=0,f_dir=2,ndfd1=00,ndfd2=00,ndfd3=0S,ndfd4=00,ndfd6=00,ndfdh=00";
+
+        // act
+        ControlInfo info = ControlInfo.parse(incomingMessage);
+
+        // assert
+        assertEquals(FanMovement.HORIZONTAL, info.fanMovement);
+    }
+
+    @Test
+    public void combinedStoppedTest() throws IOException {
+        // arrange
+        String incomingMessage = "ret=OK,pow=0,mode=3,stemp=21.0,shum=0,adv=13,dt1=21.0,dt2=M,dt3=21.0,dt4=25.0,dh1=0,dh2=0,dh3=0,dh4=0,dhh=0,alert=16,f_rate=3,dfr1=A,dfr2=A,dfr3=3,dfr4=A,dfr6=A,dfrh=0,f_dir=0,ndfd1=00,ndfd2=00,ndfd3=00,ndfd4=00,ndfd6=00,ndfdh=00";
+
+        // act
+        ControlInfo info = ControlInfo.parse(incomingMessage);
+
+        // assert
+        assertEquals(FanMovement.STOPPED, info.fanMovement);
+    }
+
+    @Test
+    public void combinedTwoDimensionalTest() throws IOException {
+        // arrange
+        String incomingMessage = "ret=OK,pow=0,mode=3,stemp=21.0,shum=0,adv=13,dt1=21.0,dt2=M,dt3=21.0,dt4=25.0,dh1=0,dh2=0,dh3=0,dh4=0,dhh=0,alert=16,f_rate=3,dfr1=A,dfr2=A,dfr3=3,dfr4=A,dfr6=A,dfrh=0,f_dir=3,ndfd1=00,ndfd2=00,ndfd3=SS,ndfd4=00,ndfd6=00,ndfdh=00";
+
+        // act
+        ControlInfo info = ControlInfo.parse(incomingMessage);
+
+        // assert
+        assertEquals(FanMovement.VERTICAL_AND_HORIZONTAL, info.fanMovement);
+    }
+}