this post was submitted on 25 Jun 2025
654 points (98.5% liked)

Technology

71897 readers
4978 users here now

This is a most excellent place for technology news and articles.


Our Rules


  1. Follow the lemmy.world rules.
  2. Only tech related news or articles.
  3. Be excellent to each other!
  4. Mod approved content bots can post up to 10 articles per day.
  5. Threads asking for personal tech support may be deleted.
  6. Politics threads may be removed.
  7. No memes allowed as posts, OK to post as comments.
  8. Only approved bots from the list below, this includes using AI responses and summaries. To ask if your bot can be added please contact a mod.
  9. Check for duplicates before posting, duplicates may be removed
  10. Accounts 7 days and younger will have their posts automatically removed.

Approved Bots


founded 2 years ago
MODERATORS
 

The revived No JS Club celebrates websites that don't use Javascript, the powerful but sometimes overused code that's been bloating the web and crashing tabs since 1995. The No CSS Club goes a step further and forbids even a scrap of styling beyond the browser defaults. And there is even the No HTML Club, where you're not even allowed to use HTML. Plain text websites!

The modern web is the pure incarnation of evil. When Satan has a 1v1 with his manager, he confers with the modern web. If Satan is Sauron, then the modern web is Melkor [1]. Every horror that you can imagine is because of the modern web. Modern web is not an existential risk (X-risk), but is an astronomic suffering risk (S-risk) [2]. It is the duty of each and every man, woman, and child to revolt against it. If you're not working on returning civilization to ooga-booga, you're a bad person.

A compromise with the clubs is called for. A hypertext brutalism that uses the raw materials of the web to functional, honest ends while allowing web technologies to support clarity, legibility and accessibility. Compare this notion to the web brutalism of recent times, which started off in similar vein but soon became a self-subverting aesthetic: sites using 2.4MB frameworks to add text-shadow: 40px 40px 0px hotpink to 400kb Helvetica webfonts that were already on your computer.

I also like the idea of implementing "hypotext" as an inversion of hypertext. This would somehow avoid the failure modes of extending the structure of text by failing in other ways that are more fun. But I'm in two minds about whether that would be just a toy (e.g. references banished to metadata, i.e. footnotes are the hypertext) or something more conceptual that uses references to collapse the structure of text rather than extend it (e.g. links are includes and going near them spaghettifies your brain). The term is already in use in a structuralist sense, which is to say there are 2 million words of French I have to read first if I want to get away with any of this.

Republished Under Creative Commons Terms. Boing Boing Original Article.

you are viewing a single comment's thread
view the rest of the comments
[–] Banthex@feddit.org 23 points 17 hours ago (3 children)

Jesus. This is getting out of hand.

[–] Agent641@lemmy.world 6 points 17 hours ago* (last edited 17 hours ago) (2 children)

We can go further. We could take away your fancy "URL"s and just use IP addresses for navigation.

Heck, we could do away with TCP/IP altogether and network over serial. It's a perfectly functional protocol with several baud rates to choose from. I like ol' reliable 9600, but I sometimes dabble in 115200 when I'm feeling adventurous.

[–] hakunawazo@lemmy.world 3 points 8 hours ago

At this point: Just sing the voice dial tone by yourself.

[–] raldone01@lemmy.world 3 points 13 hours ago* (last edited 13 hours ago) (1 children)

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.

[–] DontNoodles@discuss.tchncs.de 2 points 9 hours ago (2 children)

You've convinced me to learn and implement OTA on my 8266. Thanks!

[–] raldone01@lemmy.world 1 points 4 hours ago* (last edited 3 hours 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.world 1 points 4 hours ago

Hahahah. Awesome. Have fun! You just need a simple webserver. The builtin one will do and then you use the ota functions of the ESP IDF.

[–] MonkderVierte@lemmy.zip 4 points 14 hours ago

Forces one to avoid deep links and parameter crap. I'm sorta two minds about this.

[–] HeyThisIsntTheYMCA@lemmy.world 1 points 3 hours ago

I photocopied my screen (those all in one printers are heavy) and I cannot find the glue little help?