Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESP32 to imitate BLE TPMS sensors #40

Open
avicarmeli opened this issue May 22, 2024 · 11 comments
Open

ESP32 to imitate BLE TPMS sensors #40

avicarmeli opened this issue May 22, 2024 · 11 comments
Labels
documentation Improvements or additions to documentation

Comments

@avicarmeli
Copy link

I would like to send the data that ESP32 collect from 433MHz TPMS sensors to Your Android app.
To do that I need to know the SERVICE_UUID and the format the data of the sensors sent over the BLE.
Could you direct me where to find that info?
Thanks in advance.

@avicarmeli avicarmeli added the enhancement New feature or request label May 22, 2024
@VincentMasselis VincentMasselis added help wanted Extra attention is needed documentation Improvements or additions to documentation and removed enhancement New feature or request help wanted Extra attention is needed labels Jun 4, 2024
@VincentMasselis
Copy link
Owner

Hello !

No prob, TPMS Advance support 2 different kind of sensors, those from Sysgration, those from Pecham. The byte array sent by the sensors are a little bit different, the most important difference is the integration of the wheel location for the Sysgration manufacturer (front left, front right, rear left, rear right).

Sysgration uses the service: 0000fbb0-0000-1000-8000-00805f9b34fb
Pecham uses: 000027a5-0000-1000-8000-00805f9b34fb

If you're comfortable with Kotlin and Android, take a look at theses classes:

This code contains byte array parsing for both sensor types

@avicarmeli
Copy link
Author

Great, thank you.
Do you think if I send the 4 wheels data from the same MAC address, would it be a problem?

@VincentMasselis
Copy link
Owner

In this case, your BLE data packets should be formatted like Sysgration sensors, on Pecham sensors, mac address is used as unique id.

Which antenna do you use on your ESP32 to intercept 433 signal ? I use ESPHome on my ESP32 and I'm curious about your project

@avicarmeli
Copy link
Author

avicarmeli commented Jun 6, 2024

Well, I ported this code to ESP32 with CC1101.
I was able to receive the 433MGHz signal of my 2013 Nissan Micra with the ESP32 Board.
Now I plan to add to the code the ability to publish the 4 sensors data over BLE.

@avicarmeli
Copy link
Author

avicarmeli commented Jun 6, 2024

About the MAC address, I saw that the Sysgration parser use the manufacture data to determine location of the sensor. I wonder would the code be ok with one BLE connection with one service number and 4 different manufacture data frames?

@avicarmeli
Copy link
Author

avicarmeli commented Jun 7, 2024

I am having hard time scanning the QR code I came up with into the app. I gave the virtual sensors the following ID's 108A78, 108A79, 108A7A and 108A7B. The QR code I came up with is for the 5 right digits. Am I doing something wrong?

@VincentMasselis
Copy link
Owner

About the MAC address, I saw that the Sysgration parser use the manufacture data to determine location of the sensor. I wonder would the code be ok with one BLE connection with one service number and 4 different manufacture data frames?

As long the 4 packets are sent separately, you can sent them at the same time from the same device, TPMS Advanced will managed them like real sensors.

I am having hard time scanning the QR code I came up with into the app. I gave the virtual sensors the following ID's 108A78, 108A79, 108A7A and 108A7B. The QR code I came up with is for the 5 right digits. Am I doing something wrong?

11AD8B&21563D&31A4F0&41A552 is a valid QRCode recognized by TPMS advanced. The first digit is important since 1, 2, 3 and 4 represent the location of the wheel's sensor. The code maps theses numbers to theses locations: FRONT_LEFT, FRONT_RIGHT, REAR_LEFT and REAR_RIGHT.
Then, the whole id is converted as int to represent the unique id of the sensor. For instance, on my front left sensor, 11AD8B was prefixed by 0x00 and converter to an int, the result is: -1951592192.

@avicarmeli
Copy link
Author

I am publishing manufacture data for each sensor according to the format I have found here. Is that correct?
I was able to scan the QR code after I formatted it as you advised, but no data was displayed in the main screen. So I guess I am still not doing it right.
Attached is the screen video from nRF Connect app.

ESP32BLE.mp4

@avicarmeli
Copy link
Author

Update:
It turned out that I wasn't publishing the service UUID. There is a limit for advertisement size in BLE 4 (which ESP32 comply with) of 31 byte. Since service UUID is 16 bytes and manufacturer data (the sensor data - ID, location, pressure, temperature etc.) is 18 bytes, one have to set the Service UUID into Scan response advertisement data.
After mending that the data sent was visible in the TPMS advanced app.
I also found that if I set the advertisement type to ADV_TYPE_NONCONN_IND (non connect and indirect) then the data is not showing up in the TPMS advanced app.

