Repurpose Kinetic switch 433mhz


Bought a 2 gang kinetic switch from Aliexpress about 18 months ago like in the picture but without the relay. To be fair Aliexpress messaged to say the switch would only work with their hardware and I could cancel if I wanted.
OpenMqttGateway could detect it. RTL_433 app and original RTL_433.exe couldn’t pick it up.
Put my RF bridge with Tasmota in raw mode and it just got spammed by every device in the area.

Then ESPhome started supporting CC1101 and RF proxy was announced so I installed it on a old ESP32 on a perf board.



I tested the antenna that came with the CC1101 on my VNAnano. It was tuned for 2.4Ghz

So I built my own antenna similar to the one in the pic below. I used a SMA chassie with flange. The VSWR was 1.17 when I tested it in place in the roof space of my garage.

The ESPhome could only pick it up in raw mode.

-1448, 310, -3978, 292, -3964, 311, -3973, 289, -3970, 287, -3977, 279, -4004, 237, -4033, 232 -1448, 310, -3978, 292, -3964, 311, -3973, 289, -3970, 287, -3977, 279, -4004, 237, -4033, 232

I used universal radio hacker and saw it was a repeating sequence of 7 sections each 3.74ms that were identical and 2 fading sections that weren’t the same. This is all very new territory for me but learning fast.

When I demodulated one of those first 7 sections I could see it was made up of 2 patterns. One was 3 highs and a low and the other was one high and 3 lows which I thought represented 1 and O. This looked the same as the coding for a door sensor that rc_switch picked up as protocol 1

That gave a code 1001100101001001000100010 on one switch but it was same code for both positions of the switch.
The other switch was 1001101100000000110100010 different from first switch but same for both positions.
It didn’t seem to work as a rc_switch binary sensor.

I then turned to use @dbuezas onlince oscilloscope to look at the raw codes.


It made the pulses look a bit more human readable. A much more simple repeating pattern.

So I just went with a binary sensor using raw. Read a lot of @Karosm posts on RF.

  - platform: remote_receiver
    name: "kinetic1"
    id: kineticone
    raw:
      code: [-1450, 315, -3970, 290, -3980, 305, -3970, 295, -3970, 280]

    filters: 
      - delayed_off: 
          2s 

I used a shorter sequence of the raw codes. Each time you rock the switches a slightly different sequence comes out . Each number could vary by at least 30 so I went with an average.

It worked. Don’t have any plans to use it yet. It’ll have to be something low risk and very close to the ESP/CC1101

And if my wife askes. That’s how I spent saturday.
Might go back and look at those fading sections of the signal to see if anthing in there to tell the difference between rocker positions.

No AI tokens were used in the wasting of my time.

I wouldn’t call that wasting time. Trying new things and doing some brainwork is likely beneficial after all. Did you miss some less “wasteful” events because of this?
I’m surprised they sold you cc1101 with 2.4G antenna and I really like your custom one.

I never trust those little black sticks. Got another 2.4ghz with a Heltec V2 Lora 433mhz. I replaced that with a diy colinear J pole. Running well for 4 years.

Nice! At least your nanoVNA was not wasted purchase.


Decent heat map for LEO sats packets. Sitting in a West facing window.

I had a look at the signal you captured.
If I can count correctly from the image, the pulse timing in us is around [100, -33] for 1 and [33, -100] for 0.

I’m curious if esphome can capture that with CC1101. Hardwarewise it should be doable. Just in case you feel to waste more time…

Will definitely conto look at it.

Try to capture raw with parameters like:

filter: 15us
idle: 200us
filter_symbols: 24 # add this later when you get valid captures


I just looked at the data I have already and a press of switch generates about 32ms transmission. I laid that against the raw received and just measures when a burst of waves occur.
Is that how raw works in just showing the timings rather than anything to do with 0 and 1s?

I’m not perfectly following you now. What approach did you use to capture that nice pink/green signal ?
That presents valid signal that has a timeframe or 1/10 of common RF signal. It could never be decoded by any common protocol, but it’s logical to have approach like that for minimal energy reserve from kinetic button.
Your last image presents just fading repeats of the signal.


On universal radio hacker that captures the transmisssion on an SDR the signal can be viewed in a demodulated way.

