jeongsoo commited on
Commit
0f13aa5
·
1 Parent(s): c074b9a
Files changed (1) hide show
  1. app.py +239 -93
app.py CHANGED
@@ -104,16 +104,40 @@ def get_devices():
104
  """장치 목록 조회"""
105
  global SERVER_URL
106
 
 
 
 
 
107
  if not SERVER_URL:
108
- return "서버 URL이 설정되지 않았습니다. 먼저 서버에 연결하세요.", []
 
 
 
 
 
109
 
110
- # 디버그 정보 기록
111
- print(f"Fetching devices from {SERVER_URL}/api/devices - Timeout set to {REQUEST_TIMEOUT} seconds")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
- loading_html = "<div style='text-align: center; padding: 20px;'>"
114
- loading_html += f"<p>장치 목록을 불러오는 중입니다...</p>"
115
- loading_html += f"<p>이 작업은 최대 {REQUEST_TIMEOUT}초가 소요될 수 있습니다.</p>"
116
- loading_html += "</div>"
117
 
118
  try:
119
  # 타임아웃 증가 및 헤더 추가
@@ -124,12 +148,15 @@ def get_devices():
124
  "Connection": "keep-alive"
125
  }
126
 
 
127
  response = session.get(
128
  f"{SERVER_URL}/api/devices",
129
  headers=headers,
130
  timeout=REQUEST_TIMEOUT
131
  )
132
 
 
 
133
  if response.status_code == 200:
134
  result_json = response.json()
135
  devices = result_json.get("devices", [])
@@ -179,64 +206,121 @@ def get_devices():
179
  return error_html, []
180
  except RequestException as e:
181
  # 오류 상세 로그
182
- print(f"Error during device list request: {str(e)}")
183
  error_type = type(e).__name__
184
  error_detail = str(e)
185
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  # 타임아웃일 경우 더 상세한 오류 메시지
187
  if "timeout" in error_detail.lower() or "timed out" in error_detail.lower():
188
  error_html = f"<div style='padding: 15px; background-color: #f8d7da; border-radius: 5px; border-left: 5px solid #dc3545;'>"
189
  error_html += f"<h3 style='margin-top: 0; color: #721c24;'>장치 목록 조회 타임아웃</h3>"
190
  error_html += f"<p>서버가 {REQUEST_TIMEOUT}초 내에 응답하지 않았습니다.</p>"
191
- error_html += f"<p>이 문제는 다음과 같은 이유로 발생할 있습니다:</p>"
192
- error_html += f"<ul>"
193
- error_html += f"<li>ngrok 서버가 많은 요청을 처리 중이거나 도메인 제한에 걸렸습니다.</li>"
194
- error_html += f"<li>서버가 많은 장치 목록을 처리하는 중입니다.</li>"
195
- error_html += f"<li>네트워크 연결이 불안정합니다.</li>"
196
- error_html += f"</ul>"
197
- error_html += f"<p><strong>해결 방법:</strong></p>"
198
- error_html += f"<ol>"
199
- error_html += f"<li>한번 더 시도해보세요.</li>"
200
- error_html += f"<li>서버 연결 상태를 다시 확인하고 다시 연결해보세요.</li>"
201
- error_html += f"<li>ngrok을 다시 시작하고 새 URL로 연결해보세요.</li>"
202
- error_html += f"</ol>"
203
- error_html += f"<p><strong>오류 상세 정보:</strong> {error_type} - {error_detail}</p>"
204
  error_html += "</div>"
205
  else:
206
  error_html = f"<div style='padding: 15px; background-color: #f8d7da; border-radius: 5px; border-left: 5px solid #dc3545;'>"
207
  error_html += f"<h3 style='margin-top: 0; color: #721c24;'>장치 목록 조회 중 오류 발생</h3>"
208
  error_html += f"<p>{str(e)}</p>"
209
  error_html += f"<p><strong>오류 유형:</strong> {error_type}</p>"
210
- error_html += f"<p>이 오류는 다음과 같은 이유로 발생할 수 있습니다:</p>"
211
- error_html += f"<ul>"
212
- error_html += f"<li>서버 응답 시간이 너무 깃니다. 서버가 혼잡한지 확인하세요.</li>"
213
- error_html += f"<li>네트워크 연결이 불안정합니다.</li>"
214
- error_html += f"<li>ngrok 세션이 만료되었습니다. 서버를 다시 시작해보세요.</li>"
215
- error_html += f"</ul>"
216
- error_html += f"<p><strong>해결 방법:</strong> 서버를 다시 시작하거나, 새로운 ngrok 세션을 생성한 후 다시 연결해보세요.</p>"
217
  error_html += "</div>"
