221 lines
6.9 KiB
Markdown
221 lines
6.9 KiB
Markdown
# 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/<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*
|