| 
					
				 | 
			
			
				@@ -1,16 +1,29 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-from typing import Any 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-from unittest.mock import Mock 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+from unittest.mock import AsyncMock, Mock 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import pytest 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from bleak.backends.device import BLEDevice 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from switchbot import SwitchBotAdvertisement, SwitchbotModel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from switchbot.devices import curtain 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+from switchbot.devices.base_cover import COVER_EXT_SUM_KEY 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from .test_adv_parser import generate_ble_device 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-def set_advertisement_data(ble_device: BLEDevice, in_motion: bool, position: int): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def create_device_for_command_testing(calibration=True, reverse_mode=False): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, True, 50, calibration) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device._send_multiple_commands = AsyncMock() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device.update = AsyncMock() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return curtain_device 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def make_advertisement_data( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ble_device: BLEDevice, in_motion: bool, position: int, calibration: bool = True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """Set advertisement data with defaults.""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return SwitchBotAdvertisement( 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -18,7 +31,7 @@ def set_advertisement_data(ble_device: BLEDevice, in_motion: bool, position: int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         data={ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             "rawAdvData": b"c\xc0X\x00\x11\x04", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             "data": { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "calibration": True, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                "calibration": calibration, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 "battery": 88, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 "inMotion": in_motion, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 "position": position, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -42,7 +55,7 @@ def test_device_passive_not_in_motion(reverse_mode): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_advertisement_data(ble_device, False, 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, False, 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     assert curtain_device.is_opening() is False 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -55,10 +68,10 @@ def test_device_passive_opening(reverse_mode): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_advertisement_data(ble_device, True, 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, True, 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_advertisement_data(ble_device, True, 10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, True, 10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     assert curtain_device.is_opening() is True 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -71,10 +84,10 @@ def test_device_passive_closing(reverse_mode): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_advertisement_data(ble_device, True, 100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, True, 100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_advertisement_data(ble_device, True, 90) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, True, 90) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     assert curtain_device.is_opening() is False 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -87,13 +100,13 @@ def test_device_passive_opening_then_stop(reverse_mode): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_advertisement_data(ble_device, True, 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, True, 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_advertisement_data(ble_device, True, 10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, True, 10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_advertisement_data(ble_device, False, 10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, False, 10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     assert curtain_device.is_opening() is False 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -106,13 +119,13 @@ def test_device_passive_closing_then_stop(reverse_mode): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_advertisement_data(ble_device, True, 100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, True, 100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_advertisement_data(ble_device, True, 90) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, True, 90) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_advertisement_data(ble_device, False, 90) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, False, 90) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     assert curtain_device.is_opening() is False 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -126,7 +139,7 @@ async def test_device_active_not_in_motion(reverse_mode): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_advertisement_data(ble_device, False, 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, False, 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     basic_info = bytes([0, 0, 0, 0, 0, 0, 100, 0]) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -149,7 +162,7 @@ async def test_device_active_opening(reverse_mode): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_advertisement_data(ble_device, True, 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, True, 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     basic_info = bytes([0, 0, 0, 0, 0, 67, 10, 0]) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -172,7 +185,7 @@ async def test_device_active_closing(reverse_mode): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_advertisement_data(ble_device, True, 100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, True, 100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     basic_info = bytes([0, 0, 0, 0, 0, 67, 90, 0]) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -195,7 +208,7 @@ async def test_device_active_opening_then_stop(reverse_mode): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_advertisement_data(ble_device, True, 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, True, 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     basic_info = bytes([0, 0, 0, 0, 0, 67, 10, 0]) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -222,7 +235,7 @@ async def test_device_active_closing_then_stop(reverse_mode): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device = curtain.SwitchbotCurtain(ble_device, reverse_mode=reverse_mode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_advertisement_data(ble_device, True, 100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, True, 100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     basic_info = bytes([0, 0, 0, 0, 0, 67, 90, 0]) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -240,3 +253,174 @@ async def test_device_active_closing_then_stop(reverse_mode): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     assert curtain_device.is_opening() is False 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     assert curtain_device.is_closing() is False 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@pytest.mark.asyncio 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+async def test_get_basic_info_returns_none_when_no_data(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device = curtain.SwitchbotCurtain(ble_device) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, True, 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device._get_basic_info = AsyncMock(return_value=None) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert await curtain_device.get_basic_info() is None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@pytest.mark.asyncio 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@pytest.mark.parametrize( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "data,result", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            bytes([0, 1, 10, 2, 255, 255, 50, 4]), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            [1, 1, 2, "right_to_left", 1, 1, 50, 4], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        (bytes([0, 1, 10, 2, 0, 0, 50, 4]), [1, 1, 2, "left_to_right", 0, 0, 50, 4]), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+async def test_get_basic_info(data, result): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device = curtain.SwitchbotCurtain(ble_device) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device.update_from_advertisement( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        make_advertisement_data(ble_device, True, 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    async def custom_implementation(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return data 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device._get_basic_info = Mock(side_effect=custom_implementation) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    info = await curtain_device.get_basic_info() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert info["battery"] == result[0] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert info["firmware"] == result[1] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert info["chainLength"] == result[2] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert info["openDirection"] == result[3] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert info["touchToOpen"] == result[4] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert info["light"] == result[4] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert info["fault"] == result[4] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert info["solarPanel"] == result[5] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert info["calibration"] == result[5] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert info["calibrated"] == result[5] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert info["inMotion"] == result[5] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert info["position"] == result[6] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert info["timers"] == result[7] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@pytest.mark.asyncio 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+async def test_open(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device = create_device_for_command_testing() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    await curtain_device.open() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert curtain_device.is_opening() is True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert curtain_device.is_closing() is False 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device._send_multiple_commands.assert_awaited_once() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@pytest.mark.asyncio 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+async def test_close(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device = create_device_for_command_testing() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    await curtain_device.close() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert curtain_device.is_opening() is False 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert curtain_device.is_closing() is True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device._send_multiple_commands.assert_awaited_once() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@pytest.mark.asyncio 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+async def test_stop(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device = create_device_for_command_testing() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    await curtain_device.stop() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert curtain_device.is_opening() is False 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert curtain_device.is_closing() is False 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device._send_multiple_commands.assert_awaited_once() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@pytest.mark.asyncio 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+async def test_set_position_opening(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device = create_device_for_command_testing() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    await curtain_device.set_position(100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert curtain_device.is_opening() is True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert curtain_device.is_closing() is False 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device._send_multiple_commands.assert_awaited_once() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@pytest.mark.asyncio 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+async def test_set_position_closing(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device = create_device_for_command_testing() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    await curtain_device.set_position(0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert curtain_device.is_opening() is False 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert curtain_device.is_closing() is True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device._send_multiple_commands.assert_awaited_once() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def test_get_position(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device = create_device_for_command_testing() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert curtain_device.get_position() == 50 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@pytest.mark.asyncio 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+async def test_get_extended_info_summary_sends_command(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device = create_device_for_command_testing() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device._send_command = AsyncMock() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    await curtain_device.get_extended_info_summary() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device._send_command.assert_awaited_once_with(key=COVER_EXT_SUM_KEY) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@pytest.mark.asyncio 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@pytest.mark.parametrize("data_value", [(None), (b"\x07"), (b"\x00")]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+async def test_get_extended_info_summary_returns_none_when_bad_data(data_value): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device = create_device_for_command_testing() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device._send_command = AsyncMock(return_value=data_value) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert await curtain_device.get_extended_info_summary() is None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@pytest.mark.asyncio 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@pytest.mark.parametrize( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "data,result", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ([0, 0, 0], [True, False, False, "right_to_left"]), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ([255, 255, 0], [False, True, True, "left_to_right"]), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+async def test_get_extended_info_summary_returns_device0(data, result): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device = create_device_for_command_testing() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device._send_command = AsyncMock(return_value=bytes(data)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ext_result = await curtain_device.get_extended_info_summary() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert ext_result["device0"]["openDirectionDefault"] == result[0] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert ext_result["device0"]["touchToOpen"] == result[1] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert ext_result["device0"]["light"] == result[2] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert ext_result["device0"]["openDirection"] == result[3] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert "device1" not in ext_result 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@pytest.mark.asyncio 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@pytest.mark.parametrize( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "data,result", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ([0, 0, 1], [True, False, False, "right_to_left"]), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ([255, 255, 255], [False, True, True, "left_to_right"]), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+async def test_get_extended_info_summary_returns_device1(data, result): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device = create_device_for_command_testing() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device._send_command = AsyncMock(return_value=bytes(data)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ext_result = await curtain_device.get_extended_info_summary() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert ext_result["device1"]["openDirectionDefault"] == result[0] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert ext_result["device1"]["touchToOpen"] == result[1] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert ext_result["device1"]["light"] == result[2] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert ext_result["device1"]["openDirection"] == result[3] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def test_get_light_level(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device = create_device_for_command_testing() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert curtain_device.get_light_level() == 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@pytest.mark.parametrize("reverse_mode", [(True), (False)]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def test_is_reversed(reverse_mode): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device = create_device_for_command_testing(reverse_mode=reverse_mode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert curtain_device.is_reversed() == reverse_mode 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@pytest.mark.parametrize("calibration", [(True), (False)]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def test_is_calibrated(calibration): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    curtain_device = create_device_for_command_testing(calibration=calibration) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    assert curtain_device.is_calibrated() == calibration 
			 |