38 Commits
Author SHA1 Message Date
Robin Anderson dbc01cd59a Let people choose what knocking twice or thrice does
Settings has a Knock actions screen with Knock twice and Knock thrice
side by side. Each lists four actions, and one press picks one: switch
passthrough, switch the style, show or hide SteamVR's performance graph,
or do nothing. The defaults stay the same, and the lists mark them with
(default).

config.json stores the actions under knock_actions, keyed by kind and
count, so each kind of knock can have its own actions and a new count
needs no format change. The screen sets every kind the same. The
performance graph is the SteamVR setting perfcheck.perfGraphInHMD. The
tour still teaches the default actions.
2026-10-17 12:18:18 -04:00
Robin Anderson 82976da1aa Remove the Classic bar icon row from Settings
Settings is down to five rows. The classic_bar_icon key in config.json
still works, so anyone who turned it on keeps the colored icon.

The calibrate, update, and report GIFs in the README show the new
Settings screen.
2026-10-17 11:36:18 -04:00
Robin Anderson 8fdae6111f Keep the dashboard-changed flag in the app, not the panel state
The panel never read it. The app uses it to log a missing Room View
button once per change.
2026-10-16 15:51:07 -04:00
Robin Anderson 28c22a1b93 Number the first public release 1.0.0
The version defaults in CMakeLists.txt, build-arm64.sh, and package.mjs
say 1.0.0, and so do the README's manual install and build examples.
The README's update GIF goes from 1.0.0 to 1.1.0, not 0.1.0 to 0.2.0.
2026-10-16 13:59:30 -04:00
Robin Anderson a63205e140 Say where a triple knock goes while passthrough is off
A triple knock while passthrough is off switches the style, and
passthrough opens in it next time. The README table and the tour's
triple knock step now say so. The tour title names the style, not Room
View, so one card never calls passthrough by two names.
2026-10-16 13:00:34 -04:00
Robin Anderson e8a8d28b77 End the calibration GIF on Done and hold the report card longer before the headset turns 2026-10-16 11:17:44 -04:00
Robin Anderson 8d8b700526 Document the no-PC and Frameloader installs and the new update flow, and blur the QR only while it shows 2026-10-16 11:08:58 -04:00
Robin Anderson 6bfa33d6c9 Turn the headset from front to lenses in the report GIF, rendered from Valve's CAD 2026-10-16 10:49:16 -04:00
Robin Anderson 4a6eecb30f Show the headset taken off and a phone scanning a lens in the report GIF 2026-10-16 10:49:16 -04:00
Robin Anderson 720c43817b Show reporting a problem as a GIF with the phone beside the panel 2026-10-16 10:49:16 -04:00
Robin Anderson 1e11b3e576 Document updates, bug reports, and purge in the README, with an update GIF and a report card still 2026-10-16 10:49:16 -04:00
Robin Anderson fa85d199fe Keep the calibration pointer on screen, loop it without a jump, and stop clipping the click ring 2026-10-16 10:49:16 -04:00
Robin Anderson e82c2a8198 Draw the calibration pointer like SteamVR's and move it on curves with hand-like timing 2026-10-16 10:49:16 -04:00
Robin Anderson 21b84386f2 Show a pointer in the calibration animation and skip from the second knock to the tenth 2026-10-16 10:49:16 -04:00
Robin Anderson 3f902c74a1 Add a README calibration animation rendered from the panel 2026-10-16 10:49:16 -04:00
Robin Anderson 33920762ac Revamp the README for non-technical readers
The README now opens with an animation of the dashboard panel reacting
to knocks, then covers install, how to knock, the dashboard tab, and
troubleshooting in plain words. Settings, SSH calibration, commands,
manual install, and build move into collapsed sections at the bottom.

scripts/readme_media.py makes the images: the hero and dashboard images
come from the real panel code through panel_preview --readme, and the
knock kinds and timing animations are drawn with Pillow. ffmpeg writes
the GIFs.
2026-10-16 10:49:15 -04:00
Robin Anderson cb0d853544 Show update progress, a Restart step, and the result after restart
Installing an update fills the Install button with a progress bar,
driven by the ZIP's size against its Content-Length. When the install
finishes, a blue Restart button starts the new version. After the
restart, a card names the new and old versions. A failed install or a
missed restart shows a card with the reason.

A pending update marks the Settings button and the Settings header with
Steam's alert yellow (#FFC82C) and its exclamation mark, taken from the
SettingsAlert icon in Steam's UI on the Frame. The automatic check runs
daily instead of weekly, and retries after an hour when it fails.
2026-10-15 23:43:22 -04:00
Robin Anderson b3f8928155 Record knocks for a bug report
Record knocks on the report card records 20 s of headset and controller
motion in the tests/data CSV format, gzips it to
~/knockthru-knocks.csv.gz, and adds the knocks and actions heard to the
report. The phone page then offers the recording as a download to
attach to the issue.

