Show battery charging state in the config panels (#6356)

This commit is contained in:
J. Nick Koston 2020-07-12 09:30:27 -10:00 committed by GitHub
parent def1ec3518
commit 3bc54aa9e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 124 additions and 44 deletions

View File

@ -0,0 +1,28 @@
/** Return an icon representing a battery state. */
import { HassEntity } from "home-assistant-js-websocket";
export const batteryIcon = (
batteryState: HassEntity,
batteryChargingState?: HassEntity
) => {
const battery = Number(batteryState.state);
const battery_charging =
batteryChargingState && batteryChargingState.state === "on";
if (isNaN(battery)) {
return "hass:battery-unknown";
}
var icon = "hass:battery";
const batteryRound = Math.round(battery / 10) * 10;
if (battery_charging && battery > 10) {
icon += `-charging-${batteryRound}`;
} else if (battery_charging) {
icon += "-outline";
} else if (battery <= 5) {
icon += "-alert";
} else if (battery > 5 && battery < 95) {
icon += `-${batteryRound}`;
}
return icon;
};

View File

@ -2,6 +2,7 @@
import { HassEntity } from "home-assistant-js-websocket";
import { UNIT_C, UNIT_F } from "../const";
import { domainIcon } from "./domain_icon";
import { batteryIcon } from "./battery_icon";
const fixedDeviceClassIcons = {
humidity: "hass:water-percent",
@ -19,29 +20,7 @@ export const sensorIcon = (state: HassEntity) => {
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}`;
return batteryIcon(state);
}
const unit = state.attributes.unit_of_measurement;

View File

@ -0,0 +1,20 @@
import { batteryIcon } from "../../common/entity/battery_icon";
import "../ha-icon";
import { customElement, html, property, LitElement } from "lit-element";
@customElement("ha-battery-icon")
class HaBatteryIcon extends LitElement {
@property() public batteryStateObj;
@property() public batteryChargingStateObj;
protected render() {
return html`
<ha-icon
.icon=${batteryIcon(this.batteryStateObj, this.batteryChargingStateObj)}
></ha-icon>
`;
}
}
customElements.define("ha-battery-icon", HaBatteryIcon);

View File

@ -37,6 +37,17 @@ export const findBatteryEntity = (
hass.states[entity.entity_id].attributes.device_class === "battery"
);
export const findBatteryChargingEntity = (
hass: HomeAssistant,
entities: EntityRegistryEntry[]
): EntityRegistryEntry | undefined =>
entities.find(
(entity) =>
hass.states[entity.entity_id] &&
hass.states[entity.entity_id].attributes.device_class ===
"battery_charging"
);
export const computeEntityRegistryName = (
hass: HomeAssistant,
entry: EntityRegistryEntry

View File

@ -14,7 +14,7 @@ import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { computeStateName } from "../../../common/entity/compute_state_name";
import { createValidEntityId } from "../../../common/entity/valid_entity_id";
import { compare } from "../../../common/string/compare";
import "../../../components/entity/ha-state-icon";
import "../../../components/entity/ha-battery-icon";
import "../../../components/ha-icon-next";
import { AreaRegistryEntry } from "../../../data/area_registry";
import { ConfigEntry } from "../../../data/config_entries";
@ -26,6 +26,7 @@ import {
import {
EntityRegistryEntry,
findBatteryEntity,
findBatteryChargingEntity,
updateEntityRegistryEntry,
} from "../../../data/entity_registry";
import { SceneEntities, showSceneEditor } from "../../../data/scene";
@ -117,6 +118,11 @@ export class HaConfigDevicePage extends LitElement {
| EntityRegistryEntry
| undefined => findBatteryEntity(this.hass, entities));
private _batteryChargingEntity = memoizeOne(
(entities: EntityRegistryEntry[]): EntityRegistryEntry | undefined =>
findBatteryChargingEntity(this.hass, entities)
);
protected firstUpdated(changedProps) {
super.firstUpdated(changedProps);
loadDeviceRegistryDetailDialog();
@ -145,9 +151,13 @@ export class HaConfigDevicePage extends LitElement {
const integrations = this._integrations(device, this.entries);
const entities = this._entities(this.deviceId, this.entities);
const batteryEntity = this._batteryEntity(entities);
const batteryChargingEntity = this._batteryChargingEntity(entities);
const batteryState = batteryEntity
? this.hass.states[batteryEntity.entity_id]
: undefined;
const batteryChargingState = batteryChargingEntity
? this.hass.states[batteryChargingEntity.entity_id]
: undefined;
const area = this._computeArea(this.areas, device);
return html`
@ -201,10 +211,11 @@ export class HaConfigDevicePage extends LitElement {
? html`
<div class="battery">
${batteryState.state}%
<ha-state-icon
<ha-battery-icon
.hass=${this.hass!}
.stateObj=${batteryState}
></ha-state-icon>
.batteryStateObj=${batteryState}
.batteryChargingStateObj=${batteryChargingState}
></ha-battery-icon>
</div>
`
: ""

View File

@ -14,7 +14,7 @@ import {
DataTableRowData,
RowClickedEvent,
} from "../../../components/data-table/ha-data-table";
import "../../../components/entity/ha-state-icon";
import "../../../components/entity/ha-battery-icon";
import { AreaRegistryEntry } from "../../../data/area_registry";
import { ConfigEntry } from "../../../data/config_entries";
import {
@ -25,6 +25,7 @@ import {
import {
EntityRegistryEntry,
findBatteryEntity,
findBatteryChargingEntity,
} from "../../../data/entity_registry";
import { domainToName } from "../../../data/integration";
import "../../../layouts/hass-tabs-subpage-data-table";
@ -35,7 +36,7 @@ interface DeviceRowData extends DeviceRegistryEntry {
device?: DeviceRowData;
area?: string;
integration?: string;
battery_entity?: string;
battery_entity?: [string | undefined, string | undefined];
}
@customElement("ha-config-devices-dashboard")
@ -167,7 +168,10 @@ export class HaConfigDeviceDashboard extends LitElement {
)
.join(", ")
: "No integration",
battery_entity: this._batteryEntity(device.id, deviceEntityLookup),
battery_entity: [
this._batteryEntity(device.id, deviceEntityLookup),
this._batteryChargingEntity(device.id, deviceEntityLookup),
],
};
});
@ -201,17 +205,25 @@ export class HaConfigDeviceDashboard extends LitElement {
sortable: true,
type: "numeric",
width: "90px",
template: (batteryEntity: string) => {
const battery = batteryEntity
? this.hass.states[batteryEntity]
: undefined;
template: (
batteryEntityPair: DeviceRowData["battery_entity"]
) => {
const battery =
batteryEntityPair && batteryEntityPair[0]
? this.hass.states[batteryEntityPair[0]]
: undefined;
const batteryCharging =
batteryEntityPair && batteryEntityPair[1]
? this.hass.states[batteryEntityPair[1]]
: undefined;
return battery
? html`
${isNaN(battery.state as any) ? "-" : battery.state}%
<ha-state-icon
<ha-battery-icon
.hass=${this.hass!}
.stateObj=${battery}
></ha-state-icon>
.batteryStateObj=${battery}
.batteryChargingStateObj=${batteryCharging}
></ha-battery-icon>
`
: html` - `;
},
@ -267,17 +279,25 @@ export class HaConfigDeviceDashboard extends LitElement {
type: "numeric",
width: "15%",
maxWidth: "90px",
template: (batteryEntity: string) => {
const battery = batteryEntity
? this.hass.states[batteryEntity]
: undefined;
template: (
batteryEntityPair: DeviceRowData["battery_entity"]
) => {
const battery =
batteryEntityPair && batteryEntityPair[0]
? this.hass.states[batteryEntityPair[0]]
: undefined;
const batteryCharging =
batteryEntityPair && batteryEntityPair[1]
? this.hass.states[batteryEntityPair[1]]
: undefined;
return battery && !isNaN(battery.state as any)
? html`
${battery.state}%
<ha-state-icon
<ha-battery-icon
.hass=${this.hass!}
.stateObj=${battery}
></ha-state-icon>
.batteryStateObj=${battery}
.batteryChargingStateObj=${batteryCharging}
></ha-battery-icon>
`
: html` - `;
},
@ -336,6 +356,17 @@ export class HaConfigDeviceDashboard extends LitElement {
return batteryEntity ? batteryEntity.entity_id : undefined;
}
private _batteryChargingEntity(
deviceId: string,
deviceEntityLookup: DeviceEntityLookup
): string | undefined {
const batteryChargingEntity = findBatteryChargingEntity(
this.hass,
deviceEntityLookup[deviceId] || []
);
return batteryChargingEntity ? batteryChargingEntity.entity_id : undefined;
}
private _handleRowClicked(ev: HASSDomEvent<RowClickedEvent>) {
const deviceId = ev.detail.id;
navigate(this, `/config/devices/device/${deviceId}`);