mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-27 19:26:36 +00:00
Adjust for latest trace API (#8755)
This commit is contained in:
parent
46580376dd
commit
b866166425
@ -13,7 +13,55 @@ export const basicTrace: DemoTrace = {
|
|||||||
trigger: "state of input_boolean.toggle_1",
|
trigger: "state of input_boolean.toggle_1",
|
||||||
domain: "automation",
|
domain: "automation",
|
||||||
item_id: "1615419646544",
|
item_id: "1615419646544",
|
||||||
action_trace: {
|
trace: {
|
||||||
|
"condition/0": [
|
||||||
|
{
|
||||||
|
path: "condition/0",
|
||||||
|
timestamp: "2021-03-25T04:36:51.228243+00:00",
|
||||||
|
changed_variables: {
|
||||||
|
trigger: {
|
||||||
|
platform: "state",
|
||||||
|
entity_id: "input_boolean.toggle_1",
|
||||||
|
from_state: {
|
||||||
|
entity_id: "input_boolean.toggle_1",
|
||||||
|
state: "on",
|
||||||
|
attributes: {
|
||||||
|
editable: true,
|
||||||
|
friendly_name: "Toggle 1",
|
||||||
|
},
|
||||||
|
last_changed: "2021-03-24T19:03:59.141440+00:00",
|
||||||
|
last_updated: "2021-03-24T19:03:59.141440+00:00",
|
||||||
|
context: {
|
||||||
|
id: "5d0918eb379214d07554bdab6a08bcff",
|
||||||
|
parent_id: null,
|
||||||
|
user_id: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
to_state: {
|
||||||
|
entity_id: "input_boolean.toggle_1",
|
||||||
|
state: "off",
|
||||||
|
attributes: {
|
||||||
|
editable: true,
|
||||||
|
friendly_name: "Toggle 1",
|
||||||
|
},
|
||||||
|
last_changed: "2021-03-25T04:36:51.220696+00:00",
|
||||||
|
last_updated: "2021-03-25T04:36:51.220696+00:00",
|
||||||
|
context: {
|
||||||
|
id: "664d6d261450a9ecea6738e97269a149",
|
||||||
|
parent_id: null,
|
||||||
|
user_id: "d1b4e89da01445fa8bc98e39fac477ca",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
for: null,
|
||||||
|
attribute: null,
|
||||||
|
description: "state of input_boolean.toggle_1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
result: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
"action/0": [
|
"action/0": [
|
||||||
{
|
{
|
||||||
path: "action/0",
|
path: "action/0",
|
||||||
@ -158,56 +206,7 @@ export const basicTrace: DemoTrace = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
condition_trace: {
|
|
||||||
"condition/0": [
|
|
||||||
{
|
|
||||||
path: "condition/0",
|
|
||||||
timestamp: "2021-03-25T04:36:51.228243+00:00",
|
|
||||||
changed_variables: {
|
|
||||||
trigger: {
|
|
||||||
platform: "state",
|
|
||||||
entity_id: "input_boolean.toggle_1",
|
|
||||||
from_state: {
|
|
||||||
entity_id: "input_boolean.toggle_1",
|
|
||||||
state: "on",
|
|
||||||
attributes: {
|
|
||||||
editable: true,
|
|
||||||
friendly_name: "Toggle 1",
|
|
||||||
},
|
|
||||||
last_changed: "2021-03-24T19:03:59.141440+00:00",
|
|
||||||
last_updated: "2021-03-24T19:03:59.141440+00:00",
|
|
||||||
context: {
|
|
||||||
id: "5d0918eb379214d07554bdab6a08bcff",
|
|
||||||
parent_id: null,
|
|
||||||
user_id: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
to_state: {
|
|
||||||
entity_id: "input_boolean.toggle_1",
|
|
||||||
state: "off",
|
|
||||||
attributes: {
|
|
||||||
editable: true,
|
|
||||||
friendly_name: "Toggle 1",
|
|
||||||
},
|
|
||||||
last_changed: "2021-03-25T04:36:51.220696+00:00",
|
|
||||||
last_updated: "2021-03-25T04:36:51.220696+00:00",
|
|
||||||
context: {
|
|
||||||
id: "664d6d261450a9ecea6738e97269a149",
|
|
||||||
parent_id: null,
|
|
||||||
user_id: "d1b4e89da01445fa8bc98e39fac477ca",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
for: null,
|
|
||||||
attribute: null,
|
|
||||||
description: "state of input_boolean.toggle_1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
result: {
|
|
||||||
result: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
config: {
|
config: {
|
||||||
id: "1615419646544",
|
id: "1615419646544",
|
||||||
alias: "Ensure Party mode",
|
alias: "Ensure Party mode",
|
||||||
|
@ -13,7 +13,7 @@ export const motionLightTrace: DemoTrace = {
|
|||||||
trigger: "state of binary_sensor.pauluss_macbook_pro_camera_in_use",
|
trigger: "state of binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||||
domain: "automation",
|
domain: "automation",
|
||||||
item_id: "1614732497392",
|
item_id: "1614732497392",
|
||||||
action_trace: {
|
trace: {
|
||||||
"action/0": [
|
"action/0": [
|
||||||
{
|
{
|
||||||
path: "action/0",
|
path: "action/0",
|
||||||
@ -124,7 +124,6 @@ export const motionLightTrace: DemoTrace = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
condition_trace: {},
|
|
||||||
config: {
|
config: {
|
||||||
mode: "restart",
|
mode: "restart",
|
||||||
max_exceeded: "silent",
|
max_exceeded: "silent",
|
||||||
|
@ -11,19 +11,18 @@ import {
|
|||||||
import { formatDateTimeWithSeconds } from "../../common/datetime/format_date_time";
|
import { formatDateTimeWithSeconds } from "../../common/datetime/format_date_time";
|
||||||
import {
|
import {
|
||||||
AutomationTraceExtended,
|
AutomationTraceExtended,
|
||||||
ChooseActionTrace,
|
ChooseActionTraceStep,
|
||||||
getDataFromPath,
|
getDataFromPath,
|
||||||
|
TriggerTraceStep,
|
||||||
} from "../../data/trace";
|
} from "../../data/trace";
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
import "./ha-timeline";
|
import "./ha-timeline";
|
||||||
import type { HaTimeline } from "./ha-timeline";
|
import type { HaTimeline } from "./ha-timeline";
|
||||||
import {
|
import {
|
||||||
mdiCheckCircleOutline,
|
|
||||||
mdiCircle,
|
mdiCircle,
|
||||||
mdiCircleOutline,
|
mdiCircleOutline,
|
||||||
mdiPauseCircleOutline,
|
mdiPauseCircleOutline,
|
||||||
mdiRecordCircleOutline,
|
mdiRecordCircleOutline,
|
||||||
mdiStopCircleOutline,
|
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
import { LogbookEntry } from "../../data/logbook";
|
import { LogbookEntry } from "../../data/logbook";
|
||||||
import {
|
import {
|
||||||
@ -36,8 +35,6 @@ import { fireEvent } from "../../common/dom/fire_event";
|
|||||||
|
|
||||||
const LOGBOOK_ENTRIES_BEFORE_FOLD = 2;
|
const LOGBOOK_ENTRIES_BEFORE_FOLD = 2;
|
||||||
|
|
||||||
const pathToName = (path: string) => path.split("/").join(" ");
|
|
||||||
|
|
||||||
/* eslint max-classes-per-file: "off" */
|
/* eslint max-classes-per-file: "off" */
|
||||||
|
|
||||||
// Report time entry when more than this time has passed
|
// Report time entry when more than this time has passed
|
||||||
@ -190,12 +187,13 @@ class ActionRenderer {
|
|||||||
private keys: string[];
|
private keys: string[];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
private hass: HomeAssistant,
|
||||||
private entries: TemplateResult[],
|
private entries: TemplateResult[],
|
||||||
private trace: AutomationTraceExtended,
|
private trace: AutomationTraceExtended,
|
||||||
private logbookRenderer: LogbookRenderer,
|
private logbookRenderer: LogbookRenderer,
|
||||||
private timeTracker: RenderedTimeTracker
|
private timeTracker: RenderedTimeTracker
|
||||||
) {
|
) {
|
||||||
this.keys = Object.keys(trace.action_trace);
|
this.keys = Object.keys(trace.trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
get curItem() {
|
get curItem() {
|
||||||
@ -211,7 +209,7 @@ class ActionRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _getItem(index: number) {
|
private _getItem(index: number) {
|
||||||
return this.trace.action_trace[this.keys[index]];
|
return this.trace.trace[this.keys[index]];
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderItem(
|
private _renderItem(
|
||||||
@ -219,6 +217,11 @@ class ActionRenderer {
|
|||||||
actionType?: ReturnType<typeof getActionType>
|
actionType?: ReturnType<typeof getActionType>
|
||||||
): number {
|
): number {
|
||||||
const value = this._getItem(index);
|
const value = this._getItem(index);
|
||||||
|
|
||||||
|
if (value[0].path === "trigger") {
|
||||||
|
return this._handleTrigger(index, value[0] as TriggerTraceStep);
|
||||||
|
}
|
||||||
|
|
||||||
const timestamp = new Date(value[0].timestamp);
|
const timestamp = new Date(value[0].timestamp);
|
||||||
|
|
||||||
// Render all logbook items that are in front of this item.
|
// Render all logbook items that are in front of this item.
|
||||||
@ -262,6 +265,20 @@ class ActionRenderer {
|
|||||||
return index + 1;
|
return index + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _handleTrigger(index: number, triggerStep: TriggerTraceStep): number {
|
||||||
|
this._renderEntry(
|
||||||
|
"trigger",
|
||||||
|
`Triggered by the
|
||||||
|
${triggerStep.changed_variables.trigger.description} at
|
||||||
|
${formatDateTimeWithSeconds(
|
||||||
|
new Date(triggerStep.timestamp),
|
||||||
|
this.hass.locale
|
||||||
|
)}`,
|
||||||
|
mdiCircle
|
||||||
|
);
|
||||||
|
return index + 1;
|
||||||
|
}
|
||||||
|
|
||||||
private _handleChoose(index: number): number {
|
private _handleChoose(index: number): number {
|
||||||
// startLevel: choose root config
|
// startLevel: choose root config
|
||||||
|
|
||||||
@ -280,7 +297,7 @@ class ActionRenderer {
|
|||||||
const choosePath = this.keys[index];
|
const choosePath = this.keys[index];
|
||||||
const startLevel = choosePath.split("/").length - 1;
|
const startLevel = choosePath.split("/").length - 1;
|
||||||
|
|
||||||
const chooseTrace = this._getItem(index)[0] as ChooseActionTrace;
|
const chooseTrace = this._getItem(index)[0] as ChooseActionTraceStep;
|
||||||
const defaultExecuted = chooseTrace.result.choice === "default";
|
const defaultExecuted = chooseTrace.result.choice === "default";
|
||||||
const chooseConfig = this._getDataFromPath(
|
const chooseConfig = this._getDataFromPath(
|
||||||
this.keys[index]
|
this.keys[index]
|
||||||
@ -333,9 +350,13 @@ class ActionRenderer {
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderEntry(path: string, description: string) {
|
private _renderEntry(
|
||||||
|
path: string,
|
||||||
|
description: string,
|
||||||
|
icon = mdiRecordCircleOutline
|
||||||
|
) {
|
||||||
this.entries.push(html`
|
this.entries.push(html`
|
||||||
<ha-timeline .icon=${mdiRecordCircleOutline} data-path=${path}>
|
<ha-timeline .icon=${icon} data-path=${path}>
|
||||||
${description}
|
${description}
|
||||||
</ha-timeline>
|
</ha-timeline>
|
||||||
`);
|
`);
|
||||||
@ -362,66 +383,33 @@ export class HaAutomationTracer extends LitElement {
|
|||||||
if (!this.trace) {
|
if (!this.trace) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
const entries = [
|
|
||||||
html`
|
|
||||||
<ha-timeline .icon=${mdiCircle}>
|
|
||||||
Triggered by the ${this.trace.variables.trigger.description} at
|
|
||||||
${formatDateTimeWithSeconds(
|
|
||||||
new Date(this.trace.timestamp.start),
|
|
||||||
this.hass.locale
|
|
||||||
)}
|
|
||||||
</ha-timeline>
|
|
||||||
`,
|
|
||||||
];
|
|
||||||
|
|
||||||
if (this.trace.condition_trace) {
|
const entries: TemplateResult[] = [];
|
||||||
for (const [path, value] of Object.entries(this.trace.condition_trace)) {
|
|
||||||
entries.push(html`
|
const timeTracker = new RenderedTimeTracker(this.hass, entries, this.trace);
|
||||||
<ha-timeline
|
const logbookRenderer = new LogbookRenderer(
|
||||||
?lastItem=${!value[0].result.result}
|
entries,
|
||||||
class="condition"
|
timeTracker,
|
||||||
.icon=${value[0].result.result
|
this.logbookEntries || []
|
||||||
? mdiCheckCircleOutline
|
);
|
||||||
: mdiStopCircleOutline}
|
const actionRenderer = new ActionRenderer(
|
||||||
data-path=${path}
|
this.hass,
|
||||||
>
|
entries,
|
||||||
${getDataFromPath(this.trace!.config, path).alias ||
|
this.trace,
|
||||||
pathToName(path)}
|
logbookRenderer,
|
||||||
${value[0].result.result ? "passed" : "failed"}
|
timeTracker
|
||||||
</ha-timeline>
|
);
|
||||||
`);
|
|
||||||
}
|
while (actionRenderer.hasNext) {
|
||||||
|
actionRenderer.renderItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.trace.action_trace && this.logbookEntries) {
|
while (logbookRenderer.hasNext) {
|
||||||
const timeTracker = new RenderedTimeTracker(
|
logbookRenderer.maybeRenderItem();
|
||||||
this.hass,
|
|
||||||
entries,
|
|
||||||
this.trace
|
|
||||||
);
|
|
||||||
const logbookRenderer = new LogbookRenderer(
|
|
||||||
entries,
|
|
||||||
timeTracker,
|
|
||||||
this.logbookEntries
|
|
||||||
);
|
|
||||||
const actionRenderer = new ActionRenderer(
|
|
||||||
entries,
|
|
||||||
this.trace,
|
|
||||||
logbookRenderer,
|
|
||||||
timeTracker
|
|
||||||
);
|
|
||||||
|
|
||||||
while (actionRenderer.hasNext) {
|
|
||||||
actionRenderer.renderItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
while (logbookRenderer.hasNext) {
|
|
||||||
logbookRenderer.maybeRenderItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
logbookRenderer.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logbookRenderer.flush();
|
||||||
|
|
||||||
// null means it was stopped by a condition
|
// null means it was stopped by a condition
|
||||||
if (this.trace.last_action !== null) {
|
if (this.trace.last_action !== null) {
|
||||||
entries.push(html`
|
entries.push(html`
|
||||||
@ -456,7 +444,13 @@ export class HaAutomationTracer extends LitElement {
|
|||||||
super.updated(props);
|
super.updated(props);
|
||||||
|
|
||||||
// Pick first path when we load a new trace.
|
// Pick first path when we load a new trace.
|
||||||
if (this.allowPick && props.has("trace")) {
|
if (
|
||||||
|
this.allowPick &&
|
||||||
|
props.has("trace") &&
|
||||||
|
this.trace &&
|
||||||
|
this.selectedPath &&
|
||||||
|
!(this.selectedPath in this.trace.trace)
|
||||||
|
) {
|
||||||
const element = this.shadowRoot!.querySelector<HaTimeline>(
|
const element = this.shadowRoot!.querySelector<HaTimeline>(
|
||||||
"ha-timeline[data-path]"
|
"ha-timeline[data-path]"
|
||||||
);
|
);
|
||||||
|
@ -14,16 +14,16 @@ import {
|
|||||||
mdiCheckboxBlankOutline,
|
mdiCheckboxBlankOutline,
|
||||||
mdiAsterisk,
|
mdiAsterisk,
|
||||||
mdiDevices,
|
mdiDevices,
|
||||||
|
mdiFlare,
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { Condition } from "../../data/automation";
|
import { Condition } from "../../data/automation";
|
||||||
import { Action, ChooseAction, RepeatAction } from "../../data/script";
|
import { Action, ChooseAction, RepeatAction } from "../../data/script";
|
||||||
import {
|
import {
|
||||||
ActionTrace,
|
|
||||||
AutomationTraceExtended,
|
AutomationTraceExtended,
|
||||||
ChooseActionTrace,
|
ChooseActionTraceStep,
|
||||||
ChooseChoiceActionTrace,
|
ChooseChoiceActionTraceStep,
|
||||||
ConditionTrace,
|
ConditionTraceStep,
|
||||||
} from "../../data/trace";
|
} from "../../data/trace";
|
||||||
|
|
||||||
import { NodeInfo, TreeNode } from "./hat-graph";
|
import { NodeInfo, TreeNode } from "./hat-graph";
|
||||||
@ -106,7 +106,7 @@ export class ActionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createGraph = memoizeOne((_actions, _selected, _trace) =>
|
_createGraph = memoizeOne((_actions, _selected, _trace) =>
|
||||||
this._renderConditions().concat(
|
this._renderTraceHead().concat(
|
||||||
this.actions.map((action, idx) =>
|
this.actions.map((action, idx) =>
|
||||||
this._createTreeNode(
|
this._createTreeNode(
|
||||||
idx,
|
idx,
|
||||||
@ -118,23 +118,44 @@ export class ActionHandler {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
_renderConditions(): TreeNode[] {
|
_renderTraceHead(): TreeNode[] {
|
||||||
// action/ = default pathPrefix for trace-based actions
|
if (this.pathPrefix !== TRACE_ACTION_PREFIX) {
|
||||||
if (
|
|
||||||
this.pathPrefix !== TRACE_ACTION_PREFIX ||
|
|
||||||
!this.trace?.config.condition
|
|
||||||
) {
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return this.trace.config.condition.map((condition, idx) =>
|
|
||||||
this._createConditionNode(
|
const triggerNodeInfo = {
|
||||||
"condition/",
|
path: "trigger",
|
||||||
this.trace?.condition_trace,
|
// Just all triggers for now.
|
||||||
idx,
|
config: this.trace!.config.trigger,
|
||||||
condition,
|
};
|
||||||
!this.actions.length && this.trace!.config.condition!.length === idx + 1
|
|
||||||
)
|
const nodes: TreeNode[] = [
|
||||||
);
|
{
|
||||||
|
icon: mdiFlare,
|
||||||
|
nodeInfo: triggerNodeInfo,
|
||||||
|
clickCallback: () => {
|
||||||
|
this._selectNode(triggerNodeInfo);
|
||||||
|
},
|
||||||
|
isActive: this.selected === "trigger",
|
||||||
|
isTracked: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (this.trace!.config.condition) {
|
||||||
|
this.trace!.config.condition.forEach((condition, idx) =>
|
||||||
|
nodes.push(
|
||||||
|
this._createConditionNode(
|
||||||
|
"condition/",
|
||||||
|
idx,
|
||||||
|
condition,
|
||||||
|
!this.actions.length &&
|
||||||
|
this.trace!.config.condition!.length === idx + 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateAction(idx: number, action) {
|
_updateAction(idx: number, action) {
|
||||||
@ -192,7 +213,7 @@ export class ActionHandler {
|
|||||||
this._selectNode(nodeInfo);
|
this._selectNode(nodeInfo);
|
||||||
},
|
},
|
||||||
isActive: path === this.selected,
|
isActive: path === this.selected,
|
||||||
isTracked: this.trace && path in this.trace.action_trace,
|
isTracked: this.trace && path in this.trace.trace,
|
||||||
end,
|
end,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -212,13 +233,7 @@ export class ActionHandler {
|
|||||||
(idx: number, action: any, end: boolean) => TreeNode
|
(idx: number, action: any, end: boolean) => TreeNode
|
||||||
> = {
|
> = {
|
||||||
condition: (idx, action: Condition, end: boolean): TreeNode =>
|
condition: (idx, action: Condition, end: boolean): TreeNode =>
|
||||||
this._createConditionNode(
|
this._createConditionNode(this.pathPrefix, idx, action, end),
|
||||||
this.pathPrefix,
|
|
||||||
this.trace?.action_trace,
|
|
||||||
idx,
|
|
||||||
action,
|
|
||||||
end
|
|
||||||
),
|
|
||||||
|
|
||||||
repeat: (idx, action: RepeatAction, end: boolean): TreeNode => {
|
repeat: (idx, action: RepeatAction, end: boolean): TreeNode => {
|
||||||
let seq: Array<Action | NoAction> = action.repeat.sequence;
|
let seq: Array<Action | NoAction> = action.repeat.sequence;
|
||||||
@ -227,11 +242,10 @@ export class ActionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const path = `${this.pathPrefix}${idx}`;
|
const path = `${this.pathPrefix}${idx}`;
|
||||||
const isTracked = this.trace && path in this.trace.action_trace;
|
const isTracked = this.trace && path in this.trace.trace;
|
||||||
|
|
||||||
const repeats =
|
const repeats =
|
||||||
this.trace &&
|
this.trace && this.trace.trace[`${path}/repeat/sequence/0`]?.length;
|
||||||
this.trace.action_trace[`${path}/repeat/sequence/0`]?.length;
|
|
||||||
|
|
||||||
const nodeInfo: NodeInfo = {
|
const nodeInfo: NodeInfo = {
|
||||||
path,
|
path,
|
||||||
@ -268,10 +282,10 @@ export class ActionHandler {
|
|||||||
const choosePath = `${this.pathPrefix}${idx}`;
|
const choosePath = `${this.pathPrefix}${idx}`;
|
||||||
let choice: number | "default" | undefined;
|
let choice: number | "default" | undefined;
|
||||||
|
|
||||||
if (this.trace?.action_trace && choosePath in this.trace.action_trace) {
|
if (this.trace?.trace && choosePath in this.trace.trace) {
|
||||||
const chooseResult = this.trace.action_trace[
|
const chooseResult = this.trace.trace[
|
||||||
choosePath
|
choosePath
|
||||||
] as ChooseActionTrace[];
|
] as ChooseActionTraceStep[];
|
||||||
choice = chooseResult[0].result.choice;
|
choice = chooseResult[0].result.choice;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,10 +294,10 @@ export class ActionHandler {
|
|||||||
// If we have a trace, highlight the chosen track here.
|
// If we have a trace, highlight the chosen track here.
|
||||||
const choicePath = `${this.pathPrefix}${idx}/choose/${choiceIdx}`;
|
const choicePath = `${this.pathPrefix}${idx}/choose/${choiceIdx}`;
|
||||||
let chosen = false;
|
let chosen = false;
|
||||||
if (this.trace && choicePath in this.trace.action_trace) {
|
if (this.trace && choicePath in this.trace.trace) {
|
||||||
const choiceResult = this.trace.action_trace[
|
const choiceResult = this.trace.trace[
|
||||||
choicePath
|
choicePath
|
||||||
] as ChooseChoiceActionTrace[];
|
] as ChooseChoiceActionTraceStep[];
|
||||||
chosen = choiceResult[0].result.result;
|
chosen = choiceResult[0].result.result;
|
||||||
}
|
}
|
||||||
const choiceNodeInfo: NodeInfo = {
|
const choiceNodeInfo: NodeInfo = {
|
||||||
@ -380,7 +394,6 @@ export class ActionHandler {
|
|||||||
|
|
||||||
private _createConditionNode(
|
private _createConditionNode(
|
||||||
pathPrefix: string,
|
pathPrefix: string,
|
||||||
tracePaths: Record<string, ActionTrace[]> | undefined,
|
|
||||||
idx: number,
|
idx: number,
|
||||||
action: Condition,
|
action: Condition,
|
||||||
end: boolean
|
end: boolean
|
||||||
@ -389,8 +402,8 @@ export class ActionHandler {
|
|||||||
let result: boolean | undefined;
|
let result: boolean | undefined;
|
||||||
let isTracked = false;
|
let isTracked = false;
|
||||||
|
|
||||||
if (tracePaths && path in tracePaths) {
|
if (this.trace && path in this.trace.trace) {
|
||||||
const conditionResult = tracePaths[path] as ConditionTrace[];
|
const conditionResult = this.trace.trace[path] as ConditionTraceStep[];
|
||||||
result = conditionResult[0].result.result;
|
result = conditionResult[0].result.result;
|
||||||
isTracked = true;
|
isTracked = true;
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,27 @@
|
|||||||
import { HomeAssistant, Context } from "../types";
|
import { HomeAssistant, Context } from "../types";
|
||||||
import { AutomationConfig } from "./automation";
|
import { AutomationConfig } from "./automation";
|
||||||
|
|
||||||
interface TraceVariables extends Record<string, unknown> {
|
interface BaseTraceStep {
|
||||||
trigger: {
|
|
||||||
description: string;
|
|
||||||
[key: string]: unknown;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
interface BaseTrace {
|
|
||||||
path: string;
|
path: string;
|
||||||
timestamp: string;
|
timestamp: string;
|
||||||
changed_variables?: Record<string, unknown>;
|
changed_variables?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ConditionTrace extends BaseTrace {
|
export interface TriggerTraceStep extends BaseTraceStep {
|
||||||
|
changed_variables: {
|
||||||
|
trigger: {
|
||||||
|
description: string;
|
||||||
|
[key: string]: unknown;
|
||||||
|
};
|
||||||
|
[key: string]: unknown;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ConditionTraceStep extends BaseTraceStep {
|
||||||
result: { result: boolean };
|
result: { result: boolean };
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CallServiceActionTrace extends BaseTrace {
|
export interface CallServiceActionTraceStep extends BaseTraceStep {
|
||||||
result: {
|
result: {
|
||||||
limit: number;
|
limit: number;
|
||||||
running_script: boolean;
|
running_script: boolean;
|
||||||
@ -31,19 +34,20 @@ export interface CallServiceActionTrace extends BaseTrace {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChooseActionTrace extends BaseTrace {
|
export interface ChooseActionTraceStep extends BaseTraceStep {
|
||||||
result: { choice: number | "default" };
|
result: { choice: number | "default" };
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChooseChoiceActionTrace extends BaseTrace {
|
export interface ChooseChoiceActionTraceStep extends BaseTraceStep {
|
||||||
result: { result: boolean };
|
result: { result: boolean };
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ActionTrace =
|
export type ActionTraceStep =
|
||||||
| BaseTrace
|
| BaseTraceStep
|
||||||
| CallServiceActionTrace
|
| ConditionTraceStep
|
||||||
| ChooseActionTrace
|
| CallServiceActionTraceStep
|
||||||
| ChooseChoiceActionTrace;
|
| ChooseActionTraceStep
|
||||||
|
| ChooseChoiceActionTraceStep;
|
||||||
|
|
||||||
export interface AutomationTrace {
|
export interface AutomationTrace {
|
||||||
domain: string;
|
domain: string;
|
||||||
@ -60,10 +64,9 @@ export interface AutomationTrace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface AutomationTraceExtended extends AutomationTrace {
|
export interface AutomationTraceExtended extends AutomationTrace {
|
||||||
condition_trace: Record<string, ConditionTrace[]>;
|
trace: Record<string, ActionTraceStep[]>;
|
||||||
action_trace: Record<string, ActionTrace[]>;
|
|
||||||
context: Context;
|
context: Context;
|
||||||
variables: TraceVariables;
|
variables: Record<string, unknown>;
|
||||||
config: AutomationConfig;
|
config: AutomationConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,9 +10,9 @@ import {
|
|||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import {
|
import {
|
||||||
ActionTrace,
|
ActionTraceStep,
|
||||||
AutomationTraceExtended,
|
AutomationTraceExtended,
|
||||||
ChooseActionTrace,
|
ChooseActionTraceStep,
|
||||||
getDataFromPath,
|
getDataFromPath,
|
||||||
} from "../../../../data/trace";
|
} from "../../../../data/trace";
|
||||||
import "../../../../components/ha-icon-button";
|
import "../../../../components/ha-icon-button";
|
||||||
@ -77,14 +77,8 @@ export class HaAutomationTracePathDetails extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getPaths() {
|
|
||||||
return this.selected.path.split("/")[0] === "condition"
|
|
||||||
? this.trace!.condition_trace
|
|
||||||
: this.trace!.action_trace;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _renderSelectedTraceInfo() {
|
private _renderSelectedTraceInfo() {
|
||||||
const paths = this._getPaths();
|
const paths = this.trace.trace;
|
||||||
|
|
||||||
if (!this.selected?.path) {
|
if (!this.selected?.path) {
|
||||||
return "Select a node on the left for more information.";
|
return "Select a node on the left for more information.";
|
||||||
@ -95,7 +89,7 @@ export class HaAutomationTracePathDetails extends LitElement {
|
|||||||
if (pathParts[pathParts.length - 1] === "default") {
|
if (pathParts[pathParts.length - 1] === "default") {
|
||||||
const parentTraceInfo = paths[
|
const parentTraceInfo = paths[
|
||||||
pathParts.slice(0, pathParts.length - 1).join("/")
|
pathParts.slice(0, pathParts.length - 1).join("/")
|
||||||
] as ChooseActionTrace[];
|
] as ChooseActionTraceStep[];
|
||||||
|
|
||||||
if (parentTraceInfo && parentTraceInfo[0]?.result?.choice === "default") {
|
if (parentTraceInfo && parentTraceInfo[0]?.result?.choice === "default") {
|
||||||
return "The default node was executed because no choices matched.";
|
return "The default node was executed because no choices matched.";
|
||||||
@ -106,7 +100,7 @@ export class HaAutomationTracePathDetails extends LitElement {
|
|||||||
return "This node was not executed and so no further trace information is available.";
|
return "This node was not executed and so no further trace information is available.";
|
||||||
}
|
}
|
||||||
|
|
||||||
const data: ActionTrace[] = paths[this.selected.path];
|
const data: ActionTraceStep[] = paths[this.selected.path];
|
||||||
|
|
||||||
return data.map((trace, idx) => {
|
return data.map((trace, idx) => {
|
||||||
const {
|
const {
|
||||||
@ -146,16 +140,11 @@ export class HaAutomationTracePathDetails extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _renderChangedVars() {
|
private _renderChangedVars() {
|
||||||
const paths = this._getPaths();
|
const paths = this.trace.trace;
|
||||||
const data: ActionTrace[] = paths[this.selected.path];
|
const data: ActionTraceStep[] = paths[this.selected.path];
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div class="padded-box">
|
<div class="padded-box">
|
||||||
<p>
|
|
||||||
The following variables have changed while the step ran. If this is
|
|
||||||
the first condition or action, this will include the trigger
|
|
||||||
variables.
|
|
||||||
</p>
|
|
||||||
${data.map(
|
${data.map(
|
||||||
(trace, idx) => html`
|
(trace, idx) => html`
|
||||||
${idx > 0 ? html`<p>Iteration ${idx + 1}</p>` : ""}
|
${idx > 0 ? html`<p>Iteration ${idx + 1}</p>` : ""}
|
||||||
@ -171,15 +160,9 @@ ${safeDump(trace.changed_variables).trimRight()}</pre
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _renderLogbook() {
|
private _renderLogbook() {
|
||||||
const paths = {
|
const paths = this.trace.trace;
|
||||||
...this.trace.condition_trace,
|
|
||||||
...this.trace.action_trace,
|
|
||||||
};
|
|
||||||
|
|
||||||
const startTrace = paths[this.selected.path];
|
const startTrace = paths[this.selected.path];
|
||||||
|
|
||||||
const trackedPaths = Object.keys(this.trackedNodes);
|
const trackedPaths = Object.keys(this.trackedNodes);
|
||||||
|
|
||||||
const index = trackedPaths.indexOf(this.selected.path);
|
const index = trackedPaths.indexOf(this.selected.path);
|
||||||
|
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
|
@ -367,7 +367,7 @@ export class HaAutomationTrace extends LitElement {
|
|||||||
const nodes = this.shadowRoot!.querySelector(
|
const nodes = this.shadowRoot!.querySelector(
|
||||||
"hat-script-graph"
|
"hat-script-graph"
|
||||||
)!.getTrackedNodes();
|
)!.getTrackedNodes();
|
||||||
this._selected = nodes[path].nodeInfo;
|
this._selected = nodes[path]?.nodeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user