Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions hardwarelibrary/sources/millennia.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,13 @@ def doInitializeDevice(self):
self.port = SerialPort(portPath=self.portPath)
self.port.open(baudRate=self.defaultBaudRate)
self.readIdentity()
except Exception:
except Exception as error:
if self.port is not None and self.port.isOpen:
self.port.close()
raise PhysicalDevice.UnableToInitialize()
# Preserve the underlying error (e.g. pyserial's "[Errno 16]
# Resource busy") so callers can tell a busy port from a missing
# one instead of seeing a bare, info-less UnableToInitialize.
raise PhysicalDevice.UnableToInitialize(error) from error

def readIdentity(self):
# The eV identifies via the SCPI-style *IDN? query. The ?IDN form in
Expand Down Expand Up @@ -197,6 +200,20 @@ def doGetPower(self) -> float:
# token.
return float(self.queryString("?P").split()[0])

# Status snapshot

def doGetStatusUserInfo(self) -> dict:
# Single-call snapshot for PhysicalDevice.startBackgroundStatusUpdates()
# (posted as PhysicalDeviceNotification.status) and for GUI polling: the
# output power plus the diode (emission) and shutter states. Without this
# override the base returns None, so the monitoring loop posts nothing
# useful for the eV.
return {
"power": self.doGetPower(),
"isLaserOn": self.doGetOnOffState(),
"isShutterOpen": self.doGetShutterState(),
}


class DebugMillenniaEv25Device(MillenniaEv25Device):
classIdVendor = 0xFFFF
Expand Down
9 changes: 9 additions & 0 deletions hardwarelibrary/tests/testMillennia.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ def testShutterIsIndependentOfOnOff(self):
self.assertFalse(self.laser.isLaserOn())
self.assertTrue(self.laser.isShutterOpen()) # off, shutter unchanged

def testStatusUserInfoSnapshotsPowerOnOffAndShutter(self):
self.laser.setPower(7.5)
self.laser.turnOn()
self.laser.openShutter()
self.assertEqual(
self.laser.doGetStatusUserInfo(),
{"power": 7.5, "isLaserOn": True, "isShutterOpen": True},
)


class TestMillenniaEv25Device(unittest.TestCase):
def setUp(self):
Expand Down
Loading