218
 
219
- return error_html, []
220
 
221
  def get_device_info(device_id):
222
  """장치 상세 정보 조회"""
223
  global SERVER_URL
224
 
225
- if not SERVER_URL:
226
- return "서버 URL이 설정되지 않았습니다. 먼저 서버에 연결하세요."
227
 
228
  if not device_id:
229
  return "장치를 선택해주세요."
 
 
 
 
 
 
 
 
 
 
 
230
 
231
- # 디버그 정보 기록
232
- print(f"Getting info for device: {device_id} from {SERVER_URL}/api/device/{device_id}/info")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
 
234
  try:
 
 
 
 
 
 
 
 
235
  response = session.get(
236
  f"{SERVER_URL}/api/device/{device_id}/info",
 
237
  timeout=REQUEST_TIMEOUT
238
  )
239
 
 
 
240
  if response.status_code == 200:
241
  result_json = response.json()
242
  device_info = result_json.get("device_info", {})
@@ -281,68 +365,86 @@ def get_device_info(device_id):
281
  error_html += "</div>"
282
  return error_html
283
  except RequestException as e:
284
- error_html = f"<div style='padding: 15px; background-color: #f8d7da; border-radius: 5px; border-left: 5px solid #dc3545;'>"
285
- error_html += f"<h3 style='margin-top: 0; color: #721c24;'>장치 정보 조회 중 오류 발생</h3>"
286
- error_html += f"<p>{str(e)}</p>"
287
- error_html += "</div>"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  return error_html
289
 
290
  def get_programs():
291
  """프로그램 목록 조회"""
292
  global SERVER_URL
293
 
 
 
 
 
294
  if not SERVER_URL:
295
- return "서버 URL이 설정되지 않았습니다. 먼저 서버에 연결하세요.", []
296
-
297
- # 디버그 정보 기록 - 여기서 모든 오류 상황을 축적해보자
298
- print(f"[DEBUG] 시작: 프로그램 목록 조회 시도 - {SERVER_URL}/api/programs")
299
-
300
- try:
301
- # 임시 테스트 - 응답을 시뮬레이션해보자
302
- print(f"[DEBUG] 헤더 구성 및 요청 준비 중")
303
-
304
- # 헤더 추가
305
- headers = {
306
- "User-Agent": "LocalPCAgent-Client/1.0",
307
- "Accept": "application/json",
308
- "Cache-Control": "no-cache",
309
- "Connection": "keep-alive"
310
- }
311
-
312
- # ���롭다운 배열 설정 오류 테스트
313
  test_programs = [
314
  {"id": "test1", "name": "테스트 프로그램 1", "description": "테스트 설명 1", "path": "C:\\test\\program1.exe"},
315
  {"id": "test2", "name": "테스트 프로그램 2", "description": "테스트 설명 2", "path": "C:\\test\\program2.exe"}
316
  ]
317
 
318
- # 코드 실행 로깅
319
- print(f"[DEBUG] 테스트 데이터 생성 완료")
320
-
321
- # 프로그램 목록을 바로 만들기
322
  program_options = []
323
  for program in test_programs:
324
  program_id = program.get("id", "")
325
  program_name = program.get("name", "Unknown Program")
326
  program_desc = program.get("description", "")
327
- entry = (f"{program_name} - {program_desc}", program_id)
328
- program_options.append(entry)
329
- print(f"[DEBUG] 드롭다운 옵션 추가: {entry}")
330
 
331
  # 디버그 정보 추가
332
- print(f"[DEBUG] 프로그램 옵션 만들기 완료 - 개수: {len(program_options)}, 데이터: {program_options}")
333
 
334
  # HTML 생성
335
- html_output = "<div style='padding: 10px; background-color: #e6f7ff; border-radius: 5px;'>"
336
- html_output += "<h4>테스트 프로그램 목록</h4>"
337
- html_output += "<ul>"
338
- for program in test_programs:
339
- html_output += f"<li><strong>{program['name']}</strong> - {program['description']}</li>"
340
- html_output += "</ul>"
341
  html_output += "</div>"
342
 
343
- print(f"[DEBUG] HTML 생성 완료, 결과 반환 준비 완료")
344
  return html_output, program_options
345
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
346
  if response.status_code == 200:
347
  result_json = response.json()
348
  programs = result_json.get("programs", [])
@@ -391,28 +493,34 @@ def get_programs():
391
  return error_html, []
392
  except RequestException as e:
393
  # 오류 상세 로그
394
- print(f"Error during program list request: {str(e)}")
395
  error_type = type(e).__name__
