Repository navigation
Conversation
jw098
marked this pull request as draft
October 19, 2026 04:42
Adds _pa_core, a pybind11 module (new PA_PYTHON_BINDINGS cmake option, OFF by default) that wraps the existing CoreLib class NintendoSwitch::PybindSwitchProController so Python can act as a Nintendo Switch controller through a PABotBase2 serial device: status, queued button / d-pad / stick commands, flush and cancel, button/d-pad constants, and log-to-stderr/file controls. C++ exceptions surface as RuntimeError; blocking calls release the GIL. The pokemon_automation Python package sits on top of it: SwitchController (button names instead of bitfields), button parsing, list_serial_ports(), a hardware-free FakeController, a hardware self-test, and a pytest suite. See SerialPrograms/Source/PythonBindings/README.md. A new CI workflow builds the GUI-free core plus the module on Ubuntu and runs the pytest suite. PR #1519 is used as a reference.
jw098
force-pushed
the
python-pybind-basic
branch
from
October 19, 2026 05:37
23b3635 to
871232d
Compare
…ng CoreLib The rebased branch picked up AbstractController::cancel_all_and_wait() (cancel + wait for the device to acknowledge the neutral state, returns a bool), which replaced the old fire-and-forget cancel_all_commands(). Update the _pa_core binding, the pokemon_automation API (cancel_all_and_wait() now returns whether the device confirmed; close() uses it to guarantee a neutral state), the fake controller, the tests, and the docs. Also compile the third-party 3rdParty-Core/miniz-3.1.1/miniz.c with warnings off (/W0 on MSVC, -w on GCC/Clang): it is compiled straight into CoreLib, and newer compilers emit warnings in it that -Werror / /WX turn into build errors. It includes miniz.h from its own directory, so a SYSTEM include directory cannot shield it; suppressing the file itself is the portable fix.
…ties() The old copy in CMakeLists.txt only runs in the full build: with PA_CORE_ONLY the configure returns before reaching it, so miniz.c was still compiled with -Werror / /WX in core-only builds. Setting the source property from pa_apply_base_target_properties() (cmake/CoreLib.cmake) covers both build modes and every target that uses it; the two now-redundant copies are removed. Use if(MSVC) instead of if(WIN32) - the flag choice follows the compiler's command-line dialect (true for cl and for clang-cl), and COMPILE_OPTIONS instead of the deprecated COMPILE_FLAGS.
…e PA_CORE_ONLY miniz.c is compiled into every target that uses CORE_LIBRARY_SOURCES - CoreLib in both build modes, and SerialProgramsLib in the full build (which compiles its own copy of the core sources), so the fix belongs in the base CMakeLists.txt, not CoreLib.cmake. It must also run before the PA_CORE_ONLY early return, which is where the old copy at the bottom of the file (from #1098) was, and why core-only builds still failed. Source properties are global, so one set_source_files_properties() covers all targets; verified that in a full build both CoreLib's and SerialProgramsLib's miniz.c compile lines carry the suppression.
jw098
marked this pull request as ready for review
October 19, 2026 17:43
jw098
marked this pull request as draft
October 19, 2026 17:43
- 'simulatenously' -> 'simultaneously' - selftest code block: [port] is not shell syntax; show the optional argument as a real example instead - rename 'Running the test file' to 'Hardware self-test' (the pytest suite lives in tests/) and add the missing 'Running the unit tests' section, which the Layout section advertises but nothing in the file explained - add wait() to the method list (it is used in the example) - drop trailing whitespace
jw098
marked this pull request as ready for review
October 19, 2026 20:00
jw098
marked this pull request as draft
October 19, 2026 20:29
Add comments naming the C++ source each Python definition mirrors or depends on (repo-relative paths): the BUTTON_BITS/DPAD_POSITIONS constants and check_against_core() vs the enums in NintendoSwitch_ControllerButtons.h; the ControllerBackend protocol, status/flush/cancel_all_and_wait and press() vs PybindSwitchProController / AbstractController; the fake and the _core loader vs the module source and the wrapped class; and the test headers. Also note that DEFAULT_HOLD_MS/DEFAULT_RELEASE_MS are Python-side defaults (the C++ issue_buttons() takes explicit durations).
The command methods of SwitchController now match the names of the
_p a_core.Controller methods they wrap (and thus the C++
PybindSwitchProController methods):
- press() -> push_button() / push_dpad() (mixed combos now go to
controller_state(); each method rejects the other kind
with a pointer to the right method)
- hold() -> controller_state() (duration_ms first, like the C++
signature; no implicit release wait)
- stick(side) -> push_left_joystick() / push_right_joystick()
- flush() -> wait_for_all_requests()
- status() -> current_status()
- name() -> controller_name()
- wait(), cancel_all_and_wait(), is_ready() and close() already matched.
Button-name parsing is unchanged; _pa_core and FakeController are
untouched. Updated examples in the package docstrings, README,
switch_connection_test.py and the tests (31 tests now, including
rejection of mixed inputs in push_button()/push_dpad()).
Each call now queues exactly one tap, matching the single-command semantics of the C++ layer; repeated presses are just repeated calls (or a controller_state() with a longer hold).
…ation/Arduino-Source into python-pybind-basic
Drop the FetchContent fallback. If pybind11 is not found (system package or pip-installed for the target interpreter), configure now fails with a FATAL_ERROR that names the interpreter and gives the install commands, instead of silently git-cloning a pinned pybind11 release during configure. Builds no longer reach the network on their own. README updated to match.
- controller.py: cancel_all_and_wait() docstring cited the old C++\n parameter name (timeout_millis -> timeout_ms).\n- README: 'insid' -> 'inside', 'run the all tests' -> 'run all the tests',\n queue examples used a nonexistent duration kwarg (now hold_ms, which is\n what push_left_joystick() actually takes), and mkdir bin -> mkdir -p bin\n so the instructions work on a re-run.\n- test_push_right_joystick now actually passes a [x, y] list, matching its\n docstring (lists are accepted via parse_stick_pair).
close() no longer lets a command slip in after the cancel: the closed flag is set under the command lock, and every command method re-checks it while holding the lock before sending, so commands starting while the cancel is in flight are rejected.
jw098
force-pushed
the
python-pybind-basic
branch
from
October 22, 2026 22:04
a9db077 to
b1698ea
Compare
…eturns
nullptr for an empty name, leaving m_connection null and crashing
current_status(). The constructor, destructor, controller() and
current_status() now tolerate a null connection ("No connection."), and
SwitchController rejects an empty port up front with a ValueError.
#1 Destruction race (PybindSwitchController.cpp): the connection thread is joined only when m_connection is destroyed, i.e. after m_controller, m_cv and m_lock already were. Destroying the controller while a connection is still establishing (e.g. SwitchController's timeout path) let the connect thread write to destroyed members. The destructor now resets m_connection first, so the thread is joined before any member is destroyed. #2 Empty port name: SerialPABotBase2_Descriptor::open_connection() returns nullptr for an empty name, leaving m_connection null and crashing current_status(). The constructor, destructor, controller() and current_status() now tolerate a null connection ("No connection."), and SwitchController rejects an empty port up front with a ValueError.
jw098
force-pushed
the
python-pybind-basic
branch
from
October 22, 2026 22:57
1b6d376 to
3d248db
Compare
jw098
marked this pull request as ready for review
October 23, 2026 01:09
jw098
reviewed
Oct 23, 2026
Mysticial
reviewed
Oct 24, 2026
Mysticial
reviewed
Oct 24, 2026
Collaborator
|
I've looked through about half the files so far. Still working on the rest. I'm wondering if we should rename |
Matches the C++ class it wraps (PybindSwitchProController) and the device's controller type (the Pro Controller / wired controller). No backwards-compat alias: the package is pre-release (0.1.0).
START/SELECT/L3/LS/R3/RS and the "+"/"-" spellings no longer map to PLUS/MINUS/LCLICK/RCLICK. "+" remains a separator (a lone "+" parses to no input), and "-" and the former alias names are now unknown buttons with the usual ValueError. Removed the now-dead "+"/"-" special cases in _split()/parse_buttons(), the __init__ export, and the docs; the alias test now pins the new behavior.
Mysticial
approved these changes
Oct 25, 2026
Mysticial
left a comment
Collaborator
There was a problem hiding this comment.
Approved at a high level. Rubber stamping most of the Python details. API seems ok.
We'll want to follow up later with a Python TurboA or something just to feel it out before we commit to the API. But at least we're not a in a hurry, gen10 is a year away.
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.
Basic Python interface using pybind11, so a Python developer can send simple commands to the microcontroller. Used PR #1519 as a reference, but kept this to the small, well-understood part of it (no MCP server, video or OCR).
What's in it
_pa_core(new,SerialPrograms/Source/PythonBindings/PythonBindings_Module.cpp): a pybind11 module that wraps the existing CoreLib classNintendoSwitch::PybindSwitchProController— a thin 1:1 binding:Controller(port)+wait_for_ready(),is_ready(),current_status(),controller_name()push_button(),push_dpad(),push_left_joystick(),push_right_joystick(),controller_state(),wait(), pluswait_for_all_requests()(flush) andcancel_all_and_wait(timeout_ms)(cancel + wait for the device to confirm the neutral state, returns a bool)BUTTONS/DPAD_POSITIONSconstants generated from the C++ enumsset_log_stderr(),set_log_file(),log(),recent_logs()) — nothing goes to stdoutPokemonAutomation::Exception-> PythonRuntimeError; blocking calls release the GILpokemon_automationPython package on top of it:SwitchControllerwith button names instead of bitfields:sw.press("L+R"),sw.press("up", repeat=2),sw.stick("left", "up", duration_ms=1500),sw.hold("B", left="up"),sw.flush(),sw.cancel_all_and_wait();close()cancels with confirmation firstbuttons.py(name parsing, verified against the C++ enums),devices.list_serial_ports(),fake.FakeControllerfor tests without hardware,python -m pokemon_automation.selftest [port]for a quick hardware checkpip install -e SerialPrograms/Source/PythonBindingsworksPA_PYTHON_BINDINGSoption (OFF by default, so existing builds/CI are unaffected), wired into both the full andPA_CORE_ONLYbuilds. pybind11 is picked up from a system package orpip install pybind11, with a pinnedFetchContentfallback.3rdParty-Core/miniz-3.1.1/miniz.cis compiled into every target that usesCORE_LIBRARY_SOURCES— CoreLib in both build modes, and SerialProgramsLib in the full build. It now gets a per-file warning suppression (/W0on MSVC,-won GCC/Clang) set in the baseCMakeLists.txtbefore thePA_CORE_ONLYearly return (the old copy from File Unzip using miniz library #1098 sat below it, so core-only builds never got it; source properties are global, so one setting covers all targets). It includes its own header from its own directory, so no SYSTEM include directory can shield it, andif(MSVC)/COMPILE_OPTIONSreplace the oldif(MSVC)-with-COMPILE_FLAGSform.Example
Verified (aarch64 Linux)
-w; module builds clean_pa_coreisn't built)Notes / follow-ups
A CI workflow for this (core-only build + pytest on Ubuntu) is ready locally but the bot's token can't push
.github/workflows/files (noworkflowscope) — a maintainer can add it:PR Agent mcp server #1519 extends this with the full package (MCP server, video, OCR) — this PR is meant to land as the understood foundation for that.