((LitElement) => {
console.info(
'%c BATTERY-ENTITY-ROW %c 1.3.1 ',
'color: cyan; background: black; font-weight: bold;',
'color: darkblue; background: white; font-weight: bold;',
);
const {html, css} = LitElement.prototype;
const defaultOnStates = ['on', 'charging', 'true'];
class BatteryEntityRow extends LitElement {
static get properties() {
return {
_hass: Object,
_config: Object,
stateObj: Object
}
}
static get styles() {
return css`
:host {
display: flex;
align-items: center;
}
.flex {
flex: 1;
margin-left: 16px;
display: flex;
justify-content: space-between;
align-items: center;
min-width: 0;
}
.info, state-badge {
cursor: pointer;
}
.secondary {
color: var(--secondary-text-color);
}
.good {
color: var(--label-badge-green);
}
.warning {
color: var(--label-badge-yellow);
}
.critical {
color: var(--label-badge-red);
}`;
}
render() {
if (!this._hass || !this._config) return html``;
if (!this.stateObj) return this.renderWarning();
const charging = this.getChargingState(this._config.charging)
const batteryValue = this.getBatteryLevel(this._config.attribute);
const isUnavailable = !batteryValue || ['unavailable', 'unknown'].includes(batteryValue);
const isNumeric = !isNaN(parseFloat(batteryValue)) && isFinite(batteryValue);
const numericValue = isUnavailable ? null : isNumeric ? batteryValue : this.parseStringValue(batteryValue);
const icon = this._config.icon || this.getIcon(numericValue, charging);
const color = this.getColor(numericValue);
const name = this._config.name || this.stateObj.attributes.friendly_name;
const unit = this._config.unit === false ? null : (this._config.unit || (isNumeric ? '%' : null));
const state = isUnavailable
? this._hass.localize('state.default.unknown')
: html`${batteryValue}${unit && html` ${unit}`}`;
return html`
${name}${this.renderSecondaryInfo()}
${state}
`;
}
renderSecondaryInfo() {
const secondaryInfo = this._config.secondary_info;
let content = undefined;
if (secondaryInfo === 'last-changed') {
content = html``;
} else if (secondaryInfo === 'last-updated') {
content = html``;
} else if (secondaryInfo in this.stateObj.attributes) {
content = this.stateObj.attributes[secondaryInfo];
}
return content ? html`${content}
` : null;
}
renderWarning() {
return html`
${this._hass.localize('ui.panel.lovelace.warning.entity_not_found', 'entity', this._config.entity)}
`;
}
setConfig(config) {
if (!config.entity) throw new Error('Please define a valid entity.');
this.moreInfo = () => this.fireEvent(this, 'hass-more-info', {entityId: config.entity});
this._config = config;
}
shouldUpdate(changedProps) {
return changedProps.has('stateObj');
}
set hass(hass) {
this._hass = hass;
if (hass && this._config) {
this.stateObj = this._config.entity in hass.states ? hass.states[this._config.entity] : null;
}
}
getBatteryLevel(attribute) {
let batteryValue = this.stateObj.state;
if (this.stateObj.attributes.battery) batteryValue = this.stateObj.attributes.battery;
if (this.stateObj.attributes.battery_level) batteryValue = this.stateObj.attributes.battery_level;
if (this.stateObj.attributes[attribute]) batteryValue = this.stateObj.attributes[attribute];
return !isNaN(parseFloat(batteryValue)) && isFinite(batteryValue)
? Math.round(parseInt(batteryValue, 10)) : batteryValue;
}
getChargingState(chargingConfig) {
if (!chargingConfig) return false;
if (chargingConfig === true) {
return defaultOnStates.includes(this.stateObj.state.toString().toLowerCase());
}
const additionalStates = chargingConfig.state || [];
const onStates = defaultOnStates.concat(additionalStates).map(value => value.toString().toLowerCase());
const entity = (chargingConfig.entity && chargingConfig.entity in this._hass.states)
? this._hass.states[chargingConfig.entity] : this.stateObj;
const state = chargingConfig.attribute ? entity.attributes[chargingConfig.attribute] : entity.state;
return onStates.includes(state.toString().toLowerCase());
}
getIcon(batteryLevel, charging) {
if (!batteryLevel) return 'mdi:battery-unknown';
const roundedLevel = Math.round(batteryLevel / 10) * 10;
return roundedLevel >= 100
? (charging ? 'mdi:battery-charging-100' : 'mdi:battery')
: roundedLevel === 0
? (charging ? 'mdi:battery-charging-outline' : 'mdi:battery-outline')
: (charging ? 'mdi:battery-charging-' : 'mdi:battery-') + roundedLevel;
}
getColor(batteryLevel) {
if (!batteryLevel) return 'unknown';
const warning = this._config.warning || 35;
const critical = this._config.critical || 15;
return (batteryLevel > warning)
? 'good'
: (batteryLevel > critical)
? 'warning'
: 'critical';
}
parseStringValue(v) {
const val = v.toString().toLowerCase();
if (['full', 'high', 'max', 'maximum'].includes(val)) return 90;
if (['medium', 'med', 'normal'].includes(val)) return 50;
if (['low', 'min', 'minimal'].includes(val)) return 10;
if (['empty', 'critical', 'none'].includes(val)) return 0;
return null;
}
fireEvent(node, type, detail = {}, options = {}) {
const event = new Event(type, {
bubbles: options.bubbles || true,
cancelable: options.cancelable || true,
composed: options.composed || true,
});
event.detail = detail;
node.dispatchEvent(event);
}
}
customElements.define('battery-entity-row', BatteryEntityRow);
})(window.LitElement || Object.getPrototypeOf(customElements.get('hui-masonry-view') || customElements.get('hui-view')));