Spaces:
Sleeping
Sleeping
""" | |
RAG ๊ฒ์ ์ฑ๋ด ์น ์ ํ๋ฆฌ์ผ์ด์ - ์ฅ์น ๊ด๋ฆฌ API ๋ผ์ฐํธ ์ ์ (์ฌ์ฉ์ ์ ์ ์คํ, f-string ์ค๋ฅ ์์ ๋จ) | |
""" | |
import logging | |
import requests | |
import uuid # ์ฌ์ฉ์ ์ ์ ์คํ์ ์ํด ์ถ๊ฐ | |
import time # ์ฌ์ฉ์ ์ ์ ์คํ์ ์ํด ์ถ๊ฐ | |
import shlex # ์ฌ์ฉ์ ์ ์ ์คํ์ ์ํด ์ถ๊ฐ | |
import os # ๊ฒฝ๋ก ์ฒ๋ฆฌ๋ฅผ ์ํด ์ถ๊ฐ (ํ์์) | |
from flask import request, jsonify | |
import json | |
# ๋ก๊ฑฐ ๊ฐ์ ธ์ค๊ธฐ | |
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>๋.") | |
def scan_device_ports(): | |
"""๋ก์ปฌPC์ ์ฐ๊ฒฐ๋ ์ฅ์น(COM ํฌํธ ๋ฐ USB ์ฅ์น) ๋ชฉ๋ก ์กฐํ API""" | |
logger.info("์ฅ์น ํฌํธ ์ค์บ ์์ฒญ") | |
try: | |
# ํ๋ก๊ทธ๋จ ID (์ฅ์น ์ค์บ ์คํฌ๋ฆฝํธ ID - scan_ports) | |
program_id = "scan_ports" | |
# ํ์ฌ ์ฅ์น ์๋ฒ URL ๊ฐ์ ธ์ค๊ธฐ | |
current_device_url = get_device_url() | |
if not current_device_url: | |
logger.error("์ฅ์น ์๋ฒ URL์ด ์ค์ ๋์ง ์์์ต๋๋ค.") | |
return jsonify({ | |
"success": False, | |
"error": "์ฅ์น ์๋ฒ URL์ด ์ค์ ๋์ง ์์ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค." | |
}), 503 # Service Unavailable | |
# ์ฅ์น ์ค์บ ํ๋ก๊ทธ๋จ ์คํ (ํ๋ก๊ทธ๋จ ID: scan_ports) | |
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=20 # ์ฅ์น ์ค์บ์ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆด ์ ์์ผ๋ฏ๋ก ํ์์์ ์ฆ๊ฐ | |
) | |
logger.debug(f"์ฅ์น ํฌํธ ์ค์บ ์๋ต ์ํ ์ฝ๋: {response.status_code}") | |
if response.status_code == 200: | |
try: | |
data = response.json() | |
# LocalPCAgent ์๋ต์์ ํ์ํ ์ ๋ณด ์ถ์ถ | |
if data.get("success", False): | |
# ์ค์บ ๊ฒฐ๊ณผ ์ถ๋ ฅ ๊ฐ์ ธ์ค๊ธฐ | |
output = data.get("output", "") | |
try: | |
# ์ถ๋ ฅ์ด JSON ํ์์ธ์ง ํ์ธ ๋ฐ ํ์ฑ | |
scan_results = json.loads(output) | |
logger.info("์ฅ์น ํฌํธ ์ค์บ ๊ฒฐ๊ณผ ํ์ฑ ์ฑ๊ณต") | |
# ๊ฒฐ๊ณผ ๋ฐํ | |
return jsonify({ | |
"success": True, | |
"timestamp": scan_results.get("timestamp", ""), | |
"system_info": scan_results.get("system_info", {}), | |
"devices": scan_results.get("devices", {}) | |
}) | |
except json.JSONDecodeError as json_err: | |
logger.error(f"์ฅ์น ํฌํธ ์ค์บ ๊ฒฐ๊ณผ JSON ํ์ฑ ์คํจ: {json_err}") | |
return jsonify({ | |
"success": False, | |
"error": "์ฅ์น ํฌํธ ์ค์บ ๊ฒฐ๊ณผ๋ฅผ JSON์ผ๋ก ํ์ฑํ ์ ์์ต๋๋ค.", | |
"raw_output": output[:1000] # ๊ธด ์ถ๋ ฅ์ ์๋ผ์ ๋ฐํ | |
}), 500 | |
else: | |
# ํ๋ก๊ทธ๋จ ์คํ์ ์ฑ๊ณตํ์ง๋ง ์ค์บ ์์ฒด๊ฐ ์คํจํ ๊ฒฝ์ฐ | |
error_message = data.get("error", "์ ์ ์๋ ์ค๋ฅ") | |
logger.error(f"์ฅ์น ํฌํธ ์ค์บ ํ๋ก๊ทธ๋จ ์ค๋ฅ: {error_message}") | |
return jsonify({ | |
"success": False, | |
"error": f"์ฅ์น ํฌํธ ์ค์บ ํ๋ก๊ทธ๋จ ์ค๋ฅ: {error_message}" | |
}), 500 | |
except Exception as parse_err: | |
logger.error(f"์ฅ์น ํฌํธ ์ค์บ ์๋ต ์ฒ๋ฆฌ ์ค ์ค๋ฅ: {parse_err}") | |
return jsonify({ | |
"success": False, | |
"error": f"์ฅ์น ํฌํธ ์ค์บ ์๋ต ์ฒ๋ฆฌ ์ค ์ค๋ฅ: {str(parse_err)}" | |
}), 500 | |
else: | |
# API ์์ฒญ ์์ฒด๊ฐ ์คํจํ ๊ฒฝ์ฐ | |
error_message = f"์ฅ์น ํฌํธ ์ค์บ API ์์ฒญ ์คํจ (์ํ ์ฝ๋: {response.status_code})" | |
try: | |
error_data = response.json() | |
if 'error' in error_data: | |
error_message += f": {error_data['error']}" | |
except: | |
if response.text: | |
error_message += f": {response.text[:200]}" | |
logger.error(error_message) | |
return jsonify({ | |
"success": False, | |
"error": error_message | |
}), response.status_code | |
except requests.exceptions.Timeout: | |
error_message = "์ฅ์น ํฌํธ ์ค์บ ์์ฒญ ์๊ฐ ์ด๊ณผ" | |
logger.error(error_message) | |
return jsonify({ | |
"success": False, | |
"error": error_message | |
}), 504 # Gateway Timeout | |
except requests.exceptions.ConnectionError: | |
error_message = f"์ฅ์น ์๋ฒ ์ฐ๊ฒฐ ์คํจ ({get_device_url()})" | |
logger.error(error_message) | |
return jsonify({ | |
"success": False, | |
"error": "์ฅ์น ์๋ฒ์ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค. ์๋ฒ๊ฐ ์คํ ์ค์ธ์ง ํ์ธํด์ฃผ์ธ์." | |
}), 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 | |
# register_device_routes ํจ์์ ๋ |