Autodetect motion and occupancy sensors.

This commit is contained in:
Dermot Duffy
2022-05-21 11:23:31 -07:00
parent 4a40e4a943
commit c8d9e89b78
10 changed files with 358 additions and 80 deletions
+109
View File
@@ -0,0 +1,109 @@
import { HomeAssistant } from 'custom-card-helpers';
import { homeAssistantWSRequest } from '.';
import {
Entity,
EntityList,
entityListSchema,
ExtendedEntity,
extendedEntitySchema
} from '../../types.js';
export class ExtendedEntityCache {
protected _cache: Map<string, ExtendedEntity> = new Map();
/**
* Determine if the cache has a given entity_id.
* @param id
* @returns `true` if the id is in the cache, `false` otherwise.
*/
public has(id: string): boolean {
return this._cache.has(id);
}
/**
* Get the first value that returns true for the given predicate.
* @param func A callback function that returns a boolean.
* @returns The first matching value.
*/
public getMatch(func: (arg: ExtendedEntity) => boolean): ExtendedEntity | null {
return [...this._cache.values()].find(func) ?? null;
}
/**
* Get entity information given an id.
* @param id The entity id.
* @returns The `ExtendedEntity` for this id.
*/
public get(id: string): ExtendedEntity | undefined {
return this._cache.get(id);
}
/**
* Add a given ExtendedEntity to the cache.
* @param extendedEntity
*/
public set(extendedEntity: ExtendedEntity): void {
this._cache.set(extendedEntity.entity_id, extendedEntity);
}
}
/**
* Get the extended entity information for an entity. May throw.
* @param hass The Home Assistant object.
* @param entity The entity id.
* @param cache An optional ExtendedEntityCache.
* @returns The ExtendedEntity information.
*/
export const getExtendedEntity = async (
hass: HomeAssistant,
entity: string,
cache?: ExtendedEntityCache,
): Promise<ExtendedEntity> => {
const cachedValue = cache ? cache.get(entity) : undefined;
if (cachedValue) {
return cachedValue;
}
const result = await homeAssistantWSRequest<ExtendedEntity>(
hass,
extendedEntitySchema,
{
type: 'config/entity_registry/get',
entity_id: entity,
},
);
if (cache) {
cache.set(result);
}
return result;
};
/**
* Get the extended entity information for an array of entities.
* @param hass The Home Assistant object.
* @param entities An array of entity ids.
* @param cache An optional ExtendedEntityCache.
* @returns A map of entity id to ExtendedEntity objects.
*/
export const getExtendedEntities = async (
hass: HomeAssistant,
entities: string[],
cache?: ExtendedEntityCache,
): Promise<Map<string, Entity>> => {
const output: Map<string, Entity> = new Map();
const _storeExtendedEntity = async (entity: string): Promise<void> => {
output.set(entity, await getExtendedEntity(hass, entity, cache));
};
await Promise.all(entities.map(_storeExtendedEntity));
return output;
};
/**
* Get a list of all entities from the entity registry.
* @param hass The Home Assistant object.
* @returns An entity list object.
*/
export const getAllEntities = async (hass: HomeAssistant): Promise<EntityList> => {
return await homeAssistantWSRequest<EntityList>(hass, entityListSchema, {
type: 'config/entity_registry/list',
});
};
+18 -2
View File
@@ -4,8 +4,7 @@ import { StyleInfo } from 'lit/directives/style-map.js';
import { ZodSchema } from 'zod';
import { localize } from '../../localize/localize.js';
import {
CardHelpers,
ExtendedHomeAssistant,
CardHelpers, ExtendedHomeAssistant,
SignedPath,
signedPathSchema,
StateParameters
@@ -306,3 +305,20 @@ export const sideLoadHomeAssistantElements = async (): Promise<boolean> => {
export const isTriggeredState = (state?: HassEntity): boolean => {
return !!state && ['on', 'open'].includes(state.state);
};
/**
* Get entities from the HASS object.
* @param hass
* @param domain
* @returns
*/
export const getEntitiesFromHASS = (hass: HomeAssistant, domain?: string): string[] => {
if (!hass) {
return [];
}
const entities = Object.keys(hass.states).filter(
(eid) => !domain || eid.substr(0, eid.indexOf('.')) === domain,
);
entities.sort();
return entities;
}
@@ -1,11 +1,11 @@
import { HomeAssistant } from 'custom-card-helpers';
import QuickLRU from 'quick-lru';
import { homeAssistantWSRequest } from '.';
import {
FrigateBrowseMediaSource,
ResolvedMedia,
resolvedMediaSchema
} from '../types.js';
import { homeAssistantWSRequest } from './ha';
FrigateBrowseMediaSource,
ResolvedMedia,
resolvedMediaSchema
} from '../../types.js';
// It's important the cache size be at least as large as the largest likely
// media query or media items will from a given query will be evicted for other
@@ -21,19 +21,42 @@ export class ResolvedMediaCache {
this._cache = new QuickLRU({ maxSize: RESOLVED_MEDIA_CACHE_SIZE });
}
/**
* Determine if the cache has a given id.
* @param id
* @returns `true` if the id is in the cache, `false` otherwise.
*/
public has(id: string): boolean {
return this._cache.has(id);
}
/**
* Get resolved media information given an id.
* @param id The id.
* @returns The `ResolvedMedia` for this id.
*/
public get(id: string): ResolvedMedia | undefined {
return this._cache.get(id);
}
/**
* Add a given ResolvedMedia to the cache.
* @param id The id for the object.
* @param resolvedMedia The `ResolvedMedia` object.
*/
public set(id: string, resolvedMedia: ResolvedMedia): void {
this._cache.set(id, resolvedMedia);
}
}
/**
* Resolve a given media source item.
* @param hass The Home Assistant object.
* @param mediaSource The media source object.
* @param cache An optional ResolvedMediaCache object.
* @returns
*/
export const resolveMedia = async (
hass: HomeAssistant,
mediaSource?: FrigateBrowseMediaSource,