Lovelace Custom Fan Card Example

If I remember correctly I ran into some kind of issue using that code but I don’t know if that was it or not. But I’ve modified the code here and made it pretty customizable and it works really good.

If you’re interested see my post up above for a link to the thread about my control row which has the link to the code on github.

@finity Can you confirm whether your fan card works with 0.92. I’m fairly certain I have it set up correctly but I keep getting the dreaded Red Box of No Worky. Below is the code I have in my ui-lovelace.yaml. The card was RAW downloaded from github using wget and stored in the www/ folder.

resources
- url: /local/fan-control-entity-row.js
  type: js 

- type: entities
  title: Fans
  show_header_toggle: false
  entities:
  - entity: fan.master_bedroom_fan
    type: custom:fan-contol-entity-row
    name: Master Bedroom
    customTheme: false

i haven’t updated to v92 yet and likely won’t for a few days until the dust settles on the new release.

ill let you know what i find then.

did you have it working before on an older version and now its not or is this the first version you tried it on?

This is the first time. I hadn’t updated since 0.88 so I was still running old fan button code.

ok. i’ll try to remember to let you know what i find when i update.

Used your yaml code for the fan (with off in quotes and not in quotes [I noticed when not in quotes its blue instead of orange]) and the json code on your link https://community.home-assistant.io/t/lovelace-fan-control-entity-row-split-from-the-other-topics/102952/3. Still same issue, the OFF button stays highlighted and is not selectable in HA. The HI, MED, and LOW buttons all work correctly.

Funny thing, is I also have HomeKit installed and it works correctly on my iPhone and iPad (turns on and off). So just HA/Lovelace is the issue.

I’m going to answer you in my other thread to prevent from jumbling up this thread any more with off (this) topic posts…

And I’ll do the same for @daphatty as well…

thank you!

it’s usefull code!

i’m customize to Xiaomi Airpurifier
silent / auto / favorite & on/off toggle

%EC%9D%B4%EB%AF%B8%EC%A7%80%203

Looks nice ! Is that possible to have your code about this Air Purifier ? thanks!

For my Xiaomi Airpurifier 2S code here.
save file name : custom-fan-card-xiaomiair.js
pickpick_1

class CustomFanCard extends Polymer.Element {

static get template() {
    return Polymer.html`
        <style is="custom-style" include="iron-flex iron-flex-alignment"></style>
        <style>
            :host {
                line-height: inherit;
            }
            .speed {
                min-width: 34px;
                max-width: 34px;
                height: 34px;
                margin-left: 2px;
                margin-right: 2px;
                background-color:'var(--dark-accent-color)';
	                border: 1px var(--dark-theme-disabled-color);  
                border-radius: 4px;
	                font-size: 11px !important;
                text-align: center;
	                float: right !important;
                padding: 1px;
                font-family : inherit;
		    }
				
        </style>
        <hui-generic-entity-row hass="[[hass]]" config="[[_config]]">
            <div class='horizontal justified layout' on-click="stopPropagation">
				    <button
                        class='speed'
                        style='[[_silOnColor]]'
                        toggles name="silent"
                        on-click='setSpeed'
                        disabled='[[_isOnSil]]'><ha-icon icon="mdi:power-sleep"></ha-icon></button>
                <button
                        class='speed'
                        style='[[_autoOnColor]]'
                        toggles name="auto"
                        on-click='setSpeed'
                        disabled='[[_isOnAuto]]'><ha-icon icon="mdi:brightness-auto"></ha-icon></button>
                <button
                        class='speed'
                        style='[[_favoOnColor]]'
                        toggles name="favorite"
                        on-click='setSpeed'
                        disabled='[[_isOnFavo]]'><ha-icon icon="mdi:fan"></ha-icon></button>
                <ha-entity-toggle hass="[[hass]]" state-obj="[[_stateObj]]"></ha-entity-toggle>

                </div>
        </hui-generic-entity-row>
    `;
}

static get properties() {
    return {
        hass: {
            type: Object,
            observer: 'hassChanged'
        },
        _config: Object,
        _stateObj: Object,
        _silOnColor: String,
        _autoOnColor: String,
        _favoOnColor: String,
        _offColor: String,
        _isOffState: Boolean,
        _isOnState: Boolean,
        _isOnSil: Boolean,
        _isOnAuto: Boolean,
        _isOnFavo: Boolean
    }
}

setConfig(config) {
    this._config = config;
}

hassChanged(hass) {

    const config = this._config;
    const stateObj = hass.states[config.entity];

    let speed;
    if (stateObj && stateObj) {
        speed = stateObj.state || 'off';
    }
		
    let sil;
	    let auto;
	    let favo;
	    let offstate;
		
	    if (stateObj && stateObj.attributes) {
	        if (stateObj.state == 'on' && stateObj.attributes.speed == 'Silent') {
		        sil = 'on';
		} else if (stateObj.state == 'on' && stateObj.attributes.speed == 'Auto') {
		        auto = 'on';
		} else if (stateObj.state == 'on' && stateObj.attributes.speed == 'Favorite') {
		        favo = 'on';
		} else {
			offstate = 'on';
		}
	}
		
    let silcolor;
    let autocolor;
	    let favocolor;
	    let offcolor;
		
	   if (sil == 'on') {
    silcolor = 'background-color: var(--dark-primary-color); color: white;';
} else { 
    silcolor = '';
}

if (auto == 'on') {
    autocolor = 'background-color: var(--dark-primary-color); color: white;';
} else {
    autocolor = '';
}

if (favo == 'on') {
    favocolor = 'background-color: var(--dark-primary-color); color: white;';
} else {
    favocolor = '';
}
	
if (offstate == 'on') {
    offcolor = 'background-color: var(--dark-primary-color); color: white;';
} else {
    offcolor = '';
}
		
	this.setProperties({
    _stateObj: stateObj,
	    _isOffState: stateObj.state == 'off',
    _isOnSil: sil === 'on',
	    _isOnAuto: auto === 'on',
	    _isOnFavo: favo === 'on',
	    _silOnColor: silcolor,
	    _autoOnColor: autocolor,
	    _favoOnColor: favocolor,
	    _offColor: offcolor
});
}

stopPropagation(e) {
    e.stopPropagation();
}

setSpeed(e) {
    const speed = e.currentTarget.getAttribute('name');
    this.hass.callService('fan', 'set_speed', {
        entity_id: this._config.entity, speed: speed
    });
}

}

