Pairing/Bonding rak4631

hello I want to design a project using the rak4631 and an obd2 ELM327, however I am in conflict since I do not know if I can pair the elm327 with the rak4631 module via bluetooth, could someone advise me how to make the pairing?.
thanks !

Hello @JorgeFG
Welcome to the forum.
What we found is that the ELM327 V2.1 OBD2 is a Bluetooth Classic device. The RAK4631 supports only Bluetooth Low Energy (BLE) and cannot connect to a Bluetooth Classic device.

@beegee thanks for answering. I also have the OBDLink CX, and that is BLE 5.1, I imagine that with that if I can perform a pairing, to obtain the data read, could you illustrate how to start with pairing them?.
What I am looking for is to read the real time data sent by the OBDLink CX using BLE but I am still a bit inexperienced in the field.

@JorgeFG
First you need to understand how BLE communications works:

In your particular case the OBDLink CX is a peripheral device and RAK4631 needs to be programmed as Central device.
There are some examples of Central Devices for the BlueFruit library that can be used for RAK4631:

The closest example for the OBDLink CX is central_custom_hrm

The central_custom_hrm application filters BLE packets and only receives the UUID16_SVC_HEART_RATE.

#define UUID16_SVC_HEART_RATE 0x180D

BLEClientService hrms(UUID16_SVC_HEART_RATE);
BLEClientCharacteristic hrmc(UUID16_CHR_HEART_RATE_MEASUREMENT);
BLEClientCharacteristic bslc(UUID16_CHR_BODY_SENSOR_LOCATION);

In the example BLE services and characteristics are known as part of the Bluetooth Core Specification

You need to know what BLE services and characteristics OBDLink provides to the application developer.

1 Like

@marcio thanks for you opinion, Consider what you mentioned to me and use the example of hmr custom, where I use the uuids that would return the name of the device but it did not respond

I tried just changing this part:

BLEClientService hrms(0x180A);
BLEClientCharacteristic hrmc(0x2A29);
BLEClientCharacteristic bslc(0x2A24);

With the mobile application “nRF Connect”, I got the uuid and uuid feature services.

Generic Access (0x1800)

  • Device Name [R] (0x2A00)
  • Appearance [R] (0x2A01)
    Generic Attribute (0x1801)
  • Service Changed [I R] (0x2A05)
    Client Characteristic Configuration (0x2902)
    Device Information (0x180A)
  • Manufacturer Name String [R] (0x2A29)
  • Model Number String [R] (0x2A24)
  • Firmware Revision String [R] (0x2A26)
  • Software Revision String [R] (0x2A28)
    Unknown Service (0000fef5-0000-1000-8000-00805f9b34fb)
  • Unknown Characteristic [R W] (8082caa8-41a6-4021-91c6-56f9b954cc34)
  • Unknown Characteristic [R W] (724249f0-5ec3-4b5f-8804-42345af08651)
  • Unknown Characteristic [R] (6c53db25-47a1-45fe-a022-7c92fb334fd4)
  • Unknown Characteristic [R W] (9d84b9a3-000c-49d8-9183-855b673fda31)
  • Unknown Characteristic [R W WNR] (457871e8-d516-4ca1-9116-57d0b17b9cb2)
  • Unknown Characteristic [N R] (5f78df94-798c-46f5-990a-b3eb6a065c88)
    Client Characteristic Configuration (0x2902)
  • Unknown Characteristic [R] (64b4e8b5-0de5-401b-a21d-acc8db3b913a)
  • Unknown Characteristic [R] (42c3dfdd-77be-4d9c-8454-8f875267fb3b)
  • Unknown Characteristic [R] (b7de1eea-823d-43bb-a3af-c4903dfce23c)
    Unknown Service (0000fff0-0000-1000-8000-00805f9b34fb)
  • Unknown Characteristic [N] (0000fff1-0000-1000-8000-00805f9b34fb)
    Client Characteristic Configuration (0x2902)
  • Unknown Characteristic [W WNR] (0000fff2-0000-1000-8000-00805f9b34fb)

So I investigated, I need to use the TX and RX serial communication uuids to communicate with the OBDLink and be able to make requests with AT, ST commands etc. But I don’t know which one is correct and I don’t know how to handle it, could you help me again?

@JorgeFG


Based on the log you sent, note the items highlighted in green and red. Items highlighted in green are part of the bluetooth standard and everything is documented. Items in red are proprietary. The manufacturer is not obligated to disclose the content. That’s why it appears as unknown on nrf connect. You can discover unknown services and features if you have access to the source code of the mobile application or the manufacturer discloses it.
In your case, RAK is a central and obd is a peripheral. It’s easy to understand: The Central always originates a BLE connection. The peripheral always accepts a connection. It is possible to make a central BLE application to read the items highlighted in green. I think the information doesn’t help much . For example read the name of the device manufacturer:

BLEClientService obd_info(0x180a);
BLEClientCharacteristic obd_name (0x2A29);

