Skip to content

Commit

Permalink
Compile web content as a C source file and unpack it on the flash fil…
Browse files Browse the repository at this point in the history
…e system.
  • Loading branch information
bertrik committed Dec 19, 2024
1 parent 5fe4fa6 commit 032f706
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 7 deletions.
45 changes: 45 additions & 0 deletions create_webcontent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env python3

import os

def create_c_header(directory, output_file):
with open(output_file, 'w') as header:
header.write("// Auto-generated header file\n\n")
header.write('#include <Arduino.h>\n')
header.write('#include "webcontent.h"\n\n')

# Iterate over all files in the directory
entries = ""
for filename in os.listdir(directory):
filepath = os.path.join(directory, filename)

# Read file as a byte array
with open(filepath, 'rb') as file:
byte_array = file.read()

# Write the byte array to the header file
identifier = filename.replace('.', '_').replace('-', '_')
header.write(f"// Byte array for {filename}\n")
header.write(f"const unsigned char {identifier}[] PROGMEM = {{\n")
for i in range(0, len(byte_array), 16):
chunk = byte_array[i:i+16]
hex_bytes = ', '.join(f'0x{byte:02x}' for byte in chunk)
header.write(f" {hex_bytes},\n")
header.write("};\n\n")

# create entry for table
entries += f' {{ "/{filename}", {identifier}, sizeof({identifier}) }},\n'

# write table with file entries
header.write("const file_entry_t file_table[] = {\n")
header.write(entries)
header.write(' {"", NULL, 0}\n')
header.write('};\n\n')


# Specify the directory containing the files and the output header file
input_directory = 'data'
output_header = 'webcontent.cpp'

print(f"Creating C file with file contents: {output_header}")
create_c_header(input_directory, output_header)
9 changes: 4 additions & 5 deletions data/config.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin="*"></script>
<script>
document.addEventListener("DOMContentLoaded", function () {
var map = L.map('map').setView([52.15517, 5.38721], 8);

var lat = document.getElementById('lat').value
var lng = document.getElementById('lng').value
var map = L.map('map').setView([lat, lng], 10);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors',
maxZoom: 19,
}).addTo(map);

var lat = document.getElementById('lat').value
var lng = document.getElementById('lng').value
var marker = L.marker([lat, lng]).addTo(map);

// Listen for click events on the map
Expand Down Expand Up @@ -72,4 +71,4 @@
</script>


</html>
</html>
4 changes: 2 additions & 2 deletions data/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
</head>

<body>
Hello world<br>
<p>Stofananas</p>
<ul>
<li><a href="/config">Configuration</a></li>
<li><a href="/update">Firmware update</a></li>
</ul>

</body>

</html>
</html>
1 change: 1 addition & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ framework = arduino
monitor_speed = 115200
upload_speed = 1000000
board_build.filesystem = littlefs
extra_scripts = pre:create_webcontent.py
lib_deps = fastled/[email protected]
alanswx/ESPAsyncWiFiManager@^0.31.0
bblanchon/ArduinoJson@^6.21.5
Expand Down
48 changes: 48 additions & 0 deletions stofananas.ino
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

#include "config.h"

#include "webcontent.h"

#define printf Serial.printf

// we send the colour to two sets of LEDs: a single LED on pin D2, a star of 7 LEDs on pin D4
Expand Down Expand Up @@ -253,6 +255,49 @@ static int do_led(int argc, char *argv[])
return 0;
}

static void unpack_file(FS &fs, const file_entry_t *entry)
{
uint8_t buf[1024];
File file = fs.open(entry->filename, "w");
if (file) {
const unsigned char *p = entry->data;
size_t remain = entry->length;
for (size_t block; remain > 0; remain -= block, p += block) {
block = remain > sizeof(buf) ? sizeof(buf) : remain;
memcpy_P(buf, p, block);
file.write(buf, block);
}
file.close();
}
}

static void unpack_fs(FS &fs, const file_entry_t *table, bool force)
{
printf("Unpacking files...\n");
for (const file_entry_t *entry = table; *entry->filename; entry++) {
size_t filesize = 0;
File file = fs.open(entry->filename, "r");
if (file) {
filesize = file.size();
file.close();
}
if (force || (filesize != entry->length)) {
printf("Writing %d bytes to '%s'...", entry->length, entry->filename);
unpack_file(fs, entry);
printf("done\n");
} else {
printf("Skipping '%s'\n", entry->filename);
}
}
printf("All files unpacked\n");
}

static int do_unpack(int argc, char *argv[])
{
unpack_fs(LittleFS, file_table, true);
return 0;
}

const cmd_t commands[] = {
{ "help", do_help, "Show help" },
{ "get", do_get, "[id] GET the PM2.5 value from stofradar.nl" },
Expand All @@ -261,6 +306,7 @@ const cmd_t commands[] = {
{ "reboot", do_reboot, "Reboot" },
{ "error", do_error, "[fetch] [decode] Simulate a fetch/decode error" },
{ "led", do_led, "<RRGGBB> Set the LED to a specific value (hex)" },
{ "unpack", do_unpack, "Unpack files" },
{ NULL, NULL, NULL }
};

Expand Down Expand Up @@ -302,8 +348,10 @@ void setup(void)

// load settings, save defaults if necessary
LittleFS.begin();
unpack_fs(LittleFS, file_table, false);
config_begin(LittleFS, "/config.json");
if (!config_load()) {
printf("Loading config defaults\n");
config_set_value("loc_latitude", "52.15517");
config_set_value("loc_longitude", "5.38721");
config_set_value("led_type", "grb");
Expand Down
11 changes: 11 additions & 0 deletions webcontent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include <stddef.h>

typedef struct {
const char *filename;
const unsigned char *data;
size_t length;
} file_entry_t;


extern const file_entry_t file_table[];

0 comments on commit 032f706

Please sign in to comment.