2018-10-18 09:49:14 +00:00
|
|
|
#include "Bluetooth.h"
|
|
|
|
#include "pins.h"
|
2018-10-20 07:11:23 +00:00
|
|
|
#include "Protocol.h"
|
|
|
|
#include "debugport.h"
|
2018-10-18 09:49:14 +00:00
|
|
|
|
2018-10-20 07:11:23 +00:00
|
|
|
#ifdef ESP32
|
2018-10-18 09:49:14 +00:00
|
|
|
|
2018-10-27 06:35:17 +00:00
|
|
|
#define ESP32_USE_HC05
|
|
|
|
|
2018-10-20 07:11:23 +00:00
|
|
|
const int LED = 2;
|
2018-10-18 09:49:14 +00:00
|
|
|
|
|
|
|
// ESP32
|
|
|
|
|
2018-10-20 11:28:32 +00:00
|
|
|
sRxLine RxLine;
|
2018-10-18 09:49:14 +00:00
|
|
|
|
2018-10-27 06:35:17 +00:00
|
|
|
#ifdef ESP32_USE_HC05
|
|
|
|
|
|
|
|
//static HardwareSerial& Bluetooth(Serial2); // TODO: make proper ESP32 BT client
|
|
|
|
|
|
|
|
bool Bluetooth_ATCommand(const char* cmd);
|
|
|
|
|
|
|
|
const int BTRates[] = {
|
|
|
|
9600, 38400, 115200, 19200, 57600, 2400, 4800, 1200
|
|
|
|
};
|
|
|
|
|
|
|
|
bool bHC05Available = false;
|
|
|
|
|
|
|
|
void Bluetooth_Init()
|
|
|
|
{
|
|
|
|
RxLine.clear();
|
|
|
|
|
|
|
|
// search for BlueTooth adapter, trying the common baud rates, then less common
|
|
|
|
// as the device cannot be guaranteed to power up with the key pin high
|
|
|
|
// we are at the mercy of the baud rate stored in the module.
|
|
|
|
digitalWrite(KeyPin, HIGH);
|
|
|
|
delay(5000);
|
|
|
|
Serial2.begin(9600, SERIAL_8N1, Rx2Pin, Tx2Pin); // need to explicitly specify pins for pin multiplexer!);
|
|
|
|
|
|
|
|
DebugPort.println("\r\n\r\nAttempting to detect HC-05 Bluetooth module...");
|
|
|
|
|
|
|
|
int BTidx = 0;
|
|
|
|
int maxTries = sizeof(BTRates)/sizeof(int);
|
|
|
|
for(BTidx = 0; BTidx < maxTries; BTidx++) {
|
|
|
|
DebugPort.print(" @ ");
|
|
|
|
DebugPort.print(BTRates[BTidx]);
|
|
|
|
DebugPort.print(" baud... ");
|
|
|
|
Serial2.begin(BTRates[BTidx], SERIAL_8N1, Rx2Pin, Tx2Pin); // open serial port at a certain baud rate
|
|
|
|
delay(100);
|
|
|
|
Serial2.print("\r\n");
|
|
|
|
Serial2.setTimeout(100);
|
|
|
|
|
|
|
|
if(Bluetooth_ATCommand("AT\r\n")) {
|
|
|
|
DebugPort.println(" OK.");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(Bluetooth_ATCommand("AT\r\n")) {
|
|
|
|
DebugPort.println(" OK.");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// failed, try another baud rate
|
|
|
|
DebugPort.println("");
|
|
|
|
Serial2.flush();
|
|
|
|
Serial2.end();
|
|
|
|
delay(1000);
|
|
|
|
}
|
|
|
|
|
|
|
|
DebugPort.println("");
|
|
|
|
if(BTidx == maxTries) {
|
|
|
|
DebugPort.println("FAILED to detect HC-05 Bluetooth module :-(");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/*// if(BTRates[BTidx] == 115200) {
|
|
|
|
if(BTRates[BTidx] == 9600) {
|
|
|
|
// DebugPort.println("HC-05 found and already set to 115200 baud, skipping Init.");
|
|
|
|
DebugPort.println("HC-05 found and already set to 9600 baud, skipping Init.");
|
|
|
|
bHC05Available = true;
|
|
|
|
}
|
|
|
|
else*/ {
|
|
|
|
do {
|
|
|
|
DebugPort.println("HC-05 found");
|
|
|
|
|
|
|
|
DebugPort.print(" Setting Name to \"Diesel Heater\"... ");
|
|
|
|
if(!Bluetooth_ATCommand("AT+NAME=\"Diesel Heater\"\r\n")) {
|
|
|
|
DebugPort.println("FAILED");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
DebugPort.println("OK");
|
|
|
|
|
|
|
|
// DebugPort.print(" Setting baud rate to 115200N81...");
|
|
|
|
// if(!Bluetooth_ATCommand("AT+UART=115200,1,0\r\n")) {
|
|
|
|
DebugPort.print(" Setting baud rate to 9600N81...");
|
|
|
|
if(!Bluetooth_ATCommand("AT+UART=9600,1,0\r\n")) {
|
|
|
|
DebugPort.println("FAILED");
|
|
|
|
break;
|
|
|
|
};
|
|
|
|
DebugPort.println("OK");
|
|
|
|
|
|
|
|
// Serial2.begin(115200, SERIAL_8N1, Rx2Pin, Tx2Pin);
|
|
|
|
Serial2.begin(9600, SERIAL_8N1, Rx2Pin, Tx2Pin);
|
|
|
|
bHC05Available = true;
|
|
|
|
|
|
|
|
} while(0);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
digitalWrite(KeyPin, LOW); // leave HC-05 command mode
|
|
|
|
|
|
|
|
delay(500);
|
|
|
|
|
|
|
|
if(!bHC05Available)
|
|
|
|
Serial2.end(); // close serial port if no module found
|
|
|
|
|
|
|
|
DebugPort.println("");
|
|
|
|
}
|
|
|
|
|
|
|
|
void Bluetooth_Check()
|
|
|
|
{
|
|
|
|
// check for data coming back over Bluetooth
|
|
|
|
if(bHC05Available) {
|
|
|
|
if(Serial2.available()) {
|
|
|
|
char rxVal = Serial2.read();
|
|
|
|
if(isControl(rxVal)) { // "End of Line"
|
|
|
|
Command_Interpret(RxLine.Line);
|
|
|
|
RxLine.clear();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
RxLine.append(rxVal); // append new char to our Rx buffer
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Bluetooth_SendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm)
|
|
|
|
{
|
|
|
|
DebugPort.print(millis());
|
|
|
|
DebugReportFrame(pHdr, Frame, lineterm ? "\r\n" : " ");
|
|
|
|
|
|
|
|
if(bHC05Available) {
|
|
|
|
if(Frame.verifyCRC()) {
|
|
|
|
digitalWrite(LED, !digitalRead(LED)); // toggle LED
|
|
|
|
Serial2.print(pHdr);
|
|
|
|
Serial2.write(Frame.Data, 24);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DebugPort.print("Bluetooth data not sent, CRC error ");
|
|
|
|
DebugPort.println(pHdr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DebugPort.println("No Bluetooth client");
|
|
|
|
digitalWrite(LED, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// local function, typically to perform Hayes commands with HC-05
|
|
|
|
bool Bluetooth_ATCommand(const char* cmd)
|
|
|
|
{
|
|
|
|
// if(bHC05Available) {
|
|
|
|
Serial2.print(cmd);
|
|
|
|
char RxBuffer[16];
|
|
|
|
memset(RxBuffer, 0, 16);
|
|
|
|
int read = Serial2.readBytesUntil('\n', RxBuffer, 16); // \n is not included in returned string!
|
|
|
|
if((read == 3) && (0 == strcmp(RxBuffer, "OK\r")) ) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
// }
|
|
|
|
// return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else // ESP32_USE_HC05
|
2018-10-18 09:49:14 +00:00
|
|
|
#ifndef ESP32_USE_BLE_RLJ
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// CLASSIC BLUETOOTH
|
|
|
|
// |
|
|
|
|
// V
|
|
|
|
|
|
|
|
|
|
|
|
#include "BluetoothSerial.h"
|
|
|
|
|
|
|
|
BluetoothSerial SerialBT;
|
|
|
|
|
|
|
|
void Bluetooth_Init()
|
|
|
|
{
|
2018-10-20 11:28:32 +00:00
|
|
|
RxLine.clear();
|
2018-10-20 07:11:23 +00:00
|
|
|
pinMode(LED, OUTPUT);
|
|
|
|
|
2018-10-18 09:49:14 +00:00
|
|
|
if(!SerialBT.begin("ESPHEATER")) {
|
2018-10-20 07:11:23 +00:00
|
|
|
DebugPort.println("An error occurred initialising Bluetooth");
|
2018-10-18 09:49:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Bluetooth_Check()
|
|
|
|
{
|
|
|
|
if(SerialBT.available()) {
|
|
|
|
char rxVal = SerialBT.read();
|
|
|
|
if(isControl(rxVal)) { // "End of Line"
|
2018-10-20 11:28:32 +00:00
|
|
|
Command_Interpret(RxLine.Line);
|
|
|
|
RxLine.clear();
|
2018-10-18 09:49:14 +00:00
|
|
|
}
|
|
|
|
else {
|
2018-10-20 11:28:32 +00:00
|
|
|
RxLine.append(rxVal);
|
2018-10-18 09:49:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-20 11:28:32 +00:00
|
|
|
void Bluetooth_SendFrame(const char* pHdr, const CProtocol& Frame, bool lineterm)
|
2018-10-18 09:49:14 +00:00
|
|
|
{
|
2018-10-27 06:35:17 +00:00
|
|
|
char fullMsg[32];
|
|
|
|
|
|
|
|
DebugPort.print(millis());
|
2018-10-20 11:28:32 +00:00
|
|
|
DebugReportFrame(pHdr, Frame, lineterm ? "\r\n" : " ");
|
2018-10-27 06:35:17 +00:00
|
|
|
delay(40);
|
2018-10-18 09:49:14 +00:00
|
|
|
if(SerialBT.hasClient()) {
|
2018-10-20 07:11:23 +00:00
|
|
|
|
|
|
|
if(Frame.verifyCRC()) {
|
|
|
|
digitalWrite(LED, !digitalRead(LED)); // toggle LED
|
2018-10-27 06:35:17 +00:00
|
|
|
int len = strlen(pHdr);
|
|
|
|
if(len < 8) {
|
|
|
|
strcpy(fullMsg, pHdr);
|
|
|
|
memcpy(&fullMsg[len], Frame.Data, 24);
|
|
|
|
SerialBT.write((uint8_t*)fullMsg, 24+len);
|
|
|
|
}
|
|
|
|
/* SerialBT.print(pHdr);
|
|
|
|
delay(1);
|
|
|
|
SerialBT.write(Frame.Data, 24);*/
|
|
|
|
delay(10);
|
2018-10-20 07:11:23 +00:00
|
|
|
}
|
|
|
|
else {
|
2018-10-20 11:28:32 +00:00
|
|
|
DebugPort.println("Data not sent to Bluetooth, CRC error!");
|
2018-10-20 07:11:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2018-10-20 11:28:32 +00:00
|
|
|
DebugPort.println("No Bluetooth client");
|
2018-10-20 07:11:23 +00:00
|
|
|
digitalWrite(LED, 0);
|
2018-10-18 09:49:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-27 06:35:17 +00:00
|
|
|
void Bluetooth_SendACK()
|
|
|
|
{
|
|
|
|
/* if(SerialBT.hasClient()) {
|
|
|
|
SerialBT.print("[ACK]");
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-10-18 09:49:14 +00:00
|
|
|
// ^
|
|
|
|
// |
|
|
|
|
// CLASSIC BLUETOOTH
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#else // ESP32_USE_BLE_RLJ
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// BLE
|
|
|
|
// |
|
|
|
|
// V
|
|
|
|
|
|
|
|
|
|
|
|
#include <BLEDevice.h>
|
|
|
|
#include <BLEServer.h>
|
|
|
|
#include <BLEUtils.h>
|
|
|
|
#include <BLE2902.h>
|
|
|
|
|
|
|
|
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
|
|
|
|
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
|
|
|
|
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
|
|
|
|
|
|
|
|
void BLE_Send(std::string Data);
|
|
|
|
|
|
|
|
BLEServer *pServer = NULL;
|
|
|
|
BLECharacteristic* pTxCharacteristic = NULL;
|
|
|
|
volatile bool deviceConnected = false;
|
|
|
|
bool oldDeviceConnected = false;
|
|
|
|
|
|
|
|
class MyServerCallbacks : public BLEServerCallbacks {
|
|
|
|
|
|
|
|
void onConnect(BLEServer* pServer) {
|
|
|
|
deviceConnected = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void onDisconnect(BLEServer* pServer) {
|
|
|
|
deviceConnected = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class MyCallbacks : public BLECharacteristicCallbacks {
|
|
|
|
|
|
|
|
// this callback is called when the ESP WRITE characteristic has been written to by a client
|
|
|
|
// We need to *read* the new information!
|
|
|
|
void onWrite(BLECharacteristic* pCharacteristic) {
|
|
|
|
|
|
|
|
std::string rxValue = pCharacteristic->getValue();
|
|
|
|
|
|
|
|
while(rxValue.length() > 0) {
|
|
|
|
char rxVal = rxValue[0];
|
|
|
|
if(isControl(rxVal)) { // "End of Line"
|
2018-10-20 07:11:23 +00:00
|
|
|
Command_Interpret(BluetoothRxLine);
|
2018-10-18 09:49:14 +00:00
|
|
|
BluetoothRxLine = "";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BluetoothRxLine += rxVal; // append new char to our Rx buffer
|
|
|
|
}
|
|
|
|
rxValue.erase(0, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
void Bluetooth_Init()
|
|
|
|
{
|
|
|
|
// create the BLE device
|
|
|
|
BLEDevice::init("DieselHeater");
|
|
|
|
|
|
|
|
// create the BLE server
|
|
|
|
pServer = BLEDevice::createServer();
|
|
|
|
pServer->setCallbacks(new MyServerCallbacks);
|
|
|
|
|
|
|
|
// create the BLE service
|
|
|
|
BLEService *pService = pServer->createService(SERVICE_UUID);
|
|
|
|
|
|
|
|
// create a BLE characteristic
|
|
|
|
pTxCharacteristic = pService->createCharacteristic(
|
|
|
|
CHARACTERISTIC_UUID_TX,
|
|
|
|
BLECharacteristic::PROPERTY_NOTIFY
|
|
|
|
);
|
|
|
|
pTxCharacteristic->addDescriptor(new BLE2902());
|
|
|
|
|
|
|
|
|
|
|
|
BLECharacteristic* pRxCharacteristic = pService->createCharacteristic(
|
|
|
|
CHARACTERISTIC_UUID_RX,
|
|
|
|
BLECharacteristic::PROPERTY_WRITE
|
|
|
|
);
|
|
|
|
pRxCharacteristic->setCallbacks(new MyCallbacks/*()*/);
|
|
|
|
|
|
|
|
// start the service
|
|
|
|
pService->start();
|
|
|
|
// start advertising
|
|
|
|
pServer->getAdvertising()->start();
|
2018-10-20 07:11:23 +00:00
|
|
|
DebugPort.println("Awaiting a client to notify...");
|
2018-10-18 09:49:14 +00:00
|
|
|
}
|
|
|
|
|
2018-10-20 07:11:23 +00:00
|
|
|
void Bluetooth_Report(const char* pHdr, const CProtocol& Frame)
|
2018-10-18 09:49:14 +00:00
|
|
|
{
|
|
|
|
if(deviceConnected) {
|
2018-10-20 07:11:23 +00:00
|
|
|
if(Frame.verifyCRC()) {
|
|
|
|
// BLE can only squirt 20 bytes per packet.
|
|
|
|
// build the entire message then divide and conquer
|
|
|
|
std::string txData = pHdr;
|
|
|
|
txData.append((char*)Frame.Data, 24);
|
2018-10-18 09:49:14 +00:00
|
|
|
|
2018-10-20 07:11:23 +00:00
|
|
|
BLE_Send(txData);
|
|
|
|
}
|
2018-10-18 09:49:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Bluetooth_Check()
|
|
|
|
{
|
|
|
|
// disconnecting
|
|
|
|
if (!deviceConnected && oldDeviceConnected) {
|
|
|
|
delay(500); // give the bluetooth stack the chance to get things ready
|
|
|
|
pServer->startAdvertising(); // restart advertising
|
2018-10-20 07:11:23 +00:00
|
|
|
DebugPort.println("start advertising");
|
2018-10-18 09:49:14 +00:00
|
|
|
oldDeviceConnected = deviceConnected;
|
|
|
|
}
|
|
|
|
// connecting
|
|
|
|
if (deviceConnected && !oldDeviceConnected) {
|
|
|
|
// do stuff here on connecting
|
|
|
|
oldDeviceConnected = deviceConnected;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// break down supplied string into 20 byte chunks (or less)
|
|
|
|
// BLE can only handle 20 bytes per packet!
|
|
|
|
void BLE_Send(std::string Data)
|
|
|
|
{
|
|
|
|
while(!Data.empty()) {
|
|
|
|
std::string substr = Data.substr(0, 20);
|
|
|
|
int len = substr.length();
|
|
|
|
pTxCharacteristic->setValue((uint8_t*)Data.data(), len);
|
|
|
|
pTxCharacteristic->notify();
|
|
|
|
Data.erase(0, len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ^
|
|
|
|
// |
|
|
|
|
// BLE
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#endif // ESP32_USE_BLE_RLJ
|
|
|
|
|
2018-10-27 06:35:17 +00:00
|
|
|
#endif // ESP32_USE_HC05
|
|
|
|
|
|
|
|
#endif // __ESP32__
|