# Extrudex > Filament inventory and print tracking system for CubeCraft Creations. Extrudex replaces Spoolman with a fully custom solution built for Joshua's 7-printer fleet. It tracks spool stock, per-print material consumption, and cost-of-goods — with a touch-optimized kiosk interface on a Raspberry Pi 5. --- ## Tech Stack | Layer | Technology | |---|---| | Backend | ASP.NET Core Web API (.NET 8) | | Database | PostgreSQL (snake_case via EF Core) | | ORM | Entity Framework Core | | Real-time | SignalR (`PrinterHub`) | | Printer integration | Moonraker REST/WebSocket (Elegoo) · MQTTnet + TLS (Bambu Lab) | | Frontend | Angular 17+, Angular Material | | Deployment | Docker · Docker Compose | --- ## Project Structure ``` Extrudex/ ├── backend/ │ ├── Domain/ │ │ ├── Base/ # BaseEntity, AuditableEntity │ │ ├── Entities/ # Spool, Printer, PrintJob, FilamentUsage, │ │ │ # AmsUnit, AmsSlot, MaterialBase, │ │ │ # MaterialFinish, MaterialModifier │ │ ├── Enums/ # ConnectionType, DataSource, JobStatus, │ │ │ # PrinterStatus, PrinterType, QrResourceType │ │ └── Interfaces/ # ICostPerPrintService, IFilamentUsageSyncService, │ │ # IMoonrakerClient, IQrCodeService │ ├── Infrastructure/ │ │ ├── Configuration/ # FilamentUsageSyncOptions │ │ ├── Data/ │ │ │ ├── Configurations/ # EF Core fluent configs (snake_case) │ │ │ ├── Migrations/ # EF migrations │ │ │ ├── Seed/ # SeedData.cs │ │ │ └── ExtrudexDbContext.cs │ │ └── Services/ # CostPerPrintService, FilamentUsageSyncService, │ │ # MoonrakerClient, QrCodeService │ └── API/ │ ├── Controllers/ # Filaments, Spools, Printers, PrintJobs, │ │ # MaterialBases, MaterialFinishes, │ │ # MaterialModifiers, MaterialLookups, │ │ # CostAnalysis, QR │ ├── DTOs/ # Request/response shapes per domain │ ├── Filters/ # FluentValidationFilter │ ├── Hubs/ # PrinterHub, IPrinterClient │ ├── Jobs/ # FilamentUsageSyncJob (background) │ ├── Validators/ # FluentValidation validators │ ├── Program.cs │ └── appsettings.json ├── frontend/ │ └── src/app/ │ ├── components/ # DashboardSummary, FilamentFilter, FilamentTable │ ├── models/ # Filament, Agent model types │ └── app.routes.ts ├── design/ # UX specs and mockups (kiosk + mobile) ├── docker-compose.dev.yml ├── deploy.sh └── README.md ``` --- ## Domain Model ### Materials (normalized taxonomy) | Entity | Description | |---|---| | `MaterialBase` | The base material type — PLA, PETG, ABS, ASA, TPU, etc. | | `MaterialFinish` | Required. Surface finish — Basic (default), Matte, Silk, Sparkle, etc. | | `MaterialModifier` | Optional. Composite fill — Carbon Fiber, Glass Fiber, Wood, etc. | **Rules:** - `MaterialFinish` is required — every spool must have one. Default is `"Basic"`. - `MaterialModifier` is optional — plain PLA has no modifier. ### Consumption calculation ``` grams_used = mm_extruded × filament_cross_section_area × material_density ``` Grams are always derived, never assumed from printer telemetry directly. ### Printers | Type | Integration | |---|---| | Bambu Lab (×5) | MQTTnet with TLS | | Elegoo Centauri Carbon | Moonraker REST + WebSocket | | Elegoo Saturn (resin ×2) | Manual / future | AMS units and slots are modelled as `AmsUnit` → `AmsSlot[]` → `Spool`. --- ## Key Design Decisions 1. **Spoolman rejected** — Full custom system for data model control and workflow flexibility. 2. **`"Basic"` not `"Standard"`** — Default `MaterialFinish` value is `Basic`. 3. **`MaterialFinish` is required** — No null/optional finish state allowed. 4. **`MaterialModifier` is optional** — Not every spool has a modifier. 5. **Derived consumption** — Grams calculated from mm × density, never assumed. 6. **Push over poll** — SignalR and MQTT preferred over periodic polling. 7. **Snake_case PostgreSQL** — All database identifiers follow this convention via EF Core. --- ## Getting Started ### Prerequisites - .NET 8 SDK - Node.js 20+ - Docker + Docker Compose - PostgreSQL (or use the dev compose stack) ### Backend ```bash cd backend # Restore and build dotnet restore dotnet build # Apply migrations dotnet ef database update # Run API (dev) dotnet run --project API ``` API runs at `http://localhost:5000` · Swagger at `http://localhost:5000/swagger` ### Frontend ```bash cd frontend npm install ng serve ``` Frontend runs at `http://localhost:4200` ### Docker (dev stack) ```bash docker-compose -f docker-compose.dev.yml up ``` --- ## Configuration `backend/appsettings.json` — override in `appsettings.Development.json` or environment variables: | Key | Default | Description | |---|---|---| | `ConnectionStrings:ExtrudexDb` | `Host=localhost;...` | PostgreSQL connection string | | `FilamentUsageSync:PollingInterval` | `00:05:00` | Sync job interval | | `FilamentUsageSync:RequestTimeout` | `00:00:30` | Moonraker request timeout | | `FilamentUsageSync:Enabled` | `true` | Enable/disable background sync | --- ## Real-Time Events SignalR hub endpoint: `/hubs/printer` Clients receive `PrinterHub` events for live printer status, job progress, and spool consumption updates. --- ## API Overview | Route prefix | Resource | |---|---| | `/api/filaments` | Filament catalog | | `/api/spools` | Spool inventory | | `/api/printers` | Printer registry | | `/api/print-jobs` | Print job tracking | | `/api/material-bases` | Material base types | | `/api/material-finishes` | Material finishes | | `/api/material-modifiers` | Material modifiers | | `/api/material-lookups` | Combined material lookup | | `/api/cost-analysis` | Cost-per-print and COGS | | `/api/qr` | QR code generation | Full schema available at `/swagger` when running in dev. --- ## CI Gitea Actions pipeline (`.gitea/workflows/dev.yml`) runs on every push to `dev`: - `dotnet build` - Frontend `ng build` --- ## Branch & PR Rules - All feature branches target `dev` — **never `main`** - Branch naming: `agent//CUB-N-short-description` - PR titles: `CUB-N: short description` - PRs require Otto review before Joshua merges --- *Built by CubeCraft Creations · Orchestrated by Otto*