TorqueWrench/backend/app.py

535 lines
16 KiB
Python
Raw Normal View History

2026-01-24 02:54:01 +08:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
电动扳手后端API服务器
提供工单查询认领数据提交等接口
"""
from flask import Flask, request, jsonify
from flask_cors import CORS
import json
import os
import sys
from datetime import datetime
from typing import Dict, List, Optional
from database import Database
# 添加父目录到路径以便导入wrench_controller
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from wrench_controller import WrenchController
app = Flask(__name__)
CORS(app) # 允许跨域请求
# 初始化数据库
# 确保使用正确的数据库路径相对于app.py所在目录
import os
db_path = os.path.join(os.path.dirname(__file__), "wrench.db")
db = Database(db_path)
print(f"[INFO] 数据库路径: {db_path}")
@app.route('/api/work-orders', methods=['GET'])
def get_work_orders():
"""
查询工单列表
如果不传参数返回所有可用工单
如果传trace_id和process_id返回符合条件的工单
"""
trace_id = request.args.get('trace_id')
process_id = request.args.get('process_id')
try:
# 如果没有传参数,返回所有可用工单
if not trace_id or not process_id:
available_orders = db.get_all_available_work_orders()
print(f"[DEBUG] 查询所有可用工单,结果数量: {len(available_orders)}")
else:
# 从数据库查询指定条件的可用工单
available_orders = db.get_available_work_orders(trace_id, process_id)
print(f"[DEBUG] 查询参数: trace_id={trace_id}, process_id={process_id}, 结果数量: {len(available_orders)}")
return jsonify({
"success": True,
"message": "查询成功",
"data": available_orders
})
except Exception as e:
print(f"[ERROR] 查询工单异常: {e}")
import traceback
traceback.print_exc()
return jsonify({
"success": False,
"message": f"查询失败: {str(e)}",
"data": []
}), 500
@app.route('/api/work-orders/claim', methods=['POST'])
def claim_work_order():
"""
认领工单
参数: trace_id (追溯号), process_id (工序号), operator (操作员)
返回: 认领结果和工单详情
"""
data = request.get_json()
trace_id = data.get('trace_id')
process_id = data.get('process_id')
operator = data.get('operator', '未知操作员')
if not trace_id or not process_id:
return jsonify({
"success": False,
"message": "追溯号和工序号不能为空"
}), 400
# 检查是否已被认领
claimed = db.get_claimed_order(trace_id, process_id)
if claimed:
return jsonify({
"success": False,
"message": "该工单已被认领"
}), 400
# 查找工单
order = db.get_work_order(trace_id, process_id)
if not order:
return jsonify({
"success": False,
"message": "未找到符合条件的工单"
}), 404
# 认领工单
if db.claim_work_order(trace_id, process_id, operator):
return jsonify({
"success": True,
"message": "认领成功",
"data": order
})
else:
return jsonify({
"success": False,
"message": "认领失败"
}), 500
@app.route('/api/work-orders/submit', methods=['POST'])
def submit_work_order():
"""
提交工单数据
参数: trace_id, process_id, bolts (螺栓数据列表), device_sn, device_name
返回: 提交结果
"""
data = request.get_json()
trace_id = data.get('trace_id')
process_id = data.get('process_id')
bolts = data.get('bolts', [])
device_sn = data.get('device_sn')
device_name = data.get('device_name')
# 调试:打印接收到的数据
print(f"[DEBUG] 接收提交工单数据:")
print(f" trace_id: {trace_id}")
print(f" process_id: {process_id}")
print(f" device_sn: {device_sn}")
print(f" device_name: {device_name}")
print(f" bolts数量: {len(bolts)}")
if not trace_id or not process_id:
return jsonify({
"success": False,
"message": "追溯号和工序号不能为空"
}), 400
# 检查是否已被认领
claimed = db.get_claimed_order(trace_id, process_id)
if not claimed:
return jsonify({
"success": False,
"message": "该工单未被认领,无法提交"
}), 400
# 提交结果
if db.submit_work_order(trace_id, process_id, bolts, device_sn, device_name):
return jsonify({
"success": True,
"message": "数据提交成功",
"data": {
"trace_id": trace_id,
"process_id": process_id,
"submitted_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
})
else:
return jsonify({
"success": False,
"message": "提交失败"
}), 500
@app.route('/api/work-orders/release', methods=['POST'])
def release_work_order():
"""
释放工单取消认领
参数: trace_id, process_id
"""
data = request.get_json()
trace_id = data.get('trace_id')
process_id = data.get('process_id')
if not trace_id or not process_id:
return jsonify({
"success": False,
"message": "追溯号和工序号不能为空"
}), 400
if db.release_work_order(trace_id, process_id):
return jsonify({
"success": True,
"message": "释放成功"
})
else:
return jsonify({
"success": False,
"message": "该工单未被认领"
}), 400
@app.route('/api/work-orders/create', methods=['POST'])
def create_work_order():
"""
创建工单
参数: trace_id, process_id, process_name, product_name, station, operator, bolts
返回: 创建结果
"""
data = request.get_json()
# 验证必填字段
required_fields = ['trace_id', 'process_id', 'bolts']
for field in required_fields:
if not data.get(field):
return jsonify({
"success": False,
"message": f"字段 {field} 不能为空"
}), 400
# 构建工单数据
order_data = {
"trace_id": data.get('trace_id'),
"process_id": data.get('process_id'),
"process_name": data.get('process_name', ''),
"product_name": data.get('product_name', ''),
"operator": data.get('operator', ''),
"status": data.get('status', 'pending'),
"bolts": data.get('bolts', [])
}
# 创建工单
if db.create_work_order(order_data):
return jsonify({
"success": True,
"message": "工单创建成功",
"data": {
"trace_id": order_data['trace_id'],
"process_id": order_data['process_id']
}
})
else:
return jsonify({
"success": False,
"message": "工单创建失败"
}), 500
@app.route('/api/wrench-devices', methods=['GET'])
def get_wrench_devices():
"""获取所有扳手设备列表"""
try:
devices = db.get_wrench_devices()
return jsonify({
"success": True,
"message": "查询成功",
"data": devices
})
except Exception as e:
return jsonify({
"success": False,
"message": f"查询失败: {str(e)}",
"data": []
}), 500
@app.route('/api/wrench-devices', methods=['POST'])
def create_wrench_device():
"""创建扳手设备"""
data = request.get_json()
required_fields = ['device_name', 'ip_address']
for field in required_fields:
if not data.get(field):
return jsonify({
"success": False,
"message": f"字段 {field} 不能为空"
}), 400
if db.create_wrench_device(data):
return jsonify({
"success": True,
"message": "设备创建成功"
})
else:
return jsonify({
"success": False,
"message": "设备创建失败"
}), 500
@app.route('/api/wrench-devices/<int:device_id>', methods=['PUT'])
def update_wrench_device(device_id):
"""更新扳手设备"""
data = request.get_json()
if db.update_wrench_device(device_id, data):
return jsonify({
"success": True,
"message": "设备更新成功"
})
else:
return jsonify({
"success": False,
"message": "设备更新失败"
}), 500
@app.route('/api/wrench-devices/<int:device_id>', methods=['DELETE'])
def delete_wrench_device(device_id):
"""删除扳手设备"""
if db.delete_wrench_device(device_id):
return jsonify({
"success": True,
"message": "设备删除成功"
})
else:
return jsonify({
"success": False,
"message": "设备删除失败"
}), 500
@app.route('/api/wrench-devices/<int:device_id>/status', methods=['POST'])
def update_device_status(device_id):
"""更新设备状态(用于心跳检测)"""
data = request.get_json()
status = data.get('status', 'offline')
if db.update_wrench_device_status(device_id, status):
return jsonify({
"success": True,
"message": "状态更新成功"
})
else:
return jsonify({
"success": False,
"message": "状态更新失败"
}), 500
@app.route('/api/wrench-devices/<int:device_id>/check-status', methods=['POST'])
def check_device_status(device_id):
"""检测设备在线状态"""
device = db.get_wrench_device(device_id)
if not device:
return jsonify({
"success": False,
"message": "设备不存在"
}), 404
try:
device_config = {
"ip_address": device.get('ip_address'),
"port": device.get('port', 7888),
"address_code": device.get('address_code', 1)
}
# 尝试连接设备
wrench = WrenchController(device_config=device_config)
is_online = wrench.connect()
if is_online:
wrench.disconnect()
# 更新设备状态为在线
db.update_wrench_device_status(device_id, 'online')
return jsonify({
"success": True,
"message": "设备在线",
"data": {
"status": "online"
}
})
else:
# 更新设备状态为离线
db.update_wrench_device_status(device_id, 'offline')
return jsonify({
"success": True,
"message": "设备离线",
"data": {
"status": "offline"
}
})
except Exception as e:
# 连接失败,更新为离线
db.update_wrench_device_status(device_id, 'offline')
return jsonify({
"success": False,
"message": f"检测失败: {str(e)}",
"data": {
"status": "offline"
}
})
@app.route('/api/wrench-devices/<int:device_id>/query-sn', methods=['POST'])
def query_device_sn(device_id):
"""查询设备SN码"""
device = db.get_wrench_device(device_id)
if not device:
return jsonify({
"success": False,
"message": "设备不存在"
}), 404
try:
device_config = {
"ip_address": device.get('ip_address'),
"port": device.get('port', 7888),
"address_code": device.get('address_code', 1)
}
wrench = WrenchController(device_config=device_config)
if wrench.connect():
sn = wrench.query_device_sn()
wrench.disconnect()
if sn:
# 更新设备SN码
db.update_wrench_device_sn(device_id, sn)
# 同时更新状态为在线
db.update_wrench_device_status(device_id, 'online')
return jsonify({
"success": True,
"message": "查询成功",
"data": {
"device_sn": sn,
"status": "online"
}
})
else:
return jsonify({
"success": False,
"message": "查询SN码失败"
}), 500
else:
db.update_wrench_device_status(device_id, 'offline')
return jsonify({
"success": False,
"message": "无法连接到设备"
}), 500
except Exception as e:
db.update_wrench_device_status(device_id, 'offline')
return jsonify({
"success": False,
"message": f"查询失败: {str(e)}"
}), 500
@app.route('/api/work-results', methods=['GET'])
def get_work_results():
"""
查询工单执行结果
参数: trace_id (追溯号), process_id (工序号)
如果两个参数都提供返回指定工单的结果
如果只提供一个参数返回符合该条件的所有结果
如果都不提供返回所有结果
"""
trace_id = request.args.get('trace_id')
process_id = request.args.get('process_id')
try:
if trace_id and process_id:
# 查询指定追溯号和工序号的结果(返回单个结果)
result = db.get_work_result(trace_id, process_id)
if result:
return jsonify({
"success": True,
"message": "查询成功",
"data": result
})
else:
return jsonify({
"success": False,
"message": "未找到执行结果",
"data": None
}), 404
else:
# 查询结果列表
results = db.get_work_results(trace_id, process_id)
return jsonify({
"success": True,
"message": "查询成功",
"data": results,
"count": len(results)
})
except Exception as e:
print(f"[ERROR] 查询执行结果异常: {e}")
import traceback
traceback.print_exc()
return jsonify({
"success": False,
"message": f"查询失败: {str(e)}",
"data": []
}), 500
@app.route('/api/health', methods=['GET'])
def health_check():
"""健康检查"""
return jsonify({
"success": True,
"message": "服务运行正常",
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
})
if __name__ == '__main__':
# 检查数据库是否为空如果为空则从JSON导入数据
orders = db.get_work_orders()
if not orders and os.path.exists("work_orders.json"):
print("检测到数据库为空正在从JSON文件导入数据...")
try:
with open("work_orders.json", 'r', encoding='utf-8') as f:
json_orders = json.load(f)
count = 0
for order in json_orders:
if db.create_work_order(order):
count += 1
print(f"[OK] 成功导入 {count}/{len(json_orders)} 个工单")
except Exception as e:
print(f"[FAIL] 导入失败: {e}")
import traceback
traceback.print_exc()
print("="*60)
print("电动扳手后端API服务器")
print("="*60)
print("启动服务器...")
print("API地址: http://localhost:5000")
print("数据库: wrench.db")
# 显示当前工单数量
total_orders = len(db.get_work_orders())
print(f"当前工单数量: {total_orders}")
print("="*60)
app.run(host='0.0.0.0', port=5000, debug=True)