BLE

Let’s take a look at the hierarchy of the system we are about to design:

graph LR
    subgraph "DevBoard (Rust)"
        subgraph "Front End"
            A2(LED)
        end

        subgraph "Back End"
            B2(BLE)
            C2(Events)
            D2(Logic)
        end

        B2 --> C2 --> D2 --> A2
        D2 --> B2
    end

    subgraph "Phone (Swift)"
        subgraph "Front End"
            A1(UI)
            B1(Alerts)
        end

        subgraph "Back End"
            C1(Delegate)
            D1(Logic)
            E1(BLE)
        end

        A1 --> C1 --> D1 <--> E1
        D1 --> B1
    end

    B2 <--> E1

Now, I know this looks complicated, but we will tackle each block one by one, nice and slow.

Once you are done with this, you will have a solid understanding of creating systems involving bidirectional communication between 2 devices, which is super useful for a ton of applications (including your final project).

So let’s get started.

How Does BLE Work?

Modern BLE (Bluetooth Low Energy) systems rely on the Service -> Characteristic architecture.

Your iPhone can scan for BLE devices advertising services, to decide whether to connect to them or not.

A service is like an Object, it contains states, and represents some kind of data or behavior.

Services contain characteristics, which are the states of the service. You can configure characteristics to be readable and writable.

In this case, we will have one service with one characteristic: LED.

Here is a flowchart of how our BLE system will work:

flowchart TD
P(Peripheral) --> L
    subgraph "Client (iPhone)"
    C(Central Manager) --> P
    end

    subgraph "Server (ESP32)"
    subgraph Services
    L(MyFirstService) --> R
    L --> G
    L --> B
    subgraph Characteristics
    R(C0)
    G(C1)
    B(C2)
    end
    end
    end

This layout is called GATT (Generic ATTribute Profile)