Need help with making a dumb fan smart

Thanks @123 and @BeyondRico! I tweaked it slightly to work with my fan that has separate + and - speed buttons. It works fine from HA.

Is there a way to get Google Assistant/Home to recognize the speed controls for voice control? It looks like there’s support for it, but it doesn’t seem to work. I’ve been trying “set the bedroom fan to speed 5” and “set the bedroom fan to maximum”.

Thanks!

Someone else will have to respond to your question because I don’t have any experience using Google Assistant with Home Assistant.

1 Like

Hey. Care to share your config for the desperate +/- buttons?

Hi,

Sorry for the late reply! This is what I did. Hope it makes sense to you, as I’ve forgotten what I did! :sweat_smile:

configuration.yaml

input_boolean:
  status_fan_power:
    name: Status Fan Power

input_text:
  status_fan_speed:
    name: Status Fan Speed

fan:
  - platform: template
    fans:
      bedroom_fan:
        friendly_name: "Bedroom Fan"
        value_template: "{{ states('input_boolean.status_fan_power') }}"
        speed_template: "{{ states('input_text.status_fan_speed') }}"
        speeds: ['1', '2', '3', '4', '5', '6', '7', '8', '9','10']
        turn_on:
          - condition: state
            entity_id: input_boolean.status_fan_power
            state: 'off'
          - service: broadlink.send
            data:
              host: '192.168.1.103'
              packet: 'JgAkAEobGTMbGhkbGTIbGhkaGRoZHBkbGRsZGhkbGRoZGhkyGgANBQAAAAA='
          - service: input_boolean.turn_on
            entity_id: input_boolean.status_fan_power
        turn_off:
          - service: broadlink.send
            data:
              host: '192.168.1.103'
              packet: 'JgAkAEobGTMbGhkbGTIbGhkaGRoZHBkbGRsZGhkbGRoZGhkyGgANBQAAAAA='
          - service: input_boolean.turn_off
            entity_id: input_boolean.status_fan_power
        set_speed:
          - service: python_script.fan_speed_control
            data_template:
              fan_speed: "{{ speed }}"
          - service: input_text.set_value
            data_template:
              entity_id: input_text.status_fan_speed
              value: "{{ speed }}"

I have been looking into Dialogflow for creating a custom section in google assistant. However did not go fully into it because of lack of time. Maybe this is something that could help you.

Just wanted to say A BIG THANK YOU because I finally managed to get the Template Fan to work (documentation is REALLY POOR on this component). The solution to this thread should be added to the example section of the Template Fan page.
Only problem I encountered is that for some reason sometimes the “else 1” part of the script didn’t work and since my fan always does a “clean” start with fan at 1 ad oscillation off I added this to the turn on part:

          - service: input_text.set_value
            data:
              entity_id: input_text.ventilatore_sala_fan_speed
              value: 1

Maybe it’s overkill for someone, but worked for me.

Some improvements I’d like to suggest:

  1. I’d make the script as much plug and play as possible. Isn’t it possible to get the number of speeds from the component (the length of the speeds array)?
  2. I’d make the broadlink part easier to setup, by using the alternative method to send commands:
- service: remote.send_command
            data:
              entity_id: remote.broadlink
              device: ventilatore
              command: speed

Doing so I’d only need to put the device and command name in the script, that should be easier than looking for the IP and the command string.

Now I’ll try to work on the script to make it work with oscillation modes, that are 4 in my fan (fixed, left/right, up/down and a mix of the two) while the Template only has on and off. I thinks that it can’t be done directly with the template but I’ll have to make some extra text_select and the automations to change it in cycle via the script.
Maybe if I succeed I’ll post the solution here.

OK, I added the oscillation mode as a separate input_select and here’s my solution:

1 setup input_select: First I define an input select containing the modes starting with a number (I extract the number in the script to cycle correctly, so this is mandatory):

