Rtl_433: Garage Door - SecPlus & SecPlus 2.0+

Created on 10 Aug 2020  Â·  67Comments  Â·  Source: merbanan/rtl_433

I've found some old references (eg #652 ) which seem to indicate that rtl_433 can decode ternary to binary. Is this still the case? As I no longer see anything using -X help.

I'm looking at garage door opener decoding, specifically the Security+2.0 protocol - attached.

sec2plus.pdf

EDIT: Update to general request for SecPlus/SecPlus 2.0+ support.

@argilo has done all the hard work and the code can be found here : https://github.com/argilo/secplus/blob/master/secplus.py I can provide samples and testing.

device support

Most helpful comment

@evilpete I tested your branch with the test vectors from secplus, and it produces the correct output now.

rtl_433 -F json -y "{96}111311117333773177773000 {96}713337733137313113331000"
rtl_433 -F json -y "{96}111733737111111131731000 {96}713333317731717131317000"
rtl_433 -F json -y "{96}133771737777337333177000 {96}713113171333177711137000"
rtl_433 -F json -y "{96}111737173731313177773000 {96}737717317733133333711000"
rtl_433 -F json -y "{96}111171713317731377717000 {96}737711733373313333773000"
rtl_433 -F json -y "{96}111313333171773177773000 {96}737377113717111311133000"
rtl_433 -F json -y "{96}133331377111111713717000 {96}737137777733111171773000"
rtl_433 -F json -y "{96}133113333733717331773000 {96}737371331337313113337000"
rtl_433 -F json -y "{96}133111173173177771133000 {96}771311777733133731117000"
rtl_433 -F json -y "{96}133333771711111373313000 {96}771177171117133313173000"
rtl_433 -F json -y "{96}111311131373133317133000 {96}771317373133133737713000"
rtl_433 -F json -y "{96}111733737777371371111000 {96}771313137317133731173000"
rtl_433 -F json -y "{96}133177733773373317317000 {96}731771731733737311171000"
rtl_433 -F json -y "{96}133711171311111177373000 {96}731337133117737177331000"
rtl_433 -F json -y "{96}117171777133717377373000 {96}717317717711117177373000"
rtl_433 -F json -y "{96}113373171317731311137000 {96}717313313113311113331000"
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 2, "switch_id" : 1, "remote_id" : 32445552, "button_id" : "left", "fixed" : "876029923", "rolling" : "2320616988"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 2, "switch_id" : 1, "remote_id" : 32445552, "button_id" : "left", "fixed" : "876029923", "rolling" : "2320616990"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 2, "switch_id" : 1, "remote_id" : 32445552, "button_id" : "left", "fixed" : "876029923", "rolling" : "2320616994"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 2, "switch_id" : 0, "remote_id" : 32445552, "button_id" : "middle", "fixed" : "876029922", "rolling" : "3869428096"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 2, "switch_id" : 0, "remote_id" : 32445552, "button_id" : "middle", "fixed" : "876029922", "rolling" : "3869428100"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 2, "switch_id" : 0, "remote_id" : 32445552, "button_id" : "middle", "fixed" : "876029922", "rolling" : "3869428102"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 2, "switch_id" : 0, "remote_id" : 32445552, "button_id" : "middle", "fixed" : "876029922", "rolling" : "3869428106"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 2, "id1" : 1, "switch_id" : 2, "remote_id" : 32445552, "button_id" : "right", "fixed" : "876029921", "rolling" : "570150738"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 2, "id1" : 1, "switch_id" : 2, "remote_id" : 32445552, "button_id" : "right", "fixed" : "876029921", "rolling" : "570150742"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 2, "id1" : 1, "switch_id" : 2, "remote_id" : 32445552, "button_id" : "right", "fixed" : "876029921", "rolling" : "570150744"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 2, "id1" : 1, "switch_id" : 2, "remote_id" : 32445552, "button_id" : "right", "fixed" : "876029921", "rolling" : "570150748"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 0, "switch_id" : 1, "pad_id" : 1478, "pin" : "enter", "fixed" : "595667170", "rolling" : "2615434906"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 0, "switch_id" : 1, "pad_id" : 1478, "pin" : "1234", "fixed" : "72906373", "rolling" : "2615434910"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 0, "switch_id" : 1, "pad_id" : 1478, "pin" : "1234*", "fixed" : "2397429307", "rolling" : "2615434912"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 0, "switch_id" : 1, "pad_id" : 1478, "pin" : "1234#", "fixed" : "1235167840", "rolling" : "2615434916"}

