Custom Manifest creation on the fly
Hello, i am currently looking into rebuilding a webinstaller where i would like to have the user select the flash size and some other options that would result in a high number of possible combinations and thus manifest files.
While looking around in the issues, i found this reply (https://github.com/esphome/esp-web-tools/issues/469#issuecomment-1926157937 ) by @balloob.
In my opinion i would be able to craft a manifest string based on the User input, but i cant write that to a file and provide that to the install button.
Is there a way around that, or does this need more development in the install scripts?
i have looked into this a bit. with a small change in the install dialog script this is possible. but my implementation will break the current manifest file method. there might be a way to use a if statement to filter between them. ~~Is there a technical reason why the code is minified?~~ Ok can answer myself after some research. It can improve performance
I think a simple way of handling this would be to make manifest property be either a string or a Promise that returns a Manifest.
https://github.com/esphome/esp-web-tools/blob/b7b4b5beba5a496fa4ff29a0df2659364fd57344/src/install-button.ts#L55C3-L55C28
From:
public manifest?: string;
To:
public manifest?: string | Promise<Manifest>;
or
public manifest?: string;
public manifestResolver?: Promise<Manifest>;
If the value is a string, then it would refer to the path to fetch the manifest like it does now. If the value is a Promise , then it await the promise and the resulting should return the manifest value. Alternatively, another property could be added that would return the manifest such as manifestFactory manifestProvider manifestResolver, etc.
I would be fine to allow manifest and a manifestContent: Promise<Manifest> properties
I use something like this....
Client side:
<esp-web-install-button id="install-button">
<button slot="activate">Install</button>
<span slot="unsupported">Ah snap, your browser doesn't work, use Chromium instead!</span>
<span slot="not-allowed">Ah snap, you are not allowed to use this on HTTP, you need HTTPS!</span>
</esp-web-install-button>
<script>
function updateManifest() {
const brand = document.querySelector('#brand').value;
const model = document.querySelector('#model').value;
const version = document.querySelector('#version').value;
const build = document.querySelector('#build').value;
const lang = document.querySelector('#language').value;
if (!brand || !model || !version || !build || !lang) return;
const manifestUrl = `generate-manifest.php?brand=${brand}&model=${model}&version=${version}&build=${build}&lang=${lang}`;
document.querySelector('#install-button').setAttribute('manifest', manifestUrl);
}
document.querySelectorAll('select').forEach(select => {
select.addEventListener('change', updateManifest);
});
</script>
server side generate-maifest.php:
<?php
require_once 'session.php';
header('Content-Type: application/json');
$brand = $_GET['brand'] ?? null;
$model = $_GET['model'] ?? null;
$version = $_GET['version'] ?? null;
$build = $_GET['build'] ?? null;
$lang = $_GET['lang'] ?? null;
if (!$brand || !$model || !$version || !$build || !$lang) {
echo json_encode(['error' => 'Missing parameters']);
exit;
}
$firmware = "$brand-$version-$model-$lang-$build";
$manifest = [
'name' => "Firmware",
'version' => $version,
'new_install_prompt_erase' => true,
'new_install_improv_wait_time' => 0,
'builds' => [
[
'chipFamily' => "ESP32",
'parts' => [
[ 'path' => "bin/{$version}/{$firmware}.img", 'offset' => 0x0 ]
]
]
]
];
echo json_encode($manifest);
maybe this helps someone!
Is this going to be implemented properly? I need to do version management and it's not quite easy to release 3 different firmwares at a time with a ton of pre-made manifests while supporting old firmware versions too. I've been looking in to ways to do essentially what @everslick suggested but I host on github io so no backend makes this quite difficult. Github has built in rest endpoints for viewing files in a directory which will help me with finding all the .bin files, but still no easy way to generate the json file for esp web tools!
You can probably use https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL_static in JavaScript
You can probably use https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL_static in JavaScript
Okay I have tried this and it seems to work. One thing worth noting though is the pathing changes. Before I was able to use paths of what is can only now assume was relative to the location of the manifest file. eg: { "path": "firmware/controller/bootloader.bin", "offset": 4096 },
Now, I must use the entire path instead, relative doesn't seem to work anymore.
Example usage of URL.createObjectURL:
var json = JSON.stringify(manifest);
var blob = new Blob([json], {type: "application/json"});
return URL.createObjectURL(blob)
The result is a blob url like blob:null/57f378a5-6c55-4d67-b8b4-b64230e03371
Unless the dev's have intentions to add another way to implement it, this works great and I would mark this issue as closed.
Would you want to open a PR to the docs to document this approach?
Would you want to open a PR to the docs to document this approach?
Okay PR made https://github.com/esphome/esp-web-tools/pull/602