|
1 | | -# Shield Remote |
| 1 | +# Something Remote |
2 | 2 |
|
3 | | -BLE HID remote control for Nvidia Shield using M5Stack Atom Echo and MicroPython. |
| 3 | +A port of [TheStockPot's Everything Remote](https://www.thestockpot.net/videos/theeverythingremote) to MicroPython, with changes that make it work much better on the Nvidia Shield by using a mix of BLE and Home Assistant. |
| 4 | + |
| 5 | +## Why BLE + Home Assistant? |
| 6 | + |
| 7 | +I found the HA actions on the original for navigation on the Shield had much too high latency, so I reimplemented the main nav buttons using BLE. You pair the remote to the Shield as a bluetooth remote and it works with very similar performance to the original Shield remote. |
| 8 | + |
| 9 | +For the HA actions I use MQTT auto-discovery with triggers for the buttons. To set up an automation in HA (after doing the WiFi setup including your MQTT broker), target the device as "Something Remote" and use the trigger dropdown to select the button you want. Remember to set the automation mode to "queued" if you want multiple presses to all process (e.g., for dimming a light). |
| 10 | + |
| 11 | +## Re-pairing |
| 12 | + |
| 13 | +- **BLE**: Hold **Power + Back** for 5 seconds |
| 14 | +- **WiFi/MQTT**: Hold **Shortcut1 + Shortcut3** for 5 seconds |
| 15 | + |
| 16 | +## Config |
| 17 | + |
| 18 | +You can select whether the power button works over BLE or triggers a Home Assistant automation. This depends on your setup and whether you need to trigger other actions on power on/off. Configure this in the WiFi setup portal. |
4 | 19 |
|
5 | 20 | ## Hardware |
6 | 21 |
|
7 | | -- M5Stack Atom Echo (ESP32-PICO-D4) |
8 | | -- Button: GPIO39 (top button) |
9 | | -- LED: GPIO27 (SK6812 NeoPixel) |
| 22 | +- Everything Remote v1.1 board (ESP32 with 21 buttons) |
| 23 | +- MPU6050 accelerometer for motion wake (optional) |
| 24 | + - SDA: GPIO33, SCL: GPIO22, INT: GPIO36 (VP) |
10 | 25 |
|
11 | 26 | ## Features |
12 | 27 |
|
13 | | -- BLE HID Keyboard profile |
14 | | -- Press button to send Right Arrow key |
15 | | -- LED status: Blue=advertising, Green=connected, White=key pressed |
16 | | -- Bonding keys stored in ESP32 NVS |
| 28 | +- **BLE HID** - Keyboard and Consumer Control for Shield navigation |
| 29 | +- **Home Assistant** - MQTT integration with auto-discovery |
| 30 | +- **Power Management** - Light sleep and deep sleep with motion wake |
| 31 | +- **Captive Portal** - WiFi/MQTT setup via browser |
17 | 32 |
|
18 | | -## Prerequisites |
| 33 | +## Quick Start - Flashing Pre-built Firmware |
19 | 34 |
|
20 | | -- Docker |
| 35 | +### Download |
21 | 36 |
|
22 | | -## Build (Docker) |
| 37 | +Get `something-remote-firmware.bin` from [Releases](../../releases/latest). |
23 | 38 |
|
24 | | -### 1. Build Docker Image (first time only) |
| 39 | +### Flash |
25 | 40 |
|
26 | | -```bash |
27 | | -make docker-build |
28 | | -``` |
| 41 | +1. **Connect** board via USB and find the port: |
| 42 | + - Linux: `/dev/ttyUSB0` |
| 43 | + - Mac: `/dev/cu.usbserial-*` |
| 44 | + - Windows: `COMx` (check Device Manager → Ports) |
29 | 45 |
|
30 | | -### 2. Build Firmware |
| 46 | +2. **Erase and flash**: |
| 47 | + ```bash |
| 48 | + # Using uv (recommended - no install needed) |
| 49 | + uvx esptool --port /dev/ttyUSB0 erase_flash |
| 50 | + uvx esptool --port /dev/ttyUSB0 write_flash 0x0 something-remote-firmware.bin |
31 | 51 |
|
32 | | -```bash |
33 | | -make build |
34 | | -``` |
| 52 | + # Or using pip |
| 53 | + pip install esptool |
| 54 | + esptool.py --port /dev/ttyUSB0 erase_flash |
| 55 | + esptool.py --port /dev/ttyUSB0 write_flash 0x0 something-remote-firmware.bin |
| 56 | + ``` |
35 | 57 |
|
36 | | -### 3. Copy Firmware to Local Directory |
| 58 | +3. **Configure**: Connect to "SomethingRemote-Setup" WiFi (password: `12345678`), enter your WiFi and MQTT settings |
37 | 59 |
|
38 | | -```bash |
39 | | -make copy-firmware |
40 | | -``` |
| 60 | +4. **Pair**: See [Pairing with Shield](#pairing-with-shield) below |
41 | 61 |
|
42 | | -### 4. Flash to Device |
| 62 | +## LED Status |
43 | 63 |
|
44 | | -Connect Atom Echo via USB, then: |
| 64 | +| Color | State | |
| 65 | +|-------|-------| |
| 66 | +| Blue | Advertising (ready to pair) | |
| 67 | +| Green | Connected to Shield | |
| 68 | +| White | Button pressed | |
| 69 | +| Purple | Home Assistant activity | |
| 70 | +| Yellow | Setup portal active | |
| 71 | +| Red | Error or BLE forget | |
45 | 72 |
|
46 | | -```bash |
47 | | -make flash PORT=/dev/ttyUSB0 |
48 | | -``` |
| 73 | +## Button Combos |
49 | 74 |
|
50 | | -Or flash manually with esptool: |
| 75 | +| Combo | Hold Time | Action | |
| 76 | +|-------|-----------|--------| |
| 77 | +| **Power + Back** | 5 seconds | Clear BLE bonds, restart advertising (for pairing) | |
| 78 | +| **Shortcut1 + Shortcut3** | 5 seconds | Enter WiFi/MQTT setup portal | |
51 | 79 |
|
52 | | -```bash |
53 | | -pip install esptool |
54 | | -esptool.py --chip esp32 --port /dev/ttyUSB0 write_flash -z 0x1000 build/firmware.bin |
55 | | -``` |
| 80 | +## Button Mapping |
56 | 81 |
|
57 | | -### Interactive Shell |
| 82 | +### BLE HID (Shield Control) |
| 83 | +- D-pad: Up/Down/Left/Right arrows |
| 84 | +- Select: Enter |
| 85 | +- Back: Consumer Control Back (AC Back) |
| 86 | +- Home: Consumer Control Home (AC Home) |
| 87 | +- Play/Pause, Vol+, Vol-, Mute: Consumer Control media keys |
| 88 | +- Ch+/Ch-: Page Up/Down |
58 | 89 |
|
59 | | -To debug or explore the build environment: |
| 90 | +### Home Assistant (MQTT) |
| 91 | +- Power: `power` action |
| 92 | +- Shortcuts 1-4: `shortcut_1` to `shortcut_4` actions |
| 93 | +- Brightness +/-: `brightness_up`/`brightness_down` actions |
60 | 94 |
|
61 | | -```bash |
62 | | -make shell |
63 | | -``` |
| 95 | +## Setup |
64 | 96 |
|
65 | | -## Usage |
| 97 | +### First Time Setup |
66 | 98 |
|
67 | | -1. After flashing, device starts advertising (blue LED) |
68 | | -2. On Nvidia Shield: Settings → Remote & Accessories → Add Accessory |
69 | | -3. Select "Shield Remote" |
70 | | -4. Once connected (green LED), press button to navigate right |
71 | | -5. LED flashes white on button press |
| 99 | +1. Flash firmware (see Build section) |
| 100 | +2. Device creates WiFi AP: "Something Remote Setup" |
| 101 | +3. Connect to AP, browser opens setup page |
| 102 | +4. Enter WiFi credentials and MQTT broker details |
| 103 | +5. Device restarts and connects |
72 | 104 |
|
73 | | -## Troubleshooting |
| 105 | +### Pairing with Shield |
| 106 | + |
| 107 | +1. Ensure LED is **blue** (advertising) |
| 108 | +2. If not blue, hold **Power + Back** for 5 seconds |
| 109 | +3. On Shield: Settings → Remote & Accessories → Add Accessory |
| 110 | +4. Select "Something Remote" |
| 111 | +5. LED turns **green** when connected |
| 112 | + |
| 113 | +### Re-entering Setup |
| 114 | + |
| 115 | +Hold **Shortcut1 + Shortcut3** for 5 seconds. LED turns yellow. |
| 116 | + |
| 117 | +## Power Management |
| 118 | + |
| 119 | +- **1 minute** idle → Light sleep (BLE stays active) |
| 120 | +- **5 minutes** of light sleep → Deep sleep |
| 121 | +- **Wake**: Any button press or motion (if MPU6050 installed) |
| 122 | + |
| 123 | +## Build |
| 124 | + |
| 125 | +### Prerequisites |
74 | 126 |
|
75 | | -- If Shield won't pair, ensure location services are enabled on Shield |
76 | | -- Use `screen /dev/ttyUSB0 115200` to view debug output |
77 | | -- Check BLE advertising with nRF Connect app on phone |
| 127 | +```bash |
| 128 | +# ESP-IDF v5.2.x |
| 129 | +cd ~ |
| 130 | +git clone -b v5.2.2 --recursive https://github.com/espressif/esp-idf.git |
| 131 | +cd esp-idf && ./install.sh esp32 && source export.sh |
| 132 | + |
| 133 | +# MicroPython |
| 134 | +cd ~ |
| 135 | +git clone https://github.com/micropython/micropython.git |
| 136 | +cd micropython && git checkout v1.24.1 && git submodule update --init |
| 137 | +make -C mpy-cross |
| 138 | +``` |
| 139 | + |
| 140 | +### Build & Flash |
| 141 | + |
| 142 | +```bash |
| 143 | +./build.sh |
| 144 | +./flash.sh /dev/ttyUSB0 |
| 145 | +``` |
78 | 146 |
|
79 | 147 | ## Project Structure |
80 | 148 |
|
81 | 149 | ``` |
82 | | -├── board/ATOM_ECHO/ # MicroPython board definition |
83 | | -├── modules/ # Python code (frozen into firmware) |
84 | | -│ ├── hid_services.py # BLE HID implementation |
85 | | -│ ├── shield_remote.py # Main application |
86 | | -│ └── main.py # Entry point |
87 | | -├── build.sh # Build script |
88 | | -└── flash.sh # Flash script |
| 150 | +├── board/ATOM_ECHO/ # MicroPython board definition |
| 151 | +├── modules/ # Python code (frozen into firmware) |
| 152 | +│ ├── shield_remote.py # Main application |
| 153 | +│ ├── hid_services.py # BLE HID implementation |
| 154 | +│ ├── hid_keystores.py # BLE bonding key storage |
| 155 | +│ ├── ha_client.py # Home Assistant MQTT client |
| 156 | +│ ├── wifi_setup.py # Captive portal for setup |
| 157 | +│ ├── config.py # Configuration storage |
| 158 | +│ ├── mpu6050_wake.py # Accelerometer motion wake |
| 159 | +│ ├── logger.py # File-based logging |
| 160 | +│ └── main.py # Entry point |
| 161 | +├── build.sh # Build script |
| 162 | +└── flash.sh # Flash script |
89 | 163 | ``` |
90 | 164 |
|
| 165 | +## Troubleshooting |
| 166 | + |
| 167 | +- **Can't pair**: Hold Power + Back 5 sec to clear bonds, then retry |
| 168 | +- **Can't see in Shield menu**: Check LED is blue, try nRF Connect app to verify advertising |
| 169 | +- **WiFi issues**: Hold Shortcut1 + Shortcut3 5 sec to re-enter setup |
| 170 | +- **Debug output**: `screen /dev/ttyUSB0 115200` |
| 171 | + |
91 | 172 | ## License |
92 | 173 |
|
93 | 174 | BLE HID library adapted from MicroPythonBLEHID (GPL-3.0). |
0 commit comments