test_curtain.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import pytest
  2. from typing import Any
  3. from bleak.backends.device import BLEDevice
  4. from switchbot import SwitchBotAdvertisement, SwitchbotModel
  5. from switchbot.devices import curtain
  6. from test_adv_parser import generate_ble_device
  7. def set_advertisement_data(ble_device: BLEDevice, in_motion: bool, position: int):
  8. """Set advertisement data with defaults."""
  9. return SwitchBotAdvertisement(
  10. address="aa:bb:cc:dd:ee:ff",
  11. data={
  12. "rawAdvData": b"c\xc0X\x00\x11\x04",
  13. "data": {
  14. "calibration": True,
  15. "battery": 88,
  16. "inMotion": in_motion,
  17. "position": position,
  18. "lightLevel": 1,
  19. "deviceChain": 1,
  20. },
  21. "isEncrypted": False,
  22. "model": "c",
  23. "modelFriendlyName": "Curtain",
  24. "modelName": SwitchbotModel.CURTAIN,
  25. },
  26. device=ble_device,
  27. rssi=-80,
  28. active=True,
  29. )
  30. @pytest.mark.parametrize("reverse_mode", [(True),(False)])
  31. def test_device_passive_not_in_motion(reverse_mode):
  32. """Test passive not in motion advertisement."""
  33. ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any")
  34. curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode)
  35. curtain_device.update_from_advertisement(set_advertisement_data(ble_device, False, 0))
  36. assert curtain_device.is_opening() == False
  37. assert curtain_device.is_closing() == False
  38. @pytest.mark.parametrize("reverse_mode", [(True),(False)])
  39. def test_device_passive_opening(reverse_mode):
  40. """Test passive opening advertisement."""
  41. ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any")
  42. curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode)
  43. curtain_device.update_from_advertisement(set_advertisement_data(ble_device, True, 0))
  44. curtain_device.update_from_advertisement(set_advertisement_data(ble_device, True, 10))
  45. assert curtain_device.is_opening() == True
  46. assert curtain_device.is_closing() == False
  47. @pytest.mark.parametrize("reverse_mode", [(True),(False)])
  48. def test_device_passive_closing(reverse_mode):
  49. """Test passive closing advertisement."""
  50. ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any")
  51. curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode)
  52. curtain_device.update_from_advertisement(set_advertisement_data(ble_device, True, 100))
  53. curtain_device.update_from_advertisement(set_advertisement_data(ble_device, True, 90))
  54. assert curtain_device.is_opening() == False
  55. assert curtain_device.is_closing() == True
  56. @pytest.mark.parametrize("reverse_mode", [(True),(False)])
  57. def test_device_passive_opening_then_stop(reverse_mode):
  58. """Test passive stopped after opening advertisement."""
  59. ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any")
  60. curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode)
  61. curtain_device.update_from_advertisement(set_advertisement_data(ble_device, True, 0))
  62. curtain_device.update_from_advertisement(set_advertisement_data(ble_device, True, 10))
  63. curtain_device.update_from_advertisement(set_advertisement_data(ble_device, False, 10))
  64. assert curtain_device.is_opening() == False
  65. assert curtain_device.is_closing() == False
  66. @pytest.mark.parametrize("reverse_mode", [(True),(False)])
  67. def test_device_passive_closing_then_stop(reverse_mode):
  68. """Test passive stopped after closing advertisement."""
  69. ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any")
  70. curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode)
  71. curtain_device.update_from_advertisement(set_advertisement_data(ble_device, True, 100))
  72. curtain_device.update_from_advertisement(set_advertisement_data(ble_device, True, 90))
  73. curtain_device.update_from_advertisement(set_advertisement_data(ble_device, False, 90))
  74. assert curtain_device.is_opening() == False
  75. assert curtain_device.is_closing() == False
  76. @pytest.mark.asyncio
  77. @pytest.mark.parametrize("reverse_mode", [(True),(False)])
  78. async def test_device_active_not_in_motion(mocker, reverse_mode):
  79. """Test active not in motion."""
  80. ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any")
  81. curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode)
  82. curtain_device.update_from_advertisement(set_advertisement_data(ble_device, False, 0))
  83. basic_info = bytes([0,0,0,0,0,0,100,0])
  84. async def custom_implementation():
  85. return basic_info
  86. mocker.patch.object(curtain_device, '_get_basic_info', side_effect=custom_implementation)
  87. await curtain_device.get_basic_info()
  88. assert curtain_device.is_opening() == False
  89. assert curtain_device.is_closing() == False
  90. @pytest.mark.asyncio
  91. @pytest.mark.parametrize("reverse_mode", [(True),(False)])
  92. async def test_device_active_opening(mocker, reverse_mode):
  93. """Test active opening."""
  94. ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any")
  95. curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode)
  96. curtain_device.update_from_advertisement(set_advertisement_data(ble_device, True, 0))
  97. basic_info = bytes([0,0,0,0,0,67,10,0])
  98. async def custom_implementation():
  99. return basic_info
  100. mocker.patch.object(curtain_device, '_get_basic_info', side_effect=custom_implementation)
  101. await curtain_device.get_basic_info()
  102. assert curtain_device.is_opening() == True
  103. assert curtain_device.is_closing() == False
  104. @pytest.mark.asyncio
  105. @pytest.mark.parametrize("reverse_mode", [(True),(False)])
  106. async def test_device_active_closing(mocker, reverse_mode):
  107. """Test active closing."""
  108. ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any")
  109. curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode)
  110. curtain_device.update_from_advertisement(set_advertisement_data(ble_device, True, 100))
  111. basic_info = bytes([0,0,0,0,0,67,90,0])
  112. async def custom_implementation():
  113. return basic_info
  114. mocker.patch.object(curtain_device, '_get_basic_info', side_effect=custom_implementation)
  115. await curtain_device.get_basic_info()
  116. assert curtain_device.is_opening() == False
  117. assert curtain_device.is_closing() == True
  118. @pytest.mark.asyncio
  119. @pytest.mark.parametrize("reverse_mode", [(True),(False)])
  120. async def test_device_active_opening_then_stop(mocker, reverse_mode):
  121. """Test active stopped after opening."""
  122. ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any")
  123. curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode)
  124. curtain_device.update_from_advertisement(set_advertisement_data(ble_device, True, 0))
  125. basic_info = bytes([0,0,0,0,0,67,10,0])
  126. async def custom_implementation():
  127. return basic_info
  128. mocker.patch.object(curtain_device, '_get_basic_info', side_effect=custom_implementation)
  129. await curtain_device.get_basic_info()
  130. basic_info = bytes([0,0,0,0,0,0,10,0])
  131. await curtain_device.get_basic_info()
  132. assert curtain_device.is_opening() == False
  133. assert curtain_device.is_closing() == False
  134. @pytest.mark.asyncio
  135. @pytest.mark.parametrize("reverse_mode", [(True),(False)])
  136. async def test_device_active_closing_then_stop(mocker, reverse_mode):
  137. """Test active stopped after closing."""
  138. ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any")
  139. curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode)
  140. curtain_device.update_from_advertisement(set_advertisement_data(ble_device, True, 100))
  141. basic_info = bytes([0,0,0,0,0,67,90,0])
  142. async def custom_implementation():
  143. return basic_info
  144. mocker.patch.object(curtain_device, '_get_basic_info', side_effect=custom_implementation)
  145. await curtain_device.get_basic_info()
  146. basic_info = bytes([0,0,0,0,0,0,90,0])
  147. await curtain_device.get_basic_info()
  148. assert curtain_device.is_opening() == False
  149. assert curtain_device.is_closing() == False