All 67 comments

oneclick.zip

Detected OOK package    @0.942424s
Analyzing pulses...
Total count:   51,  width: 30.61 ms     ( 7653 S)
Pulse width distribution:
 [ 0] count:   40,  width:  264 us [260;292]    (  66 S)
 [ 1] count:   11,  width:  516 us [512;520]    ( 129 S)
Gap width distribution:
 [ 0] count:   39,  width:  228 us [220;240]    (  57 S)
 [ 1] count:   11,  width:  476 us [476;480]    ( 119 S)
Pulse period distribution:
 [ 0] count:   33,  width:  496 us [488;512]    ( 124 S)
 [ 1] count:   12,  width:  744 us [744;748]    ( 186 S)
 [ 2] count:    5,  width:  992 us [988;1000]   ( 248 S)
Level estimates [high, low]:  15877,     25
RSSI: -0.1 dB SNR: 28.0 dB Noise: -28.2 dB
Frequency offsets [F1, F2]:    -467,      0 (-1.8 kHz, +0.0 kHz)
Guessing modulation: Manchester coding
Attempting demodulation... short_width: 264, long_width: 0, reset_limit: 484, sync_width: 0
Use a flex decoder with -X 'n=name,m=OOK_MC_ZEROBIT,s=264,l=0,r=484'
pulse_demod_manchester_zerobit(): Analyzer Device
bitbuffer:: Number of rows: 1 
[00] {62} 00 00 0b e6 fd 4b e9 ec 

On a glance it looks similar to Manchester or the x1521 encoder, i.e. we are only dealing with two symbols, that then can be decoded by grouping. Actual ternary with three symbols would only be possible if we could grab it as PCM.

The OOK looks like a very good fit for PCM plus custom decoding:
oneclick

So the original (old) Security+ used Ternary

https://github.com/argilo/secplus
Transmissions use on-off keying, with an alphabet of three symbols (0, 1, 2) corresponding to three different pulse widths:

  • 0: 1.5ms off, 0.5ms on
  • 1: 1ms off, 1ms on
  • 2: 0.5ms off, 1.5ms on

Perhaps the new protocol does not. If you need any other captures let me know.

In PCM:

  • 0: 0001
  • 1: 0011
  • 2: 0111
    That also comes down to a "double frequency" or 2-bit/4-bit encoding (Manchester is 1-bit/2-bit), with the nice property of a transition in the middle and at the end which can be read as PCM robustly.

The "new" protocol here doesn't show 111or 000 sequences, the doc indicate codes of 00, 01, and 10. So we should spot a 000 somewhere, which we don't, strange.

Right it mentions "11" being useful as an invalid sequence, so I do think it might use ternary. But perhaps the data stream is just binary?

This section seems relevant (you = "skilled in the art", not I :) )
image

image

image

Someone else did the heavy lifting on 2.0+ of the protocol and has it decoded in GNU Radio. https://github.com/argilo/secplus/issues/2

Any interest in adding to rtl_433? For both v1+v2.

I can open new issues to provide captures or continue on this one.

BTW all the encoding & decoding logic can be found in the _v2 functions here: https://github.com/argilo/secplus/blob/master/secplus.py

@gcormier, edit the topic of this issue and supply some test samples. Eventually someone will get bored and implement a decoder. (hint @evilpete :)

Done, and I'll try to capture some samples of the original (v1) protocol today or tomorrow. rtl_433_tests additions will have to wait a week or so.

https://github.com/merbanan/rtl_433/issues/1464#issuecomment-671526419 attachment is a v2 capture.

@merbanan

Sure, i'll take a look, haven't f'cked with ternary yet.

get be a bunch of clean samples and i'll see about cranking something out.

  • include their decoded form also (if you have it)

might be a week or two depending on my day job and sobriety..

2.0+ (v2) samples available in draft PR https://github.com/merbanan/rtl_433_tests/pull/360