Ok.
From the previous “pink-green” I posted I can see valid signal, like you did as well, and counted binary representation of it.
It was 24bit signal ~3.2ms repeated (not confirmed) several times until energy reserve faded out.
Your esphome approach is just considering whole signal as one pulse. It could even “kind of work” if you adjust all parameters well, but I would prefer to zoom in to real signal.
I’m pretty confident it’s doable and maybe even custom RC-switch binary sensor could be applied later.
But I’m not 100% sure if I understood correctly everything you posted here…

Me too! I have no prevous experience in decoding.

I’ll show you how I was able to see how I got from a device that esp dumped rc_switch.


The URH picked up 20 signals when known device transmitted. I isolated one and copied the long list of 1,0s. The blue highlighted list at bottom of picture above.
I saw the list was made up of only patterns of 1000 and 1110. I thought 1000 could be simply be replaced by a 0 and 1110 by a 1.

That gave me a shorter code of 001111001011111100001010. This sequence agreed exactly what rc_switch dumped when device transmitted as a protocol 2.

I thought this decoding RF signals is easy if I could work this out so quickly. So I then attempted to do the same with kinetic switch. No so easy this time.


Again I was easily able to identify 3 highs and a low as 1 and one high and 3 lows as a 0. It looked the same as RC_switch protocol 2. Limited energy device is not like to use some form of differential coding. All a switch has send is on or off.
The 1001100101001001000100010 code I got didn’t work. Perhaps I just haven’t set it up right.

