diff --git a/homeassistant/components/coolmaster/__init__.py b/homeassistant/components/coolmaster/__init__.py index 18a3e943bbc..d2dd940a443 100644 --- a/homeassistant/components/coolmaster/__init__.py +++ b/homeassistant/components/coolmaster/__init__.py @@ -7,7 +7,7 @@ from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.helpers import device_registry as dr -from .const import CONF_SWING_SUPPORT, DOMAIN +from .const import CONF_SEND_WAKEUP_PROMPT, CONF_SWING_SUPPORT, DOMAIN from .coordinator import CoolmasterConfigEntry, CoolmasterDataUpdateCoordinator PLATFORMS = [Platform.BINARY_SENSOR, Platform.BUTTON, Platform.CLIMATE, Platform.SENSOR] @@ -17,10 +17,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: CoolmasterConfigEntry) - """Set up Coolmaster from a config entry.""" host = entry.data[CONF_HOST] port = entry.data[CONF_PORT] + send_wakeup_prompt = entry.data.get(CONF_SEND_WAKEUP_PROMPT, False) if not entry.data.get(CONF_SWING_SUPPORT): coolmaster = CoolMasterNet( host, port, + send_initial_line_feed=send_wakeup_prompt, ) else: # Swing support adds an additional request per unit. The requests are @@ -29,6 +31,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: CoolmasterConfigEntry) - coolmaster = CoolMasterNet( host, port, + send_initial_line_feed=send_wakeup_prompt, read_timeout=5, swing_support=True, ) diff --git a/homeassistant/components/coolmaster/config_flow.py b/homeassistant/components/coolmaster/config_flow.py index 19832eaef0a..d9c16dcb7cf 100644 --- a/homeassistant/components/coolmaster/config_flow.py +++ b/homeassistant/components/coolmaster/config_flow.py @@ -12,7 +12,13 @@ from homeassistant.config_entries import ConfigFlow, ConfigFlowResult from homeassistant.const import CONF_HOST, CONF_PORT from homeassistant.core import callback -from .const import CONF_SUPPORTED_MODES, CONF_SWING_SUPPORT, DEFAULT_PORT, DOMAIN +from .const import ( + CONF_SEND_WAKEUP_PROMPT, + CONF_SUPPORTED_MODES, + CONF_SWING_SUPPORT, + DEFAULT_PORT, + DOMAIN, +) AVAILABLE_MODES = [ HVACMode.OFF.value, @@ -25,17 +31,15 @@ AVAILABLE_MODES = [ MODES_SCHEMA = {vol.Required(mode, default=True): bool for mode in AVAILABLE_MODES} -DATA_SCHEMA = vol.Schema( - { - vol.Required(CONF_HOST): str, - **MODES_SCHEMA, - vol.Required(CONF_SWING_SUPPORT, default=False): bool, - } -) +DATA_SCHEMA = { + vol.Required(CONF_HOST): str, + **MODES_SCHEMA, + vol.Required(CONF_SWING_SUPPORT, default=False): bool, +} -async def _validate_connection(host: str) -> bool: - cool = CoolMasterNet(host, DEFAULT_PORT) +async def _validate_connection(host: str, send_wakeup_prompt: bool) -> bool: + cool = CoolMasterNet(host, DEFAULT_PORT, send_initial_line_feed=send_wakeup_prompt) units = await cool.status() return bool(units) @@ -45,6 +49,14 @@ class CoolmasterConfigFlow(ConfigFlow, domain=DOMAIN): VERSION = 1 + def _get_data_schema(self) -> vol.Schema: + schema_dict = DATA_SCHEMA.copy() + + if self.show_advanced_options: + schema_dict[vol.Required(CONF_SEND_WAKEUP_PROMPT, default=False)] = bool + + return vol.Schema(schema_dict) + @callback def _async_get_entry(self, data: dict[str, Any]) -> ConfigFlowResult: supported_modes = [ @@ -57,6 +69,7 @@ class CoolmasterConfigFlow(ConfigFlow, domain=DOMAIN): CONF_PORT: DEFAULT_PORT, CONF_SUPPORTED_MODES: supported_modes, CONF_SWING_SUPPORT: data[CONF_SWING_SUPPORT], + CONF_SEND_WAKEUP_PROMPT: data.get(CONF_SEND_WAKEUP_PROMPT, False), }, ) @@ -64,15 +77,19 @@ class CoolmasterConfigFlow(ConfigFlow, domain=DOMAIN): self, user_input: dict[str, Any] | None = None ) -> ConfigFlowResult: """Handle a flow initialized by the user.""" + data_schema = self._get_data_schema() + if user_input is None: - return self.async_show_form(step_id="user", data_schema=DATA_SCHEMA) + return self.async_show_form(step_id="user", data_schema=data_schema) errors = {} host = user_input[CONF_HOST] try: - result = await _validate_connection(host) + result = await _validate_connection( + host, user_input.get(CONF_SEND_WAKEUP_PROMPT, False) + ) if not result: errors["base"] = "no_units" except OSError: @@ -80,7 +97,7 @@ class CoolmasterConfigFlow(ConfigFlow, domain=DOMAIN): if errors: return self.async_show_form( - step_id="user", data_schema=DATA_SCHEMA, errors=errors + step_id="user", data_schema=data_schema, errors=errors ) return self._async_get_entry(user_input) diff --git a/homeassistant/components/coolmaster/const.py b/homeassistant/components/coolmaster/const.py index 567b7e9f13b..ce6fe45adc4 100644 --- a/homeassistant/components/coolmaster/const.py +++ b/homeassistant/components/coolmaster/const.py @@ -6,5 +6,6 @@ DEFAULT_PORT = 10102 CONF_SUPPORTED_MODES = "supported_modes" CONF_SWING_SUPPORT = "swing_support" +CONF_SEND_WAKEUP_PROMPT = "send_wakeup_prompt" MAX_RETRIES = 3 BACKOFF_BASE_DELAY = 2 diff --git a/homeassistant/components/coolmaster/manifest.json b/homeassistant/components/coolmaster/manifest.json index 6b1839771bd..f68aea9fb29 100644 --- a/homeassistant/components/coolmaster/manifest.json +++ b/homeassistant/components/coolmaster/manifest.json @@ -7,5 +7,5 @@ "integration_type": "hub", "iot_class": "local_polling", "loggers": ["pycoolmasternet_async"], - "requirements": ["pycoolmasternet-async==0.2.2"] + "requirements": ["pycoolmasternet-async==0.2.4"] } diff --git a/homeassistant/components/coolmaster/strings.json b/homeassistant/components/coolmaster/strings.json index 77c5765ab78..3697f50efb9 100644 --- a/homeassistant/components/coolmaster/strings.json +++ b/homeassistant/components/coolmaster/strings.json @@ -14,10 +14,12 @@ "heat_cool": "Support automatic heat/cool mode", "host": "[%key:common::config_flow::data::host%]", "off": "Can be turned off", + "send_wakeup_prompt": "Send wakeup prompt", "swing_support": "Control swing mode" }, "data_description": { - "host": "The hostname or IP address of your CoolMasterNet device." + "host": "The hostname or IP address of your CoolMasterNet device.", + "send_wakeup_prompt": "Send the coolmaster unit an empty commaand before issuing any actual command. This is required for serial models." }, "description": "Set up your CoolMasterNet connection details." } diff --git a/requirements_all.txt b/requirements_all.txt index 55f095ff04a..e6feb79e225 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1946,7 +1946,7 @@ pycmus==0.1.1 pycomfoconnect==0.5.1 # homeassistant.components.coolmaster -pycoolmasternet-async==0.2.2 +pycoolmasternet-async==0.2.4 # homeassistant.components.radio_browser pycountry==24.6.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index f0a922da75f..67b2da6c255 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1653,7 +1653,7 @@ pycfdns==3.0.0 pycomfoconnect==0.5.1 # homeassistant.components.coolmaster -pycoolmasternet-async==0.2.2 +pycoolmasternet-async==0.2.4 # homeassistant.components.radio_browser pycountry==24.6.1 diff --git a/tests/components/coolmaster/test_config_flow.py b/tests/components/coolmaster/test_config_flow.py index 83a074815b5..4439c2b5a33 100644 --- a/tests/components/coolmaster/test_config_flow.py +++ b/tests/components/coolmaster/test_config_flow.py @@ -9,18 +9,34 @@ from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResultType -def _flow_data(): +def _flow_data(advanced=False): options = {"host": "1.1.1.1"} for mode in AVAILABLE_MODES: options[mode] = True options["swing_support"] = False + if advanced: + options["send_wakeup_prompt"] = True return options -async def test_form(hass: HomeAssistant) -> None: +async def test_form_non_advanced(hass: HomeAssistant) -> None: + """Test we get the form in non-advanced mode.""" + await form_base(hass, advanced=False) + + +async def test_form_advanced(hass: HomeAssistant) -> None: + """Test we get the form in advanced mode.""" + await form_base(hass, advanced=True) + + +async def form_base(hass: HomeAssistant, advanced: bool) -> None: """Test we get the form.""" result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": config_entries.SOURCE_USER} + DOMAIN, + context={ + "source": config_entries.SOURCE_USER, + "show_advanced_options": advanced, + }, ) assert result["type"] is FlowResultType.FORM assert result["errors"] is None @@ -36,18 +52,22 @@ async def test_form(hass: HomeAssistant) -> None: ) as mock_setup_entry, ): result2 = await hass.config_entries.flow.async_configure( - result["flow_id"], _flow_data() + result["flow_id"], _flow_data(advanced) ) await hass.async_block_till_done() assert result2["type"] is FlowResultType.CREATE_ENTRY assert result2["title"] == "1.1.1.1" - assert result2["data"] == { + _expected_data = { "host": "1.1.1.1", "port": 10102, "supported_modes": AVAILABLE_MODES, "swing_support": False, + "send_wakeup_prompt": False, } + if advanced: + _expected_data["send_wakeup_prompt"] = True + assert result2["data"] == _expected_data assert len(mock_setup_entry.mock_calls) == 1