Skip to content

Commit

Permalink
Support server translation in select boxes
Browse files Browse the repository at this point in the history
  • Loading branch information
ekutner committed Oct 24, 2023
1 parent d21372e commit c561dcc
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 44 deletions.
2 changes: 1 addition & 1 deletion .devcontainer/config/configuration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ home_connect_alt:
client_secret: !secret home_connect_client_secret
# cache: false
language: en-GB
sensor_value_translation: local
sensor_value_translation: server
name_template: $appliance $name ($brand)
log_mode: 7
#api_host: https://simulator.home-connect.com
Expand Down
81 changes: 44 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,50 @@ home_connect_alt:

After the integration is configured READ THE FAQ then add it from the Home-Assistant UI.

<br>

# Automation Notes

## Integration state
* There is a special sensor called **Home Connect Status** which shows the status of the integration. It has the following values:
* INIT - The integration is initializing
* RUNNING - The integration has started running
* LOADED - The integration finished loading the initial data from the Home Connect service
* READY - The integration has successfully subscribed to real time updates from the cloud service and is now fully functional.
* BLOCKED - The Home Connect service has blocked additional API calls for a period of time due to exceeding the service rate limits
*It may take up to one minute to go from LOADED to READY*

## Services
The following services are available for use with automations:
**select_program** - Selects a program and optionally set its options
**start_program** - Starts a program and optionally set its options
**stop_program** - Stops the active program
**pause_program** - Pauses the active program (if and when supported by the appliance)
**resume_program** - Resumes a paused program (if and when supported by the appliance)
**set_program_option** - Sets an option on the active program if one exists or on the selected program otherwise
**apply_setting** - Applies the sepecified setting on an appliance
**run_command** - Runs the specified command on an appliance

## Events
The integration exposes the events fired by the service as Home Assistant events under the name: **"home_connect_alt_event"**
The published events values are:
* **BSH.Common.Status.OperationState**
* **All the events with the keyword "Event" in their names**

## Triggers
The integration exposes two triggers for easy automation:
* program_started
* program_finished

## Local vs. Server translation
The default behavior of this integration is to use "local" value translation. That means that all string sensors keep their internal value in a raw, language independant format. Those values are "translated" in the UI to a human friendly text by using local translation files.
This method is different than most other Home Assistant integration but it has three important benefits:
1. It makes automation code language independent. As a developer I strongly believe that code shouldn't relay on the specific human language currently selected by the user.
2. It allows users to look up possible values in the Home Connect developer documentation. So you can know in advance which values to epxect for a given sensor.
3. It allows add translation for languages which are not supported by the Home COnnect API.

In contrast, setting ```sensor_value_translation: server``` will override this behavior and use translations provided by the Home Connect API. This is limited to languages supported by the API but it does make sensor have the actual textual values displayed in the UI. So you can use that if you prefer,

</br>

# FAQ
Expand Down Expand Up @@ -196,43 +240,6 @@ After the integration is configured READ THE FAQ then add it from the Home-Assis

</br>

# Automation Notes

## Integration state
* There is a special sensor called **Home Connect Status** which shows the status of the integration. It has the following values:
* INIT - The integration is initializing
* RUNNING - The integration has started running
* LOADED - The integration finished loading the initial data from the Home Connect service
* READY - The integration has successfully subscribed to real time updates from the cloud service and is now fully functional.
* BLOCKED - The Home Connect service has blocked additional API calls for a period of time due to exceeding the service rate limits
*It may take up to one minute to go from LOADED to READY*

## Services
The following services are available for use with automations:
**select_program** - Selects a program and optionally set its options
**start_program** - Starts a program and optionally set its options
**stop_program** - Stops the active program
**pause_program** - Pauses the active program (if and when supported by the appliance)
**resume_program** - Resumes a paused program (if and when supported by the appliance)
**set_program_option** - Sets an option on the active program if one exists or on the selected program otherwise
**apply_setting** - Applies the sepecified setting on an appliance
**run_command** - Runs the specified command on an appliance

## Events
The integration exposes the events fired by the service as Home Assistant events under the name: **"home_connect_alt_event"**
The published events values are:
* **BSH.Common.Status.OperationState**
* **All the events with the keyword "Event" in their names**

## Triggers
The integration exposes two triggers for easy automation:
* program_started
* program_finished


<br>


