Added documentation

This commit is contained in:
Brikwerk 2020-09-15 19:30:50 -07:00
commit 518c7d44be
11 changed files with 412 additions and 23 deletions

356
README.md
View file

@ -1,34 +1,350 @@
# NXBT
<h1 align="center">
<br>
<img src="docs/img/nxbt-logo.png" alt="NXBT" width="200">
<br>
NXBT
<br>
</h1>
Control a Nintendo Switch Locally or Remotely
<h4 align="center">Control your Nintendo Switch through a website, terminal, or macro.</h4>
---
<div align="center">
This is meant to serve as an all-in-one solution to controlling a Nintendo Switch from a variety of devices.
[![Stars](https://img.shields.io/github/stars/brikwerk/nxbt.svg)]()
[![GitHub Issues](https://img.shields.io/github/issues/brikwerk/nxbt.svg)](https://github.com/brikwerk/ctqa/issues)
[![GitHub Pull Requests](https://img.shields.io/github/issues-pr/brikwerk/nxbt.svg)](https://github.com/brikwerk/ctqa/pulls)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](/LICENSE)
Functionality is currently under development.
</div>
## Prerequisites
<p align="center">
<a href="#key-features">Key Features</a> •
<a href="#installation">Installation</a> •
<a href="#getting-started">Getting Started</a> •
<a href="#troubleshooting">Troubleshooting</a> •
<a href="#credits">Credits</a> •
<a href="#license">License</a>
</p>
- A Bluetooth adapter with a Bluetooth version greater than or equal to 4.0
- A computer running Linux
- A Nintendo Switch
![screenshot](docs/img/nxbt-example.png)
## Key Features
- Use your favourite web browser to control a Nintendo Switch with any keyboard or gamepad.
- Use your terminal to control a Nintendo Switch with a keyboard.
- Use a macro from your terminal, browser, or Python script
- Use the NXBT Python API to write programs to control your Nintendo Switch.
- Primitive loop support in macros.
- In-depth command line interface.
- Support for emulating multiple controllers at once.
- Support for fast connection or reconnection to a Nintendo Switch.
- Emulated ontrollers support thread-safe access.
## Installation
### Linux
```bash
sudo pip3 install nxbt
```
**Please Note:** NXBT needs root privileges to toggle the BlueZ Input plugin. If you're not comfortable running this program as root, you can disable the Input plugin manually, and install NXBT as a regular user.
### MacOS
Coming Soon (time permitting)
### Windows
Under Investigation
## Getting Started
TBA
**Note:** If you installed NXBT as a non-root user, please omit the use of `sudo` from any of the following commands.
## TODO
### Running the demo
- Rebinding of keys within the TUI and webapp
- Incorporate React and components library into the webapp
- Allow for recording macros from direct input from within the webapp
- Allow for playing recorded direct input macros from the API
- Write a full testing suite
The demo is meant to gauge whether or not NXBT is working. To do so, the demo will create a Pro Controller and run through a small loop of commands.
**NOTE:** If this is your first time connecting to an NXBT emulated controller on the specific host computer, you **MUST** have the "Change Grip/Order Menu" open on your Nintendo Switch. You can see how to navigate to the "Change Grip/Order Menu" [HERE](docs/img/change-grip-order-menu.png).
To start the demo, run the following command in your terminal:
```bash
sudo nxbt demo
```
If all is working correctly, the controller should connect, navigate to the settings, test the stick calibration, and navigate back to the "Change Grip/Order Menu".
### Using the Webapp
The NXBT webapp provides a web interface that allows for quick creation of a Nintendo Switch controller and use of a keyboard or gamepad to control the Nintendo Switch. This lets anyone who can access the website control a Nintendo Switch with their favourite keyboard or gamepad.
The webapp server can be started with the following command:
```bash
sudo nxbt webapp
```
The above command boots NXBT and an accompanying web server that allows for controller creation and use over your web browser.
The webapp itself will be locally accessible at `http://127.0.0.1:8000` or, if you're on the same network as the host computer, http://HOST_COMPUTER_IP:8000. It's also possible to expose your NXBT webapp to the internet, however, you'll need to configure a reverse proxy, which is out of the scope of this readme.
You should see a webpage similar to the following image:
<div style="text-align:center">
<img src="docs/img/nxbt-webapp-start.png" alt="NXBT Webapp Start Screen" width="600">
</div>
To create and start a Pro Controller, click the Pro controller graphic. If creation/boot is successful, the website will switch to a loading screen. During this time, you should have the Nintendo Switch you wish to connect to powered on and within range of the host computer.
**NOTE:** If this is your first time connecting to your Nintendo Switch with the specific host computer, make sure you're on the "Change Grip/Order Menu". If you're still unable to connect, try running the demo (in the above section) or refer to the troubleshooting documentation.
Once you've successfully connected to the Nintendo Switch, you should see a webpage similar to below:
<div style="text-align:center">
<img src="docs/img/nxbt-webapp-connected.png" alt="NXBT Webapp Start Screen" width="600">
</div>
Here, you can change your input method, shutdown or restart the controller, and run an NXBT macro.
A few other functions to note:
- If you exit the webpage, the controller will shutdown.
- Once you've connected over the "Change Grip/Order Menu", NXBT will automatically reconnect. This applies on a per-Bluetooth-adapter basis.
- Most gamepads should be usable over the browser. To get started with a gamepad, click a button and it should show up under the input dropdown list. If it doesn't show up, try another browser. Chrome is the recommended standard as it seems to have the best gamepad support currently (as of September 2020)
### Using the TUI
The TUI (Terminal User Interface) allows for local or remote (SSH/Mosh) terminal sessions to control a Nintendo Switch with a keyboard.
The TUI can be started with:
```bash
sudo nxbt tui
```
**NOTE:** If this is your first time connecting to your Nintendo Switch with the specific host computer, make sure you're on the "Change Grip/Order Menu". If you're still unable to connect, try running the demo (in the above section) or refer to the troubleshooting documentation.
A loading screen should open and, once connected, the main TUI control screen should load. This should look something like below:
<div style="text-align:center">
<img src="docs/img/nxbt-tui.png" alt="NXBT Webapp Start Screen" width="600">
</div>
There are two types of NXBT TUI sessions:
1. **Remote Mode (pictured above):** When connecting over an SSH (or Mosh) connection, "Remote Mode" is used to compensate for keyup events not being sent over remote terminal sessions. This functionally means that "Remote Mode" is a bit less responsive than "Direct Mode".
2. **Direct Mode:** When running the NXBT TUI directly on the host computer, keyboard key presses are taken directly from any keyboard plugged in.
Once you've successfully connected to a Nintendo Switch over the "Change Grip/Order Menu", you can reconnect quickly to the same Switch with the following command:
```bash
sudo nxbt tui -r
```
A couple other funcionality notes:
- Press 'q' to exit the TUI.
- In Direct Mode, press Escape to toggle input to the Nintendo Switch.
- NXBT looks for SSH and Mosh connections before deciding whether or note Remote Mode should be used. If you use another method for creating a remote terminal instance, NXBT likely won't detect it. Please open an issue if this happens to you!
### Running Macros
NXBT provides three ways to run macros on your Nintendo Switch:
1. The NXBT Webapp (easiest)
2. The CLI
3. The Python API
For the first method, refer to the "Using the Webapp" section for more info.
#### Running Macros with the Command Line Interface
To run a simple, inline macro, you can use the following command:
```bash
sudo nxbt macro -c "B 0.1s\n 0.1s"
```
The above command will press the B button for 0.1 seconds and release all buttons for 0.1 seconds. The `-c` flag specifies the commands you would like to run. You'll need to be on the "Change Grip/Order Menu" for the above command to work. If you've already connected to the Switch on the host computer, you can reconnect and run the macro by adding the `-r` or `--reconnect` flag:
```bash
sudo nxbt macro -c "B 0.1s\n 0.1s" -r
```
Since it can be a little cumbersome typing out a large macro in the terminal, the macro command also supports reading from text files instead!
commands.txt file:
```
B 0.1s
0.1s
```
```bash
sudo nxbt macro -c "commands.txt" -r
```
If you want more information on NXBT's CLI arguments:
```bash
sudo nxbt -h
```
#### Running Macros with the Python API
Macros are supported with the `macro` function in the Python API. All macros are expected as strings (multiline strings are accepted).
Minimal working example:
```python
import nxbt
macro = """
B 0.1s
0.1s
"""
# Start the NXBT service
nx = nxbt.Nxbt()
# Create a Pro Controller and wait for it to connect
controller_index = nx.create_controller(nxbt.PRO_CONTROLLER)
nx.wait_for_connection(controller_index)
# Run a macro on the Pro Controller
nx.macro(controller_index, macro)
```
The above example uses a blocking macro call, however, multiple macros can be queued (or other actions taken) with the non-blocking syntax. Queued macros are processed in FIFO (First-In-First-Out) order.
```python
# Run a macro on the Pro Controller but don't block.
# In this instance, we record the macro ID so we can keep track of its status later on.
macro_id = nx.macro(controller_index, macro, block=False)
from time import sleep
while macro_id not in nx.state[controller_index]["finished_macros"]:
print("Macro hasn't finished")
sleep(1/10)
print("Macro has finished")
```
### Using the API
NXBT provides a Python API for use in Python applications or code.
If you're someone that learns by example, check out the `demo.py` file located at the root of this project.
For a more in-depth look at all the functionality provided by the API, checkout the `nxbt/nxbt.py` file.
For those looking to get started with a few simple examples: Read on!
**Creating a Controller and Waiting for it to Connect**
```python
import nxbt
# Start the NXBT service
nx = nxbt.Nxbt()
# Create a Pro Controller and wait for it to connect
controller_index = nx.create_controller(nxbt.PRO_CONTROLLER)
nx.wait_for_connection(controller_index)
print("Connected")
```
**Pressing a Button**
```python
# Press the B button
# press_buttons defaults to pressing a button for 0.1s and releasing for 0.1s
nx.press_buttons(controller_idx, [nxbt.Buttons.B])
# Pressing the B button for 1.0s instead of 0.1s
nx.press_buttons(controller_idx, [nxbt.Buttons.B], down=1.0)
```
**Tilting a Analog Stick**
```python
# Tilt the right stick fully to the left.
# tilt_stick defaults to tilting the stick for 0.1s and releasing for 0.1s
nx.tilt_stick(controller_idx, Sticks.RIGHT_STICK, -100, 0)
# Tilting the stick for 1.0s instead of 0.1s
nx.tilt_stick(controller_idx, Sticks.RIGHT_STICK, -100, 0, tilted=1.0)
```
**Getting the available Bluetooth adapters**
```python
# This prints the device paths for each available adapter.
# If a controller is in use, an adapter will be removed from this list.
print(nx.get_available_adapters)
```
**Shutting Down a running Controller**
```python
# This frees up the adapter that was in use by this controller
nx.remove_controller(controller_index)
```
**Reconnecting to a Switch**
```python
# Get a list of all previously connected Switches and pass it as a reconnect_address argument
controller_index = nx.create_controller(
nxbt.PRO_CONTROLLER,
reconnect_address=nx.get_switch_addresses())
```
**Stopping or Clearning Macros**
```python
# Stops/deletes a single macro from a specified controller
nx.stop_macro(controller_index, macro_id)
# Clears all macros from a given controller
nx.clear_macros(controller_index)
# Clears all macros from every created controller
nx.clear_all_macros()
```
## Troubleshooting
### "No Available Adapters"
This means that NXBT wasn't able to find a suitable Bluetooth adapter to use for Nintendo Switch controller emulation. Only one controller can be emulated per adapter on the system, so if you've got one Bluetooth adapter available, you'll only be able to emulate one Nintendo Switch controller. The general causes (and solutions) to the above error follows:
1. **Cause:** All available adapters are currently emulating a controller.
- **Solution:** End one of the other controller sessions (either through the webapp or command line) or plug in another Bluetooth adapter.
2. **Cause:** No Bluetooth adapters are available to NXBT.
- **Solution:** Ensure that you've installed the relevant Bluetooth stack for your operating system (BlueZ on Linux) and check that your Bluetooh adapter is visible within to your OS.
### "Address already in use"
This means that another service has already bound itself to the Control and Interrupt ports on the specified Bluetooth adapter. Causes/solutions follow:
1. **Cause:** (Linux specific solution) This is typically the BlueZ input plugin binding itself to the Control/Interrupt ports for your adapter.
- **Solution:** Either disable the input plugin (you will lose access to Bluetooth keyboards/mice while it is disabled) or install NXBT as root to allow for temporary toggling of the Input plugin.
## Future Plans
1. Allows for rebinding keys within the TUI and webapp
2. Add a touchscreen input option for the webapp to enable input on smartphones
3. Transition the webapp to a more maintainable React build
4. Allow for recording macros from direct input within the webapp
5. Allow for replaying recorded input
6. Write a full testing suite
### Plans that Need More Testing
- Use mouse movement as right stick input
## Issues
- Switching from the slow frequency mode on the "Change Grip/Order" menu to the full input report
frequency is still a bit of a frail process. Some game start menus have a frequency of 15Hz
but specifically only allow exiting by pressing the A button. The "Change Grip/Order" menu
allows for exiting with A, B, or the Home button, however.
- Switching from the slow frequency mode on the "Change Grip/Order" menu to the full input report frequency is still a bit of a frail process. Some game start menus have a frequency of 15Hz but specifically only allow exiting by pressing the A button. The "Change Grip/Order" menu allows for exiting with A, B, or the Home button, however.
- The webapp can sometimes have small amounts of input lag (<8ms).
## Credits
A big thank you goes out to all the contributors at the [dekuNukem/Nintendo_Switch_Reverse_Engineering](https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering) repository! Almost all information pertaining to the innerworkings of the Nintendo Switch Controllers comes from the documentation in that repo. Without it, NXBT wouldn't have been possible.
## License
MIT

71
docs/Macros.md Normal file
View file

@ -0,0 +1,71 @@
# NXBT Macros
## Writing an NXBT Macro
Each NXBT macro line is composed of the buttons/sticks being set and the amount of time they are set for. A simple macro follows:
```
B 0.1s
0.1s
```
The above macro is the B button being pressed for 0.1s and no controls being set for 0.1s. This is effectively a single B button press.
A slightly more complicated example follows:
```
A B 0.5s
B 0.1s
0.1s
```
This new macro, first, has both the A and the B button being pressed for 0.5s. Next, the A button is released and the B button continues to be held for an additional 0.1s. Finally, no controls are set for 0.1s.
The above macros deal with only button-based input. A stick input example follows:
```
L_STICK@-100+000 0.75s
1.0s
```
Above, we're setting the left analog stick to 100% in the left horizontal direction. To explain, analog stick positions are composed of two values: and X position and Y position. You can think of both as positions on a traditional X/Y plane, with X being the horizontal component and Y being the vertical component. An X/Y of 0/0 means that the analog stick is in a neutral position (no input), while an X/Y position of 0/100 means our stick is tilted 100% up.
<div style="text-align:center">
<img src="img/pro-controller-stick-axis.jpg" alt="NXBT Webapp Start Screen" width="300">
</div>
To be clear, the first numeric argument after L_STICK@ is the X value and the second is the Y value. Eg: An X value of 50 and a Y Value of 25 on the right stick would be `R_STICK@+050+025`.
As such, a neutral stick position is as follows:
```
L_STICK@+000+000 0.75s
1.0s
```
## Macro Control Values
| Macro Value | Control Name |
--- | ---
Y | Y Button
X | X Button
B | B Button
A | A Button
JCL_SR | Left Joy-Con SR
JCL_SL | Left Joy-Con SL
R | Upper Right Shoulder Trigger
ZR | Lower Right Shoulder Trigger
MINUS | Minus Button
PLUS | Plus Button
R_STICK_PRESS | Right Stick Press
L_STICK_PRESS | Left Stick Press
HOME | Home Button
CAPTURE | Capture Button
DPAD_DOWN | Down Button on the DPad
DPAD_UP | Up Button on the DPad
DPAD_RIGHT | Right Button on the DPad
DPAD_LEFT | Left Button on the DPad
JCR_SR | Right Joy-Con SR
JCR_SL | Right Joy-Con SL
L | Upper Left Shoulder Trigger
ZL | Lower Left Should Trigger

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 KiB

BIN
docs/img/nxbt-example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

BIN
docs/img/nxbt-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
docs/img/nxbt-tui.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View file

@ -8,8 +8,9 @@ project_urls =
Issue tracker = https://github.com/Brikwerk/nxbt/issues
license = MIT
license-file = LICENSE
description = Control a Nintendo Switch Locally or Remotely
description = Control your Nintendo Switch through a website, terminal, or macro.
long-description = file: README.md
long_description_content_type = 'text/markdown',
platform = any
url = https://pypi.python.org/pypi/nxbt
classifiers =

View file

@ -1,6 +1,6 @@
import setuptools
from setuptools import setup
setuptools.setup(
setup(
name="nxbt",
install_requires=[
"dbus-python>=1.2.16",
@ -9,6 +9,7 @@ setuptools.setup(
"eventlet>=0.25.2",
"blessed>=1.17.9",
"pynput>=1.6.8",
"psutil>=5.5.1",
],
extra_require={
"dev": [