/**
* Create a sample BLE client that connects to a BLE server and then retrieves the current
* characteristic value. It will then periodically update the value of the characteristic on the
* remote server with the current time since boot.
*/
#include <esp_log.h>
#include <string>
#include <iostream>
#include <sstream>
#include <sys/time.h>
#include "BLEDevice.h"
#include "BLEAdvertisedDevice.h"
#include "BLEClient.h"
#include "BLEScan.h"
#include "BLEUtils.h"
#include "Task.h"
#include "sdkconfig.h"
static const char* CTL_NAME = "DSD TECH";
static const char* HARM_NAME = "HarmCtl";
#define SERVICE_UUID "0000FFE0-0000-1000-8000-00805F9B34FB"
#define CHARACTERISTIC_UUID "0000FFE1-0000-1000-8000-00805F9B34FB"
#define DESCRIPTOR_UUID "00002902-0000-1000-8000-00805F9B34FB"
static BLEUUID serviceUUID(SERVICE_UUID);
static BLEUUID charUUID(CHARACTERISTIC_UUID);
bool finishedScanning = false;
bool CtlCompletedConn = false;
bool HarmCompletedConn = false;
static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify)
{
char arr[32];
for(int i = 0; i < length && i < 32; i++)
{
arr[i] = pData[i];
}
arr[length] = '\0';
printf("%s (%d)\n", arr, length);
}
/**
* Become a BLE client to a remote BLE server. We are passed in the address of the BLE server
* as the input parameter when the task is created.
*/
class MyClient
{
public:
bool CompletedConn = false;
bool ConnSuccess = false;
std::string deviceName;
MyClient(std::string s, BLEAddress* data)
{
deviceName = s;
pAddress = new BLEAddress(*data->getNative());
}
~MyClient()
{
pClient->disconnect();
Log( "%s clean up\n", deviceName.c_str());
}
bool createClient()
{
try
{
//esp_ble_gap_set_prefer_conn_params(*(pAddress->getNative()), 8, 20, 0, 600);
Log("Creating client connection\n");
pClient = BLEDevice::createClient();
Log("client object created\n");
// esp_ble_gap_set_prefer_conn_params(*(pAddress->getNative()), 8, 20, 0, 6000);
pClient->connect(*pAddress);
// esp_ble_gap_set_prefer_conn_params(*(pAddress->getNative()), 8, 20, 0, 6000);
Log("Client is Connected\n");
// Obtain a reference to the service we are after in the remote BLE server.
pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr)
{
Log("Failed to find our service UUID: %s\n", serviceUUID.toString().c_str());
ConnSuccess = false;
CompletedConn = true;
return ConnSuccess;
}
Log("Service retrieved\n");
// Obtain a reference to the characteristic in the service of the remote BLE server.
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (pRemoteCharacteristic == nullptr) {
Log("Failed to find our characteristic UUID: %s\n", charUUID.toString().c_str());
ConnSuccess = false;
CompletedConn = true;
return ConnSuccess;
}
Log("Remote characteristic created\n");
if(pRemoteCharacteristic->canNotify())
pRemoteCharacteristic->registerForNotify(notifyCallback);
Log("Char Notify created\n");
ConnSuccess = true;
CompletedConn = true;
}
catch(...)
{
ConnSuccess = false;
CompletedConn = true;
Log("!!! Exception while starting client connection\n");
}
return ConnSuccess;
}
void Send(std::string s)
{
if(pRemoteCharacteristic != nullptr)
{
pRemoteCharacteristic->writeValue(s.c_str());
}
else
{
Log("Error sending value");
}
}
bool isConnected()
{
return pClient->isConnected();
}
private:
void Log(const char * format, ...)
{
va_list argptr;
printf("%s: ", deviceName.c_str());
va_start(argptr, format);
vprintf(format, argptr);
va_end(argptr);
}
BLERemoteCharacteristic* pRemoteCharacteristic = nullptr;
BLERemoteService* pRemoteService = nullptr;
BLEClient* pClient = nullptr;
BLEAddress* pAddress;
}; // MyClient
MyClient* pCtlClient;
MyClient* pHarmClient;
/**
* Scan for BLE servers and find the first one that advertises the service we are looking for.
*/
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks
{
bool foundBoth = false;
void logprint(char *, ...)
{
}
/**
* Called for each advertising BLE server.
*/
void onResult(BLEAdvertisedDevice advertisedDevice)
{
if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID))
{
std::string devName = advertisedDevice.getName();
if(devName == CTL_NAME || devName == HARM_NAME)
{
printf("Found %s! address: %s\n", devName.c_str(), advertisedDevice.getAddress().toString().c_str());
if(devName == CTL_NAME)
{
pCtlClient = new MyClient(devName, new BLEAddress(*advertisedDevice.getAddress().getNative()));
}
else
{
pHarmClient = new MyClient(devName, new BLEAddress(*advertisedDevice.getAddress().getNative()));
}
if(foundBoth)
{
advertisedDevice.getScan()->stop();
finishedScanning = true;
}
foundBoth = true;
}
} // Found our server
} // onResult
}; // MyAdvertisedDeviceCallbacks
/**
* Perform the work of a sample BLE client.
*/
void SampleClient(void)
{
printf("Scanning sample starting\n");
BLEDevice::init("HarmCentral");
BLEScan *pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true);
pBLEScan->start(15);
printf("Waiting for discovery to complete: ");
while(!finishedScanning)
{
FreeRTOS::sleep(500);
printf(".");
}
printf("\n");
if(pCtlClient->createClient() && pHarmClient->createClient())
{
while(pHarmClient->isConnected() && pCtlClient->isConnected())
{
printf("Running start...\n");
//pHarmClient->Send("Hi client");
//pCtlClient->Send("Hi controller");
FreeRTOS::sleep(5000);
printf("Running end...\n");
}
printf("Lost connection %s\n", pHarmClient->isConnected() ? "Controller" : "Harmonizer");
}
else
{
printf("HarmCtl = %d Ctl = %d\n", pHarmClient->ConnSuccess, pCtlClient->ConnSuccess);
}
delete pCtlClient;
delete pHarmClient;
} // SampleClient
extern "C" void app_main()
{
SampleClient();
printf("================ DONE =================\n");
esp_restart();
} // app_main