NBA Feed
팀 뉴스와 경기 정보를 제공, 점수는 직접 확인할 때까지 숨겨져 있습니다
오픈소스 안드로이드 앱으로 WaterRower S4 모니터를 USB로 읽어 아날로그 계기, 19가지 게임, 캘리포니아 해안 비행을 구현합니다
An open-source Android app that reads the WaterRower S4 monitor over USB and turns it into analog instruments, 19 games and a Cesium flight down the California coast.
스포츠·피트니스Java · JavaScriptGitHub @dustin-gamble온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Rowing instruments, 21 games and a coastal flight, driven by a WaterRower S4 monitor over USB. Runs on the rower's own Android tablet. No root.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Rowing instruments, 19 games and a coastal flight, driven by a WaterRower S4 monitor over USB.
📥 Download the APK and read the guide →
Your rowing machine already measures everything. WAKE reads the WaterRower S4 monitor over USB
from the Android tablet on the machine, and turns it into analog instruments that behave like
water, a shelf of games driven by your real power and cadence, and a flight down the California
coast on a 3D globe.README 전문 보기 ↗Rowing instruments, 19 games and a coastal flight, driven by a WaterRower S4 monitor over USB.
📥 Download the APK and read the guide →
The machine all of this was written on and measured against. Nothing was added to the hardware — the app reads the S4 monitor over the USB cable that is already there.
Your rowing machine already measures everything. WAKE reads the WaterRower S4 monitor over USB from the Android tablet on the machine, and turns it into analog instruments that behave like water, a shelf of games driven by your real power and cadence, and a flight down the California coast on a 3D globe.
If Ergatta does not read your strokes after you exit WAKE, restart the screen.
Built against a WaterRower in an Ergatta fit-out, but it talks to the S4, not to Ergatta: no root, no system changes, and Ergatta itself is untouched and still the fallback.
node server/server.js) for live capture, an event stream and
protocol decoding. The app finds it on the Wi-Fi by itself; everything works without it.A real boat decelerates between strokes. Rowers call it the run of the boat, and reading it is how you judge your own stroke — a strong drive shows a high peak and a slow decay.
The S4 does not decay its readings: it holds the last value until the next one. Showing that value flat is the single mistake that cost this project the most rework. Instead every needle coasts.
Pure quadratic drag, ω(t) = ω₀ / (1 + (k/I)ω₀t), was the first model, and on the machine it read
wrong: steepest the instant you stop, then hovering just above zero for minutes — 11 rpm on a paddle
at rest. The coast now holds its run, eases off through the middle, and lands on exactly zero.
Knowing when to coast turned out to be the hard part. Three candidate triggers were tested against thousands of captured samples before one survived:
| Trigger | Result |
|---|---|
watts == 0 | Rejected — zero in 27% of samples taken while actively rowing, runs up to 9.7 s |
| Speed value unchanged | Rejected — it is an average and holds its last figure for ~10 s |
| Flywheel pulses stopped | Rejected — the paddle turns for many seconds after you let go |
| Stroke counter gone quiet | Used — exact, one tick per stroke, allowance scaled to your rating |
Pulses stopping is no good for starting a coast, but it is the one true signal the paddle has stopped — so once they stop, whatever is left of the coast finishes within 1.5 s.
1A9 with no multiplier. An inherited ×2 produced 74 spm and 294
readings above 55 spm, beyond human cadence.1A9 dipping to 19–21 in ~9% of samples, so the displayed
rate is now a trimmed mean over 15 s. The raw value still drives every decision.055 is not a distance. It is the low byte of a metres counter; real distance is 057.Device : WR USB sensor, 04D8:000A (Microchip CDC-ACM)
Tablet : Android 9, Ergatta rower tablet (minSdk 23)
Decoded: 088 watts · 14A speed · 1A9 rate · 140 strokes
057 distance · 1A0 heart rate · 1E1 clock
Any WaterRower S4 exposing USB serial should work, as should other Android tablets. Reports from different hardware are very welcome — open an issue.
WAKE was built with an AI coding agent, and everything learned the hard way is written down for the next one. Open Claude Code or any coding agent, paste this, and describe what you want:
I want to customize WAKE, a rowing app for the WaterRower S4 on an Ergatta tablet.
1. Fork https://github.com/dustin-gamble/wake to my GitHub account, clone my fork,
and create a branch called my-wake.
2. Before changing anything, read AGENTS.md, then README.md, then CLAUDE.md.
3. Help me with this: <describe what you want - e.g. "a game where I race a shark
that speeds up whenever my stroke rate drops">
4. There is no emulator for this tablet. Build the APK, tell me how to get it onto
my rower, and ask me what I see before moving on.
Your agent can't see the tablet, so you are its eyes: install each build, row, and tell it what you see. Made something others would enjoy? Send a pull request.
# JDK 17+ and the Android SDK (platform 35); one dependency, usb-serial-for-android.
./gradlew assembleDebug
# Optionally bake in your laptop's dashboard URL, otherwise it is discovered over UDP:
./gradlew assembleDebug -PdiagnosticServerUrl=http://<your-laptop-ip>:8787
The dashboard needs no dependencies at all:
node server/server.js # http://localhost:8787
For Coast Flight's satellite maps, supply a Cesium Ion token — either
CESIUM_ION_TOKEN in the environment or server/cesium.local.json as {"ionToken":"..."}. It is
served to the app once over the LAN and cached there; no token is ever committed or compiled
into the APK. Without one the flight falls back to OpenStreetMap.
Protocol and physics run without Android, so they are tested with plain javac:
S=app/src/main/java/com/codex/waterrowerdiagnostic T=tools/prototest/com/codex/waterrowerdiagnostic
javac -d /tmp/t $S/S4Protocol.java $S/PulseMeter.java $S/Coast.java $S/BoatSpeedModel.java \
$S/RowerProfile.java $S/Progress.java $S/ShuffleBag.java $T/*.java
for t in S4ProtocolTest PulseMeterTest BoatSpeedModelTest RowerProfileTest ProgressTest ShuffleBagTest; do
java -cp /tmp/t com.codex.waterrowerdiagnostic.$t
done
app/ Android app: protocol, instruments, games, Coast Flight WebView
server/ Optional laptop dashboard: HTTP, SSE, capture, UDP discovery
tools/ Capture analysis (Python) and offline tests (plain javac)
docs/ The GitHub Pages site and the published APK
AGENTS.md Start here if an AI agent is customizing it
CLAUDE.md Engineering notes: what was measured, what was ruled out, and why
MIT. Not affiliated with WaterRower or Ergatta.
If it made a row go quicker, you can sponsor the project.