IvoryOS dynamically inspects functions from any Python script, rendering them as draggable method cards in the browser.
The source code below is the source script used to build this demo. Three instances "pump", "balance" and "sdl" are created in this script, and can be either called in Device tab, or used to build a workflow in Design tab.
SocketIO
is currently not working.
import logging
import time
from abc import ABC
class AbstractPump:
def __init__(self, com_port: str):
self.com_port = com_port
self.logger = logging.getLogger("pump")
def dose_liquid(self, amount_in_ml: float, rate_ml_per_minute: float = 1):
"""dose liquid"""
self.logger.info(f"pretending dosing {amount_in_ml} at {rate_ml_per_minute} ml/min")
return 1
class AbstractBalance:
def __init__(self, com_port: str):
self.com_port = com_port
self._value = None
self.logger = logging.getLogger("balance")
@property
def setter_value(self):
return self._value
@setter_value.setter
def setter_value(self, value):
self._value = value
def weigh_sample(self):
self.logger.info(f"Weighing sample using {self.com_port}")
return 1
def dose_solid(self, amount_in_mg: float):
"""this function is used to dose solid"""
self.logger.info(f"Dosing {amount_in_mg} mg using {self.com_port}")
return 1
def _helper(self):
"""helper function will not be extracted and displayed over function panel"""
pass
class AbstractSDL(ABC):
def __init__(self, pump: AbstractPump, balance: AbstractBalance):
self.pump = pump
self.balance = balance
self.logger = logging.getLogger(f"logger_name")
def analyze(self):
self.logger.info("analyze")
return 1
def dose_solid(self,
amount_in_mg: float = 5,
solid_name: str = "Acetaminophen"
):
"""dose current chemical"""
self.balance.dose_solid(amount_in_mg=amount_in_mg)
self.balance.weigh_sample()
self.logger.info(f"dosing solid {amount_in_mg} mg of {solid_name}")
return 1
def dose_solvent(self,
solvent_name: str = "Methanol",
amount_in_ml: float = 5,
rate_ml_per_minute: float = 1
):
self.logger.info(f"dosing {amount_in_ml} ml of {solvent_name} solvent at {rate_ml_per_minute} ml/min")
return 1
def equilibrate(self,
temp: float,
duration: float
):
self.logger.info(f"equilibrate at {temp} for {duration}")
def simulate_error(self):
raise ValueError("some error")
def _send_command(self):
"""helper function"""
pass
# initializing hardware
balance = AbstractBalance("Fake com port 1")
pump = AbstractPump("Fake com port 2")
sdl = AbstractSDL(pump, balance)
if __name__ == "__main__":
import ivoryos
ivoryos.run(__name__)