Sinilink WIFI USB Controller XY-WFUSB (turns USB port power on/off) - ESPHome YAML

This device allows you to turn the USB device connected to it on and off. It supports data pass through however my main uses are just to turn USB devices, such as a USB Microscope, on and off.

I found some very basic YAML online so I figured I’d create my own. Sharing in case others would like to use it. I split the YAML into two so that you don’t need to edit many files if you make changes to the core functionality in the template file.

While you can use the restore_mode to define the USB port state at boot up, I wanted to be able to configure it so I set it to ALWAYS_OFF and then switch it on if the configured default is On. If it isn’t, then it will switch it off at boot… this is not necessary unless you change the restore_mode to something that may default it to on.

The Red led is wired to the output mosfet that controls power to the USB port so it can’t be configured and will always turn on when the port is on. The green and blue leds are configurable however I let the blue led remain the status_led as I had no other function for it. The green led turns on when the port is off to indicate there is power, and off when the port is on and thus the red led is on. You can now also configure it to be on when the port is on (along with the red), or just disable it to minimize light output & power draw.

If you want to merge all the YAML into one file, remember to remove the extra indent on the YAML in the template file.

I am not a programmer so I am quite sure there are better ways to accomplish what I did… glad to get feedback on how to improve the YAML.

EDIT: For those who will likely tell me that I could have avoided lambda… I used it as it is more compact and IMO versatile. Boils down to personal preference.

microscope.yaml

substitutions:
  devicename: microscope
  devicename_no_dashes: microscope
  friendly_devicename: "Microscope"
  device_description: "Microscope"
  update_interval_wifi: "120s"
  restore_mode_setting: ALWAYS_OFF
  #restore_mode: Control how the relay attempts to restore state on bootup.
  #RESTORE_DEFAULT_OFF          - Attempt to restore state and default to OFF if not possible to restore.
  #RESTORE_DEFAULT_ON           - Attempt to restore state and default to ON.
  #RESTORE_INVERTED_DEFAULT_OFF - Attempt to restore state inverted from the previous state and default to OFF.
  #RESTORE_INVERTED_DEFAULT_ON  - Attempt to restore state inverted from the previous state and default to ON.
  #ALWAYS_OFF                   - Always initialize the pin as OFF on bootup.
  #ALWAYS_ON                    - Always initialize the pin as ON on bootup.

esphome:
  name: "${devicename}"
  friendly_name: "${friendly_devicename}"
  comment: "${device_description}"
  on_boot:
    then:
      - script.execute: on_boot_default_state

esp8266:
  board: esp01_1m
  framework:
    version: recommended
  restore_from_flash: true

wifi:
  ssid: !secret iot_wifi_ssid
  password: !secret iot_wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "${devicename}"
    password: !secret iot_wifi_password
    ap_timeout: 3min

#Faster than DHCP. Also use if can't reach because of name change
  #manual_ip:
    #static_ip: 192.168.3.218
    #gateway: 192.168.3.1
    #subnet: 255.255.255.0
    #dns1: 192.168.1.25
    #dns2: 192.168.1.26

#Manually override what address to use to connect to the ESP.
#Defaults to auto-generated value. Example, if you have changed your
#static IP and want to flash OTA to the previously configured IP address.
  #use_address: 192.168.3.218


<<: !include usb-port-switch-template.yaml

usb-port-switch-template.yaml


  logger:
    logs:
      sensor: INFO
      binary_sensor: INFO
      text_sensor: INFO

  # Enable Home Assistant API
  api:

  ota:
    password: !secret ota_pwd

  web_server:
    port: 80
    version: 2
    include_internal: true
    ota: false

  captive_portal:

  # Sync time with Home Assistant
  time:
    - platform: homeassistant
      id: ha_time

  text_sensor:
    - platform: wifi_info
      ip_address:
        name: "IP"
        icon: "mdi:ip-outline"
        update_interval: ${update_interval_wifi}
      ssid:
        name: "SSID"
        icon: "mdi:wifi-settings"
        update_interval: ${update_interval_wifi}
      bssid:
        name: "BSSID"
        icon: "mdi:wifi-settings"
        update_interval: ${update_interval_wifi}
      mac_address:
        name: "MAC"
        icon: "mdi:network-outline"
      scan_results:
        name: "Wifi Scan"
        icon: "mdi:wifi-refresh"
        disabled_by_default: true

  #Alternative, if blue led is needed for something else:
  #https://esphome.io/components/light/status_led.html
  status_led:
    pin:
      number: 16 # Blue LED

  switch:
    - platform: gpio
      id: port_power
      restore_mode: ${restore_mode_setting}
      pin: 5

    - platform: gpio
      pin: 14
      id: green_led
      inverted: false

    - platform: template
      id: usb_port
      name: ""
      lambda: |-
        if (id(port_power).state) {
          return true;
        } else {
          return false;
        }
      turn_on_action:
        - lambda: |-
            id(port_power).turn_on();
      turn_off_action:
        - lambda: |-
            id(port_power).turn_off();
      on_turn_on:
        - lambda: |-
            if (id(green_led_mode).state != "Never" && id(green_led_mode).state != "Always") {
              if (id(green_led_mode).state == "Port On") {
                id(green_led).turn_on();
                }
                else {
                  id(green_led).turn_off();
                }
            }
      on_turn_off:
        - lambda: |-
            if (id(green_led_mode).state != "Never" && id(green_led_mode).state != "Always") {
              if (id(green_led_mode).state == "Port On") {
                id(green_led).turn_off();
                }
                else {
                  id(green_led).turn_on();
                }
            }
      
  # Button
  binary_sensor:
    - platform: gpio
      id: btn
      name: "Button"
      pin:
        number: 4
        inverted: true
        mode:
          input: true
          pullup: true
      on_press:
        - switch.toggle: port_power

  sensor:
    - platform: wifi_signal
      name: "WiFi Signal"
      update_interval: ${update_interval_wifi}
      device_class: signal_strength

  button:
    - platform: restart
      name: "Restart"
      entity_category: diagnostic

    - platform: safe_mode
      name: "Safe Mode"
      entity_category: diagnostic

  select:
      # option to control how LEDs are used. Red led is hardwaired to output so it cannot be controlled
    - platform: template
      name: "Green LED ON when"
      icon: mdi:led-on
      id: green_led_mode
      optimistic: true
      options:
        - "Port On"
        - "Port Off"
        - "Always"
        - "Never"
      initial_option: "Port Off"
      restore_value: true
      entity_category: config
      on_value:
        - lambda: |-
            if (id(green_led_mode).state == "Always") {
              id(green_led).turn_on();
            }
            if (id(green_led_mode).state == "Never") {
              id(green_led).turn_off();
            }
            if (id(green_led_mode).state == "Port On" && id(usb_port).state) {
              id(green_led).turn_on();
            }
            if (id(green_led_mode).state == "Port On" && !id(usb_port).state) {
              id(green_led).turn_off();
            }
            if (id(green_led_mode).state == "Port Off" && id(usb_port).state) {
              id(green_led).turn_off();
            }
            if (id(green_led_mode).state == "Port Off" && !id(usb_port).state) {
              id(green_led).turn_on();
            }

      # option to disable button
    - platform: template
      name: "Default Port State"
      id: default_state
      optimistic: true
      options:
        - "On"
        - "Off"
      initial_option: "On"
      restore_value: true
      entity_category: config

  script:
    - id: on_boot_default_state
      then:
        lambda: |-
              if(id(default_state).state == "On") {
                id(port_power).turn_on();
              } else {
                id(port_power).turn_off();
              }