97 lines
2.6 KiB
Python
Executable File
97 lines
2.6 KiB
Python
Executable File
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)")
|