1 Punkte von GN⁺ 2023-09-11 | 1 Kommentare | Auf WhatsApp teilen
  • Um zu vermeiden, dass an den Verpflegungsstationen beim Gravel Worlds Long Voyage in Nebraska die Pizza ausgeht, baute ich eine Automatisierung, die anhand der GPS-Position meines Fahrrads vorab Pizza bei Casey's bestellt
  • Die Struktur: AWS Location-Geofencing erkennt, wenn sich der GPS-Tracker entfernt, und Lambda führt passend zur ETA des nächsten Stopps die Online-Bestellung aus
  • Da Casey's keine öffentliche Bestell-API hat, nutzte ich Playwright zum Screen-Scraping der React-basierten Website; das Bestellergebnis wurde per Push-Benachrichtigung auf iPhone und Apple Watch zugestellt
  • Im echten Rennen kam zwar eine Erfolgsbenachrichtigung für die Bestellung an, im Laden gab es jedoch keinen Bestelleintrag — ein false positive der Browser-Automatisierung in der Cloud
  • Danach stellte ich es so um, dass ein Video der Browser-Aktionen in S3 gespeichert wird; Testbestellungen klappten dann, aber in der Lambda-Umgebung ist Zuverlässigkeit allein aus lokalen Tests schwer abzuleiten

Warum ich während des Rennens Pizza sichern wollte

  • Ich nahm während der Erntesaison im Mittleren Westen am Fahrradrennen Gravel Worlds Long Voyage in Nebraska teil
  • Im Vorjahr waren die schnellen Fahrer zuerst angekommen und hatten die gesamte Casey's-Pizza an der Verpflegungsstation mitgenommen; als ich ankam, war keine Pizza mehr übrig
  • Das Ziel in diesem Jahr war, rechtzeitig zum Stopp frische Pizza im Voraus zu bestellen
  • Auf meinen bestehenden serverlosen Fahrrad-GPS-Tracker wollte ich eine Logik aufsetzen, die beim Verlassen eines bestimmten Geofence ein Bestellskript ausführt

So wurde die Bestellung mit GPS und Lambda ausgelöst

  • Das Gesamtdesign bestand aus Geofences in AWS Location, die den GPS-Tracker überwachen
    • Wenn der Tracker den Geofence verlässt, wird eine Lambda-Funktion ausgelöst
    • Lambda berechnet die ETA bis zur nächsten Verpflegungsstation
    • Passend zu dieser berechneten Zeit wird Casey's-Pizza bestellt
  • Da Casey's keine öffentliche API für Online-Bestellungen hat, fiel die Wahl auf Screen-Scraping der Website
    • Die Casey's-Website war eine komplexe, clientseitig gerenderte React-App
    • Statt eines gewöhnlichen Scrapers wurde Playwright verwendet
    • Playwright in Lambda auszuführen war so knifflig, dass es dazu einen eigenen Beitrag geben könnte
  • Um den Bestellstatus zu prüfen, wurde eingerichtet, bei Erfolg oder Fehler Push-Benachrichtigungen an Telefon und Uhr zu senden
    • Auch die Einrichtung von Web Push auf iOS-Geräten wäre Stoff für einen eigenen Beitrag gewesen

Vor-Ort-Ergebnis anders als die Erfolgsbenachrichtigung

  • Der Geofence zum Auslösen der Bestellung wurde in der Nähe von Meile 180 des Rennens gesetzt
  • Die Pizza sollte bei Meile 200 abgeholt werden
  • Sobald ich den Geofence verlassen hatte, kam auf der Uhr eine Push-Benachrichtigung über eine erfolgreiche Pizzabestellung an
  • Als ich an der Verpflegungsstation ankam, gab es am Tresen keine Bestellung, und auch im Laden war kein Bestellverlauf vorhanden
  • Ein Blick ins Konto zeigte ebenfalls keine tatsächlich erzeugte Bestellung — es war also nur ein false positive mit Erfolgsbenachrichtigung
  • Vor Ort gab es ein paar vorbereitete Pizzastücke, die ich stattdessen kaufte
  • Danach dachte ich bis zum Ende des 300-Meilen-Rennens weiter darüber nach, was in der Lambda-Funktion schiefgelaufen war

