| cmpfrequency | The compressor frequency |
| specialmode | The special mode currently active (OFF, STREAMER, ECO, POWERFUL, POWERFUL & STREAMER, ECO & STREAMER). Not all modes might be available on the unit. |
| specialmode-powerful | Turns the powerful mode on/off for the air conditioning unit. |
+| energyheatingtoday | The energy consumption when heating for today |
+| energyheatingthisweek | The energy consumption when heating for this week |
+| energyheatinglastweek | The energy consumption when heating for last week |
| energyheatingcurrentyear-1 | The energy consumption when heating for current year January |
| energyheatingcurrentyear-2 | The energy consumption when heating for current year February |
| energyheatingcurrentyear-3 | The energy consumption when heating for current year March |
| energyheatingcurrentyear-10| The energy consumption when heating for current year October |
| energyheatingcurrentyear-11| The energy consumption when heating for current year November |
| energyheatingcurrentyear-12| The energy consumption when heating for current year December |
+| energycoolingtoday | The energy consumption when cooling for today |
+| energycoolingthisweek | The energy consumption when cooling for this week |
+| energycoolinglastweek | The energy consumption when cooling for last week |
| energycoolingcurrentyear-1 | The energy consumption when cooling for current year January |
| energycoolingcurrentyear-2 | The energy consumption when cooling for current year February |
| energycoolingcurrentyear-3 | The energy consumption when cooling for current year March |
public static final String CHANNEL_CMP_FREQ = "cmpfrequency";
// Prefix and channel id format for energy - currentyear
- public static final String CHANNEL_ENERGY_HEATING_CURRENTYEAR_PREFIX = "energyheatingcurrentyear";
- public static final String CHANNEL_ENERGY_COOLING_CURRENTYEAR_PREFIX = "energycoolingcurrentyear";
+ public static final String CHANNEL_ENERGY_HEATING_CURRENTYEAR = "energyheatingcurrentyear";
+ public static final String CHANNEL_ENERGY_COOLING_CURRENTYEAR = "energycoolingcurrentyear";
+
+ public static final String CHANNEL_ENERGY_HEATING_TODAY = "energyheatingtoday";
+ public static final String CHANNEL_ENERGY_HEATING_THISWEEK = "energyheatingthisweek";
+ public static final String CHANNEL_ENERGY_HEATING_LASTWEEK = "energyheatinglastweek";
+ public static final String CHANNEL_ENERGY_COOLING_TODAY = "energycoolingtoday";
+ public static final String CHANNEL_ENERGY_COOLING_THISWEEK = "energycoolingthisweek";
+ public static final String CHANNEL_ENERGY_COOLING_LASTWEEK = "energycoolinglastweek";
+
public static final String CHANNEL_ENERGY_STRING_FORMAT = "%s-%d";
public static final String CHANNEL_AC_SPECIALMODE = "specialmode";
import org.eclipse.jetty.http.HttpStatus;
import org.openhab.binding.daikin.internal.api.BasicInfo;
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.SensorInfo;
private String getSensorInfoUri;
private String registerUuidUri;
private String getEnergyInfoYearUri;
+ private String getEnergyInfoWeekUri;
private String setSpecialModeUri;
private String setAirbaseControlInfoUri;
getSensorInfoUri = baseUri + "aircon/get_sensor_info";
registerUuidUri = baseUri + "common/register_terminal";
getEnergyInfoYearUri = baseUri + "aircon/get_year_power_ex";
+ getEnergyInfoWeekUri = baseUri + "aircon/get_week_power_ex";
setSpecialModeUri = baseUri + "aircon/set_special_mode";
// Daikin Airbase API
return EnergyInfoYear.parse(response);
}
+ public EnergyInfoDayAndWeek getEnergyInfoDayAndWeek() throws DaikinCommunicationException {
+ String response = invoke(getEnergyInfoWeekUri);
+ return EnergyInfoDayAndWeek.parse(response);
+ }
+
public boolean setSpecialMode(SpecialModeKind specialModeKind, boolean state) throws DaikinCommunicationException {
Map<String, String> queryParams = new HashMap<>();
queryParams.put("spmode_kind", String.valueOf(specialModeKind.getValue()));
*/
@NonNullByDefault
public class ControlInfo {
- private static final Logger logger = LoggerFactory.getLogger(ControlInfo.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(ControlInfo.class);
public String ret = "";
public boolean power = false;
}
public static ControlInfo parse(String response) {
- logger.debug("Parsing string: \"{}\"", response);
+ LOGGER.debug("Parsing string: \"{}\"", response);
Map<String, String> responseMap = InfoParser.parse(response);
--- /dev/null
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.daikin.internal.api;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Holds information from the get_week_power_ex call.
+ *
+ * @author Wouter Denayer - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class EnergyInfoDayAndWeek {
+ public Optional<Double> energyHeatingToday = Optional.empty();
+ public Optional<Double> energyHeatingThisWeek = Optional.empty();
+ public Optional<Double> energyHeatingLastWeek = Optional.empty();
+ public Optional<Double> energyCoolingToday = Optional.empty();
+ public Optional<Double> energyCoolingThisWeek = Optional.empty();
+ public Optional<Double> energyCoolingLastWeek = Optional.empty();
+
+ private static final Logger logger = LoggerFactory.getLogger(EnergyInfoDayAndWeek.class);
+
+ private EnergyInfoDayAndWeek() {
+ }
+
+ public static EnergyInfoDayAndWeek parse(String response) {
+ EnergyInfoDayAndWeek info = new EnergyInfoDayAndWeek();
+
+ logger.trace("Parsing string: \"{}\"", response);
+
+ // /aircon/get_week_power_ex
+ // ret=OK,s_dayw=0,week_heat=1/1/1/1/1/5/2/1/1/1/1/2/1/1,week_cool=0/0/0/0/0/0/0/0/0/0/0/0/0/0
+ // week_heat=<today>/<today-1>/<today-2>/<today-3>/...
+ Map<String, String> responseMap = Arrays.asList(response.split(",")).stream().filter(kv -> kv.contains("="))
+ .map(kv -> {
+ String[] keyValue = kv.split("=");
+ String key = keyValue[0];
+ String value = keyValue.length > 1 ? keyValue[1] : "";
+ return new String[] { key, value };
+ }).collect(Collectors.toMap(x -> x[0], x -> x[1]));
+
+ if (responseMap.get("ret") != null && ("OK".equals(responseMap.get("ret")))) {
+ Optional<Integer> dayOfWeek = Optional.ofNullable(responseMap.get("s_dayw"))
+ .flatMap(value -> InfoParser.parseInt(value));
+
+ if (dayOfWeek.isPresent()) {
+ // Daikin API week starts on Sunday, ours on Monday
+ int thisWeekLastDayIndex = (dayOfWeek.get().intValue() == 0) ? 7 : dayOfWeek.get().intValue();
+
+ // get the heating info
+ String[] heatingValues = responseMap.get("week_heat").split("/");
+ info.energyHeatingToday = Optional.of(Double.parseDouble(heatingValues[0]) / 10);
+ double thisWeekEnergy = 0;
+ for (int i = 0; i < thisWeekLastDayIndex; i += 1) {
+ thisWeekEnergy += Integer.parseInt(heatingValues[i]);
+ }
+ double previousWeekEnergy = 0;
+ for (int i = thisWeekLastDayIndex; i < thisWeekLastDayIndex + 7; i += 1) {
+ previousWeekEnergy += Integer.parseInt(heatingValues[i]);
+ }
+ info.energyHeatingThisWeek = Optional.of(thisWeekEnergy / 10);
+ info.energyHeatingLastWeek = Optional.of(previousWeekEnergy / 10);
+
+ // get the cooling info
+ String[] coolingValues = responseMap.get("week_cool").split("/");
+ info.energyCoolingToday = Optional.of(Double.parseDouble(coolingValues[0]) / 10);
+ thisWeekEnergy = 0;
+ for (int i = 0; i < thisWeekLastDayIndex; i += 1) {
+ thisWeekEnergy += Integer.parseInt(coolingValues[i]);
+ }
+ previousWeekEnergy = 0;
+ for (int i = thisWeekLastDayIndex; i < thisWeekLastDayIndex + 7; i += 1) {
+ previousWeekEnergy += Integer.parseInt(coolingValues[i]);
+ }
+ info.energyCoolingThisWeek = Optional.of(thisWeekEnergy / 10);
+ info.energyCoolingLastWeek = Optional.of(previousWeekEnergy / 10);
+ }
+ } else {
+ logger.debug("did not receive 'ret=OK' from adapter");
+ }
+ return info;
+ }
+}
*/
@NonNullByDefault
public class EnergyInfoYear {
- private static final Logger logger = LoggerFactory.getLogger(EnergyInfoYear.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(EnergyInfoYear.class);
public Optional<Integer[]> energyHeatingThisYear = Optional.empty();
}
public static EnergyInfoYear parse(String response) {
- logger.debug("Parsing string: \"{}\"", response);
+
+ LOGGER.trace("Parsing string: \"{}\"", response);
Map<String, String> responseMap = InfoParser.parse(response);
}
try {
return Optional.of(Stream.of(value.split("/")).map(val -> Integer.parseInt(val)).toArray(Integer[]::new));
-
} catch (NumberFormatException e) {
return Optional.empty();
}
*/
@NonNullByDefault
public class SensorInfo {
- private static final Logger logger = LoggerFactory.getLogger(SensorInfo.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(SensorInfo.class);
public Optional<Double> indoortemp = Optional.empty();
public Optional<Double> indoorhumidity = Optional.empty();
}
public static SensorInfo parse(String response) {
- logger.debug("Parsing string: \"{}\"", response);
+ LOGGER.debug("Parsing string: \"{}\"", response);
Map<String, String> responseMap = InfoParser.parse(response);
info.zonenames = Optional.ofNullable(responseMap.get("zone_name")).orElse("");
String zoneinfo = Optional.ofNullable(responseMap.get("zone_onoff")).orElse("");
- String[] Zones = zoneinfo.split("%3b");
+ String[] zones = zoneinfo.split("%3b");
for (int i = 1; i < 9; i++)
- info.zone[i] = "1".equals(Zones[i - 1]);
+ info.zone[i] = "1".equals(zones[i - 1]);
return info;
}
thingDiscovered(result);
return true;
}
-
} catch (Exception e) {
return false;
}
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.Mode;
import org.openhab.binding.daikin.internal.api.Enums.SpecialModeKind;
import org.openhab.binding.daikin.internal.api.SensorInfo;
+import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType;
* Handles communicating with a Daikin air conditioning unit.
*
* @author Tim Waterhouse - Initial Contribution
- * @author Paul Smedley <paul@smedley.id.au> - Modifications to support Airbase Controllers
+ * @author Paul Smedley - Modifications to support Airbase Controllers
* @author Lukas Agethen - Added support for Energy Year reading, compressor frequency and powerful mode
+ * @author Wouter Denayer - Added to support for weekly & daily energy reading
+ *
*/
@NonNullByDefault
public class DaikinAcUnitHandler extends DaikinBaseHandler {
EnergyInfoYear energyInfoYear = webTargets.getEnergyInfoYear();
if (energyInfoYear.energyHeatingThisYear.isPresent()) {
- updateEnergyYearChannel(DaikinBindingConstants.CHANNEL_ENERGY_HEATING_CURRENTYEAR_PREFIX,
+ updateEnergyYearChannel(DaikinBindingConstants.CHANNEL_ENERGY_HEATING_CURRENTYEAR,
energyInfoYear.energyHeatingThisYear);
}
if (energyInfoYear.energyCoolingThisYear.isPresent()) {
- updateEnergyYearChannel(DaikinBindingConstants.CHANNEL_ENERGY_COOLING_CURRENTYEAR_PREFIX,
+ updateEnergyYearChannel(DaikinBindingConstants.CHANNEL_ENERGY_COOLING_CURRENTYEAR,
energyInfoYear.energyCoolingThisYear);
}
} catch (DaikinCommunicationException e) {
// Suppress any error if energy info is not supported.
logger.debug("getEnergyInfoYear() error: {}", e.getMessage());
}
+
+ try {
+ EnergyInfoDayAndWeek energyInfoDayAndWeek = webTargets.getEnergyInfoDayAndWeek();
+
+ updateEnergyDayAndWeekChannel(DaikinBindingConstants.CHANNEL_ENERGY_HEATING_TODAY,
+ energyInfoDayAndWeek.energyHeatingToday);
+ updateEnergyDayAndWeekChannel(DaikinBindingConstants.CHANNEL_ENERGY_HEATING_THISWEEK,
+ energyInfoDayAndWeek.energyHeatingThisWeek);
+ updateEnergyDayAndWeekChannel(DaikinBindingConstants.CHANNEL_ENERGY_HEATING_LASTWEEK,
+ energyInfoDayAndWeek.energyHeatingLastWeek);
+ updateEnergyDayAndWeekChannel(DaikinBindingConstants.CHANNEL_ENERGY_COOLING_TODAY,
+ energyInfoDayAndWeek.energyCoolingToday);
+ updateEnergyDayAndWeekChannel(DaikinBindingConstants.CHANNEL_ENERGY_COOLING_THISWEEK,
+ energyInfoDayAndWeek.energyCoolingThisWeek);
+ updateEnergyDayAndWeekChannel(DaikinBindingConstants.CHANNEL_ENERGY_COOLING_LASTWEEK,
+ energyInfoDayAndWeek.energyCoolingLastWeek);
+ } catch (DaikinCommunicationException e) {
+ // Suppress any error if energy info is not supported.
+ logger.debug("getEnergyInfoDayAndWeek() error: {}", e.getMessage());
+ }
}
@Override
/**
* Updates energy year channels. Values are provided in hundreds of Watt
*
- * @param channelPrefix
+ * @param channel
* @param maybePower
*/
- protected void updateEnergyYearChannel(String channelPrefix, Optional<Integer[]> maybePower) {
+ protected void updateEnergyYearChannel(String channel, Optional<Integer[]> maybePower) {
IntStream.range(1, 13).forEach(i -> updateState(
- String.format(DaikinBindingConstants.CHANNEL_ENERGY_STRING_FORMAT, channelPrefix, i),
+ String.format(DaikinBindingConstants.CHANNEL_ENERGY_STRING_FORMAT, channel, i),
maybePower.<State> map(
t -> new QuantityType<>(BigDecimal.valueOf(t[i - 1].longValue(), 1), Units.KILOWATT_HOUR))
.orElse(UnDefType.UNDEF))
);
}
+ /**
+ *
+ * @param channel
+ * @param maybePower
+ */
+ protected void updateEnergyDayAndWeekChannel(String channel, Optional<Double> maybePower) {
+ if (maybePower.isPresent()) {
+ updateState(channel,
+ maybePower.<State> map(t -> new QuantityType<>(new DecimalType(t), Units.KILOWATT_HOUR))
+ .orElse(UnDefType.UNDEF));
+ }
+ }
+
@Override
protected void registerUuid(@Nullable String key) {
if (key == null) {
<channel id="cmpfrequency" typeId="acunit-cmpfrequency"></channel>
<channel id="specialmode" typeId="acunit-specialmode"></channel>
<channel id="specialmode-powerful" typeId="acunit-specialmode-powerful"></channel>
+ <channel id="energyheatingtoday" typeId="acunit-energyheatingtoday"/>
+ <channel id="energyheatingthisweek" typeId="acunit-energyheatingthisweek"/>
+ <channel id="energyheatinglastweek" typeId="acunit-energyheatinglastweek"/>
<channel id="energyheatingcurrentyear-1" typeId="acunit-energyheatingcurrentyear-1"></channel>
<channel id="energyheatingcurrentyear-2" typeId="acunit-energyheatingcurrentyear-2"></channel>
<channel id="energyheatingcurrentyear-3" typeId="acunit-energyheatingcurrentyear-3"></channel>
<channel id="energyheatingcurrentyear-10" typeId="acunit-energyheatingcurrentyear-10"></channel>
<channel id="energyheatingcurrentyear-11" typeId="acunit-energyheatingcurrentyear-11"></channel>
<channel id="energyheatingcurrentyear-12" typeId="acunit-energyheatingcurrentyear-12"></channel>
+ <channel id="energycoolingtoday" typeId="acunit-energycoolingtoday"/>
+ <channel id="energycoolingthisweek" typeId="acunit-energycoolingthisweek"/>
+ <channel id="energycoolinglastweek" typeId="acunit-energycoolinglastweek"/>
<channel id="energycoolingcurrentyear-1" typeId="acunit-energycoolingcurrentyear-1"></channel>
<channel id="energycoolingcurrentyear-2" typeId="acunit-energycoolingcurrentyear-2"></channel>
<channel id="energycoolingcurrentyear-3" typeId="acunit-energycoolingcurrentyear-3"></channel>
</state>
</channel-type>
+ <channel-type id="acunit-energyheatingtoday" advanced="true">
+ <item-type>Number:Energy</item-type>
+ <label>Energy Heating Today</label>
+ <description>The energy usage for heating today</description>
+ <category>Energy</category>
+ <state readOnly="true" pattern="%.1f %unit%"></state>
+ </channel-type>
+
+ <channel-type id="acunit-energyheatingthisweek" advanced="true">
+ <item-type>Number:Energy</item-type>
+ <label>Energy Heating This Week</label>
+ <description>The energy usage for heating this week</description>
+ <category>Energy</category>
+ <state readOnly="true" pattern="%.1f %unit%"></state>
+ </channel-type>
+
+ <channel-type id="acunit-energyheatinglastweek" advanced="true">
+ <item-type>Number:Energy</item-type>
+ <label>Energy Heating Last Week</label>
+ <description>The energy usage for heating last week</description>
+ <category>Energy</category>
+ <state readOnly="true" pattern="%.1f %unit%"></state>
+ </channel-type>
+
+ <channel-type id="acunit-energycoolingtoday" advanced="true">
+ <item-type>Number:Energy</item-type>
+ <label>Energy Cooling Today</label>
+ <description>The energy usage for cooling today</description>
+ <category>Energy</category>
+ <state readOnly="true" pattern="%.1f %unit%"></state>
+ </channel-type>
+
+ <channel-type id="acunit-energycoolingthisweek" advanced="true">
+ <item-type>Number:Energy</item-type>
+ <label>Energy Cooling This Week</label>
+ <description>The energy usage for cooling this week</description>
+ <category>Energy</category>
+ <state readOnly="true" pattern="%.1f %unit%"></state>
+ </channel-type>
+
+ <channel-type id="acunit-energycoolinglastweek" advanced="true">
+ <item-type>Number:Energy</item-type>
+ <label>Energy Cooling Last Week</label>
+ <description>The energy usage for cooling last week</description>
+ <category>Energy</category>
+ <state readOnly="true" pattern="%.1f %unit%"></state>
+ </channel-type>
+
<channel-type id="acunit-cmpfrequency" advanced="true">
<item-type>Number:Dimensionless</item-type>
<label>Compressor Frequency</label>