import json import hmac import hashlib import base64 import time from datetime import datetime from logger_manager import log_info, log_error import os import aiohttp from env import VUFORIA_SERVER_ACCESS_KEY, VUFORIA_SERVER_SECRET_KEY,UPLOADED_IMAGES_DIR async def add_target_to_vuforia(image_name: str, image_path: str) -> str: """ Adds a target to the Vuforia database and returns the Vuforia target ID. Implements proper Vuforia authentication and request format. """ log_info(f"Adding target {image_name} to Vuforia") try: # Read image data with open(image_path, "rb") as image_file: image_data = image_file.read() # Base64 encode the image image_base64 = base64.b64encode(image_data).decode('utf-8') # Create request data request_path = '/targets' host = 'vws.vuforia.com' url = f"https://{host}{request_path}" # Create payload payload = { "name": image_name, "width": 150.0, # Default width in scene units "image": image_base64, "active_flag": True, } # Convert payload to JSON body = json.dumps(payload) # Get current date in proper format for Vuforia date = datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT') # Set content type content_type = 'application/json' # Calculate MD5 of request body content_md5 = hashlib.md5(body.encode('utf-8')).hexdigest() # Create string to sign according to Vuforia docs string_to_sign = f"POST\n{content_md5}\n{content_type}\n{date}\n{request_path}" # Generate signature signature = hmac.new( VUFORIA_SERVER_SECRET_KEY.encode('utf-8'), string_to_sign.encode('utf-8'), hashlib.sha1 ).digest() signature_hex = base64.b64encode(signature).decode('utf-8') # Create headers headers = { 'Authorization': f'VWS {VUFORIA_SERVER_ACCESS_KEY}:{signature_hex}', 'Content-Type': content_type, 'Date': date, 'Content-MD5': content_md5 } # Make the API request async with aiohttp.ClientSession() as session: async with session.post(url, headers=headers, data=body) as response: # Get response text and try to parse as JSON response_text = await response.text() try: response_json = json.loads(response_text) except: response_json = {"error": "Failed to parse response"} log_info(f"Vuforia response status: {response.status}") if response.status == 201: # Created log_info(f"Target added successfully: {response_json}") return response_json.get("target_id", "unknown_target_id") else: log_error(f"Failed to add target: Status {response.status}, Response: {response_text}") raise Exception(f"Failed to add target {image_name}: Status {response.status}, Error: {response_json.get('result_code', 'Unknown')}") except Exception as e: log_error(f"Error adding target {image_name}: {e}", e) raise