chore: add pre-commit hooks and CI workflow#6
Merged
Conversation
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Implements the JSON-ready payload builder for the firmware's POST /transmit endpoint. Validates binary bit strings and extracts the six required timing keys from the device profile. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Refactor the CLI from a single click command into a click group with two subcommands: - 'send': takes (device, unit, command) and POSTs to /transmit endpoint - 'raw': takes arbitrary bit string and device profile, POSTs to /transmit Both subcommands now hit the generic /transmit endpoint instead of the per-button endpoints, matching the firmware's new generic handler. Add comprehensive test suite (5 tests) covering subcommand structure, error handling, and HTTP payload validation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both fans are physically in the living room; rename from bedroom/living_room to main/stairs to reflect which is nearer the main room vs the staircase landing. CLAUDE.md confirmed the operating frequency as 433.935 MHz during capture; the YAML and PROTOCOL.md were stale with the old 315 MHz guess. Firmware just toggles TX_PIN, so the YAML field was informational only, but the mismatch was misleading. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
TX on 433 MHz confirmed; fans don't respond; RTL-SDR capture of our own transmission shows smeared pulse envelope vs the real remote's crisp pulses. Most likely TX module wiring (3V3 vs VIN) or timing constants off. Includes ranked hypotheses, next-session plan, and pointers to /tmp comparison artifacts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Loads a dumb shell script that curl-posts a fixed reminder pointing at the fan-debugging findings doc. Lives in scripts/ with a template plist for re-creation on a new machine. The live plist at ~/Library/LaunchAgents/com.tomclancy.rf-nudge.plist is already loaded and smoke-tested. Update scripts/rf-nudge.sh's MSG as the project's bottleneck shifts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
After three weeks of "TX is alive but fans ignore us," the fix was that our hand-decoded pulse and gap timings were systematically off. The biggest miss was sync_gap_us: we had 670 µs, the real remote uses ~4500 µs to give the fan's AGC time to settle after the long sync burst before trying to decode bits. Recapturing remote 1's light press with rtl_fm -M am (instead of the default WBFM) gave a clean envelope where pulse and gap widths are unambiguous. Measured values: pulse_us: 400 → 560 sync_us: 8000 → 8200 sync_gap_us: 670 → 4500 (the critical fix) zero_gap_us: 670 → 570 one_gap_us: 1800 → 1700 All 5 commands (light, off, speed1/2/3) now drive both fans (main and stairs) reliably. The "derived" stairs commands turned out correct; nothing about the bit pattern needed changing. Also adds a "Tom's setup checklist" section to README so cold-start sessions don't lose half an hour to "where's pio" / "what's the IP" / "why is monitor showing noise" again. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Generic-bits firmware + corrected timing values + working fan control
for both Sofucor fans across all five commands.
Highlights:
- POST /transmit endpoint accepts {bits, timing} JSON; firmware no longer
device-specific
- CLI split into 'send' (named commands from YAML profile) and 'raw'
(arbitrary bit string) over click groups
- Units renamed bedroom/living_room → main/stairs
- Frequency corrected 315.4 → 433.935 MHz across YAML/PROTOCOL.md/tests
- Timing values re-measured from a clean AM-demod RTL-SDR capture; the
original WBFM-decoded values were systematically off, especially
sync_gap_us (was 670, real ≈ 4500)
- README has a Tom-setup-checklist for cold-start sessions
- 22/22 tests green
The original goal was an HA automation, not a CLI. Sketches the rest_command config and flags the three open items: stale legacy endpoint timing, no mDNS so nodemcu.local won't resolve, and the template integration if HA needs to model fan state properly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two HA-readiness fixes in one reflash:
1. Timing constants (SYNC_US, SYNC_GAP, PULSE_US, ZERO_GAP, ONE_GAP)
updated to the values measured from the AM-demod capture, matching
what's in devices/sofa_king_fan.yaml. The legacy /fan/{N}/{cmd}
endpoints now drive the fans correctly. Generic /transmit still
reads timing from the JSON payload — both paths now equivalent.
2. mDNS responder added: chip advertises as ceilingfans.local and
announces _http._tcp on :80 for service-discovery visibility.
No more IP-hunting after DHCP lease changes — both Tom's CLI
and HA's rest_command can use the stable hostname.
Also updates cli.py default --host to ceilingfans.local and refreshes
the README's HA notes (the previously-flagged caveats are now fixed)
plus the cold-start checklist (try the hostname before falling back
to serial-monitor IP-hunting).
Caveat for HA in Docker: bridge networking can't see mDNS. Use
network_mode: host or a DHCP reservation + hardcoded IP.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Standard hook set matching other active repos. Pre-push pytest gate. Move pre-commit and ruff to dev dependencies. Closes #5 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <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
.pre-commit-config.yamlwith standard hooks (trailing-whitespace, end-of-file-fixer, check-yaml, check-toml, check-merge-conflict, ruff lint + format)[tool.pytest.ini_options]to pyproject.tomlTest plan
Note: main has 14 local commits ahead of origin/main — Tom may need to push main before merging this PR.
Closes #5
🤖 Generated with Claude Code