From 38b01e9335f04516554df788966804c20dfaec9b Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 16 Jan 2024 21:29:08 -0500 Subject: [PATCH] Add a download button to history panel --- src/panels/history/ha-panel-history.ts | 40 +++++++++++++++++++++++++- src/translations/en.json | 3 +- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/panels/history/ha-panel-history.ts b/src/panels/history/ha-panel-history.ts index 75a2b99265..67b481b71b 100644 --- a/src/panels/history/ha-panel-history.ts +++ b/src/panels/history/ha-panel-history.ts @@ -1,4 +1,4 @@ -import { mdiFilterRemove, mdiRefresh } from "@mdi/js"; +import { mdiDownload, mdiFilterRemove, mdiRefresh } from "@mdi/js"; import { differenceInHours } from "date-fns/esm"; import { HassServiceTarget, @@ -53,6 +53,7 @@ import { getSensorNumericDeviceClasses } from "../../data/sensor"; import { SubscribeMixin } from "../../mixins/subscribe-mixin"; import { haStyle } from "../../resources/styles"; import { HomeAssistant } from "../../types"; +import { fileDownload } from "../../util/file_download"; class HaPanelHistory extends SubscribeMixin(LitElement) { @property({ attribute: false }) hass!: HomeAssistant; @@ -172,6 +173,13 @@ class HaPanelHistory extends SubscribeMixin(LitElement) { .path=${mdiRefresh} .label=${this.hass.localize("ui.common.refresh")} > +
@@ -630,6 +638,36 @@ class HaPanelHistory extends SubscribeMixin(LitElement) { navigate(`/history?${createSearchParam(params)}`, { replace: true }); } + private _downloadHistory() { + const csv: string[] = ["entity_id,state,last_changed\n"]; + const formatDate = (number) => new Date(number).toISOString(); + + for (const line of this._mungedStateHistory!.line) { + for (const entity of line.data) { + const entityId = entity.entity_id; + for (const data of [entity.states, entity.statistics]) { + if (!data) { + continue; + } + for (const s of data) { + csv.push(`${entityId},${s.state},${formatDate(s.last_changed)}\n`); + } + } + } + } + for (const timeline of this._mungedStateHistory!.timeline) { + const entityId = timeline.entity_id; + for (const s of timeline.data) { + csv.push(`${entityId},${s.state},${formatDate(s.last_changed)}\n`); + } + } + const blob = new Blob(csv, { + type: "text/csv", + }); + const url = window.URL.createObjectURL(blob); + fileDownload(url, "history.csv"); + } + static get styles() { return [ haStyle, diff --git a/src/translations/en.json b/src/translations/en.json index 6ea99bc0ad..08e3980d54 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -6412,7 +6412,8 @@ "history": { "start_search": "Start by selecting an area, device or entity above", "add_all": "Add all entities", - "remove_all": "Remove all selections" + "remove_all": "Remove all selections", + "download_data": "Download data" } }, "tips": {