input_select:

  ventilatore_sala_oscillation_mode:
    name: 'Ventilatore sala oscillazione'
    icon:  mdi:arrow-decision-outline
    options:
      - '1 - off'
      - '2 - destra sinistra'
      - '3 - su giù'
      - '4 - misto'

2. revert to 1 at every turno_on: Then in the Template Fan I add an action on turn_on so that the input_select is back to 1 at startup (remember that my fan start from fresh no oscillation, fan speed 1 at every startup - it may or may not be necessary for your setup but then I’d lock or hide the control when the fan is off), my full turn_on automation goes like this:

turn_on:
          - condition: state
            entity_id: input_boolean.ventilatore_sala_stato
            state: 'off'
          - service: remote.send_command
            data:
              entity_id: remote.broadlink
              device: ventilatore
              command: power
          - service: input_select.select_option
            data:
              entity_id: input_select.ventilatore_sala_oscillation_mode
              option: '1 - off'
          - service: input_boolean.turn_on
            entity_id: input_boolean.ventilatore_sala_stato
          - service: input_text.set_value
            data:
              entity_id: input_text.ventilatore_sala_fan_speed
              value: 1

I added the same automation on turn_off, even if it’s not necessary, but it’s a sort of “reset” when turning off.
3 - automate script launch when the input_select changes Then I setup an automation that feeds the script with the from and to state of input_select:

- id: '1598781094128'
  alias: Fan - modo oscillazione
  description: ''
  trigger:
  - entity_id: input_select.ventilatore_sala_oscillation_mode
    platform: state
  condition:
  - condition: state
    entity_id: fan.ventilatore_sala
    state: 'on'
  action:
  - data_template:
      oscillation_mode: '{{ trigger.to_state.state }}'
      oscillation_mode_from: '{{ trigger.from_state.state }}'
    service: python_script.fan_oscillation
  mode: single

**4 - The script: ** and finally the modified script goes like this, set broadlink IP, code and number of states in the input_select accordingly to your setup (I’m no python programmer so excuse if it’s not very clean code):

# Set code to whatever RF code your fan uses for oscillation mode.
code = 'JgByAJWUETERMRIxETERMRIxEVERMhExETESMRFREVESURExETIRMZaUETERMREyETERMRExElERMhExETERMRJREVERUhExETESAAGhAAEpSBMABo4AAShKEgAGjgABKEoRAAaPAAEnShIACPUGAAzFCAANBQAAAAA='

oscillation_raw = data.get('oscillation_mode')
status_oscillation_raw = data.get('oscillation_mode_from')
# status_oscillation_raw = hass.states.get('input_select.ventilatore_sala_oscillation_mode')

# extracting the first charachter that is the mode in numeric form
# maybe define an array and compare?
oscillation = oscillation_raw[0]
# logger.warning('to:'+ oscillation)
# logger.warning(oscillation_raw[0])
status_oscillation = status_oscillation_raw[0]
# logger.warning('from:' + status_oscillation)
# logger.warning(status_oscillation_raw[0])

if oscillation is not None:
  oscillation = int(oscillation)
  # last_oscillation = int(status_oscillation.state) if status_oscillation.state else 1
  last_oscillation = int(status_oscillation)
  if 1 <= oscillation <= 4:
    if oscillation > last_oscillation:
      loop = oscillation - last_oscillation
    else:
      loop = (4 - last_oscillation) + oscillation

    # Set the IP address to match the one used by your Broadlink device
    service_data = {'host':'192.168.0.195', 'packet':'{}'.format(code)}
    for i in range(loop):
      hass.services.call('broadlink', 'send', service_data, False)
      time.sleep(0.5)
  else:
    logger.warning('<fan_oscillation_control> Received fan oscillation is invalid ({})'.format(fan_oscillation))
else:
  logger.warning('<fan_oscillation_control> Received fan oscillation is invalid (None)')

All improvements are strongly welcome.
Thanks again to everyone that allowed me to get it to work.