Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.vscode/

__pycache__/
.venv*/
2 changes: 1 addition & 1 deletion HNroute.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"lng":"120.7335575167566","lat":"30.52802386594508"},{"lng":"120.7335664998117","lat":"30.527949984828833"},{"lng":"120.73357997439435","lat":"30.527887769107984"},{"lng":"120.73361590661474","lat":"30.527825553346897"},{"lng":"120.7336653134178","lat":"30.527771114522935"},{"lng":"120.73372370327594","lat":"30.527720564158813"},{"lng":"120.73379107618919","lat":"30.527689456229226"},{"lng":"120.73387641521265","lat":"30.527662236782586"},{"lng":"120.73397073729119","lat":"30.52765057130309"},{"lng":"120.73407404242484","lat":"30.527646682809618"},{"lng":"120.73416387297584","lat":"30.527677790753035"},{"lng":"120.73428514421968","lat":"30.52773611811983"},{"lng":"120.73436150018803","lat":"30.52781388788721"},{"lng":"120.73441539851864","lat":"30.527922765455916"},{"lng":"120.73444234768392","lat":"30.52803941985705"},{"lng":"120.73445133073903","lat":"30.528156074116726"},{"lng":"120.73445582226658","lat":"30.5283038359759"},{"lng":"120.73446031379413","lat":"30.528420489914918"},{"lng":"120.73446031379413","lat":"30.52852158988096"},{"lng":"120.73446480532168","lat":"30.528618801286576"},{"lng":"120.73446480532168","lat":"30.528719901044198"},{"lng":"120.73445582226658","lat":"30.52881322380307"},{"lng":"120.73442887310128","lat":"30.528902658028688"},{"lng":"120.73439294088088","lat":"30.52898820373192"},{"lng":"120.73434353407784","lat":"30.529034864992525"},{"lng":"120.73427616116459","lat":"30.529081526230495"},{"lng":"120.73420429672379","lat":"30.52912429901208"},{"lng":"120.73414590686563","lat":"30.529143741179244"},{"lng":"120.73408302547993","lat":"30.52915929491014"},{"lng":"120.73399319492894","lat":"30.52915540647765"},{"lng":"120.73390785590549","lat":"30.52915540647765"},{"lng":"120.73383599146469","lat":"30.529135964312847"},{"lng":"120.733773110079","lat":"30.529108745275526"},{"lng":"120.73372370327594","lat":"30.529065972487018"},{"lng":"120.73365633036269","lat":"30.529003757487974"},{"lng":"120.73361590661474","lat":"30.528925988682573"},{"lng":"120.7335754828668","lat":"30.528855996703964"},{"lng":"120.7335664998117","lat":"30.528782116226836"},{"lng":"120.7335575167566","lat":"30.528719901044198"},{"lng":"120.7335575167566","lat":"30.52863435510235"},{"lng":"120.7335575167566","lat":"30.528541032169947"},{"lng":"120.7335575167566","lat":"30.528451597608097"},{"lng":"120.7335485337015","lat":"30.528350497568482"},{"lng":"120.73355302522906","lat":"30.528261062829475"},{"lng":"120.7335575167566","lat":"30.52818329342363"},{"lng":"120.73356200828415","lat":"30.528128854802127"}
{"lng":"120.08826462728848","lat":"30.311727137354364"},{"lng":"120.08818377979257","lat":"30.31171544577161"},{"lng":"120.08809844076913","lat":"30.311656987836667"},{"lng":"120.08805801702118","lat":"30.31163360465283"},{"lng":"120.08804005091098","lat":"30.31161022146335"},{"lng":"120.08801310174569","lat":"30.311579043868623"},{"lng":"120.08799513563548","lat":"30.311528380255805"},{"lng":"120.08797716952529","lat":"30.311469922208154"},{"lng":"120.08796369494263","lat":"30.31143874456834"},{"lng":"120.08796818647018","lat":"30.311384183674555"},{"lng":"120.08796818647018","lat":"30.311345211588783"},{"lng":"120.08795920341508","lat":"30.311298445065198"},{"lng":"120.08795920341508","lat":"30.31125167851906"},{"lng":"120.08796818647018","lat":"30.31117373422542"},{"lng":"120.08798166105284","lat":"30.311138659272842"},{"lng":"120.08799064410793","lat":"30.311091892649703"},{"lng":"120.08799064410793","lat":"30.31104902322535"},{"lng":"120.08800411869058","lat":"30.311017845450287"},{"lng":"120.08801310174569","lat":"30.310978873217366"},{"lng":"120.08801310174569","lat":"30.31093600374308"},{"lng":"120.08803106785588","lat":"30.310900928704577"},{"lng":"120.08803106785588","lat":"30.31084636750836"},{"lng":"120.08804454243852","lat":"30.31081129243745"},{"lng":"120.08804903396609","lat":"30.310760628423754"},{"lng":"120.08806250854873","lat":"30.31070216991354"},{"lng":"120.08807149160383","lat":"30.310659300316996"},{"lng":"120.08808047465892","lat":"30.310604738984914"},{"lng":"120.08809394924158","lat":"30.310581355547484"},{"lng":"120.08809844076913","lat":"30.31054238313925"},{"lng":"120.08811191535177","lat":"30.31048002725351"},{"lng":"120.08811191535177","lat":"30.31042936306685"},{"lng":"120.08813437298953","lat":"30.310386493349778"},{"lng":"120.08814784757217","lat":"30.31033972636409"},{"lng":"120.08817030520993","lat":"30.31028516485231"},{"lng":"120.08819725437523","lat":"30.310253986831796"},{"lng":"120.08824666117827","lat":"30.31023450056389"},{"lng":"120.08828259339867","lat":"30.310195528016337"},{"lng":"120.08832301714662","lat":"30.310179938992935"},{"lng":"120.08840835617008","lat":"30.310164349967025"},{"lng":"120.08847572908333","lat":"30.310172144480294"},{"lng":"120.08852962741392","lat":"30.310172144480294"},{"lng":"120.08859250879962","lat":"30.310183836249024"},{"lng":"120.08866437324042","lat":"30.310218911546745"},{"lng":"120.08874522073631","lat":"30.310253986831796"},{"lng":"120.08879462753936","lat":"30.3103202401134"},{"lng":"120.08883954281487","lat":"30.310386493349778"},{"lng":"120.08886649198016","lat":"30.31050341071536"},{"lng":"120.08883505128732","lat":"30.310620327940075"},{"lng":"120.08882606823221","lat":"30.31073724502389"},{"lng":"120.08878564448426","lat":"30.31085026473768"},{"lng":"120.08875420379141","lat":"30.310982770441356"},{"lng":"120.08873174615367","lat":"30.311119173182615"},{"lng":"120.08869581393327","lat":"30.31123608966534"},{"lng":"120.08868233935061","lat":"30.311364697633625"},{"lng":"120.08865089865776","lat":"30.311501099837947"},{"lng":"120.08861496643736","lat":"30.311625810256956"},{"lng":"120.08857454268941","lat":"30.311719342966015"},{"lng":"120.08848920366597","lat":"30.311758314901514"},{"lng":"120.08838140700477","lat":"30.311770006479115"}
75 changes: 59 additions & 16 deletions driver/connect.py
Original file line number Diff line number Diff line change
@@ -1,55 +1,98 @@
import logging
import asyncio
import inspect
import multiprocessing

