diff --git a/CHANGELOG.md b/CHANGELOG.md index c8e70aabc..a3cbe5d53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v0.37.8 + +- Create a set_select() function, combining the set_dhw_mode(), set_gateway_mode(), set_regulation_mode() and set_schedule_state() functions. + ## v0.37.7 - Don't output schedule-related data when no valid schedule(s) found. @@ -17,6 +21,8 @@ ## v0.37.4 - not released +- Create a set_number() function, combining the set_number_setpoint() and set_temperature_offset() functions. + ## v0.37.3 - Fix for [plugwise-beta #620](https://github.com/plugwise/plugwise-beta/issues/620). diff --git a/plugwise/__init__.py b/plugwise/__init__.py index 9ccbf8335..245aadae1 100644 --- a/plugwise/__init__.py +++ b/plugwise/__init__.py @@ -306,6 +306,16 @@ async def async_update(self) -> PlugwiseData: ### API Set and HA Service-related Functions ### ######################################################################################################## + async def set_select( + self, + key: str, + loc_id: str, + option: str, + name: str | None = None, + ) -> None: + """Set the selected option for the applicable Select.""" + await self._smile_api.set_select(key, loc_id, option, name) + async def set_schedule_state( self, loc_id: str, @@ -344,15 +354,15 @@ async def set_switch_state( async def set_gateway_mode(self, mode: str) -> None: """Set the gateway mode.""" - await self._smile_api.set_gateway_mode(mode) + await self._smile_api.set_gateway_mode(mode) # pragma: no cover async def set_regulation_mode(self, mode: str) -> None: """Set the heating regulation mode.""" - await self._smile_api.set_regulation_mode(mode) + await self._smile_api.set_regulation_mode(mode) # pragma: no cover async def set_dhw_mode(self, mode: str) -> None: """Set the domestic hot water heating regulation mode.""" - await self._smile_api.set_dhw_mode(mode) + await self._smile_api.set_dhw_mode(mode) # pragma: no cover async def delete_notification(self) -> None: """Delete the active Plugwise Notification.""" diff --git a/plugwise/legacy/smile.py b/plugwise/legacy/smile.py index 293f0dfb3..6bb8f6854 100644 --- a/plugwise/legacy/smile.py +++ b/plugwise/legacy/smile.py @@ -182,6 +182,12 @@ async def set_preset(self, _: str, preset: str) -> None: async def set_regulation_mode(self, mode: str) -> None: """Set-function placeholder for legacy devices.""" + async def set_select(self, key: str, loc_id: str, option: str, name: str | None) -> None: + """Set the thermostat schedule option.""" + # schedule state corresponds to select option + # schedule name corresponds to select name + await self.set_schedule_state("dummy", option, name) + async def set_schedule_state(self, _: str, state: str, name: str | None) -> None: """Activate/deactivate the Schedule. diff --git a/plugwise/smile.py b/plugwise/smile.py index e1cbdc359..e26d90ab7 100644 --- a/plugwise/smile.py +++ b/plugwise/smile.py @@ -149,39 +149,6 @@ async def delete_notification(self) -> None: """Delete the active Plugwise Notification.""" await self._request(NOTIFICATIONS, method="delete") - async def set_dhw_mode(self, mode: str) -> None: - """Set the domestic hot water heating regulation mode.""" - if mode not in self._dhw_allowed_modes: - raise PlugwiseError("Plugwise: invalid dhw mode.") - - uri = f"{APPLIANCES};type=heater_central/domestic_hot_water_mode_control" - data = f"{mode}" - - await self._request(uri, method="put", data=data) - - async def set_gateway_mode(self, mode: str) -> None: - """Set the gateway mode.""" - if mode not in self._gw_allowed_modes: - raise PlugwiseError("Plugwise: invalid gateway mode.") - - end_time = "2037-04-21T08:00:53.000Z" - valid = "" - if mode == "away": - time_1 = self._domain_objects.find("./gateway/time").text - away_time = dt.datetime.fromisoformat(time_1).astimezone(dt.UTC).isoformat(timespec="milliseconds").replace("+00:00", "Z") - valid = ( - f"{away_time}{end_time}" - ) - if mode == "vacation": - time_2 = str(dt.date.today() - dt.timedelta(1)) - vacation_time = time_2 + "T23:00:00.000Z" - valid = f"{vacation_time}{end_time}" - - uri = f"{APPLIANCES};id={self.gateway_id}/gateway_mode_control" - data = f"{mode}{valid}" - - await self._request(uri, method="put", data=data) - async def set_number( self, dev_id: str, @@ -241,6 +208,53 @@ async def set_preset(self, loc_id: str, preset: str) -> None: await self._request(uri, method="put", data=data) + async def set_select(self, key: str, loc_id: str, option: str, name: str | None) -> None: + """Set a dhw/gateway/regulation mode or the thermostat schedule option.""" + match key: + case "select_dhw_mode": + await self.set_dhw_mode(option) + case "select_gateway_mode": + await self.set_gateway_mode(option) + case "select_regulation_mode": + await self.set_regulation_mode(option) + case "select_schedule": + # schedule state corresponds to select option + # schedule name corresponds to select name + await self.set_schedule_state(loc_id, option, name) + + async def set_dhw_mode(self, mode: str) -> None: + """Set the domestic hot water heating regulation mode.""" + if mode not in self._dhw_allowed_modes: + raise PlugwiseError("Plugwise: invalid dhw mode.") + + uri = f"{APPLIANCES};type=heater_central/domestic_hot_water_mode_control" + data = f"{mode}" + + await self._request(uri, method="put", data=data) + + async def set_gateway_mode(self, mode: str) -> None: + """Set the gateway mode.""" + if mode not in self._gw_allowed_modes: + raise PlugwiseError("Plugwise: invalid gateway mode.") + + end_time = "2037-04-21T08:00:53.000Z" + valid = "" + if mode == "away": + time_1 = self._domain_objects.find("./gateway/time").text + away_time = dt.datetime.fromisoformat(time_1).astimezone(dt.UTC).isoformat(timespec="milliseconds").replace("+00:00", "Z") + valid = ( + f"{away_time}{end_time}" + ) + if mode == "vacation": + time_2 = str(dt.date.today() - dt.timedelta(1)) + vacation_time = time_2 + "T23:00:00.000Z" + valid = f"{vacation_time}{end_time}" + + uri = f"{APPLIANCES};id={self.gateway_id}/gateway_mode_control" + data = f"{mode}{valid}" + + await self._request(uri, method="put", data=data) + async def set_regulation_mode(self, mode: str) -> None: """Set the heating regulation mode.""" if mode not in self._reg_allowed_modes: @@ -258,7 +272,7 @@ async def set_schedule_state( self, loc_id: str, new_state: str, - name: str | None = None, + name: str | None, ) -> None: """Activate/deactivate the Schedule, with the given name, on the relevant Thermostat. diff --git a/pyproject.toml b/pyproject.toml index ada21a99a..295d235b9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "plugwise" -version = "0.37.7" +version = "0.37.8" license = {file = "LICENSE"} description = "Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3." readme = "README.md" diff --git a/tests/test_init.py b/tests/test_init.py index fbc6cc727..45fc05469 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -733,7 +733,7 @@ async def tinker_thermostat_schedule( new_schedule = new_schedule[1:] _LOGGER.info("- Adjusting schedule to %s", f"{new_schedule}{warning}") try: - await smile.set_schedule_state(loc_id, state, new_schedule) + await smile.set_select("select_schedule", loc_id, state, new_schedule) tinker_schedule_passed = True _LOGGER.info(" + working as intended") except pw_exceptions.PlugwiseError: @@ -763,7 +763,7 @@ async def tinker_legacy_thermostat_schedule(self, smile, unhappy=False): for state in states: _LOGGER.info("- Adjusting schedule to state %s", state) try: - await smile.set_schedule_state(None, state) + await smile.set_select("select_schedule", "dummy", state) tinker_schedule_passed = True _LOGGER.info(" + working as intended") except pw_exceptions.PlugwiseError: @@ -847,7 +847,7 @@ async def tinker_dhw_mode(smile): mode = mode[1:] _LOGGER.info("%s", f"- Adjusting dhw mode to {mode}{warning}") try: - await smile.set_dhw_mode(mode) + await smile.set_select("select_dhw_mode", "dummy", mode) _LOGGER.info(" + tinker_dhw_mode worked as intended") except pw_exceptions.PlugwiseError: _LOGGER.info(" + tinker_dhw_mode found invalid mode, as expected") @@ -862,7 +862,7 @@ async def tinker_regulation_mode(smile): mode = mode[1:] _LOGGER.info("%s", f"- Adjusting regulation mode to {mode}{warning}") try: - await smile.set_regulation_mode(mode) + await smile.set_select("select_regulation_mode", "dummy", mode) _LOGGER.info(" + tinker_regulation_mode worked as intended") except pw_exceptions.PlugwiseError: _LOGGER.info( @@ -904,7 +904,7 @@ async def tinker_gateway_mode(smile): mode = mode[1:] _LOGGER.info("%s", f"- Adjusting gateway mode to {mode}{warning}") try: - await smile.set_gateway_mode(mode) + await smile.set_select("select_gateway_mode", "dummy", mode) _LOGGER.info(" + worked as intended") except pw_exceptions.PlugwiseError: _LOGGER.info(" + found invalid mode, as expected")