MVP Z-Wave JS Log Viewer (#9008)

* Add element to subscribe to ZJS logs

* set log level and adjust styling

* review comments

* add ZWaveJS to function names

* use flexbox

* Review comments

* import

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
Charles Garwood 2021-04-28 13:00:13 -04:00 committed by GitHub
parent 9d33c0cfaf
commit ebe0caba83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 221 additions and 5 deletions

View File

@ -173,9 +173,9 @@ export const reinterviewNode = (
);
};
export const getIdentifiersFromDevice = function (
export const getIdentifiersFromDevice = (
device: DeviceRegistryEntry
): ZWaveJSNodeIdentifiers | undefined {
): ZWaveJSNodeIdentifiers | undefined => {
if (!device) {
return undefined;
}
@ -193,3 +193,48 @@ export const getIdentifiersFromDevice = function (
home_id: identifiers[0],
};
};
export interface ZWaveJSLogMessage {
timestamp: string;
level: string;
primary_tags: string;
message: string | string[];
}
export const subscribeZWaveJSLogs = (
hass: HomeAssistant,
entry_id: string,
callback: (message: ZWaveJSLogMessage) => void
) =>
hass.connection.subscribeMessage<ZWaveJSLogMessage>(callback, {
type: "zwave_js/subscribe_logs",
entry_id,
});
export interface ZWaveJSLogConfig {
level: string;
enabled: boolean;
filename: string;
log_to_file: boolean;
force_console: boolean;
}
export const fetchZWaveJSLogConfig = (
hass: HomeAssistant,
entry_id: string
): Promise<ZWaveJSLogConfig> =>
hass.callWS({
type: "zwave_js/get_log_config",
entry_id,
});
export const setZWaveJSLogLevel = (
hass: HomeAssistant,
entry_id: string,
level: string
): Promise<ZWaveJSLogConfig> =>
hass.callWS({
type: "zwave_js/update_log_config",
entry_id,
config: { level },
});

View File

@ -7,7 +7,7 @@ import { HomeAssistant } from "../../../../../types";
import { navigate } from "../../../../../common/navigate";
import { PageNavigation } from "../../../../../layouts/hass-tabs-subpage";
import { mdiServerNetwork } from "@mdi/js";
import { mdiServerNetwork, mdiMathLog } from "@mdi/js";
export const configTabs: PageNavigation[] = [
{
@ -15,6 +15,11 @@ export const configTabs: PageNavigation[] = [
path: `/config/zwave_js/dashboard`,
iconPath: mdiServerNetwork,
},
{
translationKey: "ui.panel.config.zwave_js.navigation.logs",
path: `/config/zwave_js/logs`,
iconPath: mdiMathLog,
},
];
@customElement("zwave_js-config-router")
@ -41,6 +46,10 @@ class ZWaveJSConfigRouter extends HassRouterPage {
tag: "zwave_js-node-config",
load: () => import("./zwave_js-node-config"),
},
logs: {
tag: "zwave_js-logs",
load: () => import("./zwave_js-logs"),
},
},
};

View File

@ -0,0 +1,157 @@
import { UnsubscribeFunc } from "home-assistant-js-websocket";
import {
css,
html,
property,
customElement,
LitElement,
CSSResultArray,
internalProperty,
query,
} from "lit-element";
import "@polymer/paper-listbox/paper-listbox";
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
import {
fetchZWaveJSLogConfig,
setZWaveJSLogLevel,
subscribeZWaveJSLogs,
ZWaveJSLogConfig,
} from "../../../../../data/zwave_js";
import { SubscribeMixin } from "../../../../../mixins/subscribe-mixin";
import { HomeAssistant, Route } from "../../../../../types";
import { configTabs } from "./zwave_js-config-router";
import "../../../../../layouts/hass-tabs-subpage";
import { haStyle } from "../../../../../resources/styles";
@customElement("zwave_js-logs")
class ZWaveJSLogs extends SubscribeMixin(LitElement) {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Object }) public route!: Route;
@property({ type: Boolean }) public narrow!: boolean;
@property() public configEntryId!: string;
@internalProperty() private _logConfig?: ZWaveJSLogConfig;
@query("textarea", true) private _textarea?: HTMLTextAreaElement;
public hassSubscribe(): Array<UnsubscribeFunc | Promise<UnsubscribeFunc>> {
return [
subscribeZWaveJSLogs(this.hass, this.configEntryId, (log) => {
if (!this.hasUpdated) {
return;
}
if (Array.isArray(log.message)) {
for (const line of log.message) {
this._textarea!.value += `${line}\n`;
}
} else {
this._textarea!.value += `${log.message}\n`;
}
}),
];
}
protected render() {
return html`
<hass-tabs-subpage
.hass=${this.hass}
.narrow=${this.narrow}
.route=${this.route}
.tabs=${configTabs}
>
<div class="container">
<ha-card>
<div class="card-header">
<h1>
${this.hass.localize("ui.panel.config.zwave_js.logs.title")}
</h1>
</div>
<div class="card-content">
${this._logConfig
? html`
<paper-dropdown-menu
dynamic-align
.label=${this.hass.localize(
"ui.panel.config.zwave_js.logs.log_level"
)}
>
<paper-listbox
slot="dropdown-content"
.selected=${this._logConfig.level}
attr-for-selected="value"
@iron-select=${this._dropdownSelected}
>
<paper-item value="error">Error</paper-item>
<paper-item value="warn">Warn</paper-item>
<paper-item value="info">Info</paper-item>
<paper-item value="verbose">Verbose</paper-item>
<paper-item value="debug">Debug</paper-item>
<paper-item value="silly">Silly</paper-item>
</paper-listbox>
</paper-dropdown-menu>
`
: ""}
</div>
</ha-card>
<textarea readonly></textarea>
</div>
</hass-tabs-subpage>
`;
}
protected firstUpdated(changedProps) {
super.firstUpdated(changedProps);
this._fetchData();
}
private async _fetchData() {
if (!this.configEntryId) {
return;
}
this._logConfig = await fetchZWaveJSLogConfig(
this.hass!,
this.configEntryId
);
}
private _dropdownSelected(ev) {
if (ev.target === undefined || this._logConfig === undefined) {
return;
}
if (this._logConfig.level === ev.target.selected) {
return;
}
setZWaveJSLogLevel(this.hass!, this.configEntryId, ev.target.selected);
}
static get styles(): CSSResultArray {
return [
haStyle,
css`
.container {
display: flex;
flex-direction: column;
height: 100%;
box-sizing: border-box;
padding: 16px;
}
textarea {
flex-grow: 1;
padding: 16px;
}
ha-card {
margin: 16px 0;
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"zwave_js-logs": ZWaveJSLogs;
}
}

View File

@ -2562,7 +2562,8 @@
},
"zwave_js": {
"navigation": {
"network": "Network"
"network": "Network",
"logs": "Logs"
},
"common": {
"network": "Network",
@ -2649,6 +2650,10 @@
"in_progress": "The device is being interviewed. This may take some time.",
"interview_failed": "The device interview failed. Additional information may be available in the logs.",
"interview_complete": "Device interview complete."
},
"logs": {
"title": "Z-Wave JS Logs",
"log_level": "Log Level"
}
}
},
@ -3936,4 +3941,4 @@
}
}
}
}
}