-
-
Save CubeLegend/f77c6f0d8b2aaee78a30d2c6508cdaf2 to your computer and use it in GitHub Desktop.
Connecting to an Xbox one controller
This file contains 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
import binascii | |
import ubluetooth | |
from micropython import const | |
_IRQ_CENTRAL_CONNECT = const(1) | |
_IRQ_CENTRAL_DISCONNECT = const(2) | |
_IRQ_GATTS_WRITE = const(3) | |
_IRQ_GATTS_READ_REQUEST = const(4) | |
_IRQ_SCAN_RESULT = const(5) | |
_IRQ_SCAN_DONE = const(6) | |
_IRQ_PERIPHERAL_CONNECT = const(7) | |
_IRQ_PERIPHERAL_DISCONNECT = const(8) | |
_IRQ_GATTC_SERVICE_RESULT = const(9) | |
_IRQ_GATTC_SERVICE_DONE = const(10) | |
_IRQ_GATTC_CHARACTERISTIC_RESULT = const(11) | |
_IRQ_GATTC_CHARACTERISTIC_DONE = const(12) | |
_IRQ_GATTC_DESCRIPTOR_RESULT = const(13) | |
_IRQ_GATTC_DESCRIPTOR_DONE = const(14) | |
_IRQ_GATTC_READ_RESULT = const(15) | |
_IRQ_GATTC_READ_DONE = const(16) | |
_IRQ_GATTC_WRITE_DONE = const(17) | |
_IRQ_GATTC_NOTIFY = const(18) | |
_IRQ_GATTC_INDICATE = const(19) | |
_IRQ_GATTS_INDICATE_DONE = const(20) | |
_IRQ_MTU_EXCHANGED = const(21) | |
_IRQ_L2CAP_ACCEPT = const(22) | |
_IRQ_L2CAP_CONNECT = const(23) | |
_IRQ_L2CAP_DISCONNECT = const(24) | |
_IRQ_L2CAP_RECV = const(25) | |
_IRQ_L2CAP_SEND_READY = const(26) | |
_IRQ_CONNECTION_UPDATE = const(27) | |
_IRQ_ENCRYPTION_UPDATE = const(28) | |
_IRQ_GET_SECRET = const(29) | |
_IRQ_SET_SECRET = const(30) | |
_ADV_IND = const(0x00) | |
_ADV_DIRECT_IND = const(0x01) | |
_ADV_SCAN_IND = const(0x02) | |
_ADV_NONCONN_IND = const(0x03) | |
_UART_SERVICE_UUID = ubluetooth.UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E") | |
_UART_RX_CHAR_UUID = ubluetooth.UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E") | |
_UART_TX_CHAR_UUID = ubluetooth.UUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E") | |
class BLESimpleCentral: | |
def __init__(self, ble): | |
self.gamepad_name = None | |
self.gamepad_addr_type = None | |
self.gamepad_addr = None | |
self._ble = ble | |
self._ble.active(True) | |
self._ble.irq(self.bt_irq) | |
def bt_irq(self, event, data): | |
if event == _IRQ_SCAN_RESULT: | |
# A single scan result. | |
addr_type, addr, adv_type, rssi, adv_data = data | |
if find_adv_name(adv_data) is None: | |
return | |
print('Address-Type: ', addr_type) | |
print('Address: ', [hex(n) for n in addr]) | |
print('ADV-Type: ', adv_type) | |
print('RSSI in dBm: ', rssi) | |
print('ADV-Data: ', [hex(n) for n in adv_data]) | |
print('ADV-Data (Name): ', find_adv_name(adv_data)) # Xbox Wireless Controller | |
print() | |
if find_adv_name(adv_data) == "Xbox Wireless Controller": | |
self.gamepad_name = find_adv_name(adv_data) | |
self.gamepad_addr_type = addr_type | |
self.gamepad_addr = addr | |
self._ble.gap_scan(None) | |
self.connect() | |
elif event == _IRQ_SCAN_DONE: | |
# Scan duration finished or manually stopped. | |
pass | |
elif event == _IRQ_PERIPHERAL_CONNECT: | |
# A successful gap_connect(). | |
conn_handle, addr_type, addr = data | |
print("connect") | |
print(data) | |
print('Address-Type: ', addr_type) | |
print('Address: ', [hex(n) for n in addr]) | |
print() | |
elif event == _IRQ_PERIPHERAL_DISCONNECT: | |
# Connected peripheral has disconnected. | |
conn_handle, addr_type, addr = data | |
print("disconnect") | |
print(data) | |
print('Address-Type: ', addr_type) | |
print('Address: ', [hex(n) for n in addr]) | |
print() | |
# Find a device advertising the environmental sensor service. | |
def scan(self): | |
self._ble.gap_scan(5000, 100000, 25000, True) | |
def connect(self): | |
print(self.gamepad_addr) | |
self._ble.gap_connect(self.gamepad_addr_type, self.gamepad_addr) | |
def find_adv(adv_type, data): | |
i = 0 | |
while i + 1 < len(data): | |
ad_structure_len = data[i] | |
ad_structure_type = data[i + 1] | |
ad_structure_payload = data[i + 2: i + ad_structure_len + 1] | |
if ad_structure_type == adv_type: | |
return ad_structure_payload | |
i += ad_structure_len + 1 | |
return None | |
def find_adv_name(data): | |
n = find_adv(9, data) | |
if n: | |
return str(n, 'UTF-8') # Text | |
return None | |
def demo(): | |
ble = ubluetooth.BLE() | |
central = BLESimpleCentral(ble) | |
central.scan() | |
def demo_connect(): | |
ble = ubluetooth.BLE() | |
central = BLESimpleCentral(ble) | |
central.connect() | |
if __name__ == "__main__": | |
demo() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment