screentinker/docs/134-device-reporting.md
screentinker 1f2e923005
fix(#134): quiet false "reconnect" log + report HDMI output and UI render resolution (#136)
Two device-REPORTING fixes from the #134 investigation (the PiP rendering itself
was #135).

1) "Device reconnects every ~45s" was a logging artifact, not instability. The
   player re-emits a full device:register on the SAME socket every ~45-60s
   (requestPlaylistRefresh) to pull a fresh playlist; the server logged
   "Device reconnected" for every register of a known device. The attached 4-day
   log showed 1415 "reconnected" vs 30 real socket connects and 0 heartbeat
   timeouts — the socket never dropped, so #134's "PiP lost between reconnects"
   was a misdiagnosis. Fix: only log a genuine reconnect (new socket); a
   same-socket re-register is a refresh (currentDeviceId === device_id) and stays
   quiet. The playlist still refreshes.

2) Device reported 720p while the monitor showed a 1080 signal. DeviceInfo
   reported getRealMetrics() — the UI RENDER SURFACE — but TV boxes render the UI
   at 720p and upscale to a 1080p HDMI signal. Now report BOTH: screen_width/height
   = the output mode (Display.Mode.physicalWidth/Height), render_width/height =
   the render surface (getRealMetrics). Two new nullable devices columns, stored on
   pairing INSERT + reconnect UPDATE, exposed via the device API, shown on the
   dashboard as "1920x1080 (UI 1280x720)" when they differ.

Backward compatible (required + verified on emulator): a device that omits
render_* — or sends no device_info at all — still registers, with render_* = null,
on both the INSERT and UPDATE paths. New columns nullable; stores use
`?? null` / `|| null`. All 167 server tests pass.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 15:32:11 -05:00

3.9 KiB
Raw Blame History

#134 follow-ups — device reporting fixes

Two issues surfaced while investigating #134 (the PiP bug report). Neither is the PiP rendering itself (that was #135) — both are device reporting problems.

1. "Device reconnects every ~45s" — a logging artifact, not instability

Symptom (#134): the server log shows the device reconnecting every ~45s, read as an unstable WebSocket that could drop PiP commands.

Reality: the connection is stable. The player calls requestPlaylistRefresh() every ~4560s, which re-emits a full device:register on the same socket to pull a fresh playlist. The server's register handler logged Device reconnected for every register of a known device, so a healthy device that re-registers ~2000×/day looked like it was flapping.

Evidence from the attached 4-day log:

Signal Count
Device reconnected 1415
Device socket connected (real) 30
Device disconnected (real) 21
marked offline (heartbeat timeout) 0

1415 "reconnects" vs 30 real socket connects, and the socket never timed out. So #134's "PiP lost between reconnects / queue TTL-expired" was a misdiagnosis — the socket doesn't drop; the PiP failure was the rendering bugs fixed in #135.

Fix (ws/deviceSocket.js): a re-register on the same socket (currentDeviceId === device_id) is a playlist refresh, not a reconnect — only log Device reconnected for a genuinely new socket. The refresh still resends the playlist; it just no longer spams the log / reads as instability.

Verified on the emulator: a periodic refresh was processed (device received a new playlist) while the server's Device reconnected count stayed flat; two genuine reconnects logged exactly twice.

Follow-up (not done here): the full re-register every ~45s is heavier than it needs to be (re-runs fingerprint/token/eviction + resends the playlist). A lightweight device:request-playlist event would cut that churn. Left as a separate optimization.

2. Reports 720p while the monitor shows a 1080 signal

Symptom (#134-adjacent): a panel receiving a real 1080p HDMI signal was reported as 720p.

Cause: DeviceInfo reported getRealMetrics() — the UI render surface. Many Android TV boxes/sticks (YaOS, Fire TV, etc.) render the UI at 1280×720 and let the hardware scaler upscale to a 1920×1080 (or 4K) HDMI signal. getRealMetrics honestly reports the 720p render surface; the monitor sees the 1080p output mode. They are two different numbers.

Fix: report both, so neither is lost:

  • screen_width / screen_height = the HDMI/panel output mode, from Display.getMode().getPhysicalWidth()/getPhysicalHeight() (orientation-independent; the panel doesn't rotate when the stage is software-rotated). This is the headline resolution and now reads 1080 on those boxes.
  • render_width / render_height = the UI render surface, from getRealMetrics().

Wiring: Android DeviceInfo.getDeviceInfo() → two new nullable devices columns (render_width, render_height, migration) → stored in both the pairing INSERT and the reconnect UPDATE → exposed via the device API (SELECT d.*) → the dashboard device detail shows 1920x1080 (UI 1280x720) when they differ.

Backward compatibility

Required and verified: a device that doesn't report the new fields must still be accepted.

  • New columns are nullable; the store uses device_info.render_width ?? null (reconnect) and device_info?.render_width || null (pairing); device_info itself remains optional.
  • Verified on the emulator: an old-style register with screen_* but no render_*, and a register with no device_info at all, both succeed with render_* = null — on both the INSERT (pairing) and UPDATE (reconnect) paths.
  • The dashboard only appends (UI …) when render_* is present and differs, so legacy devices render as before.