Last active
April 7, 2020 09:08
-
-
Save kholia/9d74960b7dd39be23a080031f5101bcf to your computer and use it in GitHub Desktop.
ESP32 + UT353-BT Mini Sound Level Meter. NO SUPPORT IS PROVIDED.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A BLE client example that is rich in capabilities. | |
* There is a lot new capabilities implemented. | |
* author unknown | |
* updated by chegewara | |
*/ | |
// QnD support for "UT353-BT Mini Sound Level Meter" by Dhiru Kholia (March 2020) | |
// - Publishes sensor data to a Redis server on LAN | |
// https://raw.githubusercontent.com/RuiSantosdotme/ESP32-Course/master/code/Dual_Core/Dual_Core_Blinking_LEDs/Dual_Core_Blinking_LEDs.ino | |
#include <WiFi.h> | |
#include <WiFiMulti.h> | |
#include <HTTPClient.h> | |
#include "variables.h" | |
#include "BLEDevice.h" | |
//#include "BLEScan.h" | |
#include <ArduinoJson.h> | |
TaskHandle_t Task1; | |
TaskHandle_t Task2; | |
QueueHandle_t queue; | |
int capacity = 1024; | |
// The remote service we wish to connect to - WX_SERVICE_UUID | |
static BLEUUID serviceUUID("0000FF12-0000-1000-8000-00805f9b34fb"); | |
// The characteristic of the remote service we are interested in - WX_CHAR_UUID | |
static BLEUUID charUUID("0000FF01-0000-1000-8000-00805f9b34fb"); | |
static BLEUUID WX_NOTIFICATION_UUID("0000FF02-0000-1000-8000-00805f9b34fb"); | |
static boolean doConnect = false; | |
static boolean connected = false; | |
static boolean doScan = false; | |
static BLERemoteCharacteristic *pRemoteCharacteristic, | |
*pRemoteCharacteristicNotify; | |
static BLEAdvertisedDevice *myDevice; | |
static void notifyCallback(BLERemoteCharacteristic *pBLERemoteCharacteristic, | |
uint8_t *pData, size_t length, bool isNotify) { | |
static int counter = 0; | |
counter++; | |
if (counter % 32 == 0) { | |
Serial.println("+"); | |
// Serial.println(ESP.getFreeHeap()); | |
counter = 0; | |
} | |
/* Serial.print("Notify callback for characteristic "); | |
Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str()); | |
Serial.print(" of data length "); | |
Serial.println(length); */ | |
// Serial.print("data: "); | |
String buf = (char *)pData + 6; // offset to data | |
float value = buf.toFloat(); | |
// Serial.println(value); // with offset to data | |
xQueueSend(queue, &value, portMAX_DELAY); | |
} | |
class MyClientCallback : public BLEClientCallbacks { | |
void onConnect(BLEClient *pclient) {} | |
void onDisconnect(BLEClient *pclient) { | |
connected = false; | |
Serial.println("onDisconnect"); | |
} | |
}; | |
bool connectToServer() { | |
Serial.print("Forming a connection to "); | |
Serial.println(myDevice->getAddress().toString().c_str()); | |
BLEClient *pClient = BLEDevice::createClient(); | |
Serial.println(" - Created client"); | |
pClient->setClientCallbacks(new MyClientCallback()); | |
// Connect to the remove BLE Server. | |
pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of | |
// address, it will be recognized type of peer | |
// device address (public or private) | |
Serial.println(" - Connected to server"); | |
// Obtain a reference to the service we are after in the remote BLE server. | |
BLERemoteService *pRemoteService = pClient->getService(serviceUUID); | |
if (pRemoteService == nullptr) { | |
Serial.print("Failed to find our service UUID: "); | |
Serial.println(serviceUUID.toString().c_str()); | |
pClient->disconnect(); | |
return false; | |
} | |
Serial.println(" - Found our service"); | |
// Obtain a reference to the characteristic in the service of the remote BLE | |
// server. | |
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID); | |
if (pRemoteCharacteristic == nullptr) { | |
Serial.print("Failed to find our characteristic UUID: "); | |
Serial.println(charUUID.toString().c_str()); | |
pClient->disconnect(); | |
return false; | |
} | |
Serial.println(" - Found our characteristic"); | |
// notify hack | |
pRemoteCharacteristicNotify = | |
pRemoteService->getCharacteristic(WX_NOTIFICATION_UUID); | |
if (pRemoteCharacteristicNotify == nullptr) { | |
Serial.print("Failed to find our characteristic UUID: "); | |
Serial.println(charUUID.toString().c_str()); | |
pClient->disconnect(); | |
return false; | |
} | |
Serial.println(" - Found our notify characteristic"); | |
// Read the value of the characteristic. | |
if (pRemoteCharacteristicNotify->canRead()) { | |
std::string value = pRemoteCharacteristic->readValue(); | |
Serial.print("The characteristic value was: "); | |
Serial.println(value.c_str()); | |
} | |
const uint8_t notificationOn[] = {0x1, 0x0}; | |
pRemoteCharacteristicNotify->getDescriptor(BLEUUID((uint16_t)0x2902)) | |
->writeValue((uint8_t *)notificationOn, 2, true); | |
if (pRemoteCharacteristic->canNotify()) | |
pRemoteCharacteristic->registerForNotify(notifyCallback); | |
if (pRemoteCharacteristicNotify->canNotify()) | |
pRemoteCharacteristicNotify->registerForNotify(notifyCallback); | |
else | |
Serial.println("Failed to setup notify!"); | |
connected = true; | |
return true; | |
} | |
/** | |
* Scan for BLE servers and find the first one that advertises the service we | |
* are looking for. | |
*/ | |
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks { | |
/** | |
* Called for each advertising BLE server. | |
*/ | |
void onResult(BLEAdvertisedDevice advertisedDevice) { | |
Serial.print("BLE Advertised Device found: "); | |
Serial.println(advertisedDevice.toString().c_str()); | |
// We have found a device, let us now see if it contains the service we are | |
// looking for. | |
if (advertisedDevice.haveServiceUUID() && | |
advertisedDevice.isAdvertisingService(serviceUUID)) { | |
BLEDevice::getScan()->stop(); | |
myDevice = new BLEAdvertisedDevice(advertisedDevice); | |
doConnect = true; | |
doScan = true; | |
} // Found our server | |
} // onResult | |
}; // MyAdvertisedDeviceCallbacks | |
// Not sure if WiFiClientSecure checks the validity date of the certificate. | |
// Setting clock just to be sure... | |
void setClock() { | |
configTime(0, 0, "pool.ntp.org", "time.nist.gov"); | |
Serial.print(F("Waiting for NTP time sync: ")); | |
time_t nowSecs = time(nullptr); | |
while (nowSecs < 8 * 3600 * 2) { | |
delay(500); | |
Serial.print(F(".")); | |
yield(); | |
nowSecs = time(nullptr); | |
} | |
Serial.println(); | |
struct tm timeinfo; | |
gmtime_r(&nowSecs, &timeinfo); | |
Serial.print(F("Current time: ")); | |
Serial.print(asctime(&timeinfo)); | |
} | |
WiFiMulti WiFiMulti; | |
void setup() { | |
Serial.begin(115200); | |
Serial.println("Starting Arduino BLE Client application..."); | |
BLEDevice::init(""); | |
Serial.println(); | |
Serial.println(); | |
Serial.print("Connecting to "); | |
Serial.println(ssid); | |
WiFi.mode(WIFI_STA); | |
WiFiMulti.addAP(ssid, password); | |
// wait for WiFi connection | |
Serial.print("Waiting for WiFi to connect..."); | |
while ((WiFiMulti.run() != WL_CONNECTED)) { | |
Serial.print("."); | |
delay(500); | |
} | |
Serial.println(""); | |
Serial.println("WiFi connected"); | |
Serial.println("IP address: "); | |
Serial.println(WiFi.localIP()); | |
// Retrieve a Scanner and set the callback we want to use to be informed when | |
// we have detected a new device. Specify that we want active scanning and | |
// start the scan to run for 5 seconds. | |
BLEScan *pBLEScan = BLEDevice::getScan(); | |
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); | |
pBLEScan->setInterval(1349); | |
pBLEScan->setWindow(449); | |
pBLEScan->setActiveScan(true); | |
pBLEScan->start(5, false); | |
// create a task that will be executed in the Task1Sensor() function, with | |
// priority 1 and executed on core 0 | |
xTaskCreatePinnedToCore( | |
Task1Sensor, /* Task function. */ | |
"Task1", /* name of task. */ | |
10000, /* Stack size of task */ | |
NULL, /* parameter of the task */ | |
7, /* priority of the task */ | |
&Task1, /* Task handle to keep track of created task */ | |
0); /* pin task to core 0 */ | |
delay(500); | |
// create a task that will be executed in the Task2Publish() function, with | |
// priority 1 and executed on core 1 | |
xTaskCreatePinnedToCore( | |
Task2Publish, | |
"Task2", | |
10000, | |
NULL, | |
1, | |
&Task2, | |
1); | |
queue = xQueueCreate(capacity, sizeof(float)); | |
if (queue == NULL) { | |
Serial.println("Error creating the queue"); | |
} | |
} // End of setup. | |
// Task1Sensor: blinks an LED every 1000 ms | |
void Task1Sensor(void *pvParameters) { | |
Serial.print("Task1 running on core "); | |
Serial.println(xPortGetCoreID()); | |
for (;;) { | |
/* digitalWrite(led1, HIGH); | |
delay(1000); | |
digitalWrite(led1, LOW); | |
delay(1000); */ | |
// If the flag "doConnect" is true then we have scanned for and found the | |
// desired BLE Server with which we wish to connect. Now we connect to it. | |
// Once we are connected we set the connected flag to be true. | |
if (doConnect == true) { | |
if (connectToServer()) { | |
Serial.println("We are now connected to the BLE Server."); | |
} else { | |
Serial.println("We have failed to connect to the server; there is " | |
"nothing more we will do."); | |
} | |
doConnect = false; | |
} | |
// If we are connected to a peer BLE Server, update the characteristic each | |
// time we are reached with the current time since boot. | |
if (connected) { | |
// String newValue = "Time since boot: " + String(millis() / 1000); | |
// Serial.println("Setting new characteristic value to \"" + newValue + | |
// "\""); | |
// Set the characteristic's value to be the array of bytes that is | |
// actually a string. pRemoteCharacteristic->writeValue(newValue.c_str(), | |
// newValue.length()); | |
// BluetoothLeService.this.writeRXCharacteristic("0x5e"); | |
pRemoteCharacteristic->writeValue(0x5e, 1); | |
} else if (doScan) { | |
BLEDevice::getScan()->start( | |
0); // this is just eample to start scan after disconnect, most likely | |
// there is better way to do it in arduino | |
} | |
delay(10); | |
} | |
} | |
void Task2Publish(void *pvParameters) { | |
Serial.print("Task2 running on core "); | |
Serial.println(xPortGetCoreID()); | |
char buf[1024]; | |
WiFiClient redis; | |
IPAddress gateway; | |
float element; | |
for (;;) { | |
if ((WiFiMulti.run() == WL_CONNECTED)) { | |
gateway = WiFi.gatewayIP(); | |
// Serial.println(gateway); | |
// Serial.println("-"); | |
int qlen = uxQueueMessagesWaiting(queue); | |
Serial.println(qlen); | |
for (int i = 0; i < 64; i++) { | |
redis.connect(gateway, 6379); | |
xQueueReceive(queue, &element, portMAX_DELAY); | |
String szValue = String(element); | |
sprintf(buf, "*3\r\n$5\r\nLPUSH\r\n$4\r\ndata\r\n$%d\r\n%s\r\n", szValue.length(), szValue.c_str()); | |
redis.write(buf); | |
/* if (redis.available()) { | |
redis.read(); | |
} */ | |
redis.stop(); | |
} | |
} | |
// With delay(10) in sensor loop, we produce < 24 data points every second, | |
// and we have storage for 1024 such points. | |
delay(1000); | |
} | |
} | |
void loop() {} // End of loop |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment