From 6818316dc93e7f96428aa6542ce2358e82dce687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Wiedemann?= Date: Sat, 14 Mar 2020 14:25:26 +0100 Subject: [PATCH] Add support for stateIcon --- src/binary_sensor_icon.ts | 51 +++++++++++++++++++++++++++++++++++++ src/cover_icon.ts | 21 +++++++++++++++ src/index.ts | 1 + src/input_datetime_icon.ts | 13 ++++++++++ src/sensor_icon.ts | 52 ++++++++++++++++++++++++++++++++++++++ src/state_icon.ts | 31 +++++++++++++++++++++++ 6 files changed, 169 insertions(+) create mode 100644 src/binary_sensor_icon.ts create mode 100644 src/cover_icon.ts create mode 100644 src/input_datetime_icon.ts create mode 100644 src/sensor_icon.ts create mode 100644 src/state_icon.ts diff --git a/src/binary_sensor_icon.ts b/src/binary_sensor_icon.ts new file mode 100644 index 0000000..c1eb694 --- /dev/null +++ b/src/binary_sensor_icon.ts @@ -0,0 +1,51 @@ +import { HassEntity } from "home-assistant-js-websocket"; + +/** Return an icon representing a binary sensor state. */ + +export const binarySensorIcon = (state: HassEntity) => { + const activated = state.state && state.state === "off"; + switch (state.attributes.device_class) { + case "battery": + return activated ? "hass:battery" : "hass:battery-outline"; + case "cold": + return activated ? "hass:thermometer" : "hass:snowflake"; + case "connectivity": + return activated ? "hass:server-network-off" : "hass:server-network"; + case "door": + return activated ? "hass:door-closed" : "hass:door-open"; + case "garage_door": + return activated ? "hass:garage" : "hass:garage-open"; + case "gas": + case "power": + case "problem": + case "safety": + case "smoke": + return activated ? "hass:shield-check" : "hass:alert"; + case "heat": + return activated ? "hass:thermometer" : "hass:fire"; + case "light": + return activated ? "hass:brightness-5" : "hass:brightness-7"; + case "lock": + return activated ? "hass:lock" : "hass:lock-open"; + case "moisture": + return activated ? "hass:water-off" : "hass:water"; + case "motion": + return activated ? "hass:walk" : "hass:run"; + case "occupancy": + return activated ? "hass:home-outline" : "hass:home"; + case "opening": + return activated ? "hass:square" : "hass:square-outline"; + case "plug": + return activated ? "hass:power-plug-off" : "hass:power-plug"; + case "presence": + return activated ? "hass:home-outline" : "hass:home"; + case "sound": + return activated ? "hass:music-note-off" : "hass:music-note"; + case "vibration": + return activated ? "hass:crop-portrait" : "hass:vibrate"; + case "window": + return activated ? "hass:window-closed" : "hass:window-open"; + default: + return activated ? "hass:radiobox-blank" : "hass:checkbox-marked-circle"; + } +}; diff --git a/src/cover_icon.ts b/src/cover_icon.ts new file mode 100644 index 0000000..2cf6ca5 --- /dev/null +++ b/src/cover_icon.ts @@ -0,0 +1,21 @@ +/** Return an icon representing a cover state. */ +import { HassEntity } from "home-assistant-js-websocket"; +import { domainIcon } from "./domain_icons"; + +export const coverIcon = (state: HassEntity): string => { + const open = state.state !== "closed"; + switch (state.attributes.device_class) { + case "garage": + return open ? "hass:garage-open" : "hass:garage"; + case "door": + return open ? "hass:door-open" : "hass:door-closed"; + case "shutter": + return open ? "hass:window-shutter-open" : "hass:window-shutter"; + case "blind": + return open ? "hass:blinds-open" : "hass:blinds"; + case "window": + return open ? "hass:window-open" : "hass:window-closed"; + default: + return domainIcon("cover", state.state); + } +}; diff --git a/src/index.ts b/src/index.ts index 92ba63a..7136bee 100644 --- a/src/index.ts +++ b/src/index.ts @@ -28,3 +28,4 @@ export * from "./turn-on-off-entities" export * from "./turn-on-off-entity"; export * from "./types"; export * from "./get-lovelace"; +export * from "./state_icon" diff --git a/src/input_datetime_icon.ts b/src/input_datetime_icon.ts new file mode 100644 index 0000000..9507be8 --- /dev/null +++ b/src/input_datetime_icon.ts @@ -0,0 +1,13 @@ +/** Return an icon representing an input datetime state. */ +import { domainIcon } from "./domain_icons"; +import { HassEntity } from "home-assistant-js-websocket"; + +export const inputDateTimeIcon = (state: HassEntity): string => { + if (!state.attributes.has_date) { + return "hass:clock"; + } + if (!state.attributes.has_time) { + return "hass:calendar"; + } + return domainIcon("input_datetime"); +}; diff --git a/src/sensor_icon.ts b/src/sensor_icon.ts new file mode 100644 index 0000000..516996f --- /dev/null +++ b/src/sensor_icon.ts @@ -0,0 +1,52 @@ +/** Return an icon representing a sensor state. */ +import { HassEntity } from "home-assistant-js-websocket"; +import { UNIT_C, UNIT_F } from "./const"; +import { domainIcon } from "./domain_icons"; + +const fixedDeviceClassIcons = { + humidity: "hass:water-percent", + illuminance: "hass:brightness-5", + temperature: "hass:thermometer", + pressure: "hass:gauge", + power: "hass:flash", + signal_strength: "hass:wifi", +}; + +export const sensorIcon = (state: HassEntity) => { + const dclass = state.attributes.device_class; + + if (dclass && dclass in fixedDeviceClassIcons) { + return fixedDeviceClassIcons[dclass]; + } + if (dclass === "battery") { + const battery = Number(state.state); + if (isNaN(battery)) { + return "hass:battery-unknown"; + } + const batteryRound = Math.round(battery / 10) * 10; + if (batteryRound >= 100) { + return "hass:battery"; + } + if (batteryRound <= 0) { + return "hass:battery-alert"; + } + // Will return one of the following icons: (listed so extractor picks up) + // hass:battery-10 + // hass:battery-20 + // hass:battery-30 + // hass:battery-40 + // hass:battery-50 + // hass:battery-60 + // hass:battery-70 + // hass:battery-80 + // hass:battery-90 + // We obscure 'hass' in iconname so this name does not get picked up + return `${"hass"}:battery-${batteryRound}`; + } + + const unit = state.attributes.unit_of_measurement; + if (unit === UNIT_C || unit === UNIT_F) { + return "hass:thermometer"; + } + return domainIcon("sensor"); +}; diff --git a/src/state_icon.ts b/src/state_icon.ts new file mode 100644 index 0000000..97d3cd3 --- /dev/null +++ b/src/state_icon.ts @@ -0,0 +1,31 @@ +import { HassEntity } from "home-assistant-js-websocket"; +import { computeDomain } from "./compute-domain"; +import { DEFAULT_DOMAIN_ICON } from "./const"; +import { binarySensorIcon } from "./binary_sensor_icon"; +import { coverIcon } from "./cover_icon"; +import { sensorIcon } from "./sensor_icon"; +import { inputDateTimeIcon } from "./input_datetime_icon"; +import { domainIcon } from "./domain_icons"; + +const domainIcons = { + binary_sensor: binarySensorIcon, + cover: coverIcon, + sensor: sensorIcon, + input_datetime: inputDateTimeIcon, +}; + +export const stateIcon = (state: HassEntity) => { + if (!state) { + return DEFAULT_DOMAIN_ICON; + } + if (state.attributes.icon) { + return state.attributes.icon; + } + + const domain = computeDomain(state.entity_id); + + if (domain in domainIcons) { + return domainIcons[domain](state); + } + return domainIcon(domain, state.state); +};