From c77404f1fefe27db4156f49554f71665fcaa8eee Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Wed, 7 May 2025 11:01:58 -0700 Subject: [PATCH 01/22] Initial steps to enabling bluetooth - Added Bluetooth Files - Made edits to EmotiBit.h+.cpp - This build goes into bluetooth mode, does not stream --- EmotiBit.cpp | 26 +++++- EmotiBit.h | 10 ++- EmotiBitBluetooth.cpp | 65 +++++++++++++++ EmotiBitBluetooth.h | 80 +++++++++++++++++++ EmotiBit_stock_firmware/.gitignore | 5 ++ .../EmotiBitGithub.code-workspace | 18 +++++ EmotiBit_stock_firmware/platformio.ini | 5 +- board_feather_esp32.ini | 4 +- 8 files changed, 203 insertions(+), 10 deletions(-) create mode 100644 EmotiBitBluetooth.cpp create mode 100644 EmotiBitBluetooth.h create mode 100644 EmotiBit_stock_firmware/.gitignore create mode 100644 EmotiBit_stock_firmware/EmotiBitGithub.code-workspace diff --git a/EmotiBit.cpp b/EmotiBit.cpp index 3e3e1e6f..eb2492f7 100644 --- a/EmotiBit.cpp +++ b/EmotiBit.cpp @@ -110,7 +110,7 @@ uint8_t EmotiBit::setup(String firmwareVariant) #endif #ifdef ARDUINO_FEATHER_ESP32 - esp_bt_controller_disable(); + //esp_bt_controller_disable(); // ToDo: assess similarity with btStop(); setCpuFrequencyMhz(CPU_HZ / 1000000); // 80MHz has been tested working to save battery life #endif @@ -952,6 +952,17 @@ uint8_t EmotiBit::setup(String firmwareVariant) Serial.println(factoryTestSerialOutput); sleep(true); } + + if (_emotibitBluetooth.begin(emotibitDeviceId)) + { + setPowerMode(PowerMode::BLUETOOTH); + Serial.println("Bluetooth setup completed"); + } + else{ + Serial.println("Bluetooth setup failed"); + #ifdef ARDUINO_FEATHER_ESP32 + esp_bt_controller_disable(); + #endif //WiFi Setup; Serial.print("\nSetting up WiFi\n"); #if defined(ADAFRUIT_FEATHER_M0) @@ -998,6 +1009,8 @@ uint8_t EmotiBit::setup(String firmwareVariant) #endif setPowerMode(PowerMode::NORMAL_POWER); + } + typeTags[(uint8_t)EmotiBit::DataType::EDA] = EmotiBitPacket::TypeTag::EDA; typeTags[(uint8_t)EmotiBit::DataType::EDL] = EmotiBitPacket::TypeTag::EDL; typeTags[(uint8_t)EmotiBit::DataType::EDR] = EmotiBitPacket::TypeTag::EDR; @@ -1574,6 +1587,7 @@ void EmotiBit::parseIncomingControlPackets(String &controlPackets, uint16_t &pac else if (header.typeTag.equals(EmotiBitPacket::TypeTag::MODE_WIRELESS_OFF)) { setPowerMode(EmotiBit::PowerMode::WIRELESS_OFF); } + else if (header.typeT) else if (header.typeTag.equals(EmotiBitPacket::TypeTag::MODE_HIBERNATE)) { setPowerMode(EmotiBit::PowerMode::HIBERNATE); } @@ -1747,7 +1761,7 @@ uint8_t EmotiBit::update() dataSendTimer = millis(); - +//maybe move into send data if (_sendTestData) { appendTestData(_outDataPackets, _outDataPacketCounter); @@ -3635,8 +3649,8 @@ bool EmotiBit::writeSdCardMessage(const String & s) { firstIndex = 0; while (firstIndex < s.length()) { static int16_t lastIndex; - if (s.length() - firstIndex > MAX_SD_WRITE_LEN) { - lastIndex = firstIndex + MAX_SD_WRITE_LEN; + if (s.length() - firstIndex > MAX_SEND_LEN) { //used to be MAX_SD_WRITE_LEN + lastIndex = firstIndex + MAX_SEND_LEN; } else { lastIndex = s.length(); @@ -4655,3 +4669,7 @@ void EmotiBit::restartMcu() NVIC_SystemReset(); #endif } + +void EmotiBit::nameSdCardFile(){ + +} \ No newline at end of file diff --git a/EmotiBit.h b/EmotiBit.h index c9796cc4..d40d2fc4 100644 --- a/EmotiBit.h +++ b/EmotiBit.h @@ -17,6 +17,7 @@ #include "DoubleBufferFloat.h" #include #include "EmotiBitWiFi.h" +#include "EmotiBitBluetooth.h" #include #ifdef ARDUINO_FEATHER_ESP32 #include @@ -266,7 +267,8 @@ class EmotiBit { MAX_LOW_POWER, // data not sent, time-syncing accuracy low LOW_POWER, // data not sent, time-syncing accuracy high NORMAL_POWER, // data sending, time-syncing accuracy high - length + length, + BLUETOOTH }; Si7013 tempHumiditySensor; @@ -279,6 +281,7 @@ class EmotiBit { MLX90632 thermopile; EmotiBitEda emotibitEda; EmotiBitNvmController _emotibitNvmController; + EmotiBitBluetooth _emotibitBluetooth; #ifdef ARDUINO_FEATHER_ESP32 FileTransferManager _fileTransferManager; #endif @@ -298,7 +301,8 @@ class EmotiBit { static const uint16_t OUT_MESSAGE_RESERVE_SIZE = 2048; static const uint16_t OUT_MESSAGE_TARGET_SIZE = 1024; static const uint16_t DATA_SEND_INTERVAL = 100; - static const uint16_t MAX_SD_WRITE_LEN = 512; // 512 is the size of the sdFat buffer +// static const uint16_t MAX_SD_WRITE_LEN = 512; // 512 is the size of the sdFat buffer + static const uint16_t MAX_SEND_LEN = 512; // new max send length for splitting in send data, used to be "MAX_SD_WRITE_LEN" static const uint16_t MAX_DATA_BUFFER_SIZE = 48; static const uint16_t NORMAL_POWER_MODE_PACKET_INTERVAL = 200; static const uint16_t LOW_POWER_MODE_PACKET_INTERVAL = 1000; @@ -458,7 +462,7 @@ class EmotiBit { bool processThermopileData(); // placeholder until separate EmotiBitThermopile controller is implemented void writeSerialData(EmotiBit::DataType t); void printEmotiBitInfo(); - + void nameSdCardFile(); /** * Copies data buffer of the specified DataType into the passed array diff --git a/EmotiBitBluetooth.cpp b/EmotiBitBluetooth.cpp new file mode 100644 index 00000000..8e226175 --- /dev/null +++ b/EmotiBitBluetooth.cpp @@ -0,0 +1,65 @@ +#include "EmotiBitBluetooth.h" + + + + +uint8_t EmotiBitBluetooth::begin(const String& emotibitDeviceId) +{ +//IF BLUETOOTH +#ifdef BLUETOOTH_ENABLED + _emotibitDeviceId = emotibitDeviceId; + Serial.println("Bluetooth tag detected, turning on bluetooth."); + BLEDevice::init(_emotibitDeviceId.c_str()); + pServer = BLEDevice::createServer(); + pServer->setCallbacks(new MyServerCallbacks(this)); + BLEService* pService = pServer->createService("6E400001-B5A3-F393-E0A9-E50E24DCCA9E"); + pTxCharacteristic = pService->createCharacteristic("6E400003-B5A3-F393-E0A9-E50E24DCCA9E", BLECharacteristic::PROPERTY_NOTIFY); + pTxCharacteristic->addDescriptor(new BLE2902()); + BLECharacteristic* pRxCharacteristic = pService->createCharacteristic("6E400002-B5A3-F393-E0A9-E50E24DCCA9E", BLECharacteristic::PROPERTY_WRITE); + pRxCharacteristic->setCallbacks(new MyCallbacks()); + pService->start(); + pServer->getAdvertising()->start(); + return 1; +#else + Serial.println("Bluetooth disabled."); + return 0; +#endif +} + +void EmotiBitBluetooth::MyServerCallbacks::onConnect(BLEServer* pServer) +{ + server -> deviceConnected = true; + Serial.println("BLE client connected"); + +} + +void EmotiBitBluetooth::MyServerCallbacks::onDisconnect(BLEServer* pServer) +{ + server -> deviceConnected = false; + Serial.println("BLE client disconnected"); +} + +void EmotiBitBluetooth::MyCallbacks::onWrite(BLECharacteristic *pCharacteristic) +{ + std::string rxValue = pCharacteristic->getValue(); + if (rxValue.length() > 0) { + Serial.print("Received: "); + Serial.println(rxValue.c_str()); + } +} + +void EmotiBitBluetooth::setDeviceId(const String emotibitDeviceId) +{ + _emotibitDeviceId = emotibitDeviceId; +} + +void EmotiBitBluetooth::sendData(const String &message) +{ + if (deviceConnected) { + pTxCharacteristic->setValue(message.c_str()); + pTxCharacteristic->notify(); + } + else { + Serial.println("unable to send data."); + } +} \ No newline at end of file diff --git a/EmotiBitBluetooth.h b/EmotiBitBluetooth.h new file mode 100644 index 00000000..5e46cbbb --- /dev/null +++ b/EmotiBitBluetooth.h @@ -0,0 +1,80 @@ +/**************************************************************************/ +/*! + @file EmotiBitBluetooth.h + + This file facilitates the use of Bluetooth on the EmotiBit + + EmotiBit invests time and resources providing this open source code, + please support EmotiBit and open-source hardware by purchasing + products from EmotiBit! + + Written by Joseph Jacobson for EmotiBit. + + BSD license, all text here must be included in any redistribution +*/ +/**************************************************************************/ +#pragma once +/*! +* @brief inclusions for BLE Device, Server, Utils, 2902, and Arduino +*/ +#include "Arduino.h" +#include +#include +#include +#include + + +/*! + * @brief Handles Bluetooth communication for EmotiBit. +*/ +class EmotiBitBluetooth { + public: + BLEServer* pServer = nullptr; ///points to the server + BLECharacteristic* pTxCharacteristic = nullptr; ///points to the tx characteristic + bool deviceConnected = false; ///boolean to check if device is connected + String _emotibitDeviceId = ""; ///string to hold device id + + /*! + * @brief Server callbacks for connections + */ + class MyServerCallbacks: public BLEServerCallbacks { + public: + MyServerCallbacks(EmotiBitBluetooth* server) : server(server) {} + void onConnect(BLEServer* pServer); + void onDisconnect(BLEServer* pServer); + private: + EmotiBitBluetooth* server; + }; + + /*! + * @brief Characteristic callbacks for data transfer + */ + class MyCallbacks : public BLECharacteristicCallbacks { + void onWrite(BLECharacteristic *pCharacteristic); + }; + + /*! + * @brief Initializes the BLE device and starts advertising + * @param emotibitDeviceId ID from setDeviceId + * @return 1 on success, 0 on failure + */ + //TO DO use int for error handling + uint8_t begin(const String& emotibitDeviceId); + + /*! + * @brief Sends data over BLE + * @param message data to be sent + */ + void sendData(const String &message); + + /*! + * @brief Checks if the device is connected to a BLE client + * @param emotibitDeviceId + */ + void setDeviceId(const String emotibitDeviceId); + + //void update();for when we sync data over BLE + //move to emotibit + //void sdCardFileNaming(); for when we choose bluetooth and there is no rb start time +}; + diff --git a/EmotiBit_stock_firmware/.gitignore b/EmotiBit_stock_firmware/.gitignore new file mode 100644 index 00000000..89cc49cb --- /dev/null +++ b/EmotiBit_stock_firmware/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/EmotiBit_stock_firmware/EmotiBitGithub.code-workspace b/EmotiBit_stock_firmware/EmotiBitGithub.code-workspace new file mode 100644 index 00000000..d99d9a2b --- /dev/null +++ b/EmotiBit_stock_firmware/EmotiBitGithub.code-workspace @@ -0,0 +1,18 @@ +{ + "folders": [ + { + "path": "../.." + }, + { + "name": "EmotiBit_stock_firmware", + "path": "." + } + ], + "settings": { + "files.associations": { + "regex": "cpp", + "xlocale": "cpp", + "xstring": "cpp" + } + } +} \ No newline at end of file diff --git a/EmotiBit_stock_firmware/platformio.ini b/EmotiBit_stock_firmware/platformio.ini index d8e9cbd7..9e16331f 100644 --- a/EmotiBit_stock_firmware/platformio.ini +++ b/EmotiBit_stock_firmware/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [platformio] extra_configs = - ../board_feather_m0.ini + ;../board_feather_m0.ini ../board_feather_esp32.ini src_dir = ./ lib_dir = ../../ @@ -19,4 +19,5 @@ lib_dir = ../../ variant_flags = -DSTOCK_FIRMWARE [env] -lib_ldf_mode = deep+ \ No newline at end of file +lib_ldf_mode = deep+ +build_flags = -DBLUETOOTH_ENABLED \ No newline at end of file diff --git a/board_feather_esp32.ini b/board_feather_esp32.ini index 16ba6c5d..858fefa6 100644 --- a/board_feather_esp32.ini +++ b/board_feather_esp32.ini @@ -5,7 +5,9 @@ board = featheresp32 framework = arduino build_flags = -DARDUINO_FEATHER_ESP32 ${custom.variant_flags} + -DBLUETOOTH_ENABLED ; change MCU frequency board_build.f_cpu = 240000000L extra_scripts = pre:../pio_scripts/renameFw.py -firmware_name_board_name = feather_esp32 \ No newline at end of file +firmware_name_board_name = feather_esp32 +board_build.partitions = huge_app.csv ;added to support bluetooth \ No newline at end of file From 2f416622029d6eb25f27dc233f51754d3dbd97bb Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Mon, 12 May 2025 13:45:49 -0700 Subject: [PATCH 02/22] Next bluetooth build before creating test software --- EmotiBit.cpp | 146 +++++++++++++++++++++++-- EmotiBit.h | 4 +- EmotiBitBluetooth.cpp | 7 +- EmotiBit_stock_firmware/platformio.ini | 2 +- board_feather_esp32.ini | 2 +- 5 files changed, 146 insertions(+), 15 deletions(-) diff --git a/EmotiBit.cpp b/EmotiBit.cpp index eb2492f7..7b4c65aa 100644 --- a/EmotiBit.cpp +++ b/EmotiBit.cpp @@ -955,11 +955,13 @@ uint8_t EmotiBit::setup(String firmwareVariant) if (_emotibitBluetooth.begin(emotibitDeviceId)) { + // Bluetooth setup setPowerMode(PowerMode::BLUETOOTH); Serial.println("Bluetooth setup completed"); + nameSdCardFile(); } else{ - Serial.println("Bluetooth setup failed"); + Serial.println("Bluetooth setup failed"); //TODO can remove this in PR #ifdef ARDUINO_FEATHER_ESP32 esp_bt_controller_disable(); #endif @@ -1297,7 +1299,7 @@ bool EmotiBit::setupSdCard(bool loadConfig) #if defined ARDUINO_FEATHER_ESP32 Serial.println("ESP::: Reading SD-Card"); File dir; - dir = SD.open("/"); + dir = SD.open("/"); // look here for files and grab everything // taken from SD examples: listFiles while (true) { @@ -1587,7 +1589,9 @@ void EmotiBit::parseIncomingControlPackets(String &controlPackets, uint16_t &pac else if (header.typeTag.equals(EmotiBitPacket::TypeTag::MODE_WIRELESS_OFF)) { setPowerMode(EmotiBit::PowerMode::WIRELESS_OFF); } - else if (header.typeT) + else if (header.typeTag.equals(EmotiBitPacket::TypeTag::MODE_BLUETOOTH)) { + setPowerMode(EmotiBit::PowerMode::BLUETOOTH); + } else if (header.typeTag.equals(EmotiBitPacket::TypeTag::MODE_HIBERNATE)) { setPowerMode(EmotiBit::PowerMode::HIBERNATE); } @@ -1764,7 +1768,7 @@ uint8_t EmotiBit::update() //maybe move into send data if (_sendTestData) { - appendTestData(_outDataPackets, _outDataPacketCounter); + appendTestData(_outDataPackets, _outDataPacketCounter); // add here for testing if (getPowerMode() == PowerMode::NORMAL_POWER) { _emotiBitWiFi.sendData(_outDataPackets); @@ -3226,6 +3230,35 @@ void EmotiBit::readSensors() led.setState(EmotiBitLedController::Led::BLUE, true); led.setState(EmotiBitLedController::Led::YELLOW, true); } + //new if statment to check if we are in powermode + if (getPowerMode() == PowerMode::BLUETOOTH){ + // Bluetooth connected status LED + if (_emotibitBluetooth.deviceConnected){ + led.setState(EmotiBitLedController::Led::BLUE, true); + } + else { + // blink LED + static unsigned long onTime = 125; // msec + static unsigned long totalTime = 250; // msec changed to 250 + static bool wifiConnectedBlinkState = false; + + static unsigned long wifiConnBlinkTimer = millis(); + + unsigned long timeNow = millis(); + if (timeNow - wifiConnBlinkTimer < onTime) + { + led.setState(EmotiBitLedController::Led::BLUE, true); + } + else if (timeNow - wifiConnBlinkTimer < totalTime) + { + led.setState(EmotiBitLedController::Led::BLUE, false); + } + else + { + wifiConnBlinkTimer = timeNow; + } + } + } else { // WiFi connected status LED @@ -3439,33 +3472,78 @@ void EmotiBit::sendData() { for (int16_t i = 0; i < (uint8_t)EmotiBit::DataType::length; i++) { + //Serial.print(_outDataPackets); addPacket((EmotiBit::DataType) i); if (_outDataPackets.length() > OUT_MESSAGE_TARGET_SIZE) { + //writeSdCardMessage(_outDataPackets); //moved out of loop to test + + static int16_t firstIndex; + firstIndex = 0; + while (firstIndex < _outDataPackets.length()) { + static int16_t lastIndex; + if (_outDataPackets.length() - firstIndex > MAX_SEND_LEN) { //used to be MAX_SD_WRITE_LEN + lastIndex = firstIndex + MAX_SEND_LEN; + } + else { + lastIndex = _outDataPackets.length(); + } // Avoid overrunning our reserve memory //if (_outDataPackets.length() > 2000) //{ // Serial.println(_outDataPackets.length()); //} + String s = _outDataPackets.substring(firstIndex, lastIndex); if (getPowerMode() == PowerMode::NORMAL_POWER) { - _emotiBitWiFi.sendData(_outDataPackets); + _emotiBitWiFi.sendData(s); } //Serial.println("_emotiBitWiFi.sendData()"); - writeSdCardMessage(_outDataPackets); + if (getPowerMode() == PowerMode::BLUETOOTH) + { + _emotibitBluetooth.sendData(s); + //_emotibitBluetooth.sendData("Hello World"); + //Serial.println("sending data via bluetooth"); + } + //writeSdCardMessage(s); //Serial.println("writeSdCardMessage()"); - _outDataPackets = ""; + firstIndex = lastIndex; + //_outDataPackets = ""; + _outDataPackets = ""; + + } } } if (_outDataPackets.length() > 0) { + //writeSdCardMessage(_outDataPackets); //moved out of loop to test + static int16_t firstIndex; + firstIndex = 0; + while (firstIndex < _outDataPackets.length()) { + static int16_t lastIndex; + if (_outDataPackets.length() - firstIndex > MAX_SEND_LEN) { //used to be MAX_SD_WRITE_LEN + lastIndex = firstIndex + MAX_SEND_LEN; + } + else { + lastIndex = _outDataPackets.length(); + } + String s = _outDataPackets.substring(firstIndex, lastIndex); if (getPowerMode() == PowerMode::NORMAL_POWER) { - _emotiBitWiFi.sendData(_outDataPackets); + _emotiBitWiFi.sendData(s); } - writeSdCardMessage(_outDataPackets); + + if (getPowerMode() == PowerMode::BLUETOOTH) + { + _emotibitBluetooth.sendData(s); + //_emotibitBluetooth.sendData("Hello World"); + //Serial.println("sending data via bluetooth"); + } + writeSdCardMessage(s); + firstIndex = lastIndex; + } _outDataPackets = ""; } } @@ -3747,6 +3825,11 @@ void EmotiBit::setPowerMode(PowerMode mode) Serial.println("PowerMode::WIRELESS_OFF"); _emotiBitWiFi.end(); } + else if (getPowerMode() == PowerMode::BLUETOOTH) + { + Serial.println("PowerMode::BLUETOOTH"); + //TODO: we can turn on/off disable bluetooth here and wifi + } else if (getPowerMode() == PowerMode::HIBERNATE) { Serial.println("PowerMode::HIBERNATE"); @@ -4670,6 +4753,49 @@ void EmotiBit::restartMcu() #endif } -void EmotiBit::nameSdCardFile(){ +void EmotiBit::nameSdCardFile() { + int maxSuffix = -1; + File dir = SD.open("/"); + while (true) { + File entry = dir.openNextFile(); + if (!entry) break; + String name = entry.name(); + if (name.startsWith("BLUETOOTH_") && name.endsWith(".csv")) { + int underscore = name.lastIndexOf('_'); + int dot = name.lastIndexOf('.'); + if (underscore != -1 && dot != -1 && dot > underscore + 1) { + String numStr = name.substring(underscore + 1, dot); + int num = numStr.toInt(); + if (num > maxSuffix) maxSuffix = num; + } + } + entry.close(); + } + int nextSuffix = maxSuffix + 1; + char filename[32]; + snprintf(filename, sizeof(filename), "/BLUETOOTH_%04d.csv", nextSuffix); + _sdCardFilename = String(filename); + Serial.print("Creating SD card file: "); + Serial.println(_sdCardFilename); + /* + // Write test line to the file + File testFile = SD.open(_sdCardFilename, FILE_WRITE); + if (testFile) { + testFile.print("test working for "); + testFile.println(nextSuffix); + testFile.close(); + Serial.println("Test line written to SD card file."); + } else { + Serial.println("Failed to create SD card file!"); + }*/ + // Open the file for writing and set _sdWrite + _dataFile = SD.open(_sdCardFilename, FILE_WRITE); + if (_dataFile) { + _sdWrite = true; + Serial.println("SD card file opened."); + } else { + _sdWrite = false; + Serial.println("Failed to open SD card"); + } } \ No newline at end of file diff --git a/EmotiBit.h b/EmotiBit.h index 2ef3fb43..c5e95f72 100644 --- a/EmotiBit.h +++ b/EmotiBit.h @@ -267,8 +267,8 @@ class EmotiBit { MAX_LOW_POWER, // data not sent, time-syncing accuracy low LOW_POWER, // data not sent, time-syncing accuracy high NORMAL_POWER, // data sending, time-syncing accuracy high - length, - BLUETOOTH + BLUETOOTH, + length }; Si7013 tempHumiditySensor; diff --git a/EmotiBitBluetooth.cpp b/EmotiBitBluetooth.cpp index 8e226175..6b609857 100644 --- a/EmotiBitBluetooth.cpp +++ b/EmotiBitBluetooth.cpp @@ -9,7 +9,7 @@ uint8_t EmotiBitBluetooth::begin(const String& emotibitDeviceId) #ifdef BLUETOOTH_ENABLED _emotibitDeviceId = emotibitDeviceId; Serial.println("Bluetooth tag detected, turning on bluetooth."); - BLEDevice::init(_emotibitDeviceId.c_str()); + BLEDevice::init(("EmotiBit: " + _emotibitDeviceId).c_str()); pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks(this)); BLEService* pService = pServer->createService("6E400001-B5A3-F393-E0A9-E50E24DCCA9E"); @@ -37,6 +37,9 @@ void EmotiBitBluetooth::MyServerCallbacks::onDisconnect(BLEServer* pServer) { server -> deviceConnected = false; Serial.println("BLE client disconnected"); + //need to restart advertising to allow new connections after disconnection + pServer->getAdvertising()->start(); + Serial.println("Restarted BLE advertising"); } void EmotiBitBluetooth::MyCallbacks::onWrite(BLECharacteristic *pCharacteristic) @@ -58,6 +61,8 @@ void EmotiBitBluetooth::sendData(const String &message) if (deviceConnected) { pTxCharacteristic->setValue(message.c_str()); pTxCharacteristic->notify(); + //Serial.print("Sent: "); + //Serial.println(message.c_str()); } else { Serial.println("unable to send data."); diff --git a/EmotiBit_stock_firmware/platformio.ini b/EmotiBit_stock_firmware/platformio.ini index 9e16331f..6aa93799 100644 --- a/EmotiBit_stock_firmware/platformio.ini +++ b/EmotiBit_stock_firmware/platformio.ini @@ -20,4 +20,4 @@ variant_flags = -DSTOCK_FIRMWARE [env] lib_ldf_mode = deep+ -build_flags = -DBLUETOOTH_ENABLED \ No newline at end of file +;build_flags = -DBLUETOOTH_ENABLED \ No newline at end of file diff --git a/board_feather_esp32.ini b/board_feather_esp32.ini index 858fefa6..875f599f 100644 --- a/board_feather_esp32.ini +++ b/board_feather_esp32.ini @@ -5,7 +5,7 @@ board = featheresp32 framework = arduino build_flags = -DARDUINO_FEATHER_ESP32 ${custom.variant_flags} - -DBLUETOOTH_ENABLED + shee-DBLUETOOTH_ENABLED ; change MCU frequency board_build.f_cpu = 240000000L extra_scripts = pre:../pio_scripts/renameFw.py From 2244162ea0f10d1e470df1d2dbbd5dd1782c72eb Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Tue, 15 Jul 2025 09:19:55 -0700 Subject: [PATCH 03/22] Adding multiple characteristics --- EmotiBitBluetooth.cpp | 25 ++++++++++++++++++------- EmotiBitBluetooth.h | 5 +++++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/EmotiBitBluetooth.cpp b/EmotiBitBluetooth.cpp index 6b609857..015f5355 100644 --- a/EmotiBitBluetooth.cpp +++ b/EmotiBitBluetooth.cpp @@ -12,13 +12,23 @@ uint8_t EmotiBitBluetooth::begin(const String& emotibitDeviceId) BLEDevice::init(("EmotiBit: " + _emotibitDeviceId).c_str()); pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks(this)); - BLEService* pService = pServer->createService("6E400001-B5A3-F393-E0A9-E50E24DCCA9E"); - pTxCharacteristic = pService->createCharacteristic("6E400003-B5A3-F393-E0A9-E50E24DCCA9E", BLECharacteristic::PROPERTY_NOTIFY); - pTxCharacteristic->addDescriptor(new BLE2902()); - BLECharacteristic* pRxCharacteristic = pService->createCharacteristic("6E400002-B5A3-F393-E0A9-E50E24DCCA9E", BLECharacteristic::PROPERTY_WRITE); - pRxCharacteristic->setCallbacks(new MyCallbacks()); + BLEService* pService = pServer->createService(EMOTIBIT_SERVICE_UUID); + + pDataTxCharacteristic = pService->createCharacteristic(EMOTIBIT_DATA_TX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_NOTIFY); + pDataTxCharacteristic->addDescriptor(new BLE2902()); + + pDataRxCharacteristic = pService->createCharacteristic(EMOTIBIT_DATA_RX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE); + pDataRxCharacteristic->setCallbacks(new MyCallbacks()); + + pSyncTxCharacteristic = pService->createCharacteristic(EMOTIBIT_SYNC_TX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_NOTIFY); + pSyncTxCharacteristic->addDescriptor(new BLE2902()); + + pSyncRxCharacteristic = pService->createCharacteristic(EMOTIBIT_SYNC_RX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE); + pSyncRxCharacteristic->setCallbacks(new MyCallbacks()); + pService->start(); pServer->getAdvertising()->start(); + Serial.println("BLE advertising started"); return 1; #else Serial.println("Bluetooth disabled."); @@ -26,6 +36,7 @@ uint8_t EmotiBitBluetooth::begin(const String& emotibitDeviceId) #endif } +//ToDO: consider splitting this function into two: one for sending data and another for sending sync data void EmotiBitBluetooth::MyServerCallbacks::onConnect(BLEServer* pServer) { server -> deviceConnected = true; @@ -59,8 +70,8 @@ void EmotiBitBluetooth::setDeviceId(const String emotibitDeviceId) void EmotiBitBluetooth::sendData(const String &message) { if (deviceConnected) { - pTxCharacteristic->setValue(message.c_str()); - pTxCharacteristic->notify(); + pDataTxCharacteristic->setValue(message.c_str()); + pDataTxCharacteristic->notify(); //Serial.print("Sent: "); //Serial.println(message.c_str()); } diff --git a/EmotiBitBluetooth.h b/EmotiBitBluetooth.h index 5e46cbbb..8c6308b6 100644 --- a/EmotiBitBluetooth.h +++ b/EmotiBitBluetooth.h @@ -23,6 +23,11 @@ #include #include +#define EMOTIBIT_SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" +#define EMOTIBIT_DATA_TX_CHARACTERISTIC_UUID "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" +#define EMOTIBIT_DATA_RX_CHARACTERISTIC_UUID "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" +#define EMOTIBIT_SYNC_TX_CHARACTERISTIC_UUID "6E400004-B5A3-F393-E0A9-E50E24DCCA9E" +#define EMOTIBIT_SYNC_RX_CHARACTERISTIC_UUID "6E400005-B5A3-F393-E0A9-E50E24DCCA9E" /*! * @brief Handles Bluetooth communication for EmotiBit. From 80d7099c35c00e395b346fb588feab8dd970c478 Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Tue, 15 Jul 2025 11:51:06 -0700 Subject: [PATCH 04/22] added read control- untested --- EmotiBit.cpp | 2 ++ EmotiBitBluetooth.cpp | 31 ++++++++++++++++++++++++++++++- EmotiBitBluetooth.h | 8 +++++++- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/EmotiBit.cpp b/EmotiBit.cpp index 7b4c65aa..992527eb 100644 --- a/EmotiBit.cpp +++ b/EmotiBit.cpp @@ -1514,6 +1514,8 @@ void EmotiBit::parseIncomingControlPackets(String &controlPackets, uint16_t &pac static String packet; static EmotiBitPacket::Header header; int16_t dataStartChar = 0; + //use the following + //while (_emotiBitWiFi.readControl(packet) > 0 || _emotiBitBluetooth.readControl(packet) > 0) while (_emotiBitWiFi.readControl(packet) > 0) { Serial.println(packet); diff --git a/EmotiBitBluetooth.cpp b/EmotiBitBluetooth.cpp index 015f5355..a2355b2e 100644 --- a/EmotiBitBluetooth.cpp +++ b/EmotiBitBluetooth.cpp @@ -1,5 +1,5 @@ #include "EmotiBitBluetooth.h" - +//NOTE, remove ifdefs for bluetooth when we can manually choose to enable/disable bluetooth @@ -78,4 +78,33 @@ void EmotiBitBluetooth::sendData(const String &message) else { Serial.println("unable to send data."); } +} + +uint8_t EmotiBitBluetooth::readControl(String& packet) +{ + uint8_t numPackets = 0; +#ifdef BLUETOOTH_ENABLED + if (deviceConnected) + { + std::string rxValue = pDataRxCharacteristic->getValue(); + if (rxValue.length() > 0) + { + // Append new data to buffer + _receivedControlMessage += String(rxValue.c_str()); + + // Look for complete packets (delimited by EmotiBitPacket::PACKET_DELIMITER_CSV) + int delimIndex; + while ((delimIndex = _receivedControlMessage.indexOf(EmotiBitPacket::PACKET_DELIMITER_CSV)) != -1) + { + // Extract one packet + packet = _receivedControlMessage.substring(0, delimIndex + 1); + _receivedControlMessage = _receivedControlMessage.substring(delimIndex + 1); + numPackets++; + // Optionally: return after first packet if you want one-at-a-time behavior + return numPackets; + } + } + } +#endif + return numPackets; } \ No newline at end of file diff --git a/EmotiBitBluetooth.h b/EmotiBitBluetooth.h index 8c6308b6..3b7a4a4d 100644 --- a/EmotiBitBluetooth.h +++ b/EmotiBitBluetooth.h @@ -77,7 +77,13 @@ class EmotiBitBluetooth { * @param emotibitDeviceId */ void setDeviceId(const String emotibitDeviceId); - + + /*! + * @brief Reads control messages from the BLE characteristic + * @param packet the control message packet + */ + uint8_t readControl(String& packet); + //void update();for when we sync data over BLE //move to emotibit //void sdCardFileNaming(); for when we choose bluetooth and there is no rb start time From 9d4ba9c3c4adab617be96e56c898cea8f4a080e8 Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Thu, 17 Jul 2025 11:58:13 -0700 Subject: [PATCH 05/22] Changes to parseIncomingControlPackets to enable bluetooth control packets --- EmotiBit.cpp | 19 ++++++++--- EmotiBit.h | 2 +- EmotiBitBluetooth.cpp | 47 +++++++++++++++++++------- EmotiBitBluetooth.h | 20 ++++++++--- EmotiBit_stock_firmware/platformio.ini | 5 ++- board_feather_esp32.ini | 2 +- 6 files changed, 67 insertions(+), 28 deletions(-) diff --git a/EmotiBit.cpp b/EmotiBit.cpp index 8be29d3a..6329a901 100644 --- a/EmotiBit.cpp +++ b/EmotiBit.cpp @@ -953,12 +953,12 @@ uint8_t EmotiBit::setup(String firmwareVariant) sleep(true); } - if (_emotibitBluetooth.begin(emotibitDeviceId)) + if (_emotiBitBluetooth.begin(emotibitDeviceId)) { // Bluetooth setup setPowerMode(PowerMode::BLUETOOTH); Serial.println("Bluetooth setup completed"); - nameSdCardFile(); + //nameSdCardFile(); } else{ Serial.println("Bluetooth setup failed"); //TODO can remove this in PR @@ -1515,8 +1515,8 @@ void EmotiBit::parseIncomingControlPackets(String &controlPackets, uint16_t &pac static EmotiBitPacket::Header header; int16_t dataStartChar = 0; //use the following - //while (_emotiBitWiFi.readControl(packet) > 0 || _emotiBitBluetooth.readControl(packet) > 0) - while (_emotiBitWiFi.readControl(packet) > 0) + while (_emotiBitWiFi.readControl(packet) > 0 || _emotiBitBluetooth.readControl(packet) > 0) + //while (_emotiBitWiFi.readControl(packet) > 0) { Serial.println(packet); dataStartChar = EmotiBitPacket::getHeader(packet, header); @@ -3220,7 +3220,7 @@ void EmotiBit::readSensors() //new if statment to check if we are in powermode if (getPowerMode() == PowerMode::BLUETOOTH){ // Bluetooth connected status LED - if (_emotibitBluetooth.deviceConnected){ + if (_emotiBitBluetooth.deviceConnected){ led.setState(EmotiBitLedController::Led::BLUE, true); } else { @@ -3502,6 +3502,9 @@ void EmotiBit::sendData() if (getPowerMode() == PowerMode::NORMAL_POWER) { _emotiBitWiFi.sendData(s); } + if (getPowerMode() == PowerMode::BLUETOOTH) { + _emotiBitBluetooth.sendData(s); + } writeSdCardMessage(s); firstIndex = lastIndex + 1; } @@ -3540,6 +3543,9 @@ void EmotiBit::sendData() if (getPowerMode() == PowerMode::NORMAL_POWER) { _emotiBitWiFi.sendData(s); } + if (getPowerMode() == PowerMode::BLUETOOTH) { + _emotiBitBluetooth.sendData(s); + } writeSdCardMessage(s); firstIndex = lastIndex + 1; } @@ -4413,6 +4419,8 @@ void EmotiBit::processDebugInputs(String &debugPackets, uint16_t &packetNumber) else if (c == '>') { _sendTestData = true; + //nameSdCardFile(); //temp + Serial.println("Entering Sending Test Data Mode"); } else if (c == '@' && _sendTestData == true) @@ -4778,6 +4786,7 @@ void EmotiBit::restartMcu() #endif } +//unneeded can be removed void EmotiBit::nameSdCardFile() { int maxSuffix = -1; File dir = SD.open("/"); diff --git a/EmotiBit.h b/EmotiBit.h index 927bb610..5a73d0d2 100644 --- a/EmotiBit.h +++ b/EmotiBit.h @@ -281,7 +281,7 @@ class EmotiBit { MLX90632 thermopile; EmotiBitEda emotibitEda; EmotiBitNvmController _emotibitNvmController; - EmotiBitBluetooth _emotibitBluetooth; + EmotiBitBluetooth _emotiBitBluetooth; #ifdef ARDUINO_FEATHER_ESP32 FileTransferManager _fileTransferManager; #endif diff --git a/EmotiBitBluetooth.cpp b/EmotiBitBluetooth.cpp index a2355b2e..b4173cff 100644 --- a/EmotiBitBluetooth.cpp +++ b/EmotiBitBluetooth.cpp @@ -20,11 +20,11 @@ uint8_t EmotiBitBluetooth::begin(const String& emotibitDeviceId) pDataRxCharacteristic = pService->createCharacteristic(EMOTIBIT_DATA_RX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE); pDataRxCharacteristic->setCallbacks(new MyCallbacks()); - pSyncTxCharacteristic = pService->createCharacteristic(EMOTIBIT_SYNC_TX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_NOTIFY); - pSyncTxCharacteristic->addDescriptor(new BLE2902()); + //pSyncTxCharacteristic = pService->createCharacteristic(EMOTIBIT_SYNC_TX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_NOTIFY); + //pSyncTxCharacteristic->addDescriptor(new BLE2902()); - pSyncRxCharacteristic = pService->createCharacteristic(EMOTIBIT_SYNC_RX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE); - pSyncRxCharacteristic->setCallbacks(new MyCallbacks()); + //pSyncRxCharacteristic = pService->createCharacteristic(EMOTIBIT_SYNC_RX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE); + //pSyncRxCharacteristic->setCallbacks(new MyCallbacks()); pService->start(); pServer->getAdvertising()->start(); @@ -53,6 +53,7 @@ void EmotiBitBluetooth::MyServerCallbacks::onDisconnect(BLEServer* pServer) Serial.println("Restarted BLE advertising"); } + void EmotiBitBluetooth::MyCallbacks::onWrite(BLECharacteristic *pCharacteristic) { std::string rxValue = pCharacteristic->getValue(); @@ -84,25 +85,45 @@ uint8_t EmotiBitBluetooth::readControl(String& packet) { uint8_t numPackets = 0; #ifdef BLUETOOTH_ENABLED + packet = ""; if (deviceConnected) { + std::string rxValue = pDataRxCharacteristic->getValue(); - if (rxValue.length() > 0) + if (!rxValue.empty()) { - // Append new data to buffer + Serial.print("Received: "); + Serial.println(rxValue.c_str()); _receivedControlMessage += String(rxValue.c_str()); - // Look for complete packets (delimited by EmotiBitPacket::PACKET_DELIMITER_CSV) - int delimIndex; - while ((delimIndex = _receivedControlMessage.indexOf(EmotiBitPacket::PACKET_DELIMITER_CSV)) != -1) + // *** CLEAR THE CHAR VALUE SO WE DON’T REUSE IT *** + pDataRxCharacteristic->setValue(""); + } + + String tempPacket = ""; + while (_receivedControlMessage.length() > 0) + { + int c = _receivedControlMessage[0]; + _receivedControlMessage.remove(0, 1); + + if (c == (int)EmotiBitPacket::PACKET_DELIMITER_CSV) { - // Extract one packet - packet = _receivedControlMessage.substring(0, delimIndex + 1); - _receivedControlMessage = _receivedControlMessage.substring(delimIndex + 1); numPackets++; - // Optionally: return after first packet if you want one-at-a-time behavior + packet = tempPacket; + tempPacket = ""; + _receivedControlMessage = ""; return numPackets; } + else + { + if (c == 0) { + // Throw out null term + } + else + { + tempPacket += (char)c; + } + } } } #endif diff --git a/EmotiBitBluetooth.h b/EmotiBitBluetooth.h index 3b7a4a4d..3527f6d5 100644 --- a/EmotiBitBluetooth.h +++ b/EmotiBitBluetooth.h @@ -22,12 +22,16 @@ #include #include #include +#include "EmotiBitPacket.h" + #define EMOTIBIT_SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" -#define EMOTIBIT_DATA_TX_CHARACTERISTIC_UUID "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" -#define EMOTIBIT_DATA_RX_CHARACTERISTIC_UUID "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" -#define EMOTIBIT_SYNC_TX_CHARACTERISTIC_UUID "6E400004-B5A3-F393-E0A9-E50E24DCCA9E" -#define EMOTIBIT_SYNC_RX_CHARACTERISTIC_UUID "6E400005-B5A3-F393-E0A9-E50E24DCCA9E" +#define EMOTIBIT_DATA_RX_CHARACTERISTIC_UUID "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" +#define EMOTIBIT_DATA_TX_CHARACTERISTIC_UUID "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" + +//untested below +//#define EMOTIBIT_SYNC_TX_CHARACTERISTIC_UUID "6E400004-B5A3-F393-E0A9-E50E24DCCA9E" +//#define EMOTIBIT_SYNC_RX_CHARACTERISTIC_UUID "6E400005-B5A3-F393-E0A9-E50E24DCCA9E" /*! * @brief Handles Bluetooth communication for EmotiBit. @@ -35,9 +39,15 @@ class EmotiBitBluetooth { public: BLEServer* pServer = nullptr; ///points to the server - BLECharacteristic* pTxCharacteristic = nullptr; ///points to the tx characteristic + + BLECharacteristic* pDataTxCharacteristic = nullptr; ///points to the data tx characteristic + BLECharacteristic* pDataRxCharacteristic = nullptr; ///points to the data rx characteristic + //BLECharacteristic* pSyncTxCharacteristic = nullptr; ///points to the sync tx characteristic + //BLECharacteristic* pSyncRxCharacteristic = nullptr; ///points to the sync rx characteristic + bool deviceConnected = false; ///boolean to check if device is connected String _emotibitDeviceId = ""; ///string to hold device id + String _receivedControlMessage = ""; /*! * @brief Server callbacks for connections diff --git a/EmotiBit_stock_firmware/platformio.ini b/EmotiBit_stock_firmware/platformio.ini index 6aa93799..d8e9cbd7 100644 --- a/EmotiBit_stock_firmware/platformio.ini +++ b/EmotiBit_stock_firmware/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [platformio] extra_configs = - ;../board_feather_m0.ini + ../board_feather_m0.ini ../board_feather_esp32.ini src_dir = ./ lib_dir = ../../ @@ -19,5 +19,4 @@ lib_dir = ../../ variant_flags = -DSTOCK_FIRMWARE [env] -lib_ldf_mode = deep+ -;build_flags = -DBLUETOOTH_ENABLED \ No newline at end of file +lib_ldf_mode = deep+ \ No newline at end of file diff --git a/board_feather_esp32.ini b/board_feather_esp32.ini index 875f599f..858fefa6 100644 --- a/board_feather_esp32.ini +++ b/board_feather_esp32.ini @@ -5,7 +5,7 @@ board = featheresp32 framework = arduino build_flags = -DARDUINO_FEATHER_ESP32 ${custom.variant_flags} - shee-DBLUETOOTH_ENABLED + -DBLUETOOTH_ENABLED ; change MCU frequency board_build.f_cpu = 240000000L extra_scripts = pre:../pio_scripts/renameFw.py From d7acd3b9abfd57088202485603816f68f654e5f6 Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Tue, 22 Jul 2025 15:06:40 -0700 Subject: [PATCH 06/22] Initial Wireless Off Testing --- EmotiBit.cpp | 143 ++++++++-------- EmotiBit.h | 9 +- EmotiBitBluetooth.cpp | 157 +++++++++++++++--- EmotiBitBluetooth.h | 22 ++- .../EmotiBit_stock_firmware.ino | 28 +++- board_feather_esp32.ini | 1 - 6 files changed, 263 insertions(+), 97 deletions(-) diff --git a/EmotiBit.cpp b/EmotiBit.cpp index 6329a901..52fb92dd 100644 --- a/EmotiBit.cpp +++ b/EmotiBit.cpp @@ -455,6 +455,13 @@ uint8_t EmotiBit::setup(String firmwareVariant) while (!Serial.available() && millis() - now < 2000) { +#ifdef ARDUINO_FEATHER_ESP32 + if (digitalRead(buttonPin)) { + Serial.println("Bluetooth Enabled"); + _enableBluetooth = true; + break; + } +#endif // ARDUINO_FEATHER_ESP32 } #ifdef ADAFRUIT_FEATHER_M0 AdcCorrection::AdcCorrectionValues adcCorrectionValues; @@ -953,17 +960,17 @@ uint8_t EmotiBit::setup(String firmwareVariant) sleep(true); } - if (_emotiBitBluetooth.begin(emotibitDeviceId)) + if (_enableBluetooth == true) { - // Bluetooth setup + #ifdef ARDUINO_FEATHER_ESP32 setPowerMode(PowerMode::BLUETOOTH); - Serial.println("Bluetooth setup completed"); - //nameSdCardFile(); + #endif // ARDUINO_FEATHER_ESP32 } - else{ - Serial.println("Bluetooth setup failed"); //TODO can remove this in PR + + else + { #ifdef ARDUINO_FEATHER_ESP32 - esp_bt_controller_disable(); + esp_bt_controller_disable(); #endif //WiFi Setup; Serial.print("\nSetting up WiFi\n"); @@ -1515,8 +1522,11 @@ void EmotiBit::parseIncomingControlPackets(String &controlPackets, uint16_t &pac static EmotiBitPacket::Header header; int16_t dataStartChar = 0; //use the following + #ifdef ARDUINO_FEATHER_ESP32 while (_emotiBitWiFi.readControl(packet) > 0 || _emotiBitBluetooth.readControl(packet) > 0) - //while (_emotiBitWiFi.readControl(packet) > 0) + #else + while (_emotiBitWiFi.readControl(packet) > 0) + #endif //ARDUINO_FEATHER_ESP32 { Serial.println(packet); dataStartChar = EmotiBitPacket::getHeader(packet, header); @@ -3218,33 +3228,61 @@ void EmotiBit::readSensors() led.setState(EmotiBitLedController::Led::YELLOW, true); } //new if statment to check if we are in powermode - if (getPowerMode() == PowerMode::BLUETOOTH){ + + if (getPowerMode() == PowerMode::BLUETOOTH) { +#ifdef ARDUINO_FEATHER_ESP32 // Bluetooth connected status LED - if (_emotiBitBluetooth.deviceConnected){ + if (_emotiBitBluetooth.deviceConnected) { led.setState(EmotiBitLedController::Led::BLUE, true); } else { // blink LED static unsigned long onTime = 125; // msec static unsigned long totalTime = 250; // msec changed to 250 - static bool wifiConnectedBlinkState = false; + static bool bleConnectedBlinkState = false; - static unsigned long wifiConnBlinkTimer = millis(); + static unsigned long bleConnBlinkTimer = millis(); unsigned long timeNow = millis(); - if (timeNow - wifiConnBlinkTimer < onTime) + if (timeNow - bleConnBlinkTimer < onTime) { led.setState(EmotiBitLedController::Led::BLUE, true); } - else if (timeNow - wifiConnBlinkTimer < totalTime) + else if (timeNow - bleConnBlinkTimer < totalTime) { led.setState(EmotiBitLedController::Led::BLUE, false); } else { - wifiConnBlinkTimer = timeNow; + bleConnBlinkTimer = timeNow; } - } + } + // Battery LED + if (battIndicationSeq) + { + led.setState(EmotiBitLedController::Led::YELLOW, true); + } + else + { + led.setState(EmotiBitLedController::Led::YELLOW, false); + } + + // Recording status LED + if (_sdWrite) + { + static uint32_t recordBlinkDuration = millis(); + if (millis() - recordBlinkDuration >= 500) + { + led.setState(EmotiBitLedController::Led::RED, !led.getState(EmotiBitLedController::Led::RED)); + recordBlinkDuration = millis(); + } + } + else if (!_sdWrite && led.getState(EmotiBitLedController::Led::RED) == true) + { + led.setState(EmotiBitLedController::Led::RED, false); + } + +#endif //ARDUINO_FEATHER_ESP32 } else { @@ -3503,7 +3541,9 @@ void EmotiBit::sendData() _emotiBitWiFi.sendData(s); } if (getPowerMode() == PowerMode::BLUETOOTH) { + #ifdef ARDUINO_FEATHER_ESP32 _emotiBitBluetooth.sendData(s); + #endif //ARDUINO_FEATHER_ESP32 } writeSdCardMessage(s); firstIndex = lastIndex + 1; @@ -3544,7 +3584,9 @@ void EmotiBit::sendData() _emotiBitWiFi.sendData(s); } if (getPowerMode() == PowerMode::BLUETOOTH) { + #ifdef ARDUINO_FEATHER_ESP32 _emotiBitBluetooth.sendData(s); + #endif //ARDUINO_FEATHER_ESP32 } writeSdCardMessage(s); firstIndex = lastIndex + 1; @@ -3830,12 +3872,29 @@ void EmotiBit::setPowerMode(PowerMode mode) else if (getPowerMode() == PowerMode::WIRELESS_OFF) { Serial.println("PowerMode::WIRELESS_OFF"); + + if (_enableBluetooth == true) + { +#ifdef ARDUINO_FEATHER_ESP32 + _emotiBitBluetooth.end(); +// _enableBluetooth = false; +#endif //ARDUINO_FEATHER_ESP32 + } + else + { _emotiBitWiFi.end(); + } } else if (getPowerMode() == PowerMode::BLUETOOTH) { - Serial.println("PowerMode::BLUETOOTH"); - //TODO: we can turn on/off disable bluetooth here and wifi +#ifdef ARDUINO_FEATHER_ESP32 + if (_emotiBitBluetooth.isOff()) + { + Serial.println("PowerMode::BLUETOOTH"); + _emotiBitBluetooth.begin(emotibitDeviceId); + } + +#endif //ARDUINO_FEATHER_ESP32 } else if (getPowerMode() == PowerMode::HIBERNATE) { @@ -4785,51 +4844,3 @@ void EmotiBit::restartMcu() NVIC_SystemReset(); #endif } - -//unneeded can be removed -void EmotiBit::nameSdCardFile() { - int maxSuffix = -1; - File dir = SD.open("/"); - while (true) { - File entry = dir.openNextFile(); - if (!entry) break; - String name = entry.name(); - if (name.startsWith("BLUETOOTH_") && name.endsWith(".csv")) { - int underscore = name.lastIndexOf('_'); - int dot = name.lastIndexOf('.'); - if (underscore != -1 && dot != -1 && dot > underscore + 1) { - String numStr = name.substring(underscore + 1, dot); - int num = numStr.toInt(); - if (num > maxSuffix) maxSuffix = num; - } - } - entry.close(); - } - int nextSuffix = maxSuffix + 1; - char filename[32]; - snprintf(filename, sizeof(filename), "/BLUETOOTH_%04d.csv", nextSuffix); - _sdCardFilename = String(filename); - Serial.print("Creating SD card file: "); - Serial.println(_sdCardFilename); - - /* - // Write test line to the file - File testFile = SD.open(_sdCardFilename, FILE_WRITE); - if (testFile) { - testFile.print("test working for "); - testFile.println(nextSuffix); - testFile.close(); - Serial.println("Test line written to SD card file."); - } else { - Serial.println("Failed to create SD card file!"); - }*/ - // Open the file for writing and set _sdWrite - _dataFile = SD.open(_sdCardFilename, FILE_WRITE); - if (_dataFile) { - _sdWrite = true; - Serial.println("SD card file opened."); - } else { - _sdWrite = false; - Serial.println("Failed to open SD card"); - } -} \ No newline at end of file diff --git a/EmotiBit.h b/EmotiBit.h index 5a73d0d2..df5f1222 100644 --- a/EmotiBit.h +++ b/EmotiBit.h @@ -17,12 +17,11 @@ #include "DoubleBufferFloat.h" #include #include "EmotiBitWiFi.h" -#include "EmotiBitBluetooth.h" #include #ifdef ARDUINO_FEATHER_ESP32 #include #include "driver/adc.h" -#include +#include //consider moving into bluetooth #else #include #include @@ -40,6 +39,9 @@ #include "FileTransferManager.h" #endif #include "EmotiBitConfigManager.h" +#ifdef ARDUINO_FEATHER_ESP32 +#include "EmotiBitBluetooth.h" +#endif class EmotiBit { @@ -281,7 +283,9 @@ class EmotiBit { MLX90632 thermopile; EmotiBitEda emotibitEda; EmotiBitNvmController _emotibitNvmController; + #ifdef ARDUINO_FEATHER_ESP32 EmotiBitBluetooth _emotiBitBluetooth; + #endif //ARDUINO_FEATHER_ESP32 #ifdef ARDUINO_FEATHER_ESP32 FileTransferManager _fileTransferManager; #endif @@ -433,6 +437,7 @@ class EmotiBit { DataType _serialData = DataType::length; volatile bool buttonPressed = false; bool startBufferOverflowTest = false; + bool _enableBluetooth = false; void setupFailed(const String failureMode, int buttonPin = -1, bool configFileError = false); bool setupSdCard(bool loadConfig = true); diff --git a/EmotiBitBluetooth.cpp b/EmotiBitBluetooth.cpp index b4173cff..6af23313 100644 --- a/EmotiBitBluetooth.cpp +++ b/EmotiBitBluetooth.cpp @@ -1,15 +1,24 @@ +#ifdef ARDUINO_FEATHER_ESP32 #include "EmotiBitBluetooth.h" -//NOTE, remove ifdefs for bluetooth when we can manually choose to enable/disable bluetooth - - uint8_t EmotiBitBluetooth::begin(const String& emotibitDeviceId) { + if (pServer) + { + + EmotiBitBluetooth::reconnect(); + Serial.println("Bluetooth already initialized, reconnecting..."); + return 1; // Success + } + //IF BLUETOOTH -#ifdef BLUETOOTH_ENABLED +//#ifdef BLUETOOTH_ENABLED _emotibitDeviceId = emotibitDeviceId; + + //btStart(); Serial.println("Bluetooth tag detected, turning on bluetooth."); BLEDevice::init(("EmotiBit: " + _emotibitDeviceId).c_str()); + pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks(this)); BLEService* pService = pServer->createService(EMOTIBIT_SERVICE_UUID); @@ -25,32 +34,39 @@ uint8_t EmotiBitBluetooth::begin(const String& emotibitDeviceId) //pSyncRxCharacteristic = pService->createCharacteristic(EMOTIBIT_SYNC_RX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE); //pSyncRxCharacteristic->setCallbacks(new MyCallbacks()); - pService->start(); + pServer->getAdvertising()->start(); + //_bluetoothOff = false; //was true?? + _bluetoothReconnect = true; // Allow reconnection after disconnection Serial.println("BLE advertising started"); + return 1; -#else - Serial.println("Bluetooth disabled."); - return 0; -#endif +//#else +// Serial.println("Bluetooth disabled."); +// return 0; +//#endif } //ToDO: consider splitting this function into two: one for sending data and another for sending sync data void EmotiBitBluetooth::MyServerCallbacks::onConnect(BLEServer* pServer) { server -> deviceConnected = true; - Serial.println("BLE client connected"); - + Serial.println("BLE client connected"); } void EmotiBitBluetooth::MyServerCallbacks::onDisconnect(BLEServer* pServer) { + server -> deviceConnected = false; Serial.println("BLE client disconnected"); - //need to restart advertising to allow new connections after disconnection - pServer->getAdvertising()->start(); - Serial.println("Restarted BLE advertising"); + //need to restart advertising to allow new connections after disconnection if accidental + //ToDo gracefully handle this + if (server -> _bluetoothReconnect) + { + server -> reconnect(); + Serial.println("Restarted BLE advertising"); + } } @@ -58,8 +74,8 @@ void EmotiBitBluetooth::MyCallbacks::onWrite(BLECharacteristic *pCharacteristic) { std::string rxValue = pCharacteristic->getValue(); if (rxValue.length() > 0) { - Serial.print("Received: "); - Serial.println(rxValue.c_str()); + //Serial.print("Received: "); + //Serial.println(rxValue.c_str()); } } @@ -68,11 +84,13 @@ void EmotiBitBluetooth::setDeviceId(const String emotibitDeviceId) _emotibitDeviceId = emotibitDeviceId; } +/* void EmotiBitBluetooth::sendData(const String &message) { if (deviceConnected) { pDataTxCharacteristic->setValue(message.c_str()); pDataTxCharacteristic->notify(); + //Serial.print("Sent: "); //Serial.println(message.c_str()); } @@ -80,11 +98,49 @@ void EmotiBitBluetooth::sendData(const String &message) Serial.println("unable to send data."); } } +*/ + +void EmotiBitBluetooth::sendData(const String &message) +{ + if (deviceConnected) { + if (pDataTxCharacteristic == nullptr) { + //Serial.println("ERROR: pDataTxCharacteristic is NULL!"); + return; + } + + //Serial.print("BLE TX: Message length="); + //Serial.print(message.length()); + + // Set the value + pDataTxCharacteristic->setValue(message.c_str()); + + // Call notify - note: doesn't return success/failure status + pDataTxCharacteristic->notify(); + + // Check descriptor status + BLEDescriptor* p2902 = pDataTxCharacteristic->getDescriptorByUUID(BLEUUID((uint16_t)0x2902)); + if (p2902) { + const uint8_t* val = p2902->getValue(); + if (val) { + //Serial.print(" | Notifications enabled="); + //Serial.print((val[0] & 0x01) ? "YES" : "NO"); + } + } + + //Serial.print(" | Char ptr=0x"); + //Serial.print((uint32_t)pDataTxCharacteristic, HEX); + //Serial.print(" | Message: "); + //Serial.println(message.c_str()); + } + else { + Serial.println("unable to send data: deviceConnected=false"); + } +} uint8_t EmotiBitBluetooth::readControl(String& packet) { uint8_t numPackets = 0; -#ifdef BLUETOOTH_ENABLED +//#ifdef BLUETOOTH_ENABLED packet = ""; if (deviceConnected) { @@ -92,8 +148,8 @@ uint8_t EmotiBitBluetooth::readControl(String& packet) std::string rxValue = pDataRxCharacteristic->getValue(); if (!rxValue.empty()) { - Serial.print("Received: "); - Serial.println(rxValue.c_str()); + //Serial.print("Received: "); + //Serial.println(rxValue.c_str()); _receivedControlMessage += String(rxValue.c_str()); // *** CLEAR THE CHAR VALUE SO WE DON’T REUSE IT *** @@ -126,6 +182,65 @@ uint8_t EmotiBitBluetooth::readControl(String& packet) } } } -#endif +//#endif return numPackets; -} \ No newline at end of file +} + +bool EmotiBitBluetooth::isOff() +{ + return _bluetoothOff; +} + +/* +void EmotiBitBluetooth::end() +{ + //if (pServer && deviceConnected) { + // // Disconnect all connected clients + // pServer->disconnect(0); // 0 = first client, or use the correct connection ID if you track it + deviceConnected = false; + // Serial.println("BLE client disconnected by end()"); + //} + if (pServer) { + pServer->getAdvertising()->stop(); + Serial.println("BLE advertising stopped"); + } + + //esp_bt_controller_disable(); + + //pServer = nullptr; + //pDataTxCharacteristic = nullptr; + //pDataRxCharacteristic = nullptr; + _bluetoothOff = true; + _bluetoothReconnect = false; // No longer allow reconnection + //btStop(); + //esp_bt_controller_deinit(); +} +*/ +void EmotiBitBluetooth::end() +{ + if (pServer && deviceConnected) + { + // gracefully tear down the old connection + pServer->disconnect(0); + Serial.println("BLE client disconnected by end()"); + } + if (pServer) + { + pServer->getAdvertising()->stop(); + Serial.println("BLE advertising stopped"); + } + _bluetoothOff = true; + _bluetoothReconnect = false; + // NOTE: do *not* touch deviceConnected here—let onDisconnect handle it +} + + +void EmotiBitBluetooth::reconnect() +{ + if (!pServer) return; + pServer->getAdvertising()->start(); + Serial.println("BLE advertising restarted after reconnect"); + _bluetoothOff = false; + _bluetoothReconnect = true; +} +#endif //ARDUINO_FEATHER_ESP32 \ No newline at end of file diff --git a/EmotiBitBluetooth.h b/EmotiBitBluetooth.h index 3527f6d5..02158903 100644 --- a/EmotiBitBluetooth.h +++ b/EmotiBitBluetooth.h @@ -13,6 +13,7 @@ BSD license, all text here must be included in any redistribution */ /**************************************************************************/ +#ifdef ARDUINO_FEATHER_ESP32 #pragma once /*! * @brief inclusions for BLE Device, Server, Utils, 2902, and Arduino @@ -25,6 +26,7 @@ #include "EmotiBitPacket.h" + #define EMOTIBIT_SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" #define EMOTIBIT_DATA_RX_CHARACTERISTIC_UUID "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" #define EMOTIBIT_DATA_TX_CHARACTERISTIC_UUID "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" @@ -48,7 +50,8 @@ class EmotiBitBluetooth { bool deviceConnected = false; ///boolean to check if device is connected String _emotibitDeviceId = ""; ///string to hold device id String _receivedControlMessage = ""; - + bool _bluetoothOff = true; + bool _bluetoothReconnect = false; /*! * @brief Server callbacks for connections */ @@ -97,5 +100,22 @@ class EmotiBitBluetooth { //void update();for when we sync data over BLE //move to emotibit //void sdCardFileNaming(); for when we choose bluetooth and there is no rb start time + + /*! + * @brief Ends the BLE connection + */ + void end(); + + /*! + * @brief Checks if the Bluetooth is off + * @return if Bluetooth is off, returns true, otherwise false + */ + bool isOff(); + + /*! + + */ + void reconnect(); }; +#endif //ARDUINO_FEATHER_ESP32 \ No newline at end of file diff --git a/EmotiBit_stock_firmware/EmotiBit_stock_firmware.ino b/EmotiBit_stock_firmware/EmotiBit_stock_firmware.ino index c9fbebe0..64c45285 100644 --- a/EmotiBit_stock_firmware/EmotiBit_stock_firmware.ino +++ b/EmotiBit_stock_firmware/EmotiBit_stock_firmware.ino @@ -10,16 +10,32 @@ float data[dataSize]; void onShortButtonPress() { - // toggle wifi on/off - if (emotibit.getPowerMode() == EmotiBit::PowerMode::NORMAL_POWER) + if (emotibit._enableBluetooth == true) { - emotibit.setPowerMode(EmotiBit::PowerMode::WIRELESS_OFF); - Serial.println("PowerMode::WIRELESS_OFF"); + if (emotibit.getPowerMode() == EmotiBit::PowerMode::BLUETOOTH) + { + emotibit.setPowerMode(EmotiBit::PowerMode::WIRELESS_OFF); + Serial.println("PowerMode::WIRELESS_OFF"); + } + else + { + emotibit.setPowerMode(EmotiBit::PowerMode::BLUETOOTH); + Serial.println("PowerMode::BLUETOOTH"); + } } else { - emotibit.setPowerMode(EmotiBit::PowerMode::NORMAL_POWER); - Serial.println("PowerMode::NORMAL_POWER"); + // toggle wifi on/off + if (emotibit.getPowerMode() == EmotiBit::PowerMode::NORMAL_POWER) + { + emotibit.setPowerMode(EmotiBit::PowerMode::WIRELESS_OFF); + Serial.println("PowerMode::WIRELESS_OFF"); + } + else + { + emotibit.setPowerMode(EmotiBit::PowerMode::NORMAL_POWER); + Serial.println("PowerMode::NORMAL_POWER"); + } } } diff --git a/board_feather_esp32.ini b/board_feather_esp32.ini index 858fefa6..31a4310e 100644 --- a/board_feather_esp32.ini +++ b/board_feather_esp32.ini @@ -5,7 +5,6 @@ board = featheresp32 framework = arduino build_flags = -DARDUINO_FEATHER_ESP32 ${custom.variant_flags} - -DBLUETOOTH_ENABLED ; change MCU frequency board_build.f_cpu = 240000000L extra_scripts = pre:../pio_scripts/renameFw.py From 0a735a53061786a2bc7d878f49aa96912f0b7754 Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Wed, 30 Jul 2025 09:04:44 -0700 Subject: [PATCH 07/22] removed gitIgnore --- EmotiBit_stock_firmware/.gitignore | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 EmotiBit_stock_firmware/.gitignore diff --git a/EmotiBit_stock_firmware/.gitignore b/EmotiBit_stock_firmware/.gitignore deleted file mode 100644 index 89cc49cb..00000000 --- a/EmotiBit_stock_firmware/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -.pio -.vscode/.browse.c_cpp.db* -.vscode/c_cpp_properties.json -.vscode/launch.json -.vscode/ipch From e58e16953c7980b81d8a6b37b7671d9bd4fec449 Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Thu, 31 Jul 2025 08:58:14 -0700 Subject: [PATCH 08/22] Code cleanup --- EmotiBitBluetooth.cpp | 102 +++++++++++++++--------------------------- EmotiBitBluetooth.h | 7 ++- 2 files changed, 43 insertions(+), 66 deletions(-) diff --git a/EmotiBitBluetooth.cpp b/EmotiBitBluetooth.cpp index 6af23313..41af099d 100644 --- a/EmotiBitBluetooth.cpp +++ b/EmotiBitBluetooth.cpp @@ -8,18 +8,21 @@ uint8_t EmotiBitBluetooth::begin(const String& emotibitDeviceId) EmotiBitBluetooth::reconnect(); Serial.println("Bluetooth already initialized, reconnecting..."); - return 1; // Success + return 0; // Success } -//IF BLUETOOTH -//#ifdef BLUETOOTH_ENABLED _emotibitDeviceId = emotibitDeviceId; - //btStart(); Serial.println("Bluetooth tag detected, turning on bluetooth."); BLEDevice::init(("EmotiBit: " + _emotibitDeviceId).c_str()); pServer = BLEDevice::createServer(); + + if (!pServer) { + Serial.println("ERROR: Failed to create BLE server"); + return 1; + } + pServer->setCallbacks(new MyServerCallbacks(this)); BLEService* pService = pServer->createService(EMOTIBIT_SERVICE_UUID); @@ -36,19 +39,13 @@ uint8_t EmotiBitBluetooth::begin(const String& emotibitDeviceId) //pSyncRxCharacteristic->setCallbacks(new MyCallbacks()); pService->start(); - pServer->getAdvertising()->start(); - //_bluetoothOff = false; //was true?? + EmotiBitBluetooth::startAdvertising(); _bluetoothReconnect = true; // Allow reconnection after disconnection Serial.println("BLE advertising started"); - return 1; -//#else -// Serial.println("Bluetooth disabled."); -// return 0; -//#endif + return 0; } -//ToDO: consider splitting this function into two: one for sending data and another for sending sync data void EmotiBitBluetooth::MyServerCallbacks::onConnect(BLEServer* pServer) { server -> deviceConnected = true; @@ -60,8 +57,7 @@ void EmotiBitBluetooth::MyServerCallbacks::onDisconnect(BLEServer* pServer) server -> deviceConnected = false; Serial.println("BLE client disconnected"); - //need to restart advertising to allow new connections after disconnection if accidental - //ToDo gracefully handle this + //need to restart advertising to allow new connections after disconnection if accidentally disconnected if (server -> _bluetoothReconnect) { server -> reconnect(); @@ -69,7 +65,6 @@ void EmotiBitBluetooth::MyServerCallbacks::onDisconnect(BLEServer* pServer) } } - void EmotiBitBluetooth::MyCallbacks::onWrite(BLECharacteristic *pCharacteristic) { std::string rxValue = pCharacteristic->getValue(); @@ -84,22 +79,6 @@ void EmotiBitBluetooth::setDeviceId(const String emotibitDeviceId) _emotibitDeviceId = emotibitDeviceId; } -/* -void EmotiBitBluetooth::sendData(const String &message) -{ - if (deviceConnected) { - pDataTxCharacteristic->setValue(message.c_str()); - pDataTxCharacteristic->notify(); - - //Serial.print("Sent: "); - //Serial.println(message.c_str()); - } - else { - Serial.println("unable to send data."); - } -} -*/ - void EmotiBitBluetooth::sendData(const String &message) { if (deviceConnected) { @@ -140,7 +119,6 @@ void EmotiBitBluetooth::sendData(const String &message) uint8_t EmotiBitBluetooth::readControl(String& packet) { uint8_t numPackets = 0; -//#ifdef BLUETOOTH_ENABLED packet = ""; if (deviceConnected) { @@ -152,7 +130,7 @@ uint8_t EmotiBitBluetooth::readControl(String& packet) //Serial.println(rxValue.c_str()); _receivedControlMessage += String(rxValue.c_str()); - // *** CLEAR THE CHAR VALUE SO WE DON’T REUSE IT *** + //CLEAR THE CHAR VALUE SO WE DON’T REUSE IT pDataRxCharacteristic->setValue(""); } @@ -182,7 +160,6 @@ uint8_t EmotiBitBluetooth::readControl(String& packet) } } } -//#endif return numPackets; } @@ -191,36 +168,12 @@ bool EmotiBitBluetooth::isOff() return _bluetoothOff; } -/* -void EmotiBitBluetooth::end() -{ - //if (pServer && deviceConnected) { - // // Disconnect all connected clients - // pServer->disconnect(0); // 0 = first client, or use the correct connection ID if you track it - deviceConnected = false; - // Serial.println("BLE client disconnected by end()"); - //} - if (pServer) { - pServer->getAdvertising()->stop(); - Serial.println("BLE advertising stopped"); - } - - //esp_bt_controller_disable(); - //pServer = nullptr; - //pDataTxCharacteristic = nullptr; - //pDataRxCharacteristic = nullptr; - _bluetoothOff = true; - _bluetoothReconnect = false; // No longer allow reconnection - //btStop(); - //esp_bt_controller_deinit(); -} -*/ void EmotiBitBluetooth::end() { if (pServer && deviceConnected) { - // gracefully tear down the old connection + //tear down the old connection pServer->disconnect(0); Serial.println("BLE client disconnected by end()"); } @@ -231,16 +184,35 @@ void EmotiBitBluetooth::end() } _bluetoothOff = true; _bluetoothReconnect = false; - // NOTE: do *not* touch deviceConnected here—let onDisconnect handle it } void EmotiBitBluetooth::reconnect() { - if (!pServer) return; - pServer->getAdvertising()->start(); - Serial.println("BLE advertising restarted after reconnect"); - _bluetoothOff = false; - _bluetoothReconnect = true; + if (pServer) + { + EmotiBitBluetooth::startAdvertising(); + Serial.println("BLE advertising restarted after reconnect"); + _bluetoothOff = false; + _bluetoothReconnect = true; + } + else + { + Serial.println("ERROR: pServer is NULL, cannot reconnect"); + } +} + +void EmotiBitBluetooth::startAdvertising() +{ + if (pServer) + { + pServer->getAdvertising()->start(); + Serial.println("BLE advertising started"); + } + else + { + Serial.println("ERROR: pServer is NULL, cannot start advertising"); + } } + #endif //ARDUINO_FEATHER_ESP32 \ No newline at end of file diff --git a/EmotiBitBluetooth.h b/EmotiBitBluetooth.h index 02158903..e46c16ac 100644 --- a/EmotiBitBluetooth.h +++ b/EmotiBitBluetooth.h @@ -113,9 +113,14 @@ class EmotiBitBluetooth { bool isOff(); /*! - + * @brief Reconnects the BLE server if disconnected */ void reconnect(); + + /*! + * @brief Starts Advertising + */ + void startAdvertising(); }; #endif //ARDUINO_FEATHER_ESP32 \ No newline at end of file From a70b0c9f5704b37ed8d8a8bd47f66313e4eeebb0 Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Thu, 31 Jul 2025 09:10:49 -0700 Subject: [PATCH 09/22] tab fixes --- EmotiBitBluetooth.cpp | 292 +++++++++++++++++++++--------------------- EmotiBitBluetooth.h | 162 +++++++++++------------ 2 files changed, 226 insertions(+), 228 deletions(-) diff --git a/EmotiBitBluetooth.cpp b/EmotiBitBluetooth.cpp index 41af099d..14ec7f35 100644 --- a/EmotiBitBluetooth.cpp +++ b/EmotiBitBluetooth.cpp @@ -3,75 +3,74 @@ uint8_t EmotiBitBluetooth::begin(const String& emotibitDeviceId) { - if (pServer) - { - - EmotiBitBluetooth::reconnect(); - Serial.println("Bluetooth already initialized, reconnecting..."); - return 0; // Success - } - - _emotibitDeviceId = emotibitDeviceId; + if (pServer) + { + EmotiBitBluetooth::reconnect(); + Serial.println("Bluetooth already initialized, reconnecting..."); + return 0; // Success + } + +_emotibitDeviceId = emotibitDeviceId; - Serial.println("Bluetooth tag detected, turning on bluetooth."); - BLEDevice::init(("EmotiBit: " + _emotibitDeviceId).c_str()); + Serial.println("Bluetooth tag detected, turning on bluetooth."); + BLEDevice::init(("EmotiBit: " + _emotibitDeviceId).c_str()); - pServer = BLEDevice::createServer(); + pServer = BLEDevice::createServer(); - if (!pServer) { - Serial.println("ERROR: Failed to create BLE server"); - return 1; - } + if (!pServer) { + Serial.println("ERROR: Failed to create BLE server"); + return 1; + } - pServer->setCallbacks(new MyServerCallbacks(this)); - BLEService* pService = pServer->createService(EMOTIBIT_SERVICE_UUID); + pServer->setCallbacks(new MyServerCallbacks(this)); + BLEService* pService = pServer->createService(EMOTIBIT_SERVICE_UUID); - pDataTxCharacteristic = pService->createCharacteristic(EMOTIBIT_DATA_TX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_NOTIFY); - pDataTxCharacteristic->addDescriptor(new BLE2902()); + pDataTxCharacteristic = pService->createCharacteristic(EMOTIBIT_DATA_TX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_NOTIFY); + pDataTxCharacteristic->addDescriptor(new BLE2902()); - pDataRxCharacteristic = pService->createCharacteristic(EMOTIBIT_DATA_RX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE); - pDataRxCharacteristic->setCallbacks(new MyCallbacks()); + pDataRxCharacteristic = pService->createCharacteristic(EMOTIBIT_DATA_RX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE); + pDataRxCharacteristic->setCallbacks(new MyCallbacks()); - //pSyncTxCharacteristic = pService->createCharacteristic(EMOTIBIT_SYNC_TX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_NOTIFY); - //pSyncTxCharacteristic->addDescriptor(new BLE2902()); + //pSyncTxCharacteristic = pService->createCharacteristic(EMOTIBIT_SYNC_TX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_NOTIFY); + //pSyncTxCharacteristic->addDescriptor(new BLE2902()); - //pSyncRxCharacteristic = pService->createCharacteristic(EMOTIBIT_SYNC_RX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE); - //pSyncRxCharacteristic->setCallbacks(new MyCallbacks()); - pService->start(); + //pSyncRxCharacteristic = pService->createCharacteristic(EMOTIBIT_SYNC_RX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE); + //pSyncRxCharacteristic->setCallbacks(new MyCallbacks()); + pService->start(); - EmotiBitBluetooth::startAdvertising(); - _bluetoothReconnect = true; // Allow reconnection after disconnection - Serial.println("BLE advertising started"); + EmotiBitBluetooth::startAdvertising(); + _bluetoothReconnect = true; // Allow reconnection after disconnection + Serial.println("BLE advertising started"); - return 0; + return 0; } void EmotiBitBluetooth::MyServerCallbacks::onConnect(BLEServer* pServer) { - server -> deviceConnected = true; - Serial.println("BLE client connected"); + server -> deviceConnected = true; + Serial.println("BLE client connected"); } void EmotiBitBluetooth::MyServerCallbacks::onDisconnect(BLEServer* pServer) { - server -> deviceConnected = false; - Serial.println("BLE client disconnected"); - //need to restart advertising to allow new connections after disconnection if accidentally disconnected - if (server -> _bluetoothReconnect) - { - server -> reconnect(); - Serial.println("Restarted BLE advertising"); - } + server -> deviceConnected = false; + Serial.println("BLE client disconnected"); + //need to restart advertising to allow new connections after disconnection if accidentally disconnected + if (server -> _bluetoothReconnect) + { + server -> reconnect(); + Serial.println("Restarted BLE advertising"); + } } void EmotiBitBluetooth::MyCallbacks::onWrite(BLECharacteristic *pCharacteristic) { - std::string rxValue = pCharacteristic->getValue(); - if (rxValue.length() > 0) { - //Serial.print("Received: "); - //Serial.println(rxValue.c_str()); - } + std::string rxValue = pCharacteristic->getValue(); + if (rxValue.length() > 0) { + //Serial.print("Received: "); + //Serial.println(rxValue.c_str()); + } } void EmotiBitBluetooth::setDeviceId(const String emotibitDeviceId) @@ -81,86 +80,85 @@ void EmotiBitBluetooth::setDeviceId(const String emotibitDeviceId) void EmotiBitBluetooth::sendData(const String &message) { - if (deviceConnected) { - if (pDataTxCharacteristic == nullptr) { - //Serial.println("ERROR: pDataTxCharacteristic is NULL!"); - return; + if (deviceConnected) { + if (pDataTxCharacteristic == nullptr) { + //Serial.println("ERROR: pDataTxCharacteristic is NULL!"); + return; + } + + //Serial.print("BLE TX: Message length="); + //Serial.print(message.length()); + + // Set the value + pDataTxCharacteristic->setValue(message.c_str()); + + // Call notify - note: doesn't return success/failure status + pDataTxCharacteristic->notify(); + + // Check descriptor status + BLEDescriptor* p2902 = pDataTxCharacteristic->getDescriptorByUUID(BLEUUID((uint16_t)0x2902)); + if (p2902) { + const uint8_t* val = p2902->getValue(); + if (val) { + //Serial.print(" | Notifications enabled="); + //Serial.print((val[0] & 0x01) ? "YES" : "NO"); + } + } + + //Serial.print(" | Char ptr=0x"); + //Serial.print((uint32_t)pDataTxCharacteristic, HEX); + //Serial.print(" | Message: "); + //Serial.println(message.c_str()); } - - //Serial.print("BLE TX: Message length="); - //Serial.print(message.length()); - - // Set the value - pDataTxCharacteristic->setValue(message.c_str()); - - // Call notify - note: doesn't return success/failure status - pDataTxCharacteristic->notify(); - - // Check descriptor status - BLEDescriptor* p2902 = pDataTxCharacteristic->getDescriptorByUUID(BLEUUID((uint16_t)0x2902)); - if (p2902) { - const uint8_t* val = p2902->getValue(); - if (val) { - //Serial.print(" | Notifications enabled="); - //Serial.print((val[0] & 0x01) ? "YES" : "NO"); - } + else { + Serial.println("unable to send data: deviceConnected=false"); } - - //Serial.print(" | Char ptr=0x"); - //Serial.print((uint32_t)pDataTxCharacteristic, HEX); - //Serial.print(" | Message: "); - //Serial.println(message.c_str()); - } - else { - Serial.println("unable to send data: deviceConnected=false"); - } } uint8_t EmotiBitBluetooth::readControl(String& packet) { - uint8_t numPackets = 0; - packet = ""; - if (deviceConnected) - { - - std::string rxValue = pDataRxCharacteristic->getValue(); - if (!rxValue.empty()) + uint8_t numPackets = 0; + packet = ""; + if (deviceConnected) { - //Serial.print("Received: "); - //Serial.println(rxValue.c_str()); - _receivedControlMessage += String(rxValue.c_str()); - - //CLEAR THE CHAR VALUE SO WE DON’T REUSE IT - pDataRxCharacteristic->setValue(""); - } + std::string rxValue = pDataRxCharacteristic->getValue(); + if (!rxValue.empty()) + { + //Serial.print("Received: "); + //Serial.println(rxValue.c_str()); + _receivedControlMessage += String(rxValue.c_str()); - String tempPacket = ""; - while (_receivedControlMessage.length() > 0) - { - int c = _receivedControlMessage[0]; - _receivedControlMessage.remove(0, 1); - - if (c == (int)EmotiBitPacket::PACKET_DELIMITER_CSV) - { - numPackets++; - packet = tempPacket; - tempPacket = ""; - _receivedControlMessage = ""; - return numPackets; - } - else - { - if (c == 0) { - // Throw out null term + //CLEAR THE CHAR VALUE SO WE DON’T REUSE IT + pDataRxCharacteristic->setValue(""); } - else + + String tempPacket = ""; + while (_receivedControlMessage.length() > 0) { - tempPacket += (char)c; + int c = _receivedControlMessage[0]; + _receivedControlMessage.remove(0, 1); + + if (c == (int)EmotiBitPacket::PACKET_DELIMITER_CSV) + { + numPackets++; + packet = tempPacket; + tempPacket = ""; + _receivedControlMessage = ""; + return numPackets; + } + else + { + if (c == 0) { + // Throw out null term + } + else + { + tempPacket += (char)c; + } + } } - } } - } - return numPackets; + return numPackets; } bool EmotiBitBluetooth::isOff() @@ -171,48 +169,48 @@ bool EmotiBitBluetooth::isOff() void EmotiBitBluetooth::end() { - if (pServer && deviceConnected) - { - //tear down the old connection - pServer->disconnect(0); - Serial.println("BLE client disconnected by end()"); - } - if (pServer) - { - pServer->getAdvertising()->stop(); - Serial.println("BLE advertising stopped"); - } - _bluetoothOff = true; - _bluetoothReconnect = false; + if (pServer && deviceConnected) + { + //tear down the old connection + pServer->disconnect(0); + Serial.println("BLE client disconnected by end()"); + } + if (pServer) + { + pServer->getAdvertising()->stop(); + Serial.println("BLE advertising stopped"); + } + _bluetoothOff = true; + _bluetoothReconnect = false; } void EmotiBitBluetooth::reconnect() { - if (pServer) - { - EmotiBitBluetooth::startAdvertising(); - Serial.println("BLE advertising restarted after reconnect"); - _bluetoothOff = false; - _bluetoothReconnect = true; - } - else - { - Serial.println("ERROR: pServer is NULL, cannot reconnect"); - } + if (pServer) + { + EmotiBitBluetooth::startAdvertising(); + Serial.println("BLE advertising restarted after reconnect"); + _bluetoothOff = false; + _bluetoothReconnect = true; + } + else + { + Serial.println("ERROR: pServer is NULL, cannot reconnect"); + } } void EmotiBitBluetooth::startAdvertising() { - if (pServer) - { - pServer->getAdvertising()->start(); - Serial.println("BLE advertising started"); - } - else - { - Serial.println("ERROR: pServer is NULL, cannot start advertising"); - } + if (pServer) + { + pServer->getAdvertising()->start(); + Serial.println("BLE advertising started"); + } + else + { + Serial.println("ERROR: pServer is NULL, cannot start advertising"); + } } #endif //ARDUINO_FEATHER_ESP32 \ No newline at end of file diff --git a/EmotiBitBluetooth.h b/EmotiBitBluetooth.h index e46c16ac..5b37b035 100644 --- a/EmotiBitBluetooth.h +++ b/EmotiBitBluetooth.h @@ -39,88 +39,88 @@ * @brief Handles Bluetooth communication for EmotiBit. */ class EmotiBitBluetooth { - public: - BLEServer* pServer = nullptr; ///points to the server - - BLECharacteristic* pDataTxCharacteristic = nullptr; ///points to the data tx characteristic - BLECharacteristic* pDataRxCharacteristic = nullptr; ///points to the data rx characteristic - //BLECharacteristic* pSyncTxCharacteristic = nullptr; ///points to the sync tx characteristic - //BLECharacteristic* pSyncRxCharacteristic = nullptr; ///points to the sync rx characteristic - - bool deviceConnected = false; ///boolean to check if device is connected - String _emotibitDeviceId = ""; ///string to hold device id - String _receivedControlMessage = ""; - bool _bluetoothOff = true; - bool _bluetoothReconnect = false; - /*! - * @brief Server callbacks for connections - */ - class MyServerCallbacks: public BLEServerCallbacks { public: - MyServerCallbacks(EmotiBitBluetooth* server) : server(server) {} - void onConnect(BLEServer* pServer); - void onDisconnect(BLEServer* pServer); - private: - EmotiBitBluetooth* server; - }; - - /*! - * @brief Characteristic callbacks for data transfer - */ - class MyCallbacks : public BLECharacteristicCallbacks { - void onWrite(BLECharacteristic *pCharacteristic); - }; - - /*! - * @brief Initializes the BLE device and starts advertising - * @param emotibitDeviceId ID from setDeviceId - * @return 1 on success, 0 on failure - */ - //TO DO use int for error handling - uint8_t begin(const String& emotibitDeviceId); - - /*! - * @brief Sends data over BLE - * @param message data to be sent - */ - void sendData(const String &message); - - /*! - * @brief Checks if the device is connected to a BLE client - * @param emotibitDeviceId - */ - void setDeviceId(const String emotibitDeviceId); - - /*! - * @brief Reads control messages from the BLE characteristic - * @param packet the control message packet - */ - uint8_t readControl(String& packet); - - //void update();for when we sync data over BLE - //move to emotibit - //void sdCardFileNaming(); for when we choose bluetooth and there is no rb start time - - /*! - * @brief Ends the BLE connection - */ - void end(); - - /*! - * @brief Checks if the Bluetooth is off - * @return if Bluetooth is off, returns true, otherwise false - */ - bool isOff(); - - /*! - * @brief Reconnects the BLE server if disconnected - */ - void reconnect(); - - /*! - * @brief Starts Advertising - */ - void startAdvertising(); + BLEServer* pServer = nullptr; ///points to the server + + BLECharacteristic* pDataTxCharacteristic = nullptr; ///points to the data tx characteristic + BLECharacteristic* pDataRxCharacteristic = nullptr; ///points to the data rx characteristic + //BLECharacteristic* pSyncTxCharacteristic = nullptr; ///points to the sync tx characteristic + //BLECharacteristic* pSyncRxCharacteristic = nullptr; ///points to the sync rx characteristic + + bool deviceConnected = false; ///boolean to check if device is connected + String _emotibitDeviceId = ""; ///string to hold device id + String _receivedControlMessage = ""; + bool _bluetoothOff = true; + bool _bluetoothReconnect = false; + /*! + * @brief Server callbacks for connections + */ + class MyServerCallbacks: public BLEServerCallbacks { + public: + MyServerCallbacks(EmotiBitBluetooth* server) : server(server) {} + void onConnect(BLEServer* pServer); + void onDisconnect(BLEServer* pServer); + private: + EmotiBitBluetooth* server; + }; + + /*! + * @brief Characteristic callbacks for data transfer + */ + class MyCallbacks : public BLECharacteristicCallbacks { + void onWrite(BLECharacteristic *pCharacteristic); + }; + + /*! + * @brief Initializes the BLE device and starts advertising + * @param emotibitDeviceId ID from setDeviceId + * @return 1 on success, 0 on failure + */ + //TO DO use int for error handling + uint8_t begin(const String& emotibitDeviceId); + + /*! + * @brief Sends data over BLE + * @param message data to be sent + */ + void sendData(const String &message); + + /*! + * @brief Checks if the device is connected to a BLE client + * @param emotibitDeviceId + */ + void setDeviceId(const String emotibitDeviceId); + + /*! + * @brief Reads control messages from the BLE characteristic + * @param packet the control message packet + */ + uint8_t readControl(String& packet); + + //void update();for when we sync data over BLE + //move to emotibit + //void sdCardFileNaming(); for when we choose bluetooth and there is no rb start time + + /*! + * @brief Ends the BLE connection + */ + void end(); + + /*! + * @brief Checks if the Bluetooth is off + * @return if Bluetooth is off, returns true, otherwise false + */ + bool isOff(); + + /*! + * @brief Reconnects the BLE server if disconnected + */ + void reconnect(); + + /*! + * @brief Starts Advertising + */ + void startAdvertising(); }; #endif //ARDUINO_FEATHER_ESP32 \ No newline at end of file From 3339bf0f972f7f1b5825e29a61a35707321ed6c2 Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Thu, 31 Jul 2025 09:25:41 -0700 Subject: [PATCH 10/22] removed sync code --- EmotiBitBluetooth.cpp | 5 ----- EmotiBitBluetooth.h | 7 +------ 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/EmotiBitBluetooth.cpp b/EmotiBitBluetooth.cpp index 14ec7f35..2d67713b 100644 --- a/EmotiBitBluetooth.cpp +++ b/EmotiBitBluetooth.cpp @@ -31,11 +31,6 @@ _emotibitDeviceId = emotibitDeviceId; pDataRxCharacteristic = pService->createCharacteristic(EMOTIBIT_DATA_RX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE); pDataRxCharacteristic->setCallbacks(new MyCallbacks()); - //pSyncTxCharacteristic = pService->createCharacteristic(EMOTIBIT_SYNC_TX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_NOTIFY); - //pSyncTxCharacteristic->addDescriptor(new BLE2902()); - - //pSyncRxCharacteristic = pService->createCharacteristic(EMOTIBIT_SYNC_RX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE); - //pSyncRxCharacteristic->setCallbacks(new MyCallbacks()); pService->start(); EmotiBitBluetooth::startAdvertising(); diff --git a/EmotiBitBluetooth.h b/EmotiBitBluetooth.h index 5b37b035..4e0e5757 100644 --- a/EmotiBitBluetooth.h +++ b/EmotiBitBluetooth.h @@ -31,10 +31,6 @@ #define EMOTIBIT_DATA_RX_CHARACTERISTIC_UUID "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" #define EMOTIBIT_DATA_TX_CHARACTERISTIC_UUID "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" -//untested below -//#define EMOTIBIT_SYNC_TX_CHARACTERISTIC_UUID "6E400004-B5A3-F393-E0A9-E50E24DCCA9E" -//#define EMOTIBIT_SYNC_RX_CHARACTERISTIC_UUID "6E400005-B5A3-F393-E0A9-E50E24DCCA9E" - /*! * @brief Handles Bluetooth communication for EmotiBit. */ @@ -44,8 +40,7 @@ class EmotiBitBluetooth { BLECharacteristic* pDataTxCharacteristic = nullptr; ///points to the data tx characteristic BLECharacteristic* pDataRxCharacteristic = nullptr; ///points to the data rx characteristic - //BLECharacteristic* pSyncTxCharacteristic = nullptr; ///points to the sync tx characteristic - //BLECharacteristic* pSyncRxCharacteristic = nullptr; ///points to the sync rx characteristic + bool deviceConnected = false; ///boolean to check if device is connected String _emotibitDeviceId = ""; ///string to hold device id From 5687d78146df9edc8b352103a54b6fc186207ea7 Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Thu, 31 Jul 2025 09:28:01 -0700 Subject: [PATCH 11/22] More tab changes --- EmotiBitBluetooth.cpp | 2 +- EmotiBitBluetooth.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/EmotiBitBluetooth.cpp b/EmotiBitBluetooth.cpp index 2d67713b..523fb421 100644 --- a/EmotiBitBluetooth.cpp +++ b/EmotiBitBluetooth.cpp @@ -10,7 +10,7 @@ uint8_t EmotiBitBluetooth::begin(const String& emotibitDeviceId) return 0; // Success } -_emotibitDeviceId = emotibitDeviceId; + _emotibitDeviceId = emotibitDeviceId; Serial.println("Bluetooth tag detected, turning on bluetooth."); BLEDevice::init(("EmotiBit: " + _emotibitDeviceId).c_str()); diff --git a/EmotiBitBluetooth.h b/EmotiBitBluetooth.h index 4e0e5757..9cc52776 100644 --- a/EmotiBitBluetooth.h +++ b/EmotiBitBluetooth.h @@ -41,7 +41,6 @@ class EmotiBitBluetooth { BLECharacteristic* pDataTxCharacteristic = nullptr; ///points to the data tx characteristic BLECharacteristic* pDataRxCharacteristic = nullptr; ///points to the data rx characteristic - bool deviceConnected = false; ///boolean to check if device is connected String _emotibitDeviceId = ""; ///string to hold device id String _receivedControlMessage = ""; From 2db7d38a9c35c5f2881f3b52d155708fc81dc98a Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Thu, 31 Jul 2025 10:55:58 -0700 Subject: [PATCH 12/22] Code cleanup --- EmotiBit.cpp | 6 ++---- EmotiBitBluetooth.cpp | 3 --- EmotiBitBluetooth.h | 7 +++---- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/EmotiBit.cpp b/EmotiBit.cpp index 52fb92dd..62a9e207 100644 --- a/EmotiBit.cpp +++ b/EmotiBit.cpp @@ -110,8 +110,6 @@ uint8_t EmotiBit::setup(String firmwareVariant) #endif #ifdef ARDUINO_FEATHER_ESP32 - //esp_bt_controller_disable(); - // ToDo: assess similarity with btStop(); setCpuFrequencyMhz(CPU_HZ / 1000000); // 80MHz has been tested working to save battery life #endif @@ -971,6 +969,7 @@ uint8_t EmotiBit::setup(String firmwareVariant) { #ifdef ARDUINO_FEATHER_ESP32 esp_bt_controller_disable(); + // ToDo: assess similarity with btStop(); #endif //WiFi Setup; Serial.print("\nSetting up WiFi\n"); @@ -1521,9 +1520,8 @@ void EmotiBit::parseIncomingControlPackets(String &controlPackets, uint16_t &pac static String packet; static EmotiBitPacket::Header header; int16_t dataStartChar = 0; - //use the following #ifdef ARDUINO_FEATHER_ESP32 - while (_emotiBitWiFi.readControl(packet) > 0 || _emotiBitBluetooth.readControl(packet) > 0) + while (_emotiBitWiFi.readControl(packet) > 0 || _emotiBitBluetooth.readControl(packet) > 0) //Bluetooth and WiFi control packets are read in the same loop #else while (_emotiBitWiFi.readControl(packet) > 0) #endif //ARDUINO_FEATHER_ESP32 diff --git a/EmotiBitBluetooth.cpp b/EmotiBitBluetooth.cpp index 523fb421..347dfe52 100644 --- a/EmotiBitBluetooth.cpp +++ b/EmotiBitBluetooth.cpp @@ -48,7 +48,6 @@ void EmotiBitBluetooth::MyServerCallbacks::onConnect(BLEServer* pServer) void EmotiBitBluetooth::MyServerCallbacks::onDisconnect(BLEServer* pServer) { - server -> deviceConnected = false; Serial.println("BLE client disconnected"); //need to restart advertising to allow new connections after disconnection if accidentally disconnected @@ -161,7 +160,6 @@ bool EmotiBitBluetooth::isOff() return _bluetoothOff; } - void EmotiBitBluetooth::end() { if (pServer && deviceConnected) @@ -179,7 +177,6 @@ void EmotiBitBluetooth::end() _bluetoothReconnect = false; } - void EmotiBitBluetooth::reconnect() { if (pServer) diff --git a/EmotiBitBluetooth.h b/EmotiBitBluetooth.h index 9cc52776..27a12c1b 100644 --- a/EmotiBitBluetooth.h +++ b/EmotiBitBluetooth.h @@ -25,8 +25,6 @@ #include #include "EmotiBitPacket.h" - - #define EMOTIBIT_SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" #define EMOTIBIT_DATA_RX_CHARACTERISTIC_UUID "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" #define EMOTIBIT_DATA_TX_CHARACTERISTIC_UUID "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" @@ -43,9 +41,10 @@ class EmotiBitBluetooth { bool deviceConnected = false; ///boolean to check if device is connected String _emotibitDeviceId = ""; ///string to hold device id - String _receivedControlMessage = ""; + String _receivedControlMessage = ""; bool _bluetoothOff = true; - bool _bluetoothReconnect = false; + bool _bluetoothReconnect = false; + /*! * @brief Server callbacks for connections */ From a473162571622ccec2e106ec4ce56332627c7fea Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Thu, 31 Jul 2025 11:18:38 -0700 Subject: [PATCH 13/22] Deleted workspace --- .../EmotiBitGithub.code-workspace | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 EmotiBit_stock_firmware/EmotiBitGithub.code-workspace diff --git a/EmotiBit_stock_firmware/EmotiBitGithub.code-workspace b/EmotiBit_stock_firmware/EmotiBitGithub.code-workspace deleted file mode 100644 index d99d9a2b..00000000 --- a/EmotiBit_stock_firmware/EmotiBitGithub.code-workspace +++ /dev/null @@ -1,18 +0,0 @@ -{ - "folders": [ - { - "path": "../.." - }, - { - "name": "EmotiBit_stock_firmware", - "path": "." - } - ], - "settings": { - "files.associations": { - "regex": "cpp", - "xlocale": "cpp", - "xstring": "cpp" - } - } -} \ No newline at end of file From bbfd66bc2d5c6e2207b6e77003a0a6582de65634 Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Thu, 31 Jul 2025 15:49:20 -0700 Subject: [PATCH 14/22] enabled the ability to run debug mode + bluetooth at the same time --- EmotiBit.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/EmotiBit.cpp b/EmotiBit.cpp index 878856e5..15a816bc 100644 --- a/EmotiBit.cpp +++ b/EmotiBit.cpp @@ -454,10 +454,9 @@ uint8_t EmotiBit::setup(String firmwareVariant) while (!Serial.available() && millis() - now < 2000) { #ifdef ARDUINO_FEATHER_ESP32 - if (digitalRead(buttonPin)) { + if (digitalRead(buttonPin) && !_enableBluetooth) { Serial.println("Bluetooth Enabled"); _enableBluetooth = true; - break; } #endif // ARDUINO_FEATHER_ESP32 } From 38f7c975c402a4d52bcd09df071b34252f0eadd4 Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Thu, 31 Jul 2025 16:24:35 -0700 Subject: [PATCH 15/22] More cleanup --- EmotiBit.cpp | 3 +-- board_feather_esp32.ini | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/EmotiBit.cpp b/EmotiBit.cpp index 15a816bc..e4e9a81e 100644 --- a/EmotiBit.cpp +++ b/EmotiBit.cpp @@ -1304,7 +1304,7 @@ bool EmotiBit::setupSdCard(bool loadConfig) #if defined ARDUINO_FEATHER_ESP32 Serial.println("ESP::: Reading SD-Card"); File dir; - dir = SD.open("/"); // look here for files and grab everything + dir = SD.open("/"); // taken from SD examples: listFiles while (true) { @@ -3223,7 +3223,6 @@ void EmotiBit::readSensors() led.setState(EmotiBitLedController::Led::BLUE, true); led.setState(EmotiBitLedController::Led::YELLOW, true); } - //new if statment to check if we are in powermode if (getPowerMode() == PowerMode::BLUETOOTH) { #ifdef ARDUINO_FEATHER_ESP32 diff --git a/board_feather_esp32.ini b/board_feather_esp32.ini index 31a4310e..6b1999cf 100644 --- a/board_feather_esp32.ini +++ b/board_feather_esp32.ini @@ -9,4 +9,4 @@ build_flags = board_build.f_cpu = 240000000L extra_scripts = pre:../pio_scripts/renameFw.py firmware_name_board_name = feather_esp32 -board_build.partitions = huge_app.csv ;added to support bluetooth \ No newline at end of file +board_build.partitions = huge_app.csv \ No newline at end of file From 69bf79840ecbf3286a56740a6a8827a2c7638e83 Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Mon, 4 Aug 2025 08:30:35 -0700 Subject: [PATCH 16/22] Updated versioning --- EmotiBit.h | 2 +- library.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/EmotiBit.h b/EmotiBit.h index 5bb7a9db..f63f919b 100644 --- a/EmotiBit.h +++ b/EmotiBit.h @@ -58,7 +58,7 @@ class EmotiBit { - String firmware_version = "1.14.1"; + String firmware_version = "1.14.1.feat-blePrototype-Example.1"; diff --git a/library.properties b/library.properties index 84edaa7b..dd84ca17 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=EmotiBit FeatherWing -version=1.14.1 +version=1.14.1.feat-blePrototype-Example.1 author=Connected Future Labs maintainer=Connected Future Labs sentence=A library written for EmotiBit FeatherWing that supports all sensors included on the wing. From 6e919d321791dcfcbdd140d04c0e3b124bb9aa43 Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Wed, 6 Aug 2025 11:26:56 -0700 Subject: [PATCH 17/22] Bumped library --- EmotiBit.h | 2 +- library.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/EmotiBit.h b/EmotiBit.h index f63f919b..052beb6a 100644 --- a/EmotiBit.h +++ b/EmotiBit.h @@ -58,7 +58,7 @@ class EmotiBit { - String firmware_version = "1.14.1.feat-blePrototype-Example.1"; + String firmware_version = "1.14.2.feat-blePrototype-Example.1"; diff --git a/library.properties b/library.properties index dd84ca17..77cc6a96 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=EmotiBit FeatherWing -version=1.14.1.feat-blePrototype-Example.1 +version=1.14.2.feat-blePrototype-Example.1 author=Connected Future Labs maintainer=Connected Future Labs sentence=A library written for EmotiBit FeatherWing that supports all sensors included on the wing. From 0ed979a8eed53f65d3915b0d00a948817cec1f65 Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Wed, 6 Aug 2025 12:01:04 -0700 Subject: [PATCH 18/22] Spacing --- EmotiBitBluetooth.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EmotiBitBluetooth.cpp b/EmotiBitBluetooth.cpp index 347dfe52..67c54903 100644 --- a/EmotiBitBluetooth.cpp +++ b/EmotiBitBluetooth.cpp @@ -201,7 +201,7 @@ void EmotiBitBluetooth::startAdvertising() } else { - Serial.println("ERROR: pServer is NULL, cannot start advertising"); + Serial.println("ERROR: pServer is NULL, cannot start advertising"); } } From 176cb580bd62239918247912599f74e3f079ac7b Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Fri, 17 Oct 2025 14:06:49 -0700 Subject: [PATCH 19/22] Removed nameSdCardFile() --- EmotiBit.cpp | 1 - EmotiBit.h | 1 - 2 files changed, 2 deletions(-) diff --git a/EmotiBit.cpp b/EmotiBit.cpp index 75a3bd95..5c619d1a 100644 --- a/EmotiBit.cpp +++ b/EmotiBit.cpp @@ -4446,7 +4446,6 @@ void EmotiBit::processDebugInputs(String &debugPackets, uint16_t &packetNumber) } else if (c == '>') { _sendTestData = true; - //nameSdCardFile(); //temp Serial.println("Entering Sending Test Data Mode"); } diff --git a/EmotiBit.h b/EmotiBit.h index 7594a5d3..e5212188 100644 --- a/EmotiBit.h +++ b/EmotiBit.h @@ -467,7 +467,6 @@ class EmotiBit { bool processThermopileData(); // placeholder until separate EmotiBitThermopile controller is implemented void writeSerialData(EmotiBit::DataType t); void printEmotiBitInfo(); - void nameSdCardFile(); /** * Copies data buffer of the specified DataType into the passed array From 7d6574e8bee60e926b1fe09d696a6ac7ebc36833 Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Fri, 7 Nov 2025 10:33:18 -0800 Subject: [PATCH 20/22] Minor fixes --- EmotiBit.cpp | 8 ++++---- EmotiBitBluetooth.cpp | 32 +++++++++++++++++++++++++------- EmotiBitBluetooth.h | 2 +- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/EmotiBit.cpp b/EmotiBit.cpp index 5c619d1a..126967b9 100644 --- a/EmotiBit.cpp +++ b/EmotiBit.cpp @@ -4444,15 +4444,15 @@ void EmotiBit::processDebugInputs(String &debugPackets, uint16_t &packetNumber) _emotibitNvmController.eraseEeprom(); } } - else if (c == '>') { + else if (c == '>') + { _sendTestData = true; - Serial.println("Entering Sending Test Data Mode"); } else if (c == '<') { - _sendTestData = true; - Serial.println("Entering Sending Test Data Mode"); + _sendTestData = false; + Serial.println("Exiting Sending Test Data Mode"); } else if (c == '@' && _sendTestData == true) { diff --git a/EmotiBitBluetooth.cpp b/EmotiBitBluetooth.cpp index 67c54903..3bb25d5e 100644 --- a/EmotiBitBluetooth.cpp +++ b/EmotiBitBluetooth.cpp @@ -17,7 +17,8 @@ uint8_t EmotiBitBluetooth::begin(const String& emotibitDeviceId) pServer = BLEDevice::createServer(); - if (!pServer) { + if (!pServer) + { Serial.println("ERROR: Failed to create BLE server"); return 1; } @@ -26,9 +27,19 @@ uint8_t EmotiBitBluetooth::begin(const String& emotibitDeviceId) BLEService* pService = pServer->createService(EMOTIBIT_SERVICE_UUID); pDataTxCharacteristic = pService->createCharacteristic(EMOTIBIT_DATA_TX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_NOTIFY); + if (!pDataTxCharacteristic) + { + Serial.println("ERROR: Failed to create TX characteristic"); + return 1; + } pDataTxCharacteristic->addDescriptor(new BLE2902()); pDataRxCharacteristic = pService->createCharacteristic(EMOTIBIT_DATA_RX_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE); + if (!pDataRxCharacteristic) + { + Serial.println("ERROR: Failed to create RX characteristic"); + return 1; + } pDataRxCharacteristic->setCallbacks(new MyCallbacks()); pService->start(); @@ -67,15 +78,18 @@ void EmotiBitBluetooth::MyCallbacks::onWrite(BLECharacteristic *pCharacteristic) } } -void EmotiBitBluetooth::setDeviceId(const String emotibitDeviceId) +void EmotiBitBluetooth::setDeviceId(const String& emotibitDeviceId) { _emotibitDeviceId = emotibitDeviceId; } void EmotiBitBluetooth::sendData(const String &message) { - if (deviceConnected) { - if (pDataTxCharacteristic == nullptr) { + if (deviceConnected) + { + //TODO: consider truncating via MTU if message is too long + if (pDataTxCharacteristic == nullptr) + { //Serial.println("ERROR: pDataTxCharacteristic is NULL!"); return; } @@ -91,9 +105,11 @@ void EmotiBitBluetooth::sendData(const String &message) // Check descriptor status BLEDescriptor* p2902 = pDataTxCharacteristic->getDescriptorByUUID(BLEUUID((uint16_t)0x2902)); - if (p2902) { + if (p2902) + { const uint8_t* val = p2902->getValue(); - if (val) { + if (val) + { //Serial.print(" | Notifications enabled="); //Serial.print((val[0] & 0x01) ? "YES" : "NO"); } @@ -104,7 +120,9 @@ void EmotiBitBluetooth::sendData(const String &message) //Serial.print(" | Message: "); //Serial.println(message.c_str()); } - else { + else + { + //ToDO: consider gating behind a debug flag Serial.println("unable to send data: deviceConnected=false"); } } diff --git a/EmotiBitBluetooth.h b/EmotiBitBluetooth.h index 27a12c1b..4bc66c91 100644 --- a/EmotiBitBluetooth.h +++ b/EmotiBitBluetooth.h @@ -82,7 +82,7 @@ class EmotiBitBluetooth { * @brief Checks if the device is connected to a BLE client * @param emotibitDeviceId */ - void setDeviceId(const String emotibitDeviceId); + void setDeviceId(const String& emotibitDeviceId); /*! * @brief Reads control messages from the BLE characteristic From 8300982be4f34b5daa44aa36829b16f0774e94a6 Mon Sep 17 00:00:00 2001 From: Sean Montgomery Date: Tue, 11 Nov 2025 16:53:40 -0800 Subject: [PATCH 21/22] Fixed setPowerMode() to handle BT mode changes --- EmotiBit.cpp | 159 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 103 insertions(+), 56 deletions(-) diff --git a/EmotiBit.cpp b/EmotiBit.cpp index 126967b9..b7b04fb9 100644 --- a/EmotiBit.cpp +++ b/EmotiBit.cpp @@ -959,12 +959,13 @@ uint8_t EmotiBit::setup(String firmwareVariant) if (_enableBluetooth == true) { - #ifdef ARDUINO_FEATHER_ESP32 - setPowerMode(PowerMode::BLUETOOTH); - #endif // ARDUINO_FEATHER_ESP32 + if (!setPowerMode(PowerMode::BLUETOOTH)) + { + _enableBluetooth = false; + } } - else + if (_enableBluetooth == false) { #ifdef ARDUINO_FEATHER_ESP32 esp_bt_controller_disable(); @@ -3800,94 +3801,140 @@ EmotiBit::PowerMode EmotiBit::getPowerMode() return _powerMode; } -void EmotiBit::setPowerMode(PowerMode mode) +bool EmotiBit::setPowerMode(PowerMode mode) { - _powerMode = mode; - String modePacket; - sendModePacket(modePacket, _outDataPacketCounter); - if (getPowerMode() == PowerMode::NORMAL_POWER) + bool ret = false; + if (mode == PowerMode::NORMAL_POWER) { - Serial.println("PowerMode::NORMAL_POWER"); - if (_emotiBitWiFi.isOff()) + Serial.println("SetPowerMode(NORMAL_POWER)"); + if (_enableBluetooth) { - unsigned long beginTime = millis(); - _emotiBitWiFi.begin(100, 1, 100); // This ToDo: create a async begin option - Serial.print("Total WiFi.begin() = "); - Serial.println(millis() - beginTime); + Serial.println("SetPowerMode() FAILED: BLUETOOTH <-> WIFI requires device reset"); } + else + { + if (_emotiBitWiFi.isOff()) + { + unsigned long beginTime = millis(); + _emotiBitWiFi.begin(100, 1, 100); // This ToDo: create a async begin option + Serial.print("Total WiFi.begin() = "); + Serial.println(millis() - beginTime); + } #ifdef ADAFRUIT_FEATHER_M0 - // For ADAFRUIT_FEATHER_M0, lowPowerMode() is a good balance of performance and battery - WiFi.lowPowerMode(); - // For ESP32 the default WIFI_PS_MIN_MODEM is probably optimal https://www.mischianti.org/2021/03/06/esp32-practical-power-saving-manage-wifi-and-cpu-1/ + // For ADAFRUIT_FEATHER_M0, lowPowerMode() is a good balance of performance and battery + WiFi.lowPowerMode(); + // For ESP32 the default WIFI_PS_MIN_MODEM is probably optimal https://www.mischianti.org/2021/03/06/esp32-practical-power-saving-manage-wifi-and-cpu-1/ #endif - modePacketInterval = NORMAL_POWER_MODE_PACKET_INTERVAL; + modePacketInterval = NORMAL_POWER_MODE_PACKET_INTERVAL; + Serial.println("PowerMode::NORMAL_POWER"); + _powerMode = mode; + ret = true; + } } - else if (getPowerMode() == PowerMode::LOW_POWER) - { - Serial.println("PowerMode::LOW_POWER"); - if (_emotiBitWiFi.isOff()) + else if (mode == PowerMode::LOW_POWER) + { + Serial.println("SetPowerMode(LOW_POWER)"); + if (_enableBluetooth) { - unsigned long beginTime = millis(); - _emotiBitWiFi.begin(100, 1, 100); // This ToDo: create a async begin option - Serial.print("Total WiFi.begin() = "); - Serial.println(millis() - beginTime); + Serial.println("SetPowerMode() FAILED: BLUETOOTH <-> WIFI requires device reset"); } + else + { + if (_emotiBitWiFi.isOff()) + { + unsigned long beginTime = millis(); + _emotiBitWiFi.begin(100, 1, 100); // This ToDo: create a async begin option + Serial.print("Total WiFi.begin() = "); + Serial.println(millis() - beginTime); + } #ifdef ADAFRUIT_FEATHER_M0 - WiFi.lowPowerMode(); + WiFi.lowPowerMode(); #endif - modePacketInterval = LOW_POWER_MODE_PACKET_INTERVAL; + modePacketInterval = LOW_POWER_MODE_PACKET_INTERVAL; + Serial.println("PowerMode::LOW_POWER"); + _powerMode = mode; + ret = true; + } } - else if (getPowerMode() == PowerMode::MAX_LOW_POWER) + else if (mode == PowerMode::MAX_LOW_POWER) { - Serial.println("PowerMode::MAX_LOW_POWER"); - if (_emotiBitWiFi.isOff()) + Serial.println("SetPowerMode(MAX_LOW_POWER)"); + if (_enableBluetooth) { - unsigned long beginTime = millis(); - _emotiBitWiFi.begin(100, 1, 100); // This ToDo: create a async begin option - Serial.print("Total WiFi.begin() = "); - Serial.println(millis() - beginTime); + Serial.println("SetPowerMode() FAILED: BLUETOOTH <-> WIFI requires device reset"); } + else + { + if (_emotiBitWiFi.isOff()) + { + unsigned long beginTime = millis(); + _emotiBitWiFi.begin(100, 1, 100); // This ToDo: create a async begin option + Serial.print("Total WiFi.begin() = "); + Serial.println(millis() - beginTime); + } #ifdef ADAFRUIT_FEATHER_M0 - WiFi.maxLowPowerMode(); + WiFi.maxLowPowerMode(); #endif - // ToDo: for ESP32 There may be some value to explore WIFI_PS_MAX_MODEM https://www.mischianti.org/2021/03/06/esp32-practical-power-saving-manage-wifi-and-cpu-1/ - modePacketInterval = LOW_POWER_MODE_PACKET_INTERVAL; + // ToDo: for ESP32 There may be some value to explore WIFI_PS_MAX_MODEM https://www.mischianti.org/2021/03/06/esp32-practical-power-saving-manage-wifi-and-cpu-1/ + modePacketInterval = LOW_POWER_MODE_PACKET_INTERVAL; + Serial.println("PowerMode::MAX_LOW_POWER"); + _powerMode = mode; + ret = true; + } } - else if (getPowerMode() == PowerMode::WIRELESS_OFF) + else if (mode == PowerMode::WIRELESS_OFF) { - Serial.println("PowerMode::WIRELESS_OFF"); - - if (_enableBluetooth == true) - { -#ifdef ARDUINO_FEATHER_ESP32 - _emotiBitBluetooth.end(); -// _enableBluetooth = false; + Serial.println("SetPowerMode(WIRELESS_OFF)"); + if (_enableBluetooth) + { +#ifdef ARDUINO_FEATHER_ESP32 // consider moving this ifdef into EmotiBitBluetooth + _emotiBitBluetooth.end(); + // Note: we're NOT setting _enableBluetooth = false here because BLUETOOTH <-> WIFI requires device reset #endif //ARDUINO_FEATHER_ESP32 - } + } else { - _emotiBitWiFi.end(); + _emotiBitWiFi.end(); } + Serial.println("PowerMode::WIRELESS_OFF"); + _powerMode = mode; + ret = true; } - else if (getPowerMode() == PowerMode::BLUETOOTH) + else if (mode == PowerMode::BLUETOOTH) { -#ifdef ARDUINO_FEATHER_ESP32 - if (_emotiBitBluetooth.isOff()) + Serial.println("SetPowerMode(BLUETOOTH)"); + if (!_enableBluetooth) { - Serial.println("PowerMode::BLUETOOTH"); - _emotiBitBluetooth.begin(emotibitDeviceId); + Serial.println("SetPowerMode() FAILED: BLUETOOTH <-> WIFI requires device reset"); } - + else + { +#ifdef ARDUINO_FEATHER_ESP32 // consider moving this ifdef into EmotiBitBluetooth + if (_emotiBitBluetooth.isOff()) + { + if (_emotiBitBluetooth.begin(emotibitDeviceId) == 0) // ToDo: add EmotiBitBluetooth::SUCCESS for improved readability + { + Serial.println("PowerMode::BLUETOOTH"); + _powerMode = mode; + ret = true; + } + } + // ToDo: consider adding serial output to clarify !isOff() and !begin() #endif //ARDUINO_FEATHER_ESP32 + } } - else if (getPowerMode() == PowerMode::HIBERNATE) + else if (mode == PowerMode::HIBERNATE) { Serial.println("PowerMode::HIBERNATE"); + _powerMode = mode; } else { Serial.println("PowerMode Not Recognized"); } + String modePacket; + sendModePacket(modePacket, _outDataPacketCounter); + return status; } void EmotiBit::writeSerialData(EmotiBit::DataType t) From b270aeef1e00c4d4a4de8526a1ccbd2763b893d2 Mon Sep 17 00:00:00 2001 From: Joseph-Jacobson Date: Mon, 17 Nov 2025 17:43:54 -0800 Subject: [PATCH 22/22] PR review changes --- EmotiBit.cpp | 206 +++++++----------- EmotiBit.h | 5 +- .../EmotiBit_stock_firmware.ino | 2 +- 3 files changed, 87 insertions(+), 126 deletions(-) diff --git a/EmotiBit.cpp b/EmotiBit.cpp index b7b04fb9..824a5618 100644 --- a/EmotiBit.cpp +++ b/EmotiBit.cpp @@ -454,9 +454,9 @@ uint8_t EmotiBit::setup(String firmwareVariant) while (!Serial.available() && millis() - now < 2000) { #ifdef ARDUINO_FEATHER_ESP32 - if (digitalRead(buttonPin) && !_enableBluetooth) { + if (digitalRead(buttonPin) && !_bluetoothEnabled ) { Serial.println("Bluetooth Enabled"); - _enableBluetooth = true; + _bluetoothEnabled = true; } #endif // ARDUINO_FEATHER_ESP32 } @@ -957,66 +957,66 @@ uint8_t EmotiBit::setup(String firmwareVariant) sleep(true); } - if (_enableBluetooth == true) + if (_bluetoothEnabled == true) { if (!setPowerMode(PowerMode::BLUETOOTH)) { - _enableBluetooth = false; + _bluetoothEnabled = false; } } - if (_enableBluetooth == false) + if (_bluetoothEnabled == false) { - #ifdef ARDUINO_FEATHER_ESP32 +#ifdef ARDUINO_FEATHER_ESP32 + // ToDo: assess similarity with btStop(); esp_bt_controller_disable(); - // ToDo: assess similarity with btStop(); - #endif - //WiFi Setup; - Serial.print("\nSetting up WiFi\n"); +#endif //ARDUINO_FEATHER_ESP32 + //WiFi Setup; + Serial.print("\nSetting up WiFi\n"); #if defined(ADAFRUIT_FEATHER_M0) - WiFi.setPins(8, 7, 4, 2); - WiFi.lowPowerMode(); + WiFi.setPins(8, 7, 4, 2); + WiFi.lowPowerMode(); #endif - printEmotiBitInfo(); - // turn BLUE on to signify we are trying to connect to WiFi - led.setState(EmotiBitLedController::Led::BLUE, true, true); - uint16_t attemptDelay = 20000; // in mS. ESP32 has been observed to take >10 seconds to resolve an enterprise connection - uint8_t maxAttemptsPerCred = 1; - uint32_t timeout = attemptDelay * maxAttemptsPerCred * _emotiBitWiFi.getNumCredentials() * 2; // Try cycling through all credentials at least 2x before giving up and trying a restart - if (_emotiBitWiFi.isEnterpriseNetworkListed()) - { - // enterprise network is listed in network credential list. - // restart MCU after timeout - _emotiBitWiFi.begin(timeout, maxAttemptsPerCred, attemptDelay); - } - else - { - // only personal networks listed in credentials list. - // keep trying to connect to networks without any timeout - _emotiBitWiFi.begin(-1, maxAttemptsPerCred, attemptDelay); - } - if (_emotiBitWiFi.status(false) != WL_CONNECTED) - { - // Could not connect to network. software restart and begin setup again. - restartMcu(); - } - led.setState(EmotiBitLedController::Led::BLUE, false, true); - if (testingMode == TestingMode::FACTORY_TEST) - { - // Add Pass or fail - // ToDo: add mechanism to detect fail/pass - EmotiBitFactoryTest::updateOutputString(factoryTestSerialOutput, EmotiBitFactoryTest::TypeTag::WIFI, EmotiBitFactoryTest::TypeTag::TEST_PASS); - } - Serial.println(" WiFi setup Completed"); - #ifdef ARDUINO_FEATHER_ESP32 - Serial.println("Setting up FTP"); - Serial.println("Setting Protocol"); - _fileTransferManager.setProtocol(FileTransferManager::Protocol::FTP); - Serial.println("Setting Auth"); - _fileTransferManager.setFtpAuth("ftp", "ftp"); - #endif + printEmotiBitInfo(); + // turn BLUE on to signify we are trying to connect to WiFi + led.setState(EmotiBitLedController::Led::BLUE, true, true); + uint16_t attemptDelay = 20000; // in mS. ESP32 has been observed to take >10 seconds to resolve an enterprise connection + uint8_t maxAttemptsPerCred = 1; + uint32_t timeout = attemptDelay * maxAttemptsPerCred * _emotiBitWiFi.getNumCredentials() * 2; // Try cycling through all credentials at least 2x before giving up and trying a restart + if (_emotiBitWiFi.isEnterpriseNetworkListed()) + { + // enterprise network is listed in network credential list. + // restart MCU after timeout + _emotiBitWiFi.begin(timeout, maxAttemptsPerCred, attemptDelay); + } + else + { + // only personal networks listed in credentials list. + // keep trying to connect to networks without any timeout + _emotiBitWiFi.begin(-1, maxAttemptsPerCred, attemptDelay); + } + if (_emotiBitWiFi.status(false) != WL_CONNECTED) + { + // Could not connect to network. software restart and begin setup again. + restartMcu(); + } + led.setState(EmotiBitLedController::Led::BLUE, false, true); + if (testingMode == TestingMode::FACTORY_TEST) + { + // Add Pass or fail + // ToDo: add mechanism to detect fail/pass + EmotiBitFactoryTest::updateOutputString(factoryTestSerialOutput, EmotiBitFactoryTest::TypeTag::WIFI, EmotiBitFactoryTest::TypeTag::TEST_PASS); + } + Serial.println(" WiFi setup Completed"); + #ifdef ARDUINO_FEATHER_ESP32 + Serial.println("Setting up FTP"); + Serial.println("Setting Protocol"); + _fileTransferManager.setProtocol(FileTransferManager::Protocol::FTP); + Serial.println("Setting Auth"); + _fileTransferManager.setFtpAuth("ftp", "ftp"); + #endif - setPowerMode(PowerMode::NORMAL_POWER); + setPowerMode(PowerMode::NORMAL_POWER); } typeTags[(uint8_t)EmotiBit::DataType::EDA] = EmotiBitPacket::TypeTag::EDA; @@ -3224,66 +3224,14 @@ void EmotiBit::readSensors() led.setState(EmotiBitLedController::Led::BLUE, true); led.setState(EmotiBitLedController::Led::YELLOW, true); } - - if (getPowerMode() == PowerMode::BLUETOOTH) { -#ifdef ARDUINO_FEATHER_ESP32 - // Bluetooth connected status LED - if (_emotiBitBluetooth.deviceConnected) { - led.setState(EmotiBitLedController::Led::BLUE, true); - } - else { - // blink LED - static unsigned long onTime = 125; // msec - static unsigned long totalTime = 250; // msec changed to 250 - static bool bleConnectedBlinkState = false; - - static unsigned long bleConnBlinkTimer = millis(); - - unsigned long timeNow = millis(); - if (timeNow - bleConnBlinkTimer < onTime) - { - led.setState(EmotiBitLedController::Led::BLUE, true); - } - else if (timeNow - bleConnBlinkTimer < totalTime) - { - led.setState(EmotiBitLedController::Led::BLUE, false); - } - else - { - bleConnBlinkTimer = timeNow; - } - } - // Battery LED - if (battIndicationSeq) - { - led.setState(EmotiBitLedController::Led::YELLOW, true); - } - else - { - led.setState(EmotiBitLedController::Led::YELLOW, false); - } - - // Recording status LED - if (_sdWrite) - { - static uint32_t recordBlinkDuration = millis(); - if (millis() - recordBlinkDuration >= 500) - { - led.setState(EmotiBitLedController::Led::RED, !led.getState(EmotiBitLedController::Led::RED)); - recordBlinkDuration = millis(); - } - } - else if (!_sdWrite && led.getState(EmotiBitLedController::Led::RED) == true) - { - led.setState(EmotiBitLedController::Led::RED, false); - } - -#endif //ARDUINO_FEATHER_ESP32 - } else { // WiFi connected status LED +#ifdef ARDUINO_FEATHER_ESP32 + if (_emotiBitWiFi.isConnected() || _emotiBitBluetooth.deviceConnected) +#else if (_emotiBitWiFi.isConnected()) +#endif // ARDUINO_FEATHER_ESP32 { // Connected to oscilloscope // turn LED on @@ -3291,28 +3239,32 @@ void EmotiBit::readSensors() } else { - if (_emotiBitWiFi.status(false) == WL_CONNECTED) // ToDo: assess if WiFi.status() is thread/interrupt safe + if (_emotiBitWiFi.status(false) == WL_CONNECTED || _bluetoothEnabled) // ToDo: assess if WiFi.status() is thread/interrupt safe { // Not connected to oscilloscope, but connected to wifi // blink LED - static unsigned long onTime = 125; // msec - static unsigned long totalTime = 500; // msec - static bool wifiConnectedBlinkState = false; + unsigned long onTime = 125; // msec + unsigned long totalTime = 500; // msec + if (_bluetoothEnabled) + { + totalTime = 250; // msec + } + static bool ConnectedBlinkState = false; - static unsigned long wifiConnBlinkTimer = millis(); + static unsigned long ConnBlinkTimer = millis(); unsigned long timeNow = millis(); - if (timeNow - wifiConnBlinkTimer < onTime) + if (timeNow - ConnBlinkTimer < onTime) { led.setState(EmotiBitLedController::Led::BLUE, true); } - else if (timeNow - wifiConnBlinkTimer < totalTime) + else if (timeNow - ConnBlinkTimer < totalTime) { led.setState(EmotiBitLedController::Led::BLUE, false); } else { - wifiConnBlinkTimer = timeNow; + ConnBlinkTimer = timeNow; } } else @@ -3807,7 +3759,7 @@ bool EmotiBit::setPowerMode(PowerMode mode) if (mode == PowerMode::NORMAL_POWER) { Serial.println("SetPowerMode(NORMAL_POWER)"); - if (_enableBluetooth) + if (_bluetoothEnabled ) { Serial.println("SetPowerMode() FAILED: BLUETOOTH <-> WIFI requires device reset"); } @@ -3834,7 +3786,7 @@ bool EmotiBit::setPowerMode(PowerMode mode) else if (mode == PowerMode::LOW_POWER) { Serial.println("SetPowerMode(LOW_POWER)"); - if (_enableBluetooth) + if (_bluetoothEnabled ) { Serial.println("SetPowerMode() FAILED: BLUETOOTH <-> WIFI requires device reset"); } @@ -3859,7 +3811,7 @@ bool EmotiBit::setPowerMode(PowerMode mode) else if (mode == PowerMode::MAX_LOW_POWER) { Serial.println("SetPowerMode(MAX_LOW_POWER)"); - if (_enableBluetooth) + if (_bluetoothEnabled ) { Serial.println("SetPowerMode() FAILED: BLUETOOTH <-> WIFI requires device reset"); } @@ -3885,11 +3837,11 @@ bool EmotiBit::setPowerMode(PowerMode mode) else if (mode == PowerMode::WIRELESS_OFF) { Serial.println("SetPowerMode(WIRELESS_OFF)"); - if (_enableBluetooth) + if (_bluetoothEnabled ) { #ifdef ARDUINO_FEATHER_ESP32 // consider moving this ifdef into EmotiBitBluetooth _emotiBitBluetooth.end(); - // Note: we're NOT setting _enableBluetooth = false here because BLUETOOTH <-> WIFI requires device reset + // Note: we're NOT setting _bluetoothEnabled = false here because BLUETOOTH <-> WIFI requires device reset #endif //ARDUINO_FEATHER_ESP32 } else @@ -3903,7 +3855,7 @@ bool EmotiBit::setPowerMode(PowerMode mode) else if (mode == PowerMode::BLUETOOTH) { Serial.println("SetPowerMode(BLUETOOTH)"); - if (!_enableBluetooth) + if (!_bluetoothEnabled ) { Serial.println("SetPowerMode() FAILED: BLUETOOTH <-> WIFI requires device reset"); } @@ -3934,7 +3886,7 @@ bool EmotiBit::setPowerMode(PowerMode mode) } String modePacket; sendModePacket(modePacket, _outDataPacketCounter); - return status; + return ret; } void EmotiBit::writeSerialData(EmotiBit::DataType t) @@ -4842,7 +4794,15 @@ void EmotiBit::printEmotiBitInfo() Serial.print(ip); Serial.println("\""); } - + + if (!_bluetoothEnabled ) + { + Serial.print("WiFi Enabled"); + } + else + { + Serial.print("Bluetooth Enabled"); +} Serial.println("}}]"); } diff --git a/EmotiBit.h b/EmotiBit.h index e5212188..9d9199e9 100644 --- a/EmotiBit.h +++ b/EmotiBit.h @@ -436,7 +436,7 @@ class EmotiBit { DataType _serialData = DataType::length; volatile bool buttonPressed = false; bool startBufferOverflowTest = false; - bool _enableBluetooth = false; + bool _bluetoothEnabled = false; void setupFailed(const String failureMode, int buttonPin = -1, bool configFileError = false); bool setupSdCard(bool loadConfig = true); @@ -452,7 +452,8 @@ class EmotiBit { void attachShortButtonPress(void(*shortButtonPressFunction)(void)); void attachLongButtonPress(void(*longButtonPressFunction)(void)); PowerMode getPowerMode(); - void setPowerMode(PowerMode mode); + //void setPowerMode(PowerMode mode); + bool setPowerMode(PowerMode mode); bool writeSdCardMessage(const String &s); int freeMemory(); bool loadConfigFile(const String &filename); diff --git a/EmotiBit_stock_firmware/EmotiBit_stock_firmware.ino b/EmotiBit_stock_firmware/EmotiBit_stock_firmware.ino index 64c45285..482afbdb 100644 --- a/EmotiBit_stock_firmware/EmotiBit_stock_firmware.ino +++ b/EmotiBit_stock_firmware/EmotiBit_stock_firmware.ino @@ -10,7 +10,7 @@ float data[dataSize]; void onShortButtonPress() { - if (emotibit._enableBluetooth == true) + if (emotibit._bluetoothEnabled == true) { if (emotibit.getPowerMode() == EmotiBit::PowerMode::BLUETOOTH) {