/* Based on 31337Ghost's reference code from https://github.com/nkolban/esp32-snippets/issues/385#issuecomment-362535434 which is based on pcbreflux's Arduino ESP32 port of Neil Kolban's example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp */ /* Create a BLE server that will send periodic iBeacon frames. The design of creating the BLE server is: 1. Create a BLE Server 2. Create advertising data 3. Start advertising. 4. wait 5. Stop advertising. */ #include #include #include #include #include #define DEVICE_NAME "Current second is below 50" #define SERVICE_UUID "f9fde96b-d917-4877-ba4f-0813e69410c1" #define BEACON_UUID "80e972d1-066f-4235-b44c-b6b681e63bf2" #define BEACON_UUID_REV "ee4dadbb-6c32-48d5-9622-1d2dcc520154" #define CHARACTERISTIC_UUID "c093f2ae-a81f-4683-b324-7a19f0f5e363" BLEServer *pServer; BLECharacteristic *pCharacteristic; bool deviceConnected = false; uint8_t value = 0; class MyServerCallbacks : public BLEServerCallbacks { void onConnect(BLEServer *pServer) { deviceConnected = true; Serial.println("deviceConnected = true"); }; void onDisconnect(BLEServer *pServer) { deviceConnected = false; Serial.println("deviceConnected = false"); // Restart advertising to be visible and connectable again BLEAdvertising *pAdvertising; pAdvertising = pServer->getAdvertising(); pAdvertising->start(); Serial.println("iBeacon advertising restarted"); } }; class MyCallbacks : public BLECharacteristicCallbacks { void onWrite(BLECharacteristic *pCharacteristic) { String rxValue = pCharacteristic->getValue(); if (rxValue.length() > 0) { Serial.println("*********"); Serial.print("Received Value: "); for (int i = 0; i < rxValue.length(); i++) { Serial.print(rxValue[i]); } Serial.println(); Serial.println("*********"); } } }; void init_service() { BLEAdvertising *pAdvertising; pAdvertising = pServer->getAdvertising(); pAdvertising->stop(); // Create the BLE Service BLEService *pService = pServer->createService(BLEUUID(SERVICE_UUID)); // Create a BLE Characteristic pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY ); pCharacteristic->setCallbacks(new MyCallbacks()); pCharacteristic->addDescriptor(new BLE2902()); pAdvertising->addServiceUUID(BLEUUID(SERVICE_UUID)); // Start the service pService->start(); pAdvertising->start(); } void init_beacon() { BLEAdvertising *pAdvertising; pAdvertising = pServer->getAdvertising(); pAdvertising->stop(); // iBeacon BLEBeacon myBeacon; myBeacon.setManufacturerId(0x4c00); myBeacon.setMajor(5); myBeacon.setMinor(88); myBeacon.setSignalPower(0xc5); myBeacon.setProximityUUID(BLEUUID(BEACON_UUID_REV)); BLEAdvertisementData advertisementData; advertisementData.setFlags(0x1A); advertisementData.setManufacturerData(myBeacon.getData()); pAdvertising->setAdvertisementData(advertisementData); pAdvertising->start(); } void setup() { Serial.begin(115200); Serial.println(); Serial.println("Initializing..."); Serial.flush(); BLEDevice::init(DEVICE_NAME); pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks()); init_service(); init_beacon(); Serial.printf("iBeacon + service defined and advertising: %s", DEVICE_NAME); } void loop() { if (deviceConnected) { // Get the current second (0-59) unsigned long currentTime = millis(); unsigned long totalSeconds = currentTime / 1000; unsigned long currentSecond = totalSeconds % 60; String msg = "good"; if (currentSecond >= 9) msg = "bad"; Serial.printf("*** NOTIFY: %s ***\n", msg); pCharacteristic->setValue(msg); pCharacteristic->notify(); value++; } delay(2000); }