The library documentation is very brief. You can reference the example central_custom_hrm at the link below. But it is necessary to obtain documentation of services and proprietary features from the manufacturer for a complete example.

Adafruit_nRF52_Arduino/libraries/Bluefruit52Lib/examples/Central/central_custom_hrm at master · adafr.
See a similar case on stackoverflow:
bluetooth - Interpretting data from a BLE device without a published GATT profile - Stack Overflow. Best regards

This is my initial code @marcio, according to what you told me to review, I still have doubts how to make AT command requests, should I send them through uuid 0x00fff1 and read the response for 0x00ff2? If so, could you tell me how to proceed?

#include <bluefruit.h>

uint8_t Device_information[]= {0xFB,0x34,0x9B,0x5F,0x80,0x00,0x00,0x80,0x00,0x10,0x00,0x00,0x0A,0x18,0x00,0x00};
uint8_t manufacture_name[] = {0xFB,0x34,0x9B,0x5F,0x80,0x00,0x00,0x80,0x00,0x10,0x00,0x00,0x29,0x2A,0x00,0x00};
BLEClientService obd_info(Device_information);
BLEClientCharacteristic obd_name(manufacture_name);

uint8_t OBDRXSERVICE[]= {0xFB,0x34,0x9B,0x5F,0x80,0x00,0x00,0x80,0x00,0x10,0x00,0x00,0xF0,0xFF,0x00,0x00};
uint8_t RXCHAR[] = {0xFB,0x34,0x9B,0x5F,0x80,0x00,0x00,0x80,0x00,0x10,0x00,0x00,0xF2,0xFF,0x00,0x00};
uint8_t TXCHAR[] = {0xFB,0x34,0x9B,0x5F,0x80,0x00,0x00,0x80,0x00,0x10,0x00,0x00,0xF1,0xFF,0x00,0x00};

BLEClientService obd_rxservice(OBDRXSERVICE);
BLEClientCharacteristic obd_rxchar(RXCHAR);
BLEClientCharacteristic obd_txchar(TXCHAR);

uint8_t OBDII_ADV_COMPLETE_LOCAL_NAME[] = {0x4F,0x42,0x44,0x4C,0x69,0x6E,0x6B,0x20,0x43,0x58};

void setup()
{
Serial.begin(115200);
while ( !Serial ) delay(10); // for nrf52840 with native usb

Serial.println(“Bluefruit52 Central OBDLink”);
Serial.println("--------------------------------------\n");

// Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1
// SRAM usage required by SoftDevice will increase dramatically with number of connections
Bluefruit.begin(0, 1);

Bluefruit.setName(“Bluefruit52 Central”);

// Initialize client

obd_info.begin();
obd_rxservice.begin();

// Initialize client characteristics

obd_name.begin();
obd_rxchar.begin();
obd_txchar.begin();

// set up callback for receiving measurement
obd_name.setNotifyCallback(obd_name_notify_callback);

// Increase Blink rate to different from PrPh advertising mode
Bluefruit.setConnLedInterval(250);

// Callbacks for Central
Bluefruit.Central.setDisconnectCallback(disconnect_callback);
Bluefruit.Central.setConnectCallback(connect_callback);

/* Start Central Scanning

    • Enable auto scan if disconnected
    • Interval = 100 ms, window = 80 ms
    • Don’t use active scan
    • Filter only accept HRM service
    • Start(timeout) with timeout = 0 will scan forever (until connected)
      */
      Bluefruit.Scanner.setRxCallback(scan_callback);
      Bluefruit.Scanner.restartOnDisconnect(true);
      Bluefruit.Scanner.setInterval(160, 80); // in unit of 0.625 ms
      // Bluefruit.Scanner.filterUuid(obd_rxservice.uuid);
      Bluefruit.Scanner.useActiveScan(false);
      Bluefruit.Scanner.start(0); // // 0 = Don’t stop scanning after n seconds
      }

void loop()
{
// do nothing
}

/**

  • Callback invoked when scanner pick up an advertising data

  • @param report Structural advertising data
    /
    void scan_callback(ble_gap_evt_adv_report_t
    report){
    Serial.println("");
    Serial.println(“Scan Callback”);
    printReport(report);

    /* Choose a peripheral to connect with by searching for an advertisement packet with a
    Complete Local Name matching our target device*/
    uint8_t buffer[BLE_GAP_ADV_SET_DATA_SIZE_MAX] = { 0 };

    Serial.print(“Parsing report for Local Name … “);
    if (Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, buffer, sizeof(buffer)))
    {
    Serial.println(“Found Local Name”);
    Serial.printf(”%14s %s\n”, “Local Name:”, buffer);

     Serial.print("   Local Name data: ");
     printHexList(buffer, BLE_GAP_ADV_SET_DATA_SIZE_MAX);
    
     Serial.print("Determining Local Name Match ... ");
     if (!memcmp(buffer, OBDII_ADV_COMPLETE_LOCAL_NAME, sizeof(OBDII_ADV_COMPLETE_LOCAL_NAME)))
     {
         Serial.println("Local Name Match!");
    
         Serial.println("Connecting to Peripheral ... ");
         Bluefruit.Central.connect(report);
     }
     else
     {
         Serial.println("No Match");
         Bluefruit.Scanner.resume(); // continue scanning
     }
    

    }
    else
    {
    Serial.println(“Failed”);

     // For Softdevice v6: after received a report, scanner will be paused
     // We need to call Scanner resume() to continue scanning
     Bluefruit.Scanner.resume();
    

    }
    }