detector_test FILE replays any recording and prints every knock and
action, for triaging a report.
2026-10-15 22:10:19 -04:00
Robin Anderson e870557c1a Log SteamVR version changes and check for updates once a week
state.json remembers the SteamVR version, the date KnockThru first saw
it, and the version before. Each change goes in the log, and the report
shows the history, so a report after a Steam update names the cause.

A minute after start, KnockThru asks GitHub for the latest release if
the last automatic check was a week ago or more. A newer release puts a
dot on the Settings button and Install in the Settings header. Failures
only go in the log. check_updates: false in config.json turns it off.
2026-10-15 22:07:20 -04:00
Robin Anderson 20b7cc75c5 Hand the full report to a phone through a page the headset serves
The report card's QR code now opens a page on the Frame, over the local
Wi-Fi, with the whole report. One button copies it and opens the
prefilled GitHub form, where it goes in the Report box. The page also
offers the report as a download. It needs a random token in the path and
stops when the card closes or after 15 minutes. SteamOS's firewall opens
TCP 1024 to 65535, and the kernel picks the port from that range.

Without a network, the QR code opens the GitHub form directly, as before.
2026-10-15 21:50:04 -04:00
Robin Anderson 4a84f1fdd3 Walk through sending a report in three steps, with an optional file
The report card numbers the steps: open the phone camera, scan the code
through a lens, then sign in and press Create. Save report file is a
separate button that keeps the full report on the headset and says it
sends nothing. The issue link also carries the last error KnockThru
showed, in a new last-error field on the bug form.
2026-10-15 21:44:22 -04:00
Robin Anderson d421116efe Show a QR code that opens a GitHub issue from the report card
Report in Settings opens a card with a QR code. A phone held up to a lens
scans it and opens the bug form in .github/ISSUE_TEMPLATE/bug.yml, with
the KnockThru version, SteamVR version, and passthrough status filled in.
The full report still goes to ~/knockthru-report.txt.

Vendors nayuki/QR-Code-generator (MIT) to encode the code.
2026-10-15 21:38:42 -04:00
Robin Anderson 59b5b21d63 Put the version and update button at the top right of Settings
Settings rows are 92 px so a sixth row fits: Something wrong?, with a
Report button. The update button reads Check for updates, Checking,
Install X.Y.Z, Installing, or Try again.
2026-10-15 21:30:56 -04:00
Robin Anderson 61121b3688 Add updates, bug reports, purge, and a Steam-update warning
--update installs the latest GitHub release over the running one and
restarts it. It reads the FrameDrop manifest, checks the ZIP's SHA-256,
and renames each new file over the old one. The resident app has the same
check and install behind CheckUpdate and InstallUpdate, for the panel.

--report writes ~/knockthru-report.txt with the KnockThru and SteamVR
versions, registration state, settings, and the end of both logs.

--uninstall --purge also deletes ~/.config/knockthru and SteamVR's
vrappconfig file for KnockThru.

A missing Room View button now throws DashboardChanged. The passthrough
tile then says a Steam update moved the button, and the log records the
SteamVR version once.
2026-10-15 21:20:02 -04:00
Robin Anderson c8887532ad Confirm before skipping the tour and fix tour copy
Skip opens a confirm card that says the tour can be replayed from
Settings. The knock steps list only the knock kinds that are on, and
pick-your-knocks says why Next is off when every kind is off. Errors
show in the strip under the buttons, where no step draws. The knock
steps ignore pause and per-game blocks only while the panel shows them.
2026-10-15 20:54:23 -04:00
Robin Anderson 7df3a7edf5 Add a first-run tour, tour replay, and factory reset
The tour shows the first time someone opens the KnockThru tab. It walks
through picking knock kinds, calibrating each kind that is on, and a
live double and triple knock that really switch passthrough and style.
Next stays off until a step is complete. Skip ends the tour from any step.
Anyone with an existing config.json or calibration.json skips it.

Settings now holds Calibrate, which moves off the main screen, plus a
Sounds switch, Replay for the tour, and Factory reset. Reset deletes
config.json and calibration.json, keeps application.log, and starts
the tour again.
2026-10-15 20:49:50 -04:00
Robin Anderson bb2f4f5db8 Log one summary per recording and close usability gaps
Recording logs one line with how each knock ended (counted, too soon,
too light, other kind, ignored) instead of a line per knock, and the
panel no longer logs frame timings. Canceling a recording logs the same
summary.

The learn step names the ring it asks people to wait for. The Saved
banner says when the calibrated kind or KnockThru itself is turned off,
since knocks would do nothing until it is back on. The calibration plan
records the current decisions.
2026-10-15 19:16:46 -04:00
Robin Anderson 55eef3c62d Count a calibration knock only once the pacing ring fills
The ring started when a knock was confirmed, about 0.3 s after it, and
filled over 1 s, while counting only needed 0.6 s of quiet. So a knock
could count with the ring partway full. The ring now runs from the knock
itself, and a knock before it fills, or during Get ready, shows "Too
soon. Wait for the ring." The surface knock animation turns the
controller to 135 degrees, so it lies flatter with the handle to the
right.
2026-10-15 19:08:06 -04:00
Robin Anderson 8dd6bd3927 Drop the sensitivity step and go straight to trying the knocks
The slider earned little in testing. Its middle and most sensitive ends
gave nearly the same replay results, and its least sensitive end only
lost real knocks. The walkthrough is now four steps: pick, learn,
record, and try. Recording goes straight to the try step, with the
approach threshold fixed at 55 percent of the second slowest knock,
and a miss offers Record again.
2026-10-15 18:54:26 -04:00
Robin Anderson f2fcce5893 Ignore knocks right after Start and let Less drop weak knocks
On the Frame, the hand coming down from pressing Start counted as a
knock 1 s in. Recording now opens with a 1.5 s Get ready ring, and
knocks during it do not count.