customElements.define('custom-fan-card-xiaomiair', CustomFanCard);
2 Likes

Thanks I will try!

do u mind sharing how u got it done? I have 6 speed on my fan too and would like to achieve the same result

I have this

class CustomFanCard extends Polymer.Element {

    static get template() {
        return Polymer.html`
            <style is="custom-style" include="iron-flex iron-flex-alignment"></style>
            <style>
                :host {
                    line-height: 1.5;
                }
                .speed {
                    min-width: 30px;
                    max-width: 30px;
                    margin-left: 0px;
                    margin-right: 0px;
                }
                ha-entity-toggle {
                    margin-left: 16px;
                }
            </style>
            <hui-generic-entity-row hass="[[hass]]" config="[[_config]]">
                <div class='horizontal justified layout' on-click="stopPropagation">
                    <mwc-button
                        class='speed'
                        toggles name="1"
                        on-click='setSpeed'
                        disabled='[[_is1Speed]]'>1</mwc-button>
                    <mwc-button
                        class='speed'
                        toggles name="2"
                        on-click='setSpeed'
                        disabled='[[_is2Speed]]'>2</mwc-button>
                    <mwc-button
                        class='speed'
                        toggles name="3"
                        on-click='setSpeed'
                        disabled='[[_is3Speed]]'>3</mwc-button>
                    <mwc-button
                        class='speed'
                        toggles name="4"
                        on-click='setSpeed'
                        disabled='[[_is4Speed]]'>4</mwc-button>
                    <mwc-button
                        class='speed'
                        toggles name="5"
                        on-click='setSpeed'
                        disabled='[[_is5Speed]]'>5</mwc-button>
                    <mwc-button
                        class='speed'
                        toggles name="6"
                        on-click='setSpeed'
                        disabled='[[_is6Speed]]'>6</mwc-button>
                    <ha-entity-toggle hass="[[hass]]" state-obj="[[_stateObj]]"></ha-entity-toggle>
                </div>
            </hui-generic-entity-row>
        `;
    }

    static get properties() {
        return {
            hass: {
                type: Object,
                observer: 'hassChanged'
            },
            _config: Object,
            _stateObj: Object,
            _is1Speed: Boolean,
            _is2Speed: Boolean,
            _is3Speed: Boolean,
            _is4Speed: Boolean,
            _is5Speed: Boolean,
            _is6Speed: Boolean
        }
    }

    setConfig(config) {
        this._config = config;
    }

    hassChanged(hass) {

        const config = this._config;
        const stateObj = hass.states[config.entity];

        let speed;
        if (stateObj && stateObj.attributes) {
            speed = stateObj.attributes.speed || 'off';
        }

        this.setProperties({
            _stateObj: stateObj,
            _is1Speed: speed === '1',
            _is2Speed: speed === '2',
            _is3Speed: speed == '3',
            _is4Speed: speed == '4',
            _is5Speed: speed == '5',
            _is6Speed: speed == '6'
        });
    }

    stopPropagation(e) {
        e.stopPropagation();
    }

    setSpeed(e) {
        const speed = e.currentTarget.getAttribute('name');
        this.hass.callService('fan', 'set_speed', {
            entity_id: this._config.entity, speed: speed
        });
    }

}

