SmartSwitch @4€!

Hi all!
I would like to share some good hints to quickly assemble a Smart Switch ESPHome compatible with a total cost of around 4€.

  1. Go on Aliexpress and buy a Smart Switch Tuya-compliant, the cheapest version at around 2€. Here is the picture:

Then you can desolder the original, totally unknown wifi board:

Then , still on the same site, buy an ESP-02 which is pin to pin compatible. Program it with a standard Usb-to-serial programmer with ESP Home and then solder it in the same place:

Then, once the chip is connected, configure the pins as follows:
GPIO12: Relay
GPIO14: Manual switch

That’s all. Hope you will find it useful!

Cheers!

1 Like

Have you tried to connect a programmer to the original? Maybe it is actually an ESP chip. Might get some info via something like esptool.py.

It’s an LN882H, not esp but now supported by openbeken

https://www.elektroda.com/rtvforum/topic4028087.html

2 Likes

Tasmota template
{“NAME”:“Mini Smart Switch”,“GPIO”:[1,1,1,1,320,1,1,1,224,32,160,1,1,1],“FLAG”:0,“BASE”:18}

Hi.
I have a similar device, but with a CB2S module and an LN882H chip. I installed OpenBeken, but I prefer ESPHome with HA. The switch works, but it has a few minor issues with ESPHome:

  1. Despite the IP configuration, ESPHome obtains its address from DHCP.
  2. It doesn’t display signal strength when scanning for WiFi networks.
  3. The only update option is OTA via the website.

My configuration:

esphome:
  name: sw-garaz
  friendly_name: sw-garaz

ln882x:
  board: generic-ln882hki

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "***"

ota:
  - platform: esphome
    password: !secret ota_password

wifi:
  networks:
    - ssid: ***
      password: !secret wifi_password_1
    - ssid: ***
      password: !secret wifi_password_2
    - ssid: ***
      password: !secret wifi_password_3
    - ssid: ***
      password: !secret wifi_password_4
  manual_ip:
    static_ip: 192.168.1.84
    gateway: 192.168.1.1
    subnet: 255.255.255.0
    dns1: 192.168.1.1
    dns2: 91.234.8.8
  ap:
    ssid: !secret wifi_ap_ssid
    password: !secret wifi_ap_password
captive_portal:
preferences:
  flash_write_interval: 12h  
web_server:
  port: 80
  version: 3
  auth:
    username: !secret web_username
    password: !secret web_password
time:
  - id: time_provider
    platform: homeassistant
    on_time_sync:
      - logger.log: "Synchronized system clock"    
text_sensor:
  - platform: wifi_info
    ip_address:
      name: ESP IP Address
    ssid:
      name: ESP Connected SSID
    mac_address:
      name: ESP Mac Wifi Address
    scan_results:
      name: ESP Latest Scan Results
binary_sensor:
  - platform: gpio
    id: ext_onoff
    pin:
      number: P6
      inverted: true
      mode: INPUT_PULLUP
    on_click:
      - min_length: 50ms
        max_length: 500ms
        then:
          - if:
              condition:
                lambda: 'return id(rel_1).state;'
              then:
                - switch.turn_off: rel_1
                - script.stop: timer
              else:
                - script.execute: timer
    on_press:
      then:
        - script.stop: timer
        - switch.turn_on: rel_1 
    on_release: 
      then:
        - switch.turn_off: rel_1     

  - platform: gpio
    id: int_onoff
    pin:
      number: P10
      inverted: true
      mode: INPUT_PULLUP
    on_click:
      - min_length: 50ms
        max_length: 500ms
        then:
          - if:
              condition:
                lambda: 'return id(rel_1).state;'
              then:
                - switch.turn_off: rel_1
                - script.stop: timer
              else:
                - script.execute: timer
      - min_length: 1000ms
        max_length: 5000ms
        then:
          - script.stop: timer        
          - switch.turn_on: rel_1     

switch:
  - platform: gpio
    id: rel_1
    name: Relay 1
    pin: P11

button:    
  - platform: template
    on_press: 
      - if:
          condition:
            lambda: 'return id(rel_1).state;'
          then:
            - switch.turn_off: rel_1
            - script.stop: timer
          else:
            - script.execute: timer
    name: "Start"
    icon: mdi:timer
  - platform: restart
    name: Restart 
    
status_led:
  pin:
    number: P7
    inverted: true

script:
  - id: timer
    then:
      - switch.turn_on: rel_1
      - delay: !lambda return id(run_time).state*60000;
      - switch.turn_off: rel_1

number:
  - platform: template
    id: run_time
    name: "Nast. czasu"
    icon: mdi:av-timer
    unit_of_measurement: "min."
    optimistic: True
    step: 1
    mode: box
    min_value: 1
    max_value: 60
    restore_value: True
    on_value:
      - sensor.template.publish:
          id: runtime
          state: !lambda 'return x;'

sensor:
  - platform: template
    id:  runtime
    name: "Timer"

logs:

