mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2025-12-17 13:01:12 +00:00
fix bioyond resource io
This commit is contained in:
@@ -149,6 +149,22 @@ class WorkstationHTTPHandler(BaseHTTPRequestHandler):
|
|||||||
)
|
)
|
||||||
self._send_response(error_response)
|
self._send_response(error_response)
|
||||||
|
|
||||||
|
def do_OPTIONS(self):
|
||||||
|
"""处理OPTIONS请求 - CORS预检请求"""
|
||||||
|
try:
|
||||||
|
# 发送CORS响应头
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header('Access-Control-Allow-Origin', '*')
|
||||||
|
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
|
||||||
|
self.send_header('Access-Control-Allow-Headers', 'Content-Type, Authorization')
|
||||||
|
self.send_header('Access-Control-Max-Age', '86400')
|
||||||
|
self.end_headers()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"OPTIONS请求处理失败: {e}")
|
||||||
|
self.send_response(500)
|
||||||
|
self.end_headers()
|
||||||
|
|
||||||
def _handle_step_finish_report(self, request_data: Dict[str, Any]) -> HttpResponse:
|
def _handle_step_finish_report(self, request_data: Dict[str, Any]) -> HttpResponse:
|
||||||
"""处理步骤完成报送(统一LIMS协议规范)"""
|
"""处理步骤完成报送(统一LIMS协议规范)"""
|
||||||
try:
|
try:
|
||||||
@@ -206,7 +222,7 @@ class WorkstationHTTPHandler(BaseHTTPRequestHandler):
|
|||||||
|
|
||||||
# 验证data字段内容
|
# 验证data字段内容
|
||||||
data = request_data['data']
|
data = request_data['data']
|
||||||
data_required_fields = ['orderCode', 'orderName', 'sampleId', 'startTime', 'endTime', 'Status']
|
data_required_fields = ['orderCode', 'orderName', 'sampleId', 'startTime', 'endTime', 'status']
|
||||||
if data_missing_fields := [field for field in data_required_fields if field not in data]:
|
if data_missing_fields := [field for field in data_required_fields if field not in data]:
|
||||||
return HttpResponse(
|
return HttpResponse(
|
||||||
success=False,
|
success=False,
|
||||||
@@ -227,7 +243,7 @@ class WorkstationHTTPHandler(BaseHTTPRequestHandler):
|
|||||||
"0": "待生产", "2": "进样", "10": "开始",
|
"0": "待生产", "2": "进样", "10": "开始",
|
||||||
"20": "完成", "-2": "异常停止", "-3": "人工停止"
|
"20": "完成", "-2": "异常停止", "-3": "人工停止"
|
||||||
}
|
}
|
||||||
status_desc = status_names.get(str(data['Status']), f"状态{data['Status']}")
|
status_desc = status_names.get(str(data['status']), f"状态{data['status']}")
|
||||||
|
|
||||||
return HttpResponse(
|
return HttpResponse(
|
||||||
success=True,
|
success=True,
|
||||||
@@ -380,6 +396,21 @@ class WorkstationHTTPHandler(BaseHTTPRequestHandler):
|
|||||||
"""处理物料变更报送"""
|
"""处理物料变更报送"""
|
||||||
try:
|
try:
|
||||||
# 验证必需字段
|
# 验证必需字段
|
||||||
|
if 'brand' in request_data:
|
||||||
|
if request_data['brand'] == "bioyond": # 奔曜
|
||||||
|
error_msg = request_data["text"]
|
||||||
|
logger.info(f"收到奔曜错误处理报送: {error_msg}")
|
||||||
|
return HttpResponse(
|
||||||
|
success=True,
|
||||||
|
message=f"错误处理报送已收到: {error_msg}",
|
||||||
|
acknowledgment_id=f"ERROR_{int(time.time() * 1000)}_{error_msg.get('action_id', 'unknown')}",
|
||||||
|
data=None
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return HttpResponse(
|
||||||
|
success=False,
|
||||||
|
message=f"缺少厂家信息(brand字段)"
|
||||||
|
)
|
||||||
required_fields = ['workstation_id', 'timestamp', 'resource_id', 'change_type']
|
required_fields = ['workstation_id', 'timestamp', 'resource_id', 'change_type']
|
||||||
if missing_fields := [field for field in required_fields if field not in request_data]:
|
if missing_fields := [field for field in required_fields if field not in request_data]:
|
||||||
return HttpResponse(
|
return HttpResponse(
|
||||||
@@ -407,7 +438,29 @@ class WorkstationHTTPHandler(BaseHTTPRequestHandler):
|
|||||||
def _handle_error_handling_report(self, request_data: Dict[str, Any]) -> HttpResponse:
|
def _handle_error_handling_report(self, request_data: Dict[str, Any]) -> HttpResponse:
|
||||||
"""处理错误处理报送"""
|
"""处理错误处理报送"""
|
||||||
try:
|
try:
|
||||||
# 验证必需字段
|
# 检查是否为奔曜格式的错误报送
|
||||||
|
if 'brand' in request_data and str(request_data['brand']).lower() == "bioyond":
|
||||||
|
# 奔曜格式处理
|
||||||
|
if 'text' not in request_data:
|
||||||
|
return HttpResponse(
|
||||||
|
success=False,
|
||||||
|
message="奔曜格式缺少text字段"
|
||||||
|
)
|
||||||
|
|
||||||
|
error_data = request_data["text"]
|
||||||
|
logger.info(f"收到奔曜错误处理报送: {error_data}")
|
||||||
|
|
||||||
|
# 调用工作站的处理方法
|
||||||
|
result = self.workstation.handle_external_error(error_data)
|
||||||
|
|
||||||
|
return HttpResponse(
|
||||||
|
success=True,
|
||||||
|
message=f"错误处理报送已收到: 任务{error_data.get('task', 'unknown')}, 错误代码{error_data.get('code', 'unknown')}",
|
||||||
|
acknowledgment_id=f"ERROR_{int(time.time() * 1000)}_{error_data.get('task', 'unknown')}",
|
||||||
|
data=result
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# 标准格式处理
|
||||||
required_fields = ['workstation_id', 'timestamp', 'error_type', 'error_message']
|
required_fields = ['workstation_id', 'timestamp', 'error_type', 'error_message']
|
||||||
if missing_fields := [field for field in required_fields if field not in request_data]:
|
if missing_fields := [field for field in required_fields if field not in request_data]:
|
||||||
return HttpResponse(
|
return HttpResponse(
|
||||||
@@ -548,13 +601,19 @@ class WorkstationHTTPService:
|
|||||||
"""停止HTTP服务"""
|
"""停止HTTP服务"""
|
||||||
try:
|
try:
|
||||||
if self.running and self.server:
|
if self.running and self.server:
|
||||||
|
logger.info("正在停止工作站HTTP报送服务...")
|
||||||
self.running = False
|
self.running = False
|
||||||
self.server.shutdown()
|
|
||||||
self.server.server_close()
|
|
||||||
|
|
||||||
|
# 停止serve_forever循环
|
||||||
|
self.server.shutdown()
|
||||||
|
|
||||||
|
# 等待服务器线程结束
|
||||||
if self.server_thread and self.server_thread.is_alive():
|
if self.server_thread and self.server_thread.is_alive():
|
||||||
self.server_thread.join(timeout=5.0)
|
self.server_thread.join(timeout=5.0)
|
||||||
|
|
||||||
|
# 关闭服务器套接字
|
||||||
|
self.server.server_close()
|
||||||
|
|
||||||
logger.info("工作站HTTP报送服务已停止")
|
logger.info("工作站HTTP报送服务已停止")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -563,11 +622,13 @@ class WorkstationHTTPService:
|
|||||||
def _run_server(self):
|
def _run_server(self):
|
||||||
"""运行HTTP服务器"""
|
"""运行HTTP服务器"""
|
||||||
try:
|
try:
|
||||||
while self.running:
|
# 使用serve_forever()让服务持续运行
|
||||||
self.server.handle_request()
|
self.server.serve_forever()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if self.running: # 只在非正常停止时记录错误
|
if self.running: # 只在非正常停止时记录错误
|
||||||
logger.error(f"HTTP服务运行错误: {e}")
|
logger.error(f"HTTP服务运行错误: {e}")
|
||||||
|
finally:
|
||||||
|
logger.info("HTTP服务器线程已退出")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_running(self) -> bool:
|
def is_running(self) -> bool:
|
||||||
@@ -603,3 +664,49 @@ __all__ = [
|
|||||||
'MaterialChangeReport',
|
'MaterialChangeReport',
|
||||||
'TaskExecutionReport'
|
'TaskExecutionReport'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# 简单测试HTTP服务
|
||||||
|
class DummyWorkstation:
|
||||||
|
device_id = "WS-001"
|
||||||
|
|
||||||
|
def process_step_finish_report(self, report_request):
|
||||||
|
return {"processed": True}
|
||||||
|
|
||||||
|
def process_sample_finish_report(self, report_request):
|
||||||
|
return {"processed": True}
|
||||||
|
|
||||||
|
def process_order_finish_report(self, report_request, used_materials):
|
||||||
|
return {"processed": True}
|
||||||
|
|
||||||
|
def process_material_change_report(self, report_data):
|
||||||
|
return {"processed": True}
|
||||||
|
|
||||||
|
def handle_external_error(self, error_data):
|
||||||
|
return {"handled": True}
|
||||||
|
|
||||||
|
workstation = DummyWorkstation()
|
||||||
|
http_service = WorkstationHTTPService(workstation)
|
||||||
|
|
||||||
|
try:
|
||||||
|
http_service.start()
|
||||||
|
print(f"测试服务器已启动: {http_service.service_url}")
|
||||||
|
print("按 Ctrl+C 停止服务器")
|
||||||
|
print("服务将持续运行,等待接收HTTP请求...")
|
||||||
|
|
||||||
|
# 保持服务器运行 - 使用更好的等待机制
|
||||||
|
try:
|
||||||
|
while http_service.is_running:
|
||||||
|
time.sleep(1)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\n接收到停止信号...")
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\n正在停止服务器...")
|
||||||
|
http_service.stop()
|
||||||
|
print("服务器已停止")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"服务器运行错误: {e}")
|
||||||
|
http_service.stop()
|
||||||
|
|
||||||
|
|||||||
@@ -10,3 +10,15 @@ BIOYOND_PolymerReactionStation_Deck:
|
|||||||
init_param_schema: {}
|
init_param_schema: {}
|
||||||
registry_type: resource
|
registry_type: resource
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
|
BIOYOND_PolymerPreparationStation_Deck:
|
||||||
|
category:
|
||||||
|
- deck
|
||||||
|
class:
|
||||||
|
module: unilabos.resources.bioyond.decks:BIOYOND_PolymerPreparationStation_Deck
|
||||||
|
type: pylabrobot
|
||||||
|
description: BIOYOND PolymerPreparationStation Deck
|
||||||
|
handles: []
|
||||||
|
icon: '配液站.webp'
|
||||||
|
init_param_schema: {}
|
||||||
|
registry_type: resource
|
||||||
|
version: 1.0.0
|
||||||
|
|||||||
@@ -36,9 +36,18 @@ class BIOYOND_PolymerReactionStation_Deck(Deck):
|
|||||||
|
|
||||||
|
|
||||||
class BIOYOND_PolymerPreparationStation_Deck(Deck):
|
class BIOYOND_PolymerPreparationStation_Deck(Deck):
|
||||||
def __init__(self, name: str = "PolymerPreparationStation_Deck") -> None:
|
def __init__(
|
||||||
|
self,
|
||||||
|
name: str = "PolymerPreparationStation_Deck",
|
||||||
|
size_x: float = 2700.0,
|
||||||
|
size_y: float = 1080.0,
|
||||||
|
size_z: float = 1500.0,
|
||||||
|
category: str = "deck",
|
||||||
|
setup: bool = False
|
||||||
|
) -> None:
|
||||||
super().__init__(name=name, size_x=2700.0, size_y=1080.0, size_z=1500.0)
|
super().__init__(name=name, size_x=2700.0, size_y=1080.0, size_z=1500.0)
|
||||||
self.warehouses = {}
|
if setup:
|
||||||
|
self.setup()
|
||||||
|
|
||||||
def setup(self) -> None:
|
def setup(self) -> None:
|
||||||
# 添加仓库
|
# 添加仓库
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ class ItemizedCarrier(ResourcePLR):
|
|||||||
raise ValueError(f"resource {resource} has no location")
|
raise ValueError(f"resource {resource} has no location")
|
||||||
if resource is not None:
|
if resource is not None:
|
||||||
self.child_locations[spot] = resource.location
|
self.child_locations[spot] = resource.location
|
||||||
self.child_size[spot] = {"width": resource.size_x, "height": resource.size_y, "depth": resource.size_z}
|
self.child_size[spot] = {"width": resource._size_x, "height": resource._size_y, "depth": resource._size_z}
|
||||||
else:
|
else:
|
||||||
self.child_locations[spot] = Coordinate.zero()
|
self.child_locations[spot] = Coordinate.zero()
|
||||||
self.child_size[spot] = {"width": 0, "height": 0, "depth": 0}
|
self.child_size[spot] = {"width": 0, "height": 0, "depth": 0}
|
||||||
|
|||||||
Reference in New Issue
Block a user