Skip to content

Commit

Permalink
[daikin] Fix Special Mode and Streamer support (openhab#12324)
Browse files Browse the repository at this point in the history
* [daikin] Fix Special Mode support

Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
  • Loading branch information
jimtng authored and psmedley committed Feb 23, 2023
1 parent fe50735 commit 462c815
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 166 deletions.
126 changes: 62 additions & 64 deletions bundles/org.openhab.binding.daikin/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public class DaikinBindingConstants {
public static final String CHANNEL_ENERGY_STRING_FORMAT = "%s-%d";

public static final String CHANNEL_AC_SPECIALMODE = "specialmode";
public static final String CHANNEL_AC_SPECIALMODE_POWERFUL = "specialmode-powerful";
public static final String CHANNEL_AC_STREAMER = "streamer";

// additional channels for Airbase Controller
public static final String CHANNEL_AIRBASE_AC_FAN_SPEED = "airbasefanspeed";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import org.openhab.binding.daikin.internal.api.ControlInfo;
import org.openhab.binding.daikin.internal.api.EnergyInfoDayAndWeek;
import org.openhab.binding.daikin.internal.api.EnergyInfoYear;
import org.openhab.binding.daikin.internal.api.Enums.SpecialModeKind;
import org.openhab.binding.daikin.internal.api.Enums.SpecialMode;
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;
Expand Down Expand Up @@ -137,12 +137,21 @@ public EnergyInfoDayAndWeek getEnergyInfoDayAndWeek() throws DaikinCommunication
return EnergyInfoDayAndWeek.parse(response);
}

public boolean setSpecialMode(SpecialModeKind specialModeKind, boolean state) throws DaikinCommunicationException {
public void setSpecialMode(SpecialMode specialMode) throws DaikinCommunicationException {
Map<String, String> queryParams = new HashMap<>();
queryParams.put("spmode_kind", String.valueOf(specialModeKind.getValue()));
queryParams.put("set_spmode", state ? "1" : "0");
if (specialMode == SpecialMode.NORMAL) {
queryParams.put("set_spmode", "0");
} else {
queryParams.put("set_spmode", "1");
queryParams.put("spmode_kind", Integer.toString(specialMode.getValue()));
}
String response = invoke(setSpecialModeUri, queryParams);
}

public void setStreamerMode(boolean state) throws DaikinCommunicationException {
Map<String, String> queryParams = new HashMap<>();
queryParams.put("en_streamer", state ? "1" : "0");
String response = invoke(setSpecialModeUri, queryParams);
return !response.contains("ret=OK");
}

// Daikin Airbase API
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.util.Optional;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.daikin.internal.api.Enums.AdvancedMode;
import org.openhab.binding.daikin.internal.api.Enums.FanMovement;
import org.openhab.binding.daikin.internal.api.Enums.FanSpeed;
import org.openhab.binding.daikin.internal.api.Enums.Mode;
Expand Down Expand Up @@ -44,7 +45,7 @@ public class ControlInfo {
public FanMovement fanMovement = FanMovement.STOPPED;
/* Not supported by all units. Sets the target humidity for dehumidifying. */
public Optional<Integer> targetHumidity = Optional.empty();
public SpecialMode specialMode = SpecialMode.UNKNOWN;
public AdvancedMode advancedMode = AdvancedMode.UNKNOWN;

private ControlInfo() {
}
Expand All @@ -66,8 +67,8 @@ public static ControlInfo parse(String response) {
.map(value -> FanMovement.fromValue(value)).orElse(FanMovement.STOPPED);
info.targetHumidity = Optional.ofNullable(responseMap.get("shum")).flatMap(value -> InfoParser.parseInt(value));

info.specialMode = Optional.ofNullable(responseMap.get("adv")).map(value -> SpecialMode.fromValue(value))
.orElse(SpecialMode.UNKNOWN);
info.advancedMode = Optional.ofNullable(responseMap.get("adv")).map(value -> AdvancedMode.fromValue(value))
.orElse(AdvancedMode.UNKNOWN);
return info;
}

Expand All @@ -82,4 +83,8 @@ public Map<String, String> getParamString() {

return params;
}

public SpecialMode getSpecialMode() {
return SpecialMode.fromAdvancedMode(advancedMode);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ public String getValue() {
}
}

public enum SpecialMode {
public enum AdvancedMode {
STREAMER("13"),
ECO("12"),
POWERFUL("2"),
Expand All @@ -148,65 +148,63 @@ public enum SpecialMode {
OFF(""),
UNKNOWN("??");

private static final Logger LOGGER = LoggerFactory.getLogger(SpecialMode.class);
private static final Logger LOGGER = LoggerFactory.getLogger(AdvancedMode.class);
private final String value;

SpecialMode(String value) {
AdvancedMode(String value) {
this.value = value;
}

public String getValue() {
return value;
}

public boolean isPowerfulActive() {
return this.equals(POWERFUL) || this.equals(POWERFUL_STREAMER);
public boolean isStreamerActive() {
return this.equals(STREAMER) || this.equals(POWERFUL_STREAMER) || this.equals(ECO_STREAMER);
}

public boolean isUndefined() {
return this.equals(UNKNOWN);
}

public static SpecialMode fromValue(String value) {
for (SpecialMode m : SpecialMode.values()) {
public static AdvancedMode fromValue(String value) {
for (AdvancedMode m : AdvancedMode.values()) {
if (m.getValue().equals(value)) {
return m;
}
}
LOGGER.debug("Unexpected SpecialMode value of \"{}\"", value);
LOGGER.debug("Unexpected AdvancedMode value of \"{}\"", value);

// Default to UNKNOWN
return UNKNOWN;
}
}

public enum SpecialModeKind {
UNKNOWN(-1),
STREAMER(0),
public enum SpecialMode {
NORMAL(0),
POWERFUL(1),
ECO(2);

private static final Logger LOGGER = LoggerFactory.getLogger(SpecialModeKind.class);
private final int value;

SpecialModeKind(int value) {
SpecialMode(int value) {
this.value = value;
}

public int getValue() {
return value;
}

public static SpecialModeKind fromValue(int value) {
for (SpecialModeKind m : SpecialModeKind.values()) {
if (m.getValue() == value) {
return m;
}
public static SpecialMode fromAdvancedMode(AdvancedMode advMode) {
switch (advMode) {
case POWERFUL:
case POWERFUL_STREAMER:
return SpecialMode.POWERFUL;
case ECO:
case ECO_STREAMER:
return SpecialMode.ECO;
}
LOGGER.debug("Unexpected SpecialModeKind value of \"{}\"", value);

// Default to UNKNOWN
return UNKNOWN;
return NORMAL;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,14 @@
import org.openhab.binding.daikin.internal.DaikinBindingConstants;
import org.openhab.binding.daikin.internal.DaikinCommunicationException;
import org.openhab.binding.daikin.internal.DaikinDynamicStateDescriptionProvider;
import org.openhab.binding.daikin.internal.DaikinWebTargets;
import org.openhab.binding.daikin.internal.api.ControlInfo;
import org.openhab.binding.daikin.internal.api.EnergyInfoDayAndWeek;
import org.openhab.binding.daikin.internal.api.EnergyInfoYear;
import org.openhab.binding.daikin.internal.api.Enums.FanMovement;
import org.openhab.binding.daikin.internal.api.Enums.FanSpeed;
import org.openhab.binding.daikin.internal.api.Enums.HomekitMode;
import org.openhab.binding.daikin.internal.api.Enums.Mode;
import org.openhab.binding.daikin.internal.api.Enums.SpecialModeKind;
import org.openhab.binding.daikin.internal.api.Enums.SpecialMode;
import org.openhab.binding.daikin.internal.api.SensorInfo;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
Expand Down Expand Up @@ -69,7 +68,7 @@ protected void pollStatus() throws DaikinCommunicationException {
if (!"OK".equals(controlInfo.ret)) {
throw new DaikinCommunicationException("Invalid response from host");
}
updateState(DaikinBindingConstants.CHANNEL_AC_POWER, controlInfo.power ? OnOffType.ON : OnOffType.OFF);
updateState(DaikinBindingConstants.CHANNEL_AC_POWER, OnOffType.from(controlInfo.power));
updateTemperatureChannel(DaikinBindingConstants.CHANNEL_AC_TEMP, controlInfo.temp);

updateState(DaikinBindingConstants.CHANNEL_AC_MODE, new StringType(controlInfo.mode.name()));
Expand All @@ -86,13 +85,14 @@ protected void pollStatus() throws DaikinCommunicationException {
updateState(DaikinBindingConstants.CHANNEL_AC_HOMEKITMODE, new StringType(HomekitMode.AUTO.getValue()));
}

updateState(DaikinBindingConstants.CHANNEL_AC_SPECIALMODE, new StringType(controlInfo.specialMode.name()));

if (controlInfo.specialMode.isUndefined()) {
updateState(DaikinBindingConstants.CHANNEL_AC_SPECIALMODE_POWERFUL, UnDefType.UNDEF);
if (controlInfo.advancedMode.isUndefined()) {
updateState(DaikinBindingConstants.CHANNEL_AC_STREAMER, UnDefType.UNDEF);
updateState(DaikinBindingConstants.CHANNEL_AC_SPECIALMODE, UnDefType.UNDEF);
} else {
updateState(DaikinBindingConstants.CHANNEL_AC_SPECIALMODE_POWERFUL,
controlInfo.specialMode.isPowerfulActive() ? OnOffType.ON : OnOffType.OFF);
updateState(DaikinBindingConstants.CHANNEL_AC_STREAMER,
OnOffType.from(controlInfo.advancedMode.isStreamerActive()));
updateState(DaikinBindingConstants.CHANNEL_AC_SPECIALMODE,
new StringType(controlInfo.getSpecialMode().name()));
}

SensorInfo sensorInfo = webTargets.getSensorInfo();
Expand Down Expand Up @@ -161,9 +161,15 @@ protected boolean handleCommandInternal(ChannelUID channelUID, Command command)
return true;
}
break;
case DaikinBindingConstants.CHANNEL_AC_SPECIALMODE_POWERFUL:
case DaikinBindingConstants.CHANNEL_AC_SPECIALMODE:
if (command instanceof StringType) {
changeSpecialMode(((StringType) command).toString());
return true;
}
break;
case DaikinBindingConstants.CHANNEL_AC_STREAMER:
if (command instanceof OnOffType) {
changeSpecialModePowerful(((OnOffType) command).equals(OnOffType.ON));
changeStreamer(((OnOffType) command).equals(OnOffType.ON));
return true;
}
break;
Expand All @@ -173,32 +179,20 @@ protected boolean handleCommandInternal(ChannelUID channelUID, Command command)

@Override
protected void changePower(boolean power) throws DaikinCommunicationException {
DaikinWebTargets webTargets = this.webTargets;
if (webTargets == null) {
return;
}
ControlInfo info = webTargets.getControlInfo();
info.power = power;
webTargets.setControlInfo(info);
}

@Override
protected void changeSetPoint(double newTemperature) throws DaikinCommunicationException {
DaikinWebTargets webTargets = this.webTargets;
if (webTargets == null) {
return;
}
ControlInfo info = webTargets.getControlInfo();
info.temp = Optional.of(newTemperature);
webTargets.setControlInfo(info);
}

@Override
protected void changeMode(String mode) throws DaikinCommunicationException {
DaikinWebTargets webTargets = this.webTargets;
if (webTargets == null) {
return;
}
Mode newMode;
try {
newMode = Mode.valueOf(mode);
Expand All @@ -213,10 +207,6 @@ protected void changeMode(String mode) throws DaikinCommunicationException {

@Override
protected void changeFanSpeed(String fanSpeed) throws DaikinCommunicationException {
DaikinWebTargets webTargets = this.webTargets;
if (webTargets == null) {
return;
}
FanSpeed newSpeed;
try {
newSpeed = FanSpeed.valueOf(fanSpeed);
Expand All @@ -230,10 +220,6 @@ protected void changeFanSpeed(String fanSpeed) throws DaikinCommunicationExcepti
}

protected void changeFanDir(String fanDir) throws DaikinCommunicationException {
DaikinWebTargets webTargets = this.webTargets;
if (webTargets == null) {
return;
}
FanMovement newMovement;
try {
newMovement = FanMovement.valueOf(fanDir);
Expand All @@ -246,18 +232,19 @@ protected void changeFanDir(String fanDir) throws DaikinCommunicationException {
webTargets.setControlInfo(info);
}

/**
*
* @param powerfulMode
* @return Is change successful
* @throws DaikinCommunicationException
*/
protected boolean changeSpecialModePowerful(boolean powerfulMode) throws DaikinCommunicationException {
DaikinWebTargets webTargets = this.webTargets;
if (webTargets == null) {
return false;
protected void 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 webTargets.setSpecialMode(SpecialModeKind.POWERFUL, powerfulMode);
webTargets.setSpecialMode(newMode);
}

protected void changeStreamer(boolean streamerMode) throws DaikinCommunicationException {
webTargets.setStreamerMode(streamerMode);
}

/**
Expand Down Expand Up @@ -295,10 +282,6 @@ protected void registerUuid(@Nullable String key) {
return;
}
try {
DaikinWebTargets webTargets = this.webTargets;
if (webTargets == null) {
return;
}
webTargets.registerUuid(key);
} catch (DaikinCommunicationException e) {
// suppress exceptions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ public DaikinBaseHandler(Thing thing, DaikinDynamicStateDescriptionProvider stat

@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (webTargets == null) {
logger.warn("webTargets is null. This is possibly a bug.");
return;
}
try {
if (handleCommandInternal(channelUID, command)) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,12 @@ channel-type.daikin.acunit-power.label = Power
channel-type.daikin.acunit-power.description = Power for the AC unit
channel-type.daikin.acunit-settemp.label = Set Point
channel-type.daikin.acunit-settemp.description = The set point temperature
channel-type.daikin.acunit-specialmode-powerful.label = Powerful Mode
channel-type.daikin.acunit-specialmode-powerful.description = Powerful mode switch
channel-type.daikin.acunit-specialmode.label = Special Mode
channel-type.daikin.acunit-specialmode.description = Current special mode
channel-type.daikin.acunit-specialmode.state.option.NORMAL = Normal
channel-type.daikin.acunit-specialmode.state.option.ECO = ECO
channel-type.daikin.acunit-specialmode.state.option.POWERFUL = Powerful
channel-type.daikin.acunit-streamer.label = Streamer
channel-type.daikin.acunit-streamer.description = Streamer Mode
channel-type.daikin.airbase-acunit-fan.label = Fan
channel-type.daikin.airbase-acunit-fan.description = Current fan speed setting of the AC unit
channel-type.daikin.airbase-acunit-zone1.label = Zone 1
Expand Down
Loading

0 comments on commit 462c815

Please sign in to comment.