Good day!
The following configuration should turn a fan on and off at specified intervals. The initial state doesn’t matter. According to home assistant, when the esp32 board starts, it turns off the fan. That should trigger the on_turn_off event. But nothing happens. The events don’t seem to get called.
esp32:
board: esp32dev
framework:
type: arduino
fan:
- platform: binary
id: fan1
name: "Fan"
output: gpio_fan
on_turn_on:
- delay: 60min
- fan.turn_off: fan1
on_turn_off:
- delay: 120min
- fan.turn_on: fan1
Many Greetings!
Remo
May relate to this. Setting of the initial state may not trigger the event.
opened 09:55AM - 03 Aug 23 UTC
<!-- READ THIS FIRST:
- This is for feature requests only, for issues please g… o to the issues repository.
- Please be as descriptive as possible, especially use-cases that can otherwise not be solved boost the problem's priority.
DO NOT DELETE ANY TEXT from this template! Otherwise the issue may be closed without a comment.
-->
**Describe the problem you have/What new integration you would like**
Idea is to have triggers on component registered actions.
Which will fire on command/action received by component.
F.e. for ```switch``` see 3 registered actions:
```
@automation.register_action("switch.toggle", ToggleAction, SWITCH_ACTION_SCHEMA)
@automation.register_action("switch.turn_off", TurnOffAction, SWITCH_ACTION_SCHEMA)
@automation.register_action("switch.turn_on", TurnOnAction, SWITCH_ACTION_SCHEMA)
```
So, idea is to have triggers (naming just example) ```action_turn_on```, ```action_turn_off```, ```action_toggle```.
**Please describe your use case for this integration and alternatives you've tried:**
Aim:
* to do something regardless on state change, just on action received;
* to override command received from HA, f.e. not turn on on certain circumstances.
Use case.
Entering to room light is turned on by wall switch, where inching is coded to switch off light after some time (save the nature).
Or by door which send action ```turn_on``` to wall switch through HA or ```http_request``` directly to switch.
Also motion/presence sensor is installed to detect presence and prolong/restart inching time for light.
Which also send action ```turn_on``` while person still moves in room - by HA or ```http_request``` directly.
Currently action ```Turning ON``` is logged by ```switch```, but as state not changed - ```on_turn_on``` not firing.
As per design, thanx for explanation to @ssieb.
```action_turn_on``` will fire on received command/action through HA API or by direct ```http_request``` from another ESPHome device - regardless on actual state & can be used to restart script with delay.
Which is not possible to achieve by ```on_turn_on``` trigger.
```yaml
switch:
- platform: output
output: out_relay
id: sw_relay
action_turn_on:
- script.execute: delay_relay
on_turn_off:
- script.stop: delay_relay
script:
- id: delay_relay
mode: restart
then:
- delay: 5
- switch.turn_off: sw_relay
```
IMHO it will add a lot of flexibility and usability.
**Additional context**
As alternatives you could look into using on_boot:
and/or interval:
Hi Mahko!
No, this suggestion is, in my opinion, a needless increase of complexity. You can solve that with scripts.
Actually the documentation doesn’t state, when exactly the events get called. So I assumed the fan has an uninitialized state during boot and gets a new state during initialization. But it seems that there is no such thing as an uninitialized state and the initialization is no state change.
Triggering with on_boot event works, but since I need asymmetric time delays, the interval component wont work. But eventually I solved it with an endless loop in a script now, that allows for cleaner code and solves some potential technical issues the initial solution with events has. Like what happens if a manual toggle occurs while one of the event handlers is still running.
Many Greetings!
Remo
1 Like
Great you found a solution you prefer. Please share it back for the next person;) I can see how a script could work well too. They are quite flexible.
You could include delays in the interval to handle that. Probably in a similar way to how your script is working. Script prob sounds better though.
Hi Mahko!
Yes, a solution was not the reason for this thread. I wanted to find out more about events in esp home. But here is my current solution for a binary fan with asymmetric on/off interval. The current code has one remaining issue: After boot, when fan automation is restored as on, the first turn on command is lost. It may be solved with a higher on_boot priority. Or a more robust command queue in esp home.
esphome:
name: cabinet
friendly_name: Cabinet
on_boot:
- script.execute: fan_operate
esp32:
board: esp32dev
framework:
type: arduino
number:
- platform: template
id: fan_on_min
name: "Fan On Minutes"
optimistic: true
restore_value: true
min_value: 5
max_value: 240
step: 5
initial_value: 60
icon: "mdi:timer"
- platform: template
id: fan_off_min
name: "Fan Off Minutes"
optimistic: true
restore_value: true
min_value: 5
max_value: 240
step: 5
initial_value: 120
icon: "mdi:timer"
script:
- id: fan_operate
mode: restart
then:
- while:
condition:
- lambda: "return true;"
then:
- if:
condition:
lambda: "return id(fan_auto).state;"
then:
- fan.turn_on: fan1
- delay: !lambda "return id(fan_on_min).state * 60000.0;"
- if:
condition:
lambda: "return id(fan_auto).state;"
then:
- fan.turn_off: fan1
- delay: !lambda "return id(fan_off_min).state * 60000.0;"
binary_sensor:
- platform: gpio
name: "Fan Button"
pin:
number: GPIO18
mode:
input: true
pullup: true
filters:
- invert:
- delayed_on: 10ms
- delayed_off: 10ms
on_press:
then:
- fan.toggle: fan1
switch:
- platform: template
id: fan_auto
name: "Fan Automation"
optimistic: true
icon: "mdi:fan-clock"
restore_mode: RESTORE_DEFAULT_ON
on_turn_on:
- script.execute: fan_operate
output:
- platform: gpio
id: gpio_fan
pin: GPIO14
fan:
- platform: binary
id: fan1
name: "Fan"
output: gpio_fan
In my opinion it would be great if this script could be solved without any lambdas.
Many Greetings!
Remo
Well now we know;)
^^ That part you can replace with a switch condition if you prefer.
^^ This part I think needs to stay as a lambda if you want to be able to adjust it during operation.
^^ Not sure what this part is for?
Hi Mahko!
Thanks for the hint with the switch condition.
while (true) …
Is an endless loop. I was thinking about different solutions and I think this one has the least complexity.
Many Greetings!
Remo
1 Like
Oh of course…
^^ You might be able to replace this with this if you prefer. Not sure though.
condition:
- script.is_running: fan_operate
Hi Mahko!
While this might be technically working, I don’t like the circular reference it creates.
Many Greetings!
Remo
1 Like
Default restore_mode
is ALWAYS_OFF
which means - Always initialize the fan as OFF on bootup.
IMHO Initialize as OFF is not a same as turn it OFF. That is a reason of not calling on_turn_off
.
I just realized that I got the boot priority the wrong way around. The final version works without quirks and probably the least amount of lambdas.
esphome:
name: cabinet
friendly_name: Cabinet
on_boot:
priority: 400
then:
- script.execute: fan_operate
esp32:
board: esp32dev
framework:
type: arduino
number:
- platform: template
id: fan_on_min
name: "Fan On Minutes"
optimistic: true
restore_value: true
min_value: 5
max_value: 240
step: 5
initial_value: 60
icon: "mdi:timer"
- platform: template
id: fan_off_min
name: "Fan Off Minutes"
optimistic: true
restore_value: true
min_value: 5
max_value: 240
step: 5
initial_value: 120
icon: "mdi:timer"
script:
- id: fan_operate
mode: restart
then:
- while:
condition:
switch.is_on: fan_auto
then:
- fan.turn_on: fan1
- delay: !lambda "return id(fan_on_min).state * 60000.0;"
- if:
condition:
switch.is_on: fan_auto
then:
- fan.turn_off: fan1
- delay: !lambda "return id(fan_off_min).state * 60000.0;"
binary_sensor:
- platform: gpio
name: "Fan Button"
pin:
number: GPIO18
mode:
input: true
pullup: true
filters:
- invert:
- delayed_on: 10ms
- delayed_off: 10ms
on_press:
then:
- fan.toggle: fan1
switch:
- platform: template
id: fan_auto
name: "Fan Automation"
optimistic: true
icon: "mdi:fan-clock"
restore_mode: RESTORE_DEFAULT_ON
on_turn_on:
- script.execute: fan_operate
output:
- platform: gpio
id: gpio_fan
pin: GPIO14
fan:
- platform: binary
id: fan1
name: "Fan"
output: gpio_fan
Many Greetings!
Remo
1 Like