396
  error_detail = str(e)
397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
398
  # 타임아웃일 경우 더 상세한 오류 메시지
399
  if "timeout" in error_detail.lower() or "timed out" in error_detail.lower():
400
  error_html = f"<div style='padding: 15px; background-color: #f8d7da; border-radius: 5px; border-left: 5px solid #dc3545;'>"
401
  error_html += f"<h3 style='margin-top: 0; color: #721c24;'>프로그램 목록 조회 ��임아웃</h3>"
402
  error_html += f"<p>서버가 {REQUEST_TIMEOUT}초 내에 응답하지 않았습니다.</p>"
403
- error_html += f"<p>이 문제는 다음과 같은 이유로 발생할 있습니다:</p>"
404
- error_html += f"<ul>"
405
- error_html += f"<li>ngrok 서버가 많은 요청을 처리 중이거나 도메인 제한에 걸렸습니다.</li>"
406
- error_html += f"<li>서버가 매우 많은 프로그램 목록을 처리하는 중입니다.</li>"
407
- error_html += f"<li>네트워크 연결이 불안정합니다.</li>"
408
- error_html += f"</ul>"
409
- error_html += f"<p><strong>해결 방법:</strong></p>"
410
- error_html += f"<ol>"
411
- error_html += f"<li>한번 더 시도해보세요.</li>"
412
- error_html += f"<li>서버 연결 상태를 다시 확인하고 다시 연결해보세요.</li>"
413
- error_html += f"<li>ngrok을 다시 시작하고 새 URL로 연결해보세요.</li>"
414
- error_html += f"</ol>"
415
- error_html += f"<p><strong>오류 상세 정보:</strong> {error_type} - {error_detail}</p>"
416
  error_html += "</div>"
417
  else:
418
  error_html = f"<div style='padding: 15px; background-color: #f8d7da; border-radius: 5px; border-left: 5px solid #dc3545;'>"
@@ -420,22 +528,42 @@ def get_programs():
420
  error_html += f"<p>{str(e)}</p>"
421
  error_html += f"<p><strong>오류 유형:</strong> {error_type}</p>"
422
  error_html += f"<p><strong>해결 방법:</strong> 서버 연결을 확인하고 다시 시도해보세요.</p>"
 
423
  error_html += "</div>"
424
 
425
- return error_html, []
426
 
427
  def execute_program(program_id):
428
  """프로그램 실행"""
429
  global SERVER_URL
430
 
431
- if not SERVER_URL:
432
- return "서버 URL이 설정되지 않았습니다. 먼저 서버에 연결하세요."
433
 
434
  if not program_id:
435
  return "프로그램을 선택해주세요."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
436
 
437
  # 디버그 정보 기록
438
- print(f"Executing program {program_id} at {SERVER_URL}/api/programs/{program_id}/execute")
439
 
440
  try:
441
  # 로딩 표시
@@ -450,6 +578,7 @@ def execute_program(program_id):
450
  "Content-Type": "application/json"
451
  }
452
 
 
453
  response = session.post(
454
  f"{SERVER_URL}/api/programs/{program_id}/execute",
455
  headers=headers,
@@ -457,6 +586,8 @@ def execute_program(program_id):
457
  timeout=REQUEST_TIMEOUT
458
  )
459
 
 
 
460
  if response.status_code == 200:
461
  result = response.json()
462
 
@@ -483,11 +614,26 @@ def execute_program(program_id):
483
 
484
  return html_output
485
  except RequestException as e:
486
- # 오류 메시지 HTML로 표시
487
- html_output = "<div style='padding: 15px; background-color: #f8d7da; border-radius: 5px; border-left: 5px solid #dc3545;'>"
488
- html_output += f"<h3 style='margin-top: 0; color: #721c24;'>오류 발생</h3>"
489
- html_output += f"<p style='margin-bottom: 0;'>{str(e)}</p>"
490
- html_output += "</div>"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
491
 
492
  return html_output
493
 
 
104
  """장치 목록 조회"""
105
  global SERVER_URL
106
 
107
+ # 디버그 정보 기록
108
+ print(f"[DEBUG] 장치 목록 조회 함수 시작")
109
+
110
+ # 서버 URL이 없을 경우 테스트 데이터 사용
111
  if not SERVER_URL:
112
+ print(f"[DEBUG] 서버 URL이 설정되지 않았습니다. 테스트 데이터를 사용합니다.")
113
+ # 테스트 장치 데이터
114
+ test_devices = [
115
+ {"id": "device1", "name": "테스트 PC", "type": "PC", "status": "online"},
116
+ {"id": "device2", "name": "테스트 모바일", "type": "Mobile", "status": "online"}
117
+ ]
118
 
