ESPHome for Sonoff T5 family of Switches
ESPHome for Sonoff T5 family of Switches
It’s hard to beat Sonoff switches when it comes to well-made, affordable, Home Assistant compatible switches. Ever since they announced the T5 series, I’ve been patiently waiting for the US variant to become available so I could replace my M5 switches with T5 switches.
Don’t get me wrong, the M5 switches are great… but not perfect.
The T5 switches improve on the M5 limitations with some new and novel hardware features. Taking advantage of these unique features requires a considerably more complex ESPHome configuration than the M5 series switches.
But before diving into the configuration, let’s briefly take a closer look at the hardware.
Brief hardware overview
Everything I’m going to cover below is for the US version.
Presumably the international version has a different layout and total number of LEDs.
The T5 series follows the “two part” design of the M5 switches; there’s a “base” that gets mounted in the wall and then the “face plate” that snaps on to the base. All high-voltage electronics stay in the base and the face plate is just a PCB with a touch sensor and LEDs. As far as I can tell, the face plates are interchangeable between the 1, 2, 3 and 4 relay variants but only within the same family; the physical features that mate the face plate to the base differ between M and T series switches.
The one bit of information that doesn’t seem to be readily available online is the location of the LEDs on the PCB, specifically the US version.
LED locations
For the US version, there are 32 LEDs around the perimeter of the switch; 6 on the top, 6 on the bottom, and 10 on each side.
From the front of the switch, mounted in traditional “tall” orientation:
- Top right corner going down the right side LED 32, 1-9
- Bottom right corner going across the bottom to the left LED 10-15
- Bottom left corner going up the left side LED 16-25
- Top left corner going across the top to the right LED 26-31
T5 improvements over M5
My issues with the M5 switches can be broadly summarized as:
- The physical touch targets are TINY relative to the size of the switch face.
- There’s only a TINY single-color LED that indicates the state of the switch and where the user should touch to trigger the relay.
Small Touch Area
The 1C
variant has the largest touch area but it’s still only about 50% of the switch face.
As you increase the number of relays, the area dedicated to each physical touch zone decreases which makes it harder to press.
If you’re coming into a room with arms full of groceries and you try to hit one of the buttons on the 3C
variant with your elbow, you’re going to have a bad time.
There’s no reason why the physical touch zones couldn’t use the entire surface of the switch.
The T5 series fixes this by making the entire surface of the switch touch sensitive!
This introduces a new problem, though, how do you know where to touch to toggle a given output? Look at these two styles of face plates for the T5 series and see if you can identify which belongs to the 1, 2, 3 and 4 relay variants:
You can’t.
If you look really close, you can see very faint delineation lines between the touch zones but it’s not obvious at a glance and it certainly will not be obvious to guests looking at the switch from across the room. Trying to figure out where to touch in a dark room is even harder.
We can solve this with the LEDs around the perimeter of the switch, though!
Indicating touch zone and relay state
The M5 switches have a single red LED for each physical button that is fully illuminated when the relay is on. As a group, these indicator LEDs can be dimmed to indicate where to touch to trigger the relay.
To get a comparable visual indicator, we can use the LEDs around the perimeter of the touch panel; split the LEDs on the sides into groups; one group per relay/touch-area.
Instead of using LEDs on both the right and left side together, alternate which side is lit up to indicate the state of the relay; if the LEDs on the left are lit up, the relay is on and if the LEDs on the right are lit up, the relay is off.
Given this picture, you can clearly tell that this T5 switch supports two touch areas and both relays are currently off:
This is a huge improvement over the M5 series switches but it comes with a cost: complexity. The T5 comes in 1, 2, 3 and 4 relay variants. Each relay means a set of lights that need to be controlled. Excluding the RGB LEDs on the top/bottom of the switch, this gives us up to 8 partition lights that we need to create in the ESPHome configuration.
ESPHome Configuration
Here’s what the UI looks like for the 1 relay variant.
For a single switch that has just a single relay, there’s an awful lot going on here as the copious amount of yaml
below will demonstrate.
Normally I’d just show the yaml
with comments in the relevant sections but there’s a few “features” that I want to detail first before diving into how they are implemented.
Features
Controls:
light.{Bottom,Top}
: These are the bottom/top partitions of the RGB LEDs around the perimeter of the switch. I don’t use them for anything in the ESPHome configuration but they are exposed to Home Assistant so that I can use them for other automations and notifications. Think “pulse the top LEDs on the front-door switch when the garage door is open” …light.Mood Light
: This is the entire ring of RGB LEDs around the perimeter of the switch. Like the Top/Bottom lights, I don’t use this for anything explicitly in the ESPHome configuration but it is exposed to Home Assistant so that I can use it for other automations and notifications.light.Light
: This is the actual light entity that is controlled by the relay.
Configuration:
button.{Daytime,Nighttime} Mode
: These act as simple “one touch” buttons that set thelight.Indicator
to a hardcoded color/brightness for a given regime.button.Determine Mode
: This is a manual trigger for an otherwise automatic script that determines which regime to use.light.Indicator
: This is a “template” light that wraps the set of lights that indicate the state of the relay and touch zone.number.Light Timer
: This is a dynamic timer that is used to turn off the light after a given amount of time. A sane default value is chosen but it can be overridden from the Home Assistant UI if needed. Example: normally, keep the bathroom fan on for 30 minutes unless taking a long and luxurious bath, then adjust the timer for 90 minutes.button.Light Timer Restart
: Restarts the dynamic timer for the light. Useful for extending the amount of time the light is on if, for example, Home Assistant detects that the room is still occupied.switch.Light Timer
: Toggle to control if the dynamic timer should be armed or not.switch.Sun position changes light regime
: Toggle to control if the sun position should trigger a change in the regime.switch.Touch Enable
: Toggle to control if the touch sensor inputs should be processed or ignored.
Diagnostic:
text.Light Timeout Time Remaining
: This is a template text that displays the remaining time on the dynamic timer. Useful for triggering other automations when the timer is about to expire.
Indicator / “Template” Light
Remember that the solution to the “where do I touch to toggle / what’s the current state of the” relay problem is to use the LEDs around the perimeter of the switch. Specifically, cut the LEDs on left and right side into groups and then associate each left/right pair with a relay/touch zone.
This will result in two “lights” for each relay; one for the “on” state and one for the “off” state. I want to hide these lights from Home Assistant as they are just an implementation detail and should not be controlled directly. For each relay, I want only a single “template” light that I can assign color/brightness to and have that automatically propagate to the “on” or “off” partition light as appropriate for the relay’s current state.
This single light is the light.Indicator
entity.
ESPHome doesn’t technically have a “template” light but it does have a custom light component that can be used to create a “template” light.
For convenience, the button.{Daytime,Nighttime} Mode
entities set the color/brightness of the light.Indicator
to a hardcoded value for the given regime.
This is useful for quickly getting each indicator light into a consistent state after some other automation has changed the color/brightness for a subset of indicator lights.
Regimes
I use the word regime and mode interchangeably to refer to a set of color/brightness values for the indicator lights. This is a byproduct of an earlier version of the configuration where I had stricter control over weather or not the partition lights or moodlight should be “in control” of what the RGB LEDs are doing. I’ve since relaxed this requirement and settled on a general “the partition lights are in control until the Moodlight is turned on” policy.
This ultimately stems from how ESPHome tries to make a single string of addressable LEDs behave like multiple independent strings of LEDs. The last “light” to be updated is the one that “wins”, and gets to control the LEDs. If you set an effect like Rainbow on the moodlight and then turn on the partition lights, the partition lights will “win” until the moodlight moves to a new color; then the moodlight will “win” until the partition lights are updated again.
However, when the moodlight is turned off, the partition lights will resume their default regime.
Since each “indicator” light is exposed to Home Assistant, it’s possible to set a unique color for each relay if desired. But without explicitly changing the color/brightness of the indicator lights, two “baked-in” modes are present: daytime, and nighttime.
The color/brightness values for these two modes are declared once in the yaml
, so they’re easy to change if your particular deployment calls for different colors.
It just so happened that given the various locations that each switch is deployed a soft blue and red happened to work best for me.
Here’s two pictures of the same switch under the “no-moodlight” regime in both daytime and nighttime mode.
In the first photo, relays 1 and 3 are on, relay 2 is off. In the second photo, relay 1 is off but 2 and 3 are on.
Dynamic Timer
I’ve already covered the basics of how to do this with ESPHome in my “dynamic timers in ESPHome” post. The same technique is used again here but it’s been refined a bit and turned into a proper package which is easier to re-use.
YAML
There are some similarities to the examples provided by SmartHome-yourself
in their sonoff-tx-ultimate-for-esphome
custom component but I ultimately decided to go in a different direction for most things.
I still use his custom component for the touch sensor but the rest of the configuration is my own.
Below I have provided a complete and working example of the configuration for a 3 relay variant. I specifically chose the 3 relay variant because it’s the most complex; creating a 1 or 2 relay variant is a subset of the 3 relay variant; take what’s below and delete the parts you don’t need.
For this example, I’ve provided a sample garage.yaml
file which is a lightly modified version of the configuration I have deployed.
Specifically, I have a combination of lights and a fan wired to the switch so the example demonstrates how to use multiple relays to control multiple different types of devices.
I’ve left comments throughout the files to explain what’s going on and why. Those comments - in addition to the “features” described above - should be enough to get you started with your own configuration.
File structure
For readability and composability, I like to break up my ESPHome configuration into multiple files using the packages
pattern.
Here is how I have this example laid out:
|
|
Assuming you reproduce this structure, you can compile and flash the example with:
|
|
If you don’t want to embed the git hash into the build, remove the -s version_hash $(git rev-parse --short HEAD)
part and remove the version_hash
substitution from packages/base.esphome.yaml
.
garage.yaml
|
|
packages/base.esphome.yaml
|
|
packages/base.yaml
|
|
packages/buzzer.yaml
|
|
packages/countdown-timer.yaml
|
|
packages/light-automations.yaml
|
|
packages/status_led.yaml
|
|
packages/template_light.h
|
|
packages/touch_disable.yaml
|
|
packages/variant.c3.yaml
|
|