Skip to content

Commit

Permalink
[daikin] Support the BRP1B61 (aka Airbase) controller (openhab#5910)
Browse files Browse the repository at this point in the history
* Support the BRP1B61 (aka Airbase) controller
* Move common thing config to a separate xml file

Signed-off-by: Paul Smedley <paul@smedley.id.au>
Signed-off-by: Maximilian Hess <mail@ne0h.de>
  • Loading branch information
psmedley authored and ne0h committed Sep 15, 2019
1 parent 84d83b7 commit a2b909b
Show file tree
Hide file tree
Showing 15 changed files with 789 additions and 43 deletions.
48 changes: 43 additions & 5 deletions bundles/org.openhab.binding.daikin/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Daikin Binding

The Daikin binding allows you to control your Daikin air conditioning units with openHAB. In order to do so, your Daikin air conditioning unit must have a BRP072A42 WiFi adapter installed.
The Daikin binding allows you to control your Daikin air conditioning units with openHAB. In order to do so, your Daikin air conditioning unit must have a BRP072A42 or BRP15B61 WiFi adapter installed.

## Supported Things

Daikin air conditioning units with a BRP072A42 installed. This may work with the older KRP series of wired adapters, but has not been tested with them.
Daikin air conditioning units with a BRP072A42 or BRP15B61 installed. This may work with the older KRP series of wired adapters, but has not been tested with them.

## Discovery

Expand All @@ -18,7 +18,7 @@ This addon will broadcast messages on your local network looking for Daikin air
## Channels

The temperature channels have a precision of one half degree Celsius.

For the BRP072A42:
| Channel Name | Description |
|--------------|---------------------------------------------------------------------------------------------|
| power | Turns the power on/off for the air conditioning unit. |
Expand All @@ -27,15 +27,33 @@ The temperature channels have a precision of one half degree Celsius.
| outdoortemp | The outdoor temperature as measured by the external part of the air conditioning system. May not be available when unit is off. |
| humidity | The indoor humidity as measured by the unit. This is not available on all units. |
| mode | The mode set for the unit (AUTO, DEHUMIDIFIER, COLD, HEAT, FAN) |
| fan | The fan speed set for the unit (AUTO, SILENCE, LEVEL_1, LEVEL_2, LEVEL_3, LEVEL_4, LEVEL_5) |

| fanspeed | The fan speed set for the unit (AUTO, SILENCE, LEVEL_1, LEVEL_2, LEVEL_3, LEVEL_4, LEVEL_5) |

For the BRP15B61:
| Channel Name | Description |
|-----------------|---------------------------------------------------------------------------------------------|
| power | Turns the power on/off for the air conditioning unit. |
| settemp | The temperature set for the air conditioning unit. |
| indoortemp | The indoor temperature as measured by the unit. |
| outdoortemp | The outdoor temperature as measured by the external part of the air conditioning system. May not be available when unit is off. |
| mode | The mode set for the unit (AUTO, DEHUMIDIFIER, COLD, HEAT, FAN) |
| airbasefanspeed | The fan speed set for the unit (AUTO, LEVEL_1, LEVEL_2, LEVEL_3) |
| zone1 | Turns zone 1 on/off for the air conditioning unit (if a zoned controller is installed. |
| zone2 | Turns zone 2 on/off for the air conditioning unit. |
| zone3 | Turns zone 3 on/off for the air conditioning unit. |
| zone4 | Turns zone 4 on/off for the air conditioning unit. |
| zone5 | Turns zone 5 on/off for the air conditioning unit. |
| zone6 | Turns zone 6 on/off for the air conditioning unit. |
| zone7 | Turns zone 7 on/off for the air conditioning unit. |
| zone8 | Turns zone 8 on/off for the air conditioning unit. |

## Full Example

daikin.things:

```
daikin:ac_unit:living_room_ac [ host="192.168.0.5" ]
daikin:airbase_ac_unit:living_room_ac [ host="192.168.0.5" ]
```

daikin.items:
Expand All @@ -47,6 +65,16 @@ String DaikinACUnit_Mode { channel="daikin:ac_unit:living_room_ac:mode" }
String DaikinACUnit_Fan { channel="daikin:ac_unit:living_room_ac:fanspeed" }
Number:Temperature DaikinACUnit_IndoorTemperature { channel="daikin:ac_unit:living_room_ac:indoortemp" }
Number:Temperature DaikinACUnit_OutdoorTemperature { channel="daikin:ac_unit:living_room_ac:outdoortemp" }
# Additional items for BRP1B61
Switch DaikinACUnit_Zone1 { channel="daikin:airbase_ac_unit:living_room_ac:zone1" }
Switch DaikinACUnit_Zone2 { channel="daikin:airbase_ac_unit:living_room_ac:zone2" }
Switch DaikinACUnit_Zone3 { channel="daikin:airbase_ac_unit:living_room_ac:zone3" }
Switch DaikinACUnit_Zone4 { channel="daikin:airbase_ac_unit:living_room_ac:zone4" }
Switch DaikinACUnit_Zone5 { channel="daikin:airbase_ac_unit:living_room_ac:zone5" }
Switch DaikinACUnit_Zone6 { channel="daikin:airbase_ac_unit:living_room_ac:zone6" }
Switch DaikinACUnit_Zone7 { channel="daikin:airbase_ac_unit:living_room_ac:zone7" }
Switch DaikinACUnit_Zone8 { channel="daikin:airbase_ac_unit:living_room_ac:zone8" }
```

daikin.sitemap:
Expand All @@ -58,4 +86,14 @@ Selection item=DaikinACUnit_Mode mappings=["AUTO"="Auto", "DEHUMIDIFIER"="Dehumi
Selection item=DaikinACUnit_Fan mappings=["AUTO"="Auto", "SILENCE"="Silence", "LEVEL_1"="Level 1", "LEVEL_2"="Level 2", "LEVEL_3"="Level 3", "LEVEL_4"="Level 4", "LEVEL_5"="Level 5"] visibility=[DaikinACUnit_Power==ON]
Text item=DaikinACUnit_IndoorTemperature
Text item=DaikinACUnit_OutdoorTemperature
# Additional items for BRP1B61
Switch item=DaikinACUnit_Zone1 visibility=[DaikinACUnit_Power==ON]
Switch item=DaikinACUnit_Zone2 visibility=[DaikinACUnit_Power==ON]
Switch item=DaikinACUnit_Zone3 visibility=[DaikinACUnit_Power==ON]
Switch item=DaikinACUnit_Zone4 visibility=[DaikinACUnit_Power==ON]
Switch item=DaikinACUnit_Zone5 visibility=[DaikinACUnit_Power==ON]
Switch item=DaikinACUnit_Zone6 visibility=[DaikinACUnit_Power==ON]
Switch item=DaikinACUnit_Zone7 visibility=[DaikinACUnit_Power==ON]
Switch item=DaikinACUnit_Zone8 visibility=[DaikinACUnit_Power==ON]
```
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
Expand All @@ -23,6 +25,7 @@
* used across the whole binding.
*
* @author Tim Waterhouse <tim@timwaterhouse.com> - Initial contribution
* @author Paul Smedley <paul@smedley.id.au> - Modifications to support Airbase Controllers
*/
@NonNullByDefault
public class DaikinBindingConstants {
Expand All @@ -31,6 +34,7 @@ public class DaikinBindingConstants {

// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_AC_UNIT = new ThingTypeUID(BINDING_ID, "ac_unit");
public static final ThingTypeUID THING_TYPE_AIRBASE_AC_UNIT = new ThingTypeUID(BINDING_ID, "airbase_ac_unit");

// List of all Channel ids
public static final String CHANNEL_AC_TEMP = "settemp";
Expand All @@ -42,5 +46,10 @@ public class DaikinBindingConstants {
public static final String CHANNEL_AC_FAN_DIR = "fandir";
public static final String CHANNEL_HUMIDITY = "humidity";

public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_AC_UNIT);
// additional channels for Airbase Controller
public static final String CHANNEL_AIRBASE_AC_FAN_SPEED = "airbasefanspeed";
public static final String CHANNEL_AIRBASE_AC_ZONE = "zone";

public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
.unmodifiableSet(Stream.of(THING_TYPE_AC_UNIT, THING_TYPE_AIRBASE_AC_UNIT).collect(Collectors.toSet()));
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
* handlers.
*
* @author Tim Waterhouse <tim@timwaterhouse.com> - Initial contribution
* @author Paul Smedley <paul@smedley.id.au> - Modifications to support Airbase Controllers
*/
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.daikin")
@NonNullByDefault
Expand All @@ -41,7 +43,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();

if (thingTypeUID.equals(DaikinBindingConstants.THING_TYPE_AC_UNIT)) {
if (thingTypeUID.equals(DaikinBindingConstants.THING_TYPE_AC_UNIT) || thingTypeUID.equals(DaikinBindingConstants.THING_TYPE_AIRBASE_AC_UNIT)) {
return new DaikinAcUnitHandler(thing);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,24 @@
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import org.eclipse.smarthome.io.net.http.HttpUtil;
import org.openhab.binding.daikin.internal.api.ControlInfo;
import org.openhab.binding.daikin.internal.api.SensorInfo;
import org.openhab.binding.daikin.internal.api.airbase.AirbaseControlInfo;
import org.openhab.binding.daikin.internal.api.airbase.AirbaseBasicInfo;
import org.openhab.binding.daikin.internal.api.airbase.AirbaseModelInfo;
import org.openhab.binding.daikin.internal.api.airbase.AirbaseZoneInfo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Handles performing the actual HTTP requests for communicating with Daiking air conditioning units.
* Handles performing the actual HTTP requests for communicating with Daikin air conditioning units.
*
* @author Tim Waterhouse - Initial Contribution
* @author Paul Smedley <paul@smedley.id.au> - Modifications to support Airbase Controllers
*
*/
public class DaikinWebTargets {
Expand All @@ -35,15 +42,33 @@ public class DaikinWebTargets {
private String setControlInfoUri;
private String getControlInfoUri;
private String getSensorInfoUri;
private String setAirbaseControlInfoUri;
private String getAirbaseControlInfoUri;
private String getAirbaseSensorInfoUri;
private String getAirbaseBasicInfoUri;
private String getAirbaseModelInfoUri;
private String getAirbaseZoneInfoUri;
private String setAirbaseZoneInfoUri;

private Logger logger = LoggerFactory.getLogger(DaikinWebTargets.class);

public DaikinWebTargets(String ipAddress) {
String baseUri = "http://" + ipAddress + "/";
setControlInfoUri = baseUri + "aircon/set_control_info";
getControlInfoUri = baseUri + "aircon/get_control_info";
getSensorInfoUri = baseUri + "aircon/get_sensor_info";

//Daikin Airbase API
getAirbaseBasicInfoUri = baseUri + "skyfi/common/basic_info";
setAirbaseControlInfoUri = baseUri + "skyfi/aircon/set_control_info";
getAirbaseControlInfoUri = baseUri + "skyfi/aircon/get_control_info";
getAirbaseSensorInfoUri = baseUri + "skyfi/aircon/get_sensor_info";
getAirbaseModelInfoUri = baseUri + "skyfi/aircon/get_model_info";
getAirbaseZoneInfoUri = baseUri + "skyfi/aircon/get_zone_setting";
setAirbaseZoneInfoUri = baseUri + "skyfi/aircon/set_zone_setting";
}

// Standard Daikin API
public ControlInfo getControlInfo() throws DaikinCommunicationException {
String response = invoke(getControlInfoUri);
return ControlInfo.parse(response);
Expand All @@ -59,6 +84,48 @@ public SensorInfo getSensorInfo() throws DaikinCommunicationException {
return SensorInfo.parse(response);
}

//Daikin Airbase API
public AirbaseControlInfo getAirbaseControlInfo() throws DaikinCommunicationException {
String response = invoke(getAirbaseControlInfoUri);
return AirbaseControlInfo.parse(response);
}

public void setAirbaseControlInfo(AirbaseControlInfo info) throws DaikinCommunicationException {
Map<String, String> queryParams = info.getParamString();
invoke(setAirbaseControlInfoUri, queryParams);
}

public SensorInfo getAirbaseSensorInfo() throws DaikinCommunicationException {
String response = invoke(getAirbaseSensorInfoUri);
return SensorInfo.parse(response);
}

public AirbaseBasicInfo getAirbaseBasicInfo() throws DaikinCommunicationException {
String response = invoke(getAirbaseBasicInfoUri);
return AirbaseBasicInfo.parse(response);
}

public AirbaseModelInfo getAirbaseModelInfo() throws DaikinCommunicationException {
String response = invoke(getAirbaseModelInfoUri);
return AirbaseModelInfo.parse(response);
}

public AirbaseZoneInfo getAirbaseZoneInfo() throws DaikinCommunicationException {
String response = invoke(getAirbaseZoneInfoUri);
return AirbaseZoneInfo.parse(response);
}

public void setAirbaseZoneInfo(AirbaseZoneInfo zoneinfo, AirbaseModelInfo modelinfo) throws DaikinCommunicationException {
long count = IntStream.range(0, zoneinfo.zone.length).filter(idx -> zoneinfo.zone[idx]).count() + modelinfo.commonzone;
logger.debug("Number of open zones: \"{}\"", count);

Map<String, String> queryParams = zoneinfo.getParamString();
if (count >= 1) {
invoke(setAirbaseZoneInfoUri, queryParams);
}
}


private String invoke(String uri) throws DaikinCommunicationException {
return invoke(uri, new HashMap<>());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@
* Class for holding the set of parameters used by set and get control info.
*
* @author Tim Waterhouse - Initial Contribution
* @author Paul Smedley <paul@smedley.id.au> - mods for Daikin Airbase
*
*/
public class ControlInfo {
private static Logger LOGGER = LoggerFactory.getLogger(ControlInfo.class);
private static final Logger LOGGER = LoggerFactory.getLogger(ControlInfo.class);

public String ret;
public boolean power = false;
public Mode mode = Mode.AUTO;
/** Degrees in Celsius. */
Expand All @@ -57,6 +59,7 @@ public static ControlInfo parse(String response) {
}).collect(Collectors.toMap(x -> x[0], x -> x[1]));

ControlInfo info = new ControlInfo();
info.ret = responseMap.get("ret");
info.power = "1".equals(responseMap.get("pow"));
info.mode = Optional.ofNullable(responseMap.get("mode")).flatMap(value -> parseInt(value))
.map(value -> Mode.fromValue(value)).orElse(Mode.AUTO);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public enum Mode {
HEAT(4),
FAN(6);

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

Mode(int value) {
Expand Down Expand Up @@ -64,7 +64,7 @@ public enum FanSpeed {
LEVEL_4("6"),
LEVEL_5("7");

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

FanSpeed(String value) {
Expand Down Expand Up @@ -96,7 +96,7 @@ public enum FanMovement {
HORIZONTAL(2),
VERTICAL_AND_HORIZONTAL(3);

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

FanMovement(int value) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* Copyright (c) 2010-2019 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.airbase;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Holds information from the basic_info call.
*
* @author Paul Smedley - Initial contribution
*
*/
public class AirbaseBasicInfo {
private static final Logger LOGGER = LoggerFactory.getLogger(AirbaseBasicInfo.class);

public String ssid;

private AirbaseBasicInfo() {
}

public static AirbaseBasicInfo parse(String response) {
LOGGER.debug("Parsing string: \"{}\"", response);

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]));

AirbaseBasicInfo info = new AirbaseBasicInfo();
info.ssid = responseMap.get("ssid");
return info;
}

public Map<String, String> getParamString() {
Map<String, String> params = new HashMap<>();
params.put("ssid", ssid);
return params;
}

}
Loading

0 comments on commit a2b909b

Please sign in to comment.