def test_get_device_info(monkeypatch): import types from opentrons.drivers.temp_deck import TempDeck temp_deck = TempDeck() temp_deck.simulating = False command_log = [] model = 'temp-v1' firmware_version = 'edge-1a2b345' serial = 'td20180102A01' def _mock_send_command(self, command, timeout=None, tag=None): nonlocal command_log command_log += [command] return 'model:' + model \ + ' version:' + firmware_version \ + ' serial:' + serial temp_deck._send_command = types.MethodType(_mock_send_command, temp_deck) res = temp_deck.get_device_info() assert res == { 'model': model, 'version': firmware_version, 'serial': serial }
class TempDeck(commands.CommandPublisher): """ Under development. API subject to change without a version bump """ def __init__(self, lw=None, port=None, broker=None): super().__init__(broker) self.labware = lw self._port = port self._driver = None self._device_info = None self._poll_stop_event = None @commands.publish.both(command=commands.tempdeck_set_temp) def set_temperature(self, celsius): """ Set temperature in degree Celsius Range: 4 to 95 degree Celsius (QA tested). The internal temp range is -9 to 99 C, which is limited by the 2-digit temperature display. Any input outside of this range will be clipped to the nearest limit """ if self._driver and self._driver.is_connected(): self._driver.legacy_set_temperature(celsius) @commands.publish.both(command=commands.tempdeck_deactivate) def deactivate(self): """ Stop heating/cooling and turn off the fan """ if self._driver and self._driver.is_connected(): self._driver.deactivate() def wait_for_temp(self): """ This method exits only if set temperature has reached.Subject to change """ if self._driver and self._driver.is_connected(): while self.status != 'holding at target': pass @classmethod def name(cls): return 'tempdeck' @classmethod def display_name(cls): return 'Temperature 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': { 'currentTemp': self.temperature, 'targetTemp': self.target } } @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 temperature(self): """ Current temperature in degree celsius """ return self._driver.temperature @property def target(self): """ Target temperature in degree celsius. Returns None if no target set """ return self._driver.target @property def status(self): """ Returns a string: 'heating'/'cooling'/'holding at target'/'idle'. NOTE: Depends on _poll_temperature thread to update the temperature to be used to determine the status """ return self._driver and self._driver.status # Internal Methods def _poll_temperature(self): while not self._poll_stop_event.wait(TEMP_POLL_INTERVAL_SECS): self._driver and self._driver.update_temperature() def connect(self): """ Connect to the 'TempDeck' port Planned change- will connect to the correct port in case of multiple TempDecks """ if self._port: if temp_locks.get(self._port): self._driver = temp_locks[self._port][1] else: self._driver = TempDeckDriver() if not self._driver.is_connected(): self._driver.connect(self._port) self._device_info = self._driver.get_device_info() self._poll_stop_event = Event() Thread(target=self._poll_temperature, daemon=True).start() else: # Sanity check Should never happen, because connect should never # be called without a port on Module raise MissingDevicePortError( "TempDeck couldn't connect to port {}".format(self._port)) def disconnect(self): ''' Disconnect from the serial port ''' if self._poll_stop_event: self._poll_stop_event.set() if self._driver: if self.status != 'idle': self.deactivate() self._driver.disconnect(port=self._port)