customElements.define('custom-fan-card', CustomFanCard);

awesome… if i have 2 fans with 2 diff speed (4 and 9), do I have to create 2 separate custom component?

I don’t know. Have a try see how it goes. I have 4 6-speed only.

Has anyone got this working on .96 ?
I can get it to display, but the toggles dont work. If i change the speed elsewhere, the changes ARE reflected by the button being selected.

Not working for me either, popped here hoping someone else already fixed it ;/

It’s now working for me, but I’m not sure what I did.

I started fiddling with the surveillance card, did a couple of restarts, and then actually turned on the fan by accident!

Not overly helpful I know, but it does work.

had the same problem.
i add a line to the code and now it works fine:

class CustomFanCard extends Polymer.Element {

    static get template() {
        return Polymer.html`
            <style is="custom-style" include="iron-flex iron-flex-alignment"></style>
            <style>
                :host {
                    line-height: 1.5;
                }
                .speed {
                   min-width: 20px;
                   max-width: 85px;
                   margin-left: 2px;
                   margin-right: 2px;
                   float: right !important;  
                }
               </style>
            <hui-generic-entity-row hass="[[hass]]" config="[[_config]]">
                <div class='horizontal justified layout' on-click="stopPropagation">
                    <mwc-button
                        class='speed'
						style='[[_lowOnColor]]'
                        toggles name="low"
                        on-click='setSpeed'
                        disabled='[[_isonLow]]'>LOW</mwc-button>
                    <mwc-button
                        class='speed'
						style='[[_medOnColor]]'
                        toggles name="medium"
                        on-click='setSpeed'
                        disabled='[[_isonMed]]'>MED</mwc-button>
                    <mwc-button
                        class='speed'
						style='[[_highOnColor]]'
                        toggles name="high"
                        on-click='setSpeed'
                        disabled='[[_isonHigh]]'>HIGH</mwc-button>
				    <mwc-button
                        class='speed'
						style='[[_offColor]]'
                        toggles name="off"
                        on-click='setSpeed'
                        disabled='[[_isOffState]]'>OFF</mwc-button>
                </div>
            </hui-generic-entity-row>
        `;
    }

    static get properties() {
        return {
            hass: {
                type: Object,
                observer: 'hassChanged'
            },
            _config: Object,
            _stateObj: Object,
			_lowOnColor: String,
			_medOnColor: String,
			_highOnColor: String,
			_offColor: String,
            _isOffState: Boolean,
            _isOnState: Boolean,
            _isOnLow: Boolean,
            _isOnMed: Boolean,
            _isOnHigh: Boolean
        }
    }

    setConfig(config) {
        this._config = config;
    }

    hassChanged(hass) {

        const config = this._config;
        const stateObj = hass.states[config.entity];

        let speed;
        if (stateObj && stateObj.attributes) {
            speed = stateObj.attributes.speed || 'off';
        }
		
		let low;
		let med;
		let high;
		let offstate;
		
		if (stateObj && stateObj.attributes) {
		    if (stateObj.state == 'on' && stateObj.attributes.speed == 'low') {
			    low = 'on';
		    } else if (stateObj.state == 'on' && stateObj.attributes.speed == 'medium') {
			    med = 'on';
		    } else if (stateObj.state == 'on' && stateObj.attributes.speed == 'high') {
			    high = 'on';
		    } else {
				offstate = 'on';
			}
		}
		
        let lowcolor;
		let medcolor;
		let hicolor;
		let offcolor;
		
		if (low == 'on') {
			lowcolor = 'background-color: #43A047';
		} else {
			lowcolor = '';
		}
		
		if (med == 'on') {
			medcolor = 'background-color: #43A047';
		} else {
			medcolor = '';
		}
		
		if (high == 'on') {
			hicolor = 'background-color: #43A047';
		} else {
			hicolor = '';
		}
		
		if (offstate == 'on') {
			//offcolor = 'background-color: #43A047';
			offcolor = 'background-color: #f44c09';
		} else {
			offcolor = '';
		}
		
		this.setProperties({
            _stateObj: stateObj,
			_isOffState: stateObj.state == 'off',
            _isOnLow: low === 'on',
			_isOnMed: med === 'on',
			_isOnHigh: high === 'on',
			_lowOnColor: lowcolor,
			_medOnColor: medcolor,
			_highOnColor: hicolor,
			_offColor: offcolor
        });
    }

    stopPropagation(e) {
        e.stopPropagation();
    }

    setSpeed(e) {
        const speed = e.currentTarget.getAttribute('name');
        this.hass.callService('fan', 'turn_on', {
            entity_id: this._config.entity
        });
        this.hass.callService('fan', 'set_speed', {
            entity_id: this._config.entity, speed: speed
        });
    }


}

customElements.define('custom-fan-card', CustomFanCard);

does anyone know how to add oscillation button?

How does this play with Google assistant?