magnax 1.0.0__py3-none-any.whl

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.
Files changed (87) hide show
  1. magnax/__init__.py +3 -0
  2. magnax/__main__.py +25 -0
  3. magnax/debug.py +65 -0
  4. magnax/public/__init__.py +1 -0
  5. magnax/public/adb/linux/adb +0 -0
  6. magnax/public/adb/linux_arm/adb +0 -0
  7. magnax/public/adb/mac/adb +0 -0
  8. magnax/public/adb/windows/AdbWinApi.dll +0 -0
  9. magnax/public/adb/windows/AdbWinUsbApi.dll +0 -0
  10. magnax/public/adb/windows/adb.exe +0 -0
  11. magnax/public/adb.py +96 -0
  12. magnax/public/android_fps.py +750 -0
  13. magnax/public/apm.py +1306 -0
  14. magnax/public/apm_pk.py +184 -0
  15. magnax/public/common.py +1598 -0
  16. magnax/public/config.json +1 -0
  17. magnax/public/ios_perf_adapter.py +790 -0
  18. magnax/public/report_template/android.html +526 -0
  19. magnax/public/report_template/ios.html +482 -0
  20. magnax/public/scrcpy/scrcpy-win32-v2.4/AdbWinApi.dll +0 -0
  21. magnax/public/scrcpy/scrcpy-win32-v2.4/AdbWinUsbApi.dll +0 -0
  22. magnax/public/scrcpy/scrcpy-win32-v2.4/SDL2.dll +0 -0
  23. magnax/public/scrcpy/scrcpy-win32-v2.4/adb.exe +0 -0
  24. magnax/public/scrcpy/scrcpy-win32-v2.4/avcodec-60.dll +0 -0
  25. magnax/public/scrcpy/scrcpy-win32-v2.4/avformat-60.dll +0 -0
  26. magnax/public/scrcpy/scrcpy-win32-v2.4/avutil-58.dll +0 -0
  27. magnax/public/scrcpy/scrcpy-win32-v2.4/icon.png +0 -0
  28. magnax/public/scrcpy/scrcpy-win32-v2.4/libusb-1.0.dll +0 -0
  29. magnax/public/scrcpy/scrcpy-win32-v2.4/open_a_terminal_here.bat +1 -0
  30. magnax/public/scrcpy/scrcpy-win32-v2.4/scrcpy-console.bat +2 -0
  31. magnax/public/scrcpy/scrcpy-win32-v2.4/scrcpy-noconsole.vbs +7 -0
  32. magnax/public/scrcpy/scrcpy-win32-v2.4/scrcpy-server +0 -0
  33. magnax/public/scrcpy/scrcpy-win32-v2.4/scrcpy.exe +0 -0
  34. magnax/public/scrcpy/scrcpy-win32-v2.4/swresample-4.dll +0 -0
  35. magnax/public/scrcpy/scrcpy-win64-v2.4/AdbWinApi.dll +0 -0
  36. magnax/public/scrcpy/scrcpy-win64-v2.4/AdbWinUsbApi.dll +0 -0
  37. magnax/public/scrcpy/scrcpy-win64-v2.4/SDL2.dll +0 -0
  38. magnax/public/scrcpy/scrcpy-win64-v2.4/avformat-60.dll +0 -0
  39. magnax/public/scrcpy/scrcpy-win64-v2.4/avutil-58.dll +0 -0
  40. magnax/public/scrcpy/scrcpy-win64-v2.4/open_a_terminal_here.bat +1 -0
  41. magnax/public/scrcpy/scrcpy-win64-v2.4/scrcpy-noconsole.vbs +7 -0
  42. magnax/public/scrcpy/scrcpy-win64-v2.4/scrcpy-server +0 -0
  43. magnax/public/scrcpy/scrcpy-win64-v2.4/scrcpy.exe +0 -0
  44. magnax/public/scrcpy/scrcpy-win64-v2.4/swresample-4.dll +0 -0
  45. magnax/static/css/highlight.min.css +9 -0
  46. magnax/static/css/magnax-dark-theme.css +1237 -0
  47. magnax/static/css/select2-bootstrap-5-theme.min.css +3 -0
  48. magnax/static/css/select2-bootstrap-5-theme.rtl.min.css +3 -0
  49. magnax/static/css/select2.min.css +1 -0
  50. magnax/static/css/sweetalert2.min.css +1 -0
  51. magnax/static/css/tabler.demo.min.css +9 -0
  52. magnax/static/css/tabler.min.css +14 -0
  53. magnax/static/image/500.png +0 -0
  54. magnax/static/image/avatar.png +0 -0
  55. magnax/static/image/empty.png +0 -0
  56. magnax/static/image/readme/home.png +0 -0
  57. magnax/static/image/readme/pk.png +0 -0
  58. magnax/static/js/apexcharts.js +14 -0
  59. magnax/static/js/gray.js +16 -0
  60. magnax/static/js/highlight.min.js +1173 -0
  61. magnax/static/js/highstock.js +803 -0
  62. magnax/static/js/html2canvas.min.js +20 -0
  63. magnax/static/js/jquery.min.js +2 -0
  64. magnax/static/js/magnax-chart-theme.js +492 -0
  65. magnax/static/js/select2.min.js +2 -0
  66. magnax/static/js/sweetalert2.min.js +1 -0
  67. magnax/static/js/tabler.demo.min.js +9 -0
  68. magnax/static/js/tabler.min.js +9 -0
  69. magnax/static/logo/logo.png +0 -0
  70. magnax/templates/404.html +30 -0
  71. magnax/templates/analysis.html +1375 -0
  72. magnax/templates/analysis_compare.html +600 -0
  73. magnax/templates/analysis_pk.html +680 -0
  74. magnax/templates/base.html +365 -0
  75. magnax/templates/index.html +2471 -0
  76. magnax/templates/pk.html +743 -0
  77. magnax/templates/report.html +416 -0
  78. magnax/view/__init__.py +1 -0
  79. magnax/view/apis.py +952 -0
  80. magnax/view/pages.py +146 -0
  81. magnax/web.py +345 -0
  82. magnax-1.0.0.dist-info/METADATA +242 -0
  83. magnax-1.0.0.dist-info/RECORD +87 -0
  84. magnax-1.0.0.dist-info/WHEEL +5 -0
  85. magnax-1.0.0.dist-info/entry_points.txt +2 -0
  86. magnax-1.0.0.dist-info/licenses/LICENSE +21 -0
  87. magnax-1.0.0.dist-info/top_level.txt +1 -0
