diff --git a/include/ble_serial.h b/include/ble_serial.h index beee672..d4353cc 100644 --- a/include/ble_serial.h +++ b/include/ble_serial.h @@ -17,11 +17,19 @@ #include "Arduino.h" #include "Stream.h" + +#ifdef USE_NIMBLE +#include +#include +#else #include #include #include #include #include +#endif + + #define SERVICE_UUID "00000001-ba2a-46c9-ae49-01b0961f68bb" // KISS service UUID #define CHARACTERISTIC_UUID_TX "00000003-ba2a-46c9-ae49-01b0961f68bb" @@ -46,9 +54,15 @@ class BLESerial: public Stream private: String local_name; +#ifdef USE_NIMBLE + NimBLEServer *pServer = NULL; + NimBLEService *pService; + NimBLECharacteristic * pTxCharacteristic; +#else BLEServer *pServer = NULL; BLEService *pService; BLECharacteristic * pTxCharacteristic; +#endif bool deviceConnected = false; uint8_t txValue = 0; diff --git a/include/config.h b/include/config.h index 46f2223..07ac21a 100644 --- a/include/config.h +++ b/include/config.h @@ -3,10 +3,15 @@ // Uncomment for SX126X module usage // #define USE_SX126X +// #define WIFI_LoRa_32_V3 // Check your module name at https://github.com/jgromes/RadioLib/wiki/Modules #ifdef USE_SX126X -#define MODULE_NAME SX1268 + #ifdef WIFI_LoRa_32_V3 + #define MODULE_NAME SX1262 + #else + #define MODULE_NAME SX1268 + #endif #else #define MODULE_NAME SX1278 #endif @@ -25,6 +30,22 @@ #define CFG_IS_CLIENT_MODE true // false - server mode (APRS-IS gate mode) #endif +// Support for heltec_wifi_lora_32_V3 board +// https://github.com/espressif/arduino-esp32/blob/master/variants/heltec_wireless_stick_lite_v3/pins_arduino.h +//static const uint8_t RST_LoRa = 12; +//static const uint8_t BUSY_LoRa = 13; +//static const uint8_t DIO1 = 14; + + + +#ifdef WIFI_LoRa_32_V3 + #define LORA_RST RST_LoRa //OK + #define LORA_IRQ 14 + #define LED_BUILTIN 35 + #define BUILTIN_LED 35 +#endif + + // change pinouts if not defined through native board LORA_* definitions #ifndef LORA_RST #pragma message("LoRa pin definitions are not found, redefining...") @@ -33,13 +54,20 @@ #endif // LoRa pinouts -#define CFG_LORA_PIN_SS SS #define CFG_LORA_PIN_RST LORA_RST #define CFG_LORA_PIN_A LORA_IRQ // (sx127x - dio0, sx126x/sx128x - dio1) #ifdef USE_SX126X -#define CFG_LORA_PIN_B 14 // (sx127x - dio1, sx126x/sx128x - busy) -#define CFG_LORA_PIN_RXEN 32 // (sx127x - unused, sx126x - RXEN pin number) -#define CFG_LORA_PIN_TXEN 33 // (sx127x - unused, sx126x - TXEN pin number) + #ifdef WIFI_LoRa_32_V3 + #define CFG_LORA_PIN_B BUSY_LoRa + #define CFG_LORA_PIN_RXEN RADIOLIB_NC // (sx1262 unused) + #define CFG_LORA_PIN_TXEN RADIOLIB_NC // (sx1262 unused) + #define CFG_LORA_PIN_SS 8 // NSS_LoRa + #else + #define CFG_LORA_PIN_B 14 // (sx127x - dio1, sx126x/sx128x - busy) + #define CFG_LORA_PIN_RXEN 32 // (sx127x - unused, sx126x - RXEN pin number) + #define CFG_LORA_PIN_TXEN 33 // (sx127x - unused, sx126x - TXEN pin number) + #define CFG_LORA_PIN_SS SS + #endif #else #define CFG_LORA_PIN_B RADIOLIB_NC #define CFG_LORA_PIN_RXEN RADIOLIB_NC @@ -90,13 +118,13 @@ // Bluetooth #define CFG_BT_NAME "loraprs" // set to empty to disable Bluetooth -#define CFG_BT_USE_BLE false // set to true to use bluetooth low energy (for ios devices) +#define CFG_BT_USE_BLE true // set to true to use bluetooth low energy (for ios devices) // USB serial #define CFG_USB_SERIAL_ENABLE false // true - enable KISS communication over USB Serial (e.g. with APRSDroid over USB-OTG), disables USB logging // KISS protocol options -#define CFG_KISS_EXTENSIONS false // true - enable modem control from application with KISS commands and signal reports +#define CFG_KISS_EXTENSIONS true // true - enable modem control from application with KISS commands and signal reports #define CFG_KISS_TCP_IP false // true - run as KISS TCP/IP server, no bluetooth operations performed // APRS-IS options, valid in when CFG_IS_CLIENT_MODE = false diff --git a/include/loraprs_service.h b/include/loraprs_service.h index 292d901..2414a8f 100644 --- a/include/loraprs_service.h +++ b/include/loraprs_service.h @@ -18,7 +18,9 @@ #include #include +#ifndef USE_NIMBLE #include "BluetoothSerial.h" +#endif #include "ble_serial.h" #include "ax25_payload.h" #include "kiss_processor.h" @@ -187,7 +189,9 @@ class Service : virtual public Kiss::Processor std::shared_ptr rig_; // bluetooth, wifi + #ifndef USE_NIMBLE BluetoothSerial serialBt_; + #endif BLESerial serialBLE_; WiFiClient aprsisConnection_; diff --git a/platformio.ini b/platformio.ini index d658b41..dccd618 100644 --- a/platformio.ini +++ b/platformio.ini @@ -14,18 +14,24 @@ lib_deps = contrem/arduino-timer @ 3.0.1 jgromes/RadioLib @ 6.2.0 rlogiacco/CircularBuffer @ 1.3.3 + h2zero/NimBLE-Arduino @1.4.1 + check_tool = cppcheck check_flags = cppcheck: --suppress=*:*.pio\* --inline-suppr -DCPPCHECK check_skip_packages = yes [env:esp32dev_sx126x_modem] +lib_ignore = + NimBLE-Arduino board = esp32dev build_flags = -D CFG_IS_CLIENT_MODE=true -D USE_SX126X [env:esp32dev_sx126x_igate] +lib_ignore = + NimBLE-Arduino board = esp32dev board_build.f_cpu = 240000000L build_flags = @@ -33,22 +39,58 @@ build_flags = -D USE_SX126X [env:esp32dev_sx127x_modem] +lib_ignore = + NimBLE-Arduino board = esp32dev build_flags = -D CFG_IS_CLIENT_MODE=true [env:esp32dev_sx127x_igate] +lib_ignore = + NimBLE-Arduino board = esp32dev board_build.f_cpu = 240000000L build_flags = -D CFG_IS_CLIENT_MODE=false [env:ttgo-lora32-v1_modem] +lib_ignore = + NimBLE-Arduino board = ttgo-lora32-v1 build_flags = -D CFG_IS_CLIENT_MODE=true [env:ttgo-lora32-v2_modem] +lib_ignore = + NimBLE-Arduino board = ttgo-lora32-v2 build_flags = -D CFG_IS_CLIENT_MODE=true + +[env:heltec-lora32-v3_modem] +lib_ignore = + ESP32 BLE Arduino + BluetoothSerial +board = heltec_wifi_lora_32_V3 +board_build.f_cpu = 240000000L +board_build.mcu = esp32s3 +build_flags = + -D CFG_IS_CLIENT_MODE=true + -D USE_SX126X + -D CFG_BT_USE_BLE=true + -D USE_NIMBLE + -D WIFI_LoRa_32_V3 + +[env:heltec-lora32-v3_igate] +lib_ignore = + ESP32 BLE Arduino + BluetoothSerial +board = heltec_wifi_lora_32_V3 +board_build.f_cpu = 240000000L +board_build.mcu = esp32s3 +build_flags = + -D CFG_IS_CLIENT_MODE=false + -D USE_SX126X + -D CFG_BT_USE_BLE=true + -D USE_NIMBLE + -D WIFI_LoRa_32_V3 \ No newline at end of file diff --git a/src/ble_serial.cpp b/src/ble_serial.cpp index 2341703..a2293f8 100644 --- a/src/ble_serial.cpp +++ b/src/ble_serial.cpp @@ -13,6 +13,35 @@ // limitations under the License. #include "ble_serial.h" +#ifdef USE_NIMBLE +static const char* LOG_TAG = "[NimBLE]"; + +class BLESerialServerCallbacks: public BLEServerCallbacks { + friend class BLESerial; + BLESerial* bleSerial; + + void onConnect(NimBLEServer* pServer) { + // do anything needed on connection + NIMBLE_LOGI(LOG_TAG , "BLE client connected"); + delay(1000); // wait for connection to complete or messages can be lost + }; + + void onDisconnect(NimBLEServer* pServer) { + pServer->startAdvertising(); // restart advertising + NIMBLE_LOGI(LOG_TAG, "BLE client disconnected, started advertising"); + } +}; + +class BLESerialCharacteristicCallbacks: public NimBLECharacteristicCallbacks { + friend class BLESerial; + BLESerial* bleSerial; + + void onWrite(NimBLECharacteristic *pCharacteristic) { + bleSerial->receiveBuffer += pCharacteristic->getValue(); + } + +}; +#else class BLESerialServerCallbacks: public BLEServerCallbacks { friend class BLESerial; @@ -35,16 +64,18 @@ class BLESerialCharacteristicCallbacks: public BLECharacteristicCallbacks { BLESerial* bleSerial; void onWrite(BLECharacteristic *pCharacteristic) { - bleSerial->receiveBuffer = bleSerial->receiveBuffer + pCharacteristic->getValue(); + bleSerial->receiveBuffer += pCharacteristic->getValue(); } }; +#endif + // Constructor BLESerial::BLESerial() - : pService(NULL) - , pTxCharacteristic(NULL) + : pService(nullptr) + , pTxCharacteristic(nullptr) , receiveBuffer("") { } @@ -60,6 +91,15 @@ BLESerial::~BLESerial(void) bool BLESerial::begin(const char* localName) { +#ifdef USE_NIMBLE + // Create the BLE Device + NimBLEDevice::init(localName); + + // Create the BLE Server + pServer = NimBLEDevice::createServer(); + if (pServer == nullptr) + return false; +#else // Create the BLE Device BLEDevice::init(localName); @@ -67,6 +107,7 @@ bool BLESerial::begin(const char* localName) pServer = BLEDevice::createServer(); if (pServer == nullptr) return false; +#endif BLESerialServerCallbacks* bleSerialServerCallbacks = new BLESerialServerCallbacks(); bleSerialServerCallbacks->bleSerial = this; @@ -77,26 +118,53 @@ bool BLESerial::begin(const char* localName) if (pService == nullptr) return false; +#ifdef USE_NIMBLE // Create a BLE Characteristic + pTxCharacteristic = pService->createCharacteristic( + CHARACTERISTIC_UUID_TX, + NIMBLE_PROPERTY::NOTIFY + ); + if (pTxCharacteristic == nullptr) + return false; + + NimBLECharacteristic * pRxCharacteristic = pService->createCharacteristic( + CHARACTERISTIC_UUID_RX, + NIMBLE_PROPERTY::WRITE | + NIMBLE_PROPERTY::WRITE_NR + ); +#else pTxCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY ); if (pTxCharacteristic == nullptr) return false; - pTxCharacteristic->addDescriptor(new BLE2902()); BLECharacteristic * pRxCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_WRITE_NR - ); + ); +#endif + if (pRxCharacteristic == nullptr) return false; BLESerialCharacteristicCallbacks* bleSerialCharacteristicCallbacks = new BLESerialCharacteristicCallbacks(); bleSerialCharacteristicCallbacks->bleSerial = this; pRxCharacteristic->setCallbacks(bleSerialCharacteristicCallbacks); +#ifdef USE_NIMBLE + // Start the service + pService->start(); + NIMBLE_LOGI(LOG_TAG , "BLE started service"); + // Start advertising + NimBLEAdvertising* pAdvertising = NimBLEDevice::getAdvertising(); + pAdvertising->addServiceUUID(pService->getUUID()); + pAdvertising->setScanResponse(true); + pAdvertising->start(); + NIMBLE_LOGI(LOG_TAG ,"BLE started advertising and waiting for client connection..."); + return true; +#else // Start the service pService->start(); LOG_INFO("BLE started service"); @@ -109,6 +177,7 @@ bool BLESerial::begin(const char* localName) pServer->getAdvertising()->start(); LOG_INFO("BLE started advertising and waiting for client connection..."); return true; +#endif } int BLESerial::available(void) diff --git a/src/loraprs_service.cpp b/src/loraprs_service.cpp index 66dbaae..b86f333 100644 --- a/src/loraprs_service.cpp +++ b/src/loraprs_service.cpp @@ -16,7 +16,9 @@ Service::Service() , rigCurrentTxPacketSize_(0) , isIsrInstalled_(false) , rigIsImplicitMode_(false) +#ifndef USE_NIMBLE , serialBt_() +#endif , serialBLE_() , kissServer_(new WiFiServer(CfgKissPort)) , isKissClientConnected_(false) @@ -245,8 +247,13 @@ void Service::setupRig(long loraFreq, long bw, int sf, int cr, int pwr, int sync } rig_->setCRC(crcBytes); rig_->setPreambleLength(config_.LoraPreamble); -#ifdef USE_SX126X - #pragma message("Using SX126X") +#if defined(USE_SX126X) && MODULE_NAME == SX1262 + #pragma message("Using SX1262") + LOG_INFO("Using SX1262 module"); + if (isIsrInstalled_) rig_->clearDio1Action(); + rig_->setDio1Action(onRigIsrRxPacket); + isIsrInstalled_ = true; +#elif defined(USE_SX126X) LOG_INFO("Using SX126X module"); rig_->setRfSwitchPins(config_.LoraPinSwitchRx, config_.LoraPinSwitchTx); if (isIsrInstalled_) rig_->clearDio1Action(); @@ -288,13 +295,22 @@ void Service::setupRigFsk(long freq, float bitRate, float freqDev, float rxBw, i LOG_ERROR("Radio start error:", state); } rig_->disableAddressFiltering(); -#ifdef USE_SX126X + + #if defined(USE_SX126X) && MODULE_NAME == SX1262 + #pragma message("Using SX1262") + LOG_INFO("Using SX1262 module"); + if (isIsrInstalled_) rig_->clearDio1Action(); + rig_->setDio1Action(onRigIsrRxPacket); + isIsrInstalled_ = true; + +#elif defined(USE_SX126X) #pragma message("Using SX126X") LOG_INFO("Using SX126X module"); rig_->setRfSwitchPins(config_.LoraPinSwitchRx, config_.LoraPinSwitchTx); if (isIsrInstalled_) rig_->clearDio1Action(); rig_->setDio1Action(onRigIsrRxPacket); isIsrInstalled_ = true; + #else #pragma message("Using SX127X") LOG_INFO("Using SX127X module"); @@ -316,9 +332,13 @@ void Service::setupBt(const String &btName) String btType = config_.BtEnableBle ? "BLE" : "BT"; LOG_INFO(btType, "init", btName); - bool btOk = config_.BtEnableBle + bool btOk = config_.BtEnableBle ? serialBLE_.begin(btName.c_str()) + #ifdef USE_NIMBLE + : false; + #else : serialBt_.begin(btName); + #endif if (btOk) { LOG_INFO(btType, "initialized"); @@ -725,12 +745,18 @@ void Service::onSerialTx(byte b) else if (isKissClientConnected_) { kissConnnection_.write(b); } + #ifndef USE_NIMBLE else if (config_.BtEnableBle) { serialBLE_.write(b); } else { serialBt_.write(b); } + #else + else { + serialBLE_.write(b); + } + #endif } bool Service::onSerialRxHasData() @@ -741,12 +767,23 @@ bool Service::onSerialRxHasData() else if (isKissClientConnected_) { return kissConnnection_.available(); } + + #ifndef USE_NIMBLE + else if (config_.BtEnableBle) { return serialBLE_.available(); } else { return serialBt_.available(); } + + #else + + else { + return serialBLE_.available(); + } + + #endif } bool Service::onSerialRx(byte *b) @@ -767,7 +804,12 @@ bool Service::onSerialRx(byte *b) else { rxResult = config_.BtEnableBle ? serialBLE_.read() + #ifdef USE_NIMBLE + : -1; + #else : serialBt_.read(); + #endif + } if (rxResult == -1) { return false;