Following is a short ESP32 demo code to send data to TPMS advanced app:

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>

// 128-bit Service UUID
static BLEUUID serviceUUID("0000fbb0-0000-1000-8000-00805f9b34fb");

// Manufacturer Data
// Fake TPMS data for 4 sensors
uint8_t tpmsData[4][18] = {
  {0x00, 0x01, 0x80, 0xEA, 0xCA, 0x10, 0x8A, 0x78, 0xE3, 0x6D, 0x00, 0x00, 0xE6, 0x0A, 0x00, 0x00, 0x5B, 0x00}, // Sensor 1
  {0x00, 0x01, 0x81, 0xEA, 0xCA, 0x20, 0x8A, 0x79, 0xD2, 0x4B, 0x00, 0x00, 0xE6, 0x0A, 0x00, 0x00, 0x4A, 0x00}, // Sensor 2
  {0x00, 0x01, 0x82, 0xEA, 0xCA, 0x30, 0x8A, 0x7A, 0xC1, 0x2A, 0x00, 0x00, 0xE6, 0x0A, 0x00, 0x00, 0x39, 0x00}, // Sensor 3
  {0x00, 0x01, 0x83, 0xEA, 0xCA, 0x40, 0x8A, 0x7B, 0xB0, 0x09, 0x00, 0x00, 0xE6, 0x0A, 0x00, 0x00, 0x28, 0x00}  // Sensor 4
};

void setup() {
  Serial.begin(115200);
  Serial.println("Starting BLE work!");

  // Initialize the BLE device
  BLEDevice::init("ESP32");

  // Create BLE Server
  BLEServer *pServer = BLEDevice::createServer();

  // Create the BLE Service
  BLEService *pService = pServer->createService(serviceUUID);

  // Start the service
  pService->start();


  // Start advertising
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  

// Set manufacturer data for each sensor
  for (int i = 0; i < 4; i++) {
    BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
    String manufacturerData((char*)tpmsData[i], sizeof(tpmsData[i]));
    oAdvertisementData.setManufacturerData(manufacturerData);
    pAdvertising->setAdvertisementData(oAdvertisementData);
    //pAdvertising->setAdvertisementType(ADV_TYPE_NONCONN_IND);

    BLEAdvertisementData scanResponseData;
    scanResponseData.setCompleteServices(serviceUUID);
    pAdvertising->setScanResponseData(scanResponseData);

     // Configure advertising
    pAdvertising->setScanResponse(true);
    pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
    pAdvertising->setMinPreferred(0x12);
    
    // Start advertising
    pAdvertising->start();
    Serial.print("Advertising started! Sending Sensor no.");
    Serial.println(i);
    delay(1000); // Advertise each sensor data for 1 second
    pAdvertising->stop();
  }
}


void loop() {
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  for (int i = 0; i < 4; i++) {
    BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
    String manufacturerData((char*)tpmsData[i], sizeof(tpmsData[i]));
    oAdvertisementData.setManufacturerData(manufacturerData);
    pAdvertising->setAdvertisementData(oAdvertisementData);
    //pAdvertising->setAdvertisementType(ADV_TYPE_NONCONN_IND);

    BLEAdvertisementData scanResponseData;
    scanResponseData.setCompleteServices(serviceUUID);
    pAdvertising->setScanResponseData(scanResponseData);

     // Configure advertising
    pAdvertising->setScanResponse(true);
    pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
    pAdvertising->setMinPreferred(0x12);
    
    // Start advertising
    pAdvertising->start();
    //Serial.println("Advertising started!");
    Serial.print("Advertising started! Sending Sensor no.");
    Serial.println(i);
    delay(1000); // Advertise each sensor data for 1 second
    pAdvertising->stop();
  }
  delay(2000);
}

@avicarmeli
Copy link
Author

avicarmeli commented Jun 15, 2024

11AD8B&21563D&31A4F0&41A552 is a valid QRCode recognized by TPMS advanced. The first digit is important since 1, 2, 3 and 4 represent the location of the wheel's sensor. The code maps theses numbers to theses locations: FRONT_LEFT, FRONT_RIGHT, REAR_LEFT and REAR_RIGHT.

Just to be sure, I see that with first digit set to 1 the sensor mapped to Front Right.
The complete map looks like that:

First Digit Wheel
1 Front Right
2 Front Left
3 Rear Right
4 Rear Left

Could anyone confirm?

@avicarmeli avicarmeli reopened this Jun 15, 2024
@nlroth
Copy link

nlroth commented Jun 26, 2024

Your map is not correct to industry standards. My Autel TPMS reader reads in the order of:
Fl, Fr, Rr, Rl, spare.
Of course, you can read and assign in any order as long as your SW takes that order into account.

I would like to see a manual way to enter the sensor IDs into the android app though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

3 participants