diff --git a/Python/Python_Codes/00.0_HelloWorld/00.0_HelloWorld.py b/Python/Python_Codes/00.0_HelloWorld/HelloWorld.py similarity index 100% rename from Python/Python_Codes/00.0_HelloWorld/00.0_HelloWorld.py rename to Python/Python_Codes/00.0_HelloWorld/HelloWorld.py diff --git a/Python/Python_Codes/01.1_Blink/01.1_Blink.py b/Python/Python_Codes/01.1_Blink/Blink.py similarity index 100% rename from Python/Python_Codes/01.1_Blink/01.1_Blink.py rename to Python/Python_Codes/01.1_Blink/Blink.py diff --git a/Python/Python_Codes/02.1_Station_mode/02.1_Station_mode.py b/Python/Python_Codes/02.1_Station_mode/Station_mode.py similarity index 100% rename from Python/Python_Codes/02.1_Station_mode/02.1_Station_mode.py rename to Python/Python_Codes/02.1_Station_mode/Station_mode.py diff --git a/Python/Python_Codes/02.2_AP_mode/02.2_AP_mode.py b/Python/Python_Codes/02.2_AP_mode/AP_mode.py similarity index 100% rename from Python/Python_Codes/02.2_AP_mode/02.2_AP_mode.py rename to Python/Python_Codes/02.2_AP_mode/AP_mode.py diff --git a/Python/Python_Codes/02.3_AP+STA_mode/02.3_AP+STA_mode.py b/Python/Python_Codes/02.3_AP+STA_mode/AP+STA_mode.py similarity index 100% rename from Python/Python_Codes/02.3_AP+STA_mode/02.3_AP+STA_mode.py rename to Python/Python_Codes/02.3_AP+STA_mode/AP+STA_mode.py diff --git a/Python/Python_Codes/03.1_TCP_as_Client/03.1_TCP_as_Client.py b/Python/Python_Codes/03.1_TCP_as_Client/TCP_as_Client.py similarity index 100% rename from Python/Python_Codes/03.1_TCP_as_Client/03.1_TCP_as_Client.py rename to Python/Python_Codes/03.1_TCP_as_Client/TCP_as_Client.py diff --git a/Python/Python_Codes/03.2_TCP_as_Server/03.2_TCP_as_Server.py b/Python/Python_Codes/03.2_TCP_as_Server/TCP_as_Server.py similarity index 100% rename from Python/Python_Codes/03.2_TCP_as_Server/03.2_TCP_as_Server.py rename to Python/Python_Codes/03.2_TCP_as_Server/TCP_as_Server.py diff --git a/Python/Python_Codes/04.1_BLE/BLE.py b/Python/Python_Codes/04.1_BLE/BLE.py new file mode 100644 index 0000000..bad86fe --- /dev/null +++ b/Python/Python_Codes/04.1_BLE/BLE.py @@ -0,0 +1,100 @@ +# This example demonstrates a UART periperhal. + +import bluetooth +import random +import struct +import time +from ble_advertising import advertising_payload + +from micropython import const + +_IRQ_CENTRAL_CONNECT = const(1) +_IRQ_CENTRAL_DISCONNECT = const(2) +_IRQ_GATTS_WRITE = const(3) + +_FLAG_READ = const(0x0002) +_FLAG_WRITE_NO_RESPONSE = const(0x0004) +_FLAG_WRITE = const(0x0008) +_FLAG_NOTIFY = const(0x0010) + +_UART_UUID = bluetooth.UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E") +_UART_TX = ( + bluetooth.UUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E"), + _FLAG_READ | _FLAG_NOTIFY, +) +_UART_RX = ( + bluetooth.UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E"), + _FLAG_WRITE | _FLAG_WRITE_NO_RESPONSE, +) +_UART_SERVICE = ( + _UART_UUID, + (_UART_TX, _UART_RX), +) + + +class BLESimplePeripheral: + def __init__(self, ble, name="ESP32"): + self._ble = ble + self._ble.active(True) + self._ble.irq(self._irq) + ((self._handle_tx, self._handle_rx),) = self._ble.gatts_register_services((_UART_SERVICE,)) + self._connections = set() + self._write_callback = None + self._payload = advertising_payload(name=name, services=[_UART_UUID]) + self._advertise() + + def _irq(self, event, data): + # Track connections so we can send notifications. + if event == _IRQ_CENTRAL_CONNECT: + conn_handle, _, _ = data + print("New connection", conn_handle) + print("\nThe BLE connection is successful.") + self._connections.add(conn_handle) + elif event == _IRQ_CENTRAL_DISCONNECT: + conn_handle, _, _ = data + print("Disconnected", conn_handle) + self._connections.remove(conn_handle) + # Start advertising again to allow a new connection. + self._advertise() + elif event == _IRQ_GATTS_WRITE: + conn_handle, value_handle = data + value = self._ble.gatts_read(value_handle) + if value_handle == self._handle_rx and self._write_callback: + self._write_callback(value) + + def send(self, data): + for conn_handle in self._connections: + self._ble.gatts_notify(conn_handle, self._handle_tx, data) + + def is_connected(self): + return len(self._connections) > 0 + + def _advertise(self, interval_us=500000): + print("Starting advertising") + self._ble.gap_advertise(interval_us, adv_data=self._payload) + + def on_write(self, callback): + self._write_callback = callback + + +def demo(): + ble = bluetooth.BLE() + p = BLESimplePeripheral(ble) + + def on_rx(rx_data): + print("RX", rx_data) + + p.on_write(on_rx) + + print("Please use LightBlue to connect to ESP32.") + + while True: + if p.is_connected(): + # Short burst of queued notifications. + tx_data = input("Enter anything: ") + print("Send: ", tx_data) + p.send(tx_data) + + +if __name__ == "__main__": + demo() diff --git a/Python/Python_Codes/04.1_BLE/ble_advertising.py b/Python/Python_Codes/04.1_BLE/ble_advertising.py new file mode 100644 index 0000000..eed527f --- /dev/null +++ b/Python/Python_Codes/04.1_BLE/ble_advertising.py @@ -0,0 +1,93 @@ +# Helpers for generating BLE advertising payloads. + +from micropython import const +import struct +import bluetooth + +# Advertising payloads are repeated packets of the following form: +# 1 byte data length (N + 1) +# 1 byte type (see constants below) +# N bytes type-specific data + +_ADV_TYPE_FLAGS = const(0x01) +_ADV_TYPE_NAME = const(0x09) +_ADV_TYPE_UUID16_COMPLETE = const(0x3) +_ADV_TYPE_UUID32_COMPLETE = const(0x5) +_ADV_TYPE_UUID128_COMPLETE = const(0x7) +_ADV_TYPE_UUID16_MORE = const(0x2) +_ADV_TYPE_UUID32_MORE = const(0x4) +_ADV_TYPE_UUID128_MORE = const(0x6) +_ADV_TYPE_APPEARANCE = const(0x19) + + +# Generate a payload to be passed to gap_advertise(adv_data=...). +def advertising_payload(limited_disc=False, br_edr=False, name=None, services=None, appearance=0): + payload = bytearray() + + def _append(adv_type, value): + nonlocal payload + payload += struct.pack("BB", len(value) + 1, adv_type) + value + + _append( + _ADV_TYPE_FLAGS, + struct.pack("B", (0x01 if limited_disc else 0x02) + (0x18 if br_edr else 0x04)), + ) + + if name: + _append(_ADV_TYPE_NAME, name) + + if services: + for uuid in services: + b = bytes(uuid) + if len(b) == 2: + _append(_ADV_TYPE_UUID16_COMPLETE, b) + elif len(b) == 4: + _append(_ADV_TYPE_UUID32_COMPLETE, b) + elif len(b) == 16: + _append(_ADV_TYPE_UUID128_COMPLETE, b) + + # See org.bluetooth.characteristic.gap.appearance.xml + if appearance: + _append(_ADV_TYPE_APPEARANCE, struct.pack("