diff --git a/myGates/MACAddr.txt b/myGates/MACAddr.txt new file mode 100644 index 0000000000000000000000000000000000000000..f856d08d3270c55fbae6f3fc1a9dc883087c7993 --- /dev/null +++ b/myGates/MACAddr.txt @@ -0,0 +1 @@ + GATE 4 : 34:94:54:5A:2B:94 diff --git a/myGates/myGates_Barrier/credentials.h b/myGates/myGates_Barrier/credentials.h new file mode 100644 index 0000000000000000000000000000000000000000..32038a95eb372b202d9dcc605c7915f9fcdd8478 --- /dev/null +++ b/myGates/myGates_Barrier/credentials.h @@ -0,0 +1,3 @@ +// Wifi and OTA credentials +const char *ssid = "Gate"; +const char *password = "neOCampus"; diff --git a/myGates/myGates_Barrier/gateParameters.h b/myGates/myGates_Barrier/gateParameters.h new file mode 100644 index 0000000000000000000000000000000000000000..130a5ada981fad5793a95e568b311982d9293a03 --- /dev/null +++ b/myGates/myGates_Barrier/gateParameters.h @@ -0,0 +1,15 @@ +// MY GATES PARAMETERS + +#define NAVETTE_UUID "DEADDEAD-F88F-0042-F88F-010203040506" // same UUID for all vehicles +#define FORCEGATEOPEN 0b0100 // minor high bits = 0b01 => force gate to open +#define CLEARGATECALIBRATION 0b1000 // minor high bits = 0b10 => disable BLE scan and upload software +#define OTASWUPDATE 0b1100 // minor high bits = 0b11 => clear gate calibration + +#define OTA_EXIT_AFTER 60*5 // after X sec if the software is not updating, getting out of the mode STATE_OTA +#define SCAN_TIME 1 // scan period in second +#define GO_TO_SCAN_STATE_DELAY 4 // if no frame was received during X sec, go to STATE_SCAN +#define DELAY_REJECT_FRAME 3 // if the last frame was received more than X seconds ago, the average RSSI is not computed and returns an average RSSI of -100 +#define PULSE_DURATION 500 // pulse to open gate. duration in ms +#define DELAY_BETWEEN_PULSE 5 // to keep the gate open emit a pulse every X seconds +#define RSSI_THRESHOLD_OPEN_GATE -95 // if the average RSSI is above this threshold the gate can be open +#define SERIAL_BAUDRATE 115200 diff --git a/myGates/myGates_Barrier/myGates_Barrier.ino b/myGates/myGates_Barrier/myGates_Barrier.ino new file mode 100644 index 0000000000000000000000000000000000000000..fea8c60fd07777f214ac6d31632205369069ed27 --- /dev/null +++ b/myGates/myGates_Barrier/myGates_Barrier.ino @@ -0,0 +1,410 @@ +/*******************************/ +/*********** INCLUDES***********/ +/*******************************/ + +#include <Arduino.h> +#include <ArduinoOTA.h> +#include <WiFi.h> +#include <BLEDevice.h> +#include <BLEUtils.h> +#include <BLEScan.h> +#include <BLEAdvertisedDevice.h> +#include <BLEBeacon.h> +#include "sdkconfig.h" +#include "esp_task_wdt.h" + +#include "gateParameters.h" +#include "credentials.h" + +/*******************************/ +/********* DEFINITIONS *********/ +/*******************************/ + +#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00) >> 8) + (((x)&0xFF) << 8)) +#define HIGH4BITS_U16(x) (((x)&0b1111000000000000) >> 12) +#define RELAY1 32 + +// State enumeration +typedef enum { + STATE_SCAN = 0, /*STATE_SCAN : scanning iBeacon frame with UUID = NAVETTE_UUID. Opening door when the RSSI is high enough. Go to STATE_OPEN_GATE after opening the door.*/ + STATE_OPEN_GATE, /*TATE_OPEN_GATE : door is open. Keep the door open while receiving frame. Go to STATE_SCAN when not receiving frame after GO_TO_SCAN_STATE_DELAY*/ + STATE_OTA /*STATE_OTA : disable BLE and start uploading software with Wifi*/ +} MACHINE_STATE; + +MACHINE_STATE STATE; /*state of the system : can be either STATE_SCAN or STATE_OPEN_GATE or STATE_OTA*/ + +// Time related definition +time_t t; /*time is seconds*/ +time_t timerOTA; /*time OTA software update started*/ +time_t tPulseGate = 0; /*time last Pulse to open gate*/ + +struct InfoBeacon { /*structure contening received beacon RSSI and time*/ + int rssi = -100; + time_t time = 0; +} tabRecBeacon[3]; /*info of the last 3 received frames. Used to compute the average RSSI.*/ + +bool BLEScanActivated = false; + +/*****************************/ +/********* FONCTIONS *********/ +/*****************************/ + +// set up Serial Port +void setupSerial() { +#ifdef SERIAL_BAUDRATE + delay(3000); /*time for USB serial link to come up anew*/ + Serial.begin(SERIAL_BAUDRATE); /*start serial for output*/ + Serial.setDebugOutput(true); +#endif +} + +// compute WiFi AP name +const char *getAPname( void ) { + uint8_t macAddr[6]; + static char _apName[16] = ""; + if( !strlen(_apName) ) { + WiFi.macAddress(macAddr); /*get MAC address*/ + snprintf(_apName,sizeof(_apName),"GATE_%02X%02X",macAddr[4],macAddr[5]); + } + return (const char*)_apName; +} + +// set up WiFi AP +void setUpWifiAP() { + WiFi.mode(WIFI_AP); + WiFi.softAP(getAPname(), password); +} + +// set up Wdtifor BLE scan_evt timeout error +void setupWdtBLE(){ + esp_task_wdt_init(10, true); /*enable panic so ESP32 restarts, interrupt when task executed for more than 10 seconds*/ + esp_task_wdt_add(NULL); /*add current thread to WDT watch*/ +} + +// set up On The Air software upload +void setupOTA() { + // Port defaults to 3232 + ArduinoOTA.setPort(3232); + // Hostname + ArduinoOTA.setHostname(ssid); + // Authentication + ArduinoOTA.setPassword(password); + + ArduinoOTA.onStart([]() { + String type; + if (ArduinoOTA.getCommand() == U_FLASH) + type = "sketch"; + else /*U_SPIFFS*/ + type = "filesystem"; + + /*NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()*/ + Serial.println("Start updating " + type); + }); + ArduinoOTA.onEnd([]() { + Serial.println("\nEnd"); + STATE = STATE_SCAN; + }); + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { + Serial.printf("Progress: %u%%\r", (progress / (total / 100))); + }); + ArduinoOTA.onError([](ota_error_t error) { + Serial.printf("Error[%u]: ", error); + if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); + else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); + else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); + else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); + else if (error == OTA_END_ERROR) Serial.println("End Failed"); + }); +} + +// open gate +void openGate() { + Serial.printf("OPENING GATE\n"); /*DEBUG*/ + digitalWrite(RELAY1, HIGH); /*activate relay1 for 0.5 sec*/ + delay(PULSE_DURATION); + digitalWrite(RELAY1, LOW); + time(&tPulseGate); /*save time of the last pulse*/ +} + +// update Beacon RSSI table +void updateBeaconTab(InfoBeacon newBeacon) { /*save RSSI and time in the table tabRecBeacon*/ + tabRecBeacon[2] = tabRecBeacon[1]; + tabRecBeacon[1] = tabRecBeacon[0]; + tabRecBeacon[0] = newBeacon; +} + +// compute average RSSI +int averageRSSI() { + time(&t); // get time + if (difftime(t,tabRecBeacon[2].time) > DELAY_REJECT_FRAME) { /*if last frames were received more than x sec ago, return an average RSSI of -100*/ + return -100; + } else { + int avRSSI = (tabRecBeacon[2].rssi + tabRecBeacon[1].rssi + tabRecBeacon[0].rssi) / 3; /*compute the average RSSI using the last 3 RSSI values*/ + return avRSSI; + } +} + +class IBeaconAdvertised : public BLEAdvertisedDeviceCallbacks { + public: + + // BLE on result + void onResult(BLEAdvertisedDevice device) { + /*check if iBeacon frame*/ + if (!isIBeacon(device)) { + return; + } + + /*check for NAVETTE_UUID*/ + if (!isNavetteUUID(device)) { + return; + } + + /*received a frame FORCE GATE OPEN*/ + if (HIGH4BITS_U16(getMinor(device)) == FORCEGATEOPEN) { + Serial.printf("FORCE OPEN FRAME "); /*DEBUG*/ + openGate(); + return; + } + + /*received a FRAME OTA Software Update*/ + if (HIGH4BITS_U16(getMinor(device)) == OTASWUPDATE) { + time(&timerOTA); /*save OTA start time */ + Serial.printf("OTA SOFTWARE UPDATING MODE \n"); /*DEBUG*/ + STATE = STATE_OTA; + return; + } + + InfoBeacon newBeacon = saveBeaconInfo(device); /*get received Beacon info*/ + updateBeaconTab(newBeacon); /*save received frame RSSI in the table*/ + printIBeacon(device); /*DEBUG*/ + } + + private: + + // is frame iBeacon ? + bool isIBeacon(BLEAdvertisedDevice device) { + if (device.getManufacturerData().length() < 25) { + return false; + } + if (getCompanyId(device) != 0x004C) { + return false; + } + if (getIBeaconHeader(device) != 0x1502) { + return false; + } + return true; + } + + // is UUID_NAVETTE ? + bool isNavetteUUID(BLEAdvertisedDevice device) { /*check if iBeacon frame UUID = NAVETTE_UUID*/ + if (getProxyUuid(device).equals(BLEUUID(NAVETTE_UUID))) { + return true; + } else { + return false; + } + } + + // save RSSI info + InfoBeacon saveBeaconInfo(BLEAdvertisedDevice device) { /*get signal RSSI and reception time*/ + InfoBeacon newBeacon; + time(&t); + newBeacon.rssi = device.getRSSI(); + newBeacon.time = t; + return newBeacon; + } + + // get companyId + unsigned short getCompanyId(BLEAdvertisedDevice device) { + const unsigned short *pCompanyId = (const unsigned short *)&device + .getManufacturerData() + .c_str()[0]; + return *pCompanyId; + } + + // get iBeacon Header + unsigned short getIBeaconHeader(BLEAdvertisedDevice device) { + const unsigned short *pHeader = (const unsigned short *)&device + .getManufacturerData() + .c_str()[2]; + return *pHeader; + } + + // get iBEACON UUID + BLEUUID getProxyUuid(BLEAdvertisedDevice device) { + BLEUUID uuid; + std::string strManufacturerData = device.getManufacturerData(); + uint8_t cManufacturerData[100]; + strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0); + BLEBeacon oBeacon = BLEBeacon(); + oBeacon.setData(strManufacturerData); + uuid = oBeacon.getProximityUUID(); + return uuid; + } + + // BEACON Major + uint16_t getMajor(BLEAdvertisedDevice device) { + std::string strManufacturerData = device.getManufacturerData(); + uint8_t cManufacturerData[100]; + strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0); + BLEBeacon oBeacon = BLEBeacon(); + oBeacon.setData(strManufacturerData); + return ENDIAN_CHANGE_U16(oBeacon.getMajor()); + } + + // iBEACON Minor + uint16_t getMinor(BLEAdvertisedDevice device) { + std::string strManufacturerData = device.getManufacturerData(); + uint8_t cManufacturerData[100]; + strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0); + BLEBeacon oBeacon = BLEBeacon(); + oBeacon.setData(strManufacturerData); + return ENDIAN_CHANGE_U16(oBeacon.getMinor()); + } + + // iBEACON TxPower + int8_t getTxPower(BLEAdvertisedDevice device) { + std::string strManufacturerData = device.getManufacturerData(); + uint8_t cManufacturerData[100]; + strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0); + BLEBeacon oBeacon = BLEBeacon(); + oBeacon.setData(strManufacturerData); + return oBeacon.getSignalPower(); + } + + // print iBeacon device info + void printIBeacon(BLEAdvertisedDevice device) { + time(&t); + Serial.printf("name:%s uuid:%s major:%d minor:%d rssi:%d, avRSSI:%d \r\n", + device.getName().c_str(), + getProxyUuid(device).toString().c_str(), + getMajor(device), + getMinor(device), + device.getRSSI(), + averageRSSI()); + } +}; + +// manage gate opening +void manageGateOpening() { + switch (STATE) { /*check gate state*/ + + case STATE_OPEN_GATE: + if (difftime(t,tPulseGate) > DELAY_BETWEEN_PULSE) { /*end a pulse to keep the gate open every X=DELAY_BETWEEN_PULSE sec*/ + openGate(); + } + break; + + case STATE_OTA : + case STATE_SCAN: + default: + /*do not open gate*/ + break; /*end case STATE_SCAN*/ + } +} + +// manage gate state +void manageState() +{ + time(&t); /*get time*/ + + switch (STATE) { /*check gate state*/ + + case STATE_OTA : + if (difftime(t,timerOTA) > OTA_EXIT_AFTER) { + STATE = STATE_SCAN; /*go to STATE_SCAN*/ + setupWdtBLE(); /*setup Wdt for BLE*/ + Serial.printf("GO TO STATE_SCAN\n"); /*DEBUG*/ + } + break;/*end case STATE_OTA*/ + + case STATE_OPEN_GATE: + if (difftime(t,tabRecBeacon[0].time) > GO_TO_SCAN_STATE_DELAY) { /*f last frame was received more than x seconds ago (GO_TO_SCAN_STATE_DELAY)*/ + STATE = STATE_SCAN; /*go to STATE_SCAN*/ + Serial.printf("GO TO STATE_SCAN\n"); /*DEBUG*/ + } + break; /*end case STATE_OPEN_GATE*/ + + case STATE_SCAN: + int avRSSI = averageRSSI(); /*compute average RSSI (with 3 last values)*/ + if (avRSSI > RSSI_THRESHOLD_OPEN_GATE) { /*if the received signal power is above the threshold RSSI_THRESHOLD_OPEN_GATE*/ + STATE = STATE_OPEN_GATE; /*change state and go to state STATE_OPEN_GATE*/ + Serial.printf("GO TO STATE_OPEN_GATE\n"); /*DEBUG*/ + } else { + /*RSSI is too low*/ + } + break; /*end case STATE_SCAN*/ + } +} + +// start BLE scan +void startScanBLE() { + BLEScan* pBLEScan = BLEDevice::getScan(); // start scanning + pBLEScan->setAdvertisedDeviceCallbacks(new IBeaconAdvertised(), true); + pBLEScan->setActiveScan(true); + pBLEScan->start(SCAN_TIME, scanCompleteCB); + BLEScanActivated = true; +} + +// scan complete Call Back +/* Callback invoked when scanning has completed */ +static void scanCompleteCB(BLEScanResults scanResults) { + BLEScanActivated = false; +} + +// manage BLE scan +void manageBLEscan() { + switch (STATE) { /*check gate state*/ + + case STATE_OTA : + /*do not restart BLE scan*/ + esp_task_wdt_delete(NULL); /*disable watchdog timer for BLE*/ + break; + + case STATE_OPEN_GATE: + case STATE_SCAN: + default: + if (!BLEScanActivated) + startScanBLE(); /*start scanning*/ + esp_task_wdt_reset(); /*reset the watchdog timer*/ + break; + } +} + +// setup +void setup() { + /*init serial port*/ + setupSerial(); + + /*init relay module*/ + pinMode(RELAY1, OUTPUT); + + /*setup WiFi as Access Point*/ + setUpWifiAP(); + + /*setup OTA*/ + setupOTA(); + ArduinoOTA.begin(); + + /*init BLE*/ + BLEDevice::init(""); + + /*init state*/ + STATE = STATE_SCAN; + + /*setup Wdt for BLE*/ + setupWdtBLE(); + + /*print ready*/ + Serial.println(); + Serial.println("Ready"); + Serial.println(); +} + +// loop +void loop() { + ArduinoOTA.handle(); + manageState(); + manageGateOpening(); + manageBLEscan(); + delay(100); +} diff --git a/myGates/myGates_Vehicle/myGates_Vehicle.ino b/myGates/myGates_Vehicle/myGates_Vehicle.ino new file mode 100644 index 0000000000000000000000000000000000000000..41fc56873c92f594d2c141109de16d4041baf277 --- /dev/null +++ b/myGates/myGates_Vehicle/myGates_Vehicle.ino @@ -0,0 +1,125 @@ +#include <M5StickCPlus.h> +#include "BLEDevice.h" +#include "BLEUtils.h" +#include "BLEBeacon.h" + +#define ADVERTISMENT_INTERVAL 500 //(ms) advertise every 0.5 second +#define ADVERTISMENT_DURATION 100 //(ms) +#define BEACON_UUID "DEADDEAD-F88F-0042-F88F-010203040506" //same UUID for all vehicles +#define UT3_AUTONOMOUS_VEHICLE 0x0042 +#define EASYMILE_EZ10 0x0000 +#define FORCE_GATE_OPEN 0b0100000000000000 +#define OTA_SW_UPDATE 0b1100000000000000 +#define CLEAR_GATE_CALIBRATION 0b1000000000000000 +#define TX_POWER ESP_PWR_LVL_N14 + + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +BLEAdvertising *pAdvertising; // BLE Advertisement type + +bool send_force_gate_frame = false; +bool send_OTA_update_frame = false; +uint16_t MAJOR; +uint16_t MINOR; + +void setBeacon() { + //configure ibeacon data + MAJOR = UT3_AUTONOMOUS_VEHICLE; + MINOR = EASYMILE_EZ10; + + if(send_force_gate_frame){ // if button A was pressed, send FORCE_GATE_OPEN trame + MINOR = (MINOR | FORCE_GATE_OPEN); + send_force_gate_frame = false; + Serial.println("forcing gate to open"); + } + if(send_OTA_update_frame){ // if button B was pressed, send FORCE_GATE_OPEN trame + MINOR = (MINOR | OTA_SW_UPDATE); + send_OTA_update_frame = false; + Serial.println("starting On The Air software update"); + } + + + BLEBeacon oBeacon = BLEBeacon(); + oBeacon.setManufacturerId(0x4C00); // fake Apple 0x004C LSB (ENDIAN_CHANGE_U16!) + oBeacon.setProximityUUID(BLEUUID(BEACON_UUID)); + oBeacon.setMajor(MAJOR); + oBeacon.setMinor(MINOR); + oBeacon.setSignalPower(TX_POWER); + BLEAdvertisementData oAdvertisementData = BLEAdvertisementData(); + BLEAdvertisementData oScanResponseData = BLEAdvertisementData(); + + oAdvertisementData.setFlags(0x04); + + std::string strServiceData = ""; + + strServiceData += (char)26; // Len + strServiceData += (char)0xFF; // Type + strServiceData += oBeacon.getData(); + oAdvertisementData.addData(strServiceData); + + pAdvertising->setAdvertisementData(oAdvertisementData); + pAdvertising->setScanResponseData(oScanResponseData); + +} +#define LED 10 + +void setup() { + pinMode(LED, OUTPUT); + pinMode(M5_BUTTON_HOME, INPUT_PULLUP); + digitalWrite(LED, HIGH); + M5.begin(); + M5.Lcd.setRotation(1); + M5.Lcd.fillScreen(BLACK); + + M5.Lcd.setCursor(2, 0, 2); + M5.Lcd.printf("UUID: %s",BEACON_UUID); + /* M5.Lcd.setCursor(2, 40, 2); + M5.Lcd.printf("Major %d Minor %d",MAJOR ,MINOR); */ + + Serial.begin(115200); + + // Create the BLE Device + BLEDevice::init("navette neOCampus"); + pAdvertising = BLEDevice::getAdvertising(); + + // Increase TX POWER + //BLEDevice::setPower(TX_POWER); + esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT, TX_POWER); + esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, TX_POWER); + + // Create the BLE Server + BLEServer *pServer = BLEDevice::createServer(); + pAdvertising = BLEDevice::getAdvertising(); + BLEDevice::startAdvertising(); + + setBeacon(); +} + +void loop() { + M5.update(); // Read the press state of the key + if (M5.BtnA.wasReleased()) { // If the button A is pressed + send_force_gate_frame = true; + Serial.println("button A was pressed"); + } + if (M5.BtnB.wasReleasefor(5000)) { // If the button B is pressed for 5sec + send_OTA_update_frame = true; + Serial.println("button B was pressed for 5 sec"); + } + setBeacon(); + pAdvertising->start(); + digitalWrite(LED, LOW); + Serial.printf("Advertizing started...\n"); + delay(ADVERTISMENT_DURATION); + Serial.println("Advertizing stop..."); + pAdvertising->stop(); + digitalWrite(LED, HIGH); + delay(ADVERTISMENT_INTERVAL - ADVERTISMENT_DURATION); +} diff --git a/tests/myGates_BLE_Beacon_Advertiser/myGates_BLE_Beacon_Advertiser.ino b/tests/myGates_BLE_Beacon_Advertiser/myGates_BLE_Beacon_Advertiser.ino index f39fdf446662f0032cd494f52a4f47db750cccc6..41fc56873c92f594d2c141109de16d4041baf277 100644 --- a/tests/myGates_BLE_Beacon_Advertiser/myGates_BLE_Beacon_Advertiser.ino +++ b/tests/myGates_BLE_Beacon_Advertiser/myGates_BLE_Beacon_Advertiser.ino @@ -1,116 +1,125 @@ -/* - Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp - Ported to Arduino ESP32 by pcbreflux - - Create a BLE server that will send periodic iBeacon frames. - The design of creating the BLE server is: - 1. Create a BLE Server - 2. Create advertising data - 3. Start advertising. - 4. wait - 5. Stop advertising. - 6. deep sleep - - TBC: Tx power changed ... check it works ! - -*/ -#include "sys/time.h" - +#include <M5StickCPlus.h> #include "BLEDevice.h" #include "BLEUtils.h" #include "BLEBeacon.h" -#include "esp_sleep.h" -#define GPIO_DEEP_SLEEP_DURATION 10 // sleep x seconds and then wake up -RTC_DATA_ATTR static time_t last; // remember last boot in RTC Memory -RTC_DATA_ATTR static uint32_t bootcount; // remember number of boots in RTC Memory +#define ADVERTISMENT_INTERVAL 500 //(ms) advertise every 0.5 second +#define ADVERTISMENT_DURATION 100 //(ms) +#define BEACON_UUID "DEADDEAD-F88F-0042-F88F-010203040506" //same UUID for all vehicles +#define UT3_AUTONOMOUS_VEHICLE 0x0042 +#define EASYMILE_EZ10 0x0000 +#define FORCE_GATE_OPEN 0b0100000000000000 +#define OTA_SW_UPDATE 0b1100000000000000 +#define CLEAR_GATE_CALIBRATION 0b1000000000000000 +#define TX_POWER ESP_PWR_LVL_N14 + + #ifdef __cplusplus extern "C" { #endif -uint8_t temprature_sens_read(); -//uint8_t g_phyFuns; - #ifdef __cplusplus } #endif -// See the following for generating UUIDs: -// https://www.uuidgenerator.net/ -BLEAdvertising *pAdvertising; -struct timeval now; +BLEAdvertising *pAdvertising; // BLE Advertisement type -#define BEACON_UUID "8ec76ea3-6668-48da-9866-75be8bc86f4d" // UUID 1 128-Bit (may use linux tool uuidgen or random numbers via https://www.uuidgenerator.net/) +bool send_force_gate_frame = false; +bool send_OTA_update_frame = false; +uint16_t MAJOR; +uint16_t MINOR; void setBeacon() { + //configure ibeacon data + MAJOR = UT3_AUTONOMOUS_VEHICLE; + MINOR = EASYMILE_EZ10; + + if(send_force_gate_frame){ // if button A was pressed, send FORCE_GATE_OPEN trame + MINOR = (MINOR | FORCE_GATE_OPEN); + send_force_gate_frame = false; + Serial.println("forcing gate to open"); + } + if(send_OTA_update_frame){ // if button B was pressed, send FORCE_GATE_OPEN trame + MINOR = (MINOR | OTA_SW_UPDATE); + send_OTA_update_frame = false; + Serial.println("starting On The Air software update"); + } + BLEBeacon oBeacon = BLEBeacon(); oBeacon.setManufacturerId(0x4C00); // fake Apple 0x004C LSB (ENDIAN_CHANGE_U16!) oBeacon.setProximityUUID(BLEUUID(BEACON_UUID)); - oBeacon.setMajor((bootcount & 0xFFFF0000) >> 16); - oBeacon.setMinor(bootcount&0xFFFF); - // ### TODO: add oBeacon.Txpower ?? + oBeacon.setMajor(MAJOR); + oBeacon.setMinor(MINOR); + oBeacon.setSignalPower(TX_POWER); BLEAdvertisementData oAdvertisementData = BLEAdvertisementData(); BLEAdvertisementData oScanResponseData = BLEAdvertisementData(); - - oAdvertisementData.setFlags(0x04); // BR_EDR_NOT_SUPPORTED 0x04 - + + oAdvertisementData.setFlags(0x04); + std::string strServiceData = ""; - + strServiceData += (char)26; // Len strServiceData += (char)0xFF; // Type strServiceData += oBeacon.getData(); oAdvertisementData.addData(strServiceData); - + pAdvertising->setAdvertisementData(oAdvertisementData); pAdvertising->setScanResponseData(oScanResponseData); - pAdvertising->setAdvertisementType(ADV_TYPE_NONCONN_IND); } +#define LED 10 void setup() { - delay(3000); // time for USB serial link to come up anew + pinMode(LED, OUTPUT); + pinMode(M5_BUTTON_HOME, INPUT_PULLUP); + digitalWrite(LED, HIGH); + M5.begin(); + M5.Lcd.setRotation(1); + M5.Lcd.fillScreen(BLACK); + + M5.Lcd.setCursor(2, 0, 2); + M5.Lcd.printf("UUID: %s",BEACON_UUID); + /* M5.Lcd.setCursor(2, 40, 2); + M5.Lcd.printf("Major %d Minor %d",MAJOR ,MINOR); */ Serial.begin(115200); - gettimeofday(&now, NULL); - // Arduino libs v2.4.1, to enable printf and debug messages output - Serial.setDebugOutput( true ); - - Serial.printf("start ESP32 %d\n",bootcount++); - - Serial.printf("deep sleep (%lds since last reset, %lds since last boot)\n",now.tv_sec,now.tv_sec-last); - - last = now.tv_sec; - // Create the BLE Device - BLEDevice::init(""); - - // [sep.22] Increase TX POWER ? - BLEDevice::setPower(ESP_PWR_LVL_P9); - // or ... - esp_err_t errRc=esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT,ESP_PWR_LVL_P9); - esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, ESP_PWR_LVL_P9); - esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_SCAN ,ESP_PWR_LVL_P9); - - + BLEDevice::init("navette neOCampus"); + pAdvertising = BLEDevice::getAdvertising(); - // Create the BLE Server - // BLEServer *pServer = BLEDevice::createServer(); // <-- no longer required to instantiate BLEServer, less flash and ram usage + // Increase TX POWER + //BLEDevice::setPower(TX_POWER); + esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT, TX_POWER); + esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, TX_POWER); + // Create the BLE Server + BLEServer *pServer = BLEDevice::createServer(); pAdvertising = BLEDevice::getAdvertising(); + BLEDevice::startAdvertising(); setBeacon(); - // Start advertising - pAdvertising->start(); - Serial.println("Advertizing started..."); - delay(100); - pAdvertising->stop(); - Serial.printf("enter deep sleep\n"); - esp_deep_sleep(1000000LL * GPIO_DEEP_SLEEP_DURATION); - Serial.printf("in deep sleep\n"); } void loop() { + M5.update(); // Read the press state of the key + if (M5.BtnA.wasReleased()) { // If the button A is pressed + send_force_gate_frame = true; + Serial.println("button A was pressed"); + } + if (M5.BtnB.wasReleasefor(5000)) { // If the button B is pressed for 5sec + send_OTA_update_frame = true; + Serial.println("button B was pressed for 5 sec"); + } + setBeacon(); + pAdvertising->start(); + digitalWrite(LED, LOW); + Serial.printf("Advertizing started...\n"); + delay(ADVERTISMENT_DURATION); + Serial.println("Advertizing stop..."); + pAdvertising->stop(); + digitalWrite(LED, HIGH); + delay(ADVERTISMENT_INTERVAL - ADVERTISMENT_DURATION); } diff --git a/tests/myGates_BLE_Beacon_Scanner/myGates_BLE_Beacon_Scanner.ino b/tests/myGates_BLE_Beacon_Scanner/myGates_BLE_Beacon_Scanner.ino index 84cb47e1a14fd729042aa9cdcced53597063411c..41d81f99be1cb04e124880b1a0f86e2e0379e16a 100644 --- a/tests/myGates_BLE_Beacon_Scanner/myGates_BLE_Beacon_Scanner.ino +++ b/tests/myGates_BLE_Beacon_Scanner/myGates_BLE_Beacon_Scanner.ino @@ -1,170 +1,402 @@ -/* - Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp - Ported to Arduino ESP32 by Evandro Copercini - Changed to a beacon scanner to report iBeacon, EddystoneURL and EddystoneTLM beacons by beegee-tokyo - - TBC: Tx power changed ... check it works ! - -*/ +/*******************************/ +/*********** INCLUDES***********/ +/*******************************/ #include <Arduino.h> - +#include <ArduinoOTA.h> +#include <WiFi.h> #include <BLEDevice.h> #include <BLEUtils.h> #include <BLEScan.h> #include <BLEAdvertisedDevice.h> -#include <BLEEddystoneURL.h> -#include <BLEEddystoneTLM.h> #include <BLEBeacon.h> +#include <time.h> +#include "sdkconfig.h" + +/*******************************/ +/********* DEFINITIONS *********/ +/*******************************/ #define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00) >> 8) + (((x)&0xFF) << 8)) +#define HIGH4BITS_U16(x) (((x)&0b1111000000000000) >> 12) -int scanTime = 5; //In seconds -BLEScan *pBLEScan; +#define RELAY1 32 -class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks -{ - void onResult(BLEAdvertisedDevice advertisedDevice) - { - if (advertisedDevice.haveName()) - { - Serial.print("Device name: "); - Serial.println(advertisedDevice.getName().c_str()); - Serial.println(""); +#define NAVETTE_UUID "DEADDEAD-F88F-0042-F88F-010203040506" // same UUID for all vehicles +#define FORCEGATEOPEN 0b0100 // minor high bits = 0b01 => force gate to open +#define CLEARGATECALIBRATION 0b1000 // minor high bits = 0b10 => disable BLE scan and upload software +#define OTASWUPDATE 0b1100 // minor high bits = 0b11 => clear gate calibration + +#define OTA_EXIT_AFTER 60*5 // after X sec if the software is not updating, getting out of the mode STATE_OTA +#define SCAN_TIME 1 // scan period in second +#define GO_TO_SCAN_STATE_DELAY 4 // if no frame was received during X sec, go to STATE_SCAN +#define DELAY_REJECT_FRAME 3 // if the last frame was received more than X seconds ago, the average RSSI is not computed and returns an average RSSI of -100 +#define PULSE_DURATION 500 // pulse to open gate. duration in ms +#define DELAY_BETWEEN_PULSE 5 // to keep the gate open emit a pulse every X seconds +#define RSSI_THRESHOLD_OPEN_GATE -95 // if the average RSSI is above this threshold the gate can be open +#define SERIAL_BAUDRATE 115200 + +// Wifi credentials +const char *ssid = "Gate"; +const char *password = "neOCampus"; + +//State enumeration +typedef enum { + STATE_SCAN = 0, // STATE_SCAN : scanning iBeacon frame with UUID = NAVETTE_UUID. Opening door when the RSSI is high enough. Go to STATE_OPEN_GATE after opening the door. + STATE_OPEN_GATE, // STATE_OPEN_GATE : door is open. Keep the door open while receiving frame. Go to STATE_SCAN when not receiving frame after GO_TO_SCAN_STATE_DELAY + STATE_OTA // STATE_OTA : disable BLE and start uploading software with Wifi +} MACHINE_STATE; + +MACHINE_STATE STATE; // state of the system : can be either STATE_SCAN or STATE_OPEN_GATE or STATE_OTA + +//Time related definition +time_t t; // time is seconds +time_t timerOTA; // time OTA software update started +time_t tPulseGate = 0; // time last Pulse to open gate + +struct InfoBeacon { // structure contening received beacon RSSI and time + int rssi = -100; + time_t time = 0; +} tabRecBeacon[3]; // info of the last 3 received frames. Used to compute the average RSSI. + +bool BLEScanActivated = false; + +/*****************************/ +/********* FONCTIONS *********/ +/*****************************/ + +// ***** set up Serial Port ***** +void setupSerial() { +#ifdef SERIAL_BAUDRATE + delay(3000); // time for USB serial link to come up anew + Serial.begin(SERIAL_BAUDRATE); // Start serial for output + Serial.setDebugOutput(true); +#endif +} + +// ***** set up WiFi AP***** +void setUpWifiAP() { + WiFi.mode(WIFI_AP); + WiFi.softAP(ssid, password); +} + +// ***** set up On The Air software upload ***** +void setupOTA() { + // Port defaults to 3232 + ArduinoOTA.setPort(3232); + // Hostname + ArduinoOTA.setHostname(ssid); + // Authentication + ArduinoOTA.setPassword(password); + + ArduinoOTA.onStart([]() { + String type; + if (ArduinoOTA.getCommand() == U_FLASH) + type = "sketch"; + else // U_SPIFFS + type = "filesystem"; + + // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end() + Serial.println("Start updating " + type); + }); + ArduinoOTA.onEnd([]() { + Serial.println("\nEnd"); + STATE = STATE_SCAN; + }); + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { + Serial.printf("Progress: %u%%\r", (progress / (total / 100))); + }); + ArduinoOTA.onError([](ota_error_t error) { + Serial.printf("Error[%u]: ", error); + if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); + else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); + else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); + else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); + else if (error == OTA_END_ERROR) Serial.println("End Failed"); + }); +} + +// ***** open gate ***** +void openGate() { + Serial.printf("OPENING GATE\n"); //DEBUG + digitalWrite(RELAY1, HIGH); //activate relay1 for 0.5 sec + delay(PULSE_DURATION); + digitalWrite(RELAY1, LOW); + time(&tPulseGate); // save time of the last pulse +} + +// ***** update Beacon RSSI table ***** +void updateBeaconTab(InfoBeacon newBeacon) { // save RSSI and time in the table tabRecBeacon + tabRecBeacon[2] = tabRecBeacon[1]; + tabRecBeacon[1] = tabRecBeacon[0]; + tabRecBeacon[0] = newBeacon; +} + +// ***** compute average RSSI ***** +int averageRSSI() { + time(&t); // get time + if (difftime(t,tabRecBeacon[2].time) > DELAY_REJECT_FRAME) { // if last frames were received more than x sec ago, return an average RSSI of -100 + return -100; + } else { + int avRSSI = (tabRecBeacon[2].rssi + tabRecBeacon[1].rssi + tabRecBeacon[0].rssi) / 3; // compute the average RSSI using the last 3 RSSI values + return avRSSI; + } +} + +class IBeaconAdvertised : public BLEAdvertisedDeviceCallbacks { + public: + + // BLE + void onResult(BLEAdvertisedDevice device) { + // check if iBeacon frame + if (!isIBeacon(device)) { + return; } - if (advertisedDevice.haveServiceUUID()) - { - BLEUUID devUUID = advertisedDevice.getServiceUUID(); - Serial.print("Found ServiceUUID: "); - Serial.println(devUUID.toString().c_str()); - Serial.println(""); + // check for NAVETTE_UUID + if (!isNavetteUUID(device)) { + return; } - else - { - if (advertisedDevice.haveManufacturerData() == true) - { - std::string strManufacturerData = advertisedDevice.getManufacturerData(); - - uint8_t cManufacturerData[100]; - strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0); - - if (strManufacturerData.length() == 25 && cManufacturerData[0] == 0x4C && cManufacturerData[1] == 0x00) - { - Serial.println("Found an iBeacon!"); - BLEBeacon oBeacon = BLEBeacon(); - oBeacon.setData(strManufacturerData); - 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()); - } - else - { - Serial.println("Found another manufacturers beacon!"); - Serial.printf("strManufacturerData: %d ", strManufacturerData.length()); - for (int i = 0; i < strManufacturerData.length(); i++) - { - Serial.printf("[%X]", cManufacturerData[i]); - } - Serial.printf("\n"); - } - } + + // received a frame FORCE GATE OPEN + if (HIGH4BITS_U16(getMinor(device)) == FORCEGATEOPEN) { + Serial.printf("FORCE OPEN FRAME "); // DEBUG + openGate(); return; } - uint8_t *payLoad = advertisedDevice.getPayload(); - - BLEUUID checkUrlUUID = (uint16_t)0xfeaa; - - if (advertisedDevice.getServiceUUID().equals(checkUrlUUID)) - { - if (payLoad[11] == 0x10) - { - Serial.println("Found an EddystoneURL beacon!"); - BLEEddystoneURL foundEddyURL = BLEEddystoneURL(); - std::string eddyContent((char *)&payLoad[11]); // incomplete EddystoneURL struct! - - foundEddyURL.setData(eddyContent); - std::string bareURL = foundEddyURL.getURL(); - if (bareURL[0] == 0x00) - { - size_t payLoadLen = advertisedDevice.getPayloadLength(); - Serial.println("DATA-->"); - for (int idx = 0; idx < payLoadLen; idx++) - { - Serial.printf("0x%08X ", payLoad[idx]); - } - Serial.println("\nInvalid Data"); - return; - } - - Serial.printf("Found URL: %s\n", foundEddyURL.getURL().c_str()); - Serial.printf("Decoded URL: %s\n", foundEddyURL.getDecodedURL().c_str()); - Serial.printf("TX power %d\n", foundEddyURL.getPower()); - Serial.println("\n"); - } - else if (payLoad[11] == 0x20) - { - Serial.println("Found an EddystoneTLM beacon!"); - BLEEddystoneTLM foundEddyURL = BLEEddystoneTLM(); - std::string eddyContent((char *)&payLoad[11]); // incomplete EddystoneURL struct! - - eddyContent = "01234567890123"; - - for (int idx = 0; idx < 14; idx++) - { - 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.print(foundEddyURL.toString().c_str()); - Serial.println("\n"); - } + // received a FRAME OTA Software Update + if (HIGH4BITS_U16(getMinor(device)) == OTASWUPDATE) { + time(&timerOTA); // save OTA start time + Serial.printf("OTA SOFTWARE UPDATING MODE \n"); // DEBUG + STATE = STATE_OTA; + return; + } + + InfoBeacon newBeacon = saveBeaconInfo(device); // get received Beacon info + updateBeaconTab(newBeacon); // save received frame RSSI in the table + printIBeacon(device); // DEBUG + } + + private: + + // ***** is frame iBeacon ? ***** + bool isIBeacon(BLEAdvertisedDevice device) { + if (device.getManufacturerData().length() < 25) { + return false; + } + if (getCompanyId(device) != 0x004C) { + return false; + } + if (getIBeaconHeader(device) != 0x1502) { + return false; } + return true; + } + + // ***** is UUID_NAVETTE ? ***** + bool isNavetteUUID(BLEAdvertisedDevice device) { // check if iBeacon frame UUID = NAVETTE_UUID + if (getProxyUuid(device).equals(BLEUUID(NAVETTE_UUID))) { + return true; + } else { + return false; + } + } + + // ***** save RSSI info ***** + InfoBeacon saveBeaconInfo(BLEAdvertisedDevice device) { // get signal RSSI and reception time + InfoBeacon newBeacon; + time(&t); + newBeacon.rssi = device.getRSSI(); + newBeacon.time = t; + return newBeacon; + } + + // ***** get companyId ***** + unsigned short getCompanyId(BLEAdvertisedDevice device) { + const unsigned short *pCompanyId = (const unsigned short *)&device + .getManufacturerData() + .c_str()[0]; + return *pCompanyId; + } + + // ***** get iBeacon Header ***** + unsigned short getIBeaconHeader(BLEAdvertisedDevice device) { + const unsigned short *pHeader = (const unsigned short *)&device + .getManufacturerData() + .c_str()[2]; + return *pHeader; + } + + // ***** get iBEACON UUID ***** + BLEUUID getProxyUuid(BLEAdvertisedDevice device) { + BLEUUID uuid; + std::string strManufacturerData = device.getManufacturerData(); + uint8_t cManufacturerData[100]; + strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0); + BLEBeacon oBeacon = BLEBeacon(); + oBeacon.setData(strManufacturerData); + uuid = oBeacon.getProximityUUID(); + return uuid; + } + + // ***** iBEACON Major ***** + uint16_t getMajor(BLEAdvertisedDevice device) { + std::string strManufacturerData = device.getManufacturerData(); + uint8_t cManufacturerData[100]; + strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0); + BLEBeacon oBeacon = BLEBeacon(); + oBeacon.setData(strManufacturerData); + return ENDIAN_CHANGE_U16(oBeacon.getMajor()); + } + + // ***** iBEACON Minor ***** + uint16_t getMinor(BLEAdvertisedDevice device) { + std::string strManufacturerData = device.getManufacturerData(); + uint8_t cManufacturerData[100]; + strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0); + BLEBeacon oBeacon = BLEBeacon(); + oBeacon.setData(strManufacturerData); + return ENDIAN_CHANGE_U16(oBeacon.getMinor()); + } + + // ***** iBEACON TxPower ***** + int8_t getTxPower(BLEAdvertisedDevice device) { + std::string strManufacturerData = device.getManufacturerData(); + uint8_t cManufacturerData[100]; + strManufacturerData.copy((char *)cManufacturerData, strManufacturerData.length(), 0); + BLEBeacon oBeacon = BLEBeacon(); + oBeacon.setData(strManufacturerData); + return oBeacon.getSignalPower(); + } + + // ***** print iBeacon device info ***** + void printIBeacon(BLEAdvertisedDevice device) { + // char buf[512]; + // memset(buf,0, sizeof (buf)); + // strncpy(buf, msg, (sizeof msg)-1); + time(&t); + Serial.printf("name:%s uuid:%s major:%d minor:%d rssi:%d, avRSSI:%d \r\n", + device.getName().c_str(), + getProxyUuid(device).toString().c_str(), + getMajor(device), + getMinor(device), + device.getRSSI(), + averageRSSI()); } }; -void setup() +// ***** manage gate Opening ***** +void manageGateOpening() { + switch (STATE) { //check gate state + + case STATE_OPEN_GATE: + if (difftime(t,tPulseGate) > DELAY_BETWEEN_PULSE) { // send a pulse to keep the gate open every X=DELAY_BETWEEN_PULSE sec + openGate(); + } + break; + + case STATE_OTA : + case STATE_SCAN: + default: + // do not open gate + break; //end case STATE_SCAN + } +} + +// ***** manage gate state ***** +void manageState() { - delay(3000); // time for USB serial link to come up anew + time(&t); // get time + + switch (STATE) { //check gate state + + case STATE_OTA : + if (difftime(t,timerOTA) > OTA_EXIT_AFTER) { + STATE = STATE_SCAN; // go to STATE_SCAN + Serial.printf("GO TO STATE_SCAN\n"); // DEBUG + } + break;//end case STATE_OTA + + case STATE_OPEN_GATE: + if (difftime(t,tabRecBeacon[0].time) > GO_TO_SCAN_STATE_DELAY) { // if last frame was received more than x seconds ago (GO_TO_SCAN_STATE_DELAY) + STATE = STATE_SCAN; // go to STATE_SCAN + Serial.printf("GO TO STATE_SCAN\n"); // DEBUG + } + break; //end case STATE_OPEN_GATE + + case STATE_SCAN: + int avRSSI = averageRSSI(); // compute average RSSI (with 3 last values) + if (avRSSI > RSSI_THRESHOLD_OPEN_GATE) { // if the received signal power is above the threshold RSSI_THRESHOLD_OPEN_GATE + STATE = STATE_OPEN_GATE; // change state and go to state STATE_OPEN_GATE + Serial.printf("GO TO STATE_OPEN_GATE\n"); // DEBUG + } else { + // RSSI is too low + } + break; //end case STATE_SCAN + } +} + +// ***** start BLE scan ***** +void startScanBLE() { + BLEScan* pBLEScan = BLEDevice::getScan(); // start scanning + pBLEScan->setAdvertisedDeviceCallbacks(new IBeaconAdvertised(), true); + pBLEScan->setActiveScan(true); + pBLEScan->start(SCAN_TIME, scanCompleteCB); + BLEScanActivated = true; +} + +// ***** scan Complete Call Back ***** +static void scanCompleteCB(BLEScanResults scanResults) { // Callback invoked when scanning has completed + BLEScanActivated = false; +} + +// ***** manage BLE scan ***** +void manageBLEscan() { + switch (STATE) { //check gate state + + case STATE_OTA : + // do not restart BLE scan + break;//end case STATE_OTA - Serial.begin(115200); + case STATE_OPEN_GATE: + case STATE_SCAN: + default: + if (!BLEScanActivated) + startScanBLE(); // start scanning + break; //end case STATE_SCAN + } +} + +void setup() { + //init serial port + setupSerial(); + + //init relay module + pinMode(RELAY1, OUTPUT); - // Arduino libs v2.4.1, to enable printf and debug messages output - Serial.setDebugOutput( true ); + //setup WiFi as Access Point + setUpWifiAP(); - Serial.println("Scanning..."); + //setup OTA + setupOTA(); + ArduinoOTA.begin(); + //init BLE BLEDevice::init(""); - // [sep.22] Increase TX POWER ? - BLEDevice::setPower(ESP_PWR_LVL_P9); - // or ... - esp_err_t errRc=esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT,ESP_PWR_LVL_P9); - esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, ESP_PWR_LVL_P9); - esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_SCAN ,ESP_PWR_LVL_P9); - - pBLEScan = BLEDevice::getScan(); //create new scan - pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); - pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster - pBLEScan->setInterval(100); - pBLEScan->setWindow(99); // less or equal setInterval value + //init state + STATE = STATE_SCAN; + + Serial.println(); + Serial.println("Ready"); + Serial.println(); } -void loop() -{ - // put your main code here, to run repeatedly: - BLEScanResults foundDevices = pBLEScan->start(scanTime, false); - Serial.print("Devices found: "); - Serial.println(foundDevices.getCount()); - Serial.println("Scan done!"); - pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory - delay(2000); +void loop() { + ArduinoOTA.handle(); + manageState(); + manageGateOpening(); + manageBLEscan(); + delay(100); }