Spaces:
Sleeping
Sleeping
""" | |
RAG κ²μ μ±λ΄ μΉ μ ν리μΌμ΄μ - μ₯μΉ κ΄λ¦¬ API λΌμ°νΈ μ μ (μ¬μ©μ μ μ μ€ν, f-string μ€λ₯ μμ λ¨) | |
""" | |
import logging | |
import requests | |
import uuid # μ¬μ©μ μ μ μ€νμ μν΄ μΆκ° | |
import time # μ¬μ©μ μ μ μ€νμ μν΄ μΆκ° | |
import shlex # μ¬μ©μ μ μ μ€νμ μν΄ μΆκ° | |
import os # κ²½λ‘ μ²λ¦¬λ₯Ό μν΄ μΆκ° (νμμ) | |
from flask import request, jsonify | |
# λ‘κ±° κ°μ Έμ€κΈ° | |
logger = logging.getLogger(__name__) | |
def register_device_routes(app, login_required, DEVICE_SERVER_URL): | |
"""Flask μ ν리μΌμ΄μ μ μ₯μΉ κ΄λ¦¬ κ΄λ ¨ λΌμ°νΈ λ±λ‘""" | |
# μ¬μ©μ μ§μ μ₯μΉ μλ² URL λ³μ | |
custom_device_url = None | |
# URL μ€μ ν¨μ | |
def get_device_url(): | |
# μ¬μ©μ μ§μ URLμ΄ μμΌλ©΄ μ¬μ©, μμΌλ©΄ νκ²½λ³μ κ° μ¬μ© | |
return custom_device_url or DEVICE_SERVER_URL | |
def connect_device_server(): | |
"""μ¬μ©μ μ§μ μ₯μΉ μλ² URL μ°κ²° API""" | |
nonlocal custom_device_url # μμ μ€μ½νμ λ³μ μ°Έμ‘° | |
try: | |
# μμ²μμ URL κ°μ Έμ€κΈ° | |
request_data = request.get_json() | |
if not request_data or 'url' not in request_data: | |
logger.error("URLμ΄ μ 곡λμ§ μμμ΅λλ€.") | |
return jsonify({ | |
"success": False, | |
"error": "URLμ΄ μ 곡λμ§ μμμ΅λλ€." | |
}), 400 # Bad Request | |
new_url = request_data['url'].strip() | |
if not new_url: | |
logger.error("URLμ΄ λΉμ΄ μμ΅λλ€.") | |
return jsonify({ | |
"success": False, | |
"error": "URLμ΄ λΉμ΄ μμ΅λλ€." | |
}), 400 # Bad Request | |
# URL μ€μ | |
logger.info(f"μ¬μ©μ μ§μ μ₯μΉ μλ² URL μ€μ : {new_url}") | |
custom_device_url = new_url | |
# μ€μ λ URLλ‘ μν νμΈ μλ | |
try: | |
api_path = "/api/status" | |
logger.info(f"μ₯μΉ μλ² μν νμΈ μμ²: {custom_device_url}{api_path}") | |
response = requests.get(f"{custom_device_url}{api_path}", timeout=5) | |
if response.status_code == 200: | |
try: | |
data = response.json() | |
logger.info(f"μ¬μ©μ μ§μ μ₯μΉ μλ² μ°κ²° μ±κ³΅. μλ΅ λ°μ΄ν°: {data}") | |
return jsonify({ | |
"success": True, | |
"message": "μ₯μΉ μλ² μ°κ²°μ μ±κ³΅νμ΅λλ€.", | |
"server_status": data.get("status", "μ μ") # μλ² μλ΅ κ΅¬μ‘°μ λ°λΌ ν€ μ‘°μ νμ | |
}) | |
except requests.exceptions.JSONDecodeError: | |
logger.error("μ₯μΉ μλ² μλ΅ JSON νμ± μ€ν¨") | |
return jsonify({ | |
"success": False, | |
"error": "μ₯μΉ μλ²λ‘λΆν° μ ν¨νμ§ μμ JSON μλ΅μ λ°μμ΅λλ€." | |
}), 502 # Bad Gateway | |
else: | |
error_message = f"μ₯μΉ μλ² μλ΅ μ€λ₯: {response.status_code}" | |
try: | |
error_detail = response.json().get("error", response.text) | |
error_message += f" - {error_detail}" | |
except Exception: | |
error_message += f" - {response.text}" | |
logger.warning(error_message) | |
custom_device_url = None # μ°κ²° μ€ν¨ μ URL μ΄κΈ°ν | |
return jsonify({ | |
"success": False, | |
"error": error_message | |
}), 502 # Bad Gateway | |
except requests.exceptions.Timeout: | |
logger.error(f"μ₯μΉ μλ² μ°κ²° νμμμ ({custom_device_url})") | |
custom_device_url = None # μ°κ²° μ€ν¨ μ URL μ΄κΈ°ν | |
return jsonify({ | |
"success": False, | |
"error": "μ₯μΉ μλ² μ°κ²° νμμμ. μλ² μλ΅μ΄ λ무 λ립λλ€." | |
}), 504 # Gateway Timeout | |
except requests.exceptions.ConnectionError: | |
logger.error(f"μ₯μΉ κ΄λ¦¬ μλ² μ°κ²° μ€ν¨ ({custom_device_url})") | |
custom_device_url = None # μ°κ²° μ€ν¨ μ URL μ΄κΈ°ν | |
return jsonify({ | |
"success": False, | |
"error": "μ₯μΉ κ΄λ¦¬ μλ²μ μ°κ²°ν μ μμ΅λλ€. μλ²κ° μ€ν μ€μΈμ§, URLμ΄ μ ννμ§ νμΈν΄μ£ΌμΈμ." | |
}), 502 # Bad Gateway | |
except Exception as e: | |
logger.error(f"μ₯μΉ μλ² μ°κ²° μ€ μμμΉ λͺ»ν μ€λ₯ λ°μ: {e}", exc_info=True) | |
custom_device_url = None # μ°κ²° μ€ν¨ μ URL μ΄κΈ°ν | |
return jsonify({ | |
"success": False, | |
"error": f"μ₯μΉ μλ² μ°κ²° μ€ μ€λ₯ λ°μ: {str(e)}" | |
}), 500 # Internal Server Error | |
except Exception as e: | |
logger.error(f"/api/device/connect μ²λ¦¬ μ€ λ΄λΆ μλ² μ€λ₯: {e}", exc_info=True) | |
return jsonify({ | |
"success": False, | |
"error": f"λ΄λΆ μλ² μ€λ₯ λ°μ: {str(e)}" | |
}), 500 # Internal Server Error | |
def device_status(): | |
"""μ₯μΉ κ΄λ¦¬ μλ²μ μνλ₯Ό νμΈνλ API μλν¬μΈνΈ""" | |
try: | |
# μ°κ²° νμμμ μ€μ | |
timeout = 5 # 5μ΄λ‘ νμμμ μ€μ | |
try: | |
# μ₯μΉ μλ² μν νμΈ - κ²½λ‘: /api/status | |
current_device_url = get_device_url() | |
api_path = "/api/status" | |
logger.info(f"μ₯μΉ μλ² μν νμΈ μμ²: {current_device_url}{api_path}") | |
response = requests.get(f"{current_device_url}{api_path}", timeout=timeout) | |
# μλ΅ μν μ½λ λ° λ΄μ© λ‘κΉ (λλ²κΉ κ°ν) | |
logger.debug(f"μ₯μΉ μλ² μλ΅ μν μ½λ: {response.status_code}") | |
try: | |
logger.debug(f"μ₯μΉ μλ² μλ΅ λ΄μ©: {response.text[:200]}...") # λ무 κΈΈλ©΄ μλΌμ λ‘κΉ | |
except Exception: | |
logger.debug("μ₯μΉ μλ² μλ΅ λ΄μ© λ‘κΉ μ€ν¨ (ν μ€νΈ νμ μλ?)") | |
if response.status_code == 200: | |
# μ±κ³΅ μ μλ΅ λ°μ΄ν° ꡬ쑰 νμΈ λ° λ‘κΉ | |
try: | |
data = response.json() | |
logger.info(f"μ₯μΉ μλ² μν νμΈ μ±κ³΅. μλ΅ λ°μ΄ν°: {data}") | |
return jsonify({"success": True, "status": "connected", "data": data}) | |
except requests.exceptions.JSONDecodeError: | |
logger.error("μ₯μΉ μλ² μλ΅ JSON νμ± μ€ν¨") | |
return jsonify({ | |
"success": False, | |
"error": "μ₯μΉ μλ²λ‘λΆν° μ ν¨νμ§ μμ JSON μλ΅μ λ°μμ΅λλ€." | |
}), 502 # Bad Gateway (μ μ€νΈλ¦Ό μλ² μ€λ₯) | |
else: | |
# μ€ν¨ μ μ€λ₯ λ©μμ§ ν¬ν¨ λ‘κΉ | |
error_message = f"μ₯μΉ μλ² μλ΅ μ€λ₯: {response.status_code}" | |
try: | |
# μλ²μμ μ€λ₯ λ©μμ§λ₯Ό jsonμΌλ‘ 보λ΄λ κ²½μ° ν¬ν¨ | |
error_detail = response.json().get("error", response.text) | |
error_message += f" - {error_detail}" | |
except Exception: | |
error_message += f" - {response.text}" # JSON νμ± μ€ν¨ μ μλ³Έ ν μ€νΈ | |
logger.warning(error_message) # κ²½κ³ λ λ²¨λ‘ λ‘κΉ | |
return jsonify({ | |
"success": False, | |
"error": error_message | |
}), 502 # Bad Gateway | |
except requests.exceptions.Timeout: | |
logger.error(f"μ₯μΉ μλ² μ°κ²° νμμμ ({get_device_url()})") | |
return jsonify({ | |
"success": False, | |
"error": "μ₯μΉ μλ² μ°κ²° νμμμ. μλ² μλ΅μ΄ λ무 λ립λλ€." | |
}), 504 # Gateway Timeout | |
except requests.exceptions.ConnectionError: | |
current_device_url = get_device_url() | |
logger.error(f"μ₯μΉ κ΄λ¦¬ μλ² μ°κ²° μ€ν¨ ({current_device_url})") | |
return jsonify({ | |
"success": False, | |
"error": "μ₯μΉ κ΄λ¦¬ μλ²μ μ°κ²°ν μ μμ΅λλ€. μλ²κ° μ€ν μ€μΈμ§, URLμ΄ μ ννμ§ νμΈν΄μ£ΌμΈμ." | |
}), 502 # Bad Gateway (μ°κ²° μ€ν¨λ μ μ€νΈλ¦Ό λ¬Έμ λ‘ κ°μ£Ό) | |
except Exception as e: | |
logger.error(f"μ₯μΉ μλ² μ°κ²° μ€ μμμΉ λͺ»ν μ€λ₯ λ°μ: {e}", exc_info=True) # μμΈ μ€ν νΈλ μ΄μ€ λ‘κΉ | |
return jsonify({ | |
"success": False, | |
"error": f"μ₯μΉ μλ² μ°κ²° μ€ μ€λ₯ λ°μ: {str(e)}" | |
}), 500 # Internal Server Error (Flask μ± λ΄λΆ λλ requests λΌμ΄λΈλ¬λ¦¬ λ¬Έμ κ°λ₯μ±) | |
except Exception as e: | |
# μ΄ try-except λΈλ‘μ /api/device/status λΌμ°νΈ μ체μ λ΄λΆ μ€λ₯ μ²λ¦¬ | |
logger.error(f"/api/device/status μ²λ¦¬ μ€ λ΄λΆ μλ² μ€λ₯: {e}", exc_info=True) | |
return jsonify({ | |
"success": False, | |
"error": f"λ΄λΆ μλ² μ€λ₯ λ°μ: {str(e)}" | |
}), 500 # Internal Server Error | |
def device_list(): | |
"""μ₯μΉ λͺ©λ‘ μ‘°ν API""" | |
logger.info("μ₯μΉ λͺ©λ‘ μ‘°ν μμ²") | |
try: | |
current_device_url = get_device_url() | |
api_path = "/api/devices" # LocalPCAgent API λ¬Έμμ λ°λΌ νμΈ νμ | |
logger.info(f"μ₯μΉ λͺ©λ‘ μ‘°ν μμ²: {current_device_url}{api_path}") | |
response = requests.get(f"{current_device_url}{api_path}", timeout=5) | |
logger.debug(f"μ₯μΉ λͺ©λ‘ μλ΅ μν μ½λ: {response.status_code}") | |
if response.status_code == 200: | |
try: | |
data = response.json() | |
devices = data.get("devices", []) # LocalPCAgent μλ΅ νμμ λ§κ² ν€ μ‘°μ | |
logger.info(f"μ₯μΉ λͺ©λ‘ μ‘°ν μ±κ³΅: {len(devices)}κ° μ₯μΉ") | |
return jsonify({ | |
"success": True, | |
"devices": devices | |
}) | |
except requests.exceptions.JSONDecodeError: | |
logger.error("μ₯μΉ λͺ©λ‘ μλ΅ JSON νμ± μ€ν¨") | |
return jsonify({"success": False, "error": "μ₯μΉ μλ²λ‘λΆν° μ ν¨νμ§ μμ JSON μλ΅"}), 502 | |
else: | |
error_message = f"μ₯μΉ λͺ©λ‘ μ‘°ν μ€ν¨: {response.status_code}" | |
try: error_message += f" - {response.json().get('error', response.text)}" | |
except Exception: error_message += f" - {response.text}" | |
logger.warning(error_message) | |
return jsonify({ | |
"success": False, | |
"error": error_message | |
}), 502 | |
except requests.exceptions.Timeout: | |
logger.error("μ₯μΉ λͺ©λ‘ μ‘°ν μκ° μ΄κ³Ό") | |
return jsonify({ | |
"success": False, | |
"error": "μ₯μΉ λͺ©λ‘ μ‘°ν μκ°μ΄ μ΄κ³Όλμμ΅λλ€." | |
}), 504 | |
except requests.exceptions.ConnectionError: | |
logger.error("μ₯μΉ κ΄λ¦¬ μλ² μ°κ²° μ€ν¨") | |
return jsonify({ | |
"success": False, | |
"error": "μ₯μΉ κ΄λ¦¬ μλ²μ μ°κ²°ν μ μμ΅λλ€. μλ²κ° μ€ν μ€μΈμ§ νμΈν΄μ£ΌμΈμ." | |
}), 503 # Service Unavailable | |
except Exception as e: | |
logger.error(f"μ₯μΉ λͺ©λ‘ μ‘°ν μ€ μ€λ₯ λ°μ: {e}", exc_info=True) | |
return jsonify({ | |
"success": False, | |
"error": f"μ₯μΉ λͺ©λ‘ μ‘°ν μ€ μ€λ₯ λ°μ: {str(e)}" | |
}), 500 | |
def device_programs(): | |
"""μ€ν κ°λ₯ν νλ‘κ·Έλ¨ λͺ©λ‘ μ‘°ν API""" | |
logger.info("νλ‘κ·Έλ¨ λͺ©λ‘ μ‘°ν μμ²") | |
try: | |
current_device_url = get_device_url() | |
api_path = "/api/programs" | |
logger.info(f"νλ‘κ·Έλ¨ λͺ©λ‘ μ‘°ν μμ²: {current_device_url}{api_path}") | |
response = requests.get(f"{current_device_url}{api_path}", timeout=5) | |
logger.debug(f"νλ‘κ·Έλ¨ λͺ©λ‘ μλ΅ μν μ½λ: {response.status_code}") | |
if response.status_code == 200: | |
try: | |
data = response.json() | |
programs = data.get("programs", []) | |
logger.info(f"νλ‘κ·Έλ¨ λͺ©λ‘ μ‘°ν μ±κ³΅: {len(programs)}κ° νλ‘κ·Έλ¨") | |
return jsonify({ | |
"success": True, | |
"programs": programs | |
}) | |
except requests.exceptions.JSONDecodeError: | |
logger.error("νλ‘κ·Έλ¨ λͺ©λ‘ μλ΅ JSON νμ± μ€ν¨") | |
return jsonify({"success": False, "error": "μ₯μΉ μλ²λ‘λΆν° μ ν¨νμ§ μμ JSON μλ΅"}), 502 | |
else: | |
error_message = f"νλ‘κ·Έλ¨ λͺ©λ‘ μ‘°ν μ€ν¨: {response.status_code}" | |
try: error_message += f" - {response.json().get('error', response.text)}" | |
except Exception: error_message += f" - {response.text}" | |
logger.warning(error_message) | |
return jsonify({ | |
"success": False, | |
"error": error_message | |
}), 502 | |
except requests.exceptions.Timeout: | |
logger.error("νλ‘κ·Έλ¨ λͺ©λ‘ μ‘°ν μκ° μ΄κ³Ό") | |
return jsonify({ | |
"success": False, | |
"error": "νλ‘κ·Έλ¨ λͺ©λ‘ μ‘°ν μκ°μ΄ μ΄κ³Όλμμ΅λλ€." | |
}), 504 | |
except requests.exceptions.ConnectionError: | |
logger.error("μ₯μΉ κ΄λ¦¬ μλ² μ°κ²° μ€ν¨") | |
return jsonify({ | |
"success": False, | |
"error": "μ₯μΉ κ΄λ¦¬ μλ²μ μ°κ²°ν μ μμ΅λλ€. μλ²κ° μ€ν μ€μΈμ§ νμΈν΄μ£ΌμΈμ." | |
}), 503 | |
except Exception as e: | |
logger.error(f"νλ‘κ·Έλ¨ λͺ©λ‘ μ‘°ν μ€ μ€λ₯ λ°μ: {e}", exc_info=True) | |
return jsonify({ | |
"success": False, | |
"error": f"νλ‘κ·Έλ¨ λͺ©λ‘ μ‘°ν μ€ μ€λ₯ λ°μ: {str(e)}" | |
}), 500 | |
def execute_program(program_id): | |
"""λ±λ‘λ νλ‘κ·Έλ¨ μ€ν API""" | |
logger.info(f"λ±λ‘λ νλ‘κ·Έλ¨ μ€ν μμ²: {program_id}") | |
try: | |
current_device_url = get_device_url() | |
api_path = f"/api/programs/{program_id}/execute" | |
logger.info(f"νλ‘κ·Έλ¨ μ€ν μμ²: {current_device_url}{api_path}") | |
response = requests.post( | |
f"{current_device_url}{api_path}", | |
json={}, # νμμ μ¬κΈ°μ νλΌλ―Έν° μΆκ° κ°λ₯ | |
timeout=10 # νλ‘κ·Έλ¨ μ€νμλ λ κΈ΄ μκ° λΆμ¬ | |
) | |
logger.debug(f"νλ‘κ·Έλ¨ μ€ν μλ΅ μν μ½λ: {response.status_code}") | |
if response.status_code == 200: | |
try: | |
data = response.json() | |
# LocalPCAgent μλ΅μμ νμν μ 보 μΆμΆ (μ: success, message, output λ±) | |
logger.info(f"νλ‘κ·Έλ¨ μ€ν μλ΅: {data}") | |
return jsonify(data) # μλ² μλ΅ κ΅¬μ‘°μ λ§μΆ° λ°ν | |
except requests.exceptions.JSONDecodeError: | |
logger.error("νλ‘κ·Έλ¨ μ€ν μλ΅ JSON νμ± μ€ν¨") | |
return jsonify({ | |
"success": False, | |
"error": "νλ‘κ·Έλ¨ μ€ν μλ²λ‘λΆν° μ ν¨νμ§ μμ JSON μλ΅" | |
}), 502 | |
else: | |
error_message = f"νλ‘κ·Έλ¨ μ€ν μμ² μ€ν¨: {response.status_code}" | |
try: error_message += f" - {response.json().get('error', response.text)}" | |
except Exception: error_message += f" - {response.text}" | |
logger.warning(error_message) | |
return jsonify({ | |
"success": False, | |
"error": error_message | |
}), 502 # λλ response.status_code λ₯Ό κ·Έλλ‘ λ°ννλ κ²λ κ³ λ € | |
except requests.exceptions.Timeout: | |
logger.error("νλ‘κ·Έλ¨ μ€ν μμ² μκ° μ΄κ³Ό") | |
return jsonify({ | |
"success": False, | |
"error": "νλ‘κ·Έλ¨ μ€ν μμ² μκ°μ΄ μ΄κ³Όλμμ΅λλ€." | |
}), 504 | |
except requests.exceptions.ConnectionError: | |
logger.error("μ₯μΉ κ΄λ¦¬ μλ² μ°κ²° μ€ν¨") | |
return jsonify({ | |
"success": False, | |
"error": "μ₯μΉ κ΄λ¦¬ μλ²μ μ°κ²°ν μ μμ΅λλ€. μλ²κ° μ€ν μ€μΈμ§ νμΈν΄μ£ΌμΈμ." | |
}), 503 | |
except Exception as e: | |
logger.error(f"νλ‘κ·Έλ¨ μ€ν μ€ μ€λ₯ λ°μ: {e}", exc_info=True) | |
return jsonify({ | |
"success": False, | |
"error": f"νλ‘κ·Έλ¨ μ€ν μ€ μ€λ₯ λ°μ: {str(e)}" | |
}), 500 | |
# ================== μ¬μ©μ μ μ νλ‘κ·Έλ¨ μ€ν μλν¬μΈνΈ μΆκ° ================== | |
def execute_custom_program(): | |
"""μ¬μ©μ μ μ νλ‘κ·Έλ¨ μ€ν API - μμ IDλ₯Ό μμ±νμ¬ λ±λ‘ ν μ€ν""" | |
logger.info("μ¬μ©μ μ μ νλ‘κ·Έλ¨ μμ λ±λ‘ λ° μ€ν μμ²") | |
# LocalPCAgent μλ² μλ΅μ μ μ₯ν λ³μ | |
execute_data = None | |
final_response = None | |
temp_id = None # μμ ID μ μ₯ λ³μ | |
try: | |
# μμ² λ°μ΄ν° νμΈ | |
request_data = request.get_json() | |
if not request_data or 'command' not in request_data: | |
logger.error("λͺ λ Ήμ΄κ° μ 곡λμ§ μμμ΅λλ€.") | |
return jsonify({ | |
"success": False, | |
"error": "μ€νν λͺ λ Ήμ΄λ₯Ό μ 곡ν΄μ£ΌμΈμ." | |
}), 400 # Bad Request | |
command = request_data['command'].strip() | |
if not command: | |
logger.error("λͺ λ Ήμ΄κ° λΉμ΄ μμ΅λλ€.") | |
return jsonify({ | |
"success": False, | |
"error": "μ€νν λͺ λ Ήμ΄λ₯Ό μ λ ₯ν΄μ£ΌμΈμ." | |
}), 400 # Bad Request | |
# νμ¬ μ₯μΉ μλ² URL κ°μ Έμ€κΈ° | |
current_device_url = get_device_url() | |
if not current_device_url: | |
logger.error("μ₯μΉ μλ² URLμ΄ μ€μ λμ§ μμμ΅λλ€.") | |
return jsonify({"success": False, "error": "μ₯μΉ μλ² URLμ΄ μ€μ λμ§ μμ μ°κ²°ν μ μμ΅λλ€."}), 503 | |
# --- 1. μμ νλ‘κ·Έλ¨ λ±λ‘ --- | |
# μμ νλ‘κ·Έλ¨ ID μμ± (μκ° κΈ°λ° uuid) | |
temp_id = f"temp_program_{int(time.time())}_{uuid.uuid4().hex[:8]}" | |
# λͺ λ Ήμ΄ κ²½λ‘μ μΈμ λΆλ¦¬ (shlex μ¬μ©) | |
try: | |
# λ°μ΄νλ‘ λ¬ΆμΈ λͺ λ Ήμ΄ μ²λ¦¬ (Windows κ²½λ‘ λ±) | |
parts = shlex.split(command) | |
except Exception as parse_err: | |
# shlex νμ± μ€λ₯ μ κ°λ¨ν λ°©μμΌλ‘ λΆλ¦¬ (μμΈ μΌμ΄μ€ μ²λ¦¬) | |
logger.warning(f"shlex νμ± μ€λ₯ ({parse_err}), λ¨μ λΆλ¦¬ μλ: {command}") | |
parts = command.split(maxsplit=1) # μ€ννμΌκ³Ό λλ¨Έμ§ μΈμλ‘ λΆλ¦¬ μλ | |
if not parts: # λΆλ¦¬ κ²°κ³Όκ° μμΌλ©΄ μ€λ₯ | |
logger.error(f"λͺ λ Ήμ΄ νμ± μ€ν¨: {command}") | |
return jsonify({"success": False, "error": "λͺ λ Ήμ΄ νμμ μΈμν μ μμ΅λλ€."}), 400 | |
path = parts[0] | |
args = parts[1:] if len(parts) > 1 else [] | |
# ================== μμ λ λΆλΆ μμ ================== | |
# κ²½λ‘μμ νμΌλͺ λ§ μΆμΆ (λ°±μ¬λμ λ¬Έμ ν΄κ²°) | |
# os.path.basename μ¬μ© λλ λ¬Έμμ΄ μ²λ¦¬ λ°©μ μ¬μ© | |
try: | |
# λͺ¨λ λ°±μ¬λμλ₯Ό μ¬λμλ‘ λ³κ²½ ν λ§μ§λ§ λΆλΆ μΆμΆ | |
filename = path.replace('\\', '/').split('/')[-1] | |
if not filename: # κ²½λ‘κ° '/'λ '\\'λ‘ λλλ κ²½μ° λλΉ | |
filename = path # μλ³Έ κ²½λ‘λ₯Ό μ¬μ©νκ±°λ λ€λ₯Έ κΈ°λ³Έκ° μ€μ | |
except Exception: | |
filename = "unknown" # μμΈ λ°μ μ κΈ°λ³Έκ° | |
# ================== μμ λ λΆλΆ λ ==================== | |
# νλ‘κ·Έλ¨ λ±λ‘ API νΈμΆ λ°μ΄ν° κ΅¬μ± | |
logger.info(f"μμ νλ‘κ·Έλ¨ λ±λ‘ μλ: ID={temp_id}, κ²½λ‘='{path}', μΈμ={args}") | |
register_data = { | |
"id": temp_id, | |
# μμ λ filename μ¬μ© | |
"name": f"μμ νλ‘κ·Έλ¨ ({filename})", | |
"path": path, | |
"args": args, | |
"ui_required": True, # UIκ° νμν κ²μΌλ‘ κ°μ (νμμ μμ ) | |
"description": f"μμ λ±λ‘λ νλ‘κ·Έλ¨: {command}" | |
} | |
register_response = requests.post( | |
f"{current_device_url}/api/programs", # LocalPCAgentμ νλ‘κ·Έλ¨ λ±λ‘ μλν¬μΈνΈ | |
json=register_data, | |
timeout=5 | |
) | |
if not register_response.ok: | |
# λ±λ‘ μ€ν¨ μ μ€λ₯ μ²λ¦¬ | |
logger.error(f"μμ νλ‘κ·Έλ¨ λ±λ‘ μ€ν¨: {register_response.status_code}") | |
try: | |
error_data = register_response.json() | |
error_message = error_data.get('error', register_response.text) | |
except: | |
error_message = register_response.text | |
return jsonify({ | |
"success": False, | |
"error": f"μμ νλ‘κ·Έλ¨ λ±λ‘ μ€ν¨({register_response.status_code}): {error_message}" | |
}), 502 # Bad Gateway (Upstream μ€ν¨) | |
# --- 2. μμ νλ‘κ·Έλ¨ μ€ν --- | |
logger.info(f"μμ νλ‘κ·Έλ¨ μ€ν μλ: {temp_id}") | |
execute_response = requests.post( | |
f"{current_device_url}/api/programs/{temp_id}/execute", # LocalPCAgentμ νλ‘κ·Έλ¨ μ€ν μλν¬μΈνΈ | |
json={}, | |
timeout=15 # μ€νμ λ κΈ΄ μκ° λΆμ¬ | |
) | |
# μ€ν κ²°κ³Όλ₯Ό μ°μ μ μ₯ (μμ ν λ°ννκΈ° μν΄) | |
if execute_response.ok: | |
try: | |
execute_data = execute_response.json() | |
# μ±κ³΅ μλ΅μ κΈ°λ³Έ μλ΅μΌλ‘ μ€μ | |
final_response = jsonify(execute_data) | |
logger.info(f"μμ νλ‘κ·Έλ¨ μ€ν μ±κ³΅ (μλ΅ μ½λ {execute_response.status_code}): {execute_data}") | |
except Exception as parse_error: | |
logger.error(f"μμ νλ‘κ·Έλ¨ μ€ν μ±κ³΅ μλ΅ νμ± μ€ν¨: {parse_error}") | |
# νμ± μ€ν¨ μ μ€λ₯ μλ΅ μ€μ | |
final_response = jsonify({ | |
"success": False, | |
"error": f"νλ‘κ·Έλ¨ μ€ν μλ΅(μ±κ³΅:{execute_response.status_code}) νμ± μ€ν¨: {str(parse_error)}" | |
}), 502 | |
else: | |
# μ€ν μ€ν¨ μ μ€λ₯ μ²λ¦¬ | |
logger.error(f"μμ νλ‘κ·Έλ¨ μ€ν μ€ν¨: {execute_response.status_code}") | |
try: | |
error_data = execute_response.json() | |
error_message = error_data.get('error', execute_response.text) | |
except: | |
error_message = execute_response.text | |
# μ€ν μ€ν¨ μλ΅μ κΈ°λ³Έ μλ΅μΌλ‘ μ€μ | |
final_response = jsonify({ | |
"success": False, | |
"error": f"νλ‘κ·Έλ¨ μ€ν μ€ν¨({execute_response.status_code}): {error_message}" | |
}), 502 | |
# --- 3. μμ νλ‘κ·Έλ¨ μμ (try-finally λΈλ‘μΌλ‘ μ΄λ) --- | |
# μ€ν μ±κ³΅/μ€ν¨ μ¬λΆμ κ΄κ³μμ΄ μμ μλ | |
return final_response # μ μ₯λ μ΅μ’ μλ΅ λ°ν | |
except requests.exceptions.Timeout: | |
logger.error("μ¬μ©μ μ μ νλ‘κ·Έλ¨ μμ² μκ° μ΄κ³Ό (λ±λ‘ λλ μ€ν λ¨κ³)") | |
return jsonify({ | |
"success": False, | |
"error": "νλ‘κ·Έλ¨ μμ² μκ°μ΄ μ΄κ³Όλμμ΅λλ€ (LocalPCAgent μλ΅ μμ)." | |
}), 504 # Gateway Timeout | |
except requests.exceptions.ConnectionError: | |
logger.error("μ₯μΉ κ΄λ¦¬ μλ² μ°κ²° μ€ν¨ (λ±λ‘ λλ μ€ν λ¨κ³)") | |
return jsonify({ | |
"success": False, | |
"error": "μ₯μΉ κ΄λ¦¬ μλ²μ μ°κ²°ν μ μμ΅λλ€. μλ²κ° μ€ν μ€μΈμ§ νμΈν΄μ£ΌμΈμ." | |
}), 503 # Service Unavailable | |
except Exception as e: | |
logger.error(f"μ¬μ©μ μ μ νλ‘κ·Έλ¨ μ€ν μ€ Flask μΈ‘ μ€λ₯ λ°μ: {e}", exc_info=True) | |
return jsonify({ | |
"success": False, | |
"error": f"νλ‘κ·Έλ¨ μ€ν μ€ λ΄λΆ μ€λ₯ λ°μ: {str(e)}" | |
}), 500 # Internal Server Error | |
finally: | |
# --- 3. μμ νλ‘κ·Έλ¨ μμ (finally λΈλ‘μμ μ€ν) --- | |
if temp_id and get_device_url(): # μμ IDκ° μμ±λμκ³ URLμ΄ μ ν¨ν λλ§ μμ μλ | |
current_device_url = get_device_url() # URL λ€μ κ°μ Έμ€κΈ° (νμμ) | |
logger.info(f"μμ νλ‘κ·Έλ¨ μμ μλ: {temp_id}") | |
try: | |
delete_response = requests.delete( | |
f"{current_device_url}/api/programs/{temp_id}", # LocalPCAgentμ νλ‘κ·Έλ¨ μμ μλν¬μΈνΈ | |
timeout=3 | |
) | |
if delete_response.ok: | |
logger.info(f"μμ νλ‘κ·Έλ¨ μμ μ±κ³΅: {temp_id}") | |
else: | |
logger.warning(f"μμ νλ‘κ·Έλ¨ μμ μ€ν¨ ({delete_response.status_code}): {temp_id} - {delete_response.text[:100]}") | |
except Exception as delete_error: | |
logger.warning(f"μμ νλ‘κ·Έλ¨ μμ μ€ μ€λ₯ λ°μ (무μλ¨): {delete_error}") | |
elif not temp_id: | |
logger.debug("μμ IDκ° μμ±λμ§ μμ μμ 건λ<0xEB>λ.") | |
elif not get_device_url(): | |
logger.warning("μ₯μΉ μλ² URLμ΄ μμ΄ μμ νλ‘κ·Έλ¨ μμ 건λ<0xEB>λ.") | |
# register_device_routes ν¨μμ λ |