#3684·rtl_433

Elero: Silent Gliss "Control N" (433.92 MHz) — same framing as `elero.c`, different payload obfuscation

Author: stuartwood-appleCreated Sep 6, 2026Updated Sep 6, 2026

Following on from #3083 and the elero.c decoder: I have a second Silent Gliss system that uses the same Elero framing but at 433.92 MHz, and whose 8-byte obfuscated block does not decode with the substitution table in elero.c.

Posting complete CRC-valid captures with known button labels in case they are useful, and to ask whether anyone recognises the variant.

Device

  • Handsets: Silent Gliss SG 11932 (6-channel) / SG 11931 (1-channel), marketed as "SG Control N"
  • Blinds: Silent Gliss SG 4970 roller blinds, Series 40 motors (SG 11943 / SG 11944), receiver integrated in the motor
  • Silent Gliss is a Nice S.p.A. brand; Nice has owned elero since 2011

This is a different product line from the SG 5600 / 11490 wall switch that elero.c targets.

Radio parameters (confirmed working)

Captured with a CC1101 in packet mode, so the chip does sync detection, de-whitening and CRC. Configuration is the one from andyboeh/esphome-elero, unchanged except the frequency:

433.92 MHz, GFSK, 76.77 kBaud, deviation 34.9 kHz, channel bandwidth 232 kHz
MDMCFG4=0x7B MDMCFG3=0x83 MDMCFG2=0x13 DEVIATN=0x43
SYNC1=0xD3 SYNC0=0x91   PKTCTRL0=0x45 (whitening + CRC + variable length)
FOCCFG=0x1D  PKTLEN=0x3C

Every packet below passed the hardware CRC-16 (poly 0x8005, init 0xffff), so framing, whitening and sync are all correct.

Frame layout

Matches elero.c exactly, with 3-byte destination addresses (dests_len = ndst * 3, as esphome-elero does for typ > 0x60):

[0]      len = 0x1D (29)   wire length = len + 3
[1]      cnt               increments per command
[2]      typ               0x6A = command from a remote, 0xCA = status from a blind
[3]      typ2              0x28
[4]      hop               0x00 from the handset, 0x0A from a blind
[5]      syst              0x01
[6]      chl               1 or 2 in commands; in a status frame, the counter being acked
[7..9]   src   [10..12] bwd   [13..15] fwd
[16]     ndst = 1
[17..19] dst               3-byte address
[20..21] p1, p2 = 0x20, 0x00
[22..29] obfuscated block (8 bytes)

Addresses seen: handset 1F23C8, blind ch1 7C0BBB, blind ch2 1BE5BA.

How this differs from elero.c

Field elero.c (SG 5600/11490) This device (Control N)
Frequency 868 / 915 MHz 433.92 MHz
typ 0x45 0x6A (cmd) / 0xCA (status)
typ2 0x10 0x28
hop 0x05 0x00 / 0x0A
chl 0x11 / 0x22 / 0x03 0x01 / 0x02
p1, p2 0x00, 0x03 0x20, 0x00
dst 1-byte channel refs 3-byte addresses

The problem

elero.c's elero_decode_command() (identical to QuadCorei8085/elero_protocol) should yield 00 00 <cmd> 00 00 00 00 <parity>. On these captures it yields no such structure: byte 2 is never a valid command and bytes 3-6 are never zero.

Captures — bytes 0..29, CRC already verified and stripped

Each group is a separate run where only one button was pressed, so block[2] should be constant within a group and differ between groups.

Only DOWN pressed (channel 1)

