Expand deployment and sync documentation

This commit is contained in:
2026-04-15 14:40:24 +03:00
parent 49d3120395
commit 791c2235c5
2 changed files with 299 additions and 96 deletions

View File

@@ -29,9 +29,9 @@ OVERWRITE_ARCHIVE_EXTERNAL_LINK=false
DEFAULT_STOCK_QUANTITY=1 DEFAULT_STOCK_QUANTITY=1
INVENTREE_STOCK_STATUS=10 INVENTREE_STOCK_STATUS=10
PART_IPN_PREFIX=BMB PART_IPN_PREFIX=BMB
PART_KEY_FIELDS=filename,name PART_KEY_FIELDS=content_hash,filename,print_name,name
BACKFILL_PAGE_SIZE=50 BACKFILL_PAGE_SIZE=50
POLL_INTERVAL_SECONDS=0 POLL_INTERVAL_SECONDS=300
SYNC_ON_STARTUP=false SYNC_ON_STARTUP=false
HTTP_TIMEOUT_SECONDS=30 HTTP_TIMEOUT_SECONDS=30

391
README.md
View File

@@ -1,147 +1,350 @@
# Bambuddy InvenTree Sync # Bambuddy InvenTree Sync
Small sidecar service for syncing Bambuddy `Archives` into InvenTree. Sidecar service for syncing successful Bambuddy print archives into InvenTree stock.
It currently: 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.
- creates an InvenTree `Part` automatically when a printed model is first seen; ## What It Does
- creates one InvenTree `StockItem` for each synced Bambuddy archive;
- stores local sync state in SQLite to avoid duplicate stock items;
- accepts Bambuddy webhooks and can also backfill existing archives.
The first version intentionally treats one Bambuddy archive as one printed stock item. Later we can add plate parsing, multi-object quantity detection, filament costing, thumbnails, 3MF attachments, and mapping rules. For each successful Bambuddy archive, the service:
## Setup - 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.
1. Copy `.env.example` to `.env`. Failed, stopped, running, or still-printing archives are skipped when `SYNC_SUCCESS_ONLY=true`.
2. Fill in:
- `BAMBUDDY_BASE_URL`
- `BAMBUDDY_API_KEY`
- `INVENTREE_BASE_URL`
- `INVENTREE_TOKEN`
- `INVENTREE_PART_CATEGORY_ID`
- `INVENTREE_STOCK_LOCATION_ID`
3. Start the service:
```powershell ## Data Flow
docker compose up -d --build
```
The service listens on `http://localhost:8088`.
## InvenTree IDs
For the first version, use numeric IDs for the target InvenTree part category and stock location. Open the desired category/location in InvenTree and copy the ID from the URL or API response.
Example:
```env
INVENTREE_PART_CATEGORY_ID=12
INVENTREE_STOCK_LOCATION_ID=7
```
## Validate Connectivity
If `SERVICE_API_TOKEN` is set in `.env`, pass it as `X-Service-Token`:
```powershell
curl.exe -H "X-Service-Token: change-me" http://localhost:8088/validate
```
## Backfill Existing Archives
Run a test with one archive first:
```powershell
curl.exe -X POST -H "X-Service-Token: change-me" "http://localhost:8088/sync/backfill?max_archives=1"
```
When `SYNC_SUCCESS_ONLY=true`, `max_archives` counts import attempts. Archives that are still `printing` or already failed are skipped and do not consume the limit.
Run full backfill for successful Bambuddy archives:
```powershell
curl.exe -X POST -H "X-Service-Token: change-me" http://localhost:8088/sync/backfill
```
The default behavior is `SYNC_SUCCESS_ONLY=true`, so failed or stopped prints are not imported.
## Bambuddy Webhook
In Bambuddy, configure a webhook to:
```text ```text
http://WINDOWS-SERVER-IP:8088/webhooks/bambuddy 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
``` ```
If `WEBHOOK_SHARED_SECRET` is configured, Bambuddy must send this header: ## InvenTree Mapping
```text | Bambuddy data | InvenTree target |
X-Sync-Secret: your-secret | --- | --- |
``` | 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` |
The service expects Bambuddy payloads with `event=print_complete` and `data.archive_id`. ## Duplicate Protection
## Part Matching The service is idempotent:
The service builds a stable key from: - 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 ```env
PART_KEY_FIELDS=filename,name PART_KEY_FIELDS=content_hash,filename,print_name,name
``` ```
That key becomes an InvenTree IPN: The generated key becomes an InvenTree IPN:
```text ```text
BMB-<first-12-sha1-chars> BMB-<first-12-sha1-chars>
``` ```
This means repeat prints of the same file/name reuse the same `Part` and create new `StockItem` rows. To change matching behavior later, edit `PART_KEY_FIELDS`. ## Delete Policy
## InvenTree Part Parameters If an archive is deleted in Bambuddy after it was synced, the corresponding InvenTree data is not deleted.
For each synced `Part`, the service updates these InvenTree parameters when matching parameter templates exist: 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.
- `Weight`: filament weight per printed item in grams. If a Bambuddy archive has `quantity=2`, the total filament weight is divided by 2. ## Requirements
- `PrintTime`: print duration from Bambuddy. The visible value is formatted as `1h 6m 1s`; `data_numeric` stores the duration in seconds.
## InvenTree Part Images - 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`.
When `SYNC_PART_IMAGES=true`, the service downloads the Bambuddy archive thumbnail and uploads it to the InvenTree `Part.image` field. On Windows Server 2022, verify Docker with:
By default, existing InvenTree part images are preserved: ```powershell
docker run --rm hello-world
```env docker run --rm python:3.12-slim python --version
OVERWRITE_PART_IMAGES=false
``` ```
Set `OVERWRITE_PART_IMAGES=true` if Bambuddy thumbnails should replace existing part images. ## Docker Deployment
## Bambuddy External Links Clone the repository:
When `SYNC_ARCHIVE_EXTERNAL_LINK=true`, the service writes the InvenTree part page URL into Bambuddy archive `external_url`. ```powershell
git clone https://git.tcom.space/tcom/Lab8DATAPROCESSOR.git
cd Lab8DATAPROCESSOR
```
The default link format is: 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 ```text
<INVENTREE_WEB_URL or INVENTREE_BASE_URL>/web/part/<part_id>/ http://WINDOWS-SERVER-IP:8088/webhooks/bambuddy
``` ```
Existing non-InvenTree external links are preserved unless: Use the `print_complete` event. If `WEBHOOK_SHARED_SECRET` is set, Bambuddy must send:
```env ```text
OVERWRITE_ARCHIVE_EXTERNAL_LINK=true X-Sync-Secret: your-secret
``` ```
## Useful Endpoints 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 ```text
GET /health GET /health
GET /sync/status
GET /validate GET /validate
GET /sync/status
POST /sync/archive/{archive_id} POST /sync/archive/{archive_id}
POST /sync/backfill POST /sync/backfill
POST /webhooks/bambuddy POST /webhooks/bambuddy
``` ```
Manual sync endpoints require `X-Service-Token` when `SERVICE_API_TOKEN` is set. 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.