25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 

119 satır
3.7 KiB

  1. import csv
  2. import logging
  3. from typing import Any, Dict, List, Optional
  4. import httpx
  5. log = logging.getLogger(__name__)
  6. def _none_if_empty(v: Any) -> Any:
  7. return None if v in ("", None, 0, "0") else v
  8. def _str_or_none(v: Any) -> Optional[str]:
  9. if v in ("", None):
  10. return None
  11. if isinstance(v, (int, float, bool)):
  12. return str(v)
  13. return v
  14. def _normalize_tracker(row: dict) -> dict:
  15. row = dict(row)
  16. row["floor"] = _none_if_empty(row.get("floor"))
  17. row["building"] = _none_if_empty(row.get("building"))
  18. row["battery"] = _str_or_none(row.get("battery"))
  19. row["temperature"] = _str_or_none(row.get("temperature"))
  20. row["acceleration"] = _str_or_none(row.get("acceleration"))
  21. row["heartRate"] = _str_or_none(row.get("heartRate"))
  22. return row
  23. async def _fetch_algorithm(core_base_url: str, timeout: float) -> Optional[str]:
  24. try:
  25. async with httpx.AsyncClient(timeout=timeout) as client:
  26. resp = await client.get(f"{core_base_url}/reslevis/settings")
  27. if 200 <= resp.status_code < 300:
  28. payload = resp.json()
  29. if isinstance(payload, list) and payload:
  30. value = payload[0].get("current_algorithm")
  31. if value is not None:
  32. return str(value).lower()
  33. except (httpx.RequestError, ValueError):
  34. pass
  35. return None
  36. async def _filter_mode_trackers(
  37. tracker_repo, core_base_url: str, timeout: float
  38. ) -> List[Dict[str, Any]]:
  39. try:
  40. async with httpx.AsyncClient(timeout=timeout) as client:
  41. resp = await client.get(f"{core_base_url}/reslevis/getTrackers")
  42. if 200 <= resp.status_code < 300:
  43. data = resp.json()
  44. if isinstance(data, list):
  45. normalized = [_normalize_tracker(r) for r in data if isinstance(r, dict)]
  46. tracker_repo._write_all(normalized)
  47. return normalized
  48. except (httpx.RequestError, ValueError):
  49. pass
  50. return tracker_repo.list()
  51. def _read_infer_positions(infer_csv_path: str) -> Dict[str, Dict[str, Optional[float]]]:
  52. positions: Dict[str, Dict[str, Optional[float]]] = {}
  53. try:
  54. with open(infer_csv_path, newline="") as f:
  55. reader = csv.DictReader(f, delimiter=";")
  56. for row in reader:
  57. mac = (row.get("mac") or "").strip().lower()
  58. if not mac:
  59. continue
  60. try:
  61. positions[mac] = {
  62. "x": int(row["x"]) if row.get("x") not in (None, "") else None,
  63. "y": int(row["y"]) if row.get("y") not in (None, "") else None,
  64. }
  65. except (KeyError, ValueError):
  66. continue
  67. except OSError:
  68. log.warning("BLE-AI infer CSV not found: %s", infer_csv_path)
  69. return positions
  70. def _ai_mode_trackers(
  71. tracker_repo, infer_csv_path: str
  72. ) -> List[Dict[str, Any]]:
  73. trackers = tracker_repo.list()
  74. positions = _read_infer_positions(infer_csv_path)
  75. if not positions:
  76. return trackers
  77. result = []
  78. for tracker in trackers:
  79. t = dict(tracker)
  80. mac = (t.get("mac") or "").strip().lower()
  81. if mac and mac in positions:
  82. t["x"] = positions[mac]["x"]
  83. t["y"] = positions[mac]["y"]
  84. result.append(t)
  85. return result
  86. async def get_mode_aware_trackers(
  87. tracker_repo,
  88. core_base_url: str,
  89. infer_csv_path: str,
  90. timeout: float,
  91. ) -> List[Dict[str, Any]]:
  92. algorithm = await _fetch_algorithm(core_base_url, timeout)
  93. if algorithm == "filter":
  94. return await _filter_mode_trackers(tracker_repo, core_base_url, timeout)
  95. if algorithm == "ai":
  96. return _ai_mode_trackers(tracker_repo, infer_csv_path)
  97. return tracker_repo.list()