Skip to content

Commit f47d50c

Browse files
committed
open and close actions added, not yet working
1 parent c71da65 commit f47d50c

File tree

2 files changed

+194
-0
lines changed

2 files changed

+194
-0
lines changed

src/bmg_driver.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import ctypes
2+
import pythoncom
3+
import comtypes.client
4+
5+
class BmgCom:
6+
def __init__(self, control_name=None):
7+
pythoncom.CoInitialize()
8+
self.com = comtypes.client.CreateObject("BMG_ActiveX.BMGRemoteControl")
9+
if control_name:
10+
self.open(control_name)
11+
12+
def open(self, control_name):
13+
ep = ctypes.c_char_p(control_name.encode('ascii'))
14+
res = self.com.OpenConnection(ep)
15+
if res:
16+
raise Exception(f"OpenConnection failed: {res}")
17+
18+
def version(self):
19+
version = self.com.GetVersion()
20+
return version
21+
22+
def dummy(self):
23+
self.exec('Dummy')
24+
25+
def status(self):
26+
item = ctypes.c_char_p(b"Status")
27+
status = self.com.GetInfo(item)
28+
return status.strip() if isinstance(status, str) else 'unknown'
29+
30+
def error(self):
31+
item = ctypes.c_char_p(b"Error")
32+
status = self.com.GetInfo(item)
33+
return status.strip() if isinstance(status, str) else 'unknown'
34+
35+
def init(self):
36+
self.exec('Init')
37+
38+
def plate_in(self):
39+
self.exec('PlateIn')
40+
41+
def plate_out(self):
42+
self.exec('PlateOut')
43+
44+
def run(self, protocol_name, ):
45+
self.exec('Run', "RNA", "C:\\Program Files (x86)\\BMG\\CLARIOstar\\User\\Definit", "C:\\Program Files (x86)\\BMG\\CLARIOstar\\User\\Data", 0, 1, 2, "C:\\Program Files (x86)\\BMG\\CLARIOstar\\User\\Data", "test2.txt")
46+
47+
def isBusy(self):
48+
return self.status() == 'Busy'
49+
50+
def exec(self, cmd, *args):
51+
args = tuple((cmd, *args))
52+
print(args)
53+
res = self.com.ExecuteAndWait(args)
54+
if res:
55+
raise Exception(f"command {cmd} failed: {res}")
56+
57+
if __name__ == '__main__':
58+
com = BmgCom("CLARIOstar")
59+
print(f"BMG LABTECH Remote Control Version: {com.version()}")
60+
com.dummy()
61+
print(f"Status: {com.status()}")
62+
63+
# TESTING command
64+
#com.plate_out()
65+
com.plate_in()
66+
#com.exec("Run", )
67+
#com.init()
68+
# print(f"Status: {com.status()}")
69+
# print(com.run())

src/bmg_rest_node.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
"""
2+
REST-based node that interfaces with WEI and provides a simple Sleep(t) function
3+
"""
4+
5+
import time
6+
from typing import Annotated
7+
from pathlib import Path
8+
from tempfile import NamedTemporaryFile
9+
10+
from fastapi.datastructures import UploadFile
11+
from starlette.datastructures import State
12+
13+
# # from typing_extensions import Annotated
14+
from wei.modules.rest_module import RESTModule
15+
from wei.types.module_types import (
16+
LocalFileModuleActionResult,
17+
ModuleAction,
18+
ModuleActionArg,
19+
ModuleState,
20+
ModuleStatus,
21+
ValueModuleActionResult,
22+
)
23+
from wei.types.step_types import (
24+
ActionRequest,
25+
StepFileResponse,
26+
StepResponse,
27+
StepStatus,
28+
)
29+
30+
from bmg_driver import BmgCom # import the bmg driver
31+
32+
rest_module = RESTModule(
33+
name="bmg_module",
34+
verson="0.0.1",
35+
description="A REST node to control the BMG VANTAstar microplate reader",
36+
model="bmg",
37+
)
38+
rest_module.arg_parser.add_argument(
39+
"--output_path", type=str, help="data ourtput directory path for bmg data", default="C:\\Program Files (x86)\\BMG\\CLARIOstar\\User\\Data"
40+
)
41+
42+
@rest_module.startup()
43+
def bmg_startup(state: State):
44+
"""BMG startup handler"""
45+
46+
try:
47+
# Connect to the BMG
48+
state.bmg = BmgCom("CLARIOstar")
49+
50+
# TODO: Set module status
51+
# state.status = check_state(state)
52+
# print(state.status)
53+
# QUESTION: Why does state.status[ModuleStatus.READY] = True work for the pf400 but not for my bmg module
54+
# state.status = state.bmg.status()
55+
# print(state.status)
56+
# state.status[ModuleStatus.READY] = True if state.bmg.status() == "Ready" else False
57+
# print(state.status[ModuleStatus.READY])
58+
# print(state.bmg.status())
59+
60+
except Exception:
61+
print("Something went wrong")
62+
raise
63+
64+
else:
65+
print("BMG online")
66+
67+
68+
# @rest_module.state_handler()
69+
# def check_state(state: State) -> ModuleState:
70+
# """Updates the BMG state"""
71+
72+
# bmg_state = state.bmg.status()
73+
74+
# if bmg_state == "Ready":
75+
# return ModuleStatus.READY
76+
# else:
77+
# return ModuleStatus.ERROR
78+
79+
80+
# OPEN TRAY ACTION
81+
@rest_module.action(
82+
name="open", description="Open the bmg plate tray"
83+
)
84+
def open(
85+
state: State,
86+
action: ActionRequest,
87+
) -> StepResponse:
88+
"""Opens the BMG plate tray"""
89+
state.bmg.plate_out()
90+
return StepResponse.step_succeeded()
91+
92+
93+
# CLOSE TRAY ACTION
94+
@rest_module.action(
95+
name="close", description="Close the BMG plate tray"
96+
)
97+
def close(
98+
state: State,
99+
action: ActionRequest,
100+
) -> StepResponse:
101+
"""Closes the BMG plate tray"""
102+
state.bmg.plate_in()
103+
return StepResponse.step_succeeded()
104+
105+
106+
# RUN ASSAY ACTION
107+
@rest_module.action(
108+
name="run_assay", description="run an assay on the BMG VANTAstar plate reader"
109+
)
110+
def run_assay(
111+
state: State,
112+
action: ActionRequest,
113+
assay_name:
114+
) -> StepFileResponse:
115+
"""Runs an assay on the BMG plate reader"""
116+
state.bmg.run()
117+
118+
119+
rest_module.start()
120+
121+
122+
123+
124+
125+

0 commit comments

Comments
 (0)