test_relay_switch.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. from unittest.mock import AsyncMock, MagicMock
  2. import pytest
  3. from bleak.backends.device import BLEDevice
  4. from switchbot import SwitchBotAdvertisement, SwitchbotModel
  5. from switchbot.devices import relay_switch
  6. from .test_adv_parser import generate_ble_device
  7. def create_device_for_command_testing(
  8. rawAdvData: bytes, model: str, init_data: dict | None = None):
  9. """Create a device for command testing."""
  10. ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any")
  11. device_class = (
  12. relay_switch.SwitchbotRelaySwitch2PM
  13. if model == SwitchbotModel.RELAY_SWITCH_2PM
  14. else relay_switch.SwitchbotRelaySwitch
  15. )
  16. device = device_class(
  17. ble_device, "ff", "ffffffffffffffffffffffffffffffff"
  18. )
  19. device.update_from_advertisement(
  20. make_advertisement_data(ble_device, rawAdvData, model, init_data)
  21. )
  22. device._send_command = AsyncMock()
  23. device._check_command_result = MagicMock()
  24. device.update = AsyncMock()
  25. return device
  26. def make_advertisement_data(
  27. ble_device: BLEDevice, rawAdvData: bytes, model: str, init_data: dict | None = None
  28. ):
  29. """Set advertisement data with defaults."""
  30. if init_data is None:
  31. init_data = {}
  32. if model == SwitchbotModel.RELAY_SWITCH_2PM:
  33. return SwitchBotAdvertisement(
  34. address="aa:bb:cc:dd:ee:ff",
  35. data={
  36. "rawAdvData": rawAdvData,
  37. "data": {
  38. 1: {
  39. "switchMode": True,
  40. "sequence_number": 99,
  41. "isOn": True,
  42. },
  43. 2: {
  44. "switchMode": True,
  45. "sequence_number": 99,
  46. "isOn": False,
  47. },
  48. }
  49. | init_data,
  50. "isEncrypted": False,
  51. "model": model,
  52. "modelFriendlyName": "Relay Switch 2PM",
  53. "modelName": SwitchbotModel.RELAY_SWITCH_2PM,
  54. },
  55. device=ble_device,
  56. rssi=-80,
  57. active=True,
  58. )
  59. return None
  60. @pytest.mark.asyncio
  61. @pytest.mark.parametrize(
  62. ("rawAdvData", "model", "init_data"),
  63. [
  64. (
  65. b"\x00\x00\x00\x00\x00\x00",
  66. SwitchbotModel.RELAY_SWITCH_2PM,
  67. {1: {"isOn": True}, 2: {"isOn": True}},
  68. ),
  69. ],
  70. )
  71. async def test_turn_on_2PM(rawAdvData, model, init_data):
  72. """Test turn on command."""
  73. device = create_device_for_command_testing(rawAdvData, model, init_data)
  74. await device.turn_on(1)
  75. device._send_command.assert_called_with(
  76. relay_switch.MULTI_CHANNEL_COMMANDS_TURN_ON[model][1]
  77. )
  78. assert device.is_on(1) is True
  79. await device.turn_on(2)
  80. device._send_command.assert_called_with(
  81. relay_switch.MULTI_CHANNEL_COMMANDS_TURN_ON[model][2]
  82. )
  83. assert device.is_on(2) is True
  84. @pytest.mark.asyncio
  85. @pytest.mark.parametrize(
  86. ("rawAdvData", "model", "init_data"),
  87. [
  88. (
  89. b"\x00\x00\x00\x00\x00\x00",
  90. SwitchbotModel.RELAY_SWITCH_2PM,
  91. {1: {"isOn": False}, 2: {"isOn": False}},
  92. ),
  93. ],
  94. )
  95. async def test_turn_off_2PM(rawAdvData, model, init_data):
  96. """Test turn off command."""
  97. device = create_device_for_command_testing(rawAdvData, model, init_data)
  98. await device.turn_off(1)
  99. device._send_command.assert_called_with(
  100. relay_switch.MULTI_CHANNEL_COMMANDS_TURN_OFF[model][1]
  101. )
  102. assert device.is_on(1) is False
  103. await device.turn_off(2)
  104. device._send_command.assert_called_with(
  105. relay_switch.MULTI_CHANNEL_COMMANDS_TURN_OFF[model][2]
  106. )
  107. assert device.is_on(2) is False
  108. @pytest.mark.asyncio
  109. @pytest.mark.parametrize(
  110. ("rawAdvData", "model"),
  111. [
  112. (
  113. b"\x00\x00\x00\x00\x00\x00",
  114. SwitchbotModel.RELAY_SWITCH_2PM,
  115. ),
  116. ],
  117. )
  118. async def test_turn_toggle_2PM(rawAdvData, model):
  119. """Test toggle command."""
  120. device = create_device_for_command_testing(rawAdvData, model)
  121. await device.async_toggle(1)
  122. device._send_command.assert_called_with(
  123. relay_switch.MULTI_CHANNEL_COMMANDS_TOGGLE[model][1]
  124. )
  125. assert device.is_on(1) is True
  126. await device.async_toggle(2)
  127. device._send_command.assert_called_with(
  128. relay_switch.MULTI_CHANNEL_COMMANDS_TOGGLE[model][2]
  129. )
  130. assert device.is_on(2) is False
  131. @pytest.mark.asyncio
  132. @pytest.mark.parametrize(
  133. ("rawAdvData", "model"),
  134. [
  135. (
  136. b"\x00\x00\x00\x00\x00\x00",
  137. SwitchbotModel.RELAY_SWITCH_2PM,
  138. ),
  139. ],
  140. )
  141. async def test_get_switch_mode_2PM(rawAdvData, model):
  142. """Test get switch mode."""
  143. device = create_device_for_command_testing(rawAdvData, model)
  144. assert device.switch_mode(1) is True
  145. assert device.switch_mode(2) is True
  146. @pytest.mark.asyncio
  147. @pytest.mark.parametrize(
  148. ("rawAdvData", "model"),
  149. [
  150. (
  151. b"\x00\x00\x00\x00\x00\x00",
  152. SwitchbotModel.RELAY_SWITCH_2PM,
  153. ),
  154. ],
  155. )
  156. @pytest.mark.parametrize(
  157. ("channel1_info", "channel2_info"), [(True, False), (False, True), (False, False)]
  158. )
  159. async def test_get_basic_info_returns_none(rawAdvData, model, channel1_info, channel2_info):
  160. device = create_device_for_command_testing(rawAdvData, model)
  161. device.get_current_time_and_start_time = MagicMock(return_value=("683074d6", "682fba80"))