119
+ # 테스트 드롭다운 옵션 생성
120
+ device_options = []
121
+ for device in test_devices:
122
+ device_id = device.get("id", "")
123
+ device_name = device.get("name", "Unknown Device")
124
+ device_type = device.get("type", "Unknown")
125
+ device_options.append((f"{device_name} ({device_type})", device_id))
126
+
127
+ # 디버그 정보 추가
128
+ print(f"[DEBUG] 테스트 장치 옵션: {device_options}")
129
+
130
+ # HTML 생성
131
+ html_output = "<div style='padding: 15px; background-color: #fffaeb; border-radius: 5px; border-left: 5px solid #ffcc00;'>"
132
+ html_output += "<h3 style='margin-top: 0; color: #856404;'>서버 연결 필요</h3>"
133
+ html_output += "<p>서버에 연결되지 않았습니다. 먼저 페이지 상단의 '서버 연결' 탭에서 ngrok URL을 입력하고 연결하세요.</p>"
134
+ html_output += "<p>* 테스트용 장치 목록이 생성되었으니 테스트를 진행해보세요.</p>"
135
+ html_output += "</div>"
136
+
137
+ return html_output, device_options
138
 
139
+ # 서버 URL이 있는 경우 API 호출
140
+ print(f"[DEBUG] 서버 URL이 있습니다. API 호출을 시도합니다: {SERVER_URL}/api/devices")
 
 
141
 
142
  try:
143
  # 타임아웃 증가 및 헤더 추가
 
148
  "Connection": "keep-alive"
149
  }
150
 
151
+ print(f"[DEBUG] API 요청 전송 - 타임아웃: {REQUEST_TIMEOUT}")
152
  response = session.get(
153
  f"{SERVER_URL}/api/devices",
154
  headers=headers,
155
  timeout=REQUEST_TIMEOUT
156
  )
157
 
158
+ print(f"[DEBUG] API 응답 받음 - 상태코드: {response.status_code}")
159
+
160
  if response.status_code == 200:
161
  result_json = response.json()
162
  devices = result_json.get("devices", [])
 
206
  return error_html, []
207
  except RequestException as e:
208
  # 오류 상세 로그
209
+ print(f"[DEBUG] 장치 목록 조회 오류: {str(e)}")
210
  error_type = type(e).__name__
211
  error_detail = str(e)
212
 
213
+ # 테스트 드롭다운 데이터 생성 (오류 시에도 테스트 가능하게)
214
+ test_devices = [
215
+ {"id": "device1", "name": "테스트 PC", "type": "PC", "status": "offline"},
216
+ {"id": "device2", "name": "테스트 모바일", "type": "Mobile", "status": "offline"}
217
+ ]
218
+
219
+ # 드롭다운 옵션 생성
220
+ device_options = []
221
+ for device in test_devices:
222
+ device_id = device.get("id", "")
223
+ device_name = device.get("name", "Unknown Device")
224
+ device_type = device.get("type", "Unknown")
225
+ device_options.append((f"{device_name} ({device_type})", device_id))
226
+
227
+ print(f"[DEBUG] 테스트 용 장치 옵션 추가: {device_options}")
228
+
229
  # 타임아웃일 경우 더 상세한 오류 메시지
230
  if "timeout" in error_detail.lower() or "timed out" in error_detail.lower():
231
  error_html = f"<div style='padding: 15px; background-color: #f8d7da; border-radius: 5px; border-left: 5px solid #dc3545;'>"
232
  error_html += f"<h3 style='margin-top: 0; color: #721c24;'>장치 목록 조회 타임아웃</h3>"
233
  error_html += f"<p>서버가 {REQUEST_TIMEOUT}초 내에 응답하지 않았습니다.</p>"
234
+ error_html += f"<p><strong>해결 방법:</strong> 서버 연결을 다시 확인하고, ngrok을 다시 시작해보세요.</p>"
235
+ error_html += f"<p><strong>오류 정보:</strong> {error_type} - {error_detail}</p>"
236
+ error_html += f"<p style='margin-top: 15px;'><strong>테스트 모드:</strong> 임시 테스트용 데이터가 로드되었습니다. 장치 정보 해붙기가 가능하도록 드롭다운이 테스트 데이터로 채워졌습니다.</p>"
 
 
 
 
 
 
 
 
 
 
237
  error_html += "</div>"
238
  else:
239
  error_html = f"<div style='padding: 15px; background-color: #f8d7da; border-radius: 5px; border-left: 5px solid #dc3545;'>"
