From 882c503fa92a1b39a9cca1530446d70c74cb4b4f Mon Sep 17 00:00:00 2001 From: Ian Richardson Date: Fri, 30 Nov 2018 09:37:44 -0600 Subject: [PATCH] Extract Supported features into own funciton (#2151) * External function to check if entity supports a feature * Typo * Update hass-media-player-model.js --- src/common/entity/can_toggle_state.ts | 4 +- src/common/entity/feature_class_names.ts | 6 +-- src/common/entity/supports-feature.ts | 9 +++++ .../more-info/controls/more-info-climate.js | 19 ++++----- .../more-info/controls/more-info-vacuum.js | 35 ++++++++-------- .../controls/more-info-water_heater.js | 7 ++-- .../hui-media-player-entity-row.ts | 15 +++---- src/util/cover-model.js | 40 +++++++++---------- src/util/hass-media-player-model.js | 30 +++++++------- 9 files changed, 81 insertions(+), 84 deletions(-) create mode 100644 src/common/entity/supports-feature.ts diff --git a/src/common/entity/can_toggle_state.ts b/src/common/entity/can_toggle_state.ts index 71a1b5d6c8..d990f363cb 100644 --- a/src/common/entity/can_toggle_state.ts +++ b/src/common/entity/can_toggle_state.ts @@ -2,6 +2,7 @@ import { HassEntity } from "home-assistant-js-websocket"; import canToggleDomain from "./can_toggle_domain"; import computeStateDomain from "./compute_state_domain"; import { HomeAssistant } from "../../types"; +import { supportsFeature } from "./supports-feature"; export default function canToggleState( hass: HomeAssistant, @@ -12,8 +13,7 @@ export default function canToggleState( return stateObj.state === "on" || stateObj.state === "off"; } if (domain === "climate") { - // tslint:disable-next-line - return (stateObj.attributes.supported_features! & 4096) !== 0; + return supportsFeature(stateObj, 4096); } return canToggleDomain(hass, domain); diff --git a/src/common/entity/feature_class_names.ts b/src/common/entity/feature_class_names.ts index d2d0cac26e..768e025a93 100644 --- a/src/common/entity/feature_class_names.ts +++ b/src/common/entity/feature_class_names.ts @@ -1,4 +1,5 @@ import { HassEntity } from "home-assistant-js-websocket"; +import { supportsFeature } from "./supports-feature"; // Expects classNames to be an object mapping feature-bit -> className export default function featureClassNames( @@ -9,12 +10,9 @@ export default function featureClassNames( return ""; } - const features = stateObj.attributes.supported_features; - return Object.keys(classNames) .map((feature) => - // tslint:disable-next-line - (features & Number(feature)) !== 0 ? classNames[feature] : "" + supportsFeature(stateObj, Number(feature)) ? classNames[feature] : "" ) .filter((attr) => attr !== "") .join(" "); diff --git a/src/common/entity/supports-feature.ts b/src/common/entity/supports-feature.ts new file mode 100644 index 0000000000..9aa833c035 --- /dev/null +++ b/src/common/entity/supports-feature.ts @@ -0,0 +1,9 @@ +import { HassEntity } from "home-assistant-js-websocket"; + +export const supportsFeature = ( + stateObj: HassEntity, + feature: number +): boolean => { + // tslint:disable-next-line:no-bitwise + return (stateObj.attributes.supported_features! & feature) !== 0; +}; diff --git a/src/dialogs/more-info/controls/more-info-climate.js b/src/dialogs/more-info/controls/more-info-climate.js index bde53875c2..27d29d228b 100644 --- a/src/dialogs/more-info/controls/more-info-climate.js +++ b/src/dialogs/more-info/controls/more-info-climate.js @@ -13,6 +13,7 @@ import "../../../components/ha-paper-slider"; import attributeClassNames from "../../../common/entity/attribute_class_names"; import featureClassNames from "../../../common/entity/feature_class_names"; +import { supportsFeature } from "../../../common/entity/supports-feature"; import EventsMixin from "../../../mixins/events-mixin"; import LocalizeMixin from "../../../mixins/localize-mixin"; @@ -385,45 +386,45 @@ class MoreInfoClimate extends LocalizeMixin(EventsMixin(PolymerElement)) { supportsTemperature(stateObj) { return ( - (stateObj.attributes.supported_features & 1) !== 0 && + supportsFeature(stateObj, 1) && typeof stateObj.attributes.temperature === "number" ); } supportsTemperatureRange(stateObj) { return ( - (stateObj.attributes.supported_features & 6) !== 0 && + supportsFeature(stateObj, 6) && (typeof stateObj.attributes.target_temp_low === "number" || typeof stateObj.attributes.target_temp_high === "number") ); } supportsHumidity(stateObj) { - return (stateObj.attributes.supported_features & 8) !== 0; + return supportsFeature(stateObj, 8); } supportsFanMode(stateObj) { - return (stateObj.attributes.supported_features & 64) !== 0; + return supportsFeature(stateObj, 64); } supportsOperationMode(stateObj) { - return (stateObj.attributes.supported_features & 128) !== 0; + return supportsFeature(stateObj, 128); } supportsSwingMode(stateObj) { - return (stateObj.attributes.supported_features & 512) !== 0; + return supportsFeature(stateObj, 512); } supportsAwayMode(stateObj) { - return (stateObj.attributes.supported_features & 1024) !== 0; + return supportsFeature(stateObj, 1024); } supportsAuxHeat(stateObj) { - return (stateObj.attributes.supported_features & 2048) !== 0; + return supportsFeature(stateObj, 2048); } supportsOn(stateObj) { - return (stateObj.attributes.supported_features & 4096) !== 0; + return supportsFeature(stateObj, 4096); } computeClassNames(stateObj) { diff --git a/src/dialogs/more-info/controls/more-info-vacuum.js b/src/dialogs/more-info/controls/more-info-vacuum.js index e822a53b14..d46a699788 100644 --- a/src/dialogs/more-info/controls/more-info-vacuum.js +++ b/src/dialogs/more-info/controls/more-info-vacuum.js @@ -8,6 +8,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import "../../../components/ha-attributes"; +import { supportsFeature } from "../../../common/entity/supports-feature"; class MoreInfoVacuum extends PolymerElement { static get template() { @@ -158,57 +159,53 @@ class MoreInfoVacuum extends PolymerElement { }; } - /* eslint-disable no-bitwise */ - supportsPause(stateObj) { - return (stateObj.attributes.supported_features & 4) !== 0; + return supportsFeature(stateObj, 4); } supportsStop(stateObj) { - return (stateObj.attributes.supported_features & 8) !== 0; + return supportsFeature(stateObj, 8); } supportsReturnHome(stateObj) { - return (stateObj.attributes.supported_features & 16) !== 0; + return supportsFeature(stateObj, 16); } supportsFanSpeed(stateObj) { - return (stateObj.attributes.supported_features & 32) !== 0; + return supportsFeature(stateObj, 32); } supportsBattery(stateObj) { - return (stateObj.attributes.supported_features & 64) !== 0; + return supportsFeature(stateObj, 64); } supportsStatus(stateObj) { - return (stateObj.attributes.supported_features & 128) !== 0; + return supportsFeature(stateObj, 128); } supportsLocate(stateObj) { - return (stateObj.attributes.supported_features & 512) !== 0; + return supportsFeature(stateObj, 512); } supportsCleanSpot(stateObj) { - return (stateObj.attributes.supported_features & 1024) !== 0; + return supportsFeature(stateObj, 1024); } supportsStart(stateObj) { - return (stateObj.attributes.supported_features & 8192) !== 0; + return supportsFeature(stateObj, 8192); } supportsCommandBar(stateObj) { return ( - ((stateObj.attributes.supported_features & 4) !== 0) | - ((stateObj.attributes.supported_features & 8) !== 0) | - ((stateObj.attributes.supported_features & 16) !== 0) | - ((stateObj.attributes.supported_features & 512) !== 0) | - ((stateObj.attributes.supported_features & 1024) !== 0) | - ((stateObj.attributes.supported_features & 8192) !== 0) + supportsFeature(stateObj, 4) | + supportsFeature(stateObj, 8) | + supportsFeature(stateObj, 16) | + supportsFeature(stateObj, 512) | + supportsFeature(stateObj, 1024) | + supportsFeature(stateObj, 8192) ); } - /* eslint-enable no-bitwise */ - fanSpeedChanged(fanSpeedIndex) { var fanSpeedInput; // Selected Option will transition to '' before transitioning to new value diff --git a/src/dialogs/more-info/controls/more-info-water_heater.js b/src/dialogs/more-info/controls/more-info-water_heater.js index e74fb7a1e6..475d338c62 100644 --- a/src/dialogs/more-info/controls/more-info-water_heater.js +++ b/src/dialogs/more-info/controls/more-info-water_heater.js @@ -12,6 +12,7 @@ import "../../../components/ha-water_heater-control"; import "../../../components/ha-paper-slider"; import featureClassNames from "../../../common/entity/feature_class_names"; +import { supportsFeature } from "../../../common/entity/supports-feature"; import EventsMixin from "../../../mixins/events-mixin"; import LocalizeMixin from "../../../mixins/localize-mixin"; @@ -198,17 +199,17 @@ class MoreInfoWaterHeater extends LocalizeMixin(EventsMixin(PolymerElement)) { supportsTemperature(stateObj) { return ( - (stateObj.attributes.supported_features & 1) !== 0 && + supportsFeature(stateObj, 1) && typeof stateObj.attributes.temperature === "number" ); } supportsOperationMode(stateObj) { - return (stateObj.attributes.supported_features & 2) !== 0; + return supportsFeature(stateObj, 2); } supportsAwayMode(stateObj) { - return (stateObj.attributes.supported_features & 4) !== 0; + return supportsFeature(stateObj, 4); } computeClassNames(stateObj) { diff --git a/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts b/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts index 907255ed3b..7707991a96 100644 --- a/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-media-player-entity-row.ts @@ -8,6 +8,7 @@ import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin"; import { EntityRow, EntityConfig } from "./types"; import { HomeAssistant } from "../../../types"; import { HassEntity } from "home-assistant-js-websocket"; +import { supportsFeature } from "../../../common/entity/supports-feature"; import { SUPPORTS_PLAY, SUPPORT_NEXT_TRACK, @@ -50,13 +51,6 @@ class HuiMediaPlayerEntityRow extends hassLocalizeLitMixin(LitElement) `; } - const supportsPlay = - // tslint:disable-next-line:no-bitwise - stateObj.attributes.supported_features! & SUPPORTS_PLAY; - const supportsNext = - // tslint:disable-next-line:no-bitwise - stateObj.attributes.supported_features! & SUPPORT_NEXT_TRACK; - return html` ${this.renderStyle()} ${ - stateObj.state !== "playing" && !supportsPlay + stateObj.state !== "playing" && + !supportsFeature(stateObj, SUPPORTS_PLAY) ? "" : html` - (stateObj.attributes.supported_features & feature) !== 0; +export const supportsOpen = (stateObj) => supportsFeature(stateObj, 1); -export const supportsOpen = (stateObj) => support(stateObj, 1); +export const supportsClose = (stateObj) => supportsFeature(stateObj, 2); -export const supportsClose = (stateObj) => support(stateObj, 2); +export const supportsSetPosition = (stateObj) => supportsFeature(stateObj, 4); -export const supportsSetPosition = (stateObj) => support(stateObj, 4); +export const supportsStop = (stateObj) => supportsFeature(stateObj, 8); -export const supportsStop = (stateObj) => support(stateObj, 8); +export const supportsOpenTilt = (stateObj) => supportsFeature(stateObj, 16); -export const supportsOpenTilt = (stateObj) => support(stateObj, 16); +export const supportsCloseTilt = (stateObj) => supportsFeature(stateObj, 32); -export const supportsCloseTilt = (stateObj) => support(stateObj, 32); +export const supportsStopTilt = (stateObj) => supportsFeature(stateObj, 64); -export const supportsStopTilt = (stateObj) => support(stateObj, 64); - -export const supportsSetTiltPosition = (stateObj) => support(stateObj, 128); +export const supportsSetTiltPosition = (stateObj) => + supportsFeature(stateObj, 128); export function isTiltOnly(stateObj) { const supportsCover = diff --git a/src/util/hass-media-player-model.js b/src/util/hass-media-player-model.js index 9f8f53b0a4..10c32fc09d 100644 --- a/src/util/hass-media-player-model.js +++ b/src/util/hass-media-player-model.js @@ -1,3 +1,5 @@ +import { supportsFeature } from "../common/entity/supports-feature"; + export default class MediaPlayerEntity { constructor(hass, stateObj) { this.hass = hass; @@ -62,58 +64,54 @@ export default class MediaPlayerEntity { return progress; } - /* eslint-disable no-bitwise */ - get supportsPause() { - return (this._feat & 1) !== 0; + return supportsFeature(this.stateObj, 1); } get supportsVolumeSet() { - return (this._feat & 4) !== 0; + return supportsFeature(this.stateObj, 4); } get supportsVolumeMute() { - return (this._feat & 8) !== 0; + return supportsFeature(this.stateObj, 8); } get supportsPreviousTrack() { - return (this._feat & 16) !== 0; + return supportsFeature(this.stateObj, 16); } get supportsNextTrack() { - return (this._feat & 32) !== 0; + return supportsFeature(this.stateObj, 32); } get supportsTurnOn() { - return (this._feat & 128) !== 0; + return supportsFeature(this.stateObj, 128); } get supportsTurnOff() { - return (this._feat & 256) !== 0; + return supportsFeature(this.stateObj, 256); } get supportsPlayMedia() { - return (this._feat & 512) !== 0; + return supportsFeature(this.stateObj, 512); } get supportsVolumeButtons() { - return (this._feat & 1024) !== 0; + return supportsFeature(this.stateObj, 1024); } get supportsSelectSource() { - return (this._feat & 2048) !== 0; + return supportsFeature(this.stateObj, 2048); } get supportsSelectSoundMode() { - return (this._feat & 65536) !== 0; + return supportsFeature(this.stateObj, 65536); } get supportsPlay() { - return (this._feat & 16384) !== 0; + return supportsFeature(this.stateObj, 16384); } - /* eslint-enable no-bitwise */ - get primaryTitle() { return this._attr.media_title; }