Merge branch 'dev' into agent/dex/CUB-10-imoonrakerclient-interface-dtos
Some checks failed
Dev Build / build-test (pull_request) Failing after 57s
Dev Build / deploy-dev (pull_request) Has been skipped
Dev Build / notify-success (pull_request) Has been skipped
Dev Build / notify-failure (pull_request) Successful in 3s

This commit is contained in:
2026-04-27 18:50:41 -04:00

220
README.md
View File

@@ -0,0 +1,220 @@
# 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*