Videoaufzeichnung statt Logs lieferte Hinweise

  • Nach dem Rennen sah ich die Logs durch, fand dort aber keine Informationen zur Fehlerursache
  • Den Logs zufolge hatte alles still und leise erfolgreich ausgesehen, daher gab es kaum Ansatzpunkte fürs Debugging
  • Einige Tage später änderte ich Lambda so, dass die Browser-Aktionen als Video aufgezeichnet und in einen S3-Bucket hochgeladen werden
  • Beim Test mit der angepassten Version funktionierte die Bestellung tatsächlich, und eine Hawaiian pizza konnte regulär abgeholt werden
  • Die genaue Ursache ist nicht geklärt
    • Möglicherweise beendete Lambda die Verarbeitung, sobald im eingebetteten Playwright-Browser das letzte form.submit() ausgeführt wurde
    • Möglicherweise konnte die Online-Bestellseite nicht bestätigen, dass der Browser die Erfolgsmeldung empfangen hatte, sodass die Bestellung nicht vollständig verarbeitet wurde
    • Die zusätzliche Zeit für Videoverarbeitung und Upload könnte dem Browser genug Zeit zum Aufräumen gegeben haben

Was ich beim nächsten Mal ändern würde

  • Eine React-Client-App per Cloud-Browser zuverlässig zu screen-scrapen ist möglich, aber sehr knifflig
  • Wenn ich es noch einmal bauen würde, käme in Frage, die native Casey's-App zu reverse engineeren und direkt ihre interne API auszulösen
  • Es braucht einen guten Workflow, um georäumliche Abläufe zu simulieren
    • Zuerst testete ich mit einem Geofence in der Nähe meines Hauses
    • Um 23 Uhr tatsächlich nach draußen zu gehen und zu testen, wurde schnell lästig
  • Tests in der realen Umgebung dürfen nicht vernachlässigt werden
    • Vor dem Rennen testete ich die Funktion meist lokal auf meiner Workstation
    • Das vermittelte die falsche Sicherheit, dass lokaler Erfolg auch in der Lambda-Umgebung korrekt funktioniert
  • Wenn man befürchtet, dass Casey's-Pizza ausverkauft ist, kann man auch versuchen, mehr als 30 Minuten Abstand zur Spitzengruppe zu haben, damit der Laden Zeit hat, neue Stücke vorzubereiten
  • Der Code ist auf GitHub veröffentlicht: https://github.com/mattdsteele/spot-tracker-tracker/…

