Esempio n. 1
0
 def connect(self):
     '''
     Connect to the serial port
     '''
     if self._port:
         self._driver = MagDeckDriver()
         self._driver.connect(self._port)
         self._device_info = self._driver.get_device_info()
     else:
         # Sanity check: Should never happen, because connect should
         # never be called without a port on Module
         raise MissingDevicePortError(
             "MagDeck couldnt connect to port {}".format(self._port))
Esempio n. 2
0
class MagDeck(commands.CommandPublisher):
    '''
    Under development. API subject to change
    '''
    def __init__(self, lw=None, port=None, broker=None):
        super().__init__(broker)
        self.labware = lw
        self._port = port
        self._engaged = False
        self._driver = None
        self._device_info = None

    @commands.publish.both(command=commands.magdeck_calibrate)
    def calibrate(self):
        '''
        Calibration involves probing for top plate to get the plate height
        '''
        if self._driver and self._driver.is_connected():
            self._driver.probe_plate()
            # return if successful or not?
            self._engaged = False

    @commands.publish.both(command=commands.magdeck_engage)
    def engage(self, **kwargs):
        '''
        Move the magnet to either:
            the default height for the labware loaded on magdeck
            [engage()]
        or  a +/- 'offset' from the default height for the labware
            [engage(offset=2)]
        or  a 'height' value specified as mm from magdeck home position
            [engage(height=20)]
        '''
        if 'height' in kwargs:
            height = kwargs.get('height')
        else:
            try:
                height = self.labware.get_children_list()[1].\
                    magdeck_engage_height()
            except KeyError:
                height = LABWARE_ENGAGE_HEIGHT.get(
                    self.labware.get_children_list()[1].get_name())
            if not height:
                raise ValueError(
                    'No engage height definition found for {}. Provide a'
                    'custom height instead'.format(
                        self.labware.get_children_list()[1].get_name()))
            if 'offset' in kwargs:
                height += kwargs.get('offset')
        if height > MAX_ENGAGE_HEIGHT or height < 0:
            raise ValueError('Invalid engage height. Should be 0 to {}'.format(
                MAX_ENGAGE_HEIGHT))
        if self._driver and self._driver.is_connected():
            self._driver.move(height)
            self._engaged = True

    @commands.publish.both(command=commands.magdeck_disengage)
    def disengage(self):
        '''
        Home the magnet
        '''
        if self._driver and self._driver.is_connected():
            self._driver.home()
            self._engaged = False

    @classmethod
    def name(cls):
        return 'magdeck'

    @classmethod
    def display_name(cls):
        return 'Magnetic Deck'

    # TODO: there should be a separate decoupled set of classes that
    # construct the http api response entity given the model instance.
    def to_dict(self):
        return {
            'name': self.name(),
            'port': self.port,
            'serial': self.device_info and self.device_info.get('serial'),
            'model': self.device_info and self.device_info.get('model'),
            'fwVersion': self.device_info and self.device_info.get('version'),
            'displayName': self.display_name(),
            **self.live_data
        }

    @property
    def live_data(self):
        return {'status': self.status, 'data': {'engaged': self._engaged}}

    @property
    def port(self):
        """ Serial Port """
        return self._port

    @property
    def device_info(self):
        """
        Returns a dict:
            { 'serial': 'abc123', 'model': '8675309', 'version': '9001' }
        """
        return self._device_info

    @property
    def status(self):
        return 'engaged' if self._engaged else 'disengaged'

    # Internal Methods

    def connect(self):
        '''
        Connect to the serial port
        '''
        if self._port:
            self._driver = MagDeckDriver()
            self._driver.connect(self._port)
            self._device_info = self._driver.get_device_info()
        else:
            # Sanity check: Should never happen, because connect should
            # never be called without a port on Module
            raise MissingDevicePortError(
                "MagDeck couldnt connect to port {}".format(self._port))

    def disconnect(self):
        '''
        Disconnect from the serial port
        '''
        if self._driver:
            self._driver.disconnect()
Esempio n. 3
0
class MagDeck:
    '''
    Under development. API subject to change
    '''
    def __init__(self, lw=None, port=None):
        self.labware = lw
        self._port = port
        self._engaged = False
        self._driver = None
        self._device_info = None

    @commands.publish.both(command=commands.magdeck_calibrate)
    def calibrate(self):
        '''
        Calibration involves probing for top plate to get the plate height
        '''
        if self._driver and self._driver.is_connected():
            self._driver.probe_plate()
            # return if successful or not?
            self._engaged = False

    @commands.publish.both(command=commands.magdeck_engage)
    def engage(self):
        '''
        Move the magnet to plate top - 1 mm
        '''
        if self._driver and self._driver.is_connected():
            self._driver.move(self._driver.plate_height - 1.0)
            self._engaged = True

    @commands.publish.both(command=commands.magdeck_disengage)
    def disengage(self):
        '''
        Home the magnet
        '''
        if self._driver and self._driver.is_connected():
            self._driver.home()
            self._engaged = False

    # TODO: there should be a separate decoupled set of classes that
    # construct the http api response entity given the model instance.
    def to_dict(self):
        return {
            'name': 'magdeck',
            'port': self.port,
            'serial': self.device_info and self.device_info.get('serial'),
            'model': self.device_info and self.device_info.get('model'),
            'fwVersion': self.device_info and self.device_info.get('version'),
            'displayName': 'Magnetic Deck',
            'status': self.status,
            'data': {
                'engaged': self._engaged
            }
        }

    @property
    def port(self):
        """ Serial Port """
        return self._port

    @property
    def device_info(self):
        """
        Returns a dict:
            { 'serial': 'abc123', 'model': '8675309', 'version': '9001' }
        """
        return self._device_info

    @property
    def status(self):
        return 'engaged' if self._engaged else 'disengaged'

    # Internal Methods

    def connect(self):
        '''
        Connect to the serial port
        '''
        if self._port:
            self._driver = MagDeckDriver()
            self._driver.connect(self._port)
            self._device_info = self._driver.get_device_info()
        else:
            # Sanity check: Should never happen, because connect should
            # never be called without a port on Module
            raise MissingDevicePortError(
                "MagDeck couldnt connect to port {}".format(self._port))

    def disconnect(self):
        '''
        Disconnect from the serial port
        '''
        if self._driver:
            self._driver.disconnect()