240
  error_html += f"<h3 style='margin-top: 0; color: #721c24;'>장치 목록 조회 중 오류 발생</h3>"
241
  error_html += f"<p>{str(e)}</p>"
242
  error_html += f"<p><strong>오류 유형:</strong> {error_type}</p>"
243
+ error_html += f"<p><strong>해결 방법:</strong> 서버 연결을 확인하고 다시 시도해보세요.</p>"
244
+ error_html += f"<p style='margin-top: 15px;'><strong>테스트 모드:</strong> 임시 테스트용 데이터가 로드되었습니다. 장치 정보 해붙기가 가능하도록 드롭다운이 테스트 데이터로 채워졌습니다.</p>"
 
 
 
 
 
245
  error_html += "</div>"
246
 
247
+ return error_html, device_options
248
 
249
  def get_device_info(device_id):
250
  """장치 상세 정보 조회"""
251
  global SERVER_URL
252
 
253
+ # 디버그 정보 기록
254
+ print(f"[DEBUG] 장치 상세 정보 조회 시도: {device_id}")
255
 
256
  if not device_id:
257
  return "장치를 선택해주세요."
258
+
259
+ # 테스트 데이터 확인 (테스트 데이터의 경우 테스트 정보 반환)
260
+ if device_id.startswith("device"):
261
+ print(f"[DEBUG] 테스트 장치 확인됨. 테스트 모드로 정보 생성")
262
+ # 장치 정보 HTML 테이블로 표시
263
+ html_output = "<div style='max-height: 400px; overflow-y: auto;'>"
264
+ html_output += "<h3 style='margin-top: 0;'>테스트 장치 정보</h3>"
265
+ html_output += "<div style='padding: 10px; background-color: #e6f7ff; border-radius: 5px; margin-bottom: 10px;'>"
266
+ html_output += "<p style='margin: 0;'><strong>주의:</strong> 현재 테스트 모드입니다. 실제 서버에 연결하려면 페이지 상단의 '서버 연결' 탭에서 ngrok URL을 입력하고 연결하세요.</p>"
267
+ html_output += "</div>"
268
+ html_output += "<table style='width: 100%; border-collapse: collapse;'>"
269
 
270
+ # 기본 정보
271
+ html_output += "<tr style='background-color: #f2f2f2;'><th colspan='2' style='padding: 8px; text-align: left; border-bottom: 1px solid #ddd;'>기본 정보</th></tr>"
272
+
273
+ # 테스트 기존 정보
274
+ if device_id == "device1":
275
+ device_info = {"name": "테스트 PC", "type": "PC", "status": "offline", "details": {"ip": "192.168.0.100", "os": "Windows 10", "cpu": "Intel Core i5"}}
276
+ else:
277
+ device_info = {"name": "테스트 모바일", "type": "Mobile", "status": "offline", "details": {"ip": "192.168.0.101", "os": "Android 12", "model": "Galaxy S21"}}
278
+
279
+ # 기본 정보 표시
280
+ for key in ['name', 'type', 'status']:
281
+ if key in device_info:
282
+ html_output += f"<tr style='border-bottom: 1px solid #ddd;'>"
283
+ html_output += f"<td style='padding: 8px; font-weight: bold; width: 30%;'>{key.capitalize()}</td>"
284
+ html_output += f"<td style='padding: 8px;'>{device_info.get(key, '')}</td>"
285
+ html_output += "</tr>"
286
+
287
+ # 상세 정보가 있으면 추가
288
+ if 'details' in device_info and isinstance(device_info['details'], dict):
289
+ html_output += "<tr style='background-color: #f2f2f2;'><th colspan='2' style='padding: 8px; text-align: left; border-bottom: 1px solid #ddd;'>상세 정보</th></tr>"
290
+ for key, value in device_info['details'].items():
291
+ html_output += f"<tr style='border-bottom: 1px solid #ddd;'>"
292
+ html_output += f"<td style='padding: 8px; font-weight: bold; width: 30%;'>{key.upper()}</td>"
293
+ html_output += f"<td style='padding: 8px;'>{value}</td>"
294
+ html_output += "</tr>"
295
+
296
+ html_output += "</table></div>"
297
+ return html_output
298
+
299
+ if not SERVER_URL:
300
+ # 서버 URL이 없을 경우 오류 메시지 반환
301
+ html_output = "<div style='padding: 15px; background-color: #fff3cd; border-radius: 5px; border-left: 5px solid #ffc107;'>"
302
+ html_output += "<h3 style='margin-top: 0; color: #856404;'>서버 연결 필요</h3>"
303
+ html_output += "장치 정보를 조회하려면 먼저 서버에 연결해야 합니다. 페이지 상단의 '서버 연결' 탭에서 ngrok URL을 입력하고 연결하세요."
304
+ html_output += "</div>"
305
+ return html_output
306
 
