🇺🇸 · Noisebridge · WebDaniel
Create donation displays page New page [[File:Donation_display.jpeg|thumb|right|300px|The donation screen]] The '''donation screens''' are the portrait TVs with LED strips around them. There are four of them around the space. Whenever someone donates through [https://donate.noisebridge.net donate.noisebridge.net], every screen updates within a second or two, plays an animation, and the LEDs do something. == What's on the screen == The top shows the most recent donation: how much, what it was for ("General Donation", "Laser Cutter", "Club Maté"...) and when. Below that is a list of the previous 20. New memberships show up too, as "Membership" with no dollar amount. The QR code in the corner says "Scan to show fireworks!" and goes to a $100 donation. === Easter eggs === Certain amounts do special things. Some of them: * Anything with a 69 in it gets a NICE sticker. * $13.37, $133.70, $313.37 - Matrix rain * $4.20, $420 - Snoop Dogg * $17.76, $86.74 - 'Merica * $42.00 - "So long and thanks for all the fish!" * Everything else gets confetti If the new donation is the largest one currently on the screen, the amount gets a rainbow sheen and the LEDs go into a rainbow hyperdrive. Feel free to add more. They live in <code>src/assets/js/alerts.mjs</code> and <code>src/assets/js/effects/</code>. == How it works == Donations go through Stripe. When a payment succeeds, Stripe sends a webhook to the donate portal server, which pushes the donation over a WebSocket to the <code>/alerts</code> page. The kiosk has that page open in a browser. When a donation comes in, the page redraws itself, plays the effect, and tells the LED server on the Pi what to do. If a bunch of donations arrive at once it queues them up and shows one every 15 seconds. There's no internal database. Everything, including the history list, comes from Stripe. The alerts page is behind a password so random people can't open it and trigger the LEDs from their phone. == Hardware == Each of the four displays is: * Raspberry Pi 5, 2GB * NeoPixel strip (WS2812B), 149 LEDs, taped around the edge of the TV * The TV, rotated 90 degrees The Pi boots straight into Firefox in kiosk mode under <code>cage</code> and loads the alerts page. A small watchdog script kicks Firefox back to the page if it ever lands on an error screen. Setup is all Ansible, in the [https://git.noisegarden.nexus/noisebridge/kiosk-provisioning kiosk-provisioning] repo. == The RGB server == The LEDs are driven by <code>rgb-server</code>, a small Bun program that runs on the Pi as a systemd service and listens on <code>localhost:3000</code>. Endpoints: * <code>POST /update</code> - start an animation * <code>POST /reset</code> - LEDs off * <code>GET /</code> - LED count, brightness, whether anything's running === Talking to localhost from an HTTPS page === The alerts page is served from donate.noisebridge.net, but it's running in a browser on the Pi. So the page's JavaScript can just <code>fetch("http://localhost:3000/update")</code> and it reaches the RGB server on the same box. Browsers treat localhost as a secure context, so the HTTPS page is allowed to make a plain HTTP request to it, and the RGB server answers with CORS headers that only allow <code>https://donate.noisebridge.net</code> as the origin. === The animations are shipped as JavaScript === The RGB server doesn't know any animations. The page sends them over, as source code: <syntaxhighlight lang="javascript"> // donate-portal: src/assets/js/effects/led_effects.mjs fetch("http://localhost:3000/update", { method: "POST", body: JSON.stringify({ function: confettiLedFn.toString(), data: { /* rocket positions, colors, whatever */ }, timeout: 5000, // optional, turns off after 5s }), }); </syntaxhighlight> The server runs <code>new Function(...)</code> on the string and then calls it 20 times a second for every LED: The upside is that adding a new light show is just a donate-portal deploy; nobody has to SSH into the Pi. The catch is that the function has to be self-contained. It only gets its four arguments. == Source == * Donate portal (site, alerts page, effects): https://github.com/noisebridge/donate-portal ** <code>src/views/alerts.tsx</code>, <code>src/assets/js/alerts.mjs</code>, <code>src/assets/js/effects/led_effects.mjs</code> * Pi provisioning and rgb-server: https://git.noisegarden.nexus/noisebridge/kiosk-provisioning