from pymobiledevice3.lockdown import create_using_usbmux, LockdownClient

from pymobiledevice3.cli.remote import install_driver_if_required
from pymobiledevice3.cli.remote import select_device, RemoteServiceDiscoveryService
from pymobiledevice3.cli.remote import start_tunnel
from pymobiledevice3.cli.remote import verify_tunnel_imports

from pymobiledevice3.services.amfi import AmfiService

from pymobiledevice3.exceptions import NoDeviceConnectedError

from util.pymobiledevice3_compat import (
RemoteServiceDiscoveryService,
get_tunnel_service,
install_driver_if_required,
start_tunnel as start_tunnel_session,
verify_tunnel_imports,
)


def _wait_if_needed(result):
if inspect.isawaitable(result):
return asyncio.run(result)
return result


def _create_using_usbmux():
return _wait_if_needed(create_using_usbmux())


async def _create_using_usbmux_async():
lockdown = create_using_usbmux()
if inspect.isawaitable(lockdown):
lockdown = await lockdown
return lockdown


def get_usbmux_lockdownclient():
while True:
try:
lockdown = create_using_usbmux()
lockdown = _create_using_usbmux()
except NoDeviceConnectedError:
print("请连接设备后按回车...")
input()
else:
break
while True:
lockdown = create_using_usbmux()
lockdown = _create_using_usbmux()
if lockdown.all_values.get("PasswordProtected"):
print("请解锁设备后按回车...")
input()
else:
break
return create_using_usbmux()
return lockdown