Incremented button pushes. Some samples were larger size on disk then others so included. We can trim them once we decide if they are interesting or not.

Looking for a v1 transmitter to capture those.

@gcormier best not to trim, the demodulators need a little lead in to get a a baseline

this is going to be fun

The example code seems a little broken

a simple encode_v2() decode_v2() test fails

import secplus

in_rolling=2731817118
in_fixed=876029924

code_v2 = secplus.encode_v2(in_rolling, in_fixed)

out_rolling, out_fixed = secplus.decode_v2(code_v2)

print("{:12d} {:12d}".format(in_rolling, in_fixed))
print("{:12d} {:12d}".format(out_rolling, out_fixed))

outputs:

2731817118 876029924
28485210 876029924

@evilpete That's because your rolling code is too big -- it must be between 0 and 3^18-1.

Perhaps things would be clearer if I modified the encode and encode_v2 to raise an exception if invalid input is given.

Correction: the upper limit on the Security+ 2.0 rolling code is actualy 2^28-1. I've updated the check accordingly: https://github.com/argilo/secplus/commit/2c063e80f083294e002048ecaec0cedb6afd9ebf

I also added unit tests to verify that encode+decode recovers the original rolling & fixed codes: https://github.com/argilo/secplus/commit/dcda471b55657cb32e97b410fe041dfecdb1103f

This is gonna be fun to turn into C

seriously _decode_v2_half() is gonna take me at least a day to cleanly convert to C. :-)

ok, I got decode_v2() working in C but it is total crap code thus will need to rewrite then wrap in a device callback.

@gcormier @argilo Anyone got a clean cu8 radio sample ?

I can also use a "clean" demodulated data sample to test my decoding methods with (or does encode_v2_manchester() provide a sufficient sample data i would expect to see from demodulation ? )

@zuckschwerdt / @merbanan : when I am done you guys will need to take a close look as there is so much bit shuffling it makes my head spin and thus will need a detailed review.

secplus produces the following output for that sample:

Security+ 2.0:  rolling=240124739  fixed=70678577664  (button=16 remote_id=1959100928)

After Manchester decoding, the bits should be as follows:

Packet 1: 00000000000000001111000001000001110110000111010010100110010001
Packet 2: 00000000000000001111010010011010011100101100000101101101101001

000000000000000011110 is the preamble. The next bit indicates whether it's the first (0) or second (1) packet, and the final 40 bits are the payload.

Packet 1: 000000000000000011110 0 0001000001110110000111010010100110010001
Packet 2: 000000000000000011110 1 0010011010011100101100000101101101101001

The two payloads together contain the data:

>>> import secplus
>>> payloads = "0001000001110110000111010010100110010001" + "0010011010011100101100000101101101101001"
>>> secplus.decode_v2([int(bit) for bit in payloads])
(240124739, 70678577664)

Thanks...

I am reading a ~276us pulse with ~232us gaps for v2

Pulse Gab

I have all the v2 code done as a standalone demo, I just need to turn it into a decoder callback..

I believe each half of the Manchester symbol is nominally 250us; I measured it at an average of 249.38us for the transmitter I have on hand. The lengths of the pulse & gap will of course vary a bit depending what your threshold level is.

I got:

rolling_total = 3841995824
fixed_total = 70678577664
button=16 remote_id=1959100928

which is close enough to move on.. (rolling_total is off a little and I will fix later [rev bits])

Yep, looks very close. Your rolling code is just shifted four bits to the left.

In case you'd like some more payloads for testing: https://github.com/argilo/secplus/blob/281f3674b2beec5f291cf5a7d911a9a4f8062b0b/test_secplus.py#L74-L89

Those should produce rolling codes 240124710 through 240124725, and the fixed codes will be 70678577664, 62088643072, 66383610368, 74973544960 each repeated four times.

Or produce as many random samples as you like:

import secplus
import random

for _ in range(10):
    rolling = random.randrange(2**28)
    fixed = random.randrange(2**40)
    payload = secplus.encode_v2(rolling, fixed)
    print("".join(str(bit) for bit in payload), rolling, fixed)
