nibcq.Device ============ .. py:class:: nibcq.Device(device_family: nibcq.enums.DeviceFamily) Class to represent and manage hardware device configurations. Handles connection and communication with National Instruments measurement devices including Digital Multimeters (DMM) and Source Measure Units (SMU). Provides device validation, session management, and hardware abstraction for measurement operations. .. attribute:: session The active session object for communication with the hardware device. :type: nidmm.Session | nidcpower.Session .. py:property:: product :type: str Get the product model name of the connected device. Returns the instrument model string as reported by the device driver. This is typically the full product name including manufacturer and model number. :returns: The product model name (e.g., "NI PXIe-4139", "NI PXI-4071") :rtype: str .. rubric:: Examples >>> device = Device.create(DeviceFamily.SMU, "PXI1Slot2") >>> print(device.product) "NI PXIe-4139" .. py:property:: serial_number :type: str Get the device serial number in raw format without leading zeros. Returns the serial number as reported directly by the device driver, without any formatting modifications. For simulated devices, this typically returns "0". :returns: The raw serial number without leading zero padding :rtype: str .. rubric:: Examples >>> device = Device.create(DeviceFamily.SMU, "PXI1Slot2") >>> print(device.serial_number) "12345678" # or "0" for simulated devices .. py:property:: device_family :type: nibcq.enums.DeviceFamily Get the device family type of the connected device. Returns the DeviceFamily enum value indicating whether this device is a Digital Multimeter (DMM) or Source Measure Unit (SMU). This information is useful for determining available functionality and measurement capabilities. :returns: The device family enum (DeviceFamily.DMM or DeviceFamily.SMU) :rtype: DeviceFamily .. rubric:: Examples >>> device = Device.create(DeviceFamily.SMU, "PXI1Slot2") >>> print(device.device_family) DeviceFamily.SMU >>> if device.device_family == DeviceFamily.SMU: ... print("This is a Source Measure Unit") .. py:property:: full_serial_number :type: str Get the device serial number formatted with leading zeros. Returns the serial number padded to 8 characters with leading zeros for consistency with file naming conventions and device identification. For simulated devices (serial number "0"), returns "0" without padding. :returns: The serial number padded to 8 characters with leading zeros, or "0" for simulated devices :rtype: str .. rubric:: Examples >>> device = Device.create(DeviceFamily.SMU, "PXI1Slot2") >>> print(device.full_serial_number) "12345678" # Raw: "12345678" >>> print(device.full_serial_number) "00001234" # Raw: "1234" >>> print(device.full_serial_number) "0" # Raw: "0" (simulated) .. py:property:: is_closed Get the current session state of the device. Returns whether the device session has been closed. A closed device cannot be used for measurements and must be reconnected to resume operation. This property is useful for session management and resource cleanup. :returns: True if the device session is closed, False if active :rtype: bool .. rubric:: Examples >>> device = Device.create(DeviceFamily.SMU, "PXI1Slot2") >>> print(device.is_closed) False >>> device.close() >>> print(device.is_closed) True .. py:method:: is_supported(device_type: nibcq.enums.DeviceFamily, device_to_check: str = None) -> bool :staticmethod: Check if a device product type is supported by the nibcq package. Validates whether the specified device model is included in the list of supported instruments for the given device family. This is used during device initialization to ensure compatibility. :param device_type: The device family to check against (DeviceFamily.DMM or DeviceFamily.SMU). :type device_type: DeviceFamily :param device_to_check: The product model name to validate. Should match the instrument_model string from the device driver. :type device_to_check: str, optional :returns: True if the device is supported, False otherwise :rtype: bool :raises ValueError: If device_type is not a valid DeviceFamily enum value .. rubric:: Examples >>> Device.is_supported(DeviceFamily.SMU, "NI PXIe-4139") True >>> Device.is_supported(DeviceFamily.DMM, "NI PXI-4071") True >>> Device.is_supported(DeviceFamily.SMU, "Unsupported Model") False .. py:method:: connect(resource_name: str, options: str = '') Connect this device instance to actual hardware. Establishes a session with the specified hardware instrument. This instance method allows you to create a device object first and then connect it later. :param resource_name: The VISA resource name of the device to connect to. Example: "PXI1Slot2" or "Dev1". :type resource_name: str :param options: Additional connection options for the VISA session. Defaults to empty string for standard connection. :type options: str, optional :returns: Self (for method chaining) :rtype: Device :raises RuntimeError: If connection to the device fails or device already connected :raises ValueError: If the device is not supported :raises nidmm.errors.DriverError: If DMM-specific driver errors occur :raises nidcpower.errors.DriverError: If SMU-specific driver errors occur .. rubric:: Examples >>> device = Device(DeviceFamily.SMU) >>> device.connect("PXI1Slot2") >>> # Or with method chaining: >>> device = Device(DeviceFamily.SMU).connect("PXI1Slot2") .. py:method:: create(device_family: nibcq.enums.DeviceFamily, resource_name: str, options: str = '') :classmethod: Create a new Device instance and connect it to hardware in one step. Alternative constructor that provides a convenient interface for creating and connecting devices in a single call. This is equivalent to calling Device(device_family).connect(resource_name, options). :param device_family: The type of device (DMM or SMU) to connect to. Must be a valid DeviceFamily enum value. :type device_family: DeviceFamily :param resource_name: The VISA resource name of the device to connect to. Example: "PXI1Slot2" or "Dev1". :type resource_name: str :param options: Additional connection options for the VISA session. Defaults to empty string for standard connection. :type options: str, optional :returns: A new Device instance connected to the specified instrument :rtype: Device :raises RuntimeError: If connection to the device fails :raises ValueError: If the device is not supported :raises nidmm.errors.DriverError: If DMM-specific driver errors occur :raises nidcpower.errors.DriverError: If SMU-specific driver errors occur .. rubric:: Examples >>> device = Device.create(DeviceFamily.SMU, "PXI1Slot2") >>> device = Device.create(DeviceFamily.DMM, "Dev1", "Simulate=1") .. py:method:: close() Close the device session and release hardware resources. Properly terminates the connection to the device and marks the session as closed. After calling this method, the device cannot be used for measurements until a new connection is established. This method should be called when finished with the device to ensure proper resource cleanup. :raises nidmm.errors.DriverError: If DMM-specific errors occur during closure :raises nidcpower.errors.DriverError: If SMU-specific errors occur during closure .. rubric:: Examples >>> device = Device.create(DeviceFamily.SMU, "PXI1Slot2") >>> # ... perform measurements ... >>> device.close() >>> print(device.is_closed) True .. py:method:: __enter__() Enter the runtime context for use with 'with' statements. Enables the Device class to be used as a context manager, allowing automatic resource management through Python's 'with' statement. The device session will be automatically closed when exiting the context, even if an exception occurs. :returns: The Device instance for use within the context :rtype: Device .. rubric:: Examples >>> with Device.create(DeviceFamily.SMU, "PXI1Slot2") as device: ... # Use device for measurements ... result = device.session.measure() # Device is automatically closed here .. py:method:: __exit__(exc_type, exc_value, traceback) Exit the runtime context and ensure proper resource cleanup. Automatically closes the device session when exiting a 'with' statement context. This ensures that hardware resources are properly released regardless of whether the context was exited normally or due to an exception. :param exc_type: The exception type if an exception occurred, None otherwise :param exc_value: The exception instance if an exception occurred, None otherwise :param traceback: The traceback object if an exception occurred, None otherwise :returns: False to allow any exception that occurred to propagate normally :rtype: bool .. rubric:: Examples >>> with Device(DeviceFamily.SMU, "PXI1Slot2") as device: ... raise ValueError("Something went wrong") # Device is still properly closed despite the exception .. py:property:: default_calibration_path Get the default calibration file path for the connected device. Generates the default calibration diary file path based on the device's full serial number and the toolkit folder structure. This path is used when no specific calibration file path is provided during initialization. :returns: The default calibration file path in the format: {TOOLKIT_FOLDER}/Calibration/{serial_number}_calibration_log.csv :rtype: str :raises RuntimeError: If the device is not initialized .. rubric:: Examples >>> measurement = Measurement(device) >>> print(measurement.default_calibration_path) "/path/to/toolkit/Calibration/12345678_calibration_log.csv" .. py:method:: with_temperature(thermocouple_settings: nibcq.temperature.ThermocoupleSettings, temperature_delta: float = math.nan) Add temperature measurement capability to this device. :param thermocouple_settings: Configuration for the thermocouple measurement :returns: This device instance for method chaining .. rubric:: Examples >>> from nibcq.temperature import ThermocoupleSettings >>> settings = ThermocoupleSettings("Dev1/ai0") >>> device = Device.create(DeviceFamily.SMU, "PXI1Slot2").with_temperature(settings) .. py:method:: with_switching(config: nibcq.switch.SwitchConfiguration, sense_switch_resource_name: str, source_switch_resource_name: Optional[str] = None, dmm_terminal_channel: Optional[str] = None, dmm_switch_type: Optional[nibcq.enums.SwitchDeviceType] = None) Add switching capability to this device. Enables multiplexer switching functionality for sequential testing of multiple DUTs. The device will support automatic channel switching based on the switch configuration. :param sense_switch_resource_name: The resource name of the sense switch. This is a VISA resource name. Defining this is manditory. In case of a DMM device, this defines the main switch, and in case of SMU devices, this is connected to the terminal responsible for sensing back the source signal impact. :type sense_switch_resource_name: str :param source_switch_resource_name: The resource name of the source switch. This is a VISA resource name. It is optional, as only SMU Devices require a source switch. This is the switch connected to the source terminal of the SMU. :type source_switch_resource_name: Optional[str] :param dmm_terminal_channel: The terminal channel connecting the switch to the DMM. :type dmm_terminal_channel: Optional[str] :param dmm_switch_type: The type of the switch being connected to the DMM. :type dmm_switch_type: Optional[str] :param config: The switch configuration object containing topology, channel definitions, and DUT information. :type config: SwitchConfiguration :returns: This device instance for method chaining :raises ValueError: If switching is not supported for this device family or it was incorrectly set up. :raises FileNotFoundError: If configuration file doesn't exist .. rubric:: Examples >>> device = Device.create(DeviceFamily.DMM, "Dev1").with_switching( ... "switch_config.json" ... ) >>> device = Device.create(DeviceFamily.SMU, "PXI1Slot2").with_switching( ... "smu_switch.json" ... )