#!/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/', 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/', 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//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//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//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)