diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 5a8b8758..67762806 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -5,17 +5,10 @@ labels: new bug assignees: kartoffeltoby --- -### Prerequisites - -* [ ] Model name of your Devices -* [ ] Output from Home Assistant Developer Tools state e.g. -* [ ] Output from Home Assistant Device Diagnostic from BT - -```json -{ - YOUR DEVICE DIAGNOSTICS JSON OUTPUT HERE -} -``` + ### Description @@ -35,9 +28,50 @@ assignees: kartoffeltoby -### Versions +### Versions and HW + + +Home Assistant: +Better Thermostat: + +TRV(s): + +### Debug data + +**diagnostic data** + + +```json +{ + YOUR DEVICE DIAGNOSTICS JSON OUTPUT HERE +} +``` + +**debug log** + + + - +**graphs** + ### Additional Information diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index daffe9b7..a72ce770 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -5,7 +5,7 @@ ## Related issue (check one): - [ ] fixes # -- [ ] there is no related issue ticket +- [ ] There is no related issue ticket ## Checklist (check one): @@ -14,7 +14,7 @@ ## Test-Hardware list (for code changes) - + HA Version: Zigbee2MQTT Version: @@ -22,9 +22,9 @@ TRV Hardware: ## New device mappings - + - [ ] I avoided any changes to other device mappings - [ ] There are no changes in `climate.py` - + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 633e94bc..abe633e3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,16 +23,16 @@ document in a pull request. #### Nice to know -- Debuging is possible with the VSCode Debuger. Just run the HomeAssistant in Debugger and open browser on http://localhost:9123 (No task run needed) +- Debugging is possible with the VSCode Debugger. Just run the HomeAssistant in Debugger and open your browser to http://localhost:9123 (No task run needed) - Update your local in devcontainer configuration.yaml to the current version of the repository to get the latest changes. -> Run "Sync configuration.yaml (Override local)" in Task Runner -- Test BT in a specific HA version -> Run "Install a specific version of Home Assistant" in Task Runner and the the version you want to test in the terminal promt. -- Test BT with the latest HA version -> Run "pgrade Home Assistant to latest dev" in Task Runner +- Test BT in a specific HA version -> Run "Install a specific version of Home Assistant" in Task Runner and the version you want to test in the terminal prompt. +- Test BT with the latest HA version -> Run "upgrade Home Assistant to latest dev" in Task Runner ## How Can I Contribute? ## New Adapter -If you want to add a new adapter, please create a new python file with the name of the adapter in the adapters folder. The file should contain all functions find in the generic.py. The if you adapter needs a special handling for one of the base functions, override it, if you can use generic functions, use them like: +If you want to add a new adapter, please create a new Python file with the name of the adapter in the adapters folder. The file should contain all functions found in the generic.py. If your adapter needs special handling for one of the base functions, override it, if you can use generic functions, use them like: ```python async def set_temperature(self, entity_id, temperature): @@ -55,4 +55,4 @@ https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_numpy.html ## Setup -Install the pip install pre-commit used for pre-commit hooks. \ No newline at end of file +Install the pip install pre-commit used for pre-commit hooks. diff --git a/custom_components/better_thermostat/calibration.py b/custom_components/better_thermostat/calibration.py index 097d02f6..2c5d682c 100644 --- a/custom_components/better_thermostat/calibration.py +++ b/custom_components/better_thermostat/calibration.py @@ -11,7 +11,6 @@ from custom_components.better_thermostat.utils.helpers import ( convert_to_float, - round_down_to_half_degree, round_by_steps, heating_power_valve_position, ) @@ -42,6 +41,9 @@ def calculate_calibration_local(self, entity_id) -> float | None: """ _context = "_calculate_calibration_local()" + def _convert_to_float(value): + return convert_to_float(value, self.name, _context) + if None in (self.cur_temp, self.bt_target_temp): return None @@ -59,11 +61,9 @@ def calculate_calibration_local(self, entity_id) -> float | None: _cur_external_temp = self.cur_temp _cur_target_temp = self.bt_target_temp - _cur_trv_temp_f = convert_to_float(str(_cur_trv_temp_s), self.device_name, _context) + _cur_trv_temp_f = _convert_to_float(_cur_trv_temp_s) - _current_trv_calibration = convert_to_float( - str(self.real_trvs[entity_id]["last_calibration"]), self.device_name, _context - ) + _current_trv_calibration = _convert_to_float(self.real_trvs[entity_id]["last_calibration"]) if None in ( _current_trv_calibration, @@ -126,17 +126,13 @@ def calculate_calibration_local(self, entity_id) -> float | None: # Adjust based on the steps allowed by the local calibration entity _new_trv_calibration = round_by_steps(_new_trv_calibration, _calibration_steps) - # Compare against min/max - if _new_trv_calibration > float(self.real_trvs[entity_id]["local_calibration_max"]): - _new_trv_calibration = float(self.real_trvs[entity_id]["local_calibration_max"]) - elif _new_trv_calibration < float( - self.real_trvs[entity_id]["local_calibration_min"] - ): - _new_trv_calibration = float(self.real_trvs[entity_id]["local_calibration_min"]) + # limit new setpoint within min/max of the TRV's range + t_min = float(self.real_trvs[entity_id]["local_calibration_min"]) + t_max = float(self.real_trvs[entity_id]["local_calibration_max"]) + _new_trv_calibration = max(t_min, min(_new_trv_calibration, t_max)) - _new_trv_calibration = convert_to_float( - str(_new_trv_calibration), self.device_name, _context - ) + + _new_trv_calibration = _convert_to_float(_new_trv_calibration) _logmsg = ( "better_thermostat %s: %s - new local calibration: %s | external_temp: %s, " @@ -188,6 +184,7 @@ def calculate_calibration_setpoint(self, entity_id) -> float | None: _cur_external_temp = self.cur_temp _cur_target_temp = self.bt_target_temp + _trv_temp_steps = 1 / ( self.real_trvs[entity_id]["target_temp_step"] or 0.5 ) if None in (_cur_target_temp, _cur_external_temp, _cur_trv_temp_s): return None @@ -236,13 +233,12 @@ def calculate_calibration_setpoint(self, entity_id) -> float | None: _cur_external_temp - (_cur_target_temp + self.tolerance) ) * 8.0 # Reduced from 10.0 since we already subtract 2.0 - _calibrated_setpoint = round_down_to_half_degree(_calibrated_setpoint) + _calibrated_setpoint = round_by_steps(_calibrated_setpoint, _trv_temp_steps) - # check if new setpoint is inside the TRV's range, else set to min or max - if _calibrated_setpoint < self.real_trvs[entity_id]["min_temp"]: - _calibrated_setpoint = self.real_trvs[entity_id]["min_temp"] - if _calibrated_setpoint > self.real_trvs[entity_id]["max_temp"]: - _calibrated_setpoint = self.real_trvs[entity_id]["max_temp"] + # limit new setpoint within min/max of the TRV's range + t_min = self.real_trvs[entity_id]["min_temp"] + t_max = self.real_trvs[entity_id]["max_temp"] + _calibrated_setpoint = max(t_min, min(_calibrated_setpoint, t_max)) _logmsg = ( "better_thermostat %s: %s - new setpoint calibration: %s | external_temp: %s, " diff --git a/custom_components/better_thermostat/climate.py b/custom_components/better_thermostat/climate.py index 8c6ca8a2..0672b7d5 100644 --- a/custom_components/better_thermostat/climate.py +++ b/custom_components/better_thermostat/climate.py @@ -859,7 +859,7 @@ async def startup(self): ) self.real_trvs[trv]["target_temp_step"] = convert_to_float( str( - self.hass.states.get(trv).attributes.get("target_temp_step", 1) + self.hass.states.get(trv).attributes.get("target_temp_step", 0.5) ), self.device_name, "startup", @@ -1105,7 +1105,7 @@ def target_temperature_step(self) -> float | None: Returns ------- float - Steps of target temperature. + Step size of target temperature. """ if self.bt_target_temp_step is not None: return self.bt_target_temp_step diff --git a/custom_components/better_thermostat/config_flow.py b/custom_components/better_thermostat/config_flow.py index 4e731093..2c924ee5 100644 --- a/custom_components/better_thermostat/config_flow.py +++ b/custom_components/better_thermostat/config_flow.py @@ -21,7 +21,7 @@ CONF_CHILD_LOCK, CONF_HEAT_AUTO_SWAPPED, CONF_HEATER, - CONF_HOMATICIP, + CONF_HOMEMATICIP, CONF_HUMIDITY, CONF_MODEL, CONF_NO_SYSTEM_MODE_OFF, @@ -246,7 +246,7 @@ async def async_step_advanced(self, user_input=None, _trv_config=None): ] = bool fields[ vol.Optional( - CONF_HOMATICIP, default=user_input.get(CONF_HOMATICIP, homematic) + CONF_HOMEMATICIP, default=user_input.get(CONF_HOMEMATICIP, homematic) ) ] = bool @@ -523,8 +523,8 @@ async def async_step_advanced( ] = bool fields[ vol.Optional( - CONF_HOMATICIP, - default=_trv_config["advanced"].get(CONF_HOMATICIP, homematic), + CONF_HOMEMATICIP, + default=_trv_config["advanced"].get(CONF_HOMEMATICIP, homematic), ) ] = bool diff --git a/custom_components/better_thermostat/diagnostics.py b/custom_components/better_thermostat/diagnostics.py index 780aa4ca..c60c7f82 100644 --- a/custom_components/better_thermostat/diagnostics.py +++ b/custom_components/better_thermostat/diagnostics.py @@ -19,16 +19,18 @@ async def async_get_config_entry_diagnostics( trv = hass.states.get(trv_id["trv"]) if trv is None: continue - _adapter_name = await load_adapter( - hass, trv_id["integration"], trv_id["trv"], True - ) - trv_id["adapter"] = _adapter_name + # TODO: this does nothing but return trv_id["integration"] as adapter_name + # -> removing this for now, to fix diagnostic export + # _adapter_name = await load_adapter( + # hass, trv_id["integration"], trv_id["trv"], True + # ) + # trv_id["adapter"] = _adapter_name trvs[trv_id["trv"]] = { "name": trv.name, "state": trv.state, "attributes": trv.attributes, "bt_config": trv_id["advanced"], - "bt_adapter": trv_id["adapter"], + # "bt_adapter": trv_id["adapter"], "bt_integration": trv_id["integration"], "model": trv_id["model"], } diff --git a/custom_components/better_thermostat/events/temperature.py b/custom_components/better_thermostat/events/temperature.py index f3edc012..6ea067b9 100644 --- a/custom_components/better_thermostat/events/temperature.py +++ b/custom_components/better_thermostat/events/temperature.py @@ -1,6 +1,6 @@ import logging -from custom_components.better_thermostat.utils.const import CONF_HOMATICIP +from custom_components.better_thermostat.utils.const import CONF_HOMEMATICIP from ..utils.helpers import convert_to_float from datetime import datetime from homeassistant.helpers import issue_registry as ir @@ -41,7 +41,7 @@ async def trigger_temperature_change(self, event): try: for trv in self.all_trvs: - if trv["advanced"][CONF_HOMATICIP]: + if trv["advanced"][CONF_HOMEMATICIP]: _time_diff = 600 except KeyError: pass diff --git a/custom_components/better_thermostat/events/trv.py b/custom_components/better_thermostat/events/trv.py index 0a8543f0..9611892c 100644 --- a/custom_components/better_thermostat/events/trv.py +++ b/custom_components/better_thermostat/events/trv.py @@ -1,7 +1,7 @@ import asyncio from datetime import datetime import logging -from custom_components.better_thermostat.utils.const import CONF_HOMATICIP +from custom_components.better_thermostat.utils.const import CONF_HOMEMATICIP from homeassistant.components.climate.const import ( HVACMode, @@ -75,7 +75,7 @@ async def trigger_trv_change(self, event): _time_diff = 5 try: for trv in self.all_trvs: - if trv["advanced"][CONF_HOMATICIP]: + if trv["advanced"][CONF_HOMEMATICIP]: _time_diff = 600 except KeyError: pass @@ -227,7 +227,7 @@ async def update_hvac_action(self): # i don't know why this is here just for hometicip / wtom - 2023-08-23 # for trv in self.all_trvs: - # if trv["advanced"][CONF_HOMATICIP]: + # if trv["advanced"][CONF_HOMEMATICIP]: # entity_id = trv["trv"] # state = self.hass.states.get(entity_id) # if state is None: diff --git a/custom_components/better_thermostat/strings.json b/custom_components/better_thermostat/strings.json index bc7b8cc3..e16f0574 100644 --- a/custom_components/better_thermostat/strings.json +++ b/custom_components/better_thermostat/strings.json @@ -10,30 +10,30 @@ "temperature_sensor": "Temperature sensor", "humidity_sensor": "Humidity sensor", "window_sensors": "Window sensor", - "off_temperature": "The outdoor temperature when the thermostat turn off", - "tolerance": "Tolerance, to prevent the thermostat from turning on and off too often.", - "window_off_delay": "Delay before the thermostat turn off when the window is opened", - "window_off_delay_after": "Delay before the thermostat turn on when the window is closed", - "outdoor_sensor": "If you have an outdoor sensor, you can use it to get the outdoor temperature", - "weather": "Your weather entity to get the outdoor temperature" + "off_temperature": "The outdoor temperature when the thermostat should turn off", + "tolerance": "Tolerance, to prevent the thermostat from turning on and off too often", + "window_off_delay": "Delay before the thermostat should turn off when the window is opened", + "window_off_delay_after": "Delay before the thermostat should turn on when the window is closed", + "outdoor_sensor": "Outdoor temperature sensor", + "weather": "Weather entity to get the outdoor temperature" } }, "advanced": { "description": "Advanced configuration {trv}\n***Info about calibration types: https://better-thermostat.org/configuration#second-step***", "data": { "protect_overheating": "Overheating protection?", - "heat_auto_swapped": "If the auto means heat for your TRV and you want to swap it", + "heat_auto_swapped": "If 'auto' means 'heat' for your TRV and you want to swap it", "child_lock": "Ignore all inputs on the TRV like a child lock", - "homaticip": "If you use HomaticIP, you should enable this to slow down the requests to prevent the duty cycle", + "homematicip": "If you use HomematicIP, you should enable this to slow down the requests to prevent the duty cycle", "valve_maintenance": "If your thermostat has no own maintenance mode, you can use this one", - "calibration": "Calibration Type", + "calibration": "Calibration type", "calibration_mode": "Calibration mode", - "no_off_system_mode": "If your TRV can't handle the off mode, you can enable this to use target temperature 5°C instead" + "no_off_system_mode": "If your TRV doesn't support the 'off' mode, enable this to use target temperature 5°C instead" }, "data_description": { - "protect_overheating": "Some TRVs don't close the valve completly when the temperature is reached. Or the radiator have a lot of rest heat. This can cause overheating. This option can prevent this.", - "calibration_mode": "The kind how the calibration should be calculated\n***Normal***: In this mode the TRV internal temperature sensor is fixed by the external temperature sensor.\n***Aggresive***: In this mode the TRV internal temperature sensor is fixed by the external temperature sensor but set much lower/higher to get a quicker boost.\n***AI Time Based***: In this mode the TRV internal temperature sensor is fixed by the external temperature sensor, but the value is calculated by a custom algorithm to improve the TRV internal algorithm.", - "calibration": "How the calibration should be applied on the TRV (Target temp or offset)\n***Target Temperature Based***: Apply the calibration to the target temperature.\n***Offset Based***: Apply the calibration to the offset." + "protect_overheating": "Some TRVs don't close the valve completely when the temperature is reached. Or the radiator has a lot of rest heat. This can cause overheating. This option can prevent this.", + "calibration_mode": "How the calibration is calculated\n***Normal***: In this mode, the TRV internal temperature sensor is fixed by the external temperature sensor.\n***Aggresive***: In this mode, the TRV internal temperature sensor is fixed by the external temperature sensor but set much lower/higher to get a quicker boost.\n***AI Time Based***: In this mode, the TRV internal temperature sensor is fixed by the external temperature sensor, but the value is calculated by a custom algorithm to improve the TRV internal algorithm.", + "calibration": "How the calibration is applied on the TRV\n***Target Temperature Based***: Apply the calibration to the target temperature.\n***Offset Based***: Apply the calibration to the temperature offset." } }, "confirm": { @@ -44,12 +44,12 @@ "error": { "failed": "Something went wrong.", "no_name": "Please enter a name.", - "no_off_mode": "You device is very special and has no off mode :(\nBetter Thermostat will use the minimal target temp instead.", + "no_off_mode": "Your device is special and has no off mode :(\nBetter Thermostat will use the minimal target temp instead.", "no_outside_temp": "You have no outside temperature sensor. Better Thermostat will use the weather entity instead." }, "abort": { - "single_instance_allowed": "Only a single Thermostat for each real is allowed.", - "no_devices_found": "No thermostat entity found, make sure you have a climate entity in your home assistant" + "single_instance_allowed": "Only a single Better Thermostat is allowed for each real thermostat.", + "no_devices_found": "No thermostat entity found, make sure you have a climate entity in your Home Assistant" } }, "options": { @@ -62,17 +62,17 @@ "temperature_sensor": "Temperature Sensor", "humidity_sensor": "Humidity sensor", "window_sensors": "Window Sensor", - "off_temperature": "The outdoor temperature when the thermostat turns off", - "tolerance": "Tolerance, to prevent the thermostat from turning on and off too often.", - "window_off_delay": "Delay before the thermostat turns off when the window is opened", - "window_off_delay_after": "Delay before the thermostat turns on when the window is closed", - "outdoor_sensor": "If you have an outdoor sensor, you can use it to get the outdoor temperature", + "off_temperature": "The outdoor temperature when the thermostat should turn off", + "tolerance": "Tolerance, to prevent the thermostat from turning on and off too often", + "window_off_delay": "Delay before the thermostat should turn off when the window is opened", + "window_off_delay_after": "Delay before the thermostat should turn on when the window is closed", + "outdoor_sensor": "Outdoor temperature sensor", + "weather": "Weather entity to get the outdoor temperature" "valve_maintenance": "If your thermostat has no own maintenance mode, you can use this one", "calibration": "The sort of calibration https://better-thermostat.org/configuration#second-step", - "weather": "Your weather entity to get the outdoor temperature", "heat_auto_swapped": "If the auto means heat for your TRV and you want to swap it", "child_lock": "Ignore all inputs on the TRV like a child lock", - "homaticip": "If you use HomaticIP, you should enable this to slow down the requests to prevent the duty cycle" + "homematicip": "If you use HomematicIP, you should enable this to slow down the requests to prevent the duty cycle" } }, "advanced": { @@ -81,17 +81,16 @@ "protect_overheating": "Overheating protection?", "heat_auto_swapped": "If the auto means heat for your TRV and you want to swap it", "child_lock": "Ignore all inputs on the TRV like a child lock", - "homaticip": "If you use HomaticIP, you should enable this to slow down the requests to prevent the duty cycle", + "homematicip": "If you use HomematicIP, you should enable this to slow down the requests to prevent the duty cycle", "valve_maintenance": "If your thermostat has no own maintenance mode, you can use this one", - "calibration": "The sort of calibration you want to use", + "calibration": "Calibration type", "calibration_mode": "Calibration mode", - "no_off_system_mode": "If your TRV can't handle the off mode, you can enable this to use target temperature 5°C instead" + "no_off_system_mode": "If your TRV doesn't support the 'off' mode, enable this to use target temperature 5°C instead" }, "data_description": { "protect_overheating": "Some TRVs don't close the valve completely when the temperature is reached. Or the radiator has a lot of rest heat. This can cause overheating. This option can prevent this.", - "calibration_mode": "The kind how the calibration should be calculated\n***Normal***: In this mode, the TRV internal temperature sensor is fixed by the external temperature sensor.\n***Aggresive***: In this mode, the TRV internal temperature sensor is fixed by the external temperature sensor but set much lower/higher to get a quicker boost.\n***AI Time Based***: In this mode, the TRV internal temperature sensor is fixed by the external temperature sensor, but a custom algorithm calculates the value to improve the TRV internal algorithm.", - "calibration": "How the calibration should be applied on the TRV (Target temp or offset)\n***Target Temperature Based***: Apply the calibration to the target temperature.\n***Offset Based***: Apply the calibration to the offset." - } + "calibration_mode": "How the calibration is calculated\n***Normal***: In this mode, the TRV internal temperature sensor is fixed by the external temperature sensor.\n***Aggresive***: In this mode, the TRV internal temperature sensor is fixed by the external temperature sensor but set much lower/higher to get a quicker boost.\n***AI Time Based***: In this mode, the TRV internal temperature sensor is fixed by the external temperature sensor, but the value is calculated by a custom algorithm to improve the TRV internal algorithm.", + "calibration": "How the calibration is applied on the TRV\n***Target Temperature Based***: Apply the calibration to the target temperature.\n***Offset Based***: Apply the calibration to the temperature offset." } } } }, @@ -123,7 +122,7 @@ }, "set_temp_target_temperature": { "name": "Set eco temperature", - "description": "Set the target temperature to a temporay like night mode, and save the old one." + "description": "Set the target temperature to a temporary like night mode, and save the old one." } } } diff --git a/custom_components/better_thermostat/translations/da.json b/custom_components/better_thermostat/translations/da.json index 6b4935e1..1f9c5777 100644 --- a/custom_components/better_thermostat/translations/da.json +++ b/custom_components/better_thermostat/translations/da.json @@ -7,30 +7,33 @@ "data": { "name": "Navn", "thermostat": "Den rigtige termostat", + "cooler": "Køleenhed (valgfri)", "temperature_sensor": "Temperatur måler", "humidity_sensor": "Fugtighedssensor", "window_sensors": "Vinduessensor", "off_temperature": "Udetemperaturen, når termostaten slukker", + "tolerance": "Tolerancen for at forhindre, at termostaten tænder og slukker for ofte.", "window_off_delay": "Forsinkelse, før termostaten slukker, når vinduet er åbent, og tændt, når vinduet er lukket", + "window_off_delay_after": "Forsinkelse, før termostaten tænder, når vinduet er lukket", "outdoor_sensor": "Hvis du har en udeføler, kan du bruge den til at få udetemperaturen", "weather": "Din vejrentitet for at få udendørstemperaturen" } }, "advanced": { - "description": "Avanceret konfiguration\n\n**Info om kalibreringstyper: https://better-thermostat.org/configuration#second-step** ", + "description": "Avanceret konfiguration {trv}\n***Info om kalibreringstyper: https://better-thermostat.org/configuration#second-step*** ", "data": { + "protect_overheating": "Overophedningsbeskyttelse?", "heat_auto_swapped": "Hvis auto betyder varme for din TRV og du vil bytte det", "child_lock": "Ignorer alle input på TRV som en børnesikring", - "homaticip": "Hvis du bruger HomaticIP, bør du aktivere dette for at bremse anmodningerne for at forhindre arbejdscyklus", + "homematicip": "Hvis du bruger HomematicIP, bør du aktivere dette for at bremse anmodningerne for at forhindre arbejdscyklus", "valve_maintenance": "Hvis din termostat ikke har nogen egen vedligeholdelsestilstand, kan du bruge denne", "calibration": "Den slags kalibrering du vil bruge", - "no_off_system_mode": "Hvis din TRV ikke kan håndtere den slukkede tilstand, kan du aktivere denne for at bruge måltemperatur 5°C i stedet", "calibration_mode": "Kalibreringstilstand", - "protect_overheating": "Overophedningsbeskyttelse?" + "no_off_system_mode": "Hvis din TRV ikke kan håndtere den slukkede tilstand, kan du aktivere denne for at bruge måltemperatur 5°C i stedet" }, "data_description": { "protect_overheating": "Nogle TRV'er lukker ikke ventilen helt, når temperaturen er nået. Eller radiatoren har meget hvilevarme. Dette kan forårsage overophedning. Denne mulighed kan forhindre dette.", - "calibration_mode": "Den slags, hvordan kalibreringen skal beregnes\n***Normal***: I denne tilstand er TRV's interne temperaturføler fastgjort af den eksterne temperaturføler.\n***Aggressiv***: I denne tilstand er TRV's interne temperaturføler fikseret af den eksterne temperaturføler, men indstillet meget lavere/højere for at få et hurtigere løft.\n***AI-tidsbaseret***: I denne tilstand er TRV's interne temperatursensor fastsat af den eksterne temperatursensor, men værdien beregnes af en brugerdefineret algoritme for at forbedre TRV's interne algoritme.", + "calibration_mode": "Hvordan kalibreringen skal beregnes\n***Normal***: I denne tilstand er TRV's interne temperaturføler fastgjort af den eksterne temperaturføler.\n***Aggressiv***: I denne tilstand er TRV's interne temperaturføler fikseret af den eksterne temperaturføler, men indstillet meget lavere/højere for at få et hurtigere løft.\n***AI-tidsbaseret***: I denne tilstand er TRV's interne temperatursensor fastsat af den eksterne temperatursensor, men værdien beregnes af en brugerdefineret algoritme for at forbedre TRV's interne algoritme.", "calibration": "Hvordan kalibreringen skal anvendes på TRV (Target temp or offset)\n***Måltemperaturbaseret***: Anvend kalibreringen til måltemperaturen.\n***Offset-baseret***: Anvend kalibreringen til offset." } }, @@ -40,10 +43,10 @@ } }, "error": { - "no_outside_temp": "Du har ingen udetemperaturføler. Bedre termostat vil bruge vejret i stedet.", - "failed": "noget gik galt.", + "failed": "Noget gik galt.", "no_name": "Indtast venligst et navn.", - "no_off_mode": "Din enhed er meget speciel og har ingen slukket tilstand :(\nDet virker alligevel, men du skal oprette en automatisering, der passer til dine specialer baseret på enhedsbegivenhederne" + "no_off_mode": "Din enhed er meget speciel og har ingen slukket tilstand :(\nDet virker alligevel, men du skal oprette en automatisering, der passer til dine specialer baseret på enhedsbegivenhederne", + "no_outside_temp": "Du har ingen udetemperaturføler. Better Thermostat vil bruge vejret i stedet." }, "abort": { "single_instance_allowed": "Kun en enkelt termostat for hver virkelige er tilladt.", @@ -55,37 +58,39 @@ "user": { "description": "Opdater dine Better Thermostat indstillinger", "data": { + "name": "Navn", + "thermostat": "Den rigtige termostat", "temperature_sensor": "Temperatur måler", "humidity_sensor": "Fugtighedssensor", "window_sensors": "Vinduessensor", "off_temperature": "Udendørstemperaturen, når termostaten skal slukker", + "tolerance": "Tolerancen for at forhindre, at termostaten tænder og slukker for ofte.", "window_off_delay": "Forsinkelse, før termostaten slukker, når vinduet er åbent, og tændt, når vinduet er lukket", + "window_off_delay_after": "Forsinkelse, før termostaten tænder, når vinduet er lukket", "outdoor_sensor": "Har du en udendørsføler, kan du bruge den til at få udetemperaturen", "valve_maintenance": "Hvis din termostat ikke har nogen egen vedligeholdelsestilstand, kan du bruge denne", "calibration": "Den slags kalibrering https://better-thermostat.org/configuration#second-step", "weather": "Din vejrentitet for at få udendørstemperaturen", "heat_auto_swapped": "Hvis auto betyder varme til din TRV, og du ønsker at bytte den", "child_lock": "Ignorer alle input på TRV som en børnesikring", - "homaticip": "Hvis du bruger HomaticIP, bør du aktivere dette for at bremse anmodningerne for at forhindre arbejdscyklus", - "name": "Navn", - "thermostat": "Den rigtige termostat" + "homaticip": "Hvis du bruger HomematicIP, bør du aktivere dette for at bremse anmodningerne for at forhindre arbejdscyklus" } }, "advanced": { - "description": "Avanceret konfiguration\n\n**Info om kalibreringstyper: https://better-thermostat.org/configuration#second-step** ", + "description": "Avanceret konfiguration {trv}\n***Info om kalibreringstyper: https://better-thermostat.org/configuration#second-step*** ", "data": { + "protect_overheating": "Overophedningsbeskyttelse?", "heat_auto_swapped": "Hvis auto betyder varme for din TRV og du vil bytte det", "child_lock": "Ignorer alle input på TRV som en børnesikring", - "homaticip": "Hvis du bruger HomaticIP, bør du aktivere dette for at bremse anmodningerne for at forhindre arbejdscyklus", + "homematicip": "Hvis du bruger HomematicIP, bør du aktivere dette for at bremse anmodningerne for at forhindre arbejdscyklus", "valve_maintenance": "Hvis din termostat ikke har nogen egen vedligeholdelsestilstand, kan du bruge denne", "calibration": "Den slags kalibrering du vil bruge", - "protect_overheating": "Overophedningsbeskyttelse?", "calibration_mode": "Kalibreringstilstand", "no_off_system_mode": "Hvis din TRV ikke kan håndtere den slukkede tilstand, kan du aktivere denne for at bruge måltemperatur 5°C i stedet" }, "data_description": { "protect_overheating": "Nogle TRV'er lukker ikke ventilen helt, når temperaturen er nået. Eller radiatoren har meget hvilevarme. Dette kan forårsage overophedning. Denne mulighed kan forhindre dette.", - "calibration_mode": "Den slags, hvordan kalibreringen skal beregnes\n***Normal***: I denne tilstand er TRV's interne temperaturføler fikseret af den eksterne temperaturføler.\n***Aggressiv***: I denne tilstand er TRV's interne temperaturføler fikseret af den eksterne temperaturføler, men indstillet meget lavere/højere for at få et hurtigere løft.\n***AI-tidsbaseret***: I denne tilstand er TRV's interne temperatursensor fastsat af den eksterne temperatursensor, men værdien beregnes af en brugerdefineret algoritme for at forbedre TRV's interne algoritme.", + "calibration_mode": "Hvordan kalibreringen skal beregnes\n***Normal***: I denne tilstand er TRV's interne temperaturføler fikseret af den eksterne temperaturføler.\n***Aggressiv***: I denne tilstand er TRV's interne temperaturføler fikseret af den eksterne temperaturføler, men indstillet meget lavere/højere for at få et hurtigere løft.\n***AI-tidsbaseret***: I denne tilstand er TRV's interne temperatursensor fastsat af den eksterne temperatursensor, men værdien beregnes af en brugerdefineret algoritme for at forbedre TRV's interne algoritme.", "calibration": "Hvordan kalibreringen skal anvendes på TRV (Target temp or offset)\n***Måltemperaturbaseret***: Anvend kalibreringen til måltemperaturen.\n***Offset-baseret***: Anvend kalibreringen til offset." } } @@ -103,5 +108,23 @@ } } } + }, + "services": { + "save_current_target_temperature": { + "name": "Gem nuværende temperatur", + "description": "Gem den nuværende måltemperatur til senere gendannelse." + }, + "restore_saved_target_temperature": { + "name": "Gendan temperatur", + "description": "Gendan den gemte måltemperatur." + }, + "reset_heating_power": { + "name": "Nulstil opvarmningskraft", + "description": "Nulstil opvarmningskraft til standardværdi." + }, + "set_temp_target_temperature": { + "name": "Indstil eco-temperatur", + "description": "Indstil måltemperaturen til en midlertidig som nattilstand, og gem den gamle." + } } -} \ No newline at end of file +} diff --git a/custom_components/better_thermostat/translations/de.json b/custom_components/better_thermostat/translations/de.json index c34bc9a5..58296033 100644 --- a/custom_components/better_thermostat/translations/de.json +++ b/custom_components/better_thermostat/translations/de.json @@ -25,7 +25,7 @@ "protect_overheating": "Überhitzung verhindern?", "heat_auto_swapped": "Tauscht die Modi auto und heat, falls diese bei dem realen Thermostat vertauscht sind.", "child_lock": "Ignoriere alle manuellen Einstellungen am realen Thermostat (Kindersicherung).", - "homaticip": "Wenn du HomaticIP nutzt, solltest du diese Option aktivieren, um die Funk-Übertragung zu reduzieren.", + "homematicip": "Wenn du HomematicIP nutzt, solltest du diese Option aktivieren, um die Funk-Übertragung zu reduzieren.", "valve_maintenance": "Soll BT die Wartung des Thermostats übernehmen?", "calibration": "Kalibrierungstyp", "calibration_mode": "Kalibrierungsmodus", @@ -71,7 +71,7 @@ "weather": "Die Wetter-Entität für die Außentemperatur.", "valve_maintenance": "Wenn Ihr Thermostat keinen eigenen Wartungsmodus hat, können Sie diesen verwenden.", "child_lock": "Ignorieren Sie alle Eingaben am TRV wie eine Kindersicherung.", - "homaticip": "Wenn Sie HomaticIP verwenden, sollten Sie dies aktivieren, um die Anfragen zu verlangsamen und den Duty Cycle zu verhindern.", + "homematicip": "Wenn Sie HomematicIP verwenden, sollten Sie dies aktivieren, um die Anfragen zu verlangsamen und den Duty Cycle zu verhindern.", "heat_auto_swapped": "Wenn das Auto Wärme für Ihr TRV bedeutet und Sie es austauschen möchten.", "calibration": "Die Art der Kalibrierung https://better-thermostat.org/configuration#second-step" } @@ -82,7 +82,7 @@ "protect_overheating": "Überhitzung verhindern?", "heat_auto_swapped": "Tauscht die Modi auto und heat, falls diese bei dem realen Thermostat vertauscht sind.", "child_lock": "Ignoriere alle manuellen Einstellungen am realen Thermostat (Kindersicherung).", - "homaticip": "Wenn du HomaticIP nutzt, solltest du diese Option aktivieren, um die Funk-Übertragung zu reduzieren.", + "homematicip": "Wenn du HomematicIP nutzt, solltest du diese Option aktivieren, um die Funk-Übertragung zu reduzieren.", "valve_maintenance": "Soll BT die Wartung des Thermostats übernehmen?", "calibration": "Kalibrierungstyp", "calibration_mode": "Kalibrierungsmodus", diff --git a/custom_components/better_thermostat/translations/en.json b/custom_components/better_thermostat/translations/en.json index c20b3fbe..2d9fcebf 100644 --- a/custom_components/better_thermostat/translations/en.json +++ b/custom_components/better_thermostat/translations/en.json @@ -25,7 +25,7 @@ "protect_overheating": "Overheating protection?", "heat_auto_swapped": "If the auto means heat for your TRV and you want to swap it", "child_lock": "Ignore all inputs on the TRV like a child lock", - "homaticip": "If you use HomaticIP, you should enable this to slow down the requests to prevent the duty cycle", + "homematicip": "If you use HomematicIP, you should enable this to slow down the requests to prevent the duty cycle", "valve_maintenance": "If your thermostat has no own maintenance mode, you can use this one", "calibration": "Calibration Type", "calibration_mode": "Calibration mode", @@ -73,7 +73,7 @@ "weather": "Your weather entity to get the outdoor temperature", "heat_auto_swapped": "If the auto means heat for your TRV and you want to swap it", "child_lock": "Ignore all inputs on the TRV like a child lock", - "homaticip": "If you use HomaticIP, you should enable this to slow down the requests to prevent the duty cycle" + "homematicip": "If you use HomematicIP, you should enable this to slow down the requests to prevent the duty cycle" } }, "advanced": { @@ -82,7 +82,7 @@ "protect_overheating": "Overheating protection?", "heat_auto_swapped": "If the auto means heat for your TRV and you want to swap it", "child_lock": "Ignore all inputs on the TRV like a child lock", - "homaticip": "If you use HomaticIP, you should enable this to slow down the requests to prevent the duty cycle", + "homematicip": "If you use HomematicIP, you should enable this to slow down the requests to prevent the duty cycle", "valve_maintenance": "If your thermostat has no own maintenance mode, you can use this one", "calibration": "The sort of calibration you want to use", "calibration_mode": "Calibration mode", diff --git a/custom_components/better_thermostat/translations/fr.json b/custom_components/better_thermostat/translations/fr.json index ea99cd87..e7b19dda 100644 --- a/custom_components/better_thermostat/translations/fr.json +++ b/custom_components/better_thermostat/translations/fr.json @@ -25,7 +25,7 @@ "protect_overheating": "Protection contre la surchauffe ?", "heat_auto_swapped": "Si le mode automatique signifie chauffage pour votre TRV et que vous voulez le permuter", "child_lock": "Ignorer toutes les entrées sur le TRV comme une sécurité enfant", - "homaticip": "Si vous utilisez HomaticIP, vous devriez l'activer pour ralentir les demandes et éviter le cycle de fonctionnement excessif", + "homematicip": "Si vous utilisez HomematicIP, vous devriez l'activer pour ralentir les demandes et éviter le cycle de fonctionnement excessif", "valve_maintenance": "Si votre thermostat n'a pas de mode maintenance propre, vous pouvez utiliser celui-ci", "calibration": "Type de calibrage", "calibration_mode": "Mode de calibrage", @@ -73,7 +73,7 @@ "weather": "Votre entité météo pour obtenir la température extérieure", "heat_auto_swapped": "Si le mode automatique signifie chauffage pour votre TRV et que vous voulez le permuter", "child_lock": "Ignorer toutes les entrées sur le TRV comme une sécurité enfant", - "homaticip": "Si vous utilisez HomaticIP, vous devriez l'activer pour ralentir les demandes et éviter le cycle de fonctionnement excessif" + "homematicip": "Si vous utilisez HomematicIP, vous devriez l'activer pour ralentir les demandes et éviter le cycle de fonctionnement excessif" } }, "advanced": { @@ -82,7 +82,7 @@ "protect_overheating": "Protection contre la surchauffe ?", "heat_auto_swapped": "Si le mode automatique signifie chauffage pour votre TRV et que vous voulez le permuter", "child_lock": "Ignorer toutes les entrées sur le TRV comme une sécurité enfant", - "homaticip": "Si vous utilisez HomaticIP, vous devriez l'activer pour ralentir les demandes et éviter le cycle de fonctionnement excessif", + "homematicip": "Si vous utilisez HomematicIP, vous devriez l'activer pour ralentir les demandes et éviter le cycle de fonctionnement excessif", "valve_maintenance": "Si votre thermostat n'a pas de mode maintenance propre, vous pouvez utiliser celui-ci", "calibration": "Le type de calibrage que vous souhaitez utiliser", "calibration_mode": "Mode de calibrage", diff --git a/custom_components/better_thermostat/translations/pl.json b/custom_components/better_thermostat/translations/pl.json index 0bf2822d..4f1a59aa 100644 --- a/custom_components/better_thermostat/translations/pl.json +++ b/custom_components/better_thermostat/translations/pl.json @@ -17,11 +17,11 @@ } }, "advanced": { - "description": "Zaawansowana konfiguracja\n\n**Informacja o typach kalibracji: https://better-thermostat.org/configuration#second-step** ", + "description": "Zaawansowana konfiguracja {trv}\n***Informacja o typach kalibracji: https://better-thermostat.org/configuration#second-step***", "data": { "heat_auto_swapped": "Jeżeli tryb auto oznacza grzanie dla Twojego TRV i chcesz to zmienić", "child_lock": "Ignoruj wszystkie wejścia w TRV jak np. Blokada dziecięca", - "homaticip": "Jeżeli używasz HomaticIP, powinieneś włączyć tę opcję, żeby spowolnić żądania cyklu pracy", + "homematicip": "Jeżeli używasz HomematicIP, powinieneś włączyć tę opcję, żeby spowolnić żądania cyklu pracy", "valve_maintenance": "Jeżeli Twój termostat nie ma trybu konserwacji, możesz użyć tej opcji.", "calibration": "Rodzaj kalibracji, której chcesz użyć", "no_off_system_mode": "Jeśli Twój TRV nie obsługuje trybu wyłączenia, możesz go włączyć, aby zamiast tego używać temperatury docelowej 5°C", @@ -66,17 +66,17 @@ "weather": "Twoja jednostka pogodowa, aby uzyskać temperaturę zewnętrzną", "heat_auto_swapped": "Jeżeli tryb auto oznacza grzanie dla Twojego TRV i chcesz to zmienić", "child_lock": "Ignoruj wszystkie wejścia w TRV jak np. Blokada dziecięca", - "homaticip": "Jeżeli używasz HomaticIP, powinienieś włączyć tę opcję żeby spowolnić żądania", + "homematicip": "Jeżeli używasz HomematicIP, powinienieś włączyć tę opcję żeby spowolnić żądania", "name": "Nazwa", "thermostat": "Prawdziwy termostat" } }, "advanced": { - "description": "Zaawansowana konfiguracja**Informacja o typach kalibracji: https://better-thermostat.org/configuration#second-step** ", + "description": "Zaawansowana konfiguracja {trv}\n***Informacja o typach kalibracji: https://better-thermostat.org/configuration#second-step***", "data": { "heat_auto_swapped": "Jeżeli tryb auto oznacza grzanie dla Twojego TRV i chcesz to zmienić", "child_lock": "Ignoruj wszystkie wejścia w TRV jak np. Blokada dziecięca", - "homaticip": "Jeżeli używasz HomaticIP, powinieneś włączyć tę opcję, żeby spowolnić żądania spowolnienia cyklu pracy", + "homematicip": "Jeżeli używasz HomematicIP, powinieneś włączyć tę opcję, żeby spowolnić żądania spowolnienia cyklu pracy", "valve_maintenance": "Jeżeli Twój termostat nie ma trybu konserwacji, możesz użyć tej opcji.", "calibration": "Rodzaj kalibracji, której chcesz użyć", "protect_overheating": "Zabezpieczenie przed przegrzaniem?", diff --git a/custom_components/better_thermostat/translations/ru.json b/custom_components/better_thermostat/translations/ru.json index 9d173760..3cfbd118 100644 --- a/custom_components/better_thermostat/translations/ru.json +++ b/custom_components/better_thermostat/translations/ru.json @@ -25,7 +25,7 @@ "protect_overheating": "Защита от перегрева?", "heat_auto_swapped": "Если автомат означает обогрев вашего термостата, и вы хотите его поменять", "child_lock": "Игнорировать все входы на термостате, как блокировку от детей.", - "homaticip": "Если вы используете HomaticIP, вам следует включить это, чтобы замедлить запросы и предотвратить рабочий цикл.", + "homematicip": "Если вы используете HomematicIP, вам следует включить это, чтобы замедлить запросы и предотвратить рабочий цикл.", "valve_maintenance": "Если у вашего термостата нет собственного режима обслуживания, вы можете использовать этот.", "calibration": "Тип калибровки", "calibration_mode": "Режим калибровки", @@ -73,7 +73,7 @@ "weather": "Датчик температуры наружного воздуха", "heat_auto_swapped": "Если автомат означает обогрев вашего термостата, и вы хотите его поменять", "child_lock": "Игнорировать все входы на термостате, как блокировку от детей.", - "homaticip": "Если вы используете HomaticIP, вам следует включить это, чтобы замедлить запросы и предотвратить рабочий цикл." + "homematicip": "Если вы используете HomematicIP, вам следует включить это, чтобы замедлить запросы и предотвратить рабочий цикл." } }, "advanced": { @@ -82,7 +82,7 @@ "protect_overheating": "Защита от перегрева?", "heat_auto_swapped": "Если стоит функция auto, это означает нагрев вашего термостата и вы хотите его заменить", "child_lock": "Игнорировать все входы на термостате, как блокировку от детей.", - "homaticip": "Если вы используете HomaticIP, вам следует включить это, чтобы замедлить запросы и предотвратить рабочий цикл.", + "homematicip": "Если вы используете HomematicIP, вам следует включить это, чтобы замедлить запросы и предотвратить рабочий цикл.", "valve_maintenance": "Если у вашего термостата нет собственного режима обслуживания, вы можете использовать этот.", "calibration": "Тип калибровки, которую вы хотите использовать", "calibration_mode": "Режим калибровки", diff --git a/custom_components/better_thermostat/translations/sk.json b/custom_components/better_thermostat/translations/sk.json index 1c7e3782..d079e433 100644 --- a/custom_components/better_thermostat/translations/sk.json +++ b/custom_components/better_thermostat/translations/sk.json @@ -25,7 +25,7 @@ "protect_overheating": "Ochrana proti prehriatiu?", "heat_auto_swapped": "Ak auto znamená teplo pre váš TRV a chcete ho vymeniť", "child_lock": "Ignorovať všetky vstupy na TRV ako detský zámok", - "homaticip": "Ak používate HomaticIP, mali by ste túto funkciu povoliť, aby ste spomalili požiadavky a zabránili tak pracovnému cyklu", + "homematicip": "Ak používate HomematicIP, mali by ste túto funkciu povoliť, aby ste spomalili požiadavky a zabránili tak pracovnému cyklu", "valve_maintenance": "Ak váš termostat nemá vlastný režim údržby, môžete použiť tento režim", "calibration": "Typ kalibrácie", "calibration_mode": "Režim kalibrácie", @@ -73,7 +73,7 @@ "weather": "Váš meteorologický subjekt na zistenie vonkajšej teploty", "heat_auto_swapped": "Ak auto znamená teplo pre váš TRV a chcete ho vymeniť", "child_lock": "Ignorovať všetky vstupy na TRV ako detský zámok", - "homaticip": "Ak používate HomaticIP, mali by ste túto funkciu povoliť, aby ste spomalili požiadavky a zabránili tak pracovnému cyklu" + "homematicip": "Ak používate HomematicIP, mali by ste túto funkciu povoliť, aby ste spomalili požiadavky a zabránili tak pracovnému cyklu" } }, "advanced": { @@ -82,7 +82,7 @@ "protect_overheating": "Ochrana proti prehriatiu?", "heat_auto_swapped": "Ak auto znamená teplo pre váš TRV a chcete ho vymeniť", "child_lock": "Ignorovať všetky vstupy na TRV ako detský zámok", - "homaticip": "Ak používate HomaticIP, mali by ste túto funkciu povoliť, aby ste spomalili požiadavky a zabránili tak pracovnému cyklu", + "homematicip": "Ak používate HomematicIP, mali by ste túto funkciu povoliť, aby ste spomalili požiadavky a zabránili tak pracovnému cyklu", "valve_maintenance": "Ak váš termostat nemá vlastný režim údržby, môžete použiť tento režim", "calibration": "Druh kalibrácie, ktorý chcete použiť", "calibration_mode": "Režim kalibrácie", diff --git a/custom_components/better_thermostat/utils/const.py b/custom_components/better_thermostat/utils/const.py index 0c8238d0..cd319a1c 100644 --- a/custom_components/better_thermostat/utils/const.py +++ b/custom_components/better_thermostat/utils/const.py @@ -49,7 +49,7 @@ CONF_CALIBRATION_MODE = "calibration_mode" CONF_HEAT_AUTO_SWAPPED = "heat_auto_swapped" CONF_MODEL = "model" -CONF_HOMATICIP = "homaticip" +CONF_HOMEMATICIP = "homematicip" CONF_INTEGRATION = "integration" CONF_NO_SYSTEM_MODE_OFF = "no_off_system_mode" CONF_TOLERANCE = "tolerance" diff --git a/custom_components/better_thermostat/utils/helpers.py b/custom_components/better_thermostat/utils/helpers.py index f619ecba..4ed99ef4 100644 --- a/custom_components/better_thermostat/utils/helpers.py +++ b/custom_components/better_thermostat/utils/helpers.py @@ -2,7 +2,10 @@ import re import logging +import math from datetime import datetime +from enum import Enum +from typing import Union from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers.entity_registry import async_entries_for_config_entry @@ -83,8 +86,8 @@ def heating_power_valve_position(self, entity_id): def convert_to_float( - value: str | int | float, instance_name: str, context: str -) -> float | None: + value: Union[str, float], instance_name: str, context: str +) -> Union[float, None]: """Convert value to float or print error message. Parameters @@ -103,72 +106,35 @@ def convert_to_float( None If error occurred and cannot convert the value. """ - if isinstance(value, float): - return round(value, 1) - elif value is None or value == "None": + if value is None or value == "None": return None - else: - try: - return round(float(str(format(float(value), ".1f"))), 1) - except (ValueError, TypeError, AttributeError, KeyError): - _LOGGER.debug( - f"better thermostat {instance_name}: Could not convert '{value}' to float in {context}" - ) - return None - - -def calibration_round(value: int | float | None) -> float | int | None: - """Round the calibration value to the nearest 0.5. - - Parameters - ---------- - value : float - the value to round - - Returns - ------- - float - the rounded value - """ - if value is None: + try: + return round_by_steps(float(value), 10) + except (ValueError, TypeError, AttributeError, KeyError): + _LOGGER.debug( + f"better thermostat {instance_name}: Could not convert '{value}' to float in {context}" + ) return None - split = str(float(str(value))).split(".", 1) - decimale = int(split[1]) - if decimale > 8: - return float(str(split[0])) + 1.0 - else: - return float(str(split[0])) -def round_by_steps( - value: int | float | None, steps: int | float | None -) -> float | int | None: - """Round the value based on the allowed decimal 'steps'. - Parameters - ---------- - value : float - the value to round +class rounding(Enum): + # rounding functions that avoid errors due to using floats - Returns - ------- - float - the rounded value - """ - if value is None: - return None - split = str(float(str(steps))).split(".", 1) - decimals = len(split[1]) + def up(x: float) -> float: + return math.ceil(x - 0.0001) - value_f = float(str(value)) - steps_f = float(str(steps)) - value_mod = value_f - (value_f % steps_f) + def down(x: float) -> float: + return math.floor(x + 0.0001) - return round(value_mod, decimals) + def nearest(x: float) -> float: + return round(x - 0.0001) -def round_down_to_half_degree(value: int | float | None) -> float | int | None: - """Round the value down to the nearest 0.5. +def round_by_steps( + value: Union[float, None], steps: Union[float, None], f_rounding: rounding = rounding.nearest +) -> Union[float, None]: + """Round the value based on the allowed decimal 'steps'. Parameters ---------- @@ -180,61 +146,10 @@ def round_down_to_half_degree(value: int | float | None) -> float | int | None: float the rounded value """ - if value is None: - return None - split = str(float(str(value))).split(".", 1) - decimale = int(split[1]) - if decimale >= 5: - if float(split[0]) > 0: - return float(str(split[0])) + 0.5 - else: - return float(str(split[0])) - 0.5 - else: - return float(str(split[0])) - -def round_to_half_degree(value: int | float | None) -> float | int | None: - """Rounds numbers to the nearest n.5/n.0 - - Parameters - ---------- - value : int, float - input value - - Returns - ------- - float, int - either an int, if input was an int, or a float rounded to n.5/n.0 - - """ - if value is None: - return None - elif isinstance(value, float): - return round(value * 2) / 2 - elif isinstance(value, int): - return value - - -def round_to_hundredth_degree(value: int | float | None) -> float | int | None: - """Rounds numbers to the nearest n.nn0 - - Parameters - ---------- - value : int, float - input value - - Returns - ------- - float, int - either an int, if input was an int, or a float rounded to n.nn0 - - """ - if value is None: + if value is None or steps is None: return None - elif isinstance(value, float): - return round(value * 100) / 100 - elif isinstance(value, int): - return value + return f_rounding(value * steps) / steps def check_float(potential_float): diff --git a/docs/Configuration/configuration.md b/docs/Configuration/configuration.md index f841cdf4..bf9d80d7 100644 --- a/docs/Configuration/configuration.md +++ b/docs/Configuration/configuration.md @@ -10,7 +10,7 @@ permalink: configuration ** Goto: `Settings` -> `Devices & Services` -> `Integrations` -> `+ Add Integration` -> `Better Thermostat` ** -or just click on the button below: +or click on the button below: Open your Home Assistant instance and start setting up a new integration. @@ -25,11 +25,11 @@ or just click on the button below: **The real thermostat** This is a required field. This is the real climate entity you want to control with BT, if you have more than one climate in your room you can select multiple climate entities, fill out the first field and a second one will appear. -**Temperature sensor** This is a required field. This is the temperature sensor you want to use to control the real climate entity. It's used to get a more accurate temperature reading than the sensor in the real climate entity. Because you can place it in the middle of the room and not close to the radiator. +**Temperature sensor** This is a required field. This is the temperature sensor you want to use to control the real climate entity. It's used to get a more accurate temperature reading than the sensor in the real climate entity because you can place it in the middle of the room and not close to the radiator. **Humidity sensor** This is an optional field. For now, the humidity is only used to display it in the UI. In the future, it will be used to make a better calculation of the temperature or set it up to a *feels-like* temperature. -**If you have an outdoor sensor...** This is an optional field. If you have an outdoor sensor you can use it to get the outdoor temperatures, this is used to set the thermostat on or off if the threshold (the last option in this screen) is reached. It uses a mean of the last 3 days and checks it every morning at 5:00 AM. +**If you have an outdoor sensor...** This field is optional. If you have an outdoor sensor you can use it to get the outdoor temperatures, this is used to set the thermostat on or off if the threshold (the last option in this screen) is reached. It uses a mean of the last 3 days and checks it every morning at 5:00 AM. **Window Sensor** This is an optional field. If you have a window sensor you can use it to turn off the thermostat if the window is open and turn it on again when the window is closed. If you have more than one window in a room, you can also select window groups (see the GitHub page for more info). @@ -53,7 +53,7 @@ group: **The outdoor temperature threshold** This is an optional field. If you have an outdoor sensor or a weather entity, you can set a threshold. If the outdoor temperature is higher than the threshold, the thermostat will be turned off. If the outdoor temperature is lower than the threshold, the thermostat will be turned on. If you don't have an outdoor sensor or a weather entity, this field will be ignored. -**Tolerance** This is an optional field. It helps prevent the thermostat from turning on an off too often. Here is an example how it works: If you set the target temperature to 20.0 and the tolerance to 0.3 for example. Then BT will heat to 20.0 and then go to idle until the temperature drops again to 19.7 and then it will heat again to 20.0. +**Tolerance** This is an optional field. It helps prevent the thermostat from turning on and off too often. Here is an example of how it works: If you set the target temperature to 20.0 and the tolerance to 0.3 for example. Then BT will heat to 20.0 and then go to idle until the temperature drops again to 19.7 and then it will heat again to 20.0. ## Second step @@ -82,6 +82,6 @@ group: **If auto means heat for your TRV and you want to swap it** Some climates in HA use the mode auto for default heating, and a boost when mode is heat. This isn't what we want, so if this is the case for you, check this option. -**Ignore all inputs on the TRV like a child lock** If this option is enabled, all changes on the real TRV, even over HA, will be ignored or reverted, only input from the BT entity are accepted. +**Ignore all inputs on the TRV like a child lock** If this option is enabled, all changes on the real TRV, even over HA, will be ignored or reverted, only input from the BT entity is accepted. **If you use HomematicIP you should enable this...** If your entity is a HomematicIP entity this option should be enabled, to prevent a duty cycle overload. diff --git a/docs/Q&A/debuggin.md b/docs/Q&A/debugging.md similarity index 94% rename from docs/Q&A/debuggin.md rename to docs/Q&A/debugging.md index 5b69b850..5ec03474 100644 --- a/docs/Q&A/debuggin.md +++ b/docs/Q&A/debugging.md @@ -8,7 +8,7 @@ parent: Q&A --- # How do I activate the debug mode? -Basically, there are two options to enable debug mode. +There are two options to enable debug mode. ## Via configuration.yaml Add the following lines to your configuration.yaml file and restart Home Assistant. diff --git a/docs/Q&A/modes.md b/docs/Q&A/modes.md index 564d1ab4..c6b2e594 100644 --- a/docs/Q&A/modes.md +++ b/docs/Q&A/modes.md @@ -10,4 +10,4 @@ parent: Q&A # What is the difference between "local calibration" and "temperature-based calibration"? Local calibration means that the temperature reported by the TRV will be corrected to the temperature of the external thermometer with an offset. The benefit of this calibration is that the temperature shown on the TRV corresponds to the temperature measured via your selected external thermometer and the desired temperature you have set via BT and not the temperature measured via the TRV. -Target temperature based method: in this case, the difference between the measured temperatures at the TRV and the external thermometer will be adjusted via the target temperature set via BT. This makes it possible to use an external thermometer even if your TRV does not have the option to use an offset. The drawback is that your TRV will keep showing its own temperatures and not the ones set via BT. +Target temperature-based method: in this case, the difference between the measured temperatures at the TRV and the external thermometer will be adjusted via the target temperature set via BT. This makes it possible to use an external thermometer even if your TRV does not have the option to use an offset. The drawback is that your TRV will keep showing its own temperatures and not the ones set via BT. diff --git a/docs/Q&A/supported.md b/docs/Q&A/supported.md index c7d015cb..6178ee26 100644 --- a/docs/Q&A/supported.md +++ b/docs/Q&A/supported.md @@ -18,4 +18,4 @@ Currently, these are the integrations compatible with local calibration mode: - Deconz Please keep in mind that even if BT supports your integration, if your device does not support "local_temperature_calibration" this feature will not be available to you. You can check your device compatibility via Zigbee2MQTT. -If your preferred integration isn’t currently available for local calibration please open a GitHub issue. +If your preferred integration isn’t currently available for local calibration please open a [GitHub issue](https://github.com/KartoffelToby/better_thermostat/issues). diff --git a/docs/schedule.md b/docs/schedule.md index 3b18b59a..50d359e5 100644 --- a/docs/schedule.md +++ b/docs/schedule.md @@ -18,8 +18,8 @@ Services you can call from Home Assistant to set a temporary target temperature # How can I set up a night mode schedule? -Basically you can set up an automation that triggers a service call for every climate entity. -As an example you can use this blueprint: +You can set up an automation that triggers a service call for every climate entity. +As an example, you can use this blueprint: Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.