Fist commit
This commit is contained in:
96
scripts/embed_ui.py
Executable file
96
scripts/embed_ui.py
Executable file
@@ -0,0 +1,96 @@
|
||||
Import("env") # noqa: F821
|
||||
|
||||
from pathlib import Path
|
||||
import hashlib
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
|
||||
project_dir = Path(env.subst("$PROJECT_DIR")) # noqa: F821
|
||||
ui_dir = project_dir / "ui"
|
||||
generated_dir = project_dir / "src" / "generated"
|
||||
generated_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
npm = shutil.which("npm")
|
||||
if npm and (ui_dir / "node_modules").is_dir():
|
||||
subprocess.run([npm, "run", "build"], cwd=ui_dir, check=True)
|
||||
|
||||
assets = {
|
||||
"indexHtml": ui_dir / "dist" / "index.html",
|
||||
"appCss": ui_dir / "dist" / "styles.min.css",
|
||||
"appJs": ui_dir / "dist" / "app.min.js",
|
||||
}
|
||||
if not all(path.is_file() for path in assets.values()):
|
||||
assets = {
|
||||
"indexHtml": ui_dir / "index.html",
|
||||
"appCss": ui_dir / "styles.css",
|
||||
"appJs": ui_dir / "app.js",
|
||||
}
|
||||
|
||||
missing = [str(path) for path in assets.values() if not path.is_file()]
|
||||
if missing:
|
||||
raise SystemExit(
|
||||
"Missing UI assets: " + ", ".join(missing)
|
||||
)
|
||||
|
||||
|
||||
def emit_array(name, data):
|
||||
lines = [f"const char {name}[] PROGMEM = {{"]
|
||||
for offset in range(0, len(data), 16):
|
||||
chunk = data[offset : offset + 16]
|
||||
values = ", ".join(f"0x{value:02X}" for value in chunk)
|
||||
lines.append(f" {values},")
|
||||
lines.append(" 0x00")
|
||||
lines.append("};")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def emit_length(name, data):
|
||||
return f"const std::size_t {name}Length = {len(data)}U;"
|
||||
|
||||
|
||||
header_lines = [
|
||||
"#pragma once",
|
||||
"",
|
||||
"#include <Arduino.h>",
|
||||
"#include <pgmspace.h>",
|
||||
"",
|
||||
"#include <cstddef>",
|
||||
"",
|
||||
]
|
||||
source_lines = [
|
||||
"// Generated by scripts/embed_ui.py. Do not edit manually.",
|
||||
"#include \"UiAssets.h\"",
|
||||
"",
|
||||
"#include <cstddef>",
|
||||
"",
|
||||
]
|
||||
|
||||
for name, path in assets.items():
|
||||
data = path.read_bytes()
|
||||
digest = hashlib.sha256(data).hexdigest()
|
||||
header_lines.append(f"extern const char {name}[] PROGMEM;")
|
||||
header_lines.append(f"extern const std::size_t {name}Length;")
|
||||
header_lines.append(f"extern const char {name}Sha256[] PROGMEM;")
|
||||
source_lines.extend(
|
||||
[
|
||||
emit_array(name, data),
|
||||
emit_length(name, data),
|
||||
f'const char {name}Sha256[] PROGMEM = "{digest}";',
|
||||
"",
|
||||
]
|
||||
)
|
||||
|
||||
def write_if_changed(path, content):
|
||||
if path.is_file() and path.read_text(encoding="utf-8") == content:
|
||||
return
|
||||
path.write_text(content, encoding="utf-8")
|
||||
|
||||
|
||||
write_if_changed(generated_dir / "UiAssets.h", "\n".join(header_lines) + "\n")
|
||||
write_if_changed(generated_dir / "UiAssets.cpp", "\n".join(source_lines) + "\n")
|
||||
|
||||
print("Embedded UI assets:")
|
||||
for name, path in assets.items():
|
||||
data = path.read_bytes()
|
||||
print(f" {name}: {path.name} ({len(data)} bytes)")
|
||||
Reference in New Issue
Block a user