LoRa_APRS_Tracker111/src/bluetooth_utils.cpp

142 lines
4.7 KiB
C++

#include <TinyGPS++.h>
#include <esp_bt.h>
#include "bluetooth_utils.h"
#include "configuration.h"
#include "KISS_TO_TNC2.h"
#include "lora_utils.h"
#include "display.h"
#include "logger.h"
extern Configuration Config;
extern BluetoothSerial SerialBT;
extern logging::Logger logger;
extern TinyGPSPlus gps;
extern bool bluetoothConnected;
extern bool bluetoothActive;
namespace BLUETOOTH_Utils {
String serialReceived;
bool shouldSendToLoRa = false;
bool useKiss = false;
void setup() {
if (!bluetoothActive) {
btStop();
esp_bt_controller_disable();
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "BT controller disabled");
return;
}
serialReceived.reserve(255);
SerialBT.register_callback(BLUETOOTH_Utils::bluetoothCallback);
SerialBT.onData(BLUETOOTH_Utils::getData); // callback instead of while to avoid RX buffer limit when NMEA data received
uint8_t dmac[6];
esp_efuse_mac_get_default(dmac);
char ourId[5];
snprintf(ourId, sizeof(ourId), "%02x%02x", dmac[4], dmac[5]);
if (!SerialBT.begin(String("LoRa Tracker " + String(ourId)))) {
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "Bluetooth", "Starting Bluetooth failed!");
show_display("ERROR", "Starting Bluetooth failed!");
while(true) {
delay(1000);
}
}
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Bluetooth", "Bluetooth init done!");
}
void bluetoothCallback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) {
if (event == ESP_SPP_SRV_OPEN_EVT) {
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Bluetooth", "Client connected !");
bluetoothConnected = true;
useKiss = false;
} else if (event == ESP_SPP_CLOSE_EVT) {
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Bluetooth", "Client disconnected !");
bluetoothConnected = false;
} else {
logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "Bluetooth", "Status: %d", event);
}
}
void getData(const uint8_t *buffer, size_t size) {
if (size == 0) {
return;
}
shouldSendToLoRa = false;
serialReceived.clear();
bool isNmea = buffer[0] == '$';
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "bluetooth", "Received buffer size %d. Nmea=%d. %s", size, isNmea, buffer);
for (int i = 0; i < size; i++) {
logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "bluetooth", "[%d/%d] %x -> %c", i + 1, size, buffer[i], buffer[i]);
}
for (int i = 0; i < size; i++) {
char c = (char) buffer[i];
if (isNmea) {
gps.encode(c);
} else {
serialReceived += c;
}
}
// Test if we have to send frame
isNmea = serialReceived.indexOf("$G") != -1 || serialReceived.indexOf("$B") != -1;
if (isNmea) {
useKiss = false;
}
if (isNmea || serialReceived.isEmpty()) {
return;
}
if (validateKISSFrame(serialReceived)) {
bool dataFrame;
String decodeKiss = decode_kiss(serialReceived, dataFrame);
serialReceived.clear();
serialReceived += decodeKiss;
logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "bluetooth", "It's a kiss frame. dataFrame: %d", dataFrame);
useKiss = true;
} else {
useKiss = false;
}
if (validateTNC2Frame(serialReceived)) {
shouldSendToLoRa = true;
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "bluetooth",
"Data received should be transmitted to RF => %s", serialReceived.c_str());
// because we can't send data here
}
}
void sendToLoRa() {
if (!shouldSendToLoRa) {
return;
}
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "BT TX", "%s", serialReceived.c_str());
show_display("BT Tx >>", "", serialReceived, 1000);
LoRa_Utils::sendNewPacket(serialReceived);
shouldSendToLoRa = false;
}
void sendPacket(const String& packet) {
if (bluetoothActive && !packet.isEmpty()) {
if (useKiss) {
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "BT RX Kiss", "%s", serialReceived.c_str());
SerialBT.println(encode_kiss(packet));
} else {
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "BT RX TNC2", "%s", serialReceived.c_str());
SerialBT.println(packet);
}
}
}
}