• 3 Posts
  • 113 Comments
Joined 2 years ago
cake
Cake day: September 8th, 2023

help-circle

  • In linux user and group names don’t matter. Only the gid and uid matter. Think of user and group names as human names like domains are for IPS.

    In docker when you use mounts, all your containers that want to share data must agree on the gid and uids.

    In rootless docker and podman things subuids and subgids make it a little more complicated since IDs get mapped between host and container, but its still the IDs that matter.













  • raldone01@lemmy.worldtoTechnology@lemmy.world*Permanently Deleted*
    link
    fedilink
    English
    arrow-up
    1
    ·
    edit-2
    5 months ago

    I don’t think the promise chain is really needed here.

    I used this script:

    import Axios from 'axios'
    import OldFS from 'fs'
    import { PromiseChain } from '@feather-ink/ts-utils'
    
    const fs = OldFS.promises
    
    const image = process.argv[2]
    const destination = `http://${process.argv[3]}/vfs/ota`
    const now = process.argv[4] === 'now'
    const once = process.argv[4] === 'once'
    
    async function triggerUpdate(): Promise<void> {
      console.log('Uploading new binary')
      const file = await fs.readFile(image)
    
      await Axios({
        method: 'POST',
        url: destination,
        headers: {
          'Content-Type': 'application/octet-stream',
          'Content-Length': file.byteLength
        },
        data: file
      })
      console.log('Finished uploading')
    }
    
    (async () => {
      const updateChain = new PromiseChain()
      console.log(`Watching file '${image}' for changes\nWill upload to '${destination}'!`)
      if (once) {
        await triggerUpdate()
        return
      }
      if (now)
        await updateChain.enqueue(triggerUpdate)
      OldFS.watch(image, async (eventType) => {
        if (eventType !== 'change')
          return
        let succ = false
        do {
          try {
            console.log('Change detected')
            await updateChain.enqueue(triggerUpdate)
            succ = true
          } catch (e) {
            console.error(e)
            console.log('Retrying upload')
          }
        } while (!succ)
        console.log('Upload finished')
      })
    })()
    

    Relevent code on the esp:

    You can ignore my cpp stuff and just put this in the handler of the stock webserver.

    auto ota = vfs->addHandler(makeDirectory("ota"));
            {
              ota->addHandler(makeDirect([](auto &con) {
                if (con.req->method != HTTP_POST)
                  return HandlerReturn::UNHANDLED;
    
                // https://github.com/espressif/esp-idf/tree/master/examples/system/ota/native_ota_example/main
                // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/ota.html
                auto updatePartition = esp_ota_get_next_update_partition(nullptr);
                if (updatePartition == nullptr)
                  return sendError(con,500, "No free ota partition found!");
                esp_ota_handle_t otaHandle;
                auto err = esp_ota_begin(updatePartition, con.req->content_len, &otaHandle);
                if (err != ESP_OK)
                  return sendError(con, 500, std::string{"Can't start ota update: "} + esp_err_to_name(err), true);
    
                int receivedBytes = 0;
                do {
                  auto end = httpd_req_recv(con.req, buf.data(), buf.size());
                  // ESP_LOGE(TAG, "Received %d", receivedBytes);
                  // hexDump("RECV:", buf.data(), end);
                  if (end <= 0) {
                    esp_ota_abort(otaHandle);
                    return sendError(con, 500, "Error receiving", true);
                  }
                  err = esp_ota_write(otaHandle, buf.data(), end);
                  if (err != ESP_OK) {
                    esp_ota_abort(otaHandle);
                    return sendError(con, 500, std::string{"Error writing: "} + esp_err_to_name(err), true);
                  }
                  receivedBytes += end;
                } while (receivedBytes < con.req->content_len);
    
                err = esp_ota_end(otaHandle);
                if (err != ESP_OK)
                  return sendError(con, 500, std::string{"Failed to end: "} + esp_err_to_name(err), true);
    
                err = esp_ota_set_boot_partition(updatePartition);
                if (err != ESP_OK)
                  return sendError(con, 500, std::string{"esp_ota_set_boot_partition failed: "} + esp_err_to_name(err), true);
                auto ret = sendOK(con);
                FactoryResetServiceCon().reboot(1000 / portTICK_PERIOD_MS);
                return ret;
              }));
            }
    

    I also used a custom partition table for 2 partitions so that when my program crashes it can just go back to boot the previous version.

    Here it is for reference:

    partitions.csv

    # Name,   Type, SubType, Offset,  Size, Flags
    # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
    nvs,      data, nvs,     0x011000, 0x006000,
    otadata,  data, ota,     0x017000, 0x002000,
    phy_init, data, phy,     0x019000, 0x001000,
    ota_0,    app,  ota_0,   0x020000, 0x1F0000,
    ota_1,    app,  ota_1,   0x210000, 0x1F0000,
    

    Note: This partition table is for a special model of the ESP32 though.

    Also another disclaimer: This code does not represent my current coding abilities and may be outdated - it worked well though.



  • raldone01@lemmy.worldtoTechnology@lemmy.world*Permanently Deleted*
    link
    fedilink
    English
    arrow-up
    3
    ·
    edit-2
    5 months ago

    Back in school my friends all flashed their mcus with 4-8MB images over serial with 115200 baud. I set up ota updates over wifi. They were all fascinated by my speedy flashes. However when I offered to help them set it up, not one was interested because their setup was working as is and slow flashing is not a “bad” thing since it gave them an excuse to do other things.

    We are talking minutes vs seconds here.

    The teachers were surprised by my quick progress and iterations. When I told them my “trick” the gave me bonus points but also were not interested in learning how to do ota which was very easy. A simple 20 minute first time setup would have saved sooo much time during the year.