mirror of
https://github.com/merbanan/rtl_433.git
synced 2026-07-31 10:37:40 -04:00
Add support for Mercedes Benz Sprinter TPMS sensor (#3553)
* Add support for Mercedes Benz Sprinter TPMS sensor * fix: stabilize Sprinter TPMS decoding (#3595) Co-authored-by: RomeoApps <294788459+RomeoApps@users.noreply.github.com> --------- Co-authored-by: RomeoApps <romeo@romeoapps.com> Co-authored-by: RomeoApps <294788459+RomeoApps@users.noreply.github.com>
This commit is contained in:
@@ -452,6 +452,7 @@ See [CONTRIBUTING.md](./docs/CONTRIBUTING.md).
|
||||
[362] Jansite TPMS TY588-EU2
|
||||
[363] Oregon Scientific WMR500 weather station
|
||||
[364] Elsner Solexa 230V
|
||||
[365] Mercedes Benz Sprinter 4500 TPMS sensor
|
||||
|
||||
* Disabled by default, use -R n or a conf file to enable
|
||||
|
||||
|
||||
@@ -604,6 +604,7 @@ convert si
|
||||
protocol 362 # Jansite TPMS TY588-EU2
|
||||
protocol 363 # Oregon Scientific WMR500 weather station
|
||||
protocol 364 # Elsner Solexa 230V
|
||||
protocol 365 # Mercedes Benz Sprinter 4500 TPMS sensor
|
||||
|
||||
## Flex devices (command line option "-X")
|
||||
|
||||
|
||||
@@ -372,6 +372,7 @@
|
||||
DECL(tpms_jansite_ty588) \
|
||||
DECL(oregon_scientific_wmr500) \
|
||||
DECL(elsner_solexa) \
|
||||
DECL(tpms_mercedes_benz) \
|
||||
/* Add new decoders here. */
|
||||
|
||||
#define DECL(name) extern r_device const name;
|
||||
|
||||
@@ -329,6 +329,7 @@ add_library(r_433 STATIC
|
||||
devices/tpms_jansite_ty468.c
|
||||
devices/tpms_jansite_ty588.c
|
||||
devices/tpms_kia.c
|
||||
devices/tpms_mercedes_benz.c
|
||||
devices/tpms_nissan.c
|
||||
devices/tpms_pmv107j.c
|
||||
devices/tpms_porsche.c
|
||||
|
||||
120
src/devices/tpms_mercedes_benz.c
Normal file
120
src/devices/tpms_mercedes_benz.c
Normal file
@@ -0,0 +1,120 @@
|
||||
/** @file
|
||||
Mercedes Benz Sprinter TPMS data.
|
||||
|
||||
Copyright (C) 2026 Bruno OCTAU (ProfBoc75)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
*/
|
||||
/**
|
||||
Mercedes Benz Sprinter TPMS data.
|
||||
|
||||
issue #3539:
|
||||
- 2025 Mercedes Benz Sprinter 4500 TPMS sensor
|
||||
- Signal is FSK MC and pulse width 25us.
|
||||
- Preamble {12} 0x002 or 0xff2
|
||||
|
||||
Data Layout:
|
||||
|
||||
Preamble Byte 0 1 2 3 4 5 6 7 8 9
|
||||
002 or ff2 ST II II II II PP TT CC FF XX
|
||||
|
||||
- ST: {8} Family/state byte, observed as 0x83 while stationary and 0xa3 while
|
||||
moving. These capture-derived values are not known to be exhaustive.
|
||||
- II: {32} ID / Serial number
|
||||
- PP: {8} Pressure, PSI, scale 2.75
|
||||
- TT: {8} Temperature, C, offset 51
|
||||
- CC: {8} Counter, increase by 1 each message
|
||||
- FF: {8} Status, observed as 0x6b, 0xe9, or 0xea
|
||||
- XX: {8} CRC-8 of the previous 9 bytes, poly 0x2f, init 0xaa, final XOR 0x00
|
||||
|
||||
*/
|
||||
|
||||
#include "decoder.h"
|
||||
|
||||
static int tpms_mercedes_benz_decode(r_device *decoder, bitbuffer_t *bitbuffer)
|
||||
{
|
||||
uint8_t const preamble[] = {0x00,0x20}; // 12 bit , 0x002
|
||||
uint8_t b[10];
|
||||
|
||||
if (bitbuffer->num_rows != 1) {
|
||||
decoder_logf(decoder, 2, __func__, "row error");
|
||||
return DECODE_ABORT_EARLY;
|
||||
}
|
||||
|
||||
int pos = bitbuffer_search(bitbuffer, 0, 0, preamble, 12);
|
||||
if (pos >= bitbuffer->bits_per_row[0]) {
|
||||
decoder_logf(decoder, 2, __func__, "Preamble 0x002 not found");
|
||||
return DECODE_ABORT_EARLY;
|
||||
}
|
||||
|
||||
if (bitbuffer->bits_per_row[0] < 80) {
|
||||
decoder_logf(decoder, 1, __func__, "Too short");
|
||||
return DECODE_ABORT_LENGTH;
|
||||
}
|
||||
|
||||
pos += 12;
|
||||
bitbuffer_extract_bytes(bitbuffer, 0, pos, b, 80);
|
||||
|
||||
decoder_log_bitrow(decoder, 2, __func__, b, 80, "MSG");
|
||||
|
||||
if (crc8(b, 10, 0x2f, 0xaa)) {
|
||||
decoder_logf(decoder, 1, __func__, "crc error, expected %02x, calculated %02x", b[9], crc8(b, 9, 0x2f, 0xaa));
|
||||
return DECODE_FAIL_MIC; // crc mismatch
|
||||
}
|
||||
|
||||
if (b[0] != 0x83 && b[0] != 0xa3) {
|
||||
decoder_logf(decoder, 1, __func__, "unexpected family/state byte %02x", b[0]);
|
||||
return DECODE_FAIL_SANITY;
|
||||
}
|
||||
|
||||
char id_str[4 * 2 + 1];
|
||||
snprintf(id_str, sizeof(id_str), "%02x%02x%02x%02x", b[1], b[2], b[3], b[4]);
|
||||
float pressure_PSI = b[5] / 2.75f;
|
||||
int temperature_C = b[6] - 51;
|
||||
int counter = b[7] & 0x1f;
|
||||
int flags1 = b[7] >> 5;
|
||||
int flags2 = b[8];
|
||||
|
||||
/* clang-format off */
|
||||
data_t *data = data_make(
|
||||
"model", "", DATA_STRING, "MercedesBenz-Sprinter",
|
||||
"type", "", DATA_STRING, "TPMS",
|
||||
"id", "", DATA_STRING, id_str,
|
||||
"pressure_PSI", "Pressure", DATA_FORMAT, "%.1f PSI", DATA_DOUBLE, (double)pressure_PSI,
|
||||
"temperature_C", "Temperature", DATA_FORMAT, "%.1f C", DATA_DOUBLE, (double)temperature_C,
|
||||
"counter", "Counter", DATA_INT, counter,
|
||||
"flags1", "Flags 1", DATA_FORMAT, "0b%03b", DATA_INT, flags1,
|
||||
"flags2", "Flags 2", DATA_INT, flags2,
|
||||
"mic", "Integrity", DATA_STRING, "CRC",
|
||||
NULL);
|
||||
/* clang-format on */
|
||||
|
||||
decoder_output_data(decoder, data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char const *const output_fields[] = {
|
||||
"model",
|
||||
"type",
|
||||
"id",
|
||||
"pressure_PSI",
|
||||
"temperature_C",
|
||||
"counter",
|
||||
"flags1",
|
||||
"flags2",
|
||||
"mic",
|
||||
NULL,
|
||||
};
|
||||
|
||||
r_device const tpms_mercedes_benz = {
|
||||
.name = "Mercedes Benz Sprinter 4500 TPMS sensor",
|
||||
.modulation = FSK_PULSE_MANCHESTER_ZEROBIT,
|
||||
.short_width = 25,
|
||||
.long_width = 25,
|
||||
.reset_limit = 2000,
|
||||
.decode_fn = &tpms_mercedes_benz_decode,
|
||||
.fields = output_fields,
|
||||
};
|
||||
Reference in New Issue
Block a user