修改物料位置与初始化位置计算方法

This commit is contained in:
q434343
2026-04-03 17:10:14 +08:00
parent 9b706236f6
commit 95f3e0b291
4 changed files with 1653 additions and 1813 deletions

View File

@@ -1369,6 +1369,10 @@ class WebSocketClient(BaseCommunicationClient):
self.message_processor = MessageProcessor(self.websocket_url, self.send_queue, self.device_manager) self.message_processor = MessageProcessor(self.websocket_url, self.send_queue, self.device_manager)
self.queue_processor = QueueProcessor(self.device_manager, self.message_processor) self.queue_processor = QueueProcessor(self.device_manager, self.message_processor)
# running状态debounce缓存: {job_id: (last_send_timestamp, last_feedback_data)}
self._job_running_last_sent: Dict[str, tuple] = {}
self._job_running_debounce_interval: float = 10.0 # 秒
# 设置相互引用 # 设置相互引用
self.message_processor.set_queue_processor(self.queue_processor) self.message_processor.set_queue_processor(self.queue_processor)
self.message_processor.set_websocket_client(self) self.message_processor.set_websocket_client(self)
@@ -1468,22 +1472,32 @@ class WebSocketClient(BaseCommunicationClient):
logger.debug(f"[WebSocketClient] Not connected, cannot publish job status for job_id: {item.job_id}") logger.debug(f"[WebSocketClient] Not connected, cannot publish job status for job_id: {item.job_id}")
return return
job_log = format_job_log(item.job_id, item.task_id, item.device_id, item.action_name)
# 拦截最终结果状态,与原版本逻辑一致 # 拦截最终结果状态,与原版本逻辑一致
if status in ["success", "failed"]: if status in ["success", "failed"]:
self._job_running_last_sent.pop(item.job_id, None)
host_node = HostNode.get_instance(0) host_node = HostNode.get_instance(0)
if host_node: if host_node:
# 从HostNode的device_action_status中移除job_id
try: try:
host_node._device_action_status[item.device_action_key].job_ids.pop(item.job_id, None) host_node._device_action_status[item.device_action_key].job_ids.pop(item.job_id, None)
except (KeyError, AttributeError): except (KeyError, AttributeError):
logger.warning(f"[WebSocketClient] Failed to remove job {item.job_id} from HostNode status") logger.warning(f"[WebSocketClient] Failed to remove job {item.job_id} from HostNode status")
# logger.debug(f"[WebSocketClient] Intercepting final status for job_id: {item.job_id} - {status}")
# 通知队列处理器job完成包括timeout的job
self.queue_processor.handle_job_completed(item.job_id, status) self.queue_processor.handle_job_completed(item.job_id, status)
# 发送job状态消息 # running状态按job_id做debounce内容变化时仍然上报
if status == "running":
now = time.time()
cached = self._job_running_last_sent.get(item.job_id)
if cached is not None:
last_ts, last_data = cached
if now - last_ts < self._job_running_debounce_interval and last_data == feedback_data:
logger.trace(f"[WebSocketClient] Job status debounced (skip): {job_log} - {status}")
return
self._job_running_last_sent[item.job_id] = (now, feedback_data)
message = { message = {
"action": "job_status", "action": "job_status",
"data": { "data": {
@@ -1499,7 +1513,6 @@ class WebSocketClient(BaseCommunicationClient):
} }
self.message_processor.send_message(message) self.message_processor.send_message(message)
job_log = format_job_log(item.job_id, item.task_id, item.device_id, item.action_name)
logger.trace(f"[WebSocketClient] Job status published: {job_log} - {status}") logger.trace(f"[WebSocketClient] Job status published: {job_log} - {status}")
def send_ping(self, ping_id: str, timestamp: float) -> None: def send_ping(self, ping_id: str, timestamp: float) -> None:

View File

@@ -797,10 +797,9 @@ class PRCXI9300Handler(LiquidHandlerAbstract):
self.x_offset = x_offset self.x_offset = x_offset
self.y_offset = y_offset self.y_offset = y_offset
self.xy_coupling = xy_coupling self.xy_coupling = xy_coupling
self.left_2_claw = Coordinate(-130.2, 34, -134) self.left_2_claw = Coordinate(-130.2, 34, -74)
self.right_2_left = Coordinate(22,-1, 11) self.right_2_left = Coordinate(22,-1, 11)
plate_positions = [] self.tip_height = 0
tablets_info = [] tablets_info = []
if is_9320 is None: if is_9320 is None:
@@ -989,12 +988,14 @@ class PRCXI9300Handler(LiquidHandlerAbstract):
def plr_pos_to_prcxi(self, resource: Resource, offset: Coordinate = Coordinate(0, 0, 0)): def plr_pos_to_prcxi(self, resource: Resource, offset: Coordinate = Coordinate(0, 0, 0)):
z_pos = 'c' z_pos = 'c'
if isinstance(resource, Tip): tip_height = self.tip_height
z_pos = 'b' if isinstance(resource, TipSpot):
z_pos = 't'
tip_height = 0
resource_pos = resource.get_absolute_location(x="c",y="c",z=z_pos) resource_pos = resource.get_absolute_location(x="c",y="c",z=z_pos)
x = resource_pos.x x = resource_pos.x
y = resource_pos.y y = resource_pos.y
z = resource_pos.z z = resource_pos.z + tip_height
# 如果z等于0则递归resource.parent的高度并向z加使用get_size_z方法 # 如果z等于0则递归resource.parent的高度并向z加使用get_size_z方法
parent = resource.parent parent = resource.parent
@@ -1157,6 +1158,49 @@ class PRCXI9300Handler(LiquidHandlerAbstract):
_dis_list = dis_vols if isinstance(dis_vols, list) else [dis_vols] _dis_list = dis_vols if isinstance(dis_vols, list) else [dis_vols]
if all(v <= 10.0 for v in _asp_list) and all(v <= 10.0 for v in _dis_list): if all(v <= 10.0 for v in _asp_list) and all(v <= 10.0 for v in _dis_list):
use_channels = [1] use_channels = [1]
mix_vol = max(min(mix_vol,10),0)
sources = await self._resolve_to_plr_resources(sources)
targets = await self._resolve_to_plr_resources(targets)
tip_racks = list(await self._resolve_to_plr_resources(tip_racks))
change_slots = []
change_slots.append(sources[0].parent)
change_slots.append(targets[0].parent)
if isinstance(tip_racks[0], TipRack):
tip_rack = tip_racks[0]
else:
tip_rack = tip_racks[0].parent
change_slots.append(tip_rack)
self.tip_height = tip_rack.children[0].get_size_z()
change_slots_positions = []
for slot in change_slots:
number = self._get_slot_number(slot)
pip_pos = self.plr_pos_to_prcxi(slot.children[0], self.left_2_claw)
half_x = slot.children[0].get_size_x() / 2 * abs(1 + self.x_increase)
z_wall = slot.children[0].get_size_z()
change_slots_positions.append({
"Number": number,
"XPos": pip_pos.x,
"YPos": pip_pos.y,
"ZPos": pip_pos.z,
"X_Left": half_x,
"X_Right": half_x,
"ZAgainstTheWall": pip_pos.z - z_wall,
"X2Pos": pip_pos.x + self.right_2_left.x,
"Y2Pos": pip_pos.y + self.right_2_left.y,
"Z2Pos": pip_pos.z + self.right_2_left.z,
"X2_Left": half_x,
"X2_Right": half_x,
"ZAgainstTheWall2": pip_pos.z - z_wall,
})
if change_slots_positions:
self._unilabos_backend.api_client.update_pipetting_position(self._unilabos_backend.matrix_id, change_slots_positions)
res = await super().transfer_liquid( res = await super().transfer_liquid(
sources, sources,
@@ -1708,6 +1752,7 @@ class PRCXI9300Backend(LiquidHandlerBackend):
assert mix_time > 0 assert mix_time > 0
step = self.api_client.Blending( step = self.api_client.Blending(
axis=axis,
dosage=mix_vol, dosage=mix_vol,
plate_no=PlateNo, plate_no=PlateNo,
is_whole_plate=False, is_whole_plate=False,

View File

@@ -418,7 +418,7 @@ def PRCXI_10ul_eTips(name: str) -> PRCXI9300TipRack:
item_dy=9.0, item_dy=9.0,
size_x=7.5, size_x=7.5,
size_y=7.5, size_y=7.5,
size_z=0.0, size_z=52.0,
make_tip=lambda: _make_tip_helper(volume=10.0, length=52.0, depth=8.2) make_tip=lambda: _make_tip_helper(volume=10.0, length=52.0, depth=8.2)
) )
) )
@@ -445,7 +445,7 @@ def PRCXI_300ul_Tips(name: str) -> PRCXI9300TipRack:
item_dy=9.0, item_dy=9.0,
size_x=7.5, size_x=7.5,
size_y=7.5, size_y=7.5,
size_z=0.0, size_z=60.0,
make_tip=lambda: _make_tip_helper(volume=300.0, length=60.0, depth=8.2) make_tip=lambda: _make_tip_helper(volume=300.0, length=60.0, depth=8.2)
) )
) )
@@ -497,7 +497,7 @@ def PRCXI_10uL_Tips(name: str) -> PRCXI9300TipRack:
item_dy=9.0, item_dy=9.0,
size_x=7.5, size_x=7.5,
size_y=7.5, size_y=7.5,
size_z=0.0, size_z=52.0,
make_tip=lambda: _make_tip_helper(volume=10.0, length=52.0, depth=8.2) make_tip=lambda: _make_tip_helper(volume=10.0, length=52.0, depth=8.2)
) )
) )
@@ -549,7 +549,7 @@ def PRCXI_200uL_Tips(name: str) -> PRCXI9300TipRack:
item_dy=9.0, item_dy=9.0,
size_x=7.0, size_x=7.0,
size_y=7.0, size_y=7.0,
size_z=0.0, size_z=60.0,
make_tip=lambda: _make_tip_helper(volume=300.0, length=60.0, depth=51.0) make_tip=lambda: _make_tip_helper(volume=300.0, length=60.0, depth=51.0)
) )
) )
@@ -575,7 +575,7 @@ def PRCXI_50uL_tips(name: str) -> PRCXI9300TipRack:
item_dy=9.0, item_dy=9.0,
size_x=7.5, size_x=7.5,
size_y=7.5, size_y=7.5,
size_z=0.0, size_z=53.0,
make_tip=lambda: _make_tip_helper(volume=50.0, length=53.0, depth=8.2) make_tip=lambda: _make_tip_helper(volume=50.0, length=53.0, depth=8.2)
) )
) )

File diff suppressed because it is too large Load Diff