1D 4C 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 98 6D C0 F1 47 6D 2C E8
1D 4D 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 66 D1 A1 A5 32 96 D5 99
1D 4E 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 28 EF 38 44 B2 BF 88 80
1D 4F 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 50 D5 6B B0 60 8A 63 4E
1D 51 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 D6 88 B6 F3 81 C7 A8 04
1D 53 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 CB 46 5B 87 6D 22 35 B4
1D 54 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 48 27 23 6F 47 74 26 B3
1D 55 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 7B C0 48 2A E3 76 02 25
1D 58 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 E9 21 E9 0D A1 43 58 D8
1D 59 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 61 3E 7B DC 54 48 42 69
1D 5A 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 31 D7 3B E3 21 BB 48 87

Only STOP pressed (channel 1)

1D 62 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 DE 21 81 83 CB BE 89 21
1D 64 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 25 DB 5B B8 39 24 85 08
1D 65 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 95 10 A7 07 9F 70 24 B6
1D 66 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 9B 0B 9C F9 AC D3 7E 9C
1D 67 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 36 AB AF 97 D6 78 0A 7B
1D 69 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 40 8A E8 EC 15 14 8F 44
1D 6B 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 11 6E CD 20 95 75 E7 12
1D 6C 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 97 A8 43 1D D7 B1 80 8C
1D 70 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 30 C7 4F A9 23 FD 2D 65

Only the Up+Down combination (recalls the stored intermediate position)

1D 73 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 C2 AE 08 2B F1 5B 2F B9
1D 74 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 58 B9 24 42 78 04 6C 14
1D 75 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 C4 D3 BA 27 07 19 FA B7
1D 76 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 CD 75 A3 B2 81 66 73 A0
1D 77 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 E0 2A FD 44 C6 9B FC C3
1D 78 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 8E 46 EF 91 EC 5B 91 E3
1D 7A 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 5A BB 40 5D 3B 44 5A 3B
1D 7B 6A 28 00 01 01 1F 23 C8 1F 23 C8 1F 23 C8 01 7C 0B BB 20 00 46 FD 5E 4F 90 1F 11 D3

Status frames from blinds (typ=0xCA)

1D 53 CA 28 0A 01 28 7C 0B BB 7C 0B BB 1F 23 C8 01 1F 23 C8 20 00 8E 54 C1 18 E5 9D 01 8B
1D 54 CA 28 0A 01 29 7C 0B BB 7C 0B BB 1F 23 C8 01 1F 23 C8 20 00 3C 9A BD A6 FF 3F 96 2A
1D EC CA 28 0A 01 2C 1B E5 BA 1B E5 BA 1F 23 C8 01 1F 23 C8 20 00 FE 0A 78 E4 5C 90 B6 E8

Already ruled out

To save anyone repeating them:

  1. elero.c / elero_protocol algorithm as-is, at every plausible block offset (17-24). Scored on how many of bytes 3-6 decode to zero: best was 0.07 out of 4.

  2. Brute force of both decrementing-key seeds (all 65,536 combinations at decrement 0x22), requiring bytes 3-6 to decode to zero. No hit.

  3. A difference attack that removes every unknown except the table. Bytes 3 and 5 share key k1; bytes 4 and 6 share k0. Differencing between packet pairs cancels the per-message key and the decrementing-key constants, leaving pure constraints on the substitution table:

    Q(Rp[3]) ^ Q(Rq[3]) == Q(Rp[5]) ^ Q(Rq[5])
    Q(Rp[4]) ^ Q(Rq[4]) == Q(Rp[6]) ^ Q(Rq[6])

    1418 such constraints from 28 packets, covering all 16 table entries. No consistent permutation exists.

Attack 3 is assumption-light — it does not depend on the key constants at all — so its failure suggests the difference is structural, not merely a different table substituted into the same algorithm.

Also tested on the live blind: replay does not work. Verbatim replay of a captured command, and replay with the plaintext cnt byte changed to unused values, were both ignored (transmission independently verified: TX FIFO draining and MARCSTATE entering TX).

The ask

Does anyone recognise this variant, or see something wrong in the assumptions above? Happy to capture whatever would help — more labelled runs, other buttons, other channels, or raw IQ with -Y minmax once my RTL-SDR arrives.