90 lines
3.3 KiB
Python
90 lines
3.3 KiB
Python
"""
|
|
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos/
|
|
"""
|
|
|
|
import threading
|
|
import time
|
|
|
|
import pyray as rl
|
|
|
|
from iqpilot.common.api import api_get
|
|
from iqpilot.common.constants import CV
|
|
from iqpilot.common.params import Params
|
|
from iqpilot.common.swaglog import cloudlog
|
|
from iqpilot.selfdrive.ui.lib.api_helpers import get_token
|
|
from iqpilot.selfdrive.ui.ui_state import ui_state, device
|
|
from iqpilot.konn3kt.registration import UNREGISTERED_DONGLE_ID
|
|
from iqpilot.system.ui.lib.application import gui_app, FontWeight
|
|
from iqpilot.system.ui.lib.text_measure import measure_text_cached
|
|
from iqpilot.system.ui.widgets.nav_widget import NavWidget
|
|
|
|
_ACCENT = rl.Color(0x3A, 0xDD, 0xC6, 255)
|
|
_CARD_BG = rl.Color(26, 27, 30, 255)
|
|
_LABEL = rl.Color(150, 150, 150, 255)
|
|
|
|
|
|
class TripsLayoutMici(NavWidget):
|
|
PARAM_KEY = "ApiCache_DriveStats"
|
|
UPDATE_INTERVAL = 30
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._params = Params()
|
|
self._stats = self._params.get(self.PARAM_KEY) or {}
|
|
self._bold = gui_app.font(FontWeight.BOLD)
|
|
self._medium = gui_app.font(FontWeight.MEDIUM)
|
|
self._running = True
|
|
self._thread = threading.Thread(target=self._update_loop, daemon=True)
|
|
self._thread.start()
|
|
|
|
def __del__(self):
|
|
self._running = False
|
|
|
|
def _fetch(self):
|
|
try:
|
|
dongle_id = self._params.get("DongleId")
|
|
if not dongle_id or dongle_id == UNREGISTERED_DONGLE_ID:
|
|
return
|
|
resp = api_get(f"v1.1/devices/{dongle_id}/stats", access_token=get_token(dongle_id))
|
|
if resp.status_code == 200:
|
|
data = resp.json()
|
|
self._stats = data
|
|
self._params.put(self.PARAM_KEY, data)
|
|
except Exception as e:
|
|
cloudlog.error(f"trips: failed to fetch drive stats: {e}")
|
|
|
|
def _update_loop(self):
|
|
while self._running:
|
|
if not ui_state.started and device._awake:
|
|
self._fetch()
|
|
time.sleep(self.UPDATE_INTERVAL)
|
|
|
|
def _render_group(self, x, y, w, h, title, data, is_metric):
|
|
rl.draw_rectangle_rounded(rl.Rectangle(x, y, w, h), 0.16, 8, _CARD_BG)
|
|
rl.draw_text_ex(self._bold, title, rl.Vector2(x + 22, y + 12), 24, 0, _ACCENT)
|
|
|
|
routes = int(data.get("routes", 0) or 0)
|
|
distance = data.get("distance", 0) or 0
|
|
dist = int(distance * CV.MPH_TO_KPH) if is_metric else int(distance)
|
|
hours = int((data.get("minutes", 0) or 0) / 60)
|
|
cols = [(str(routes), "drives"), (str(dist), "km" if is_metric else "mi"), (str(hours), "hours")]
|
|
|
|
col_w = w / 3
|
|
for i, (val, lbl) in enumerate(cols):
|
|
cx = x + col_w * i + col_w / 2
|
|
vs = measure_text_cached(self._bold, val, 46)
|
|
rl.draw_text_ex(self._bold, val, rl.Vector2(cx - vs.x / 2, y + h / 2 - 28), 46, 0, rl.WHITE)
|
|
ls = measure_text_cached(self._medium, lbl, 22)
|
|
rl.draw_text_ex(self._medium, lbl, rl.Vector2(cx - ls.x / 2, y + h / 2 + 24), 22, 0, _LABEL)
|
|
|
|
def _render(self, _):
|
|
rect = self._rect
|
|
is_metric = self._params.get_bool("IsMetric")
|
|
stats = self._stats if isinstance(self._stats, dict) else {}
|
|
pad = 12
|
|
h = (rect.height - 3 * pad) / 2
|
|
w = rect.width - 2 * pad
|
|
x = rect.x + pad
|
|
self._render_group(x, rect.y + pad, w, h, "ALL TIME", stats.get("all", {}), is_metric)
|
|
self._render_group(x, rect.y + 2 * pad + h, w, h, "PAST WEEK", stats.get("week", {}), is_metric)
|