devicely 2.1.3 → 2.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/devicely.js +105 -1
- package/lib/androidDeviceDetection.js +276 -1
- package/lib/appMappings.js +337 -1
- package/lib/deviceDetection.js +394 -1
- package/lib/devices.js +54 -1
- package/lib/doctor.js +94 -1
- package/lib/executor.js +104 -1
- package/lib/logger.js +35 -1
- package/lib/scriptLoader.js +75 -0
- package/lib/server.js +3483 -1
- package/package.json +3 -12
- package/scripts/compile-shell-scripts.js +208 -0
- package/scripts/encrypt-shell-simple.js +75 -0
- package/scripts/obfuscate-shell.js +160 -0
- package/scripts/shell/android_device_control +0 -0
- package/scripts/shell/android_device_control.sh +848 -0
- package/scripts/shell/apps_presets.conf +271 -0
- package/scripts/shell/connect_android_usb +0 -0
- package/scripts/shell/connect_android_usb_multi_final +0 -0
- package/scripts/shell/connect_android_usb_multi_final.sh +289 -0
- package/scripts/shell/connect_android_wireless +0 -0
- package/scripts/shell/connect_android_wireless.sh +58 -0
- package/scripts/shell/connect_android_wireless_multi_final +0 -0
- package/scripts/shell/connect_android_wireless_multi_final.sh +476 -0
- package/scripts/shell/connect_ios_usb +0 -0
- package/scripts/shell/connect_ios_usb_multi_final +0 -0
- package/scripts/shell/connect_ios_usb_multi_final.sh +4225 -0
- package/scripts/shell/connect_ios_wireless_multi_final +0 -0
- package/scripts/shell/connect_ios_wireless_multi_final.sh +4167 -0
- package/scripts/shell/create_production_scripts +0 -0
- package/scripts/shell/create_production_scripts.sh +38 -0
- package/scripts/shell/devices.conf +24 -0
- package/scripts/shell/diagnose_wireless_ios +0 -0
- package/scripts/shell/find_element_coordinates +0 -0
- package/scripts/shell/find_wda +0 -0
- package/scripts/shell/install_uiautomator2 +0 -0
- package/scripts/shell/install_uiautomator2.sh +93 -0
- package/scripts/shell/ios_device_control +0 -0
- package/scripts/shell/ios_device_control.sh +220 -0
- package/scripts/shell/organize_project +0 -0
- package/scripts/shell/organize_project.sh +59 -0
- package/scripts/shell/pre-publish-check +0 -0
- package/scripts/shell/pre-publish-check.sh +238 -0
- package/scripts/shell/publish +0 -0
- package/scripts/shell/publish-to-npm +0 -0
- package/scripts/shell/publish-to-npm.sh +366 -0
- package/scripts/shell/publish.sh +100 -0
- package/scripts/shell/setup +0 -0
- package/scripts/shell/setup.sh +121 -0
- package/scripts/shell/setup_android +0 -0
- package/scripts/shell/start +0 -0
- package/scripts/shell/start.sh +59 -0
- package/scripts/shell/sync-to-npm-package-final +0 -0
- package/scripts/shell/sync-to-npm-package-final.sh +60 -0
- package/scripts/shell/test-local-package.sh +95 -0
- package/scripts/shell/test_android_locators +0 -0
- package/scripts/shell/test_connect +0 -0
- package/scripts/shell/test_device_detection +0 -0
- package/scripts/shell/test_fixes +0 -0
- package/scripts/shell/test_getlocators_fix +0 -0
- package/scripts/shell/test_recording_feature +0 -0
- package/scripts/shell/verify-shell-protection +0 -0
- package/scripts/shell/verify-shell-protection.sh +73 -0
- package/scripts/shell/verify_distribution +0 -0
- package/lib/package-lock.json +0 -1678
- package/lib/package.json +0 -30
- package/lib/screenshots/screenshot_ios_iPhone17_20260205_225900.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhone17_20260205_225942.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhone17_20260205_231101.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhone17_20260205_232911.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhone17_20260208_095103.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhone17_20260208_095720.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_115040.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_115047.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_115118.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_115125.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_115143.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_120107.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_120118.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_120137.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_120201.png +0 -0
- package/lib/screenshots/screenshot_ios_iPhoneXR17x_20260206_134529.png +0 -0
- package/scripts/shell/android_device_control.enc +0 -1
- package/scripts/shell/connect_android_usb_multi_final.enc +0 -1
- package/scripts/shell/connect_android_wireless.enc +0 -1
- package/scripts/shell/connect_android_wireless_multi_final.enc +0 -1
- package/scripts/shell/connect_ios_usb_multi_final.enc +0 -1
- package/scripts/shell/connect_ios_wireless_multi_final.enc +0 -1
- package/scripts/shell/ios_device_control.enc +0 -1
package/lib/deviceDetection.js
CHANGED
|
@@ -1,2 +1,395 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
function _0x338f(_0x821082,_0x445b9b){_0x821082=_0x821082-0x186;const _0x3f581e=_0x3f58();let _0x338f00=_0x3f581e[_0x821082];if(_0x338f['VksJjG']===undefined){var _0x12b9ba=function(_0x40df78){const _0x27c18d='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x9ebfb9='',_0x506f5f='';for(let _0x3fda03=0x0,_0x458f4,_0x39b187,_0x152a18=0x0;_0x39b187=_0x40df78['charAt'](_0x152a18++);~_0x39b187&&(_0x458f4=_0x3fda03%0x4?_0x458f4*0x40+_0x39b187:_0x39b187,_0x3fda03++%0x4)?_0x9ebfb9+=String['fromCharCode'](0xff&_0x458f4>>(-0x2*_0x3fda03&0x6)):0x0){_0x39b187=_0x27c18d['indexOf'](_0x39b187);}for(let _0xb50c8b=0x0,_0x371196=_0x9ebfb9['length'];_0xb50c8b<_0x371196;_0xb50c8b++){_0x506f5f+='%'+('00'+_0x9ebfb9['charCodeAt'](_0xb50c8b)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x506f5f);};_0x338f['dUXWtt']=_0x12b9ba,_0x338f['wRXnOF']={},_0x338f['VksJjG']=!![];}const _0x5d6c4d=_0x3f581e[0x0],_0x3412d7=_0x821082+_0x5d6c4d,_0x503d3a=_0x338f['wRXnOF'][_0x3412d7];return!_0x503d3a?(_0x338f00=_0x338f['dUXWtt'](_0x338f00),_0x338f['wRXnOF'][_0x3412d7]=_0x338f00):_0x338f00=_0x503d3a,_0x338f00;}const _0x3d15b0=_0x338f;(function(_0x55016e,_0x4cf00b){const _0x3a2e30=_0x338f,_0x23aeb3=_0x55016e();while(!![]){try{const _0x486452=parseInt(_0x3a2e30(0x1a5))/0x1*(parseInt(_0x3a2e30(0x1b0))/0x2)+-parseInt(_0x3a2e30(0x19e))/0x3+-parseInt(_0x3a2e30(0x1a0))/0x4+-parseInt(_0x3a2e30(0x189))/0x5*(parseInt(_0x3a2e30(0x1a2))/0x6)+parseInt(_0x3a2e30(0x1ff))/0x7+-parseInt(_0x3a2e30(0x194))/0x8+-parseInt(_0x3a2e30(0x203))/0x9*(-parseInt(_0x3a2e30(0x1c4))/0xa);if(_0x486452===_0x4cf00b)break;else _0x23aeb3['push'](_0x23aeb3['shift']());}catch(_0xe4eb56){_0x23aeb3['push'](_0x23aeb3['shift']());}}}(_0x3f58,0x53330));function _0x3f58(){const _0x2c663e=['wLjsqui','BwfPBG','DgXtAhu','Cfjkt1K','mtq1mJuXnMrcuMzqva','icaGic0Gv2LYzwXLC3mGzgv2AwnLCYbHCMuGy29UzMLNDxjLzcbPBIbKzxzPy2vZlMnVBMy','mta4nZmYyxnquvDT','CNLfs24','ntu1nNz4tNLVtG','v0nrrgO','vujozLu','mtaWm1DVq3b0wa','reXKq3q','BMfTzq','ic0G','yxjNDG','y0TYt3m','zxHPDa','BLvJAhK','AfbXwhi','sK9zuLm','AfPhy2e','mJzjvwLoC0S','Dxvrs0W','s25xww8','Duz2uwm','Au9tlq','rwPoyMq','ENfQC3u','AwrLDMLJzv9Pza','tvzUrwe','rMXLAeG','vgjxEhy','sLrNtui','igrLDMLJzsHZktOk','vuXNAMK','Bvryy0m','wNDAsfy','Dg9tDhjPBMC','oJGXmdaVC3rHDhvZ','DhLWzq','EfnLEMO','nZy2ntKXmhjJBLjRsa','icaGsva6ia','rwHzCe4','v1rTDei','iNn0yxrLiG','s2zPrK8','y0Hzq1e','s2P4t0e','u3rpv1i','EK5hEK4','Ahr0CdOVl2XVy2fSAg9ZDdO','whDADMC','qw5KCM9PzcbKzxrLy3rPB24GBw9KDwXLig5VDcbHDMfPBgfIBgu','C3vIC3rYAw5N','icbbBMrYB2LKoG','zKrzzxG','yw5KCM9Pza','vK9nqMO','DxbWA0S','BMPtsuO','wfbwCKi','zxjYB3i','CujRAwG','yvbPA3e','ENnotMm','icaGic0GvvncigrLDMLJzxmGyxjLignVBM5Ly3rLzcbHBMqGDhj1C3rLza','u0DUAgy','4PYfief1Dg8TC2f2zwqG','C3rKB3v0','ueLSC1a','sgresLC','rKX3teO','ls1TyxGTDgLTzq','icaGic0Grgv2AwnLigLZigf1DgHVCML6zwqGkgnOzwnRigrLDMLJzsbZy3jLzw4P','EwfWAxm','Cg9YDa','Aw9cDKm','lhvZyGO','zgv0zwn0vvncrgv2AwnLCW','tg5pELu','ifvtqIbKzxzPy2uGDg8Gy29UzMLNoIa','B2zMBgLUzq','BMv3sKC','vuP2qvq','Bg9HzerLDMLJzxngCM9Tq29UzMLN','shLWt2K','uKDmyLq','icaGvurjrdOG','DeDlwwK','vMzIB2W','uhfNAg8','C3rYAw5NAwz5','vxjwvLC','DLjhu28','BwDKtMy','sgPVy28','EeLjBwC','zhPnvLm','icbPt1m6','mJG5mtKYng1pA3v5zW','y2HPBgrFChjVy2vZCW','Dg9vChbLCKnHC2u','BNDZzhe','ownfwejyBG','zgLZy292zxjbBgXezxzPy2vZ','Ewj0DuC','v3D2qLO','y01hy2O','whDRuwq','B0X4rhC','Dw5ZEvK','vu1JBxe','Ahr0CdOVlW','y1jUExi','qLHuB1i','B25SAw5L','Eu50rMi','CM9ADuK','uvLzrNK','l3n0yxr1CW','t2zYEu8','icaGic0GBgLIAw1VyMLSzwrLDMLJzsbPCYbPBNn0ywXSzwq6igjYzxCGAw5ZDgfSBcbSAwjPBw9IAwXLzgv2AwnL','DNvxu3a','Dw5hAei','y29UBMvJDgLVBLr5Cgu','CLLmugO','vxfrtKe','B0TjD0S','zg5VEfa','C29Tzq','yNfysgu','r0HbAha','uwDYEfq','BKzdsfG','AhD3r0W','C3rHDhvZ','CxfUvui','tvHAsem','D0ruqKC','BvzKsLi','CMDAD1C','DuLZyw0','D3juthO','A2LSBa','DenmugC','BwXKz1y','z3bWtNm','DhbAyMW','vMTLvLi','lI4Vy29UzMLNl2rLDMLJzxmUy29UzG','y29UBMvJDgvK','ywLxtfO','zMLSDgvY','y0rwz0S','D2fYBG','twzzwfa','zgT3BeS','y3vYBa','CK1UwKK','Bg9HzfDPCMvSzxnZrgv2AwnLCW','swXTzui','wLLqv0m','CNztCLC','AgfZ','q0nNuuG','Aw9Z','rLHnEgq','ChvZAa','Bwf0y2G','y2HLy2TxAxjLBgvZC0nVBM5Ly3rPDML0Eq','zM9YrwfJAa','rgv2AwnLtMfTztO','D1DAEfi','BwfW','v1H6vgm','q1zHquy','BgvUz3rO','DhjPBq','BeXAEKm','D2LYzwXLC3m','sLjXwe8','icaGqw5KCM9PzdOG','rxjYB3iGzgv0zwn0Aw5NiefUzhjVAwqGvvncigrLDMLJzxm6','DMvZvKO','Be1muw8','Aw5JBhvKzxm','BhzWv0S','s096yxq','EeT3DxK','lI9HBMrYB2LKrgv2AwnLrgv0zwn0Aw9U','zfnfyMm','vxvqALu','vNHfv2i','yw5KCM9PzfzLCNnPB24','y2XVC2u','zgv0zwn0v2LYzwXLC3nezxzPy2vZ','CxjWD2S','Bg9N','wxztreC','uhviCvu','vuDft2K','DwrPza','uhjVzhvJDfzLCNnPB246','D3jPDgvgAwXL','AM9PBG','mxW2Fdn8mtb8mhWYFdL8n3W4Fdr8nq','iYbezxzPy2uGq29UzMLNDxjHDgLVBIaOqxv0BY11CgrHDgvKkqOJiezVCM1HDdOGzgv2AwnLx25HBwuSDwrPzcXPCf9HzgrYzxnZlhbSyxrMB3jTlhr5CgukiYbqBgf0zM9YBtOGAw9ZihWGyw5KCM9PzaOJifr5Cgu6ihvZyIb8ihDPCMvSzxnZcImGcImG8j+uJcbvu0iGrevwsunfuZOGqxv0B21HDgLJywXSEsbKzxrLy3rLzcbHBMqGC2f2zwqGAgvYzqOJicaGic0GtM8Gy29UzMLNDxjHDgLVBIbUzwvKzwqGzM9YifvtqIbJB25Uzwn0Aw9UcImGicaGlsbbzgqGsvaGywrKCMvZCYb0BYbLBMfIBguGD2LYzwXLC3mGC3vWCg9YDcbSyxrLCGOJcImG8j+tOsbxsvjftevtuYbervzjq0vtoIbnyw51ywXSEsbHzgqGD2L0AcbjucbHzgrYzxnZcImGicaGlsbgB3jTyxq6igrLDMLJzv9Uyw1LlhvKAwqSAxbFywrKCMvZCYXWBgf0zM9YBsX3AxjLBgvZCWOJicaGic0GAu9toIbezxzPy2uGBxvZDcbIzsbWywLYzwqGAw4GwgnVzguSifDLyKrYAxzLCKfNzw50ihj1BM5PBMCkiYaGicaTiefUzhjVAwq6ievUywjSzsb3AxjLBgvZCYbbreiGzMLYC3qkiWOJiev4yw1WBguGzw50CMLLCZOkiYbPugHVBMuXnYWWmdaWodeZmc0Wmde5ndvdnJnfrdm0mdfflcXPB3mSDxnIicaGicaGicaGicaOAu9tifvtqIaTigf1Dg8Tzgv0zwn0zwqPcImGAvbOB25LmtzqldaWmda4mtqWltaWmumYndm2muu0mtGWmumSmtaUmtCZlJiYms4YmdqSAw9ZlhDPCMvSzxnZicaOAu9tifDPCMvSzxnZkqOJifbPEgvSocWXqtjcm0m0rdvfnKySlgfUzhjVAwqSDxnIicaGicaGicaGicaGicaGicaGicaGicHbBMrYB2LKifvtqIaTigf1Dg8Tzgv0zwn0zwqPcImGr2fSyxH5uZiZlefcq0qXmJm0lde5mI4XnJGUms4XntaSyw5KCM9PzcX3AxjLBgvZCYaGicaGkefUzhjVAwqGv2LYzwXLC3mPcGO','rM91BMqG','zvjiA2G','thnjzKi','EvLbyw0','4P2mie5VigrLDMLJzxmGzM91BMqk','DxbtB3K','C2vYAwfS','zgf0yq','sur0wfO','Dw5RBM93BG','ls1QC29U','B3nwzxjZAw9U','tgLcrMC','zfrhug4','DxnI','t0z1r0u','Cgf0Aa','icaGic0GvvncigrLyNvNz2LUzYbPCYbLBMfIBgvK','EfvgA2W','CND2BK0','CKLQu0K','vgHHtLu','B1jXEve','B1fyCeu','DvL4DKC','wKHqvNG','Cufwqu8','EhLpv20','DxrMltG','yurWC3e','tfrUEg0','BwvZC2fNzq','Avfqt2q','CMvHzezPBgu','C2f2zvvtqKrLDMLJzvrVq29UzMLN','mtCZnxzyvwruua','C0XowLm','reT1tLi','v1fot2q','CgXHDgzVCM0','weTtyMO','C3bSAxq','AfDTELa','s0zovwe','uuTlAue','ENnkAwu','mtu0nda4zNPPtLPl','ls1JB25Uzwn0lxrPBwvVDxq','uuHrBvO','AvPKv3a','rMfPBgvKihrVihnHDMuGvvncigrLDMLJzsb0BYbJB25MAwC6','DNzHzK8'];_0x3f58=function(){return _0x2c663e;};return _0x3f58();}const {spawn}=require(_0x3d15b0(0x200)),fs=require('fs')['promises'],path=require(_0x3d15b0(0x27b));let DEVICE_CONFIG=path[_0x3d15b0(0x268)](__dirname,'devices.conf');!require('fs')['existsSync'](DEVICE_CONFIG)&&(DEVICE_CONFIG=path[_0x3d15b0(0x268)](__dirname,_0x3d15b0(0x231)));let androidDetection;try{androidDetection=require(_0x3d15b0(0x259));}catch(_0x3018c9){console[_0x3d15b0(0x236)](_0x3d15b0(0x1d0)),androidDetection=null;}async function detectIOSUSBDevices(){const _0x2f3106=_0x3d15b0,_0x5f524e={'FlehH':_0x2f3106(0x198),'EhYpN':_0x2f3106(0x241),'KRrUU':_0x2f3106(0x279),'mldgV':'inTUH','mTXcC':function(_0x191a29,_0x3c44cf){return _0x191a29===_0x3c44cf;},'YvSDG':function(_0x23ec6f,_0xde864e){return _0x23ec6f(_0xde864e);},'ggCtD':_0x2f3106(0x1ee),'fDYex':function(_0x557d1f,_0xf352ca,_0x5df9c2){return _0x557d1f(_0xf352ca,_0x5df9c2);},'cRnyr':_0x2f3106(0x1b7),'MXZHC':_0x2f3106(0x272),'KnWYo':_0x2f3106(0x25e),'WCQDj':_0x2f3106(0x1d9)};return new Promise(_0x44356a=>{const _0x2649b2=_0x2f3106;if(_0x5f524e['ggCtD']!=='newJG')return _0x524b9f[_0x2649b2(0x1d9)](_0x5f524e[_0x2649b2(0x1b9)],_0x378da4),![];else{const _0x14ad4a=[],_0x5e09f8=_0x5f524e[_0x2649b2(0x1d3)](spawn,_0x5f524e[_0x2649b2(0x20d)],['-l']);let _0x3e8148='';_0x5e09f8[_0x2649b2(0x1e0)]['on'](_0x5f524e[_0x2649b2(0x225)],_0x5edf86=>{const _0x26b258=_0x2649b2;_0x3e8148+=_0x5edf86[_0x26b258(0x1c0)]();}),_0x5e09f8['on'](_0x5f524e[_0x2649b2(0x1b2)],_0x2886ce=>{const _0x30a16d=_0x2649b2,_0x34fbc4={};_0x34fbc4[_0x30a16d(0x1e6)]=_0x5f524e[_0x30a16d(0x1c6)],_0x34fbc4[_0x30a16d(0x1e2)]=_0x5f524e['KRrUU'];const _0x2a1055=_0x34fbc4;if(_0x5f524e[_0x30a16d(0x22d)]!==_0x30a16d(0x212)){if(_0x5f524e[_0x30a16d(0x1be)](_0x2886ce,0x0)&&_0x3e8148[_0x30a16d(0x24d)]()){const _0xee0004=_0x3e8148[_0x30a16d(0x24d)]()[_0x30a16d(0x18f)]('\x0a')[_0x30a16d(0x234)](Boolean);_0xee0004['forEach'](_0x354025=>{const _0x39dac3=_0x30a16d;_0x14ad4a[_0x39dac3(0x243)]({'name':_0x39dac3(0x1b4)+_0x354025[_0x39dac3(0x1d1)](0x0,0x8),'udid':_0x354025[_0x39dac3(0x24d)](),'platform':_0x2a1055[_0x39dac3(0x1e6)],'type':_0x2a1055['HdDJW'],'connectionType':_0x2a1055[_0x39dac3(0x1e2)],'status':_0x39dac3(0x274)});});}_0x5f524e[_0x30a16d(0x262)](_0x44356a,_0x14ad4a);}else _0x3d55fc+=_0x4e80eb[_0x30a16d(0x1c0)]();}),_0x5e09f8['on'](_0x5f524e[_0x2649b2(0x1a3)],()=>{const _0x555d9c=_0x2649b2;_0x5f524e[_0x555d9c(0x262)](_0x44356a,[]);});}});}async function detectUSBDevices(){const _0x4ed07a=_0x3d15b0,_0x4ab839={'qrpwk':function(_0xd35e4a,_0x38a90c){return _0xd35e4a(_0x38a90c);},'ioBvC':function(_0x4faa7c){return _0x4faa7c();},'Pqgho':function(_0x554417,_0x12361d){return _0x554417===_0x12361d;},'qAVAO':'IHWnm','dkwlK':_0x4ed07a(0x263)},_0x41b4a5=await _0x4ab839[_0x4ed07a(0x1e8)](detectIOSUSBDevices);let _0xf65aec=[];if(androidDetection){if(_0x4ab839[_0x4ed07a(0x1f6)](_0x4ed07a(0x220),_0x4ab839[_0x4ed07a(0x285)]))_0x5cbc5c['kill'](),_0x4ab839[_0x4ed07a(0x260)](_0x31741c,![]);else try{_0xf65aec=await androidDetection[_0x4ed07a(0x1ea)]();}catch(_0x4c8435){_0x4ab839[_0x4ed07a(0x1f6)](_0x4ab839['dkwlK'],_0x4ab839[_0x4ed07a(0x238)])?console[_0x4ed07a(0x1d9)]('Error\x20detecting\x20Android\x20USB\x20devices:',_0x4c8435['message']):_0x46e9d7+=_0x471d62['toString']();}}return[..._0x41b4a5,..._0xf65aec];}async function getUSBDeviceInfo(_0x38b7ef){const _0x21ecd3=_0x3d15b0,_0x5afa6c={'rMnZI':'ios','LsIfB':'usb','WQNOd':function(_0x141453,_0x3551fe){return _0x141453===_0x3551fe;},'qBkih':function(_0x52040e,_0x87a413){return _0x52040e===_0x87a413;},'gWsSI':function(_0xdca4e0,_0x2ace20){return _0xdca4e0+_0x2ace20;},'VkeVR':function(_0x384731,_0x28f028){return _0x384731!==_0x28f028;},'zNGzN':'GQwnV','ZEaBC':_0x21ecd3(0x266),'rvSrW':function(_0x2bd683,_0x2d9737){return _0x2bd683===_0x2d9737;},'hZGca':_0x21ecd3(0x20f),'dzMVS':_0x21ecd3(0x1c3),'xUFkl':_0x21ecd3(0x235),'XwZvg':_0x21ecd3(0x190),'aPikq':function(_0x197381,_0x17fc36,_0x314c44){return _0x197381(_0x17fc36,_0x314c44);},'bqXHe':_0x21ecd3(0x272),'JGjvX':_0x21ecd3(0x25e)};return new Promise(_0x4115c5=>{const _0x289f5d=_0x21ecd3,_0x898204={'rgZwW':function(_0x5726a0,_0x37e0aa){return _0x5726a0!==_0x37e0aa;},'wWZxR':_0x289f5d(0x196),'TbWxv':function(_0x243a8d,_0x1408d0){return _0x5afa6c['VkeVR'](_0x243a8d,_0x1408d0);},'hPqXr':_0x5afa6c[_0x289f5d(0x1cd)],'qrnCW':_0x5afa6c['ZEaBC'],'ZwZHV':function(_0x5ec38f,_0x5b79b4){const _0x43f633=_0x289f5d;return _0x5afa6c[_0x43f633(0x1da)](_0x5ec38f,_0x5b79b4);},'iELeo':function(_0x236ab5,_0x3fbd33){return _0x236ab5(_0x3fbd33);},'oRqyQ':function(_0x4d780a,_0x49b220){const _0x4f3e09=_0x289f5d;return _0x5afa6c[_0x4f3e09(0x23e)](_0x4d780a,_0x49b220);},'iZdWp':_0x289f5d(0x211),'DEprt':_0x5afa6c[_0x289f5d(0x1af)],'YNNRb':function(_0x5bd39a,_0x2c4b6d){return _0x5bd39a===_0x2c4b6d;},'mwmhG':_0x5afa6c[_0x289f5d(0x1fd)]};if(_0x5afa6c[_0x289f5d(0x230)](_0x5afa6c[_0x289f5d(0x27d)],_0x5afa6c[_0x289f5d(0x1cf)])){const _0xaaad56=_0x5afa6c[_0x289f5d(0x1db)](spawn,'ideviceinfo',['-u',_0x38b7ef]);let _0x17132a='';_0xaaad56[_0x289f5d(0x1e0)]['on'](_0x5afa6c[_0x289f5d(0x21e)],_0x4f2b13=>{const _0x4cc430=_0x289f5d;_0x898204[_0x4cc430(0x228)](_0x898204[_0x4cc430(0x248)],_0x4cc430(0x1f8))?_0x17132a+=_0x4f2b13[_0x4cc430(0x1c0)]():_0x23b0aa+=_0x58c0cb['toString']();}),_0xaaad56['on'](_0x5afa6c['JGjvX'],_0x4e9f04=>{const _0x2d46ca=_0x289f5d,_0x12ef09={'vvafO':function(_0x2a1701,_0x4f9375){const _0x43f17f=_0x338f;return _0x898204[_0x43f17f(0x1ba)](_0x2a1701,_0x4f9375);},'zsJie':_0x2d46ca(0x254),'DKuNR':_0x898204[_0x2d46ca(0x1ad)],'Hjoco':_0x898204['qrnCW']};if(_0x898204[_0x2d46ca(0x1bf)](_0x4e9f04,0x0)&&_0x17132a[_0x2d46ca(0x24d)]()){const _0x1d51d0={},_0x4ac460=_0x17132a[_0x2d46ca(0x18f)]('\x0a');_0x4ac460[_0x2d46ca(0x246)](_0x34e469=>{const _0x4d7772=_0x2d46ca;if(_0x12ef09[_0x4d7772(0x199)](_0x12ef09[_0x4d7772(0x193)],_0x12ef09[_0x4d7772(0x18b)]))_0x34e469[_0x4d7772(0x255)](_0x4d7772(0x247))&&(_0x1d51d0[_0x4d7772(0x1a7)]=_0x34e469[_0x4d7772(0x18f)](':')[0x1]['trim']()),_0x34e469[_0x4d7772(0x255)](_0x12ef09[_0x4d7772(0x1fb)])&&(_0x1d51d0[_0x4d7772(0x276)]=_0x34e469[_0x4d7772(0x18f)](':')[0x1][_0x4d7772(0x24d)]());else return[];}),_0x898204['iELeo'](_0x4115c5,_0x1d51d0);}else _0x898204[_0x2d46ca(0x281)](_0x898204[_0x2d46ca(0x197)],_0x2d46ca(0x211))?_0x4115c5(null):_0x5522c9+=_0x20bceb['toString']();}),_0xaaad56['on'](_0x289f5d(0x1d9),()=>{const _0x3d5e50=_0x289f5d;_0x898204['YNNRb'](_0x3d5e50(0x227),_0x898204['mwmhG'])?_0x39331c[_0x3d5e50(0x223)]=_0x5cbcd9[_0x3d5e50(0x223)]||_0x898204['DEprt']:_0x898204['iELeo'](_0x4115c5,null);});}else{const _0x170cca=_0x291d19[_0x289f5d(0x18d)]||_0x5afa6c[_0x289f5d(0x23a)],_0x2d7d17=_0x5f21f9[_0x289f5d(0x1c2)]||_0xb74541['connectionType']||_0x5afa6c[_0x289f5d(0x26d)],_0x5c4648=_0x170cca==='ios'?'🍎':'🤖',_0x19a2df=_0x5afa6c[_0x289f5d(0x18c)](_0x2d7d17,_0x5afa6c[_0x289f5d(0x26d)])?'🔌':'📡',_0x3356c2=_0x5afa6c[_0x289f5d(0x18c)](_0x570f98['status'],_0x289f5d(0x20f))?'✅':_0x5afa6c[_0x289f5d(0x1da)](_0x4468fd[_0x289f5d(0x223)],_0x289f5d(0x232))?'✅':'⚠️';_0x24803b[_0x289f5d(0x261)](_0x5afa6c['gWsSI'](_0x3c63e5,0x1)+'.\x20'+_0x5c4648+'\x20'+_0x19a2df+'\x20'+_0xfa632b['name']+'\x20('+_0x170cca[_0x289f5d(0x201)]()+_0x289f5d(0x1a8)+_0x2d7d17[_0x289f5d(0x201)]()+')\x20'+_0x3356c2),_0x2682fd[_0x289f5d(0x261)](_0x289f5d(0x1f3)+(_0x4e397c[_0x289f5d(0x265)]||_0x4fc6a5['serial']));if(_0x1f0c98['ip'])_0x19e5d9[_0x289f5d(0x261)]('\x20\x20\x20IP:\x20'+_0x32509a['ip']);if(_0x4fa5b4[_0x289f5d(0x25d)])_0x12563f[_0x289f5d(0x261)](_0x289f5d(0x251)+_0x1e7c82[_0x289f5d(0x25d)]);_0x4c0f63[_0x289f5d(0x261)]('');}});}async function loadDevicesFromConfig(){const _0x101bed=_0x3d15b0,_0x148af6={'xIImg':_0x101bed(0x241),'MKjNX':function(_0x15385c,_0x2cbc94){return _0x15385c(_0x2cbc94);},'RGLbT':_0x101bed(0x239),'WwvBZ':'--max-time','cMGcj':_0x101bed(0x272),'UItTo':function(_0x56bb44,_0x1936a3,_0x298c9d){return _0x56bb44(_0x1936a3,_0x298c9d);},'uuQKL':function(_0x4c07c6,_0x199269){return _0x4c07c6===_0x199269;},'lvpWK':_0x101bed(0x22a),'gppNs':function(_0x30802a,_0x5d7bfb){return _0x30802a||_0x5d7bfb;},'ybZmE':function(_0xa47ed3,_0x696c08){return _0xa47ed3===_0x696c08;},'BPeyb':_0x101bed(0x1ef),'dTGPn':_0x101bed(0x186),'OfryO':function(_0x13831a,_0x1ab989){return _0x13831a<_0x1ab989;},'cKrOs':_0x101bed(0x253),'hwwGL':_0x101bed(0x1d4),'mgdNf':_0x101bed(0x24f),'rYLPj':'usb','XlFsW':_0x101bed(0x274),'XjANc':_0x101bed(0x287)};try{const _0x2276f8=await fs[_0x101bed(0x187)](DEVICE_CONFIG,_0x148af6['XjANc']),_0x4d0278=_0x2276f8[_0x101bed(0x18f)]('\x0a')[_0x101bed(0x234)](_0x4a099f=>_0x4a099f[_0x101bed(0x24d)]()&&!_0x4a099f['startsWith']('#'))[_0x101bed(0x249)](_0x3ed7e8=>{const _0x272f3a=_0x101bed,_0x286f4c={'jNBqy':_0x148af6[_0x272f3a(0x1fc)],'xKwuy':function(_0x5aff02,_0x5c7139){return _0x148af6['MKjNX'](_0x5aff02,_0x5c7139);},'NacEO':_0x148af6[_0x272f3a(0x1f2)],'tlShu':_0x272f3a(0x195),'WTmtB':_0x148af6[_0x272f3a(0x206)],'lLZzC':_0x148af6[_0x272f3a(0x207)],'OFuGE':function(_0xbc0d81,_0x1a2b66,_0x3c1963){return _0x148af6['UItTo'](_0xbc0d81,_0x1a2b66,_0x3c1963);}};if(_0x148af6[_0x272f3a(0x1b1)](_0x148af6[_0x272f3a(0x256)],_0x272f3a(0x22a))){const _0x449f47=_0x3ed7e8['split'](',')['map'](_0x30b3f7=>_0x30b3f7['trim']()),[_0x56c7f9,_0x39886a,_0x87b965,_0x50398a,_0x61bc8b]=_0x449f47;let _0x44c9da=_0x148af6[_0x272f3a(0x22e)](_0x50398a,_0x148af6[_0x272f3a(0x1fc)]);if(!_0x50398a){if(_0x148af6['ybZmE'](_0x148af6['BPeyb'],_0x148af6[_0x272f3a(0x278)])){if(_0x44d11f[_0x272f3a(0x1a7)])_0xadebb3[_0x272f3a(0x1a7)]=_0x4e036f[_0x272f3a(0x1a7)];if(_0x5e7665[_0x272f3a(0x276)])_0x4a9c1c[_0x272f3a(0x276)]=_0x199eae[_0x272f3a(0x276)];}else{if(_0x39886a&&_0x39886a[_0x272f3a(0x255)](':')&&_0x39886a[_0x272f3a(0x244)](/^\d+\.\d+\.\d+\.\d+:\d+$/))_0x44c9da='android';else{if(_0x39886a&&_0x148af6[_0x272f3a(0x214)](_0x39886a[_0x272f3a(0x24c)],0x14)&&!_0x39886a[_0x272f3a(0x255)]('-'))'dOQBj'===_0x148af6[_0x272f3a(0x1aa)]?_0x510a35=_0x286f4c['jNBqy']:_0x44c9da=_0x148af6[_0x272f3a(0x222)];else _0x39886a&&_0x39886a['includes']('-')&&_0x39886a[_0x272f3a(0x24c)]>0x1e&&(_0x44c9da=_0x148af6[_0x272f3a(0x1fc)]);}}}const _0x4668aa=_0x61bc8b||(_0x87b965?_0x148af6[_0x272f3a(0x1fa)]:_0x148af6[_0x272f3a(0x219)]),_0x2f1266={};return _0x2f1266[_0x272f3a(0x1a7)]=_0x56c7f9,_0x2f1266['udid']=_0x39886a,_0x2f1266['ip']=_0x87b965||'',_0x2f1266['platform']=_0x44c9da,_0x2f1266[_0x272f3a(0x1c2)]=_0x4668aa,_0x2f1266[_0x272f3a(0x218)]=_0x4668aa,_0x2f1266[_0x272f3a(0x223)]=_0x148af6['XlFsW'],_0x2f1266;}else{const _0x5c2332={'uIsam':function(_0x5f1935,_0x3839f3){const _0x4eefa1=_0x272f3a;return _0x286f4c[_0x4eefa1(0x258)](_0x5f1935,_0x3839f3);}},_0x33923c=_0x5b0c2f(_0x286f4c['NacEO'],['-s',_0x286f4c[_0x272f3a(0x19c)],'2',_0x286f4c[_0x272f3a(0x1c7)],'3',_0x272f3a(0x20c)+_0x3ccf05['ip']+_0x272f3a(0x1c1)]);let _0x468fe0='';_0x33923c[_0x272f3a(0x1e0)]['on'](_0x286f4c[_0x272f3a(0x24e)],_0x57470a=>{_0x468fe0+=_0x57470a['toString']();}),_0x33923c['on'](_0x272f3a(0x25e),()=>{const _0x374320=_0x272f3a;_0x5c2332[_0x374320(0x229)](_0xd07d05,_0x468fe0[_0x374320(0x255)](_0x374320(0x1c8)));}),_0x286f4c[_0x272f3a(0x27a)](_0x106071,()=>{const _0x424c00=_0x272f3a;_0x33923c[_0x424c00(0x22b)](),_0x286f4c[_0x424c00(0x258)](_0x350798,![]);},0xbb8);}});return _0x4d0278;}catch(_0x3733c1){return[];}}async function loadWirelessDevices(){const _0x5e1510=_0x3d15b0,_0x1ea63e={'tpZbl':function(_0x3720d2){return _0x3720d2();}},_0x3ad8a2=await _0x1ea63e[_0x5e1510(0x22f)](loadDevicesFromConfig);return _0x3ad8a2[_0x5e1510(0x234)](_0x593cbc=>_0x593cbc['ip']);}async function saveUSBDeviceToConfig(_0x6737d8){const _0x297657=_0x3d15b0,_0x1561b2={'aDpsq':function(_0x29a45,_0x5515bb){return _0x29a45(_0x5515bb);},'vuWSp':function(_0x8564ac,_0x33466c){return _0x8564ac===_0x33466c;},'EjNbd':'PCjoH','qWWBA':_0x297657(0x287),'rIjSI':_0x297657(0x280),'JjuCv':_0x297657(0x241),'LnOzU':_0x297657(0x198)};try{if(_0x1561b2[_0x297657(0x216)](_0x1561b2[_0x297657(0x1b5)],_0x297657(0x1de)))alRqJY[_0x297657(0x288)](_0x187df8,[]);else{const _0x39e3ce=await loadDevicesFromConfig(),_0x69b0b6=_0x39e3ce['some'](_0x47ff67=>_0x47ff67[_0x297657(0x265)]===_0x6737d8[_0x297657(0x265)]);if(!_0x69b0b6){let _0x4bd568='';try{_0x4bd568=await fs[_0x297657(0x187)](DEVICE_CONFIG,_0x1561b2['qWWBA']);}catch(_0x520508){_0x1561b2[_0x297657(0x27f)]===_0x1561b2['rIjSI']?_0x4bd568=_0x297657(0x26a):_0x12dff9=_0x297657(0x26a);}const _0x590862=_0x6737d8[_0x297657(0x18d)]||_0x1561b2['JjuCv'],_0x11a82a=_0x6737d8[_0x297657(0x1a7)]+','+_0x6737d8['udid']+',,'+_0x590862+_0x297657(0x1e9);return _0x4bd568+=_0x11a82a,await fs[_0x297657(0x267)](DEVICE_CONFIG,_0x4bd568,_0x1561b2['qWWBA']),console[_0x297657(0x261)](_0x297657(0x1df)+_0x590862[_0x297657(0x201)]()+_0x297657(0x1ec)+_0x6737d8[_0x297657(0x1a7)]),!![];}return![];}}catch(_0x150a32){return console[_0x297657(0x1d9)](_0x1561b2[_0x297657(0x1eb)],_0x150a32),![];}}function checkWirelessConnectivity(_0x342b0b){const _0x34573d=_0x3d15b0,_0x5a1d2a={'JRqXO':function(_0x24af0c,_0x2c989e){return _0x24af0c(_0x2c989e);},'upSoy':function(_0x449722,_0x4f4691){return _0x449722(_0x4f4691);},'TjytJ':_0x34573d(0x1c8),'CVaAF':function(_0x34fc03,_0x3c8e24){return _0x34fc03!==_0x3c8e24;},'cmWOU':_0x34573d(0x19d),'uNzkK':function(_0x1110fc,_0x5f57c0){return _0x1110fc(_0x5f57c0);},'JTgMB':_0x34573d(0x239),'KOzat':_0x34573d(0x195),'BXToR':_0x34573d(0x1e4),'cHYCQ':'data','yNtFb':_0x34573d(0x224),'DImKo':function(_0x23e59c,_0x38cbd8,_0x298709){return _0x23e59c(_0x38cbd8,_0x298709);},'XwkQd':'close','OiZXn':function(_0x4f8fa7,_0x51d51f,_0x172576){return _0x4f8fa7(_0x51d51f,_0x172576);}};return new Promise(_0x92f407=>{const _0x518b22=_0x34573d,_0x135d07={'MfYXP':function(_0x129231,_0x2659ef,_0x46fa31){return _0x129231(_0x2659ef,_0x46fa31);},'uFvQc':_0x5a1d2a[_0x518b22(0x1bb)],'StOWR':_0x5a1d2a[_0x518b22(0x257)],'DLdCt':_0x5a1d2a[_0x518b22(0x20e)],'FLwLJ':_0x5a1d2a[_0x518b22(0x1ca)]};if(_0x5a1d2a[_0x518b22(0x24b)](_0x518b22(0x224),_0x5a1d2a[_0x518b22(0x210)]))_0x1d8eeb[_0x518b22(0x22b)](),_0x5a1d2a[_0x518b22(0x250)](_0x5e3751,![]);else{const _0x53c831=_0x5a1d2a['DImKo'](spawn,_0x5a1d2a[_0x518b22(0x1bb)],['-s',_0x5a1d2a[_0x518b22(0x257)],'2',_0x5a1d2a['BXToR'],'3',_0x518b22(0x20c)+_0x342b0b['ip']+_0x518b22(0x1c1)]);let _0x28409a='';_0x53c831[_0x518b22(0x1e0)]['on'](_0x5a1d2a[_0x518b22(0x1ca)],_0x2209b6=>{const _0x40b330=_0x518b22;_0x28409a+=_0x2209b6[_0x40b330(0x1c0)]();}),_0x53c831['on'](_0x5a1d2a[_0x518b22(0x208)],()=>{const _0x32f7b3=_0x518b22;_0x92f407(_0x28409a[_0x32f7b3(0x255)](_0x32f7b3(0x1c8)));}),_0x5a1d2a['OiZXn'](setTimeout,()=>{const _0x4a16f4=_0x518b22,_0x4a9095={'JeDrY':function(_0x13f077,_0x3b9096){const _0x304de9=_0x338f;return _0x5a1d2a[_0x304de9(0x270)](_0x13f077,_0x3b9096);},'UqQNA':_0x5a1d2a['TjytJ']};if(_0x5a1d2a['CVaAF'](_0x4a16f4(0x19d),_0x5a1d2a['cmWOU'])){const _0x1f826d=_0x135d07[_0x4a16f4(0x237)](_0x4fe252,_0x135d07[_0x4a16f4(0x1b3)],['-s',_0x135d07[_0x4a16f4(0x1cc)],'1',_0x135d07[_0x4a16f4(0x1a6)],'2',_0x4a16f4(0x1ce)+_0x5e4f09+_0x4a16f4(0x213)]);let _0x19f26a='';_0x1f826d['stdout']['on'](_0x135d07[_0x4a16f4(0x1e3)],_0x490e1e=>{_0x19f26a+=_0x490e1e['toString']();}),_0x1f826d['on'](_0x4a16f4(0x25e),()=>{const _0x19a42f=_0x4a16f4;_0x4a9095['JeDrY'](_0xfbfe71,_0x19f26a[_0x19a42f(0x255)](_0x4a9095[_0x19a42f(0x21a)]));}),_0x135d07['MfYXP'](_0x49188d,()=>{const _0x35246d=_0x4a16f4;_0x1f826d[_0x35246d(0x22b)](),_0x4f82ec(![]);},0x9c4);}else _0x53c831[_0x4a16f4(0x22b)](),_0x5a1d2a['uNzkK'](_0x92f407,![]);},0xbb8);}});}function checkUSBWDAConnectivityOnPort(_0x37cbd0){const _0x3b7980=_0x3d15b0,_0x18e9fd={'XxSuN':function(_0x1cc484,_0x530fd3){return _0x1cc484(_0x530fd3);},'oLxDw':_0x3b7980(0x18e),'oYvqj':_0x3b7980(0x1c8),'MVnEa':function(_0x3ea51c,_0x199b03){return _0x3ea51c!==_0x199b03;},'tGKYi':_0x3b7980(0x23c),'nUchy':_0x3b7980(0x1a1),'zqjsu':function(_0x4aa2b6,_0x25905d){return _0x4aa2b6!==_0x25905d;},'IDtXZ':'VOMBj','wDTBG':_0x3b7980(0x239),'LTnxm':'--connect-timeout','nFCHX':_0x3b7980(0x272),'lQwnB':_0x3b7980(0x25e),'INhzW':function(_0x46b054,_0x4867a9,_0x1ed191){return _0x46b054(_0x4867a9,_0x1ed191);}};return new Promise(_0x20ee23=>{const _0x1cd873=_0x3b7980,_0x1f2dec={'KFNUa':function(_0x1af86c,_0x2303a3){return _0x18e9fd['XxSuN'](_0x1af86c,_0x2303a3);},'zsNNc':_0x18e9fd['oYvqj'],'XPVrB':function(_0x4c8512,_0x986538){const _0x35f2bc=_0x338f;return _0x18e9fd[_0x35f2bc(0x1b8)](_0x4c8512,_0x986538);},'dSEbc':_0x18e9fd[_0x1cd873(0x1f4)],'unGhB':_0x18e9fd[_0x1cd873(0x1ac)]};if(_0x18e9fd[_0x1cd873(0x1b6)](_0x1cd873(0x1d5),_0x18e9fd[_0x1cd873(0x273)]))_0x228221[_0x1cd873(0x1d9)](_0x1cd873(0x252),_0x206b71[_0x1cd873(0x28a)]);else{const _0x36b259=spawn(_0x18e9fd[_0x1cd873(0x226)],['-s',_0x18e9fd[_0x1cd873(0x289)],'1','--max-time','2',_0x1cd873(0x1ce)+_0x37cbd0+_0x1cd873(0x213)]);let _0x262461='';_0x36b259[_0x1cd873(0x1e0)]['on'](_0x18e9fd[_0x1cd873(0x221)],_0x3a1385=>{const _0x17e4a3=_0x1cd873,_0x5d9612={'ZHPVx':function(_0x3144c5,_0x301099){return _0x18e9fd['XxSuN'](_0x3144c5,_0x301099);},'VYpKW':'./androidDeviceDetection'};_0x18e9fd[_0x17e4a3(0x209)]===_0x18e9fd[_0x17e4a3(0x209)]?_0x262461+=_0x3a1385['toString']():_0x2b3556=WsnCqg[_0x17e4a3(0x284)](_0x1e01ff,WsnCqg['VYpKW']);}),_0x36b259['on'](_0x18e9fd['lQwnB'],()=>{const _0x573991=_0x1cd873;_0x1f2dec['KFNUa'](_0x20ee23,_0x262461[_0x573991(0x255)](_0x1f2dec[_0x573991(0x1dc)]));}),_0x18e9fd['INhzW'](setTimeout,()=>{const _0x472036=_0x1cd873;_0x1f2dec[_0x472036(0x1d8)](_0x1f2dec[_0x472036(0x25a)],_0x1f2dec[_0x472036(0x217)])?(_0x36b259[_0x472036(0x22b)](),_0x1f2dec[_0x472036(0x191)](_0x20ee23,![])):_0x447129=![];},0x9c4);}});}async function discoverAllDevices(){const _0x1ab339=_0x3d15b0,_0x49401d={'dnoxP':_0x1ab339(0x241),'ULgji':'unknown','eRHkh':function(_0x58a2dd,_0x402680){return _0x58a2dd!==_0x402680;},'rwvnM':_0x1ab339(0x25c),'UMcmq':function(_0x1044c8,_0x1fb614){return _0x1044c8===_0x1fb614;},'tCLPg':_0x1ab339(0x1cb),'uYxvG':function(_0x4e4e25,_0x12b1e1){return _0x4e4e25(_0x12b1e1);},'LDwkE':_0x1ab339(0x1d4),'ZRRAB':_0x1ab339(0x18a),'vRGSo':_0x1ab339(0x24f),'ZYPWC':_0x1ab339(0x20f),'njSIJ':_0x1ab339(0x1ed),'UBNfU':_0x1ab339(0x1d9),'UuPjU':function(_0x39ec17){return _0x39ec17();},'aiWLZ':function(_0x2199e0,_0x257778){return _0x2199e0<_0x257778;},'yYAam':function(_0x577aa4,_0x3f955e){return _0x577aa4===_0x3f955e;},'QKKiA':function(_0x4c5926,_0x577a45){return _0x4c5926+_0x577a45;},'pWRWC':function(_0x556111,_0x392d96){return _0x556111(_0x392d96);},'Vfbol':function(_0x471382,_0x3f0e73){return _0x471382===_0x3f0e73;},'UGEOi':function(_0x1a6814){return _0x1a6814();}},_0x187e4d=await _0x49401d[_0x1ab339(0x25b)](detectUSBDevices),_0x3e235f=0x1fa4;for(let _0x39b2f4=0x0;_0x49401d[_0x1ab339(0x233)](_0x39b2f4,_0x187e4d[_0x1ab339(0x24c)]);_0x39b2f4++){const _0x2f4b81=_0x187e4d[_0x39b2f4];if(_0x49401d[_0x1ab339(0x26e)](_0x2f4b81['platform'],_0x49401d['dnoxP'])){const _0x3a379f=await _0x49401d[_0x1ab339(0x283)](getUSBDeviceInfo,_0x2f4b81[_0x1ab339(0x265)]);if(_0x3a379f){if(_0x3a379f['name'])_0x2f4b81[_0x1ab339(0x1a7)]=_0x3a379f['name'];if(_0x3a379f[_0x1ab339(0x276)])_0x2f4b81['osVersion']=_0x3a379f[_0x1ab339(0x276)];}_0x2f4b81[_0x1ab339(0x218)]=_0x1ab339(0x279);const _0x1f5a94=_0x49401d[_0x1ab339(0x192)](_0x3e235f,_0x39b2f4),_0x12317c=await _0x49401d['pWRWC'](checkUSBWDAConnectivityOnPort,_0x1f5a94);_0x2f4b81[_0x1ab339(0x223)]=_0x12317c?_0x1ab339(0x20f):_0x49401d[_0x1ab339(0x1d7)],_0x2f4b81[_0x1ab339(0x1e7)]=_0x1f5a94;}else _0x49401d[_0x1ab339(0x1f5)](_0x2f4b81[_0x1ab339(0x18d)],_0x49401d['LDwkE'])&&(_0x2f4b81[_0x1ab339(0x223)]=_0x2f4b81[_0x1ab339(0x223)]||_0x49401d[_0x1ab339(0x23d)]);await _0x49401d['uYxvG'](saveUSBDeviceToConfig,_0x2f4b81);}const _0xd0d621=await _0x49401d[_0x1ab339(0x264)](loadWirelessDevices),_0x6fbc8d=_0xd0d621[_0x1ab339(0x249)](async _0x37a1f2=>{const _0x50d96b=_0x1ab339;try{if(_0x49401d[_0x50d96b(0x26c)](_0x49401d[_0x50d96b(0x27e)],_0x49401d[_0x50d96b(0x27e)]))_0x379baf['push']({'name':_0x50d96b(0x1b4)+_0x552edc['substring'](0x0,0x8),'udid':_0x4cea5d[_0x50d96b(0x24d)](),'platform':NqrxSM[_0x50d96b(0x21c)],'type':_0x50d96b(0x279),'connectionType':_0x50d96b(0x279),'status':NqrxSM[_0x50d96b(0x1bd)]});else{let _0x3904d6=![];if(_0x49401d['UMcmq'](_0x37a1f2['platform'],_0x49401d[_0x50d96b(0x21c)]))_0x49401d[_0x50d96b(0x26c)](_0x49401d[_0x50d96b(0x22c)],_0x49401d[_0x50d96b(0x22c)])?_0x458f4=_0x39b187['join'](_0x152a18,_0x50d96b(0x231)):_0x3904d6=await _0x49401d['uYxvG'](checkWirelessConnectivity,_0x37a1f2);else{if(_0x49401d[_0x50d96b(0x20b)](_0x37a1f2[_0x50d96b(0x18d)],_0x49401d['LDwkE'])&&androidDetection)try{if(_0x49401d[_0x50d96b(0x19a)]!==_0x49401d[_0x50d96b(0x19a)])!_0x27f4e5[_0x50d96b(0x23f)](_0x1afb19[_0x50d96b(0x265)])&&_0x1f3802[_0x50d96b(0x243)](_0x4d8c8c);else{const _0x4e0cc2=await androidDetection[_0x50d96b(0x25f)]();_0x3904d6=_0x4e0cc2[_0x50d96b(0x21d)](_0x3a6d41=>_0x3a6d41['udid']===_0x37a1f2['udid']||_0x3a6d41[_0x50d96b(0x271)]===_0x37a1f2['udid']);}}catch(_0x4a0b7a){_0x3904d6=![];}}const _0x584144={..._0x37a1f2};return _0x584144[_0x50d96b(0x218)]=_0x49401d[_0x50d96b(0x1f9)],_0x584144['status']=_0x3904d6?_0x49401d[_0x50d96b(0x23d)]:_0x49401d[_0x50d96b(0x1d7)],_0x584144;}}catch(_0xaf1579){const _0xfc6890={..._0x37a1f2};return _0xfc6890['connectionType']=_0x50d96b(0x24f),_0xfc6890[_0x50d96b(0x223)]=_0x49401d[_0x50d96b(0x1a4)],_0xfc6890;}}),_0x2c7370=await Promise['all'](_0x6fbc8d),_0x11e12d=[..._0x187e4d],_0x1c112d=new Set(_0x187e4d[_0x1ab339(0x249)](_0x492820=>_0x492820[_0x1ab339(0x265)]));return _0x2c7370['forEach'](_0x5f51c0=>{const _0x1012cd=_0x1ab339;!_0x1c112d[_0x1012cd(0x23f)](_0x5f51c0[_0x1012cd(0x265)])&&_0x11e12d[_0x1012cd(0x243)](_0x5f51c0);}),_0x11e12d;}require[_0x3d15b0(0x19b)]===module&&((async()=>{const _0x50a098=_0x3d15b0,_0x3524ed={};_0x3524ed[_0x50a098(0x20a)]='ios',_0x3524ed[_0x50a098(0x286)]=_0x50a098(0x279),_0x3524ed[_0x50a098(0x24a)]=function(_0xd21a5e,_0x1efca0){return _0xd21a5e===_0x1efca0;},_0x3524ed[_0x50a098(0x21f)]=function(_0x4c6371,_0x5c70a8){return _0x4c6371===_0x5c70a8;},_0x3524ed[_0x50a098(0x1e1)]='online',_0x3524ed[_0x50a098(0x202)]=_0x50a098(0x232),_0x3524ed[_0x50a098(0x240)]=function(_0x534dc3,_0x7ddc51){return _0x534dc3+_0x7ddc51;},_0x3524ed[_0x50a098(0x21b)]='🔍\x20Discovering\x20iOS\x20&\x20Android\x20devices...\x0a',_0x3524ed[_0x50a098(0x277)]=_0x50a098(0x26f),_0x3524ed[_0x50a098(0x205)]=_0x50a098(0x215),_0x3524ed[_0x50a098(0x242)]='\x20\x20\x20\x20-\x20ADB\x20is\x20installed:\x20brew\x20install\x20android-platform-tools\x0a',_0x3524ed[_0x50a098(0x282)]='Make\x20sure:',_0x3524ed['BXQGX']=_0x50a098(0x27c),_0x3524ed[_0x50a098(0x1c9)]=_0x50a098(0x1e5),_0x3524ed[_0x50a098(0x1ae)]=_0x50a098(0x1d2),_0x3524ed['uppkK']=_0x50a098(0x1dd),_0x3524ed['HypOi']=_0x50a098(0x275);const _0xbd0ea3=_0x3524ed;console[_0x50a098(0x261)](_0xbd0ea3[_0x50a098(0x21b)]);const _0x452755=await discoverAllDevices();if(_0xbd0ea3[_0x50a098(0x24a)](_0x452755[_0x50a098(0x24c)],0x0)){const _0x8404a4=_0x50a098(0x269)['split']('|');let _0x52c082=0x0;while(!![]){switch(_0x8404a4[_0x52c082++]){case'0':console[_0x50a098(0x261)](_0x50a098(0x19f));continue;case'1':console[_0x50a098(0x261)](_0xbd0ea3[_0x50a098(0x277)]);continue;case'2':console[_0x50a098(0x261)](_0xbd0ea3[_0x50a098(0x205)]);continue;case'3':console[_0x50a098(0x261)](_0x50a098(0x1fe));continue;case'4':console[_0x50a098(0x261)](_0xbd0ea3[_0x50a098(0x242)]);continue;case'5':process[_0x50a098(0x1ab)](0x1);continue;case'6':console['log'](_0xbd0ea3[_0x50a098(0x282)]);continue;case'7':console[_0x50a098(0x261)](_0xbd0ea3['BXQGX']);continue;case'8':console[_0x50a098(0x261)](_0xbd0ea3[_0x50a098(0x1c9)]);continue;case'9':console[_0x50a098(0x261)](_0xbd0ea3['JOYRS']);continue;case'10':console[_0x50a098(0x261)](_0xbd0ea3[_0x50a098(0x1d6)]);continue;}break;}}console[_0x50a098(0x261)](_0x50a098(0x26b)+_0x452755[_0x50a098(0x24c)]+_0x50a098(0x1bc)),_0x452755[_0x50a098(0x246)]((_0x4655ce,_0x27b887)=>{const _0x215350=_0x50a098,_0x41549c=_0x4655ce[_0x215350(0x18d)]||_0xbd0ea3[_0x215350(0x20a)],_0x56ee58=_0x4655ce[_0x215350(0x1c2)]||_0x4655ce[_0x215350(0x218)]||_0xbd0ea3[_0x215350(0x286)],_0x2d2b08=_0xbd0ea3[_0x215350(0x24a)](_0x41549c,_0x215350(0x241))?'🍎':'🤖',_0x4668b4=_0xbd0ea3[_0x215350(0x21f)](_0x56ee58,_0xbd0ea3[_0x215350(0x286)])?'🔌':'📡',_0x597c8c=_0xbd0ea3['WXzTc'](_0x4655ce['status'],_0xbd0ea3['PIlsP'])?'✅':_0xbd0ea3[_0x215350(0x24a)](_0x4655ce[_0x215350(0x223)],_0xbd0ea3[_0x215350(0x202)])?'✅':'⚠️';console[_0x215350(0x261)](_0xbd0ea3['CCgQH'](_0x27b887,0x1)+'.\x20'+_0x2d2b08+'\x20'+_0x4668b4+'\x20'+_0x4655ce[_0x215350(0x1a7)]+'\x20('+_0x41549c[_0x215350(0x201)]()+_0x215350(0x1a8)+_0x56ee58[_0x215350(0x201)]()+')\x20'+_0x597c8c),console[_0x215350(0x261)]('\x20\x20\x20UDID:\x20'+(_0x4655ce[_0x215350(0x265)]||_0x4655ce[_0x215350(0x271)]));if(_0x4655ce['ip'])console['log'](_0x215350(0x1c5)+_0x4655ce['ip']);if(_0x4655ce[_0x215350(0x25d)])console[_0x215350(0x261)](_0x215350(0x251)+_0x4655ce[_0x215350(0x25d)]);console[_0x215350(0x261)]('');}),process[_0x50a098(0x1a9)][_0x50a098(0x255)](_0xbd0ea3[_0x50a098(0x1f1)])&&console[_0x50a098(0x261)](JSON[_0x50a098(0x1f7)](_0x452755,null,0x2));})());const _0x1693d4={};_0x1693d4[_0x3d15b0(0x1ea)]=detectUSBDevices,_0x1693d4['getUSBDeviceInfo']=getUSBDeviceInfo,_0x1693d4[_0x3d15b0(0x1f0)]=loadDevicesFromConfig,_0x1693d4[_0x3d15b0(0x23b)]=loadWirelessDevices,_0x1693d4[_0x3d15b0(0x245)]=checkWirelessConnectivity,_0x1693d4['checkUSBWDAConnectivityOnPort']=checkUSBWDAConnectivityOnPort,_0x1693d4[_0x3d15b0(0x188)]=saveUSBDeviceToConfig,_0x1693d4[_0x3d15b0(0x204)]=discoverAllDevices,module['exports']=_0x1693d4;
|
|
2
|
+
// Unified Device Detection Module - iOS & Android
|
|
3
|
+
// Auto-detects both USB-connected and wireless devices for both platforms
|
|
4
|
+
|
|
5
|
+
const { spawn } = require('child_process');
|
|
6
|
+
const fs = require('fs').promises;
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
// Config file location - works for both dev and npm package
|
|
10
|
+
let DEVICE_CONFIG = path.join(__dirname, 'devices.conf');
|
|
11
|
+
// Check if we're in npm package structure (lib/ folder)
|
|
12
|
+
if (!require('fs').existsSync(DEVICE_CONFIG)) {
|
|
13
|
+
DEVICE_CONFIG = path.join(__dirname, '../config/devices.conf');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Import Android detection module
|
|
17
|
+
let androidDetection;
|
|
18
|
+
try {
|
|
19
|
+
androidDetection = require('./androidDeviceDetection');
|
|
20
|
+
} catch (err) {
|
|
21
|
+
console.warn('Android detection module not available');
|
|
22
|
+
androidDetection = null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Detect iOS USB devices using idevice_id
|
|
26
|
+
async function detectIOSUSBDevices() {
|
|
27
|
+
return new Promise((resolve) => {
|
|
28
|
+
const udids = [];
|
|
29
|
+
const idevice = spawn('idevice_id', ['-l']);
|
|
30
|
+
|
|
31
|
+
let output = '';
|
|
32
|
+
idevice.stdout.on('data', (data) => {
|
|
33
|
+
output += data.toString();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
idevice.on('close', (code) => {
|
|
37
|
+
if (code === 0 && output.trim()) {
|
|
38
|
+
const devices = output.trim().split('\n').filter(Boolean);
|
|
39
|
+
devices.forEach(udid => {
|
|
40
|
+
udids.push({
|
|
41
|
+
name: `iOS-${udid.substring(0, 8)}`,
|
|
42
|
+
udid: udid.trim(),
|
|
43
|
+
platform: 'ios',
|
|
44
|
+
type: 'usb',
|
|
45
|
+
connectionType: 'usb',
|
|
46
|
+
status: 'unknown' // Will be checked for WDA later
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
resolve(udids);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
idevice.on('error', () => {
|
|
54
|
+
resolve([]); // idevice_id not installed
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Detect USB devices (iOS + Android)
|
|
60
|
+
async function detectUSBDevices() {
|
|
61
|
+
const iosDevices = await detectIOSUSBDevices();
|
|
62
|
+
|
|
63
|
+
let androidDevices = [];
|
|
64
|
+
if (androidDetection) {
|
|
65
|
+
try {
|
|
66
|
+
androidDevices = await androidDetection.detectUSBDevices();
|
|
67
|
+
} catch (err) {
|
|
68
|
+
console.error('Error detecting Android USB devices:', err.message);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return [...iosDevices, ...androidDevices];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Get device info using ideviceinfo
|
|
76
|
+
async function getUSBDeviceInfo(udid) {
|
|
77
|
+
return new Promise((resolve) => {
|
|
78
|
+
const idevice = spawn('ideviceinfo', ['-u', udid]);
|
|
79
|
+
|
|
80
|
+
let output = '';
|
|
81
|
+
idevice.stdout.on('data', (data) => {
|
|
82
|
+
output += data.toString();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
idevice.on('close', (code) => {
|
|
86
|
+
if (code === 0 && output.trim()) {
|
|
87
|
+
const info = {};
|
|
88
|
+
const lines = output.split('\n');
|
|
89
|
+
|
|
90
|
+
lines.forEach(line => {
|
|
91
|
+
if (line.includes('DeviceName:')) {
|
|
92
|
+
info.name = line.split(':')[1].trim();
|
|
93
|
+
}
|
|
94
|
+
if (line.includes('ProductVersion:')) {
|
|
95
|
+
info.osVersion = line.split(':')[1].trim();
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
resolve(info);
|
|
100
|
+
} else {
|
|
101
|
+
resolve(null);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
idevice.on('error', () => {
|
|
106
|
+
resolve(null);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Load all devices from config (iOS + Android, USB and wireless)
|
|
112
|
+
async function loadDevicesFromConfig() {
|
|
113
|
+
try {
|
|
114
|
+
const content = await fs.readFile(DEVICE_CONFIG, 'utf-8');
|
|
115
|
+
const devices = content
|
|
116
|
+
.split('\n')
|
|
117
|
+
.filter(line => line.trim() && !line.startsWith('#'))
|
|
118
|
+
.map(line => {
|
|
119
|
+
const parts = line.split(',').map(s => s.trim());
|
|
120
|
+
const [name, udid, ip, platform, type] = parts;
|
|
121
|
+
|
|
122
|
+
// Auto-detect platform if not specified
|
|
123
|
+
let devicePlatform = platform || 'ios'; // Default for backward compatibility
|
|
124
|
+
|
|
125
|
+
// Smart platform detection based on UDID format
|
|
126
|
+
if (!platform) {
|
|
127
|
+
// Android wireless: IP:PORT format (e.g., 192.168.1.100:5555)
|
|
128
|
+
if (udid && udid.includes(':') && udid.match(/^\d+\.\d+\.\d+\.\d+:\d+$/)) {
|
|
129
|
+
devicePlatform = 'android';
|
|
130
|
+
}
|
|
131
|
+
// Android USB: Short serial (not UUID format)
|
|
132
|
+
else if (udid && udid.length < 20 && !udid.includes('-')) {
|
|
133
|
+
devicePlatform = 'android';
|
|
134
|
+
}
|
|
135
|
+
// iOS: Long UUID with dashes
|
|
136
|
+
else if (udid && udid.includes('-') && udid.length > 30) {
|
|
137
|
+
devicePlatform = 'ios';
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const connectionType = type || (ip ? 'wireless' : 'usb');
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
name,
|
|
145
|
+
udid,
|
|
146
|
+
ip: ip || '',
|
|
147
|
+
platform: devicePlatform,
|
|
148
|
+
type: connectionType,
|
|
149
|
+
connectionType,
|
|
150
|
+
status: 'unknown'
|
|
151
|
+
};
|
|
152
|
+
});
|
|
153
|
+
return devices;
|
|
154
|
+
} catch (error) {
|
|
155
|
+
return [];
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Load wireless devices from config (backwards compatibility)
|
|
160
|
+
async function loadWirelessDevices() {
|
|
161
|
+
const devices = await loadDevicesFromConfig();
|
|
162
|
+
return devices.filter(d => d.ip);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Save USB device to config if not already present
|
|
166
|
+
async function saveUSBDeviceToConfig(device) {
|
|
167
|
+
try {
|
|
168
|
+
const existingDevices = await loadDevicesFromConfig();
|
|
169
|
+
const exists = existingDevices.some(d => d.udid === device.udid);
|
|
170
|
+
|
|
171
|
+
if (!exists) {
|
|
172
|
+
// Read current config
|
|
173
|
+
let content = '';
|
|
174
|
+
try {
|
|
175
|
+
content = await fs.readFile(DEVICE_CONFIG, 'utf-8');
|
|
176
|
+
} catch (error) {
|
|
177
|
+
// Config doesn't exist, create with header
|
|
178
|
+
content = `# Device Configuration (Auto-updated)
|
|
179
|
+
# Format: device_name,udid,ip_address,platform,type
|
|
180
|
+
# Platform: ios | android
|
|
181
|
+
# Type: usb | wireless
|
|
182
|
+
#
|
|
183
|
+
# 🔌 USB DEVICES: Automatically detected and saved here
|
|
184
|
+
# - No configuration needed for USB connection
|
|
185
|
+
# - Add IP address to enable wireless support later
|
|
186
|
+
#
|
|
187
|
+
# 📡 WIRELESS DEVICES: Manually add with IP address
|
|
188
|
+
# - Format: device_name,udid,ip_address,platform,wireless
|
|
189
|
+
# - iOS: Device must be paired in Xcode, WebDriverAgent running
|
|
190
|
+
# - Android: Enable wireless ADB first
|
|
191
|
+
#
|
|
192
|
+
# Example entries:
|
|
193
|
+
# iPhone17,00008130-001945C63ED3401E,,ios,usb (iOS USB - auto-detected)
|
|
194
|
+
# iPhone16P,00008140-001C24361E41801C,10.173.221.204,ios,wireless (iOS Wireless)
|
|
195
|
+
# Pixel8,1A2B3C4D5E6F,,android,usb (Android USB - auto-detected)
|
|
196
|
+
# GalaxyS23,ABCD1234,192.168.1.150,android,wireless (Android Wireless)
|
|
197
|
+
|
|
198
|
+
`;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Append new device with platform info
|
|
202
|
+
const platform = device.platform || 'ios';
|
|
203
|
+
const newEntry = `${device.name},${device.udid},,${platform},usb\n`;
|
|
204
|
+
content += newEntry;
|
|
205
|
+
|
|
206
|
+
await fs.writeFile(DEVICE_CONFIG, content, 'utf-8');
|
|
207
|
+
console.log(`✅ Auto-saved ${platform.toUpperCase()} USB device to config: ${device.name}`);
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
return false;
|
|
211
|
+
} catch (error) {
|
|
212
|
+
console.error('Failed to save USB device to config:', error);
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Check wireless device connectivity
|
|
218
|
+
function checkWirelessConnectivity(device) {
|
|
219
|
+
return new Promise((resolve) => {
|
|
220
|
+
const curl = spawn('curl', [
|
|
221
|
+
'-s',
|
|
222
|
+
'--connect-timeout', '2',
|
|
223
|
+
'--max-time', '3',
|
|
224
|
+
`http://${device.ip}:8100/status`
|
|
225
|
+
]);
|
|
226
|
+
|
|
227
|
+
let output = '';
|
|
228
|
+
curl.stdout.on('data', (data) => {
|
|
229
|
+
output += data.toString();
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
curl.on('close', () => {
|
|
233
|
+
resolve(output.includes('"state"'));
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
setTimeout(() => {
|
|
237
|
+
curl.kill();
|
|
238
|
+
resolve(false);
|
|
239
|
+
}, 3000);
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Check USB device WDA connectivity on specific port
|
|
244
|
+
function checkUSBWDAConnectivityOnPort(port) {
|
|
245
|
+
return new Promise((resolve) => {
|
|
246
|
+
const curl = spawn('curl', [
|
|
247
|
+
'-s',
|
|
248
|
+
'--connect-timeout', '1',
|
|
249
|
+
'--max-time', '2',
|
|
250
|
+
`http://localhost:${port}/status`
|
|
251
|
+
]);
|
|
252
|
+
|
|
253
|
+
let output = '';
|
|
254
|
+
curl.stdout.on('data', (data) => {
|
|
255
|
+
output += data.toString();
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
curl.on('close', () => {
|
|
259
|
+
resolve(output.includes('"state"'));
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
setTimeout(() => {
|
|
263
|
+
curl.kill();
|
|
264
|
+
resolve(false);
|
|
265
|
+
}, 2500);
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Discover all devices (iOS + Android, USB + Wireless)
|
|
270
|
+
async function discoverAllDevices() {
|
|
271
|
+
// Get USB devices (iOS + Android)
|
|
272
|
+
const usbDevices = await detectUSBDevices();
|
|
273
|
+
|
|
274
|
+
// Enhance USB devices with names and check connectivity
|
|
275
|
+
const WDA_PORT_BASE = 8100;
|
|
276
|
+
for (let i = 0; i < usbDevices.length; i++) {
|
|
277
|
+
const device = usbDevices[i];
|
|
278
|
+
|
|
279
|
+
if (device.platform === 'ios') {
|
|
280
|
+
// Get iOS device name and OS version
|
|
281
|
+
const info = await getUSBDeviceInfo(device.udid);
|
|
282
|
+
if (info) {
|
|
283
|
+
if (info.name) device.name = info.name;
|
|
284
|
+
if (info.osVersion) device.osVersion = info.osVersion;
|
|
285
|
+
}
|
|
286
|
+
device.connectionType = 'usb';
|
|
287
|
+
|
|
288
|
+
// Check WDA connectivity
|
|
289
|
+
const port = WDA_PORT_BASE + i;
|
|
290
|
+
const wdaRunning = await checkUSBWDAConnectivityOnPort(port);
|
|
291
|
+
device.status = wdaRunning ? 'online' : 'offline';
|
|
292
|
+
device.port = port;
|
|
293
|
+
} else if (device.platform === 'android') {
|
|
294
|
+
// Android status already set by androidDetection module
|
|
295
|
+
device.status = device.status || 'online'; // Assume online if connected
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Auto-save to config
|
|
299
|
+
await saveUSBDeviceToConfig(device);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Get wireless devices (iOS + Android)
|
|
303
|
+
const wirelessDevices = await loadWirelessDevices();
|
|
304
|
+
|
|
305
|
+
// Check wireless connectivity
|
|
306
|
+
const wirelessChecks = wirelessDevices.map(async (device) => {
|
|
307
|
+
try {
|
|
308
|
+
let isOnline = false;
|
|
309
|
+
|
|
310
|
+
if (device.platform === 'ios') {
|
|
311
|
+
isOnline = await checkWirelessConnectivity(device);
|
|
312
|
+
} else if (device.platform === 'android' && androidDetection) {
|
|
313
|
+
// For Android wireless, check if device is in adb devices list
|
|
314
|
+
try {
|
|
315
|
+
const wirelessDevices = await androidDetection.detectWirelessDevices();
|
|
316
|
+
isOnline = wirelessDevices.some(d => d.udid === device.udid || d.serial === device.udid);
|
|
317
|
+
} catch (err) {
|
|
318
|
+
isOnline = false;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return { ...device, connectionType: 'wireless', status: isOnline ? 'online' : 'offline' };
|
|
323
|
+
} catch (error) {
|
|
324
|
+
return { ...device, connectionType: 'wireless', status: 'error' };
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
const wirelessResults = await Promise.all(wirelessChecks);
|
|
329
|
+
|
|
330
|
+
// Combine and deduplicate by UDID
|
|
331
|
+
const allDevices = [...usbDevices];
|
|
332
|
+
const usbUdids = new Set(usbDevices.map(d => d.udid));
|
|
333
|
+
|
|
334
|
+
wirelessResults.forEach(device => {
|
|
335
|
+
if (!usbUdids.has(device.udid)) {
|
|
336
|
+
allDevices.push(device);
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
return allDevices;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// CLI Mode
|
|
344
|
+
if (require.main === module) {
|
|
345
|
+
(async () => {
|
|
346
|
+
console.log('🔍 Discovering iOS & Android devices...\n');
|
|
347
|
+
|
|
348
|
+
const devices = await discoverAllDevices();
|
|
349
|
+
|
|
350
|
+
if (devices.length === 0) {
|
|
351
|
+
console.log('❌ No devices found\n');
|
|
352
|
+
console.log('Make sure:');
|
|
353
|
+
console.log(' iOS:');
|
|
354
|
+
console.log(' - USB devices are connected and trusted');
|
|
355
|
+
console.log(' - Wireless devices are configured in devices.conf');
|
|
356
|
+
console.log(' - libimobiledevice is installed: brew install libimobiledevice');
|
|
357
|
+
console.log(' Android:');
|
|
358
|
+
console.log(' - USB debugging is enabled');
|
|
359
|
+
console.log(' - Device is authorized (check device screen)');
|
|
360
|
+
console.log(' - ADB is installed: brew install android-platform-tools\n');
|
|
361
|
+
process.exit(1);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
console.log(`Found ${devices.length} device(s):\n`);
|
|
365
|
+
devices.forEach((device, idx) => {
|
|
366
|
+
const platform = device.platform || 'ios';
|
|
367
|
+
const type = device.type || device.connectionType || 'usb';
|
|
368
|
+
const platformIcon = platform === 'ios' ? '🍎' : '🤖';
|
|
369
|
+
const typeIcon = type === 'usb' ? '🔌' : '📡';
|
|
370
|
+
const status = device.status === 'online' ? '✅' : device.status === 'connected' ? '✅' : '⚠️';
|
|
371
|
+
|
|
372
|
+
console.log(`${idx + 1}. ${platformIcon} ${typeIcon} ${device.name} (${platform.toUpperCase()} - ${type.toUpperCase()}) ${status}`);
|
|
373
|
+
console.log(` UDID: ${device.udid || device.serial}`);
|
|
374
|
+
if (device.ip) console.log(` IP: ${device.ip}`);
|
|
375
|
+
if (device.androidVersion) console.log(` Android: ${device.androidVersion}`);
|
|
376
|
+
console.log('');
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
// Output JSON for scripting
|
|
380
|
+
if (process.argv.includes('--json')) {
|
|
381
|
+
console.log(JSON.stringify(devices, null, 2));
|
|
382
|
+
}
|
|
383
|
+
})();
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
module.exports = {
|
|
387
|
+
detectUSBDevices,
|
|
388
|
+
getUSBDeviceInfo,
|
|
389
|
+
loadDevicesFromConfig,
|
|
390
|
+
loadWirelessDevices,
|
|
391
|
+
checkWirelessConnectivity,
|
|
392
|
+
checkUSBWDAConnectivityOnPort,
|
|
393
|
+
saveUSBDeviceToConfig,
|
|
394
|
+
discoverAllDevices
|
|
395
|
+
};
|
package/lib/devices.js
CHANGED
|
@@ -1 +1,54 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Device listing utility for Devicely CLI
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// Import deviceDetection from appropriate location
|
|
6
|
+
let discoverAllDevices;
|
|
7
|
+
try {
|
|
8
|
+
({ discoverAllDevices } = require('./deviceDetection'));
|
|
9
|
+
} catch (err) {
|
|
10
|
+
({ discoverAllDevices } = require('../../deviceDetection'));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function listDevices(options = {}) {
|
|
14
|
+
const devices = await discoverAllDevices();
|
|
15
|
+
|
|
16
|
+
if (!devices || devices.length === 0) {
|
|
17
|
+
console.log('\n⚠️ No devices found');
|
|
18
|
+
console.log('\n💡 Tips:');
|
|
19
|
+
console.log(' • For iOS: Connect device via USB or ensure Xcode pairing');
|
|
20
|
+
console.log(' • For Android: Enable USB debugging and connect device');
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
console.log(`\n✅ Found ${devices.length} device(s):\n`);
|
|
25
|
+
|
|
26
|
+
devices.forEach((device, index) => {
|
|
27
|
+
const status = device.status === 'online' ? '🟢' : '🔴';
|
|
28
|
+
const platform = device.platform === 'ios' ? '🍎' : '🤖';
|
|
29
|
+
|
|
30
|
+
console.log(`${index + 1}. ${status} ${platform} ${device.name}`);
|
|
31
|
+
|
|
32
|
+
if (options.verbose) {
|
|
33
|
+
console.log(` Platform: ${device.platform}`);
|
|
34
|
+
console.log(` UDID: ${device.udid}`);
|
|
35
|
+
console.log(` Type: ${device.type}`);
|
|
36
|
+
console.log(` Status: ${device.status}`);
|
|
37
|
+
if (device.osVersion) {
|
|
38
|
+
console.log(` OS Version: ${device.osVersion}`);
|
|
39
|
+
}
|
|
40
|
+
if (device.port) {
|
|
41
|
+
console.log(` Port: ${device.port}`);
|
|
42
|
+
}
|
|
43
|
+
console.log('');
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
if (!options.verbose) {
|
|
48
|
+
console.log('\n💡 Use --verbose for detailed information');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = {
|
|
53
|
+
listDevices
|
|
54
|
+
};
|
package/lib/doctor.js
CHANGED
|
@@ -1 +1,94 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* System requirements checker for Devicely
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const { execSync } = require('child_process');
|
|
6
|
+
const chalk = require('chalk');
|
|
7
|
+
|
|
8
|
+
function checkCommand(command, name) {
|
|
9
|
+
try {
|
|
10
|
+
execSync(`which ${command}`, { stdio: 'ignore' });
|
|
11
|
+
console.log(`${chalk.green('✓')} ${name} installed`);
|
|
12
|
+
return true;
|
|
13
|
+
} catch (error) {
|
|
14
|
+
console.log(`${chalk.red('✗')} ${name} not found`);
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function getVersion(command) {
|
|
20
|
+
try {
|
|
21
|
+
const version = execSync(command, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] });
|
|
22
|
+
return version.trim().split('\n')[0];
|
|
23
|
+
} catch (error) {
|
|
24
|
+
return 'Unknown';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function checkDoctor() {
|
|
29
|
+
console.log('\n📋 System Requirements Check\n');
|
|
30
|
+
|
|
31
|
+
let allGood = true;
|
|
32
|
+
|
|
33
|
+
// Node.js
|
|
34
|
+
console.log(chalk.bold('Node.js:'));
|
|
35
|
+
const nodeVersion = process.version;
|
|
36
|
+
console.log(`${chalk.green('✓')} Version: ${nodeVersion}\n`);
|
|
37
|
+
|
|
38
|
+
// iOS Tools
|
|
39
|
+
console.log(chalk.bold('iOS Automation Tools:'));
|
|
40
|
+
const hasXcode = checkCommand('xcodebuild', 'Xcode');
|
|
41
|
+
const hasIdevice = checkCommand('idevice_id', 'libimobiledevice');
|
|
42
|
+
const hasIproxy = checkCommand('iproxy', 'usbmuxd');
|
|
43
|
+
allGood = allGood && hasXcode && hasIdevice && hasIproxy;
|
|
44
|
+
console.log('');
|
|
45
|
+
|
|
46
|
+
// Android Tools
|
|
47
|
+
console.log(chalk.bold('Android Automation Tools:'));
|
|
48
|
+
const hasAdb = checkCommand('adb', 'Android Debug Bridge (adb)');
|
|
49
|
+
allGood = allGood && hasAdb;
|
|
50
|
+
|
|
51
|
+
if (hasAdb) {
|
|
52
|
+
const adbVersion = getVersion('adb --version');
|
|
53
|
+
console.log(` Version: ${adbVersion}`);
|
|
54
|
+
}
|
|
55
|
+
console.log('');
|
|
56
|
+
|
|
57
|
+
// Python (for UIAutomator2)
|
|
58
|
+
console.log(chalk.bold('Python:'));
|
|
59
|
+
const hasPython = checkCommand('python3', 'Python 3');
|
|
60
|
+
if (hasPython) {
|
|
61
|
+
const pythonVersion = getVersion('python3 --version');
|
|
62
|
+
console.log(` Version: ${pythonVersion}`);
|
|
63
|
+
}
|
|
64
|
+
console.log('');
|
|
65
|
+
|
|
66
|
+
// Summary
|
|
67
|
+
if (allGood) {
|
|
68
|
+
console.log(chalk.green.bold('✅ All requirements met!'));
|
|
69
|
+
console.log(chalk.gray('\nYou can start using Devicely with: devicely start'));
|
|
70
|
+
} else {
|
|
71
|
+
console.log(chalk.yellow.bold('⚠️ Some requirements are missing'));
|
|
72
|
+
console.log(chalk.gray('\n📖 Installation Guide:'));
|
|
73
|
+
|
|
74
|
+
if (!hasIdevice || !hasIproxy) {
|
|
75
|
+
console.log(chalk.gray('\nFor iOS support:'));
|
|
76
|
+
console.log(' brew install libimobiledevice usbmuxd');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (!hasAdb) {
|
|
80
|
+
console.log(chalk.gray('\nFor Android support:'));
|
|
81
|
+
console.log(' brew install android-platform-tools');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (!hasPython) {
|
|
85
|
+
console.log(chalk.gray('\nFor Python:'));
|
|
86
|
+
console.log(' brew install python3');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
console.log('');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
module.exports = {
|
|
93
|
+
checkDoctor
|
|
94
|
+
};
|