def get_version(lockdown: LockdownClient):
return lockdown.all_values.get("ProductVersion")

def get_developer_mode_status(lockdown: LockdownClient):
return lockdown.developer_mode_status
if hasattr(lockdown, "developer_mode_status"):
return lockdown.developer_mode_status

async def get_status():
fresh_lockdown = await _create_using_usbmux_async()
return await fresh_lockdown.get_developer_mode_status()

return asyncio.run(get_status())

def reveal_developer_mode(lockdown: LockdownClient):
AmfiService(lockdown).create_amfi_show_override_path_file()
service = AmfiService(lockdown)
if hasattr(service, "create_amfi_show_override_path_file"):
return _wait_if_needed(service.create_amfi_show_override_path_file())

async def reveal():
fresh_lockdown = await _create_using_usbmux_async()
await AmfiService(fresh_lockdown).reveal_developer_mode_option_in_ui()

return asyncio.run(reveal())

def enable_developer_mode(lockdown: LockdownClient):
AmfiService(lockdown).enable_developer_mode()
service = AmfiService(lockdown)
if not inspect.iscoroutinefunction(service.enable_developer_mode):
return service.enable_developer_mode()

async def enable():
fresh_lockdown = await _create_using_usbmux_async()
await AmfiService(fresh_lockdown).enable_developer_mode()

return asyncio.run(enable())

def get_serverrsd():
install_driver_if_required()
if not verify_tunnel_imports():
exit(1)
return select_device(None)
return get_tunnel_service()


async def tunnel(rsd: RemoteServiceDiscoveryService, queue: multiprocessing.Queue):
async with start_tunnel(rsd, None) as tunnel_result:
queue.put((tunnel_result.address, tunnel_result.port))
await tunnel_result.client.wait_closed()
await start_tunnel_session(rsd, queue)
9 changes: 4 additions & 5 deletions driver/location.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from pymobiledevice3.cli.developer import LocationSimulation
def set_location(location_client, lat: float, lng: float):
location_client.set(lat, lng)

def set_location(dvt, lat: float, lng: float):
LocationSimulation(dvt).set(lat, lng)

def clear_location(dvt):
LocationSimulation(dvt).clear()
def clear_location(location_client):
location_client.clear()
14 changes: 11 additions & 3 deletions init/tunnel.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import asyncio
import multiprocessing
import traceback

from driver import connect

def tunnel_proc(queue: multiprocessing.Queue):
server_rsd = connect.get_serverrsd()
asyncio.run(connect.tunnel(server_rsd, queue))
try:
server_rsd = connect.get_serverrsd()
asyncio.run(connect.tunnel(server_rsd, queue))
except Exception:
queue.put(("error", traceback.format_exc()))
raise


def tunnel():
Expand All @@ -16,5 +21,8 @@ def tunnel():

# get the address and port of the tunnel
address, port = queue.get()
if address == "error":
process.join(timeout=1)
raise RuntimeError(f"Failed to start tunnel:\n{port}")

return process, address, port
return process, address, port
25 changes: 14 additions & 11 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@
import coloredlogs
import os

from driver import location

from pymobiledevice3.cli.remote import RemoteServiceDiscoveryService
from pymobiledevice3.cli.developer import DvtSecureSocketProxyService

from init import init
from init import tunnel
from init import route

import run

import config
from util.pymobiledevice3_compat import (
open_location_session,
open_remote_service_discovery,
)


debug = os.environ.get("DEBUG", False)
Expand Down Expand Up @@ -60,21 +59,25 @@ def main():
logger.info(f"got route from {config.config.routeConfig}")


with RemoteServiceDiscoveryService((address, port)) as rsd:
with DvtSecureSocketProxyService(rsd) as dvt:
with open_remote_service_discovery(address, port) as rsd:
with open_location_session(rsd) as location_client:
try:
print(f"已开始模拟跑步,速度大约为 {config.config.v} m/s")
print("会无限循环,按 Ctrl+C 退出")
print("请勿直接关闭窗口,否则无法还原正常定位")
run.run(dvt, loc, config.config.v)
run.run(location_client, loc, config.config.v)
except KeyboardInterrupt:
logger.debug("get KeyboardInterrupt (inner)")
logger.debug(f"Is process alive? {process.is_alive()}")
finally:
logger.debug(f"Is process alive? {process.is_alive()}")
logger.debug("Start to clear location")
location.clear_location(dvt)
logger.info("Location cleared")
try:
location_client.clear()
except Exception:
logger.exception("Failed to clear location")
else:
logger.info("Location cleared")


except KeyboardInterrupt:
Expand All @@ -90,4 +93,4 @@ def main():


if __name__ == "__main__":
main()
main()
4 changes: 3 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pymobiledevice3==2.46.1
# Recommended on Windows: Python 3.11/3.12. Python 3.13 may require MSVC Build Tools for lzfse.
pymobiledevice3>=9.20.0,<10
qh3>=1.9.2,<2
PyYAML==6.0.1
geopy==2.4.1
26 changes: 19 additions & 7 deletions run.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,22 +134,34 @@ def fixLockT(loc: list, v, dt):
t += dt
return fixedLoc

def run1(dvt, loc: list, v, dt=0.2):
def run1(location_client, loc: list, v, dt=0.5):
fixedLoc = fixLockT(loc, v, dt)
nList = (5, 6, 7, 8, 9)
n = nList[random.randint(0, len(nList)-1)]
fixedLoc = randLoc(fixedLoc, n=n) # a path will be divided into n parts for random route
clock = time.time()
failures = 0
for i in fixedLoc:
# utils.setLoc(bd09Towgs84(i))
location.set_location(dvt, **bd09Towgs84(i))
while time.time()-clock < dt:
pass
try:
location.set_location(location_client, **bd09Towgs84(i))
failures = 0
except Exception as error:
failures += 1
print(f"定位下发失败,继续尝试 ({failures}/10): {error}")
if failures >= 10:
raise
remaining = dt - (time.time() - clock)
if remaining > 0:
time.sleep(remaining)
clock = time.time()

def run(dvt, loc: list, v, d=15):
def run(location_client, loc: list, v, d=15):
random.seed(time.time())
while True:
vRand = 1000/(1000/v-(2*random.random()-1)*d)
run1(dvt, loc, vRand)
print("跑完一圈了")
run1(location_client, loc, vRand)
refresh_session = getattr(location_client, "refresh_session", None)
if refresh_session is not None:
refresh_session()
print("跑完一圈了")
Loading