Skip to content

Commit

Permalink
Merge pull request #270 from basbruss/dev
Browse files Browse the repository at this point in the history
release
  • Loading branch information
basbruss authored Jul 31, 2024
2 parents bf5cd7a + a1ff8d4 commit 1a184d8
Show file tree
Hide file tree
Showing 15 changed files with 278 additions and 148 deletions.
3 changes: 2 additions & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

<!--- Why is this change required? What problem does it solve? -->
<!--- If it fixes an open issue, please link to the issue here. -->

- fixes:

## How has this been tested?
Expand Down Expand Up @@ -37,4 +38,4 @@

- [ ] My code follows the code style of this project.
- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.
- [ ] I have updated the documentation accordingly.
2 changes: 1 addition & 1 deletion .github/release-drafter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ exlude-contributors:
- "dependabot"

template: |
# Adaptive Cover ⛅ v$RESOLVED_VERSION
# Adaptive Cover ⛅ v$RESOLVED_VERSION
## Changes
$CHANGES
Expand Down
12 changes: 6 additions & 6 deletions .ruff.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# The contents of this file is based on https://github.com/home-assistant/core/blob/dev/pyproject.toml

target-version = "py310"
target-version = "py312"

select = [
lint.select = [
"B007", # Loop control variable {name} not used within loop body
"B014", # Exception handler with duplicate exception
"C", # complexity
Expand All @@ -26,7 +26,7 @@ select = [
"W", # pycodestyle
]

ignore = [
lint.ignore = [
"D202", # No blank lines allowed after function docstring
"D203", # 1 blank line required before class docstring
"D213", # Multi-line docstring summary should start at the second line
Expand All @@ -38,11 +38,11 @@ ignore = [
"E731", # do not assign a lambda expression, use a def
]

[flake8-pytest-style]
[lint.flake8-pytest-style]
fixture-parentheses = false

[pyupgrade]
[lint.pyupgrade]
keep-runtime-typing = true

[mccabe]
[lint.mccabe]
max-complexity = 25
40 changes: 20 additions & 20 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
MIT License
Copyright (c) 2019 - 2023 Joakim Sørensen @ludeeus
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
MIT License

Copyright (c) 2019 - 2023 Joakim Sørensen @ludeeus

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,6 @@ This mode is split up in two types of strategies; [Presence](https://github.com/

### Climate


| Variables | Default | Range | Example | Description |
| ----------------------------- | ------- | ----- | --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| Indoor Temperature Entity | `None` | | `climate.living_room` \| `sensor.indoor_temp` | |
Expand All @@ -243,7 +242,6 @@ This mode is split up in two types of strategies; [Presence](https://github.com/
| Irradiance Entity | `None` | | `sensor.irradiance` | Returns measured irradiance |
| Irradiance Threshold | `300` | | | "In non-summer, above threshold, use optimal position. Otherwise, default position or fully open in winter." |


### Blindspot

| Variables | Default | Range | Example | Description |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,13 +252,13 @@ variables:
{# default height, when automatic control is off. #}
{%- set def_h = def / 100 * h_max -%}
{%- set alpha = deg2rad * sun_ele -%}
{% set gamma = deg2rad * ((win_azi - sun_azi + 180) % 360 - 180) %}
{% set gamma = deg2rad * ((win_azi - sun_azi + 180) % 360 - 180) %}
{%- set h = (d / cos(gamma)) * tan(alpha) -%}
{# gamma is outside of FOV #}
{%- if gamma < azi_left or gamma > azi_right or alpha < elev_low or alpha > elev_high -%}
{{ clipv(h2perc(def_h) | round(0) | int , 0, 100) }}
{# gamma is inside of FOV #}
{%- else -%}
{%- else -%}
{{ clipv(h2perc(h) | round(0) | int , min_pos, 100) }}
{%- endif -%}
change_threshold: !input change_threshold
Expand Down
33 changes: 28 additions & 5 deletions custom_components/adaptive_cover/calculation.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class AdaptiveGeneralCover(ABC):
h_def: int
max_pos: int
min_pos: int
max_pos_bool: bool
min_pos_bool: bool
blind_spot_left: int
blind_spot_right: int
blind_spot_elevation: int
Expand Down Expand Up @@ -155,6 +157,29 @@ def fov(self) -> list:
"""Return field of view."""
return [self.azi_min_abs, self.azi_max_abs]

@property
def apply_min_position(self) -> bool:
"""Check if min position is applied."""
if self.min_pos is not None and self.min_pos != 0:
if self.min_pos_bool:
return self.direct_sun_valid
return True
return False

@property
def apply_max_position(self) -> bool:
"""Check if max position is applied."""
if self.max_pos is not None and self.max_pos != 100:
if self.max_pos_bool:
return self.direct_sun_valid
return True
return False

@property
def direct_sun_valid(self) -> bool:
"""Check if sun is directly in front of window."""
return (self.valid) & (not self.sunset_valid) & (not self.is_sun_in_blind_spot)

@abstractmethod
def calculate_position(self) -> float:
"""Calculate the position of the blind."""
Expand All @@ -173,16 +198,14 @@ class NormalCoverState:
def get_state(self) -> int:
"""Return state."""
state = np.where(
(self.cover.valid)
& (not self.cover.sunset_valid)
& (not self.cover.is_sun_in_blind_spot),
self.cover.direct_sun_valid,
self.cover.calculate_percentage(),
self.cover.default,
)
result = np.clip(state, 0, 100)
if result > self.cover.max_pos:
if self.cover.apply_max_position and result > self.cover.max_pos:
return self.cover.max_pos
if result < self.cover.min_pos:
if self.cover.apply_min_position and result < self.cover.min_pos:
return self.cover.min_pos
return result

Expand Down
12 changes: 7 additions & 5 deletions custom_components/adaptive_cover/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@
DOMAIN,
SensorType,
CONF_MIN_POSITION,
CONF_ENABLE_MAX_POSITION,
CONF_ENABLE_MIN_POSITION,
)

# DEFAULT_NAME = "Adaptive Cover"
Expand Down Expand Up @@ -109,14 +111,14 @@
min=0, max=100, step=1, mode="slider", unit_of_measurement="%"
)
),
vol.Optional(CONF_MAX_POSITION, default=100): selector.NumberSelector(
selector.NumberSelectorConfig(
min=1, max=100, step=1, mode="slider", unit_of_measurement="%"
)
vol.Optional(CONF_MAX_POSITION): vol.All(
vol.Coerce(int), vol.Range(min=1, max=100)
),
vol.Optional(CONF_ENABLE_MAX_POSITION, default=False): bool,
vol.Optional(CONF_MIN_POSITION): vol.All(
vol.Coerce(int), vol.Range(min=0, max=90)
vol.Coerce(int), vol.Range(min=0, max=99)
),
vol.Optional(CONF_ENABLE_MIN_POSITION, default=False): bool,
vol.Optional(CONF_MIN_ELEVATION): vol.All(
vol.Coerce(int), vol.Range(min=0, max=90)
),
Expand Down
2 changes: 2 additions & 0 deletions custom_components/adaptive_cover/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
CONF_WEATHER_STATE = "weather_state"
CONF_MAX_POSITION = "max_position"
CONF_MIN_POSITION = "min_position"
CONF_ENABLE_MAX_POSITION = "enable_max_position"
CONF_ENABLE_MIN_POSITION = "enable_min_position"
CONF_OUTSIDETEMP_ENTITY = "outside_temp"
CONF_ENABLE_BLIND_SPOT = "blind_spot"
CONF_BLIND_SPOT_RIGHT = "blind_spot_right"
Expand Down
4 changes: 4 additions & 0 deletions custom_components/adaptive_cover/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@
CONF_OUTSIDE_THRESHOLD,
DOMAIN,
LOGGER,
CONF_ENABLE_MAX_POSITION,
CONF_ENABLE_MIN_POSITION,
)
from .helpers import get_datetime_from_str, get_last_updated, get_safe_state

Expand Down Expand Up @@ -544,6 +546,8 @@ def common_data(self, options):
options.get(CONF_DEFAULT_HEIGHT),
options.get(CONF_MAX_POSITION),
options.get(CONF_MIN_POSITION),
options.get(CONF_ENABLE_MAX_POSITION, False),
options.get(CONF_ENABLE_MIN_POSITION, False),
options.get(CONF_BLIND_SPOT_LEFT),
options.get(CONF_BLIND_SPOT_RIGHT),
options.get(CONF_BLIND_SPOT_ELEVATION),
Expand Down
9 changes: 8 additions & 1 deletion custom_components/adaptive_cover/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@
"name": "Adaptive Cover",
"codeowners": ["@basbruss"],
"config_flow": true,
"dependencies": ["sun","device_tracker","zone","climate","sensor","weather"],
"dependencies": [
"sun",
"device_tracker",
"zone",
"climate",
"sensor",
"weather"
],
"documentation": "https://github.com/basbruss/adaptive-cover",
"iot_class": "calculated",
"issue_tracker": "https://github.com/basbruss/adaptive-cover/issues",
Expand Down
12 changes: 12 additions & 0 deletions custom_components/adaptive_cover/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
"default_percentage": "Default Position",
"min_position": "Minimum Position",
"max_position": "Maximum Position",
"enable_min_position": "Only force the minimum position when the sun is in front of the window",
"enable_max_position": "Only force the maximum position when the sun is in front of the window",
"fov_left": "Field of view left",
"fov_right": "Field of view right",
"group": "Cover Entities",
Expand Down Expand Up @@ -120,6 +122,8 @@
"default_percentage": "Default Position",
"min_position": "Minimum Position",
"max_position": "Maximum Position",
"enable_min_position": "Only force the minimum position when the sun is in front of the window",
"enable_max_position": "Only force the maximum position when the sun is in front of the window",
"fov_left": "Field of view left",
"fov_right": "Field of view right",
"group": "Cover Entities",
Expand Down Expand Up @@ -161,6 +165,8 @@
"default_percentage": "Default Position",
"min_position": "Minimum Position",
"max_position": "Maximum Position",
"enable_min_position": "Only force the minimum position when the sun is in front of the window",
"enable_max_position": "Only force the maximum position when the sun is in front of the window",
"fov_left": "Field of view left",
"fov_right": "Field of view right",
"group": "Cover Entities",
Expand Down Expand Up @@ -269,6 +275,8 @@
"default_percentage": "Default Position",
"min_position": "Minimum Position",
"max_position": "Maximum Position",
"enable_min_position": "Only force the minimum position when the sun is in front of the window",
"enable_max_position": "Only force the maximum position when the sun is in front of the window",
"fov_left": "Field of view left",
"fov_right": "Field of view right",
"group": "Cover Entities",
Expand Down Expand Up @@ -347,6 +355,8 @@
"default_percentage": "Default Position",
"min_position": "Minimum Position",
"max_position": "Maximum Position",
"enable_min_position": "Only force the minimum position when the sun is in front of the window",
"enable_max_position": "Only force the maximum position when the sun is in front of the window",
"fov_left": "Field of view left",
"fov_right": "Field of view right",
"group": "Cover Entities",
Expand Down Expand Up @@ -388,6 +398,8 @@
"default_percentage": "Default Position",
"min_position": "Minimum Position",
"max_position": "Maximum Position",
"enable_min_position": "Only force the minimum position when the sun is in front of the window",
"enable_max_position": "Only force the maximum position when the sun is in front of the window",
"fov_left": "Field of view left",
"fov_right": "Field of view right",
"group": "Cover Entities",
Expand Down
12 changes: 12 additions & 0 deletions custom_components/adaptive_cover/translations/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
"default_percentage": "Standaard positie",
"min_position": "Minimale positie",
"max_position": "Maximale positie",
"enable_min_position": "Forceer alleen de minimale positie wanneer de zon voor het raam staat",
"enable_max_position": "Forceer alleen de maximale positie wanneer de zon voor het raam staat",
"fov_left": "Links gezichtsveld",
"fov_right": "Rechts gezichtsveld",
"group": "Cover Entiteiten",
Expand Down Expand Up @@ -119,6 +121,8 @@
"default_percentage": "Standaard positie",
"min_position": "Minimale positie",
"max_position": "Maximale positie",
"enable_min_position": "Forceer alleen de minimale positie wanneer de zon voor het raam staat",
"enable_max_position": "Forceer alleen de maximale positie wanneer de zon voor het raam staat",
"fov_left": "Links gezichtsveld",
"fov_right": "Rechts gezichtsveld",
"group": "Cover Entities",
Expand Down Expand Up @@ -159,6 +163,8 @@
"default_percentage": "Standaard positie",
"min_position": "Minimale positie",
"max_position": "Maximale positie",
"enable_min_position": "Forceer alleen de minimale positie wanneer de zon voor het raam staat",
"enable_max_position": "Forceer alleen de maximale positie wanneer de zon voor het raam staat",
"fov_left": "Links gezichtsveld",
"fov_right": "Rechts gezichtsveld",
"group": "Cover Entities",
Expand Down Expand Up @@ -266,6 +272,8 @@
"default_percentage": "Standaard positie",
"min_position": "Minimale positie",
"max_position": "Maximale positie",
"enable_min_position": "Forceer alleen de minimale positie wanneer de zon voor het raam staat",
"enable_max_position": "Forceer alleen de maximale positie wanneer de zon voor het raam staat",
"fov_left": "Links gezichtsveld",
"fov_right": "Rechts gezichtsveld",
"group": "Cover Entiteiten",
Expand Down Expand Up @@ -335,6 +343,8 @@
"default_percentage": "Standaard positie",
"min_position": "Minimale positie",
"max_position": "Maximale positie",
"enable_min_position": "Forceer alleen de minimale positie wanneer de zon voor het raam staat",
"enable_max_position": "Forceer alleen de maximale positie wanneer de zon voor het raam staat",
"fov_left": "Links gezichtsveld",
"fov_right": "Rechts gezichtsveld",
"group": "Cover Entities",
Expand Down Expand Up @@ -375,6 +385,8 @@
"default_percentage": "Standaard positie",
"min_position": "Minimale positie",
"max_position": "Maximale positie",
"enable_min_position": "Forceer alleen de minimale positie wanneer de zon voor het raam staat",
"enable_max_position": "Forceer alleen de maximale positie wanneer de zon voor het raam staat",
"fov_left": "Links gezichtsveld",
"fov_right": "Rechts gezichtsveld",
"group": "Cover Entities",
Expand Down
Loading

0 comments on commit 1a184d8

Please sign in to comment.