mirror of
https://github.com/home-assistant/frontend.git
synced 2026-07-31 03:18:22 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e0b93c2cd4 | |||
| 86f459d2f7 | |||
| 62089c1649 | |||
| c6565d6d76 | |||
| e5e6b6f28f | |||
| 73ea61395a |
@@ -1,4 +1,6 @@
|
||||
import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import { isTiltOnly } from "../../data/cover";
|
||||
import { CoverEntityFeature } from "../../data/feature/cover_entity_feature";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
import { canToggleDomain } from "./can_toggle_domain";
|
||||
import { computeStateDomain } from "./compute_state_domain";
|
||||
@@ -26,6 +28,13 @@ export const canToggleState = (hass: HomeAssistant, stateObj: HassEntity) => {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Tilt-only covers toggle via toggle_cover_tilt, which requires both tilt features
|
||||
if (domain === "cover" && isTiltOnly(stateObj)) {
|
||||
return [CoverEntityFeature.OPEN_TILT, CoverEntityFeature.CLOSE_TILT].every(
|
||||
(f) => supportsFeature(stateObj, f)
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
domain in SPECIAL_TOGGLE_ACTIONS &&
|
||||
SPECIAL_TOGGLE_ACTIONS[domain].feature
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import { isTiltOnly } from "../../data/cover";
|
||||
import { CameraEntityFeature } from "../../data/feature/camera_entity_feature";
|
||||
import { ClimateEntityFeature } from "../../data/feature/climate_entity_feature";
|
||||
import { CoverEntityFeature } from "../../data/feature/cover_entity_feature";
|
||||
@@ -63,7 +65,15 @@ export const SPECIAL_TOGGLE_ACTIONS: Record<string, SpecialToggleAction> = {
|
||||
|
||||
// This function assumes that the passed domain can toggle, it may otherwise
|
||||
// return a service that does not exist.
|
||||
export const getToggleAction = (domain: string, onOff: boolean): string => {
|
||||
export const getToggleAction = (
|
||||
domain: string,
|
||||
onOff: boolean,
|
||||
stateObj?: HassEntity
|
||||
): string => {
|
||||
// Tilt-only covers don't support open_cover/close_cover
|
||||
if (domain === "cover" && stateObj && isTiltOnly(stateObj)) {
|
||||
return onOff ? "open_cover_tilt" : "close_cover_tilt";
|
||||
}
|
||||
return (
|
||||
SPECIAL_TOGGLE_ACTIONS[domain]?.[onOff ? "on" : "off"] ||
|
||||
SPECIAL_TOGGLE_ACTIONS[domain]?.["on"] ||
|
||||
|
||||
@@ -1,8 +1,21 @@
|
||||
import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import { isTiltOnly } from "../../data/cover";
|
||||
import { UNAVAILABLE, UNKNOWN } from "../../data/entity/entity";
|
||||
import { CoverEntityFeature } from "../../data/feature/cover_entity_feature";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
import { computeStateDomain } from "./compute_state_domain";
|
||||
import { getToggleAction } from "./get_toggle_action";
|
||||
import { supportsFeature } from "./supports-feature";
|
||||
|
||||
// Tilt-only covers can only stop their tilt, and may not support it at all
|
||||
const getStopAction = (stateObj: HassEntity): string | undefined => {
|
||||
if (!isTiltOnly(stateObj)) {
|
||||
return "stop_cover";
|
||||
}
|
||||
return supportsFeature(stateObj, CoverEntityFeature.STOP_TILT)
|
||||
? "stop_cover_tilt"
|
||||
: undefined;
|
||||
};
|
||||
|
||||
export const computeGroupEntitiesState = (states: HassEntity[]): string => {
|
||||
if (!states.length) {
|
||||
@@ -58,17 +71,29 @@ export const toggleGroupEntities = (
|
||||
|
||||
const isOn = state === "on" || state === "open";
|
||||
|
||||
let service = getToggleAction(domain, !isOn);
|
||||
if (domain === "cover") {
|
||||
if (state === "opening" || state === "closing") {
|
||||
// If the cover is opening or closing, we toggle it to stop it
|
||||
service = "stop_cover";
|
||||
// If the cover is opening or closing, we toggle it to stop it
|
||||
const stopping =
|
||||
domain === "cover" && (state === "opening" || state === "closing");
|
||||
|
||||
// The service can differ per entity, e.g. for tilt-only covers,
|
||||
// so group the entities by the service they need
|
||||
const entityIdsByService: Record<string, string[]> = {};
|
||||
states.forEach((stateObj) => {
|
||||
const service = stopping
|
||||
? getStopAction(stateObj)
|
||||
: getToggleAction(domain, !isOn, stateObj);
|
||||
if (!service) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!(service in entityIdsByService)) {
|
||||
entityIdsByService[service] = [];
|
||||
}
|
||||
entityIdsByService[service].push(stateObj.entity_id);
|
||||
});
|
||||
|
||||
const entitiesIds = states.map((stateObj) => stateObj.entity_id);
|
||||
|
||||
hass.callService(domain, service, {
|
||||
entity_id: entitiesIds,
|
||||
Object.entries(entityIdsByService).forEach(([service, entityIds]) => {
|
||||
hass.callService(domain, service, {
|
||||
entity_id: entityIds,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -128,7 +128,7 @@ export class HaEntityToggle extends LitElement {
|
||||
|
||||
const serviceDomain =
|
||||
stateDomain === "group" ? "homeassistant" : stateDomain;
|
||||
const service = getToggleAction(stateDomain, turnOn);
|
||||
const service = getToggleAction(stateDomain, turnOn, this.stateObj);
|
||||
|
||||
const currentState = this.stateObj;
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { STATES_OFF } from "../../../../common/const";
|
||||
import { computeDomain } from "../../../../common/entity/compute_domain";
|
||||
import { isTiltOnly } from "../../../../data/cover";
|
||||
import { UNKNOWN } from "../../../../data/entity/entity";
|
||||
import type { HomeAssistant, ServiceCallResponse } from "../../../../types";
|
||||
import { turnOnOffEntity } from "./turn-on-off-entity";
|
||||
|
||||
@@ -6,6 +9,20 @@ export const toggleEntity = (
|
||||
hass: HomeAssistant,
|
||||
entityId: string
|
||||
): Promise<ServiceCallResponse> => {
|
||||
const turnOn = STATES_OFF.includes(hass.states[entityId].state);
|
||||
const stateObj = hass.states[entityId];
|
||||
|
||||
// Tilt-only covers may not report a state to pick a direction from,
|
||||
// let core pick one based on the tilt position instead.
|
||||
if (
|
||||
computeDomain(entityId) === "cover" &&
|
||||
isTiltOnly(stateObj) &&
|
||||
stateObj.state === UNKNOWN
|
||||
) {
|
||||
return hass.callService("cover", "toggle_cover_tilt", {
|
||||
entity_id: entityId,
|
||||
});
|
||||
}
|
||||
|
||||
const turnOn = STATES_OFF.includes(stateObj.state);
|
||||
return turnOnOffEntity(hass, entityId, turnOn);
|
||||
};
|
||||
|
||||
@@ -8,27 +8,31 @@ export const turnOnOffEntities = (
|
||||
entityIds: string[],
|
||||
turnOn = true
|
||||
): void => {
|
||||
const domainsToCall = {};
|
||||
const callsToMake: Record<
|
||||
string,
|
||||
{ domain: string; service: string; entityIds: string[] }
|
||||
> = {};
|
||||
entityIds.forEach((entityId) => {
|
||||
if (STATES_OFF.includes(hass.states[entityId].state) === turnOn) {
|
||||
const stateObj = hass.states[entityId];
|
||||
if (STATES_OFF.includes(stateObj.state) === turnOn) {
|
||||
const stateDomain = computeDomain(entityId);
|
||||
// Entities with non-standard toggle action need separate calls
|
||||
const serviceDomain =
|
||||
const domain =
|
||||
getToggleAction(stateDomain, true) !== "turn_on"
|
||||
? stateDomain
|
||||
: "homeassistant";
|
||||
// The service can differ per entity, e.g. for tilt-only covers
|
||||
const service = getToggleAction(domain, turnOn, stateObj);
|
||||
|
||||
if (!(serviceDomain in domainsToCall)) {
|
||||
domainsToCall[serviceDomain] = [];
|
||||
const key = `${domain}.${service}`;
|
||||
if (!(key in callsToMake)) {
|
||||
callsToMake[key] = { domain, service, entityIds: [] };
|
||||
}
|
||||
domainsToCall[serviceDomain].push(entityId);
|
||||
callsToMake[key].entityIds.push(entityId);
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(domainsToCall).forEach((domain) => {
|
||||
const service = getToggleAction(domain, turnOn);
|
||||
|
||||
const entities = domainsToCall[domain];
|
||||
hass.callService(domain, service, { entity_id: entities });
|
||||
Object.values(callsToMake).forEach(({ domain, service, entityIds: ids }) => {
|
||||
hass.callService(domain, service, { entity_id: ids });
|
||||
});
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ export const turnOnOffEntity = (
|
||||
const stateDomain = computeDomain(entityId);
|
||||
const serviceDomain = stateDomain === "group" ? "homeassistant" : stateDomain;
|
||||
|
||||
const service = getToggleAction(stateDomain, turnOn);
|
||||
const service = getToggleAction(stateDomain, turnOn, hass.states[entityId]);
|
||||
|
||||
return hass.callService(serviceDomain, service, { entity_id: entityId });
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@ import { assert, describe, it } from "vitest";
|
||||
|
||||
import { canToggleState } from "../../../src/common/entity/can_toggle_state";
|
||||
import { ClimateEntityFeature } from "../../../src/data/climate";
|
||||
import { CoverEntityFeature } from "../../../src/data/feature/cover_entity_feature";
|
||||
|
||||
describe("canToggleState", () => {
|
||||
const hass: any = {
|
||||
@@ -66,6 +67,39 @@ describe("canToggleState", () => {
|
||||
assert.isFalse(canToggleState(hass, stateObj));
|
||||
});
|
||||
|
||||
it("Detects cover with toggle", () => {
|
||||
const stateObj: any = {
|
||||
entity_id: "cover.bla",
|
||||
attributes: {
|
||||
supported_features: CoverEntityFeature.OPEN + CoverEntityFeature.CLOSE,
|
||||
},
|
||||
};
|
||||
assert.isTrue(canToggleState(hass, stateObj));
|
||||
});
|
||||
|
||||
it("Detects tilt-only cover with toggle", () => {
|
||||
const stateObj: any = {
|
||||
entity_id: "cover.bla",
|
||||
attributes: {
|
||||
supported_features:
|
||||
CoverEntityFeature.OPEN_TILT +
|
||||
CoverEntityFeature.CLOSE_TILT +
|
||||
CoverEntityFeature.SET_TILT_POSITION,
|
||||
},
|
||||
};
|
||||
assert.isTrue(canToggleState(hass, stateObj));
|
||||
});
|
||||
|
||||
it("Detects tilt-only cover without toggle", () => {
|
||||
const stateObj: any = {
|
||||
entity_id: "cover.bla",
|
||||
attributes: {
|
||||
supported_features: CoverEntityFeature.STOP_TILT,
|
||||
},
|
||||
};
|
||||
assert.isFalse(canToggleState(hass, stateObj));
|
||||
});
|
||||
|
||||
it("Detects group with missing entity", () => {
|
||||
const stateObj: any = {
|
||||
entity_id: "group.bla",
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import { getToggleAction } from "../../../src/common/entity/get_toggle_action";
|
||||
import { CoverEntityFeature } from "../../../src/data/feature/cover_entity_feature";
|
||||
|
||||
describe("getToggleAction", () => {
|
||||
it("Uses turn_on/turn_off for default domains", () => {
|
||||
assert.strictEqual(getToggleAction("light", true), "turn_on");
|
||||
assert.strictEqual(getToggleAction("light", false), "turn_off");
|
||||
});
|
||||
|
||||
it("Uses open_cover/close_cover for covers without a state object", () => {
|
||||
assert.strictEqual(getToggleAction("cover", true), "open_cover");
|
||||
assert.strictEqual(getToggleAction("cover", false), "close_cover");
|
||||
});
|
||||
|
||||
it("Uses open_cover/close_cover for covers supporting open/close", () => {
|
||||
const stateObj: any = {
|
||||
entity_id: "cover.bla",
|
||||
attributes: {
|
||||
supported_features:
|
||||
CoverEntityFeature.OPEN +
|
||||
CoverEntityFeature.CLOSE +
|
||||
CoverEntityFeature.OPEN_TILT +
|
||||
CoverEntityFeature.CLOSE_TILT,
|
||||
},
|
||||
};
|
||||
assert.strictEqual(getToggleAction("cover", true, stateObj), "open_cover");
|
||||
assert.strictEqual(
|
||||
getToggleAction("cover", false, stateObj),
|
||||
"close_cover"
|
||||
);
|
||||
});
|
||||
|
||||
it("Uses tilt services for tilt-only covers", () => {
|
||||
const stateObj: any = {
|
||||
entity_id: "cover.bla",
|
||||
state: "open",
|
||||
attributes: {
|
||||
supported_features:
|
||||
CoverEntityFeature.OPEN_TILT +
|
||||
CoverEntityFeature.CLOSE_TILT +
|
||||
CoverEntityFeature.SET_TILT_POSITION,
|
||||
},
|
||||
};
|
||||
assert.strictEqual(
|
||||
getToggleAction("cover", true, stateObj),
|
||||
"open_cover_tilt"
|
||||
);
|
||||
assert.strictEqual(
|
||||
getToggleAction("cover", false, stateObj),
|
||||
"close_cover_tilt"
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,101 @@
|
||||
import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { toggleGroupEntities } from "../../../src/common/entity/group_entities";
|
||||
import { CoverEntityFeature } from "../../../src/data/feature/cover_entity_feature";
|
||||
import type { HomeAssistant } from "../../../src/types";
|
||||
|
||||
const cover = (
|
||||
entityId: string,
|
||||
state: string,
|
||||
supportedFeatures: number
|
||||
): HassEntity =>
|
||||
({
|
||||
entity_id: entityId,
|
||||
state,
|
||||
attributes: { supported_features: supportedFeatures },
|
||||
}) as HassEntity;
|
||||
|
||||
const TILT_ONLY =
|
||||
CoverEntityFeature.OPEN_TILT +
|
||||
CoverEntityFeature.CLOSE_TILT +
|
||||
CoverEntityFeature.STOP_TILT;
|
||||
const OPEN_CLOSE = CoverEntityFeature.OPEN + CoverEntityFeature.CLOSE;
|
||||
|
||||
const mockHass = () => {
|
||||
const callService = vi.fn();
|
||||
return { hass: { callService } as unknown as HomeAssistant, callService };
|
||||
};
|
||||
|
||||
describe("toggleGroupEntities", () => {
|
||||
it("Uses tilt services for a group of tilt-only covers", () => {
|
||||
const { hass, callService } = mockHass();
|
||||
toggleGroupEntities(hass, [cover("cover.tilt", "closed", TILT_ONLY)]);
|
||||
|
||||
expect(callService).toHaveBeenCalledOnce();
|
||||
expect(callService).toHaveBeenCalledWith("cover", "open_cover_tilt", {
|
||||
entity_id: ["cover.tilt"],
|
||||
});
|
||||
});
|
||||
|
||||
it("Splits the call when a group mixes tilt-only and regular covers", () => {
|
||||
const { hass, callService } = mockHass();
|
||||
toggleGroupEntities(hass, [
|
||||
cover("cover.regular", "closed", OPEN_CLOSE),
|
||||
cover("cover.tilt", "closed", TILT_ONLY),
|
||||
]);
|
||||
|
||||
expect(callService).toHaveBeenCalledTimes(2);
|
||||
expect(callService).toHaveBeenCalledWith("cover", "open_cover", {
|
||||
entity_id: ["cover.regular"],
|
||||
});
|
||||
expect(callService).toHaveBeenCalledWith("cover", "open_cover_tilt", {
|
||||
entity_id: ["cover.tilt"],
|
||||
});
|
||||
});
|
||||
|
||||
it("Stops the tilt of tilt-only covers", () => {
|
||||
const { hass, callService } = mockHass();
|
||||
toggleGroupEntities(hass, [
|
||||
cover("cover.regular", "opening", OPEN_CLOSE),
|
||||
cover("cover.tilt", "closed", TILT_ONLY),
|
||||
]);
|
||||
|
||||
expect(callService).toHaveBeenCalledTimes(2);
|
||||
expect(callService).toHaveBeenCalledWith("cover", "stop_cover", {
|
||||
entity_id: ["cover.regular"],
|
||||
});
|
||||
expect(callService).toHaveBeenCalledWith("cover", "stop_cover_tilt", {
|
||||
entity_id: ["cover.tilt"],
|
||||
});
|
||||
});
|
||||
|
||||
it("Skips tilt-only covers that can't stop", () => {
|
||||
const { hass, callService } = mockHass();
|
||||
toggleGroupEntities(hass, [
|
||||
cover("cover.regular", "opening", OPEN_CLOSE),
|
||||
cover(
|
||||
"cover.tilt",
|
||||
"closed",
|
||||
CoverEntityFeature.OPEN_TILT + CoverEntityFeature.CLOSE_TILT
|
||||
),
|
||||
]);
|
||||
|
||||
expect(callService).toHaveBeenCalledOnce();
|
||||
expect(callService).toHaveBeenCalledWith("cover", "stop_cover", {
|
||||
entity_id: ["cover.regular"],
|
||||
});
|
||||
});
|
||||
|
||||
it("Uses a single call for a group of regular covers", () => {
|
||||
const { hass, callService } = mockHass();
|
||||
toggleGroupEntities(hass, [
|
||||
cover("cover.one", "open", OPEN_CLOSE),
|
||||
cover("cover.two", "open", OPEN_CLOSE),
|
||||
]);
|
||||
|
||||
expect(callService).toHaveBeenCalledOnce();
|
||||
expect(callService).toHaveBeenCalledWith("cover", "close_cover", {
|
||||
entity_id: ["cover.one", "cover.two"],
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,64 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { CoverEntityFeature } from "../../../../../src/data/feature/cover_entity_feature";
|
||||
import { toggleEntity } from "../../../../../src/panels/lovelace/common/entity/toggle-entity";
|
||||
import type { HomeAssistant } from "../../../../../src/types";
|
||||
|
||||
const TILT_ONLY = CoverEntityFeature.OPEN_TILT + CoverEntityFeature.CLOSE_TILT;
|
||||
|
||||
const mockHass = (state: string, supportedFeatures = TILT_ONLY) => {
|
||||
const callService = vi.fn();
|
||||
return {
|
||||
hass: {
|
||||
states: {
|
||||
"cover.tilt": {
|
||||
entity_id: "cover.tilt",
|
||||
state,
|
||||
attributes: { supported_features: supportedFeatures },
|
||||
},
|
||||
},
|
||||
callService,
|
||||
} as unknown as HomeAssistant,
|
||||
callService,
|
||||
};
|
||||
};
|
||||
|
||||
describe("toggleEntity", () => {
|
||||
it("Opens the tilt of a closed tilt-only cover", () => {
|
||||
const { hass, callService } = mockHass("closed");
|
||||
toggleEntity(hass, "cover.tilt");
|
||||
|
||||
expect(callService).toHaveBeenCalledWith("cover", "open_cover_tilt", {
|
||||
entity_id: "cover.tilt",
|
||||
});
|
||||
});
|
||||
|
||||
it("Closes the tilt of an open tilt-only cover", () => {
|
||||
const { hass, callService } = mockHass("open");
|
||||
toggleEntity(hass, "cover.tilt");
|
||||
|
||||
expect(callService).toHaveBeenCalledWith("cover", "close_cover_tilt", {
|
||||
entity_id: "cover.tilt",
|
||||
});
|
||||
});
|
||||
|
||||
it("Lets core pick the direction when the tilt-only cover state is unknown", () => {
|
||||
const { hass, callService } = mockHass("unknown");
|
||||
toggleEntity(hass, "cover.tilt");
|
||||
|
||||
expect(callService).toHaveBeenCalledWith("cover", "toggle_cover_tilt", {
|
||||
entity_id: "cover.tilt",
|
||||
});
|
||||
});
|
||||
|
||||
it("Uses open/close for covers supporting it", () => {
|
||||
const { hass, callService } = mockHass(
|
||||
"closed",
|
||||
CoverEntityFeature.OPEN + CoverEntityFeature.CLOSE
|
||||
);
|
||||
toggleEntity(hass, "cover.tilt");
|
||||
|
||||
expect(callService).toHaveBeenCalledWith("cover", "open_cover", {
|
||||
entity_id: "cover.tilt",
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,83 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { CoverEntityFeature } from "../../../../../src/data/feature/cover_entity_feature";
|
||||
import { turnOnOffEntities } from "../../../../../src/panels/lovelace/common/entity/turn-on-off-entities";
|
||||
import type { HomeAssistant } from "../../../../../src/types";
|
||||
|
||||
const TILT_ONLY = CoverEntityFeature.OPEN_TILT + CoverEntityFeature.CLOSE_TILT;
|
||||
const OPEN_CLOSE = CoverEntityFeature.OPEN + CoverEntityFeature.CLOSE;
|
||||
|
||||
const mockHass = (states: Record<string, any>) => {
|
||||
const callService = vi.fn();
|
||||
return {
|
||||
hass: { states, callService } as unknown as HomeAssistant,
|
||||
callService,
|
||||
};
|
||||
};
|
||||
|
||||
describe("turnOnOffEntities", () => {
|
||||
it("Batches standard domains into a single homeassistant call", () => {
|
||||
const { hass, callService } = mockHass({
|
||||
"light.one": { entity_id: "light.one", state: "off", attributes: {} },
|
||||
"switch.two": { entity_id: "switch.two", state: "off", attributes: {} },
|
||||
});
|
||||
turnOnOffEntities(hass, ["light.one", "switch.two"], true);
|
||||
|
||||
expect(callService).toHaveBeenCalledOnce();
|
||||
expect(callService).toHaveBeenCalledWith("homeassistant", "turn_on", {
|
||||
entity_id: ["light.one", "switch.two"],
|
||||
});
|
||||
});
|
||||
|
||||
it("Uses tilt services for tilt-only covers", () => {
|
||||
const { hass, callService } = mockHass({
|
||||
"cover.tilt": {
|
||||
entity_id: "cover.tilt",
|
||||
state: "closed",
|
||||
attributes: { supported_features: TILT_ONLY },
|
||||
},
|
||||
});
|
||||
turnOnOffEntities(hass, ["cover.tilt"], true);
|
||||
|
||||
expect(callService).toHaveBeenCalledOnce();
|
||||
expect(callService).toHaveBeenCalledWith("cover", "open_cover_tilt", {
|
||||
entity_id: ["cover.tilt"],
|
||||
});
|
||||
});
|
||||
|
||||
it("Splits the call when covers need different services", () => {
|
||||
const { hass, callService } = mockHass({
|
||||
"cover.regular": {
|
||||
entity_id: "cover.regular",
|
||||
state: "closed",
|
||||
attributes: { supported_features: OPEN_CLOSE },
|
||||
},
|
||||
"cover.tilt": {
|
||||
entity_id: "cover.tilt",
|
||||
state: "closed",
|
||||
attributes: { supported_features: TILT_ONLY },
|
||||
},
|
||||
});
|
||||
turnOnOffEntities(hass, ["cover.regular", "cover.tilt"], true);
|
||||
|
||||
expect(callService).toHaveBeenCalledTimes(2);
|
||||
expect(callService).toHaveBeenCalledWith("cover", "open_cover", {
|
||||
entity_id: ["cover.regular"],
|
||||
});
|
||||
expect(callService).toHaveBeenCalledWith("cover", "open_cover_tilt", {
|
||||
entity_id: ["cover.tilt"],
|
||||
});
|
||||
});
|
||||
|
||||
it("Skips entities already in the requested state", () => {
|
||||
const { hass, callService } = mockHass({
|
||||
"light.on": { entity_id: "light.on", state: "on", attributes: {} },
|
||||
"light.off": { entity_id: "light.off", state: "off", attributes: {} },
|
||||
});
|
||||
turnOnOffEntities(hass, ["light.on", "light.off"], true);
|
||||
|
||||
expect(callService).toHaveBeenCalledOnce();
|
||||
expect(callService).toHaveBeenCalledWith("homeassistant", "turn_on", {
|
||||
entity_id: ["light.off"],
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user