magnax/view/apis.py ADDED
@@ -0,0 +1,952 @@
1
+ import os
2
+ import shutil
3
+ import time
4
+ import requests
5
+ import json
6
+ from flask import request, make_response
7
+ from loguru import logger
8
+ from flask import Blueprint
9
+ from magnax import __version__
10
+ from magnax.public.apm import (CPU, Memory, Network, FPS, Battery, GPU, Energy, Disk,ThermalSensor, Target)
11
+ from magnax.public.apm_pk import (CPU_PK, MEM_PK, Flow_PK, FPS_PK)
12
+ from magnax.public.common import (Devices, File, Method, Install, Platform, Scrcpy)
13
+
14
+ d = Devices()
15
+ f = File()
16
+ api = Blueprint("api", __name__)
17
+ method = Method()
18
+
19
+ @api.route('/apm/cookie', methods=['post', 'get'])
20
+ def setCookie():
21
+ """set apm data to cookie"""
22
+ cpuWarning = request.args.get('cpuWarning')
23
+ memWarning = request.args.get('memWarning')
24
+ fpsWarning = request.args.get('fpsWarning')
25
+ netdataRecvWarning = request.args.get('netdataRecvWarning')
26
+ netdataSendWarning = request.args.get('netdataSendWarning')
27
+ betteryWarning = request.args.get('betteryWarning')
28
+ gpuWarning = request.args.get('gpuWarning')
29
+ duration = request.args.get('duration')
30
+ magnax_host = request.args.get('magnax_host')
31
+ host_switch = request.args.get('host_switch')
32
+
33
+ resp = make_response('set cookie ok')
34
+ resp.set_cookie('cpuWarning', cpuWarning)
35
+ resp.set_cookie('memWarning', memWarning)
36
+ resp.set_cookie('fpsWarning', fpsWarning)
37
+ resp.set_cookie('netdataRecvWarning', netdataRecvWarning)
38
+ resp.set_cookie('netdataSendWarning', netdataSendWarning)
39
+ resp.set_cookie('betteryWarning', betteryWarning)
40
+ resp.set_cookie('gpuWarning', gpuWarning)
41
+ resp.set_cookie('duration', duration)
42
+ resp.set_cookie('magnax_host', magnax_host)
43
+ resp.set_cookie('host_switch', host_switch)
44
+ return resp
45
+
46
+ @api.route('/magnax/version', methods=['post', 'get'])
47
+ def version():
48
+ try:
49
+ pypi = json.loads(requests.get(url='https://pypi.org/pypi/magnax/json',timeout=3).text)
50
+ if 'info' in pypi and 'version' in pypi['info']:
51
+ version = pypi['info']['version']
52
+ result = {'status': 1, 'lastest_version': version, 'current_version': __version__}
53
+ else:
54
+ # Package not found on PyPI
55
+ result = {'status': 1, 'lastest_version': __version__, 'current_version': __version__}
56
+ except Exception as e:
57
+ logger.exception(e)
58
+ result = {'status': 0, 'msg': str(e)}
59
+ return result
60
+
61
+ @api.route('/apm/initialize', methods=['post', 'get'])
62
+ def initialize():
63
+ """initialize apm env"""
64
+ try:
65
+ f.clear_file()
66
+ result = {'status': 1, 'msg': 'initialize env success'}
67
+ except Exception as e:
68
+ logger.exception(e)
69
+ result = {'status': 0, 'msg': str(e)}
70
+ return result
71
+
72
+ @api.route('/device/info', methods=['post', 'get'])
73
+ def deviceinfo():
74
+ """get devices info"""
75
+ platform = method._request(request, 'platform')
76
+ try:
77
+ match(platform):
78
+ case Platform.Android:
79
+ deviceids = d.getDeviceIds()
80
+ devices = d.getDevices()
81
+ if len(deviceids) > 0:
82
+ pkgnames = d.getPkgname(deviceids[0])
83
+ device_detail = d.getDdeviceDetail(deviceId=deviceids[0], platform=platform)
84
+ result = {'status': 1,
85
+ 'deviceids': deviceids,
86
+ 'devices': devices,
87
+ 'pkgnames': pkgnames,
88
+ 'device_detail': device_detail}
89
+ else:
90
+ result = {'status': 0, 'msg': 'no devices'}
91
+ case Platform.iOS:
92
+ deviceinfos = d.getDeviceInfoByiOS()
93
+ if len(deviceinfos) > 0:
94
+ pkgnames = d.getPkgnameByiOS(deviceinfos[0])
95
+ device_detail = d.getDdeviceDetail(deviceId=deviceinfos[0], platform=platform)
96
+ result = {'status': 1,
97
+ 'deviceids': deviceinfos,
98
+ 'devices': deviceinfos,
99
+ 'pkgnames': pkgnames,
100
+ 'device_detail': device_detail}
101
+ else:
102
+ result = {'status': 0, 'msg': 'no devices'}
103
+ case _:
104
+ result = {'status': 0, 'msg': f'no this platform = {platform}'}
105
+ except Exception as e:
106
+ logger.exception(e)
107
+ result = {'status': 0, 'msg': 'devices connect error!'}
108
+ return result
109
+
110
+ @api.route('/device/cpucore', methods=['post', 'get'])
111
+ def cpucore():
112
+ try:
113
+ deviceId = d.getDeviceIds()[0]
114
+ num = d.getCpuCores(deviceId)
115
+ result = {'status': 1, 'num': num}
116
+ except Exception as e:
117
+ result = {'status': 1, 'num': 0}
118
+ return result
119
+
120
+ @api.route('/device/package', methods=['post', 'get'])
121
+ def packageNames():
122
+ """get devices packageNames"""
123
+ platform = method._request(request, 'platform')
124
+ device = method._request(request, 'device')
125
+ match(platform):
126
+ case Platform.Android:
127
+ deviceId = d.getIdbyDevice(device, platform)
128
+ pkgnames = d.getPkgname(deviceId)
129
+ case Platform.iOS:
130
+ pkgnames = d.getPkgnameByiOS(device)
131
+ case _:
132
+ result = {'status': 0, 'msg': 'platform is undefined'}
133
+ return result
134
+ result = {'status': 1, 'pkgnames': pkgnames} if len(pkgnames) > 0 else {'status': 0, 'msg': 'no pkgnames'}
135
+ return result
136
+
137
+ @api.route('/package/pids', methods=['post', 'get'])
138
+ def getPackagePids():
139
+ platform = method._request(request, 'platform')
140
+ device = method._request(request, 'device')
141
+ pkgname = method._request(request, 'pkgname')
142
+ try:
143
+ deviceId = d.getIdbyDevice(device, platform)
144
+ pids = d.getPid(deviceId, pkgname)
145
+ if len(pids) > 0:
146
+ result = {'status': 1, 'pids': pids}
147
+ else:
148
+ result = {'status': 0, 'msg': 'No process found, please start the app first.'}
149
+ except Exception as e:
150
+ logger.exception(e)
151
+ result = {'status': 0, 'msg': 'No process found, please start the app first.'}
152
+ return result
153
+
154
+ @api.route('/package/activity', methods=['post', 'get'])
155
+ def getPackageActivity():
156
+ platform = method._request(request, 'platform')
157
+ device = method._request(request, 'device')
158
+ try:
159
+ deviceId = d.getIdbyDevice(device, platform)
160
+ activity = d.getCurrentActivity(deviceId)
161
+ result = {'status': 1, 'activity': activity}
162
+ except Exception as e:
163
+ logger.exception(e)
164
+ result = {'status': 0, 'msg': 'no activity found'}
165
+ return result
166
+
167
+ @api.route('/package/start/time/android', methods=['post', 'get'])
168
+ def getStartupTimeByAndroid():
169
+ platform = method._request(request, 'platform')
170
+ device = method._request(request, 'device')
171
+ activity = method._request(request, 'activity')
172
+ try:
173
+ deviceId = d.getIdbyDevice(device, platform)
174
+ time = d.getStartupTimeByAndroid(activity, deviceId)
175
+ result = {'status': 1, 'time': time}
176
+ except Exception as e:
177
+ logger.exception(e)
178
+ result = {'status': 0, 'msg': 'no result found'}
179
+ return result
180
+
181
+ @api.route('/package/start/time/ios', methods=['post', 'get'])
182
+ def getStartupTimeByiOS():
183
+ pkgname = method._request(request, 'pkgname')
184
+ try:
185
+ time = d.getStartupTimeByiOS(pkgname)
186
+ result = {'status': 1, 'time': time}
187
+ except Exception as e:
188
+ logger.exception(e)
189
+ result = {'status': 0, 'msg': 'no result found'}
190
+ return result
191
+
192
+ @api.route('/apm/cpu', methods=['post', 'get'])
193
+ def getCpuRate():
194
+ """get process cpu rate"""
195
+ model = method._request(request, 'model')
196
+ platform = method._request(request, 'platform')
197
+ pkgname = method._request(request, 'pkgname')
198
+ device = method._request(request, 'device')
199
+ try:
200
+ match(model):
201
+ case '2-devices':
202
+ pkgNameList = []
203
+ pkgNameList.append(pkgname)
204
+ deviceId1 = d.getIdbyDevice(device.split(',')[0], 'Android')
205
+ deviceId2 = d.getIdbyDevice(device.split(',')[1], 'Android')
206
+ cpu = CPU_PK(pkgNameList=pkgNameList, deviceId1=deviceId1, deviceId2=deviceId2)
207
+ first, second = cpu.getAndroidCpuRate()
208
+ result = {'status': 1, 'first': first, 'second': second}
209
+ case '2-app':
210
+ pkgNameList = pkgname.split(',')
211
+ deviceId1 = d.getIdbyDevice(device.split(',')[0], 'Android')
212
+ deviceId2 = d.getIdbyDevice(device.split(',')[1], 'Android')
213
+ cpu = CPU_PK(pkgNameList=pkgNameList, deviceId1=deviceId1, deviceId2=deviceId2)
214
+ first, second = cpu.getAndroidCpuRate()
215
+ result = {'status': 1, 'first': first, 'second': second}
216
+ case _:
217
+ process = method._request(request, 'process')
218
+ pid = None
219
+ deviceId = d.getIdbyDevice(device, platform)
220
+ if process and platform == Platform.Android :
221
+ pid = process.split(':')[0]
222
+ cpu = CPU(pkgName=pkgname, deviceId=deviceId, platform=platform, pid=pid)
223
+ appCpuRate, systemCpuRate = cpu.getCpuRate()
224
+ result = {'status': 1, 'appCpuRate': appCpuRate, 'systemCpuRate': systemCpuRate}
225
+ except Exception as e:
226
+ logger.error('get cpu failed')
227
+ logger.exception(e)
228
+ result = {'status': 1, 'appCpuRate': 0, 'systemCpuRate': 0, 'first': 0, 'second': 0}
229
+ return result
230
+
231
+ @api.route('/apm/corecpu', methods=['post', 'get'])
232
+ def getCoreCpuRate():
233
+ """get process cpu core rate"""
234
+ platform = method._request(request, 'platform')
235
+ pkgname = method._request(request, 'pkgname')
236
+ device = method._request(request, 'device')
237
+ cores = method._request(request, 'cores')
238
+ process = method._request(request, 'process')
239
+ try:
240
+ cores = int(cores)
241
+ pid = None
242
+ deviceId = d.getIdbyDevice(device, platform)
243
+ if process and platform == Platform.Android :
244
+ pid = process.split(':')[0]
245
+ corecpu = CPU(pkgName=pkgname, deviceId=deviceId, platform=platform, pid=pid)
246
+ coreCpuRate = corecpu.getCoreCpuRate(cores)
247
+ result = {'status': 1, 'coreCpuRate': coreCpuRate}
248
+ except Exception as e:
249
+ logger.error('get core cpu failed')
250
+ logger.exception(e)
251
+ coreCpuRate = list()
252
+ while cores > 0:
253
+ coreCpuRate.append(0)
254
+ cores = cores -1
255
+ result = {'status': 1, 'coreCpuRate': coreCpuRate}
256
+ return result
257
+
258
+ @api.route('/apm/mem', methods=['post', 'get'])
259
+ def getMemory():
260
+ """get memery data"""
261
+ model = method._request(request, 'model')
262
+ platform = method._request(request, 'platform')
263
+ pkgname = method._request(request, 'pkgname')
264
+ device = method._request(request, 'device')
265
+ try:
266
+ match(model):
267
+ case '2-devices':
268
+ pkgNameList = []
269
+ pkgNameList.append(pkgname)
270
+ deviceId1 = d.getIdbyDevice(device.split(',')[0], 'Android')
271
+ deviceId2 = d.getIdbyDevice(device.split(',')[1], 'Android')
272
+ mem = MEM_PK(pkgNameList=pkgNameList, deviceId1=deviceId1, deviceId2=deviceId2)
273
+ first, second = mem.getProcessMemory()
274
+ result = {'status': 1, 'first': first, 'second': second}
275
+ case '2-app':
276
+ pkgNameList = pkgname.split(',')
277
+ deviceId1 = d.getIdbyDevice(device.split(',')[0], 'Android')
278
+ deviceId2 = d.getIdbyDevice(device.split(',')[1], 'Android')
279
+ mem = MEM_PK(pkgNameList=pkgNameList, deviceId1=deviceId1, deviceId2=deviceId2)
280
+ first, second = mem.getProcessMemory()
281
+ result = {'status': 1, 'first': first, 'second': second}
282
+ case _:
283
+ process = method._request(request, 'process')
284
+ pid = None
285
+ deviceId = d.getIdbyDevice(device, platform)
286
+ if process and platform == Platform.Android :
287
+ pid = process.split(':')[0]
288
+ mem = Memory(pkgName=pkgname, deviceId=deviceId, platform=platform, pid=pid)
289
+ totalPass, swapPass = mem.getProcessMemory()
290
+ result = {'status': 1, 'totalPass': totalPass, 'swapPass': swapPass}
291
+ except Exception as e:
292
+ logger.error('get memory data failed')
293
+ logger.exception(e)
294
+ result = {'status': 1, 'totalPass': 0, 'nativePass': 0, 'dalvikPass': 0, 'first': 0, 'second': 0}
295
+ return result
296
+
297
+ @api.route('/apm/mem/detail', methods=['post', 'get'])
298
+ def getMemoryDetail():
299
+ """get memery detail data"""
300
+ platform = method._request(request, 'platform')
301
+ pkgname = method._request(request, 'pkgname')
302
+ device = method._request(request, 'device')
303
+ process = method._request(request, 'process')
304
+ try:
305
+ deviceId = d.getIdbyDevice(device, platform)
306
+ pid = process.split(':')[0]
307
+ memory = Memory(pkgName=pkgname, deviceId=deviceId, platform=platform, pid=pid)
308
+ memory_detail = memory.getAndroidMemoryDetail()
309
+ result = {'status': 1, 'memory_detail': memory_detail}
310
+ except Exception as e:
311
+ logger.error('get memory detail data failed')
312
+ logger.exception(e)
313
+ result = {'status': 1, 'memory_detail': memory_detail}
314
+ return result
315
+
316
+ @api.route('/apm/set/network', methods=['post', 'get'])
317
+ def setNetWorkData():
318
+ """set network data"""
319
+ platform = method._request(request, 'platform')
320
+ pkgname = method._request(request, 'pkgname')
321
+ device = method._request(request, 'device')
322
+ wifi_switch = method._request(request, 'wifi_switch')
323
+ type = method._request(request, 'type')
324
+ process = method._request(request, 'process')
325
+ try:
326
+ wifi = False if wifi_switch == 'false' else True
327
+ deviceId = d.getIdbyDevice(device, platform)
328
+ pid = None
329
+ if process and platform == Platform.Android :
330
+ pid = process.split(':')[0]
331
+ network = Network(pkgName=pkgname, deviceId=deviceId, platform=platform, pid=pid)
332
+ data = network.setAndroidNet(wifi=wifi)
333
+ f.record_net(type, data[0], data[1])
334
+ result = {'status': 1, 'msg':'set network data success'}
335
+ except Exception as e:
336
+ logger.exception(e)
337
+ result = {'status': 0, 'msg':'set network data failed'}
338
+ return result
339
+
340
+ @api.route('/apm/network', methods=['post', 'get'])
341
+ def getNetWorkData():
342
+ """get network data"""
343
+ model = method._request(request, 'model')
344
+ platform = method._request(request, 'platform')
345
+ pkgname = method._request(request, 'pkgname')
346
+ device = method._request(request, 'device')
347
+ wifi_switch = method._request(request, 'wifi_switch')
348
+ try:
349
+ wifi = False if wifi_switch == 'false' else True
350
+ match(model):
351
+ case '2-devices':
352
+ pkgNameList = []
353
+ pkgNameList.append(pkgname)
354
+ deviceId1 = d.getIdbyDevice(device.split(',')[0], 'Android')
355
+ deviceId2 = d.getIdbyDevice(device.split(',')[1], 'Android')
356
+ network = Flow_PK(pkgNameList=pkgNameList, deviceId1=deviceId1, deviceId2=deviceId2)
357
+ first, second = network.getNetWorkData()
358
+ result = {'status': 1, 'first': first, 'second': second}
359
+ case '2-app':
360
+ pkgNameList = pkgname.split(',')
361
+ deviceId1 = d.getIdbyDevice(device.split(',')[0], 'Android')
362
+ deviceId2 = d.getIdbyDevice(device.split(',')[1], 'Android')
363
+ network = Flow_PK(pkgNameList=pkgNameList, deviceId1=deviceId1, deviceId2=deviceId2)
364
+ first, second = network.getNetWorkData()
365
+ result = {'status': 1, 'first': first, 'second': second}
366
+ case _:
367
+ process = method._request(request, 'process')
368
+ pid = None
369
+ deviceId = d.getIdbyDevice(device, platform)
370
+ if process and platform == Platform.Android :
371
+ pid = process.split(':')[0]
372
+ network = Network(pkgName=pkgname, deviceId=deviceId, platform=platform, pid=pid)
373
+ data = network.getNetWorkData(wifi=wifi,noLog=False)
374
+ result = {'status': 1, 'upflow': data[0], 'downflow': data[1]}
375
+ except Exception as e:
376
+ logger.error('get network data failed')
377
+ logger.exception(e)
378
+ result = {'status': 1, 'upflow': 0, 'downflow': 0, 'first': 0, 'second': 0}
379
+ return result
380
+
381
+ @api.route('/apm/fps', methods=['post', 'get'])
382
+ def getFps():
383
+ """get fps data"""
384
+ model = method._request(request, 'model')
385
+ platform = method._request(request, 'platform')
386
+ pkgname = method._request(request, 'pkgname')
387
+ device = method._request(request, 'device')
388
+ surv = method._request(request, 'surv')
389
+ try:
390
+ surfaceview = False if surv == 'false' else True
391
+ match(model):
392
+ case '2-devices':
393
+ pkgNameList = []
394
+ pkgNameList.append(pkgname)
395
+ deviceId1 = d.getIdbyDevice(device.split(',')[0], 'Android')
396
+ deviceId2 = d.getIdbyDevice(device.split(',')[1], 'Android')
397
+ fps = FPS_PK(pkgNameList=pkgNameList, deviceId1=deviceId1, deviceId2=deviceId2, surfaceview=surfaceview)
398
+ first, second = fps.getFPS()
399
+ result = {'status': 1, 'first': first, 'second': second}
400
+ case '2-app':
401
+ pkgNameList = pkgname.split(',')
402
+ deviceId1 = d.getIdbyDevice(device.split(',')[0], 'Android')
403
+ deviceId2 = d.getIdbyDevice(device.split(',')[1], 'Android')
404
+ fps = FPS_PK(pkgNameList=pkgNameList, deviceId1=deviceId1, deviceId2=deviceId2, surfaceview=surfaceview)
405
+ first, second = fps.getFPS()
406
+ result = {'status': 1, 'first': first, 'second': second}
407
+ case _:
408
+ deviceId = d.getIdbyDevice(device, platform)
409
+ fps_monitor = FPS.getObject(pkgName=pkgname, deviceId=deviceId, surfaceview=surfaceview, platform=platform)
410
+ fps, jank = fps_monitor.getFPS()
411
+ result = {'status': 1, 'fps': fps, 'jank': jank}
412
+ except Exception as e:
413
+ logger.error('get fps failed')
414
+ logger.exception(e)
415
+ result = {'status': 1, 'fps': 0, 'jank': 0, 'first': 0, 'second': 0}
416
+ return result
417
+
418
+ @api.route('/apm/battery', methods=['post', 'get'])
419
+ def getBattery():
420
+ """get Battery data"""
421
+ platform = method._request(request, 'platform')
422
+ device = method._request(request, 'device')
423
+ try:
424
+ deviceId = d.getIdbyDevice(device, platform)
425
+ battery_monitor = Battery(deviceId=deviceId, platform=platform)
426
+ final = battery_monitor.getBattery()
427
+ if platform == Platform.Android:
428
+ result = {'status': 1, 'level': final[0], 'temperature': final[1]}
429
+ else:
430
+ result = {
431
+ 'status': 1,
432
+ 'temperature': final[0],
433
+ 'current': final[1],
434
+ 'voltage': final[2],
435
+ 'power': final[3]}
436
+ except Exception as e:
437
+ logger.exception(e)
438
+ result = {'status': 1, 'level': 0, 'temperature': 0, 'current':0, 'voltage':0 , 'power':0}
439
+ return result
440
+
441
+ @api.route('/apm/gpu', methods=['post', 'get'])
442
+ def getGpu():
443
+ """get gpu data"""
444
+ pkgname = method._request(request, 'pkgname')
445
+ device = method._request(request, 'device')
446
+ platform = method._request(request, 'platform')
447
+ try:
448
+ deviceId = d.getIdbyDevice(device, platform)
449
+ gpu = GPU(pkgName=pkgname, deviceId=deviceId, platform=platform)
450
+ value = gpu.getGPU()
451
+ result = {'status': 1, 'gpu': value}
452
+ except Exception as e:
453
+ logger.exception(e)
454
+ result = {'status': 1, 'gpu': 0}
455
+ return result
456
+
457
+ @api.route('/apm/energy', methods=['post', 'get'])
458
+ def getEnergy():
459
+ """get energy data"""
460
+ pkgname = method._request(request, 'pkgname')
461
+ device = method._request(request, 'device')
462
+ platform = method._request(request, 'platform')
463
+ try:
464
+ deviceId = d.getIdbyDevice(device, platform)
465
+ enery = Energy(deviceId=deviceId, packageName=pkgname)
466
+ value = enery.getEnergy()
467
+ result = {'status': 1, 'value': value}
468
+ except Exception as e:
469
+ logger.exception(e)
470
+ value = {
471
+ "energy.overhead": 0,
472
+ "energy.version": 0,
473
+ "energy.gpu.cost": 0,
474
+ "energy.cpu.cost": 0,
475
+ "energy.appstate.cost": 0,
476
+ "energy.thermalstate.cost": 0,
477
+ "energy.networking.cost": 0,
478
+ "energy.cost": 0,
479
+ "energy.display.cost": 0,
480
+ "energy.location.cost": 0,
481
+ }
482
+ result = {'status': 1, 'value': value}
483
+ return result
484
+
485
+ @api.route('/apm/disk', methods=['post', 'get'])
486
+ def getDisk():
487
+ """get disk data"""
488
+ device = method._request(request, 'device')
489
+ platform = method._request(request, 'platform')
490
+ try:
491
+ deviceId = d.getIdbyDevice(device, platform)
492
+ disk = Disk(deviceId=deviceId, platform=platform)
493
+ value = disk.getDisk()
494
+ result = {'status': 1, 'used': value['used'], 'free':value['free']}
495
+ except Exception as e:
496
+ logger.exception(e)
497
+ result = {'status': 1, 'used': 0, 'free':0}
498
+ return result
499
+
500
+ @api.route('/apm/set/disk', methods=['post', 'get'])
501
+ def setDiskData():
502
+ """set disk data"""
503
+ platform = method._request(request, 'platform')
504
+ device = method._request(request, 'device')
505
+ try:
506
+ deviceId = d.getIdbyDevice(device, platform)
507
+ disk = Disk(deviceId=deviceId)
508
+ disk.setInitialDisk()
509
+ result = {'status': 1, 'msg':'set disk data success'}
510
+ except Exception as e:
511
+ logger.exception(e)
512
+ result = {'status': 0, 'msg':'set disk data failed'}
513
+ return result
514
+
515
+ @api.route('/apm/set/thermal', methods=['post', 'get'])
516
+ def setThermalData():
517
+ """set thermal data"""
518
+ platform = method._request(request, 'platform')
519
+ device = method._request(request, 'device')
520
+ try:
521
+ deviceId = d.getIdbyDevice(device, platform)
522
+ thermal = ThermalSensor(deviceId=deviceId)
523
+ thermal.setInitalThermalTemp()
524
+ result = {'status': 1, 'msg':'set thermal data success'}
525
+ except Exception as e:
526
+ logger.exception(e)
527
+ result = {'status': 0, 'msg':'set thermal data failed'}
528
+ return result
529
+
530
+ @api.route('/apm/create/report', methods=['post', 'get'])
531
+ def makeReport():
532
+ """Create test report records"""
533
+ platform = method._request(request, 'platform')
534
+ app = method._request(request, 'app')
535
+ model = method._request(request, 'model')
536
+ devices = method._request(request, 'devices')
537
+ wifi_switch = method._request(request, 'wifi_switch')
538
+ record_switch = method._request(request, 'record_switch')
539
+ thermal_switch = method._request(request, 'thermal_switch')
540
+ process = method._request(request, 'process')
541
+ cores = method._request(request, 'cores')
542
+ try:
543
+ video = 0
544
+ if platform == Platform.Android and model == 'normal':
545
+ deviceId = d.getIdbyDevice(devices, platform)
546
+ battery_monitor = Battery(deviceId=deviceId)
547
+ battery_monitor.recoverBattery()
548
+ wifi = False if wifi_switch == 'false' else True
549
+ pid = None
550
+ if process and platform == Platform.Android :
551
+ pid = process.split(':')[0]
552
+
553
+ # set current natwork
554
+ network = Network(pkgName=app, deviceId=deviceId, platform=platform, pid=pid)
555
+ data = network.setAndroidNet(wifi=wifi)
556
+ f.record_net('end', data[0], data[1])
557
+
558
+ # set current disk
559
+ disk = Disk(deviceId=deviceId)
560
+ disk.setCurrentDisk()
561
+
562
+ # set current thermal
563
+ thermal_checked = False if thermal_switch == 'false' else True
564
+ if thermal_checked:
565
+ thermal = ThermalSensor(deviceId=deviceId)
566
+ thermal.setCurrentThermalTemp()
567
+
568
+ record = False if record_switch == 'false' else True
569
+ if record:
570
+ video = 1
571
+ logger.info('停止录屏,准备生成报告...')
572
+ Scrcpy.stop_record()
573
+ # 等待录屏进程完全结束,确保文件不被占用
574
+ logger.info('等待录屏文件释放...')
575
+ time.sleep(3) # 等待3秒确保进程完全结束并释放文件
576
+ logger.info('开始生成报告')
577
+
578
+ f.make_report(app=app, devices=devices, video=video, platform=platform, model=model, cores=cores)
579
+ result = {'status': 1}
580
+ except Exception as e:
581
+ logger.exception(e)
582
+ result = {'status': 0, 'msg': str(e)}
583
+ return result
584
+
585
+ @api.route('/apm/edit/report', methods=['post', 'get'])
586
+ def editReport():
587
+ """Edit test report records"""
588
+ old_scene = method._request(request, 'old_scene')
589
+ new_scene = method._request(request, 'new_scene')
590
+ report_dir = os.path.join(os.getcwd(), 'report')
591
+ if old_scene == new_scene:
592
+ result = {'status': 0, 'msg': 'scene not changed'}
593
+ elif os.path.exists(os.path.join(report_dir, new_scene)):
594
+ result = {'status': 0, 'msg': 'scene existed'}
595
+ else:
596
+ try:
597
+ new_scene = new_scene.replace('/', '_').replace(' ', '').replace('&', '_')
598
+ os.rename(os.path.join(report_dir, old_scene), os.path.join(report_dir, new_scene))
599
+ result = {'status': 1}
600
+ except Exception as e:
601
+ logger.exception(e)
602
+ result = {'status': 0, 'msg': str(e)}
603
+ return result
604
+
605
+ @api.route('/apm/export/report', methods=['post', 'get'])
606
+ def exportReport():
607
+ platform = method._request(request, 'platform')
608
+ scene = method._request(request, 'scene')
609
+ try:
610
+ path = f.export_excel(platform=platform, scene=scene)
611
+ result = {'status': 1, 'msg':'success', 'path': path}
612
+ except Exception as e:
613
+ logger.exception(e)
614
+ result = {'status': 0, 'msg':str(e)}
615
+ return result
616
+
617
+ @api.route('/apm/export/html/android', methods=['post', 'get'])
618
+ def exportAndroidHtml():
619
+ scene = method._request(request, 'scene')
620
+ cpu_app = method._request(request, 'cpu_app')
621
+ cpu_sys = method._request(request, 'cpu_sys')
622
+ mem_total = method._request(request, 'mem_total')
623
+ mem_swap = method._request(request, 'mem_swap')
624
+ fps = method._request(request, 'fps')
625
+ jank = method._request(request, 'jank')
626
+ level = method._request(request, 'level')
627
+ temperature = method._request(request, 'temperature')
628
+ net_send = method._request(request, 'net_send')
629
+ net_recv = method._request(request, 'net_recv')
630
+ gpu = method._request(request, 'gpu')
631
+ try:
632
+ summary_dict = dict()
633
+ summary_dict['app'] = f.readJson(scene).get('app')
634
+ summary_dict['platform'] = f.readJson(scene).get('platform')
635
+ summary_dict['devices'] = f.readJson(scene).get('devices')
636
+ summary_dict['ctime'] = f.readJson(scene).get('ctime')
637
+ summary_dict['cpu_app'] = cpu_app
638
+ summary_dict['cpu_sys'] = cpu_sys
639
+ summary_dict['mem_total'] = mem_total
640
+ summary_dict['mem_swap'] = mem_swap
641
+ summary_dict['fps'] = fps
642
+ summary_dict['jank'] = jank
643
+ summary_dict['level'] = level
644
+ summary_dict['tem'] = temperature
645
+ summary_dict['net_send'] = net_send
646
+ summary_dict['net_recv'] = net_recv
647
+ summary_dict['gpu'] = gpu
648
+ summary_dict['cpu_charts'] = f.getCpuLog(Platform.Android, scene)
649
+ summary_dict['mem_charts'] = f.getMemLog(Platform.Android, scene)
650
+ summary_dict['mem_detail_charts'] = f.getMemDetailLog(Platform.Android, scene)
651
+ summary_dict['net_charts'] = f.getFlowLog(Platform.Android, scene)
652
+ summary_dict['battery_charts'] = f.getBatteryLog(Platform.Android, scene)
653
+ summary_dict['fps_charts'] = f.getFpsLog(Platform.Android, scene)['fps']
654
+ summary_dict['jank_charts'] = f.getFpsLog(Platform.Android, scene)['jank']
655
+ summary_dict['gpu_charts'] = f.getGpuLog(Platform.Android, scene)
656
+ path = f.make_android_html(scene, summary_dict)
657
+ result = {'status': 1, 'msg':'success', 'path':path}
658
+ except Exception as e:
659
+ logger.exception(e)
660
+ result = {'status': 0, 'msg':str(e)}
661
+ return result
662
+
663
+ @api.route('/apm/export/html/ios', methods=['post', 'get'])
664
+ def exportiOSHtml():
665
+ scene = method._request(request, 'scene')
666
+ cpu_app = method._request(request, 'cpu_app')
667
+ cpu_sys = method._request(request, 'cpu_sys')
668
+ mem_total = method._request(request, 'mem_total')
669
+ gpu = method._request(request, 'gpu')
670
+ fps = method._request(request, 'fps')
671
+ temperature = method._request(request, 'temperature')
672
+ current = method._request(request, 'current')
673
+ voltage = method._request(request, 'voltage')
674
+ power = method._request(request, 'power')
675
+ net_send = method._request(request, 'net_send')
676
+ net_recv = method._request(request, 'net_recv')
677
+ try:
678
+ summary_dict = dict()
679
+ summary_dict['app'] = f.readJson(scene).get('app')
680
+ summary_dict['platform'] = f.readJson(scene).get('platform')
681
+ summary_dict['devices'] = f.readJson(scene).get('devices')
682
+ summary_dict['ctime'] = f.readJson(scene).get('ctime')
683
+ summary_dict['cpu_app'] = cpu_app
684
+ summary_dict['cpu_sys'] = cpu_sys
685
+ summary_dict['mem_total'] = mem_total
686
+ summary_dict['gpu'] = gpu
687
+ summary_dict['fps'] = fps
688
+ summary_dict['tem'] = temperature
689
+ summary_dict['current'] = current
690
+ summary_dict['voltage'] = voltage
691
+ summary_dict['power'] = power
692
+ summary_dict['net_send'] = net_send
693
+ summary_dict['net_recv'] = net_recv
694
+ summary_dict['cpu_charts'] = f.getCpuLog(Platform.iOS, scene)
695
+ summary_dict['mem_charts'] = f.getMemLog(Platform.iOS, scene)
696
+ summary_dict['net_charts'] = f.getFlowLog(Platform.iOS, scene)
697
+ summary_dict['battery_charts'] = f.getBatteryLog(Platform.iOS, scene)
698
+ summary_dict['fps_charts'] = f.getFpsLog(Platform.iOS, scene)
699
+ summary_dict['gpu_charts'] = f.getGpuLog(Platform.iOS, scene)
700
+ path = f.make_ios_html(scene, summary_dict)
701
+ result = {'status': 1, 'msg':'success', 'path':path}
702
+ except Exception as e:
703
+ logger.exception(e)
704
+ result = {'status': 0, 'msg':str(e)}
705
+ return result
706
+
707
+ @api.route('/apm/log', methods=['post', 'get'])
708
+ def getLogData():
709
+ """Get apm detailed data with optional downsampling"""
710
+ scene = method._request(request, 'scene')
711
+ target = method._request(request, 'target')
712
+ platform = method._request(request, 'platform')
713
+ # 获取采样参数,默认 1000 点(可选:0 表示不采样)
714
+ max_points = request.args.get('max_points', 1000, type=int)
715
+ try:
716
+ fucDic = {
717
+ 'cpu': f.getCpuLog(platform, scene, max_points=max_points),
718
+ 'mem': f.getMemLog(platform, scene, max_points=max_points),
719
+ 'mem_detail': f.getMemDetailLog(platform, scene, max_points=max_points),
720
+ 'battery': f.getBatteryLog(platform, scene, max_points=max_points),
721
+ 'flow': f.getFlowLog(platform, scene, max_points=max_points),
722
+ 'fps': f.getFpsLog(platform, scene, max_points=max_points),
723
+ 'gpu': f.getGpuLog(platform, scene, max_points=max_points),
724
+ 'disk': f.getDiskLog(platform, scene, max_points=max_points),
725
+ 'cpu_core': f.getCpuCoreLog(platform, scene, max_points=max_points)
726
+ }
727
+ result = fucDic[target]
728
+ except Exception as e:
729
+ logger.exception(e)
730
+ result = {'status': 0, 'msg': str(e)}
731
+ return result
732
+
733
+ @api.route('/apm/log/compare', methods=['post', 'get'])
734
+ def getLogCompareData():
735
+ """Get apm detailed data for comparison with optional downsampling"""
736
+ scene1 = method._request(request, 'scene1')
737
+ scene2 = method._request(request, 'scene2')
738
+ target = method._request(request, 'target')
739
+ platform = method._request(request, 'platform')
740
+ # 获取采样参数,默认 1000 点
741
+ max_points = request.args.get('max_points', 1000, type=int)
742
+ try:
743
+ match(target):
744
+ case Target.CPU:
745
+ result = f.getCpuLogCompare(platform, scene1, scene2, max_points=max_points)
746
+ case Target.Memory:
747
+ result = f.getMemLogCompare(platform, scene1, scene2, max_points=max_points)
748
+ case Target.Battery:
749
+ result = f.getBatteryLogCompare(platform, scene1, scene2, max_points=max_points)
750
+ case Target.FPS:
751
+ result = f.getFpsLogCompare(platform, scene1, scene2, max_points=max_points)
752
+ case Target.GPU:
753
+ result = f.getGpuLogCompare(platform, scene1, scene2, max_points=max_points)
754
+ case 'net_send':
755
+ result = f.getFlowSendLogCompare(platform, scene1, scene2, max_points=max_points)
756
+ case 'net_recv':
757
+ result = f.getFlowRecvLogCompare(platform, scene1, scene2, max_points=max_points)
758
+ case _:
759
+ result = {'status': 0, 'msg': 'no target found'}
760
+ except Exception as e:
761
+ logger.exception(e)
762
+ result = {'status': 0, 'msg': str(e)}
763
+ return result
764
+
765
+ @api.route('/apm/log/pk', methods=['post', 'get'])
766
+ def getpkLogData():
767
+ """Get apm detailed data for pk mode with optional downsampling"""
768
+ scene = method._request(request, 'scene')
769
+ target1 = method._request(request, 'target1')
770
+ target2 = method._request(request, 'target2')
771
+ # 获取采样参数,默认 1000 点
772
+ max_points = request.args.get('max_points', 1000, type=int)
773
+ try:
774
+ first_data, _, first_total = f.readLog(scene=scene, filename=f'{target1}.log', max_points=max_points)
775
+ second_data, _, second_total = f.readLog(scene=scene, filename=f'{target2}.log', max_points=max_points)
776
+ result = {
777
+ 'status': 1,
778
+ 'first': first_data,
779
+ 'second': second_data,
780
+ 'meta': {
781
+ 'sampled': max_points > 0 and max(first_total, second_total) > max_points,
782
+ 'max_points': max_points,
783
+ 'total_points': max(first_total, second_total)
784
+ }
785
+ }
786
+ except Exception as e:
787
+ logger.exception(e)
788
+ result = {'status': 0, 'msg': str(e)}
789
+ return result
790
+
791
+ @api.route('/apm/remove/report', methods=['post', 'get'])
792
+ def removeReport():
793
+ """Remove test report record"""
794
+ scene = method._request(request, 'scene')
795
+ report_dir = os.path.join(os.getcwd(), 'report')
796
+ try:
797
+ shutil.rmtree(f'{report_dir}/{scene}', True)
798
+ result = {'status': 1}
799
+ except Exception as e:
800
+ logger.exception(e)
801
+ result = {'status': 0, 'msg': str(e)}
802
+ return result
803
+
804
+ @api.route('/apm/collect', methods=['post', 'get'])
805
+ def apmCollect():
806
+ """apm common api"""
807
+ platform = method._request(request, 'platform')
808
+ deviceid = method._request(request, 'deviceid')
809
+ pkgname = method._request(request, 'pkgname')
810
+ target = method._request(request, 'target')
811
+ try:
812
+ match(target):
813
+ case Target.CPU:
814
+ cpu = CPU(pkgName=pkgname, deviceId=deviceid, platform=platform)
815
+ appCpuRate, systemCpuRate = cpu.getCpuRate(noLog=True)
816
+ result = {'status': 1, 'appCpuRate': appCpuRate, 'systemCpuRate': systemCpuRate}
817
+ case Target.Memory:
818
+ mem = Memory(pkgName=pkgname, deviceId=deviceid, platform=platform)
819
+ totalPass, swapPass = mem.getProcessMemory(noLog=True)
820
+ result = {'status': 1, 'totalPass': totalPass, 'swapPass': swapPass}
821
+ case Target.MemoryDetail:
822
+ if platform == Platform.Android:
823
+ mem = Memory(pkgName=pkgname, deviceId=deviceid, platform=platform)
824
+ data = mem.getAndroidMemoryDetail(noLog=True)
825
+ result = {'status': 1, 'data': data}
826
+ else:
827
+ result = {'status': 0, 'msg': 'not support ios'}
828
+ case Target.Network:
829
+ network = Network(pkgName=pkgname, deviceId=deviceid, platform=platform)
830
+ data = network.getNetWorkData(wifi=True, noLog=True)
831
+ result = {'status': 1, 'upflow': data[0], 'downflow': data[1]}
832
+ case Target.FPS:
833
+ fps_monitor = FPS(pkgName=pkgname, deviceId=deviceid, platform=platform)
834
+ fps, jank = fps_monitor.getFPS(noLog=True)
835
+ result = {'status': 1, 'fps': fps, 'jank': jank}
836
+ case Target.Battery:
837
+ battery_monitor = Battery(deviceId=deviceid)
838
+ final = battery_monitor.getBattery(noLog=True)
839
+ if platform == 'Android':
840
+ result = {'status': 1, 'level': final[0], 'temperature': final[1]}
841
+ else:
842
+ result = {'status': 1, 'temperature': final[0], 'current': final[1], 'voltage': final[2], 'power': final[3]}
843
+ case Target.GPU:
844
+ gpu = GPU(pkgname=pkgname)
845
+ final = gpu.getGPU()
846
+ result = {'status': 1, 'gpu': final}
847
+ case _:
848
+ result = {'status': 0, 'msg': 'no this target'}
849
+ except Exception as e:
850
+ logger.exception(e)
851
+ result = {'status': 0, 'msg': str(e)}
852
+ return result
853
+
854
+ @api.route('/apm/install/file', methods=['post', 'get'])
855
+ def installFile():
856
+ """install apk/ipa from file"""
857
+ platform = method._request(request, 'platform')
858
+ file = request.files['file']
859
+ currentPath = os.path.dirname(os.path.realpath(__file__))
860
+ install = Install()
861
+ unixtime = int(time.time())
862
+ if platform == Platform.Android:
863
+ file_path = os.path.join(currentPath, '{}.apk'.format(unixtime))
864
+ if install.uploadFile(file_path, file):
865
+ install_status = install.installAPK(file_path)
866
+ else:
867
+ result = {'status': 0, 'msg': 'install file failed'}
868
+ return result
869
+ else:
870
+ file_path = os.path.join(currentPath, '{}.ipa'.format(unixtime))
871
+ if install.uploadFile(file_path, file):
872
+ install_status = install.installIPA(file_path)
873
+ else:
874
+ result = {'status': 0, 'msg': 'install file failed'}
875
+ return result
876
+ if install_status[0]:
877
+ result = {'status': 1, 'msg': 'install sucess'}
878
+ else:
879
+ result = {'status': 0, 'msg': install_status[1]}
880
+ return result
881
+
882
+ @api.route('/apm/install/link', methods=['post', 'get'])
883
+ def installLink():
884
+ """install apk/ipa from link"""
885
+ platform = method._request(request, 'platform')
886
+ link = method._request(request, 'link')
887
+ currentPath = os.path.dirname(os.path.realpath(__file__))
888
+ install = Install()
889
+ unixtime = int(time.time())
890
+ if platform == Platform.Android:
891
+ d_status = install.downloadLink(filelink=link, path=currentPath, name='{}.apk'.format(unixtime))
892
+ if d_status:
893
+ install_status = install.installAPK(os.path.join(currentPath, '{}.apk'.format(unixtime)))
894
+ else:
895
+ result = {'status': 0, 'msg': 'download link failed'}
896
+ return result
897
+ else:
898
+ d_status = install.downloadLink(filelink=link, path=currentPath, name='{}.ipa'.format(unixtime))
899
+ if d_status:
900
+ install_status = install.installIPA(os.path.join(currentPath, '{}.ipa'.format(unixtime)))
901
+ else:
902
+ result = {'status': 0, 'msg': 'download link failed'}
903
+ return result
904
+ if install_status[0]:
905
+ result = {'status': 1, 'msg': 'install sucess'}
906
+ else:
907
+ result = {'status': 0, 'msg': install_status[1]}
908
+ return result
909
+
910
+ @api.route('/apm/record/start', methods=['post', 'get'])
911
+ def start_record():
912
+ device = method._request(request, 'device')
913
+ platform = method._request(request, 'platform')
914
+ try:
915
+ deviceId = d.getIdbyDevice(device, platform)
916
+ final = Scrcpy.start_record(deviceId)
917
+ if final == 0:
918
+ result = {'status': 1, 'msg': 'success'}
919
+ else:
920
+ result = {'status': 0, 'msg': 'record screen failed'}
921
+ except Exception as e:
922
+ logger.exception(e)
923
+ result = {'status': 0, 'msg': 'record screen failed'}
924
+ return result
925
+
926
+ @api.route('/apm/record/cast', methods=['post', 'get'])
927
+ def cast_screen():
928
+ device = method._request(request, 'device')
929
+ platform = method._request(request, 'platform')
930
+ try:
931
+ deviceId = d.getIdbyDevice(device, platform)
932
+ final = Scrcpy.cast_screen(deviceId)
933
+ if final == 0:
934
+ result = {'status': 1, 'msg': 'success'}
935
+ else:
936
+ result = {'status': 0, 'msg': 'cast screen failed'}
937
+ except Exception as e:
938
+ logger.exception(e)
939
+ result = {'status': 0, 'msg': 'cast screen failed'}
940
+ return result
941
+
942
+ @api.route('/apm/record/play', methods=['post', 'get'])
943
+ def play_record():
944
+ scene = method._request(request, 'scene')
945
+ video = os.path.join(f.get_repordir(), scene, 'record.mkv')
946
+ try:
947
+ Scrcpy.play_video(video)
948
+ result = {'status': 1, 'msg': 'success'}
949
+ except Exception as e:
950
+ logger.exception(e)
951
+ result = {'status': 0, 'msg': 'play video failed'}
952
+ return result