11# -*- coding: utf-8 -*-
22
33import abc
4+ import traceback
45import tempfile
56from typing import List , Dict , Union , Tuple
67from functools import cached_property # python3.8+
78
89from PIL import Image
10+ from requests import request
911import tidevice
1012import adbutils
1113import wda
@@ -27,10 +29,8 @@ def list_serials(platform: str) -> List[str]:
2729 elif platform == Platform .IOS :
2830 raw = tidevice .Usbmux ().device_list ()
2931 devices = [d .udid for d in raw ]
30- elif platform == Platform .HARMONY :
31- devices = hdc .list_devices ()
3232 else :
33- raise HTTPException ( status_code = 200 , detail = "Unsupported platform" )
33+ devices = hdc . list_devices ( )
3434
3535 return devices
3636
@@ -51,7 +51,7 @@ def __init__(self, serial: str):
5151 self .client = Driver (serial )
5252
5353 @cached_property
54- def display_size (self ) -> Tuple :
54+ def _display_size (self ) -> Tuple :
5555 return self .client .display_size
5656
5757 def take_screenshot (self ) -> str :
@@ -68,18 +68,19 @@ def dump_hierarchy(self) -> BaseHierarchy:
6868 jsonHierarchy = hierarchy ,
6969 activityName = pageName ,
7070 packageName = packageName ,
71- windowSize = self .display_size ,
71+ windowSize = self ._display_size ,
7272 scale = 1
7373 )
7474
7575
7676class AndroidDevice (DeviceMeta ):
7777 def __init__ (self , serial : str ):
7878 self .serial = serial
79+ adbutils .AdbClient ()
7980 self .d : u2 .Device = u2 .connect (serial )
8081
8182 @cached_property
82- def window_size (self ) -> Tuple :
83+ def _window_size (self ) -> Tuple :
8384 return self .d .window_size ()
8485
8586 def take_screenshot (self ) -> str :
@@ -94,58 +95,79 @@ def dump_hierarchy(self) -> BaseHierarchy:
9495 jsonHierarchy = page_json ,
9596 activityName = current ['activity' ],
9697 packageName = current ['package' ],
97- windowSize = self .window_size ,
98+ windowSize = self ._window_size ,
9899 scale = 1
99100 )
100101
101102
102103class IosDevice (DeviceMeta ):
103- def __init__ (self , udid : str , wda_url : str ) -> None :
104+ def __init__ (self , udid : str , wda_url : str , max_depth : int ) -> None :
104105 self .udid = udid
106+ self .wda_url = wda_url
107+ self .max_depth = max_depth
105108 self .client = wda .Client (wda_url )
106109
107110 @cached_property
108111 def scale (self ) -> int :
109112 return self .client .scale
110113
111114 @cached_property
112- def window_size (self ) -> Tuple :
115+ def _window_size (self ) -> Tuple :
113116 return self .client .window_size ()
114117
115118 def take_screenshot (self ) -> str :
116119 img : Image .Image = self .client .screenshot ()
117120 return image_to_base64 (img )
118121
122+ def _current_bundle_id (self ) -> str :
123+ resp = request ("GET" , f"{ self .wda_url } /wda/activeAppInfo" , timeout = 10 ).json ()
124+ bundleId = resp .get ("value" , {}).get ("bundleId" , None )
125+ return bundleId
126+
119127 def dump_hierarchy (self ) -> BaseHierarchy :
128+ self .client .appium_settings ({"snapshotMaxDepth" : self .max_depth })
120129 data : Dict = self .client .source (format = "json" )
121130 hierarchy : Dict = ios_hierarchy .convert_ios_hierarchy (data , self .scale )
122131 return BaseHierarchy (
123132 jsonHierarchy = hierarchy ,
124133 activityName = None ,
125- packageName = self .client . bundle_id ,
126- windowSize = self .window_size ,
134+ packageName = self ._current_bundle_id () ,
135+ windowSize = self ._window_size ,
127136 scale = self .scale
128137 )
129138
139+ def wda_health (self ) -> bool :
140+ resp = request ("GET" , f"{ self .wda_url } /status" , timeout = 5 ).json ()
141+ state = resp .get ("value" , {}).get ("state" )
142+ return state == "success"
130143
131- def get_device (platform : str , serial : str , wda_url : str = None ) -> Union [HarmonyDevice , AndroidDevice ]:
132- if serial not in list_serials (platform ):
133- raise HTTPException (status_code = 200 , detail = "Device not found" )
144+
145+ def get_device (platform : str , serial : str , wda_url : str , max_depth : int ) -> Union [HarmonyDevice , AndroidDevice ]:
134146 if platform == Platform .HARMONY :
135147 return HarmonyDevice (serial )
136148 elif platform == Platform .ANDROID :
137149 return AndroidDevice (serial )
138- elif platform == Platform .IOS :
139- return IosDevice (serial , wda_url )
140150 else :
141- raise HTTPException ( status_code = 200 , detail = "Unsupported platform" )
151+ return IosDevice ( serial , wda_url , max_depth )
142152
143153
144154# Global cache for devices
145155cached_devices = {}
146156
147157
148- def init_device (platform : str , serial : str , wda_url : str = None ):
149- device = get_device (platform , serial , wda_url )
150- cached_devices [(platform , serial )] = device
151- return platform , serial
158+ def init_device (platform : str , serial : str , wda_url : str = None , max_depth : int = 30 ) -> bool :
159+
160+ if serial not in list_serials (platform ):
161+ raise HTTPException (status_code = 500 , detail = f"Device<{ serial } > not found" )
162+
163+ try :
164+ device : Union [HarmonyDevice , AndroidDevice ] = get_device (platform , serial , wda_url , max_depth )
165+ cached_devices [(platform , serial )] = device
166+
167+ if isinstance (device , IosDevice ):
168+ return device .wda_health ()
169+ except Exception :
170+ error = traceback .format_exc ()
171+ raise HTTPException (status_code = 500 , detail = error )
172+
173+ return True
0 commit comments