You cannot assume that every byte will arrive instantaneously ... Serial.availble() may say there is nothing left to receive... because you are asking the question more often than bytes are received. Generally serial is slower than your micro-controller .. you need to handle this.
#include "BluetoothSerial.h"
const byte LED = 2;
const byte MaxMessageLength = 10;
BluetoothSerial SerialBT;
String message = "";
void setup() {
pinMode(LED, OUTPUT);
Serial.begin(115200);
if(!SerialBT.begin("ESP32")){
Serial.println("An error occurred initializing Bluetooth");
}
digitalWrite(LED, HIGH);
}
void loop() {
if (MessageReceived()) React();
}
boolean MessageReceived(){ // Returns TRUE if either \r or \n was received
boolean complete = false;
while (SerialBT.available()) {
char incomingChar = SerialBT.read();
if (incomingChar == '\r' || incomingChar == '\n') {
complete = true;
} else message += String(incomingChar);
// If required we discard messages which are too long:
if (message.length() > MaxMessageLength) message = "";
}
// If the message is not "complete" (no \r or \n received or too long)
// it will go on collecting characters in the next loop
return complete;
}
void React(){
if (message == "on") {
digitalWrite(LED, HIGH);
}
// no real need for "else" as the comparison(s) do not require much time
// and all used commands exclude each other
// This makes it easier to expand the list of messages
// and to follow the program sequence
if (message == "off") {
digitalWrite(LED, LOW);
}
Serial.print("<");
Serial.print(message);
Serial.println(">");
message = ""; // Reset the message here after evaluation, reaction and printing
}
It uses a receiving routine which is independent from delays between single characters of a message and also discards messages which are too long thus avoiding an overflow.
In most cases in the "real world" these problems will not occur, but to take care of Murphy's Law (If something bad can happen it will happen) ...