pymodaq 5.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pymodaq/__init__.py +98 -0
- pymodaq/control_modules/__init__.py +1 -0
- pymodaq/control_modules/daq_move.py +1238 -0
- pymodaq/control_modules/daq_move_ui/__init__.py +0 -0
- pymodaq/control_modules/daq_move_ui/factory.py +48 -0
- pymodaq/control_modules/daq_move_ui/ui_base.py +359 -0
- pymodaq/control_modules/daq_move_ui/uis/__init__.py +0 -0
- pymodaq/control_modules/daq_move_ui/uis/binary.py +139 -0
- pymodaq/control_modules/daq_move_ui/uis/original.py +120 -0
- pymodaq/control_modules/daq_move_ui/uis/relative.py +124 -0
- pymodaq/control_modules/daq_move_ui/uis/simple.py +126 -0
- pymodaq/control_modules/daq_viewer.py +1517 -0
- pymodaq/control_modules/daq_viewer_ui.py +407 -0
- pymodaq/control_modules/mocks.py +57 -0
- pymodaq/control_modules/move_utility_classes.py +1141 -0
- pymodaq/control_modules/thread_commands.py +137 -0
- pymodaq/control_modules/ui_utils.py +72 -0
- pymodaq/control_modules/utils.py +591 -0
- pymodaq/control_modules/viewer_utility_classes.py +670 -0
- pymodaq/daq_utils/__init__.py +0 -0
- pymodaq/daq_utils/daq_utils.py +6 -0
- pymodaq/dashboard.py +2396 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.aliases +3 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvlps +3 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvproj +32 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_1Dgaussian.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_2Dgaussian.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_cmd.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_float.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_int.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_data.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_int.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_scalar.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_string.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/client_state.ctl +0 -0
- pymodaq/examples/Labview_TCP_Client/cmd_types.ctl +0 -0
- pymodaq/examples/__init__.py +0 -0
- pymodaq/examples/function_plotter.py +160 -0
- pymodaq/examples/nonlinearscanner.py +126 -0
- pymodaq/examples/qt_less_standalone_module.py +165 -0
- pymodaq/examples/tcp_client.py +97 -0
- pymodaq/extensions/__init__.py +25 -0
- pymodaq/extensions/adaptive/__init__.py +2 -0
- pymodaq/extensions/adaptive/adaptive_optimization.py +179 -0
- pymodaq/extensions/adaptive/loss_function/_1d_loss_functions.py +73 -0
- pymodaq/extensions/adaptive/loss_function/_2d_loss_functions.py +73 -0
- pymodaq/extensions/adaptive/loss_function/__init__.py +3 -0
- pymodaq/extensions/adaptive/loss_function/loss_factory.py +110 -0
- pymodaq/extensions/adaptive/utils.py +123 -0
- pymodaq/extensions/bayesian/__init__.py +2 -0
- pymodaq/extensions/bayesian/acquisition/__init__.py +2 -0
- pymodaq/extensions/bayesian/acquisition/acquisition_function_factory.py +80 -0
- pymodaq/extensions/bayesian/acquisition/base_acquisition_function.py +105 -0
- pymodaq/extensions/bayesian/bayesian_optimization.py +143 -0
- pymodaq/extensions/bayesian/utils.py +180 -0
- pymodaq/extensions/console.py +73 -0
- pymodaq/extensions/daq_logger/__init__.py +1 -0
- pymodaq/extensions/daq_logger/abstract.py +52 -0
- pymodaq/extensions/daq_logger/daq_logger.py +519 -0
- pymodaq/extensions/daq_logger/db/__init__.py +0 -0
- pymodaq/extensions/daq_logger/db/db_logger.py +300 -0
- pymodaq/extensions/daq_logger/db/db_logger_models.py +100 -0
- pymodaq/extensions/daq_logger/h5logging.py +84 -0
- pymodaq/extensions/daq_scan.py +1218 -0
- pymodaq/extensions/daq_scan_ui.py +241 -0
- pymodaq/extensions/data_mixer/__init__.py +0 -0
- pymodaq/extensions/data_mixer/daq_0Dviewer_DataMixer.py +97 -0
- pymodaq/extensions/data_mixer/data_mixer.py +262 -0
- pymodaq/extensions/data_mixer/model.py +108 -0
- pymodaq/extensions/data_mixer/models/__init__.py +0 -0
- pymodaq/extensions/data_mixer/models/equation_model.py +91 -0
- pymodaq/extensions/data_mixer/models/gaussian_fit_model.py +65 -0
- pymodaq/extensions/data_mixer/parser.py +53 -0
- pymodaq/extensions/data_mixer/utils.py +23 -0
- pymodaq/extensions/h5browser.py +9 -0
- pymodaq/extensions/optimizers_base/__init__.py +0 -0
- pymodaq/extensions/optimizers_base/optimizer.py +1016 -0
- pymodaq/extensions/optimizers_base/thread_commands.py +22 -0
- pymodaq/extensions/optimizers_base/utils.py +427 -0
- pymodaq/extensions/pid/__init__.py +16 -0
- pymodaq/extensions/pid/actuator_controller.py +14 -0
- pymodaq/extensions/pid/daq_move_PID.py +154 -0
- pymodaq/extensions/pid/pid_controller.py +1016 -0
- pymodaq/extensions/pid/utils.py +189 -0
- pymodaq/extensions/utils.py +111 -0
- pymodaq/icon.ico +0 -0
- pymodaq/post_treatment/__init__.py +6 -0
- pymodaq/post_treatment/load_and_plot.py +352 -0
- pymodaq/resources/__init__.py +0 -0
- pymodaq/resources/config_template.toml +57 -0
- pymodaq/resources/preset_default.xml +1 -0
- pymodaq/resources/setup_plugin.py +73 -0
- pymodaq/splash.png +0 -0
- pymodaq/utils/__init__.py +0 -0
- pymodaq/utils/array_manipulation.py +6 -0
- pymodaq/utils/calibration_camera.py +180 -0
- pymodaq/utils/chrono_timer.py +203 -0
- pymodaq/utils/config.py +53 -0
- pymodaq/utils/conftests.py +5 -0
- pymodaq/utils/daq_utils.py +158 -0
- pymodaq/utils/data.py +128 -0
- pymodaq/utils/enums.py +6 -0
- pymodaq/utils/exceptions.py +38 -0
- pymodaq/utils/gui_utils/__init__.py +10 -0
- pymodaq/utils/gui_utils/loader_utils.py +75 -0
- pymodaq/utils/gui_utils/utils.py +18 -0
- pymodaq/utils/gui_utils/widgets/lcd.py +8 -0
- pymodaq/utils/h5modules/__init__.py +2 -0
- pymodaq/utils/h5modules/module_saving.py +526 -0
- pymodaq/utils/leco/__init__.py +25 -0
- pymodaq/utils/leco/daq_move_LECODirector.py +217 -0
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py +163 -0
- pymodaq/utils/leco/director_utils.py +74 -0
- pymodaq/utils/leco/leco_director.py +166 -0
- pymodaq/utils/leco/pymodaq_listener.py +364 -0
- pymodaq/utils/leco/rpc_method_definitions.py +43 -0
- pymodaq/utils/leco/utils.py +74 -0
- pymodaq/utils/logger.py +6 -0
- pymodaq/utils/managers/__init__.py +0 -0
- pymodaq/utils/managers/batchscan_manager.py +346 -0
- pymodaq/utils/managers/modules_manager.py +589 -0
- pymodaq/utils/managers/overshoot_manager.py +242 -0
- pymodaq/utils/managers/preset_manager.py +229 -0
- pymodaq/utils/managers/preset_manager_utils.py +262 -0
- pymodaq/utils/managers/remote_manager.py +484 -0
- pymodaq/utils/math_utils.py +6 -0
- pymodaq/utils/messenger.py +6 -0
- pymodaq/utils/parameter/__init__.py +10 -0
- pymodaq/utils/parameter/utils.py +6 -0
- pymodaq/utils/scanner/__init__.py +5 -0
- pymodaq/utils/scanner/scan_config.py +16 -0
- pymodaq/utils/scanner/scan_factory.py +259 -0
- pymodaq/utils/scanner/scan_selector.py +477 -0
- pymodaq/utils/scanner/scanner.py +324 -0
- pymodaq/utils/scanner/scanners/_1d_scanners.py +174 -0
- pymodaq/utils/scanner/scanners/_2d_scanners.py +299 -0
- pymodaq/utils/scanner/scanners/__init__.py +1 -0
- pymodaq/utils/scanner/scanners/sequential.py +224 -0
- pymodaq/utils/scanner/scanners/tabular.py +319 -0
- pymodaq/utils/scanner/utils.py +110 -0
- pymodaq/utils/svg/__init__.py +6 -0
- pymodaq/utils/svg/svg_renderer.py +20 -0
- pymodaq/utils/svg/svg_view.py +35 -0
- pymodaq/utils/svg/svg_viewer2D.py +50 -0
- pymodaq/utils/tcp_ip/__init__.py +6 -0
- pymodaq/utils/tcp_ip/mysocket.py +12 -0
- pymodaq/utils/tcp_ip/serializer.py +13 -0
- pymodaq/utils/tcp_ip/tcp_server_client.py +772 -0
- pymodaq-5.1.6.dist-info/METADATA +238 -0
- pymodaq-5.1.6.dist-info/RECORD +154 -0
- pymodaq-5.1.6.dist-info/WHEEL +4 -0
- pymodaq-5.1.6.dist-info/entry_points.txt +7 -0
- pymodaq-5.1.6.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,772 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on Fri Aug 30 12:21:56 2019
|
|
4
|
+
|
|
5
|
+
@author: Weber
|
|
6
|
+
"""
|
|
7
|
+
from collections import OrderedDict
|
|
8
|
+
import select
|
|
9
|
+
from typing import List
|
|
10
|
+
import socket
|
|
11
|
+
from threading import Timer
|
|
12
|
+
|
|
13
|
+
import numpy as np
|
|
14
|
+
from qtpy.QtCore import QObject, Signal, Slot, QThread
|
|
15
|
+
from qtpy import QtWidgets
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
from pymodaq_utils.utils import getLineInfo, ThreadCommand
|
|
19
|
+
from pymodaq_utils import math_utils as mutils
|
|
20
|
+
from pymodaq_utils.config import Config
|
|
21
|
+
from pymodaq_gui.parameter import utils as putils
|
|
22
|
+
from pymodaq_gui.parameter import ioxml
|
|
23
|
+
from pymodaq_gui.parameter import Parameter
|
|
24
|
+
from pymodaq_data.data import DataToExport
|
|
25
|
+
|
|
26
|
+
from pymodaq.utils.data import DataFromPlugins, DataActuator
|
|
27
|
+
from pymodaq_utils.serialize.mysocket import Socket
|
|
28
|
+
from pymodaq_utils.serialize.serializer_legacy import Serializer, DeSerializer
|
|
29
|
+
from pymodaq_gui.managers.parameter_manager import ParameterManager
|
|
30
|
+
|
|
31
|
+
config = Config()
|
|
32
|
+
|
|
33
|
+
tcp_parameters = [
|
|
34
|
+
{'title': 'Port:', 'name': 'port_id', 'type': 'int', 'value': config('network', 'tcp-server', 'port'), },
|
|
35
|
+
{'title': 'IP:', 'name': 'socket_ip', 'type': 'str', 'value': config('network', 'tcp-server', 'ip'), },
|
|
36
|
+
{'title': 'Settings PyMoDAQ Client:', 'name': 'settings_client', 'type': 'group', 'children': []},
|
|
37
|
+
{'title': 'Infos Client:', 'name': 'infos', 'type': 'group', 'children': []},
|
|
38
|
+
{'title': 'Connected clients:', 'name': 'conn_clients', 'type': 'table',
|
|
39
|
+
'value': dict(), 'header': ['Type', 'adress']}, ]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class TCPClientTemplate:
|
|
43
|
+
def __init__(self, ipaddress="192.168.1.62", port=6341, client_type=""):
|
|
44
|
+
"""Create a socket client
|
|
45
|
+
|
|
46
|
+
Parameters
|
|
47
|
+
----------
|
|
48
|
+
ipaddress: (str) the IP address of the server
|
|
49
|
+
port: (int) the port where to communicate with the server
|
|
50
|
+
client_type: (str) should be one of the accepted client_type by the TCPServer instance (within pymodaq it is
|
|
51
|
+
either 'GRABBER' or 'ACTUATOR'
|
|
52
|
+
"""
|
|
53
|
+
#super().__init__()
|
|
54
|
+
|
|
55
|
+
self.ipaddress = ipaddress
|
|
56
|
+
self.port = port
|
|
57
|
+
self._socket: Socket = None
|
|
58
|
+
self._deserializer: DeSerializer = None
|
|
59
|
+
self.connected = False
|
|
60
|
+
self.client_type = client_type
|
|
61
|
+
self.timer = Timer(0.1, self.poll_connection)
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def socket(self) -> Socket:
|
|
65
|
+
return self._socket
|
|
66
|
+
|
|
67
|
+
@socket.setter
|
|
68
|
+
def socket(self, sock: Socket):
|
|
69
|
+
self._socket = sock
|
|
70
|
+
self._deserializer = DeSerializer(sock)
|
|
71
|
+
|
|
72
|
+
def close(self):
|
|
73
|
+
if self.socket is not None:
|
|
74
|
+
self.socket.close()
|
|
75
|
+
|
|
76
|
+
def _connect_socket(self):
|
|
77
|
+
# create an INET, STREAMing socket
|
|
78
|
+
self.socket = Socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
|
|
79
|
+
# now connect to the web server on port 80 - the normal http port
|
|
80
|
+
self.socket.connect((self.ipaddress, self.port))
|
|
81
|
+
|
|
82
|
+
def init_connection(self, extra_commands=[]):
|
|
83
|
+
"""init the socket connection then call the post_init method where to place custom
|
|
84
|
+
initialization"""
|
|
85
|
+
try:
|
|
86
|
+
self._connect_socket()
|
|
87
|
+
self.post_init(extra_commands)
|
|
88
|
+
self.connected = True
|
|
89
|
+
|
|
90
|
+
self.poll_connection()
|
|
91
|
+
#self.timer.start()
|
|
92
|
+
|
|
93
|
+
except ConnectionRefusedError as e:
|
|
94
|
+
self.not_connected(e)
|
|
95
|
+
self.connected = False
|
|
96
|
+
|
|
97
|
+
def poll_connection(self):
|
|
98
|
+
while True:
|
|
99
|
+
try:
|
|
100
|
+
ready_to_read, ready_to_write, in_error = \
|
|
101
|
+
select.select([self.socket.socket], [self.socket.socket], [self.socket.socket], 0)
|
|
102
|
+
|
|
103
|
+
if len(ready_to_read) != 0:
|
|
104
|
+
self.ready_to_read()
|
|
105
|
+
|
|
106
|
+
if len(in_error) != 0:
|
|
107
|
+
self.ready_with_error()
|
|
108
|
+
|
|
109
|
+
if len(ready_to_write) != 0:
|
|
110
|
+
self.ready_to_write()
|
|
111
|
+
|
|
112
|
+
QtWidgets.QApplication.processEvents()
|
|
113
|
+
|
|
114
|
+
except Exception as e:
|
|
115
|
+
self.process_error_in_polling(e)
|
|
116
|
+
break
|
|
117
|
+
|
|
118
|
+
def not_connected(self, e: ConnectionRefusedError):
|
|
119
|
+
raise NotImplementedError
|
|
120
|
+
|
|
121
|
+
def ready_to_read(self):
|
|
122
|
+
"""Do stuff (like read data) when messages arrive through the socket"""
|
|
123
|
+
raise NotImplementedError
|
|
124
|
+
|
|
125
|
+
def ready_to_write(self):
|
|
126
|
+
"""Send stuff into the socket"""
|
|
127
|
+
raise NotImplementedError
|
|
128
|
+
|
|
129
|
+
def ready_with_error(self):
|
|
130
|
+
"""Error in the socket communication"""
|
|
131
|
+
raise NotImplementedError
|
|
132
|
+
|
|
133
|
+
def process_error_in_polling(self, e: Exception):
|
|
134
|
+
raise NotImplementedError
|
|
135
|
+
|
|
136
|
+
def post_init(self, extra_commands=[]):
|
|
137
|
+
"""To implement in a real object implementation"""
|
|
138
|
+
raise NotImplementedError
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class TCPClient(TCPClientTemplate, QObject):
|
|
142
|
+
"""
|
|
143
|
+
PyQt5 object initializing a TCP socket client. Can be used by any module but is a builtin functionality of all
|
|
144
|
+
actuators and detectors of PyMoDAQ
|
|
145
|
+
|
|
146
|
+
The module should init TCPClient, move it in a thread and communicate with it using a custom signal connected to
|
|
147
|
+
TCPClient.queue_command slot. The module should also connect TCPClient.cmd_signal to one of its methods inorder to
|
|
148
|
+
get info/data back from the client
|
|
149
|
+
|
|
150
|
+
The client itself communicate with a TCP server, it is best to use a server object subclassing the TCPServer
|
|
151
|
+
class defined within this python module
|
|
152
|
+
|
|
153
|
+
Parameters
|
|
154
|
+
----------
|
|
155
|
+
params_state: (dict) state of the Parameter settings of the module instantiating this client and wishing to
|
|
156
|
+
export its settings to the server. Obtained from param.saveState() where param is an
|
|
157
|
+
instance of Parameter object, see pyqtgraph.parametertree::Parameter
|
|
158
|
+
|
|
159
|
+
"""
|
|
160
|
+
cmd_signal = Signal(ThreadCommand) # signal to connect with a module slot in order to start communication back
|
|
161
|
+
params = []
|
|
162
|
+
|
|
163
|
+
def __init__(self, ipaddress="192.168.1.62", port=6341, params_state=None,
|
|
164
|
+
client_type="GRABBER"):
|
|
165
|
+
"""Create a socket client particularly fit to be used with PyMoDAQ's TCPServer
|
|
166
|
+
|
|
167
|
+
Parameters
|
|
168
|
+
----------
|
|
169
|
+
ipaddress: (str) the IP address of the server
|
|
170
|
+
port: (int) the port where to communicate with the server
|
|
171
|
+
params_state: (dict) state of the Parameter settings of the module instantiating this client and wishing to
|
|
172
|
+
export its settings to the server. Obtained from param.saveState() where param is an
|
|
173
|
+
instance of Parameter object, see pyqtgraph.parametertree::Parameter
|
|
174
|
+
client_type: (str) should be one of the accepted client_type by the TCPServer instance (within pymodaq it is
|
|
175
|
+
either 'GRABBER' or 'ACTUATOR'
|
|
176
|
+
"""
|
|
177
|
+
QObject.__init__(self)
|
|
178
|
+
TCPClientTemplate.__init__(self, ipaddress, port, client_type)
|
|
179
|
+
|
|
180
|
+
self.settings = Parameter.create(name='Settings', type='group', children=self.params)
|
|
181
|
+
if params_state is not None:
|
|
182
|
+
if isinstance(params_state, dict):
|
|
183
|
+
self.settings.restoreState(params_state)
|
|
184
|
+
elif isinstance(params_state, Parameter):
|
|
185
|
+
self.settings.restoreState(params_state.saveState())
|
|
186
|
+
|
|
187
|
+
def send_data(self, data: DataToExport):
|
|
188
|
+
# first send 'Done' and then send the length of the list
|
|
189
|
+
if not isinstance(data, DataToExport):
|
|
190
|
+
raise TypeError(f'should send a DataToExport object')
|
|
191
|
+
if self.socket is not None:
|
|
192
|
+
self.socket.check_sended_with_serializer('Done')
|
|
193
|
+
self.socket.check_sended_with_serializer(data)
|
|
194
|
+
|
|
195
|
+
def send_infos_xml(self, infos: str):
|
|
196
|
+
if self.socket is not None:
|
|
197
|
+
self.socket.check_sended_with_serializer('Infos')
|
|
198
|
+
self.socket.check_sended_with_serializer(infos)
|
|
199
|
+
|
|
200
|
+
def send_info_string(self, info_to_display, value_as_string):
|
|
201
|
+
if self.socket is not None:
|
|
202
|
+
self.socket.check_sended_with_serializer('Info')
|
|
203
|
+
self.socket.check_sended_with_serializer(info_to_display) # the actual info to display as a string
|
|
204
|
+
if not isinstance(value_as_string, str):
|
|
205
|
+
value_as_string = str(value_as_string)
|
|
206
|
+
self.socket.check_sended_with_serializer(value_as_string)
|
|
207
|
+
|
|
208
|
+
@Slot(ThreadCommand)
|
|
209
|
+
def queue_command(self, command=ThreadCommand):
|
|
210
|
+
"""
|
|
211
|
+
when this TCPClient object is within a thread, the corresponding module communicate with it with signal and slots
|
|
212
|
+
from module to client: module_signal to queue_command slot
|
|
213
|
+
from client to module: self.cmd_signal to a module slot
|
|
214
|
+
"""
|
|
215
|
+
if command.command == "ini_connection":
|
|
216
|
+
status = self.init_connection()
|
|
217
|
+
|
|
218
|
+
elif command.command == "quit":
|
|
219
|
+
try:
|
|
220
|
+
self.socket.close()
|
|
221
|
+
except Exception as e:
|
|
222
|
+
pass
|
|
223
|
+
finally:
|
|
224
|
+
self.cmd_signal.emit(ThreadCommand('disconnected'))
|
|
225
|
+
|
|
226
|
+
elif command.command == 'update_connection':
|
|
227
|
+
self.ipaddress = command.attribute['ipaddress']
|
|
228
|
+
self.port = command.attribute['port']
|
|
229
|
+
|
|
230
|
+
elif command.command == 'data_ready':
|
|
231
|
+
self.data_ready(command.attribute)
|
|
232
|
+
|
|
233
|
+
elif command.command == 'send_info':
|
|
234
|
+
if self.socket is not None:
|
|
235
|
+
path = command.attribute['path']
|
|
236
|
+
param = command.attribute['param']
|
|
237
|
+
|
|
238
|
+
self.socket.check_sended_with_serializer('Info_xml')
|
|
239
|
+
self.socket.check_sended_with_serializer(path)
|
|
240
|
+
|
|
241
|
+
# send value
|
|
242
|
+
data = ioxml.parameter_to_xml_string(param)
|
|
243
|
+
self.socket.check_sended_with_serializer(data)
|
|
244
|
+
|
|
245
|
+
elif command.command == 'position_is':
|
|
246
|
+
if self.socket is not None:
|
|
247
|
+
self.socket.check_sended_with_serializer('position_is')
|
|
248
|
+
self.socket.check_sended_with_serializer(command.attribute)
|
|
249
|
+
|
|
250
|
+
elif command.command == 'move_done':
|
|
251
|
+
if self.socket is not None:
|
|
252
|
+
self.socket.check_sended_with_serializer('move_done')
|
|
253
|
+
self.socket.check_sended_with_serializer(command.attribute)
|
|
254
|
+
|
|
255
|
+
elif command.command == 'x_axis':
|
|
256
|
+
raise DeprecationWarning('Getting axis though TCPIP is deprecated use the data objects directly')
|
|
257
|
+
|
|
258
|
+
elif command.command == 'y_axis':
|
|
259
|
+
raise DeprecationWarning('Getting axis though TCPIP is deprecated use the data objects directly')
|
|
260
|
+
else:
|
|
261
|
+
raise IOError('Unknown TCP client command')
|
|
262
|
+
|
|
263
|
+
def not_connected(self, e):
|
|
264
|
+
self.connected = False
|
|
265
|
+
self.cmd_signal.emit(ThreadCommand('disconnected'))
|
|
266
|
+
self.cmd_signal.emit(ThreadCommand('Update_Status', [getLineInfo() + str(e), 'log']))
|
|
267
|
+
|
|
268
|
+
def ready_to_read(self):
|
|
269
|
+
message = self._deserializer.string_deserialization()
|
|
270
|
+
self.get_data(message)
|
|
271
|
+
|
|
272
|
+
def ready_to_write(self):
|
|
273
|
+
pass
|
|
274
|
+
|
|
275
|
+
def ready_with_error(self):
|
|
276
|
+
self.connected = False
|
|
277
|
+
self.cmd_signal.emit(ThreadCommand('disconnected'))
|
|
278
|
+
|
|
279
|
+
def process_error_in_polling(self, e: Exception):
|
|
280
|
+
try:
|
|
281
|
+
self.cmd_signal.emit(ThreadCommand('Update_Status', [getLineInfo() + str(e), 'log']))
|
|
282
|
+
self.socket.check_sended_with_serializer('Quit')
|
|
283
|
+
self.socket.close()
|
|
284
|
+
except Exception: # pragma: no cover
|
|
285
|
+
pass
|
|
286
|
+
|
|
287
|
+
def post_init(self, extra_commands=[]):
|
|
288
|
+
|
|
289
|
+
self.cmd_signal.emit(ThreadCommand('connected'))
|
|
290
|
+
self.socket.check_sended_with_serializer(self.client_type)
|
|
291
|
+
|
|
292
|
+
self.send_infos_xml(ioxml.parameter_to_xml_string(self.settings))
|
|
293
|
+
for command in extra_commands:
|
|
294
|
+
if isinstance(command, ThreadCommand):
|
|
295
|
+
self.cmd_signal.emit(command)
|
|
296
|
+
|
|
297
|
+
def get_data(self, message: str):
|
|
298
|
+
"""
|
|
299
|
+
|
|
300
|
+
Parameters
|
|
301
|
+
----------
|
|
302
|
+
message
|
|
303
|
+
|
|
304
|
+
Returns
|
|
305
|
+
-------
|
|
306
|
+
|
|
307
|
+
"""
|
|
308
|
+
if self.socket is not None:
|
|
309
|
+
messg = ThreadCommand(message)
|
|
310
|
+
|
|
311
|
+
if message == 'set_info':
|
|
312
|
+
path = self._deserializer.list_deserialization()
|
|
313
|
+
param_xml = self._deserializer.string_deserialization()
|
|
314
|
+
messg.attribute = [path, param_xml]
|
|
315
|
+
|
|
316
|
+
elif message == 'move_abs' or message == 'move_rel':
|
|
317
|
+
position = self._deserializer.dwa_deserialization()
|
|
318
|
+
messg.attribute = [position]
|
|
319
|
+
|
|
320
|
+
self.cmd_signal.emit(messg)
|
|
321
|
+
|
|
322
|
+
def data_ready(self, data: DataToExport):
|
|
323
|
+
self.send_data(data)
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
class TCPServer(QObject):
|
|
327
|
+
"""
|
|
328
|
+
Abstract class to be used as inherited by DAQ_Viewer_TCP or DAQ_Move_TCP
|
|
329
|
+
"""
|
|
330
|
+
|
|
331
|
+
def __init__(self, client_type='GRABBER'):
|
|
332
|
+
QObject.__init__(self)
|
|
333
|
+
self.serversocket: Socket = None
|
|
334
|
+
self.connected_clients = []
|
|
335
|
+
self.listening = True
|
|
336
|
+
self.processing = False
|
|
337
|
+
self.client_type = client_type
|
|
338
|
+
|
|
339
|
+
def close_server(self):
|
|
340
|
+
"""
|
|
341
|
+
close the current opened server.
|
|
342
|
+
Update the settings tree consequently.
|
|
343
|
+
|
|
344
|
+
See Also
|
|
345
|
+
--------
|
|
346
|
+
set_connected_clients_table, daq_utils.ThreadCommand
|
|
347
|
+
"""
|
|
348
|
+
server_socket = self.find_socket_within_connected_clients('server')
|
|
349
|
+
self.remove_client(server_socket)
|
|
350
|
+
|
|
351
|
+
def init_server(self):
|
|
352
|
+
self.emit_status(ThreadCommand("Update_Status", [
|
|
353
|
+
"Started new server for {:s}:{:d}".format(self.settings['socket_ip'],
|
|
354
|
+
self.settings['port_id']), 'log']))
|
|
355
|
+
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
356
|
+
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
357
|
+
self.serversocket = Socket(serversocket)
|
|
358
|
+
# bind the socket to a public host, and a well-known port
|
|
359
|
+
try:
|
|
360
|
+
self.serversocket.bind(
|
|
361
|
+
(self.settings['socket_ip'], self.settings['port_id']))
|
|
362
|
+
# self.serversocket.bind((socket.gethostname(), self.settings.child(('port_id')).value()))
|
|
363
|
+
except socket.error as msg:
|
|
364
|
+
self.emit_status(ThreadCommand("Update_Status",
|
|
365
|
+
['Bind failed. Error Code : ' + str(msg.errno) + ' Message ' + msg.strerror,
|
|
366
|
+
'log']))
|
|
367
|
+
raise ConnectionError('Bind failed. Error Code : ' + str(msg.errno) + ' Message ' + msg.strerror)
|
|
368
|
+
|
|
369
|
+
self.serversocket.listen(1)
|
|
370
|
+
self.connected_clients.append(dict(socket=self.serversocket, type='server'))
|
|
371
|
+
self.settings.child('conn_clients').setValue(self.set_connected_clients_table())
|
|
372
|
+
|
|
373
|
+
self.timer = self.startTimer(100) # Timer event fired every 100ms
|
|
374
|
+
# self.listen_client()
|
|
375
|
+
|
|
376
|
+
def timerEvent(self, event):
|
|
377
|
+
"""
|
|
378
|
+
Called by set timers.
|
|
379
|
+
If the process is free, start the listen_client function.
|
|
380
|
+
|
|
381
|
+
=============== ==================== ==============================================
|
|
382
|
+
**Parameters** **Type** **Description**
|
|
383
|
+
|
|
384
|
+
*event* QTimerEvent object Containing id from timer issuing this event
|
|
385
|
+
=============== ==================== ==============================================
|
|
386
|
+
|
|
387
|
+
See Also
|
|
388
|
+
--------
|
|
389
|
+
listen_client
|
|
390
|
+
"""
|
|
391
|
+
if not self.processing:
|
|
392
|
+
self.listen_client()
|
|
393
|
+
|
|
394
|
+
def find_socket_within_connected_clients(self, client_type) -> Socket:
|
|
395
|
+
"""
|
|
396
|
+
Find a socket from a connected client with socket type corresponding.
|
|
397
|
+
|
|
398
|
+
=============== =========== ================================
|
|
399
|
+
**Parameters** **Type** **Description**
|
|
400
|
+
*client_type* string The corresponding client type
|
|
401
|
+
=============== =========== ================================
|
|
402
|
+
|
|
403
|
+
Returns
|
|
404
|
+
-------
|
|
405
|
+
dictionnary
|
|
406
|
+
the socket dictionnary
|
|
407
|
+
"""
|
|
408
|
+
res = None
|
|
409
|
+
for socket_dict in self.connected_clients:
|
|
410
|
+
if socket_dict['type'] == client_type:
|
|
411
|
+
res = socket_dict['socket']
|
|
412
|
+
return res
|
|
413
|
+
|
|
414
|
+
def find_socket_type_within_connected_clients(self, sock):
|
|
415
|
+
"""
|
|
416
|
+
Find a socket type from a connected client with socket content corresponding.
|
|
417
|
+
|
|
418
|
+
=============== =========== ===================================
|
|
419
|
+
**Parameters** **Type** **Description**
|
|
420
|
+
*sock* ??? The socket content corresponding.
|
|
421
|
+
=============== =========== ===================================
|
|
422
|
+
|
|
423
|
+
Returns
|
|
424
|
+
-------
|
|
425
|
+
dictionnary
|
|
426
|
+
the socket dictionnary
|
|
427
|
+
"""
|
|
428
|
+
res = None
|
|
429
|
+
for socket_dict in self.connected_clients:
|
|
430
|
+
if socket_dict['socket'] == sock:
|
|
431
|
+
res = socket_dict['type']
|
|
432
|
+
return res
|
|
433
|
+
|
|
434
|
+
def set_connected_clients_table(self):
|
|
435
|
+
"""
|
|
436
|
+
|
|
437
|
+
"""
|
|
438
|
+
con_clients = OrderedDict()
|
|
439
|
+
for socket_dict in self.connected_clients:
|
|
440
|
+
try:
|
|
441
|
+
address = str(socket_dict['socket'].getsockname())
|
|
442
|
+
except Exception:
|
|
443
|
+
address = "unconnected invalid socket"
|
|
444
|
+
con_clients[socket_dict['type']] = address
|
|
445
|
+
return con_clients
|
|
446
|
+
|
|
447
|
+
@Slot(list)
|
|
448
|
+
def print_status(self, status):
|
|
449
|
+
"""
|
|
450
|
+
Print the given status.
|
|
451
|
+
|
|
452
|
+
=============== ============= ================================================
|
|
453
|
+
**Parameters** **Type** **Description**
|
|
454
|
+
*status* string list a string list representing the status socket
|
|
455
|
+
=============== ============= ================================================
|
|
456
|
+
"""
|
|
457
|
+
print(status)
|
|
458
|
+
|
|
459
|
+
def remove_client(self, sock):
|
|
460
|
+
sock_type = self.find_socket_type_within_connected_clients(sock)
|
|
461
|
+
if sock_type is not None:
|
|
462
|
+
self.connected_clients.remove(dict(socket=sock, type=sock_type))
|
|
463
|
+
self.settings.child('conn_clients').setValue(self.set_connected_clients_table())
|
|
464
|
+
try:
|
|
465
|
+
sock.close()
|
|
466
|
+
except Exception:
|
|
467
|
+
pass
|
|
468
|
+
self.emit_status(ThreadCommand("Update_Status", ['Client ' + sock_type + ' disconnected', 'log']))
|
|
469
|
+
|
|
470
|
+
def select(self, rlist, wlist=[], xlist=[], timeout=0):
|
|
471
|
+
"""
|
|
472
|
+
Implements the select method, https://docs.python.org/3/library/select.html
|
|
473
|
+
Parameters
|
|
474
|
+
----------
|
|
475
|
+
rlist: (list) wait until ready for reading
|
|
476
|
+
wlist: (list) wait until ready for writing
|
|
477
|
+
xlist: (list) wait for an “exceptional condition”
|
|
478
|
+
timeout: (float) optional timeout argument specifies a time-out as a floating point number in seconds.
|
|
479
|
+
When the timeout argument is omitted the function blocks until at least one file descriptor is ready.
|
|
480
|
+
A time-out value of zero specifies a poll and never blocks.
|
|
481
|
+
|
|
482
|
+
Returns
|
|
483
|
+
-------
|
|
484
|
+
list: readable sockets
|
|
485
|
+
list: writable sockets
|
|
486
|
+
list: sockets with error pending
|
|
487
|
+
"""
|
|
488
|
+
|
|
489
|
+
read_sockets, write_sockets, error_sockets = select.select([sock.socket for sock in rlist],
|
|
490
|
+
[sock.socket for sock in wlist],
|
|
491
|
+
[sock.socket for sock in xlist],
|
|
492
|
+
timeout)
|
|
493
|
+
|
|
494
|
+
return ([Socket(sock) for sock in read_sockets], [Socket(sock) for sock in write_sockets],
|
|
495
|
+
[Socket(sock) for sock in error_sockets])
|
|
496
|
+
|
|
497
|
+
def listen_client(self):
|
|
498
|
+
"""
|
|
499
|
+
Server function.
|
|
500
|
+
Used to connect or listen incoming message from a client.
|
|
501
|
+
"""
|
|
502
|
+
try:
|
|
503
|
+
self.processing = True
|
|
504
|
+
# QtWidgets.QApplication.processEvents() #to let external commands in
|
|
505
|
+
read_sockets, write_sockets, error_sockets = self.select(
|
|
506
|
+
[client['socket'] for client in self.connected_clients], [],
|
|
507
|
+
[client['socket'] for client in self.connected_clients],
|
|
508
|
+
0)
|
|
509
|
+
for sock in error_sockets:
|
|
510
|
+
self.remove_client(sock)
|
|
511
|
+
|
|
512
|
+
for sock in read_sockets:
|
|
513
|
+
QThread.msleep(100)
|
|
514
|
+
if sock == self.serversocket: # New connection
|
|
515
|
+
# means a new socket (client) try to reach the server
|
|
516
|
+
(client_socket, address) = self.serversocket.accept()
|
|
517
|
+
DAQ_type = DeSerializer(client_socket).string_deserialization()
|
|
518
|
+
if DAQ_type not in self.socket_types:
|
|
519
|
+
self.emit_status(ThreadCommand("Update_Status", [DAQ_type + ' is not a valid type', 'log']))
|
|
520
|
+
client_socket.close()
|
|
521
|
+
break
|
|
522
|
+
|
|
523
|
+
self.connected_clients.append(dict(socket=client_socket, type=DAQ_type))
|
|
524
|
+
self.settings.child('conn_clients').setValue(self.set_connected_clients_table())
|
|
525
|
+
self.emit_status(ThreadCommand("Update_Status",
|
|
526
|
+
[DAQ_type + ' connected with ' + address[0] + ':' + str(address[1]),
|
|
527
|
+
'log']))
|
|
528
|
+
QtWidgets.QApplication.processEvents()
|
|
529
|
+
|
|
530
|
+
else: # Some incoming message from a client
|
|
531
|
+
# Data received from client, process it
|
|
532
|
+
try:
|
|
533
|
+
message = DeSerializer(sock).string_deserialization()
|
|
534
|
+
if message in ['Done', 'Info', 'Infos', 'Info_xml', 'position_is', 'move_done']:
|
|
535
|
+
self.process_cmds(message, command_sock=None)
|
|
536
|
+
elif message == 'Quit':
|
|
537
|
+
raise Exception("socket disconnect by user")
|
|
538
|
+
else:
|
|
539
|
+
self.process_cmds(message, command_sock=sock)
|
|
540
|
+
|
|
541
|
+
# client disconnected, so remove from socket list
|
|
542
|
+
except Exception as e:
|
|
543
|
+
self.remove_client(sock)
|
|
544
|
+
|
|
545
|
+
self.processing = False
|
|
546
|
+
|
|
547
|
+
except Exception as e:
|
|
548
|
+
self.emit_status(ThreadCommand("Update_Status", [str(e), 'log']))
|
|
549
|
+
|
|
550
|
+
def send_command(self, sock: Socket, command="move_at"):
|
|
551
|
+
"""
|
|
552
|
+
Send one of the message contained in self.message_list toward a socket with identity socket_type.
|
|
553
|
+
First send the length of the command with 4bytes.
|
|
554
|
+
|
|
555
|
+
=============== =========== ==========================
|
|
556
|
+
**Parameters** **Type** **Description**
|
|
557
|
+
*sock* ??? The current socket
|
|
558
|
+
*command* string The command as a string
|
|
559
|
+
=============== =========== ==========================
|
|
560
|
+
|
|
561
|
+
See Also
|
|
562
|
+
--------
|
|
563
|
+
utility_classes.DAQ_Viewer_base.emit_status, daq_utils.ThreadCommand, message_to_bytes
|
|
564
|
+
"""
|
|
565
|
+
if command not in self.message_list:
|
|
566
|
+
self.emit_status(
|
|
567
|
+
ThreadCommand("Update_Status", [f'Command: {command} is not in the specified list: {self.message_list}',
|
|
568
|
+
'log']))
|
|
569
|
+
return
|
|
570
|
+
|
|
571
|
+
if sock is not None:
|
|
572
|
+
sock.check_sended_with_serializer(command)
|
|
573
|
+
|
|
574
|
+
def emit_status(self, status):
|
|
575
|
+
print(status)
|
|
576
|
+
|
|
577
|
+
def read_data(self, sock):
|
|
578
|
+
pass
|
|
579
|
+
|
|
580
|
+
def send_data(self, sock, data):
|
|
581
|
+
pass
|
|
582
|
+
|
|
583
|
+
def command_done(self, command_sock):
|
|
584
|
+
pass
|
|
585
|
+
|
|
586
|
+
def command_to_from_client(self, command):
|
|
587
|
+
pass
|
|
588
|
+
|
|
589
|
+
def process_cmds(self, command, command_sock=None):
|
|
590
|
+
"""
|
|
591
|
+
Process the given command.
|
|
592
|
+
"""
|
|
593
|
+
if command not in self.message_list:
|
|
594
|
+
self.emit_status(
|
|
595
|
+
ThreadCommand("Update_Status", [f'Command: {command} is not in the specified list: {self.message_list}',
|
|
596
|
+
'log']))
|
|
597
|
+
return
|
|
598
|
+
|
|
599
|
+
if command == 'Done': # means the given socket finished grabbing data and is ready to send them
|
|
600
|
+
self.command_done(command_sock)
|
|
601
|
+
|
|
602
|
+
elif command == "Infos":
|
|
603
|
+
"""replace entirely the client settings information on the server widget
|
|
604
|
+
should be done as the init of the client module"""
|
|
605
|
+
try:
|
|
606
|
+
sock = self.find_socket_within_connected_clients(self.client_type)
|
|
607
|
+
if sock is not None: # if client self.client_type is connected then send it the command
|
|
608
|
+
self.read_infos(sock)
|
|
609
|
+
|
|
610
|
+
except Exception as e:
|
|
611
|
+
self.emit_status(ThreadCommand("Update_Status", [str(e), 'log']))
|
|
612
|
+
|
|
613
|
+
elif command == 'Info_xml':
|
|
614
|
+
"""update the state of one of the client settings on the server widget"""
|
|
615
|
+
sock = self.find_socket_within_connected_clients(self.client_type)
|
|
616
|
+
if sock is not None:
|
|
617
|
+
self.read_info_xml(sock)
|
|
618
|
+
|
|
619
|
+
elif command == "Info":
|
|
620
|
+
# add a custom info (as a string value) in the server widget settings. To be used if the client is not a
|
|
621
|
+
# PyMoDAQ's module
|
|
622
|
+
|
|
623
|
+
try:
|
|
624
|
+
sock = self.find_socket_within_connected_clients(self.client_type)
|
|
625
|
+
if sock is not None: # if client self.client_type is connected then send it the command
|
|
626
|
+
self.read_info(sock)
|
|
627
|
+
except Exception as e:
|
|
628
|
+
self.emit_status(ThreadCommand("Update_Status", [str(e), 'log']))
|
|
629
|
+
|
|
630
|
+
else:
|
|
631
|
+
self.command_to_from_client(command)
|
|
632
|
+
|
|
633
|
+
def read_infos(self, sock: Socket = None, infos=''):
|
|
634
|
+
if sock is not None:
|
|
635
|
+
infos = DeSerializer(sock).string_deserialization()
|
|
636
|
+
params = ioxml.XML_string_to_parameter(infos)
|
|
637
|
+
|
|
638
|
+
param_state = {'title': 'Infos Client:', 'name': 'settings_client', 'type': 'group', 'children': params}
|
|
639
|
+
self.settings.child('settings_client').restoreState(param_state)
|
|
640
|
+
|
|
641
|
+
def read_info_xml(self, sock: Socket, path=['settings', 'apathinsettings'], param_xml=''):
|
|
642
|
+
if sock is not None:
|
|
643
|
+
deser = DeSerializer(sock)
|
|
644
|
+
path = deser.list_deserialization()
|
|
645
|
+
param_xml = deser.string_deserialization()
|
|
646
|
+
try:
|
|
647
|
+
param_dict = ioxml.XML_string_to_parameter(param_xml)[0]
|
|
648
|
+
except Exception as e:
|
|
649
|
+
raise Exception(f'Invalid xml structure for TCP server settings: {str(e)}')
|
|
650
|
+
try:
|
|
651
|
+
param_here = self.settings.child('settings_client', *path[1:])
|
|
652
|
+
except Exception as e:
|
|
653
|
+
raise Exception(f'Invalid path for TCP server settings: {str(e)}')
|
|
654
|
+
param_here.restoreState(param_dict)
|
|
655
|
+
|
|
656
|
+
def read_info(self, sock: Socket=None, test_info='an_info', test_value=''):
|
|
657
|
+
"""
|
|
658
|
+
if the client is not from PyMoDAQ it can use this method to display some info into the server widget
|
|
659
|
+
"""
|
|
660
|
+
# #first get the info type
|
|
661
|
+
if sock is None:
|
|
662
|
+
info = test_info
|
|
663
|
+
data = test_value
|
|
664
|
+
else:
|
|
665
|
+
deser = DeSerializer(sock)
|
|
666
|
+
info = deser.string_deserialization()
|
|
667
|
+
data = deser.string_deserialization()
|
|
668
|
+
|
|
669
|
+
if info not in putils.iter_children(self.settings.child('infos'), []):
|
|
670
|
+
self.settings.child('infos').addChild({'name': info, 'type': 'str', 'value': data})
|
|
671
|
+
pass
|
|
672
|
+
else:
|
|
673
|
+
self.settings.child('infos', info).setValue(data)
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
class MockServer(TCPServer):
|
|
677
|
+
params = []
|
|
678
|
+
|
|
679
|
+
def __init__(self, client_type='GRABBER'):
|
|
680
|
+
super().__init__(client_type)
|
|
681
|
+
|
|
682
|
+
self.settings = Parameter.create(name='settings', type='group', children=tcp_parameters)
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
class MockDataGrabber:
|
|
686
|
+
|
|
687
|
+
def __init__(self, grabber_dim='2D'):
|
|
688
|
+
super().__init__()
|
|
689
|
+
self.Nx = 256
|
|
690
|
+
self.Ny = 128
|
|
691
|
+
self.x_axis = np.linspace(0, self.Nx-1, self.Nx)
|
|
692
|
+
self.y_axis = np.linspace(0, self.Ny-1, self.Ny)
|
|
693
|
+
self.grabber_dim = grabber_dim
|
|
694
|
+
|
|
695
|
+
def grab(self) -> List[DataFromPlugins]:
|
|
696
|
+
if self.grabber_dim == '0D':
|
|
697
|
+
return [DataFromPlugins(data=[np.array([np.random.rand()])])]
|
|
698
|
+
|
|
699
|
+
elif self.grabber_dim == '1D':
|
|
700
|
+
return [DataFromPlugins(data=[mutils.gauss1D(self.x_axis, 128, 25) +
|
|
701
|
+
np.random.rand(self.Nx)])]
|
|
702
|
+
|
|
703
|
+
elif self.grabber_dim == '2D':
|
|
704
|
+
return [DataFromPlugins(data=[mutils.gauss2D(self.x_axis, 128, 65,
|
|
705
|
+
self.y_axis, 60, 10) +
|
|
706
|
+
np.random.rand(self.Ny, self.Nx)])]
|
|
707
|
+
|
|
708
|
+
|
|
709
|
+
class Grabber(QObject):
|
|
710
|
+
command_tcpip = Signal(ThreadCommand)
|
|
711
|
+
|
|
712
|
+
def __init__(self, grab_method=None):
|
|
713
|
+
super().__init__()
|
|
714
|
+
self.send_to_tcpip = False
|
|
715
|
+
self.grab_method = grab_method
|
|
716
|
+
|
|
717
|
+
def connect_tcp_ip(self, ip='localhost', port=6341):
|
|
718
|
+
self.tcpclient_thread = QThread()
|
|
719
|
+
tcpclient = TCPClient(ip, port=port)
|
|
720
|
+
|
|
721
|
+
tcpclient.moveToThread(self.tcpclient_thread)
|
|
722
|
+
self.tcpclient_thread.tcpclient = tcpclient
|
|
723
|
+
tcpclient.cmd_signal.connect(self.process_tcpip_cmds)
|
|
724
|
+
|
|
725
|
+
self.command_tcpip[ThreadCommand].connect(tcpclient.queue_command)
|
|
726
|
+
|
|
727
|
+
self.tcpclient_thread.start()
|
|
728
|
+
#tcpclient.init_connection(extra_commands=[ThreadCommand('get_axis', )])
|
|
729
|
+
tcpclient.init_connection()
|
|
730
|
+
self.send_to_tcpip = True
|
|
731
|
+
|
|
732
|
+
def snapshot(self, info='', send_to_tcpip=True):
|
|
733
|
+
self.grab_data()
|
|
734
|
+
|
|
735
|
+
def grab_data(self):
|
|
736
|
+
"""
|
|
737
|
+
Do a grab session using 2 profile :
|
|
738
|
+
* if grab pb checked do a continous save and send an "update_channels" thread command and a "grab" too.
|
|
739
|
+
* if not send a "stop_grab" thread command with settings "main settings-naverage" node value as an attribute.
|
|
740
|
+
|
|
741
|
+
See Also
|
|
742
|
+
--------
|
|
743
|
+
daq_utils.ThreadCommand, set_enabled_Ini_buttons
|
|
744
|
+
"""
|
|
745
|
+
data = self.grab_method()
|
|
746
|
+
self.command_tcpip.emit(ThreadCommand('data_ready', data))
|
|
747
|
+
|
|
748
|
+
@Slot(ThreadCommand)
|
|
749
|
+
def process_tcpip_cmds(self, status):
|
|
750
|
+
if 'Send Data' in status.command:
|
|
751
|
+
self.snapshot('', send_to_tcpip=True)
|
|
752
|
+
|
|
753
|
+
elif status.command == 'connected':
|
|
754
|
+
#self.settings.child('main_settings', 'tcpip', 'tcp_connected').setValue(True)
|
|
755
|
+
pass
|
|
756
|
+
|
|
757
|
+
elif status.command == 'disconnected':
|
|
758
|
+
#self.settings.child('main_settings', 'tcpip', 'tcp_connected').setValue(False)
|
|
759
|
+
pass
|
|
760
|
+
|
|
761
|
+
elif status.command == 'Update_Status':
|
|
762
|
+
print(status)
|
|
763
|
+
|
|
764
|
+
|
|
765
|
+
if __name__ == '__main__': # pragma: no cover
|
|
766
|
+
import sys
|
|
767
|
+
app = QtWidgets.QApplication(sys.argv)
|
|
768
|
+
mockdata_grabber = MockDataGrabber('2D')
|
|
769
|
+
grabber = Grabber(mockdata_grabber.grab)
|
|
770
|
+
grabber.connect_tcp_ip()
|
|
771
|
+
|
|
772
|
+
sys.exit(app.exec_())
|