Deployment and Operations¶
This page describes how the Wine Platform is deployed on the Raspberry Pi.
The platform uses systemd for:
- always-on services
- kiosk startup
- daily stock scheduling
Canonical unit names¶
Use these names consistently.
| Purpose | Unit |
|---|---|
| FastAPI backend | winecellar-api.service |
| Qt kiosk frontend | winecellar-kiosk.service |
| Daily stock batch | wine-inventory-stock.service |
| Daily stock scheduler | wine-inventory-stock.timer |
FastAPI Backend¶
Source location:
/home/pi/wine_platform/apps/winecellar/backend
Manual start for development:
cd /home/pi/wine_platform/apps/winecellar/backend
source ../.venv/bin/activate
python -m uvicorn app.main:app --host 0.0.0.0 --port 8000
The API becomes reachable at:
http://<pi-ip>:8000/docs
FastAPI Production Service¶
Service file:
/etc/systemd/system/winecellar-api.service
Example unit:
[Unit]
Description=Winecellar FastAPI
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=pi
Group=pi
WorkingDirectory=/home/pi/wine_platform/apps/winecellar
EnvironmentFile=/home/pi/wine_platform/shared/config/shared.env
Environment=PYTHONPATH=/home/pi/wine_platform/apps/winecellar/backend
Environment=GOOGLE_APPLICATION_CREDENTIALS=/home/pi/secret/gcp-vision-key.json
ExecStart=/home/pi/wine_platform/apps/winecellar/.venv/bin/python -m uvicorn backend.app.main:app --host 0.0.0.0 --port 8000
Restart=always
RestartSec=2
[Install]
WantedBy=multi-user.target
Activate and manage:
sudo systemctl daemon-reload
sudo systemctl enable --now winecellar-api.service
sudo systemctl restart winecellar-api.service
systemctl status winecellar-api.service --no-pager
journalctl -u winecellar-api.service -n 100 --no-pager
Qt Kiosk Service¶
Launcher:
/home/pi/wine_platform/apps/winecellar/frontend/qt_kiosk/run_qt_kiosk.sh
Service file:
/etc/systemd/system/winecellar-kiosk.service
Example unit:
[Unit]
Description=Winecellar Qt Kiosk
After=network-online.target winecellar-api.service
Wants=network-online.target
[Service]
Type=simple
User=pi
Group=pi
Environment=DISPLAY=:0
Environment=XAUTHORITY=/home/pi/.Xauthority
WorkingDirectory=/home/pi/wine_platform/apps/winecellar/frontend/qt_kiosk
ExecStart=/home/pi/wine_platform/apps/winecellar/frontend/qt_kiosk/run_qt_kiosk.sh
Restart=always
RestartSec=3
[Install]
WantedBy=graphical.target
Useful commands:
sudo systemctl daemon-reload
sudo systemctl enable --now winecellar-kiosk.service
sudo systemctl restart winecellar-kiosk.service
systemctl status winecellar-kiosk.service --no-pager
journalctl -u winecellar-kiosk.service -f
Daily Stock Runtime Scheduling¶
Agreed production solution¶
The daily stock scan is scheduled with:
wine-inventory-stock.serviceas a oneshot batch servicewine-inventory-stock.timeras the daily scheduler
This is preferred over cron.
Confirmed script path¶
/home/pi/wine_platform/workers/wine_inventory/src/pince_shelf/cli/stock_runtime.py
Do not use the old documentation path under pince_shelf/vision/stock_runtime.py.
Daily stock service¶
Service file:
/etc/systemd/system/wine-inventory-stock.service
Canonical content:
[Unit]
Description=Wine Inventory Daily Stock Runtime
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
User=pi
Group=pi
WorkingDirectory=/home/pi/wine_platform/workers/wine_inventory
ExecStart=/usr/bin/flock -n /tmp/wine_stock_runtime.lock /home/pi/wine_platform/workers/wine_inventory/.venv/bin/python /home/pi/wine_platform/workers/wine_inventory/src/pince_shelf/cli/stock_runtime.py
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
Why flock is used:
- prevents overlap if a previous batch is still running
- prevents overlap if someone manually starts the service during a scheduled run
Daily stock timer¶
Timer file:
/etc/systemd/system/wine-inventory-stock.timer
Canonical content:
[Unit]
Description=Run Wine Inventory Stock Runtime Daily
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
Unit=wine-inventory-stock.service
[Install]
WantedBy=timers.target
Behavior:
- runs every day at
03:00 Persistent=truecatches up a missed run after reboot
Activation¶
sudo systemctl daemon-reload
sudo systemctl enable --now wine-inventory-stock.timer
Manual testing¶
Run one daily stock batch immediately:
sudo systemctl start wine-inventory-stock.service
Verify:
systemctl status wine-inventory-stock.service --no-pager
systemctl status wine-inventory-stock.timer --no-pager
systemctl list-timers --all | grep wine-inventory-stock
journalctl -u wine-inventory-stock.service -n 200 --no-pager
Vision pipeline flow¶
stock_runtime.py
↓
take_clean_snapshot.py
↓
shelf_rectify.py
↓
crop_with_json.py
↓
onnx_batch.py
↓
DB_compare.py
Deployment overview¶
flowchart TD
BOOT[Raspberry Pi boot]
NET[Network online]
NAS[NAS mount]
API[winecellar-api.service]
KIOSK[winecellar-kiosk.service]
TIMER[wine-inventory-stock.timer]
SERVICE[wine-inventory-stock.service]
SCRIPT[stock_runtime.py]
BOOT --> NET
NET --> NAS
NAS --> API
API --> KIOSK
API --> TIMER
TIMER --> SERVICE
SERVICE --> SCRIPT
Scheduled execution sequence¶
sequenceDiagram
participant Timer as wine-inventory-stock.timer
participant Service as wine-inventory-stock.service
participant Script as stock_runtime.py
participant DB as MariaDB
participant API as Backend API
Timer->>Service: trigger daily at 03:00
Service->>Script: run via worker venv
Script->>DB: update comparison results
Script->>API: optional notifications or sync
Script-->>Service: exit
Runtime data paths¶
/mnt/nasWeb/web_images/Stock_vision/data/snapshots
/mnt/nasWeb/web_images/Stock_vision/data/cells_runtime
/mnt/nasWeb/web_images/Stock_vision/data/cells_runtime_res
Synology internal equivalent:
/volume2/web/web_images/Stock_vision/data/...
Operational monitoring¶
systemctl | egrep 'winecellar|wine-inventory'
journalctl -u winecellar-api.service -f
journalctl -u winecellar-kiosk.service -f
journalctl -u wine-inventory-stock.service -f
systemctl list-timers --all | grep wine-inventory
Summary¶
Use this deployment model consistently:
winecellar-api.service
winecellar-kiosk.service
wine-inventory-stock.timer
→ wine-inventory-stock.service
→ /home/pi/wine_platform/workers/wine_inventory/src/pince_shelf/cli/stock_runtime.py