307
  try:
308
+ # API 요청 전송
309
+ print(f"[DEBUG] API 요청 전송 - 타임아웃: {REQUEST_TIMEOUT}")
310
+ headers = {
311
+ "User-Agent": "LocalPCAgent-Client/1.0",
312
+ "Accept": "application/json",
313
+ "Cache-Control": "no-cache"
314
+ }
315
+
316
  response = session.get(
317
  f"{SERVER_URL}/api/device/{device_id}/info",
318
+ headers=headers,
319
  timeout=REQUEST_TIMEOUT
320
  )
321
 
322
+ print(f"[DEBUG] API 응답 받음 - 상태코드: {response.status_code}")
323
+
324
  if response.status_code == 200:
325
  result_json = response.json()
326
  device_info = result_json.get("device_info", {})
 
365
  error_html += "</div>"
366
  return error_html
367
  except RequestException as e:
368
+ # 오류 상세 로그
369
+ print(f"[DEBUG] 장치 정보 조회 중 오류: {str(e)}")
370
+ error_type = type(e).__name__
371
+ error_detail = str(e)
372
+
373
+ # 타임아웃 오류 확인
374
+ if "timeout" in error_detail.lower() or "timed out" in error_detail.lower():
375
+ error_html = "<div style='padding: 15px; background-color: #f8d7da; border-radius: 5px; border-left: 5px solid #dc3545;'>"
376
+ error_html += f"<h3 style='margin-top: 0; color: #721c24;'>장치 정보 조회 타임아웃</h3>"
377
+ error_html += f"<p>서버가 {REQUEST_TIMEOUT}초 내에 응답하지 않았습니다.</p>"
378
+ error_html += f"<p><strong>해결 방법:</strong> 서버 연결을 다시 확인하고, ngrok을 다시 시작해보세요.</p>"
379
+ error_html += "</div>"
380
+ else:
381
+ error_html = "<div style='padding: 15px; background-color: #f8d7da; border-radius: 5px; border-left: 5px solid #dc3545;'>"
382
+ error_html += f"<h3 style='margin-top: 0; color: #721c24;'>장치 정보 조회 중 오류 발생</h3>"
383
+ error_html += f"<p>{str(e)}</p>"
384
+ error_html += f"<p><strong>오류 유형:</strong> {error_type}</p>"
385
+ error_html += f"<p><strong>해결 방법:</strong> 서버 연결을 확인하고 다시 시도해보세요.</p>"
386
+ error_html += "</div>"
387
+
388
  return error_html
389
 
390
  def get_programs():
391
  """프로그램 목록 조회"""
392
  global SERVER_URL
393
 
394
+ # 디버그 정보 기록
395
+ print(f"[DEBUG] 프로그램 목록 조회 함수 시작")
396
+
397
+ # 서버 URL이 없을 경우 테스트 데이터 사용
398
  if not SERVER_URL:
399
+ print(f"[DEBUG] 서버 URL이 설정되지 않았습니다. 테스트 데이터를 사용합니다.")
400
+ # 테스트 프로그램 데이터
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
  test_programs = [
402
  {"id": "test1", "name": "테스트 프로그램 1", "description": "테스트 설명 1", "path": "C:\\test\\program1.exe"},
403
  {"id": "test2", "name": "테스트 프로그램 2", "description": "테스트 설명 2", "path": "C:\\test\\program2.exe"}
404
  ]
405
 
406
+ # 테스트 드롭다운 옵션 생성
 
 
 
407
  program_options = []
408
  for program in test_programs:
409
  program_id = program.get("id", "")
410
  program_name = program.get("name", "Unknown Program")
411
  program_desc = program.get("description", "")
412
+ program_options.append((f"{program_name} - {program_desc}", program_id))
 
 
413
 
414
  # 디버그 정보 추가
415
+ print(f"[DEBUG] 테스트 프로그램 옵션: {program_options}")
416
 
417
  # HTML 생성
418
+ html_output = "<div style='padding: 15px; background-color: #fffaeb; border-radius: 5px; border-left: 5px solid #ffcc00;'>"
419
+ html_output += "<h3 style='margin-top: 0; color: #856404;'>서버 연결 필요</h3>"
420
+ html_output += "<p>서버에 연결되지 않았습니다. 먼저 페이지 상단의 '서버 연결' 탭에서 ngrok URL을 입력하고 연결하세요.</p>"
421
+ html_output += "<p>* 테스트용 프로그램 목록이 생성되었으니 테스트를 진행해보세요.</p>"
 
 
422
  html_output += "</div>"
