Skip to content

Add device Pacific TPMS for Kia. #3214

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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ See [CONTRIBUTING.md](./docs/CONTRIBUTING.md).
[273] Landis & Gyr Gridstream Power Meters 38.4k
[274] Revolt ZX-7717 power meter
[275] GM-Aftermarket TPMS
[276] Kia TPMS (Pacific HKMC)

* Disabled by default, use -R n or a conf file to enable

Expand All @@ -370,7 +371,7 @@ See [CONTRIBUTING.md](./docs/CONTRIBUTING.md).
[-d <RTL-SDR USB device index>] (default: 0)
[-d :<RTL-SDR USB device serial (can be set with rtl_eeprom -s)>]
To set gain for RTL-SDR use -g <gain> to set an overall gain in dB.
SoapySDR device driver is available.
SoapySDR device driver is not available.
[-d ""] Open default SoapySDR device
[-d driver=rtlsdr] Open e.g. specific SoapySDR device
To set gain for SoapySDR use -g ELEM=val,ELEM=val,... e.g. -g LNA=20,TIA=8,PGA=2 (for LimeSDR).
Expand Down
1 change: 1 addition & 0 deletions conf/rtl_433.example.conf
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ convert si
protocol 273 # Landis & Gyr Gridstream Power Meters 38.4k
protocol 274 # Revolt ZX-7717 power meter
protocol 275 # GM-Aftermarket TPMS
protocol 276 # Kia TPMS (Pacific HKMC)

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

Expand Down
1 change: 1 addition & 0 deletions include/rtl_433_devices.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@
DECL(gridstream384) \
DECL(revolt_zx7717) \
DECL(tpms_gm) \
DECL(tpms_pacific_hkmc) \

/* Add new decoders here. */

Expand Down
2 changes: 1 addition & 1 deletion man/man1/rtl_433.1
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ RTL\-SDR device driver is available.
To set gain for RTL\-SDR use \-g <gain> to set an overall gain in dB.
.RE
.RS
SoapySDR device driver is available.
SoapySDR device driver is not available.
.RE
.TP
[ \fB\-d\fI ""\fP ]
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ add_library(r_433 STATIC
devices/tpms_jansite_solar.c
devices/tpms_kia.c
devices/tpms_nissan.c
devices/tpms_pacific_hkmc.c
devices/tpms_pmv107j.c
devices/tpms_porsche.c
devices/tpms_renault.c
Expand Down
137 changes: 137 additions & 0 deletions src/devices/tpms_pacific_hkmc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/** @file
KIA Pacific HKMC TPMS data.

File created by modifying the tpms_hyundai_vdo.c.

Copyright (C) 2025 Ondrej Sychrovsky.

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.
*/

/**
KIA Pacific HKMC TPMS data.

Tested on a KIA Ceed 2023. The sensors used are not original, probably coded for Kia.
They identify themselves as Pacific HKMC.

It seems that the sensor uses FSK modulation, sends the preamble 55 55 56 and then makes a 3-bit gap.
When the gap is coded into the decoder a new line of data is received, which I do not know how to detect.
The decoder is therefore configured without gap and the gap is accounted for by shifting the data after removing
the preamble. That is the reason for + 27 instead of + 24 in the code below.
After removing the preamble, the Differential Manchester decoding is run on the remaining data:

For my four sensors I have obtained the following message:

90 id id id PP xx xx xx xx xx

where
- id id id = ID of the sensor. I was able to match this ID to the ID that was shown on a dedicated programming
device for all four sensors.
- PP = Pressure with an experimentally set compute formula of p_kPa = PP * 3.2282 - 448.706

I was not able to locate the temperature, which this sensor is also sending.

I was not able to locate any CRC, I have seen transmissions differ only in the last nibble, which it should not
if that were any kind of CRC.

There is also no repeat counter, I have seen e.g. 10 identical messages at quick succession.

The main purpose of this code is only to intercept the message from the sensors. Decoding it is only the icing.
The reason for this is that at higher speeds, the sensors seem to stop transmitting. I needed to verify it.

*/

#include "decoder.h"

static int tpms_pacific_hkmc_decode(r_device *decoder, bitbuffer_t *bitbuffer, unsigned row, unsigned bitpos)
{
bitbuffer_t packet_bits = {0};
uint8_t *b;
int state;
unsigned id;
int pressure;

bitbuffer_differential_manchester_decode(bitbuffer,row,bitpos,&packet_bits,80);

if (packet_bits.bits_per_row[0] < 80) {
return DECODE_FAIL_SANITY; // too short to be a whole packet
}

b = packet_bits.bb[0];

state = b[0];
id = (unsigned) (b[0] & 0x0f) << 24 | b[1] << 16 | b[2] << 8 | b[3];
pressure = b[4];

char id_str[8 + 1];
snprintf(id_str, sizeof(id_str), "%07x", id);

char data_str[13+1];
snprintf(data_str, sizeof(data_str), "%02x%02x%02x%02x%02x%02x", b[4], b[5], b[6], b[7], b[8], b[9] );

char state_str[3];
snprintf(state_str,sizeof(state_str), "%02x", state );

/* clang-format off */
data_t *data = data_make(
"model", "", DATA_STRING, "Pacific HKMC",
"type", "", DATA_STRING, "TPMS",
"id", "", DATA_STRING, id_str,
"state", "", DATA_STRING, state_str,
"pressure_kPa", "pressure", DATA_FORMAT, "%.0f kPa", DATA_DOUBLE, (double)pressure * 3.2282 - 448.706,
"data", "", DATA_STRING, data_str,
NULL);
/* clang-format on */

decoder_output_data(decoder, data);
return 1;
}

/**
Wrapper for the Kia Pacific HKMC tpms.
@sa tpms_pacific_hkmc_decode()
*/
static int tpms_pacific_hkmc_callback(r_device *decoder, bitbuffer_t *bitbuffer)
{
// full preamble is 55 55 56
uint8_t const preamble_pattern[3] = {0x55, 0x55, 0x56};

unsigned bitpos = 0;
int ret = 0;
int events = 0;

// Find a preamble with enough bits after it that it could be a complete packet
while ((bitpos = bitbuffer_search(bitbuffer, 0, bitpos, preamble_pattern, 24)) + 83 <=
bitbuffer->bits_per_row[0]) {
// See description for why "+ 27" instead of "+ 24"
ret = tpms_pacific_hkmc_decode(decoder, bitbuffer, 0, bitpos + 27);
if (ret > 0)
events += ret;
bitpos += 2;
}

return events > 0 ? events : ret;
}

static char const *const output_fields[] = {
"model",
"type",
"id",
"state",
"pressure_kPa",
"data",
NULL,
};

r_device const tpms_pacific_hkmc = {
.name = "Kia TPMS (Pacific HKMC)",
.modulation = FSK_PULSE_PCM,
.short_width = 52,
.long_width = 52,
.reset_limit = 500,
.decode_fn = &tpms_pacific_hkmc_callback,
.fields = output_fields,
};
Loading