mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-23 09:16:38 +00:00
Adjust traces to latest API (#8656)
This commit is contained in:
parent
f34dfde925
commit
3c75eb96f1
@ -15,6 +15,7 @@ export const basicTrace: DemoTrace = {
|
|||||||
action_trace: {
|
action_trace: {
|
||||||
"action/0": [
|
"action/0": [
|
||||||
{
|
{
|
||||||
|
path: "action/0",
|
||||||
timestamp: "2021-03-12T21:38:48.054395+00:00",
|
timestamp: "2021-03-12T21:38:48.054395+00:00",
|
||||||
changed_variables: {
|
changed_variables: {
|
||||||
trigger: {
|
trigger: {
|
||||||
@ -60,6 +61,7 @@ export const basicTrace: DemoTrace = {
|
|||||||
condition_trace: {
|
condition_trace: {
|
||||||
"condition/0": [
|
"condition/0": [
|
||||||
{
|
{
|
||||||
|
path: "condition/0",
|
||||||
timestamp: "2021-03-12T21:38:48.050783+00:00",
|
timestamp: "2021-03-12T21:38:48.050783+00:00",
|
||||||
changed_variables: {
|
changed_variables: {
|
||||||
trigger: {
|
trigger: {
|
||||||
|
@ -1,187 +0,0 @@
|
|||||||
import { DemoTrace } from "./types";
|
|
||||||
|
|
||||||
export const deviceTriggerEventTrace: DemoTrace = {
|
|
||||||
trace: {
|
|
||||||
last_action: "action/0",
|
|
||||||
last_condition: null,
|
|
||||||
run_id: "3",
|
|
||||||
state: "stopped",
|
|
||||||
timestamp: {
|
|
||||||
start: "2021-03-13T10:30:30.058878+00:00",
|
|
||||||
finish: "2021-03-13T10:30:30.205801+00:00",
|
|
||||||
},
|
|
||||||
trigger: "event 'lutron_caseta_button_event'",
|
|
||||||
unique_id: "1578616228911",
|
|
||||||
action_trace: {
|
|
||||||
"action/0": [
|
|
||||||
{
|
|
||||||
timestamp: "2021-03-13T10:30:30.059607+00:00",
|
|
||||||
changed_variables: {
|
|
||||||
trigger: {
|
|
||||||
platform: "device",
|
|
||||||
event: {
|
|
||||||
event_type: "lutron_caseta_button_event",
|
|
||||||
data: {
|
|
||||||
serial: 47850540,
|
|
||||||
type: "Pico3ButtonRaiseLower",
|
|
||||||
button_number: 4,
|
|
||||||
device_name: "Right Light Pico",
|
|
||||||
area_name: "Master Bed",
|
|
||||||
action: "press",
|
|
||||||
},
|
|
||||||
origin: "LOCAL",
|
|
||||||
time_fired: "2021-03-13T10:30:30.053185+00:00",
|
|
||||||
context: {
|
|
||||||
id: "e5387dff0c615c67e8fa43bf9d5d72ca",
|
|
||||||
parent_id: null,
|
|
||||||
user_id: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
description: "event 'lutron_caseta_button_event'",
|
|
||||||
},
|
|
||||||
context: {
|
|
||||||
id: "1c7d0dd26e031960e0ccbf0d9e0d8a16",
|
|
||||||
parent_id: "e5387dff0c615c67e8fa43bf9d5d72ca",
|
|
||||||
user_id: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
condition_trace: {},
|
|
||||||
config: {
|
|
||||||
id: "1578616228911",
|
|
||||||
alias: "Turn Off Master Bed Lights from Picos",
|
|
||||||
description: "",
|
|
||||||
trigger: [
|
|
||||||
{
|
|
||||||
platform: "device",
|
|
||||||
device_id: "36fd7cb4103ad0ce927e26a7ee44fa3a",
|
|
||||||
domain: "lutron_caseta",
|
|
||||||
type: "press",
|
|
||||||
subtype: "off",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
platform: "device",
|
|
||||||
device_id: "392111b5a9a362db57e2c49ec68b7a40",
|
|
||||||
domain: "lutron_caseta",
|
|
||||||
type: "press",
|
|
||||||
subtype: "off",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
condition: [],
|
|
||||||
action: [
|
|
||||||
{
|
|
||||||
entity_id: "light.master_bed_lights",
|
|
||||||
service: "light.turn_off",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
mode: "single",
|
|
||||||
},
|
|
||||||
context: {
|
|
||||||
id: "1c7d0dd26e031960e0ccbf0d9e0d8a16",
|
|
||||||
parent_id: "e5387dff0c615c67e8fa43bf9d5d72ca",
|
|
||||||
user_id: null,
|
|
||||||
},
|
|
||||||
variables: {
|
|
||||||
trigger: {
|
|
||||||
platform: "device",
|
|
||||||
event: {
|
|
||||||
event_type: "lutron_caseta_button_event",
|
|
||||||
data: {
|
|
||||||
serial: 47850540,
|
|
||||||
type: "Pico3ButtonRaiseLower",
|
|
||||||
button_number: 4,
|
|
||||||
device_name: "Right Light Pico",
|
|
||||||
area_name: "Master Bed",
|
|
||||||
action: "press",
|
|
||||||
},
|
|
||||||
origin: "LOCAL",
|
|
||||||
time_fired: "2021-03-13T10:30:30.053185+00:00",
|
|
||||||
context: {
|
|
||||||
id: "e5387dff0c615c67e8fa43bf9d5d72ca",
|
|
||||||
parent_id: null,
|
|
||||||
user_id: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
description: "event 'lutron_caseta_button_event'",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
logbookEntries: [
|
|
||||||
{
|
|
||||||
name: "Turn Off Master Bed Lights from Picos",
|
|
||||||
message: "has been triggered by event 'lutron_caseta_button_event'",
|
|
||||||
source: "event 'lutron_caseta_button_event'",
|
|
||||||
entity_id: "automation.turn_off_master_bed_lights_from_picos",
|
|
||||||
when: "2021-03-13T10:30:30.059052+00:00",
|
|
||||||
domain: "automation",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
when: "2021-03-13T10:30:30.200532+00:00",
|
|
||||||
name: "Master Bed Lights",
|
|
||||||
state: "off",
|
|
||||||
entity_id: "light.master_bed_lights",
|
|
||||||
context_entity_id: "automation.turn_off_master_bed_lights_from_picos",
|
|
||||||
context_entity_id_name: "Turn Off Master Bed Lights from Picos",
|
|
||||||
context_event_type: "automation_triggered",
|
|
||||||
context_domain: "automation",
|
|
||||||
context_name: "Turn Off Master Bed Lights from Picos",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
when: "2021-03-13T10:30:30.200532+00:00",
|
|
||||||
name: "Master Bed Lights",
|
|
||||||
state: "off",
|
|
||||||
entity_id: "light.master_bed_lights",
|
|
||||||
context_entity_id: "automation.turn_off_master_bed_lights_from_picos",
|
|
||||||
context_entity_id_name: "Turn Off Master Bed Lights from Picos",
|
|
||||||
context_event_type: "automation_triggered",
|
|
||||||
context_domain: "automation",
|
|
||||||
context_name: "Turn Off Master Bed Lights from Picos",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
when: "2021-03-13T10:30:30.200532+00:00",
|
|
||||||
name: "Master Bed Lights",
|
|
||||||
state: "off",
|
|
||||||
entity_id: "light.master_bed_lights",
|
|
||||||
context_entity_id: "automation.turn_off_master_bed_lights_from_picos",
|
|
||||||
context_entity_id_name: "Turn Off Master Bed Lights from Picos",
|
|
||||||
context_event_type: "automation_triggered",
|
|
||||||
context_domain: "automation",
|
|
||||||
context_name: "Turn Off Master Bed Lights from Picos",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
when: "2021-03-13T10:30:30.200532+00:00",
|
|
||||||
name: "Master Bed Lights",
|
|
||||||
state: "off",
|
|
||||||
entity_id: "light.master_bed_lights",
|
|
||||||
context_entity_id: "automation.turn_off_master_bed_lights_from_picos",
|
|
||||||
context_entity_id_name: "Turn Off Master Bed Lights from Picos",
|
|
||||||
context_event_type: "automation_triggered",
|
|
||||||
context_domain: "automation",
|
|
||||||
context_name: "Turn Off Master Bed Lights from Picos",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
when: "2021-03-13T10:30:30.200532+00:00",
|
|
||||||
name: "Master Bed Lights",
|
|
||||||
state: "off",
|
|
||||||
entity_id: "light.master_bed_lights",
|
|
||||||
context_entity_id: "automation.turn_off_master_bed_lights_from_picos",
|
|
||||||
context_entity_id_name: "Turn Off Master Bed Lights from Picos",
|
|
||||||
context_event_type: "automation_triggered",
|
|
||||||
context_domain: "automation",
|
|
||||||
context_name: "Turn Off Master Bed Lights from Picos",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
when: "2021-03-13T10:30:30.200532+00:00",
|
|
||||||
name: "Master Bed Lights",
|
|
||||||
state: "off",
|
|
||||||
entity_id: "light.master_bed_lights",
|
|
||||||
context_entity_id: "automation.turn_off_master_bed_lights_from_picos",
|
|
||||||
context_entity_id_name: "Turn Off Master Bed Lights from Picos",
|
|
||||||
context_event_type: "automation_triggered",
|
|
||||||
context_domain: "automation",
|
|
||||||
context_name: "Turn Off Master Bed Lights from Picos",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
@ -15,6 +15,7 @@ export const motionLightTrace: DemoTrace = {
|
|||||||
action_trace: {
|
action_trace: {
|
||||||
"action/0": [
|
"action/0": [
|
||||||
{
|
{
|
||||||
|
path: "action/0",
|
||||||
timestamp: "2021-03-14T06:07:01.771038+00:00",
|
timestamp: "2021-03-14T06:07:01.771038+00:00",
|
||||||
changed_variables: {
|
changed_variables: {
|
||||||
trigger: {
|
trigger: {
|
||||||
@ -64,12 +65,11 @@ export const motionLightTrace: DemoTrace = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
"action/1": [
|
"action/1": [
|
||||||
{
|
{ path: "action/1", timestamp: "2021-03-14T06:07:01.875316+00:00" },
|
||||||
timestamp: "2021-03-14T06:07:01.875316+00:00",
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
"action/2": [
|
"action/2": [
|
||||||
{
|
{
|
||||||
|
path: "action/2",
|
||||||
timestamp: "2021-03-14T06:07:53.195013+00:00",
|
timestamp: "2021-03-14T06:07:53.195013+00:00",
|
||||||
changed_variables: {
|
changed_variables: {
|
||||||
wait: {
|
wait: {
|
||||||
@ -118,6 +118,7 @@ export const motionLightTrace: DemoTrace = {
|
|||||||
],
|
],
|
||||||
"action/3": [
|
"action/3": [
|
||||||
{
|
{
|
||||||
|
path: "action/3",
|
||||||
timestamp: "2021-03-14T06:07:53.196014+00:00",
|
timestamp: "2021-03-14T06:07:53.196014+00:00",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -13,13 +13,8 @@ import { HomeAssistant } from "../../../src/types";
|
|||||||
import { DemoTrace } from "../data/traces/types";
|
import { DemoTrace } from "../data/traces/types";
|
||||||
import { basicTrace } from "../data/traces/basic_trace";
|
import { basicTrace } from "../data/traces/basic_trace";
|
||||||
import { motionLightTrace } from "../data/traces/motion-light-trace";
|
import { motionLightTrace } from "../data/traces/motion-light-trace";
|
||||||
import { deviceTriggerEventTrace } from "../data/traces/device_trigger_event_trace";
|
|
||||||
|
|
||||||
const traces: DemoTrace[] = [
|
const traces: DemoTrace[] = [basicTrace, motionLightTrace];
|
||||||
basicTrace,
|
|
||||||
motionLightTrace,
|
|
||||||
deviceTriggerEventTrace,
|
|
||||||
];
|
|
||||||
|
|
||||||
@customElement("demo-automation-trace")
|
@customElement("demo-automation-trace")
|
||||||
export class DemoAutomationTrace extends LitElement {
|
export class DemoAutomationTrace extends LitElement {
|
||||||
|
@ -11,7 +11,7 @@ import { formatDateTimeWithSeconds } from "../../common/datetime/format_date_tim
|
|||||||
import {
|
import {
|
||||||
ActionTrace,
|
ActionTrace,
|
||||||
AutomationTraceExtended,
|
AutomationTraceExtended,
|
||||||
getConfigFromPath,
|
getDataFromPath,
|
||||||
} from "../../data/automation_debug";
|
} from "../../data/automation_debug";
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
import "./ha-timeline";
|
import "./ha-timeline";
|
||||||
@ -24,7 +24,7 @@ import {
|
|||||||
mdiStopCircleOutline,
|
mdiStopCircleOutline,
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
import { LogbookEntry } from "../../data/logbook";
|
import { LogbookEntry } from "../../data/logbook";
|
||||||
import { Action, describeAction } from "../../data/script";
|
import { describeAction } from "../../data/script";
|
||||||
import relativeTime from "../../common/datetime/relative_time";
|
import relativeTime from "../../common/datetime/relative_time";
|
||||||
|
|
||||||
const LOGBOOK_ENTRIES_BEFORE_FOLD = 2;
|
const LOGBOOK_ENTRIES_BEFORE_FOLD = 2;
|
||||||
@ -68,7 +68,7 @@ export class HaAutomationTracer extends LitElement {
|
|||||||
? mdiCheckCircleOutline
|
? mdiCheckCircleOutline
|
||||||
: mdiStopCircleOutline}
|
: mdiStopCircleOutline}
|
||||||
>
|
>
|
||||||
${getConfigFromPath(this.trace!.config, path).alias ||
|
${getDataFromPath(this.trace!.config, path).alias ||
|
||||||
pathToName(path)}
|
pathToName(path)}
|
||||||
${value[0].result.result ? "passed" : "failed"}
|
${value[0].result.result ? "passed" : "failed"}
|
||||||
</ha-timeline>
|
</ha-timeline>
|
||||||
@ -77,7 +77,7 @@ export class HaAutomationTracer extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.trace.action_trace && this.logbookEntries) {
|
if (this.trace.action_trace && this.logbookEntries) {
|
||||||
const actionTraces = Object.entries(this.trace.action_trace);
|
const actionTraces = Object.values(this.trace.action_trace);
|
||||||
|
|
||||||
let logbookIndex = 0;
|
let logbookIndex = 0;
|
||||||
let actionTraceIndex = 0;
|
let actionTraceIndex = 0;
|
||||||
@ -123,7 +123,7 @@ export class HaAutomationTracer extends LitElement {
|
|||||||
// Find next item time-wise.
|
// Find next item time-wise.
|
||||||
const logbookItem = this.logbookEntries[logbookIndex];
|
const logbookItem = this.logbookEntries[logbookIndex];
|
||||||
const actionTrace = actionTraces[actionTraceIndex];
|
const actionTrace = actionTraces[actionTraceIndex];
|
||||||
const actionTimestamp = new Date(actionTrace[1][0].timestamp);
|
const actionTimestamp = new Date(actionTrace[0].timestamp);
|
||||||
|
|
||||||
if (new Date(logbookItem.when) > actionTimestamp) {
|
if (new Date(logbookItem.when) > actionTimestamp) {
|
||||||
actionTraceIndex++;
|
actionTraceIndex++;
|
||||||
@ -133,7 +133,7 @@ export class HaAutomationTracer extends LitElement {
|
|||||||
groupedLogbookItems = [];
|
groupedLogbookItems = [];
|
||||||
}
|
}
|
||||||
maybeRenderTime(actionTimestamp);
|
maybeRenderTime(actionTimestamp);
|
||||||
entries.push(this._renderActionTrace(...actionTrace));
|
entries.push(this._renderActionTrace(actionTrace));
|
||||||
} else {
|
} else {
|
||||||
logbookIndex++;
|
logbookIndex++;
|
||||||
groupedLogbookItems.push(logbookItem);
|
groupedLogbookItems.push(logbookItem);
|
||||||
@ -152,8 +152,8 @@ export class HaAutomationTracer extends LitElement {
|
|||||||
|
|
||||||
while (actionTraceIndex < actionTraces.length) {
|
while (actionTraceIndex < actionTraces.length) {
|
||||||
const trace = actionTraces[actionTraceIndex];
|
const trace = actionTraces[actionTraceIndex];
|
||||||
maybeRenderTime(new Date(trace[1][0].timestamp));
|
maybeRenderTime(new Date(trace[0].timestamp));
|
||||||
entries.push(this._renderActionTrace(...trace));
|
entries.push(this._renderActionTrace(trace));
|
||||||
actionTraceIndex++;
|
actionTraceIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -221,11 +221,25 @@ export class HaAutomationTracer extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderActionTrace(path: string, _value: ActionTrace[]) {
|
private _renderActionTrace(value: ActionTrace[]) {
|
||||||
const action = getConfigFromPath(this.trace!.config, path) as Action;
|
const path = value[0].path;
|
||||||
|
let data;
|
||||||
|
try {
|
||||||
|
data = getDataFromPath(this.trace!.config, path);
|
||||||
|
} catch (err) {
|
||||||
|
return html`Unable to extract path ${path}. Download trace and report as
|
||||||
|
bug`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const description =
|
||||||
|
// Top-level we know it's an action
|
||||||
|
path.split("/").length === 2
|
||||||
|
? data.alias || describeAction(data, this.hass.localize)
|
||||||
|
: path.replace(/\//g, " ");
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-timeline .icon=${mdiRecordCircleOutline}>
|
<ha-timeline .icon=${mdiRecordCircleOutline}>
|
||||||
${action.alias || describeAction(action, this.hass.localize)}
|
${description}
|
||||||
</ha-timeline>
|
</ha-timeline>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ export interface ManualAutomationConfig {
|
|||||||
| "info"
|
| "info"
|
||||||
| "debug"
|
| "debug"
|
||||||
| "notset";
|
| "notset";
|
||||||
|
variables?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BlueprintAutomationConfig extends ManualAutomationConfig {
|
export interface BlueprintAutomationConfig extends ManualAutomationConfig {
|
||||||
@ -55,7 +56,7 @@ export interface StateTrigger {
|
|||||||
entity_id: string;
|
entity_id: string;
|
||||||
attribute?: string;
|
attribute?: string;
|
||||||
from?: string | number;
|
from?: string | number;
|
||||||
to?: string | number;
|
to?: string | string[] | number;
|
||||||
for?: string | number | ForDict;
|
for?: string | number | ForDict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { HomeAssistant, Context } from "../types";
|
import { HomeAssistant, Context } from "../types";
|
||||||
import { AutomationConfig, Condition } from "./automation";
|
import { AutomationConfig } from "./automation";
|
||||||
import { Action } from "./script";
|
|
||||||
|
|
||||||
interface TraceVariables extends Record<string, unknown> {
|
interface TraceVariables extends Record<string, unknown> {
|
||||||
trigger: {
|
trigger: {
|
||||||
@ -10,6 +9,7 @@ interface TraceVariables extends Record<string, unknown> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface BaseTrace {
|
interface BaseTrace {
|
||||||
|
path: string;
|
||||||
timestamp: string;
|
timestamp: string;
|
||||||
changed_variables?: Record<string, unknown>;
|
changed_variables?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
@ -18,7 +18,18 @@ export interface ConditionTrace extends BaseTrace {
|
|||||||
result: { result: boolean };
|
result: { result: boolean };
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ActionTrace = BaseTrace;
|
export interface ChooseActionTrace extends BaseTrace {
|
||||||
|
result: { choice: number };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ChooseChoiceActionTrace extends BaseTrace {
|
||||||
|
result: { result: boolean };
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ActionTrace =
|
||||||
|
| BaseTrace
|
||||||
|
| ChooseActionTrace
|
||||||
|
| ChooseChoiceActionTrace;
|
||||||
|
|
||||||
export interface AutomationTrace {
|
export interface AutomationTrace {
|
||||||
last_action: string | null;
|
last_action: string | null;
|
||||||
@ -53,16 +64,40 @@ export const loadAutomationTrace = (
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const loadAutomationTraces = (
|
export const loadAutomationTraces = (
|
||||||
hass: HomeAssistant
|
hass: HomeAssistant,
|
||||||
|
automation_id?: string
|
||||||
): Promise<AutomationTrace[]> =>
|
): Promise<AutomationTrace[]> =>
|
||||||
hass.callWS({
|
hass.callWS({
|
||||||
type: "automation/trace/list",
|
type: "automation/trace/list",
|
||||||
|
automation_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const getConfigFromPath = <T extends Condition | Action>(
|
export const getDataFromPath = (
|
||||||
config: AutomationConfig,
|
config: AutomationConfig,
|
||||||
path: string
|
path: string
|
||||||
): T => {
|
): any => {
|
||||||
const parts = path.split("/");
|
const parts = path.split("/").reverse();
|
||||||
return config[parts[0]][Number(parts[1])];
|
|
||||||
|
let result: any = config;
|
||||||
|
|
||||||
|
while (parts.length) {
|
||||||
|
const raw = parts.pop()!;
|
||||||
|
const asNumber = Number(raw);
|
||||||
|
|
||||||
|
if (isNaN(asNumber)) {
|
||||||
|
result = result[raw];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(result)) {
|
||||||
|
result = result[asNumber];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asNumber !== 0) {
|
||||||
|
throw new Error("If config is not an array, can only return index 0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
|
@ -118,6 +118,36 @@ class HaAutomationPicker extends LitElement {
|
|||||||
></ha-icon-button>
|
></ha-icon-button>
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
columns.trace = {
|
||||||
|
title: "",
|
||||||
|
type: "icon-button",
|
||||||
|
template: (_info, automation: any) => html`
|
||||||
|
<a
|
||||||
|
href=${ifDefined(
|
||||||
|
automation.attributes.id
|
||||||
|
? `/config/automation/trace/${automation.attributes.id}`
|
||||||
|
: undefined
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<ha-icon-button
|
||||||
|
icon="hass:hammer"
|
||||||
|
.disabled=${!automation.attributes.id}
|
||||||
|
title="${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.picker.dev_automation"
|
||||||
|
)}"
|
||||||
|
></ha-icon-button>
|
||||||
|
</a>
|
||||||
|
${!automation.attributes.id
|
||||||
|
? html`
|
||||||
|
<paper-tooltip animation-delay="0" position="left">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.picker.dev_only_editable"
|
||||||
|
)}
|
||||||
|
</paper-tooltip>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
`,
|
||||||
|
};
|
||||||
columns.edit = {
|
columns.edit = {
|
||||||
title: "",
|
title: "",
|
||||||
type: "icon-button",
|
type: "icon-button",
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { AutomationEntity } from "../../../../data/automation";
|
import { AutomationEntity } from "../../../../data/automation";
|
||||||
import {
|
import {
|
||||||
|
AutomationTrace,
|
||||||
AutomationTraceExtended,
|
AutomationTraceExtended,
|
||||||
loadAutomationTrace,
|
loadAutomationTrace,
|
||||||
loadAutomationTraces,
|
loadAutomationTraces,
|
||||||
@ -23,6 +24,9 @@ import {
|
|||||||
getLogbookDataForContext,
|
getLogbookDataForContext,
|
||||||
LogbookEntry,
|
LogbookEntry,
|
||||||
} from "../../../../data/logbook";
|
} from "../../../../data/logbook";
|
||||||
|
import { formatDateTimeWithSeconds } from "../../../../common/datetime/format_date_time";
|
||||||
|
import { repeat } from "lit-html/directives/repeat";
|
||||||
|
import { showAlertDialog } from "../../../../dialogs/generic/show-dialog-box";
|
||||||
|
|
||||||
@customElement("ha-automation-trace")
|
@customElement("ha-automation-trace")
|
||||||
export class HaAutomationTrace extends LitElement {
|
export class HaAutomationTrace extends LitElement {
|
||||||
@ -40,6 +44,10 @@ export class HaAutomationTrace extends LitElement {
|
|||||||
|
|
||||||
@internalProperty() private _entityId?: string;
|
@internalProperty() private _entityId?: string;
|
||||||
|
|
||||||
|
@internalProperty() private _traces?: AutomationTrace[];
|
||||||
|
|
||||||
|
@internalProperty() private _runId?: string;
|
||||||
|
|
||||||
@internalProperty() private _trace?: AutomationTraceExtended;
|
@internalProperty() private _trace?: AutomationTraceExtended;
|
||||||
|
|
||||||
@internalProperty() private _logbookEntries?: LogbookEntry[];
|
@internalProperty() private _logbookEntries?: LogbookEntry[];
|
||||||
@ -63,24 +71,45 @@ export class HaAutomationTrace extends LitElement {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<button @click=${this._loadTrace}>
|
${this._traces && this._traces.length > 0
|
||||||
Load last trace
|
? html`
|
||||||
|
<select .value=${this._runId} @change=${this._pickTrace}>
|
||||||
|
${repeat(
|
||||||
|
this._traces,
|
||||||
|
(trace) => trace.run_id,
|
||||||
|
(trace) =>
|
||||||
|
html`<option value=${trace.run_id}
|
||||||
|
>${formatDateTimeWithSeconds(
|
||||||
|
new Date(trace.timestamp.start),
|
||||||
|
this.hass.language
|
||||||
|
)}</option
|
||||||
|
>`
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
<button @click=${this._loadTraces}>
|
||||||
|
Refresh
|
||||||
</button>
|
</button>
|
||||||
<button @click=${this._downloadTrace}>
|
<button @click=${this._downloadTrace}>
|
||||||
Download
|
Download
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
${this._trace
|
<div class="card-content">
|
||||||
? html`
|
${this._traces === undefined
|
||||||
<div class="card-content">
|
? "Loading…"
|
||||||
|
: this._traces.length === 0
|
||||||
|
? "No traces found"
|
||||||
|
: this._trace === undefined
|
||||||
|
? "Loading…"
|
||||||
|
: html`
|
||||||
<hat-trace
|
<hat-trace
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.trace=${this._trace}
|
.trace=${this._trace}
|
||||||
.logbookEntries=${this._logbookEntries}
|
.logbookEntries=${this._logbookEntries}
|
||||||
></hat-trace>
|
></hat-trace>
|
||||||
</div>
|
`}
|
||||||
`
|
</div>
|
||||||
: ""}
|
|
||||||
</ha-card>
|
</ha-card>
|
||||||
</hass-tabs-subpage>
|
</hass-tabs-subpage>
|
||||||
`;
|
`;
|
||||||
@ -90,10 +119,22 @@ export class HaAutomationTrace extends LitElement {
|
|||||||
super.updated(changedProps);
|
super.updated(changedProps);
|
||||||
|
|
||||||
if (changedProps.has("automationId")) {
|
if (changedProps.has("automationId")) {
|
||||||
|
this._traces = undefined;
|
||||||
this._entityId = undefined;
|
this._entityId = undefined;
|
||||||
|
this._runId = undefined;
|
||||||
this._trace = undefined;
|
this._trace = undefined;
|
||||||
this._logbookEntries = undefined;
|
this._logbookEntries = undefined;
|
||||||
this._loadTrace();
|
if (this.automationId) {
|
||||||
|
this._loadTraces();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changedProps.has("_runId") && this._runId) {
|
||||||
|
this._trace = undefined;
|
||||||
|
this._logbookEntries = undefined;
|
||||||
|
if (this._runId) {
|
||||||
|
this._loadTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -101,24 +142,44 @@ export class HaAutomationTrace extends LitElement {
|
|||||||
this.automationId &&
|
this.automationId &&
|
||||||
!this._entityId
|
!this._entityId
|
||||||
) {
|
) {
|
||||||
this._setEntityId();
|
const automation = this.automations.find(
|
||||||
|
(entity: AutomationEntity) => entity.attributes.id === this.automationId
|
||||||
|
);
|
||||||
|
this._entityId = automation?.entity_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _pickTrace(ev) {
|
||||||
|
this._runId = ev.target.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _loadTraces() {
|
||||||
|
this._traces = await loadAutomationTraces(this.hass, this.automationId);
|
||||||
|
// Newest will be on top.
|
||||||
|
this._traces.reverse();
|
||||||
|
|
||||||
|
// Check if current run ID still exists
|
||||||
|
if (
|
||||||
|
this._runId &&
|
||||||
|
!this._traces.some((trace) => trace.run_id === this._runId)
|
||||||
|
) {
|
||||||
|
await showAlertDialog(this, {
|
||||||
|
text: "Chosen trace is no longer available",
|
||||||
|
});
|
||||||
|
this._runId = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if we can set a default runID
|
||||||
|
if (!this._runId && this._traces.length > 0) {
|
||||||
|
this._runId = this._traces[0].run_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _loadTrace() {
|
private async _loadTrace() {
|
||||||
const traces = await loadAutomationTraces(this.hass);
|
|
||||||
const automationTraces = traces[this.automationId];
|
|
||||||
|
|
||||||
if (!automationTraces || automationTraces.length === 0) {
|
|
||||||
// TODO no trace found.
|
|
||||||
alert("NO traces found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const trace = await loadAutomationTrace(
|
const trace = await loadAutomationTrace(
|
||||||
this.hass,
|
this.hass,
|
||||||
this.automationId,
|
this.automationId,
|
||||||
automationTraces[automationTraces.length - 1].run_id
|
this._runId!
|
||||||
);
|
);
|
||||||
this._logbookEntries = await getLogbookDataForContext(
|
this._logbookEntries = await getLogbookDataForContext(
|
||||||
this.hass,
|
this.hass,
|
||||||
@ -129,20 +190,15 @@ export class HaAutomationTrace extends LitElement {
|
|||||||
this._trace = trace;
|
this._trace = trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _setEntityId() {
|
|
||||||
const automation = this.automations.find(
|
|
||||||
(entity: AutomationEntity) => entity.attributes.id === this.automationId
|
|
||||||
);
|
|
||||||
this._entityId = automation?.entity_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _backTapped(): void {
|
private _backTapped(): void {
|
||||||
history.back();
|
history.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _downloadTrace() {
|
private _downloadTrace() {
|
||||||
const aEl = document.createElement("a");
|
const aEl = document.createElement("a");
|
||||||
aEl.download = `trace-${this._entityId}.json`;
|
aEl.download = `trace ${this._entityId} ${
|
||||||
|
this._trace!.timestamp.start
|
||||||
|
}.json`;
|
||||||
aEl.href = `data:application/json;charset=utf-8,${encodeURI(
|
aEl.href = `data:application/json;charset=utf-8,${encodeURI(
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
{
|
{
|
||||||
|
@ -1180,7 +1180,9 @@
|
|||||||
"no_automations": "We couldn’t find any editable automations",
|
"no_automations": "We couldn’t find any editable automations",
|
||||||
"add_automation": "Add automation",
|
"add_automation": "Add automation",
|
||||||
"only_editable": "Only automations defined in automations.yaml are editable.",
|
"only_editable": "Only automations defined in automations.yaml are editable.",
|
||||||
|
"dev_only_editable": "Only automations defined in automations.yaml are debuggable.",
|
||||||
"edit_automation": "Edit automation",
|
"edit_automation": "Edit automation",
|
||||||
|
"dev_automation": "Debug automation",
|
||||||
"show_info_automation": "Show info about automation",
|
"show_info_automation": "Show info about automation",
|
||||||
"delete_automation": "Delete automation",
|
"delete_automation": "Delete automation",
|
||||||
"delete_confirm": "Are you sure you want to delete this automation?",
|
"delete_confirm": "Are you sure you want to delete this automation?",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user