├── README.md └── TPMS ├── Output └── .gitkeep ├── Resources ├── PMV-107J.py ├── code_gen ├── lib │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-310.pyc │ │ ├── __init__.cpython-311.pyc │ │ ├── crc.cpython-310.pyc │ │ └── crc.cpython-311.pyc │ └── crc.py ├── subghz_ook_to_sub.py ├── toyota.py ├── tpms_citroen.py ├── tpms_ford.py ├── tpms_fsk.grc ├── tpms_fsk.py ├── tpms_renault.py └── tpms_smd3ma4.py └── TPMS-Helper.sh /README.md: -------------------------------------------------------------------------------- 1 | # ARCHIVING 2 | Got CRC for the regular toyota working PMV-c210 iirc. This is what you need: 3 | 4 | 5 | crc8 = crcmod.mkCrcFun(0x107, rev=False, initCrc=0x80, xorOut=0) 6 | crc_bytes = int(payload, 2).to_bytes(len(payload) // 8, byteorder='big') 7 | calculated_crc = crc8(crc_bytes[0:8]) 8 | crc_bits = str(bin(calculated_crc)[2:]) 9 | 10 | crc_bits= crc_bits.zfill(8) 11 | 12 | fin = "010101010011110" + differential_manchester_encode(payload + crc_bits) + "11" 13 | 14 | I am not putting it in, but this combined with everything in my included work shoud be enough for you to do it yourself 15 | 16 | It appears some of these are now broken, but I don't intend on working on these anymore 17 | 18 | 19 | # TPMS-Flipper 20 | Generate TPMS sub files for the Flipper Zero 21 | 22 | **Primer:** 23 | Since approx 2009 all vehicles in the United States are required to have a method of measuring tire pressure. These sensors are called Tire Pressure Monitoring Systems (TPMS). There are two main types of TPMS, Direct and Indirect, direct sensors are mounted in the wheel and usually transmit information to the car ECU via radio frequency signals. RF TPMS transmissions are the subject of this repository. In order to prevent your vehicle's TPMS system from effecting other cars, TPMS makers rely on different encoding modulations, formats, Preambles and the TPMS sensor IDs that are set in the car's ECU. 24 | 25 | **TPMS-Helper** 26 | The files in this repo generate valid Flipper Zero TPMS "Low Pressure" sub files in the correct format and modulations with a user specified TPMS ID for a few TPMS types. 27 | 28 | **Demonstration** 29 | 30 | https://user-images.githubusercontent.com/85343771/210616359-4581ef6e-6c41-4738-b60f-186451180579.mp4 31 | 32 | **Usage:** 33 | You must be using Ubuntu (Debian had some weird package issues for me). Download the entire repo. Extract the TPMS folder in you home dir. Chmod +x the TPMS-helper.sh. Run it. It *should* install all needed tools and set correct permissions for Code_gen in the Resources folder. This will only happen once. Choose the TPMS type, enter the hex ID, and a Flipper sub file will be output to the Output folder. You can test it against rtl_433. 34 | 35 | **Before the Flipper tiktokers ask, you need to generate a SPECIFIC file with the correct ID for each car/tire (you only need one tire id) or it will not work. The SUB for your car/tire will have a different ID than every other car/tire and could have a completely different encoding (very likely)** 36 | 37 | **Credits:** 38 | 39 | Like most projects, I built on and utilized the work of others: 40 | 41 | - Helper Script, Schrader SMD3MA4 encoding and python modifications by Lord Daikon (me) 42 | - Massive thanks for help wih signals analysis, python fixes, and overall wisdom from Jimilinux https://github.com/jimilinuxguy 43 | - The excellent work of rtl_433 reversing signals was a heavily utilized resource 44 | - PMV-107J and very useful encoding tools that are the backbone of this project from https://github.com/triq-org/tx_tools 45 | - Citroen, and Ford from https://github.com/cdeletre/txtpms/ 46 | - subghz_ook_to_sub.py by https://github.com/evilpete/flipper_toolbox 47 | 48 | - Also utilizes GNUradio, rtl_433, sox and python 3.10 49 | 50 | **Contributions of protocols are welcome** 51 | 52 | -------------------------------------------------------------------------------- /TPMS/Output/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /TPMS/Resources/PMV-107J.py: -------------------------------------------------------------------------------- 1 | import time 2 | import crcmod 3 | import os 4 | 5 | home_directory = os.path.expanduser( '~' ) 6 | 7 | def differential_manchester_encode(s): 8 | last_bit = 0 9 | state = 0 10 | result = [] 11 | for sbit in s: 12 | bit = 0 13 | if sbit == '1': bit = 1 14 | if bit == last_bit: 15 | result.append('10') 16 | state=0 17 | else: 18 | result.append('01') 19 | state=1 20 | last_bit = state 21 | return ''.join(result) 22 | 23 | 24 | def main(): 25 | 26 | crc8 = crcmod.mkCrcFun(0x113, rev=False, initCrc=0, xorOut=0) 27 | 28 | # TPMS sensor 7 hex digit ID as printed on the sensor 29 | id = input('What is the 7 digit hex ID?\n') 30 | id = int(id, 16) 31 | device = format((id), '028b') 32 | 33 | # Battery low if set 34 | battlow = '0' 35 | 36 | # Counter (two bits counts 1,2,3) 37 | ctr = format(0x3, '02b') 38 | 39 | # Must be zero for packet to be recognized 40 | mustbezero = '0' 41 | # Ignored bit, sensor sets this to 0 42 | ignored = '0' 43 | # Fault indicator of some sort (if 1 TPMS light starts flashing and values are ignored) 44 | fault = '0' 45 | 46 | # Tire pressure in PSI/0.363 + 40 constant added or 47 | # kPa/2.48 + 40 constant added 48 | pressure = 0/0.363 + 40 49 | pressureint = int(pressure + 0.5) 50 | pressurebits = format(pressureint, '08b') 51 | pressureinvbits = format(pressureint^0xff, '08b') 52 | 53 | # Temperature in Celsius with a constant 40 added (resulting range -40 to 215C) 54 | temperature = format(42 + 40, '08b') 55 | 56 | # Assemble the complete payload to calculate CRC 57 | payload = device + battlow + ctr + mustbezero + ignored + fault + pressurebits + pressureinvbits + temperature 58 | 59 | # Pad payload to make it even 8 bits (won't affect CRC8 as long as it's done in front) 60 | padpayload = '000000'+payload 61 | crc_bytes = int(padpayload, 2).to_bytes(len(padpayload) // 8, byteorder='big') 62 | calculated_crc = crc8(crc_bytes[0:8]) 63 | crc_bits = format(calculated_crc, '08b') 64 | 65 | bitstream = '00000000000000001111110' + differential_manchester_encode('1'+payload+crc_bits+'1') + '000000' 66 | 67 | f = open(os.path.join( home_directory, 'TPMS', 'Output', 'test.txt'),"w") 68 | f.write("[_ (8000us) ]\n[0 (-40kHz 100us) ]\n[1 (40kHz 100us) ]\n\n\n_ _ _\n%s" % bitstream) 69 | 70 | print('bitstream = %s' % bitstream) 71 | 72 | if __name__ == '__main__': 73 | main() 74 | -------------------------------------------------------------------------------- /TPMS/Resources/code_gen: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UberGuidoZ/TPMS-Flipper/a89d31a584f95fe58c9912ce66b23e9c8a7638c5/TPMS/Resources/code_gen -------------------------------------------------------------------------------- /TPMS/Resources/lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UberGuidoZ/TPMS-Flipper/a89d31a584f95fe58c9912ce66b23e9c8a7638c5/TPMS/Resources/lib/__init__.py -------------------------------------------------------------------------------- /TPMS/Resources/lib/__pycache__/__init__.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UberGuidoZ/TPMS-Flipper/a89d31a584f95fe58c9912ce66b23e9c8a7638c5/TPMS/Resources/lib/__pycache__/__init__.cpython-310.pyc -------------------------------------------------------------------------------- /TPMS/Resources/lib/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UberGuidoZ/TPMS-Flipper/a89d31a584f95fe58c9912ce66b23e9c8a7638c5/TPMS/Resources/lib/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /TPMS/Resources/lib/__pycache__/crc.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UberGuidoZ/TPMS-Flipper/a89d31a584f95fe58c9912ce66b23e9c8a7638c5/TPMS/Resources/lib/__pycache__/crc.cpython-310.pyc -------------------------------------------------------------------------------- /TPMS/Resources/lib/__pycache__/crc.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UberGuidoZ/TPMS-Flipper/a89d31a584f95fe58c9912ce66b23e9c8a7638c5/TPMS/Resources/lib/__pycache__/crc.cpython-311.pyc -------------------------------------------------------------------------------- /TPMS/Resources/lib/crc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Port of C crc8 function from rtl_433 util 5 | https://github.com/merbanan/rtl_433/blob/master/src/util.c 6 | """ 7 | 8 | def crc8(message,nBytes,polynomial=0x07,init=0x00): 9 | remainder = init 10 | nBytes = bytes(nBytes) 11 | for byte in nBytes: 12 | remainder ^= message[byte] 13 | for bit in range(8): 14 | if(remainder & 0x80): 15 | remainder = (remainder << 1) ^ polynomial 16 | else: 17 | remainder = (remainder << 1) 18 | remainder = remainder & 0xff 19 | 20 | return remainder 21 | -------------------------------------------------------------------------------- /TPMS/Resources/subghz_ook_to_sub.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # 4 | # Peter Shipley github.com/evilpete 5 | # 6 | # From pkg https://github.com/evilpete/flipper_toolbox 7 | # 8 | # convert .ook files produced by rtl_433 to the Flipper .sub format 9 | 10 | # 11 | # Usage: 12 | # subghz_ook_to_sub.py FILENAME [freq]") 13 | # 14 | # default freq 433920000 [433.92Mhz] 15 | # 16 | # 17 | 18 | 19 | # to convert unsigned 8-bit sdr data do the following: 20 | # 21 | # convert rtl-sdr raw data file into .ook file with rtl_sdr 22 | # (this will partially demodulate the data) 23 | # 24 | # rtl_443 -r rtl_sample.cu8 -w rf_sample.ook 25 | # 26 | # convert the .ook file into a Flipper .sub file 27 | # 28 | # subghz_ook_to_sub.py rf_sample.ook 29 | # 30 | # this will generate the file rf_sample.sub 31 | # 32 | # Note: you may have to manually set the frequancy on the 33 | # command line or by editing the file 34 | 35 | # 36 | # With multiple packets per ook file: 37 | # currently only reads first header and assumes all 38 | # following packets use same modulation 39 | 40 | 41 | # To do: 42 | # parse header 43 | # split samples into multiple files (opton) 44 | # data validation 45 | # .fsk file format ? 46 | # insert breaks between pkts 47 | 48 | 49 | import sys 50 | import os 51 | # import pprint 52 | 53 | filen = None 54 | rf_freq = 0 55 | rf_freq_default = 433920000 56 | 57 | _debug = 0 58 | 59 | # ;pulse data 60 | # ;version 1 61 | # ;timescale 1us 62 | # ;created 2022-11-14 13:59:15-0800 63 | # ;ook 21 pulses 64 | # ;freq1 -75324 65 | # ;centerfreq 0 Hz 66 | # ;samplerate 250000 Hz 67 | # ;sampledepth 8 bits 68 | # ;range 42.1 dB 69 | # ;rssi -0.1 dB 70 | # ;snr 8.0 dB 71 | # ;noise -8.1 dB 72 | # 532 1492 73 | 74 | 75 | def chunks(lst, n=500): 76 | """Yield successive 500-sized chunks from lst.""" 77 | for i in range(0, len(lst), n): 78 | yield lst[i:i + n] 79 | 80 | 81 | def gen_sub(freq, rf_samples): 82 | 83 | if _debug: 84 | print("\n\n\nrf_samples", rf_samples) 85 | 86 | dat = rf_samples[0].get('header') 87 | 88 | if _debug: 89 | print(f"header {dat}") 90 | 91 | comment_text = "generated with ook_to_sub.py" 92 | rf_Preset = None 93 | # Preset: FuriHalSubGhzPreset2FSKDev238Async 94 | # Preset: FuriHalSubGhzPreset2FSKDev476Async 95 | # Preset: FuriHalSubGhzPresetOok270Async 96 | # Preset: FuriHalSubGhzPresetOok650Async 97 | if 'ook' in dat: 98 | rf_Preset = "FuriHalSubGhzPresetOok650Async" 99 | elif 'fsk' in dat: 100 | # calc freq shift deviation 101 | # f1 = get('freq1', 0) 102 | # f2 = get('freq2', 0) 103 | # fq = abs((f1 - f2) / 2) 104 | # print(f"FSK shift = {fq}") 105 | 106 | rf_Preset = "FuriHalSubGhzPreset2FSKDev476Async" 107 | else: 108 | print("Can't determine modulation type from header") 109 | print(dat) 110 | sys.exit(1) 111 | 112 | try: 113 | if rf_freq: 114 | freq = rf_freq 115 | else: 116 | fhz = dat.get('centerfreq', '0 Hz').split()[0] 117 | fhz = int(fhz) 118 | if fhz: 119 | freq = fhz 120 | else: 121 | freq = rf_freq_default 122 | print(f"Using default frequency {rf_freq_default}") 123 | except ValueError: 124 | freq = rf_freq_default 125 | 126 | res = f"""Filetype: Flipper SubGhz RAW File 127 | Version: 1 128 | # {comment_text} 129 | Frequency: {freq} 130 | Preset: {rf_Preset} 131 | Protocol: RAW 132 | """ 133 | 134 | data = [] 135 | raw_data = [] 136 | for ds in rf_samples: 137 | data = [] 138 | dat = ds.get('data', []) 139 | 140 | for d in dat: 141 | a = list(map(int, d.split())) 142 | a[1] *= -1 143 | if a[0] == 0: 144 | del a[0] 145 | elif a[1] == 0: 146 | del a[1] 147 | data += a 148 | 149 | data = list(map(str, data)) 150 | 151 | for i in chunks(data): 152 | raw_data.append(f'RAW_Data: {" ".join(i)}') 153 | 154 | res += '\n'.join(raw_data) 155 | 156 | return res 157 | 158 | 159 | def main(): 160 | 161 | # file_header = {} 162 | 163 | ook_Headers = [";pulse data"] 164 | # samp_mod = "" 165 | # samp_freq1 = 0 166 | # samp_freq2 = 0 167 | 168 | pulse_samples = [] 169 | dat_sample = None 170 | 171 | if _debug: 172 | print(f"open {filen}") 173 | 174 | with open(filen, 'r', encoding="utf-8") as fd: 175 | 176 | header = fd.readline().strip() 177 | if header not in ook_Headers: 178 | print(f"Error: {filen} is not a 'rtl_443 ook' data file") 179 | sys.exit(1) 180 | 181 | for line in fd: 182 | 183 | if line.startswith(';end'): 184 | if _debug: 185 | print("\n\ndat_sample", dat_sample) 186 | print("pulse_samples", pulse_samples) 187 | 188 | dat_sample = None 189 | 190 | if _debug: 191 | print("\nPULSE_SAMPLES", pulse_samples) 192 | continue 193 | 194 | if dat_sample is None: 195 | dat_sample = {} 196 | dat_sample['header'] = file_header = {} 197 | dat_sample['data'] = pulse_data = [] 198 | pulse_samples.append(dat_sample) 199 | 200 | if line[0] == ';': 201 | a = line[1:].strip().split(None, 1) 202 | file_header[a[0]] = a[1] 203 | continue 204 | 205 | pulse_data.append(line.strip()) 206 | 207 | print("Total packets in file", len(pulse_samples)) 208 | 209 | sub_data = gen_sub(rf_freq, pulse_samples) 210 | 211 | if _debug: 212 | print("\n\n{sub_data}\n\n") 213 | 214 | outfilen = os.path.splitext(filen)[0] + ".sub" 215 | with open(outfilen, 'w', encoding="utf-8") as fd: 216 | print(sub_data, file=fd) 217 | 218 | 219 | if __name__ == '__main__': 220 | args = sys.argv[1:] 221 | 222 | if args: 223 | filen = args.pop(0) 224 | else: 225 | print("needs filename arg") 226 | print(f"{sys.argv[0]} FILENAME [freq]") 227 | sys.exit(0) 228 | 229 | if args: 230 | rf_freq = int(args.pop(0)) 231 | 232 | main() 233 | -------------------------------------------------------------------------------- /TPMS/Resources/toyota.py: -------------------------------------------------------------------------------- 1 | import time 2 | import os 3 | from lib.crc import crc8 4 | from bitstring import BitArray 5 | 6 | #home_directory = os.path.expanduser( '~' ) 7 | 8 | MODEL='Toyota' 9 | 10 | PRESSURE=int((33.5 + 7)*4) 11 | TEMP=int(25 + 40) 12 | State = int('0', 16) 13 | 14 | 15 | def main(): 16 | 17 | id = input('What is the 8 digit hex ID?\n') 18 | id = int('f0d681a0', 16) 19 | 20 | start= str(100001) 21 | device= format((id), '032b') 22 | psi= format((PRESSURE), '08b') 23 | t = int(psi, 2) 24 | inverse_s = t ^ (2 ** (len(psi) + 1) - 1) 25 | invpsi = bin(inverse_s)[3 : ] 26 | temp= format((TEMP), '08b') 27 | s= format((State), '07b') 28 | 29 | payload= device + str(1) + psi + temp + s + invpsi 30 | 31 | print('Payload = %s' % payload) 32 | 33 | crc_bytes = int(payload, 2).to_bytes(len(payload) // 8, byteorder='big') 34 | 35 | print(crc_bytes) 36 | 37 | crc = crc8(crc_bytes,8,0x7,0x80) 38 | print(crc) 39 | 40 | check = format((crc), '08b') 41 | 42 | payload=BitArray(bin=start + device + str(1) + psi + temp + s + invpsi + check) 43 | 44 | print('Payload = %s' % payload.bin) 45 | 46 | if __name__ == '__main__': 47 | exit(main()) 48 | -------------------------------------------------------------------------------- /TPMS/Resources/tpms_citroen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Coding based on rtl_433 device source code from https://github.com/merbanan/rtl_433 5 | rtl_433/src/devices/tpms_citroen.c 6 | """ 7 | 8 | from binascii import unhexlify,hexlify 9 | from struct import pack,unpack_from 10 | import argparse 11 | import os 12 | 13 | """ 14 | Default values 15 | based on test file: https://github.com/merbanan/rtl_433_tests/raw/master/tests/Citroen_TPMS/gfile001.cu8 16 | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 17 | time : @0.198304s 18 | model : Citroen type : TPMS state : d2 id : 8add48d4 19 | flags : 0 repeat : 1 Pressure : 289 kPa Temperature: 23 C maybe_battery: 14 mic : CHECKSUM 20 | """ 21 | home_directory = os.path.expanduser( '~' ) 22 | 23 | MODEL='Citroen' 24 | 25 | SENSORID=int('8add48d4',16) 26 | PRESSURE=10 27 | TEMPERATURE=23 28 | STATUS=int('d2',16) 29 | FLAGS=0 30 | REPEAT=1 31 | BATTERY=14 32 | 33 | # Manchester levels 34 | HIGH = 0xff 35 | LOW = HIGH ^ HIGH 36 | MMODE='manch' # diffmanch | manch 37 | NBYTES=10 38 | 39 | def get_payload(sensorid=SENSORID,pressure=PRESSURE,temperature=TEMPERATURE,state=STATUS,flags=FLAGS,repeat=REPEAT,battery=BATTERY): 40 | 41 | int_payload = 0x00 42 | 43 | int_payload = int_payload << 8 44 | 45 | int_payload += sensorid & 0xffffffff 46 | 47 | int_payload = int_payload << 4 48 | 49 | int_payload += flags & 0xf 50 | 51 | int_payload = int_payload << 4 52 | 53 | int_payload += repeat & 0xf 54 | 55 | int_payload = int_payload << 8 56 | 57 | int_payload += int( pressure / 1.364 ) & 0xff 58 | 59 | int_payload = int_payload << 8 60 | 61 | int_payload += int( temperature + 50 ) & 0xff 62 | 63 | int_payload = int_payload << 8 64 | 65 | int_payload += battery & 0xff 66 | 67 | payload = pack('>Q',int_payload) 68 | 69 | checksum = 0x00 70 | 71 | for byte in unpack_from('<8B',payload): 72 | checksum ^= byte 73 | 74 | payload = pack('Q',int_payload) 60 | 61 | payload = payload[:-1] 62 | 63 | checksum = sum(unpack_from('<7B',payload)) & 0xff 64 | 65 | payload += pack('> 8) & 0x3 49 | 50 | int_payload = int_payload << 8 51 | 52 | int_payload += int(pressure / 0.75) & 0xff 53 | 54 | int_payload = int_payload << 8 55 | 56 | int_payload += int( temperature + 30 ) & 0xff 57 | 58 | int_payload = int_payload << 24 59 | 60 | int_payload += sensorid & 0xffffff 61 | 62 | int_payload = int_payload << 16 63 | 64 | int_payload += unknown & 0xffff 65 | 66 | payload = pack('>Q',int_payload) 67 | 68 | crc = crc8(payload,8) 69 | 70 | payload += pack(' $HOME/TPMS/Output/citroen.cu8 109 | cat $HOME/TPMS/Output/citroen0.cu8 >> $HOME/TPMS/Output/citroen.cu8 110 | dd bs=5000 count=1 if=/dev/zero | sox -t raw -v 0 -c2 -b8 -eunsigned-integer -r 250k - -t raw - >> $HOME/TPMS/Output/citroen.cu8 111 | cat $HOME/TPMS/Output/citroen1.cu8 >> $HOME/TPMS/Output/citroen.cu8 112 | dd bs=5000 count=1 if=/dev/zero | sox -t raw -v 0 -c2 -b8 -eunsigned-integer -r 250k - -t raw - >> $HOME/TPMS/Output/citroen.cu8 113 | cat $HOME/TPMS/Output/citroen2.cu8 >> $HOME/TPMS/Output/citroen.cu8 114 | dd bs=5000 count=1 if=/dev/zero | sox -t raw -v 0 -c2 -b8 -eunsigned-integer -r 250k - -t raw - >> $HOME/TPMS/Output/citroen.cu8 115 | cat $HOME/TPMS/Output/citroen3.cu8 >> $HOME/TPMS/Output/citroen.cu8 116 | dd bs=5000 count=1 if=/dev/zero | sox -t raw -v 0 -c2 -b8 -eunsigned-integer -r 250k - -t raw - >> $HOME/TPMS/Output/citroen.cu8 117 | 118 | rtl_433 -r $HOME/TPMS/Output/citroen.cu8 -w $HOME/TPMS/Output/citroen.ook 119 | 120 | python3 Resources/subghz_ook_to_sub.py $HOME/TPMS/Output/citroen.ook 315000000 121 | 122 | rm $HOME/TPMS/Output/Citroen0.u8 123 | rm $HOME/TPMS/Output/Citroen1.u8 124 | rm $HOME/TPMS/Output/Citroen2.u8 125 | rm $HOME/TPMS/Output/Citroen3.u8 126 | 127 | rm $HOME/TPMS/Output/citroen0.cu8 128 | rm $HOME/TPMS/Output/citroen1.cu8 129 | rm $HOME/TPMS/Output/citroen2.cu8 130 | rm $HOME/TPMS/Output/citroen3.cu8 131 | 132 | rm $HOME/TPMS/Output/citroen.cu8 133 | 134 | rm $HOME/TPMS/Output/citroen.ook 135 | 136 | exit 1 137 | ;; 138 | 139 | "3") echo Enter 8 digit Ford hex id 140 | read id 141 | python3 Resources/tpms_ford.py -i $id 142 | python3 Resources/tpms_fsk.py -b 19200 -r $HOME/TPMS/Output/Ford.u8 -w $HOME/TPMS/Output/ford1.cu8 143 | 144 | dd bs=5000 count=1 if=/dev/zero | sox -t raw -v 0 -c2 -b8 -eunsigned-integer -r 250k - -t raw - > $HOME/TPMS/Output/ford.cu8 145 | cat $HOME/TPMS/Output/ford1.cu8 >> $HOME/TPMS/Output/ford.cu8 146 | dd bs=5000 count=1 if=/dev/zero | sox -t raw -v 0 -c2 -b8 -eunsigned-integer -r 250k - -t raw - >> $HOME/TPMS/Output/ford.cu8 147 | cat $HOME/TPMS/Output/ford1.cu8 >> $HOME/TPMS/Output/ford.cu8 148 | dd bs=5000 count=1 if=/dev/zero | sox -t raw -v 0 -c2 -b8 -eunsigned-integer -r 250k - -t raw - >> $HOME/TPMS/Output/ford.cu8 149 | cat $HOME/TPMS/Output/ford1.cu8 >> $HOME/TPMS/Output/ford.cu8 150 | dd bs=5000 count=1 if=/dev/zero | sox -t raw -v 0 -c2 -b8 -eunsigned-integer -r 250k - -t raw - >> $HOME/TPMS/Output/ford.cu8 151 | cat $HOME/TPMS/Output/ford1.cu8 >> $HOME/TPMS/Output/ford.cu8 152 | dd bs=5000 count=1 if=/dev/zero | sox -t raw -v 0 -c2 -b8 -eunsigned-integer -r 250k - -t raw - >> $HOME/TPMS/Output/ford.cu8 153 | 154 | rtl_433 -r $HOME/TPMS/Output/ford.cu8 -w $HOME/TPMS/Output/ford.ook 155 | 156 | python3 Resources/subghz_ook_to_sub.py $HOME/TPMS/Output/ford.ook 315000000 157 | 158 | rm $HOME/TPMS/Output/Ford.u8 159 | 160 | rm $HOME/TPMS/Output/ford1.cu8 161 | 162 | rm $HOME/TPMS/Output/ford.cu8 163 | 164 | rm $HOME/TPMS/Output/ford.ook 165 | 166 | exit 1 167 | ;; 168 | 169 | "4")python3 Resources/tpms_smd3ma4.py 170 | 171 | Resources/./code_gen -s 250k -r $HOME/TPMS/Output/smd3ma4.txt -w $HOME/TPMS/Output/smd3ma4.cu8 172 | 173 | rtl_433 -r $HOME/TPMS/Output/smd3ma4.cu8 -w $HOME/TPMS/Output/smd3ma4.ook 174 | 175 | python3 Resources/subghz_ook_to_sub.py $HOME/TPMS/Output/smd3ma4.ook 315000000 176 | 177 | rm $HOME/TPMS/Output/smd3ma4.txt 178 | 179 | rm $HOME/TPMS/Output/smd3ma4.cu8 180 | 181 | rm $HOME/TPMS/Output/smd3ma4.ook 182 | 183 | exit 1 184 | ;; 185 | 186 | "5") 187 | echo TPMS Helper 188 | echo Generates Flipper Zero .sub files for a variety of car TPMS 189 | echo Helper Script, Schrader SMD3MA4 encoding and python modifications by Lord Daikon 190 | echo Massive thanks for help wih signals analysis, python fixes, and overall wisdom from Jimilinux 191 | echo PMV-107J and tools from https://github.com/triq-org/tx_tools 192 | echo Citroen, and Ford from https://github.com/cdeletre/txtpms/ 193 | echo subghz_ook_to_sub.py by https://github.com/evilpete/flipper_toolbox 194 | echo Utilizes GNUradio, rtl_433, sox and python 3.10. Use Ubuntu, Debian stable has issues 195 | echo 196 | echo Is there a better way to do this? Probably, but it works. 197 | echo If I missed crediting someone please let me know 198 | 199 | exit 1 200 | ;; 201 | 202 | esac 203 | 204 | --------------------------------------------------------------------------------