Skip to content

feat(tv): turn the TV on and switch input over the network (Google TV / Android TV) - #93

Merged
lippdev merged 4 commits into
lippdev:mainfrom
nextestudios:feat/tv-control
Sep 30, 2026
Merged

lippdev merged 4 commits into
lippdev:mainfrom
nextestudios:feat/tv-control

Conversation

@nextestudios

Copy link
Copy Markdown
Contributor

Summary

First step for #75: console mode turns the TV on and switches it to the PC's HDMI input, and can put it in standby after the restore. This PR adds the plumbing plus the Google TV / Android TV route (TCL, Sony, Hisense, Philips…), which needs no extra hardware and nothing installed on the PC.

  • Settings → TV (new section): route (Don't control it / Google TV / Android TV (network)), TV IP, optional MAC for Wake-on-LAN, PC's HDMI input, an advanced input command, "Put the TV in standby on restore" (off by default) and Test now.
  • Engine: ConsoleEngine.Start calls TvControlService.TurnOn first, so the TV is up before the fresh screen read / EnsureActive wait; Stop optionally calls TurnOff after the desk is back. Both are bounded (30 s / 15 s) and never throw: a TV that doesn't answer is only logged, and the existing "game screen did not turn on" path does the rest.
  • Android TV: a small in-process ADB client (Services/Tv/AdbClient.cs) on port 5555: CNXN, AUTH with this PC's RSA-2048 key (kept in the data folder as adbkey.pem, so the TV asks "Allow debugging?" once), then shell:input keyevent WAKEUP → TV_INPUT_HDMI_n (SLEEP for standby). No adb.exe to ship. If the TV is unreachable and a MAC is set, it sends Wake-on-LAN and retries for 20 s. "Wireless debugging" (TLS pairing) is detected and explained instead of hanging.
  • ITvController / TvControlService.Create are the extension point for the other routes in the issue (LG webOS, Home Assistant, USB-CEC), which I'll send as separate PRs on top of this one.
  • Pure logic in AdbProtocol.cs / WakeOnLan.cs (framing, checksum/magic, token signature, Android's RSAPublicKey layout with n0inv/rr, endpoint parsing, HDMI key codes, MAC parsing, magic packet), linked into the test project.
  • Strings in pt-BR / en-US / es-ES; guide section "TV control" (en + pt-BR), README bullet, docs/TESTING.md §3c, changelog under [Unreleased].

Validation

  • New TvControlTests (ADB framing and header validation, signature verifies as a SHA-1 digest, public key layout checked against BigInteger math, endpoint/HDMI mapping, MAC parsing, magic packet).
  • Written on macOS: the app build and dotnet test are left to CI.
  • Hardware checks in docs/TESTING.md §3c; to be run on a TCL Google TV.

🤖 Generated with Claude Code

nextestudios added a commit to nextestudios/consolemode that referenced this pull request Sep 26, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@lippdev

lippdev commented Sep 29, 2026

Copy link
Copy Markdown
Owner

Thanks, this is a solid base for #75. Before it moves out of draft:

  1. Rebase on main. It conflicts in CHANGELOG.md, CHANGELOG.en-US.md and ConsoleEngine.cs. main has moved a lot (native audio and displays without the NirSoft tools, a [Unreleased] section with more entries, AGENTS.md). Please follow the conventions there: changelog under ## [Unreleased] in both files ending with the PR number, strings in all three catalogs, docs in pairs.
  2. Merge order for feat(tv): turn the TV on and switch input over the network (Google TV / Android TV) #93–#96. #94, #95 and #96 each carry this PR's commits, so they can't all be merged as they are. The plan is to merge this one first; please rebase the other three on main afterwards so each shows only its own route.
  3. adbkey.pem is written in plain text in the data folder (AdbKeyStore). #95 already protects the Home Assistant token with DPAPI (SecretProtector); please use the same for this private key. Portable mode keeps the data folder next to the exe, so the file travels with it.
  4. Hardware. The tests are pure logic, which is good, but the route itself has not run on a real TV. Please tick the checks in docs/TESTING.md §3c on the TV you have and note the model in the description before marking it ready.
  5. Start-up cost. TurnOn runs first in ConsoleEngine.Start with a 30 s bound. Please confirm nothing is added when the route is Don't control it (the default), and say in the guide what the worst case is when the TV doesn't answer.

nextestudios and others added 2 commits September 30, 2026 14:31
… / Android TV)

Settings → TV: console mode wakes the TV and switches it to the PC's HDMI
input before the display flow, and can put it in standby after the restore.
First provider: Google TV / Android TV through ADB (port 5555), with a small
in-process ADB client, so nothing has to be installed on the PC. Optional
Wake-on-LAN for TVs that drop off the network in standby, and a custom input
command for TVs that ignore the HDMI key codes. A TV that doesn't answer is
only logged.

Refs lippdev#75

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- adbkey.pem is written through SecretProtector (DPAPI, per Windows user);
  a key from another user/PC, or a plain one from an older build, is
  handled (recreated / protected in place).
- Guide: nothing is added with the default route, and the TV step is capped
  at 30 s on start / 15 s on restore.
- Tests: the default config runs no TV route.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@nextestudios

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Updated, point by point:

  1. Rebased on main (4cac117) and squashed into one commit; conflicts in both changelogs and ConsoleEngine.cs resolved. The [Unreleased] entry sits under Novidades / What's new and ends with (#93); strings are in all three catalogs, docs in pairs.
  2. Merge order. Agreed: this one first. #94, #95 and #96 are now rebased on top of this branch so each shows only its own route (and no longer conflicts); after feat(tv): turn the TV on and switch input over the network (Google TV / Android TV) #93 lands I'll rebase them on main.
  3. adbkey.pem is now DPAPI-protected. I moved SecretProtector into this PR (Services/SecretProtector.cs, plus the System.Security.Cryptography.ProtectedData package reference) so the key is written as dpapi:…. A plain key from an earlier build is protected in place; a key copied to another Windows user/PC can't be read, so a new one is created and the TV just asks "Allow debugging?" once more (logged, and explained in the guide). #95 and #94 use the same class.
  4. Hardware. Not run on a real TV yet, so this stays a draft. I'll run docs/TESTING.md §3c (including the new DPAPI and timing checks) on a TCL Google TV and put the model and results here before marking it ready.
  5. Start-up cost. With the default (Don't control it) ConsoleEngine.Start only does a config.Tv is { IsEnabled: true } check: no service is created, nothing is sent, no delay (new test asserts the default config has the route off). The guide now states the worst case: with a route selected the TV step is capped at 30 s on start (TV not answering + Wake-on-LAN retries) and 15 s for the optional standby on restore, and a TV that's on answers in ~1-2 s.

@lippdev
lippdev marked this pull request as ready for review September 30, 2026 22:13
@lippdev
lippdev merged commit 12c8ad0 into lippdev:main Sep 30, 2026
4 checks passed

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ One changelog placement issue; no behavioral issues found in the reviewed code.

Reviewed changes This review covers the TV settings/configuration, Android TV ADB and Wake-on-LAN implementation, console-engine integration, and related tests and documentation.

  • TV configuration: Adds a disabled-by-default TV provider and settings for Android TV network control.
  • ADB control: Adds authentication, shell commands for wake/input/standby, and optional Wake-on-LAN.
  • Session integration: Wakes the TV before reading displays at start and optionally puts it in standby after restoring the desktop.
  • Validation and guidance: Adds pure-logic tests, localized UI strings, paired guides, and manual hardware checks.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using GPT Luna | 𝕏

Comment thread CHANGELOG.en-US.md
- Sounds in the Console interface when you move the focus, pick and go back (made by the app itself, at a low volume). Turn them off in Settings → Interface sounds. (#117)
- Controller shortcuts of your choice: the button that opens Console Mode, the session menu's and the one that goes back to the PC are now set in Settings (hold the buttons you want and let go on the same controller). Capture never combines buttons from different controllers. None is on by default: the first time you open this version the app shows the setup, with a suggestion for each action (Home, Select + Y and Start + Select). One button can't serve two actions. If you used the Home button or Start + Select before, choose them again. (#116)
- Settings → "Receive test versions (alpha and beta)": anyone can join the tests of upcoming versions from the app. Off by default; turning it on shows a warning that test versions can have bugs.
- Settings → TV: console mode turns the TV on and switches it to the PC's HDMI input, and can put it in standby on restore. First route: Google TV / Android TV over the network (ADB), nothing to install on the PC. (#93)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feature is already listed under [Unreleased] above, but this second entry places it in the published [1.6.0-alpha.3] notes as well. Please keep it only under [Unreleased] so that the historical release notes do not claim this PR shipped in alpha.3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants