[daikin] add energy usage day & week (#9602)

* add energy usage day & week

Signed-off-by: Wouter Denayer <wouter@denayer.com>

* updated readme

Signed-off-by: Wouter Denayer <wouter@denayer.com>

* updated readme

Signed-off-by: Wouter Denayer <wouter@denayer.com>

* removed email from @author, set log lvl to trace for parsed strings

Signed-off-by: Wouter Denayer <wouter@denayer.com>

* fixed some some checkstyle warnings

Signed-off-by: Wouter Denayer <wouter@denayer.com>

* addressed some checkstyle warnings

Signed-off-by: Wouter Denayer <wouter@denayer.com>

* updated copyright to 2021

Signed-off-by: Wouter Denayer <wouter@denayer.com>

* made private static final Logger logger uppercase

Signed-off-by: Wouter Denayer <wouter@denayer.com>

* made this logger lowercase again

Signed-off-by: Wouter Denayer <wouter@denayer.com>

Co-authored-by: Wouter Denayer <wouter@denayer.com>
This commit is contained in:
Wouter Denayer 2021-03-31 19:59:16 +02:00 committed by GitHub
parent 0eb48e6abe
commit 634ee3ca69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 231 additions and 18 deletions

View File

@ -48,6 +48,9 @@ For the BRP072A42 and BRP072C42:
| 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 |
@ -60,6 +63,9 @@ For the BRP072A42 and BRP072C42:
| 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 |

View File

@ -49,8 +49,16 @@ public class DaikinBindingConstants {
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";

View File

@ -27,6 +27,7 @@ import org.eclipse.jetty.http.HttpMethod;
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;
@ -56,6 +57,7 @@ public class DaikinWebTargets {
private String getSensorInfoUri;
private String registerUuidUri;
private String getEnergyInfoYearUri;
private String getEnergyInfoWeekUri;
private String setSpecialModeUri;
private String setAirbaseControlInfoUri;
@ -83,6 +85,7 @@ public class DaikinWebTargets {
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
@ -128,6 +131,11 @@ public class DaikinWebTargets {
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()));

View File

@ -33,7 +33,7 @@ import org.slf4j.LoggerFactory;
*/
@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;
@ -50,7 +50,7 @@ public class ControlInfo {
}
public static ControlInfo parse(String response) {
logger.debug("Parsing string: \"{}\"", response);
LOGGER.debug("Parsing string: \"{}\"", response);
Map<String, String> responseMap = InfoParser.parse(response);

View File

@ -0,0 +1,101 @@
/**
* 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;
}
}

View File

@ -27,7 +27,7 @@ import org.slf4j.LoggerFactory;
*/
@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();
@ -37,7 +37,8 @@ public class EnergyInfoYear {
}
public static EnergyInfoYear parse(String response) {
logger.debug("Parsing string: \"{}\"", response);
LOGGER.trace("Parsing string: \"{}\"", response);
Map<String, String> responseMap = InfoParser.parse(response);

View File

@ -67,7 +67,6 @@ public class InfoParser {
}
try {
return Optional.of(Stream.of(value.split("/")).map(val -> Integer.parseInt(val)).toArray(Integer[]::new));
} catch (NumberFormatException e) {
return Optional.empty();
}

View File

@ -27,7 +27,7 @@ import org.slf4j.LoggerFactory;
*/
@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();
@ -38,7 +38,7 @@ public class SensorInfo {
}
public static SensorInfo parse(String response) {
logger.debug("Parsing string: \"{}\"", response);
LOGGER.debug("Parsing string: \"{}\"", response);
Map<String, String> responseMap = InfoParser.parse(response);

View File

@ -48,10 +48,10 @@ public class AirbaseZoneInfo {
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;
}

View File

@ -180,7 +180,6 @@ public class DaikinACUnitDiscoveryService extends AbstractDiscoveryService {
thingDiscovered(result);
return true;
}
} catch (Exception e) {
return false;
}

View File

@ -25,6 +25,7 @@ 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;
@ -32,6 +33,7 @@ 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.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;
@ -49,8 +51,10 @@ import org.slf4j.LoggerFactory;
* 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 {
@ -118,17 +122,37 @@ 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
@ -243,12 +267,12 @@ public class DaikinAcUnitHandler extends DaikinBaseHandler {
/**
* 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))
@ -256,6 +280,19 @@ public class DaikinAcUnitHandler extends DaikinBaseHandler {
);
}
/**
*
* @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) {

View File

@ -21,6 +21,9 @@
<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>
@ -33,6 +36,9 @@
<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>
@ -174,6 +180,54 @@
</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>