Skip to content

Instantly share code, notes, and snippets.

@quazzie
Last active April 12, 2021 17:54
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save quazzie/09ee3ef2c419ecbcf979a7410062481b to your computer and use it in GitHub Desktop.
Save quazzie/09ee3ef2c419ecbcf979a7410062481b to your computer and use it in GitHub Desktop.
esphome ifan02 cookbook info
#include "esphome.h"
using namespace esphome;
class IFan02Output : public Component, public FloatOutput {
public:
void write_state(float state) override {
if (state < 0.3) {
// OFF
digitalWrite(5, LOW);
digitalWrite(4, LOW);
digitalWrite(15, LOW);
} else if (state < 0.6) {
// low speed
digitalWrite(5, HIGH);
digitalWrite(4, LOW);
digitalWrite(15, LOW);
} else if (state < 0.9) {
// medium speed
digitalWrite(5, HIGH);
digitalWrite(4, HIGH);
digitalWrite(15, LOW);
} else {
// high speed
digitalWrite(5, HIGH);
digitalWrite(4, LOW);
digitalWrite(15, HIGH);
}
}
};
esphome:
name: ifan02
platform: ESP8266
board: esp8285
includes:
- ifan02.h
on_boot:
priority: 225
# turn off the light as early as possible
then:
- light.turn_off: ifan02_light
wifi:
ssid: <YOUR_SSID>
password: <YOUR_PASSWORD>
api:
logger:
ota:
binary_sensor:
- platform: gpio
id: vbutton_light
pin:
number: GPIO0
inverted: True
on_press:
then:
- light.toggle: ifan02_light
- platform: gpio
id: vbutton_relay_1
pin:
number: GPIO9
inverted: True
on_press:
then:
- switch.toggle: fan_relay1
- switch.turn_on: update_fan_speed
- platform: gpio
id: vbutton_relay_2
pin:
number: GPIO10
inverted: True
on_press:
then:
- switch.toggle: fan_relay2
- switch.turn_on: update_fan_speed
- platform: gpio
id: vbutton_relay_3
pin:
number: GPIO14
inverted: True
on_press:
then:
- switch.toggle: fan_relay3
- switch.turn_on: update_fan_speed
output:
- platform: custom
type: float
outputs:
id: fanoutput
lambda: |-
auto ifan02_fan = new IFan02Output();
App.register_component(ifan02_fan);
return {ifan02_fan};
- platform: gpio
pin: GPIO12
id: light_output
light:
- platform: binary
name: "iFan02 Light"
output: light_output
id: ifan02_light
switch:
- platform: template
id: update_fan_speed
optimistic: True
turn_on_action:
then:
- delay: 200ms
- if:
condition:
and:
- switch.is_off: fan_relay1
- switch.is_off: fan_relay2
- switch.is_off: fan_relay3
then:
- fan.turn_off: ifan02_fan
- if:
condition:
and:
- switch.is_on: fan_relay1
- switch.is_off: fan_relay2
- switch.is_off: fan_relay3
then:
- fan.turn_on:
id: ifan02_fan
speed: LOW
- if:
condition:
and:
- switch.is_on: fan_relay1
- switch.is_on: fan_relay2
- switch.is_off: fan_relay3
then:
- fan.turn_on:
id: ifan02_fan
speed: MEDIUM
- if:
condition:
and:
- switch.is_on: fan_relay1
- switch.is_off: fan_relay2
- switch.is_on: fan_relay3
then:
- fan.turn_on:
id: ifan02_fan
speed: HIGH
- switch.turn_off: update_fan_speed
- platform: gpio
pin: GPIO5
id: fan_relay1
- platform: gpio
pin: GPIO4
id: fan_relay2
- platform: gpio
pin: GPIO15
id: fan_relay3
fan:
- platform: speed
output: fanoutput
id: ifan02_fan
name: "iFan02 Fan"
@quazzie
Copy link
Author

quazzie commented Apr 3, 2019