00000000000011110010101001100011101001100001100110010011010111011001000110010011 117552618 765452761112
00011000100001100000111110000110111000110001001010100010001110111000001101100000 252418534 981783629209
00101000101111100111010011111111000000110010100101101110110101100011110101101101 162243766 924383723928
00011000100110111000110001000010011110010001010110101011111001111111111000001110 211740595 189853670073
00001001011100111011111110001111100010110001100100001101010111100010100111101101 229312100 296198791979
00101000001010001000110001110110100001100001000110000010111011111110111001111101 115322601 393965486267
00011001100111100110111110000011100111100010011001010101110000010111011100001000 59201602 297451940536
00000001100111111011110000100110011100100010010101110110110110100000011101111001 158227390 483238331338
00100110001010001111110001110001110001100001000010101100001100001110111100101011 258285579 777612776286
00010001001001111101111111111001110010100000000110010100001110001011110010010010 14922294 696861926223

OK... got a version of secplus V2 running

https://github.com/evilpete/rtl_433/tree/secplus_v2

secplus_v2.c

Warning; the current state of the code is "_hammer code_" and will need major cleanup before committing

hammer code == Code that looks like it was beaten with a hammer to get it to work...

@zuckschwerdt for the life of me I could not get the different pulse groups to show up on separate rows (or I needed to put the wine glass down )

g002_310.01M_250k.cu8.gz

r_device secplus_v2 = {
        .name        = "Secplus v2",
        .modulation  = OOK_PULSE_PCM_RZ,
        .short_width = 230,
        .long_width  = 230,
        .tolerance   = 50,
        .gap_limit   = 1500,
        .reset_limit = 9000,
        // .gap_limit   = 2500,
        // .reset_limit = 4000,
        .decode_fn = &secplus_v2_callback,
        .disabled  = 0,
        .fields    = output_fields,
};

Yeah, the thing is: PCM doesn't support gap limit or rows… (cue, maniacal laugh)

Post some SecPlus (v1?) samples and i'll get that done while i'm at it...

Just asked around some friends, family and neighbors for the color of their button/antenna and it appears to be all SecPlus v2. I also dug up an old remote but it is a static-code type and not rolling code, so too old!

@argilo might be able to provide captures if he still has v1 hardware kicking around from his secplus work?

Just back from vacation so I'll catch up on this during the week :)

@gcormier No need to rush...

src/rtl_433 -R 164 -f 310.01M -s 250k -r g002_310.01M_250k.cu8

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
time      : @0.139004s   ID        : Secplus_v2
Button-ID : 16           Remote-ID : 1959100928    Fixed_Code: 70678577664   Rolling_Code: 240124739
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
time      : @0.843604s   ID        : Secplus_v2
Button-ID : 16           Remote-ID : 1959100928    Fixed_Code: 70678577664   Rolling_Code: 240124739
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
time      : @1.548164s   ID        : Secplus_v2
Button-ID : 16           Remote-ID : 1959100928    Fixed_Code: 70678577664   Rolling_Code: 240124739

src/rtl_433 -R 164 -r g002_310.01M_250k.cu8 -F json

{"time" : "@0.139004s", "id" : "Secplus_v2", "button_id" : 16, "remote_id" : 1959100928, "fixed" : "70678577664", "rolling" : "240124739"}
{"time" : "@0.843604s", "id" : "Secplus_v2", "button_id" : 16, "remote_id" : 1959100928, "fixed" : "70678577664", "rolling" : "240124739"}
{"time" : "@1.548164s", "id" : "Secplus_v2", "button_id" : 16, "remote_id" : 1959100928, "fixed" : "70678577664", "rolling" : "240124739"}

@evilpete I'll make a Security+ (v1) recording tomorrow.

@argilo thanks for all the help

Here's a recording of a Security+ remote: https://drive.google.com/file/d/17NbbkDFbJQuHkXr9e1TaoICvuN7M8jBt/view?usp=sharing

Secplus produces the following output:

Security+:  rolling=2320615320  fixed=1846948897  (id1=2 id0=0 switch=1 remote_id=68405514 button=left)

The ternary bits in each packet are as follows:

0 01100210020120120022
2 11221020201022122102

The first symbol in each packet identifies which half it is: 0 = first half, 2 = second half.

16 test vectors and their expected decoding can be found here: https://github.com/argilo/secplus/blob/281f3674b2beec5f291cf5a7d911a9a4f8062b0b/test_secplus.py#L27-L71

