Here is the project I just finished, the goal was to connect the Xiaomi Temperature and Humidity sensor (that you can buy for around 12€) with Blynk through ESP32.
Code
#include <esp_log.h>
#include <string>
#include <sstream>
#include <sys/time.h>
#include <BLEDevice.h>
#include <BLEAdvertisedDevice.h>
#include <BLEClient.h>
#include <BLEScan.h>
#include <BLEUtils.h>
#include <sdkconfig.h>
#define BLYNK_PRINT Serial // Defines the object that is used for printing
#define BLYNK_DEBUG // Optional, this enables more detailed prints
#define BLYNK_NO_BUILTIN // Disable built-in analog & digital pin operations
#include <Time.h>
#include <TimeLib.h>
//#include <WiFi.h>
//#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
//WidgetRTC rtc;
BlynkTimer timer;
BLEClient* pClient;
//**********TOKEN (OK)**********//
char auth[] = "YOUR BLINK TOKEN";
//**********WIFI (OK)**********//
char ssid[] = "WIFI";
char pass[] = "PASS";
#define MJ_ADDR "58:2D:34:31:F8:50"
static BLEAddress MJAddress(MJ_ADDR);
static boolean connected = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
uint8_t* pData;
float temp;
float humi;
int n=0;
WidgetBridge bridge1(V10); //Initiating Bridge Widget on V1 of Device LolinD32
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
// The remote service we wish to connect to.
static BLEUUID serviceUUID("226c0000-6476-4566-7562-66734470666d");
// The characteristic of the remote service we are interested in.
static BLEUUID charUUID("226caa55-6476-4566-7562-66734470666d");
static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
Serial.print("Notify callback for characteristic ");
Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
Serial.print(" of data length ");
Serial.println(length);
Serial.print("data: ");
Serial.println((char*)pData);
temp = ((pData[2]-48)*10 + pData[3]-48 + (pData[5]-48)*0.1);
Serial.println(temp);
humi = ((pData[9]-48)*10 + pData[10]-48 + (pData[12]-48)*0.1);
Serial.println(humi);
}
void sendSensorData(){
Serial.println("Sending data to Blynk");
Serial.println(temp);
Serial.println(humi);
Blynk.begin(auth, ssid, pass);
Blynk.connect();
bridge1.setAuthToken("BRIDGE TOKEN");
Blynk.virtualWrite(V17, temp);
Blynk.virtualWrite(V18, humi);
bridge1.virtualWrite(V17, temp);
bridge1.virtualWrite(V18, humi);
delay(500);
Blynk.disconnect();
WiFi.mode(WIFI_OFF);
}
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
Serial.println("on connect");
}
void onDisconnect(BLEClient* pclient) {
connected = false;
Serial.println("onDisconnect");
if (n==0){
Serial.println("RESTART");
ESP.restart();
}
}
};
void getSensorData1(){
connectToServer(MJAddress);
}
void connectToServer(BLEAddress pAddress){
n=0;
Serial.println(" - Created client");
pClient->setClientCallbacks(new MyClientCallback());
Serial.println("=================== Forming a connection to Flora device ====================");
Serial.println(pAddress.toString().c_str());
Serial.println(" - Connection to MJ");
pClient->connect(pAddress);
n=1;
Serial.println(" - Connected to MJ");
// 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();
}
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();
}
Serial.println(" - Found our characteristic");
pRemoteCharacteristic->registerForNotify(notifyCallback);
timer.setTimeout(10000L, sendSensorData);
}
void setup() {
Serial.begin(115200);
Serial.println("Starting MJ client...");
delay(500);
BLEDevice::init("");
pClient = BLEDevice::createClient();
delay(500);
timer.setInterval(600000L, getSensorData1);
}
void loop() {
timer.run();
}
You can find your sensor’s address using “nRF Connect” app on your Smartphone and replace the address in the sketch
Of course, the bridge part is not mandatory.
Hi @bog, this is also the Xiaomi device I used.
I can’t tell how to use a local server, because I use Blynk Cloud server, and I have no clue how to use a local one.
Nevertheless, the code for the ESP32 in the 1st message can be adapted. What you might need to change :
Sensor address
#define MJ_ADDR "58:2D:34:31:F8:50"
Change it with address of your Xiaomi device (nRF Connect on Appstore/Playstore)
In my code, Blynk.begin is not called in setup() function.
Try to delete Blynk.begin from setup(), and put it into sendSensorData() function, as I did.
Next, you can remove Bridge related code if you don’t need it. You also can try to delete any libraries (like esp_log for example) and try if it’s still work. To be honest, I copied a code without checking if every library is needed.
To implement multiple sensors, you can declare multiple address’ :
@cricri19top please edit your post, using the pencil icon at the bottom, and add triple backticks at the beginning and end of your code so that it displays correctly.
Triple backticks look like this:
```
@cricri19top despite me giving you some triple backticks to copy and paste, youve used different characters, which don’t work.
Please re-edit your code and use the correct triple backtick characters, otherwise your unformatted code will be deleted.
The thing I don’t like about your code is that you are clearing and re-writing your sensor data to your OLED display (and writing data to Blynk) every time the void loop is processed (which would normally be hundreds of times per second, but is being throttled to 5 times per second by the two 100ms delays).
However, your sensor data is changing much more slowly than this, so most of these OLED and Blynk actions are redundant as the data is the same.
A much more efficient way would be to have a function which re-writes your OLED and updates Blynk, and just call this function when the data from your sensors actually changes.