what was printed as output wasn't understood, i'd post a screenshot. BTW, i found that i could use getBytes() to read byte by byte and then copy into a char array. I'd see if it gives me a different result. Also, ble with ESP32 is quite easy, you can setup within minutes. If you have one laying around, maybe i could send you my code, flash it and download an app to send the token. Let me know if you'd be willing to try. But in all, i appreciate your help so far.
Ok, here's a chunk of code based on what you PM'd me. There are huge caveats attached to the code in that I have almost no experience with BLE and it is purely a demonstration of receiving and decoding a JSON Web Token (without the final decryption stage).
The encoded data doesn't end with a NULL char as far as I can see, so I had to put together a basic timeout so that I could assume that the whole encoded token had been received after a period of no data being received. Maybe there's some clever BLE code that does this already - I don't know (see caveat above!).
Compiled for an ESP32-CAM and tried out using the token from post #90.
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
Ported to Arduino ESP32 by Evandro Copercini
updated by chegewara and MoThunderz
*/
#include "base64.hpp"
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
// Initialize all pointers
BLEServer* pServer = NULL; // Pointer to the server
BLECharacteristic* pCharacteristic = NULL; // Pointer to Characteristic 1
// Some variables to keep track on device connected
bool deviceConnected = false;
bool oldDeviceConnected = false;
// BLE timeout (2 seconds) used to detect end of transmission
const uint32_t bleMillisTimeout = 2000;
const uint16_t maxEncBuffSize = 1700;
volatile char encDataBuff[ maxEncBuffSize ];
volatile uint16_t encBuffPtr = 0;
volatile bool bleReceiveInProgress = false;
volatile uint32_t bleCommsMillis = 0;
uint32_t currentMillis = 0;
bool tokenReceived = false;
// these arrays hold the BASE64 decoded data
char headerStr[128];
char payloadStr[2000];
uint8_t encryptedSig[128];
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
// UUIDs used in this example:
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID_1 "0ceb186c-853a-460a-a743-8d07fd6ff031"
// Callback function that is called whenever a client is connected or disconnected
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
class CharacteristicCallBack: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pChar) override {
std::string rxValue = pChar -> getValue();
if (rxValue.length() > 0) {
bleCommsMillis = millis();
bleReceiveInProgress = true;
// transfer the received data into our big encoded data array
for (uint16_t i = 0; i < rxValue.length(); i++) {
if ( encBuffPtr < maxEncBuffSize-1 ) {
encDataBuff[ encBuffPtr++ ] = rxValue[i];
// make sure it's always NULL terminated
encDataBuff[ encBuffPtr ] = 0;
}
}
Serial.println(encBuffPtr);
}
}
};
void setup() {
Serial.begin(115200);
// Create the BLE Device
BLEDevice::init("ESP32");
// 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
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_1,
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY
);
// add callback functions here:
pCharacteristic->setCallbacks(new CharacteristicCallBack());
// Start the service
pService->start();
// Start advertising
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(false);
pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter
BLEDevice::startAdvertising();
}
void loop() {
uint16_t delimCounter = 0;
uint16_t idx;
char *ch;
// The code below keeps the connection status uptodate:
// Disconnecting
if (!deviceConnected && oldDeviceConnected) {
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
//Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// Connecting
if (deviceConnected && !oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}
// try and figure out when we may have received a complete JSON Web Token packet
// by assuming BLE comms has finished if no activity for 2 seconds (a guess!!)
// as there doesn't appear to be any indication from the sending device that
// a transmission has finished.
currentMillis = millis();
if ( bleReceiveInProgress == true ) {
if (( currentMillis - bleCommsMillis ) > bleMillisTimeout ) {
Serial.println("ble token received - maybe?");
bleReceiveInProgress = false;
tokenReceived = true;
}
}
// finshed receiving some data? - lets see if it's a JSON Web Token
if ( tokenReceived == true ) {
delimCounter = 0;
// simple check to see if the received token has 2 dots - i.e. '.'
// and replace the BASE64URL chars with standard BASE64 chars
for (idx=0; idx<encBuffPtr; idx++) {
if ( encDataBuff[idx] == '.' ) delimCounter++;
if ( encDataBuff[idx] == '-' ) encDataBuff[idx] = '+';
if ( encDataBuff[idx] == '_' ) encDataBuff[idx] = '/';
}
if ( delimCounter != 2 ) {
// didn't get 2 dots so not the whole packet
Serial.println("ERR: Didn't get 2 dots.");
tokenReceived = false;
encBuffPtr = 0;
}
else
{
// might have an encoded JWT so try and decode it
ch = strtok( (char *)encDataBuff, "." );
BASE64::decode( ch, (uint8_t*) headerStr );
ch = strtok( NULL, "." );
BASE64::decode( ch, (uint8_t*) payloadStr );
ch = strtok( NULL, "." );
BASE64::decode( ch, encryptedSig );
Serial.print("\nDecoded Header: (");
Serial.println( headerStr );
Serial.print("\nDecoded Payload: (");
Serial.println( payloadStr );
Serial.print("\nDecoded Signature: (");
for (idx=0; idx<BASE64::decodeLength(ch); idx++ ) {
if ( encryptedSig[idx] < 0x10 ) Serial.print( '0' );
Serial.print( encryptedSig[idx], HEX );
Serial.print( ' ' );
if ( idx%16 == 15 ) Serial.println();
}
Serial.println();
}
tokenReceived = false;
encBuffPtr = 0;
}
}
Wow!!!...gonna give this a try soon and revert....i knew i'd to give the packets sometime to fully arrive. Your code captured that well...Can't wait to try.
Ok so i gave it a try although with another token entirely and it worked to a large extent. With few tweaks here and there, it's now decoding just fine. Thanks again Mark.
Excellent - good luck with your project.
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.