Cache thumbnails (#2924)

This commit is contained in:
Paulus Schoutsen 2019-03-12 19:43:04 -07:00 committed by GitHub
parent e2ed1a9fd9
commit bbc32278d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 97 additions and 9 deletions

View File

@ -6,6 +6,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag";
import { PolymerElement } from "@polymer/polymer/polymer-element"; import { PolymerElement } from "@polymer/polymer/polymer-element";
import HassMediaPlayerEntity from "../util/hass-media-player-model"; import HassMediaPlayerEntity from "../util/hass-media-player-model";
import { fetchMediaPlayerThumbnailWithCache } from "../data/media-player";
import computeStateName from "../common/entity/compute_state_name"; import computeStateName from "../common/entity/compute_state_name";
import EventsMixin from "../mixins/events-mixin"; import EventsMixin from "../mixins/events-mixin";
@ -271,10 +272,13 @@ class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
// We have a new picture url // We have a new picture url
try { try {
const { content_type: contentType, content } = await this.hass.callWS({ const {
type: "media_player_thumbnail", content_type: contentType,
entity_id: playerObj.stateObj.entity_id, content,
}); } = await fetchMediaPlayerThumbnailWithCache(
this.hass,
playerObj.stateObj.entity_id
);
this._coverShowing = true; this._coverShowing = true;
this._coverLoadError = false; this._coverLoadError = false;
this.$.cover.style.backgroundImage = `url(data:${contentType};base64,${content})`; this.$.cover.style.backgroundImage = `url(data:${contentType};base64,${content})`;

View File

@ -0,0 +1,47 @@
import { HomeAssistant } from "../../types";
interface ResultCache<T> {
[entityId: string]: Promise<T> | undefined;
}
export const timeCachePromiseFunc = async <T>(
cacheKey: string,
cacheTime: number,
func: (
hass: HomeAssistant,
entityId: string,
...args: Array<unknown>
) => Promise<T>,
hass: HomeAssistant,
entityId: string,
...args: Array<unknown>
): Promise<T> => {
let cache: ResultCache<T> | undefined = (hass as any)[cacheKey];
if (!cache) {
cache = hass[cacheKey] = {};
}
const lastResult = cache[entityId];
if (lastResult) {
return lastResult;
}
const result = func(hass, entityId, ...args);
cache[entityId] = result;
result.then(
// When successful, set timer to clear cache
() =>
setTimeout(() => {
cache![entityId] = undefined;
}, cacheTime),
// On failure, clear cache right away
() => {
cache![entityId] = undefined;
}
);
return result;
};

View File

@ -1,4 +1,5 @@
import { HomeAssistant, CameraEntity } from "../types"; import { HomeAssistant, CameraEntity } from "../types";
import { timeCachePromiseFunc } from "../common/util/time-cache-function-promise";
export interface CameraThumbnail { export interface CameraThumbnail {
content_type: string; content_type: string;
@ -14,6 +15,11 @@ export const computeMJPEGStreamUrl = (entity: CameraEntity) =>
entity.attributes.access_token entity.attributes.access_token
}`; }`;
export const fetchThumbnailWithCache = (
hass: HomeAssistant,
entityId: string
) => timeCachePromiseFunc("_cameraTmb", 9000, fetchThumbnail, hass, entityId);
export const fetchThumbnail = (hass: HomeAssistant, entityId: string) => export const fetchThumbnail = (hass: HomeAssistant, entityId: string) =>
hass.callWS<CameraThumbnail>({ hass.callWS<CameraThumbnail>({
type: "camera_thumbnail", type: "camera_thumbnail",

View File

@ -1,4 +1,35 @@
import { HomeAssistant } from "../types";
import { timeCachePromiseFunc } from "../common/util/time-cache-function-promise";
export const SUPPORT_PAUSE = 1; export const SUPPORT_PAUSE = 1;
export const SUPPORT_NEXT_TRACK = 32; export const SUPPORT_NEXT_TRACK = 32;
export const SUPPORTS_PLAY = 16384; export const SUPPORTS_PLAY = 16384;
export const OFF_STATES = ["off", "idle"]; export const OFF_STATES = ["off", "idle"];
export interface MediaPlayerThumbnail {
content_type: string;
content: string;
}
export const fetchMediaPlayerThumbnailWithCache = (
hass: HomeAssistant,
entityId: string
) =>
timeCachePromiseFunc(
"_media_playerTmb",
9000,
fetchMediaPlayerThumbnail,
hass,
entityId
);
export const fetchMediaPlayerThumbnail = (
hass: HomeAssistant,
entityId: string
) => {
return hass.callWS<MediaPlayerThumbnail>({
type: "media_player_thumbnail",
entity_id: entityId,
});
};

View File

@ -18,7 +18,7 @@ import { HomeAssistant } from "../../../types";
import { styleMap } from "lit-html/directives/style-map"; import { styleMap } from "lit-html/directives/style-map";
import { classMap } from "lit-html/directives/class-map"; import { classMap } from "lit-html/directives/class-map";
import { b64toBlob } from "../../../common/file/b64-to-blob"; import { b64toBlob } from "../../../common/file/b64-to-blob";
import { fetchThumbnail } from "../../../data/camera"; import { fetchThumbnailWithCache } from "../../../data/camera";
const UPDATE_INTERVAL = 10000; const UPDATE_INTERVAL = 10000;
const DEFAULT_FILTER = "grayscale(100%)"; const DEFAULT_FILTER = "grayscale(100%)";
@ -179,10 +179,10 @@ class HuiImage extends LitElement {
return; return;
} }
try { try {
const { content_type: contentType, content } = await fetchThumbnail( const {
this.hass, content_type: contentType,
this.cameraImage content,
); } = await fetchThumbnailWithCache(this.hass, this.cameraImage);
if (this._cameraImageSrc) { if (this._cameraImageSrc) {
URL.revokeObjectURL(this._cameraImageSrc); URL.revokeObjectURL(this._cameraImageSrc);
} }