generated from Grigo/AndroidTemplate
added refference point
This commit is contained in:
+126
-2
@@ -551,6 +551,68 @@ def _metric_stats(values: list[float]) -> dict[str, Any]:
|
||||
}
|
||||
|
||||
|
||||
_TX_PARAM_KEYS = (
|
||||
"frequency_hz",
|
||||
"power_dbm",
|
||||
"spreading_factor",
|
||||
"bandwidth_khz",
|
||||
"code_rate",
|
||||
"preamble_length",
|
||||
"tx_timeout_ms",
|
||||
"crc_enabled",
|
||||
)
|
||||
|
||||
|
||||
def _role_from_row(row: dict[str, Any]) -> Optional[str]:
|
||||
role = row.get("role")
|
||||
if role:
|
||||
return str(role)
|
||||
meta = _json_load(row.get("meta"))
|
||||
if isinstance(meta, dict) and meta.get("role"):
|
||||
return str(meta["role"])
|
||||
return None
|
||||
|
||||
|
||||
def _tx_params_from_meta(meta: Any) -> dict[str, Any]:
|
||||
data = _json_load(meta)
|
||||
if not isinstance(data, dict):
|
||||
return {}
|
||||
return {key: data[key] for key in _TX_PARAM_KEYS if data.get(key) is not None}
|
||||
|
||||
|
||||
def _reference_context(rows: list[dict[str, Any]]) -> dict[str, Any]:
|
||||
tx_params = None
|
||||
tx_device = None
|
||||
rx_position = None
|
||||
roles: set[str] = set()
|
||||
devices: set[str] = set()
|
||||
for row in sorted(rows, key=lambda r: float(r.get("ts") or 0)):
|
||||
role = _role_from_row(row)
|
||||
if role:
|
||||
roles.add(role)
|
||||
device_id = row.get("device_id")
|
||||
if device_id:
|
||||
devices.add(str(device_id))
|
||||
params = _tx_params_from_meta(row.get("meta"))
|
||||
if params and (role == "TX" or tx_params is None):
|
||||
tx_params = params
|
||||
tx_device = device_id
|
||||
if role == "RX" and row.get("lat") is not None and row.get("lon") is not None:
|
||||
rx_position = {
|
||||
"device_id": device_id,
|
||||
"lat": row.get("lat"),
|
||||
"lon": row.get("lon"),
|
||||
"ts": row.get("ts"),
|
||||
}
|
||||
return {
|
||||
"tx_params": tx_params,
|
||||
"tx_device_id": tx_device,
|
||||
"rx_position": rx_position,
|
||||
"roles": sorted(roles),
|
||||
"devices": sorted(devices),
|
||||
}
|
||||
|
||||
|
||||
def _reference_stats(samples: list[dict[str, Any]]) -> dict[str, Any]:
|
||||
per = [_metric_from_meta(s.get("meta"), "per_percent") for s in samples]
|
||||
quality = [_metric_from_meta(s.get("meta"), "rx_quality_percent") for s in samples]
|
||||
@@ -634,13 +696,47 @@ def add_reference_point_samples(
|
||||
def finish_reference_point_session(session_id: int) -> dict[str, Any]:
|
||||
ts = time.time()
|
||||
with _db() as conn:
|
||||
session = conn.execute(
|
||||
"""
|
||||
SELECT id, device_id, started_at, meta
|
||||
FROM reference_point_sessions WHERE id = ?
|
||||
""",
|
||||
(session_id,),
|
||||
).fetchone()
|
||||
if not session:
|
||||
raise ValueError(f"reference point session {session_id} not found")
|
||||
sample_rows = conn.execute(
|
||||
"""
|
||||
SELECT ? AS device_id, ts, lat, lon, rssi, role, meta
|
||||
FROM reference_point_samples
|
||||
WHERE session_id = ?
|
||||
ORDER BY ts ASC
|
||||
""",
|
||||
(session["device_id"], session_id),
|
||||
).fetchall()
|
||||
telemetry_rows = conn.execute(
|
||||
"""
|
||||
SELECT device_id, ts, lat, lon, rssi, role, meta
|
||||
FROM telemetry
|
||||
WHERE source = 'android' AND ts >= ? AND ts <= ?
|
||||
ORDER BY ts ASC
|
||||
LIMIT 1000
|
||||
""",
|
||||
(session["started_at"], ts),
|
||||
).fetchall()
|
||||
meta = _json_load(session["meta"]) if session["meta"] else {}
|
||||
if not isinstance(meta, dict):
|
||||
meta = {}
|
||||
meta["reference_context"] = _reference_context(
|
||||
[dict(r) for r in sample_rows] + [dict(r) for r in telemetry_rows]
|
||||
)
|
||||
cur = conn.execute(
|
||||
"""
|
||||
UPDATE reference_point_sessions
|
||||
SET ended_at = ?, status = 'finished'
|
||||
SET ended_at = ?, status = 'finished', meta = ?
|
||||
WHERE id = ? AND status = 'recording'
|
||||
""",
|
||||
(ts, session_id),
|
||||
(ts, _json_or_none(meta), session_id),
|
||||
)
|
||||
if cur.rowcount == 0:
|
||||
raise ValueError(f"reference point session {session_id} not found or inactive")
|
||||
@@ -711,6 +807,34 @@ def get_reference_point_session(session_id: int) -> dict[str, Any]:
|
||||
result["sample_count"] = len(samples)
|
||||
result["samples"] = samples
|
||||
result["stats"] = _reference_stats(samples)
|
||||
meta = _json_load(result.get("meta"))
|
||||
if not isinstance(meta, dict):
|
||||
meta = {}
|
||||
context = meta.get("reference_context")
|
||||
if not isinstance(context, dict):
|
||||
telemetry_rows = []
|
||||
with _db() as conn:
|
||||
telemetry_rows = conn.execute(
|
||||
"""
|
||||
SELECT device_id, ts, lat, lon, rssi, role, meta
|
||||
FROM telemetry
|
||||
WHERE source = 'android' AND ts >= ? AND ts <= ?
|
||||
ORDER BY ts ASC
|
||||
LIMIT 1000
|
||||
""",
|
||||
(
|
||||
result["started_at"],
|
||||
result["ended_at"] if result["ended_at"] is not None else time.time(),
|
||||
),
|
||||
).fetchall()
|
||||
context = _reference_context(
|
||||
[
|
||||
{"device_id": result["device_id"], **sample}
|
||||
for sample in samples
|
||||
]
|
||||
+ [dict(r) for r in telemetry_rows]
|
||||
)
|
||||
result["reference_context"] = context
|
||||
return result
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user