====== Web of Things at FOSDEM 2026 ====== ===== Quick start ===== * [[https://wot-wrench.chrpaul.de/#try=https://wot-why.jaller.de/receipt-printers-for-events/photo|Print photos on the receipt printer]] (select a photo then click "Invoke") * [[https://wot-wrench.chrpaul.de/#try=https://wot.chrpaul.de/image-storage/LDN3dJE3vu|Display images on the e-paper screen]] ===== Advanced: HTTP API ===== Web of Things is a set of standards for Internet of Things use cases. At the Matrix Hackathon and FOSDEM 2026, I brought the following hardware. They support support Web of Things via HTTP and Websockets. ==== Receipt printer ==== Current status: Ready {{:web_of_things:43384356-377a-4866-ad5c-95b7f105e780.jpg?300|}} * Epson TM-T20III * Native colors: 1-bit * ''#ffffff'' (white) * ''#000000'' (black) * Native resolution: 576 pixels wide, any height (will be converted to be divisible by 8 pixels) * Supported image formats: PNG (best results), JPG === URLs === * URL for printing images: https://wot-wrench.chrpaul.de/#try=https://wot-why.jaller.de/receipt-printers-for-events/photo * URL for scripts: https://wot-why.jaller.de/receipt-printers-for-events/photo/actions/print-photo * UI for printing text: https://wot-wrench.chrpaul.de/#try=https://wot-why.jaller.de/receipt-printers-for-events/text * URL for scripts: https://wot-why.jaller.de/receipt-printers-for-events/text/actions/print-text ==== Code examples (images) ==== Bash: curl -X POST \ -H "Content-Type: application/json" \ --data "{\"image\":\"$(base64 image.png | tr -d '\n')\"}" \ https://wot-why.jaller.de/receipt-printers-for-events/photo/actions/print-photo Or in NodeJS / Bun / Deno: import { readFile } from "node:fs/promise"; const image = await readFile("image.png"); const response = await fetch("https://wot-why.jaller.de/receipt-printers-for-events/photo/actions/print-photo", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ image: image.toString("base64"), }), }); if (!response.ok) { throw Error(`Failed to queue print job. HTTP ${response.status}`); } ==== Code examples (text) ==== Bash: curl -X POST \ --header "Content-Type: application/json" \ --data '{"text":"Hello World!"}' \ https://wot-why.jaller.de/receipt-printers-for-events/text/actions/print-text Or in NodeJS / Bun / Deno: const response = await fetch("https://wot-why.jaller.de/receipt-printers-for-events/text/actions/print-text", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ text: "Hello World!", }), }); if (!response.ok) { throw Error(`Failed to queue print job. HTTP ${response.status}`); } ==== E-paper screen ==== Current status: Ready at https://wot-wrench.chrpaul.de/#try=https://wot.chrpaul.de/image-storage/LDN3dJE3vu {{:web_of_things:c31e9a7b-9110-497c-89f8-39eadb726685.jpg?400|}} * [[https://www.waveshare.com/7.3inch-e-paper-hat-f.htm|7.3inch ACeP 7-Color E-Paper Display]] * Native colors: 7 colors * ''#000000'' (black) * ''#ffffff'' (white) * ''#ff0000'' (red) * ''#00ff00'' (green) * ''#0000ff'' (blue) * ''#ffff00'' (yellow) * ''#ff8000'' (orange) * Native resolution: 800x480 pixels * Supported image formats: PNG (best results), JPG === URLs === Use these URLs to test your scripts. They will not display anything on the screen, but the Thing has a preview property. * Test URL: https://wot-wrench.chrpaul.de/#try=https://wot.chrpaul.de/image-storage/fosdem * Image property for scripts: https://wot.chrpaul.de/image-storage/fosdem/properties/image Use this URL to HTTP PUT an image onto the screen. * Production URL for scripts: https://wot-wrench.chrpaul.de/#try=https://wot.chrpaul.de/image-storage/LDN3dJE3vu * Image property for scripts: https://wot.chrpaul.de/image-storage/LDN3dJE3vu/properties/image ==== Code Examples ==== To upload a local PNG file ''image.png'' via a Bash: curl -X PUT \ -H "Content-Type: application/json" \ --data "\"$(base64 image.png | tr -d '\n')\"" \ https://wot.chrpaul.de/image-storage/fosdem/properties/image Or in NodeJS / Bun / Deno: Have a look at this demo project: https://codeberg.org/jaller94/wot-fosdem-demo import { readFile } from "node:fs/promise"; const image = await readFile("image.png"); const response = await fetch("https://wot.chrpaul.de/image-storage/fosdem/properties/image", { method: "PUT", headers: { "Content-Type": "application/json", }, body: JSON.stringify(image.toString("base64")), }); if (!response.ok) { throw Error(`Failed to upload image. HTTP ${response.status}`); } ===== Dithering ===== Images will be resized and [[https://en.wikipedia.org/wiki/Dither|dithered]] automatically. However, if you want full control over the result, you can send images in the right resolution using only the supported color palette. For TypeScript, I recommend using [[https://jsr.io/@jaller94/dither-me-this|my fork of dither-me-this]]. It supports custom color palettes which is optimal for the e-paper screens. Previously, I used [[https://jsr.io/@jaller94/canvas-dither|my fork of canvas-dither]]. Its API is easier and more mature, but it only supports 1-bit dithering. It's most suitable for the receipt printer.