-
-
Notifications
You must be signed in to change notification settings - Fork 129
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update to rtl_433 release 22.11 (#75)
* WIP * Updated contrib decoders * Update oregon scientific * WIP * FSK Primitives included * WIP * Update signalDecoder.cpp * tuning * WIP * WIP * Update * Update tools * Update platformio.ini * LINT * Reporting * memory tuning * Further tuning * Update update_rtl_433_devices.sh * Reporting * almost final * Lint * Update README.md
- Loading branch information
1 parent
e582ebb
commit 65bad3c
Showing
277 changed files
with
32,634 additions
and
7,374 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,239 @@ | ||
/** @file | ||
Interlogix/GE/UTC Wireless Device Decoder. | ||
Copyright (C) 2017 Brent Bailey <[email protected]> | ||
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. | ||
*/ | ||
/** | ||
Interlogix/GE/UTC Wireless Device Decoder. | ||
Also tested with ELK-319DWM module as well as a Alula RE101 319.5MHz sensor (both short preamble). | ||
- Frequency: 319.5 MHz | ||
Decoding done per us patent #5761206 | ||
https://www.google.com/patents/US5761206 | ||
## Protocol Bits | ||
- 00-02 976 uS RF front porch pulse | ||
- 03-14 12 sync pulses, logical zeros | ||
- 15 start pulse, logical one | ||
- 16-35 20 bit sensor identification code (ID bits 0-19) | ||
- 36-39 4 bit device type code (DT bits 0-3) | ||
- 40-42 3 bit trigger count (TC bit 0-2) | ||
- 43 low battery bit | ||
- 44 F1 latch bit NOTE that F1 latch bit and debounce are reversed. Typo or endianness issue? | ||
- 45 F1 debounced level | ||
- 46 F2 latch bit | ||
- 47 F2 debounced level | ||
- 48 F3 latch bit (cover latch for contact sensors) | ||
- 49 F3 debounced level | ||
- 50 F4 latch bit | ||
- 51 F4 debounced level | ||
- 52 F5 positive latch bit | ||
- 53 F5 debounced level | ||
- 54 F5 negative latch bit | ||
- 55 even parity over odd bits 15-55 | ||
- 56 odd parity over even bits 16-56 | ||
- 57 zero/one, programmable | ||
- 58 RF on for 366 uS (old stop bit) | ||
- 59 one | ||
- 60-62 modulus 8 count of number of ones in bits 15-54 | ||
- 63 zero (new stop bit) | ||
## Protocol Description | ||
- Bits 00 to 02 are a 976 ms RF front porch pulse, providing a wake up period that allows the | ||
system controller receiver to synchronize with the incoming packet. | ||
- Bits 3 to 14 include 12 sync pulses, e.g., logical 0's, to synchronize the receiver. | ||
- Bit 15 is a start pulse, e.g., a logical 1, that tells the receiver that data is to follow. | ||
- Bits 16-58 provide information regarding the transmitter and associated sensor. In other | ||
embodiments, bits 16-58 may be replaced by an analog signal. | ||
- Bits 16 to 35 provide a 20-bit sensor identification code that uniquely identifies the particular | ||
sensor sending the message. Bits 36 to 39 provide a 4 bit device-type code that identifies the | ||
specific-type of sensor, e.g., smoke, PIR, door, window, etc. The combination of the sensor | ||
bits and device bits provide a set of data bits. | ||
- Bits 40 through 42 provide a 3-bit trigger count that is incremented for each group of message | ||
packets. The trigger count is a simple but effective way for preventing a third party from | ||
recording a message packet transmission and then re-transmitting that message packet | ||
transmission to make the system controller think that a valid message packet is being transmitted. | ||
- Bit 43 provides the low battery bit. | ||
- Bits 44 through 53 provide the latch bit value and the debounced value for each of the five inputs | ||
associated with the transmitter. For the F5 input, both a positive and negative latch bit are provided. | ||
- Bit 55 provides even parity over odd bits 15 to 55. | ||
- Bit 56 provides odd parity over even bits 16 to 56. | ||
- Bit 57 is a programmable bit that can be used for a variety of applications, including providing an | ||
additional bit that could be used for the sensor identification code or device type code. | ||
- Bit 58 is a 366 ms RF on signal that functions as the "old" stop bit. This bit provides compatibility with | ||
prior system controllers that may be programmed to receive a 58-bit message. | ||
- Bit 59 is a logical 1. | ||
- Bits 60 to 62 are a modulus eight count of the number of 1 bits in bits 15 through 54, providing enhanced | ||
error detection information to be used by the system controller. Finally, bit 63 is the "new" stop bit, | ||
e.g., a logical 0, that tells the system controller that it is the end of the message packet. | ||
## Addendum | ||
GE/Interlogix keyfobs do not follow the documented iti protocol and it | ||
appears the protocol was misread by the team that created the keyfobs. | ||
The button states are sent in the three trigger count bits (bit 40-42) | ||
and no battery status appears to be provided. 4 buttons and a single | ||
multi-button press (buttons 1 - lock and buttons 2 - unlock) for a total | ||
of 5 buttons available on the keyfob. | ||
For contact sensors, latch 3 (typically the tamper/case open latch) will | ||
float (giving misreads) if the external contacts are used (ie; closed) | ||
and there is no 4.7 Kohm end of line resistor in place on the external | ||
circuit | ||
*/ | ||
|
||
#include "decoder.h" | ||
|
||
#define INTERLOGIX_MSG_BIT_LEN 46 | ||
|
||
static int interlogix_decode(r_device *decoder, bitbuffer_t *bitbuffer) | ||
{ | ||
// preamble message | ||
// only searching for 0000 0001 (bottom 8 bits of the 13 bits preamble) | ||
uint8_t const preamble_pattern[1] = {0x01}; // 8 bits | ||
|
||
data_t *data; | ||
unsigned int row = 0; | ||
char device_type_id[2]; | ||
char const *device_type; | ||
char device_serial[7]; | ||
char raw_message[7]; | ||
int low_battery; | ||
char const *f1_latch_state; | ||
char const *f2_latch_state; | ||
char const *f3_latch_state; | ||
char const *f4_latch_state; | ||
char const *f5_latch_state; | ||
|
||
if (bitbuffer->num_rows != 1) { | ||
return DECODE_ABORT_EARLY; | ||
} | ||
|
||
// Check if the message length is between the length seen in test files (57) | ||
// and the 64 bits discussed above. | ||
if (bitbuffer->bits_per_row[0] < 57 | ||
|| bitbuffer->bits_per_row[0] > 64) { | ||
return DECODE_ABORT_LENGTH; | ||
} | ||
|
||
// search for preamble and exit if not found | ||
unsigned int bit_offset = bitbuffer_search(bitbuffer, row, 0, preamble_pattern, (sizeof preamble_pattern) * 8); | ||
if (bit_offset == bitbuffer->bits_per_row[row]) { | ||
decoder_logf(decoder, 2, __func__, "Preamble not found, bit_offset: %u", bit_offset); | ||
return DECODE_FAIL_SANITY; | ||
} | ||
|
||
// set message starting position (just past preamble and sync bit) | ||
bit_offset += (sizeof preamble_pattern) * 8; | ||
|
||
uint8_t message[(INTERLOGIX_MSG_BIT_LEN + 7) / 8]; | ||
|
||
bitbuffer_extract_bytes(bitbuffer, row, bit_offset, message, INTERLOGIX_MSG_BIT_LEN); | ||
|
||
// reduce false positives, abort if id or code looks wrong | ||
if (message[0] == 0x00 && message[1] == 0x00 && message[2] == 0x00) | ||
return DECODE_FAIL_SANITY; | ||
if (message[0] == 0xff && message[1] == 0xff && message[2] == 0xff) | ||
return DECODE_FAIL_SANITY; | ||
if (message[3] == 0x00 && message[4] == 0x00 && message[5] == 0x00) | ||
return DECODE_FAIL_SANITY; | ||
if (message[3] == 0xff && message[4] == 0xff && message[5] == 0xff) | ||
return DECODE_FAIL_SANITY; | ||
|
||
// parity check: even data bits from message[0 .. 40] and odd data bits from message[1 .. 41] | ||
// i.e. 5 bytes and two (top-most) bits. | ||
int parity = message[0] ^ message[1] ^ message[2] ^ message[3] ^ message[4]; // parity as byte | ||
parity = (parity >> 4) ^ (parity & 0xF); // fold to nibble | ||
parity = (parity >> 2) ^ (parity & 0x3); // fold to 2 bits | ||
parity ^= message[5] >> 6; // add check bits | ||
int parity_error = parity ^ 0x3; // both parities are odd, i.e. 1 on success | ||
|
||
if (parity_error) { | ||
decoder_logf(decoder, 1, __func__, "Parity check failed (%d %d)", parity >> 1, parity & 1); | ||
return DECODE_FAIL_MIC; | ||
} | ||
|
||
sprintf(device_type_id, "%01x", (reverse8(message[2]) >> 4)); | ||
|
||
switch ((reverse8(message[2]) >> 4)) { | ||
case 0xa: device_type = "contact"; break; | ||
case 0xf: device_type = "keyfob"; break; | ||
case 0x4: device_type = "motion"; break; | ||
case 0x6: device_type = "heat"; break; | ||
case 0x9: device_type = "glass"; break; // switch1 changes from open to closed on trigger | ||
|
||
default: device_type = "unknown"; return DECODE_FAIL_SANITY; break; | ||
} | ||
|
||
sprintf(device_serial, "%02x%02x%02x", reverse8(message[2]), reverse8(message[1]), reverse8(message[0])); | ||
|
||
sprintf(raw_message, "%02x%02x%02x", message[3], message[4], message[5]); | ||
|
||
// keyfob logic. see protocol description addendum for protocol exceptions | ||
if ((reverse8(message[2]) >> 4) == 0xf) { | ||
low_battery = 0; | ||
f1_latch_state = ((message[3] & 0xe) == 0x4) ? "CLOSED" : "OPEN"; | ||
f2_latch_state = ((message[3] & 0xe) == 0x8) ? "CLOSED" : "OPEN"; | ||
f3_latch_state = ((message[3] & 0xe) == 0xc) ? "CLOSED" : "OPEN"; | ||
f4_latch_state = ((message[3] & 0xe) == 0x2) ? "CLOSED" : "OPEN"; | ||
f5_latch_state = ((message[3] & 0xe) == 0xa) ? "CLOSED" : "OPEN"; | ||
} else { | ||
low_battery = (message[3] & 0x10) ? 1 : 0; | ||
f1_latch_state = (message[3] & 0x04) ? "OPEN" : "CLOSED"; | ||
f2_latch_state = (message[3] & 0x01) ? "OPEN" : "CLOSED"; | ||
f3_latch_state = (message[4] & 0x40) ? "OPEN" : "CLOSED"; | ||
f4_latch_state = (message[4] & 0x10) ? "OPEN" : "CLOSED"; | ||
f5_latch_state = (message[4] & 0x04) ? "OPEN" : "CLOSED"; | ||
} | ||
|
||
/* clang-format off */ | ||
data = data_make( | ||
"model", "Model", DATA_STRING, "Interlogix-Security", | ||
"subtype", "Device Type", DATA_STRING, device_type, | ||
"id", "ID", DATA_STRING, device_serial, | ||
"battery_ok", "Battery", DATA_INT, !low_battery, | ||
"switch1", "Switch1 State", DATA_STRING, f1_latch_state, | ||
"switch2", "Switch2 State", DATA_STRING, f2_latch_state, | ||
"switch3", "Switch3 State", DATA_STRING, f3_latch_state, | ||
"switch4", "Switch4 State", DATA_STRING, f4_latch_state, | ||
"switch5", "Switch5 State", DATA_STRING, f5_latch_state, | ||
"raw_message", "Raw Message", DATA_STRING, raw_message, | ||
NULL); | ||
/* clang-format on */ | ||
|
||
decoder_output_data(decoder, data); | ||
return 1; | ||
} | ||
|
||
static char const *const output_fields[] = { | ||
"model", | ||
"subtype", | ||
"id", | ||
"raw_message", | ||
"battery_ok", | ||
"switch1", | ||
"switch2", | ||
"switch3", | ||
"switch4", | ||
"switch5", | ||
NULL, | ||
}; | ||
|
||
r_device const interlogix = { | ||
.name = "Interlogix GE UTC Security Devices", | ||
.modulation = OOK_PULSE_PPM, | ||
.short_width = 122, | ||
.long_width = 244, | ||
.reset_limit = 500, // Maximum gap size before End Of Message | ||
.decode_fn = &interlogix_decode, | ||
.fields = output_fields, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.