Use signed path for camera snapshot (#3138)

This commit is contained in:
Paulus Schoutsen 2019-04-29 11:27:40 -07:00 committed by GitHub
parent 1e85880d7b
commit 73ef03e33f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 58 additions and 42 deletions

View File

@ -6,7 +6,7 @@ import "@polymer/paper-icon-button/paper-icon-button";
import "@polymer/paper-input/paper-input";
import { html } from "@polymer/polymer/lib/utils/html-tag";
import { PolymerElement } from "@polymer/polymer/polymer-element";
import { getSignedPath } from "../../../../src/auth/data";
import { getSignedPath } from "../../../../src/data/auth";
import "../../../../src/resources/ha-style";
import "../../../../src/components/dialog/ha-paper-dialog";

View File

@ -1,7 +0,0 @@
import { HomeAssistant } from "../types";
import { SignedPath } from "./types";
export const getSignedPath = (
hass: HomeAssistant,
path: string
): Promise<SignedPath> => hass.callWS({ type: "auth/sign_path", path });

View File

@ -1,3 +0,0 @@
export interface SignedPath {
path: string;
}

View File

@ -5,6 +5,7 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
import computeStateName from "../common/entity/compute_state_name";
import EventsMixin from "../mixins/events-mixin";
import LocalizeMixin from "../mixins/localize-mixin";
import { fetchThumbnailUrlWithCache } from "../data/camera";
const UPDATE_INTERVAL = 10000; // ms
/*
@ -54,6 +55,8 @@ class HaCameraCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
src="[[cameraFeedSrc]]"
class="camera-feed"
alt="[[_computeStateName(stateObj)]]"
on-load="_imageLoaded"
on-error="_imageError"
/>
</template>
<div class="caption">
@ -98,23 +101,23 @@ class HaCameraCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
clearInterval(this.timer);
}
_imageLoaded() {
this.imageLoaded = true;
}
_imageError() {
this.imageLoaded = false;
}
cardTapped() {
this.fire("hass-more-info", { entityId: this.stateObj.entity_id });
}
async updateCameraFeedSrc() {
try {
const { content_type: contentType, content } = await this.hass.callWS({
type: "camera_thumbnail",
entity_id: this.stateObj.entity_id,
});
this.setProperties({
imageLoaded: true,
cameraFeedSrc: `data:${contentType};base64, ${content}`,
});
} catch (err) {
this.imageLoaded = false;
}
this.cameraFeedSrc = await fetchThumbnailUrlWithCache(
this.hass,
this.stateObj.entity_id
);
}
_computeStateName(stateObj) {

View File

@ -1,3 +1,5 @@
import { HomeAssistant } from "../types";
export interface AuthProvider {
name: string;
id: string;
@ -7,3 +9,12 @@ export interface AuthProvider {
export interface Credential {
type: string;
}
export interface SignedPath {
path: string;
}
export const getSignedPath = (
hass: HomeAssistant,
path: string
): Promise<SignedPath> => hass.callWS({ type: "auth/sign_path", path });

View File

@ -1,5 +1,6 @@
import { HomeAssistant, CameraEntity } from "../types";
import { timeCachePromiseFunc } from "../common/util/time-cache-function-promise";
import { getSignedPath } from "./auth";
export const CAMERA_SUPPORT_ON_OFF = 1;
export const CAMERA_SUPPORT_STREAM = 2;
@ -22,16 +23,29 @@ export const computeMJPEGStreamUrl = (entity: CameraEntity) =>
entity.attributes.access_token
}`;
export const fetchThumbnailWithCache = (
export const fetchThumbnailUrlWithCache = (
hass: HomeAssistant,
entityId: string
) => timeCachePromiseFunc("_cameraTmb", 9000, fetchThumbnail, hass, entityId);
) =>
timeCachePromiseFunc(
"_cameraTmbUrl",
9000,
fetchThumbnailUrl,
hass,
entityId
);
export const fetchThumbnail = (hass: HomeAssistant, entityId: string) =>
hass.callWS<CameraThumbnail>({
export const fetchThumbnailUrl = (hass: HomeAssistant, entityId: string) =>
getSignedPath(hass, `/api/camera_proxy/${entityId}`).then(({ path }) => path);
export const fetchThumbnail = (hass: HomeAssistant, entityId: string) => {
// tslint:disable-next-line: no-console
console.warn("This method has been deprecated.");
return hass.callWS<CameraThumbnail>({
type: "camera_thumbnail",
entity_id: entityId,
});
};
export const fetchStreamUrl = (
hass: HomeAssistant,

View File

@ -17,8 +17,7 @@ import {
import { HomeAssistant, CameraEntity } from "../../../types";
import { styleMap } from "lit-html/directives/style-map";
import { classMap } from "lit-html/directives/class-map";
import { b64toBlob } from "../../../common/file/b64-to-blob";
import { fetchThumbnailWithCache } from "../../../data/camera";
import { fetchThumbnailUrlWithCache } from "../../../data/camera";
const UPDATE_INTERVAL = 10000;
const DEFAULT_FILTER = "grayscale(100%)";
@ -197,21 +196,20 @@ export class HuiImage extends LitElement {
if (!this.hass || !this.cameraImage) {
return;
}
try {
const {
content_type: contentType,
content,
} = await fetchThumbnailWithCache(this.hass, this.cameraImage);
if (this._cameraImageSrc) {
URL.revokeObjectURL(this._cameraImageSrc);
}
this._cameraImageSrc = URL.createObjectURL(
b64toBlob(content, contentType)
);
this._onImageLoad();
} catch (err) {
const cameraState = this.hass.states[this.cameraImage] as
| CameraEntity
| undefined;
if (!cameraState) {
this._onImageError();
return;
}
this._cameraImageSrc = await fetchThumbnailUrlWithCache(
this.hass,
this.cameraImage
);
}
static get styles(): CSSResult {