423
 
 
424
  return html_output, program_options
425
 
426
+ # 서버 URL이 있는 경우 API 호출
427
+ print(f"[DEBUG] 서버 URL이 있습니다. API 호출을 시도합니다: {SERVER_URL}/api/programs")
428
+
429
+ try:
430
+ # 헤더 추가
431
+ headers = {
432
+ "User-Agent": "LocalPCAgent-Client/1.0",
433
+ "Accept": "application/json",
434
+ "Cache-Control": "no-cache",
435
+ "Connection": "keep-alive"
436
+ }
437
+
438
+ # API 요청 실행
439
+ print(f"[DEBUG] API 요청 시도 - 타임아웃: {REQUEST_TIMEOUT}")
440
+ response = session.get(
441
+ f"{SERVER_URL}/api/programs",
442
+ headers=headers,
443
+ timeout=REQUEST_TIMEOUT
444
+ )
445
+
446
+ print(f"[DEBUG] API 응답 받음 - 상태코드: {response.status_code}")
447
+
448
  if response.status_code == 200:
449
  result_json = response.json()
450
  programs = result_json.get("programs", [])
 
493
  return error_html, []
494
  except RequestException as e:
495
  # 오류 상세 로그
496
+ print(f"[DEBUG] API 요청 오류: {str(e)}")
497
  error_type = type(e).__name__
498
  error_detail = str(e)
499
 
500
+ # 테스트 드롭다운 데이터 생성 (오류 시에도 테스트 가능하게)
501
+ test_programs = [
502
+ {"id": "test1", "name": "테스트 프로그램 1", "description": "테스트 설명 1", "path": "C:\\test\\program1.exe"},
503
+ {"id": "test2", "name": "테스트 프로그램 2", "description": "테스트 설명 2", "path": "C:\\test\\program2.exe"}
504
+ ]
505
+
506
+ # 드롭다운 옵션 생성
507
+ program_options = []
508
+ for program in test_programs:
509
+ program_id = program.get("id", "")
510
+ program_name = program.get("name", "Unknown Program")
511
+ program_desc = program.get("description", "")
512
+ program_options.append((f"{program_name} - {program_desc}", program_id))
513
+
514
+ print(f"[DEBUG] 테스트 용 드롭다운 옵션 추가: {program_options}")
515
+
516
  # 타임아웃일 경우 더 상세한 오류 메시지
517
  if "timeout" in error_detail.lower() or "timed out" in error_detail.lower():
518
  error_html = f"<div style='padding: 15px; background-color: #f8d7da; border-radius: 5px; border-left: 5px solid #dc3545;'>"
519
  error_html += f"<h3 style='margin-top: 0; color: #721c24;'>프로그램 목록 조회 ��임아웃</h3>"
520
  error_html += f"<p>서버가 {REQUEST_TIMEOUT}초 내에 응답하지 않았습니다.</p>"
521
+ error_html += f"<p><strong>해결 방법:</strong> 서버 연결을 다시 확인하고, ngrok을 다시 시작해보세요.</p>"
522
+ error_html += f"<p><strong>오류 정보:</strong> {error_type} - {error_detail}</p>"
523
+ error_html += f"<p style='margin-top: 15px;'><strong>테스트 모드:</strong> 임시 테스트용 데이터가 로드되었습니다. 프로그램 실행 해붙기가 가능하도록 드롭다운이 테스트 데이터로 채워졌습니다.</p>"
 
 
 
 
 
 
 
 
 
 
524
  error_html += "</div>"
525
  else:
526
  error_html = f"<div style='padding: 15px; background-color: #f8d7da; border-radius: 5px; border-left: 5px solid #dc3545;'>"
 
528
  error_html += f"<p>{str(e)}</p>"
529
  error_html += f"<p><strong>오류 유형:</strong> {error_type}</p>"
530
  error_html += f"<p><strong>해결 방법:</strong> 서버 연결을 확인하고 다시 시도해보세요.</p>"
531
+ error_html += f"<p style='margin-top: 15px;'><strong>테스트 모드:</strong> 임시 테스트용 데이터가 로드되었습니다. 프로그램 실행 해붙기가 가능하도록 드롭다운이 테스트 데이터로 채워졌습니다.</p>"
532
  error_html += "</div>"
533
 
534
+ return error_html, program_options
535
 
