/* 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 "Cycles of five good then one bad" #define SERVICE_UUID "32eed4b3-e233-4808-a120-c4cee1a8e0c5" #define BEACON_UUID "84b7f168-a742-49b7-bd15-dc808dddb672" #define BEACON_UUID_REV "87a3c0f9-695f-4c04-8195-3a89d6cd44f0" #define CHARACTERISTIC_UUID "738e7085-9717-4288-ab21-c59ff7c5dd96" 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 second-long cyclic counter 0-11 unsigned long currentTime = millis(); unsigned long totalSeconds = currentTime / 1000; unsigned long currentSecond = totalSeconds % 12; String msg = "good"; if (currentSecond >= 9) msg = "bad"; Serial.printf("*** NOTIFY: %s ***\n", msg); pCharacteristic->setValue(msg); pCharacteristic->notify(); value++; } delay(2000); }