{"id":135186,"date":"2023-10-26T13:10:38","date_gmt":"2023-10-26T13:10:38","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=135186"},"modified":"2023-10-29T01:14:56","modified_gmt":"2023-10-29T01:14:56","slug":"esp32-ble-server-environmental-sensing-service","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-ble-server-environmental-sensing-service\/","title":{"rendered":"ESP32 BLE Peripheral (Server): Environmental Sensing Service"},"content":{"rendered":"\n<p>In this guide, you&#8217;ll learn how to set up the ESP32 as a BLE Peripheral (or BLE Server) with an Environmental Sensing Service. This service exposes measurement data from environmental sensors and supports a wide range of environmental parameters like temperature, humidity, pressure, and others. As an example, we&#8217;ll use the measurements from a BME280 sensor, but this can be applied to any other sensor. This is a great tutorial to help you understand the BLE protocol.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-BLE-Server-Environmental-Sensing-Service.jpg?resize=1024%2C576&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 BLE Peripheral (Server): Environmental Sensing Service\" class=\"wp-image-135236\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-BLE-Server-Environmental-Sensing-Service.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-BLE-Server-Environmental-Sensing-Service.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-BLE-Server-Environmental-Sensing-Service.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-BLE-Server-Environmental-Sensing-Service.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclblue\"><strong>New to the ESP32?<\/strong> <a href=\"https:\/\/randomnerdtutorials.com\/getting-started-with-esp32\/\" title=\"\">Start here: Getting Started with the ESP32 Development Board<\/a>.<\/p>\n\n\n\n<p><strong>Table of Contents<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"#BLE-intro\" title=\"\">Introducing Bluetooth Low Energy (BLE)<\/a><\/li>\n\n\n\n<li><a href=\"#project-overview\" title=\"\">Project Overview<\/a><\/li>\n\n\n\n<li><a href=\"#prepare-smartphone\" title=\"\">Preparing your Smartphone<\/a><\/li>\n\n\n\n<li><a href=\"#circuit\" title=\"\">Building the Circuit<\/a><\/li>\n\n\n\n<li><a href=\"#esp32-ble-server-code\" title=\"\">ESP32 &#8211; Creating an Environmental Sensing BLE Service (Arduino sketch)<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"BLE-intro\">Introducing Bluetooth Low Energy (BLE)<\/h2>\n\n\n\n<p>The ESP32 comes not only with Wi-Fi but also with Bluetooth and Bluetooth Low Energy (BLE).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"400\" height=\"129\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/03\/Bluetooth-low-energy.png?resize=400%2C129&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Bluetooth Low Energy\" class=\"wp-image-95092\" style=\"width:200px;height:65px\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/03\/Bluetooth-low-energy.png?w=400&amp;quality=100&amp;strip=all&amp;ssl=1 400w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/03\/Bluetooth-low-energy.png?resize=300%2C97&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 400px) 100vw, 400px\" \/><\/figure><\/div>\n\n\n<p>Bluetooth Low Energy, BLE for short, is a power-conserving variant of Bluetooth. BLE\u2019s primary application is short-distance transmission of small amounts of data (low bandwidth). Unlike Bluetooth which is always on, BLE remains in sleep mode constantly except for when a connection is initiated.<\/p>\n\n\n\n<p>This makes it consume very little power. BLE consumes approximately 100x less power than Bluetooth (depending on the use case). You can&nbsp;<a href=\"https:\/\/www.bluetooth.com\/learn-about-bluetooth\/tech-overview\/\" target=\"_blank\" rel=\"noreferrer noopener\">check the main differences between Bluetooth and Bluetooth Low Energy here<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">BLE Server and Client<\/h3>\n\n\n\n<p>With Bluetooth Low Energy, there are two types of devices: the server (also called peripheral) and the client. The ESP32 can act either as a client or as a server.<\/p>\n\n\n\n<p>The server advertises its existence, so it can be found by other devices and contains data that the client can read. The client scans the nearby devices, and when it finds the server it is looking for, it establishes a connection and listens for incoming data. This is called point-to-point communication and this is the communication mode we&#8217;ll use with the ESP32.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"308\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/BLE-Server-Client-Server-Advertising-03.png?resize=750%2C308&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"BLE Client Server Server Advertising\" class=\"wp-image-107774\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/BLE-Server-Client-Server-Advertising-03.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/11\/BLE-Server-Client-Server-Advertising-03.png?resize=300%2C123&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">GATT<\/h3>\n\n\n\n<p>GATT stands for Generic Attributes and it defines a hierarchical data structure that is exposed to connected BLE devices. This means that GATT defines the way that two BLE devices send and receive standard messages.&nbsp;Understanding this hierarchy is important because it will make it easier to understand how to use BLE with the ESP32.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"421\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/06\/GATT-BLE-ESP32.png?resize=750%2C421&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"GATT structure\" class=\"wp-image-63558\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/06\/GATT-BLE-ESP32.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/06\/GATT-BLE-ESP32.png?resize=300%2C168&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Profile<\/strong>: standard collection of services for a specific use case;<\/li>\n\n\n\n<li><strong>Service<\/strong>: collection of related information, like sensor readings, battery level, heart rate, etc. ;<\/li>\n\n\n\n<li><strong>Characteristic<\/strong>: it is where the actual data is saved on the hierarchy (<strong>value<\/strong>);<\/li>\n\n\n\n<li><strong>Descriptor<\/strong>: metadata about the data;<\/li>\n\n\n\n<li><strong>Properties<\/strong>: describes how the characteristic value can be interacted with. For example: read, write, notify, broadcast, indicate, etc.<\/li>\n<\/ul>\n\n\n\n<p class=\"rntbox rntclblue\">For a more in-depth introduction to BLE with the ESP32, read the following guide: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-bluetooth-low-energy-ble-arduino-ide\/\">Getting Started with ESP32 Bluetooth Low Energy (BLE) on Arduino IDE<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">UUID<\/h3>\n\n\n\n<p>Each service, characteristic, and descriptor have a UUID (Universally Unique Identifier). A UUID is a unique 128-bit (16 bytes) number. For example:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>55072829-bc9e-4c53-938a-74a6d4c78776<\/strong><\/pre>\n\n\n\n<p>There are shortened default UUIDs for all types, services, and profiles specified in the <a href=\"https:\/\/www.bluetooth.com\/specifications\/gatt\/services\" target=\"_blank\" rel=\"noreferrer noopener\">SIG (Bluetooth Special Interest Group)<\/a>. We&#8217;ll use the default UUIDs for the Environmental Sensing Service, and for the temperature, humidity, and pressure characteristics.<\/p>\n\n\n\n<p>If your application needs its own UUID, you can generate it using this <a href=\"https:\/\/www.uuidgenerator.net\/\" target=\"_blank\" rel=\"noreferrer noopener\">UUID generator website<\/a>.<\/p>\n\n\n\n<p>In summary, the UUID is used for uniquely identifying information. For example, it can identify a particular service provided by a Bluetooth device.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"project-overview\">Project Overview<\/h2>\n\n\n\n<p>In our example, we&#8217;ll create an <em>Environmental Sensing Service<\/em> with three <em>characteristics<\/em>. One for the temperature, another for the humidity, and another for the pressure. <\/p>\n\n\n\n<p>The actual temperature, humidity, and pressure readings are saved on the <em>value <\/em>under their <em>characteristics<\/em>. Each characteristic has the <em>notify <\/em>property so that it notifies the client whenever the values change.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"858\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-Environmental-Sensing-Service-Bluetooth-Low-Energy-1024x858.png?resize=1024%2C858&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 BLE Server: Environmental Sensing Service Structure\" class=\"wp-image-135218\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-Environmental-Sensing-Service-Bluetooth-Low-Energy.png?resize=1024%2C858&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-Environmental-Sensing-Service-Bluetooth-Low-Energy.png?resize=300%2C251&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-Environmental-Sensing-Service-Bluetooth-Low-Energy.png?resize=768%2C643&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-Environmental-Sensing-Service-Bluetooth-Low-Energy.png?resize=1536%2C1286&amp;quality=100&amp;strip=all&amp;ssl=1 1536w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-Environmental-Sensing-Service-Bluetooth-Low-Energy.png?resize=2048%2C1715&amp;quality=100&amp;strip=all&amp;ssl=1 2048w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-Environmental-Sensing-Service-Bluetooth-Low-Energy.png?w=2400&amp;quality=100&amp;strip=all&amp;ssl=1 2400w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n<p>We&#8217;re going to use the default UUIDs for the Environmental Sensing Profile and corresponding characteristics.<\/p>\n\n\n\n<p><a href=\"https:\/\/www.bluetooth.com\/specifications\/assigned-numbers\/\" target=\"_blank\" rel=\"noopener\" title=\"\">If you go to this page<\/a> and open the <a href=\"https:\/\/btprodspecificationrefs.blob.core.windows.net\/assigned-numbers\/Assigned%20Number%20Types\/Assigned_Numbers.pdf\" target=\"_blank\" rel=\"noopener\" title=\"\">Assigned Numbers Document (PDF)<\/a>, you&#8217;ll find all the default assigned UUID numbers. If you search for the <em>Environmental Sensing Service<\/em>, you&#8217;ll find all the permitted characteristics that you can use with that service. You can see that it supports, temperature, humidity, and pressure.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"627\" height=\"636\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/Environmental-sensing-service-permitted-characteristics.png?resize=627%2C636&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Environmental Sensing Service Supported Characteristics\" class=\"wp-image-135219\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/Environmental-sensing-service-permitted-characteristics.png?w=627&amp;quality=100&amp;strip=all&amp;ssl=1 627w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/Environmental-sensing-service-permitted-characteristics.png?resize=296%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 296w\" sizes=\"(max-width: 627px) 100vw, 627px\" \/><\/figure><\/div>\n\n\n<p>There&#8217;s a table with the UUIDs for all services. You can see that the UUID for the Environmental Sensing service is <strong>0x181A<\/strong>.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"612\" height=\"76\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/environmental-sensing-service-uuid.png?resize=612%2C76&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Environmental Sensing Service UUI\" class=\"wp-image-135220\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/environmental-sensing-service-uuid.png?w=612&amp;quality=100&amp;strip=all&amp;ssl=1 612w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/environmental-sensing-service-uuid.png?resize=300%2C37&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 612px) 100vw, 612px\" \/><\/figure><\/div>\n\n\n<p>Then, search for the temperature, humidity, and pressure characteristics UUIDs. You&#8217;ll find a table with the values for all characteristics. The UUIDs for the temperature, humidity, and pressure are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>pressure: <strong>0x2A6D<\/strong><\/li>\n\n\n\n<li>temperature: <strong><strong>0x2A6E<\/strong><\/strong><\/li>\n\n\n\n<li>humidity: <strong>0x246F<\/strong><\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"615\" height=\"89\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/pressure-temperature-humidity-uuids.png?resize=615%2C89&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Pressure, Temperature and Humidity characteristics default shortened UUIDs\" class=\"wp-image-135222\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/pressure-temperature-humidity-uuids.png?w=615&amp;quality=100&amp;strip=all&amp;ssl=1 615w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/pressure-temperature-humidity-uuids.png?resize=300%2C43&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 615px) 100vw, 615px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"prepare-smartphone\">Preparing your Smartphone<\/h2>\n\n\n\n<p>To check if the ESP32 BLE Server was created properly and receive temperature, humidity, and pressure notifications, we&#8217;ll use an app on the smartphone.<\/p>\n\n\n\n<p>Most modern smartphones should have BLE capabilities. You can search for your smartphone specifications to check if it has BLE or not.<\/p>\n\n\n\n<p><strong>Note<\/strong>: the smartphone can act as a client or as a server. In this case, it will be the client that connects to the ESP32 BLE server.<\/p>\n\n\n\n<p>For our tests, we\u2019ll be using a free app called&nbsp;nRF Connect for Mobile&nbsp;from Nordic. It works on&nbsp;<a href=\"https:\/\/play.google.com\/store\/apps\/details?id=no.nordicsemi.android.mcp\" target=\"_blank\" rel=\"noreferrer noopener\">Android (Google Play Store)<\/a>&nbsp;and&nbsp;<a href=\"https:\/\/itunes.apple.com\/us\/app\/nrf-connect\/id1054362403?mt=8\" target=\"_blank\" rel=\"noreferrer noopener\">iOS (App Store)<\/a>. Go to Google Play Store or App Store, search for \u201cnRF Connect for Mobile&#8221; and install the app.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/nRF-connect-app.png?quality=100&#038;strip=all&#038;ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"650\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/nRF-connect-app.png?resize=300%2C650&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"nRF Connect App\" class=\"wp-image-135214\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/nRF-connect-app.png?w=300&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/nRF-connect-app.png?resize=138%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 138w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Parts Required<\/h2>\n\n\n\n<p>For this tutorial, you&#8217;ll need the following parts:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP32 Board<\/a>&nbsp;\u2013 read&nbsp;<a href=\"https:\/\/makeradvisor.com\/esp32-development-boards-review-comparison\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP32 Development Boards Review and Comparison<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/bme280-sensor-module\/\" target=\"_blank\" rel=\"noreferrer noopener\">BME280 sensor module<\/a>&nbsp;\u2013 check the&nbsp;<a href=\"https:\/\/randomnerdtutorials.com\/esp32-bme280-arduino-ide-pressure-temperature-humidity\/\">BME280 getting started guide with the ESP32<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\" rel=\"noreferrer noopener\">Breadboard<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\" rel=\"noreferrer noopener\">Jumper wires<\/a><\/li>\n<\/ul>\n\n\n\n<p>For this example, we\u2019ll use a BME280 sensor, but you can easily modify the code to use any other sensor you\u2019re familiar with.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"circuit\">Building the Circuit<\/h2>\n\n\n\n<p>For this particular example, we&#8217;ll use a BME280 sensor. So, you need to wire a BME280 sensor to your ESP32. You can also use any other sensor you&#8217;re familiar with.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Schematic Diagram<\/h3>\n\n\n\n<p>We\u2019re going to use I2C communication with the BME280 sensor module. For that, wire the sensor to the default ESP32&nbsp;SCL (<span class=\"rnthl rntcblue\">GPIO 22<\/span>)&nbsp;and&nbsp;SDA (<span class=\"rnthl rntcgreen\">GPIO 21<\/span>)&nbsp;pins, as shown in the following schematic diagram.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"675\" height=\"670\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP32-BME280-Sensor-Temperature-Humidity-Pressure-Wiring-Diagram-Circuit_f.png?resize=675%2C670&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Wiring to BME280 Schematic Diagram\" class=\"wp-image-99755\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP32-BME280-Sensor-Temperature-Humidity-Pressure-Wiring-Diagram-Circuit_f.png?w=675&amp;quality=100&amp;strip=all&amp;ssl=1 675w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP32-BME280-Sensor-Temperature-Humidity-Pressure-Wiring-Diagram-Circuit_f.png?resize=300%2C298&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/10\/ESP32-BME280-Sensor-Temperature-Humidity-Pressure-Wiring-Diagram-Circuit_f.png?resize=150%2C150&amp;quality=100&amp;strip=all&amp;ssl=1 150w\" sizes=\"(max-width: 675px) 100vw, 675px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclblue\">Recommended reading: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-pinout-reference-gpios\/\">ESP32 Pinout Reference: Which GPIO pins should you use?<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"esp32-ble-server-code\">ESP32 &#8211; Creating an Environmental Sensing BLE Service<\/h2>\n\n\n\n<p>We&#8217;ll program the ESP32 using Arduino IDE. So, you need to have the ESP32 boards installed on the IDE. Follow the next tutorial if you haven&#8217;t already:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/installing-the-esp32-board-in-arduino-ide-windows-instructions\/\" title=\"\">Installing the ESP32 Board in Arduino IDE<\/a><\/li>\n<\/ul>\n\n\n\n<p>Here are the steps to create an ESP32 BLE peripheral with an Environmental Sensing BLE service with temperature, humidity, and pressure, characteristics:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create a BLE device (server) with a name of your choice (we&#8217;ll call it <strong>ESP32_BME2820<\/strong>, but you can call it any other name).<\/li>\n\n\n\n<li>Create an Environmental Sensing service (UUID: <strong>0x181A<\/strong>).<\/li>\n\n\n\n<li>Add characteristics to that service:\n<ul class=\"wp-block-list\">\n<li>pressure: <strong>0x2A6D<\/strong><\/li>\n\n\n\n<li>temperature: <strong>0x2A6E<\/strong><\/li>\n\n\n\n<li>humidity: <strong>0x246F<\/strong><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Add descriptors to the characteristics.<\/li>\n\n\n\n<li>Start the BLE server.<\/li>\n\n\n\n<li>Start advertising so BLE clients can connect and read the characteristics.<\/li>\n\n\n\n<li>Once a connection is established with a client, it will write new values on the characteristics and will notify the client, every time there&#8217;s a change.<\/li>\n<\/ol>\n\n\n\n<p>Copy the following code to the Arduino IDE and upload it to your board.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*\n  Rui Santos\n  Complete project details at https:\/\/RandomNerdTutorials.com\/esp32-ble-server-environmental-sensing-service\/\n  \n  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files. \n  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n*\/\n\n#include &lt;BLEDevice.h&gt;\n#include &lt;BLEServer.h&gt;\n#include &lt;BLEUtils.h&gt;\n#include &lt;BLE2902.h&gt;\n#include &lt;Adafruit_Sensor.h&gt;\n#include &lt;Adafruit_BME280.h&gt;\n\n\/\/BLE server name\n#define bleServerName &quot;ESP32_BME280&quot;\n\n\/\/ Default UUID for Environmental Sensing Service\n\/\/ https:\/\/www.bluetooth.com\/specifications\/assigned-numbers\/\n#define SERVICE_UUID (BLEUUID((uint16_t)0x181A))\n\n\/\/ Temperature Characteristic and Descriptor (default UUID)\n\/\/ Check the default UUIDs here: https:\/\/www.bluetooth.com\/specifications\/assigned-numbers\/\nBLECharacteristic temperatureCharacteristic(BLEUUID((uint16_t)0x2A6E), BLECharacteristic::PROPERTY_NOTIFY);\nBLEDescriptor temperatureDescriptor(BLEUUID((uint16_t)0x2902));\n\n\/\/ Humidity Characteristic and Descriptor (default UUID)\nBLECharacteristic humidityCharacteristic(BLEUUID((uint16_t)0x2A6F), BLECharacteristic::PROPERTY_NOTIFY);\nBLEDescriptor humidityDescriptor(BLEUUID((uint16_t)0x2902));\n\n\/\/ Pressure Characteristic and Descriptor (default UUID)\nBLECharacteristic pressureCharacteristic(BLEUUID((uint16_t)0x2A6D), BLECharacteristic::PROPERTY_NOTIFY);\nBLEDescriptor pressureDescriptor(BLEUUID((uint16_t)0x2902));\n\n\/\/ Create a sensor object\nAdafruit_BME280 bme;\n\n\/\/ Init BME280\nvoid initBME(){\n  if (!bme.begin(0x76)) {\n    Serial.println(&quot;Could not find a valid BME280 sensor, check wiring!&quot;);\n    while (1);\n  }\n}\n\nbool deviceConnected = false;\n\n\/\/Setup callbacks onConnect and onDisconnect\nclass MyServerCallbacks: public BLEServerCallbacks {\n  void onConnect(BLEServer* pServer) {\n    deviceConnected = true;\n    Serial.println(&quot;Device Connected&quot;);\n  };\n  void onDisconnect(BLEServer* pServer) {\n    deviceConnected = false;\n    Serial.println(&quot;Device Disconnected&quot;);\n  }\n};\n\nvoid setup() {\n  \/\/ Start serial communication \n  Serial.begin(115200);\n\n  \/\/ Start BME sensor\n  initBME();\n\n  \/\/ Create the BLE Device\n  BLEDevice::init(bleServerName);\n\n  \/\/ Create the BLE Server\n  BLEServer *pServer = BLEDevice::createServer();\n  pServer-&gt;setCallbacks(new MyServerCallbacks());\n\n  \/\/ Create the BLE Service\n  BLEService *bmeService = pServer-&gt;createService(SERVICE_UUID);\n\n  \/\/ Create BLE Characteristics and corresponding Descriptors\n  bmeService-&gt;addCharacteristic(&amp;temperatureCharacteristic);\n  temperatureCharacteristic.addDescriptor(&amp;temperatureDescriptor);\n  \n  bmeService-&gt;addCharacteristic(&amp;humidityCharacteristic);\n  humidityCharacteristic.addDescriptor(&amp;humidityDescriptor);\n\n  bmeService-&gt;addCharacteristic(&amp;pressureCharacteristic);\n  pressureCharacteristic.addDescriptor(&amp;pressureDescriptor);\n  \n  \/\/ Start the service\n  bmeService-&gt;start();\n\n  \/\/ Start advertising\n  pServer-&gt;getAdvertising()-&gt;start();\n  Serial.println(&quot;Waiting a client connection to notify...&quot;);\n}\n\nvoid loop() {\n  if (deviceConnected) {\n    \/\/ Read temperature as Celsius (the default)\n    float t = bme.readTemperature();\n    \/\/ Read humidity\n    float h = bme.readHumidity();\n    \/\/ Read pressure\n    float p = bme.readPressure()\/100.0F;\n    \n    \/\/Notify temperature reading\n    uint16_t temperature = (uint16_t)t;\n    \/\/Set temperature Characteristic value and notify connected client\n    temperatureCharacteristic.setValue(temperature);\n    temperatureCharacteristic.notify();\n    Serial.print(&quot;Temperature Celsius: &quot;);\n    Serial.print(t);\n    Serial.println(&quot; \u00baC&quot;);\n   \n    \/\/Notify humidity reading\n    uint16_t humidity = (uint16_t)h;\n    \/\/Set humidity Characteristic value and notify connected client\n    humidityCharacteristic.setValue(humidity);\n    humidityCharacteristic.notify();   \n    Serial.print(&quot;Humidity: &quot;);\n    Serial.print(h);\n    Serial.println(&quot; %&quot;);\n\n    \/\/Notify pressure reading\n    uint16_t pressure = (uint16_t)p;\n    \/\/Set humidity Characteristic value and notify connected client\n    pressureCharacteristic.setValue(pressure);\n    pressureCharacteristic.notify();   \n    Serial.print(&quot;Pressure: &quot;);\n    Serial.print(p);\n    Serial.println(&quot; hPa&quot;);\n    \n    delay(10000);\n  }\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/ESP32_BLE_Environmental_Sensing_Service.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How does the Code Work?<\/h2>\n\n\n\n<p>Continue reading to learn how the code works or skip to the <a href=\"#demonstration\" title=\"Demonstration \">Demonstration <\/a>section.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Importing libraries<\/h3>\n\n\n\n<p>You start by importing the required libraries: the libraries to use BLE and the libraries to interface with the BME280 sensor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;BLEDevice.h&gt;\n#include &lt;BLEServer.h&gt;\n#include &lt;BLEUtils.h&gt;\n#include &lt;BLE2902.h&gt;\n#include &lt;Adafruit_Sensor.h&gt;\n#include &lt;Adafruit_BME280.h&gt;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">BLE server name<\/h3>\n\n\n\n<p>In the following line, you can define the name of your BLE device. We&#8217;ll call it <strong>ESP32_BME2820<\/strong>, but you can call it any other name.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/BLE server name\n#define bleServerName \"ESP32_BME280\"<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Bluetooth UUIDs<\/h3>\n\n\n\n<p>We\u2019re using default UUIDs for services and characteristics already defined in the SIG (Bluetooth Special Interest Group). To report temperature, humidity, and pressure there\u2019s a service called <em>Environmental Sensing<\/em> that supports temperature, humidity, and pressure characteristics as we&#8217;ve seen previously.<\/p>\n\n\n\n<p>You can find all the default UUIDs for profiles and characteristics in the following document: <a href=\"https:\/\/www.bluetooth.com\/specifications\/assigned-numbers\/\" target=\"_blank\" rel=\"noopener\" title=\"\">https:\/\/www.bluetooth.com\/specifications\/assigned-numbers\/<\/a> .<\/p>\n\n\n\n<p>We create an Environmental Sensing Service on the following line:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define SERVICE_UUID (BLEUUID((uint16_t)0x181A))<\/code><\/pre>\n\n\n\n<p>Then, we create the temperature characteristic as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>BLECharacteristic temperatureCharacteristic(BLEUUID((uint16_t)0x2A6E), BLECharacteristic::PROPERTY_NOTIFY);<\/code><\/pre>\n\n\n\n<p>This line of code is creating a BLE characteristic named <span class=\"rnthl rntliteral\">temperatureCharacteristic<\/span> with a UUID of <span class=\"rnthl rntliteral\">0x2A6E<\/span> (representing the &#8220;Temperature&#8221; characteristic) and configuring it to support notifications (<span class=\"rnthl rntliteral\">PROPERTY_NOTIFY<\/span>) &#8211; this will allow other BLE devices to subscribe to and receive notifications when the temperature value changes on the ESP32.<\/p>\n\n\n\n<p>Then, we create a descriptor for the temperature characteristic. A descriptor provides additional information about a characteristic and how it should be accessed or interpreted. Our descriptor has the default UUID <strong>0x2902<\/strong> and it represents the &#8220;Client Characteristic Configuration&#8221; descriptor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>BLEDescriptor temperatureDescriptor(BLEUUID((uint16_t)0x2902));<\/code><\/pre>\n\n\n\n<p>The &#8220;Client Characteristic Configuration&#8221; descriptor, with UUID <span class=\"rnthl rntliteral\"><strong>0x2902<\/strong><\/span>, is commonly used in BLE to configure how notifications and indications are handled by the client (usually a central device like a smartphone) when it subscribes to a characteristic&#8217;s notifications. <\/p>\n\n\n\n<p>This descriptor allows the client to configure how it wants to receive updates (e.g., notifications) from the associated characteristic, giving more control over the communication between the ESP32 and the connected BLE devices.<\/p>\n\n\n\n<p>We proceed in a similar way to create the temperature and pressure characteristics and corresponding descriptors.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Humidity Characteristic and Descriptor (default UUID)\nBLECharacteristic humidityCharacteristic(BLEUUID((uint16_t)0x2A6F), BLECharacteristic::PROPERTY_NOTIFY);\nBLEDescriptor humidityDescriptor(BLEUUID((uint16_t)0x2902));\n\n\/\/ Pressure Characteristic and Descriptor (default UUID)\nBLECharacteristic pressureCharacteristic(BLEUUID((uint16_t)0x2A6D), BLECharacteristic::PROPERTY_NOTIFY);\nBLEDescriptor pressureDescriptor(BLEUUID((uint16_t)0x2902));<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Initialize the BME280 Sensor<\/h3>\n\n\n\n<p>The following line creates an <span class=\"rnthl rntliteral\">Adafruit_BME280<\/span> object to refer to the sensor called <span class=\"rnthl rntliteral\">bme<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Create a sensor object\nAdafruit_BME280 bme;<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">initBME()<\/span> function initializes the sensor. It will be called later in the <span class=\"rnthl rntliteral\">setup()<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Init BME280\nvoid initBME(){\n  if (!bme.begin(0x76)) {\n    Serial.println(\"Could not find a valid BME280 sensor, check wiring!\");\n    while (1);\n  }\n}<\/code><\/pre>\n\n\n\n<p class=\"rntbox rntclblue\">Learn more about the BME280 sensor: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-bme280-arduino-ide-pressure-temperature-humidity\/\" title=\"\">ESP32 with BME280 Sensor using Arduino IDE (Pressure, Temperature, Humidity)<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">BLE Callback functions<\/h3>\n\n\n\n<p>Then, we need to set up callback functions for when the BLE device connects (<span class=\"rnthl rntliteral\">onConnect<\/span>) or disconnects (<span class=\"rnthl rntliteral\">onDisconnect<\/span>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/Setup callbacks onConnect and onDisconnect\nclass MyServerCallbacks: public BLEServerCallbacks {\n  void onConnect(BLEServer* pServer) {\n    deviceConnected = true;\n    Serial.println(\"Device Connected\");\n  };\n  void onDisconnect(BLEServer* pServer) {\n    deviceConnected = false;\n    Serial.println(\"Device Disconnected\");\n  }\n};<\/code><\/pre>\n\n\n\n<p>We create a boolean variable called <span class=\"rnthl rntliteral\">deviceConnected<\/span> that keeps track of whether a Bluetooth device is currently connected to the ESP32.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>bool deviceConnected = false;<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">onConnect<\/span> function changes the <span class=\"rnthl rntliteral\">deviceConnected<\/span> variable to <span class=\"rnthl rntliteral\">true<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void onConnect(BLEServer* pServer) {\n  deviceConnected = true;\n  Serial.println(\"Device Connected\");\n};<\/code><\/pre>\n\n\n\n<p>And the <span class=\"rnthl rntliteral\">onDisconnect<\/span>, changes it to <span class=\"rnthl rntliteral\">false<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void onDisconnect(BLEServer* pServer) {\n  deviceConnected = false;\n  Serial.println(\"Device Disconnected\");\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">setup()<\/h3>\n\n\n\n<p>In the&nbsp;<span class=\"rnthl rntliteral\">setup()<\/span>, start the serial port at a baud rate of 115200:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.begin(115200);<\/code><\/pre>\n\n\n\n<p>Initialize the BME280 sensor by calling the <span class=\"rnthl rntliteral\">initBME()<\/span> function we created previously.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Start BME sensor\ninitBME();<\/code><\/pre>\n\n\n\n<p>Create a new BLE device with the BLE server name you\u2019ve defined earlier:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Create the BLE Device\nBLEDevice::init(bleServerName);<\/code><\/pre>\n\n\n\n<p>Set the BLE device as a server and assign the callback functions.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Create the BLE Server\nBLEServer *pServer = BLEDevice::createServer();\npServer-&gt;setCallbacks(new MyServerCallbacks());<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Creating the BLE Service and Characteristics<\/h4>\n\n\n\n<p>Continuing with the&nbsp;<span class=\"rnthl rntliteral\">setup()<\/span>, start a BLE service with the service UUID defined earlier.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Create the BLE Service\nBLEService *bmeService = pServer-&gt;createService(SERVICE_UUID);<\/code><\/pre>\n\n\n\n<p>Then, create the temperature, humidity, and pressure BLE characteristics using the UUIDs you defined earlier and assign the corresponding descriptors.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Create BLE Characteristics and corresponding Descriptors\nbmeService-&gt;addCharacteristic(&amp;temperatureCharacteristic);\ntemperatureCharacteristic.addDescriptor(&amp;temperatureDescriptor);\n  \nbmeService-&gt;addCharacteristic(&amp;humidityCharacteristic);\nhumidityCharacteristic.addDescriptor(&amp;humidityDescriptor);\n\nbmeService-&gt;addCharacteristic(&amp;pressureCharacteristic);\npressureCharacteristic.addDescriptor(&amp;pressureDescriptor);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Starting the Service and the Advertising<\/h4>\n\n\n\n<p>Finally, you start the service, and the server begins the advertising so other devices can find it.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Start the service\nbmeService-&gt;start();\n\n\/\/ Start advertising\npServer-&gt;getAdvertising()-&gt;start();<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">loop()<\/h3>\n\n\n\n<p>The&nbsp;<span class=\"rnthl rntliteral\">loop()<\/span>&nbsp;function is fairly straightforward. You constantly check if the device is connected or not. If it\u2019s connected, it reads the current temperature, humidity, and pressure.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if (deviceConnected) {\n  \/\/ Read temperature as Celsius \n  float t = bme.readTemperature();\n  \/\/ Read humidity\n  float h = bme.readHumidity();\n  \/\/ Read pressure\n  float p = bme.readPressure()\/100.0F;<\/code><\/pre>\n\n\n\n<p>Then, convert the readings to uint16_t format (unsigned 16-bit integer), a suitable format to use in BLE.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>uint16_t temperature = (uint16_t)t;<\/code><\/pre>\n\n\n\n<p>The following two lines update the current characteristic value (using&nbsp;<span class=\"rnthl rntliteral\">.setValue()<\/span>) and send it to the connected client (using&nbsp;<span class=\"rnthl rntliteral\">.notify()<\/span>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/Set temperature Characteristic value and notify connected client\ntemperatureCharacteristic.setValue(temperature);\ntemperatureCharacteristic.notify();<\/code><\/pre>\n\n\n\n<p>There are also three lines to print the temperature in the Serial Monitor for debugging purposes.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.print(\"Temperature Celsius: \");\nSerial.print(t);\nSerial.println(\" \u00baC\");<\/code><\/pre>\n\n\n\n<p>Sending the humidity and pressure uses the same process.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/Notify humidity reading\nuint16_t humidity = (uint16_t)h;\n\/\/Set humidity Characteristic value and notify connected client\nhumidityCharacteristic.setValue(humidity);\nhumidityCharacteristic.notify();   \nSerial.print(\"Humidity: \");\nSerial.print(h);\nSerial.println(\" %\");\n\n\/\/Notify pressure reading\nuint16_t pressure = (uint16_t)p;\n\/\/Set humidity Characteristic value and notify connected client\npressureCharacteristic.setValue(pressure);\npressureCharacteristic.notify();   \nSerial.print(\"Pressure: \");\nSerial.print(p);\nSerial.println(\" hPa\");<\/code><\/pre>\n\n\n\n<p>The delay function waits 10 seconds between readings.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>delay(10000);<\/code><\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">Demonstration<\/h1>\n\n\n\n<p>Upload the code to your board. After uploading, open the Serial Monitor, and restart the ESP32 by pressing the RST\/EN button. You should get a similar message in the Serial Monitor.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"601\" height=\"444\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/Waiting-client-notify.png?resize=601%2C444&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 BLE Server Advertising Serial Monitor\" class=\"wp-image-135213\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/Waiting-client-notify.png?w=601&amp;quality=100&amp;strip=all&amp;ssl=1 601w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/Waiting-client-notify.png?resize=300%2C222&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 601px) 100vw, 601px\" \/><\/figure><\/div>\n\n\n<p>This means everything is working as expected and the ESP32 is waiting for a BLE client to connect.<\/p>\n\n\n\n<p>Then, go to your smartphone, open the nRF Connect app from Nordic, and start scanning for new devices. You should find a device called <strong>ESP32_BME280<\/strong>\u2014this is the BLE server name you defined earlier.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"350\" height=\"720\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/Scanning-BLE-devices-nrf-connect.png?resize=350%2C720&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"nRF Connect App Scanning Devices\" class=\"wp-image-135229\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/Scanning-BLE-devices-nrf-connect.png?w=350&amp;quality=100&amp;strip=all&amp;ssl=1 350w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/Scanning-BLE-devices-nrf-connect.png?resize=146%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 146w\" sizes=\"(max-width: 350px) 100vw, 350px\" \/><\/figure><\/div>\n\n\n<p>Connect to it. You\u2019ll see that it displays the Environmental Sensing service with the temperature, humidity, and pressure characteristics. Click on the arrows to activate the notifications.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"473\" height=\"1024\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/environmental-sensing-service-nrf-connect.png?resize=473%2C1024&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Environmental Sensing Service\" class=\"wp-image-135230\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/environmental-sensing-service-nrf-connect.png?resize=473%2C1024&amp;quality=100&amp;strip=all&amp;ssl=1 473w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/environmental-sensing-service-nrf-connect.png?resize=139%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 139w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/environmental-sensing-service-nrf-connect.png?w=500&amp;quality=100&amp;strip=all&amp;ssl=1 500w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/figure><\/div>\n\n\n<p>Then, click on the second icon at the left to change the format. You can change to unsigned int for all characteristics. You\u2019ll start seeing the temperature, humidity, and pressure values being reported every 10 seconds.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"473\" height=\"1024\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/Scan-ESP32-BLE-Environmental-Sensing-Service.png?resize=473%2C1024&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Environmental Sensing Service and Characteristics\" class=\"wp-image-135231\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/Scan-ESP32-BLE-Environmental-Sensing-Service.png?resize=473%2C1024&amp;quality=100&amp;strip=all&amp;ssl=1 473w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/Scan-ESP32-BLE-Environmental-Sensing-Service.png?resize=139%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 139w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/Scan-ESP32-BLE-Environmental-Sensing-Service.png?w=500&amp;quality=100&amp;strip=all&amp;ssl=1 500w\" sizes=\"(max-width: 473px) 100vw, 473px\" \/><\/figure><\/div>\n\n\n<p>You should also get the readings on the Serial Monitor.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"601\" height=\"528\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-BLE-Notify-Client.png?resize=601%2C528&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Environmental Service BLE Advertising Serial Monitor\" class=\"wp-image-135232\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-BLE-Notify-Client.png?w=601&amp;quality=100&amp;strip=all&amp;ssl=1 601w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-BLE-Notify-Client.png?resize=300%2C264&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 601px) 100vw, 601px\" \/><\/figure><\/div>\n\n\n<p>Congratulations! You&#8217;ve successfully created an ESP32 BLE Peripheral that advertises the Environmental Sensing Service. Now, you can develop an app, or program another ESP32 to interface with the ESP32 BLE device.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"demonstration\">Wrapping Up<\/h2>\n\n\n\n<p>In this tutorial, you learned how to create a BLE device with the ESP32 with the default UUIDs defined by the SIG. As an example, we created an Environmental Sensing Service with temperature, humidity, and pressure characteristics. The Environmental Sensing Service also supports many other characteristics. So, you can easily modify this project to work with other sensors. Or you can also create a different Service to advertise other types of characteristics\u2014the workflow is the same.<\/p>\n\n\n\n<p>We hope you found this tutorial useful and that it has helped you understand more about BLE protocol with the ESP32.<\/p>\n\n\n\n<p>We have other BLE and Bluetooth Classic tutorials that you may find useful:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-bluetooth-low-energy-ble-arduino-ide\/\">Getting Started with ESP32 Bluetooth Low Energy (BLE) on Arduino IDE<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-ble-server-client\/\">ESP32 BLE Server and Client (Bluetooth Low Energy)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-bluetooth-classic-arduino-ide\/\">ESP32 Bluetooth Classic with Arduino IDE \u2013 Getting Started<\/a><\/li>\n<\/ul>\n\n\n\n<p>Learn more about the ESP32 with our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\">Learn ESP32 with Arduino IDE (eBook)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/build-web-servers-esp32-esp8266-ebook\/\">Build Web Servers with ESP32 and ESP8266 (eBook)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/firebase-esp32-esp8266-ebook\/\">Firebase Web App with ESP32 and ESP8266 (eBook)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/smart-home-ebook\/\">SMART HOME with Raspberry Pi, ESP32, and ESP8266<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32\/\">Free ESP32 Projects and Tutorials\u2026<\/a><\/li>\n<\/ul>\n\n\n\n<p>Thanks for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this guide, you&#8217;ll learn how to set up the ESP32 as a BLE Peripheral (or BLE Server) with an Environmental Sensing Service. This service exposes measurement data from environmental &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32 BLE Peripheral (Server): Environmental Sensing Service\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-ble-server-environmental-sensing-service\/#more-135186\" aria-label=\"Read more about ESP32 BLE Peripheral (Server): Environmental Sensing Service\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":135236,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[276,281,277,299,264],"tags":[],"class_list":["post-135186","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32","category-esp32-project","category-esp32-arduino-ide","category-0-esp32","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-BLE-Server-Environmental-Sensing-Service.jpg?fit=1280%2C720&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/135186","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=135186"}],"version-history":[{"count":18,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/135186\/revisions"}],"predecessor-version":[{"id":137850,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/135186\/revisions\/137850"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/135236"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=135186"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=135186"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=135186"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}