esp-web-tools icon indicating copy to clipboard operation
esp-web-tools copied to clipboard

Custom Manifest creation on the fly

Open lost-hope opened this issue 1 year ago • 10 comments

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?

lost-hope avatar Apr 11 '24 20:04 lost-hope

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

lost-hope avatar Apr 13 '24 22:04 lost-hope

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.

pbolduc avatar Sep 24 '24 03:09 pbolduc

I would be fine to allow manifest and a manifestContent: Promise<Manifest> properties

balloob avatar Jan 02 '25 15:01 balloob

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!

everslick avatar Feb 05 '25 17:02 everslick

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!

gopro2027 avatar Jun 13 '25 01:06 gopro2027

You can probably use https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL_static in JavaScript

balloob avatar Jun 14 '25 10:06 balloob

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.

gopro2027 avatar Jun 20 '25 02:06 gopro2027

Would you want to open a PR to the docs to document this approach?

balloob avatar Jun 20 '25 03:06 balloob

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

gopro2027 avatar Jun 20 '25 20:06 gopro2027