Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 98 additions & 70 deletions bundles/org.openhab.binding.homeconnect/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public class HomeConnectBindingConstants {
public static final ThingTypeUID THING_TYPE_COFFEE_MAKER = new ThingTypeUID(BINDING_ID, "coffeemaker");
public static final ThingTypeUID THING_TYPE_HOOD = new ThingTypeUID(BINDING_ID, "hood");
public static final ThingTypeUID THING_TYPE_COOKTOP = new ThingTypeUID(BINDING_ID, "hob");
public static final ThingTypeUID THING_TYPE_CLEANING_ROBOT = new ThingTypeUID(BINDING_ID, "cleaningrobot");

// Setting
public static final String SETTING_POWER_STATE = "BSH.Common.Setting.PowerState";
Expand All @@ -59,6 +60,7 @@ public class HomeConnectBindingConstants {
public static final String SETTING_REFRIGERATOR_SETPOINT_TEMPERATURE = "Refrigeration.FridgeFreezer.Setting.SetpointTemperatureRefrigerator";
public static final String SETTING_REFRIGERATOR_SUPER_MODE = "Refrigeration.FridgeFreezer.Setting.SuperModeRefrigerator";
public static final String SETTING_FREEZER_SUPER_MODE = "Refrigeration.FridgeFreezer.Setting.SuperModeFreezer";
public static final String SETTING_CURRENT_MAP = "ConsumerProducts.CleaningRobot.Setting.CurrentMap";

// Status
public static final String STATUS_DOOR_STATE = "BSH.Common.Status.DoorState";
Expand All @@ -67,6 +69,7 @@ public class HomeConnectBindingConstants {
public static final String STATUS_REMOTE_CONTROL_START_ALLOWED = "BSH.Common.Status.RemoteControlStartAllowed";
public static final String STATUS_REMOTE_CONTROL_ACTIVE = "BSH.Common.Status.RemoteControlActive";
public static final String STATUS_LOCAL_CONTROL_ACTIVE = "BSH.Common.Status.LocalControlActive";
public static final String STATUS_BATTERY_LEVEL = "BSH.Common.Status.BatteryLevel";

// SSE Event types
public static final String EVENT_ELAPSED_PROGRAM_TIME = "BSH.Common.Option.ElapsedProgramTime";
Expand Down Expand Up @@ -106,6 +109,8 @@ public class HomeConnectBindingConstants {
public static final String EVENT_AMBIENT_LIGHT_BRIGHTNESS_STATE = SETTING_AMBIENT_LIGHT_BRIGHTNESS;
public static final String EVENT_AMBIENT_LIGHT_COLOR_STATE = SETTING_AMBIENT_LIGHT_COLOR;
public static final String EVENT_AMBIENT_LIGHT_CUSTOM_COLOR_STATE = SETTING_AMBIENT_LIGHT_CUSTOM_COLOR;
public static final String EVENT_BATTERY_LEVEL = STATUS_BATTERY_LEVEL;
public static final String EVENT_CURRENT_MAP = SETTING_CURRENT_MAP;

// Channel IDs
public static final String CHANNEL_DOOR_STATE = "door_state";
Expand Down Expand Up @@ -155,16 +160,18 @@ public class HomeConnectBindingConstants {
public static final String CHANNEL_AMBIENT_LIGHT_BRIGHTNESS_STATE = "ambient_light_brightness_state";
public static final String CHANNEL_AMBIENT_LIGHT_COLOR_STATE = "ambient_light_color_state";
public static final String CHANNEL_AMBIENT_LIGHT_CUSTOM_COLOR_STATE = "ambient_light_custom_color_state";
public static final String CHANNEL_BATTERY_LEVEL = "battery_level";

// List of all supported devices
public static final Set<ThingTypeUID> SUPPORTED_DEVICE_THING_TYPES_UIDS = Set.of(THING_TYPE_API_BRIDGE,
THING_TYPE_DISHWASHER, THING_TYPE_OVEN, THING_TYPE_WASHER, THING_TYPE_DRYER, THING_TYPE_WASHER_DRYER,
THING_TYPE_FRIDGE_FREEZER, THING_TYPE_COFFEE_MAKER, THING_TYPE_HOOD, THING_TYPE_COOKTOP);
THING_TYPE_FRIDGE_FREEZER, THING_TYPE_COFFEE_MAKER, THING_TYPE_HOOD, THING_TYPE_COOKTOP,
THING_TYPE_CLEANING_ROBOT);

// Discoverable devices
public static final Set<ThingTypeUID> DISCOVERABLE_DEVICE_THING_TYPES_UIDS = Set.of(THING_TYPE_DISHWASHER,
THING_TYPE_OVEN, THING_TYPE_WASHER, THING_TYPE_DRYER, THING_TYPE_WASHER_DRYER, THING_TYPE_FRIDGE_FREEZER,
THING_TYPE_COFFEE_MAKER, THING_TYPE_HOOD, THING_TYPE_COOKTOP);
THING_TYPE_COFFEE_MAKER, THING_TYPE_HOOD, THING_TYPE_COOKTOP, THING_TYPE_CLEANING_ROBOT);

// List of state values
public static final String STATE_POWER_OFF = "BSH.Common.EnumType.PowerState.Off";
Expand Down Expand Up @@ -240,6 +247,28 @@ public class HomeConnectBindingConstants {
public static final String PROGRAM_HOOD_AUTOMATIC = "Cooking.Common.Program.Hood.Automatic";
public static final String PROGRAM_HOOD_VENTING = "Cooking.Common.Program.Hood.Venting";
public static final String PROGRAM_HOOD_DELAYED_SHUT_OFF = "Cooking.Common.Program.Hood.DelayedShutOff";
public static final String PROGRAM_CLEANING_ROBOT_GO_HOME = "ConsumerProducts.CleaningRobot.Program.Basic.GoHome";
public static final String PROGRAM_CLEANING_ROBOT_CLEAN_MAP = "ConsumerProducts.CleaningRobot.Program.Cleaning.CleanMap";

// Cleaning robot options
public static final String OPTION_CLEANING_MODE = "ConsumerProducts.CleaningRobot.Option.CleaningMode";
public static final String OPTION_SUCTION_POWER = "ConsumerProducts.CleaningRobot.Option.SuctionPower";
public static final String OPTION_WATER_FLOW_RATE = "ConsumerProducts.CleaningRobot.Option.WaterFlowRate";
public static final String OPTION_CLEANING_PASSES = "ConsumerProducts.CleaningRobot.Option.CleaningPasses";
public static final String OPTION_CARPET_BOOST = "ConsumerProducts.CleaningRobot.Option.CarpetBoostEnabled";
public static final String OPTION_CLEANING_SPEED = "ConsumerProducts.CleaningRobot.Option.CleaningSpeed";
public static final String OPTION_MOP_EXTENSION = "ConsumerProducts.CleaningRobot.Option.MopExtensionEnabled";

// Cleaning robot cleaning modes
public static final String CLEANING_MODE_PREFIX = "ConsumerProducts.CleaningRobot.EnumType.CleaningMode.";
public static final String CLEANING_MODE_SILENT = CLEANING_MODE_PREFIX + "Silent";
public static final String CLEANING_MODE_STANDARD = CLEANING_MODE_PREFIX + "Standard";
public static final String CLEANING_MODE_POWER = CLEANING_MODE_PREFIX + "Power";
public static final String CLEANING_MODE_INTELLIGENT = CLEANING_MODE_PREFIX + "IntelligentMode";
public static final String CLEANING_MODE_VACUUM_ONLY = CLEANING_MODE_PREFIX + "VacuumOnly";
public static final String CLEANING_MODE_MOP_ONLY = CLEANING_MODE_PREFIX + "MopOnly";
public static final String CLEANING_MODE_VACUUM_AND_MOP = CLEANING_MODE_PREFIX + "VacuumAndMop";
public static final String CLEANING_MODE_MOP_AFTER_VACUUM = CLEANING_MODE_PREFIX + "MopAfterVacuum";

// Network and oAuth constants
public static final String API_BASE_URL = "https://api.home-connect.com";
Expand Down Expand Up @@ -272,6 +301,23 @@ public class HomeConnectBindingConstants {
public static final String COMMAND_VENTING_INTENSIVE_2 = "ventingIntensive2";
public static final String COMMAND_AUTOMATIC = "automatic";
public static final String COMMAND_DELAYED_SHUT_OFF = "delayed";
public static final String COMMAND_PAUSE = "pause";
public static final String COMMAND_RESUME = "resume";
public static final String COMMAND_GO_HOME = "gohome";

// Home Connect API commands
public static final String API_COMMAND_PAUSE = "BSH.Common.Command.PauseCommand";
public static final String API_COMMAND_RESUME = "BSH.Common.Command.ResumeCommand";

// Channel IDs (cleaning robot)
public static final String CHANNEL_CLEANING_MODE_STATE = "cleaning_mode_state";
public static final String CHANNEL_SUCTION_POWER_STATE = "suction_power_state";
public static final String CHANNEL_WATER_FLOW_RATE_STATE = "water_flow_rate_state";
public static final String CHANNEL_CLEANING_PASSES_STATE = "cleaning_passes_state";
public static final String CHANNEL_CARPET_BOOST = "carpet_boost";
public static final String CHANNEL_CLEANING_SPEED_STATE = "cleaning_speed_state";
public static final String CHANNEL_MOP_EXTENSION = "mop_extension";
public static final String CHANNEL_CURRENT_MAP = "current_map";

// light
public static final int BRIGHTNESS_MIN = 10;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,48 @@ public Data getDoorState(String haId)
return getStatus(haId, STATUS_DOOR_STATE);
}

/**
* Get battery level of device.
*
* @param haId home appliance id
* @return {@link Data}
* @throws CommunicationException API communication exception
* @throws AuthorizationException oAuth authorization exception
* @throws ApplianceOfflineException appliance is not connected to the cloud
*/
public Data getBatteryLevel(String haId)
throws CommunicationException, AuthorizationException, ApplianceOfflineException {
return getStatus(haId, STATUS_BATTERY_LEVEL);
}

/**
* Get current map of cleaning robot.
*
* @param haId home appliance id
* @return {@link Data}
* @throws CommunicationException API communication exception
* @throws AuthorizationException oAuth authorization exception
* @throws ApplianceOfflineException appliance is not connected to the cloud
*/
public Data getCurrentMap(String haId)
throws CommunicationException, AuthorizationException, ApplianceOfflineException {
return getSetting(haId, SETTING_CURRENT_MAP);
}

/**
* Set current map of cleaning robot.
*
* @param haId home appliance id
* @param map map value (e.g. ConsumerProducts.CleaningRobot.EnumType.AvailableMaps.Map1)
* @throws CommunicationException API communication exception
* @throws AuthorizationException oAuth authorization exception
* @throws ApplianceOfflineException appliance is not connected to the cloud
*/
public void setCurrentMap(String haId, String map)
throws CommunicationException, AuthorizationException, ApplianceOfflineException {
putSettings(haId, new Data(SETTING_CURRENT_MAP, map, null));
}

/**
* Get operation state of device.
*
Expand Down Expand Up @@ -652,6 +694,21 @@ public void stopProgram(String haId)
sendDelete(haId, BASE_PATH + haId + "/programs/active");
}

/**
* Send a command to the active program.
*
* @param haId home appliance id
* @param commandKey the command key (e.g. BSH.Common.Command.PauseCommand)
* @throws CommunicationException API communication exception
* @throws AuthorizationException oAuth authorization exception
* @throws ApplianceOfflineException appliance is not connected to the cloud
*/
public void putCommand(String haId, String commandKey)
throws CommunicationException, AuthorizationException, ApplianceOfflineException {
putData(haId, BASE_PATH + haId + "/commands/" + commandKey, new Data(commandKey, Boolean.TRUE.toString(), null),
VALUE_TYPE_BOOLEAN);
}

public List<AvailableProgram> getPrograms(String haId)
throws CommunicationException, AuthorizationException, ApplianceOfflineException {
return getAvailablePrograms(haId, BASE_PATH + haId + "/programs");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ protected synchronized void stopScan() {
thingTypeUID = THING_TYPE_COOKTOP;
} else if (THING_TYPE_WASHER.getId().equalsIgnoreCase(appliance.getType())) {
thingTypeUID = THING_TYPE_WASHER;
} else if (THING_TYPE_CLEANING_ROBOT.getId().equalsIgnoreCase(appliance.getType())) {
thingTypeUID = THING_TYPE_CLEANING_ROBOT;
}

return thingTypeUID;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.homeconnect.internal.handler.HomeConnectBridgeHandler;
import org.openhab.binding.homeconnect.internal.handler.HomeConnectCleaningRobotHandler;
import org.openhab.binding.homeconnect.internal.handler.HomeConnectCoffeeMakerHandler;
import org.openhab.binding.homeconnect.internal.handler.HomeConnectCooktopHandler;
import org.openhab.binding.homeconnect.internal.handler.HomeConnectDishwasherHandler;
Expand All @@ -32,6 +33,8 @@
import org.openhab.binding.homeconnect.internal.servlet.HomeConnectServlet;
import org.openhab.binding.homeconnect.internal.type.HomeConnectDynamicStateDescriptionProvider;
import org.openhab.core.auth.client.oauth2.OAuthFactory;
import org.openhab.core.i18n.LocaleProvider;
import org.openhab.core.i18n.TranslationProvider;
import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Thing;
Expand Down Expand Up @@ -60,19 +63,24 @@ public class HomeConnectHandlerFactory extends BaseThingHandlerFactory {
private final OAuthFactory oAuthFactory;
private final HomeConnectDynamicStateDescriptionProvider dynamicStateDescriptionProvider;
private final HomeConnectServlet homeConnectServlet;
private final TranslationProvider i18nProvider;
private final LocaleProvider localeProvider;

@Activate
public HomeConnectHandlerFactory(@Reference HttpClientFactory httpClientFactory,
@Reference ClientBuilder clientBuilder, @Reference SseEventSourceFactory eventSourceFactory,
@Reference OAuthFactory oAuthFactory,
@Reference HomeConnectDynamicStateDescriptionProvider dynamicStateDescriptionProvider,
@Reference HomeConnectServlet homeConnectServlet) {
@Reference HomeConnectServlet homeConnectServlet, @Reference TranslationProvider i18nProvider,
@Reference LocaleProvider localeProvider) {
this.httpClient = httpClientFactory.getCommonHttpClient();
this.clientBuilder = clientBuilder;
this.eventSourceFactory = eventSourceFactory;
this.oAuthFactory = oAuthFactory;
this.dynamicStateDescriptionProvider = dynamicStateDescriptionProvider;
this.homeConnectServlet = homeConnectServlet;
this.i18nProvider = i18nProvider;
this.localeProvider = localeProvider;
}

@Override
Expand Down Expand Up @@ -105,6 +113,9 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return new HomeConnectHoodHandler(thing, dynamicStateDescriptionProvider);
} else if (THING_TYPE_COOKTOP.equals(thingTypeUID)) {
return new HomeConnectCooktopHandler(thing, dynamicStateDescriptionProvider);
} else if (THING_TYPE_CLEANING_ROBOT.equals(thingTypeUID)) {
return new HomeConnectCleaningRobotHandler(thing, dynamicStateDescriptionProvider, i18nProvider,
localeProvider);
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,17 @@ protected EventHandler defaultPercentHandler(String channelId) {
.ifPresent(channel -> updateState(channel.getUID(), new PercentType(event.getValueAsInt())));
}

protected EventHandler defaultStringEventHandler(String channelId) {
return event -> getLinkedChannel(channelId).ifPresent(channel -> {
String value = event.getValue();
if (value != null) {
updateState(channel.getUID(), new StringType(value));
} else {
updateState(channel.getUID(), UnDefType.UNDEF);
}
});
}

protected ChannelUpdateHandler defaultDoorStateChannelUpdateHandler() {
return (channelUID, cache) -> updateState(channelUID, cache.putIfAbsentAndGet(channelUID, () -> {
Optional<HomeConnectApiClient> apiClient = getApiClient();
Expand Down Expand Up @@ -1427,13 +1438,17 @@ protected void processProgramOptions(List<Option> options) {
Map.of(CHANNEL_WASHER_TEMPERATURE, OPTION_WASHER_TEMPERATURE, CHANNEL_WASHER_SPIN_SPEED,
OPTION_WASHER_SPIN_SPEED, CHANNEL_WASHER_IDOS1_LEVEL, OPTION_WASHER_IDOS_1_DOSING_LEVEL,
CHANNEL_WASHER_IDOS2_LEVEL, OPTION_WASHER_IDOS_2_DOSING_LEVEL, CHANNEL_DRYER_DRYING_TARGET,
OPTION_DRYER_DRYING_TARGET)
OPTION_DRYER_DRYING_TARGET, CHANNEL_CLEANING_MODE_STATE, OPTION_CLEANING_MODE,
CHANNEL_SUCTION_POWER_STATE, OPTION_SUCTION_POWER, CHANNEL_WATER_FLOW_RATE_STATE,
OPTION_WATER_FLOW_RATE, CHANNEL_CLEANING_PASSES_STATE, OPTION_CLEANING_PASSES,
CHANNEL_CLEANING_SPEED_STATE, OPTION_CLEANING_SPEED)
.forEach((channel, option) -> setStringChannelFromOption(channel, options, option, UnDefType.UNDEF));

Map.of(CHANNEL_WASHER_IDOS1, OPTION_WASHER_IDOS_1_ACTIVE, CHANNEL_WASHER_IDOS2, OPTION_WASHER_IDOS_2_ACTIVE,
CHANNEL_WASHER_LESS_IRONING, OPTION_WASHER_LESS_IRONING, CHANNEL_WASHER_PRE_WASH,
OPTION_WASHER_PRE_WASH, CHANNEL_WASHER_SOAK, OPTION_WASHER_SOAK, CHANNEL_WASHER_RINSE_HOLD,
OPTION_WASHER_RINSE_HOLD)
OPTION_WASHER_RINSE_HOLD, CHANNEL_CARPET_BOOST, OPTION_CARPET_BOOST, CHANNEL_MOP_EXTENSION,
OPTION_MOP_EXTENSION)
.forEach((channel, option) -> setOnOffChannelFromOption(channel, options, option, OnOffType.OFF));

setStringChannelFromOption(CHANNEL_HOOD_INTENSIVE_LEVEL, options, OPTION_HOOD_INTENSIVE_LEVEL,
Expand Down
Loading
Loading