Skip to content

Commit

Permalink
basic working example, low functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
warmfire540 committed Jan 22, 2025
1 parent e576a91 commit a7d8a7d
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 116 deletions.
26 changes: 11 additions & 15 deletions src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
import { html } from 'lit';

import type { EntityState, HomeAssistant } from './types';
import type { Device, Entity, HomeAssistant, State } from './types';

export const createStateIcon = (
hass: HomeAssistant,
state: EntityState,
state: State,
classes: String[],
) =>
html`<div class="${['icon', ...classes].join(' ')}">
<ha-state-icon
.hass=${hass}
.stateObj=${state}
.icon=${state.attributes.icon || 'mdi:help-circle'}
></ha-state-icon>
<ha-state-icon .hass=${hass} .stateObj=${state}></ha-state-icon>
</div>`;

// <div class="icon entity entity-${position}">
// <ha-state-icon
// .hass=${this._hass}
// .stateObj=${state}
// .icon=${state.attributes.icon || "mdi:help-circle"}
// id="icon"
// ></ha-state-icon>
// </div>
export const getState = (hass: HomeAssistant, entityId: string): State =>
(hass.states as { [key: string]: any })[entityId];

export const getEntity = (hass: HomeAssistant, entityId: string): Entity =>
(hass.entities as { [key: string]: any })[entityId];

export const getDevice = (hass: HomeAssistant, deviceId: string): Device =>
(hass.devices as { [key: string]: any })[deviceId];
87 changes: 42 additions & 45 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ import { CSSResult, LitElement, html } from 'lit';
import { state } from 'lit/decorators.js';

import { version } from '../package.json';
import { createStateIcon } from './helpers';
import { createStateIcon, getDevice, getEntity, getState } from './helpers';
import { styles } from './styles';
import type { Config, HomeAssistant } from './types';
import type { EntityConfig } from './types';
import type { Config, HomeAssistant, State } from './types';

