-
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Svelte UI: add hamburger menu and compile to esp
Svelte UI - add build_interface.py (like done in cdata.js / webbundle.py) - move svelte files to src folder (so build_interface can find them) - package.json: add svelte-hamburgers - add App.svelte (Hamburgers and Menu) - add Menu.svelte pio.ini - add EMBED_WWW and add pre build_interface.py
- Loading branch information
Showing
12 changed files
with
293 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
.pio | ||
node_modules | ||
dist | ||
WWWData.h | ||
.vscode | ||
.DS_Store | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
# StarBase modified version from https://github.com/theelims/ESP32-sveltekit/blob/main/scripts/build_interface.py | ||
|
||
# ESP32 SvelteKit -- | ||
# | ||
# A simple, secure and extensible framework for IoT projects for ESP32 platforms | ||
# with responsive Sveltekit front-end built with TailwindCSS and DaisyUI. | ||
# https://github.com/theelims/ESP32-sveltekit | ||
# | ||
# Copyright (C) 2018 - 2023 rjwats | ||
# Copyright (C) 2023 - 2024 theelims | ||
# Copyright (C) 2023 Maxtrium B.V. [ code available under dual license ] | ||
# Copyright (C) 2024 runeharlyk | ||
# | ||
# All Rights Reserved. This software may be modified and distributed under | ||
# the terms of the LGPL v3 license. See the LICENSE file for details. | ||
|
||
from pathlib import Path | ||
from shutil import copytree, rmtree, copyfileobj | ||
from os.path import exists, getmtime | ||
import os | ||
import gzip | ||
import mimetypes | ||
import glob | ||
from datetime import datetime | ||
|
||
Import("env") | ||
|
||
project_dir = env["PROJECT_DIR"] | ||
buildFlags = env.ParseFlags(env["BUILD_FLAGS"]) | ||
|
||
interface_dir = project_dir + "/data/svelte" | ||
output_file = project_dir + "/src/WWWData.h" | ||
source_www_dir = interface_dir + "/src" | ||
build_dir = interface_dir + "/dist" | ||
filesystem_dir = project_dir + "/data/www" | ||
|
||
|
||
def find_latest_timestamp_for_app(): | ||
return max( | ||
(getmtime(f) for f in glob.glob(f"{source_www_dir}/**/*", recursive=True)) | ||
) | ||
|
||
|
||
def should_regenerate_output_file(): | ||
if not flag_exists("EMBED_WWW") or not exists(output_file): | ||
return True | ||
last_source_change = find_latest_timestamp_for_app() | ||
last_build = getmtime(output_file) | ||
|
||
print( | ||
f"Newest file: {datetime.fromtimestamp(last_source_change)}, output file: {datetime.fromtimestamp(last_build)}" | ||
) | ||
|
||
return last_build < last_source_change | ||
|
||
|
||
def gzip_file(file): | ||
with open(file, 'rb') as f_in: | ||
with gzip.open(file + '.gz', 'wb') as f_out: | ||
copyfileobj(f_in, f_out) | ||
os.remove(file) | ||
|
||
|
||
def flag_exists(flag): | ||
for define in buildFlags.get("CPPDEFINES"): | ||
if (define == flag or (isinstance(define, list) and define[0] == flag)): | ||
return True | ||
return False | ||
|
||
|
||
def get_package_manager(): | ||
if exists(os.path.join(interface_dir, "pnpm-lock.yaml")): | ||
return "pnpm" | ||
if exists(os.path.join(interface_dir, "yarn.lock")): | ||
return "yarn" | ||
if exists(os.path.join(interface_dir, "package-lock.json")): | ||
return "npm" | ||
|
||
|
||
def build_webapp(): | ||
if package_manager := get_package_manager(): | ||
print(f"Building interface with {package_manager}") | ||
os.chdir(interface_dir) | ||
env.Execute(f"{package_manager} install") | ||
env.Execute(f"{package_manager} run build") | ||
os.chdir("..") | ||
else: | ||
raise Exception( | ||
"No lock-file found. Please install dependencies for interface (eg. npm install)" | ||
) | ||
|
||
|
||
def embed_webapp(): | ||
if flag_exists("EMBED_WWW"): | ||
print("Converting interface to PROGMEM") | ||
build_progmem() | ||
return | ||
add_app_to_filesystem() | ||
|
||
|
||
def build_progmem(): | ||
mimetypes.init() | ||
with open(output_file, "w") as progmem: | ||
progmem.write("#include <functional>\n") | ||
progmem.write("#include <Arduino.h>\n") | ||
|
||
assetMap = {} | ||
|
||
for idx, path in enumerate(Path(build_dir).rglob("*.*")): | ||
asset_path = path.relative_to(build_dir).as_posix() | ||
asset_mime = ( | ||
mimetypes.guess_type(asset_path)[0] or "application/octet-stream" | ||
) | ||
print(f"Converting {asset_path}") | ||
|
||
asset_var = f"ESP_SVELTEKIT_DATA_{idx}" | ||
progmem.write(f"// {asset_path}\n") | ||
progmem.write(f"const uint8_t {asset_var}[] = {{\n\t") | ||
file_data = gzip.compress(path.read_bytes()) | ||
|
||
for i, byte in enumerate(file_data): | ||
if i and not (i % 16): | ||
progmem.write("\n\t") | ||
progmem.write(f"0x{byte:02X},") | ||
|
||
progmem.write("\n};\n\n") | ||
assetMap[asset_path] = { | ||
"name": asset_var, | ||
"mime": asset_mime, | ||
"size": len(file_data), | ||
} | ||
|
||
progmem.write( | ||
"typedef std::function<void(const String& uri, const String& contentType, const uint8_t * content, size_t len)> RouteRegistrationHandler;\n\n" | ||
) | ||
progmem.write("class WWWData {\n") | ||
progmem.write("\tpublic:\n") | ||
progmem.write( | ||
"\t\tstatic void registerRoutes(RouteRegistrationHandler handler) {\n" | ||
) | ||
|
||
for asset_path, asset in assetMap.items(): | ||
progmem.write( | ||
f'\t\t\thandler("/{asset_path}", "{asset["mime"]}", {asset["name"]}, {asset["size"]});\n' | ||
) | ||
|
||
progmem.write("\t\t}\n") | ||
progmem.write("};\n\n") | ||
|
||
|
||
def add_app_to_filesystem(): | ||
build_path = Path(build_dir) | ||
www_path = Path(filesystem_dir) | ||
if www_path.exists() and www_path.is_dir(): | ||
rmtree(www_path) | ||
print("Copying and compress interface to data directory") | ||
copytree(build_path, www_path) | ||
for current_path, _, files in os.walk(www_path): | ||
for file in files: | ||
gzip_file(os.path.join(current_path, file)) | ||
print("Build LittleFS file system image and upload to ESP32") | ||
env.Execute("pio run --target uploadfs") | ||
|
||
|
||
print("running: build_interface.py") | ||
if should_regenerate_output_file(): | ||
build_webapp() | ||
embed_webapp() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<!-- | ||
Example by GHOST and Fractal | ||
GHOST: https://github.com/ghostdevv | ||
Fractal: https://github.com/FractalHQ | ||
--> | ||
|
||
<!-- | ||
THIS REPL IS FOR svelte-hamburgers 2 | ||
To view v3 check here: https://svelte.dev/repl/2339dbd1356a4149aabb17daa0a17e40 | ||
--> | ||
|
||
<!-- StarBase: --> | ||
<!-- https://www.npmjs.com/package/svelte-hamburgers?ref=madewithsvelte.com --> | ||
<!-- https://svelte.dev/playground/86b10871cc7f42b39e74d71bdb4d643e?version=3.38.2 --> | ||
|
||
<script> | ||
import {Hamburger} from 'svelte-hamburgers'; | ||
import Menu from './Menu.svelte'; | ||
let open = $state('foo'); | ||
</script> | ||
|
||
<Hamburger | ||
bind:open | ||
color="white" /> | ||
|
||
<Menu bind:open /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<script> | ||
import { fly, scale } from 'svelte/transition'; | ||
import { quadOut } from 'svelte/easing'; | ||
export let open; | ||
</script> | ||
|
||
{#if open} | ||
<div> | ||
{#each ['Home', 'Example', 'About', 'Contact'] as link, i} | ||
<p transition:fly={{ y: -15, delay: 50 * i }}> | ||
{link} | ||
</p> | ||
{/each} | ||
</div> | ||
|
||
<hr transition:scale={{ duration: 750, easing: quadOut, opacity: 1 }} /> | ||
{/if} | ||
|
||
<style> | ||
:global(html) { | ||
background: #1d1d2f; | ||
} | ||
div { | ||
text-align: center; | ||
font-size: 1.5em; | ||
letter-spacing: 0.15em; | ||
padding: 1em; | ||
padding-top: 0; | ||
color: #eef; | ||
} | ||
p { | ||
cursor: pointer; | ||
width: max-content; | ||
margin: 1rem auto; | ||
} | ||
p:hover { | ||
text-decoration: underline; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters