Browse Source

curtains: report position after sending stop command

Fabian Peter Hammerle 3 years ago
parent
commit
5bb37cf6e9
4 changed files with 38 additions and 10 deletions
  1. 4 0
      CHANGELOG.md
  2. 1 1
      setup.py
  3. 5 0
      switchbot_mqtt/__init__.py
  4. 28 9
      tests/test_switchbot_curtain_motor.py

+ 4 - 0
CHANGELOG.md

@@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 ## [Unreleased]
+### Added
+- Report position of curtain motor on topic  `homeassistant/cover/switchbot-curtain/MAC_ADDRESS/position`
+  after sending stop command.
+
 ### Fixed
 - dockerfile: split `pipenv install` into two stages to speed up image builds
 - dockerfile: `chmod` files copied from host to no longer require `o=rX` perms on host

+ 1 - 1
setup.py

@@ -72,7 +72,7 @@ setuptools.setup(
     ],
     entry_points={"console_scripts": ["switchbot-mqtt = switchbot_mqtt:_main"]},
     install_requires=[
-        # >=0.10.0 for SwitchbotCurtain.get_position
+        # >=0.10.0 for SwitchbotCurtain.{update,get_position}
         "PySwitchbot>=0.10.0,<0.11",
         "paho-mqtt<2",
     ],

+ 5 - 0
switchbot_mqtt/__init__.py

@@ -227,6 +227,10 @@ class _CurtainMotor(_MQTTControlledActor):
             mqtt_client=mqtt_client,
         )
 
+    def _update_position(self, mqtt_client: paho.mqtt.client.Client) -> None:
+        self._device.update()
+        self._report_position(mqtt_client=mqtt_client)
+
     def execute_command(
         self, mqtt_message_payload: bytes, mqtt_client: paho.mqtt.client.Client
     ) -> None:
@@ -255,6 +259,7 @@ class _CurtainMotor(_MQTTControlledActor):
                 # https://www.home-assistant.io/integrations/cover.mqtt/#configuration-variables
                 # https://community.home-assistant.io/t/mqtt-how-to-remove-retained-messages/79029/2
                 self.report_state(mqtt_client=mqtt_client, state=b"")
+                self._update_position(mqtt_client=mqtt_client)
         else:
             _LOGGER.warning(
                 "unexpected payload %r (expected 'OPEN', 'CLOSE', or 'STOP')",

+ 28 - 9
tests/test_switchbot_curtain_motor.py

@@ -87,6 +87,19 @@ def test__report_position_invalid(caplog, position):
     publish_mock.assert_not_called()
 
 
+def test__update_position():
+    with unittest.mock.patch("switchbot.SwitchbotCurtain.__init__", return_value=None):
+        actor = switchbot_mqtt._CurtainMotor(mac_address="dummy")
+    with unittest.mock.patch(
+        "switchbot.SwitchbotCurtain.update"
+    ) as update_mock, unittest.mock.patch.object(
+        actor, "_report_position"
+    ) as report_position_mock:
+        actor._update_position(mqtt_client="client")
+    update_mock.assert_called_once_with()
+    report_position_mock.assert_called_once_with(mqtt_client="client")
+
+
 @pytest.mark.parametrize("mac_address", ["aa:bb:cc:dd:ee:ff", "aa:bb:cc:11:22:33"])
 @pytest.mark.parametrize(
     ("message_payload", "action_name"),
@@ -108,16 +121,18 @@ def test_execute_command(
 ):
     with unittest.mock.patch(
         "switchbot.SwitchbotCurtain.__init__", return_value=None
-    ) as device_init_mock, caplog.at_level(logging.INFO):
+    ) as device_init_mock:
         actor = switchbot_mqtt._CurtainMotor(mac_address=mac_address)
-        with unittest.mock.patch.object(
-            actor, "report_state"
-        ) as report_mock, unittest.mock.patch(
-            action_name, return_value=command_successful
-        ) as action_mock:
-            actor.execute_command(
-                mqtt_client="dummy", mqtt_message_payload=message_payload
-            )
+    with unittest.mock.patch.object(
+        actor, "report_state"
+    ) as report_mock, unittest.mock.patch(
+        action_name, return_value=command_successful
+    ) as action_mock, unittest.mock.patch.object(
+        actor, "_update_position"
+    ) as update_position_mock, caplog.at_level(
+        logging.INFO
+    ):
+        actor.execute_command(mqtt_client="dummy", mqtt_message_payload=message_payload)
     device_init_mock.assert_called_once_with(mac=mac_address, reverse_mode=True)
     action_mock.assert_called_once_with()
     if command_successful:
@@ -151,6 +166,10 @@ def test_execute_command(
             )
         ]
         report_mock.assert_not_called()
+    if action_name == "switchbot.SwitchbotCurtain.stop" and command_successful:
+        update_position_mock.assert_called_once_with(mqtt_client="dummy")
+    else:
+        update_position_mock.assert_not_called()
 
 
 @pytest.mark.parametrize("mac_address", ["aa:bb:cc:dd:ee:ff"])