mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2025-12-18 05:21:19 +00:00
feat(workstation): 添加温度/粘度报送处理功能
- 在反应站设备配置中添加温度/粘度相关状态类型 - 实现温度/粘度报送处理逻辑并添加ROS消息发布 - 扩展HTTP服务支持温度/粘度报送端点 - 添加HTTP请求日志记录功能
This commit is contained in:
@@ -2,7 +2,10 @@ import json
|
||||
import time
|
||||
import requests
|
||||
from typing import List, Dict, Any
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from unilabos.devices.workstation.bioyond_studio.station import BioyondWorkstation
|
||||
from unilabos.ros.msgs.message_converter import convert_to_ros_msg, Float64, String
|
||||
from unilabos.devices.workstation.bioyond_studio.config import (
|
||||
WORKFLOW_STEP_IDS,
|
||||
WORKFLOW_TO_SECTION_MAP,
|
||||
@@ -38,6 +41,17 @@ class BioyondReactionStation(BioyondWorkstation):
|
||||
print(f"BioyondReactionStation初始化完成 - workflow_mappings: {self.workflow_mappings}")
|
||||
print(f"workflow_mappings长度: {len(self.workflow_mappings)}")
|
||||
|
||||
self.in_temperature = 0.0
|
||||
self.out_temperature = 0.0
|
||||
self.pt100_temperature = 0.0
|
||||
self.sensor_average_temperature = 0.0
|
||||
self.target_temperature = 0.0
|
||||
self.setting_temperature = 0.0
|
||||
self.viscosity = 0.0
|
||||
self.average_viscosity = 0.0
|
||||
self.speed = 0.0
|
||||
self.force = 0.0
|
||||
|
||||
# ==================== 工作流方法 ====================
|
||||
|
||||
def reactor_taken_out(self):
|
||||
@@ -514,6 +528,94 @@ class BioyondReactionStation(BioyondWorkstation):
|
||||
print(f"[DEBUG] 返回结果: {result}")
|
||||
return result
|
||||
|
||||
def process_temperature_cutoff_report(self, report_request) -> Dict[str, Any]:
|
||||
try:
|
||||
data = report_request.data
|
||||
def _f(v):
|
||||
try:
|
||||
return float(v)
|
||||
except Exception:
|
||||
return 0.0
|
||||
self.target_temperature = _f(data.get("targetTemperature"))
|
||||
self.setting_temperature = _f(data.get("settingTemperature"))
|
||||
self.in_temperature = _f(data.get("inTemperature"))
|
||||
self.out_temperature = _f(data.get("outTemperature"))
|
||||
self.pt100_temperature = _f(data.get("pt100Temperature"))
|
||||
self.sensor_average_temperature = _f(data.get("sensorAverageTemperature"))
|
||||
self.speed = _f(data.get("speed"))
|
||||
self.force = _f(data.get("force"))
|
||||
self.viscosity = _f(data.get("viscosity"))
|
||||
self.average_viscosity = _f(data.get("averageViscosity"))
|
||||
|
||||
try:
|
||||
if hasattr(self, "_ros_node") and self._ros_node is not None:
|
||||
props = [
|
||||
"in_temperature","out_temperature","pt100_temperature","sensor_average_temperature",
|
||||
"target_temperature","setting_temperature","viscosity","average_viscosity",
|
||||
"speed","force"
|
||||
]
|
||||
for name in props:
|
||||
pub = self._ros_node._property_publishers.get(name)
|
||||
if pub:
|
||||
pub.publish_property()
|
||||
except Exception:
|
||||
pass
|
||||
event = {
|
||||
"frameCode": data.get("frameCode"),
|
||||
"generateTime": data.get("generateTime"),
|
||||
"targetTemperature": data.get("targetTemperature"),
|
||||
"settingTemperature": data.get("settingTemperature"),
|
||||
"inTemperature": data.get("inTemperature"),
|
||||
"outTemperature": data.get("outTemperature"),
|
||||
"pt100Temperature": data.get("pt100Temperature"),
|
||||
"sensorAverageTemperature": data.get("sensorAverageTemperature"),
|
||||
"speed": data.get("speed"),
|
||||
"force": data.get("force"),
|
||||
"viscosity": data.get("viscosity"),
|
||||
"averageViscosity": data.get("averageViscosity"),
|
||||
"request_time": report_request.request_time,
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
}
|
||||
|
||||
base_dir = Path(__file__).resolve().parents[3] / "unilabos_data"
|
||||
base_dir.mkdir(parents=True, exist_ok=True)
|
||||
out_file = base_dir / "temperature_cutoff_events.json"
|
||||
try:
|
||||
existing = json.loads(out_file.read_text(encoding="utf-8")) if out_file.exists() else []
|
||||
if not isinstance(existing, list):
|
||||
existing = []
|
||||
except Exception:
|
||||
existing = []
|
||||
existing.append(event)
|
||||
out_file.write_text(json.dumps(existing, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
|
||||
if hasattr(self, "_ros_node") and self._ros_node is not None:
|
||||
ns = self._ros_node.namespace
|
||||
topics = {
|
||||
"targetTemperature": f"{ns}/metrics/temperature_cutoff/target_temperature",
|
||||
"settingTemperature": f"{ns}/metrics/temperature_cutoff/setting_temperature",
|
||||
"inTemperature": f"{ns}/metrics/temperature_cutoff/in_temperature",
|
||||
"outTemperature": f"{ns}/metrics/temperature_cutoff/out_temperature",
|
||||
"pt100Temperature": f"{ns}/metrics/temperature_cutoff/pt100_temperature",
|
||||
"sensorAverageTemperature": f"{ns}/metrics/temperature_cutoff/sensor_average_temperature",
|
||||
"speed": f"{ns}/metrics/temperature_cutoff/speed",
|
||||
"force": f"{ns}/metrics/temperature_cutoff/force",
|
||||
"viscosity": f"{ns}/metrics/temperature_cutoff/viscosity",
|
||||
"averageViscosity": f"{ns}/metrics/temperature_cutoff/average_viscosity",
|
||||
}
|
||||
for k, t in topics.items():
|
||||
v = data.get(k)
|
||||
if v is not None:
|
||||
pub = self._ros_node.create_publisher(Float64, t, 10)
|
||||
pub.publish(convert_to_ros_msg(Float64, float(v)))
|
||||
|
||||
evt_pub = self._ros_node.create_publisher(String, f"{ns}/events/temperature_cutoff", 10)
|
||||
evt_pub.publish(convert_to_ros_msg(String, json.dumps(event, ensure_ascii=False)))
|
||||
|
||||
return {"processed": True, "frame": data.get("frameCode")}
|
||||
except Exception as e:
|
||||
return {"processed": False, "error": str(e)}
|
||||
|
||||
def wait_for_multiple_orders_and_get_reports(self, batch_create_result: str = None, timeout: int = 7200, check_interval: int = 10) -> Dict[str, Any]:
|
||||
try:
|
||||
timeout = int(timeout) if timeout else 7200
|
||||
|
||||
@@ -9,6 +9,7 @@ import traceback
|
||||
from datetime import datetime
|
||||
from typing import Dict, Any, List, Optional, Union
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from unilabos.devices.workstation.workstation_base import WorkstationBase, ResourceSynchronizer
|
||||
from unilabos.devices.workstation.bioyond_studio.bioyond_rpc import BioyondV1RPC
|
||||
@@ -19,6 +20,7 @@ from unilabos.resources.graphio import resource_bioyond_to_plr, resource_plr_to_
|
||||
|
||||
from unilabos.ros.nodes.base_device_node import ROS2DeviceNode, BaseROS2DeviceNode
|
||||
from unilabos.ros.nodes.presets.workstation import ROS2WorkstationNode
|
||||
from unilabos.ros.msgs.message_converter import convert_to_ros_msg, Float64, String
|
||||
from pylabrobot.resources.resource import Resource as ResourcePLR
|
||||
|
||||
from unilabos.devices.workstation.bioyond_studio.config import (
|
||||
@@ -676,13 +678,13 @@ class BioyondWorkstation(WorkstationBase):
|
||||
self._synced_resources = []
|
||||
|
||||
def transfer_resource_to_another(self, resource: List[ResourceSlot], mount_resource: List[ResourceSlot], sites: List[str], mount_device_id: DeviceSlot):
|
||||
time.sleep(3)
|
||||
ROS2DeviceNode.run_async_func(self._ros_node.transfer_resource_to_another, True, **{
|
||||
future = ROS2DeviceNode.run_async_func(self._ros_node.transfer_resource_to_another, True, **{
|
||||
"plr_resources": resource,
|
||||
"target_device_id": mount_device_id,
|
||||
"target_resources": mount_resource,
|
||||
"sites": sites,
|
||||
})
|
||||
return future
|
||||
|
||||
def _create_communication_module(self, config: Optional[Dict[str, Any]] = None) -> None:
|
||||
"""创建Bioyond通信模块"""
|
||||
@@ -1327,6 +1329,7 @@ class BioyondWorkstation(WorkstationBase):
|
||||
logger.error(f"处理物料变更报送失败: {e}")
|
||||
return {"processed": False, "error": str(e)}
|
||||
|
||||
|
||||
def handle_external_error(self, error_data: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""处理错误处理报送
|
||||
|
||||
|
||||
Reference in New Issue
Block a user