Arduino ESP32 如何将 BLEUUID 对象分配给字符串
Arduino ESP32 how to assign BLEUUID object into string
目前我们正在开发一个 android 应用程序,它可以在 BLE(bluetooth low energy)
到 ESP32
设备上宣传自己。 ESP32 收集 MAC address
、device name
和服务 UUID
并将数据发送到 MySQL server
。到目前为止,ESP32 可以发送设备名称和 MAC 地址,但不知何故,我们无法发送 UUID 数据。
http://www.neilkolban.com/esp32/docs/cpp_utils/html/class_b_l_e_advertised_device.html
从 BLEadvertisedDevice
库中,可以找到一些有用的信息。
据我所知,getServiceUUID () returns 一个 BlEUUID(http://www.neilkolban.com/esp32/docs/cpp_utils/html/class_b_l_e_u_u_i_d.html) 对象,它有一个 toString 方法,它接受 void 参数(不是 BLEadvertisedDevice 对象,而是 BLEUUID 对象)。我的第一个问题是为什么 BLEadvertisedDevice 不接受任何参数,但 BLEUUID 将 void 作为 toString 方法的参数。我试图将对象分配给字符串,但我没有机会尝试这些,下面给出了完整的代码。
const char *dev_uuid;
dev_uuid = device.getServiceUUID().toString().c_str();
strcpy(dev_uuid, device.getServiceUUID().toString().c_str());
dev_uuid = device.getServiceUUID().toString();
strcpy(dev_uuid, device.getServiceUUID().toString();
错误日志如下
这是完整的代码
#include <WiFi.h>
#include <BLEDevice.h>
#include <BLEAdvertisedDevice.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>
/*
INSERT CREDENTIALS
*/
char ssid[] = ""; // your SSID
char pass[] = ""; // your SSID Password
IPAddress server_addr(192, 168, 1, xx); // IP of the MySQL *server* here
char user[] = ""; // MySQL user login username
char password[] = ""; // MySQL user login password
IPAddress local_IP(192, 168, 1, xx); // ESP 32 IP
IPAddress gateway(192, 168, 1, xx); // GATEWAY
IPAddress subnet(255, 255, 255, 0); // SUBNET
IPAddress primaryDNS(192, 168, 1, xx); // DNS
WiFiClient client;
MySQL_Connection conn((Client *)&client);
int LED_BUILTIN = 2;
int scanTime = 10;
int RSSI_data;
int device_count = 0;
char MAC_data[17];
char query[128];
const char *dev_name;
const char *uuid_string;
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
}
};
char INSERT_DATA[] = "INSERT INTO yoklama.esp3_table (rssi, mac_address, device_name, dev_uuid) VALUES (%d,'%s','%s','%s')";
void setup()
{
Serial.begin(115200);
if (!WiFi.config(local_IP, gateway, subnet, primaryDNS)) {
Serial.println("STA Failed to configure");
}
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Serial.print("ESP Mac Address: ");
Serial.println(WiFi.macAddress());
Serial.print("Subnet Mask: ");
Serial.println(WiFi.subnetMask());
Serial.print("Gateway IP: ");
Serial.println(WiFi.gatewayIP());
Serial.print("DNS: ");
Serial.println(WiFi.dnsIP());
}
void loop()
{
while (WiFi.status() != WL_CONNECTED) {
delay(500);
WiFi.begin(ssid, pass);
Serial.print("Trying to Connect");
}
if (conn.connect(server_addr, 3306, user, password)) {
Serial.println("Connected to database!");
delay(10000);
}
else
Serial.println("Connection failed.");
//conn.close();
Serial.println("Scanning ...\n");
BLEDevice::init("");
BLEScan* pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
BLEScanResults foundDevices = pBLEScan->start(scanTime);
digitalWrite(LED_BUILTIN, LOW);
device_count = foundDevices.getCount();
Serial.printf("Cihaz sayısı: %d\n", device_count);
Serial.print("Devices found: \n"); // THIS IS THE PART THE DATA IS SENT TO MYSQL
for (uint32_t i = 0; i < device_count; i++)
{
digitalWrite(LED_BUILTIN, HIGH);
BLEAdvertisedDevice device = foundDevices.getDevice(i);
RSSI_data = device.getRSSI(); // CAN GET THE RSSI WITHOUT PROBLEM
dev_name = device.getName().c_str(); // CAN GET THE DEV NAME WITHOUT PROBLEM
strcpy( MAC_data, device.getAddress().toString().c_str()); // CAN GET THE MAC WITHOUT PROBLEM
/* I NEED HELP TO GET THE UUID DATA SO FAR I TRIED THESE METHODS.
dev_uuid = device.getServiceUUID().toString().c_str();
strcpy(dev_uuid, device.getServiceUUID().toString().c_str());
dev_uuid = device.getServiceUUID().toString();
strcpy(dev_uuid, device.getServiceUUID().toString();
*/
Serial.printf("MAC adres = %s --- ", MAC_data);
Serial.printf("Device Name = '%s' --- ", dev_name);
Serial.printf("RSSI = %d --- ", RSSI_data);
//Serial.printf("UUID %d\n", dev_uuid);
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
sprintf(query, INSERT_DATA, RSSI_data, MAC_data, dev_name, dev_uuid);
cur_mem->execute(query);
delete cur_mem;
delay(2000);
}
pBLEScan->clearResults();
delay(300);
}
错误:dev_uuid = device.getServiceUUID().toString().c_str();
它编译但来自串行监视器:
08:58:59.404 -> entry 0x400806a8
08:58:59.914 -> Connecting to
08:59:00.421 -> .
08:59:00.421 -> WiFi connected!
08:59:00.421 -> IP address: 192.168.1.
08:59:00.421 -> ESP Mac Address: 80:7D:3A:99:82:D4
08:59:00.421 -> Subnet Mask: 255.255.255.0
08:59:00.421 -> Gateway IP: 192.168.1
08:59:00.421 -> DNS: 192.168.1
08:59:00.454 -> Connected to database!
08:59:10.459 -> Scanning...
08:59:10.459 ->
08:59:21.115 -> Cihaz sayısı: 8
08:59:21.115 -> Devices found:
08:59:21.115 -> Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
08:59:21.115 -> Core 1 register dump:
08:59:21.115 -> PC : 0x4000c2e0 PS : 0x00060430 A0 : 0x800d3160 A1 : 0x3ffcecb0
08:59:21.115 -> A2 : 0x3ffced30 A3 : 0x00000000 A4 : 0x00000013 A5 : 0x3ffced30
08:59:21.150 -> A6 : 0x00000000 A7 : 0x00000001 A8 : 0x00000000 A9 : 0x3ffcec70
08:59:21.150 -> A10 : 0x00000000 A11 : 0x3ffced7c A12 : 0x3ffced7c A13 : 0x00000000
08:59:21.150 -> A14 : 0x00000000 A15 : 0x5b0a0a20 SAR : 0x0000001e EXCCAUSE: 0x0000001c
08:59:21.150 -> EXCVADDR: 0x00000000 LBEG : 0x4000c2e0 LEND : 0x4000c2f6 LCOUNT : 0x00000000
08:59:21.185 ->
08:59:21.185 -> Backtrace: 0x4000c2e0:0x3ffcecb0 0x400d315d:0x3ffcecc0 0x400d188a:0x3ffcece0 0x400d821d:0x3ffcee00 0x4008e095:0x3ffcee20
08:59:21.185 ->
08:59:21.185 -> Rebooting...
08:59:21.185 -> ets Jun 8 2016 00:22:57
错误:strcpy(dev_uuid,device.getServiceUUID().toString().c_str());
C:\Users\...\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/newlib/string.h:30:15: note: initializing argument 1 of 'char* strcpy(char*, const char*)'
char *_EXFUN(strcpy,(char *__restrict, const char *__restrict));
错误:strcpy(dev_uuid,device.getServiceUUID().toString());
invalid conversion from 'const char*' to 'char*' [-fpermissive]
错误:dev_uuid = device.getServiceUUID().toString());
cannot convert 'std::__cxx11::string {aka std::__cxx11::basic_string<char>}' to 'const char*' in assignment
在您的代码中:
const char *dev_uuid;
dev_uuid = device.getServiceUUID().toString().c_str();
strcpy(dev_uuid, device.getServiceUUID().toString().c_str());
dev_uuid = device.getServiceUUID().toString();
strcpy(dev_uuid, device.getServiceUUID().toString();
您的 strcpy()
尝试不可能像您写的那样奏效。您有一个未初始化的指针 (dev_uuid
),并且您正在将数据复制到……它恰好指向的任何地方。这就是你感到恐慌的原因。
使用 String
对象,而不是 C 字符串:
String dev_uuid;
dev_uuid = device.getServiceUUID().toString();
Arduino String
class 和 C 字符串之间存在巨大差异。一般来说,如果你看到 toString()
方法,它就是 Arduino 字符串 class。阅读文档应该清楚一个方法 returns a String
;如果是,您应该将 return 值分配给 String
.
C 字符串更难处理。您正在直接操纵指向内存和内存内容的指针。它们的空终止字符总是比它们的长度指示的多一个字节。在复制到它们之前,您需要确保为它们分配了内存。
对此进行更新。
dev_uuid = device.getServiceUUID().toString().c_str();
这是正确的方法。
如果广告商设备未设置 UUID,则获取扫描结果时 dev_uuid
returns 为 null,无法打印或任何内容。您可以将 .haveServiceUUID 方法添加到 return 布尔值,如果它为真,那么您可以毫无问题地获取 UUID。否则,如果广告商设备未设置 UUID,则会出现导致 Guru Meditation Error: Core
的问题
if (advertisedDevice.haveServiceUUID ())
dev_uuid = advertisedDevice.toString().c_str();
目前我们正在开发一个 android 应用程序,它可以在 BLE(bluetooth low energy)
到 ESP32
设备上宣传自己。 ESP32 收集 MAC address
、device name
和服务 UUID
并将数据发送到 MySQL server
。到目前为止,ESP32 可以发送设备名称和 MAC 地址,但不知何故,我们无法发送 UUID 数据。
http://www.neilkolban.com/esp32/docs/cpp_utils/html/class_b_l_e_advertised_device.html
从 BLEadvertisedDevice
库中,可以找到一些有用的信息。
据我所知,getServiceUUID () returns 一个 BlEUUID(http://www.neilkolban.com/esp32/docs/cpp_utils/html/class_b_l_e_u_u_i_d.html) 对象,它有一个 toString 方法,它接受 void 参数(不是 BLEadvertisedDevice 对象,而是 BLEUUID 对象)。我的第一个问题是为什么 BLEadvertisedDevice 不接受任何参数,但 BLEUUID 将 void 作为 toString 方法的参数。我试图将对象分配给字符串,但我没有机会尝试这些,下面给出了完整的代码。
const char *dev_uuid;
dev_uuid = device.getServiceUUID().toString().c_str();
strcpy(dev_uuid, device.getServiceUUID().toString().c_str());
dev_uuid = device.getServiceUUID().toString();
strcpy(dev_uuid, device.getServiceUUID().toString();
错误日志如下
这是完整的代码
#include <WiFi.h>
#include <BLEDevice.h>
#include <BLEAdvertisedDevice.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>
/*
INSERT CREDENTIALS
*/
char ssid[] = ""; // your SSID
char pass[] = ""; // your SSID Password
IPAddress server_addr(192, 168, 1, xx); // IP of the MySQL *server* here
char user[] = ""; // MySQL user login username
char password[] = ""; // MySQL user login password
IPAddress local_IP(192, 168, 1, xx); // ESP 32 IP
IPAddress gateway(192, 168, 1, xx); // GATEWAY
IPAddress subnet(255, 255, 255, 0); // SUBNET
IPAddress primaryDNS(192, 168, 1, xx); // DNS
WiFiClient client;
MySQL_Connection conn((Client *)&client);
int LED_BUILTIN = 2;
int scanTime = 10;
int RSSI_data;
int device_count = 0;
char MAC_data[17];
char query[128];
const char *dev_name;
const char *uuid_string;
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
}
};
char INSERT_DATA[] = "INSERT INTO yoklama.esp3_table (rssi, mac_address, device_name, dev_uuid) VALUES (%d,'%s','%s','%s')";
void setup()
{
Serial.begin(115200);
if (!WiFi.config(local_IP, gateway, subnet, primaryDNS)) {
Serial.println("STA Failed to configure");
}
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Serial.print("ESP Mac Address: ");
Serial.println(WiFi.macAddress());
Serial.print("Subnet Mask: ");
Serial.println(WiFi.subnetMask());
Serial.print("Gateway IP: ");
Serial.println(WiFi.gatewayIP());
Serial.print("DNS: ");
Serial.println(WiFi.dnsIP());
}
void loop()
{
while (WiFi.status() != WL_CONNECTED) {
delay(500);
WiFi.begin(ssid, pass);
Serial.print("Trying to Connect");
}
if (conn.connect(server_addr, 3306, user, password)) {
Serial.println("Connected to database!");
delay(10000);
}
else
Serial.println("Connection failed.");
//conn.close();
Serial.println("Scanning ...\n");
BLEDevice::init("");
BLEScan* pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
BLEScanResults foundDevices = pBLEScan->start(scanTime);
digitalWrite(LED_BUILTIN, LOW);
device_count = foundDevices.getCount();
Serial.printf("Cihaz sayısı: %d\n", device_count);
Serial.print("Devices found: \n"); // THIS IS THE PART THE DATA IS SENT TO MYSQL
for (uint32_t i = 0; i < device_count; i++)
{
digitalWrite(LED_BUILTIN, HIGH);
BLEAdvertisedDevice device = foundDevices.getDevice(i);
RSSI_data = device.getRSSI(); // CAN GET THE RSSI WITHOUT PROBLEM
dev_name = device.getName().c_str(); // CAN GET THE DEV NAME WITHOUT PROBLEM
strcpy( MAC_data, device.getAddress().toString().c_str()); // CAN GET THE MAC WITHOUT PROBLEM
/* I NEED HELP TO GET THE UUID DATA SO FAR I TRIED THESE METHODS.
dev_uuid = device.getServiceUUID().toString().c_str();
strcpy(dev_uuid, device.getServiceUUID().toString().c_str());
dev_uuid = device.getServiceUUID().toString();
strcpy(dev_uuid, device.getServiceUUID().toString();
*/
Serial.printf("MAC adres = %s --- ", MAC_data);
Serial.printf("Device Name = '%s' --- ", dev_name);
Serial.printf("RSSI = %d --- ", RSSI_data);
//Serial.printf("UUID %d\n", dev_uuid);
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
sprintf(query, INSERT_DATA, RSSI_data, MAC_data, dev_name, dev_uuid);
cur_mem->execute(query);
delete cur_mem;
delay(2000);
}
pBLEScan->clearResults();
delay(300);
}
错误:dev_uuid = device.getServiceUUID().toString().c_str(); 它编译但来自串行监视器:
08:58:59.404 -> entry 0x400806a8
08:58:59.914 -> Connecting to
08:59:00.421 -> .
08:59:00.421 -> WiFi connected!
08:59:00.421 -> IP address: 192.168.1.
08:59:00.421 -> ESP Mac Address: 80:7D:3A:99:82:D4
08:59:00.421 -> Subnet Mask: 255.255.255.0
08:59:00.421 -> Gateway IP: 192.168.1
08:59:00.421 -> DNS: 192.168.1
08:59:00.454 -> Connected to database!
08:59:10.459 -> Scanning...
08:59:10.459 ->
08:59:21.115 -> Cihaz sayısı: 8
08:59:21.115 -> Devices found:
08:59:21.115 -> Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
08:59:21.115 -> Core 1 register dump:
08:59:21.115 -> PC : 0x4000c2e0 PS : 0x00060430 A0 : 0x800d3160 A1 : 0x3ffcecb0
08:59:21.115 -> A2 : 0x3ffced30 A3 : 0x00000000 A4 : 0x00000013 A5 : 0x3ffced30
08:59:21.150 -> A6 : 0x00000000 A7 : 0x00000001 A8 : 0x00000000 A9 : 0x3ffcec70
08:59:21.150 -> A10 : 0x00000000 A11 : 0x3ffced7c A12 : 0x3ffced7c A13 : 0x00000000
08:59:21.150 -> A14 : 0x00000000 A15 : 0x5b0a0a20 SAR : 0x0000001e EXCCAUSE: 0x0000001c
08:59:21.150 -> EXCVADDR: 0x00000000 LBEG : 0x4000c2e0 LEND : 0x4000c2f6 LCOUNT : 0x00000000
08:59:21.185 ->
08:59:21.185 -> Backtrace: 0x4000c2e0:0x3ffcecb0 0x400d315d:0x3ffcecc0 0x400d188a:0x3ffcece0 0x400d821d:0x3ffcee00 0x4008e095:0x3ffcee20
08:59:21.185 ->
08:59:21.185 -> Rebooting...
08:59:21.185 -> ets Jun 8 2016 00:22:57
错误:strcpy(dev_uuid,device.getServiceUUID().toString().c_str());
C:\Users\...\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/newlib/string.h:30:15: note: initializing argument 1 of 'char* strcpy(char*, const char*)'
char *_EXFUN(strcpy,(char *__restrict, const char *__restrict));
错误:strcpy(dev_uuid,device.getServiceUUID().toString());
invalid conversion from 'const char*' to 'char*' [-fpermissive]
错误:dev_uuid = device.getServiceUUID().toString());
cannot convert 'std::__cxx11::string {aka std::__cxx11::basic_string<char>}' to 'const char*' in assignment
在您的代码中:
const char *dev_uuid;
dev_uuid = device.getServiceUUID().toString().c_str();
strcpy(dev_uuid, device.getServiceUUID().toString().c_str());
dev_uuid = device.getServiceUUID().toString();
strcpy(dev_uuid, device.getServiceUUID().toString();
您的 strcpy()
尝试不可能像您写的那样奏效。您有一个未初始化的指针 (dev_uuid
),并且您正在将数据复制到……它恰好指向的任何地方。这就是你感到恐慌的原因。
使用 String
对象,而不是 C 字符串:
String dev_uuid;
dev_uuid = device.getServiceUUID().toString();
Arduino String
class 和 C 字符串之间存在巨大差异。一般来说,如果你看到 toString()
方法,它就是 Arduino 字符串 class。阅读文档应该清楚一个方法 returns a String
;如果是,您应该将 return 值分配给 String
.
C 字符串更难处理。您正在直接操纵指向内存和内存内容的指针。它们的空终止字符总是比它们的长度指示的多一个字节。在复制到它们之前,您需要确保为它们分配了内存。
对此进行更新。
dev_uuid = device.getServiceUUID().toString().c_str();
这是正确的方法。
如果广告商设备未设置 UUID,则获取扫描结果时 dev_uuid
returns 为 null,无法打印或任何内容。您可以将 .haveServiceUUID 方法添加到 return 布尔值,如果它为真,那么您可以毫无问题地获取 UUID。否则,如果广告商设备未设置 UUID,则会出现导致 Guru Meditation Error: Core
if (advertisedDevice.haveServiceUUID ())
dev_uuid = advertisedDevice.toString().c_str();