├── crc80.py ├── schrader_ook37.py ├── siemens_ook80.py └── tpms.py /crc80.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | def print_hex_list(lst): 4 | print ' '.join(["%02x" % item for item in lst]) 5 | 6 | def crc_80(payload): 7 | print_hex_list(payload) 8 | polynomial = 0x01 9 | value = 0 10 | for byte in payload[1:]: 11 | for i in range(8): 12 | bit1 = (byte >> i) & 0x01 13 | bit2 = value & 0x01 14 | value = value >> 1 15 | value = value | (bit1^bit2) << 7 16 | return value 17 | 18 | if __name__ == '__main__': 19 | payload = [0xc0, 0x0c, 0xbc, 0xfe, 0xee, 0x02, 0x01, 0x4a, 0x0d, 0xe4] 20 | crc = crc_80(payload[:-1]) 21 | print "%02x %02x" % (crc, payload[-1]) 22 | 23 | -------------------------------------------------------------------------------- /schrader_ook37.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from rflib import * 4 | import sys 5 | import bitstring 6 | 7 | def manchester_decode(symbols): 8 | bits = [] 9 | for dibit in symbols.cut(2): 10 | if dibit == '0b01': 11 | bits.append(0) 12 | elif dibit == '0b10': 13 | bits.append(1) 14 | else: 15 | return None 16 | return bitstring.BitStream(bits) 17 | 18 | def schrader_ook37_validate(bits, checksum): 19 | padded_bits = '0b0' + bits 20 | total = 0 21 | for word in padded_bits.cut(2, 0, padded_bits.len-2): 22 | total += word.int & 3 23 | return (checksum == 3 - (total & 3)) 24 | 25 | # Schrader TPMS 37 bit OOK format 26 | def schrader_ook37_decode(pkt): 27 | data = manchester_decode(bitstring.pack('bytes', pkt)[:74]) 28 | if data is None: 29 | return 30 | function, identifier, pressure, checksum = data.unpack('uint:3, uint:24, uint:8, uint:2') 31 | if schrader_ook37_validate(data, checksum): 32 | print "function code: %01x" % function 33 | print "ID: %06x" % identifier 34 | print "pressure: %02x" % pressure 35 | print "checksum: %01x" % checksum 36 | 37 | def rxook(device): 38 | device.setFreq(315052000) 39 | device.setMdmModulation(MOD_ASK_OOK) 40 | device.setMdmDRate(8192) 41 | device.setPktPQT(4) 42 | device.setMdmSyncMode(SYNC_MODE_16_16) 43 | device.setMdmSyncWord(0b0101010101011110) 44 | device.makePktFLEN(10) 45 | 46 | while not keystop(): 47 | try: 48 | pkt, ts = device.RFrecv() 49 | schrader_ook37_decode(pkt) 50 | except ChipconUsbTimeoutException: 51 | pass 52 | sys.stdin.read(1) 53 | 54 | if __name__ == "__main__": 55 | device = RfCat() 56 | rxook(device) 57 | -------------------------------------------------------------------------------- /siemens_ook80.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from rflib import * 4 | import sys 5 | import bitstring 6 | from pyfiglet import Figlet 7 | 8 | f = Figlet(font='doh') 9 | 10 | def manchester_decode(symbols): 11 | bits = [] 12 | for dibit in symbols.cut(2): 13 | if dibit == '0b01': 14 | bits.append(0) 15 | elif dibit == '0b10': 16 | bits.append(1) 17 | else: 18 | return None 19 | return bitstring.BitStream(bits) 20 | 21 | def siemens_ook80_validate(bits, checksum): 22 | # include bits from sync word 23 | padded_bits = '0b0100' + bits 24 | total = 0 25 | for word in padded_bits.cut(8, 0, padded_bits.len-8): 26 | total += word.int & 0xff 27 | return (checksum == total & 0xff) 28 | 29 | # Siemens VDO TPMS 80 bit OOK format 30 | def siemens_ook80_decode(pkt): 31 | data = manchester_decode(bitstring.pack('bytes', pkt)[:152]) 32 | if data is None: 33 | return 34 | function, identifier, pressure, temperature, checksum = data.unpack('uint:20, uint:32, uint:8, uint:8, uint:8') 35 | if siemens_ook80_validate(data, checksum): 36 | print "function code: %05x" % function 37 | print "ID: %08x" % identifier 38 | print "pressure: %02x" % pressure 39 | print "temperature: %02x" % temperature 40 | print "checksum: %02x" % checksum 41 | 42 | def rxook(device): 43 | device.setFreq(315000000) 44 | device.setMdmModulation(MOD_ASK_OOK) 45 | device.setMdmDRate(8400) 46 | device.setPktPQT(7) 47 | device.setMdmSyncMode(SYNC_MODE_16_16) 48 | device.setMdmSyncWord(0b0101010101100101) 49 | device.makePktFLEN(20) 50 | 51 | while not keystop(): 52 | try: 53 | pkt, ts = device.RFrecv() 54 | siemens_ook80_decode(pkt) 55 | except ChipconUsbTimeoutException: 56 | pass 57 | sys.stdin.read(1) 58 | 59 | if __name__ == "__main__": 60 | device = RfCat() 61 | rxook(device) 62 | -------------------------------------------------------------------------------- /tpms.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from rflib import * 4 | from itertools import izip 5 | import sys 6 | 7 | def print_packet(payload): 8 | address = payload[1] << 24 | payload[2] << 16 | payload[3] << 8 | payload[4] 9 | pressure = payload[6] * 4 / 3 10 | temperature = payload[7] - 50 11 | print "Address: %08x, Pressure: %d kPa, Temp: %d C" % (address, pressure, temperature) 12 | 13 | def crc_80(payload): 14 | polynomial = 0x01 15 | value = 0 16 | for byte in payload[1:]: 17 | for i in range(8): 18 | bit1 = (byte >> i) & 0x01 19 | bit2 = value & 0x01 20 | value = value >> 1 21 | value = value | (bit1^bit2) << 7 22 | return value 23 | 24 | def packet_valid(payload): 25 | if crc_80(payload[:-1]) == payload[-1]: 26 | return True 27 | return False 28 | 29 | def grouped(iterable, n): 30 | "s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), (s2n,s2n+1,s2n+2,...s3n-1), ..." 31 | return izip(*[iter(iterable)]*n) 32 | 33 | def decode_manchester_byte(x, y): 34 | z = (x & 0x80) | (x & 0x20) << 1 | (x & 0x08) << 2 | (x & 0x02) << 3 \ 35 | | (y & 0x80) >> 4 | (y & 0x20) >> 3 | (y & 0x08) >> 2 | (y & 0x02) >> 1 36 | #print "%02x" % z 37 | return z 38 | 39 | def decode_manchester(pkt): 40 | return [ 41 | decode_manchester_byte(x, y) 42 | for x, y in grouped(pkt, 2) 43 | ] 44 | 45 | def config_radio(device): 46 | # device.setFreq(433000000) 47 | # device.setFreq(315009000) 48 | device.setFreq(315000000) 49 | device.setMdmModulation(MOD_2FSK) 50 | # device.setEnableMdmManchester() 51 | device.setMdmDRate(19200) 52 | # device.setMdmSyncMode(2) 53 | device.setMdmSyncMode(SYNCM_16_of_16) 54 | device.setMdmSyncWord(0x5556) 55 | device.setMdmNumPreamble(0) 56 | device.setMaxPower() 57 | device.makePktFLEN(20) 58 | 59 | def rxtpms(device): 60 | config_radio(device) 61 | while not keystop(): 62 | try: 63 | pkt, ts = device.RFrecv() 64 | #print "Received: %s" % pkt.encode('hex') 65 | packet = [ord(p) for p in pkt] 66 | payload = decode_manchester(packet) 67 | #print "Decoded: ", ["%02x" % p for p in payload] 68 | if packet_valid(payload): 69 | print "Decoded: ", ' '.join(["%02x" % p for p in payload]) 70 | print_packet(payload) 71 | except ChipconUsbTimeoutException: 72 | pass 73 | sys.stdin.read(1) 74 | 75 | if __name__ == "__main__": 76 | device = RfCat() 77 | rxtpms(device) 78 | 79 | --------------------------------------------------------------------------------