esp-nimble-cpp/md__new__user__guide.html
2024-12-17 01:50:27 +00:00

412 lines
26 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.9.8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>esp-nimble-cpp: New User Guide</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr id="projectrow">
<td id="projectalign">
<div id="projectname">esp-nimble-cpp<span id="projectnumber">&#160;2.0.1</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.9.8 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
var searchBox = new SearchBox("searchBox", "search/",'.html');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(function() {
initMenu('',true,false,'search.php','Search');
$(document).ready(function() { init_search(); });
});
/* @license-end */
</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(document).ready(function(){initNavTree('md__new__user__guide.html',''); initResizable(); });
/* @license-end */
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<div id="MSearchResults">
<div class="SRPage">
<div id="SRIndex">
<div id="SRResults"></div>
<div class="SRStatus" id="Loading">Loading...</div>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
</div>
</div>
</div>
</div>
<div><div class="header">
<div class="headertitle"><div class="title">New User Guide</div></div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><a class="anchor" id="new-user-guide"></a> <b>Note:</b> If you are migrating an existing project from the original Bluedroid library please see the <a class="el" href="md__migration__guide.html">Migration Guide.</a> <br />
</p>
<p>If you are a new user this will guide you through a simple server and client application. <br />
</p>
<ul>
<li><a class="el" href="md__new__user__guide.html#creating-a-server">Creating a Server</a></li>
<li><a class="el" href="md__new__user__guide.html#creating-a-client">Creating a Client</a> <br />
<br />
</li>
</ul>
<h1><a class="anchor" id="include-files"></a>
Include Files</h1>
<p>At the top of your application file add <code>#include <a class="el" href="_nim_b_l_e_device_8h_source.html">NimBLEDevice.h</a></code>, this is the only header required and provides access to all classes. <br />
<br />
</p>
<h1><a class="anchor" id="using-the-library"></a>
Using the Library</h1>
<p>In order to perform any BLE tasks you must first initialize the library, this prepares the NimBLE stack to be ready for commands. <br />
</p>
<p>To do this you must call <code><a class="el" href="class_nim_b_l_e_device.html#a2e8bb71daabbffd9eab8787493a45ce7" title="Initialize the BLE environment.">NimBLEDevice::init</a>("your device name here")</code>, the parameter passed is a character string containing the name you want to advertise. <br />
If you're not creating a server or do not want to advertise a name, simply pass an empty string for the parameter. <br />
</p>
<p>This can be called any time you wish to use BLE functions and does not need to be called from app_main(IDF) or setup(Arduino) but usually is. <br />
<br />
</p>
<h1><a class="anchor" id="creating-a-server"></a>
Creating a Server</h1>
<p>BLE servers perform 2 tasks, they advertise their existence for clients to find them and they provide services which contain information for the connecting client. <br />
</p>
<p>After initializing the NimBLE stack we create a server by calling <code><a class="el" href="class_nim_b_l_e_device.html#a4d9780d0b5fafc279483822af802a508" title="Create an instance of a server.">NimBLEDevice::createServer()</a></code>, this will create a server instance and return a pointer to it. <br />
</p>
<p>Once we have created the server we need to tell it the services it hosts. <br />
To do this we call <code><a class="el" href="class_nim_b_l_e_server.html#aaeb58b4de85754d1aac6964e9248aa35" title="Create a BLE Service.">NimBLEServer::createService(const char* uuid)</a></code>. Which returns a pointer to an instance of <code><a class="el" href="class_nim_b_l_e_service.html" title="The model of a BLE service.">NimBLEService</a></code>. <br />
The <code>uuid</code> parameter is a hexadecimal string with the uuid we want to give the service, it can be 16, 32, or 128 bits. <br />
</p>
<p>For this example we will keep it simple and use a 16 bit value: ABCD. <br />
<br />
</p>
<p><b>Example code:</b> <br />
</p><div class="fragment"><div class="line">#include &quot;NimBLEDevice.h&quot;</div>
<div class="line"> </div>
<div class="line">// void setup() in Arduino</div>
<div class="line">void app_main(void) </div>
<div class="line">{</div>
<div class="line"> NimBLEDevice::init(&quot;NimBLE&quot;);</div>
<div class="line"> </div>
<div class="line"> NimBLEServer *pServer = NimBLEDevice::createServer();</div>
<div class="line"> NimBLEService *pService = pServer-&gt;createService(&quot;ABCD&quot;);</div>
<div class="line">}</div>
</div><!-- fragment --><p>Now we have NimBLE initialized, a server created and a service assigned to it. <br />
We can't do much with this yet so now we should add a characteristic to the service to provide some data. <br />
</p>
<p>Next we call <code><a class="el" href="class_nim_b_l_e_service.html#a415e1b836946831c6f9edd74adba8763" title="Create a new BLE Characteristic associated with this service.">NimBLEService::createCharacteristic</a></code> which returns a pointer to an instance of <code><a class="el" href="class_nim_b_l_e_characteristic.html" title="The model of a BLE Characteristic.">NimBLECharacteristic</a></code>, and takes two parameters: A <code>uuid</code> to specify the UUID of the characteristic and a bitmask of the properties we want applied to it. <br />
</p>
<p>Just as with the service UUID we will use a simple 16 bit value: 1234. <br />
The properties bitmask is a little more involved. It is a combination of NIMBLE_PROPERTY:: values. <br />
</p>
<p>Here is the list of options: <br />
</p><blockquote class="doxtable">
<p>&zwj;NIMBLE_PROPERTY::READ <br />
NIMBLE_PROPERTY::READ_ENC <br />
NIMBLE_PROPERTY::READ_AUTHEN <br />
NIMBLE_PROPERTY::READ_AUTHOR <br />
NIMBLE_PROPERTY::WRITE <br />
NIMBLE_PROPERTY::WRITE_NR <br />
NIMBLE_PROPERTY::WRITE_ENC <br />
NIMBLE_PROPERTY::WRITE_AUTHEN <br />
NIMBLE_PROPERTY::WRITE_AUTHOR <br />
NIMBLE_PROPERTY::BROADCAST <br />
NIMBLE_PROPERTY::NOTIFY <br />
NIMBLE_PROPERTY::INDICATE <br />
</p>
</blockquote>
<p>For this example we won't need to specify these as the default value is <code>NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE</code> <br />
which will allow reading and writing values to the characteristic without encryption or security. <br />
The function call will simply be <code>pService-&gt;createCharacteristic("1234");</code> <br />
<br />
</p>
<p><b>Our example code now is:</b> <br />
</p><div class="fragment"><div class="line">#include &quot;NimBLEDevice.h&quot;</div>
<div class="line"> </div>
<div class="line">// void setup() in Arduino</div>
<div class="line">void app_main(void)</div>
<div class="line">{</div>
<div class="line"> NimBLEDevice::init(&quot;NimBLE&quot;);</div>
<div class="line"> </div>
<div class="line"> NimBLEServer *pServer = NimBLEDevice::createServer();</div>
<div class="line"> NimBLEService *pService = pServer-&gt;createService(&quot;ABCD&quot;);</div>
<div class="line"> NimBLECharacteristic *pCharacteristic = pService-&gt;createCharacteristic(&quot;1234&quot;);</div>
<div class="line">}</div>
</div><!-- fragment --><p>All that's left to do now is start the service, give the characteristic a value and start advertising for clients. <br />
</p>
<p>Fist we start the service by calling <code><a class="el" href="class_nim_b_l_e_service.html#ad37324ed0404d596923d6fdc0133b985" title="Builds the database of characteristics/descriptors for the service and registers it with the NimBLE s...">NimBLEService::start()</a></code>.</p>
<p>Next we need to call <code>NimBLECharacteristic::setValue</code> to set the characteristic value that the client will read. <br />
There are many different types you can send as parameters for the value but for this example we will use a simple string. <code>pCharacteristic-&gt;setValue("Hello BLE");</code> <br />
</p>
<p>Next we need to advertise for connections. <br />
To do this we create an instance of <code><a class="el" href="class_nim_b_l_e_advertising.html" title="Perform and manage BLE advertising.">NimBLEAdvertising</a></code> add our service to it (optional) and start advertisng. <br />
</p>
<p><b>The code for this will be:</b> <br />
</p><div class="fragment"><div class="line">NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising(); // create advertising instance</div>
<div class="line">pAdvertising-&gt;addServiceUUID(&quot;ABCD&quot;); // tell advertising the UUID of our service</div>
<div class="line">pAdvertising-&gt;start(); // start advertising</div>
</div><!-- fragment --><p> That's it, this will be enough to create a BLE server with a service and a characteristic and advertise for client connections. <br />
</p>
<p><b>The full example code:</b> <br />
</p><div class="fragment"><div class="line">#include &quot;NimBLEDevice.h&quot;</div>
<div class="line"> </div>
<div class="line">// void setup() in Arduino</div>
<div class="line">void app_main(void)</div>
<div class="line">{</div>
<div class="line"> NimBLEDevice::init(&quot;NimBLE&quot;);</div>
<div class="line"> </div>
<div class="line"> NimBLEServer *pServer = NimBLEDevice::createServer();</div>
<div class="line"> NimBLEService *pService = pServer-&gt;createService(&quot;ABCD&quot;);</div>
<div class="line"> NimBLECharacteristic *pCharacteristic = pService-&gt;createCharacteristic(&quot;1234&quot;);</div>
<div class="line"> </div>
<div class="line"> pService-&gt;start();</div>
<div class="line"> pCharacteristic-&gt;setValue(&quot;Hello BLE&quot;);</div>
<div class="line"> </div>
<div class="line"> NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();</div>
<div class="line"> pAdvertising-&gt;addServiceUUID(&quot;ABCD&quot;); </div>
<div class="line"> pAdvertising-&gt;start(); </div>
<div class="line">}</div>
</div><!-- fragment --><p>Now if you scan with your phone using nRFConnect or any other BLE app you should see a device named "NimBLE" with a service of "ABCD". <br />
</p>
<p>For more advanced features and options please see the server examples in the examples folder. <br />
<br />
</p>
<h1><a class="anchor" id="creating-a-client"></a>
Creating a Client</h1>
<p>BLE clients perform 2 tasks, they scan for advertising servers and form connections to them to read and write to their characteristics/descriptors.</p>
<p>After initializing the NimBLE stack we create a scan instance by calling <code><a class="el" href="class_nim_b_l_e_device.html#af93d92316454b051125460056368baec" title="Retrieve the Scan object that we use for scanning.">NimBLEDevice::getScan()</a></code>, this will create a <code><a class="el" href="class_nim_b_l_e_scan.html" title="Perform and manage BLE scans.">NimBLEScan</a></code> instance and return a pointer to it. <br />
</p>
<p>Once we have created the scan we can start looking for advertising servers. <br />
</p>
<p>To do this we call <code>NimBLEScan::start(duration)</code>, the duration parameter is a uint32_t that specifies the number of milliseconds to scan for, <br />
passing 0 will scan forever. <br />
</p>
<p>In this example we will scan for 10 seconds. This is a blocking function (a non blocking overload is also available). <br />
This call returns an instance of <code><a class="el" href="class_nim_b_l_e_scan_results.html" title="A class that contains and operates on the results of a BLE scan.">NimBLEScanResults</a></code> when the scan completes which can be parsed for advertisers we are interested in. <br />
</p>
<p><b>Example Code:</b> <br />
</p><div class="fragment"><div class="line">#include &quot;NimBLEDevice.h&quot;</div>
<div class="line"> </div>
<div class="line">// void setup() in Arduino</div>
<div class="line">void app_main(void) </div>
<div class="line">{</div>
<div class="line"> NimBLEDevice::init(&quot;&quot;);</div>
<div class="line"> </div>
<div class="line"> NimBLEScan *pScan = NimBLEDevice::getScan();</div>
<div class="line"> NimBLEScanResults results = pScan-&gt;getResults(10 * 1000);</div>
<div class="line">}</div>
</div><!-- fragment --><p> <br />
</p>
<p>Now that we have scanned we need to check the results for any advertisers we are interested in connecting to. <br />
</p>
<p>To do this we iterate through the results and check if any of the devices found are advertising the service we want <code>ABCD</code>. <br />
Each result in <code><a class="el" href="class_nim_b_l_e_scan_results.html" title="A class that contains and operates on the results of a BLE scan.">NimBLEScanResults</a></code> is a <code><a class="el" href="class_nim_b_l_e_advertised_device.html" title="A representation of a BLE advertised device found by a scan.">NimBLEAdvertisedDevice</a></code> instance that we can access data from.</p>
<p>We will check each device found for the <code>ABCD</code> service by calling <code><a class="el" href="class_nim_b_l_e_advertised_device.html#ad006b08552281a3e6c9d9444e7942709" title="Check advertised services for existence of the required UUID.">NimBLEAdvertisedDevice::isAdvertisingService</a></code>. <br />
This takes an instance of <code><a class="el" href="class_nim_b_l_e_u_u_i_d.html" title="A model of a BLE UUID.">NimBLEUUID</a></code> as a parameter so we will need to create one. <br />
</p>
<p><b>The code for this looks like:</b> </p><div class="fragment"><div class="line">NimBLEUUID serviceUuid(&quot;ABCD&quot;);</div>
<div class="line"> </div>
<div class="line">for(int i = 0; i &lt; results.getCount(); i++) {</div>
<div class="line"> NimBLEAdvertisedDevice device = results.getDevice(i);</div>
<div class="line"> </div>
<div class="line"> if (device.isAdvertisingService(serviceUuid)) {</div>
<div class="line"> // create a client and connect</div>
<div class="line"> }</div>
<div class="line">}</div>
</div><!-- fragment --><p> <br />
</p>
<p>Now that we can scan and parse advertisers we need to be able to create a <code><a class="el" href="class_nim_b_l_e_client.html" title="A model of a BLE client.">NimBLEClient</a></code> instance and use it to connect. <br />
</p>
<p>To do this we call <code><a class="el" href="class_nim_b_l_e_device.html#a010b12177917f33e7d3633736c0cc553" title="Creates a new client object, each client can connect to 1 peripheral device.">NimBLEDevice::createClient</a></code> which creates the <code><a class="el" href="class_nim_b_l_e_client.html" title="A model of a BLE client.">NimBLEClient</a></code> instance and returns a pointer to it. <br />
</p>
<p>After this we call <code><a class="el" href="class_nim_b_l_e_client.html#a2b49bc73802bf716cf3df3b5a93f0543" title="Connect to an advertising device.">NimBLEClient::connect</a></code> to connect to the advertiser. <br />
This takes a pointer to the <code><a class="el" href="class_nim_b_l_e_advertised_device.html" title="A representation of a BLE advertised device found by a scan.">NimBLEAdvertisedDevice</a></code> and returns <code>true</code> if successful.</p>
<p><b>Lets do that now:</b> </p><div class="fragment"><div class="line">NimBLEUUID serviceUuid(&quot;ABCD&quot;);</div>
<div class="line"> </div>
<div class="line">for(int i = 0; i &lt; results.getCount(); i++) {</div>
<div class="line"> NimBLEAdvertisedDevice device = results.getDevice(i);</div>
<div class="line"> </div>
<div class="line"> if (device.isAdvertisingService(serviceUuid)) {</div>
<div class="line"> NimBLEClient *pClient = NimBLEDevice::createClient();</div>
<div class="line"> </div>
<div class="line"> if(pClient-&gt;connect(&amp;device)) {</div>
<div class="line"> //success</div>
<div class="line"> } else {</div>
<div class="line"> // failed to connect</div>
<div class="line"> }</div>
<div class="line"> }</div>
<div class="line">}</div>
</div><!-- fragment --><p> As shown, the call to <code><a class="el" href="class_nim_b_l_e_client.html#a2b49bc73802bf716cf3df3b5a93f0543" title="Connect to an advertising device.">NimBLEClient::connect</a></code> should have it's return value tested to make sure it succeeded before proceeding to get data. <br />
<br />
</p>
<p>Next we need to access the servers data by asking it for the service and the characteristic we are interested in, then read the characteristic value.</p>
<p>To do this we call <code><a class="el" href="class_nim_b_l_e_client.html#ae22379ab10bd82932d2303fb3753c366" title="Get the service BLE Remote Service instance corresponding to the uuid.">NimBLEClient::getService</a></code>, which takes as a parameter the UUID of the service and returns <br />
a pointer an instance to <code><a class="el" href="class_nim_b_l_e_remote_service.html" title="A model of a remote BLE service.">NimBLERemoteService</a></code> or <code>nullptr</code> if the service was not found. <br />
</p>
<p>Next we will call <code><a class="el" href="class_nim_b_l_e_remote_service.html#ae10ddb56bc48bd06538ab49e4a561594" title="Get the remote characteristic object for the characteristic UUID.">NimBLERemoteService::getCharacteristic</a></code> which takes as a parameter the UUID of the service and returns <br />
a pointer to an instance of <code><a class="el" href="class_nim_b_l_e_remote_characteristic.html" title="A model of a remote BLE characteristic.">NimBLERemoteCharacteristic</a></code> or <code>nullptr</code> if not found. <br />
</p>
<p>Finally we will read the characteristic value with <code>NimBLERemoteCharacteristic::readValue()</code>. <br />
</p>
<p><b>Here is what that looks like:</b> </p><div class="fragment"><div class="line">NimBLEUUID serviceUuid(&quot;ABCD&quot;);</div>
<div class="line"> </div>
<div class="line">for(int i = 0; i &lt; results.getCount(); i++) {</div>
<div class="line"> NimBLEAdvertisedDevice device = results.getDevice(i);</div>
<div class="line"> </div>
<div class="line"> if (device.isAdvertisingService(serviceUuid)) {</div>
<div class="line"> NimBLEClient *pClient = NimBLEDevice::createClient();</div>
<div class="line"> </div>
<div class="line"> if (pClient-&gt;connect(&amp;device)) {</div>
<div class="line"> NimBLERemoteService *pService = pClient-&gt;getService(serviceUuid);</div>
<div class="line"> </div>
<div class="line"> if (pService != nullptr) {</div>
<div class="line"> NimBLERemoteCharacteristic *pCharacteristic = pService-&gt;getCharacteristic(&quot;1234&quot;);</div>
<div class="line"> </div>
<div class="line"> if (pCharacteristic != nullptr) {</div>
<div class="line"> std::string value = pCharacteristic-&gt;readValue();</div>
<div class="line"> // print or do whatever you need with the value</div>
<div class="line"> }</div>
<div class="line"> }</div>
<div class="line"> } else {</div>
<div class="line"> // failed to connect</div>
<div class="line"> }</div>
<div class="line"> }</div>
<div class="line">}</div>
</div><!-- fragment --><p> <br />
</p>
<p>The last thing we should do is clean up once we are done with the connection. <br />
Because multiple clients are supported and can be created we should delete them when finished with them to conserve resources. <br />
This is done by calling <code><a class="el" href="class_nim_b_l_e_device.html#a83aa0a3d9d57358d35082a442edf8549" title="Delete the client object and remove it from the list. Checks if it is connected or trying to connect ...">NimBLEDevice::deleteClient</a></code>.</p>
<p><b>Lets add that now:</b> </p><div class="fragment"><div class="line">NimBLEUUID serviceUuid(&quot;ABCD&quot;);</div>
<div class="line"> </div>
<div class="line">for(int i = 0; i &lt; results.getCount(); i++) {</div>
<div class="line"> NimBLEAdvertisedDevice device = results.getDevice(i);</div>
<div class="line"> </div>
<div class="line"> if (device.isAdvertisingService(serviceUuid)) {</div>
<div class="line"> NimBLEClient *pClient = NimBLEDevice::createClient();</div>
<div class="line"> </div>
<div class="line"> if (pClient-&gt;connect(&amp;device)) {</div>
<div class="line"> NimBLERemoteService *pService = pClient-&gt;getService(serviceUuid);</div>
<div class="line"> </div>
<div class="line"> if (pService != nullptr) {</div>
<div class="line"> NimBLERemoteCharacteristic *pCharacteristic = pService-&gt;getCharacteristic(&quot;1234&quot;);</div>
<div class="line"> </div>
<div class="line"> if (pCharacteristic != nullptr) {</div>
<div class="line"> std::string value = pCharacteristic-&gt;readValue();</div>
<div class="line"> // print or do whatever you need with the value</div>
<div class="line"> }</div>
<div class="line"> }</div>
<div class="line"> } else {</div>
<div class="line"> // failed to connect</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> NimBLEDevice::deleteClient(pClient);</div>
<div class="line"> }</div>
<div class="line">}</div>
</div><!-- fragment --><p> Note that there is no need to disconnect as that will be done when deleting the client instance. <br />
<br />
</p>
<p><b>Here is the full example code:</b> <br />
</p><div class="fragment"><div class="line">#include &quot;NimBLEDevice.h&quot;</div>
<div class="line"> </div>
<div class="line">// void setup() in Arduino</div>
<div class="line">void app_main(void) </div>
<div class="line">{</div>
<div class="line"> NimBLEDevice::init(&quot;&quot;);</div>
<div class="line"> </div>
<div class="line"> NimBLEScan *pScan = NimBLEDevice::getScan();</div>
<div class="line"> NimBLEScanResults results = pScan-&gt;start(10 * 1000);</div>
<div class="line"> </div>
<div class="line"> NimBLEUUID serviceUuid(&quot;ABCD&quot;);</div>
<div class="line"> </div>
<div class="line"> for(int i = 0; i &lt; results.getCount(); i++) {</div>
<div class="line"> NimBLEAdvertisedDevice device = results.getDevice(i);</div>
<div class="line"> </div>
<div class="line"> if (device.isAdvertisingService(serviceUuid)) {</div>
<div class="line"> NimBLEClient *pClient = NimBLEDevice::createClient();</div>
<div class="line"> </div>
<div class="line"> if (pClient-&gt;connect(&amp;device)) {</div>
<div class="line"> NimBLERemoteService *pService = pClient-&gt;getService(serviceUuid);</div>
<div class="line"> </div>
<div class="line"> if (pService != nullptr) {</div>
<div class="line"> NimBLERemoteCharacteristic *pCharacteristic = pService-&gt;getCharacteristic(&quot;1234&quot;);</div>
<div class="line"> </div>
<div class="line"> if (pCharacteristic != nullptr) {</div>
<div class="line"> std::string value = pCharacteristic-&gt;readValue();</div>
<div class="line"> // print or do whatever you need with the value</div>
<div class="line"> }</div>
<div class="line"> }</div>
<div class="line"> } else {</div>
<div class="line"> // failed to connect</div>
<div class="line"> }</div>
<div class="line"> </div>
<div class="line"> NimBLEDevice::deleteClient(pClient);</div>
<div class="line"> }</div>
<div class="line"> }</div>
<div class="line">}</div>
</div><!-- fragment --><p> <br />
</p>
<p>For more advanced features and options please see the client examples in the examples folder. <br />
<br />
</p>
</div></div><!-- contents -->
</div><!-- PageDoc -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.8 </li>
</ul>
</div>
</body>
</html>