title: ESP32 Arduino BLE DeepSleep
body: <p>I am working on a project involving 2 ESP32 Wemos D1 Mini boards. I am using the BLE feature to transmit a sensor reading from the "server" to the "client". I use a Characteristic Notify to the client which receives the sensor reading. If I want to implement deep sleep functionality to the server, what would happen to the client? Does the client also have to reset at some point?
  Also, is it advisable to use Characteristic.Notify in a deep sleep scenario?</p>
  
  <p>Thanks.</p>
  
  <p>Server code:</p>
  
  <pre><code>#include &lt;BLEServer.h&gt;
  #include &lt;BLEUtils.h&gt;
  #include &lt;BLE2902.h&gt;
  #include "DHT.h"
  
  #define DHTPIN 4
  #define DHTTYPE DHT22
  #define uS_TO_S_FACTOR 1000000  //Conversion factor for micro seconds to seconds
  #define TIME_TO_SLEEP  15        //Time ESP32 will go to sleep (in seconds)
  
  RTC_DATA_ATTR int bootCount = 0;
  DHT dht(DHTPIN, DHTTYPE);
  BLECharacteristic *pCharacteristic;
  
  bool deviceConnected = false;
  uint8_t txValue = 50;
  
  #define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
  #define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
  
  class MyServerCallbacks: public BLEServerCallbacks {
      void onConnect(BLEServer* pServer) {
        deviceConnected = true;
      };
  
      void onDisconnect(BLEServer* pServer) {
        deviceConnected = false;
      }
  };
  
  //Function that prints the reason by which ESP32 has been awaken from sleep
  void print_wakeup_reason(){
    esp_sleep_wakeup_cause_t wakeup_reason;
    wakeup_reason = esp_sleep_get_wakeup_cause();
    switch(wakeup_reason)
    {
      case 1  : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
      case 2  : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
      case 3  : Serial.println("Wakeup caused by timer"); break;
      case 4  : Serial.println("Wakeup caused by touchpad"); break;
      case 5  : Serial.println("Wakeup caused by ULP program"); break;
      default : Serial.println("Wakeup was not caused by deep sleep"); break;
    }
  }
  
  void setup() {
    Serial.begin(115200);
  
    Serial.println(F("initating DHT22..."));
    dht.begin();
  
    // Create the BLE Device
    BLEDevice::init("UART"); // Name must not be longer than 5 chars!!!
  
    // Create the BLE Server
    BLEServer *pServer = BLEDevice::createServer();
    pServer-&gt;setCallbacks(new MyServerCallbacks());
  
    // Create the BLE Service
    BLEService *pService = pServer-&gt;createService(SERVICE_UUID);
  
    // Create a BLE Characteristic
    pCharacteristic = pService-&gt;createCharacteristic(
                        CHARACTERISTIC_UUID_TX,
                        BLECharacteristic::PROPERTY_NOTIFY|BLECharacteristic::PROPERTY_READ|BLECharacteristic::PROPERTY_WRITE
                      );
  
    BLE2902 *desc = new BLE2902();
    desc-&gt;setNotifications(true);
    pCharacteristic-&gt;addDescriptor(desc);
  
    // Start the service
    pService-&gt;start();
    pServer-&gt;getAdvertising()-&gt;addServiceUUID(SERVICE_UUID);
    // Start advertising
    pServer-&gt;getAdvertising()-&gt;start();
    Serial.println(pService-&gt;getUUID().toString().c_str());
    Serial.println("Waiting a client connection to notify...");
  
    if (deviceConnected) {
  
      float f = dht.readTemperature(true);
      char fStr[10];
      sprintf(fStr, "%4.4f", f);
  
      Serial.print("Temperature reading: ");
      Serial.println(fStr);
  
      Serial.printf("*** Sent Value: %d ***\n", fStr);
      pCharacteristic-&gt;setValue(fStr);
  
      pCharacteristic-&gt;notify();
  
      //Set timer to 5 seconds
      esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
      Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
      " Seconds");
  
      //Go to sleep now
      esp_deep_sleep_start();
  
    }
    //delay(60000);
  }
  
  void loop() {}
  </code></pre>
  
  <p>Client code:</p>
  
  <pre><code>#include "BLEDevice.h"
  #include &lt;WiFi.h&gt;
  
  // The remote service we wish to connect to.
  static BLEUUID serviceUUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E");
  static BLEUUID    charUUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E");
  
  static BLEAddress *pServerAddress;
  static boolean doConnect = false;
  static boolean connected = false;
  static BLERemoteCharacteristic* pRemoteCharacteristic;
  
  const char* ssid     = "Kings";
  const char* password = "GoCanada";
  const char* host = "menezes-service.herokuapp.com";
  WiFiClient client;
  
  static void notifyCallback(
    BLERemoteCharacteristic* pBLERemoteCharacteristic,
    uint8_t* pData,
    size_t length,
    bool isNotify) {
      Serial.print(pBLERemoteCharacteristic-&gt;getUUID().toString().c_str());
      Serial.print(" of data length ");
      Serial.println(length);
      //std::string value = pBLERemoteCharacteristic-&gt;readValue();
      byte buffer[42];
      Serial.print("The characteristic value sent was: ");
      //Serial.println(pBLERemoteCharacteristic-&gt;readValue().c_str());
      //Serial.println(pBLERemoteCharacteristic-&gt;readUInt8());
      std::string farhenheight = pRemoteCharacteristic-&gt;readValue();
      Serial.print("Farheinheight: ");
      Serial.println(farhenheight.c_str());
      Serial.println(F("Posting to api!"));
      Serial.println();
      Serial.println("closing connection");
  }
  
  class MyClientCallback : public BLEClientCallbacks {
    void onConnect(BLEClient* pclient) {
      Serial.println("connected again ... ");
    }
  
    void onDisconnect(BLEClient* pclient) {
      connected = false;
      Serial.println("onDisconnect");
    }
  };
  
  bool connectToServer(BLEAddress pAddress) {
      Serial.print("Forming a connection to ");
      Serial.println(pAddress.toString().c_str());
  
      BLEClient*  pClient  = BLEDevice::createClient();
      Serial.println(" - Created client");
  
      pClient-&gt;setClientCallbacks(new MyClientCallback());
  
      // Connect to the remove BLE Server.
      pClient-&gt;connect(pAddress);
      Serial.println(" - Connected to server");
  
      // Obtain a reference to the service we are after in the remote BLE server.
      BLERemoteService* pRemoteService = pClient-&gt;getService(serviceUUID);
      Serial.println(pRemoteService-&gt;toString().c_str());
      if (pRemoteService == nullptr) {
        Serial.print("Failed to find our service UUID: ");
        Serial.println(serviceUUID.toString().c_str());
        return false;
      }
      Serial.println(" - Found our service");
  
      // Obtain a reference to the characteristic in the service of the remote BLE server.
      pRemoteCharacteristic = pRemoteService-&gt;getCharacteristic(charUUID);
      if (pRemoteCharacteristic == nullptr) {
        Serial.print("Failed to find our characteristic UUID: ");
        Serial.println(charUUID.toString().c_str());
        return false;
      }
      Serial.println(" - Found our characteristic");
  
      pRemoteCharacteristic-&gt;registerForNotify(notifyCallback);
  }
  
  class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      Serial.print("BLE Advertised Device found: ");
      Serial.println(advertisedDevice.toString().c_str());
      //Serial.print(advertisedDevice.haveServiceUUID());
  
      if(advertisedDevice.haveServiceUUID()){
        Serial.println(advertisedDevice.getServiceUUID().toString().c_str());
      }
  
  
      // We have found a device, let us now see if it contains the service we are looking for.
      if (advertisedDevice.haveServiceUUID() &amp;&amp; advertisedDevice.getServiceUUID().equals(serviceUUID)) {
  
        // 
        Serial.print("Found our device!  address: "); 
        advertisedDevice.getScan()-&gt;stop();
  
        pServerAddress = new BLEAddress(advertisedDevice.getAddress());
        doConnect = true;
  
      } // Found our server
  
    } // onResult
  }; // MyAdvertisedDeviceCallbacks
  
  void setup() {
    Serial.begin(115200);
    Serial.println("Starting Arduino BLE Client application...");
    BLEDevice::init("");
    BLEScan* pBLEScan = BLEDevice::getScan();
    pBLEScan-&gt;setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
    pBLEScan-&gt;setActiveScan(true);
    pBLEScan-&gt;start(30);
  
  } // End of setup.
  
  // This is the Arduino main loop function.
  void loop() {
    if (doConnect == true) {
      if (connectToServer(*pServerAddress)) {
          Serial.println("We are now connected to the BLE Server.");
          connected = true;
      } else {
        Serial.println("We have failed to connect to the server; there is nothin more we will do.");
      }
      //doConnect = false;
    }
  
    if (connected == false){
      BLEDevice::getScan()-&gt;start(0);
    }
    else{
      doConnect = false;
    }
  
    delay(1000); // Delay a second between loops.
  } // End of loop
  </code></pre>