Rev 1 -> 2 changed the lambdas to AND conditions

@DeeBeeKay
Copy link

Hi @quazzie, thanks for this code. I got it to compile with only one change: since you wrote this, esphome has reserved the word "light", and it can't be used as an id. Changing the lught's id to "light1" (or anything really) fixes that.

I have a new bug, though. The device powers on with the light turned on, no matter what I do. I don't care in the lounge, but it's a deal breaker for the kids bedroom. Any ideas?

@quazzie
Copy link
Author

quazzie commented Oct 2, 2019

@DeeBeeKay check esphome/esphome-docs#218
It's updated and has a "fix" for the light on power. It tries to shut it off as soon as possible.

@quazzie
Copy link
Author

quazzie commented Oct 2, 2019

This gist is now updated also.

@DeeBeeKay
Copy link

Thanks very much, you've written a neat piece of code. I tried a similar solution. but I see that the problem is the hardware.

For my needs, this means I can't use the ifan02 in my kids' bedroom. Will have to construct an IR emitter to control the existing fanlight instead. Oh well. :D

@rishabmehta7
Copy link

Hey guys I am new to this. I have a ESPhome addon setup with my home assistant. I also have a few sonoff basic programmed.
I am assuming ur yaml should be plug and play for my ifan02?
Where do i put the ifan02.h
Also does this give a speed control and light control with HA?
Also does it retain state (remember the on/off state of fan, speed of fan, state of light after a power cycle)?

@quazzie
Copy link
Author

quazzie commented Nov 19, 2019

ifan02.h in the same directory as the yaml file.
Yes speed and light control.
If you power cycle the fan or use the remote the state will change in HA.
It does not turn on fan if powercycle, ex. if the fan is on 2 and you powercycle the fan ha state will update to off for fan and on for light.
Light on because the hardware of ifan02 starts the light on bootup.

@rishabmehta7
Copy link

Thanks Tommy for replying so promptly,
Question, you turn off the light in your yaml right? probably after a few sec/micro sec?

Another question probably not related to your yaml, HA should have option to remember the last state on powercycle right? I am looking at a powercut which is very frequent in my area.

@quazzie
Copy link
Author

quazzie commented Nov 19, 2019

Yes my code turns off the light as soon as possible after a reboot. Ha state retain does not impact this. After reboot fan will be off.

@quazzie
Copy link
Author

quazzie commented Nov 19, 2019

You might be able to do something within espho e on boot to return to last state but I have not tried that.

@DeeBeeKay
Copy link

@rishabmehta7, here's the thing. @quazzie's excellent yaml file is designed to use native HA API, which is great for 99% of people because it's fast and just works.

But in your case, you have many power failures and you need the fan to remember the last state. This is much more easily done using the old MQTT method of connecting to HA. This is because the MQTT broker stores the last state of everything, so when you recover from a power loss, restoring the last state is baked into the protocol - you don't need to think about how to achieve it.

I love ESPHome very much, but I do acknowledge that restoring the last state often doesn't work as well using HA API as it did using MQTT.

So for you, @rishabmehta7, I think MQTT will work best. If you don't already have an MQTT broker set up, it is very easy to do from HomeAssistant Integrations page - just select the big + to add new integration and select Mosquitto broker. You will need to google for tutorials to understand MQTT setup, it's beyond the scope of this post.

Once you have an MQTT broker in HA, you could modify @quazzie's YAML file to use MQTT connection instead of HA API (MQTT is still supported by ESPHome, it's just not included by default).

Or else, you could flash the latest Tasmota binary firmware instead, which has an option for the iFan02, and is already set up for MQTT out of the box. I would point you to the excellent YouTube channel of Dr Zzs, he has many tutorials for configuring Sonoff devices with MQTT.

Best of luck!

@quazzie
Copy link
Author

quazzie commented Nov 20, 2019

Great tip @DeeBeeKay

@rishabmehta7
Copy link

Thanks @DeeBeeKay And @quazzie

