feat: sideband payload complet — cpu_pct, throttled, bitrate_kbps, uptime_s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@ -53,6 +53,7 @@ DEFAULTS: dict = {
|
||||
|
||||
FLASK_PORT = 5000
|
||||
SIDEBAND_PORT = 5602
|
||||
START_TIME = time.time()
|
||||
|
||||
# --- Logging -----------------------------------------------------------------
|
||||
|
||||
@ -65,15 +66,41 @@ log = logging.getLogger(__name__)
|
||||
# --- Helpers -----------------------------------------------------------------
|
||||
|
||||
def _get_temp_celsius() -> float | None:
|
||||
"""Read SoC temperature via vcgencmd. Returns None if unavailable."""
|
||||
try:
|
||||
out = subprocess.check_output(["vcgencmd", "measure_temp"], text=True, timeout=1)
|
||||
# output: "temp=45.2'C"
|
||||
return float(out.strip().split("=")[1].replace("'C", ""))
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def _get_throttled() -> bool:
|
||||
try:
|
||||
out = subprocess.check_output(["vcgencmd", "get_throttled"], text=True, timeout=1)
|
||||
# output: "throttled=0x0"
|
||||
return out.strip().split("=")[1] != "0x0"
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def _get_cpu_pct() -> float | None:
|
||||
"""Read /proc/stat twice 0.5 s apart, return CPU busy %."""
|
||||
def _read() -> list[int] | None:
|
||||
try:
|
||||
with open("/proc/stat") as f:
|
||||
return [int(x) for x in f.readline().split()[1:]]
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
s1 = _read()
|
||||
time.sleep(0.5)
|
||||
s2 = _read()
|
||||
if s1 is None or s2 is None:
|
||||
return None
|
||||
d_total = sum(s2) - sum(s1)
|
||||
d_idle = (s2[3] + s2[4]) - (s1[3] + s1[4]) # idle + iowait
|
||||
return round(100.0 * (1 - d_idle / d_total), 1) if d_total else 0.0
|
||||
|
||||
|
||||
def _h264_level(w: int, h: int) -> str:
|
||||
"""Minimum H.264 level for the given resolution."""
|
||||
# level 4 required for anything above 720p
|
||||
@ -118,20 +145,26 @@ def _sideband_worker(gst: "GstManager") -> None:
|
||||
try:
|
||||
while not gst._shutdown.is_set():
|
||||
cfg = gst.get_cfg()
|
||||
temp = _get_temp_celsius()
|
||||
cpu_pct = _get_cpu_pct() # blocks 0.5 s internally
|
||||
temp = _get_temp_celsius()
|
||||
throttled = _get_throttled()
|
||||
payload = json.dumps({
|
||||
"ts": time.time(),
|
||||
"width": cfg["width"],
|
||||
"height": cfg["height"],
|
||||
"fps": cfg["fps"],
|
||||
"encoder": gst.encoder_active or "unknown",
|
||||
"temp_c": temp,
|
||||
"ts": time.time(),
|
||||
"width": cfg["width"],
|
||||
"height": cfg["height"],
|
||||
"fps": cfg["fps"],
|
||||
"encoder": gst.encoder_active or "unknown",
|
||||
"bitrate_kbps": cfg["bitrate_kbps"],
|
||||
"temp_c": temp,
|
||||
"cpu_pct": cpu_pct,
|
||||
"throttled": throttled,
|
||||
"uptime_s": int(time.time() - START_TIME),
|
||||
}).encode()
|
||||
try:
|
||||
sock.sendto(payload, (cfg["jetson_host"], SIDEBAND_PORT))
|
||||
except OSError as exc:
|
||||
log.debug("sideband send: %s", exc)
|
||||
time.sleep(1)
|
||||
time.sleep(0.5) # 0.5 s cpu read + 0.5 s sleep ≈ 1 Hz
|
||||
finally:
|
||||
sock.close()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user