mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-21 08:16:36 +00:00
Show battery charging state in the config panels (#6356)
This commit is contained in:
parent
def1ec3518
commit
3bc54aa9e0
28
src/common/entity/battery_icon.ts
Normal file
28
src/common/entity/battery_icon.ts
Normal 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;
|
||||
};
|
@ -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;
|
||||
|
20
src/components/entity/ha-battery-icon.ts
Normal file
20
src/components/entity/ha-battery-icon.ts
Normal 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);
|
@ -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
|
||||
|
@ -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>
|
||||
`
|
||||
: ""
|
||||
|
@ -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}`);
|
||||
|
Loading…
x
Reference in New Issue
Block a user