twrecked / hass-virtual

Virtual Components for Home Assistant
GNU General Public License v3.0
167 stars 28 forks source link

Support stop and set_position for virtual cover #106

Closed lodegaard closed 5 months ago

lodegaard commented 5 months ago

Hey

I just found this project and it's been really helpful, but when creating som blueprints for a new cover entity I needed some more features from the virtual cover.

This PR adds support for "stop" and "set_position" for the virtual cover entity, and uses the async_call_later helper from homeassistant to fake a moving cover.

It also introduces two new config parameters for the virtual cover to control how "fast" the cover opens and closes

twrecked commented 5 months ago

First, thanks for doing this.

But it doesn't work as-is on my device. It complains about async calls not happening on the event loop and doesn't stop opening or closing. I'm not sure how to update your PR so I'll just post a diff here.

diff --git a/custom_components/virtual/cover.py b/custom_components/virtual/cover.py
--- a/custom_components/virtual/cover.py    (revision 81891c3163cdec67fb8e7f85f22bbb4c9bc7fa56)
+++ b/custom_components/virtual/cover.py    (date 1719149889851)
@@ -109,12 +109,14 @@
         _LOGGER.info(f"opening {self.name}")
         self._attr_is_opening = True
         self._attr_is_closing = False
+        self._target_cover_position = 100
         self._tick()

     def close_cover(self, **kwargs: Any) -> None:
         _LOGGER.info(f"closing {self.name}")
         self._attr_is_opening = False
         self._attr_is_closing = True
+        self._target_cover_position = 0
         self._tick()

     def stop_cover(self, **kwargs: Any) -> None:
@@ -128,9 +130,9 @@
             self._attr_is_closed = False
         else:
             self._attr_is_closed = True
-            
-        self.async_write_ha_state()
-        
+
+        self.schedule_update_ha_state()
+
     def set_cover_position(self, **kwargs: Any) -> None:
         _LOGGER.info(f"setting {self.name} position {kwargs['position']}")
         self._target_cover_position = kwargs['position']
@@ -141,7 +143,7 @@
         elif self._target_cover_position > self._attr_current_cover_position:
             self.open_cover()

-    def _update_cover_position(self, *args: Any) -> None:
+    async def _update_cover_position(self, *args: Any) -> None:
         if self._target_cover_position is not None:
             if self._attr_is_closing and self._attr_current_cover_position <= self._target_cover_position :
                 self.stop_cover()

These fixed it for me.

lodegaard commented 5 months ago

@twrecked Thanks for testing it.

I pushed a commit with your suggested changes.

The zigbee-puck I used as a reference had to be stopped explicitly once started, so I did the same for the virtual device since it was useful for debugging my blueprints.

twrecked commented 5 months ago

Many thanks for this!

ofercohen commented 4 months ago

Thank you very much for this!

When I try to set a position (by calling a service or using the slider), the virtual cover opens/closes all the way (or until I pause it). Any advice on this?