Skip to content
Snippets Groups Projects
Commit f624e280 authored by Christoph Schmidt's avatar Christoph Schmidt
Browse files

Removed unused files. Process exits now with window close

parent c3f7106b
Branches
Tags
No related merge requests found
...@@ -2,7 +2,7 @@ import logging ...@@ -2,7 +2,7 @@ import logging
import sys import sys
import os import os
sys.path.append('../src') sys.path.append('./src')
from PySide6.QtWidgets import QApplication from PySide6.QtWidgets import QApplication
from rich.logging import RichHandler from rich.logging import RichHandler
......
import logging import logging
import os import os
import sys
import time import time
from abc import abstractmethod from abc import abstractmethod
from collections import deque from collections import deque
...@@ -8,8 +9,7 @@ from PySide6.QtCore import QObject, QThreadPool ...@@ -8,8 +9,7 @@ from PySide6.QtCore import QObject, QThreadPool
from numpy import ndarray from numpy import ndarray
from rich.logging import RichHandler from rich.logging import RichHandler
from CaptDeviceControl.controller.mp_AD2Capture.AD2StateMPSetter import AD2State
from CaptDeviceControl.controller.mp_AD2Capture.MPDeviceControl import mp_capture
from CaptDeviceControl.model.AD2CaptDeviceModel import AD2CaptDeviceModel, AD2CaptDeviceSignals from CaptDeviceControl.model.AD2CaptDeviceModel import AD2CaptDeviceModel, AD2CaptDeviceSignals
from CaptDeviceControl.model.AD2Constants import AD2Constants from CaptDeviceControl.model.AD2Constants import AD2Constants
from multiprocessing import Process, Queue, Value, Lock from multiprocessing import Process, Queue, Value, Lock
...@@ -224,56 +224,11 @@ class BaseAD2CaptDevice(QObject): ...@@ -224,56 +224,11 @@ class BaseAD2CaptDevice(QObject):
#time.sleep(0.1) #time.sleep(0.1)
self.logger.info("Status data consume thread ended") self.logger.info("Status data consume thread ended")
def _set_ad2state_from_process(self, ad2state: AD2State):
# print(ad2state.__dict__)
self.model.pid = ad2state.pid
self.model.dwf_version = ad2state.dwf_version
self.model.connected = ad2state.connected
self.model.device_name = ad2state.device_name
self.model.device_serial_number = ad2state.device_serial_number
self.model.device_index = ad2state.device_index
if ad2state.acquisition_state == AD2Constants.CapturingState.RUNNING():
self.logger.info("[START ACQ] Started acquisition")
self.model.capturing_finished = False
self.model.start_recording = True
self.model.stop_recording = False
elif ad2state.acquisition_state == AD2Constants.CapturingState.STOPPED():
if self.model.start_recording:
self.model.capturing_finished = True
self.logger.info(f"[STOP ACQ] Finished acquisition {self.model.capturing_finished}.")
# Emit a signal, that the Capturing has finished
self.model.start_recording = False
self.model.stop_recording = True
self.model.device_capturing_state = ad2state.acquisition_state
self.model.sample_rate = ad2state.sample_rate
self.model.selected_ain_channel = ad2state.selected_ain_channel
self.model.ain_channels = ad2state.ain_channels
self.model.ain_buffer_size = ad2state.ain_buffer_size
self.model.ain_bits = ad2state.ain_bits
self.model.ain_device_state = ad2state.ain_device_state
self.model.recording_time = ad2state.recording_time
# ================================================================================================================== # ==================================================================================================================
# Destructor # Destructor
# ================================================================================================================== # ==================================================================================================================
def stop_process(self): def exit(self):
#self.end_process_flag.value = True self.mpcaptdevicecontrol.safe_exit()
time_start = time.time()
#while self.proc.is_alive():
# time.sleep(0.1)
self.logger.warning(f"AD2 process exited after {time.time()-time_start}s")
self.kill_thread = True
def __del__(self):
self.logger.info("Exiting AD2 controller")
self.stop_process()
self.logger.warning("AD2 controller exited")
\ No newline at end of file
from ctypes import c_int, c_byte
from CaptDeviceControl.model.AD2Constants import AD2Constants
class AD2State:
def __init__(self):
# Multiprocessing Information
self._pid = None
self._ppid = None
# WaveForms Runtime (DWF) Information
self._dwf_version: str = "Unknown"
# Device information
self._connected: bool = False
self._device_name: str = "Unknown"
self._serial_number: str = "Unknown"
self._device_index: int = -1
# Acquisition Settings
self._sample_rate: int = -1
self._selected_ain_channel: int = -1
# Analog In Information
self._ain_channels: list = []
self._ain_buffer_size: int = -1
self._ain_bits: int = -1
self._ain_device_state: c_byte = c_byte()
# Analog Out Information
self._aout_channels: list = []
# Acquired Signal Information
self._acquisition_state: int = AD2Constants.CapturingState.STOPPED()
self._time_capture_started: float = -1 # The time the capturing has started
self._time_capture_ended: float = -1 # The time the capturing has ended
self._recording_time: float = -1
self._samples_captured: int = 0
self._samples_lost: int = -1
self._samples_corrupted: int = -1
# Device Status
self._device_ready: bool = False
self._device_capturing = False
def reinit(self, fields: dict):
for k, v in fields.items():
setattr(self, k, v)
# =========== Multiprocessing Information
@property
def pid(self):
return self._pid
@property
def ppid(self):
return self._ppid
# =========== WaveForms Runtime (DWF) Information
@property
def dwf_version(self):
return self._dwf_version
# =========== Device Information
@property
def connected(self):
return self._connected
@property
def device_name(self):
return self._device_name
@property
def device_serial_number(self):
return self._serial_number
@property
def device_index(self):
return self._device_index
# ========== Acquisition Settings
@property
def sample_rate(self):
return self._sample_rate
@property
def selected_ain_channel(self):
return self._selected_ain_channel
# =========== Analog In Information
@property
def ain_channels(self):
return self._ain_channels
@property
def ain_buffer_size(self):
return self._ain_buffer_size
@property
def ain_bits(self):
return self._ain_bits
@property
def ain_device_state(self):
return self._ain_device_state
# =========== Analog Out Information
@property
def aout_channels(self):
return self._aout_channels
# =========== Acquired Signal Information
@property
def acquisition_state(self):
return self._acquisition_state
@property
def time_capture_started(self) -> float:
"""The time the capturing has started"""
return self._time_capture_started
@property
def time_capture_ended(self) -> float:
"""The time the capturing has ended"""
return self._time_capture_ended
@property
def recording_time(self):
return self._recording_time
@property
def samples_captured(self):
return self._samples_captured
@property
def samples_lost(self):
return self._samples_lost
@property
def samples_corrupted(self):
return self._samples_corrupted
# =========== Device Status
@property
def device_ready(self):
return self._device_ready
@property
def device_capturing(self):
return self._device_capturing
class AD2StateMPSetter(AD2State):
def __init__(self, state_queue):
super().__init__()
self._state_queue = state_queue
# =========== Multiprocessing Information
@AD2State.pid.setter
def pid(self, value):
self._pid = value
self._state_queue.put(self.to_simple_class())
@AD2State.ppid.setter
def ppid(self, value):
self._ppid = value
self._state_queue.put(self.to_simple_class())
# =========== WaveForms Runtime (DWF) Information
@AD2State.dwf_version.setter
def dwf_version(self, value):
self._dwf_version = value
self._state_queue.put(self.to_simple_class())
# =========== Device Information
@AD2State.connected.setter
def connected(self, value):
self._connected = value
self._state_queue.put(self.to_simple_class())
@AD2State.device_name.setter
def device_name(self, value):
self._device_name = value
self._state_queue.put(self.to_simple_class())
@AD2State.device_serial_number.setter
def device_serial_number(self, value):
self._serial_number = value
self._state_queue.put(self.to_simple_class())
@AD2State.device_index.setter
def device_index(self, value):
self._device_index = value
self._state_queue.put(self.to_simple_class())
# ========== Acquisition Settings
@AD2State.sample_rate.setter
def sample_rate(self, value):
self._sample_rate = value
self._state_queue.put(self.to_simple_class())
@AD2State.selected_ain_channel.setter
def selected_ain_channel(self, value):
self._selected_ain_channel = value
self._state_queue.put(self.to_simple_class())
# =========== Analog In Information
@AD2State.ain_channels.setter
def ain_channels(self, value):
self._ain_channels = value
self._state_queue.put(self.to_simple_class())
@AD2State.ain_buffer_size.setter
def ain_buffer_size(self, value):
self._ain_buffer_size = value
self._state_queue.put(self.to_simple_class())
@AD2State.ain_bits.setter
def ain_bits(self, value):
self._ain_bits = value
self._state_queue.put(self.to_simple_class())
@AD2State.ain_device_state.setter
def ain_device_state(self, value):
self._ain_device_state = value
self._state_queue.put(self.to_simple_class())
# =========== Analog Out Information
@AD2State.aout_channels.setter
def aout_channels(self, value):
self._aout_channels = value
self._state_queue.put(self.to_simple_class())
# =========== Acquired Signal Information
@AD2State.acquisition_state.setter
def acquisition_state(self, value):
self._acquisition_state = value
self._state_queue.put(self.to_simple_class())
@AD2State.time_capture_ended.setter
def time_capture_started(self, value: float):
"""The time the capturing has started"""
self._time_capture_started = value
self._state_queue.put(self.to_simple_class())
@AD2State.time_capture_ended.setter
def time_capture_ended(self, value: float):
self._time_capture_ended = value
self._state_queue.put(self.to_simple_class())
@AD2State.recording_time.setter
def recording_time(self, value):
self._recording_time = value
self._state_queue.put(self.to_simple_class())
@AD2State.samples_captured.setter
def samples_captured(self, value):
self._samples_captured = value
self._state_queue.put(self.to_simple_class())
@AD2State.samples_lost.setter
def samples_lost(self, value):
self._samples_lost = value
self._state_queue.put(self.to_simple_class())
@AD2State.samples_corrupted.setter
def samples_corrupted(self, value):
self._samples_corrupted = value
self._state_queue.put(self.to_simple_class())
# =========== Device Status
@AD2State.device_ready.setter
def device_ready(self, value):
self._device_ready = value
self._state_queue.put(self.to_simple_class())
@AD2State.device_capturing.setter
def device_capturing(self, value):
self._device_capturing = value
self._state_queue.put(self.to_simple_class())
def to_simple_class(self) -> AD2State:
exclude = ["_state_queue"]
ad2state = AD2State()
to_dict = {}
for item, value in self.__dict__.items():
if item in exclude:
continue
else:
to_dict[item] = value
ad2state.reinit(to_dict)
return ad2state
...@@ -4,8 +4,8 @@ import cmp ...@@ -4,8 +4,8 @@ import cmp
from PySide6.QtCore import Signal from PySide6.QtCore import Signal
from CaptDeviceControl.controller.mp_AD2Capture.MPCaptDevice import MPCaptDevice from CaptDeviceControl.controller.mp_AD2Capture.MPCaptDevice import MPCaptDevice
from model.AD2CaptDeviceModel import AD2CaptDeviceSignals, AD2CaptDeviceModel from CaptDeviceControl.model.AD2CaptDeviceModel import AD2CaptDeviceSignals, AD2CaptDeviceModel
from model.AD2Constants import AD2Constants from CaptDeviceControl.model.AD2Constants import AD2Constants
class MPCaptDeviceControl(cmp.CProcessControl): class MPCaptDeviceControl(cmp.CProcessControl):
......
"""
File for methods that run the multiporcessing capture.
Here we can init the device capturing and stream the data using ques.
(c) Christoph Schmidt, 2023
christoph.schmidt@tugraz.at
"""
import os
import random
import sys
import time
from ctypes import c_int, byref, c_double, cdll, create_string_buffer, c_int32, CDLL
from CaptDeviceControl.controller.mp_AD2Capture.AD2StateMPSetter import AD2StateMPSetter
from CaptDeviceControl.model.AD2Constants import AD2Constants
from CaptDeviceControl.constants.dwfconstants import acqmodeRecord, DwfStateConfig, DwfStatePrefill, DwfStateArmed, enumfilterType, \
enumfilterUSB, enumfilterDemo
# ======================================================================================================================
# Process logging function
# ======================================================================================================================
def _mp_log_debug(msg, prefix="AD2 Thread"):
print(f"DBG | [{prefix}/{os.getpid()}]: {msg}")
def _mp_log_error(msg, prefix="AD2 Thread"):
print(f"ERR | [{prefix}/{os.getpid()}]: {msg}")
def _mp_log_info(msg, prefix="AD2 Thread"):
print(f"INF | [{prefix}/{os.getpid()}]: {msg}")
def _mp_log_warning(msg, prefix="AD2 Thread"):
print(f"WARN | [{prefix}/{os.getpid()}]: {msg}")
# ======================================================================================================================
# Process Main function, used for capturing and streaming data
# ======================================================================================================================
def mp_capture(stream_data_queue, capture_data_queue, state_queue,
start_capture, end_process,
device_id, channel, sample_rate):
"""
Captures data from the device and puts it into a queue.
:param capture_data_queue:
:param state_queue:
:param start_capture:
:param end_process:
:param device_id:
:param sample_rate:
:param stream_data_queue: Queue to put the data into.
:param channel: Channel to capture data from.
:return: None
"""
time_capture_started = 0
capturing_notified = False
ad2_state = AD2StateMPSetter(state_queue)
ad2_state.pid = os.getpid()
ad2_state.ppid = os.getppid()
# Print pid and ppid
_mp_log_info(f"Starting capture thread, pid={ad2_state.pid}, ppid={ad2_state.ppid}")
ad2_state.selected_ain_channel = channel
ad2_state.sample_rate = sample_rate
ad2_state.device_index = device_id
_mp_log_debug(f"Setting up device {ad2_state.device_index} with "
f"channel {ad2_state.selected_ain_channel} and "
f"acquisition rate {ad2_state.sample_rate} Hz")
dwf, hdwf = _mp_open_device(device_id, ad2_state)
# acquisition_state = c_byte()
cAvailable = c_int()
cLost = c_int()
cCorrupted = c_int()
# FDwfAnalogInStatus(HDWF hdwf, BOOL fReadData, DwfState* psts)
_t_setup_aquisition(dwf, hdwf, ad2_state)
_t_setup_sine_wave(dwf, hdwf, ad2_state)
_mp_log_info("Configuring acquisition. Starting oscilloscope.")
# FDwfAnalogInConfigure(HDWF hdwf, int fReconfigure, int fStart)
# Configures the instrument and start or stop the acquisition. To reset the Auto trigger timeout, set
# fReconfigure to TRUE.
# hdwf – Interface handle.
# fReconfigure – Configure the device.
# fStart – Start the acquisition.
dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1))
_mp_log_info("Device configured. Starting acquisition.")
cSamples = 0
ad2_state.device_ready = True
capture_samples = 0
print(end_process.value)
while end_process.value == int(False):
# Checks the state of the acquisition. To read the data from the device, set fReadData to TRUE. For
# single acquisition mode, the data will be read only when the acquisition is finished
dwf.FDwfAnalogInStatus(hdwf, c_int(1),
byref(ad2_state.ain_device_state)) # Variable to receive the acquisition state
if cSamples == 0 and (
ad2_state.ain_device_state == DwfStateConfig or
ad2_state.ain_device_state == DwfStatePrefill or
ad2_state.ain_device_state == DwfStateArmed):
_mp_log_info("Device in idle state. Waiting for acquisition to start.")
continue # Acquisition not yet started.
dwf.FDwfAnalogInStatusRecord(hdwf,
byref(cAvailable),
byref(cLost),
byref(cCorrupted))
cSamples += cLost.value
if cLost.value:
ad2_state.samples_lost += cLost.value
if cCorrupted.value:
ad2_state.samples_corrupted += cCorrupted.value
# self.dwf.FDwfAnalogInStatusSamplesValid(self.hdwf, byref(self.cValid))
if cAvailable.value == 0:
continue
else:
# print(f"Available: {cAvailable.value}")
# if cSamples + cAvailable.value > self.ad2capt_model.n_samples:
# cAvailable = c_int(self.ad2capt_model.n_samples - cSamples)
rgdSamples = (c_double * cAvailable.value)()
dwf.FDwfAnalogInStatusData(hdwf, c_int(ad2_state.selected_ain_channel), byref(rgdSamples),
cAvailable) # get channel data
# Print how many samples are available
status = {"available": cAvailable.value, 'captured': 0, 'lost': cLost.value,
'corrupted': cCorrupted.value, "time": time.time()}
#print(status)
time.sleep(random.random())
#print(len(rgdSamples))
stream_data_queue.put(
([(float(s)) for s in rgdSamples], status)
)
if start_capture.value == 1:
if not capturing_notified:
time_capture_started = time.time()
capture_samples = 0
_mp_log_info("Starting command recieved. Acquisition started.")
ad2_state.acquisition_state = AD2Constants.CapturingState.RUNNING()
capturing_notified = True
capture_samples = capture_samples + len(rgdSamples)
status = {
"available": cAvailable.value,
"captured": capture_samples,
"lost": cLost.value,
"corrupted": cCorrupted.value,
"recording_time": time.time() - time_capture_started}
capture_data_queue.put(([float(s) for s in rgdSamples], status))
# capture_data_queue.put([float(s) for s in rgdSamples])
elif start_capture.value == 0:
if capturing_notified:
ad2_state.acquisition_state = AD2Constants.CapturingState.STOPPED()
time_capture_stopped = time.time()
time_captured = time_capture_stopped - time_capture_started
ad2_state.recording_time = time_captured
_mp_log_info(f"Acquisition stopped after {time_captured} seconds. Captured {capture_samples} "
f"samples. Resulting in a time of {capture_samples / ad2_state.sample_rate} s.")
status = {
"available": cAvailable.value,
"captured": capture_samples,
"lost": cLost.value,
"corrupted": cCorrupted.value,
"recording_time": time.time() - time_capture_started}
capture_data_queue.put(([float(s) for s in rgdSamples], status))
capturing_notified = False
cSamples += cAvailable.value
_mp_close_device(dwf, hdwf, channel, ad2_state)
def _mp_update_device_information(dwf, hdwf, ad2_state: AD2StateMPSetter):
in_channel = c_int()
out_channel = c_int()
buffer_size = c_int()
# Get the Analog In Channels and Buffer Size
dwf.FDwfAnalogInChannelCount(hdwf, byref(in_channel))
ad2_state.ain_channels = list(range(0, int(in_channel.value)))
dwf.FDwfAnalogInBufferSizeInfo(hdwf, 0, byref(buffer_size))
# Get the Analog Out Channels and Buffer Size
ad2_state.analog_analog_in_buffer_size = int(buffer_size.value)
dwf.FDwfAnalogOutCount(hdwf, byref(out_channel))
ad2_state.aout_channels = list(range(0, int(out_channel.value)))
# # Select the first Analog In Channel
# ad2_state.selected_channel = ad2_state.list_of_analog_in_channels[0]
def _mp_get_dwf_information(dwf, ad2_state: AD2StateMPSetter):
_mp_log_debug(f"Getting DWF version information...")
version = create_string_buffer(16)
dwf.FDwfGetVersion(version)
ad2_state.dwf_version = version.value.decode("utf-8")
_mp_log_debug(f"DWF Version: {ad2_state.dwf_version}")
# ======================================================================================================================
# Setup the device
# ======================================================================================================================
def _t_setup_sine_wave(dwf, hdwf, ad2_state: AD2StateMPSetter):
_mp_log_debug("Generating AM sine wave...")
dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), c_int(0), c_int(1)) # carrier
dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), c_int(0), c_int(1)) # sine
dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), c_int(0), c_double(0.1))
dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), c_int(0), c_double(1))
# dwf.FDwfAnalogOutNodeOffsetSet(hdwf, c_int(0), c_int(0), c_double(0.5))
# dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), c_int(2), c_int(1)) # AM
# dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), c_int(2), c_int(3)) # triangle
# dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), c_int(2), c_double(0.1))
# dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), c_int(2), c_double(50))
dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_int(1))
_mp_log_debug("Sine wave on output channel 0 configured.")
def _t_setup_aquisition(dwf, hdwf, ad2_state: AD2StateMPSetter):
dwf.FDwfAnalogInStatus(hdwf, c_int(1),
byref(ad2_state.ain_device_state)) # Variable to receive the acquisition state
_mp_log_info(f"[Task] Setup for acquisition on channel"
f" {ad2_state.selected_ain_channel} with rate {ad2_state.sample_rate} Hz.")
dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(ad2_state.selected_ain_channel), c_int(1))
dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(ad2_state.selected_ain_channel), c_double(5))
dwf.FDwfAnalogInAcquisitionModeSet(hdwf, acqmodeRecord)
dwf.FDwfAnalogInFrequencySet(hdwf, c_double(ad2_state.sample_rate))
dwf.FDwfAnalogInRecordLengthSet(hdwf, 0) # -1 infinite record length
# Variable to receive the acquisition state
dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(ad2_state.ain_device_state))
_mp_log_info(f"[Task] Wait 2 seconds for the offset to stabilize.")
# wait at least 2 seconds for the offset to stabilize
time.sleep(2)
_mp_log_info(f"[Task] Setup for acquisition done.")
def _mp_discover_connected_devices(dwf):
_mp_log_info(f"Discovering connected devices...")
num_of_connected_devices = 0
devicename = create_string_buffer(64)
serialnum = create_string_buffer(16)
for iDevice in enumerate_devices(dwf, show_demo_devices=True):
dwf.FDwfEnumDeviceName(c_int(iDevice), devicename)
dwf.FDwfEnumSN(c_int(iDevice), serialnum)
connected_devices.append({
'type': type,
'device_id': int(iDevice),
'device_name': str(devicename.value.decode('UTF-8')),
'serial_number': str(serialnum.value.decode('UTF-8'))
})
#_mp_log_debug(f"Found {type} device: {devicename.value.decode('UTF-8')} ({serialnum.value.decode('UTF-8')})")
# print(connected_devices)
# print(f"Discoverd {len(self.model.connected_devices)} devices.")
return connected_devices
def enumerate_devices(dwf: CDLL, show_demo_devices=False) -> list:
"""
Enumerates all connected devices. Function is used to discover all connected, compatible devices.
Builds an internal list of detected devices filtered by the enumfilter parameter. It must be called
before using other FDwfEnum functions because they obtain information about enumerated devices
from this list identified by the device index.
:param show_demo_devices: Specify if demo devices should be shown.
:return: A list from 0 to n devices.
"""
if show_demo_devices:
enum_filter = c_int32(enumfilterType.value | enumfilterUSB.value | enumfilterDemo.value)
else:
enum_filter = c_int32(enumfilterType.value | enumfilterUSB.value)
cDevice = c_int()
dwf.FDwfEnum(enum_filter, byref(cDevice))
return list(range(0, cDevice.value))
def _mp_open_device(ad2_state: AD2StateMPSetter):
"""
Opens the device and returns the handle.
:return: Device handle.
"""
_mp_log_debug(f"Importing dwf library for {sys.platform}...")
if sys.platform.startswith("win"):
dwf = cdll.dwf
elif sys.platform.startswith("darwin"):
dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
else:
dwf = cdll.LoadLibrary("libdwf.so")
hdwf = c_int()
_mp_get_dwf_information(dwf, ad2_state)
# This is needed, otherwise, the device is not found.
_mp_discover_connected_devices(dwf)
# Opens the device specified by idxDevice. The device handle is returned in hdwf. If idxDevice is -1, the
# first available device is opened.
_mp_log_info(f"[Task] Opening device #{ad2_state.device_index}...")
dwf.FDwfDeviceOpen(c_int(ad2_state.device_index), byref(hdwf))
devicename = create_string_buffer(64)
serialnum = create_string_buffer(16)
dwf.FDwfEnumDeviceName(c_int(ad2_state.device_index), devicename)
dwf.FDwfEnumSN(c_int(ad2_state.device_index), serialnum)
ad2_state.device_name = str(devicename.value.decode("utf-8"))
ad2_state.device_serial_number = str(serialnum.value.decode("utf-8")).replace("SN:", "")
# open device
if hdwf.value == 0:
szerr = create_string_buffer(512)
dwf.FDwfGetLastErrorMsg(szerr)
_mp_log_error(f"Failed to open device: {szerr.value}")
ad2_state.connected = False
raise Exception(f"Failed to open device: {szerr.value}")
else:
_mp_log_info(f"Device opened: {ad2_state.device_name} ({ad2_state.device_serial_number})")
ad2_state.connected = True
return dwf, hdwf
def _mp_close_device(dwf, hdwf, channel, ad2_state: AD2StateMPSetter):
dwf.FDwfAnalogOutReset(hdwf, c_int(channel))
_mp_log_info(f"[Task] Closing device...")
dwf.FDwfDeviceClose(hdwf)
ad2_state.connected = False
_mp_log_info(f"[Task] Device closed.")
...@@ -481,3 +481,9 @@ class ControlWindow(QMainWindow): ...@@ -481,3 +481,9 @@ class ControlWindow(QMainWindow):
else: else:
item = QStandardItem(str(data)) item = QStandardItem(str(data))
parent.appendRow(item) parent.appendRow(item)
def closeEvent(self, args):
print("Destroyed")
self.controller.exit()
self.destroyed.emit()
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment