]> git.basschouten.com Git - openhab-addons.git/commitdiff
[daikin] Update channels immediately after a successful API command (#17149)
authorjimtng <2554958+jimtng@users.noreply.github.com>
Wed, 28 Aug 2024 09:43:16 +0000 (19:43 +1000)
committerGitHub <noreply@github.com>
Wed, 28 Aug 2024 09:43:16 +0000 (11:43 +0200)
* [daikin] Update channels immediately after a successful API command

Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinWebTargets.java
bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/Enums.java
bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAcUnitHandler.java
bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAirbaseUnitHandler.java
bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinBaseHandler.java
bundles/org.openhab.binding.daikin/src/main/resources/OH-INF/thing/thing-types.xml

index 9228d538e8064afdc80116dcb07e238d40927ecc..31f4c761e5d6b473f33cf6a980c4be3bac1ad8df 100644 (file)
@@ -15,7 +15,6 @@ package org.openhab.binding.daikin.internal;
 import java.io.EOFException;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Optional;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
@@ -33,7 +32,6 @@ import org.openhab.binding.daikin.internal.api.DemandControl;
 import org.openhab.binding.daikin.internal.api.EnergyInfoDayAndWeek;
 import org.openhab.binding.daikin.internal.api.EnergyInfoYear;
 import org.openhab.binding.daikin.internal.api.Enums.SpecialMode;
-import org.openhab.binding.daikin.internal.api.InfoParser;
 import org.openhab.binding.daikin.internal.api.SensorInfo;
 import org.openhab.binding.daikin.internal.api.airbase.AirbaseBasicInfo;
 import org.openhab.binding.daikin.internal.api.airbase.AirbaseControlInfo;
@@ -119,9 +117,7 @@ public class DaikinWebTargets {
 
     public boolean setControlInfo(ControlInfo info) throws DaikinCommunicationException {
         Map<String, String> queryParams = info.getParamString();
-        String result = invoke(setControlInfoUri, queryParams);
-        Map<String, String> responseMap = InfoParser.parse(result);
-        return Optional.ofNullable(responseMap.get("ret")).orElse("").equals("OK");
+        return isSuccessful(invoke(setControlInfoUri, queryParams));
     }
 
     public SensorInfo getSensorInfo() throws DaikinCommunicationException {
@@ -146,7 +142,7 @@ public class DaikinWebTargets {
         return EnergyInfoDayAndWeek.parse(response);
     }
 
-    public void setSpecialMode(SpecialMode newMode) throws DaikinCommunicationException {
+    public boolean setSpecialMode(SpecialMode newMode) throws DaikinCommunicationException {
         Map<String, String> queryParams = new HashMap<>();
         if (newMode == SpecialMode.NORMAL) {
             queryParams.put("set_spmode", "0");
@@ -160,17 +156,23 @@ public class DaikinWebTargets {
             queryParams.put("spmode_kind", newMode.getValue());
         }
         String response = invoke(setSpecialModeUri, queryParams);
-        if (!response.contains("ret=OK")) {
+        if (isSuccessful(response)) {
+            return true;
+        } else {
             logger.warn("Error setting special mode. Response: '{}'", response);
+            return false;
         }
     }
 
-    public void setStreamerMode(boolean state) throws DaikinCommunicationException {
+    public boolean setStreamerMode(boolean state) throws DaikinCommunicationException {
         Map<String, String> queryParams = new HashMap<>();
         queryParams.put("en_streamer", state ? "1" : "0");
         String response = invoke(setSpecialModeUri, queryParams);
-        if (!response.contains("ret=OK")) {
+        if (isSuccessful(response)) {
+            return true;
+        } else {
             logger.warn("Error setting streamer mode. Response: '{}'", response);
+            return false;
         }
     }
 
@@ -181,9 +183,7 @@ public class DaikinWebTargets {
 
     public boolean setDemandControl(DemandControl info) throws DaikinCommunicationException {
         Map<String, String> queryParams = info.getParamString();
-        String result = invoke(setDemandControlUri, queryParams);
-        Map<String, String> responseMap = InfoParser.parse(result);
-        return Optional.ofNullable(responseMap.get("ret")).orElse("").equals("OK");
+        return isSuccessful(invoke(setDemandControlUri, queryParams));
     }
 
     // Daikin Airbase API
@@ -192,9 +192,9 @@ public class DaikinWebTargets {
         return AirbaseControlInfo.parse(response);
     }
 
-    public void setAirbaseControlInfo(AirbaseControlInfo info) throws DaikinCommunicationException {
+    public boolean setAirbaseControlInfo(AirbaseControlInfo info) throws DaikinCommunicationException {
         Map<String, String> queryParams = info.getParamString();
-        invoke(setAirbaseControlInfoUri, queryParams);
+        return isSuccessful(invoke(setAirbaseControlInfoUri, queryParams));
     }
 
     public SensorInfo getAirbaseSensorInfo() throws DaikinCommunicationException {
@@ -217,9 +217,13 @@ public class DaikinWebTargets {
         return AirbaseZoneInfo.parse(response);
     }
 
-    public void setAirbaseZoneInfo(AirbaseZoneInfo zoneinfo) throws DaikinCommunicationException {
+    public boolean setAirbaseZoneInfo(AirbaseZoneInfo zoneinfo) throws DaikinCommunicationException {
         Map<String, String> queryParams = zoneinfo.getParamString();
-        invoke(setAirbaseZoneInfoUri, queryParams);
+        return isSuccessful(invoke(setAirbaseZoneInfoUri, queryParams));
+    }
+
+    private boolean isSuccessful(String response) {
+        return response.contains("ret=OK");
     }
 
     private String invoke(String uri) throws DaikinCommunicationException {
index 3b1918bc80dca9869667dfcd1c38ff9d53d28bcb..1f7ffcf72f84c66f5dd73378c1f600ae4b8eb55f 100644 (file)
@@ -129,7 +129,6 @@ public class Enums {
         HEAT("heat"),
         OFF("off");
 
-        private static final Logger LOGGER = LoggerFactory.getLogger(HomekitMode.class);
         private final String value;
 
         HomekitMode(String value) {
index 3b34ad5642649cdb9c9dad5b6dbab64b817006ef..e2eecfab09e8682efd014e0249af588609e7935e 100644 (file)
@@ -192,19 +192,25 @@ public class DaikinAcUnitHandler extends DaikinBaseHandler {
         switch (channelUID.getId()) {
             case DaikinBindingConstants.CHANNEL_AC_FAN_DIR:
                 if (command instanceof StringType stringCommand) {
-                    changeFanDir(stringCommand.toString());
+                    if (changeFanDir(stringCommand.toString())) {
+                        updateState(channelUID, stringCommand);
+                    }
                     return true;
                 }
                 break;
             case DaikinBindingConstants.CHANNEL_AC_SPECIALMODE:
                 if (command instanceof StringType stringCommand) {
-                    changeSpecialMode(stringCommand.toString());
+                    if (changeSpecialMode(stringCommand.toString())) {
+                        updateState(channelUID, stringCommand);
+                    }
                     return true;
                 }
                 break;
             case DaikinBindingConstants.CHANNEL_AC_STREAMER:
                 if (command instanceof OnOffType onOffCommand) {
-                    changeStreamer(onOffCommand.equals(OnOffType.ON));
+                    if (changeStreamer(onOffCommand.equals(OnOffType.ON))) {
+                        updateState(channelUID, onOffCommand);
+                    }
                     return true;
                 }
                 break;
@@ -216,13 +222,21 @@ public class DaikinAcUnitHandler extends DaikinBaseHandler {
                 break;
             case DaikinBindingConstants.CHANNEL_AC_DEMAND_MAX_POWER:
                 if (command instanceof PercentType percentCommand) {
-                    changeDemandMaxPower(percentCommand.intValue());
+                    if (changeDemandMaxPower(percentCommand.intValue())) {
+                        updateState(DaikinBindingConstants.CHANNEL_AC_DEMAND_MODE,
+                                new StringType(DemandControlMode.MANUAL.name()));
+                        updateState(channelUID, percentCommand);
+                    }
                     return true;
                 }
                 break;
             case DaikinBindingConstants.CHANNEL_AC_DEMAND_SCHEDULE:
                 if (command instanceof StringType stringCommand) {
-                    changeDemandSchedule(stringCommand.toString());
+                    if (changeDemandSchedule(stringCommand.toString())) {
+                        updateState(DaikinBindingConstants.CHANNEL_AC_DEMAND_MODE,
+                                new StringType(DemandControlMode.SCHEDULED.name()));
+                        updateState(channelUID, stringCommand);
+                    }
                     return true;
                 }
                 break;
@@ -231,27 +245,27 @@ public class DaikinAcUnitHandler extends DaikinBaseHandler {
     }
 
     @Override
-    protected void changePower(boolean power) throws DaikinCommunicationException {
+    protected boolean changePower(boolean power) throws DaikinCommunicationException {
         ControlInfo info = webTargets.getControlInfo();
         info.power = power;
-        webTargets.setControlInfo(info);
+        return webTargets.setControlInfo(info);
     }
 
     @Override
-    protected void changeSetPoint(double newTemperature) throws DaikinCommunicationException {
+    protected boolean changeSetPoint(double newTemperature) throws DaikinCommunicationException {
         ControlInfo info = webTargets.getControlInfo();
         info.temp = Optional.of(newTemperature);
-        webTargets.setControlInfo(info);
+        return webTargets.setControlInfo(info);
     }
 
     @Override
-    protected void changeMode(String mode) throws DaikinCommunicationException {
+    protected boolean changeMode(String mode) throws DaikinCommunicationException {
         Mode newMode;
         try {
             newMode = Mode.valueOf(mode);
         } catch (IllegalArgumentException ex) {
             logger.warn("Invalid mode: {}. Valid values: {}", mode, Mode.values());
-            return;
+            return false;
         }
         ControlInfo info = webTargets.getControlInfo();
         info.mode = newMode;
@@ -263,55 +277,58 @@ public class DaikinAcUnitHandler extends DaikinBaseHandler {
         // If mode=0 is not accepted try AUTO1 (mode=1)
         if (!accepted && newMode == Mode.AUTO && autoModeValue.isEmpty()) {
             info.autoModeValue = Mode.AUTO1.getValue();
-            if (webTargets.setControlInfo(info)) {
+            accepted = webTargets.setControlInfo(info);
+            if (accepted) {
                 autoModeValue = Optional.of(info.autoModeValue);
                 logger.debug("AUTO uses mode={}", info.autoModeValue);
             } else {
                 logger.warn("AUTO mode not accepted with mode=0 or mode=1");
             }
         }
+
+        return accepted;
     }
 
     @Override
-    protected void changeFanSpeed(String fanSpeed) throws DaikinCommunicationException {
+    protected boolean changeFanSpeed(String fanSpeed) throws DaikinCommunicationException {
         FanSpeed newSpeed;
         try {
             newSpeed = FanSpeed.valueOf(fanSpeed);
         } catch (IllegalArgumentException ex) {
             logger.warn("Invalid fan speed: {}. Valid values: {}", fanSpeed, FanSpeed.values());
-            return;
+            return false;
         }
         ControlInfo info = webTargets.getControlInfo();
         info.fanSpeed = newSpeed;
-        webTargets.setControlInfo(info);
+        return webTargets.setControlInfo(info);
     }
 
-    protected void changeFanDir(String fanDir) throws DaikinCommunicationException {
+    protected boolean changeFanDir(String fanDir) throws DaikinCommunicationException {
         FanMovement newMovement;
         try {
             newMovement = FanMovement.valueOf(fanDir);
         } catch (IllegalArgumentException ex) {
             logger.warn("Invalid fan direction: {}. Valid values: {}", fanDir, FanMovement.values());
-            return;
+            return false;
         }
         ControlInfo info = webTargets.getControlInfo();
         info.fanMovement = newMovement;
-        webTargets.setControlInfo(info);
+        return webTargets.setControlInfo(info);
     }
 
-    protected void changeSpecialMode(String specialMode) throws DaikinCommunicationException {
+    protected boolean changeSpecialMode(String specialMode) throws DaikinCommunicationException {
         SpecialMode newMode;
         try {
             newMode = SpecialMode.valueOf(specialMode);
         } catch (IllegalArgumentException e) {
             logger.warn("Invalid specialmode: {}. Valid values: {}", specialMode, SpecialMode.values());
-            return;
+            return false;
         }
-        webTargets.setSpecialMode(newMode);
+        return webTargets.setSpecialMode(newMode);
     }
 
-    protected void changeStreamer(boolean streamerMode) throws DaikinCommunicationException {
-        webTargets.setStreamerMode(streamerMode);
+    protected boolean changeStreamer(boolean streamerMode) throws DaikinCommunicationException {
+        return webTargets.setStreamerMode(streamerMode);
     }
 
     protected void changeDemandMode(String mode) throws DaikinCommunicationException {
@@ -323,40 +340,54 @@ public class DaikinAcUnitHandler extends DaikinBaseHandler {
             return;
         }
         DemandControl demandInfo = webTargets.getDemandControl();
+        boolean scheduleChanged = false;
+        boolean maxPowerChanged = false;
         if (demandInfo.mode != newMode) {
             if (newMode == DemandControlMode.SCHEDULED && savedDemandControlSchedule.isPresent()) {
                 // restore previously saved schedule
                 demandInfo.setSchedule(savedDemandControlSchedule.get());
+                scheduleChanged = true;
             }
 
             if (newMode == DemandControlMode.MANUAL && savedDemandControlMaxPower.isPresent()) {
                 // restore previously saved maxPower
                 demandInfo.maxPower = savedDemandControlMaxPower.get();
+                maxPowerChanged = true;
             }
         }
         demandInfo.mode = newMode;
-        webTargets.setDemandControl(demandInfo);
+        if (webTargets.setDemandControl(demandInfo)) {
+            updateState(DaikinBindingConstants.CHANNEL_AC_DEMAND_MODE, new StringType(newMode.name()));
+            if (scheduleChanged) {
+                updateState(DaikinBindingConstants.CHANNEL_AC_DEMAND_SCHEDULE,
+                        new StringType(savedDemandControlSchedule.get()));
+            }
+            if (maxPowerChanged) {
+                updateState(DaikinBindingConstants.CHANNEL_AC_DEMAND_MAX_POWER,
+                        new PercentType(savedDemandControlMaxPower.get()));
+            }
+        }
     }
 
-    protected void changeDemandMaxPower(int maxPower) throws DaikinCommunicationException {
+    protected boolean changeDemandMaxPower(int maxPower) throws DaikinCommunicationException {
         DemandControl demandInfo = webTargets.getDemandControl();
         demandInfo.mode = DemandControlMode.MANUAL;
         demandInfo.maxPower = maxPower;
-        webTargets.setDemandControl(demandInfo);
         savedDemandControlMaxPower = Optional.of(maxPower);
+        return webTargets.setDemandControl(demandInfo);
     }
 
-    protected void changeDemandSchedule(String schedule) throws DaikinCommunicationException {
+    protected boolean changeDemandSchedule(String schedule) throws DaikinCommunicationException {
         DemandControl demandInfo = webTargets.getDemandControl();
         try {
             demandInfo.setSchedule(schedule);
         } catch (JsonSyntaxException e) {
             logger.warn("Invalid schedule: {}. {}", schedule, e.getMessage());
-            return;
+            return false;
         }
         demandInfo.mode = DemandControlMode.SCHEDULED;
-        webTargets.setDemandControl(demandInfo);
         savedDemandControlSchedule = Optional.of(demandInfo.getSchedule());
+        return webTargets.setDemandControl(demandInfo);
     }
 
     /**
index 62601846b05fad0ae6a535e31a8d78d600b6f771..4d15e95ef0c299b1007469af797c2f595b5252ee 100644 (file)
@@ -64,8 +64,10 @@ public class DaikinAirbaseUnitHandler extends DaikinBaseHandler {
             throws DaikinCommunicationException {
         if (channelUID.getId().startsWith(DaikinBindingConstants.CHANNEL_AIRBASE_AC_ZONE)) {
             int zoneNumber = Integer.parseInt(channelUID.getId().substring(4));
-            if (command instanceof OnOffType) {
-                changeZone(zoneNumber, command == OnOffType.ON);
+            if (command instanceof OnOffType onOffCommand) {
+                if (changeZone(zoneNumber, onOffCommand == OnOffType.ON)) {
+                    updateState(channelUID, onOffCommand);
+                }
                 return true;
             }
         }
@@ -110,63 +112,63 @@ public class DaikinAirbaseUnitHandler extends DaikinBaseHandler {
     }
 
     @Override
-    protected void changePower(boolean power) throws DaikinCommunicationException {
+    protected boolean changePower(boolean power) throws DaikinCommunicationException {
         AirbaseControlInfo info = webTargets.getAirbaseControlInfo();
         info.power = power;
-        webTargets.setAirbaseControlInfo(info);
+        return webTargets.setAirbaseControlInfo(info);
     }
 
     @Override
-    protected void changeSetPoint(double newTemperature) throws DaikinCommunicationException {
+    protected boolean changeSetPoint(double newTemperature) throws DaikinCommunicationException {
         AirbaseControlInfo info = webTargets.getAirbaseControlInfo();
         info.temp = Optional.of(newTemperature);
-        webTargets.setAirbaseControlInfo(info);
+        return webTargets.setAirbaseControlInfo(info);
     }
 
     @Override
-    protected void changeMode(String mode) throws DaikinCommunicationException {
+    protected boolean changeMode(String mode) throws DaikinCommunicationException {
         AirbaseMode newMode;
         try {
             newMode = AirbaseMode.valueOf(mode);
         } catch (IllegalArgumentException ex) {
             logger.warn("Invalid mode: {}. Valid values: {}", mode, AirbaseMode.values());
-            return;
+            return false;
         }
         if (airbaseModelInfo != null) {
             if ((newMode == AirbaseMode.AUTO && !airbaseModelInfo.features.contains(AirbaseFeature.AUTO))
                     || (newMode == AirbaseMode.DRY && !airbaseModelInfo.features.contains(AirbaseFeature.DRY))) {
                 logger.warn("{} mode is not supported by your controller", mode);
-                return;
+                return false;
             }
         }
         AirbaseControlInfo info = webTargets.getAirbaseControlInfo();
         info.mode = newMode;
-        webTargets.setAirbaseControlInfo(info);
+        return webTargets.setAirbaseControlInfo(info);
     }
 
     @Override
-    protected void changeFanSpeed(String speed) throws DaikinCommunicationException {
+    protected boolean changeFanSpeed(String speed) throws DaikinCommunicationException {
         AirbaseFanSpeed newFanSpeed;
         try {
             newFanSpeed = AirbaseFanSpeed.valueOf(speed);
         } catch (IllegalArgumentException ex) {
             logger.warn("Invalid fan speed: {}. Valid values: {}", speed, AirbaseFanSpeed.values());
-            return;
+            return false;
         }
         if (airbaseModelInfo != null) {
             if (EnumSet.range(AirbaseFanSpeed.AUTO_LEVEL_1, AirbaseFanSpeed.AUTO_LEVEL_5).contains(newFanSpeed)
                     && !airbaseModelInfo.features.contains(AirbaseFeature.FRATE_AUTO)) {
                 logger.warn("Fan AUTO_LEVEL_X is not supported by your controller");
-                return;
+                return false;
             }
             if (newFanSpeed == AirbaseFanSpeed.AIRSIDE && !airbaseModelInfo.features.contains(AirbaseFeature.AIRSIDE)) {
                 logger.warn("Airside is not supported by your controller");
-                return;
+                return false;
             }
         }
         AirbaseControlInfo info = webTargets.getAirbaseControlInfo();
         info.fanSpeed = newFanSpeed;
-        webTargets.setAirbaseControlInfo(info);
+        return webTargets.setAirbaseControlInfo(info);
     }
 
     /**
@@ -178,7 +180,7 @@ public class DaikinAirbaseUnitHandler extends DaikinBaseHandler {
      * @param command true to turn on the zone, false to turn it off
      * 
      */
-    protected void changeZone(int zone, boolean command) throws DaikinCommunicationException {
+    protected boolean changeZone(int zone, boolean command) throws DaikinCommunicationException {
         AirbaseZoneInfo zoneInfo = webTargets.getAirbaseZoneInfo();
         long maxZones = zoneInfo.zone.length;
 
@@ -188,11 +190,11 @@ public class DaikinAirbaseUnitHandler extends DaikinBaseHandler {
         if (zone <= 0 || zone > maxZones) {
             logger.warn("The given zone number ({}) is outside the number of zones supported by the controller ({})",
                     zone, maxZones);
-            return;
+            return false;
         }
 
         zoneInfo.zone[zone - 1] = command;
-        webTargets.setAirbaseZoneInfo(zoneInfo);
+        return webTargets.setAirbaseZoneInfo(zoneInfo);
     }
 
     @Override
index a427459337e3575dc4450f2af49f74f3809a17f6..ef2976131c353c5b5a0a9a7d82038ae2df530142 100644 (file)
@@ -70,13 +70,13 @@ public abstract class DaikinBaseHandler extends BaseThingHandler {
     // Abstract methods to be overridden by specific Daikin implementation class
     protected abstract void pollStatus() throws DaikinCommunicationException;
 
-    protected abstract void changePower(boolean power) throws DaikinCommunicationException;
+    protected abstract boolean changePower(boolean power) throws DaikinCommunicationException;
 
-    protected abstract void changeSetPoint(double newTemperature) throws DaikinCommunicationException;
+    protected abstract boolean changeSetPoint(double newTemperature) throws DaikinCommunicationException;
 
-    protected abstract void changeMode(String mode) throws DaikinCommunicationException;
+    protected abstract boolean changeMode(String mode) throws DaikinCommunicationException;
 
-    protected abstract void changeFanSpeed(String fanSpeed) throws DaikinCommunicationException;
+    protected abstract boolean changeFanSpeed(String fanSpeed) throws DaikinCommunicationException;
 
     // Power, Temp, Fan and Mode are handled in this base class. Override this to handle additional channels.
     protected abstract boolean handleCommandInternal(ChannelUID channelUID, Command command)
@@ -104,31 +104,54 @@ public abstract class DaikinBaseHandler extends BaseThingHandler {
             switch (channelUID.getId()) {
                 case DaikinBindingConstants.CHANNEL_AC_POWER:
                     if (command instanceof OnOffType onOffCommand) {
-                        changePower(onOffCommand.equals(OnOffType.ON));
+                        if (changePower(onOffCommand.equals(OnOffType.ON))) {
+                            updateState(channelUID, onOffCommand);
+                        }
                         return;
                     }
                     break;
                 case DaikinBindingConstants.CHANNEL_AC_TEMP:
-                    if (changeSetPoint(command)) {
-                        return;
+                    double newTemperature;
+                    State newState = UnDefType.UNDEF;
+                    if (command instanceof DecimalType decimalCommand) {
+                        newTemperature = decimalCommand.doubleValue();
+                        newState = decimalCommand;
+                    } else if (command instanceof QuantityType) {
+                        QuantityType<Temperature> quantityCommand = (QuantityType<Temperature>) command;
+                        newTemperature = quantityCommand.toUnit(SIUnits.CELSIUS).doubleValue();
+                        newState = quantityCommand;
+                    } else {
+                        break; // Exit switch statement but proceed to log about unsupported command type
                     }
-                    break;
+
+                    // Only half degree increments are allowed, all others are silently rejected by the A/C units
+                    newTemperature = Math.round(newTemperature * 2) / 2.0;
+                    if (changeSetPoint(newTemperature)) {
+                        updateState(channelUID, newState);
+                    }
+                    return; // return here and don't log about wrong type below
                 case DaikinBindingConstants.CHANNEL_AIRBASE_AC_FAN_SPEED:
                 case DaikinBindingConstants.CHANNEL_AC_FAN_SPEED:
                     if (command instanceof StringType stringCommand) {
-                        changeFanSpeed(stringCommand.toString());
+                        if (changeFanSpeed(stringCommand.toString())) {
+                            updateState(channelUID, stringCommand);
+                        }
                         return;
                     }
                     break;
                 case DaikinBindingConstants.CHANNEL_AC_HOMEKITMODE:
-                    if (command instanceof StringType) {
-                        changeHomekitMode(command.toString());
+                    if (command instanceof StringType stringCommand) {
+                        if (changeHomekitMode(stringCommand.toString())) {
+                            updateState(DaikinBindingConstants.CHANNEL_AC_HOMEKITMODE, stringCommand);
+                        }
                         return;
                     }
                     break;
                 case DaikinBindingConstants.CHANNEL_AC_MODE:
                     if (command instanceof StringType stringCommand) {
-                        changeMode(stringCommand.toString());
+                        if (changeMode(stringCommand.toString())) {
+                            updateState(channelUID, stringCommand);
+                        }
                         return;
                     }
                     break;
@@ -210,37 +233,37 @@ public abstract class DaikinBaseHandler extends BaseThingHandler {
                 maybeTemperature.<State> map(t -> new QuantityType<>(t, SIUnits.CELSIUS)).orElse(UnDefType.UNDEF)));
     }
 
-    /**
-     * @return true if the command was of an expected type, false otherwise
-     */
-    private boolean changeSetPoint(Command command) throws DaikinCommunicationException {
-        double newTemperature;
-        if (command instanceof DecimalType decimalCommand) {
-            newTemperature = decimalCommand.doubleValue();
-        } else if (command instanceof QuantityType) {
-            newTemperature = ((QuantityType<Temperature>) command).toUnit(SIUnits.CELSIUS).doubleValue();
-        } else {
-            return false;
-        }
+    private boolean changeHomekitMode(String homekitmode) throws DaikinCommunicationException {
+        try {
+            HomekitMode mode = HomekitMode.valueOf(homekitmode.toUpperCase());
+            boolean power = mode != HomekitMode.OFF;
+            if (!changePower(power)) {
+                return false;
+            }
 
-        // Only half degree increments are allowed, all others are silently rejected by the A/C units
-        newTemperature = Math.round(newTemperature * 2) / 2.0;
-        changeSetPoint(newTemperature);
-        return true;
-    }
+            boolean changeModeSuccess = false;
+            updateState(DaikinBindingConstants.CHANNEL_AC_POWER, OnOffType.from(power));
 
-    private void changeHomekitMode(String homekitmode) throws DaikinCommunicationException {
-        if (HomekitMode.OFF.getValue().equals(homekitmode)) {
-            changePower(false);
-        } else {
-            changePower(true);
-            if (HomekitMode.AUTO.getValue().equals(homekitmode)) {
-                changeMode("AUTO");
-            } else if (HomekitMode.HEAT.getValue().equals(homekitmode)) {
-                changeMode("HEAT");
-            } else if (HomekitMode.COOL.getValue().equals(homekitmode)) {
-                changeMode("COLD");
+            String newMode = switch (mode) {
+                case AUTO -> "AUTO";
+                case HEAT -> "HEAT";
+                case COOL -> "COLD";
+                case OFF -> null;
+            };
+
+            if (newMode == null) {
+                return true;
             }
+
+            if (changeMode(newMode)) {
+                updateState(DaikinBindingConstants.CHANNEL_AC_MODE, new StringType(newMode));
+                return true;
+            }
+
+            return false;
+        } catch (IllegalArgumentException e) {
+            logger.warn("Invalid homekit mode: {}", homekitmode);
+            return false;
         }
     }
 }
index 64f1a37570d11caec1345478016d5c03df094dcb..e32d96656b120f7fba94dab0366f2e7d220b019f 100644 (file)
@@ -94,6 +94,7 @@
                <label>Power</label>
                <description>Power for the AC unit</description>
                <category>Switch</category>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
        <channel-type id="acunit-settemp">
                <description>The set point temperature</description>
                <category>Temperature</category>
                <state pattern="%.1f %unit%" step="0.5"/>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
        <channel-type id="acunit-indoortemp">
                                <option value="FAN">fan</option>
                        </options>
                </state>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
        <channel-type id="acunit-homekitmode">
                                <option value="off">Off</option>
                        </options>
                </state>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
        <channel-type id="acunit-fan">
                                <option value="LEVEL_5">level 5</option>
                        </options>
                </state>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
        <channel-type id="acunit-fandir">
                                <option value="VERTICAL_AND_HORIZONTAL">vertical and horizontal</option>
                        </options>
                </state>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
        <channel-type id="acunit-cmpfrequency" advanced="true">
                                <option value="POWERFUL">Powerful</option>
                        </options>
                </state>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
        <channel-type id="acunit-streamer" advanced="true">
                <item-type>Switch</item-type>
                <label>Streamer</label>
                <description>Streamer Mode</description>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
        <channel-type id="acunit-energyheatingtoday" advanced="true">
                                <option value="MANUAL">Manual</option>
                        </options>
                </state>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
        <channel-type id="acunit-demandcontrolmaxpower" advanced="true">
                <item-type>Dimmer</item-type>
                <description>The maximum power for demand control in percent. Allowed range is between 40% and 100% in increments of
                        5%.</description>
                <state pattern="%d %%" min="40" max="100" step="5"></state>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
        <channel-type id="acunit-demandcontrolschedule" advanced="true">
                <item-type>String</item-type>
                <label>Demand Control Schedule</label>
                <description>The demand control schedule in JSON format.</description>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
        <channel-type id="airbase-acunit-fan">
                <item-type>String</item-type>
                <label>Fan</label>
                <description>Current fan speed setting of the AC unit</description>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
        <channel-type id="airbase-acunit-zone1">
                <item-type>Switch</item-type>
                <label>Zone 1</label>
                <description>Zone 1 for the AC unit</description>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
        <channel-type id="airbase-acunit-zone2">
                <item-type>Switch</item-type>
                <label>Zone 2</label>
                <description>Zone 2 for the AC unit</description>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
        <channel-type id="airbase-acunit-zone3">
                <item-type>Switch</item-type>
                <label>Zone 3</label>
                <description>Zone 3 for the AC unit</description>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
        <channel-type id="airbase-acunit-zone4">
                <item-type>Switch</item-type>
                <label>Zone 4</label>
                <description>Zone 4 for the AC unit</description>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
        <channel-type id="airbase-acunit-zone5">
                <item-type>Switch</item-type>
                <label>Zone 5</label>
                <description>Zone 5 for the AC unit</description>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
        <channel-type id="airbase-acunit-zone6">
                <item-type>Switch</item-type>
                <label>Zone 6</label>
                <description>Zone 6 for the AC unit</description>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
        <channel-type id="airbase-acunit-zone7">
                <item-type>Switch</item-type>
                <label>Zone 7</label>
                <description>Zone 7 for the AC unit</description>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
        <channel-type id="airbase-acunit-zone8">
                <item-type>Switch</item-type>
                <label>Zone 8</label>
                <description>Zone 8 for the AC unit</description>
+               <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
 
 </thing:thing-descriptions>