reverse geocode async
This commit is contained in:
@@ -11,9 +11,7 @@ import random
|
||||
import math
|
||||
import socketio
|
||||
from contextlib import asynccontextmanager, suppress
|
||||
from geopy.geocoders import Nominatim
|
||||
from geopy.extra.rate_limiter import RateLimiter
|
||||
|
||||
from typing import Optional, Dict
|
||||
from dotenv import load_dotenv
|
||||
|
||||
with warnings.catch_warnings():
|
||||
@@ -21,7 +19,7 @@ with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", category=UserWarning)
|
||||
import fastapi
|
||||
import uvicorn
|
||||
from fastapi import FastAPI
|
||||
from fastapi import FastAPI, APIRouter
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.responses import FileResponse
|
||||
@@ -56,8 +54,14 @@ from pymobiledevice3.services.dvt.instruments.dvt_provider import DvtProvider
|
||||
from pymobiledevice3.tunneld.server import TunneldCore, TunnelTask
|
||||
|
||||
from .icloud_monitor import FindMyMonitor
|
||||
from .models import *
|
||||
from .models import (
|
||||
SimulationRequestData,
|
||||
SimulationRequestResponseData,
|
||||
iCloudLocationData,
|
||||
LatLng
|
||||
)
|
||||
from .json_formatter import JsonFormatter, handler, root_logger, logger
|
||||
from .geo_cache import AsyncReverseGeocoder
|
||||
|
||||
load_dotenv()
|
||||
|
||||
@@ -88,7 +92,8 @@ DVT_CONNECT_TIMEOUT_SECONDS = 20
|
||||
class LocationSimulationState:
|
||||
def __init__(self):
|
||||
self.connected_clients: set[str] = set()
|
||||
self.current_location: Optional[Dict[str, SimulationRequestResponseData]] = None
|
||||
self.current_location: Optional[Dict[str,
|
||||
SimulationRequestResponseData]] = None
|
||||
self.device_name: Optional[str] = os.getenv("SELECTED_DEVICE_NAME")
|
||||
self.fmf_location: Optional[iCloudLocationData] = None
|
||||
self.fmf_queue: asyncio.Queue = asyncio.Queue()
|
||||
@@ -115,8 +120,7 @@ class LocationSimulationState:
|
||||
self.test_mode: bool = os.getenv("TEST_MODE", "True").lower() == "true"
|
||||
self.tunnel: Optional[RemoteServiceDiscoveryService] = None
|
||||
self.udid: Optional[str] = None
|
||||
self.geolocator = Nominatim(user_agent="pymd3_location_sim")
|
||||
self.reverse_geocode = RateLimiter(self.geolocator.reverse, min_delay_seconds=1)
|
||||
self.reverse_geocode = AsyncReverseGeocoder()
|
||||
|
||||
|
||||
class TunneldRunnerSio:
|
||||
@@ -134,7 +138,17 @@ class TunneldRunnerSio:
|
||||
usbmux_monitor: bool = True,
|
||||
mobdev2_monitor: bool = True,
|
||||
) -> None:
|
||||
instance = cls(
|
||||
# instance = cls(
|
||||
# host,
|
||||
# port,
|
||||
# protocol=protocol,
|
||||
# usb_monitor=usb_monitor,
|
||||
# wifi_monitor=wifi_monitor,
|
||||
# usbmux_monitor=usbmux_monitor,
|
||||
# mobdev2_monitor=mobdev2_monitor,
|
||||
# context=context,)
|
||||
# asyncio.run(instance._run_app())
|
||||
cls(
|
||||
host,
|
||||
port,
|
||||
protocol=protocol,
|
||||
@@ -142,8 +156,7 @@ class TunneldRunnerSio:
|
||||
wifi_monitor=wifi_monitor,
|
||||
usbmux_monitor=usbmux_monitor,
|
||||
mobdev2_monitor=mobdev2_monitor,
|
||||
context=context,)
|
||||
asyncio.run(instance._run_app())
|
||||
context=context)._run_app()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -176,8 +189,8 @@ class TunneldRunnerSio:
|
||||
"127.0.0.1" if host in ("0.0.0.0", "::") else host,
|
||||
port,
|
||||
)
|
||||
self._vue_app = FastAPI()
|
||||
self._app = FastAPI(
|
||||
self._app = APIRouter()
|
||||
self._vue_app = FastAPI(
|
||||
title="iOS Device Management API",
|
||||
lifespan=lifespan,
|
||||
cors_allowed_origins="*",
|
||||
@@ -194,6 +207,7 @@ class TunneldRunnerSio:
|
||||
usbmux_monitor=usbmux_monitor,
|
||||
mobdev2_monitor=mobdev2_monitor,
|
||||
)
|
||||
|
||||
async def get_tun(
|
||||
udid: Optional[str] = None, max_retries: int = 10, retry_delay: float = 0.5
|
||||
) -> RemoteServiceDiscoveryService:
|
||||
@@ -231,7 +245,8 @@ class TunneldRunnerSio:
|
||||
)
|
||||
|
||||
try:
|
||||
rsd = RemoteServiceDiscoveryService((tunnel.address, tunnel.port))
|
||||
rsd = RemoteServiceDiscoveryService(
|
||||
(tunnel.address, tunnel.port))
|
||||
await rsd.connect()
|
||||
logger.info(
|
||||
"Connected to local tunnel at %s:%s after %s retries",
|
||||
@@ -257,8 +272,6 @@ class TunneldRunnerSio:
|
||||
|
||||
raise TunneldConnectionError()
|
||||
|
||||
|
||||
|
||||
async def get_device_name():
|
||||
if self.context.tunnel is None:
|
||||
await get_tun()
|
||||
@@ -281,31 +294,29 @@ class TunneldRunnerSio:
|
||||
return active
|
||||
|
||||
async def handle_tunnel_drop(disconnected: list[dict]) -> None:
|
||||
disconnected_udids = {d.get("udid") for d in disconnected if d.get("udid")}
|
||||
disconnected_udids = {d.get("udid")
|
||||
for d in disconnected if d.get("udid")}
|
||||
if not disconnected_udids:
|
||||
return
|
||||
|
||||
current_active = collect_active_tunnels()
|
||||
active_udids = {d.get("udid") for d in current_active.values() if d.get("udid")}
|
||||
active_udids = {d.get("udid")
|
||||
for d in current_active.values() if d.get("udid")}
|
||||
primary_disconnected = self.context.udid in disconnected_udids if self.context.udid else False
|
||||
no_tunnels_left = len(current_active) == 0
|
||||
if not primary_disconnected and not no_tunnels_left:
|
||||
return
|
||||
|
||||
logger.warning(
|
||||
"Tunnel drop detected. primary_udid=%s disconnected_udids=%s active_udids=%s",
|
||||
self.context.udid,
|
||||
sorted(disconnected_udids),
|
||||
sorted(active_udids),
|
||||
)
|
||||
|
||||
if self.context.tunnel is not None:
|
||||
with suppress(Exception):
|
||||
await self.context.tunnel.close()
|
||||
self.context.tunnel = None
|
||||
if no_tunnels_left:
|
||||
self.context.udid = None
|
||||
|
||||
if self.context.simulation_active:
|
||||
await pause_simulation_queue()
|
||||
await self.context.sio.emit(
|
||||
@@ -337,10 +348,8 @@ class TunneldRunnerSio:
|
||||
current = collect_active_tunnels()
|
||||
added_keys = set(current.keys()) - set(previous.keys())
|
||||
removed_keys = set(previous.keys()) - set(current.keys())
|
||||
|
||||
added = [current[k] for k in sorted(added_keys)]
|
||||
removed = [previous[k] for k in sorted(removed_keys)]
|
||||
|
||||
for item in added:
|
||||
logger.info(
|
||||
"Tunnel discovered interface=%s udid=%s address=%s port=%s transport=%s",
|
||||
@@ -351,7 +360,8 @@ class TunneldRunnerSio:
|
||||
item.get("transport"),
|
||||
)
|
||||
await safe_sio_emit("tunnel_device_connected", item)
|
||||
logger.info(f"Current udid: %s, new udid: %s", self.context.udid, item.get("udid"))
|
||||
logger.info(f"Current udid: %s, new udid: %s",
|
||||
self.context.udid, item.get("udid"))
|
||||
if self.context.udid is None:
|
||||
self.context.udid = item.get("udid")
|
||||
device_name = await get_device_name()
|
||||
@@ -438,7 +448,8 @@ class TunneldRunnerSio:
|
||||
)
|
||||
data = {"status": "started", "message": "Simulation started"}
|
||||
else:
|
||||
data = {"status": "error", "message": "Simulation already running"}
|
||||
data = {"status": "error",
|
||||
"message": "Simulation already running"}
|
||||
return data
|
||||
|
||||
async def start_queue_worker():
|
||||
@@ -568,7 +579,7 @@ class TunneldRunnerSio:
|
||||
try:
|
||||
delay = parse_delay_seconds(delay)
|
||||
except ValueError as e:
|
||||
return {"status": "error","command": "add", "message": str(e) }
|
||||
return {"status": "error", "command": "add", "message": str(e)}
|
||||
if latitude is not None and longitude is not None:
|
||||
logger.info(
|
||||
"Adding location %s (%s, %s) with %s delay to the queue",
|
||||
@@ -579,22 +590,24 @@ class TunneldRunnerSio:
|
||||
)
|
||||
accrued_delay = 0
|
||||
if self.context.simulation_queue_data and len(self.context.simulation_queue_order) > 1:
|
||||
current_index = get_item_index(self.context.loc_id) if self.context.loc_id else 0
|
||||
current_index = get_item_index(
|
||||
self.context.loc_id) if self.context.loc_id else 0
|
||||
remaining_items = self.context.simulation_queue_order[current_index + 1:]
|
||||
accrued_delay = sum(parse_delay_seconds(self.context.simulation_queue_data[loc_id]['delay']) for loc_id in remaining_items if loc_id in self.context.simulation_queue_data)
|
||||
accrued_delay = accrued_delay + parse_delay_seconds(self.context.next_move)
|
||||
accrued_delay = sum(parse_delay_seconds(
|
||||
self.context.simulation_queue_data[loc_id]['delay']) for loc_id in remaining_items if loc_id in self.context.simulation_queue_data)
|
||||
accrued_delay = accrued_delay + \
|
||||
parse_delay_seconds(self.context.next_move)
|
||||
|
||||
now_time = datetime.now(timezone.utc)
|
||||
new_time = (
|
||||
now_time
|
||||
+ timedelta(seconds=accrued_delay)
|
||||
+ timedelta(seconds=delay)
|
||||
now_time
|
||||
+ timedelta(seconds=accrued_delay)
|
||||
+ timedelta(seconds=delay)
|
||||
)
|
||||
start_time = new_time.isoformat()
|
||||
coords = f"{latitude}, {longitude}"
|
||||
rev_geocode = self.context.reverse_geocode(coords)
|
||||
rev_geocode = await self.context.reverse_geocode.get_address(latitude, longitude)
|
||||
if rev_geocode:
|
||||
address = rev_geocode.address
|
||||
address = rev_geocode
|
||||
else:
|
||||
address = f"{latitude}, {longitude}"
|
||||
location_item = {
|
||||
@@ -616,7 +629,8 @@ class TunneldRunnerSio:
|
||||
logger.info("Location %s added to the queue", loc_id)
|
||||
else:
|
||||
logger.error("Invalid location data: %s", data)
|
||||
resp = {"status": "error", "message": "Invalid location data", "data": data}
|
||||
resp = {"status": "error",
|
||||
"message": "Invalid location data", "data": data}
|
||||
return resp
|
||||
|
||||
async def start_icloud_monitor():
|
||||
@@ -730,9 +744,11 @@ class TunneldRunnerSio:
|
||||
new_delay = self.context.next_move or 0
|
||||
now_time = datetime.now(timezone.utc)
|
||||
for item in remaining_items:
|
||||
item_delay = parse_delay_seconds(self.context.simulation_queue_data[item].get("delay")) or 0
|
||||
item_delay = parse_delay_seconds(
|
||||
self.context.simulation_queue_data[item].get("delay")) or 0
|
||||
new_delay += item_delay
|
||||
new_time = (now_time + timedelta(seconds=new_delay)).isoformat()
|
||||
new_time = (
|
||||
now_time + timedelta(seconds=new_delay)).isoformat()
|
||||
self.context.simulation_queue_data[item].start = new_time
|
||||
update_queue_data()
|
||||
|
||||
@@ -746,8 +762,8 @@ class TunneldRunnerSio:
|
||||
"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="/" )
|
||||
|
||||
self.context.sio.emit("queue_data_update", {
|
||||
"data": data}, namespace="/")
|
||||
|
||||
async def empty_simulation_queue():
|
||||
"""Empties all items from an asyncio.Queue."""
|
||||
@@ -763,14 +779,13 @@ class TunneldRunnerSio:
|
||||
break
|
||||
clear_items()
|
||||
|
||||
|
||||
def add_item(item_id, payload):
|
||||
self.context.simulation_queue_data[item_id] = payload
|
||||
self.context.simulation_queue_order.append(item_id)
|
||||
|
||||
def remove_item(item_id):
|
||||
if item_id in self.context.simulation_queue_order:
|
||||
# self.context.simulation_queue_order.remove(item_id)
|
||||
# self.context.simulation_queue_order.remove(item_id)
|
||||
self.context.simulation_queue_data[item_id]["status"] = "deleted"
|
||||
|
||||
def clear_item(item_id):
|
||||
@@ -843,7 +858,8 @@ class TunneldRunnerSio:
|
||||
try:
|
||||
await asyncio.wait_for(self.context.simulation_task, timeout=5)
|
||||
except TimeoutError:
|
||||
logger.warning("Simulation worker did not stop in time; canceling task")
|
||||
logger.warning(
|
||||
"Simulation worker did not stop in time; canceling task")
|
||||
self.context.simulation_task.cancel()
|
||||
with suppress(asyncio.CancelledError):
|
||||
await self.context.simulation_task
|
||||
@@ -873,10 +889,11 @@ class TunneldRunnerSio:
|
||||
|
||||
def toggle_test_mode() -> dict:
|
||||
self.context.test_mode = not self.context.test_mode
|
||||
return {"test_mode": self.context.test_mode }
|
||||
return {"test_mode": self.context.test_mode}
|
||||
|
||||
def get_status() -> dict:
|
||||
current_item = self.context.simulation_queue_data.get(self.context.loc_id) if self.context.loc_id else None
|
||||
current_item = self.context.simulation_queue_data.get(
|
||||
self.context.loc_id) if self.context.loc_id else None
|
||||
current_start = (
|
||||
current_item.get("start")
|
||||
if isinstance(current_item, dict)
|
||||
@@ -893,11 +910,11 @@ class TunneldRunnerSio:
|
||||
"device_name": self.context.device_name,
|
||||
"fmf_location": self.context.fmf_location,
|
||||
"icloud": {
|
||||
"consumer_queue": self.context.fmf_queue.qsize() if self.context.fmf_queue else 0,
|
||||
"consumer_task": self.context.icloud_consumer_task.done() if self.context.icloud_consumer_task else False,
|
||||
"monitor_task": self.context.icloud_monitor_task.done() if self.context.icloud_monitor_task else False,
|
||||
"monitor_enabled": self.context.icloud_monitor_enabled,
|
||||
"monitor_running": is_icloud_monitor_running(),
|
||||
"consumer_queue": self.context.fmf_queue.qsize() if self.context.fmf_queue else 0,
|
||||
"consumer_task": self.context.icloud_consumer_task.done() if self.context.icloud_consumer_task else False,
|
||||
"monitor_task": self.context.icloud_monitor_task.done() if self.context.icloud_monitor_task else False,
|
||||
"monitor_enabled": self.context.icloud_monitor_enabled,
|
||||
"monitor_running": is_icloud_monitor_running(),
|
||||
},
|
||||
"tunnel_watcher_running": True if self.context.tunnel_watcher_task and not self.context.tunnel_watcher_task.done() else False,
|
||||
"next_move": self.context.next_move,
|
||||
@@ -916,6 +933,7 @@ class TunneldRunnerSio:
|
||||
return data
|
||||
|
||||
import numpy as np
|
||||
|
||||
def add_gps_noise(lat, lon, std_dev_meters=5):
|
||||
"""
|
||||
Simulates GPS noise by adding Gaussian noise to coordinates.
|
||||
@@ -927,7 +945,8 @@ class TunneldRunnerSio:
|
||||
|
||||
# Convert meters to degrees
|
||||
lat_diff = (std_dev_meters / earth_radius) * (180 / np.pi)
|
||||
lon_diff = (std_dev_meters / (earth_radius * np.cos(np.radians(lat)))) * (180 / np.pi)
|
||||
lon_diff = (std_dev_meters / (earth_radius *
|
||||
np.cos(np.radians(lat)))) * (180 / np.pi)
|
||||
|
||||
# Generate Gaussian noise
|
||||
noised_lat = lat + np.random.normal(0, lat_diff)
|
||||
@@ -935,7 +954,6 @@ class TunneldRunnerSio:
|
||||
|
||||
return noised_lat, noised_lon
|
||||
|
||||
|
||||
""" FastAPI HTTP Functions"""
|
||||
|
||||
def generate_http_response(
|
||||
@@ -947,7 +965,6 @@ class TunneldRunnerSio:
|
||||
content=json.dumps(jsonable_encoder(data)),
|
||||
)
|
||||
|
||||
|
||||
""" Device Functions """
|
||||
|
||||
@self._app.get("/device/name")
|
||||
@@ -956,7 +973,6 @@ class TunneldRunnerSio:
|
||||
device_name = await get_device_name()
|
||||
return generate_http_response(device_name)
|
||||
|
||||
|
||||
@self._app.get("/device/info")
|
||||
async def device_info():
|
||||
"""Get device information"""
|
||||
@@ -970,10 +986,12 @@ class TunneldRunnerSio:
|
||||
lockdown = await create_using_usbmux(
|
||||
serial=active_tunnel.udid, autopair=False
|
||||
)
|
||||
tunnels[active_tunnel.udid] = iterate_multidim(lockdown.all_values)
|
||||
tunnels[active_tunnel.udid] = iterate_multidim(
|
||||
lockdown.all_values)
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"Failed to create lockdown session for device {active_tunnel.udid}: {e}"
|
||||
f"Failed to create lockdown session for device {
|
||||
active_tunnel.udid}: {e}"
|
||||
)
|
||||
continue
|
||||
return tunnels
|
||||
@@ -1001,7 +1019,8 @@ class TunneldRunnerSio:
|
||||
async def shutdown() -> fastapi.Response:
|
||||
"""Shutdown Tunneld"""
|
||||
os.kill(os.getpid(), signal.SIGINT)
|
||||
data = {"operation": "shutdown", "data": True, "message": "Server shutting down..."}
|
||||
data = {"operation": "shutdown", "data": True,
|
||||
"message": "Server shutting down..."}
|
||||
return generate_http_response(data)
|
||||
|
||||
@self._app.get("/clear-tunnels")
|
||||
@@ -1027,7 +1046,6 @@ class TunneldRunnerSio:
|
||||
}
|
||||
return generate_http_response(data)
|
||||
|
||||
|
||||
@self._app.get("/hello")
|
||||
async def hello() -> fastapi.Response:
|
||||
data = {"message": "Hello, I'm alive"}
|
||||
@@ -1157,11 +1175,8 @@ class TunneldRunnerSio:
|
||||
}
|
||||
return generate_http_response(data)
|
||||
|
||||
|
||||
|
||||
""" iCloud Monitor"""
|
||||
|
||||
|
||||
@self._app.get("/icloud-monitor/start")
|
||||
async def app_start_icloud_monitor() -> fastapi.Response:
|
||||
await start_icloud_monitor()
|
||||
@@ -1196,7 +1211,6 @@ class TunneldRunnerSio:
|
||||
data = await refresh_icloud_location()
|
||||
return generate_http_response(data)
|
||||
|
||||
|
||||
"""Simulation Functions"""
|
||||
""" start, add, clear, pause, resume, end, status """
|
||||
|
||||
@@ -1205,7 +1219,6 @@ class TunneldRunnerSio:
|
||||
data = await start_simulation_queue()
|
||||
return generate_http_response(data)
|
||||
|
||||
|
||||
@self._app.post("/simulation/add")
|
||||
async def app_add_location(data: SimulationRequestData) -> fastapi.Response:
|
||||
"""Add a location to the simulation queue"""
|
||||
@@ -1247,14 +1260,14 @@ class TunneldRunnerSio:
|
||||
before_toggle = self.context.test_mode
|
||||
data = toggle_test_mode()
|
||||
data['status'] = "OK"
|
||||
data['message'] = f"Test mode toggled from {before_toggle} to {self.context.test_mode}"
|
||||
data['message'] = f"Test mode toggled from {
|
||||
before_toggle} to {self.context.test_mode}"
|
||||
return generate_http_response(data)
|
||||
|
||||
|
||||
"""Status Functions"""
|
||||
|
||||
@self._app.get("/status/rsd")
|
||||
async def rsd_info():
|
||||
async def app_rsd_info():
|
||||
"""Get rsd information"""
|
||||
rsd_info = {}
|
||||
if self.context.tunnel is None:
|
||||
@@ -1263,15 +1276,29 @@ class TunneldRunnerSio:
|
||||
rsd_info = self.context.tunnel.peer_info
|
||||
return generate_http_response(rsd_info)
|
||||
|
||||
|
||||
@self._app.get("/status/context")
|
||||
async def app_context_status() -> fastapi.Response:
|
||||
data = get_status()
|
||||
return generate_http_response(data)
|
||||
|
||||
|
||||
|
||||
|
||||
@self._app.post("/rev_geocode")
|
||||
async def app_proxy_osm(data: LatLng):
|
||||
logger.info("OSM Proxy Request, data: %s", data)
|
||||
latitude = (
|
||||
data.get("latitude")
|
||||
if isinstance(data, dict)
|
||||
else getattr(data, "latitude", None)
|
||||
)
|
||||
longitude = (
|
||||
data.get("longitude")
|
||||
if isinstance(data, dict)
|
||||
else getattr(data, "longitude", None)
|
||||
)
|
||||
if latitude and longitude:
|
||||
coords = f"{latitude}, {longitude}"
|
||||
rev_geocode = await self.context.reverse_geocode.get_address(latitude, longitude)
|
||||
logger.info("Reverse Geocoded %s to %s", coords, rev_geocode)
|
||||
return generate_http_response(rev_geocode)
|
||||
|
||||
""" Socket.IO Functions"""
|
||||
|
||||
@@ -1302,7 +1329,8 @@ class TunneldRunnerSio:
|
||||
@self.context.sio.event
|
||||
async def request_update(sid):
|
||||
status_update = jsonable_encoder(get_status())
|
||||
logger.info("Update request from %s sending %s", sid, status_update)
|
||||
logger.info("Update request from %s sending %s",
|
||||
sid, status_update)
|
||||
return status_update
|
||||
|
||||
@self.context.sio.event
|
||||
@@ -1413,12 +1441,14 @@ class TunneldRunnerSio:
|
||||
}
|
||||
case "end":
|
||||
""" End the simulation queue"""
|
||||
logger.info("End location simulation request from %s", sid)
|
||||
logger.info(
|
||||
"End location simulation request from %s", sid)
|
||||
data = await end_simulation_queue()
|
||||
return data
|
||||
case "start":
|
||||
""" Start the simulation queue"""
|
||||
logger.info("Start location simulation request from %s", sid)
|
||||
logger.info(
|
||||
"Start location simulation request from %s", sid)
|
||||
data = await start_simulation_queue()
|
||||
return data
|
||||
case _:
|
||||
@@ -1486,7 +1516,8 @@ class TunneldRunnerSio:
|
||||
if isinstance(data, dict)
|
||||
else getattr(data, "command", None)
|
||||
)
|
||||
logger.info("Tunneld Control command: %s requested from %s", command, sid)
|
||||
logger.info(
|
||||
"Tunneld Control command: %s requested from %s", command, sid)
|
||||
match command:
|
||||
case "start":
|
||||
"""Start Tunneld"""
|
||||
@@ -1508,7 +1539,8 @@ class TunneldRunnerSio:
|
||||
|
||||
case "start-watcher":
|
||||
""" Start Tunneld Watcher """
|
||||
logger.info("Start tunneld watcher request from %s: %s", sid, data)
|
||||
logger.info(
|
||||
"Start tunneld watcher request from %s: %s", sid, data)
|
||||
await start_tunnel_watcher()
|
||||
return {
|
||||
"status": "running",
|
||||
@@ -1517,7 +1549,8 @@ class TunneldRunnerSio:
|
||||
|
||||
case "end-watcher":
|
||||
""" End Tunneld Watcher """
|
||||
logger.info("End tunneld watcher request from %s: %s", sid, data)
|
||||
logger.info(
|
||||
"End tunneld watcher request from %s: %s", sid, data)
|
||||
await end_tunnel_watcher()
|
||||
return {
|
||||
"status": "stopped",
|
||||
@@ -1526,7 +1559,8 @@ class TunneldRunnerSio:
|
||||
|
||||
case "shutdown":
|
||||
"""Shutdown Tunneld"""
|
||||
logger.info("Shutdown tunneld request from %s: %s", sid, data)
|
||||
logger.info(
|
||||
"Shutdown tunneld request from %s: %s", sid, data)
|
||||
try:
|
||||
os.kill(os.getpid(), signal.SIGINT)
|
||||
return {
|
||||
@@ -1562,7 +1596,8 @@ class TunneldRunnerSio:
|
||||
|
||||
case "cancel":
|
||||
"""Cancel a tunnel"""
|
||||
logger.info("Canceling tunnel request from %s: %s", sid, data)
|
||||
logger.info(
|
||||
"Canceling tunnel request from %s: %s", sid, data)
|
||||
try:
|
||||
udid = (
|
||||
data.get("udid")
|
||||
@@ -1593,21 +1628,22 @@ class TunneldRunnerSio:
|
||||
"message": f"Unknown operation: {command}",
|
||||
}
|
||||
|
||||
self._vue_app.include_router(self._app, prefix="/api")
|
||||
self._vue_app.mount(
|
||||
"/assets", StaticFiles(directory="../../front-end/dist/spa/assets", html=True), name="vue")
|
||||
|
||||
self._vue_app.mount("/assets", StaticFiles(directory="../../front-end/dist/spa/assets", html=True), name="vue")
|
||||
@self._vue_app.get("/{full_path:path}")
|
||||
async def serve_vue_app(full_path: str):
|
||||
async def serve_vue_app(full_path: str):
|
||||
return FileResponse("../../front-end/dist/spa/index.html")
|
||||
|
||||
def _run_app(self) -> None:
|
||||
# api = uvicorn.Server(uvicorn.Config(self._app, host=self.host, port=49151, log_level="info"))
|
||||
# vue = uvicorn.Server(uvicorn.Config(self._asgi_app, host=self.host, port=8087, log_level="info"))
|
||||
# await asyncio.gather(api.serve(), vue.serve())
|
||||
|
||||
async def _run_app(self) -> None:
|
||||
api = uvicorn.Server(uvicorn.Config(self._app, host=self.host, port=49151, log_level="info"))
|
||||
vue = uvicorn.Server(uvicorn.Config(self._asgi_app, host=self.host, port=8087, log_level="info"))
|
||||
await asyncio.gather(api.serve(), vue.serve())
|
||||
|
||||
# uvicorn.run(
|
||||
# self._asgi_app, host=self.host, port=self.port, loop="asyncio", workers=1
|
||||
# )
|
||||
uvicorn.run(
|
||||
self._asgi_app, host=self.host, port=self.port, loop="asyncio", workers=1
|
||||
)
|
||||
|
||||
|
||||
class LocationSimulationQueue(LocationSimulation):
|
||||
@@ -1625,7 +1661,8 @@ class LocationSimulationQueue(LocationSimulation):
|
||||
cos_lat = math.cos(math.radians(lat))
|
||||
if abs(cos_lat) < 1e-6:
|
||||
cos_lat = 1e-6
|
||||
lon_sigma_deg = (std_dev_meters / (earth_radius * cos_lat)) * (180.0 / math.pi)
|
||||
lon_sigma_deg = (std_dev_meters / (earth_radius *
|
||||
cos_lat)) * (180.0 / math.pi)
|
||||
noised_lat = lat + random.gauss(0.0, lat_sigma_deg)
|
||||
noised_lon = lon + random.gauss(0.0, lon_sigma_deg)
|
||||
return noised_lat, noised_lon
|
||||
@@ -1699,7 +1736,8 @@ class LocationSimulationQueue(LocationSimulation):
|
||||
new_delay = 0 if new_delay is None else new_delay
|
||||
new_start = location_item.get("start")
|
||||
|
||||
current_location_item = self.context.simulation_queue_data.get(self.context.loc_id)
|
||||
current_location_item = self.context.simulation_queue_data.get(
|
||||
self.context.loc_id)
|
||||
current_latitude = (
|
||||
current_location_item.get("latitude")
|
||||
if isinstance(current_location_item, dict)
|
||||
@@ -1750,9 +1788,11 @@ class LocationSimulationQueue(LocationSimulation):
|
||||
if self.context.simulation_queue_state == "SHUTDOWN":
|
||||
self.context.simulation_queue.task_done()
|
||||
break
|
||||
self.context.simulation_queue_data[loc_id]["start"] = datetime.now(timezone.utc).isoformat()
|
||||
self.context.simulation_queue_data[loc_id]["start"] = datetime.now(
|
||||
timezone.utc).isoformat()
|
||||
if self.context.loc_id is not None:
|
||||
self.context.simulation_queue_data[self.context.loc_id]["end"] = datetime.now(timezone.utc).isoformat()
|
||||
self.context.simulation_queue_data[self.context.loc_id]["end"] = datetime.now(
|
||||
timezone.utc).isoformat()
|
||||
update_queue_data()
|
||||
|
||||
await self._stop_noise_task()
|
||||
@@ -1761,7 +1801,8 @@ class LocationSimulationQueue(LocationSimulation):
|
||||
self.context.latitude = new_latitude
|
||||
self.context.longitude = new_longitude
|
||||
if self.context.simulation_noise:
|
||||
self._start_noise_task(loc_id, new_latitude, new_longitude)
|
||||
self._start_noise_task(
|
||||
loc_id, new_latitude, new_longitude)
|
||||
await self.context.sio.emit(
|
||||
"simulation_status",
|
||||
{
|
||||
@@ -1850,7 +1891,8 @@ class LocationSimulationTestQueue(LocationSimulationBase):
|
||||
new_delay = 0 if new_delay is None else new_delay
|
||||
new_start = location_item.get("start")
|
||||
|
||||
current_location_item = self.context.simulation_queue_data.get(self.context.loc_id)
|
||||
current_location_item = self.context.simulation_queue_data.get(
|
||||
self.context.loc_id)
|
||||
current_latitude = (
|
||||
current_location_item.get("latitude")
|
||||
if isinstance(current_location_item, dict)
|
||||
@@ -1871,7 +1913,7 @@ class LocationSimulationTestQueue(LocationSimulationBase):
|
||||
if new_delay > 0 and not disable_sleep:
|
||||
countdown_delay = int(round(float(new_delay)))
|
||||
if timing_randomness_range > 0:
|
||||
delay = new_delay + random.uniform(
|
||||
new_delay = new_delay + random.uniform(
|
||||
-timing_randomness_range, timing_randomness_range
|
||||
)
|
||||
countdown_delay = int(round(float(new_delay)))
|
||||
@@ -1901,9 +1943,11 @@ class LocationSimulationTestQueue(LocationSimulationBase):
|
||||
if self.context.simulation_queue_state == "SHUTDOWN":
|
||||
self.context.simulation_queue.task_done()
|
||||
break
|
||||
self.context.simulation_queue_data[loc_id]["start"] = datetime.now(timezone.utc).isoformat()
|
||||
self.context.simulation_queue_data[loc_id]["start"] = datetime.now(
|
||||
timezone.utc).isoformat()
|
||||
if self.context.loc_id is not None:
|
||||
self.context.simulation_queue_data[self.context.loc_id]["end"] = datetime.now(timezone.utc).isoformat()
|
||||
self.context.simulation_queue_data[self.context.loc_id]["end"] = datetime.now(
|
||||
timezone.utc).isoformat()
|
||||
await self.set(new_latitude, new_longitude)
|
||||
self.context.loc_id = loc_id
|
||||
self.context.loc_id = loc_id
|
||||
|
||||
Reference in New Issue
Block a user