/**

  • Callback invoked when an connection is established
  • @param conn_handle
    */
    void connect_callback(uint16_t conn_handle)
    {
    Serial.println("");
    Serial.print("Connect Callback, conn_handle: ");
    Serial.println(conn_handle);

// If not found, disconnect and return
Serial.print("Discovering info Service … ");
if (!obd_info.discover(conn_handle))
{
Serial.println(“No Service information device Found”);
Bluefruit.disconnect(conn_handle);
return;
}
Serial.println(“Service information device Found”);
Serial.print("Discovering OBD_NAME … ");
if (!obd_name.discover())
{
Serial.println("No Characteristic Found. Characteristic is mandatory but not found. ");
Bluefruit.disconnect(conn_handle);
return;
}
Serial.println(“Characteristic Found”);
Serial.print("Discovering OBD RXSERVICE … ");
if (!obd_rxservice.discover())
{
Serial.println(“No RX Service Found”);
Bluefruit.disconnect(conn_handle);
return;
}
Serial.println(“RX Service Found”);
Serial.print("Discovering OBD RXCHAR … ");
if (!obd_rxchar.discover())
{
Serial.println("No Rxchar Characteristic Found. Characteristic is mandatory but not found. ");
Bluefruit.disconnect(conn_handle);
return;
}
Serial.println(“Characteristic RXchar Found”);
Serial.print("Discovering OBD TXCHAR … ");
if (!obd_txchar.discover())
{
Serial.println("No Txchar Characteristic Found. Characteristic is mandatory but not found. ");
Bluefruit.disconnect(conn_handle);
return;
}
Serial.println(“Characteristic TXchar Found”);

if (obd_name.enableNotify())
{
    Serial.println("enableNotify success, now ready to receive Characteristic values");
}
else
{
    Serial.println("Couldn't enable notify for Characteristic. Increase DEBUG LEVEL for troubleshooting");
}

}

/**

  • Callback invoked when a connection is dropped
  • @param conn_handle
  • @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
    */
    void disconnect_callback(uint16_t conn_handle, uint8_t reason)
    {
    (void) conn_handle;
    (void) reason;

Serial.print(“Disconnected, reason = 0x”); Serial.println(reason, HEX);

}

void obd_name_notify_callback(BLEClientCharacteristic* chr, uint8_t* data, uint16_t len)
{

Serial.print("obd_name IS: ");

}
void printHexList(uint8_t* buffer, uint8_t len)
{
// print forward order
for (int i = 0; i < len; i++)
{
Serial.printf("%02X-", buffer[i]);
}
Serial.println();
}
void printReport(const ble_gap_evt_adv_report_t* report)
{
Serial.print(" rssi: “);
Serial.println(report->rssi);
Serial.print(” scan_rsp: “);
Serial.println(report->type.scan_response);
// Serial.print( " type: " );
// Serial.println( report->type );
Serial.print(” dlen: “);
Serial.println(report->data.len);
Serial.print(” data: “);
for (int i = 0; i < report->data.len; i += sizeof(uint8_t))
{
Serial.printf(”%02X-", report->data.p_data[i]);
}
Serial.println("");
}

Hello @JorgeFG
The manufacturers of this type of equipment use proprietary BLE services and characteristics. With the information I have I can’t even say if there is an rx and tx characteristic .There is also no way to know what kind of data is read or written on these proprietary characteristic (without the help of the manufacturer). Maybe this message helps because the author of the OBD2 expert program responded. Best regards

android - Which GATT Profile and Services are used by OBD BLE Adapters like LELink, Automatic, Carista? - Stack Overflow

Hello @marcio and @beegee
I already know what are the uuids of the custom service UART, but I still struggle to make the code to send AT commands and read the response of the request. I have gone through most of the examples but I still can’t identify how to handle to send and receive data through the uart ble, within the examples it is noted that maybe with BLEuart it is possible, but I would have to change the uuids that come by default, however, I still don’t know how to send and receive the notification. could you advise me again?

Hello @JorgeFG
Unfortunately I don’t have enough information to help make a full application.
If communication is performed via AT commands, you need to know what to send and what response obd sends. And also the proprietary BLE service and characteristic used.

About UART Service check the link below. It is a proprietary service but it is documented.

Please note the UART service is only a means of sending and receiving data.
The data contents is determined by the application developer.
For example: The Raytac BLE manufacturer use the BLE UART service to send and receive proprietary AT messages.

Your code is ready to receive notifications if the characteristic has notification like the RX characteristic on UART service

// set up callback for receiving measurement
obd_name.setNotifyCallback(obd_name_notify_callback);

Best regards