# Known Issues
* If you have more than 3 connected devices (or you just play a lot with settings), you may hit the daily API rate limit set by the Home Connect API. The limit is set to 1000 calls per day and when it is hit the API is blocked for 24h. During that time, the integration will not get updated with new states and you won't be able to select and options or start a program.
If you hit this limit frequently, please open an issue with a debug log. I'll try to see if there is a way to reduce some calls. However, as of now, there is nothing I can do about it and the Home Connect team was unwilling to increase this limit, which hurts their best customers so there is nothing I can do about it.
Expand Down
2 changes: 1 addition & 1 deletion custom_components/home_connect_alt/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
"issue_tracker": "https://github.com/ekutner/home-connect-hass/issues",
"requirements": ["home-connect-async==0.7.12"],
"ssdp": [],
"version": "0.7.0-b1",
"version": "0.7.0-b2",
"zeroconf": []
}
29 changes: 24 additions & 5 deletions custom_components/home_connect_alt/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from homeassistant.helpers.typing import ConfigType

from .common import InteractiveEntityBase, EntityManager, is_boolean_enum, Configuration
from .const import DEVICE_ICON_MAP, DOMAIN
from .const import CONF_SENSORS_TRANSLATION, CONF_SENSORS_TRANSLATION_SERVER, DEVICE_ICON_MAP, DOMAIN

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -90,6 +90,8 @@ def available(self) -> bool:
def options(self) -> list[str]:
"""Return a set of selectable options."""
if self._appliance.available_programs:
if self._conf[CONF_SENSORS_TRANSLATION] == CONF_SENSORS_TRANSLATION_SERVER:
return [program.name if program.name else program.key for program in self._appliance.available_programs.values()]
return list(self._appliance.available_programs.keys())
return []

Expand All @@ -101,16 +103,21 @@ def current_option(self) -> str:
if self._appliance.available_programs and current_program.key in self._appliance.available_programs:
# The API sometimes returns programs which are not one of the avilable programs so we ignore it
CL.debug(_LOGGER, CL.LogMode.VERBOSE, "Current selected program is %s", current_program.key)
return current_program.key
return current_program.name if current_program.name and self._conf[CONF_SENSORS_TRANSLATION] == CONF_SENSORS_TRANSLATION_SERVER else current_program.key
else:
CL.debug(_LOGGER, CL.LogMode.VERBOSE, "Current program %s is not in available_programs", current_program.key)
else:
CL.debug(_LOGGER, CL.LogMode.VERBOSE, "Current program is None")
return None


async def async_select_option(self, option: str) -> None:
try:
await self._appliance.async_select_program(program_key=option)
if self._conf[CONF_SENSORS_TRANSLATION] == CONF_SENSORS_TRANSLATION_SERVER:
program = next((p for p in self._appliance.available_programs.values() if p.name == option), None)
await self._appliance.async_select_program(program_key=program.key)
else:
await self._appliance.async_select_program(program_key=option)
except HomeConnectError as ex:
if ex.error_description:
raise HomeAssistantError(f"Failed to set the selected program: {ex.error_description} ({ex.code} - {self._key}={option})")
Expand Down Expand Up @@ -163,7 +170,10 @@ def options(self) -> list[str]:
# #_LOGGER.info("Allowed values for %s : %s", self._key, None)
option = self._appliance.get_applied_program_available_option(self._key)
if option:
vals = option.allowedvalues.copy()
if self._conf[CONF_SENSORS_TRANSLATION] == CONF_SENSORS_TRANSLATION_SERVER:
vals = option.allowedvaluesdisplay.copy() if option.allowedvaluesdisplay else option.allowedvalues.copy()
else:
vals = option.allowedvalues.copy()
#vals.append('')
return vals

Expand All @@ -177,7 +187,12 @@ def current_option(self) -> str:
option = self._appliance.get_applied_program_option(self._key)
if option:
CL.debug(_LOGGER, CL.LogMode.VERBOSE, "Option %s current value: %s", self._key, option.value)
return option.value
if self._conf[CONF_SENSORS_TRANSLATION] == CONF_SENSORS_TRANSLATION_SERVER:
available_option = self._appliance.get_applied_program_available_option(self._key)
idx = available_option.allowedvalues.index(option.value)
return available_option.allowedvaluesdisplay[idx]
else:
return option.value
CL.debug(_LOGGER, CL.LogMode.VERBOSE, "Option %s current value is None", self._key)
return None

Expand All @@ -186,6 +201,10 @@ async def async_select_option(self, option: str) -> None:
_LOGGER.debug('Tried to set an empty option')
return
try:
if self._conf[CONF_SENSORS_TRANSLATION] == CONF_SENSORS_TRANSLATION_SERVER:
available_option = self._appliance.get_applied_program_available_option(self._key)
idx = available_option.allowedvaluesdisplay.index(option)
option = available_option.allowedvalues[idx]
await self._appliance.async_set_option(self._key, option)
except HomeConnectError as ex:
if ex.error_description:
Expand Down

0 comments on commit c561dcc

Please sign in to comment.