############################################# ############################################# # OFFICE DUAL LIGHT CONTROL # - Overhead cool white lights # - Right hand warm bunker light # # Controlled by a Sonoff Dual R1 # A sonoff dual uses serial data to turn the relays on/off # # V2.4 - 2025-06-30 Tidied up MQTT direct relay control (esps can control each other via MQTT) # V2.3 - 2025-06-18 Added MQTT direct relay control # # NOTES: # Command the lights on with MQTT # ${mqtt_local_command_full_topic}/relay1/set ON or OFF # ${mqtt_local_command_full_topic}/relay2/set ON or OFF # ${mqtt_local_status_full_topic}/relay1/set ON or OFF # ${mqtt_local_status_full_topic}/relay2/set ON or OFF # ########################################################################################## ########################################################################################## ########################################################################################## # SPECIFIC DEVICE VARIABLE SUBSTITUTIONS # If NOT using a secrets file, just replace these with the passwords etc (in quotes) ########################################################################################## substitutions: # Device Naming device_name: "esp-officeduallights" friendly_name: "Office Dual Lights" description_comment: "Dual Office Lights (Overhead and right hand Bunker) :: Sonoff Dual R1" device_area: "Office" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming project_name: "Sonoff Technologies.Sonoff Dual R1" # Project Details project_version: "v2.3" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # Passwords & Secrets api_key: !secret esp-api_key ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-officeduallights_ip # unfortunately you can't use substitutions inside secrets names mqtt_local_command_main_topic: !secret mqtt_local_command_main_topic mqtt_local_status_main_topic: !secret mqtt_local_status_main_topic # Device Settings relay_icon: "mdi:lightbulb-group" log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE update_interval: "60s" # update time for for general sensors etc # MQTT Controls mqtt_device_name: "office-dual-lights" mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA # Switch Naming switch_1_name: "Dual L1 Relay" relay_1_icon: "mdi:lightbulb" light_1_name: "Light 1 (Right Hand Bunker Light)" switch_2_name: "Dual L2 Relay" relay_2_icon: "mdi:lightbulb" light_2_name: "Light 2 (Cool White Overhead Lights)" ########################################################################################## # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html ########################################################################################## packages: common_wifi: !include file: common/network_common.yaml vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" common_api: !include file: common/api_common.yaml vars: local_api_key: "${api_key}" #common_webportal: !include # file: common/webportal_common.yaml common_mqtt: !include file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" common_sntp: !include file: common/sntp_common.yaml common_general_sensors: !include file: common/sensors_common.yaml vars: local_friendly_name: "${friendly_name}" local_update_interval: "${update_interval}" ########################################################################################## # ESPHome # https://esphome.io/components/esphome.html ########################################################################################## esphome: name: "${device_name}" friendly_name: "${friendly_name}" comment: "${description_comment}" # Appears on the esphome page in HA area: "${device_area}" platformio_options: build_flags: - "-Os" # optimize for size - "-Wl,--gc-sections" # drop unused code/data - "-fno-exceptions" # strip C++ exceptaions - "-fno-rtti" # strip C++ RTTI ########################################################################################## # ESP Platform and Framework # https://esphome.io/components/esp32.html ########################################################################################## esp8266: board: esp01_1m # The original sonoff basic restore_from_flash: False # restore some values on reboot preferences: flash_write_interval: 5min mdns: disabled: True ########################################################################################## # ESPHome Logging Enable # https://esphome.io/components/logger.html ########################################################################################## # NOTE: Sonoff Dual CANNOT send serial data to log ############################################### logger: level: "${log_level}" #INFO Level suggested, or DEBUG for testing baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM, Serial control) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 ########################################################################################## # UART Bus # https://esphome.io/components/uart.html ########################################################################################## uart: tx_pin: GPIO01 rx_pin: GPIO03 baud_rate: 19200 #data_bits: 8 #stop_bits: 1 #parity: EVEN ########################################################################################## # MQTT COMMANDS # This adds device-specific MQTT command triggers to the common MQTT configuration. ########################################################################################## mqtt: # Direct MQTT control for relays via serial commands on_message: # Relay 1 control - topic: "${mqtt_local_command_topic}/relay1/set" payload: "ON" then: - switch.turn_on: relay_1 - light.turn_on: light_1 - topic: "${mqtt_local_command_topic}/relay1/set" payload: "OFF" then: - switch.turn_off: relay_1 - light.turn_off: light_1 # Relay 2 control - topic: "${mqtt_local_command_topic}/relay2/set" payload: "ON" then: - switch.turn_on: relay_2 - light.turn_on: light_2 - topic: "${mqtt_local_command_topic}/relay2/set" payload: "OFF" then: - switch.turn_off: relay_2 - light.turn_off: light_2 ########################################################################################## # STATUS LED # https://esphome.io/components/status_led.html ########################################################################################## # Sonoff Dual LED is GPIO13 ############################################# status_led: pin: number: GPIO13 inverted: yes ########################################################################################## # BINARY SENSORS # https://esphome.io/components/binary_sensor/ ########################################################################################## # Sonoff Dual R1 buttons are GPIO04, GPIO14 ############################################# binary_sensor: - platform: gpio pin: number: GPIO4 mode: INPUT_PULLUP inverted: true id: button_1 on_press: - switch.toggle: relay_1 - platform: gpio pin: number: GPIO14 mode: INPUT_PULLUP inverted: true id: button_2 on_press: - switch.toggle: relay_2 ########################################################################################## # SWITCH COMPONENT # https://esphome.io/components/switch/ ########################################################################################## # Sonoff Dual R1 requires serial data to switch ############################################# switch: - platform: template name: "${switch_1_name}" id: relay_1 optimistic: true icon: "${relay_1_icon}" internal: true turn_on_action: - mqtt.publish: topic: "${mqtt_local_status_topic}/relay1/state" payload: "ON" - if: condition: switch.is_off: relay_2 then: - uart.write: [0xA0, 0x04, 0x01, 0xA1] else: - uart.write: [0xA0, 0x04, 0x03, 0xA1] turn_off_action: - mqtt.publish: topic: "${mqtt_local_status_topic}/relay1/state" payload: "OFF" - if: condition: switch.is_off: relay_2 then: - uart.write: [0xA0, 0x04, 0x00, 0xA1] else: - uart.write: [0xA0, 0x04, 0x02, 0xA1] - platform: template name: "${switch_2_name}" id: relay_2 optimistic: true icon: "${relay_2_icon}" internal: true turn_on_action: - mqtt.publish: topic: "${mqtt_local_status_topic}/relay2/state" payload: "ON" - if: condition: switch.is_off: relay_1 then: - uart.write: [0xA0, 0x04, 0x02, 0xA1] else: - uart.write: [0xA0, 0x04, 0x03, 0xA1] turn_off_action: - mqtt.publish: topic: "${mqtt_local_status_topic}/relay2/state" payload: "OFF" - if: condition: switch.is_off: relay_1 then: - uart.write: [0xA0, 0x04, 0x00, 0xA1] else: - uart.write: [0xA0, 0x04, 0x01, 0xA1] ################################################################################ # TEMPLATE OUTPUTS: drive the real relays when the light state changes ################################################################################ output: - platform: template id: light_output_1 type: binary write_action: - lambda: |- if (state) id(relay_1).turn_on(); else id(relay_1).turn_off(); - platform: template id: light_output_2 type: binary write_action: - lambda: |- if (state) id(relay_2).turn_on(); else id(relay_2).turn_off(); ########################################################################################## # LIGHT COMPONENT # https://esphome.io/components/light/ ########################################################################################## light: - platform: binary name: "${light_1_name}" id: light_1 output: light_output_1 - platform: binary name: "Light 2 (Cool White Overhead Lights)" id: light_2 output: light_output_2