Custom Intent - Fan Speed

Hey folks,

As the username implies, I’m not a programmer. I have been trying and researching for a few days now to create a custom intent to turn on Z-wave fans with a high, medium, and low setting using the voice satellite area. I think I’m close (maybe not), but I just can’t figure out how to get the pieces flowing together. Any help would be greatly appreciated.

Here is what I have so far, in a file named "fan_speed_setting.yaml in /custom_sentences/en:

language: "en"
intents:
  HassFanSpeed:
    data:
      - sentences:
         - "(turn | set) [on] [the] {area} (fan | fans) (on | to) {speed}"
         - "(turn | set) [on] [the] (fan | fans) (on | to) {speed}"
        slots:
          domain: "fan"
          
lists:
  speed:
    values:
      - in: "high"
        out: "100%"
      - in: "medium"
        out: "66%"
      - in: "low"
        out: "33%"

In config.yaml I have the following intent script:

intent_script:
  HassFanSpeed:
    action:
      - service: "fan.turn_on"
        target:
          area_id: "{{area}}"
        data:
          percentage: "{{speed}}"
    speech:
      text: "Fan has been set to {{speed}} in the {{area}}."
1 Like

Please post your code as preformatted text (</> in the cogwheel toolbar). That way people can copy it to try it out.

Thanks for the tip, made necessary edits!

1 Like

Not sure why setting fan speed intent isn’t native… seems like a WTH moment…

I tried the above and get this result with assist : Received invalid slot info for HassFanSpeed

Even though the parser shows this:

intent:
  name: HassFanSpeed
slots:
  area: office
  speed: high
  domain: fan
details:
  area:
    name: area
    value: Office
    text: office
  speed:
    name: speed
    value: 100%
    text: high
  domain:
    name: domain
    value: fan
    text: ''
targets:
  fan.office_fan:
    matched: true
match: true
sentence_template: (turn | set) [on] [the] {area} (fan | fans) (on | to) {speed}
unmatched_slots: {}
source: custom
file: en/fan_speed_setting.yaml
1 Like

Did you solve for this?

I’ve landed here because voice control of fan speed has been impossible since I made the switch to VPE. I was about to enter a feature request but then I as I looked at the intents for cover, it seems like we’d be able to swap those guts out and make it work for fan. I really don’t want to create scripts for this (eight 10 speed fans) and I’m even willing to tinker with custom intents now that you’ve come this far, hopefully in the time since, you’ve found the right steps to make this possible.

Unfortunately no, even enlisted GPT for support and wasn’t able to solve it. Needs someone smarter than me to work it out!

Remove the percent sign from the speed value

Hi, I got yours to work with some slight modifications (and 1 piece that’s hardcoded). I have a few 3 speed fans that I can apply this to.

This is just a starting point that confirms the functionality works as configured.

In the custom sentence, I only made minor modifications to simplify until I got it working but I don’t think YOU need to change anything. I removed the % symbols but I honestly don’t know if it helped, I just assumed they’d cause issues when passed through downstream (if you look in automations/dev tools, the percentage is always just an integer never with the % symbol):

language: "en"
intents:
  HassFanSpeed:
    data:
      - sentences:
         - "(set) [the] {area} (fan) (to) {speed}"
         - "(set) [the] (fan) (to) {speed}"
        slots:
          domain: "fan"
          
lists:
  speed:
    values:
      - in: "high"
        out: "100"
      - in: "medium"
        out: "66"
      - in: "low"
        out: "33"

and the intent script which I simplified until I got it working but I DID make substantive changes that you’ll have to update to make it work. This is also the part where I hardcoded the entity, just so I could confirm it works:

intent_script:
  HassFanSpeed:
    action:
      - action: "fan.set_percentage"
        target:
          entity_id: fan.media_room_fan
        data:
          percentage: "{{speed}}"
    speech:
      text: "Fan has been set to {{speed}}"

Service was throwing errors in VScode for legacy syntax so I looked it up and it’s been changed to action and I also changed the service from fan.turn_on to fan.set_percentage because that’s what it looks like in automations/dev tools (you will need to change this). Changed from area id to entity id so I could hard code my fan.

I confirmed I can tell it to set media room fan to low/medium/high and it responds appropriately in action and speech. Obviously, I have my media room fan hardcoded in there for right this second but I’ve been at this a few hours already and I’m tired. Successful fan speed voice control was the goal and I’ve demonstrated that today.

What I’ll need to figure out/test:
Remove the hard coded entity and see if I can pass through the area and see if it will control the fan. If not, I need to look up how to do it (this is my first custom intent).
Figure out how to scale this for 10 speed fans. I saw some [<numeric_value_set>] that I think I should be able to pass through. I also found a range that might be useful if adapted properly:

language: "en"
intents:
  SetVolume:
    data:
      - sentences:
          - "(set|change) {media_player} volume to {volume} [percent]"
          - "(set|change) [the] volume for {media_player} to {volume} [percent]"
lists:
  media_player:
    values:
      - in: "living room"
        out: "media_player.living_room"
      - in: "bedroom"
        out: "media_player.bedroom"
  volume:
    range:
      from: 0
      to: 100

I’ll take another crack at it tomorrow and try to fill in the gaps. I’m pleased as punch that I can at least control 1 fan speed by voice already.

Thanks for the updates! Removing the percent sign was definitely a step in the right direction. If we can just figure out the area piece, this should be good to go. I’ll keep trying it out and update if any success.

Hi,

Sorry for the delay. Kylie Minogue came to town and I lost my mind for like a week.

I have refined this a little further to the point where the single fan is no longer hard coded and I can pass through all my 3 speed fans. While not EXACTLY what you want, we’re one step closer:

Custom sentence:

language: "en"
intents:
  HassFanSpeed:
    data:
      - sentences:
         - "(set) [the] {fan} (fan) (to) {speed}"
        slots:
          domain: "fan"
lists:
  speed:
    values:
      - in: "high"
        out: "100"
      - in: "medium"
        out: "66"
      - in: "low"
        out: "33"
      - in: "100"
        out: "100"
      - in: "50"
        out: "66"
      - in: "25"
        out: "33"
  fan:
    values:
      - in: "Media Room"
        out: "fan.media_room_fan"
      - in: "Bedroom Two"
        out: "fan.bedroom_2_fan"
      - in: "Garage"
        out: "fan.garage_fan"
      - in: "Den"
        out: "fan.den_fan"

Why do I have additional values like 100 translated to 100, 50 translated to 66, and 25 translated to 33? Because Amazon used to natively translate these values to the correct values and Home Assistant does not. The human behavior in my house is already pre-conditioned to say “set media room fan to 100” so I made it where it could be given a number or a fan speed nomenclature and it works either way"

Intent Script:

intent_script:
  HassFanSpeed:
    action:
      - action: "fan.set_percentage"
        target:
          entity_id: "{{fan}}"
        data:
          percentage: "{{speed}}"
          entity_id: "{{fan}}"
    speech:
      text: "Fan has been set to {{speed}}"

I tried to use {area} but I kept getting errors so this will have to do for now.

I’ll need to try to create custom intents for my 10 speed fans and my 8 speed fans. Now I see why Home Assistant didn’t do this on the first go around with fans (because many fans have different speeds making this wildly more complex).

Once I get that going, I can go back and try to figure out how to pass area through instead.