Skip to content

Commit fb02531

Browse files
committed
[feat] Add esptool logs to install web dialog
1 parent 37934e7 commit fb02531

File tree

4 files changed

+153
-5
lines changed

4 files changed

+153
-5
lines changed

src/install-web/index.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,41 @@
1+
import type { IEspLoaderTerminal } from "esptool-js";
12
import { openNoPortPickedDialog } from "../no-port-picked";
23
import { createESPLoader } from "../web-serial/create-esploader";
34
import type { ESPHomeInstallWebDialog } from "./install-web-dialog";
45

6+
export class ESPLoaderTerminalStream {
7+
public stream: ReadableStream;
8+
public terminal: IEspLoaderTerminal;
9+
private controller?: ReadableStreamDefaultController<any>;
10+
11+
constructor() {
12+
const _this = this;
13+
this.stream = new ReadableStream({
14+
start (controller) {
15+
_this.controller = controller;
16+
}
17+
});
18+
19+
this.terminal = {
20+
clean: () => {
21+
this.controller?.enqueue('\n\n\n');
22+
},
23+
writeLine: (data: string) => {
24+
console.log(data);
25+
this.controller?.enqueue(`${data}\n`);
26+
},
27+
write: (data: string) => {
28+
console.log(data);
29+
// Fix "Connecting..." line break
30+
if (data == '\n\r')
31+
this.controller?.enqueue('\n');
32+
else
33+
this.controller?.enqueue(data);
34+
},
35+
};
36+
}
37+
}
38+
539
export const preloadInstallWebDialog = () => import("./install-web-dialog");
640

741
export const openInstallWebDialog = async (
@@ -30,7 +64,10 @@ export const openInstallWebDialog = async (
3064
return;
3165
}
3266
}
33-
const esploader = createESPLoader(port);
67+
68+
const terminalStream = new ESPLoaderTerminalStream();
69+
70+
const esploader = createESPLoader(port, terminalStream.terminal);
3471