536
  def execute_program(program_id):
537
  """프로그램 실행"""
538
  global SERVER_URL
539
 
540
+ # 디버그 정보 기록
541
+ print(f"[DEBUG] 프로그램 실행 시도: {program_id}")
542
 
543
  if not program_id:
544
  return "프로그램을 선택해주세요."
545
+
546
+ # 테스트 데이터 확인 (테스트 데이터의 경우 테스트 성공 반환)
547
+ if program_id.startswith("test"):
548
+ print(f"[DEBUG] 테스트 프로그램 확인됨. 테스트 모드로 성공 응답 생성")
549
+ # 성공 메시지 HTML로 표시
550
+ html_output = "<div style='padding: 15px; background-color: #d4edda; border-radius: 5px; border-left: 5px solid #28a745;'>"
551
+ html_output += f"<h3 style='margin-top: 0; color: #155724;'>테스트 실행 성공</h3>"
552
+ html_output += f"<p style='margin-bottom: 0;'>테스트 프로그램 {program_id}가 시뮬레이션되었습니다.</p>"
553
+ html_output += f"<p style='margin-top: 10px;'><strong>주의:</strong> 현재 테스트 모드입니다. 실제 서버에 연결하여 실행하시려면 서버 URL을 입력하고 연결해주세요.</p>"
554
+ html_output += "</div>"
555
+ return html_output
556
+
557
+ if not SERVER_URL:
558
+ # 서버 URL이 없을 경우 오류 메시지 반환
559
+ html_output = "<div style='padding: 15px; background-color: #fff3cd; border-radius: 5px; border-left: 5px solid #ffc107;'>"
560
+ html_output += "<h3 style='margin-top: 0; color: #856404;'>서버 연결 필요</h3>"
561
+ html_output += "프로그램을 실행하려면 먼저 서버에 연결해야 합니다. 페이지 상단의 '서버 연결' 탭에서 ngrok URL을 입력하고 연결하세요."
562
+ html_output += "</div>"
563
+ return html_output
564
 
565
  # 디버그 정보 기록
566
+ print(f"[DEBUG] 서버에 실행 요청 전송: {SERVER_URL}/api/programs/{program_id}/execute")
567
 
568
  try:
569
  # 로딩 표시
 
578
  "Content-Type": "application/json"
579
  }
580
 
581
+ print(f"[DEBUG] API 요청 전송 - 타임아웃: {REQUEST_TIMEOUT}")
582
  response = session.post(
583
  f"{SERVER_URL}/api/programs/{program_id}/execute",
584
  headers=headers,
 
586
  timeout=REQUEST_TIMEOUT
587
  )
588
 
589
+ print(f"[DEBUG] API 응답 받음 - 상태코드: {response.status_code}")
590
+
591
  if response.status_code == 200:
592
  result = response.json()
593
 
 
614
 
615
  return html_output
616
  except RequestException as e:
617
+ # 오류 상세 로그
618
+ print(f"[DEBUG] 프로그램 실행 오류: {str(e)}")
619
+ error_type = type(e).__name__
620
+ error_detail = str(e)
621
+
622
+ # 타임아웃 오류 확인
623
+ if "timeout" in error_detail.lower() or "timed out" in error_detail.lower():
624
+ html_output = "<div style='padding: 15px; background-color: #f8d7da; border-radius: 5px; border-left: 5px solid #dc3545;'>"
625
+ html_output += f"<h3 style='margin-top: 0; color: #721c24;'>프로그램 실행 타임아웃</h3>"
626
+ html_output += f"<p style='margin-bottom: 10px;'>서버가 {REQUEST_TIMEOUT}초 내에 응답하지 않았습니다.</p>"
627
+ html_output += f"<p><strong>해결 방법:</strong> 서버 연결을 확인하고 다시 시도해보세요. 서버가 다른 작업을 처리하고 있을 수 있습니다.</p>"
628
+ html_output += f"<p><strong>오류 정보:</strong> {error_type} - {error_detail}</p>"
629
+ html_output += "</div>"
630
+ else:
631
+ # 오류 메시지 HTML로 표시
632
+ html_output = "<div style='padding: 15px; background-color: #f8d7da; border-radius: 5px; border-left: 5px solid #dc3545;'>"
633
+ html_output += f"<h3 style='margin-top: 0; color: #721c24;'>오류 발생</h3>"
634
+ html_output += f"<p style='margin-bottom: 10px;'>{str(e)}</p>"
635
+ html_output += f"<p><strong>오류 유형:</strong> {error_type}</p>"
636
+ html_output += "</div>"
637
 
638
  return html_output
639