1 Kommentare

 
GN⁺ 2023-09-11
Hacker-News-Kommentare
  • Colin kann während der Lieferung auch Pizza machen: https://youtu.be/YjyJRTM0knE?si=fes2lbRntUlciPSH

    • Lustig ist, dass das Konzept dieses YouTube-Videos tatsächlich das Geschäftsmodell eines von SoftBank finanzierten Startups war, das 500 Millionen Dollar eingesammelt hatte.
      Der fatale Fehler des scheinbar wasserdichten Plans war, dass die Pizza herumflog und alle Beläge verlor, wenn der Truck über Bodenwellen fuhr: https://gizmodo.com/zume-softbank-ai-pizza-delivery-stellar-...
    • Das passiert also, wenn man den GIL entfernt.
      Das Video hat mich dieses Jahr auf YouTube am meisten zum Lachen gebracht.
    • Ich weiß nicht, ob Colins Leichtsinn wie bei Electroboom nur gespielt ist oder ob er wirklich so leichtsinnig ist, wie er wirkt.
      Ich kann das immer noch nicht einschätzen, und seltsamerweise macht es das schwerer anzusehen. Natürlich würde er wohl kein Video veröffentlichen, in dem etwas richtig schiefgeht.
    • Meine Güte, ein ganzer Sonntagabend ist verschwunden.
      Ich habe zweieinhalb Stunden lang zugesehen, wie dieser Typ einen Tunnel von seinem Haus bis zum Schuppen gräbt; ein wirklich unterhaltsamer Kanal.
  • Sehr gut. Fühlt sich an wie eine Interpretation von pizzatool fürs 21. Jahrhundert.
    https://donhopkins.medium.com/the-story-of-sun-microsystems-...
    Nebenbei: Die Pizzeria Waypoint Pizza in Tiburon liefert, wenn man nett fragt, auch aufs Wasser der San Francisco Bay. Das ist ziemlich praktisch bei weniger ernst gemeinten, skurrilen Yachtregatten wie dem Three Bridge Fiasco.

    • Normale Pizzalieferung kann ja schon 5 bis 10 Dollar extra kosten; ich frage mich, wie viel Lieferung aufs Wasser kostet, wenn man nett fragt.
  • Dean Karnazes hat bei einem Ultralauf etwas Ähnliches ohne Technik gemacht.
    Er soll die Pizza wie einen Burrito zusammengerollt getragen haben: https://gffmag.com/the-raw-endurance-of-ultramarathon-man-de...

    • Ausdauerlaufen ist im Grunde genommen Essen.
  • Wenn es eine React-Website ist, heißt das wahrscheinlich, dass es eine API gibt, die man direkt nutzen kann.
    Zum Abrufen des Tokens muss man sich vielleicht einloggen, aber das wäre deutlich robuster.

    • Stimme zu. Ich frage mich immer, warum man den Bildschirm ausliest, statt Netzwerk-Requests zu beobachten und nachzuspielen.
      Das ist viel günstiger und viel robuster; übersehe ich da etwas?
  • Ich hatte wirklich viel Spaß an diesem Beitrag.
    Ein interessantes technisches Problem, Pizza, der Umstand, dass ich nachschlagen musste, was „s-tier“ bedeutet, die schon für sich lustige Prämisse plus zusätzlicher Humor, und am Ende noch das Mea culpa samt Vermutung zur Bug-Ursache — da war viel Gutes dabei. Die Theorie wirkt auch plausibel, aber sicher ist sie nicht.

    • Ich fand ihn überhaupt nicht gut. 100 Schichten Abstraktion, Cloud-Klebstoff und Provisorien, die am Ende eine nicht funktionierende Rube-Goldberg-Maschine ergeben.
      Es fühlte sich an wie eine Sammlung von allem, was an moderner Technik schlecht ist.
  • Ehrlich gesagt ziemlich cool. Ich frage mich, ob man etwas Ähnliches auch mit Diensten wie Deliveroo machen könnte.
    An einem bestimmten Datum X, wenn die Bedingungen passen, etwa wenn man Überstunden macht und noch ungefähr Z Entfernung von zu Hause entfernt ist, automatisch eine vorher festgelegte Bestellung Y aufgeben — das scheint machbar.

    • Warum würdest du lügen, dass das ziemlich cool ist? Es klingt ein bisschen seltsam, das extra klarzustellen.
    • Man müsste es mit einem Fitness-Tracker verbinden, sodass nur so viel Pizza geliefert wird, dass man ein Kaloriendefizit beibehält und Gewicht verliert.
    • Essensbestelldienste sollten für solche Zwecke eigentlich eine gute API haben.
      Warum sollte man es nicht leicht machen, Essensbestellungen und Bezahlung in IFTTT-artige Hacks zu integrieren?
  • Ich habe gute Erinnerungen daran, mit Casey's Pizza aufzuwachsen.
    Immer wenn ich in den Mittleren Westen zurückkomme, esse ich sie; ich kann nicht genau sagen, was es ist, aber sie hat einen eigenen Charme.

    • Liegt es daran, dass sie fettiger ist? Die Frühstückspizza ist die beste. Besonders meist am Tag nach ein paar Busch Light.
  • Ah, am Ende hat es also nicht funktioniert.
    Das bei Meile 200 herauszufinden, muss ziemlich hart gewesen sein.

  • Software, Fahrräder und Pizza — das sind Dinge, die ich im Leben mag.
    Dieses Projekt und den Artikel fand ich wirklich unterhaltsam, und sie haben mich auch auf ähnliche Ideen gebracht.

    • Das sind auch Dinge, die ich mag. OP, du und ich sollten einen Club gründen.
  • Ich hätte wahrscheinlich einfach freihändig angerufen oder einen Freund gebeten anzurufen und das per Nachricht ausgelöst.
    Außerdem wird es ständig „Lieferung“ genannt, aber eigentlich ist es doch Abholung, oder?