Skip to content

Commit 7f4cc54

Browse files
authored
Add fan direction button to fan card (#1647)
* Added fan direction control * localization for direction control * fan-direction, removed active state, removed non english translations
1 parent 6809e63 commit 7f4cc54

File tree

7 files changed

+75
-3
lines changed

7 files changed

+75
-3
lines changed

.hass_dev/views/fan-view.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ cards:
4848
name: Multiple controls
4949
show_percentage_control: true
5050
show_oscillate_control: true
51+
show_direction_control: true
5152
- type: custom:mushroom-fan-card
5253
entity: fan.living_room_fan
5354
name: Collapsible controls
@@ -66,6 +67,7 @@ cards:
6667
entity: fan.living_room_fan
6768
show_percentage_control: true
6869
show_oscillate_control: true
70+
show_direction_control: true
6971
- type: grid
7072
columns: 2
7173
square: false
@@ -74,9 +76,11 @@ cards:
7476
entity: fan.living_room_fan
7577
show_percentage_control: true
7678
show_oscillate_control: true
79+
show_direction_control: true
7780
layout: "vertical"
7881
- type: custom:mushroom-fan-card
7982
entity: fan.living_room_fan
8083
show_percentage_control: true
8184
show_oscillate_control: true
85+
show_direction_control: true
8286
layout: "horizontal"

docs/cards/fan.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ All the options are available in the lovelace editor but you can use `yaml` if y
2424
| `icon_animation` | boolean | `false` | Animate the icon when fan is `on` |
2525
| `show_percentage_control` | boolean | `false` | Show a slider to control speed |
2626
| `show_oscillate_control` | boolean | `false` | Show a button to control oscillation |
27+
| `show_direction_control` | boolean | `false` | Show a button to control direction |
2728
| `collapsible_controls` | boolean | `false` | Collapse controls when off. When used if section, it can produce a layout shift for cards below |
2829
| `tap_action` | action | `toggle` | Home assistant action to perform on tap |
2930
| `hold_action` | action | `more-info` | Home assistant action to perform on hold |
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { HassEntity } from "home-assistant-js-websocket";
2+
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
3+
import { customElement, property } from "lit/decorators.js";
4+
import { classMap } from "lit/directives/class-map.js";
5+
import { HomeAssistant, isActive } from "../../../ha";
6+
import "../../../shared/slider";
7+
import { isOscillating } from "../utils";
8+
9+
@customElement("mushroom-fan-direction-control")
10+
export class FanPercentageControl extends LitElement {
11+
@property({ attribute: false }) public hass!: HomeAssistant;
12+
13+
@property({ attribute: false }) public entity!: HassEntity;
14+
15+
private _onTap(e: MouseEvent): void {
16+
e.stopPropagation();
17+
const currentDirection = this.entity.attributes.direction;
18+
const newDirection = currentDirection === "forward" ? "reverse" : "forward";
19+
20+
this.hass.callService("fan", "set_direction", {
21+
entity_id: this.entity.entity_id,
22+
direction: newDirection,
23+
});
24+
}
25+
26+
protected render(): TemplateResult {
27+
const currentDirection = this.entity.attributes.direction;
28+
const active = isActive(this.entity);
29+
30+
return html`
31+
<mushroom-button
32+
@click=${this._onTap}
33+
.disabled=${!active}
34+
>
35+
<ha-icon
36+
.icon=${currentDirection === "reverse"
37+
? "mdi:rotate-left"
38+
: "mdi:rotate-right"}
39+
></ha-icon>
40+
</mushroom-button>
41+
`;
42+
}
43+
44+
static get styles(): CSSResultGroup {
45+
return css`
46+
:host {
47+
display: flex;
48+
}
49+
`;
50+
}
51+
}

src/cards/fan-card/fan-card-config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export type FanCardConfig = LovelaceCardConfig &
2121
icon_animation?: boolean;
2222
show_percentage_control?: boolean;
2323
show_oscillate_control?: boolean;
24+
show_direction_control?: boolean;
2425
collapsible_controls?: boolean;
2526
};
2627

@@ -35,6 +36,7 @@ export const fanCardConfigStruct = assign(
3536
icon_animation: optional(boolean()),
3637
show_percentage_control: optional(boolean()),
3738
show_oscillate_control: optional(boolean()),
39+
show_direction_control: optional(boolean()),
3840
collapsible_controls: optional(boolean()),
3941
})
4042
);

src/cards/fan-card/fan-card-editor.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const FAN_LABELS = [
1616
"icon_animation",
1717
"show_percentage_control",
1818
"show_oscillate_control",
19+
"show_direction_control"
1920
];
2021

2122
const SCHEMA: HaFormSchema[] = [
@@ -40,6 +41,7 @@ const SCHEMA: HaFormSchema[] = [
4041
schema: [
4142
{ name: "show_percentage_control", selector: { boolean: {} } },
4243
{ name: "show_oscillate_control", selector: { boolean: {} } },
44+
{ name: "show_direction_control", selector: { boolean: {} } },
4345
{ name: "collapsible_controls", selector: { boolean: {} } },
4446
],
4547
},

src/cards/fan-card/fan-card.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import {
3939
FAN_ENTITY_DOMAINS,
4040
} from "./const";
4141
import "./controls/fan-oscillate-control";
42+
import "./controls/fan-direction-control";
4243
import "./controls/fan-percentage-control";
4344
import { FanCardConfig } from "./fan-card-config";
4445
import { getPercentage } from "./utils";
@@ -75,7 +76,8 @@ export class FanCard
7576
protected get hasControls(): boolean {
7677
return (
7778
Boolean(this._config?.show_percentage_control) ||
78-
Boolean(this._config?.show_oscillate_control)
79+
Boolean(this._config?.show_oscillate_control) ||
80+
Boolean(this._config?.show_direction_control)
7981
);
8082
}
8183

@@ -150,7 +152,8 @@ export class FanCard
150152
const displayControls =
151153
(!this._config.collapsible_controls || isActive(stateObj)) &&
152154
(this._config.show_percentage_control ||
153-
this._config.show_oscillate_control);
155+
this._config.show_oscillate_control ||
156+
this._config.show_direction_control);
154157

155158
return html`
156159
<ha-card
@@ -192,6 +195,14 @@ export class FanCard
192195
></mushroom-fan-oscillate-control>
193196
`
194197
: nothing}
198+
${this._config.show_direction_control
199+
? html`
200+
<mushroom-fan-direction-control
201+
.hass=${this.hass}
202+
.entity=${stateObj}
203+
></mushroom-fan-direction-control>
204+
`
205+
: nothing}
195206
</div>
196207
`
197208
: nothing}

src/translations/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@
6464
},
6565
"fan": {
6666
"show_percentage_control": "Percentage control?",
67-
"show_oscillate_control": "Oscillate control?"
67+
"show_oscillate_control": "Oscillate control?",
68+
"show_direction_control": "Direction control?"
6869
},
6970
"cover": {
7071
"show_buttons_control": "Control buttons?",

0 commit comments

Comments
 (0)