Unverified Commit 0da8ecbc authored by Me No Dev's avatar Me No Dev Committed by GitHub

Merge branch 'master' into release/v2.x

parents 1ca741eb 6d64a3b6
...@@ -18,26 +18,6 @@ ...@@ -18,26 +18,6 @@
uint32_t scanTime = 100; //In 10ms (1000ms) uint32_t scanTime = 100; //In 10ms (1000ms)
BLEScan* pBLEScan; BLEScan* pBLEScan;
/**
* @brief extend adv report parameters
*/
//typedef struct {
// esp_ble_gap_adv_type_t event_type; /*!< extend advertising type */
// uint8_t addr_type; /*!< extend advertising address type */
// esp_bd_addr_t addr; /*!< extend advertising address */
// esp_ble_gap_pri_phy_t primary_phy; /*!< extend advertising primary phy */
// esp_ble_gap_phy_t secondly_phy; /*!< extend advertising secondary phy */
// uint8_t sid; /*!< extend advertising sid */
// uint8_t tx_power; /*!< extend advertising tx power */
// int8_t rssi; /*!< extend advertising rssi */
// uint16_t per_adv_interval; /*!< periodic advertising interval */
// uint8_t dir_addr_type; /*!< direct address type */
// esp_bd_addr_t dir_addr; /*!< direct address */
// esp_ble_gap_ext_adv_data_status_t data_status; /*!< data type */
// uint8_t adv_data_len; /*!< extend advertising data length */
// uint8_t adv_data[251]; /*!< extend advertising data */
//} esp_ble_gap_ext_adv_reprot_t;
class MyBLEExtAdvertisingCallbacks: public BLEExtAdvertisingCallbacks { class MyBLEExtAdvertisingCallbacks: public BLEExtAdvertisingCallbacks {
void onResult(esp_ble_gap_ext_adv_reprot_t report) { void onResult(esp_ble_gap_ext_adv_reprot_t report) {
if(report.event_type & ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY){ if(report.event_type & ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY){
......
...@@ -25,26 +25,6 @@ static esp_ble_gap_periodic_adv_sync_params_t periodic_adv_sync_params = { ...@@ -25,26 +25,6 @@ static esp_ble_gap_periodic_adv_sync_params_t periodic_adv_sync_params = {
.sync_timeout = 1000, // timeout: 1000 * 10ms .sync_timeout = 1000, // timeout: 1000 * 10ms
}; };
/**
* @brief extend adv report parameters
*/
//typedef struct {
// esp_ble_gap_adv_type_t event_type; /*!< extend advertising type */
// uint8_t addr_type; /*!< extend advertising address type */
// esp_bd_addr_t addr; /*!< extend advertising address */
// esp_ble_gap_pri_phy_t primary_phy; /*!< extend advertising primary phy */
// esp_ble_gap_phy_t secondly_phy; /*!< extend advertising secondary phy */
// uint8_t sid; /*!< extend advertising sid */
// uint8_t tx_power; /*!< extend advertising tx power */
// int8_t rssi; /*!< extend advertising rssi */
// uint16_t per_adv_interval; /*!< periodic advertising interval */
// uint8_t dir_addr_type; /*!< direct address type */
// esp_bd_addr_t dir_addr; /*!< direct address */
// esp_ble_gap_ext_adv_data_status_t data_status; /*!< data type */
// uint8_t adv_data_len; /*!< extend advertising data length */
// uint8_t adv_data[251]; /*!< extend advertising data */
//} esp_ble_gap_ext_adv_reprot_t;
class MyBLEExtAdvertisingCallbacks : public BLEExtAdvertisingCallbacks class MyBLEExtAdvertisingCallbacks : public BLEExtAdvertisingCallbacks
{ {
void onResult(esp_ble_gap_ext_adv_reprot_t params) void onResult(esp_ble_gap_ext_adv_reprot_t params)
......
...@@ -14,8 +14,6 @@ ...@@ -14,8 +14,6 @@
#include <BLEEddystoneTLM.h> #include <BLEEddystoneTLM.h>
#include <BLEBeacon.h> #include <BLEBeacon.h>
#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00) >> 8) + (((x)&0xFF) << 8))
int scanTime = 5; //In seconds int scanTime = 5; //In seconds
BLEScan *pBLEScan; BLEScan *pBLEScan;
...@@ -37,58 +35,66 @@ class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks ...@@ -37,58 +35,66 @@ class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
Serial.println(devUUID.toString().c_str()); Serial.println(devUUID.toString().c_str());
Serial.println(""); Serial.println("");
} }
else
if (advertisedDevice.haveManufacturerData() == true)
{ {
if (advertisedDevice.haveManufacturerData() == true) std::string strManufacturerData = advertisedDevice.getManufacturerData();
{
std::string strManufacturerData = advertisedDevice.getManufacturerData();
uint8_t cManufacturerData[100]; uint8_t cManufacturerData[100];
strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0); strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0);
if (strManufacturerData.length() == 25 && cManufacturerData[0] == 0x4C && cManufacturerData[1] == 0x00) if (strManufacturerData.length() == 25 && cManufacturerData[0] == 0x4C && cManufacturerData[1] == 0x00)
{ {
Serial.println("Found an iBeacon!"); Serial.println("Found an iBeacon!");
BLEBeacon oBeacon = BLEBeacon(); BLEBeacon oBeacon = BLEBeacon();
oBeacon.setData(strManufacturerData); oBeacon.setData(strManufacturerData);
Serial.printf("iBeacon Frame\n"); Serial.printf("iBeacon Frame\n");
Serial.printf("ID: %04X Major: %d Minor: %d UUID: %s Power: %d\n", oBeacon.getManufacturerId(), ENDIAN_CHANGE_U16(oBeacon.getMajor()), ENDIAN_CHANGE_U16(oBeacon.getMinor()), oBeacon.getProximityUUID().toString().c_str(), oBeacon.getSignalPower()); Serial.printf("ID: %04X Major: %d Minor: %d UUID: %s Power: %d\n", oBeacon.getManufacturerId(), ENDIAN_CHANGE_U16(oBeacon.getMajor()), ENDIAN_CHANGE_U16(oBeacon.getMinor()), oBeacon.getProximityUUID().toString().c_str(), oBeacon.getSignalPower());
} }
else else
{
Serial.println("Found another manufacturers beacon!");
Serial.printf("strManufacturerData: %d ", strManufacturerData.length());
for (int i = 0; i < strManufacturerData.length(); i++)
{ {
Serial.println("Found another manufacturers beacon!"); Serial.printf("[%X]", cManufacturerData[i]);
Serial.printf("strManufacturerData: %d ", strManufacturerData.length());
for (int i = 0; i < strManufacturerData.length(); i++)
{
Serial.printf("[%X]", cManufacturerData[i]);
}
Serial.printf("\n");
} }
Serial.printf("\n");
} }
return;
} }
uint8_t *payLoad = advertisedDevice.getPayload(); uint8_t *payLoad = advertisedDevice.getPayload();
// search for Eddystone Service Data in the advertising payload
// *payload shall point to eddystone data or to its end when not found
const uint8_t serviceDataEddystone[3] = {0x16, 0xAA, 0xFE}; // it has Eddystone BLE UUID
const size_t payLoadLen = advertisedDevice.getPayloadLength();
uint8_t *payLoadEnd = payLoad + payLoadLen - 1; // address of the end of payLoad space
while (payLoad < payLoadEnd) {
if (payLoad[1] == serviceDataEddystone[0] && payLoad[2] == serviceDataEddystone[1] && payLoad[3] == serviceDataEddystone[2]) {
// found!
payLoad += 4;
break;
}
payLoad += *payLoad + 1; // payLoad[0] has the field Length
}
BLEUUID checkUrlUUID = (uint16_t)0xfeaa; if (payLoad < payLoadEnd) // Eddystone Service Data and respective BLE UUID were found
if (advertisedDevice.getServiceUUID().equals(checkUrlUUID))
{ {
if (payLoad[11] == 0x10) if (*payLoad == 0x10)
{ {
Serial.println("Found an EddystoneURL beacon!"); Serial.println("Found an EddystoneURL beacon!");
BLEEddystoneURL foundEddyURL = BLEEddystoneURL(); BLEEddystoneURL foundEddyURL = BLEEddystoneURL();
std::string eddyContent((char *)&payLoad[11]); // incomplete EddystoneURL struct! uint8_t URLLen = *(payLoad - 4) - 3; // Get Field Length less 3 bytes (type and UUID)
foundEddyURL.setData(std::string((char*)payLoad, URLLen));
foundEddyURL.setData(eddyContent);
std::string bareURL = foundEddyURL.getURL(); std::string bareURL = foundEddyURL.getURL();
if (bareURL[0] == 0x00) if (bareURL[0] == 0x00)
{ {
size_t payLoadLen = advertisedDevice.getPayloadLength(); // dumps all bytes in advertising payload
Serial.println("DATA-->"); Serial.println("DATA-->");
uint8_t *payLoad = advertisedDevice.getPayload();
for (int idx = 0; idx < payLoadLen; idx++) for (int idx = 0; idx < payLoadLen; idx++)
{ {
Serial.printf("0x%08X ", payLoad[idx]); Serial.printf("0x%02X ", payLoad[idx]);
} }
Serial.println("\nInvalid Data"); Serial.println("\nInvalid Data");
return; return;
...@@ -98,30 +104,19 @@ class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks ...@@ -98,30 +104,19 @@ class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
Serial.printf("Decoded URL: %s\n", foundEddyURL.getDecodedURL().c_str()); Serial.printf("Decoded URL: %s\n", foundEddyURL.getDecodedURL().c_str());
Serial.printf("TX power %d\n", foundEddyURL.getPower()); Serial.printf("TX power %d\n", foundEddyURL.getPower());
Serial.println("\n"); Serial.println("\n");
} }
else if (payLoad[11] == 0x20) else if (*payLoad == 0x20)
{ {
Serial.println("Found an EddystoneTLM beacon!"); Serial.println("Found an EddystoneTLM beacon!");
BLEEddystoneTLM foundEddyURL = BLEEddystoneTLM();
std::string eddyContent((char *)&payLoad[11]); // incomplete EddystoneURL struct! BLEEddystoneTLM eddystoneTLM;
eddystoneTLM.setData(std::string((char*)payLoad, 14));
eddyContent = "01234567890123"; Serial.printf("Reported battery voltage: %dmV\n", eddystoneTLM.getVolt());
Serial.printf("Reported temperature: %.2f°C (raw data=0x%04X)\n", eddystoneTLM.getTemp(), eddystoneTLM.getRawTemp());
for (int idx = 0; idx < 14; idx++) Serial.printf("Reported advertise count: %d\n", eddystoneTLM.getCount());
{ Serial.printf("Reported time since last reboot: %ds\n", eddystoneTLM.getTime());
eddyContent[idx] = payLoad[idx + 11];
}
foundEddyURL.setData(eddyContent);
Serial.printf("Reported battery voltage: %dmV\n", foundEddyURL.getVolt());
Serial.printf("Reported temperature from TLM class: %.2fC\n", (double)foundEddyURL.getTemp());
int temp = (int)payLoad[16] + (int)(payLoad[15] << 8);
float calcTemp = temp / 256.0f;
Serial.printf("Reported temperature from data: %.2fC\n", calcTemp);
Serial.printf("Reported advertise count: %d\n", foundEddyURL.getCount());
Serial.printf("Reported time since last reboot: %ds\n", foundEddyURL.getTime());
Serial.println("\n"); Serial.println("\n");
Serial.print(foundEddyURL.toString().c_str()); Serial.print(eddystoneTLM.toString().c_str());
Serial.println("\n"); Serial.println("\n");
} }
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
5. Stop advertising. 5. Stop advertising.
6. deep sleep 6. deep sleep
To read data advertised by this beacon use second ESP with example sketch BLE_Beacon_Scanner
*/ */
#include "sys/time.h" #include "sys/time.h"
...@@ -22,7 +23,7 @@ ...@@ -22,7 +23,7 @@
#include "BLEUtils.h" #include "BLEUtils.h"
#include "BLEBeacon.h" #include "BLEBeacon.h"
#include "BLEAdvertising.h" #include "BLEAdvertising.h"
#include "BLEEddystoneURL.h" #include "BLEEddystoneTLM.h"
#include "esp_sleep.h" #include "esp_sleep.h"
...@@ -48,10 +49,10 @@ void setBeacon() ...@@ -48,10 +49,10 @@ void setBeacon()
char beacon_data[25]; char beacon_data[25];
uint16_t beconUUID = 0xFEAA; uint16_t beconUUID = 0xFEAA;
uint16_t volt = random(2800, 3700); // 3300mV = 3.3V uint16_t volt = random(2800, 3700); // 3300mV = 3.3V
float tempFloat = random(2000, 3100) / 100.0f; float tempFloat = random(-3000, 3000) / 100.0f;
Serial.printf("Random temperature is %.2fC\n", tempFloat); Serial.printf("Random temperature is %.2f°C\n", tempFloat);
int temp = (int)(tempFloat * 256); //(uint16_t)((float)23.00); int temp = (int)(tempFloat * 256);
Serial.printf("Converted to 8.8 format %0X%0X\n", (temp >> 8), (temp & 0xFF)); Serial.printf("Converted to 8.8 format %0X%0X\n", (temp >> 8) & 0xFF, (temp & 0xFF));
BLEAdvertisementData oAdvertisementData = BLEAdvertisementData(); BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
BLEAdvertisementData oScanResponseData = BLEAdvertisementData(); BLEAdvertisementData oScanResponseData = BLEAdvertisementData();
...@@ -82,13 +83,11 @@ void setBeacon() ...@@ -82,13 +83,11 @@ void setBeacon()
void setup() void setup()
{ {
Serial.begin(115200); Serial.begin(115200);
gettimeofday(&nowTimeStruct, NULL); gettimeofday(&nowTimeStruct, NULL);
Serial.printf("start ESP32 %d\n", bootcount++); Serial.printf("Starting ESP32. Bootcount = %d\n", bootcount++);
Serial.printf("Deep sleep (%lds since last reset, %lds since last boot)\n", nowTimeStruct.tv_sec, nowTimeStruct.tv_sec - last);
Serial.printf("deep sleep (%lds since last reset, %lds since last boot)\n", nowTimeStruct.tv_sec, nowTimeStruct.tv_sec - last);
last = nowTimeStruct.tv_sec; last = nowTimeStruct.tv_sec;
lastTenth = nowTimeStruct.tv_sec * 10; // Time since last reset as 0.1 second resolution counter lastTenth = nowTimeStruct.tv_sec * 10; // Time since last reset as 0.1 second resolution counter
...@@ -103,12 +102,11 @@ void setup() ...@@ -103,12 +102,11 @@ void setup()
setBeacon(); setBeacon();
// Start advertising // Start advertising
pAdvertising->start(); pAdvertising->start();
Serial.println("Advertizing started for 10s ..."); Serial.println("Advertising started for 10s ...");
delay(10000); delay(10000);
pAdvertising->stop(); pAdvertising->stop();
Serial.printf("enter deep sleep for 10s\n"); Serial.printf("Enter deep sleep for 10s\n");
esp_deep_sleep(1000000LL * GPIO_DEEP_SLEEP_DURATION); esp_deep_sleep(1000000LL * GPIO_DEEP_SLEEP_DURATION);
Serial.printf("in deep sleep\n");
} }
void loop() void loop()
......
...@@ -40,7 +40,7 @@ uint16_t BLEBeacon::getMinor() { ...@@ -40,7 +40,7 @@ uint16_t BLEBeacon::getMinor() {
} }
BLEUUID BLEBeacon::getProximityUUID() { BLEUUID BLEBeacon::getProximityUUID() {
return BLEUUID(m_beaconData.proximityUUID, 16, false); return BLEUUID(m_beaconData.proximityUUID, 16, true);
} }
int8_t BLEBeacon::getSignalPower() { int8_t BLEBeacon::getSignalPower() {
......
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
#include "BLEEddystoneTLM.h" #include "BLEEddystoneTLM.h"
static const char LOG_TAG[] = "BLEEddystoneTLM"; static const char LOG_TAG[] = "BLEEddystoneTLM";
#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00)>>8) + (((x)&0xFF)<<8))
#define ENDIAN_CHANGE_U32(x) ((((x)&0xFF000000)>>24) + (((x)&0x00FF0000)>>8)) + ((((x)&0xFF00)<<8) + (((x)&0xFF)<<24))
BLEEddystoneTLM::BLEEddystoneTLM() { BLEEddystoneTLM::BLEEddystoneTLM() {
beaconUUID = 0xFEAA; beaconUUID = 0xFEAA;
...@@ -47,9 +45,13 @@ uint16_t BLEEddystoneTLM::getVolt() { ...@@ -47,9 +45,13 @@ uint16_t BLEEddystoneTLM::getVolt() {
} // getVolt } // getVolt
float BLEEddystoneTLM::getTemp() { float BLEEddystoneTLM::getTemp() {
return ENDIAN_CHANGE_U16(m_eddystoneData.temp) / 256.0f; return EDDYSTONE_TEMP_U16_TO_FLOAT(m_eddystoneData.temp);
} // getTemp } // getTemp
uint16_t BLEEddystoneTLM::getRawTemp() {
return ENDIAN_CHANGE_U16(m_eddystoneData.temp);
} // getRawTemp
uint32_t BLEEddystoneTLM::getCount() { uint32_t BLEEddystoneTLM::getCount() {
return ENDIAN_CHANGE_U32(m_eddystoneData.advCount); return ENDIAN_CHANGE_U32(m_eddystoneData.advCount);
} // getCount } // getCount
...@@ -73,7 +75,7 @@ std::string BLEEddystoneTLM::toString() { ...@@ -73,7 +75,7 @@ std::string BLEEddystoneTLM::toString() {
out += " mV\n"; out += " mV\n";
out += "Temperature "; out += "Temperature ";
snprintf(val, sizeof(val), "%.2f", ENDIAN_CHANGE_U16(m_eddystoneData.temp) / 256.0f); snprintf(val, sizeof(val), "%.2f", ((int16_t)ENDIAN_CHANGE_U16(m_eddystoneData.temp)) / 256.0f);
out += val; out += val;
out += " C\n"; out += " C\n";
...@@ -110,6 +112,21 @@ std::string BLEEddystoneTLM::toString() { ...@@ -110,6 +112,21 @@ std::string BLEEddystoneTLM::toString() {
/** /**
* Set the raw data for the beacon record. * Set the raw data for the beacon record.
* Example:
* uint8_t *payLoad = advertisedDevice.getPayload();
* eddystoneTLM.setData(std::string((char*)payLoad+22, advertisedDevice.getPayloadLength() - 22));
* Note: the offset 22 works for current implementation of example BLE_EddystoneTLM Beacon.ino, however it is not static and will be reimplemented
* Data frame:
* | Field || Len | Type | UUID | EddyStone TLM |
* | Offset || 0 | 1 | 2 | 4 |
* | Len || 1 B | 1 B | 2 B | 14 B |
* | Data || ?? | ?? | 0xAA | 0xFE | ??? |
*
* EddyStone TLM frame:
* | Field || Type | Version | Batt mV | Beacon temp | Cnt since boot | Time since boot |
* | Offset || 0 | 1 | 2 | 4 | 6 | 10 |
* | Len || 1 B | 1 B | 2 B | 2 B | 4 B | 4 B |
* | Data || 0x20 | ?? | ?? | ?? | ?? | ?? | | | | | | | | |
*/ */
void BLEEddystoneTLM::setData(std::string data) { void BLEEddystoneTLM::setData(std::string data) {
if (data.length() != sizeof(m_eddystoneData)) { if (data.length() != sizeof(m_eddystoneData)) {
...@@ -132,7 +149,7 @@ void BLEEddystoneTLM::setVolt(uint16_t volt) { ...@@ -132,7 +149,7 @@ void BLEEddystoneTLM::setVolt(uint16_t volt) {
} // setVolt } // setVolt
void BLEEddystoneTLM::setTemp(float temp) { void BLEEddystoneTLM::setTemp(float temp) {
m_eddystoneData.temp = (uint16_t)temp; m_eddystoneData.temp = EDDYSTONE_TEMP_FLOAT_TO_U16(temp);
} // setTemp } // setTemp
void BLEEddystoneTLM::setCount(uint32_t advCount) { void BLEEddystoneTLM::setCount(uint32_t advCount) {
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
#include "BLEUUID.h" #include "BLEUUID.h"
#define EDDYSTONE_TLM_FRAME_TYPE 0x20 #define EDDYSTONE_TLM_FRAME_TYPE 0x20
#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00)>>8) + (((x)&0xFF)<<8))
#define ENDIAN_CHANGE_U32(x) ((((x)&0xFF000000)>>24) + (((x)&0x00FF0000)>>8)) + ((((x)&0xFF00)<<8) + (((x)&0xFF)<<24))
#define EDDYSTONE_TEMP_U16_TO_FLOAT(tempU16) (((int16_t)ENDIAN_CHANGE_U16(tempU16)) / 256.0f)
#define EDDYSTONE_TEMP_FLOAT_TO_U16(tempFloat) (ENDIAN_CHANGE_U16(((int)((tempFloat) * 256))))
/** /**
* @brief Representation of a beacon. * @brief Representation of a beacon.
...@@ -18,33 +22,34 @@ ...@@ -18,33 +22,34 @@
*/ */
class BLEEddystoneTLM { class BLEEddystoneTLM {
public: public:
BLEEddystoneTLM(); BLEEddystoneTLM();
std::string getData(); std::string getData();
BLEUUID getUUID(); BLEUUID getUUID();
uint8_t getVersion(); uint8_t getVersion();
uint16_t getVolt(); uint16_t getVolt();
float getTemp(); float getTemp();
uint32_t getCount(); uint16_t getRawTemp();
uint32_t getTime(); uint32_t getCount();
std::string toString(); uint32_t getTime();
void setData(std::string data); std::string toString();
void setUUID(BLEUUID l_uuid); void setData(std::string data);
void setVersion(uint8_t version); void setUUID(BLEUUID l_uuid);
void setVolt(uint16_t volt); void setVersion(uint8_t version);
void setTemp(float temp); void setVolt(uint16_t volt);
void setCount(uint32_t advCount); void setTemp(float temp);
void setTime(uint32_t tmil); void setCount(uint32_t advCount);
void setTime(uint32_t tmil);
private: private:
uint16_t beaconUUID; uint16_t beaconUUID;
struct { struct {
uint8_t frameType; uint8_t frameType;
uint8_t version; uint8_t version;
uint16_t volt; uint16_t volt;
uint16_t temp; uint16_t temp;
uint32_t advCount; uint32_t advCount;
uint32_t tmil; uint32_t tmil;
} __attribute__((packed)) m_eddystoneData; } __attribute__((packed)) m_eddystoneData;
}; // BLEEddystoneTLM }; // BLEEddystoneTLM
......
...@@ -35,7 +35,7 @@ private: ...@@ -35,7 +35,7 @@ private:
struct { struct {
uint8_t frameType; uint8_t frameType;
int8_t advertisedTxPower; int8_t advertisedTxPower;
uint8_t url[16]; uint8_t url[18]; // 18 bytes: 1 byte for URL scheme + up to 17 bytes of URL
} __attribute__((packed)) m_eddystoneData; } __attribute__((packed)) m_eddystoneData;
}; // BLEEddystoneURL }; // BLEEddystoneURL
......
...@@ -6,6 +6,11 @@ ...@@ -6,6 +6,11 @@
#include "BluetoothSerial.h" #include "BluetoothSerial.h"
//#define USE_PIN // Uncomment this to use PIN during pairing. The pin is specified on the line below
const char *pin = "1234"; // Change this to more secure PIN.
String device_name = "ESP32-BT-Slave";
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED) #if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it #error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif #endif
...@@ -18,8 +23,13 @@ BluetoothSerial SerialBT; ...@@ -18,8 +23,13 @@ BluetoothSerial SerialBT;
void setup() { void setup() {
Serial.begin(115200); Serial.begin(115200);
SerialBT.begin("ESP32test"); //Bluetooth device name SerialBT.begin(device_name); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!"); Serial.printf("The device with name \"%s\" is started.\nNow you can pair it with Bluetooth!\n", device_name.c_str());
//Serial.printf("The device with name \"%s\" and MAC address %s is started.\nNow you can pair it with Bluetooth!\n", device_name.c_str(), SerialBT.getMacString()); // Use this after the MAC method is implemented
#ifdef USE_PIN
SerialBT.setPin(pin);
Serial.println("Using PIN");
#endif
} }
void loop() { void loop() {
......
//This example code is in the Public Domain (or CC0 licensed, at your option.) // This example code is in the Public Domain (or CC0 licensed, at your option.)
//By Victor Tchistiak - 2019 // By Victor Tchistiak - 2019
// //
//This example demostrates master mode bluetooth connection and pin // This example demonstrates master mode Bluetooth connection to a slave BT device using PIN (password)
//it creates a bridge between Serial and Classical Bluetooth (SPP) // defined either by String "slaveName" by default "OBDII" or by MAC address
//this is an extention of the SerialToSerialBT example by Evandro Copercini - 2018
// //
// This example creates a bridge between Serial and Classical Bluetooth (SPP)
// This is an extension of the SerialToSerialBT example by Evandro Copercini - 2018
//
// DO NOT try to connect to phone or laptop - they are master
// devices, same as the ESP using this code - it will NOT work!
//
// You can try to flash a second ESP32 with the example SerialToSerialBT - it should
// automatically pair with ESP32 running this code
#include "BluetoothSerial.h" #include "BluetoothSerial.h"
#define USE_NAME // Comment this to use MAC address instead of a slaveName
const char *pin = "1234"; // Change this to reflect the pin expected by the real slave BT device
#if !defined(CONFIG_BT_SPP_ENABLED) #if !defined(CONFIG_BT_SPP_ENABLED)
#error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip. #error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip.
#endif #endif
BluetoothSerial SerialBT; BluetoothSerial SerialBT;
String MACadd = "AA:BB:CC:11:22:33"; #ifdef USE_NAME
uint8_t address[6] = {0xAA, 0xBB, 0xCC, 0x11, 0x22, 0x33}; String slaveName = "ESP32-BT-Slave"; // Change this to reflect the real name of your slave BT device
//uint8_t address[6] = {0x00, 0x1D, 0xA5, 0x02, 0xC3, 0x22}; #else
String name = "OBDII"; String MACadd = "AA:BB:CC:11:22:33"; // This only for printing
const char *pin = "1234"; //<- standard pin would be provided by default uint8_t address[6] = {0xAA, 0xBB, 0xCC, 0x11, 0x22, 0x33}; // Change this to reflect real MAC address of your slave BT device
bool connected; #endif
String myName = "ESP32-BT-Master";
void setup() { void setup() {
bool connected;
Serial.begin(115200); Serial.begin(115200);
//SerialBT.setPin(pin);
SerialBT.begin("ESP32test", true); SerialBT.begin(myName, true);
//SerialBT.setPin(pin); Serial.printf("The device \"%s\" started in master mode, make sure slave BT device is on!\n", myName.c_str());
Serial.println("The device started in master mode, make sure remote BT device is on!");
#ifndef USE_NAME
// connect(address) is fast (upto 10 secs max), connect(name) is slow (upto 30 secs max) as it needs SerialBT.setPin(pin);
// to resolve name to address first, but it allows to connect to different devices with the same name. Serial.println("Using PIN");
// Set CoreDebugLevel to Info to view devices bluetooth address and device names #endif
connected = SerialBT.connect(name);
//connected = SerialBT.connect(address); // connect(address) is fast (up to 10 secs max), connect(slaveName) is slow (up to 30 secs max) as it needs
// to resolve slaveName to address first, but it allows to connect to different devices with the same name.
// Set CoreDebugLevel to Info to view devices Bluetooth address and device names
#ifdef USE_NAME
connected = SerialBT.connect(slaveName);
Serial.printf("Connecting to slave BT device named \"%s\"\n", slaveName.c_str());
#else
connected = SerialBT.connect(address);
Serial.print("Connecting to slave BT device with MAC "); Serial.println(MACadd);
#endif
if(connected) { if(connected) {
Serial.println("Connected Succesfully!"); Serial.println("Connected Successfully!");
} else { } else {
while(!SerialBT.connected(10000)) { while(!SerialBT.connected(10000)) {
Serial.println("Failed to connect. Make sure remote device is available and in range, then restart app."); Serial.println("Failed to connect. Make sure remote device is available and in range, then restart app.");
} }
} }
// disconnect() may take upto 10 secs max // Disconnect() may take up to 10 secs max
if (SerialBT.disconnect()) { if (SerialBT.disconnect()) {
Serial.println("Disconnected Succesfully!"); Serial.println("Disconnected Successfully!");
} }
// this would reconnect to the name(will use address, if resolved) or address used with connect(name/address). // This would reconnect to the slaveName(will use address, if resolved) or address used with connect(slaveName/address).
SerialBT.connect(); SerialBT.connect();
if(connected) {
Serial.println("Reconnected Successfully!");
} else {
while(!SerialBT.connected(10000)) {
Serial.println("Failed to reconnect. Make sure remote device is available and in range, then restart app.");
}
}
} }
void loop() { void loop() {
......
...@@ -7,28 +7,28 @@ ...@@ -7,28 +7,28 @@
class Button class Button
{ {
public: public:
Button(uint8_t reqPin) : PIN(reqPin){ Button(uint8_t reqPin) : PIN(reqPin){
pinMode(PIN, INPUT_PULLUP); pinMode(PIN, INPUT_PULLUP);
attachInterrupt(PIN, std::bind(&Button::isr,this), FALLING); attachInterrupt(PIN, std::bind(&Button::isr,this), FALLING);
}; };
~Button() { ~Button() {
detachInterrupt(PIN); detachInterrupt(PIN);
} }
void ARDUINO_ISR_ATTR isr() { void ARDUINO_ISR_ATTR isr() {
numberKeyPresses += 1; numberKeyPresses += 1;
pressed = true; pressed = true;
} }
void checkPressed() { void checkPressed() {
if (pressed) { if (pressed) {
Serial.printf("Button on pin %u has been pressed %u times\n", PIN, numberKeyPresses); Serial.printf("Button on pin %u has been pressed %u times\n", PIN, numberKeyPresses);
pressed = false; pressed = false;
} }
} }
private: private:
const uint8_t PIN; const uint8_t PIN;
volatile uint32_t numberKeyPresses; volatile uint32_t numberKeyPresses;
volatile bool pressed; volatile bool pressed;
}; };
...@@ -42,6 +42,6 @@ void setup() { ...@@ -42,6 +42,6 @@ void setup() {
} }
void loop() { void loop() {
button1.checkPressed(); button1.checkPressed();
button2.checkPressed(); button2.checkPressed();
} }
#include <Arduino.h>
#define BUTTON1 16
#define BUTTON2 17
struct Button {
uint8_t PIN;
volatile uint32_t numberKeyPresses;
volatile int pressed;
};
void isr(void* param) {
struct Button *button = (struct Button*) param;
button->numberKeyPresses += 1;
button->pressed = 1;
}
void checkPressed(struct Button* button) {
if(button->pressed) {
Serial.printf("Button on pin %u has been pressed %u times\n", button->PIN, button->numberKeyPresses);
button->pressed = 0;
}
}
struct Button button1 = {BUTTON1, 0, 0};
struct Button button2 = {BUTTON2, 0, 0};
void setup() {
Serial.begin(115200);
pinMode(button1.PIN, INPUT_PULLUP);
pinMode(button2.PIN, INPUT_PULLUP);
attachInterruptArg(button1.PIN, isr, (void*)&button1, FALLING);
attachInterruptArg(button2.PIN, isr, (void*)&button2, FALLING);
}
void loop() {
checkPressed(&button1);
checkPressed(&button2);
}
...@@ -3,62 +3,17 @@ ...@@ -3,62 +3,17 @@
#include <WebServer.h> #include <WebServer.h>
#include <ESPmDNS.h> #include <ESPmDNS.h>
/* const char* ssid = "WiFi_SSID";
* MultiHomedServers const char* password = "WiFi_Password";
*
* MultiHomedServers tests support for multi-homed servers, i.e. a distinct web servers on each IP interface.
* It only tests the case n=2 because on a basic ESP32 device, we only have two IP interfaces, namely
* the WiFi station interfaces and the WiFi soft AP interface.
*
* For this to work, the WebServer and the WiFiServer classes must correctly handle the case where an
* IP address is passed to their relevant constructor. It also requires WebServer to work with multiple,
* simultaneous instances.
*
* Testing the WebServer and the WiFiServer constructors was the primary purpose of this script.
* The part of WebServer used by this sketch does seem to work with multiple, simultaneous instances.
* However there is much functionality in WebServer that is not tested here. It may all be well, but
* that is not proven here.
*
* This sketch starts the mDNS server, as did HelloServer, and it resolves esp32.local on both interfaces,
* but was not otherwise tested.
*
* This script also tests that a server not bound to a specific IP address still works.
*
* We create three, simultaneous web servers, one specific to each interface and one that listens on both:
*
* name IP Address Port
* ---- ---------- ----
* server0 INADDR_ANY 8080
* server1 station address 8081
* server2 soft AP address 8081
*
* The expected responses to a brower's requests are as follows:
*
* 1. when client connected to the same WLAN as the station:
* Request URL Response
* ----------- --------
* http://stationaddress:8080 "hello from server0"
* http://stationaddress:8081 "hello from server1"
*
* 2. when client is connected to the soft AP:
*
* Request URL Response
* ----------- --------
* http://softAPaddress:8080 "hello from server0"
* http://softAPaddress:8081 "hello from server2"
*
* 3. Repeat 1 and 2 above with esp32.local in place of stationaddress and softAPaddress, respectively.
*
* MultiHomedServers was originally based on HelloServer.
*/
const char* ssid = "........";
const char* password = "........";
const char *apssid = "ESP32"; const char *apssid = "ESP32";
WebServer *server0, *server1, *server2; WebServer *server0, *server1, *server2;
#ifdef LED_BUILTIN
const int led = LED_BUILTIN;
#else
const int led = 13; const int led = 13;
#endif
void handleRoot(WebServer *server, const char *content) { void handleRoot(WebServer *server, const char *content) {
digitalWrite(led, 1); digitalWrite(led, 1);
...@@ -67,15 +22,15 @@ void handleRoot(WebServer *server, const char *content) { ...@@ -67,15 +22,15 @@ void handleRoot(WebServer *server, const char *content) {
} }
void handleRoot0() { void handleRoot0() {
handleRoot(server0, "hello from server0"); handleRoot(server0, "Hello from server0 who listens on both WLAN and own Soft AP");
} }
void handleRoot1() { void handleRoot1() {
handleRoot(server1, "hello from server1"); handleRoot(server1, "Hello from server1 who listens only on WLAN");
} }
void handleRoot2() { void handleRoot2() {
handleRoot(server2, "hello from server2"); handleRoot(server2, "Hello from server2 who listens only on own Soft AP");
} }
void handleNotFound(WebServer *server) { void handleNotFound(WebServer *server) {
...@@ -111,9 +66,12 @@ void setup(void) { ...@@ -111,9 +66,12 @@ void setup(void) {
pinMode(led, OUTPUT); pinMode(led, OUTPUT);
digitalWrite(led, 0); digitalWrite(led, 0);
Serial.begin(115200); Serial.begin(115200);
while(!Serial){ delay(100); }
Serial.println("Multi-homed Servers example starting");
delay(1000);
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password); WiFi.begin(ssid, password);
Serial.println(""); Serial.print("Connecting ");
// Wait for connection // Wait for connection
while (WiFi.status() != WL_CONNECTED) { while (WiFi.status() != WL_CONNECTED) {
...@@ -121,9 +79,9 @@ void setup(void) { ...@@ -121,9 +79,9 @@ void setup(void) {
Serial.print("."); Serial.print(".");
} }
Serial.println(""); Serial.println("");
Serial.print("Connected to "); Serial.print("Connected to \"");
Serial.println(ssid); Serial.print(ssid);
Serial.print("IP address: "); Serial.print("\", IP address: \"");
Serial.println(WiFi.localIP()); Serial.println(WiFi.localIP());
if (!WiFi.softAP(apssid)) { if (!WiFi.softAP(apssid)) {
Serial.println("failed to start softAP"); Serial.println("failed to start softAP");
...@@ -134,9 +92,9 @@ void setup(void) { ...@@ -134,9 +92,9 @@ void setup(void) {
delay(100); delay(100);
} }
} }
Serial.print("Soft AP: "); Serial.print("Soft AP SSID: \"");
Serial.print(apssid); Serial.print(apssid);
Serial.print(" IP address: "); Serial.print("\", IP address: ");
Serial.println(WiFi.softAPIP()); Serial.println(WiFi.softAPIP());
if (MDNS.begin("esp32")) { if (MDNS.begin("esp32")) {
...@@ -161,6 +119,10 @@ void setup(void) { ...@@ -161,6 +119,10 @@ void setup(void) {
Serial.println("HTTP server1 started"); Serial.println("HTTP server1 started");
server2->begin(); server2->begin();
Serial.println("HTTP server2 started"); Serial.println("HTTP server2 started");
Serial.printf("SSID: %s\n\thttp://", ssid); Serial.print(WiFi.localIP()); Serial.print(":8080\n\thttp://"); Serial.print(WiFi.localIP()); Serial.println(":8081");
Serial.printf("SSID: %s\n\thttp://", apssid); Serial.print(WiFi.softAPIP()); Serial.print(":8080\n\thttp://"); Serial.print(WiFi.softAPIP()); Serial.println(":8081");
Serial.printf("Any of the above SSIDs\n\thttp://esp32.local:8080\n\thttp://esp32.local:8081\n");
} }
void loop(void) { void loop(void) {
......
# Multi Homed Servers
This example tests support for multi-homed servers, i.e. a distinct web servers on distinct IP interface.
It only tests the case n=2 because on a basic ESP32 device, we only have two IP interfaces, namely the WiFi station interfaces and the WiFi soft AP interface.
For this to work, the WebServer and the WiFiServer classes must correctly handle the case where an IP address is passed to their relevant constructor.
It also requires WebServer to work with multiple, simultaneous instances.
Testing the WebServer and the WiFiServer constructors was the primary purpose of this script.
The part of WebServer used by this sketch does seem to work with multiple, simultaneous instances.
However there is much functionality in WebServer that is not tested here. It may all be well, but that is not proven here.
This sketch starts the mDNS server, as did HelloServer, and it resolves esp32.local on both interfaces, but was not otherwise tested.
This script also tests that a server not bound to a specific IP address still works.
We create three, simultaneous web servers, one specific to each interface and one that listens on both:
| name | IP Address | Port |
| ---- | ---------- | ---- |
| server0 | INADDR_ANY | 8080 |
| server1 | station address | 8081 |
| server2 | soft AP address | 8081 |
The expected responses to a browser's requests are as follows:
#### 1. The Client connected to the same WLAN as the station:
| Request URL | Response |
| ----------- | -------- |
| [http://stationaddress:8080](http://stationaddress:8080) | Hello from server0 who listens on both WLAN and own Soft AP |
| [http://stationaddress:8081](http://stationaddress:8081) | Hello from server1 who listens only on WLAN |
#### 2. The Client is connected to the soft AP:
| Request URL | Response |
| ----------- | -------- |
| [http://softAPaddress:8080](http://softAPaddress:8080) | Hello from server0 who listens on both WLAN and own Soft AP |
| [http://softAPaddress:8081](http://softAPaddress:8081) | Hello from server2 who listens only on own Soft AP |
#### 3. The Client is connect to either WLAN or SoftAP:
| Request URL | Response |
| ----------- | -------- |
| [http://esp32.local:8080](http://esp32.local:8080) | Hello from server0 who listens on both WLAN and own Soft AP |
| [http://esp32.local:8081](http://esp32.local:8081) | Hello from server1 who listens only on WLAN |
MultiHomedServers was originally based on HelloServer.
# Supported Targets
Currently, this example supports the following targets.
| Supported Targets | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- |
## How to Use Example
Change the SSID and password in the example to your WiFi and flash the example.
Open a serial terminal and the example will write the exact addresses with used IP addresses you can use to test the servers.
* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide).
#### Using Arduino IDE
To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits).
* Before Compile/Verify, select the correct board: `Tools -> Board`.
* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port.
#### Using Platform IO
* Select the COM port: `Devices` or set the `upload_port` option on the `platformio.ini` file.
## Example Log Output
```
Multi-homed Servers example starting
Connecting ...
Connected to "WiFi_SSID", IP address: "192.168.42.24
Soft AP SSID: "ESP32", IP address: 192.168.4.1
MDNS responder started
SSID: WiFi_SSID
http://192.168.42.24:8080
http://192.168.42.24:8081
SSID: ESP32
http://192.168.4.1:8080
http://192.168.4.1:8081
Any of the above SSIDs
http://esp32.local:8080
http://esp32.local:8081
HTTP server0 started
HTTP server1 started
HTTP server2 started
```
## Known issues
`http://esp32.local` Does not work on some Android phones
## Troubleshooting
***Important: Make sure you are using a good quality USB cable and that you have a reliable power source***
## Contribute
To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst)
If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome!
Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else.
## Resources
* Official ESP32 Forum: [Link](https://esp32.com)
* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32)
* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf)
* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf)
* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf)
* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com)
...@@ -16,7 +16,9 @@ ...@@ -16,7 +16,9 @@
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "WiFiUdp.h" #include "WiFiUdp.h"
#include <new> //std::nothrow
#include <lwip/sockets.h> #include <lwip/sockets.h>
#include <lwip/netdb.h> #include <lwip/netdb.h>
#include <errno.h> #include <errno.h>
...@@ -207,12 +209,12 @@ int WiFiUDP::parsePacket(){ ...@@ -207,12 +209,12 @@ int WiFiUDP::parsePacket(){
return 0; return 0;
struct sockaddr_in si_other; struct sockaddr_in si_other;
int slen = sizeof(si_other) , len; int slen = sizeof(si_other) , len;
char * buf = new char[1460]; char *buf = (char *)malloc(1460);
if(!buf){ if(!buf) {
return 0; return 0;
} }
if ((len = recvfrom(udp_server, buf, 1460, MSG_DONTWAIT, (struct sockaddr *) &si_other, (socklen_t *)&slen)) == -1){ if ((len = recvfrom(udp_server, buf, 1460, MSG_DONTWAIT, (struct sockaddr *) &si_other, (socklen_t *)&slen)) == -1){
delete[] buf; free(buf);
if(errno == EWOULDBLOCK){ if(errno == EWOULDBLOCK){
return 0; return 0;
} }
...@@ -222,10 +224,10 @@ int WiFiUDP::parsePacket(){ ...@@ -222,10 +224,10 @@ int WiFiUDP::parsePacket(){
remote_ip = IPAddress(si_other.sin_addr.s_addr); remote_ip = IPAddress(si_other.sin_addr.s_addr);
remote_port = ntohs(si_other.sin_port); remote_port = ntohs(si_other.sin_port);
if (len > 0) { if (len > 0) {
rx_buffer = new cbuf(len); rx_buffer = new(std::nothrow) cbuf(len);
rx_buffer->write(buf, len); rx_buffer->write(buf, len);
} }
delete[] buf; free(buf);
return len; return len;
} }
......
...@@ -106,4 +106,28 @@ For example, this is used with AWS IoT Custom Authorizers where an MQTT client m ...@@ -106,4 +106,28 @@ For example, this is used with AWS IoT Custom Authorizers where an MQTT client m
const char *aws_protos[] = {"mqtt", NULL}; const char *aws_protos[] = {"mqtt", NULL};
... ...
wiFiClient.setAlpnProtocols(aws_protos); wiFiClient.setAlpnProtocols(aws_protos);
``` ```
\ No newline at end of file
Examples
--------
#### WiFiClientInsecure
Demonstrates usage of insecure connection using `WiFiClientSecure::setInsecure()`
#### WiFiClientPSK
Wifi secure connection example for ESP32 using a pre-shared key (PSK)
This is useful with MQTT servers instead of using a self-signed cert, tested with mosquitto.
Running on TLS 1.2 using mbedTLS
#### WiFiClientSecure
Wifi secure connection example for ESP32
Running on TLS 1.2 using mbedTLS
#### WiFiClientSecureEnterprise
This example demonstrates a secure connection to a WiFi network using WPA/WPA2 Enterprise (for example eduroam),
and establishing a secure HTTPS connection with an external server (for example arduino.php5.sk) using the defined anonymous identity, user identity, and password.
.. note::
This example is outdated and might not work. For more examples see [https://github.com/martinius96/ESP32-eduroam](https://github.com/martinius96/ESP32-eduroam)
#### WiFiClientShowPeerCredentials
Example of a establishing a secure connection and then showing the fingerprint of the certificate.
This can be useful in an IoT setting to know for sure that you are connecting to the right server.
Especially in situations where you cannot hardcode a trusted root certificate for long
periods of time (as they tend to get replaced more often than the lifecycle of IoT hardware).
\ No newline at end of file
...@@ -7,6 +7,12 @@ ...@@ -7,6 +7,12 @@
/*|Supported methods: PEAP + MsCHAPv2, EAP-TTLS + MsCHAPv2 |*/ /*|Supported methods: PEAP + MsCHAPv2, EAP-TTLS + MsCHAPv2 |*/
/*|-----------------------------------------------------------|*/ /*|-----------------------------------------------------------|*/
// This example demonstrates a secure connection to a WiFi network using WPA/WPA2 Enterprise (for example eduroam),
// and establishing a secure HTTPS connection with an external server (for example arduino.php5.sk) using the defined anonymous identity, user identity, and password.
// Note: this example is outdated and may not work!
// For more examples see https://github.com/martinius96/ESP32-eduroam
#include <WiFi.h> #include <WiFi.h>
#include <WiFiClientSecure.h> #include <WiFiClientSecure.h>
#include "esp_wpa2.h" #include "esp_wpa2.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment