Search code examples
c++arduinobluetoothmicrocontrolleresp32

Convert string received from BTSerial to HEX string


I have an App where I send Hex-Strings to my ESP32. I would like these strings, as they are, to be sent via an RS232 to TTL module, that is connected to my ESP, to a scaler.

On my App side I am sending this command:

"\\e\\x34\\x54\\x45\\x53\\x54\\r" //This translates to ascii ESC4TESTCarriageReturn

It needs double escaped characters in order to actually send a single backslash.

On my microcontroller side I am doing:

//This reads the incoming BT message
String message = SerialBT.readStringUntil('\n');
//This sends the message, converted to a char * 
Serial2.write(message.c_str());

In theory, I am receiving the correct string as you can see in the serial monitor output:

BT Message received: \e\x34\x54\x45\x53\x54\r
The command to be sent via rs232: \e\x34\x54\x45\x53\x54\r
Error: E10 //This indicates that the message could not be processed by the receiver

However, if I send the message staright up like this, predefined in my microcontroller code I get the correct response from the receiver:

Serial2.write("\e\x34\x54\x45\x53\x54\r");

------ Output ------
Test4 //This indicates that Testpattern 4 was selected

I am not that familiar with c++ so I am probably doing something obviously wrong, maybe anyone knows, how I can convert the received BT-Message to an actual message that can be sent over Serial2.

Edit: So basically my question is, how can I achieve a transaltion of the string that I am receiving via bluetooth (\e\x34\x54\x45\x53\x54\r) to be converted as it is, into a Hex-string that is interpreted correctly by the microcontroller and is therefore correctly sent over rs232.


Solution

  • The solution is to write an own parser. Since you say you control the BT sender side, you don't need all of the common capabilities of the C++ standard.

    We see these different kinds of substrings for single characters:

    • "\e" for '\e';
    • "\x##" for '\x##', "##" being a two-digit hex number;
    • "\r" for '\r'.

    This is a small test sketch for a straight-forward solution:

    void setup() {
      while (!Serial);
      String message = "\\e\\x34\\x54\\x45\\x53\\x54\\r";
      Serial.println(message);
      String toSend = unescape(message);
      for (int c : toSend) {
        Serial.print(c, HEX);
      }
      Serial.println();
    }
    
    void loop() {
    }
    
    String unescape(String &escaped) {
      String unescaped;
      for (size_t index = 0; index < escaped.length(); index++) {
        if (escaped[index] == '\\') {
          index++;
          switch (escaped[index]) {
          case 'e':
            unescaped += '\e';
            break;
          case 'x':
            index++;
            {
              char hex = strtol(escaped.substring(index, index + 2).c_str(), 0, 16);
              unescaped += hex;
            }
            index++;
            break;
          case 'r':
            unescaped += '\r';
            break;
          default:
            break;
          }
        }
      }
      return unescaped;
    }
    

    Please note that this simple suggestion has some minor issues you don't want in professional software:

    • It does no error checks in unescape(). Actually, it silently returns an incomplete or erroneous result, if the input has errors.
    • It uses Arduino's String that is slow and bulky.

    Use it as a starting point for your own better solution.