The symbols are:

0 = 0.5 ms pulse
1 = 1.0 ms pulse
2 = 1.5 ms pulse

As before, you can use secplus to generate test values for decoding:

import secplus
import random

for _ in range(10):
    rolling = random.randrange(2**32) & 0xfffffffe
    fixed = random.randrange(3**20)
    payload = secplus.encode(rolling, fixed)
    print("".join(str(bit) for bit in payload), rolling, fixed)
1001101010021120121201012020122210210121 4098001162 2967351103
1210202022110201221001110122222211120102 2550814542 1342277440
0121001222212222201202111012222221211100 1507128012 1869540524
0120121221202122200012220210102001220101 2179236060 1382127756
0002010121120222201211022110012001101021 1242802240 1048422572
0000201011121112010021102111001001011100 2551241928 217352762
0001020101011222002200100100002022122021 2312000512 603379556
0200212201121200002012002121120200101112 2329696040 3088825533
0011020200011222212000000010110001011022 3899319016 148805130
1110200201210020002122210210102000101020 712513078 639975841

One thing to note: the low bit of the rolling code is always set to zero. That's done so that when the bits are reversed the high bit is zero, and the resulting number fits into 20 digits when converted to base 3.

@argilo

what does line 83 in secplus.py accomplish ?

fixed = int("{0:032b}".format(fixed), 2)

ok, got secplus working in C

(and the % Implementation-defined operator can f*ckoff)

what does line 83 in secplus.py accomplish ?

Looks like nothing at all. I removed it, and the test suite still passes.

Should have a Push Request tomorrow for Security+ (v1)

@merbanan

Q: I am working on Secplus V1 (i have all the decode logic prototyped in a standalone program.)

Like secplus V2 data is sent as two packets unfortunately, unlike v2, with v1 they are received and processed as in two separate callbacks. Any suggestions ?

as @zuckschwerdt pointed out in https://github.com/merbanan/rtl_433/issues/1464#issuecomment-679194111 :

PCM doesn't support gap limit or rows… (cue, maniacal laugh)

Any suggestions ? I obviously don't want to save state in the callback.

( I am using the sample data provided in a comment above )


Approximate Timings Using Pulseview:

v1 500µs pulse
v1 41ms packet length
v1 55ms gaps

v2 250µs pulse
v2 30ms packet length
v2 7ms gap

@zuckschwerdt any though of adding gap support to PCM or at least have it effect PD_MAX_GAP_RATIO

Adding "row"-support to the PCM-slicer would round out the picture, so I might just do that. But there aren't any PCM protocols with proper "rows" so far, and in your v1 example it likely wouldn't work as the gap is somewhat wide.

yea it ends up looking like this :

{1645}89988b988b89b89b88bb80000000000000000000000000000073377317171317737731700000000000000000000000000000226622e622e26e26e22ee000000000000000000000000000001ccddcc5c5c4c5dcddcc5c0000000000000000000000000000089988b988b89b89b88bb80000000000000000000000000000073377317171317737731700000000000000000000000000000226622e622e26e26e22ee000000000000000000000000000001ccddcc5c5c4c5dcddcc5c000000000000000000000000000000000000000

(as a test I added a 10x multiplier to PD_MAX_GAP_RATIO )

I think I'm going to add it anyway, just having that feature might allow to better explore options.

@zuckschwerdt at the very lease allowing the value of .reset_limit to override PD_MAX_GAP_RATIO

secplus_v1 working with single or multiple rows
( will not work on live or recored RF due to temporary limitations in OOK_PULSE_PCM_RZ )

https://github.com/evilpete/rtl_433/tree/secplus_v1

mostly untested, no guarantees


_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
time      : 2020-08-31 04:30:37                    Model     : Secplus_v1    ID_0      : 0             ID_1      : 2
Switch-ID : 1            Remote-ID : 68405514      Button-ID : left          Fixed     : 1846948897    Rolling_Code: 2320615320

{"time" : "2020-08-31 04:35:25", "Model" : "Secplus_v1", "id0" : 0, "id1" : 2, "switch_id" : 1, "remote_id" : 68405514, "button_id" : "left", "fixed" : 1846948897, "rolling" : "2320615320"}

