Complete re-write of the Tuya Light Plus component (#10)

This commit is contained in:
Chris Nussbaum 2021-07-12 08:33:37 -05:00 committed by GitHub
parent 4b6c87b941
commit 85a65d6307
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 900 additions and 526 deletions

143
README.md
View File

@ -1,94 +1,91 @@
# ESPHome-Devices
## Overview
> This is a collection of [ESPHome](https://ESPHome.io) configuration files and code for my various ESP8266/ESP32 devices that integrate with [Home Assistant](https://www.home-assistant.io/). I am using includes and packages pretty extensively in order to prevent duplication and allow for easy changing of common settings.
This is a collection of [ESPHome](https://ESPHome.io) custom components, configuration files, and custom code for my various ESP8266/ESP32 devices that integrate with [Home Assistant](https://www.home-assistant.io/). I am using includes and packages pretty extensively in order to prevent duplication and allow for easy changing of common settings.
> **What is ESPHome**<br>
> ESPHome is a system to control your ESP8266/ESP32 by simple yet powerful configuration files and control them remotely through Home Automation systems. For more information checkout [ESPHome.io](https://ESPHome.io).
### What is ESPHome
ESPHome is a system to control your ESP8266/ESP32 by simple yet powerful configuration files and control them remotely through Home Automation systems. For more information checkout [ESPHome.io](https://ESPHome.io).
> **What is Home Assistant**<br>
> Home Assistant is open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts. Perfect to run on a Raspberry Pi or a local server. For more information check out [Home-Assistant.io](https://www.home-assistant.io/).
## Custom Devices
> ### [Basement Bathroom Sensor](./devices/basement_bathroom_sensor.yaml)
> This is a [WEMOS D1 Mini clone](https://www.amazon.com/gp/product/B076F52NQD/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that is connected to a [motion sensor](https://www.amazon.com/gp/product/B07GJDJV63/ref=ppx_yo_dt_b_asin_title_o06_s01?ie=UTF8&psc=1), a [temperature/humidity/pressure sensor](https://www.amazon.com/gp/product/B07KYJNFMD/ref=ppx_yo_dt_b_asin_title_o06_s01?ie=UTF8&psc=1), and a [door sensor](https://www.amazon.com/gp/product/B07YBGZNNW/ref=ppx_yo_dt_b_asin_title_o09_s00?ie=UTF8&psc=1) and is used to control the lights, fan, and heater (heat lamps in the fan) in my basement bathroom.
### What is Home Assistant
Home Assistant is open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts. Perfect to run on a Raspberry Pi or a local server. For more information check out [Home-Assistant.io](https://www.home-assistant.io/).
> ### [Coffee Maker](./devices/coffee_maker.yaml)
> This is a [NodeMCU](https://www.amazon.com/gp/product/B010N1SPRK/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that I installed in my [Cuisinart Coffee Maker](https://www.amazon.com/gp/product/B01N6T5QNO/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1). It has GPIO's connected to the indicator lights for the bold setting and power and has a couple of [relays](https://www.amazon.com/gp/product/B0057OC6D8/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) connected to the bold setting button and the power button. Aside from the ability to trigger automations based on the state of the coffee maker and automate turning on the coffee maker I also added a "bloom" feature. Coffee tastes better if you let the carbon dioxide escape (bloom) after getting the coffee grounds wet before continuing the brew cycle.
## Custom Components
### Tuya
This is a copy of the standard Tuya component with a couple of fixes/tweaks that are still getting hashed out in the main branch of ESPHome that are needed to get my custom Tuya Light Plus component to work reliably. Hopefully I can remove this component soon.
> ### [Fire Pit and Fountain](./devices/fire_pit_fountain.yaml)
> This is a [WEMOS D1 Mini Pro](https://www.amazon.com/gp/product/B07G9HZ5LM/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that is connected to a couple of [relays](https://www.amazon.com/gp/product/B0057OC6D8/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) and a couple of water proof push buttons [red](https://www.amazon.com/gp/product/B079GNNSRP/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) and [blue](https://www.amazon.com/gp/product/B079GK565N/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1). The multi-click config on the fire pit switch is so that any press will turn it off but to turn it on you have to press it for 3 seconds (to try and prevent kids from turning it on). This is used to control the combination fire pit and fountain in my backyard. I just got this hooked up and is working good other then the fire pit doesn't always come on on the first try (I think I am getting some bounce in the switch but haven't had a chance to troubleshoot further).
### Tuya Light Plus
This an enhanced version of the standard [Tuya](https://esphome.io/components/light/tuya.html) light component that adds a bunch of extra features. I use this component with [Feit Dimmers](https://www.amazon.com/gp/product/B07SXDFH38/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1) but it will likely work with other Tuya dimmers. More details on features and how to use this component are available [here](./components/tuya_light_plus/README.md).
> ### [Garage Fridge](./devices/garage_fridge.yaml)
> This is a [NodeMCU](https://www.amazon.com/gp/product/B010N1SPRK/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that I have installed in the back of my garage fridge and is connected to several [temperature sensors](https://www.amazon.com/gp/product/B012C597T0/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that monitor the temperature of the compressor, the fridge, and the freezer and a pair of [relays](https://www.amazon.com/gp/product/B0057OC6D8/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that control a [heat tape](https://www.amazon.com/gp/product/B07HHB1R5S/ref=ox_sc_act_title_1?smid=A1KEJ1ZBUGV6FW&psc=1) wrapped around the compressor and a couple of [heaters](https://www.amazon.com/gp/product/B07GXSDMR2/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that are inside the fridge. This is to prevent the compressor from getting to cold (when it is cold the oil thickens up which is hard on the compressor), the fridge from dropping below freezing (frozen beer is no fun), and the freezer from getting to warm (when temperatures in the garage are around the desired fridge temperature the freezer tends to get to warm because of lack of cooling demand from the fridge so we warm the fridge up a little to get it to kick in the compressor).
> ### [Master Bed](./devices/master_bed.yaml)
> This is a [NodeMCU](https://www.amazon.com/gp/product/B010N1SPRK/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that I have installed under my bed and is connected to a pair of [Force Sensitive Resistors](https://www.kr4.us/force-sensitive-resistor-long.html?gclid=COqn7qrNxdICFVQlgQodeLEMKw) that are placed between the mattress and box spring of my bed, one for my side and one for my wife's side. Because the ESP8266 has only one analog input I had to add some transistors connected to pins D0 and D1 that are used to select which FSR is connected to the A0 analog input. The custom sensors in [bed_sensor.h](./custom/bed_sensor.h) handles switching between the FSR's and reading the values from the FSR's. Generally when the bed is empty the reading is the full 1024 (or at least close to this). If someone is on one side of the bed or the other the reading is typically around 100. However if you lay in the middle of the bed I tend to get readings of around 600-700 on both sides. Thus the 3 different binary sensors (Chris is in Bed, Melissa is in Bed, Someone is in Bed). There is also a Master Bed Count that reports the total number of people in bed, I compare this to a sensor in Home Assistant that tracks the number of "masters" (my wife and me) that are home so that I can activate night mode when everyone is in bed.
## Misc Devices
### [Basement Bathroom Sensor](./devices/basement_bathroom_sensor.yaml)
This is a [WEMOS D1 Mini clone](https://www.amazon.com/gp/product/B076F52NQD/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that is connected to a [motion sensor](https://www.amazon.com/gp/product/B07GJDJV63/ref=ppx_yo_dt_b_asin_title_o06_s01?ie=UTF8&psc=1), a [temperature/humidity/pressure sensor](https://www.amazon.com/gp/product/B07KYJNFMD/ref=ppx_yo_dt_b_asin_title_o06_s01?ie=UTF8&psc=1), and a [door sensor](https://www.amazon.com/gp/product/B07YBGZNNW/ref=ppx_yo_dt_b_asin_title_o09_s00?ie=UTF8&psc=1) and is used to control the lights, fan, and heater (heat lamps in the fan) in my basement bathroom.
> ### [Patio Lights](./devices/patio_lights.yaml)
> This is a [WEMOS D1 Mini Pro](https://www.amazon.com/gp/product/B07G9HZ5LM/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that is connected to a [relay](https://www.amazon.com/gp/product/B00VRUAHLE/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) to control the power to the landscape lights around my patio. I used the WEMOS D1 Mini Pro because it has an external antenna. I initially used a [WEMOS D1 Mini clone](https://www.amazon.com/gp/product/B076F52NQD/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) but the power supply for my lights was to far from the house and I kept having connectivity issues.
### [Coffee Maker](./devices/coffee_maker.yaml)
This is a [NodeMCU](https://www.amazon.com/gp/product/B010N1SPRK/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that I installed in my [Cuisinart Coffee Maker](https://www.amazon.com/gp/product/B01N6T5QNO/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1). It has GPIO's connected to the indicator lights for the bold setting and power and has a couple of [relays](https://www.amazon.com/gp/product/B0057OC6D8/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) connected to the bold setting button and the power button. Aside from the ability to trigger automations based on the state of the coffee maker and automate turning on the coffee maker I also added a "bloom" feature. Coffee tastes better if you let the carbon dioxide escape (bloom) after getting the coffee grounds wet before continuing the brew cycle.
> ### [Pool Pumps](./devices/pool_pumps.yaml)
> This is a [Shelly 2.5 Double Relay Switch](https://www.amazon.com/gp/product/B07RRD13DJ/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that is controlling the main pump on my pool and the auxillary pump that runs the pool cleaner. It turns the pump on and off through out the day and off at night (when we are least likely to be using the pool and when you get the most heat/water loss if the pump is running) and turns on the cleaner for a couple of hours in the morning. It also has some modes for Off (during the winter) and Continous when I need extra cleaning.
### [Fire Pit and Fountain](./devices/fire_pit_fountain.yaml)
This is a [WEMOS D1 Mini Pro](https://www.amazon.com/gp/product/B07G9HZ5LM/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that is connected to a couple of [relays](https://www.amazon.com/gp/product/B0057OC6D8/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) and a couple of water proof push buttons [red](https://www.amazon.com/gp/product/B079GNNSRP/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) and [blue](https://www.amazon.com/gp/product/B079GK565N/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1). The multi-click config on the fire pit switch is so that any press will turn it off but to turn it on you have to press it for 3 seconds (to try and prevent kids from turning it on). This is used to control the combination fire pit and fountain in my backyard. I just got this hooked up and is working good other then the fire pit doesn't always come on on the first try (I think I am getting some bounce in the switch but haven't had a chance to troubleshoot further).
### [Garage Fridge](./devices/garage_fridge.yaml)
This is a [NodeMCU](https://www.amazon.com/gp/product/B010N1SPRK/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that I have installed in the back of my garage fridge and is connected to several [temperature sensors](https://www.amazon.com/gp/product/B012C597T0/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that monitor the temperature of the compressor, the fridge, and the freezer and a pair of [relays](https://www.amazon.com/gp/product/B0057OC6D8/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that control a [heat tape](https://www.amazon.com/gp/product/B07HHB1R5S/ref=ox_sc_act_title_1?smid=A1KEJ1ZBUGV6FW&psc=1) wrapped around the compressor and a couple of [heaters](https://www.amazon.com/gp/product/B07GXSDMR2/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that are inside the fridge. This is to prevent the compressor from getting to cold (when it is cold the oil thickens up which is hard on the compressor), the fridge from dropping below freezing (frozen beer is no fun), and the freezer from getting to warm (when temperatures in the garage are around the desired fridge temperature the freezer tends to get to warm because of lack of cooling demand from the fridge so we warm the fridge up a little to get it to kick in the compressor).
### [Master Bed](./devices/master_bed.yaml)
This is a [NodeMCU](https://www.amazon.com/gp/product/B010N1SPRK/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that I have installed under my bed and is connected to a pair of [Force Sensitive Resistors](https://www.kr4.us/force-sensitive-resistor-long.html?gclid=COqn7qrNxdICFVQlgQodeLEMKw) that are placed between the mattress and box spring of my bed, one for my side and one for my wife's side. Because the ESP8266 has only one analog input I had to add some transistors connected to pins D0 and D1 that are used to select which FSR is connected to the A0 analog input. The custom sensors in [bed_sensor.h](./custom/bed_sensor.h) handles switching between the FSR's and reading the values from the FSR's. Generally when the bed is empty the reading is the full 1024 (or at least close to this). If someone is on one side of the bed or the other the reading is typically around 100. However if you lay in the middle of the bed I tend to get readings of around 600-700 on both sides. Thus the 3 different binary sensors (Chris is in Bed, Melissa is in Bed, Someone is in Bed). There is also a Master Bed Count that reports the total number of people in bed, I compare this to a sensor in Home Assistant that tracks the number of "masters" (my wife and me) that are home so that I can activate night mode when everyone is in bed.
### [Patio Lights](./devices/patio_lights.yaml)
This is a [WEMOS D1 Mini Pro](https://www.amazon.com/gp/product/B07G9HZ5LM/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that is connected to a [relay](https://www.amazon.com/gp/product/B00VRUAHLE/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) to control the power to the landscape lights around my patio. I used the WEMOS D1 Mini Pro because it has an external antenna. I initially used a [WEMOS D1 Mini clone](https://www.amazon.com/gp/product/B076F52NQD/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) but the power supply for my lights was to far from the house and I kept having connectivity issues.
### [Pool Pumps](./devices/pool_pumps.yaml)
This is a [Shelly 2.5 Double Relay Switch](https://www.amazon.com/gp/product/B07RRD13DJ/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that is controlling the main pump on my pool and the auxillary pump that runs the pool cleaner. It turns the pump on and off through out the day and off at night (when we are least likely to be using the pool and when you get the most heat/water loss if the pump is running) and turns on the cleaner for a couple of hours in the morning. It also has some modes for Off (during the winter) and Continous when I need extra cleaning.
### [Scripture of the Day Melissa](./devices/scripture_of_the_day_melissa.yaml)/[Scripture of the Day Mayson](./devices/scripture_of_the_day_mayson.yaml)
This project was one of the first projects I have done that I would call woodworking. I made 2 of these as Christmas presents for my wife and son. They consist of an [ESP32 e-Paper Panel Driver Board](https://www.waveshare.com/product/displays/e-paper-esp32-driver-board.htm) powered by a [lithium battery](https://www.amazon.com/dp/B0867KDMY7/?coliid=IE0LBNACFHG4U&colid=1LOK862UA8LA0&psc=1&ref_=lv_ov_lig_dp_it) and [TP4056 lithium battery charger module](https://www.amazon.com/dp/B06XQRQR3Q/?coliid=I1B2ELKKLLKAK0&colid=1LOK862UA8LA0&psc=1&ref_=lv_ov_lig_dp_it) and driving a [Waveshare 7.5inch 800×480 E-Ink display](https://www.waveshare.com/7.5inch-e-paper.htm). The ESP32 sits in deep-sleep most of the time but wakes up every night, grabs a random scripture from the [Our Manna Daily Verses API](http://www.ourmanna.com/verses/api/), updates the display with the verse, and goes back to sleep.
<br/><br/>
<img src="./images/scripture_of_the_day/front.jpg" alt="Front" width="600" /><img src="./images/scripture_of_the_day/back.jpg" alt="Back" width="600" />
> ### [Scripture of the Day Melissa](./devices/scripture_of_the_day_melissa.yaml)/[Scripture of the Day Mayson](./devices/scripture_of_the_day_mayson.yaml)
> This project was one of the first projects I have done that I would call woodworking. I made 2 of these as Christmas presents for my wife and son. They consist of an [ESP32 e-Paper Panel Driver Board](https://www.waveshare.com/product/displays/e-paper-esp32-driver-board.htm) powered by a [lithium battery](https://www.amazon.com/dp/B0867KDMY7/?coliid=IE0LBNACFHG4U&colid=1LOK862UA8LA0&psc=1&ref_=lv_ov_lig_dp_it) and [TP4056 lithium battery charger module](https://www.amazon.com/dp/B06XQRQR3Q/?coliid=I1B2ELKKLLKAK0&colid=1LOK862UA8LA0&psc=1&ref_=lv_ov_lig_dp_it) and driving a [Waveshare 7.5inch 800×480 E-Ink display](https://www.waveshare.com/7.5inch-e-paper.htm). The ESP32 sits in deep-sleep most of the time but wakes up every night, grabs a random scripture from the [Our Manna Daily Verses API](http://www.ourmanna.com/verses/api/), updates the display with the verse, and goes back to sleep.
> <br/><br/>
> <img src="./images/scripture_of_the_day/front.jpg" alt="Front" width="600" /><img src="./images/scripture_of_the_day/back.jpg" alt="Back" width="600" />
## Switches
> I plan to use dimmer switches for anything that is dimmable just for consistency and you never know when you might want to have the ability to dim a light. However there are times when a dimmer isn't an option.
I plan to use dimmer switches for anything that is dimmable just for consistency and you never know when you might want to have the ability to dim a light. However there are times when a dimmer isn't an option.
> ### [SANA Dual Switch](https://www.amazon.com/gp/product/B07QC5ZCHP/ref=ppx_yo_dt_b_asin_title_o03_s01?ie=UTF8&th=1)
> My basement bathroom has 4 devices (main light, fan, shower light, heat lamps) but only 2 single gang boxes (and not enough room to swith to dual gang) so these were a perfect fit. The prices is right, the buttons feel solid, and I was able to flash them using [Tuya-Convert](https://github.com/ct-Open-Source/tuya-convert). They do seem to have corners that are squarer then typical so I had a little bit of trouble getting a standard cover to fit but nothing I couldn't fix with a file.
> > * [Basement Bathroom Light and Fan](./devices/basement_bathroom_light_fan.yaml)
> > * [Basement Bathroom Shower Light and Heater](./devices/basement_bathroom_shower_light_heater.yaml)
### [SANA Dual Switch](https://www.amazon.com/gp/product/B07QC5ZCHP/ref=ppx_yo_dt_b_asin_title_o03_s01?ie=UTF8&th=1)
My basement bathroom has 4 devices (main light, fan, shower light, heat lamps) but only 2 single gang boxes (and not enough room to swith to dual gang) so these were a perfect fit. The prices is right, the buttons feel solid, and I was able to flash them using [Tuya-Convert](https://github.com/ct-Open-Source/tuya-convert). They do seem to have corners that are squarer then typical so I had a little bit of trouble getting a standard cover to fit but nothing I couldn't fix with a file.
* [Basement Bathroom Light and Fan](./devices/basement_bathroom_light_fan.yaml)
* [Basement Bathroom Shower Light and Heater](./devices/basement_bathroom_shower_light_heater.yaml)
> ### [SANA Triple Switch](https://www.amazon.com/gp/product/B07Q5XPRKD/ref=ox_sc_act_title_1?smid=A3EOKYTNCLEIKH&psc=1)
> This is installed in place of the switch that controled my [TREO LED Pool Lights](https://www.amazon.com/gp/product/B06XTRLM5M/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1). These lights have the option to select different colors by briefly turning them off and back on again and they do remember the last color when turned on again. The custom [TreoLedPoolLight.h](./custom/TreoLedPoolLight.h) component handles tracking the current color and exposes custom "effects" for each of the colors to [Home Assistant](https://www.home-assistant.io/). I went with the triple switch so that I could use the third button to control my [Patio Lights](#patio-lights) which otherwise do not have a physical switch. The one issue I am having with this is occasionally the "effect" on the switch gets out of sync with the actual color of the lights. It has only happened a couple of times so I haven't gotten around to investigating why it happens.
> > * [Patio and Pool Lights](./devices/patio_and_pool_lights.yaml)
### [SANA Triple Switch](https://www.amazon.com/gp/product/B07Q5XPRKD/ref=ox_sc_act_title_1?smid=A3EOKYTNCLEIKH&psc=1)
This is installed in place of the switch that controled my [TREO LED Pool Lights](https://www.amazon.com/gp/product/B06XTRLM5M/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1). These lights have the option to select different colors by briefly turning them off and back on again and they do remember the last color when turned on again. The custom [TreoLedPoolLight.h](./custom/TreoLedPoolLight.h) component handles tracking the current color and exposes custom "effects" for each of the colors to [Home Assistant](https://www.home-assistant.io/). I went with the triple switch so that I could use the third button to control my [Patio Lights](#patio-lights) which otherwise do not have a physical switch. The one issue I am having with this is occasionally the "effect" on the switch gets out of sync with the actual color of the lights. It has only happened a couple of times so I haven't gotten around to investigating why it happens.
* [Patio and Pool Lights](./devices/patio_and_pool_lights.yaml)
## Dimmer Switches
> ### [Feit Dimmers](https://www.amazon.com/gp/product/B07SXDFH38/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1)
> After trying several dimmers I finally decided to standardize on on the Feit dimmers. I bought the first couple of these at Costco for a better price than Amazon but Costco doesn't seem to carry them anymore.
> Things I like about these dimmers:
> > * ~~Can be flashed using [Tuya-Convert](https://github.com/ct-Open-Source/tuya-convert)~~ Unfortunately Feit has started shipping these with updated firmware that does not currently work with Tuya Convert. Hopefully the excellent Tuya Convert team can figure out how to work around the new firmware. Until then I did find this [tutorial](https://community.smartthings.com/t/costco-cheap-feit-smart-dimmer-wifi/208142) on flashing these devices (I have not tried this yet).
> > * Have a solid feel to them
> > * They can be linked via a traveler wire (this works even when flashed with ESPHome and while not mentioned in the documentation you can link more than 2 switches this way)
> Things I don't like about these dimmers:
> > * Have to click repeatedly to change the brightness (can't hold to change)
> > * All buttons are managed by the Tuya MCU so adding things like double-taps is kind of a hack
> I have created a custom [tuya_light_plus.h](./custom/tuya_light_plus.h) component for these that extends the standard Tuya Light component that should work with most (if not all) Tuya dimmers and provides the following extra features:
> > * Resets the brightness level back to a default level when turned off so that it always comes on at the same level instead of the level it was at when turned off
> > * The default level is configurable as different levels when my house is in "Day" mode vs "Night" mode (based on a sensor in Home Assistant) and via a service in Home Assistant
> > * Provides an option to auto turn off the light after a period of time
> > * The auto turn off time is configurable to be different when my house is in "Day" mode vs "Night" mode (based on a sensor in Home Assistant) and via a service in Home Assistant
> > * Adds ability to specify a function to call when the dimmer is double tapped while off
> > * Double tapping while off can be configured to leave the light in an off or on state
> > * Adds ability to specify a function to call when the dimmer is double tapped while on
> > * Allows you to "link" other light(s) in Home Assistant that will be controlled by this dimmer
> Details on using the [tuya_light_plus.h](./custom/tuya_light_plus.h) component can be found [here](TuyaLightPlus.md).
> The following devices are Feit Dimmers:
> > * [Basement Stair Lights](./devices/basement_stair_lights_1.yaml)/[Basement Stair Lights 2](./devices/basement_stair_lights_2.yaml)
> > * [Computer Light](./devices/computer_light.yaml)
> > * [Dining Room Light](./devices/dining_room_light.yaml)
> > * [Family Room Light](./devices/family_room_light.yaml)
> > * [Front Entry Lights](./devices/front_entry_lights_1.yaml)/[Front Entry Lights 2](./devices/front_entry_lights_2.yaml)
> > * [Front Lights](./devices/front_lights.yaml)
> > * [Kitchen Bar Lights](./devices/kitchen_bar_lights.yaml)
> > * [Kitchen Table Light](./devices/kitchen_table_light.yaml)
> > * [Living Room Lights](./devices/living_room_lights.yaml)
> > * [Master Bathroom Lights](./devices/master_bath_lights_1.yaml)/[Master Bathroom Lights 2](./devices/master_bath_lights_2.yaml)
> > * [Office Light](./devices/office_light.yaml)
### [Feit Dimmers](https://www.amazon.com/gp/product/B07SXDFH38/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1)
After trying several dimmers I finally decided to standardize on the Feit dimmers. I bought the first couple of these at Costco for a better price than Amazon but Costco doesn't seem to carry them anymore.
Things I like about these dimmers:
* ~~Can be flashed using [Tuya-Convert](https://github.com/ct-Open-Source/tuya-convert)~~ Unfortunately Feit has started shipping these with updated firmware that does not currently work with Tuya Convert. Hopefully the excellent Tuya Convert team can figure out how to work around the new firmware. Until then I did find this [tutorial](https://community.smartthings.com/t/costco-cheap-feit-smart-dimmer-wifi/208142) on flashing these devices (I have not tried this yet).
* Have a solid feel to them
* They can be linked via a traveler wire (this works even when flashed with ESPHome and while not mentioned in the documentation you can link more than 2 switches this way)
Things I don't like about these dimmers:
* Have to click repeatedly to change the brightness (can't hold to change)
* All buttons are managed by the Tuya MCU so adding things like double-taps is kind of a hack
All of my dimmers are using my custom [Tuya Light Plus](./components/tuya_light_plus/README.md) component.
* [Basement Stair Lights](./devices/basement_stair_lights_1.yaml)/[Basement Stair Lights 2](./devices/basement_stair_lights_2.yaml)
* [Computer Light](./devices/computer_light.yaml)
* [Dining Room Light](./devices/dining_room_light.yaml)
* [Family Room Light](./devices/family_room_light.yaml)
* [Front Entry Lights](./devices/front_entry_lights_1.yaml)/[Front Entry Lights 2](./devices/front_entry_lights_2.yaml)
* [Front Lights](./devices/front_lights.yaml)
* [Kitchen Bar Lights](./devices/kitchen_bar_lights.yaml)
* [Kitchen Table Light](./devices/kitchen_table_light.yaml)
* [Living Room Lights](./devices/living_room_lights.yaml)
* [Master Bathroom Lights](./devices/master_bath_lights_1.yaml)/[Master Bathroom Lights 2](./devices/master_bath_lights_2.yaml)
* [Office Light](./devices/office_light.yaml)
## Dimmer Switches as On/Off Switches
> ### [Feit Dimmers](https://www.amazon.com/gp/product/B07SXDFH38/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1)
> I tried to find an on/off switch that looked/felt like the Feit dimmers but didn't find anything so I decided to use the Feit dimmers as switches.
### [Feit Dimmers](https://www.amazon.com/gp/product/B07SXDFH38/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1)
I tried to find an on/off switch that looked/felt like the Feit dimmers but didn't find anything so I decided to use the Feit dimmers as switches.
> #### Fans
> I created a custom [tuya_dimmer_as_binary_fan_output.h](./custom/tuya_dimmer_as_binary_fan_output.h) component that prevents the dimmer from being dimmed (always changes it right back to 100%) and can report the change in on/off status back to a fan component.
> > * [Master Bath Fan](./devices/master_bath_fan.yaml)
#### Fans
I created a custom [tuya_dimmer_as_binary_fan_output.h](./custom/tuya_dimmer_as_binary_fan_output.h) component that prevents the dimmer from being dimmed (always changes it right back to 100%) and can report the change in on/off status back to a fan component.
* [Master Bath Fan](./devices/master_bath_fan.yaml)

View File

@ -1,105 +0,0 @@
# Tuya Light Plus
## Overview
> The custom [tuya_light_plus.h](./custom/tuya_light_plus.h) component extends the standard Tuya Light component. I have only used this with [Feit Dimmers](https://www.amazon.com/gp/product/B07SXDFH38/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1) but it should work with most (if not all) Tuya dimmers and provides the following extra features:
> > * Resets the brightness level back to a default level when turned off so that it always comes on at the same level instead of the level it was at when turned off
> > * The default level is configurable as different levels when my house is in "Day" mode vs "Night" mode (based on a sensor in Home Assistant) and via a service in Home Assistant
> > * Provides an option to auto turn off the light after a period of time
> > * The auto turn off time is configurable to be different when my house is in "Day" mode vs "Night" mode (based on a sensor in Home Assistant) and via a service in Home Assistant
> > * Adds ability to specify a function to call when the dimmer is double tapped while off
> > * Double tapping while off can be configured to leave the light in an off or on state
> > * Adds ability to specify a function to call when the dimmer is double tapped while on
> > * Allows you to "link" other light(s) in Home Assistant that will be controlled by this dimmer
## Setup
> 1. Include the custom component
> > ```yaml
> > esphome:
> > includes:
> > - ../custom/tuya_light_plus.h
> > ```
> 2. Setup Dependencies
> > Like the standard Tuya Light component we need the UART and Tuya components
> > ```yaml
> > uart:
> > rx_pin: GPIO3
> > tx_pin: GPIO1
> > baud_rate: 9600
> >
> > tuya:
> > ```
> 3. Setup the Custom Light Component
> > ```yaml
> > light:
> > - platform: custom
> > lambda: |-
> > # Required - Creates the custom light component.
> > TuyaLight = new TuyaLightPlus();
> > # Required - Sets the Tuya component used to communicate with the light.
> > TuyaLight->set_tuya_parent(tuya_tuya);
> > # Required - Sets the API Server object needed to configure the services in Home Assistant and add the Day/Night sensor listener.
> > TuyaLight->set_api_server(api_apiserver);
> > # Required - Sets the switch datapoint (same as switch_datapoint option in the standard Tuya light component).
> > TuyaLight->set_switch_id(1);
> > # Required - Sets the dimmer datapoint (same as dimmer_datapoint option in the standard Tuya light component).
> > TuyaLight->set_dimmer_id(2);
> > # Optional(default: 0) - Sets the lowest dimmer value allowed (same as min_value option in the standard Tuya light component).
> > TuyaLight->set_min_value(0);
> > # Optional(default: 255) - Sets the highest dimmer value allowed (same as max_value option in the standard Tuya light component).
> > TuyaLight->set_max_value(1000);
> > # Optional(default: "") - Sets the name of the sensor in Home Assistant that tracks day and night mode (This needs to be a Text sensor with Day and Night as the possible values).
> > TuyaLight->set_day_night_sensor("sensor.day_night");
> > # Optional(default: 1) - Sets the default brightness to turn the light on at (valid values are .01 - 1). Note this value will get updated with the Day/Night values below if the Day/Night sensor is set.
> > TuyaLight->set_default_brightness(1);
> > # Optional(default: 1) - Sets the default brightness to turn the light on at during the day (valid values are .01 - 1).
> > TuyaLight->set_day_default_brightness(1);
> > # Optional(default: .03) - Sets the default brightness to turn the light on at during the night (valid values are .01 - 1).
> > TuyaLight->set_night_default_brightness(.03);
> > # Optional(default: 0) - Sets the number of minutes before the light is turned off automatically (0 disables auto off). Note this value will get updated with the Day/Night values below if the Day/Night sensor is set.
> > TuyaLight->set_auto_off_minutes(0);
> > # Optional(default: 0) - Sets the number of minutes before the light is turned off automatically during the day (0 disables auto off during the day).
> > TuyaLight->set_day_auto_off_minutes(0);
> > # Optional(default: 0) - Sets the number of minutes before the light is turned off automatically during the night (0 disables auto off during the night).
> > TuyaLight->set_night_auto_off_minutes(15);
> > # Optional(default: "") - Sets the comma delimited list of lights in Home Assistant that are "linked" to this light and will be controlled by this dimmer.
> > TuyaLight->set_linked_lights("light.some_light,light.some_other_light");
> > # Optional - Adds a function to run when double tapped while off. This can be any valid C++ code similar to a lambda funtion. Multiple functions can be added by calling this method again.
> > TuyaLight->add_double_tap_while_off_callback([]() {
> > ESP_LOGD("tuya_light_plus", "Light was double tapped while off");
> > });
> > # Optional - Adds a function to run when double tapped while on. This can be any valid C++ code similar to a lambda funtion. Multiple functions can be added by calling this method again.
> > TuyaLight->add_double_tap_while_on_callback([]() {
> > ESP_LOGD("tuya_light_plus", "Light was double tapped while on");
> > });
> > # Optional - Adds a function to run when double tapped (both while on and while off). This can be any valid C++ code similar to a lambda funtion. Multiple functions can be added by calling this method again.
> > TuyaLight->add_double_tap_callback([]() {
> > ESP_LOGD("tuya_light_plus", "Light was double tapped");
> > });
> > # Optional(default: true) - If true and 1 or more functions are registered to run when double tap while off then the light will be turned on when double tapped while off, if false the light will remain off after the double tap.
> > TuyaLight->set_double_tap_while_off_stays_on(true);
> > # Required - Registers the custom component with ESPHome
> > App.register_component(TuyaLight);
> > # Required - Returns the configured component to be added as a light
> > return {TuyaLight};
> > lights:
> > - id: tuya_light
> > name: Tuya Light
> > gamma_correct: 1.0
> > default_transition_length: 0s
> > ```
## Operation
> 1. Update from Home Assistant
> > After connecting to Home Assistant 2 services will be created that can be used to update the lights behavior:
> > * esphome.{device_name}_set_auto_off_minutes - This service takes a parameter "minutes" and updates the current minutes to auto turn off the light. Note this value will get updated if the Day/Night sensor is set.
> > * esphome.{device_name}_set_default_brightness - This service takes a parameter "brightness" (valid values .01 - 1) and updates the current default brightness to turn the light on at. Note this value will get updated if the Day/Night sensor is set.
> 2. Update from code on the dimmer
> > The following methods can be called from a lambda function (or other custom code) at anytime to update the settings on the light:
> > * TuyaLight->set_default_brightness(float brightness);
> > * TuyaLight->set_day_default_brightness(float brightness);
> > * TuyaLight->set_night_default_brightness(float brightness);
> > * TuyaLight->set_auto_off_minutes(int minutes);
> > * TuyaLight->set_day_auto_off_minutes(int minutes);
> > * TuyaLight->set_night_auto_off_minutes(int minutes);
> > * TuyaLight->set_double_tap_while_off_stays_on(bool stays_on);

View File

@ -478,6 +478,22 @@ void Tuya::set_datapoint_value(uint8_t datapoint_id, std::string value) {
this->send_datapoint_command_(datapoint->id, datapoint->type, data);
}
void Tuya::set_datapoint_value(uint8_t datapoint_id, bool value) {
ESP_LOGD(TAG, "Setting datapoint %u to %s", datapoint_id, TRUEFALSE(value));
optional<TuyaDatapoint> datapoint = this->get_datapoint_(datapoint_id);
if (!datapoint.has_value()) {
ESP_LOGE(TAG, "Attempt to set unknown datapoint %u", datapoint_id);
}
else if (datapoint->value_bool == value) {
ESP_LOGV(TAG, "Not sending unchanged value");
return;
}
std::vector<uint8_t> data;
data.push_back(value >> 0);
this->send_datapoint_command_(datapoint_id, TuyaDatapointType::BOOLEAN, data);
}
optional<TuyaDatapoint> Tuya::get_datapoint_(uint8_t datapoint_id) {
for (auto &datapoint : this->datapoints_)
if (datapoint.id == datapoint_id)

View File

@ -77,6 +77,7 @@ class Tuya : public Component, public uart::UARTDevice {
void register_listener(uint8_t datapoint_id, const std::function<void(TuyaDatapoint)> &func);
void set_datapoint_value(uint8_t datapoint_id, uint32_t value);
void set_datapoint_value(uint8_t datapoint_id, std::string value);
void set_datapoint_value(uint8_t datapoint_id, bool value);
#ifdef USE_TIME
void set_time_id(time::RealTimeClock *time_id) { this->time_id_ = time_id; }
#endif

View File

@ -0,0 +1,87 @@
# Tuya Light Plus Component
## Overview
This an enhanced version of the standard Tuya light component that adds a bunch of extra features. I use this component with [Feit Dimmers](https://www.amazon.com/gp/product/B07SXDFH38/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1) but it will likely work with other Tuya dimmers. Extra features include the following:
* Resets the brightness level back to a default level when turned off so that it always comes on at the same level instead of the level it was at when turned off.
* The default level can be different during the "day" vs at "night" when everyone is in bed. Day and Night are based on a sensor (binary or text)in Home Assistant.
* The default level can be updated via a service that is added to Home Assistant by this component.
* Provides an option to automatically turn off the light after a specified period of time.
* The automatic turn off time can be different during the "day" vs at "night" when everyone is in bed. Day and Night are based on a sensor (binary or text)in Home Assistant.
* The automatic turn off time can be updated via a service that is added to Home Assistant by this component.
* Adds an option to configure action(s) to run when the dimmer is double clicked while off.
* Double clicking the dimmer while off can be configured to leave the light in an off or on state.
* Adds an option to configure action(s) to run when the dimmer is double clicked while on (this double click always turns the light off otherwise you get strange flash when double clicking).
* Allows you to "link" other light(s) in Home Assistant that will be controlled by this dimmer (on/off and level).
## Setup
Using the [External Components](https://esphome.io/components/external_components.html) feature in ESPHome you can add this component to your devices directly from my GitHub repo. Note currently this component requires pulling in my custom version of the Tuya component as well to prevent communication issues between the ESP8266 and the Tuya MCU.
```yaml
external_components:
- source: github://nuttytree/esphome
components: [ tuya, tuya_light_plus ]
```
Like the standard Tuya Light component you need to have the [UART](https://esphome.io/components/uart.html) and [Tuya](https://esphome.io/components/tuya.html) components.
```yaml
uart:
rx_pin: GPIO3
tx_pin: GPIO1
baud_rate: 9600
tuya:
```
Add and configure the Tuya Light Plus component
```yaml
light:
- platform: tuya_light_plus
name: my_dimmer
switch_datapoint: 1
dimmer_datapoint: 2
max_value: 1000
linked_lights:
- light.my_linked_light
day_night:
sensor_id: sensor.day_night
sensor_type: text
sensor_day_value: Day
sensor_night_value: Night
day_default_brightness: 255
night_default_brightness: 1
day_auto_off_time: 0 min
night_auto_off_time: 15 min
on_double_click_while_off:
- script.execute: double_click
double_click_while_off_stays_off: false
on_double_click_while_on:
- script.execute: double_click
```
## Configuration Variables
* id (Optional, ID): Manually specify the ID used for code generation.
* name (Required, string): The name of the light.
* switch_datapoint (Required, int): The datapoint id number of the power switch.
* dimmer_datapoint (Required, int): The datapoint id number of the dimmer value.
* min_value_datapoint (Optional, int): The datapoint id number of the MCU minimum value setting. If this is set then ESPHome will sync the min_value to the MCU on startup.
* min_value (Optional, int, default 0): The lowest dimmer value allowed.
* max_value (Optional, int, default 255): The highest dimmer value allowed.
* default_brightness (Optional, int 1-255): The default brightness level for the light.
* auto_off_time (Optional, Time): The amount of time to wait before automatically turning the light off, 0 disables auto off
* linked_lights (Optional, string): List of lights that will be controlled by this dimmer (note this one direction, changes to the linked light will not be applied to this light).
* day_night.sensor_id (Optional, string): Entity Id of a sensor in Home Assistant that indicates day/night mode.
* day_night.sensor_type (Optional, binary or text, default: binary): The type of the sensor in Home Assistant that indicates day/night mode.
* day_night.sensor_day_value (Optional, string, default: "on" for binary sensors and "Day" for text): The value of the sensor that indicates day mode.
* day_night.sensor_night_value (Optional, string, default: "off" for binary sensors and "Night" for text): The value of the sensor that indicates night mode.
* day_night.day_default_brightness (Optional, int 1-255): The default brightness level for the light during day mode.
* day_night.night_default_brightness (Optional, int 1-255): The default brightness level for the light during night mode.
* day_night.day_auto_off_time (Optional, Time): The amount of time to wait before automatically turning the light off during day mode, 0 disables auto off
* day_night.night_auto_off_time (Optional, Time): The amount of time to wait before automatically turning the light off during night mode, 0 disables auto off
* on_double_click_while_off (Optional): List of actions to run when the dimmer is double clicked while off
* double_click_while_off_stays_off (Optional, bool, default: true): Determines if the light remains off or turns on after a double click while off
* on_double_click_while_on (Optional): List of actions to run when the dimmer is double clicked while on
## Operation
This component adds 2 services to Home Assistant that can be used to update the settings of the dimmer:
* esphome.{device_name}_set_auto_off_time - This service has a single parameter "auto_off_time" that is in milliseconds, 0 will disable the auto off function. Note this value will get updated when the day/night mode changes if that option is configured.
* esphome.{device_name}_set_default_brightness - This service has a single parameter "brightness" (valid values 0 - 255), 0 will disable the default brightness feature. Note this value will get updated when the day/night mode changes if that option is configured.

View File

@ -1,5 +1,8 @@
from typing import Optional
from esphome import core
from esphome.components import light
import esphome.config_validation as cv
import esphome.automation as auto
import esphome.codegen as cg
from esphome.const import (
CONF_OUTPUT_ID,
@ -8,8 +11,7 @@ from esphome.const import (
CONF_GAMMA_CORRECT,
CONF_DEFAULT_TRANSITION_LENGTH,
CONF_SWITCH_DATAPOINT,
CONF_COLD_WHITE_COLOR_TEMPERATURE,
CONF_WARM_WHITE_COLOR_TEMPERATURE,
CONF_SENSOR_ID,
)
from esphome.components.tuya import CONF_TUYA_ID, Tuya
@ -17,32 +19,70 @@ DEPENDENCIES = ["tuya"]
CONF_DIMMER_DATAPOINT = "dimmer_datapoint"
CONF_MIN_VALUE_DATAPOINT = "min_value_datapoint"
CONF_COLOR_TEMPERATURE_DATAPOINT = "color_temperature_datapoint"
CONF_COLOR_TEMPERATURE_MAX_VALUE = "color_temperature_max_value"
CONF_DEFAULT_BRIGHTNESS = "default_brightness"
CONF_AUTO_OFF_TIME = "auto_off_time"
CONF_LINKED_LIGHTS = "linked_lights"
CONF_DAY_NIGHT = "day_night"
CONF_SENSOR_TYPE = "sensor_type"
CONF_SENSOR_DAY_VALUE = "sensor_day_value"
CONF_SENSOR_NIGHT_VALUE = "sensor_night_value"
CONF_DAY_DEFAULT_BRIGHTNESS = "day_default_brightness"
CONF_NIGHT_DEFAULT_BRIGHTNESS = "night_default_brightness"
CONF_DAY_AUTO_OFF_TIME = "day_auto_off_time"
CONF_NIGHT_AUTO_OFF_TIME = "night_auto_off_time"
CONF_ON_DOUBLE_CLICK_WHILE_OFF = "on_double_click_while_off"
CONF_DOUBLE_CLICK_WHILE_OFF_STAYS_OFF = "double_click_while_off_stays_off"
CONF_ON_DOUBLE_CLICK_WHILE_ON = "on_double_click_while_on"
tuya_ns = cg.esphome_ns.namespace("tuya")
TuyaLight = tuya_ns.class_("TuyaLightPlus", light.LightOutput, cg.Component)
api_ns = cg.esphome_ns.namespace("api")
APIServer = api_ns.class_("APIServer", cg.Component, cg.Controller)
TuyaLight = tuya_ns.class_("TuyaLightPlus", light.LightOutput, cg.Component, APIServer)
DoubleClickWhileOffTrigger = tuya_ns.class_('DoubleClickWhileOffTrigger', auto.Trigger.template())
DoubleClickWhileOnTrigger = tuya_ns.class_('DoubleClickWhileOnTrigger', auto.Trigger.template())
DayNightSensorType = tuya_ns.enum("DayNightSensorType")
DAY_NIGHT_SENSOR_TYPE = {
"BINARY": DayNightSensorType.BINARY,
"TEXT": DayNightSensorType.TEXT,
}
DAY_NIGHT_SCHEMA = cv.Schema(
{
cv.Required(CONF_SENSOR_ID): cv.entity_id,
cv.Optional(CONF_SENSOR_TYPE, default="BINARY"): cv.enum(DAY_NIGHT_SENSOR_TYPE, upper=True),
cv.Optional(CONF_SENSOR_DAY_VALUE): cv.string,
cv.Optional(CONF_SENSOR_NIGHT_VALUE): cv.string,
cv.Optional(CONF_DAY_DEFAULT_BRIGHTNESS): cv.int_range(1, 255),
cv.Optional(CONF_NIGHT_DEFAULT_BRIGHTNESS): cv.int_range(1, 255),
cv.Optional(CONF_DAY_AUTO_OFF_TIME): cv.positive_time_period_milliseconds,
cv.Optional(CONF_NIGHT_AUTO_OFF_TIME): cv.positive_time_period_milliseconds,
}
)
CONFIG_SCHEMA = cv.All(
light.BRIGHTNESS_ONLY_LIGHT_SCHEMA.extend(
{
cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(TuyaLight),
cv.GenerateID(CONF_TUYA_ID): cv.use_id(Tuya),
cv.Optional(CONF_DIMMER_DATAPOINT): cv.uint8_t,
cv.Required(CONF_SWITCH_DATAPOINT): cv.uint8_t,
cv.Required(CONF_DIMMER_DATAPOINT): cv.uint8_t,
cv.Optional(CONF_MIN_VALUE_DATAPOINT): cv.uint8_t,
cv.Optional(CONF_SWITCH_DATAPOINT): cv.uint8_t,
cv.Inclusive(
CONF_COLOR_TEMPERATURE_DATAPOINT, "color_temperature"
): cv.uint8_t,
cv.Optional(CONF_MIN_VALUE): cv.int_,
cv.Optional(CONF_MAX_VALUE): cv.int_,
cv.Optional(CONF_COLOR_TEMPERATURE_MAX_VALUE): cv.int_,
cv.Inclusive(
CONF_COLD_WHITE_COLOR_TEMPERATURE, "color_temperature"
): cv.color_temperature,
cv.Inclusive(
CONF_WARM_WHITE_COLOR_TEMPERATURE, "color_temperature"
): cv.color_temperature,
cv.Optional(CONF_DEFAULT_BRIGHTNESS): cv.int_range(1, 255),
cv.Optional(CONF_AUTO_OFF_TIME): cv.positive_time_period_milliseconds,
cv.Optional(CONF_LINKED_LIGHTS): cv.ensure_list(cv.entity_id),
cv.Optional(CONF_DAY_NIGHT): DAY_NIGHT_SCHEMA,
cv.Optional(CONF_ON_DOUBLE_CLICK_WHILE_OFF): auto.validate_automation(
{
cv.GenerateID(CONF_ON_DOUBLE_CLICK_WHILE_OFF): cv.declare_id(DoubleClickWhileOffTrigger),
}),
cv.Optional(CONF_DOUBLE_CLICK_WHILE_OFF_STAYS_OFF, default="True"): cv.boolean,
cv.Optional(CONF_ON_DOUBLE_CLICK_WHILE_ON): auto.validate_automation(
{
cv.GenerateID(CONF_ON_DOUBLE_CLICK_WHILE_ON): cv.declare_id(DoubleClickWhileOnTrigger),
}),
# Change the default gamma_correct and default transition length settings.
# The Tuya MCU handles transitions and gamma correction on its own.
cv.Optional(CONF_GAMMA_CORRECT, default=1.0): cv.positive_float,
@ -51,7 +91,6 @@ CONFIG_SCHEMA = cv.All(
): cv.positive_time_period_milliseconds,
}
).extend(cv.COMPONENT_SCHEMA),
cv.has_at_least_one_key(CONF_DIMMER_DATAPOINT, CONF_SWITCH_DATAPOINT),
)
@ -60,29 +99,50 @@ async def to_code(config):
await cg.register_component(var, config)
await light.register_light(var, config)
if CONF_DIMMER_DATAPOINT in config:
cg.add(var.set_dimmer_id(config[CONF_DIMMER_DATAPOINT]))
cg.add(var.set_switch_id(config[CONF_SWITCH_DATAPOINT]))
cg.add(var.set_dimmer_id(config[CONF_DIMMER_DATAPOINT]))
if CONF_MIN_VALUE_DATAPOINT in config:
cg.add(var.set_min_value_datapoint_id(config[CONF_MIN_VALUE_DATAPOINT]))
if CONF_SWITCH_DATAPOINT in config:
cg.add(var.set_switch_id(config[CONF_SWITCH_DATAPOINT]))
if CONF_COLOR_TEMPERATURE_DATAPOINT in config:
cg.add(var.set_color_temperature_id(config[CONF_COLOR_TEMPERATURE_DATAPOINT]))
cg.add(
var.set_cold_white_temperature(config[CONF_COLD_WHITE_COLOR_TEMPERATURE])
)
cg.add(
var.set_warm_white_temperature(config[CONF_WARM_WHITE_COLOR_TEMPERATURE])
)
if CONF_MIN_VALUE in config:
cg.add(var.set_min_value(config[CONF_MIN_VALUE]))
if CONF_MAX_VALUE in config:
cg.add(var.set_max_value(config[CONF_MAX_VALUE]))
if CONF_COLOR_TEMPERATURE_MAX_VALUE in config:
cg.add(
var.set_color_temperature_max_value(
config[CONF_COLOR_TEMPERATURE_MAX_VALUE]
)
)
if CONF_DEFAULT_BRIGHTNESS in config:
cg.add(var.set_default_brightness(config[CONF_DEFAULT_BRIGHTNESS]))
if CONF_AUTO_OFF_TIME in config:
cg.add(var.set_auto_off_time(config[CONF_AUTO_OFF_TIME]))
if CONF_LINKED_LIGHTS in config and len(config[CONF_LINKED_LIGHTS]) > 0:
cg.add(var.set_linked_lights(",".join(config[CONF_LINKED_LIGHTS])))
if CONF_DAY_NIGHT in config:
day_night = config[CONF_DAY_NIGHT]
cg.add(var.set_day_night_sensor(day_night[CONF_SENSOR_ID]))
cg.add(var.set_day_night_sensor_type(day_night[CONF_SENSOR_TYPE]))
if day_night[CONF_SENSOR_TYPE].endswith("BINARY"):
if CONF_SENSOR_DAY_VALUE not in day_night:
day_night[CONF_SENSOR_DAY_VALUE] = "on"
if CONF_SENSOR_NIGHT_VALUE not in day_night:
day_night[CONF_SENSOR_NIGHT_VALUE] = "off"
elif day_night[CONF_SENSOR_TYPE].endswith("TEXT"):
if CONF_SENSOR_DAY_VALUE not in day_night:
day_night[CONF_SENSOR_DAY_VALUE] = "Day"
if CONF_SENSOR_NIGHT_VALUE not in day_night:
day_night[CONF_SENSOR_NIGHT_VALUE] = "Night"
cg.add(var.set_day_night_day_value(day_night[CONF_SENSOR_DAY_VALUE]))
cg.add(var.set_day_night_night_value(day_night[CONF_SENSOR_NIGHT_VALUE]))
if CONF_DAY_DEFAULT_BRIGHTNESS in day_night:
cg.add(var.set_day_default_brightness(day_night[CONF_DAY_DEFAULT_BRIGHTNESS]))
if CONF_NIGHT_DEFAULT_BRIGHTNESS in day_night:
cg.add(var.set_night_default_brightness(day_night[CONF_NIGHT_DEFAULT_BRIGHTNESS]))
if CONF_DAY_AUTO_OFF_TIME in day_night:
cg.add(var.set_day_auto_off_time(day_night[CONF_DAY_AUTO_OFF_TIME]))
if CONF_NIGHT_AUTO_OFF_TIME in day_night:
cg.add(var.set_night_auto_off_time(day_night[CONF_NIGHT_AUTO_OFF_TIME]))
for conf in config.get(CONF_ON_DOUBLE_CLICK_WHILE_OFF, []):
trigger = cg.new_Pvariable(conf[CONF_ON_DOUBLE_CLICK_WHILE_OFF], var)
await auto.build_automation(trigger, [], conf)
cg.add(var.set_double_click_while_off_stays_off(config[CONF_DOUBLE_CLICK_WHILE_OFF_STAYS_OFF]))
for conf in config.get(CONF_ON_DOUBLE_CLICK_WHILE_ON, []):
trigger = cg.new_Pvariable(conf[CONF_ON_DOUBLE_CLICK_WHILE_ON], var)
await auto.build_automation(trigger, [], conf)
paren = await cg.get_variable(config[CONF_TUYA_ID])
cg.add(var.set_tuya_parent(paren))

View File

@ -5,87 +5,265 @@ namespace esphome {
namespace tuya {
static const char *TAG = "tuya.light_plus";
static const uint16_t DOUBLE_CLICK_TIMEOUT = 350;
void TuyaLightPlus::setup() {
if (this->color_temperature_id_.has_value()) {
this->parent_->register_listener(*this->color_temperature_id_, [this](TuyaDatapoint datapoint) {
auto call = this->state_->make_call();
call.set_color_temperature(this->cold_white_temperature_ +
(this->warm_white_temperature_ - this->cold_white_temperature_) *
(float(datapoint.value_uint) / float(this->color_temperature_max_value_)));
call.perform();
});
void TuyaLightPlus::setup()
{
this->parent_->register_listener(*this->switch_id_, [this](tuya::TuyaDatapoint datapoint) { this->handle_tuya_datapoint_(datapoint); });
this->parent_->register_listener(*this->dimmer_id_, [this](tuya::TuyaDatapoint datapoint) { this->handle_tuya_datapoint_(datapoint); });
if (this->min_value_datapoint_id_.has_value()) {
this->parent_->set_datapoint_value(*this->min_value_datapoint_id_, this->min_value_);
}
if (this->dimmer_id_.has_value()) {
this->parent_->register_listener(*this->dimmer_id_, [this](TuyaDatapoint datapoint) {
auto call = this->state_->make_call();
call.set_brightness(float(datapoint.value_uint) / this->max_value_);
call.perform();
});
}
if (switch_id_.has_value()) {
this->parent_->register_listener(*this->switch_id_, [this](TuyaDatapoint datapoint) {
auto call = this->state_->make_call();
call.set_state(datapoint.value_bool);
call.perform();
});
}
if (min_value_datapoint_id_.has_value()) {
parent_->set_datapoint_value(*this->min_value_datapoint_id_, this->min_value_);
this->register_service(&TuyaLightPlus::set_default_brightness, "set_default_brightness", {"brightness"});
this->register_service(&TuyaLightPlus::set_auto_off_time, "set_auto_off_time", {"auto_off_time"});
if (this->day_night_sensor_.has_value())
{
this->subscribe_homeassistant_state(&TuyaLightPlus::on_day_night_changed_, *this->day_night_sensor_);
}
}
void TuyaLightPlus::dump_config() {
void TuyaLightPlus::dump_config()
{
ESP_LOGCONFIG(TAG, "Tuya Dimmer:");
if (this->dimmer_id_.has_value())
ESP_LOGCONFIG(TAG, " Dimmer has datapoint ID %u", *this->dimmer_id_);
if (this->switch_id_.has_value())
ESP_LOGCONFIG(TAG, " Switch has datapoint ID %u", *this->switch_id_);
ESP_LOGCONFIG(TAG, " Switch has datapoint ID %u", *this->switch_id_);
ESP_LOGCONFIG(TAG, " Dimmer has datapoint ID %u", *this->dimmer_id_);
if (this->min_value_datapoint_id_.has_value())
ESP_LOGCONFIG(TAG, " Min Value has datapoint ID %u", *this->min_value_datapoint_id_);
}
light::LightTraits TuyaLightPlus::get_traits() {
light::LightTraits TuyaLightPlus::get_traits()
{
auto traits = light::LightTraits();
traits.set_supports_brightness(this->dimmer_id_.has_value());
traits.set_supports_color_temperature(this->color_temperature_id_.has_value());
if (this->color_temperature_id_.has_value()) {
traits.set_min_mireds(this->cold_white_temperature_);
traits.set_max_mireds(this->warm_white_temperature_);
}
traits.set_supports_brightness(true);
return traits;
}
void TuyaLightPlus::setup_state(light::LightState *state) { state_ = state; }
void TuyaLightPlus::write_state(light::LightState *state) {
void TuyaLightPlus::write_state(light::LightState *state)
{
ESP_LOGD(TAG, "Writing state:");
float brightness;
state->current_values_as_brightness(&brightness);
this->last_state_change_ = millis();
ESP_LOGD(TAG, " Brightness: %.0f%%", brightness * 100.0f);
if (brightness == 0.0f) {
// turning off, first try via switch (if exists), then dimmer
if (switch_id_.has_value()) {
parent_->set_datapoint_value(*this->switch_id_, false);
} else if (dimmer_id_.has_value()) {
parent_->set_datapoint_value(*this->dimmer_id_, 0);
}
this->tuya_state_is_on_ = false;
this->parent_->set_datapoint_value(*this->switch_id_, false);
}
else
{
this->tuya_state_is_on_ = true;
this->parent_->set_datapoint_value(*this->dimmer_id_, this->brightness_to_tuya_level_(brightness));
this->parent_->set_datapoint_value(*this->switch_id_, true);
}
}
void TuyaLightPlus::loop()
{
// Double click while off timed out, turn the light on and reset the timeout
if (this->double_click_while_off_timeout_ != 0 && millis() > this->double_click_while_off_timeout_)
{
ESP_LOGD(TAG, "Double click while off timedout, turning on the light");
this->double_click_while_off_timeout_ = 0;
auto on_call = this->state_->turn_on();
on_call.perform();
return;
}
if (this->color_temperature_id_.has_value()) {
uint32_t color_temp_int =
static_cast<uint32_t>(this->color_temperature_max_value_ *
(state->current_values.get_color_temperature() - this->cold_white_temperature_) /
(this->warm_white_temperature_ - this->cold_white_temperature_));
parent_->set_datapoint_value(*this->color_temperature_id_, color_temp_int);
// Double click while on timed out, reset the timeout
if (this->double_click_while_on_timeout_ != 0 && millis() > this->double_click_while_on_timeout_)
{
this->double_click_while_on_timeout_ = 0;
return;
}
auto brightness_int = static_cast<uint32_t>(brightness * this->max_value_);
brightness_int = std::max(brightness_int, this->min_value_);
if (this->dimmer_id_.has_value()) {
parent_->set_datapoint_value(*this->dimmer_id_, brightness_int);
// Auto off
if (this->state_->current_values.is_on() && this->auto_off_time_.has_value() && millis() > (this->last_state_change_ + *this->auto_off_time_))
{
auto call = this->state_->turn_off();
call.perform();
}
if (this->switch_id_.has_value()) {
parent_->set_datapoint_value(*this->switch_id_, true);
}
void TuyaLightPlus::add_new_double_click_while_off_callback(std::function<void()> &&callback)
{
this->has_double_click_while_off_ = true;
this->double_click_while_off_callback_.add(std::move(callback));
}
void TuyaLightPlus::add_new_double_click_while_on_callback(std::function<void()> &&callback)
{
this->has_double_click_while_on_ = true;
this->double_click_while_on_callback_.add(std::move(callback));
}
void TuyaLightPlus::set_default_brightness_(float brightness)
{
ESP_LOGCONFIG(TAG, "Setting the default brightness to %f", brightness);
this->default_brightness_ = brightness <= 0 ? optional<float>{} : std::min(brightness, 1.0f);
// If the light is off update the brightness state so regardless of how the light is turned on the brightness will be the default
if (this->default_brightness_.has_value() && this->state_ != nullptr && !this->tuya_state_is_on_)
{
this->state_->current_values.set_brightness(*this->default_brightness_);
this->state_->remote_values = this->state_->current_values;
}
}
void TuyaLightPlus::handle_tuya_datapoint_(tuya::TuyaDatapoint datapoint)
{
ESP_LOGD(TAG, "Received Datapoint:");
if (datapoint.id == *this->switch_id_)
{
ESP_LOGD(TAG, " Type: Switch");
ESP_LOGD(TAG, " State: %s", ONOFF(datapoint.value_bool));
// Turned on with the physical button
if (datapoint.value_bool && !this->tuya_state_is_on_)
{
ESP_LOGD(TAG, "Turned on at switch");
if (this->has_double_click_while_on_)
{
// We are in a double click while on timeout period so this is a double click
if (this->double_click_while_on_timeout_ != 0)
{
ESP_LOGD(TAG, "Switch was double clicked while on");
this->parent_->set_datapoint_value(*this->switch_id_, false);
this->double_click_while_on_timeout_ = 0;
this->double_click_while_on_callback_.call();
return;
}
}
if (this->has_double_click_while_off_)
{
// We are not in a double click while off timeout period
if (this->double_click_while_off_timeout_ == 0)
{
// Turn the light back off and wait to see if we get a double click
this->parent_->set_datapoint_value(*this->switch_id_, false);
this->double_click_while_off_timeout_ = millis() + DOUBLE_CLICK_TIMEOUT;
return;
}
// We are in a double click while off timeout period so this is a double click
else
{
ESP_LOGD(TAG, "Switch was double clicked while off");
this->double_click_while_off_timeout_ = 0;
this->double_click_while_off_callback_.call();
// Double click while off can be configured to result in the light being off or on
if (this->double_click_while_off_stays_off_)
{
this->parent_->set_datapoint_value(*this->switch_id_, false);
return;
}
}
}
// When the light is turned on at the switch the level of the Tuya device will stll be 0 so we set it to the current state value
float brightness;
this->state_->current_values_as_brightness(&brightness);
this->parent_->set_datapoint_value(*this->dimmer_id_, this->brightness_to_tuya_level_(brightness));
}
// Turned off with the physical button
if(!datapoint.value_bool && this->tuya_state_is_on_)
{
ESP_LOGD(TAG, "Turned off at switch");
if (this->has_double_click_while_on_)
{
// Start the double click while on timeout
this->double_click_while_on_timeout_ = millis() + DOUBLE_CLICK_TIMEOUT;
}
}
this->tuya_state_is_on_ = datapoint.value_bool;
this->state_->current_values.set_state(datapoint.value_bool);
// If the light was turned off we set the brightness of the Tuya device to 0 to prevent flashes during double clicks and if there is a
// default brightness set the current brightness value to the default so that if it is turned on remotely it will be at the default value
if (!datapoint.value_bool)
{
this->parent_->set_datapoint_value(*this->dimmer_id_, static_cast<uint32_t>(0));
if (this->default_brightness_.has_value())
{
this->state_->current_values.set_brightness(*this->default_brightness_);
}
}
}
else if (datapoint.id == *this->dimmer_id_)
{
ESP_LOGD(TAG, " Type: Brightness");
ESP_LOGD(TAG, " Value: %u", datapoint.value_uint);
// Only react to dimmer level changes if the light is on
if(this->state_->current_values.is_on())
{
this->state_->current_values.set_brightness(this->tuya_level_to_brightness_(datapoint.value_uint));
}
}
this->last_state_change_ = millis();
this->state_->remote_values = this->state_->current_values;
this->state_->publish_state();
if (this->linked_lights_.has_value())
{
if (this->state_->current_values.is_on())
{
this->call_homeassistant_service(
"light.turn_on",
{
{ "entity_id", *this->linked_lights_ },
{ "brightness", to_string(static_cast<uint32_t>(this->state_->current_values.get_brightness() * 255)) },
});
}
else
{
this->call_homeassistant_service(
"light.turn_off",
{
{ "entity_id", *this->linked_lights_ },
});
}
}
}
void TuyaLightPlus::on_day_night_changed_(std::string state)
{
if (state == this->day_night_day_value_)
{
if (this->day_default_brightness_.has_value())
{
this->set_default_brightness_(*this->day_default_brightness_);
}
if (this->day_auto_off_time_.has_value())
{
this->set_auto_off_time(*this->day_auto_off_time_);
}
}
else if (state == this->day_night_night_value_)
{
if (this->night_default_brightness_.has_value())
{
this->set_default_brightness_(*this->night_default_brightness_);
}
if (this->night_auto_off_time_.has_value())
{
this->set_auto_off_time(*this->night_auto_off_time_);
}
}
}

View File

@ -3,51 +3,101 @@
#include "esphome/core/component.h"
#include "esphome/components/tuya/tuya.h"
#include "esphome/components/light/light_output.h"
#include "esphome/components/api/custom_api_device.h"
namespace esphome {
namespace tuya {
class TuyaLightPlus : public Component, public light::LightOutput {
enum DayNightSensorType {
BINARY,
TEXT,
};
class TuyaLightPlus : public Component, public light::LightOutput, public api::CustomAPIDevice {
public:
void setup() override;
void dump_config() override;
void set_dimmer_id(uint8_t dimmer_id) { this->dimmer_id_ = dimmer_id; }
void set_min_value_datapoint_id(uint8_t min_value_datapoint_id) {
this->min_value_datapoint_id_ = min_value_datapoint_id;
}
void set_switch_id(uint8_t switch_id) { this->switch_id_ = switch_id; }
void set_color_temperature_id(uint8_t color_temperature_id) { this->color_temperature_id_ = color_temperature_id; }
void set_dimmer_id(uint8_t dimmer_id) { this->dimmer_id_ = dimmer_id; }
void set_min_value_datapoint_id(uint8_t min_value_datapoint_id) { this->min_value_datapoint_id_ = min_value_datapoint_id; }
void set_tuya_parent(Tuya *parent) { this->parent_ = parent; }
void set_min_value(uint32_t min_value) { min_value_ = min_value; }
void set_max_value(uint32_t max_value) { max_value_ = max_value; }
void set_color_temperature_max_value(uint32_t color_temperature_max_value) {
this->color_temperature_max_value_ = color_temperature_max_value;
}
void set_cold_white_temperature(float cold_white_temperature) {
this->cold_white_temperature_ = cold_white_temperature;
}
void set_warm_white_temperature(float warm_white_temperature) {
this->warm_white_temperature_ = warm_white_temperature;
}
void set_min_value(uint32_t min_value) { this->min_value_ = min_value; }
void set_max_value(uint32_t max_value) { this->max_value_ = max_value; }
light::LightTraits get_traits() override;
void setup_state(light::LightState *state) override;
void write_state(light::LightState *state) override;
void loop() override;
void set_linked_lights(const std::string linked_lights) { this->linked_lights_ = linked_lights; }
void set_day_night_sensor(const std::string day_night_sensor) { this->day_night_sensor_ = day_night_sensor; }
void set_day_night_sensor_type(DayNightSensorType day_night_sensor_type) { this->day_night_sensor_type_ = day_night_sensor_type; }
void set_day_night_day_value(const std::string day_night_day_value) { this->day_night_day_value_ = day_night_day_value; }
void set_day_night_night_value(const std::string day_night_night_value) { this->day_night_night_value_ = day_night_night_value; }
void set_day_default_brightness(uint8_t brightness) { this->day_default_brightness_ = brightness == 0 ? optional<float>{} : this->ha_brightness_to_brightness_(brightness); }
void set_night_default_brightness(uint8_t brightness) { this->night_default_brightness_ = brightness == 0 ? optional<float>{} : this->ha_brightness_to_brightness_(brightness); }
void set_day_auto_off_time(uint32_t auto_off_time) { this->day_auto_off_time_ = auto_off_time_ == 0 ? optional<uint32_t>{} : auto_off_time; }
void set_night_auto_off_time(uint32_t auto_off_time) { this->night_auto_off_time_ = auto_off_time_ == 0 ? optional<uint32_t>{} : auto_off_time; }
void add_new_double_click_while_off_callback(std::function<void()> &&callback);
void set_double_click_while_off_stays_off(bool stays_off) { this->double_click_while_off_stays_off_ = stays_off; }
void add_new_double_click_while_on_callback(std::function<void()> &&callback);
void set_default_brightness(int brightness) { this->set_default_brightness_(this->ha_brightness_to_brightness_(brightness)); }
void set_auto_off_time(int auto_off_time) { this->auto_off_time_ = auto_off_time == 0 ? optional<uint32_t>{} : auto_off_time; }
protected:
void update_dimmer_(uint32_t value);
void update_switch_(uint32_t value);
float ha_brightness_to_brightness_(int brightness) { return clamp(static_cast<float>(brightness) / static_cast<float>(255), 0.01f, 1.0f); }
float tuya_level_to_brightness_(uint32_t level) { return static_cast<float>(level) / static_cast<float>(this->max_value_); }
uint32_t brightness_to_tuya_level_(float brightness) { return static_cast<uint32_t>(brightness * this->max_value_); }
void set_default_brightness_(float brightness);
void handle_tuya_datapoint_(TuyaDatapoint datapoint);
void on_day_night_changed_(std::string state);
Tuya *parent_;
optional<uint8_t> switch_id_{};
optional<uint8_t> dimmer_id_{};
optional<uint8_t> min_value_datapoint_id_{};
optional<uint8_t> switch_id_{};
optional<uint8_t> color_temperature_id_{};
uint32_t min_value_ = 0;
uint32_t max_value_ = 255;
uint32_t color_temperature_max_value_ = 255;
float cold_white_temperature_;
float warm_white_temperature_;
light::LightState *state_{nullptr};
optional<float> default_brightness_{};
optional<uint32_t> auto_off_time_{};
optional<std::string> linked_lights_{};
optional<std::string> day_night_sensor_{};
optional<DayNightSensorType> day_night_sensor_type_{};
optional<std::string> day_night_day_value_{};
optional<std::string> day_night_night_value_{};
optional<float> day_default_brightness_{};
optional<float> night_default_brightness_{};
optional<uint32_t> day_auto_off_time_{};
optional<uint32_t> night_auto_off_time_{};
CallbackManager<void()> double_click_while_off_callback_{};
CallbackManager<void()> double_click_while_on_callback_{};
bool has_double_click_while_off_{false};
bool double_click_while_off_stays_off_{true};
bool has_double_click_while_on_{false};
long double_click_while_off_timeout_ = 0;
long double_click_while_on_timeout_ = 0;
bool tuya_state_is_on_{false};
long last_state_change_ = 0;
};
class DoubleClickWhileOffTrigger : public Trigger<> {
public:
DoubleClickWhileOffTrigger(TuyaLightPlus *light) {
light->add_new_double_click_while_off_callback([this, light]() {
this->trigger();
});
}
};
class DoubleClickWhileOnTrigger : public Trigger<> {
public:
DoubleClickWhileOnTrigger(TuyaLightPlus *light) {
light->add_new_double_click_while_on_callback([this, light]() {
this->trigger();
});
}
};
} // namespace tuya

View File

@ -5,20 +5,9 @@ substitutions:
ota_pwd: !secret basement_stair_lights_ota_pwd
api_pwd: !secret basement_stair_lights_api_pwd
ap_wifi_pwd: !secret basement_stair_lights_ap_wifi_pwd
day_brightness: "1"
night_brightness: ".03"
day_auto_off_minutes: "0"
night_auto_off_minutes: "15"
linked_lights: "light.basement_stair_lights_2"
double_tap_while_off_stays_on: "false"
script:
- id: startup
then:
- lambda: |-
TuyaLight->add_double_tap_callback([]() { double_tap->execute(); });
- id: double_tap
- id: double_click
then:
- homeassistant.service:
service: homeassistant.turn_off
@ -27,3 +16,27 @@ script:
packages:
feit_dimmer: !include ../packages/feit_dimmer.yaml
light:
- platform: tuya_light_plus
id: tuya_light
name: ${device_name}
switch_datapoint: 1
dimmer_datapoint: 2
max_value: 1000
linked_lights:
- light.basement_stair_lights_2
day_night:
sensor_id: sensor.day_night
sensor_type: text
sensor_day_value: Day
sensor_night_value: Night
day_default_brightness: 255
night_default_brightness: 1
day_auto_off_time: 0 min
night_auto_off_time: 15 min
on_double_click_while_off:
- script.execute: double_click
double_click_while_off_stays_off: true
on_double_click_while_on:
- script.execute: double_click

View File

@ -5,20 +5,9 @@ substitutions:
ota_pwd: !secret basement_stair_lights_2_ota_pwd
api_pwd: !secret basement_stair_lights_2_api_pwd
ap_wifi_pwd: !secret basement_stair_lights_2_ap_wifi_pwd
day_brightness: "1"
night_brightness: ".03"
day_auto_off_minutes: "0"
night_auto_off_minutes: "15"
linked_lights: "light.basement_stair_lights"
double_tap_while_off_stays_on: "false"
script:
- id: startup
then:
- lambda: |-
TuyaLight->add_double_tap_callback([]() { double_tap->execute(); });
- id: double_tap
- id: double_click
then:
- homeassistant.service:
service: homeassistant.turn_off
@ -27,3 +16,27 @@ script:
packages:
feit_dimmer: !include ../packages/feit_dimmer.yaml
light:
- platform: tuya_light_plus
id: tuya_light
name: ${device_name}
switch_datapoint: 1
dimmer_datapoint: 2
max_value: 1000
linked_lights:
- light.basement_stair_lights
day_night:
sensor_id: sensor.day_night
sensor_type: text
sensor_day_value: Day
sensor_night_value: Night
day_default_brightness: 255
night_default_brightness: 1
day_auto_off_time: 0 min
night_auto_off_time: 15 min
on_double_click_while_off:
- script.execute: double_click
double_click_while_off_stays_off: true
on_double_click_while_on:
- script.execute: double_click

View File

@ -5,17 +5,24 @@ substitutions:
ota_pwd: !secret computer_light_ota_pwd
api_pwd: !secret computer_light_api_pwd
ap_wifi_pwd: !secret computer_light_ap_wifi_pwd
day_brightness: "1"
night_brightness: ".03"
day_auto_off_minutes: "0"
night_auto_off_minutes: "15"
linked_lights: ""
double_tap_while_off_stays_on: "true"
script:
- id: startup
then:
- lambda: |-
packages:
feit_dimmer: !include ../packages/feit_dimmer.yaml
light:
- platform: tuya_light_plus
id: tuya_light
name: ${device_name}
switch_datapoint: 1
dimmer_datapoint: 2
max_value: 1000
linked_lights:
day_night:
sensor_id: sensor.day_night
sensor_type: text
sensor_day_value: Day
sensor_night_value: Night
day_default_brightness: 255
night_default_brightness: 1
day_auto_off_time: 0 min
night_auto_off_time: 15 min

View File

@ -5,17 +5,24 @@ substitutions:
ota_pwd: !secret dining_room_light_ota_pwd
api_pwd: !secret dining_room_light_api_pwd
ap_wifi_pwd: !secret dining_room_light_ap_wifi_pwd
day_brightness: "1"
night_brightness: ".03"
day_auto_off_minutes: "0"
night_auto_off_minutes: "15"
linked_lights: ""
double_tap_while_off_stays_on: "true"
script:
- id: startup
then:
- lambda: |-
packages:
feit_dimmer: !include ../packages/feit_dimmer.yaml
light:
- platform: tuya_light_plus
id: tuya_light
name: ${device_name}
switch_datapoint: 1
dimmer_datapoint: 2
max_value: 1000
linked_lights:
day_night:
sensor_id: sensor.day_night
sensor_type: text
sensor_day_value: Day
sensor_night_value: Night
day_default_brightness: 255
night_default_brightness: 1
day_auto_off_time: 0 min
night_auto_off_time: 15 min

View File

@ -5,17 +5,24 @@ substitutions:
ota_pwd: !secret family_room_light_ota_pwd
api_pwd: !secret family_room_light_api_pwd
ap_wifi_pwd: !secret family_room_light_ap_wifi_pwd
day_brightness: "1"
night_brightness: ".03"
day_auto_off_minutes: "0"
night_auto_off_minutes: "15"
linked_lights: ""
double_tap_while_off_stays_on: "true"
script:
- id: startup
then:
- lambda: |-
packages:
feit_dimmer: !include ../packages/feit_dimmer.yaml
light:
- platform: tuya_light_plus
id: tuya_light
name: ${device_name}
switch_datapoint: 1
dimmer_datapoint: 2
max_value: 1000
linked_lights:
day_night:
sensor_id: sensor.day_night
sensor_type: text
sensor_day_value: Day
sensor_night_value: Night
day_default_brightness: 255
night_default_brightness: 1
day_auto_off_time: 0 min
night_auto_off_time: 15 min

View File

@ -5,17 +5,24 @@ substitutions:
ota_pwd: !secret front_entry_lights_ota_pwd
api_pwd: !secret front_entry_lights_api_pwd
ap_wifi_pwd: !secret front_entry_lights_ap_wifi_pwd
day_brightness: "1"
night_brightness: ".03"
day_auto_off_minutes: "0"
night_auto_off_minutes: "15"
linked_lights: ""
double_tap_while_off_stays_on: "true"
script:
- id: startup
then:
- lambda: |-
packages:
feit_dimmer: !include ../packages/feit_dimmer.yaml
light:
- platform: tuya_light_plus
id: tuya_light
name: ${device_name}
switch_datapoint: 1
dimmer_datapoint: 2
max_value: 1000
linked_lights:
day_night:
sensor_id: sensor.day_night
sensor_type: text
sensor_day_value: Day
sensor_night_value: Night
day_default_brightness: 255
night_default_brightness: 1
day_auto_off_time: 0 min
night_auto_off_time: 15 min

View File

@ -5,17 +5,24 @@ substitutions:
ota_pwd: !secret front_entry_lights_2_ota_pwd
api_pwd: !secret front_entry_lights_2_api_pwd
ap_wifi_pwd: !secret front_entry_lights_2_ap_wifi_pwd
day_brightness: "1"
night_brightness: ".03"
day_auto_off_minutes: "0"
night_auto_off_minutes: "15"
linked_lights: ""
double_tap_while_off_stays_on: "true"
script:
- id: startup
then:
- lambda: |-
packages:
feit_dimmer: !include ../packages/feit_dimmer.yaml
light:
- platform: tuya_light_plus
id: tuya_light
name: ${device_name}
switch_datapoint: 1
dimmer_datapoint: 2
max_value: 1000
linked_lights:
day_night:
sensor_id: sensor.day_night
sensor_type: text
sensor_day_value: Day
sensor_night_value: Night
day_default_brightness: 255
night_default_brightness: 1
day_auto_off_time: 0 min
night_auto_off_time: 15 min

View File

@ -5,19 +5,21 @@ substitutions:
ota_pwd: !secret front_lights_ota_pwd
api_pwd: !secret front_lights_api_pwd
ap_wifi_pwd: !secret front_lights_ap_wifi_pwd
day_brightness: "1"
night_brightness: "1"
day_auto_off_minutes: "30"
night_auto_off_minutes: "15"
linked_lights: ""
double_tap_while_off_stays_on: "true"
script:
- id: startup
then:
- lambda: |-
TuyaLight->add_double_tap_while_off_callback([]() { TuyaLight->set_auto_off_minutes(0); });
packages:
feit_dimmer: !include ../packages/feit_dimmer.yaml
light:
- platform: tuya_light_plus
id: tuya_light
name: ${device_name}
switch_datapoint: 1
dimmer_datapoint: 2
max_value: 1000
default_brightness: 255
auto_off_time: 30 min
on_double_click_while_off:
- lambda: tuya_tuyalightplus->set_auto_off_time(0);
double_click_while_off_stays_off: false
on_turn_off:
- lambda: tuya_tuyalightplus->set_auto_off_time(30 * 60 * 1000);

View File

@ -5,17 +5,24 @@ substitutions:
ota_pwd: !secret kitchen_bar_lights_ota_pwd
api_pwd: !secret kitchen_bar_lights_api_pwd
ap_wifi_pwd: !secret kitchen_bar_lights_ap_wifi_pwd
day_brightness: "1"
night_brightness: ".03"
day_auto_off_minutes: "0"
night_auto_off_minutes: "15"
linked_lights: ""
double_tap_while_off_stays_on: "true"
script:
- id: startup
then:
- lambda: |-
packages:
feit_dimmer: !include ../packages/feit_dimmer.yaml
light:
- platform: tuya_light_plus
id: tuya_light
name: ${device_name}
switch_datapoint: 1
dimmer_datapoint: 2
max_value: 1000
linked_lights:
day_night:
sensor_id: sensor.day_night
sensor_type: text
sensor_day_value: Day
sensor_night_value: Night
day_default_brightness: 255
night_default_brightness: 1
day_auto_off_time: 0 min
night_auto_off_time: 15 min

View File

@ -5,17 +5,24 @@ substitutions:
ota_pwd: !secret kitchen_table_light_ota_pwd
api_pwd: !secret kitchen_table_light_api_pwd
ap_wifi_pwd: !secret kitchen_table_light_ap_wifi_pwd
day_brightness: "1"
night_brightness: ".03"
day_auto_off_minutes: "0"
night_auto_off_minutes: "15"
linked_lights: ""
double_tap_while_off_stays_on: "true"
script:
- id: startup
then:
- lambda: |-
packages:
feit_dimmer: !include ../packages/feit_dimmer.yaml
light:
- platform: tuya_light_plus
id: tuya_light
name: ${device_name}
switch_datapoint: 1
dimmer_datapoint: 2
max_value: 1000
linked_lights:
day_night:
sensor_id: sensor.day_night
sensor_type: text
sensor_day_value: Day
sensor_night_value: Night
day_default_brightness: 255
night_default_brightness: 1
day_auto_off_time: 0 min
night_auto_off_time: 15 min

View File

@ -5,17 +5,24 @@ substitutions:
ota_pwd: !secret living_room_lights_ota_pwd
api_pwd: !secret living_room_lights_api_pwd
ap_wifi_pwd: !secret living_room_lights_ap_wifi_pwd
day_brightness: "1"
night_brightness: ".03"
day_auto_off_minutes: "0"
night_auto_off_minutes: "15"
linked_lights: ""
double_tap_while_off_stays_on: "true"
script:
- id: startup
then:
- lambda: |-
packages:
feit_dimmer: !include ../packages/feit_dimmer.yaml
light:
- platform: tuya_light_plus
id: tuya_light
name: ${device_name}
switch_datapoint: 1
dimmer_datapoint: 2
max_value: 1000
linked_lights:
day_night:
sensor_id: sensor.day_night
sensor_type: text
sensor_day_value: Day
sensor_night_value: Night
day_default_brightness: 255
night_default_brightness: 1
day_auto_off_time: 0 min
night_auto_off_time: 15 min

View File

@ -5,17 +5,24 @@ substitutions:
ota_pwd: !secret master_bath_lights_ota_pwd
api_pwd: !secret master_bath_lights_api_pwd
ap_wifi_pwd: !secret master_bath_lights_ap_wifi_pwd
day_brightness: "1"
night_brightness: ".05"
day_auto_off_minutes: "0"
night_auto_off_minutes: "15"
linked_lights: ""
double_tap_while_off_stays_on: "true"
script:
- id: startup
then:
- lambda: |-
packages:
feit_dimmer: !include ../packages/feit_dimmer.yaml
light:
- platform: tuya_light_plus
id: tuya_light
name: ${device_name}
switch_datapoint: 1
dimmer_datapoint: 2
max_value: 1000
linked_lights:
day_night:
sensor_id: sensor.day_night
sensor_type: text
sensor_day_value: Day
sensor_night_value: Night
day_default_brightness: 255
night_default_brightness: 1
day_auto_off_time: 0 min
night_auto_off_time: 15 min

View File

@ -5,17 +5,24 @@ substitutions:
ota_pwd: !secret master_bath_lights_2_ota_pwd
api_pwd: !secret master_bath_lights_2_api_pwd
ap_wifi_pwd: !secret master_bath_lights_2_ap_wifi_pwd
day_brightness: "1"
night_brightness: ".05"
day_auto_off_minutes: "0"
night_auto_off_minutes: "15"
linked_lights: ""
double_tap_while_off_stays_on: "true"
script:
- id: startup
then:
- lambda: |-
packages:
feit_dimmer: !include ../packages/feit_dimmer.yaml
light:
- platform: tuya_light_plus
id: tuya_light
name: ${device_name}
switch_datapoint: 1
dimmer_datapoint: 2
max_value: 1000
linked_lights:
day_night:
sensor_id: sensor.day_night
sensor_type: text
sensor_day_value: Day
sensor_night_value: Night
day_default_brightness: 255
night_default_brightness: 1
day_auto_off_time: 0 min
night_auto_off_time: 15 min

View File

@ -5,17 +5,34 @@ substitutions:
ota_pwd: !secret office_light_ota_pwd
api_pwd: !secret office_light_api_pwd
ap_wifi_pwd: !secret office_light_ap_wifi_pwd
day_brightness: "1"
night_brightness: ".03"
day_auto_off_minutes: "0"
night_auto_off_minutes: "15"
linked_lights: ""
double_tap_while_off_stays_on: "true"
script:
- id: startup
- id: double_click
then:
- lambda: |-
- logger.log: "Double click script has been run!"
packages:
feit_dimmer: !include ../packages/feit_dimmer.yaml
light:
- platform: tuya_light_plus
id: tuya_light
name: ${device_name}
switch_datapoint: 1
dimmer_datapoint: 2
max_value: 1000
linked_lights:
day_night:
sensor_id: sensor.day_night
sensor_type: text
sensor_day_value: Day
sensor_night_value: Night
day_default_brightness: 255
night_default_brightness: 1
day_auto_off_time: 0 min
night_auto_off_time: 15 min
on_double_click_while_off:
- script.execute: double_click
double_click_while_off_stays_off: true
on_double_click_while_on:
- script.execute: double_click

View File

@ -1,16 +0,0 @@
substitutions:
device_id: computer_light
device_name: Computer Light
ip_address: !secret computer_light_ip
ota_pwd: !secret computer_light_ota_pwd
api_pwd: !secret computer_light_api_pwd
ap_wifi_pwd: !secret computer_light_ap_wifi_pwd
day_brightness: "1"
night_brightness: ".03"
day_auto_off_minutes: "0"
night_auto_off_minutes: "15"
linked_lights: ""
double_tap_while_off_stays_on: "true"
packages:
feit_dimmer: !include ../packages/feit_dimmer_test.yaml

View File

@ -1,22 +1,13 @@
substitutions:
platform: ESP8266
board: esp01_1m
log_level: verbose
esphome:
includes:
- ../custom/tuya_light_plus.h
on_boot:
priority: -100
then:
- script.execute: startup
external_components:
# - source: github://nuttytree/esphome@more-tuya-reliability-improvements
- source:
type: local
path: ../components
components: [ tuya ]
components: [ tuya, tuya_light_plus ]
packages:
base: !include device_base.yaml
@ -24,28 +15,3 @@ packages:
uart: !include uart/tuya.yaml
tuya:
light:
- platform: custom
lambda: |-
TuyaLight = new TuyaLightPlus();
TuyaLight->set_switch_id(1);
TuyaLight->set_dimmer_id(2);
TuyaLight->set_min_value(0);
TuyaLight->set_max_value(1000);
TuyaLight->set_tuya_parent(tuya_tuya);
TuyaLight->set_day_night_sensor("sensor.day_night");
TuyaLight->set_day_default_brightness(${day_brightness});
TuyaLight->set_night_default_brightness(${night_brightness});
TuyaLight->set_day_auto_off_minutes(${day_auto_off_minutes});
TuyaLight->set_night_auto_off_minutes(${night_auto_off_minutes});
TuyaLight->set_api_server(api_apiserver);
TuyaLight->set_linked_lights("${linked_lights}");
TuyaLight->set_double_tap_while_off_stays_on(${double_tap_while_off_stays_on});
App.register_component(TuyaLight);
return {TuyaLight};
lights:
- id: tuya_light
name: ${device_name}
gamma_correct: 1.0
default_transition_length: 0s

View File

@ -0,0 +1,51 @@
substitutions:
platform: ESP8266
board: esp01_1m
log_level: verbose
esphome:
includes:
- ../custom/tuya_light_plus.h
on_boot:
priority: -100
then:
- script.execute: startup
external_components:
# - source: github://nuttytree/esphome@more-tuya-reliability-improvements
- source:
type: local
path: ../components
components: [ tuya ]
packages:
base: !include device_base.yaml
logger: !include logger/logger_no_serial.yaml
uart: !include uart/tuya.yaml
tuya:
light:
- platform: custom
lambda: |-
TuyaLight = new TuyaLightPlus();
TuyaLight->set_switch_id(1);
TuyaLight->set_dimmer_id(2);
TuyaLight->set_min_value(0);
TuyaLight->set_max_value(1000);
TuyaLight->set_tuya_parent(tuya_tuya);
TuyaLight->set_day_night_sensor("sensor.day_night");
TuyaLight->set_day_default_brightness(${day_brightness});
TuyaLight->set_night_default_brightness(${night_brightness});
TuyaLight->set_day_auto_off_minutes(${day_auto_off_minutes});
TuyaLight->set_night_auto_off_minutes(${night_auto_off_minutes});
TuyaLight->set_api_server(api_apiserver);
TuyaLight->set_linked_lights("${linked_lights}");
TuyaLight->set_double_tap_while_off_stays_on(${double_tap_while_off_stays_on});
App.register_component(TuyaLight);
return {TuyaLight};
lights:
- id: tuya_light
name: ${device_name}
gamma_correct: 1.0
default_transition_length: 0s

View File

@ -1,26 +0,0 @@
substitutions:
platform: ESP8266
board: esp01_1m
log_level: verbose
external_components:
# - source: github://nuttytree/esphome@more-tuya-reliability-improvements
- source:
type: local
path: ../components
components: [ tuya, tuya_light_plus ]
packages:
base: !include device_base.yaml
logger: !include logger/logger_no_serial.yaml
uart: !include uart/tuya.yaml
tuya:
light:
- platform: tuya_light_plus
id: tuya_light
name: ${device_name}
switch_datapoint: 1
dimmer_datapoint: 2
max_value: 1000