From 493994d97f2b955092789ca834be29e15b28aa83 Mon Sep 17 00:00:00 2001 From: jimtng <2554958+jimtng@users.noreply.github.com> Date: Wed, 28 Aug 2024 19:43:16 +1000 Subject: [PATCH] [daikin] Update channels immediately after a successful API command (#17149) * [daikin] Update channels immediately after a successful API command Signed-off-by: Jimmy Tanagra Signed-off-by: Ciprian Pascu --- .../daikin/internal/DaikinWebTargets.java | 36 +++--- .../binding/daikin/internal/api/Enums.java | 1 - .../internal/handler/DaikinAcUnitHandler.java | 89 ++++++++++----- .../handler/DaikinAirbaseUnitHandler.java | 38 ++++--- .../internal/handler/DaikinBaseHandler.java | 107 +++++++++++------- .../resources/OH-INF/thing/thing-types.xml | 20 ++++ 6 files changed, 185 insertions(+), 106 deletions(-) diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinWebTargets.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinWebTargets.java index 9228d538e80..31f4c761e5d 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinWebTargets.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinWebTargets.java @@ -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 queryParams = info.getParamString(); - String result = invoke(setControlInfoUri, queryParams); - Map 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 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 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 queryParams = info.getParamString(); - String result = invoke(setDemandControlUri, queryParams); - Map 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 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 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 { diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/Enums.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/Enums.java index 3b1918bc80d..1f7ffcf72f8 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/Enums.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/Enums.java @@ -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) { diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAcUnitHandler.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAcUnitHandler.java index 3b34ad56426..e2eecfab09e 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAcUnitHandler.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAcUnitHandler.java @@ -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); } /** diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAirbaseUnitHandler.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAirbaseUnitHandler.java index 62601846b05..4d15e95ef0c 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAirbaseUnitHandler.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAirbaseUnitHandler.java @@ -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 diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinBaseHandler.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinBaseHandler.java index a427459337e..ef2976131c3 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinBaseHandler.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinBaseHandler.java @@ -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 quantityCommand = (QuantityType) 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. 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) command).toUnit(SIUnits.CELSIUS).doubleValue(); - } else { - 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; - } - - 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"); + private boolean changeHomekitMode(String homekitmode) throws DaikinCommunicationException { + try { + HomekitMode mode = HomekitMode.valueOf(homekitmode.toUpperCase()); + boolean power = mode != HomekitMode.OFF; + if (!changePower(power)) { + return false; } + + boolean changeModeSuccess = false; + updateState(DaikinBindingConstants.CHANNEL_AC_POWER, OnOffType.from(power)); + + 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; } } } diff --git a/bundles/org.openhab.binding.daikin/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.daikin/src/main/resources/OH-INF/thing/thing-types.xml index 64f1a37570d..e32d96656b1 100644 --- a/bundles/org.openhab.binding.daikin/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.daikin/src/main/resources/OH-INF/thing/thing-types.xml @@ -94,6 +94,7 @@ Power for the AC unit Switch + veto @@ -102,6 +103,7 @@ The set point temperature Temperature + veto @@ -141,6 +143,7 @@ + veto @@ -155,6 +158,7 @@ + veto @@ -172,6 +176,7 @@ + veto @@ -186,6 +191,7 @@ + veto @@ -205,12 +211,14 @@ + veto Switch Streamer Mode + veto @@ -442,6 +450,7 @@ + veto Dimmer @@ -449,65 +458,76 @@ The maximum power for demand control in percent. Allowed range is between 40% and 100% in increments of 5%. + veto String The demand control schedule in JSON format. + veto String Current fan speed setting of the AC unit + veto Switch Zone 1 for the AC unit + veto Switch Zone 2 for the AC unit + veto Switch Zone 3 for the AC unit + veto Switch Zone 4 for the AC unit + veto Switch Zone 5 for the AC unit + veto Switch Zone 6 for the AC unit + veto Switch Zone 7 for the AC unit + veto Switch Zone 8 for the AC unit + veto