Nice! I'll review and test tonight.

It looks like you need to merge the latest master, or rebase.

@argilo is it not going to work live because the Gaps are too wide during the transmissions thus the two parts are seen as separate transmissions, and since PCM-slicer does not support gap or reset_limit (yet) there is no real work around.

I tested it with the commands:

$HOME/Projects/rtl_433/build/src/rtl_433 -f 310.01M -s 250k  -R 164   
    -y "{96}113311731171371371177000   {96}733773171713177377317000"`

and

$HOME/Projects/rtl_433/build/src/rtl_433 -f 310.01M -s 250k  -R 164 \ 
    -y "{1645}89988b988b89b89b88bb80000000000000000000000000000073377317171317737731700000000000000000000000000000226622e622e26e26e22ee000000000000000000000000000001ccddcc5c5c4c5dcddcc5c0000000000000000000000000000089988b988b89b89b88bb80000000000000000000000000000073377317171317737731700000000000000000000000000000226622e622e26e26e22ee000000000000000000000000000001ccddcc5c5c4c5dcddcc5c000000000000000000000000000000000000000"

@evilpete Some comments on your code:

Done..

fixed can be as large as 3^20-1, which is too large to fit in a DATA_INT (signed int). So you'll have to use DATA_STRING here:

3^20 = 3486784401
2^32 = 4294967296

thus it should fit in a standard unsigned int,.. although because it is a unsigned it will have to be a DATA_STRING

as for my_mod(), good idea (it sucks that modulo is so implementation dependent )

@argilo : what credit would you like for me to add to the code for v1 & v2, you've done most of the work, I mostly copied your stuff into a rtl_443 callback in C

what credit would you like for me to add to the code for v1 & v2

I'm happy with what you already have there ("Based on code by Clayton Smith https://github.com/argilo/secplus").

@evilpete I tested your branch with the test vectors from secplus, and it produces the correct output now.

rtl_433 -F json -y "{96}111311117333773177773000 {96}713337733137313113331000"
rtl_433 -F json -y "{96}111733737111111131731000 {96}713333317731717131317000"
rtl_433 -F json -y "{96}133771737777337333177000 {96}713113171333177711137000"
rtl_433 -F json -y "{96}111737173731313177773000 {96}737717317733133333711000"
rtl_433 -F json -y "{96}111171713317731377717000 {96}737711733373313333773000"
rtl_433 -F json -y "{96}111313333171773177773000 {96}737377113717111311133000"
rtl_433 -F json -y "{96}133331377111111713717000 {96}737137777733111171773000"
rtl_433 -F json -y "{96}133113333733717331773000 {96}737371331337313113337000"
rtl_433 -F json -y "{96}133111173173177771133000 {96}771311777733133731117000"
rtl_433 -F json -y "{96}133333771711111373313000 {96}771177171117133313173000"
rtl_433 -F json -y "{96}111311131373133317133000 {96}771317373133133737713000"
rtl_433 -F json -y "{96}111733737777371371111000 {96}771313137317133731173000"
rtl_433 -F json -y "{96}133177733773373317317000 {96}731771731733737311171000"
rtl_433 -F json -y "{96}133711171311111177373000 {96}731337133117737177331000"
rtl_433 -F json -y "{96}117171777133717377373000 {96}717317717711117177373000"
rtl_433 -F json -y "{96}113373171317731311137000 {96}717313313113311113331000"
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 2, "switch_id" : 1, "remote_id" : 32445552, "button_id" : "left", "fixed" : "876029923", "rolling" : "2320616988"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 2, "switch_id" : 1, "remote_id" : 32445552, "button_id" : "left", "fixed" : "876029923", "rolling" : "2320616990"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 2, "switch_id" : 1, "remote_id" : 32445552, "button_id" : "left", "fixed" : "876029923", "rolling" : "2320616994"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 2, "switch_id" : 0, "remote_id" : 32445552, "button_id" : "middle", "fixed" : "876029922", "rolling" : "3869428096"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 2, "switch_id" : 0, "remote_id" : 32445552, "button_id" : "middle", "fixed" : "876029922", "rolling" : "3869428100"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 2, "switch_id" : 0, "remote_id" : 32445552, "button_id" : "middle", "fixed" : "876029922", "rolling" : "3869428102"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 2, "switch_id" : 0, "remote_id" : 32445552, "button_id" : "middle", "fixed" : "876029922", "rolling" : "3869428106"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 2, "id1" : 1, "switch_id" : 2, "remote_id" : 32445552, "button_id" : "right", "fixed" : "876029921", "rolling" : "570150738"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 2, "id1" : 1, "switch_id" : 2, "remote_id" : 32445552, "button_id" : "right", "fixed" : "876029921", "rolling" : "570150742"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 2, "id1" : 1, "switch_id" : 2, "remote_id" : 32445552, "button_id" : "right", "fixed" : "876029921", "rolling" : "570150744"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 2, "id1" : 1, "switch_id" : 2, "remote_id" : 32445552, "button_id" : "right", "fixed" : "876029921", "rolling" : "570150748"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 0, "switch_id" : 1, "pad_id" : 1478, "pin" : "enter", "fixed" : "595667170", "rolling" : "2615434906"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 0, "switch_id" : 1, "pad_id" : 1478, "pin" : "1234", "fixed" : "72906373", "rolling" : "2615434910"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 0, "switch_id" : 1, "pad_id" : 1478, "pin" : "1234*", "fixed" : "2397429307", "rolling" : "2615434912"}
{"time" : "2020-09-01 17:54:32", "Model" : "Secplus_v1", "id0" : 0, "id1" : 0, "switch_id" : 1, "pad_id" : 1478, "pin" : "1234#", "fixed" : "1235167840", "rolling" : "2615434916"}

thanks for the validations..

I'll submit a pull request later today but it should not be merged until @zuckschwerdt implements rows or a way or extend the reset_limit


@merbanan i'm bored again

@zuckschwerdt

I can not get the v1 signal to split into rows at best I get is something like

[00] {105} e6 6e e6 2e 2e 26 2e e6 ee 62 e0 00 00 00
[01] { 0}

from what I can tell (with printf debugging), it is being chopped in pulse_detect_package() at:

https://github.com/merbanan/rtl_433/blob/c29f145a2628da4749f56a1dbbf1b330d845d9c1/src/pulse_detect.c#L509

when it exceeds PD_MAX_GAP_RATIO

( I am using the sample data provided in a comment above )

Yes, PD_MAX_GAP_RATIO is a recurring issue. We could raise the value a little but that wouldn't help these cases where there really is a big gap (> 110 needed here).
The main point with this safeguard: we always want to emit a packet as soon as it ends. Waiting for more data could very likely keep us concatenating ever more packets onto the buffer.

Perhaps we can think up another mechanism to "stash" or "defer" packets? Or maybe it's time to add a layer of post-processing to the chain. I.e. most decoders emit data and are done. But a subsequent "filter" could in some cases collate, coalesce, and process further. But that would introduce state there (although more controlled perhaps) and likely needs a way to pass structured data.

@zuckschwerdt

I see two options:

  1. Add a option like -y Extended_PCM_Gap_To_Something_Longer to increase the PD_MAX_GAP_RATIO value and set the secplus_v1 device as disabled by default

or

  1. I add a 24 byte 'cache' to secplus_v1 to see to see of the other half arrived within the last 700ms. ( the time from the first to the last in the retransmission burst / sequence )

then we can call V1 done and move on :-)

I think I prefer option 2. We have some other protocols that trigger this but from duplicates. It would be nice if we could use the same logic to filter out duplicates. We would break statelessness but maybe we can do that in a nice way.

Agreed. But please make sure and note that it can be an unreliable cache only. While it will work currently, we don't want to make guarantees about concurrency in decoders.
So not real state but a best-effort cache of sorts :)

@zuckschwerdt

my plan is to have a 24 byte static buffer and a timeval timestamp and use cache only if timestamp is less then 700ms old

ok, i'll get done and have it for ya within a day or so.


[Update]

Done...

Also fixed secplusV2 to work with and without rows

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gcormier picture gcormier  Â·  15Comments

majkrzak picture majkrzak  Â·  3Comments

ALEEF02 picture ALEEF02  Â·  9Comments

zerog2k picture zerog2k  Â·  3Comments

OZ1SEJ picture OZ1SEJ  Â·  15Comments