← Tilbage til The Vault
PoC⚡ AI-augmentedlive

ArchiveFLMT

Filamentspole-lager med Moonraker-integration til automatisk forbrugssporing. NFC læs/skriv (OpenSpool, OpenPrintTag), mobil QR-scanner til fysisk spolesøgning, nightly leverandørkatalog-scraper og AI-chat-assistent med fuldt spole- og printhistorik-kontekst.

#python#nfc#moonraker#deepseek#fastapi
ArchiveFLMT

Selvinitieret, selvhostet projekt. Bygget og drevet af mig som arkitekt, product owner og reviewer, med AI som en overvåget "lærling" i udviklingsprocessen og i dele af selve produktet.

DEL 1: Resume

ArchiveFLMT er den eneste sandhedskilde for filamentspoler i et 3D-printopsætning: hvad der findes, hvad der sidder på hvilket værktøj, og hvor meget der er tilbage. Spoler registreres via QR/NFC fra en telefon, forbruget trækkes automatisk, når et print er færdigt, og slicereren får kun filament, der faktisk er på lager.

Tech stack

  • Backend: Python 3.11+, FastAPI/uvicorn, Pydantic v2, asyncio-baggrundsopgaver, uv (ca. 9.600 linjer Python og HTML)
  • Frontend: Alpine.js + Tailwind (desktop), servergenereret HTML (mobil, uden JS-framework)
  • Lagring: to JSON-filer (lager og printjobs), ODS-eksport til backup/gendannelse. Ingen database
  • Enhedsintegration: Moonraker (websocket + HTTP), Brother QL-710W-etikettprinter, NFC (OpenSpool, OpenPrintTag, producenters MIFARE-tags via en Android-hjælpeapp), QR-scanning med telefonkamera over HTTPS
  • Økosystemintegration: Archive3D (printjobs, slicerprofiler), valgfri tovejs-synkronisering med Spoolman
  • AI: DeepSeek-chatassistent med live lager, historik og skrabet leverandørkatalog som kontekst; LLM som reserve til skrabning af ikke-standard webshops

Største bedrift At lukke sløjfen mellem software og den fysiske verden uden manuel dataindtastning. En sidecar-fil (.flmt.json), som Archive3D skriver ved Send & Print, fungerer som håndtryk: ArchiveFLMT finder den på printeren, venter på at printet bliver færdigt, trækker den rette mængde fra den rette spole og sletter først filen efter succes. To uafhængige services, en printer og en telefon samarbejder uden delt database og uden message broker.

DEL 2: Dybdegående baggrund

Problemet

Enhver med flere printere eller en multi-værktøjsprinter støder på de samme spørgsmål: hvilken spole sidder på værktøj 3, hvor meget er der tilbage, er den for tør eller for fugtig, og hvad skal jeg bestille næste gang? Det typiske svar er et regneark, en håndskrevet etiket eller hukommelsen. Konsekvenserne er praktiske: print der løber tør midtvejs, forkerte temperaturer fordi slicerprofilen ikke passer til den rigtige spole, spoler ingen kan finde, og ingen historik over, hvad et print reelt kostede. Det er samme mønster som et uadministreret dele- eller aktivlager i en lille virksomhed: data findes, men kun i folks hoveder.

Arkitektur og løsning

Overordnet form. Én FastAPI-service ejer to JSON-filer og udstiller et REST-API, en desktop-UI og en mobil-UI. Alt andet er valgfrie integrationer:

