Skip to content

Commit c43fe7c

Browse files
Topper69zuckschwerdt
authored andcommitted
Add support for TyreGuard 400 TPMS (merbanan#1976)
Co-authored-by: Christian W. Zuckschwerdt <[email protected]>
1 parent 7c8cda5 commit c43fe7c

File tree

6 files changed

+259
-0
lines changed

6 files changed

+259
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ See [CONTRIBUTING.md](./docs/CONTRIBUTING.md).
307307
[222] Rubicson Pool Thermometer 48942
308308
[223] Badger ORION water meter, 100kbps (-f 916450000 -s 1200000)
309309
[224] GEO minim+ energy monitor
310+
[225] TyreGuard 400 TPMS
310311
311312
* Disabled by default, use -R n or a conf file to enable
312313

conf/rtl_433.example.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ stop_after_successful_events false
446446
protocol 222 # Rubicson Pool Thermometer 48942
447447
protocol 223 # Badger ORION water meter, 100kbps (-f 916450000 -s 1200000)
448448
protocol 224 # GEO minim+ energy monitor
449+
protocol 225 # TyreGuard 400 TPMS
449450

450451
## Flex devices (command line option "-X")
451452

conf/tyreguard400.conf

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# TYREGUARD400 from DAVIES CRAIG
2+
#
3+
# https://daviescraig.com.au/product/tyreguard-400-tpms-4-sensors-kit-1015
4+
#
5+
# - Type : TPMS
6+
# - Freq : 434.1 MHz
7+
# - Modulation : ASK -> OOK_MC_ZEROBIT (Manchester Code with fixed leading zero bit)
8+
# - Sambol duration : 100us (same for l or 0)
9+
# - Length : 22 bytes long
10+
#
11+
# Packet layout:
12+
#
13+
# bytes : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
14+
# coded : S/P S/P S/P S/P S/P S/P S/P ID ID ID ID ID ID ID Pr Pr Temp Temp Flg Flg CRC CRC
15+
#
16+
# - S/P : preamble/sync "0xfd5fd5f" << always fixed
17+
# - ID : 6 bytes long start with 0x6b????? ex 0x6b20d21
18+
# - Pr : Last 2 bytes of pressure in psi ex : 0xe8 means XX232 psi (for XX see flags bytes)
19+
# - Temp : Temperature in °C offset by +40 ex : 0x2f means (47-40)=+7°C
20+
# - Flg : Flags bytes => should be read in binary format :
21+
# - Bit 73 : Unknown ; maybe the 20th MSB pressure bit? The sensor is not capable to reach this so high pressure
22+
# - Bit 74 : add 1024 psi (19th MSB pressure bit)
23+
# - Bit 75 : add 512 psi (18th MSB pressure bit)
24+
# - Bit 76 : add 256 psi (17th MSB pressure bit)
25+
# - Bit 77 : Acknoldge pressure leaking 1=Ack 0=No_ack (nothing to report)
26+
# - Bit 78 : Unknown
27+
# - Bit 79 : Leaking pressure detected 1=Leak 0=No leak (nothing to report)
28+
# - Bit 80 : Leaking pressure detected 1=Leak 0=No leak (nothing to report)
29+
# - CRC : CRC poly 0x31 start value 0xdd final 0x00 from 1st bit 80th bits
30+
#
31+
# To peer a new sensor to the unit, bit 79 and 80 has to be both to 1.
32+
#
33+
# NOTE: In the datasheet, it is said that the sensor can report low batterie. During my tests/reseach i'm not able to see this behavior. I have fuzzed all bits nothing was reported to the reader.
34+
#
35+
36+
decoder {
37+
name = TPMS-TYREGUARD400,
38+
modulation = OOK_MC_ZEROBIT,
39+
short = 100,
40+
long = 100,
41+
gap = 0,
42+
reset = 500,
43+
preamble = fd5fd5f,
44+
get = id:@0:{28},
45+
get = pression:@57:{8},
46+
get = temp:@65:{8},
47+
get = flags:@73:{8},
48+
get = add_psi:@74:{3}:[0:no 1:256 2:512 3:768 4:1024 5:1280 6:1536 7:1792],
49+
get = AckLeaking:@77:{1}:[1: yes 0:no],
50+
get = Leaking_detected:@79:{2}:[0:no 1:yes 2:yes],
51+
get = CRC:@81:{8},
52+
}

include/rtl_433_devices.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@
232232
DECL(rubicson_pool_48942) \
233233
DECL(badger_orion) \
234234
DECL(geo_minim) \
235+
DECL(tpms_tyreguard400) \
235236

236237
/* Add new decoders here. */
237238

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ add_library(r_433 STATIC
227227
devices/tpms_renault_0435r.c
228228
devices/tpms_toyota.c
229229
devices/tpms_truck.c
230+
devices/tpms_tyreguard400.c
230231
devices/ts_ft002.c
231232
devices/ttx201.c
232233
devices/vaillant_vrt340f.c

src/devices/tpms_tyreguard400.c

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
/** @file
2+
TPMS TyreGuard 400 from Davies Craig.
3+
4+
Copyright (C) 2022 R ALVERGNAT
5+
6+
This program is free software; you can redistribute it and/or modify
7+
it under the terms of the GNU General Public License as published by
8+
the Free Software Foundation; either version 2 of the License, or
9+
(at your option) any later version.
10+
*/
11+
/**
12+
TPMS TyreGuard 400 from Davies Craig.
13+
14+
- Type: TPMS
15+
- Freq: 434.1 MHz
16+
- Modulation: ASK -> OOK_MC_ZEROBIT (Manchester Code with fixed leading zero bit)
17+
- Symbol duration: 100us (same for l or 0)
18+
- Length: 22 bytes long
19+
20+
Packet layout:
21+
22+
bytes : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
23+
coded : S/P S/P S/P S/P S/P S/P S/P ID ID ID ID ID ID ID Pr Pr Temp Temp Flg Flg CRC CRC
24+
25+
- S/P : preamble/sync "0xfd5fd5f" << always fixed
26+
- ID : 6 bytes long start with 0x6b????? ex 0x6b20d21
27+
- Pr : Last 2 bytes of pressure in psi ex : 0xe8 means XX232 psi (for XX see flags bytes)
28+
- Temp : Temperature in °C offset by +40 ex : 0x2f means (47-40)=+7°C
29+
- Flg : Flags bytes => should be read in binary format :
30+
- Bit 73 : Unknown ; maybe the 20th MSB pressure bit? The sensor is not capable to reach this so high pressure
31+
- Bit 74 : add 1024 psi (19th MSB pressure bit)
32+
- Bit 75 : add 512 psi (18th MSB pressure bit)
33+
- Bit 76 : add 256 psi (17th MSB pressure bit)
34+
- Bit 77 : Acknoldge pressure leaking 1=Ack 0=No_ack (nothing to report)
35+
- Bit 78 : Unknown
36+
- Bit 79 : Leaking pressure detected 1=Leak 0=No leak (nothing to report)
37+
- Bit 80 : Leaking pressure detected 1=Leak 0=No leak (nothing to report)
38+
- CRC : CRC poly 0x31 start value 0xdd final 0x00 from 1st bit 80th bits
39+
40+
To peer a new sensor to the unit, bit 79 and 80 has to be both to 1.
41+
42+
NOTE: In the datasheet, it is said that the sensor can report low batterie. During my tests/reseach i'm not able to see this behavior. I have fuzzed all bits nothing was reported to the reader.
43+
44+
Flex decoder:
45+
46+
-X "n=TPMS,m=OOK_MC_ZEROBIT,s=100,l=100,r=500,preamble=fd5fd5f"
47+
48+
decoder {
49+
name = TPMS-TYREGUARD400,
50+
modulation = OOK_MC_ZEROBIT,
51+
short = 100,
52+
long = 100,
53+
gap = 0,
54+
reset = 500,
55+
preamble = fd5fd5f,
56+
get = id:@0:{28},
57+
get = pression:@57:{8},
58+
get = temp:@65:{8},
59+
get = flags:@73:{8},
60+
get = add_psi:@74:{3}:[0:no 1:256 2:512 3:768 4:1024 5:1280 6:1536 7:1792],
61+
get = AckLeaking:@77:{1}:[1: yes 0:no],
62+
get = Leaking_detected:@79:{2}:[0:no 1:yes 2:yes],
63+
get = CRC:@81:{8},
64+
}
65+
66+
*/
67+
68+
#include "decoder.h"
69+
70+
#define TPMS_TYREGUARD400_MESSAGE_BITLEN 88
71+
72+
static int tpms_tyreguard400_decode(r_device *decoder, bitbuffer_t *bitbuffer, unsigned row, unsigned bitpos)
73+
{
74+
uint8_t b[(TPMS_TYREGUARD400_MESSAGE_BITLEN + 7) / 8];
75+
76+
// Extract the message
77+
bitbuffer_extract_bytes(bitbuffer, row, bitpos, b, TPMS_TYREGUARD400_MESSAGE_BITLEN);
78+
79+
//CRC poly 0x31 start value 0xdd final 0x00 from 1st bit to 80bits
80+
if (crc8(b, 11, 0x31, 0xdd) != 0) {
81+
decoder_log_bitrow(decoder, 2, __func__, b, TPMS_TYREGUARD400_MESSAGE_BITLEN, "CRC error");
82+
return DECODE_FAIL_MIC;
83+
}
84+
85+
uint8_t flags = b[9];
86+
//int bat_low = flags & 0x1; // TBC ?!?
87+
int peering_request = flags & 0x3; // bytes = 0b00000011
88+
int ack_leaking = flags & 0x8; // byte = 0b00001000 :: NOTA ack_leaking = 1 means ack ;; ack_leaking=0 nothing to do
89+
90+
// test if bits 1st or 2nd is set to 1 of 0b000000XX
91+
int leaking = flags & 0x3;
92+
93+
//int add256 = (flags & 0x10) >> 4; // bytes = 0b000X0000
94+
//int add512 = (flags & 0x20) >> 5; // bytes = 0b00X00000
95+
//int add1024 = (flags & 0x40) >> 6; // bytes = 0b0X000000
96+
97+
char id_str[8];
98+
sprintf(id_str, "%07x", (uint32_t)(((b[3] & 0xf)<<24)) | (b[4]<<16) | (b[5]<<8) | b[6]); // 28 bits ID
99+
char flags_str[3];
100+
sprintf(flags_str, "%02x", flags);
101+
102+
//id = (b[4] << 8)
103+
int pressure_kpa = b[7] | ((flags & 0x70) << 4);
104+
int temp_c = b[8] - 40;
105+
106+
/* clang-format off */
107+
data_t *data = data_make(
108+
"model", "Model", DATA_STRING, "TyreGuard400",
109+
"type", "Type", DATA_STRING, "TPMS",
110+
"id", "ID", DATA_STRING, id_str,
111+
// "flags", "Flags", DATA_STRING, flags_str,
112+
"pressure_kPa", "Pressure", DATA_FORMAT, "%.1f kPa", DATA_DOUBLE, (double)pressure_kpa,
113+
"temperature_C", "Temperature", DATA_FORMAT, "%.0f C", DATA_DOUBLE, (double)temp_c,
114+
"peering_request", "Peering req", DATA_INT, peering_request,
115+
"leaking", "Leaking detected", DATA_INT, leaking,
116+
"ack_leaking", "Ack leaking", DATA_INT, ack_leaking,
117+
// "add256", "", DATA_INT, add256,
118+
// "add512", "", DATA_INT, add512,
119+
// "add1024", "", DATA_INT, add1024,
120+
// "battery_ok", "Batt OK", DATA_INT, !bat_low,
121+
"mic", "Integrity", DATA_STRING, "CRC",
122+
NULL);
123+
/* clang-format on */
124+
125+
decoder_output_data(decoder, data);
126+
return 1;
127+
}
128+
129+
/** @sa tpms_tyreguard400_decode() */
130+
static int tpms_tyreguard400_callback(r_device *decoder, bitbuffer_t *bitbuffer)
131+
{
132+
//uint8_t const tyreguard_frame_sync[] = {0xf, 0xd5, 0xfd, 0x5f}
133+
uint8_t const tyreguard_frame_sync[] = {0xfd, 0x5f, 0xd5, 0xf0}; // needs to shift sync to align bytes 28x bits usefull
134+
135+
int ret = 0;
136+
int events = 0;
137+
138+
for (int row = 0; row < bitbuffer->num_rows; ++row) {
139+
if (bitbuffer->bits_per_row[row] < TPMS_TYREGUARD400_MESSAGE_BITLEN) {
140+
// bail out of this "too short" row early
141+
if (decoder->verbose >= 2) {
142+
// Output the bad row, only for message level debug / deciphering.
143+
decoder_logf_bitrow(decoder, 2, __func__, bitbuffer->bb[row], bitbuffer->bits_per_row[row],
144+
"Bad message in row %d need %d bits got %d",
145+
row, TPMS_TYREGUARD400_MESSAGE_BITLEN, bitbuffer->bits_per_row[row]);
146+
}
147+
continue; // DECODE_ABORT_LENGTH
148+
}
149+
150+
unsigned bitpos = 0;
151+
152+
// Find a preamble with enough bits after it that it could be a complete packet
153+
while ((bitpos = bitbuffer_search(bitbuffer, row, bitpos, tyreguard_frame_sync, 28)) + TPMS_TYREGUARD400_MESSAGE_BITLEN <=
154+
bitbuffer->bits_per_row[row]) {
155+
156+
if (decoder->verbose >= 2) {
157+
decoder_logf_bitrow(decoder, 2, __func__, bitbuffer->bb[row], bitbuffer->bits_per_row[row],
158+
"Find bitpos with preamble row %d at %u", row, bitpos);
159+
}
160+
161+
ret = tpms_tyreguard400_decode(decoder, bitbuffer, row, bitpos);
162+
if (ret > 0)
163+
events += ret;
164+
165+
bitpos += TPMS_TYREGUARD400_MESSAGE_BITLEN;
166+
}
167+
}
168+
// (Only) for future regression tests.
169+
if ((decoder->verbose >= 3) & (events == 0)) {
170+
decoder_logf(decoder, 3, __func__, "Bad transmission");
171+
}
172+
173+
return events > 0 ? events : ret;
174+
}
175+
176+
static char *output_fields[] = {
177+
"model",
178+
"type",
179+
"id",
180+
// "flags",
181+
"pressure_kPa",
182+
"temperature_C",
183+
"peering_request",
184+
"leaking",
185+
"ack_leaking",
186+
// "add256",
187+
// "add512",
188+
// "add1024",
189+
// "battery_ok",
190+
"mic",
191+
NULL,
192+
};
193+
194+
r_device tpms_tyreguard400 = {
195+
.name = "TyreGuard 400 TPMS",
196+
.modulation = OOK_PULSE_MANCHESTER_ZEROBIT,
197+
.short_width = 100,
198+
.long_width = 100,
199+
.gap_limit = 0,
200+
.reset_limit = 500,
201+
.decode_fn = &tpms_tyreguard400_callback,
202+
.fields = output_fields,
203+
};

0 commit comments

Comments
 (0)