Let’s take it easy,..
You have “signal within signal”, so it’s confusing at the beginning. One representation looks valid even if it’s not.
Your pink/green signal captured (later posted from me #7) is pretty valid.
What I’m not able to see here if those 5-7 “repetitions” are really repetitions.
Expecting they are, you just need to get trigger of that 3.2ms signal.
So what do you get with parameters I posted above?

I’m uploading those values to esphome now. I’ll then go out and press the kinetic switch.

20:17:46	[I]	[remote.raw:035]	
Received Raw: 50
20:17:46	[I]	[remote.raw:035]	
Received Raw: 159, -111, 163
20:17:46	[I]	[remote.raw:035]	
Received Raw: 160
20:17:46	[I]	[remote.raw:035]	
Received Raw: 166
20:17:46	[I]	[remote.raw:035]	
Received Raw: 170
20:17:46	[I]	[remote.raw:035]	
Received Raw: 182
20:17:46	[I]	[remote.raw:035]	
Received Raw: 186
20:17:46	[I]	[remote.raw:035]	
Received Raw: 186
20:17:46	[I]	[remote.raw:035]	
Received Raw: 175, -110, 163
20:17:46	[I]	[remote.raw:035]	
Received Raw: 163
20:17:46	[I]	[remote.raw:035]	
Received Raw: 149
20:17:46	[I]	[remote.raw:035]	
Received Raw: 183
20:17:46	[I]	[remote.raw:035]	
Received Raw: 151
20:17:46	[I]	[remote.raw:035]	
Received Raw: 173
20:17:46	[I]	[remote.raw:035]	
Received Raw: 151, -94, 162
20:17:46	[I]	[remote.raw:035]	
Received Raw: 170
20:17:46	[I]	[remote.raw:035]	
Received Raw: 149
20:17:46	[I]	[remote.raw:035]	
Received Raw: 126
20:17:46	[I]	[remote.raw:035]	
Received Raw: 124
20:17:46	[I]	[remote.raw:035]	
Received Raw: 146
20:17:46	[I]	[remote.raw:035]	
Received Raw: 127, -155, 104
20:17:46	[I]	[remote.raw:035]	
Received Raw: 99
20:17:46	[I]	[remote.raw:035]	
Received Raw: 100
20:17:46	[I]	[remote.raw:035]	
Received Raw: 127
20:17:46	[I]	[remote.raw:035]	
Received Raw: 125
20:17:46	[I]	[remote.raw:035]	
Received Raw: 104
20:17:46	[I]	[remote.raw:035]	
Received Raw: 105, -151, 95
20:17:46	[I]	[remote.raw:035]	
Received Raw: 105
20:17:46	[I]	[remote.raw:035]	
Received Raw: 120
20:17:46	[I]	[remote.raw:035]	
Received Raw: 101
20:17:46	[I]	[remote.raw:035]	
Received Raw: 101
20:17:46	[I]	[remote.raw:035]	
Received Raw: 104
20:17:46	[I]	[remote.raw:035]	
Received Raw: 80
20:17:46	[I]	[remote.raw:035]	
Received Raw: 80
20:17:46	[I]	[remote.raw:035]	
Received Raw: 78
20:17:46	[I]	[remote.raw:035]	
Received Raw: 48

That doesn’t look useful.
Can you post your receiver code which outputs this..

Do you mean the binary from the sdr?

000000000100110010100100100010001000000001001100101001001000100010000000010011001010010010001000100000000100110010100100100010001000000001001100101001001000100010000000010011001010010010001000100000000100110010100100100010001000000001001100000000

That is for the first burst and 7 repeats including the last 2 that fade of entire transmission. The 9 0 at start is just a flat bit

Sorry, I mean esphome code and logs with parameters I posted above #8.

substitutions:

  ############################################################
  # SET GPIO PINS 
  ############################################################

  # SPI pins used by the CC1101 RF module
  spi_clk_pin: GPIO18
  spi_mosi_pin: GPIO23
  spi_miso_pin: GPIO19

  # CC1101 RF module pins
  cc1101_cs_pin: GPIO5
  remote_receiver_rf_pin: GPIO15
  remote_transmitter_rf_pin: GPIO4


  ############################################################
  # ADVANCED RF SETTINGS 
  ############################################################
  cc1101_frequency: "433.92MHz"
  cc1101_output_power: "10"
  cc1101_symbol_rate: "5000"
  cc1101_filter_bandwidth: "200kHz"

  rf_carrier_duty_percent: "100%"
  rf_receiver_tolerance: "40%"
  rf_receiver_filter: "15us"    #200
  rf_receiver_idle: "200us"       #40ms




# Example configuration entry
logger:
  level: DEBUG



web_server:
  port: 80



captive_portal:

spi:
  clk_pin: ${spi_clk_pin}
  mosi_pin: ${spi_mosi_pin}
  miso_pin: ${spi_miso_pin}
  
cc1101:
  id: cc1101_module
  cs_pin: 5    
  frequency: ${cc1101_frequency}
  output_power: ${cc1101_output_power}
  modulation_type: ASK/OOK
  symbol_rate: ${cc1101_symbol_rate}
  filter_bandwidth: ${cc1101_filter_bandwidth}

remote_receiver:
  - id: rf_receiver

    tolerance: ${rf_receiver_tolerance}
    filter: ${rf_receiver_filter}
    idle: ${rf_receiver_idle}
 #   dump: all
    dump:
      - rc_switch
      - nexa         
      - keeloq       
      - brennenstuhl
      - byronsx
      - dooya
      - drayton
      - raw      
    pin:
      number: 15

    
remote_transmitter:
  - id: rf_transmitter
    pin: ${remote_transmitter_rf_pin}
    carrier_duty_percent: ${rf_carrier_duty_percent}
    non_blocking: true
    on_transmit:
      then:
        - cc1101.begin_tx: cc1101_module
    on_complete:
      then:
        - cc1101.begin_rx: cc1101_module

button:


  - platform: restart
    name: "Restart"


  - platform: template
    name: garage open test
    on_press:
      - remote_transmitter.transmit_rc_switch_raw:
          code: '001111001011111100001010'
              
          protocol: 2
          repeat:
            times: 10
            wait_time: 0s  

  - platform: template
    name: garage closed test 
    on_press:
      - remote_transmitter.transmit_rc_switch_raw:
          code: '001111001011111100001110' 
          protocol: 2
          repeat:
            times: 10
            wait_time: 0s            



binary_sensor:
  - platform: remote_receiver
    name: "mousetrap_set"
    id: contact_on
    rc_switch_raw:
      code: '010000000100001000001110'
      protocol: 1  
    filters: 
      - delayed_off: 
          0.5s      

  - platform: remote_receiver
    name: "mousetrap_fired"
    id: contact_off
    rc_switch_raw:
      code: '010000000100001000001010'
      protocol: 1    
    filters: 
      - delayed_off: 
          0.5s        

  - platform: remote_receiver
    name: "Garagedoor_closed"
    id: GDclose
    rc_switch_raw:
      code: '001111001011111100001110'
      protocol: 1  
    filters: 
      - delayed_off: 
          0.5s       

  - platform: remote_receiver
    name: "Garagedoor_opened"
    id: GDopen
    rc_switch_raw:
      code: '001111001011111100001010'
      protocol: 1  
    filters: 
      - delayed_off: 
          0.5s 

  - platform: remote_receiver
    name: "kinetic1"
    id: kineticone
    raw:
      code: [-1450, 315, -3970, 290, -3980, 305, -3970, 295, -3970, 280]

    filters: 
      - delayed_off: 
          2s 

  - platform: remote_receiver
    name: "kinetic2"
    id: kinetictwo
    raw:
      code: [-1460, 715, -1020, 585, -1960, 710, -1020, 560, -1965, 710]

    filters: 
      - delayed_off: 
          2s 
          
radio_frequency:
  - platform: ir_rf_proxy
    name: RF Transmitter
    frequency: 433.92MHz
    remote_transmitter_id: rf_transmitter
  - platform: ir_rf_proxy
    name: RF Receiver
    frequency: 433.92MHz
    remote_receiver_id: rf_receiver          

That’s my yaml code. I have to go out to garage again and press the kinetic button in a few mins.

Logs - cc1101hub
OTA
INFO ESPHome 2026.7.4
INFO Loaded validated config cache for cc1101hub.yaml, skipping validation.
INFO Starting log output from 192.168.0.77 using esphome API
INFO Successfully resolved cc1101hub @ 192.168.0.77 in 0.000s
INFO Successfully connected to cc1101hub @ 192.168.0.77 in 0.133s
INFO Successful handshake with cc1101hub @ 192.168.0.77 in 0.104s
[21:06:12.510][I][app:151]: ESPHome version 2026.7.4 compiled on 2026-08-17 20:14:22 +0100
[21:06:12.510][I][app:158]: ESP32 Chip: ESP32 rev1.0, 2 core(s)
[21:06:12.511][W][app:198]: Bootloader supports SRAM1 as IRAM (+40KB). Set sram1_as_iram: true under esp32 > framework > advanced
[21:06:12.511][C][logger:223]: Logger:
[21:06:12.511][C][logger:223]:   Max Level: DEBUG
[21:06:12.511][C][logger:223]:   Initial Level: DEBUG
[21:06:12.514][C][logger:230]:   Log Baud Rate: 115200
[21:06:12.514][C][logger:230]:   Hardware UART: UART0
[21:06:12.514][C][logger:239]:   Task Log Buffer Size: 768 bytes
[21:06:12.546][C][spi:066]: SPI bus:
[21:06:12.551][C][spi:131]:   CLK Pin: GPIO18
[21:06:12.552][C][spi:131]:   SDI Pin: GPIO19
[21:06:12.552][C][spi:131]:   SDO Pin: GPIO23
[21:06:12.552][C][spi:074]:   Using HW SPI: SPI2_HOST
[21:06:12.576][C][cc1101:241]: CC1101:
[21:06:12.576][C][cc1101:241]:   Chip ID: 0x0014
[21:06:12.576][C][cc1101:241]:   Frequency: 433919840 Hz
[21:06:12.576][C][cc1101:241]:   Channel: 0
[21:06:12.576][C][cc1101:241]:   Modulation: ASK/OOK
[21:06:12.576][C][cc1101:241]:   Symbol Rate: 4996 baud
[21:06:12.576][C][cc1101:241]:   Filter Bandwidth: 203125.0 Hz
[21:06:12.576][C][cc1101:241]:   Output Power: 9.9 dBm
[21:06:12.599][C][cc1101:131]:   CS Pin: GPIO5
[21:06:12.599][C][restart.button:014]: Restart Button 'Restart'
[21:06:12.599][C][restart.button:216]:   Icon: 'mdi:restart'
[21:06:12.617][C][remote_base:016]: Remote Receiver Binary Sensor 'mousetrap_set'
[21:06:12.665][C][remote_base:016]: Remote Receiver Binary Sensor 'mousetrap_fired'
[21:06:12.665][C][remote_base:016]: Remote Receiver Binary Sensor 'Garagedoor_closed'
[21:06:12.676][C][remote_base:016]: Remote Receiver Binary Sensor 'Garagedoor_opened'
[21:06:12.697][C][remote_base:016]: Remote Receiver Binary Sensor 'kinetic1'
[21:06:12.717][C][remote_base:016]: Remote Receiver Binary Sensor 'kinetic2'
[21:06:12.737][C][remote_receiver.esp32:120]: Remote Receiver:
[21:06:12.737][C][remote_receiver.esp32:120]:   Clock resolution: 1000000 hz
[21:06:12.737][C][remote_receiver.esp32:120]:   RMT symbols: 192
[21:06:12.737][C][remote_receiver.esp32:120]:   Filter symbols: 0
[21:06:12.737][C][remote_receiver.esp32:120]:   Receive symbols: 192
[21:06:12.737][C][remote_receiver.esp32:120]:   Tolerance: 40%
[21:06:12.737][C][remote_receiver.esp32:120]:   Carrier frequency: 0 hz
[21:06:12.737][C][remote_receiver.esp32:120]:   Carrier duty: 100%
[21:06:12.737][C][remote_receiver.esp32:120]:   Filter out pulses shorter than: 15 us
[21:06:12.737][C][remote_receiver.esp32:120]:   Signal is done after 200 us of no changes
[21:06:12.742][C][remote_receiver.esp32:131]:   Pin: GPIO15
[21:06:12.768][C][remote_transmitter:060]: Remote Transmitter:
[21:06:12.772][C][remote_transmitter:061]:   Clock resolution: 1000000 hz
[21:06:12.772][C][remote_transmitter:061]:   RMT symbols: 64
[21:06:12.781][C][remote_transmitter:131]:   Pin: GPIO4
[21:06:12.812][C][captive_portal:141]: Captive Portal:
[21:06:12.831][C][wifi:1556]: WiFi:
[21:06:12.831][C][wifi:1556]:   Local MAC: redacted
[21:06:12.831][C][wifi:1556]:   Connected: YES
[21:06:12.834][C][wifi:1259]:   IP Address: 192.168.73.77
[21:06:12.840][C][wifi:1270]:   SSID: 'redacted'
[21:06:12.840][C][wifi:1270]:   BSSID: redacted
[21:06:12.840][C][wifi:1270]:   Hostname: 'cc1101hub'
[21:06:12.840][C][wifi:1270]:   Signal strength: -65 dB ▂▄▆█
[21:06:12.840][C][wifi:1270]:   Channel: 11
[21:06:12.840][C][wifi:1270]:   Subnet: 255.255.255.0
[21:06:12.840][C][wifi:1270]:   Gateway: 192.168.0.1
[21:06:12.840][C][wifi:1270]:   DNS1: 192.168.0.114
[21:06:12.840][C][wifi:1270]:   DNS2: 192.168.0.113
[21:06:12.859][C][web_server:424]: Web Server:
[21:06:12.859][C][web_server:424]:   Address: 192.168.73.0:80
[21:06:12.881][C][esphome.ota:098]: Over-The-Air updates:
[21:06:12.881][C][esphome.ota:098]:   Address: 192.168.0.77:3232
[21:06:12.881][C][esphome.ota:098]:   Version: 2
[21:06:12.903][C][safe_mode:058]: Safe Mode:
[21:06:12.903][C][safe_mode:058]:   Successful after: 60s
[21:06:12.903][C][safe_mode:058]:   Invoke after: 10 attempts
[21:06:12.903][C][safe_mode:058]:   Duration: 300s
[21:06:12.910][C][safe_mode:079]:   Bootloader rollback: supported
[21:06:12.923][C][web_server.ota:256]: Web Server OTA
[21:06:12.943][C][api:269]: Server:
[21:06:12.943][C][api:269]:   Address: 192.168.0.77:6053
[21:06:12.943][C][api:269]:   Listen backlog: 4
[21:06:12.943][C][api:269]:   Max connections: 5
[21:06:12.949][C][api:276]:   Noise encryption: YES
[21:06:12.964][C][mdns:259]: mDNS:
[21:06:12.964][C][mdns:259]:   Hostname: cc1101hub
[21:06:12.986][C][ir_rf_proxy:107]: RF Proxy 'RF Transmitter'
[21:06:12.986][C][ir_rf_proxy:107]:   Supports Transmitter: YES
[21:06:12.986][C][ir_rf_proxy:107]:   Supports Receiver: NO
[21:06:12.991][C][ir_rf_proxy:117]:   Frequency: 433.920 MHz (fixed)
[21:06:13.008][C][ir_rf_proxy:107]: RF Proxy 'RF Receiver'
[21:06:13.008][C][ir_rf_proxy:107]:   Supports Transmitter: NO
[21:06:13.008][C][ir_rf_proxy:107]:   Supports Receiver: YES
[21:06:13.013][C][ir_rf_proxy:117]:   Frequency: 433.920 MHz (fixed)
[21:06:15.425][I][remote.raw:035]: Received Raw: 50
[21:06:15.430][I][remote.raw:035]: Received Raw: 178
[21:06:15.444][I][remote.raw:035]: Received Raw: 167, -119, 161
[21:06:15.453][I][remote.raw:035]: Received Raw: 180
[21:06:15.459][I][remote.raw:035]: Received Raw: 159
[21:06:15.465][I][remote.raw:035]: Received Raw: 155
[21:06:15.480][I][remote.raw:035]: Received Raw: 177
[21:06:15.482][I][remote.raw:035]: Received Raw: 162
[21:06:15.488][I][remote.raw:035]: Received Raw: 170, -100, 163
[21:06:15.495][I][remote.raw:035]: Received Raw: 153
[21:06:15.505][I][remote.raw:035]: Received Raw: 157
[21:06:15.522][I][remote.raw:035]: Received Raw: 151
[21:06:15.524][I][remote.raw:035]: Received Raw: 150
[21:06:15.534][I][remote.raw:035]: Received Raw: 189
[21:06:15.551][I][remote.raw:035]: Received Raw: 176, -110, 166
[21:06:15.557][I][remote.raw:035]: Received Raw: 166
[21:06:15.568][I][remote.raw:035]: Received Raw: 160
[21:06:15.574][I][remote.raw:035]: Received Raw: 177
[21:06:15.583][I][remote.raw:035]: Received Raw: 180
[21:06:15.591][I][remote.raw:035]: Received Raw: 150
[21:06:15.596][I][remote.raw:035]: Received Raw: 167, -93, 184
[21:06:15.604][I][remote.raw:035]: Received Raw: 183
[21:06:15.619][I][remote.raw:035]: Received Raw: 160
[21:06:15.623][I][remote.raw:035]: Received Raw: 182
[21:06:15.628][I][remote.raw:035]: Received Raw: 155
[21:06:15.646][I][remote.raw:035]: Received Raw: 162
[21:06:15.647][I][remote.raw:035]: Received Raw: 162
[21:06:15.653][I][remote.raw:035]: Received Raw: 150, -110, 163
[21:06:15.659][I][remote.raw:035]: Received Raw: 163
[21:06:15.665][I][remote.raw:035]: Received Raw: 158
[21:06:15.674][I][remote.raw:035]: Received Raw: 159
[21:06:15.695][I][remote.raw:035]: Received Raw: 151
[21:06:15.696][I][remote.raw:035]: Received Raw: 148
[21:06:15.696][I][remote.raw:035]: Received Raw: 124, -140, 120
[21:06:15.702][I][remote.raw:035]: Received Raw: 131
[21:06:15.755][I][remote.raw:035]: Received Raw: 131
[21:06:15.756][I][remote.raw:035]: Received Raw: 125
[21:06:15.756][I][remote.raw:035]: Received Raw: 119
[21:06:15.758][I][remote.raw:035]: Received Raw: 132
[21:06:15.758][I][remote.raw:035]: Received Raw: 73
[21:06:15.758][I][remote.raw:035]: Received Raw: 80
[21:06:15.759][I][remote.raw:035]: Received Raw: 104
[21:06:15.760][I][remote.raw:035]: Received Raw: 79
[21:06:15.760][I][remote.raw:035]: Received Raw: 75
[21:06:15.763][I][remote.raw:035]: Received Raw: 51
[21:06:15.766][I][remote.raw:035]: Received Raw: 76
[21:06:15.772][I][remote.raw:035]: Received Raw: 26, -77, 51
[21:06:15.778][I][remote.raw:035]: Received Raw: 51
[21:06:15.788][I][remote.raw:035]: Received Raw: 51
[21:06:15.793][I][remote.raw:035]: Received Raw: 26