basbruss / adaptive-cover

An Adaptive Cover component for HomeAsisstant to control covers based on the sun's position
MIT License
71 stars 10 forks source link

Factor for position percentage #129

Closed flecmart closed 4 months ago

flecmart commented 4 months ago

This is more a question than an issue: I come from germany and have this type of vertical covers, called "Rolläden": https://www.youtube.com/watch?v=_KePLmie7lE

I was wondering if the calculated percentage for positioning might not be correct for those kind of blinds, because at 50 % they are kind of fully down, but with the little wholes still letting some light through.

Could this be solved by incorporating a factor for the calculated percentage?

basbruss commented 4 months ago

The calculated position is correct. In this case, it seems to be that the integration that integrates your covers into HA does not comply with the standards from HA, where 0% means fully closed and 100% means fully open. This can either be some calibration setting in the default app (non-HA) or some (conversion) error in the code that talks with HA.

flecmart commented 4 months ago

I am not saying that the calculated position is incorrect. Also my shutters follow the HA convention where 0% means fully closed and 100% means fully open. The problem is that how the shutters here a physically built that 50 % does not mean that the shutters are halfway open. Because if you start from 0% and pull up the shutters, the first thing that happens is that the differnet shutter rips are pulled open to let a little bit of light through. Then at about 30% open, the shutter starts to physically move up and change its position.

That is why I wondered if the calculated position matches my case here, because I know that in most places shutters work differently. Is my assumption correct? The algorighm exepcts the shutters to cover half the window if the calculated position is 50%?

If that is the case the calculated position does not really reflect the right physical position to block of the glare for all shutters that work like mine. I think the problem could be solved by implementing an offset to the position, where 0% represents the state with the shutter rips pulled open. I guess this could maybe be solved by using https://www.home-assistant.io/integrations/cover.template/ on top of my cover as controllable entity for this integration.

basbruss commented 4 months ago

Ah okay I do understand the problem better now. The integration indeed assumes a linear scale from 0% to 100% for the full extension length of the cover.

I could probably build a feature that can narrow that scale and converts the original calculated position accordingly. Although this can add additional complexity for not affected users with a parameter they don't need/understand.

If that is the case the calculated position does not really reflect the right physical position to block of the glare for all shutters that work like mine. I think the problem could be solved by implementing an offset to the position, where 0% represents the state with the shutter rips pulled open. I guess this could maybe be solved by using https://www.home-assistant.io/integrations/cover.template/ on top of my cover as controllable entity for this integration.

But this seems also a rather good solution. And Imho is preferable since the position of a cover should also be correctly displayed within HA and only within the backend logic of some custom integration.

That said I still can workout a dynamic solution if the above seems not work as expected.

flecmart commented 4 months ago

Hey,

thanks for the input. I actually solved the problem with a template cover and I think you're right that this is the better solution.

If anyone has similar problems, a short explanation of how I solved it.

I had the requirements:

This cannot be one linear function so I used a piecewise linear transformation with two segments:

  1. 35% to 75% original mapping to 0% to 50% new: -> new_position = (original_position-35)/(75-35)x50

  2. 75% to 100% original mapping to 50% to 100% new -> new_position = (original_position-75)/(100-75)x50

which leads to a template cover like

cover:
  - platform: template
    covers:
      another_cover_adaptive:
        value_template: "{{ is_state('cover.another_cover', 'open') }}"
        open_cover:
          service: cover.open_cover
          data:
            entity_id: cover.another_cover
        close_cover: # this is so that if I actually want to close the cover fully, the origianl 0% is used and the cover really fully closes
          service: cover.set_cover_position
          data:
            entity_id: cover.another_cover
            position: 0
        stop_cover:
          service: cover.stop_cover
          data:
            entity_id: cover.another_cover
        position_template: >
          {% set cp = state_attr('cover.another_cover', 'current_position') %}
          {% if cp is none %}
            None
          {% elif cp <= 35 %}
            0
          {% elif cp < 75 %}
            {{ (((cp - 35) / 40 * 50) | int) }}
          {% elif cp <= 100 %}
            {{ (((cp - 75) / 25 * 50 + 50) | int) }}
          {% endif %}
        set_cover_position:
          service: cover.set_cover_position
          data_template:
            entity_id: cover.another_cover
            position: >
              {% set pos = position | float %}
              {% if pos <= 50 %}
                {{ ((pos / 50 * 40) + 35) | int }}
              {% else %}
                {{ ((pos - 50) / 50 * 25 + 75) | int }}
              {% endif %}
Eskander commented 3 months ago

Hello, thank you for the nice integration! I also have similar blinds throughout the house and wish there was an option to define the minimum position.

[...] with a parameter they don't need/understand.

I think it would be no more or less confusing than the current parameter to set the Maximum Position of covers.

basbruss commented 3 months ago

@Eskander please open a separate issue with your feature request so I can keep better track of it and the implementation is not the same as this issue