Label print API

This commit is contained in:
2026-02-07 06:41:39 -05:00
parent dd5aa7c4bc
commit 3d1c007609
5 changed files with 132 additions and 1 deletions

View File

@@ -1,11 +1,12 @@
from fastapi import FastAPI, Depends, HTTPException, APIRouter, status
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session
from typing import List, Optional
from typing import List, Optional, Dict, Any
from datetime import datetime, timedelta
from .database import engine, get_db, Base
from .models import Drug, DrugVariant, Dispensing, User
from .auth import hash_password, verify_password, create_access_token, get_current_user, get_current_admin_user, ACCESS_TOKEN_EXPIRE_MINUTES
from .mqtt_service import publish_label_print
from pydantic import BaseModel
# Create tables
@@ -117,6 +118,21 @@ class DispensingResponse(BaseModel):
class Config:
from_attributes = True
class LabelVariables(BaseModel):
practice_name: str
animal_name: str
drug_name: str
dosage: str
quantity: str
expiry_date: str
class LabelPrintRequest(BaseModel):
variables: LabelVariables
class LabelPrintResponse(BaseModel):
success: bool
message: str
# Authentication Routes
@router.post("/auth/register", response_model=TokenResponse)
def register(user_data: UserCreate, db: Session = Depends(get_db)):
@@ -475,5 +491,49 @@ def get_variant_dispensings(variant_id: int, db: Session = Depends(get_db), curr
return db.query(Dispensing).filter(Dispensing.drug_variant_id == variant_id).order_by(Dispensing.dispensed_at.desc()).all()
# Label printing endpoint
@router.post("/labels/print", response_model=LabelPrintResponse)
def print_label(label_request: LabelPrintRequest, current_user: User = Depends(get_current_user)):
"""
Print a drug label by publishing an MQTT message
This endpoint publishes a label print request to the MQTT broker,
which will be picked up by the label printing service.
"""
try:
# Get label configuration from environment
import os
template_id = os.getenv("LABEL_TEMPLATE_ID", "vet_label")
label_size = os.getenv("LABEL_SIZE", "29x90")
test_mode = os.getenv("LABEL_TEST", "false").lower() == "true"
# Convert the request to the MQTT message format
mqtt_message = {
"template_id": template_id,
"label_size": label_size,
"variables": label_request.variables.dict(),
"test": test_mode
}
# Publish to MQTT
success = publish_label_print(mqtt_message)
if success:
return LabelPrintResponse(
success=True,
message="Label print request sent successfully"
)
else:
raise HTTPException(
status_code=500,
detail="Failed to send label print request to MQTT broker"
)
except Exception as e:
raise HTTPException(
status_code=500,
detail=f"Error sending label print request: {str(e)}"
)
# Include router with /api prefix
app.include_router(router)

View File

@@ -0,0 +1,57 @@
import os
import json
import logging
from typing import Optional
import paho.mqtt.client as mqtt
logger = logging.getLogger(__name__)
# MQTT Configuration from environment
MQTT_BROKER_HOST = os.getenv("MQTT_BROKER_HOST", "localhost")
MQTT_BROKER_PORT = int(os.getenv("MQTT_BROKER_PORT", "1883"))
MQTT_USERNAME = os.getenv("MQTT_USERNAME", "")
MQTT_PASSWORD = os.getenv("MQTT_PASSWORD", "")
MQTT_LABEL_TOPIC = os.getenv("MQTT_LABEL_TOPIC", "vet/labels/print")
def publish_label_print(label_data: dict) -> bool:
"""
Publish a label print request to MQTT broker
Args:
label_data: Dictionary containing label print information
Returns:
True if successful, False otherwise
"""
try:
# Create MQTT client
client = mqtt.Client()
# Set username and password if provided
if MQTT_USERNAME and MQTT_PASSWORD:
client.username_pw_set(MQTT_USERNAME, MQTT_PASSWORD)
# Connect to broker
client.connect(MQTT_BROKER_HOST, MQTT_BROKER_PORT, 60)
# Start network loop to process connection
client.loop_start()
# Publish message with QoS 0 (fire and forget)
message = json.dumps(label_data)
result = client.publish(MQTT_LABEL_TOPIC, message, qos=0)
# Stop loop and disconnect
client.loop_stop()
client.disconnect()
if result.rc == mqtt.MQTT_ERR_SUCCESS:
logger.info(f"Successfully published label print request to {MQTT_LABEL_TOPIC}")
return True
else:
logger.error(f"Failed to publish label print request: {result.rc}")
return False
except Exception as e:
logger.error(f"Error publishing MQTT message: {str(e)}")
return False

View File

@@ -5,3 +5,4 @@ pydantic==2.5.0
python-multipart==0.0.6
python-jose[cryptography]==3.3.0
passlib[argon2]==1.7.4
paho-mqtt==1.6.1

View File

@@ -14,6 +14,14 @@ services:
- DATABASE_URL=sqlite:///./data/drugs.db
- PUID=1001
- PGID=1001
- MQTT_BROKER_HOST=${MQTT_BROKER_HOST:-localhost}
- MQTT_BROKER_PORT=${MQTT_BROKER_PORT:-1883}
- MQTT_USERNAME=${MQTT_USERNAME:-}
- MQTT_PASSWORD=${MQTT_PASSWORD:-}
- MQTT_LABEL_TOPIC=${MQTT_LABEL_TOPIC:-vet/labels/print}
- LABEL_TEMPLATE_ID=${LABEL_TEMPLATE_ID:-vet_label}
- LABEL_SIZE=${LABEL_SIZE:-29x90}
- LABEL_TEST=${LABEL_TEST:-false}
frontend:
image: nginx:alpine

View File

@@ -324,6 +324,11 @@ function renderDrugs() {
);
}
// Sort alphabetically by drug name
drugsToShow = drugsToShow.sort((a, b) =>
a.name.toLowerCase().localeCompare(b.name.toLowerCase())
);
if (drugsToShow.length === 0) {
drugsList.innerHTML = '<p class="empty">No drugs found matching your criteria</p>';
return;