INFO ESPHome 2025.12.2
INFO Reading configuration /config/esphome/sw-garaz.yaml...
INFO Detected timezone 'Europe/Warsaw'
INFO Starting log output from 192.168.1.22 using esphome API
INFO Successfully resolved sw-garaz @ 192.168.1.22 in 0.000s
INFO Successfully connected to sw-garaz @ 192.168.1.22 in 0.101s
INFO Successful handshake with sw-garaz @ 192.168.1.22 in 0.057s
[22:30:51.663][I][app:194]: ESPHome version 2025.12.2 compiled on Dec 23 2025, 20:37:01
[22:30:51.673][C][logger:261]: Logger:
[22:30:51.673][C][logger:261]:   Max Level: DEBUG
[22:30:51.673][C][logger:261]:   Initial Level: DEBUG
[22:30:51.685][C][logger:267]:   Log Baud Rate: 115200
[22:30:51.685][C][logger:267]:   Hardware UART: UART0
[22:30:51.702][C][status_led:018]: Status LED:
[22:30:51.715][C][status_led:019]:   Pin: 7
[22:30:51.715][C][switch.gpio:092]: GPIO Switch 'Relay 1'
[22:30:51.715][C][switch.gpio:092]:   Restore Mode: always OFF
[22:30:51.721][C][switch.gpio:029]:   Pin: 11
[22:30:51.744][C][template.number:016]: Template Number 'Nast. czasu'
[22:30:51.751][C][template.number:019]:   Icon: 'mdi:av-timer'
[22:30:51.757][C][template.number:023]:   Unit of Measurement: 'min.'
[22:30:51.765][C][template.number:049]:   Optimistic: YES
[22:30:51.771][C][template.number:399]:   Update Interval: 60.0s
[22:30:51.780][C][template.sensor:017]: Template Sensor 'Timer'
[22:30:51.780][C][template.sensor:017]:   State Class: ''
[22:30:51.780][C][template.sensor:017]:   Unit of Measurement: ''
[22:30:51.780][C][template.sensor:017]:   Accuracy Decimals: 1
[22:30:51.794][C][template.sensor:399]:   Update Interval: 60.0s
[22:30:51.804][C][gpio.binary_sensor:016]: GPIO Binary Sensor 'ext_onoff'
[22:30:51.811][C][gpio.binary_sensor:072]:   Pin: 6
[22:30:51.824][C][gpio.binary_sensor:073]:   Mode: polling
[22:30:51.829][C][gpio.binary_sensor:016]: GPIO Binary Sensor 'int_onoff'
[22:30:51.831][C][gpio.binary_sensor:072]:   Pin: 10
[22:30:51.837][C][gpio.binary_sensor:073]:   Mode: polling
[22:30:51.860][C][homeassistant.time:010]: Home Assistant Time
[22:30:51.873][C][time:029]: Timezone: 'CET-1CEST,M3.5.0,M10.5.0/3'
[22:30:51.875][C][wifi_info:016]: SSID 'ESP Connected SSID'
[22:30:51.893][C][wifi_info:016]: MAC Address 'ESP Mac Wifi Address'
[22:30:51.902][C][wifi_info:016]: IP Address 'ESP IP Address'
[22:30:51.917][C][restart.button:014]: Restart Button 'Restart'
[22:30:51.924][C][restart.button:017]:   Icon: 'mdi:restart'
[22:30:51.949][C][captive_portal:118]: Captive Portal:
[22:30:51.952][C][wifi:1132]: WiFi:
[22:30:51.952][C][wifi:1132]:   Connected: YES
[22:30:51.958][C][wifi:897]:   Local MAC: 00:50:C2:B9:59:E3
[22:30:51.965][C][wifi:904]:   IP Address: 192.168.1.22
[22:30:51.977][C][wifi:908]:   SSID: [redacted]
[22:30:51.977][C][wifi:908]:   BSSID: [redacted]
[22:30:51.977][C][wifi:908]:   Hostname: 'sw-garaz'
[22:30:51.977][C][wifi:908]:   Signal strength: -77 dB ▂▄▆█
[22:30:51.977][C][wifi:908]:   Channel: 10
[22:30:51.977][C][wifi:908]:   Subnet: 255.255.255.0
[22:30:51.977][C][wifi:908]:   Gateway: 192.168.1.1
[22:30:51.977][C][wifi:908]:   DNS1: 192.168.1.1
[22:30:51.977][C][wifi:908]:   DNS2: 0.0.0.0
[22:30:52.004][C][web_server:335]: Web Server:
[22:30:52.004][C][web_server:335]:   Address: 192.168.1.84:80
[22:30:52.018][C][esphome.ota:092]: Over-The-Air updates:
[22:30:52.018][C][esphome.ota:092]:   Address: 192.168.1.84:8820
[22:30:52.018][C][esphome.ota:092]:   Version: 2
[22:30:52.029][C][esphome.ota:099]:   Password configured
[22:30:52.038][C][safe_mode:018]: Safe Mode:
[22:30:52.038][C][safe_mode:018]:   Successful after: 60s
[22:30:52.038][C][safe_mode:018]:   Invoke after: 10 attempts
[22:30:52.038][C][safe_mode:018]:   Duration: 300s
[22:30:52.049][C][web_server.ota:241]: Web Server OTA
[22:30:52.068][C][api:211]: Server:
[22:30:52.068][C][api:211]:   Address: 192.168.1.84:6053
[22:30:52.068][C][api:211]:   Listen backlog: 4
[22:30:52.068][C][api:211]:   Max connections: 8
[22:30:52.073][C][api:218]:   Noise encryption: YES
[22:30:52.085][C][wifi_info:016]: Scan Results 'ESP Latest Scan Results'
[22:30:52.106][C][mdns:177]: mDNS:
[22:30:52.106][C][mdns:177]:   Hostname: sw-garaz
[22:30:52.114][C][lt.component:013]: LibreTiny:
[22:30:52.114][C][lt.component:013]:   Version: v1.9.1 on generic-ln882hki, compiled at Dec 23 2025 20:34:44, GCC 10.3.1 (-Os)
[22:30:52.114][C][lt.component:013]:   Loglevel: 3

After accepting the IP change in the HA, the switch is visible in the HA and working properly. A fix in Libretiny is probably required.