Compare commits
2 Commits
main
...
3d8521ad89
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d8521ad89 | |||
| 461d5feb01 |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -3,3 +3,11 @@ __pycache__/
|
||||
.venv/
|
||||
venv/
|
||||
.env
|
||||
|
||||
# PyInstaller build outputs
|
||||
build/
|
||||
dist/
|
||||
|
||||
# local tool / backup folders
|
||||
.claude/
|
||||
_backup/
|
||||
|
||||
801
api_routes.py
801
api_routes.py
File diff suppressed because it is too large
Load Diff
91
app.py
91
app.py
@@ -1,113 +1,70 @@
|
||||
"""팔레타이징 앱 진입점.
|
||||
|
||||
Flask(백엔드) + pywebview(데스크톱 창) + waitress(WSGI 서버) 구성.
|
||||
로봇 제어 로직과 HTTP API 는 전부 api_routes.py 에 있다.
|
||||
PyInstaller 로 빌드 시(frozen) 템플릿 경로가 임시 폴더(_MEIPASS)로 바뀌는 것을 처리한다.
|
||||
"""
|
||||
from flask import Flask, render_template, request, jsonify
|
||||
import sys
|
||||
import os
|
||||
from api_routes import api_routes
|
||||
from api_routes import api_routes
|
||||
import webview
|
||||
from waitress import serve
|
||||
|
||||
# PyInstaller 실행파일(frozen)이면 압축 해제된 임시 폴더에서 템플릿을 찾는다
|
||||
if getattr(sys, 'frozen', False):
|
||||
template_folder = os.path.join(sys._MEIPASS, 'templates')
|
||||
app = Flask(__name__, template_folder=template_folder, static_url_path='/static')
|
||||
else:
|
||||
app = Flask(__name__, static_url_path='/static')
|
||||
|
||||
app.register_blueprint(api_routes) # 로봇 제어 API 라우트 등록
|
||||
|
||||
#app = Flask(__name__, static_url_path='/static')
|
||||
app.register_blueprint(api_routes) # 분리된 API 라우트 등록
|
||||
|
||||
# ── 화면 라우트 ──────────────────────────────────────────────
|
||||
@app.route('/')
|
||||
def index():
|
||||
"""메인 화면: 팔레트 선택/적재 배치 설정."""
|
||||
return render_template('layer.html')
|
||||
|
||||
@app.route('/progress')
|
||||
def progess():
|
||||
"""일반 적재 진행 현황 화면."""
|
||||
return render_template('progress.html')
|
||||
|
||||
|
||||
@app.route('/oneLineProgress')
|
||||
def oneLineProgess():
|
||||
"""한줄쌓기 진행 현황 화면."""
|
||||
return render_template('oneLineProgress.html')
|
||||
|
||||
# 종료 함수
|
||||
|
||||
# ── 종료 처리 ────────────────────────────────────────────────
|
||||
def shutdown_waitress_server():
|
||||
"""waitress 서버 및 프로세스 전체 종료."""
|
||||
print("Shutting down the server...")
|
||||
os._exit(0)
|
||||
|
||||
def destroy(window):
|
||||
"""pywebview 창 닫기."""
|
||||
print('Destroying window..')
|
||||
window.destroy()
|
||||
print('Destroyed!')
|
||||
|
||||
@app.route('/shutdown', methods=['POST'])
|
||||
def shutdown():
|
||||
"""UI 종료 버튼: 창 닫고 서버/프로세스 종료."""
|
||||
destroy(test)
|
||||
shutdown_waitress_server()
|
||||
return 'Server shutting down'
|
||||
|
||||
port=5000
|
||||
|
||||
# if __name__ == "__main__":
|
||||
# app.run(port=port, debug=True)
|
||||
port = 5000
|
||||
|
||||
# pywebview 가 Flask 앱을 감싸는 데스크톱 창 생성
|
||||
test = webview.create_window('Palletizing', app)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# webview.start()가 창이 닫힐 때까지 블록되고,
|
||||
# 창이 닫힌 뒤에는 waitress 단독 서버로 계속 서비스한다(0.0.0.0:5000).
|
||||
webview.start()
|
||||
serve(app, host="0.0.0.0", port=port)
|
||||
|
||||
|
||||
# from flask import Flask, render_template, request
|
||||
# import sys
|
||||
# import os
|
||||
# from api_routes import api_routes
|
||||
# import webview
|
||||
# from waitress import serve
|
||||
# import threading
|
||||
|
||||
# # Flask 애플리케이션 설정
|
||||
# if getattr(sys, 'frozen', False):
|
||||
# template_folder = os.path.join(sys._MEIPASS, 'templates')
|
||||
# app = Flask(__name__, template_folder=template_folder, static_url_path='/static')
|
||||
# else:
|
||||
# app = Flask(__name__, static_url_path='/static')
|
||||
|
||||
# app.register_blueprint(api_routes)
|
||||
|
||||
# @app.route('/')
|
||||
# def index():
|
||||
# return render_template('layer.html')
|
||||
|
||||
# @app.route('/progress')
|
||||
# def progress():
|
||||
# return render_template('progress.html')
|
||||
|
||||
# @app.route('/oneLineProgress')
|
||||
# def oneLineProgress():
|
||||
# return render_template('oneLineProgress.html')
|
||||
|
||||
# # 종료 함수
|
||||
# def shutdown_server():
|
||||
# print("Shutting down the server...")
|
||||
# os._exit(0)
|
||||
|
||||
# # 종료 라우트 설정
|
||||
# @app.route('/shutdown', methods=['POST'])
|
||||
# def shutdown():
|
||||
# print("Shutdown request received.")
|
||||
# destroy(test) # Webview 윈도우 종료
|
||||
# shutdown_server() # Waitress 서버와 프로그램 종료
|
||||
# return 'Server shutting down...'
|
||||
|
||||
# # Webview 윈도우 종료 함수
|
||||
# def destroy(window):
|
||||
# print('Destroying window..')
|
||||
# window.destroy()
|
||||
# print('Destroyed!')
|
||||
|
||||
# # 서버 실행
|
||||
# port = 5000
|
||||
# test = webview.create_window('Palletizing', app)
|
||||
|
||||
# if __name__ == "__main__":
|
||||
# # Webview와 Waitress 서버를 별도 스레드로 실행
|
||||
# server_thread = threading.Thread(target=lambda: serve(app, host="0.0.0.0", port=port))
|
||||
# server_thread.start()
|
||||
# webview.start()
|
||||
|
||||
44
app.spec
Normal file
44
app.spec
Normal file
@@ -0,0 +1,44 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
|
||||
a = Analysis(
|
||||
['app.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[('templates', 'templates'), ('static', 'static'), ('SDK', 'SDK'), ('api_routes.py', 'api_routes.py')],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
noarchive=False,
|
||||
optimize=0,
|
||||
)
|
||||
pyz = PYZ(a.pure)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name='app',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=True,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
||||
coll = COLLECT(
|
||||
exe,
|
||||
a.binaries,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
name='app',
|
||||
)
|
||||
Reference in New Issue
Block a user