declare global {
interface Window {
Expand All @@ -18,25 +17,32 @@ class RoomSummaryCard extends LitElement {
@state()
private _config!: Config;

@state()
private _states!: State[];

// not state
private _hass!: HomeAssistant;

constructor() {
super();

this._states = [];

console.info(
`%c🐱 Poat's Tools: room-summary-card - ${version}`,
'color: #CFC493;',
);
}

render() {
if (!this._hass || !this._config) {
override render() {
if (!this._states.length) {
return html``;
}

const mainEntity = this._hass.states[`light.${this._config.area}`];
const isUnavailable = mainEntity?.state === 'unavailable';
const lightEntity = getState(
this._hass,
`light.${this._config.area}_light`,
);

return html`
<div class="card">
Expand All @@ -51,17 +57,19 @@ class RoomSummaryCard extends LitElement {
${this._getLabel()} <br />
<span class="stats">${this._getAreaStatistics()}</span>
</div>
${createStateIcon(this._hass, mainEntity, ['room'])}
${this._renderEntityIcon(this._config.entity_1, 1)}
${this._renderEntityIcon(this._config.entity_2, 2)}
${this._renderEntityIcon(this._config.entity_3, 3)}
${this._renderEntityIcon(this._config.entity_4, 4)}
${createStateIcon(this._hass, lightEntity, ['room'])}
${this._states.map((s, i) => {
return createStateIcon(this._hass, s, [
'entity',
`entity-${i + 1}`,
]);
})}
</div>
</div>
`;
}

static get styles(): CSSResult {
static override get styles(): CSSResult {
return styles;
}

Expand All @@ -81,40 +89,30 @@ class RoomSummaryCard extends LitElement {
// update your content.
set hass(hass: HomeAssistant) {
this._hass = hass;
}

private _renderEntityIcon(
entity: EntityConfig | undefined,
position: number,
) {
if (!entity) return null;

const state = this._hass.states[entity.entity_id];
if (!state) return null;
const baseEntities = [
`light.${this._config.area}_light`,
`switch.${this._config.area}_fan`,
];

return html`
<div class="icon entity entity-${position}">
<ha-state-icon
.hass=${this._hass}
.stateObj=${state}
.icon=${state.attributes.icon || 'mdi:help-circle'}
id="icon"
></ha-state-icon>
</div>
`;
this._states = Object.values(hass.states).filter((state) =>
baseEntities.includes(state.entity_id),
);
}

private _getLabel(): string {
if (!this._hass || !this._config.area) return '';

const climate = `${
this._hass.states[
'sensor.' + this._config.area + '_climate_air_temperature'
].state
getState(
this._hass,
'sensor.' + this._config.area + '_climate_air_temperature',
).state
}°F - ${
this._hass.states[
'sensor.' + this._config.area + '_climate_humidity'
].state
getState(
this._hass,
'sensor.' + this._config.area + '_climate_humidity',
).state
}%`;

return climate;
Expand All @@ -124,18 +122,17 @@ class RoomSummaryCard extends LitElement {
if (!this._hass || !this._config.area) return '';

const d = Object.keys(this._hass.devices).filter(
(k) => this._hass.devices[k].area_id === this._config.area,
);
const e = Object.keys(this._hass.entities).filter(
(k) =>
this._hass.entities[k].area_id === this._config.area ||
d.includes(this._hass.entities[k].device_id),
(k) => getDevice(this._hass, k).area_id === this._config.area,
);
const e = Object.keys(this._hass.entities).filter((k) => {
const e = getEntity(this._hass, k);
return e.area_id === this._config.area || d.includes(e.device_id);
});
const counts = [
[d.length, 'devices'],
[e.length, 'entities'],
]
.filter(([count]: [number]) => count > 0)
.filter((count) => count.length > 0)
.map(([count, type]) => `${count} ${type}`)
.join(' ');

Expand Down
2 changes: 1 addition & 1 deletion src/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const styles = css`
}
.icon ha-state-icon {
width: 45%;
width: 50%;
color: rgba(var(--color-theme), 0.2);
--mdc-icon-size: 100%;
}
Expand Down
76 changes: 21 additions & 55 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,60 +2,13 @@
* Configuration settings for entity display and behavior.
*/
export interface Config {
/** Area identifier where this configuration applies */
area: string;

navigate?: string;
entity_1?: EntityConfig;
entity_2?: EntityConfig;
entity_3?: EntityConfig;
entity_4?: EntityConfig;
label_use_temperature?: boolean;
label_use_brightness?: boolean;
ulm_input_select?: string;
ulm_input_select_option?: string;
icon?: string;
entities: EntityConfig[];
}

export interface EntityConfig {
entity_id: string;
templates?: string[];
tap_action?: ActionConfig;
hold_action?: ActionConfig;
}

export interface ActionConfig {
action: string;
entity?: string;
navigation_path?: string;
url_path?: string;
perform_action?: string;
target?: Record<string, any>;
}

/**
* Represents a Home Assistant entity with its relationships to areas and devices.
*/
export interface Entity {
/** ID of the area where this entity is located */
area_id: string;

/** ID of the physical device this entity belongs to */
device_id: string;

/** Array of descriptive labels associated with this entity */
labels: string[];
}

/**
* Represents a physical device in Home Assistant.
*/
export interface Device {
/** Unique identifier for the device */
id: string;

/** ID of the area where this device is located */
area_id: string;
}

/**
Expand All @@ -70,20 +23,22 @@ export interface HomeAssistant {
devices: Device[];

/** Object containing the current state of all entities in Home Assistant */
states: EntityState[];
states: State[];
}

callService(
domain: string,
service: string,
serviceData: Record<string, any>,
): void;
/**
* Represents a physical device in Home Assistant.
*/
export interface Device {
/** ID of the area where this device is located */
area_id: string;
}

/**
* Represents the current state and attributes of a Home Assistant entity.
* Used to track an entity's status and properties at a given moment.
*/
export type EntityState = {
export type State = {
/**
* Unique identifier for the entity.
* Format: `<domain>.<object_id>` (e.g. "light.living_room", "switch.kitchen")
Expand All @@ -103,3 +58,14 @@ export type EntityState = {
*/
attributes: Record<string, any>;
};

/**
* Represents a Home Assistant entity with its relationships to areas and devices.
*/
export interface Entity {
/** ID of the area where this entity is located */
area_id: string;

/** ID of the physical device this entity belongs to */
device_id: string;
}

0 comments on commit a7d8a7d

Please sign in to comment.