doc["ldr2"] = String(map(analogRead(0), 0, 4095, 100, 0)) + "%";
// Scenario 1: Simple On/Off (Standard Switch)
if (value == "A") {
digitalWrite(LED_PIN, HIGH);
Serial.println("LED State: ON");
}
else if (value == "B") {
digitalWrite(LED_PIN, LOW);
Serial.println("LED State: OFF");
}
Again, here you look at the tag you registered on your phone, and while it might say "A", you can enter a different tag. For example, I was only able to enter a tag with the size "aaa".
// ------------------------------Example code -------------------------
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <ArduinoJson.h>
#include <WiFi.h>
// --- BLE UUID Definitions ---
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
// Global Variables
BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
unsigned long lastMillis = 0;
// WiFi & API Storage
String savedSSID = "";
String savedPassword = "";
String savedApiKey = "";
// Hardware Pin Definitions
int sensorPin = 0;
const int LED_PIN = 8;
const int PWM_PIN = 3;
// PWM Configuration (v3.0+ SDK Compatible)
const int freq = 5000;
const int resolution = 8;
// BLE Server Connection Callbacks
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
Serial.println(">>> Device Connected");
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
Serial.println(">>> Device Disconnected");
// Restart advertising to remain visible for authorized devices
pServer->getAdvertising()->start();
}
};
// BLE Characteristic Write Callbacks
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
String value = String(pCharacteristic->getValue().c_str());
if (value.length() > 0) {
Serial.print("Command Received: ");
Serial.println(value);
// Scenario 1: Simple On/Off (Standard Switch)
if (value == "A") {
digitalWrite(LED_PIN, HIGH);
Serial.println("LED State: ON");
}
else if (value == "B") {
digitalWrite(LED_PIN, LOW);
Serial.println("LED State: OFF");
}
// Scenario 2: WiFi + API Key Setup
// Expected Format: "WIFI:ssid:password:apikey"
else if (value.startsWith("WIFI:")) {
String payload = value.substring(5);
int first = payload.indexOf(':');
int second = payload.indexOf(':', first + 1);
if (first == -1) {
Serial.println("WIFI format error!");
return;
}
savedSSID = payload.substring(0, first);
savedPassword = payload.substring(first + 1, second != -1 ? second : payload.length());
savedApiKey = second != -1 ? payload.substring(second + 1) : "";
Serial.println("SSID: " + savedSSID);
Serial.println("Password: " + savedPassword);
Serial.println("API Key: " + savedApiKey);
WiFi.begin(savedSSID.c_str(), savedPassword.c_str());
Serial.print("Connecting to WiFi");
int timeout = 0;
while (WiFi.status() != WL_CONNECTED && timeout < 20) {
delay(500);
Serial.print(".");
timeout++;
}
if (WiFi.status() == WL_CONNECTED) {
String ip = WiFi.localIP().toString();
Serial.println("\nWiFi Connected! IP: " + ip);
pCharacteristic->setValue(("IP:" + ip).c_str());
pCharacteristic->notify();
} else {
Serial.println("\nWiFi connection failed!");
pCharacteristic->setValue("WIFI_FAIL");
pCharacteristic->notify();
}
}
// Scenario 3: PWM Control
// Expected Format: "tag:value" — e.g., "ldr1:5"
else if (value.indexOf(':') != -1) {
int colonIndex = value.indexOf(':');
String tag = value.substring(0, colonIndex);
int val = value.substring(colonIndex + 1).toInt();
if (tag == "ldr1") {
int brightness = map(val, 0, 9, 0, 255);
ledcWrite(PWM_PIN, brightness);
Serial.printf("PWM Intensity set to: %d\n", brightness);
}
}
}
}
};
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
ledcAttach(PWM_PIN, freq, resolution);
// Initialize BLE Device
BLEDevice::init("ESP32-C3-FIIX");
// --- BLE SECURITY & STATIC PASSKEY CONFIGURATION ---
// Enable MITM (Man-in-the-middle) protection and encryption
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT_MITM);
BLESecurity *pSecurity = new BLESecurity();
pSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND); // Save pairing bond on smartphone storage
pSecurity->setCapability(ESP_IO_CAP_OUT); // Triggers native OS numeric passkey prompt
pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
// Set 6-digit static passkey (Change it if needed)
uint32_t passkey = 123456;
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint32_t));
// ---------------------------------------------------
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
// --- ENCRYPT CHARACTERISTIC ACCESS PERMISSIONS ---
// Restrict read/write operations to authenticated/paired devices only
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_WRITE_NR
);
pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
// ---------------------------------------------------
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->addDescriptor(new BLE2902());
pService->start();
// Start advertising permanently under passkey protection
pServer->getAdvertising()->start();
Serial.println("BLE Ready with Passkey Security (123456)...");
}
void loop() {
// Telemetry loop for sending JSON payloads to the app
if (deviceConnected) {
if (millis() - lastMillis > 2000) {
int sensorValue1 = random(100, 1024);
int sensorValue3 = random(100, 1024);
String mockDataStr = "123456789123456789";
StaticJsonDocument<128> doc;
doc["ldr1"] = sensorValue1;
doc["ldr2"] = String(map(analogRead(0), 0, 4095, 100, 0)) + "%";
doc["ldr3"] = sensorValue3;
doc["ldr4"] = mockDataStr;
if (digitalRead(LED_PIN) == HIGH) {
doc["aa"] = "OFF";
} else {
doc["aa"] = "ON";
}
char buffer[128];
serializeJson(doc, buffer);
pCharacteristic->setValue(buffer);
pCharacteristic->notify();
Serial.print("JSON Sent to App: ");
Serial.println(buffer);
lastMillis = millis();
}
}
}