The sensitivity range sat below every recorded knock, so moving the
line changed nothing on the chart. The least sensitive end is now the
speed a quarter of the way up from the slowest recorded knock, so
dragging toward Less greys out the weakest ones. Middle and More are
unchanged. Replays at Less keep 14 to 17 of the real doubles, with no
false or wrong actions.
2026-10-15 18:47:28 -04:00
Robin Anderson 55a927bf51 Make the sensitivity step foolproof and polish the calibration screens
The sensitivity chart is logarithmic from a quarter to two and a half
times the second slowest knock, so the scale is the same height for
everyone. Bars stay under the heading. Knocks too light to count at any
sensitivity are turned away while recording with a hint, so every bar
on the chart can count.

The pick cards fill the panel, recording bars are blue like counted
knocks on the chart, the chart heading says All when every knock
counts, and the try step goes Back by name.
2026-10-15 18:40:52 -04:00
Robin Anderson 8b70acea03 Calibrate an approach-speed threshold and drag it on the knock chart
Each calibrated kind now saves a spike threshold and an approach
threshold, with the slider position and the recorded knocks. A sequence
needs its fastest knock to reach the approach threshold. Slow knocks
still join their sequence, so clapping runs stay rejected. Together and
headset knocks get separate spike thresholds. Older calibration files
load with their shared threshold as before.

The sensitivity step charts approach speeds, and the threshold line is
the control: a press anywhere on the chart drags it, and it clicks into
Less, Middle, and More notches. A new test calibrates each kind on its
recording and replays every recording at each notch, with no false
actions and no wrong actions in mixed.
2026-10-15 18:27:48 -04:00
Robin Anderson 0291d2e566 Show knock strength as approach speed and smooth the animations
The spike size divides by pose update gaps that vary from 2 to 7 ms. In
the knock recordings, the top tenth of spikes ran 2.8 to 8.3 times the
bottom tenth. The controller's fastest speed in the 100 ms before the
knock ran 1.7 to 2.5 times, so the recording bars use it now.

The panel paints its background once and copies it, which halves the
frame time, and draws 30 times a second while something moves.
2026-10-15 16:22:13 -04:00
Robin Anderson fae831244d Show a double knock on the calibration kind cards
Knocks act in pairs outside calibration, so a single knock on the cards
read as the gesture itself.
2026-10-15 15:28:13 -04:00
Robin Anderson 1e7669c2d3 Walk calibration through five animated steps
Pick a kind, learn the knock, record single knocks, adjust sensitivity
on a notched slider, and try a double knock before saving. The knock
animations port the README timing and draw controllers and the headset
traced from the CAD sprites. The slider's middle notch keeps the old
60 percent rule. The tuning comes in a later change.
2026-10-15 15:16:56 -04:00
Robin Anderson 4049f0cabe Add a classic bar icon setting and clearer panel states
The knocks switch is now a KnockThru On/Off card with a larger switch,
tinted with the accent while on, so it no longer looks like the
per-knock switches below it.

A Settings screen holds a "Classic bar icon" switch, saved as
classic_bar_icon. Off, the bar icon is white with half-transparent
accent parts, and Steam's tint turns it grey, and white on hover. On,
it is the same mark in the logo colors, without the tint.

Calibration hints say to knock 10 times, at least 1 second apart, and
to knock as softly as KnockThru should catch. A finished calibration
shows a Saved banner with a Done button.
2026-10-15 14:53:51 -04:00
Robin Anderson 6fc03ad3fa Draw the dashboard bar icon as the bare mark at full size
The dashboard bar shows the thumbnail small, and the dark tile shrank the
mark to about three quarters of it. The bar icon now drops the tile and
fills the canvas. The SteamVR library tile and the panel header keep it.
2026-10-15 14:00:40 -04:00
Robin Anderson d6bd54ef77 Add a KnockThru tab to the SteamVR dashboard
The tab has a passthrough button, a translucent or opaque switch,
switches to pause knocks, pick knock kinds, and turn knocks off in the
running game, and a calibration screen with step-by-step progress.

The panel draws into an RGBA image with stb_truetype and Noto Sans, and
shows it through two Vulkan textures that take turns. SetOverlayRaw made
the panel flash on every update. Calibration moved into a Calibrator
class shared by the panel and --calibrate. Panel changes write to the
user config.json. SteamVR also gets an app icon.
2026-10-15 13:18:08 -04:00