Lunatic API 19 个命令:分类、流程、细节
系列指南 · 第 4 篇
Lunatic API 19 个命令:分类、流程、细节
Lunatic & Stunner Client 软件里配置完成之后,仪器就准备好被外部脚本调用了。这里说的"脚本",是工作站或调度系统上的一段小程序,常用 C#、Python 或 LabVIEW 写。它加载 DropQuant_Remote.dll 这个文件,把 19 个 API 命令一条一条发给 Lunatic。除构造函数 DropQuant() 之外,其余 18 条命令都以 DQ_ 开头(取自 DropQuant)。整套 API 按职责分成四组,其中只有 DQ_Measure 是异步命令,脚本要靠轮询判断测量何时结束。
先认识几个名词
- 同步 / 异步 — 同步命令要等仪器把动作做完才返回;异步命令启动动作后立即返回,脚本再自己查进度。19 个命令里只有 DQ_Measure 一个是异步。
- 独占访问权 — 同一时刻只能有一个脚本控制 Lunatic。脚本先用 DQ_Request_Access 申请访问权,用完再用 DQ_Release_Access 释放,别的脚本才能接手。
- 轮询(polling) — 脚本周期性地问仪器"测完了吗?",直到拿到肯定答复才往下走。DQ_Measure 异步启动测量后,就靠轮询 DQ_Get_Status 判断何时完成。
- 状态码(return code) — 每个命令调用之后,返回一个整数告诉脚本结果。Lunatic 的约定:0 是成功,正数是状态或补充信息(不是错),负数是错误,不同负数对应不同错因。
- DropQuant_Remote.dll — Lunatic API 的 Windows 动态链接库。客户脚本加载这个 DLL,就能调用 19 个 API 命令。对象类型叫 DropQuant。
- timeout(超时) — 脚本等命令返回的最长时间。超过这个时间还没返回就放弃等、报错,避免脚本永远挂在那。Lunatic 的开/关托盘要等几秒机械动作,超时配毫秒级会误报。
- plate_ID — 每块 Lunatic Plate 的标识字符串。DQ_Define_Experiment 时一次传入完整的样品定义,返回一份 plate_ID 数组(多板时就有多个);后面 DQ_Measure(plate_id) 按这个 ID 挨块测。
19 个命令分四类
按命令在测量流程中的角色,可以分成四组。
- 会话控制 — 3 条 — DropQuant() · DQ_Request_Access · DQ_Release_Access — 每个脚本开头都要走前两条建立连接、申请访问权;结尾走第三条释放访问权。
- 仪器信息 — 3 条 — DQ_Get_Instrument_Serial_Number · DQ_Get_Software_Version · DQ_Get_Status — 前两条用来开机自检,确认连的是预期那台仪器;DQ_Get_Status 全程都在用,是脚本和仪器之间唯一的状态同步手段。
- 测量动作 — 7 条 — DQ_Open_Tray · DQ_Close_Tray · DQ_Read_Bar_Code · DQ_Define_Experiment · DQ_Measure · DQ_Abort_Measurement · DQ_Get_Results — 一次测量的主干就按这组走:DQ_Define_Experiment → DQ_Open_Tray / DQ_Close_Tray → DQ_Measure → 轮询 DQ_Get_Status → DQ_Get_Results。
- 辅助命令 — 6 条 — DQ_Pause · DQ_Do_Continue · DQ_Reset · DQ_Store_Blanks · DQ_Get_Stored_Blanks · DQ_GetLastInternalError — 日常测量用不到,只在调试、应急和复用空白时调用。
同步与异步:两种返回行为
19 个命令里,18 个是同步的,只有 DQ_Measure 一个是异步的。两者返回的时机不同,分清这一点是写 Lunatic 脚本的第一件事。
18 条
同步命令
命令发出去后,函数会一直等,直到仪器真的把动作做完才返回。比如 DQ_Open_Tray() 返回的那一刻,托盘已经物理上打开了。脚本下一行可以放心继续往后走。
- · 顺着写就行,不用考虑等待
- · 开/关托盘要等几秒;读信息的命令几乎立刻返回
- · 超时至少留 10 秒,不要设成毫秒级
仅 1 条
异步命令:DQ_Measure
函数返回的不是"测完了",而是"测量已经成功启动"。实际测量在仪器那边继续跑,一板 96 孔,Lunatic Plate 约 5 分钟,High Lunatic Plate 约 10 分钟。
- · 函数返回 ≠ 测量完成
- · 后面必须接 DQ_Get_Status 反复问,直到仪器说"测完了"
- · 不轮询直接去取结果,这时数据还没出来,会拿到空
为什么 DQ_Measure 要做成异步:一板 96 孔要测约 5–10 分钟。如果这条命令也是同步等待,脚本会卡在这一行,中间什么命令都发不出去。改成异步之后,脚本在测量期间可以同时做别的事。例如让机械臂搬下一块板、清洗液体工作站、把上一板的结果发给 LIMS。轮询频率一般定在 1–2 秒一次:更快只是多占带宽;更慢则机械臂要在仪器旁边等,整批样品的处理时间会被拉长。
一次完整测量的命令顺序
按顺序把命令排起来,一块板从开始到结束的最小完整脚本就是下面这 13 步。左边是脚本发出的 API 命令,右边是同一时刻仪器或工作站在做的物理动作。
步 / 脚本(API 命令) / 仪器 / 工作台
这是单板的完整顺序。多板实验里,第 8 步测量完成后,用第 9–11 步开托盘、换板、关托盘,再回到第 7 步,用 DQ_Measure 测下一块。
DQ_Define_Experiment 只在第 3 步发一次,一次定义里可以包含多块板。返回的 plate_IDs 数组按顺序列出每块板的 ID,后续 DQ_Measure 挨个传入即可。DQ_Get_Results 留到所有板都测完再调。Manual 示例脚本反复调用这条命令。每次返回 −104(还有板未测完)就再试一次,直到返回 0(全部完成)为止。
Lunatic API Manual Figure 18。完整测量流程对照图。绿色块是脚本通过 API 发出的命令,白色块是 API 之外的物理动作(放板、取板)。多板时在 DQ_Get_Status 返回 32(load next plate)后回到 DQ_Open_Tray 换板。
命令一览
下面把 19 个命令按分组列出,便于写脚本时对照查阅。这里只列签名和一句话职责。每个命令完整的入参定义、返回字段说明,在 Lunatic API Manual §4.2 里都有。
每条命令可能返回的状态码,也在 §4.2.x 各小节明确列出。例如 DQ_Open_Tray 可能返回 0/3/−1/−2/−3/−52/−200,DQ_Close_Tray 可能返回 0/4/−1/−2/−52/−200。要查具体命令的可能返回码,就翻 Manual 对应节。所有状态码的完整中文速查在第 6 篇。
### 如何看签名
- string = 字符串、int = 整数、bool = 真/假、string[] = 一组字符串(数组)
- out 标记的参数是"输出参数"。状态码之外的额外信息,Lunatic 通过这个变量传回脚本
- 例:DQ_Read_Bar_Code(out string bar_code) 意思是"调用这条命令,Lunatic 会把读到的条码写进 bar_code 变量"
命令:职责
会话控制(3 条)
DropQuant(string address, int port):建立 TCP 连接对象。地址用仪器 IP;端口可配置,具体值以 Client Settings/Info 页面显示的为准(Manual 里出现过 6700、6300 两个值)。
DQ_Request_Access():申请独占访问权。别的脚本已占用或 License 没激活时会被拒。
DQ_Release_Access():释放访问权,让出仪器。脚本结束或出错前都应该走一次。
仪器信息(3 条)
DQ_Get_Instrument_Serial_Number():读仪器序列号。开机自检时用,确认连的是预期那台。
DQ_Get_Software_Version():读仪器软件版本,确认和 PC 上的应用版本对得上。
DQ_Get_Status(out string measurement_info) 或 DQ_Get_Status():查当前状态,任何时候都可以发。带 measurement_info 参数的那个版本,在测量进行中会同时返回更细的进度信息。
测量动作(7 条)
DQ_Open_Tray():打开托盘。返回时托盘已物理打开。
DQ_Close_Tray():关闭托盘。返回时托盘已物理关闭。
DQ_Read_Bar_Code(out string bar_code) 或 DQ_Read_Bar_Code(out string bar_code, out bool valid, out string plate_type):读已经放进托盘的 Lunatic Plate 上的条码。带 valid、plate_type 参数的那个版本,同时返回条码是否有效以及板型。
DQ_Define_Experiment(string experimentDefinition, string sampleDefinition, out string[] plate_IDs):把实验定义、样品定义两段字符串发给仪器;返回一份 plate_ID 数组,后面 DQ_Measure 要用。
DQ_Measure(string Plate_ID):异步:命令立刻返回,实际测量要靠 DQ_Get_Status 轮询确认。Plate_ID 传 "autodetect" 可让仪器先扫条码,再决定测哪块板。
DQ_Abort_Measurement():强行中断正在进行的测量。一般只在出错或上层调度取消时用。
DQ_Get_Results(string results_parameters, string plate_ID, out string results, out string experiment_path):取结果文本字符串,同时把 .bin 原始数据写到共享目录。plate_ID 留空就一次返回所有板的结果。
辅助命令(6 条)
DQ_Pause():暂停当前所有动作,直到收到 DQ_Do_Continue。
DQ_Do_Continue():从暂停状态恢复测量。
DQ_Reset():把仪器从错误状态恢复到正常。一般用在出错处理的最后一步。
DQ_Store_Blanks() 或 DQ_Store_Blanks(string file_name):把刚跑完的或共享目录里某一板的空白存到仪器本地。每种 plate type(Lunatic Plate / High Lunatic Plate)只能存 1 份;新存会覆盖该板型的旧空白。
DQ_Get_Stored_Blanks():列出当前仪器上存了哪些空白:Plate type、sample group 名、剩余有效天数。
DQ_GetLastInternalError():取 DLL 内部最近一次错误的详细文字描述。前一条命令返回 −200/−201/−202 时调用才有内容,其它状态码下返回空。
几处容易写错的细节
写 Lunatic 脚本时,下面 6 处最容易出错。
出错了怎么定位
API 出错时,Lunatic 不会主动弹窗或亮报警灯。仪器和脚本 PC 之间只有 TCP 这一条通信通道。所有出错信息都打包成一个整数(就是前面说的状态码),随命令返回值传回脚本。脚本拿到这个数字,自己决定下一步怎么做。定位故障主要靠下面两种手段。
1
查每条命令的整数状态码
每个命令调用之后都返回一个状态码。约定如下:
- 0 = 成功,继续执行
- 正数 = 补充信息,不是错误。例如 50 表示"已连接、托盘开着"、3 表示"托盘本来就开着"
- 负数 = 错误。例如 -1 无访问权、-2 仪器状态不对、-9 实验定义格式错、-104 还有板没测完不能取结果、-120 Automation License 没激活、-200 TCP 连不上
完整状态码表在 Lunatic API Manual Appendix 2,本系列第 6 篇也有中文速查。
2
−200 / −201 / −202 时,加一次 DQ_GetLastInternalError
状态码是 −200、−201 或 −202,说明问题出在 DropQuant_Remote.dll 内部(通常是连接、超时或参数解析问题)。这时立刻调一次 DQ_GetLastInternalError(),拿到一段更详细的文字描述。其它状态码下这个函数不会返回内容。所以只在这三个码后面调一次即可,不需要每条命令都调用。
### 建议:把状态码处理集中到一个函数里
生产脚本里,推荐写一个统一的函数处理所有返回的状态码,不在每条命令后各自写 if-else。函数里先看正负,负数再按应对动作归类:
- · 0:继续往下走
- · 正数:也继续(只是补充信息)
- · 特定负数(比如 −52 托盘正在移动):等几秒再重试
- · 其它负数:停止当前批次,并报警让上层调度知道(第 6 篇还加了一档降级,如条码读不到时改传 plate_ID)
- · 严重错误:调一次 DQ_Reset,把仪器从错误状态恢复
所有命令共用同一个处理函数。后续要调整出错策略时,只改这一处,不必到每条命令处分别改。
- big-picture · 19 个命令分四类
- sync-vs-async · 同步与异步:两种返回行为
- standard-flow · 一次完整测量的命令顺序
- reference-table · 命令一览
- 同步 / 异步 · 同步命令要等仪器把动作做完才返回;异步命令启动动作后立即返回,脚本再自己查进度。19 个命令里只有 DQ_Measure 一个是异步。
- 独占访问权 · 同一时刻只能有一个脚本控制 Lunatic。脚本先用 DQ_Request_Access 申请访问权,用完再用 DQ_Release_Access 释放,别的脚本才能接手。
- 轮询(polling) · 脚本周期性地问仪器"测完了吗?",直到拿到肯定答复才往下走。DQ_Measure 异步启动测量后,就靠轮询 DQ_Get_Status 判断何时完成。
- 状态码(return code) · 每个命令调用之后,返回一个整数告诉脚本结果。Lunatic 的约定:0 是成功,正数是状态或补充信息(不是错),负数是错误,不同负数对应不同错因。
- DropQuant_Remote.dll · Lunatic API 的 Windows 动态链接库。客户脚本加载这个 DLL,就能调用 19 个 API 命令。对象类型叫 DropQuant。
- timeout(超时) · 脚本等命令返回的最长时间。超过这个时间还没返回就放弃等、报错,避免脚本永远挂在那。Lunatic 的开/关托盘要等几秒机械动作,超时配毫秒级会误报。
- plate_ID · 每块 Lunatic Plate 的标识字符串。DQ_Define_Experiment 时一次传入完整的样品定义,返回一份 plate_ID 数组(多板时就有多个);后面 DQ_Measure(plate_id) 按这个 ID 挨块测。
- 会话控制 · 3 条 · DropQuant() · DQ_Request_Access · DQ_Release_Access · 每个脚本开头都要走前两条建立连接、申请访问权;结尾走第三条释放访问权。
- 仪器信息 · 3 条 · DQ_Get_Instrument_Serial_Number · DQ_Get_Software_Version · DQ_Get_Status · 前两条用来开机自检,确认连的是预期那台仪器;DQ_Get_Status 全程都在用,是脚本和仪器之间唯一的状态同步手段。
- 测量动作 · 7 条 · DQ_Open_Tray · DQ_Close_Tray · DQ_Read_Bar_Code · DQ_Define_Experiment · DQ_Measure · DQ_Abort_Measurement · DQ_Get_Results · 一次测量的主干就按这组走:DQ_Define_Experiment → DQ_Open_Tray / DQ_Close_Tray → DQ_Measure → 轮询 DQ_Get_Status → DQ_Get_Results。
- 辅助命令 · 6 条 · DQ_Pause · DQ_Do_Continue · DQ_Reset · DQ_Store_Blanks · DQ_Get_Stored_Blanks · DQ_GetLastInternalError · 日常测量用不到,只在调试、应急和复用空白时调用。
- 1 · 建立 TCP 连接对象(6300 是官方示例值;端口可配置,以 Client Settings 显示的为准)
- 3 · 把实验定义、样品定义两段字符串发过去,返回所有板的 plate_IDs
- 5 · — · 机械臂或人把 Lunatic Plate 放进托盘
- 8 · 每 1–2 秒查一次状态,直到测量完成
- 10 · — · 机械臂取出测完的板;多板实验在这里换上新板
- 12 · 拿回文本结果;同时 .bin 原始数据写到共享目录
- 13 · 释放访问权,让出仪器给下一个脚本
- 建立 TCP 连接对象(6300 是官方示例值;端口可配置,以 Client Settings 显示的为准)
- 把实验定义、样品定义两段字符串发过去,返回所有板的 plate_IDs
- 机械臂或人把 Lunatic Plate 放进托盘
- 机械臂取出测完的板;多板实验在这里换上新板
- 拿回文本结果;同时 .bin 原始数据写到共享目录
- 会话 · 访问权是独占的 · 同一时刻只有一个脚本能控制 Lunatic。多个脚本共用一台仪器时,排队由上层调度负责,API 这一层不会自动处理。
- 会话 · 访问权要主动释放 · 脚本崩溃前如果没走 DQ_Release_Access,下一个脚本启动时会被拒。建议把释放语句放在 try/finally 的 finally 块里,脚本中途出错时这一行也会被执行到。
- 异步 · DQ_Measure 不能直接等结果 · 它返回"成功"只代表测量已经启动,真正的结果要靠 DQ_Get_Status 反复问,直到拿到状态码 25(测量成功)。如果不轮询就直接去取结果,仪器还没测完,DQ_Get_Results 会返回 −104。
- 条码 · autodetect 依赖板上有可读条码 · Lunatic Plate 出厂自带 CODE128 条码,但若条码被贴纸遮住、表面污损或板被反向放置,自动识别会失败。这种情况下改用 DQ_Define_Experiment 返回的 plate_ID 更可靠。
- 机械 · 同步命令也会等托盘动完 · DQ_Open_Tray、DQ_Close_Tray 这两条命令返回之前要等几秒,因为托盘机械动作需要时间。脚本里这两条的超时至少留 10 秒,不要设成毫秒级。
- 结果 · DQ_Get_Results 配合 −104 重试 · 多板实验里,把 plate_ID 留空就会一次取回所有板的结果。如果还有板没测完,函数返回 −104。Manual 示例脚本是反复调用这条命令,每次返回 −104 就再试一次,直到返回 0(全部完成)为止。示例脚本每块板仍先轮询 DQ_Get_Status,拿到 32(换下一板)或 25(测完)才往下走;−104 重试只是取结果这一步的兜底。