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;
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;
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 {
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");
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;
}
}
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
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 {
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 {
HEAT("heat"),
OFF("off");
- private static final Logger LOGGER = LoggerFactory.getLogger(HomekitMode.class);
private final String value;
HomekitMode(String value) {
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;
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;
}
@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;
// 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 {
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);
}
/**
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;
}
}
}
@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);
}
/**
* @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;
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
// 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)
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;
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;
}
}
}
<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>