updates
This commit is contained in:
@@ -18,7 +18,6 @@ from dotenv import load_dotenv
|
||||
with warnings.catch_warnings():
|
||||
# Ignore: "Core Pydantic V1 functionality isn't compatible with Python 3.14 or greater."
|
||||
warnings.simplefilter("ignore", category=UserWarning)
|
||||
warnings.simplefilter("ignore", category=UserWarning)
|
||||
import fastapi
|
||||
import uvicorn
|
||||
from fastapi import FastAPI, APIRouter, Request, Response
|
||||
@@ -53,6 +52,10 @@ from pymobiledevice3.services.dvt.instruments.location_simulation import (
|
||||
LocationSimulation,
|
||||
)
|
||||
from pymobiledevice3.services.dvt.instruments.dvt_provider import DvtProvider
|
||||
try:
|
||||
from pymobiledevice3.services.simulate_location import DtSimulateLocation
|
||||
except Exception:
|
||||
DtSimulateLocation = None
|
||||
from pymobiledevice3.tunneld.server import TunneldCore, TunnelTask
|
||||
|
||||
from .icloud_monitor import FindMyMonitor
|
||||
@@ -575,7 +578,11 @@ class TunneldRunnerSio:
|
||||
logger.exception("Simulation worker crashed")
|
||||
await self.context.sio.emit(
|
||||
"appError",
|
||||
{"type": "simulation_crash", "udid": self.context.udid},
|
||||
{
|
||||
"type": "simulation_crash",
|
||||
"udid": self.context.udid,
|
||||
"error": traceback.format_exc(),
|
||||
},
|
||||
namespace="/",
|
||||
)
|
||||
finally:
|
||||
@@ -891,7 +898,7 @@ class TunneldRunnerSio:
|
||||
if not self.context.test_mode and self.context.tunnel is not None:
|
||||
async with (
|
||||
DvtProvider(self.context.tunnel) as dvt,
|
||||
LocationSimulationQueue(dvt) as locate_simulation,
|
||||
LocationSimulationQueue(dvt, self.context) as locate_simulation,
|
||||
):
|
||||
await locate_simulation.clear()
|
||||
|
||||
@@ -1718,9 +1725,48 @@ class LocationSimulationQueue(LocationSimulation):
|
||||
def __init__(self, dvt, context: LocationSimulationState):
|
||||
super().__init__(dvt)
|
||||
self.context = context
|
||||
self._dt_simulate_location = None
|
||||
self._prefer_dt_simulate_location = False
|
||||
self._noise_task: Optional[asyncio.Task] = None
|
||||
self._noise_loc_id: Optional[str] = None
|
||||
|
||||
async def _get_dt_simulate_location(self):
|
||||
if DtSimulateLocation is None:
|
||||
raise RuntimeError("DtSimulateLocation is not available in this pymobiledevice3 build")
|
||||
if self._dt_simulate_location is None:
|
||||
lockdown = getattr(self.provider, "lockdown", None)
|
||||
if lockdown is None:
|
||||
raise RuntimeError("DVT provider does not expose lockdown provider for fallback simulation")
|
||||
self._dt_simulate_location = DtSimulateLocation(lockdown)
|
||||
return self._dt_simulate_location
|
||||
|
||||
async def set(self, latitude: float, longitude: float) -> None:
|
||||
if not self._prefer_dt_simulate_location:
|
||||
try:
|
||||
await super().set(latitude, longitude)
|
||||
return
|
||||
except Exception:
|
||||
logger.exception(
|
||||
"DVT location set failed; switching to DtSimulateLocation fallback"
|
||||
)
|
||||
self._prefer_dt_simulate_location = True
|
||||
fallback = await self._get_dt_simulate_location()
|
||||
await fallback.set(latitude, longitude)
|
||||
|
||||
async def clear(self) -> None:
|
||||
dvt_clear_error = None
|
||||
if not self._prefer_dt_simulate_location:
|
||||
try:
|
||||
await super().clear()
|
||||
except Exception as e:
|
||||
dvt_clear_error = e
|
||||
logger.warning("DVT location clear failed: %s", e)
|
||||
if self._prefer_dt_simulate_location:
|
||||
fallback = await self._get_dt_simulate_location()
|
||||
await fallback.clear()
|
||||
elif dvt_clear_error is not None:
|
||||
raise dvt_clear_error
|
||||
|
||||
@staticmethod
|
||||
def _add_gps_noise(lat: float, lon: float, std_dev_meters: float = 5.0) -> tuple[float, float]:
|
||||
"""Apply Gaussian jitter in meters and convert to lat/lon deltas."""
|
||||
@@ -1776,6 +1822,18 @@ class LocationSimulationQueue(LocationSimulation):
|
||||
name=f"simulation-noise-{loc_id}",
|
||||
)
|
||||
|
||||
def _update_queue_data(self):
|
||||
data = {
|
||||
"simulation_queue": {
|
||||
"active": self.context.simulation_active,
|
||||
"data": self.context.simulation_queue_data,
|
||||
"order": self.context.simulation_queue_order,
|
||||
"state": self.context.simulation_queue_state,
|
||||
"worker_task": self.context.simulation_task.get_name() if self.context.simulation_task else None,
|
||||
}
|
||||
}
|
||||
self.context.sio.emit("queue_data_update", {"data": data}, namespace="/")
|
||||
|
||||
async def play_queue(
|
||||
self, disable_sleep: bool = False, timing_randomness_range: int = 0
|
||||
) -> None:
|
||||
@@ -1861,7 +1919,7 @@ class LocationSimulationQueue(LocationSimulation):
|
||||
if self.context.loc_id is not None:
|
||||
self.context.simulation_queue_data[self.context.loc_id]["end"] = datetime.now(
|
||||
timezone.utc).isoformat()
|
||||
update_queue_data()
|
||||
self._update_queue_data()
|
||||
|
||||
await self._stop_noise_task()
|
||||
await self.set(new_latitude, new_longitude)
|
||||
|
||||
Reference in New Issue
Block a user