3572
if (onDialogOpen) {
3673
onDialogOpen();
@@ -39,5 +76,6 @@ export const openInstallWebDialog = async (
3976
const dialog = document.createElement("esphome-install-web-dialog");
4077
dialog.params = params;
4178
dialog.esploader = esploader;
79+
dialog.stream = terminalStream.stream;
4280
document.body.append(dialog);
4381
};

src/install-web/install-console.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { ColoredConsole, coloredConsoleStyles } from "../util/console-color";
2+
import { Logger } from "../const";
3+
4+
export class InstallConsole extends HTMLElement {
5+
public port!: SerialPort;
6+
public logger!: Logger;
7+
8+
private _console?: ColoredConsole;
9+
10+
public logs(): string {
11+
return this._console?.logs() || "";
12+
}
13+
14+
public addLine(line: string) {
15+
this._console?.addLine(line);
16+
}
17+
18+
public connectedCallback() {
19+
if (this._console) {
20+
return;
21+
}
22+
const shadowRoot = this.attachShadow({ mode: "open" });
23+
24+
shadowRoot.innerHTML = `
25+
<style>
26+
:host, input {
27+
background-color: #1c1c1c;
28+
color: #ddd;
29+
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier,
30+
monospace;
31+
line-height: 1.45;
32+
display: flex;
33+
flex-direction: column;
34+
}
35+
form {
36+
display: flex;
37+
align-items: center;
38+
padding: 0 8px 0 16px;
39+
}
40+
input {
41+
flex: 1;
42+
padding: 4px;
43+
margin: 0 8px;
44+
border: 0;
45+
outline: none;
46+
}
47+
${coloredConsoleStyles}
48+
</style>
49+
<div class="log"></div>
50+
`;
51+
52+
this._console = new ColoredConsole(this.shadowRoot!.querySelector("div")!);
53+
}
54+
55+
}
56+
57+
customElements.define("install-console", InstallConsole);
58+
59+
declare global {
60+
interface HTMLElementTagNameMap {
61+
"install-console": InstallConsole;
62+
}
63+
}

src/install-web/install-web-dialog.ts

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { LitElement, html, PropertyValues, css, TemplateResult } from "lit";
2-
import { customElement, property, state } from "lit/decorators.js";
2+
import { customElement, property, query, state } from "lit/decorators.js";
33
import "@material/mwc-dialog";
44
import "@material/mwc-circular-progress";
55
import "@material/mwc-button";
66
import type { ESPLoader } from "esptool-js";
7+
import "./install-console";
8+
import type { InstallConsole } from "./install-console";
79
import {
810
compileConfiguration,
911
Configuration,
@@ -43,6 +45,9 @@ export class ESPHomeInstallWebDialog extends LitElement {
4345
};
4446

4547
@property() public esploader!: ESPLoader;
48+
@property() public stream?: ReadableStream;
49+
50+
@query("install-console") private _console!: InstallConsole;
4651

4752
@state() private _writeProgress?: number;
4853

@@ -56,6 +61,23 @@ export class ESPHomeInstallWebDialog extends LitElement {
5661

5762
private _platform?: ValueOf<typeof chipFamilyToPlatform>;
5863

64+
@property() private _showLogs = false;
65+
66+
connectedCallback() {
67+
super.connectedCallback();
68+
69+
// this._console won't be defined until after the first paint
70+
setTimeout(() => {
71+
this.stream?.pipeTo(
72+
new WritableStream({
73+
write: (chunk) => {
74+
this._console.addLine(chunk)
75+
},
76+
})
77+
);
78+
});
79+
}
80+
5981
protected render() {
6082
let heading;
6183
let content;
@@ -106,6 +128,8 @@ export class ESPHomeInstallWebDialog extends LitElement {
106128
}
107129
}
108130

131+
hideActions = false
132+
109133
return html`
110134
<mwc-dialog
111135
open
@@ -115,6 +139,12 @@ export class ESPHomeInstallWebDialog extends LitElement {
115139
.hideActions=${hideActions}
116140
>
117141
${content}
142+
<install-console class="${this._showLogs ? "" : "hidden"}"></install-console>
143+
<mwc-button
144+
slot="secondaryAction"
145+
@click=${this._toggleLogs}
146+
label="${this._showLogs ? "Hide" : "Show"} Logs"
147+
></mwc-button>
118148
</mwc-dialog>
119149
`;
120150
}
@@ -148,7 +178,7 @@ export class ESPHomeInstallWebDialog extends LitElement {
148178
<div class="icon">${icon}</div>
149179
${label}
150180
</div>
151-
${showClose
181+
${showClose || true
152182
? html`
153183
<mwc-button
154184
slot="primaryAction"
@@ -303,6 +333,10 @@ export class ESPHomeInstallWebDialog extends LitElement {
303333
return await getConfigurationFiles(configuration);
304334
}
305335

336+
private _toggleLogs() {
337+
this._showLogs = !this._showLogs;
338+
}
339+
306340
private _close() {
307341
this.shadowRoot!.querySelector("mwc-dialog")!.close();
308342
}
@@ -317,6 +351,18 @@ export class ESPHomeInstallWebDialog extends LitElement {
317351
static styles = [
318352
esphomeDialogStyles,
319353
css`
354+
install-console {
355+
width: 500px;
356+
height: 300px;
357+
margin-top: 16px;
358+
overflow: hidden;
359+
transition: all 0.2s ease-in-out;
360+
}
361+
install-console.hidden {
362+
margin-top: 0;
363+
width: 230px;
364+
height: 0;
365+
}
320366
mwc-list-item {
321367
margin: 0 -20px;
322368
}

src/web-serial/create-esploader.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
import { Transport, ESPLoader } from "esptool-js";
1+
import { Transport, ESPLoader, IEspLoaderTerminal } from "esptool-js";
22

3-
export const createESPLoader = (port: SerialPort) => {
3+
export const createESPLoader = (port: SerialPort, terminal?: IEspLoaderTerminal) => {
44
const transport = new Transport(port);
55
return new ESPLoader({
66
transport,
77
baudrate: 115200,
88
romBaudrate: 115200,
99
enableTracing: false,
10+
terminal,
1011
});
1112
};

0 commit comments

Comments
 (0)