ArchiveFLMT (FastAPI, systemd user service, HTTPS)
  ├── inventory.json / print_jobs.json
  ├── /api/*       REST (spoler, printjobs, notifikationer, integration, orca)
  ├── /            desktop-UI (Alpine.js + Tailwind)
  └── /mobile/*    servergenereret mobil-UI (registrering, finder, detalje)
Integrationer: Moonraker, Archive3D, Spoolman, Brother QL-710W, SpoolTagReader-app

Designvalg, der er værd at fremhæve

  • JSON-filer i stedet for database. Datasættet er hundredvis af spoler, ikke millioner af rækker. Almindelige filer er nemme at tage backup af, sammenligne og rette i hånden, og de fjerner en hel klasse driftsarbejde. Kompromiset (ingen garantier for samtidige skrivninger, ingen ad hoc-forespørgsler) er acceptabelt i denne skala og er dokumenteret.
  • Sidecar-håndtryk i stedet for tæt kobling. Archive3D skriver en lille JSON-fil ved siden af gcode på printeren. ArchiveFLMT poller efter den hvert femte minut, matcher den mod printhistorikken og sletter den, når den er behandlet. Hvis den ene side er nede, venter filen blot. Ingen delt tilstand og ingen genforsøgslogik at designe.
  • Defensive integrationsdetaljer lært på den hårde måde. Moonrakers almindelige filliste skjuler lydløst filer, der ikke er gcode, så directory-API'et skal bruges. Archive3D opretter jobs med andre ID'er end de kanoniske, så matchningen har en reserve. Det står i specifikationen, så det ikke skal opdages igen.
  • "Uafklaret" er en førsteklasses tilstand. Hvis en printslot ikke kan matches til en spole, markeres jobbet og dukker op som en notifikation med en afklaringsvej, i stedet for at gætte eller springe lydløst over.
  • Mobil uden app store. Telefon-UI'et er almindelig servergenereret HTML over HTTPS (kræves til kamera og Web NFC). Hvor browseren ikke kan læse producenters tags, overtager en lille Android-hjælpeapp, så web-UI'et forbliver den ene grænseflade.
  • Skraber, der ikke stoler på sig selv. Den natlige skraber af filamentkataloget genkender Shopify-butikker automatisk, filtrerer prøver og multipakker fra og opgraderer først en ændret post, når samme ændring ses i to kørsler i træk, som værn mod svingende LLM-output. Poster, der ikke er set i tre dage, markeres som muligvis udgåede.
  • Snapshots beskytter historikken. Mærke, materiale og farve gemmes på hver printpost, så sletning af en spole aldrig ødelægger tidligere historik.
  • Testdækningen er smal. Automatiske tests dækker Orca-profilgenerering og API (17 tests). Resten er verificeret mod den rigtige printer, etikettprinter og telefon.

AI som lærling

AI i selve produktet. En DeepSeek-chatassistent får hele konteksten ved hvert spørgsmål: aktive spoler, printhistorik, materialereferencen og det skrabede leverandørkatalog, inklusive hvilke poster der ser udgåede eller udsolgte ud. Den er tænkt til købsbeslutninger og materialesammenligninger, ikke til at ændre data. Skraberen bruger kun en LLM som reserve til butikker, der ikke er Shopify.

AI i udviklingsprocessen (human-in-the-loop). Jeg ejer krav, arkitektur og accept; en AI-kodeassistent implementerer. En levende specifikation (hver funktion, endpoint og datamodel) og en CLAUDE.md giver assistenten stabil kontekst mellem sessioner. Alt, der rører hardware, etiketter eller den levende printer, verificerer jeg selv. Specifikationen opdateres, når funktioner leveres, så dokumentation og kode ikke glider fra hinanden.

Lederens refleksion

  1. At lukke sløjfen slår flere funktioner. Værdien var ikke lagerskærmen, men at forbrug registreres uden, at nogen taster. Automatisering, der fjerner et manuelt trin, er det, der gør data troværdige.
  2. Vælg den simpleste lagring, der passer til data. Filer frem for database holdt driften nær nul. Et team bør kunne forklare, hvorfor en teknologi ikke blev brugt.
  3. Løs kobling gennem små kontrakter. En sidecar-fil er en kontrakt, som to teams (eller to services) kan blive enige om på få minutter og teste uafhængigt.
  4. Design til det umatchede tilfælde. Data fra den virkelige verden er ufuldstændige. At markere uafklarede poster til et menneske er billigere end at fejlsøge lydløst forkerte svar.
  5. Dokumentér integrationens særheder. Det meste tid gik med eksterne systemers adfærd. At skrive det ned gør én persons opdagelse til teamviden.

Ærlige begrænsninger. Single-user og selvhostet, ingen adgangsstyring for flere brugere, smal automatiseret testdækning og ingen CI. Bygget mellem maj og september 2026. I en virksomhed ville det være de første ting at tilføje.