22
33import abc
44import tempfile
5- from typing import List , Dict , Union
5+ from typing import List , Dict , Union , Tuple
6+ from functools import cached_property # python3.8+
67
78from PIL import Image
9+ import tidevice
810import adbutils
11+ import wda
912import uiautomator2 as u2
1013from hmdriver2 import hdc
14+ from hmdriver2 .driver import Driver
1115from fastapi import HTTPException
1216
1317from uiviewer ._utils import file_to_base64 , image_to_base64
@@ -20,10 +24,13 @@ def list_serials(platform: str) -> List[str]:
2024 if platform == Platform .ANDROID :
2125 raws = adbutils .AdbClient ().device_list ()
2226 devices = [item .serial for item in raws ]
23- if platform == Platform .IOS :
24- devices = []
25- if platform == Platform .HARMONY :
27+ elif platform == Platform .IOS :
28+ raw = tidevice .Usbmux ().device_list ()
29+ devices = [d .udid for d in raw ]
30+ elif platform == Platform .HARMONY :
2631 devices = hdc .list_devices ()
32+ else :
33+ raise HTTPException (status_code = 200 , detail = "Unsupported platform" )
2734
2835 return devices
2936
@@ -41,7 +48,11 @@ def dump_hierarchy(self) -> Dict:
4148class HarmonyDevice (DeviceMeta ):
4249 def __init__ (self , serial : str ):
4350 self .serial = serial
44- self .client = hdc .HdcWrapper (serial )
51+ self .client = Driver (serial )
52+
53+ @cached_property
54+ def display_size (self ) -> Tuple :
55+ return self .client .display_size
4556
4657 def take_screenshot (self ) -> str :
4758 with tempfile .NamedTemporaryFile (delete = True , suffix = ".png" ) as f :
@@ -50,15 +61,27 @@ def take_screenshot(self) -> str:
5061 return file_to_base64 (path )
5162
5263 def dump_hierarchy (self ) -> BaseHierarchy :
53- raw = self .client .dump_hierarchy ()
54- return harmony_hierarchy .convert_harmony_hierarchy (raw )
64+ packageName , pageName = self .client .current_app ()
65+ raw : Dict = self .client .dump_hierarchy ()
66+ hierarchy : Dict = harmony_hierarchy .convert_harmony_hierarchy (raw )
67+ return BaseHierarchy (
68+ jsonHierarchy = hierarchy ,
69+ activityName = pageName ,
70+ packageName = packageName ,
71+ windowSize = self .display_size ,
72+ scale = 1
73+ )
5574
5675
5776class AndroidDevice (DeviceMeta ):
5877 def __init__ (self , serial : str ):
5978 self .serial = serial
6079 self .d : u2 .Device = u2 .connect (serial )
6180
81+ @cached_property
82+ def window_size (self ) -> Tuple :
83+ return self .d .window_size ()
84+
6285 def take_screenshot (self ) -> str :
6386 img : Image .Image = self .d .screenshot ()
6487 return image_to_base64 (img )
@@ -69,20 +92,51 @@ def dump_hierarchy(self) -> BaseHierarchy:
6992 page_json = android_hierarchy .get_android_hierarchy (page_xml )
7093 return BaseHierarchy (
7194 jsonHierarchy = page_json ,
72- activity = current ['activity' ],
95+ activityName = current ['activity' ],
7396 packageName = current ['package' ],
74- windowSize = self .d . window_size () ,
97+ windowSize = self .window_size ,
7598 scale = 1
7699 )
77100
78101
79- def get_device (platform : str , serial : str ) -> Union [HarmonyDevice , AndroidDevice ]:
102+ class IosDevice (DeviceMeta ):
103+ def __init__ (self , udid : str , wda_url : str ) -> None :
104+ self .udid = udid
105+ self .client = wda .Client (wda_url )
106+
107+ @cached_property
108+ def scale (self ) -> int :
109+ return self .client .scale
110+
111+ @cached_property
112+ def window_size (self ) -> Tuple :
113+ return self .client .window_size ()
114+
115+ def take_screenshot (self ) -> str :
116+ img : Image .Image = self .client .screenshot ()
117+ return image_to_base64 (img )
118+
119+ def dump_hierarchy (self ) -> BaseHierarchy :
120+ data : Dict = self .client .source (format = "json" )
121+ hierarchy : Dict = ios_hierarchy .convert_ios_hierarchy (data , self .scale )
122+ return BaseHierarchy (
123+ jsonHierarchy = hierarchy ,
124+ activityName = None ,
125+ packageName = self .client .bundle_id ,
126+ windowSize = self .window_size ,
127+ scale = self .scale
128+ )
129+
130+
131+ def get_device (platform : str , serial : str , wda_url : str = None ) -> Union [HarmonyDevice , AndroidDevice ]:
80132 if serial not in list_serials (platform ):
81133 raise HTTPException (status_code = 200 , detail = "Device not found" )
82134 if platform == Platform .HARMONY :
83135 return HarmonyDevice (serial )
84136 elif platform == Platform .ANDROID :
85137 return AndroidDevice (serial )
138+ elif platform == Platform .IOS :
139+ return IosDevice (serial , wda_url )
86140 else :
87141 raise HTTPException (status_code = 200 , detail = "Unsupported platform" )
88142
@@ -91,7 +145,7 @@ def get_device(platform: str, serial: str) -> Union[HarmonyDevice, AndroidDevice
91145cached_devices = {}
92146
93147
94- def init_device (platform : str , serial : str ):
95- device = get_device (platform , serial )
148+ def init_device (platform : str , serial : str , wda_url : str = None ):
149+ device = get_device (platform , serial , wda_url )
96150 cached_devices [(platform , serial )] = device
97151 return platform , serial
0 commit comments