Files
Lab8DATAPROCESSOR/README.md

351 lines
8.6 KiB
Markdown

# Bambuddy InvenTree Sync
Sidecar service for syncing successful Bambuddy print archives into InvenTree stock.
The service runs as a separate Docker container. It does not modify Bambuddy or InvenTree source code. Bambuddy is used as the print-history source, while InvenTree remains the stock-control system of record.
## What It Does
For each successful Bambuddy archive, the service:
- finds or creates an InvenTree `Part`;
- creates one InvenTree `StockItem` for the Bambuddy archive;
- writes `Weight` and `PrintTime` part parameters when those templates exist in InvenTree;
- uploads the Bambuddy archive thumbnail to the InvenTree part image;
- writes an InvenTree part URL back into Bambuddy archive `external_url`;
- stores sync state in SQLite to prevent duplicate stock items.
Failed, stopped, running, or still-printing archives are skipped when `SYNC_SUCCESS_ONLY=true`.
## Data Flow
```text
Bambuddy Archives
|
| webhook or polling
v
bambuddy-inventree-sync
|
| InvenTree API
v
Part + StockItem + Parameters + Image
|
| Bambuddy API
v
Archive external_url -> InvenTree Part page
```
## InvenTree Mapping
| Bambuddy data | InvenTree target |
| --- | --- |
| archive/model identity | `Part` |
| successful print archive | `StockItem` |
| target category | `Part.category` |
| target storage | `StockItem.location` |
| archive id | `StockItem.batch = bambuddy-<archive_id>` |
| filament weight | `Part` parameter `Weight` |
| print time | `Part` parameter `PrintTime` |
| archive thumbnail | `Part.image` |
| InvenTree part page | Bambuddy `external_url` |
## Duplicate Protection
The service is idempotent:
- each Bambuddy archive ID is stored in `data/sync.sqlite3`;
- each `StockItem` gets batch `bambuddy-<archive_id>`;
- rerunning backfill does not create duplicate stock items;
- repeat prints of the same file/model reuse the same `Part` and create new `StockItem` rows.
The `Part` identity key is controlled by:
```env
PART_KEY_FIELDS=content_hash,filename,print_name,name
```
The generated key becomes an InvenTree IPN:
```text
BMB-<first-12-sha1-chars>
```
## Delete Policy
If an archive is deleted in Bambuddy after it was synced, the corresponding InvenTree data is not deleted.
This is intentional. InvenTree is the inventory record, and deleting print history in Bambuddy should not silently remove stock records. The synced `Part`, `StockItem`, parameters, and image remain in InvenTree.
## Requirements
- Docker with Linux containers enabled.
- Network access from the sync container to Bambuddy API and InvenTree API.
- Bambuddy API key.
- InvenTree API token.
- Existing InvenTree part category ID.
- Existing InvenTree stock location ID.
- Optional InvenTree parameter templates: `Weight` and `PrintTime`.
On Windows Server 2022, verify Docker with:
```powershell
docker run --rm hello-world
docker run --rm python:3.12-slim python --version
```
## Docker Deployment
Clone the repository:
```powershell
git clone https://git.tcom.space/tcom/Lab8DATAPROCESSOR.git
cd Lab8DATAPROCESSOR
```
Create the runtime config:
```powershell
Copy-Item .env.example .env
notepad .env
```
Start the service:
```powershell
docker compose up -d --build
```
View logs:
```powershell
docker compose logs --tail=100
```
Stop the service:
```powershell
docker compose down
```
Update to the latest version:
```powershell
git pull
docker compose up -d --build
```
## Configuration
Example `.env`:
```env
BAMBUDDY_BASE_URL=http://192.168.1.5:8000/api/v1
BAMBUDDY_API_KEY=replace-with-bambuddy-api-key
INVENTREE_BASE_URL=http://192.168.0.3:1337
INVENTREE_WEB_URL=
INVENTREE_TOKEN=replace-with-inventree-token
INVENTREE_PART_CATEGORY_ID=26
INVENTREE_STOCK_LOCATION_ID=98
SERVICE_API_TOKEN=change-me
WEBHOOK_SHARED_SECRET=
SYNC_SUCCESS_ONLY=true
SYNC_PART_IMAGES=true
OVERWRITE_PART_IMAGES=false
SYNC_ARCHIVE_EXTERNAL_LINK=true
OVERWRITE_ARCHIVE_EXTERNAL_LINK=false
DEFAULT_STOCK_QUANTITY=1
INVENTREE_STOCK_STATUS=10
PART_IPN_PREFIX=BMB
PART_KEY_FIELDS=content_hash,filename,print_name,name
BACKFILL_PAGE_SIZE=50
POLL_INTERVAL_SECONDS=300
SYNC_ON_STARTUP=false
HTTP_TIMEOUT_SECONDS=30
DATA_DIR=/data
```
Do not commit `.env`. It contains API tokens and is ignored by git.
## Important Settings
`BAMBUDDY_BASE_URL`
: Bambuddy API base URL. Use `/api/v1`.
`INVENTREE_BASE_URL`
: InvenTree root URL or `/api` URL. The service normalizes it internally.
`INVENTREE_WEB_URL`
: Browser-facing InvenTree URL for Bambuddy external links. If empty, `INVENTREE_BASE_URL` is used.
`INVENTREE_PART_CATEGORY_ID`
: Existing InvenTree category where auto-created printed parts are placed.
`INVENTREE_STOCK_LOCATION_ID`
: Existing InvenTree stock location where printed stock items are placed.
`SYNC_SUCCESS_ONLY`
: When `true`, only successful/completed prints are imported.
`POLL_INTERVAL_SECONDS`
: Enables automatic periodic backfill. `300` means every 5 minutes. `0` disables polling.
`SYNC_PART_IMAGES`
: Downloads Bambuddy thumbnail and uploads it to InvenTree `Part.image`.
`OVERWRITE_PART_IMAGES`
: When `false`, manually set InvenTree part images are preserved.
`SYNC_ARCHIVE_EXTERNAL_LINK`
: Writes the InvenTree part page URL into Bambuddy `external_url`.
`OVERWRITE_ARCHIVE_EXTERNAL_LINK`
: When `false`, existing non-InvenTree external links in Bambuddy are preserved.
## InvenTree IDs
Use numeric IDs for target category and stock location. You can find them from the InvenTree UI URL or API.
Example:
```powershell
curl.exe -H "Authorization: Token YOUR_TOKEN" http://192.168.0.3:1337/api/part/category/26/
curl.exe -H "Authorization: Token YOUR_TOKEN" http://192.168.0.3:1337/api/stock/location/98/
```
Current known example:
```env
INVENTREE_PART_CATEGORY_ID=26
INVENTREE_STOCK_LOCATION_ID=98
```
## Validate Connectivity
After the container starts:
```powershell
curl.exe http://localhost:8088/health
curl.exe -H "X-Service-Token: change-me" http://localhost:8088/validate
```
Expected result:
- `/health` returns `status: ok`;
- `/validate` confirms Bambuddy, InvenTree category, and InvenTree location are reachable.
## Initial Backfill
Test one successful archive first:
```powershell
curl.exe -X POST -H "X-Service-Token: change-me" "http://localhost:8088/sync/backfill?max_archives=1"
```
Run full backfill:
```powershell
curl.exe -X POST -H "X-Service-Token: change-me" http://localhost:8088/sync/backfill
```
Check status:
```powershell
curl.exe -H "X-Service-Token: change-me" http://localhost:8088/sync/status
```
When `SYNC_SUCCESS_ONLY=true`, still-printing or failed archives are skipped and do not consume `max_archives`.
## Automatic Operation
Recommended production mode:
```env
SYNC_SUCCESS_ONLY=true
POLL_INTERVAL_SECONDS=300
SYNC_ON_STARTUP=false
```
This makes the service check Bambuddy every 5 minutes and import all newly completed prints.
For near-real-time syncing, also configure a Bambuddy webhook:
```text
http://WINDOWS-SERVER-IP:8088/webhooks/bambuddy
```
Use the `print_complete` event. If `WEBHOOK_SHARED_SECRET` is set, Bambuddy must send:
```text
X-Sync-Secret: your-secret
```
Running both webhook and polling is recommended. Webhook gives fast sync, polling catches missed events after restarts or temporary failures.
## Manual Sync
Sync one archive:
```powershell
curl.exe -X POST -H "X-Service-Token: change-me" http://localhost:8088/sync/archive/11
```
Force re-sync one archive:
```powershell
curl.exe -X POST -H "X-Service-Token: change-me" "http://localhost:8088/sync/archive/11?force=true"
```
Force sync is useful after changing image, parameter, or external link behavior.
## API Endpoints
```text
GET /health
GET /validate
GET /sync/status
POST /sync/archive/{archive_id}
POST /sync/backfill
POST /webhooks/bambuddy
```
Manual sync endpoints require `X-Service-Token` when `SERVICE_API_TOKEN` is set.
## Troubleshooting
View recent logs:
```powershell
docker compose logs --tail=100
```
Rebuild after pulling code changes:
```powershell
git pull
docker compose up -d --build
```
Common issues:
- `401` from service endpoints: missing or wrong `X-Service-Token`.
- `401` from Bambuddy: wrong `BAMBUDDY_API_KEY`.
- `401` from InvenTree: wrong `INVENTREE_TOKEN`.
- InvenTree `description` length errors: update to the latest service version; descriptions are capped at 250 characters.
- No items imported: check if Bambuddy archives are still `printing` or `failed`.
- Duplicate protection prevents repeated imports: use `force=true` only when you want to refresh parameters/images/links for an existing archive.
## Backups
Persistent sync state is stored in:
```text
./data/sync.sqlite3
```
Back up the `data` directory together with `.env` if you move the service to another server.