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 ํจ์์ ๋ |