fix(system-info): tidy up x86 Device Info (CEC state + device model)#3119
Merged
Conversation
On x86 (and any host that doesn't pass /dev/cec0 or /dev/vchiq into the container, e.g. Pi 5) there is no CEC adapter, so the periodic libcec probe can only fail — it stored 'CEC error', which the System Info "Display Power (CEC)" card and the v2 /info API then surfaced as though something were broken. Gate the get_display_power Celery task on the same cec_available() helper the settings UI and the display-power SET endpoint already use: when no CEC adapter is present, record a clear 'Not available' and skip spawning a doomed subprocess every tick. CEC-capable boards (Pi 1-4) are unaffected and still report the live On/Off state. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adjusts the periodic get_display_power Celery task so hosts without a CEC adapter (e.g., x86) record "Not available" instead of surfacing "CEC error" via the System Info page and the v2 /info API.
Changes:
- Short-circuit
get_display_powerondiagnostics.cec_available()and write"Not available"to Redis when CEC isn’t present. - Update existing tests to force
cec_available() == Truewhen exercising the probe path. - Add a new test asserting the non-CEC path writes
"Not available"and does not call the probe.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/anthias_server/celery_tasks.py |
Short-circuits the display-power periodic task when CEC is unavailable, writing "Not available" to Redis. |
tests/test_celery_tasks.py |
Adds/updates tests to cover both CEC-present probe behavior and the new CEC-absent short-circuit behavior. |
Comments suppressed due to low confidence (1)
src/anthias_server/celery_tasks.py:347
- SoftTimeLimitExceeded is only caught around the probe path; in the non-CEC short-circuit branch the Redis
set()can still be interrupted by the soft time limit (or hang until the hard limit), which defeats the task’s “skip the tick instead of SIGKILLing the worker” safety behavior. Consider wrapping the whole body (including the early return) in the same try/except, and make the warning message not specific to the CEC probe so it stays accurate for both branches.
if not diagnostics.cec_available():
r.set('display_power', 'Not available', ex=3600)
return
try:
# Single SET with ex= so the value and its TTL are written
# atomically — a soft-limit signal landing between a separate
# SET and EXPIRE would otherwise leave the key without a TTL
# (a stale display_power that never expires).
r.set('display_power', str(diagnostics.get_display_power()), ex=3600)
except SoftTimeLimitExceeded:
# The CEC query is meant to be bounded by its own
# subprocess timeout, but a child wedged in libcec can keep
# the pipe open past it. Skip this tick rather than let the
# hard limit SIGKILL the worker (ANTHIAS-A / 9 / B); the next
# beat tick re-queries.
logging.warning(
'get_display_power: CEC query exceeded %ss; skipping this tick',
PERIODIC_POKE_SOFT_TIME_LIMIT_S,
)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The Device model card joined the raw DMI sys_vendor, product_name and CPU brand, so a reference/whitebox board rendered 'Intel Corporation Whiskey Platform · Intel Celeron 4205U @ 1.80GHz' — a corporate suffix plus an 'Intel ... · Intel ...' stutter. Trim trailing corporate suffixes (Corporation / Inc. / Ltd. / …) from the vendor, and drop the board vendor entirely when the CPU brand already names it (whitebox boards set sys_vendor to the CPU maker). Branded OEM boxes keep their vendor because it differs from the CPU: 'Dell Inc. OptiPlex 7090' -> 'Dell OptiPlex 7090'. The x86 label becomes 'Whiskey Platform · Intel Celeron 4205U @ 1.80GHz'. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Device model card joined the board and CPU into one string with a
'·', so a long x86 label word-wrapped at an arbitrary point (splitting
the CPU model, e.g. 'Intel Celeron' | '4205U ...').
Return the board and CPU as separate parts (get_device_model_parts) and
render the CPU as the card's secondary line, so the two facts stack
cleanly with no separator and no mid-model wrap:
Whiskey Platform
Intel Celeron 4205U @ 1.80GHz
Pi keeps its single firmware Model line (no secondary row).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Three fixes to the Display & hardware section of the System Info page as it renders on x86 players, reviewed against the x86 testbed.
1. Display Power (CEC) showed "CEC error"
x86 (and any host without a CEC adapter — no
/dev/cec0//dev/vchiq, e.g. Pi 5) can only fail the libcec probe, so the periodicget_display_powertask stored'CEC error', which the System Info card and the v2/infoAPI surfaced verbatim — reading like a fault when CEC simply isn't present.Now short-circuits on the existing
diagnostics.cec_available()gate (the same one the Settings page and the display-power SET endpoint use): records a clearNot availableand skips spawning a doomed subprocess every tick. CEC-capable boards (Pi 1–4) still report live On/Off.2 & 3. Device model: stutter + awkward wrap
The card joined the raw DMI
sys_vendor+product_name+ CPU brand into one string with a·, so the x86 label both stuttered and word-wrapped at an arbitrary point (splitting the CPU model, e.g.Intel Celeron|4205U …):Before
After
Corporation/Inc./Ltd./ …) are trimmed, and the board vendor is dropped when the CPU brand already names it (whitebox/reference boards setsys_vendorto the CPU maker). Branded OEM boxes keep their vendor because it differs:Dell Inc. OptiPlex 7090→Dell OptiPlex 7090.get_device_model_parts()now returns(board, cpu)and the template stacks the CPU as the card's secondary line — no·, no mid-model wrap. Pi keeps its single firmware Model line.Tests
get_display_power: existing True/False/error cases run withcec_available() == True; new test asserts'Not available'is written and the probe skipped when no CEC adapter is present; soft-limit test updated.get_device_model_parts: Pi, x86-with-DMI, redundant-vendor drop (Intel reference board), kept-but-trimmed branded vendor (Dell), virtual-chassis drop, and generic fallback — all asserting the(primary, secondary)tuple.test_system_info_renderscovers the template with the newdevice_model_detailline.Verified on the x86 testbed
cec_available()returnsFalseand the card renders "Not available"; the device-model helper produces('Whiskey Platform', 'Intel Celeron 4205U @ 1.80GHz')for the box's actual DMI values.🤖 Generated with Claude Code