VincentMasselis / TPMS-advanced

Android app for BLE TPMS made by Sysgration
Apache License 2.0
7 stars 3 forks source link

ESP32 to imitate BLE TPMS sensors #40

Open avicarmeli opened 1 month ago

avicarmeli commented 1 month ago

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.

VincentMasselis commented 1 month ago

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 commented 1 month ago

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

VincentMasselis commented 1 month ago

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 commented 1 month ago

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 commented 1 month ago

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 commented 1 month ago

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 commented 1 month ago

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 commented 1 month ago

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.

https://github.com/VincentMasselis/TPMS-advanced/assets/32562196/e953b1e9-8143-40d9-8fcf-5f56c8400a6d

avicarmeli commented 1 month ago

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 commented 1 month ago

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?

nlroth commented 2 weeks ago

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.