I will try setting up MQTT and report my results here. Thanks for all the help.

I would prefer ESPHome over Tasmota just for the ease of OTA update.

@rishabmehta7
Copy link

Hey @DeeBeeKay and @quazzie

I successfully flashed my iFan02 with a slightly modified form of the code here. I added 2 buttons on Rx and Tx pin for light (click to toggle) and one for fan (long press to turn off, 1 tap 2 tap or 3 tap for speed). It works amazingly. But I couldn't figure out the MQTT part, I just assumed, removing api and adding mqtt from yaml would make it work. But i guess thats not the case.
I think I will learn the mqtt side of things and set it up later.

Thanks for all the help

@DeeBeeKay
Copy link

Hi @rishabmehta7. I'm glad things are working out for you.

Unfortunately, MQTT is a little more complicated than simply swapping API for MQTT. Explaining the MQTT protocol is a little outside my paygrade; but there really are lots of very helpful videos on youtube by people more clever than I am.

But basically, here's how it works in a nutshell. With MQTT, devices don't talk directly to each other. Instead, they all talk to one central MQTT broker, a server component that manages these conversations in Topics - very much like threads here on github. Devices can post into topics, but they can also subscribe to topics, to be notified about changes.

So you need to be running a Broker, and there's one in the Integrations list of Home Assistant, called Mosquitto.

You can think of the broker like a bulletin board, and the devices are all posting into their own threads. So your fan might have a thread on the broker called house\lounge\fan1. When it turns on, it makes a post in the thread saying, "hey guys, I'm turning on now".

If you have a power failure, then when the power comes back on, everything that uses MQTT gets reset back to whatever the last post in each thread was.

Long story short, every device (like your fan) needs to be configured with its own Topic, and you will also need to define what messages, when posted to that topic, will be used to turn things on and off.

This is kind of why I suggested using Tasmota for this, not just because it already has iFan compatibility built in, but because it comes pre-configured with MQTT, so you just need to give the fan a topic name in the Tasmota settings window. After that, you enable discovery (HA discovery is not on by default in Tasmota), and HA will just pick it up after a few minutes.

Best of luck!

@CallMeAreks
Copy link

CallMeAreks commented Apr 14, 2020

Sometimes when I have a power outage it takes a really long time for the fan to be available in home assistant and sadly I have to bear with the heat until it comes back which annoys the hell out of my girlfriend. How can I make it turn on in high at boot? That way after a power outage at least I have it working until it comes online again. @quazzie

I think I can add it like this :

  on_boot:
    priority: 225
    # turn off the light as early as possible
    then:
      - light.turn_off: light_relay
      - switch.turn_on: fan_relay1
      - switch.turn_on: fan_relay3

But I'm unsure whether I need to do anything with update_fan_speed or not.

EDIT:

Ok I think I figured it out. For people that want to turn the fan on right after boot:

esphome:
  name: bedroom_fan
  platform: ESP8266
  board: esp8285
  includes:
    - ifan02.h
  on_boot:
    priority: 225
    # turn off the light as early as possible
    then:
      - light.turn_off: light_relay
      - switch.turn_on: fan_relay1
      - switch.turn_on: fan_relay3

The relevant parts are the relay1 and 3 being turned on at boot. That turns the fan at high speed but doesn't update home assistant.

From here there are two options. Either you add switch.turn_on: update_fan_speed at the bottomof the on_boot actions (which in my case it doesn't work because in case of a power outage HA isn't available yet due to the router being resetting), or find another place to make the update. I opted for the latter:

For that I added a binary sensor of platform status and made the on_state event check if the API is connected and then push the update to HA.

  - platform: status
    id: node_status
    on_state:
      if:
        condition:
          api.connected:
        then:
          - switch.turn_on: update_fan_speed

@docvipul
Copy link

'esp8266_restore_from_flash' option can help to restore settings after power failure and 'api.connected' condition can be used to prevent the early turning on of light component. Has anyone succeded in turing this code 'power failure resistant'?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment