diff --git a/README.md b/README.md index 856d7f7c..8c10f559 100644 --- a/README.md +++ b/README.md @@ -6,18 +6,18 @@ - [News](#news) - [Description](#description) - [Installation](#installation) - * [OpenSSL libraries](#openssl-libraries) + - [OpenSSL libraries](#openssl-libraries) - [Usage](#usage) - * [Working with developer tools (iOS >= 17.0)](#working-with-developer-tools-ios--170) - * [Python API](#python-api) - * [Example](#example) + - [Working with developer tools (iOS \>= 17.0)](#working-with-developer-tools-ios--170) + - [Python API](#python-api) + - [Example](#example) - [The bits and bytes](#the-bits-and-bytes) - * [Lockdown services](#lockdown-services) - + [Implemented services](#implemented-services) - + [Un-implemented services](#un-implemented-services) - + [Sending your own messages](#sending-your-own-messages) - - [Lockdown messages](#lockdown-messages) - - [Instruments messages](#instruments-messages) + - [Lockdown services](#lockdown-services) + - [Implemented services](#implemented-services) + - [Un-implemented services](#un-implemented-services) + - [Sending your own messages](#sending-your-own-messages) + - [Lockdown messages](#lockdown-messages) + - [Instruments messages](#instruments-messages) - [Contributing](#contributing) - [Useful info](#useful-info) @@ -328,6 +328,8 @@ There is A LOT you may do on the device using `pymobiledevice3`. This is just a * `pymobiledevice3 developer dvt simulate-location set --rsd HOST PORT -- lat long` * Play a .GPX file: * `pymobiledevice3 developer dvt simulate-location play route.gpx` + * Add random timing noise between -500 and 500ms on the time between two points in the GPX file: + * `pymobiledevice3 developer dvt simulate-location play route.gpx 500` * Clear the simulated location: * `pymobiledevice3 developer dvt simulate-location clear` * Taking a screenshot from the device: diff --git a/pymobiledevice3/cli/developer.py b/pymobiledevice3/cli/developer.py index 86754958..e20e7018 100644 --- a/pymobiledevice3/cli/developer.py +++ b/pymobiledevice3/cli/developer.py @@ -772,10 +772,11 @@ def simulate_location_set(service_provider: LockdownClient, latitude, longitude) @simulate_location.command('play', cls=Command) @click.argument('filename', type=click.Path(exists=True, file_okay=True, dir_okay=False)) +@click.argument('timing_randomness_range', type=click.INT) @click.option('--disable-sleep', is_flag=True, default=False) -def simulate_location_play(service_provider: LockdownClient, filename, disable_sleep): +def simulate_location_play(service_provider: LockdownClient, filename, timing_randomness_range, disable_sleep): """ play a .gpx file """ - DtSimulateLocation(service_provider).play_gpx_file(filename, disable_sleep=disable_sleep) + DtSimulateLocation(service_provider).play_gpx_file(filename, timing_randomness_range, disable_sleep=disable_sleep) @developer.group('accessibility') @@ -1030,11 +1031,12 @@ def dvt_simulate_location_set(service_provider: LockdownClient, latitude, longit @dvt_simulate_location.command('play', cls=Command) @click.argument('filename', type=click.Path(exists=True, file_okay=True, dir_okay=False)) +@click.argument('timing_randomness_range', type=click.INT, default=0) @click.option('--disable-sleep', is_flag=True, default=False) -def dvt_simulate_location_play(service_provider: LockdownClient, filename: str, disable_sleep: bool) -> None: +def dvt_simulate_location_play(service_provider: LockdownClient, filename: str, timing_randomness_range: int, disable_sleep: bool) -> None: """ play a .gpx file """ with DvtSecureSocketProxyService(service_provider) as dvt: - LocationSimulation(dvt).play_gpx_file(filename, disable_sleep=disable_sleep) + LocationSimulation(dvt).play_gpx_file(filename, disable_sleep=disable_sleep, timing_randomness_range=timing_randomness_range) OSUTILS.wait_return() diff --git a/pymobiledevice3/services/dvt/instruments/location_simulation_base.py b/pymobiledevice3/services/dvt/instruments/location_simulation_base.py index 277b8797..2832091d 100644 --- a/pymobiledevice3/services/dvt/instruments/location_simulation_base.py +++ b/pymobiledevice3/services/dvt/instruments/location_simulation_base.py @@ -1,4 +1,5 @@ import logging +import random import time from abc import abstractmethod @@ -17,11 +18,12 @@ def set(self, latitude: float, longitude: float) -> None: def clear(self) -> None: pass - def play_gpx_file(self, filename: str, disable_sleep: bool = False): + def play_gpx_file(self, filename: str, disable_sleep: bool = False, timing_randomness_range: int = 0): with open(filename) as f: gpx = gpxpy.parse(f) last_time = None + gpx_timing_noise = None for track in gpx.tracks: for segment in track.segments: for point in segment.points: @@ -29,7 +31,12 @@ def play_gpx_file(self, filename: str, disable_sleep: bool = False): duration = (point.time - last_time).total_seconds() if duration >= 0: if not disable_sleep: - self.logger.info(f'waiting for {duration}s') + + if timing_randomness_range: + gpx_timing_noise = random.randint(-timing_randomness_range, timing_randomness_range) / 1000 + duration += gpx_timing_noise + + self.logger.info(f'waiting for {duration:.3f}s') time.sleep(duration) last_time = point.time self.logger.info(f'set location to {point.latitude} {point.longitude}')