MultiPyVu 2.1.4__tar.gz → 2.2.0__tar.gz
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.
- {MultiPyVu-2.1.4/src/MultiPyVu.egg-info → MultiPyVu-2.2.0}/PKG-INFO +7 -1
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/README.md +6 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/CommandChamber.py +23 -14
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/CommandField.py +15 -6
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/CommandMultiVu_base.py +2 -6
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/CommandTemperature.py +20 -9
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/Command_factory.py +4 -3
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/MultiVuClient_base.py +2 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/MultiVuServer.py +10 -2
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/__version.py +1 -1
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/instrument.py +33 -35
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0/src/MultiPyVu.egg-info}/PKG-INFO +7 -1
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/LICENSE +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/pyproject.toml +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/setup.cfg +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/setup.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/BRT.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/CommandMultiVu_imp.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/CommandMultiVu_sim.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/CommandSdo.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/Controller.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/ICommand.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/IController.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/IView.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/MultiVuClient.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/MultiVuDataFile/MultiVuDataFile.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/MultiVuDataFile/__init__.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/MultiVuDataFile/__version.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/MultiVuDataFile/is_pathname_valid.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/ParseInputs.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/ServerEventManager.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/SocketMessage.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/SocketMessageClient.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/SocketMessageServer.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/ViewFactory.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/ViewTk.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/__init__.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/__main__.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/create_logger.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/exceptions.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/font/Play-Bold.ttf +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/font/Play-Regular.ttf +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/generate_sdo_objects.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/images/Q.png +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/images/QD_logo.jpg +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/project_vars.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/scripts/whats_my_ip_address.cmd +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu/sdo_object.py +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu.egg-info/SOURCES.txt +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu.egg-info/dependency_links.txt +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiPyVu.egg-info/top_level.txt +0 -0
- {MultiPyVu-2.1.4 → MultiPyVu-2.2.0}/src/MultiVuDataFile/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: MultiPyVu
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Control MultiVu using Python
|
|
5
5
|
Author-email: Damon D Jackson <djackson@qdusa.com>
|
|
6
6
|
Maintainer-email: "Quantum Design, Inc." <apps@qdusa.com>
|
|
@@ -383,6 +383,12 @@ client = mpv.Client(port=6000)
|
|
|
383
383
|
- A log file named QdMultiVu.log shows the traffic between the server and client which can also be useful during troubleshooting.
|
|
384
384
|
|
|
385
385
|
## Changelog<a class="anchor" id="changelog"></a>
|
|
386
|
+
**2.2.0**
|
|
387
|
+
- January 2024
|
|
388
|
+
- Corrected a bug that prevented the Server from recognizing PPMS and MPMS3 MultiVu flavors
|
|
389
|
+
- Log the version number when the Client connects to the Server
|
|
390
|
+
- Remove unwanted warnings when quitting the Server using the esc-key.
|
|
391
|
+
|
|
386
392
|
**2.1.4**
|
|
387
393
|
- October 2023
|
|
388
394
|
- Import full module as MultiPyVu. Instead of loading the three sub-modules as:
|
|
@@ -342,6 +342,12 @@ client = mpv.Client(port=6000)
|
|
|
342
342
|
- A log file named QdMultiVu.log shows the traffic between the server and client which can also be useful during troubleshooting.
|
|
343
343
|
|
|
344
344
|
## Changelog<a class="anchor" id="changelog"></a>
|
|
345
|
+
**2.2.0**
|
|
346
|
+
- January 2024
|
|
347
|
+
- Corrected a bug that prevented the Server from recognizing PPMS and MPMS3 MultiVu flavors
|
|
348
|
+
- Log the version number when the Client connects to the Server
|
|
349
|
+
- Remove unwanted warnings when quitting the Server using the esc-key.
|
|
350
|
+
|
|
345
351
|
**2.1.4**
|
|
346
352
|
- October 2023
|
|
347
353
|
- Import full module as MultiPyVu. Instead of loading the three sub-modules as:
|
|
@@ -48,7 +48,7 @@ class CommandChamberBase(ICommand):
|
|
|
48
48
|
self.instrument_name = instrument_name
|
|
49
49
|
|
|
50
50
|
# State code dictionary
|
|
51
|
-
self.
|
|
51
|
+
self._state_dictionary = {
|
|
52
52
|
0: 'Unknown',
|
|
53
53
|
1: 'Purged and Sealed',
|
|
54
54
|
2: 'Vented and Sealed',
|
|
@@ -71,22 +71,22 @@ class CommandChamberBase(ICommand):
|
|
|
71
71
|
mode_setting: IntEnum,
|
|
72
72
|
mode_readback):
|
|
73
73
|
if mode_setting == self.mode.seal:
|
|
74
|
-
returnTrue = [self.
|
|
75
|
-
self.
|
|
76
|
-
self.
|
|
74
|
+
returnTrue = [self._state_dictionary[1],
|
|
75
|
+
self._state_dictionary[2],
|
|
76
|
+
self._state_dictionary[3],
|
|
77
77
|
]
|
|
78
78
|
if mode_readback in returnTrue:
|
|
79
79
|
return True
|
|
80
80
|
elif mode_setting == self.mode.purge_seal:
|
|
81
|
-
return (mode_readback == self.
|
|
81
|
+
return (mode_readback == self._state_dictionary[1])
|
|
82
82
|
elif mode_setting == self.mode.vent_seal:
|
|
83
|
-
return (mode_readback == self.
|
|
83
|
+
return (mode_readback == self._state_dictionary[2])
|
|
84
84
|
elif mode_setting == self.mode.pump_continuous:
|
|
85
|
-
return (mode_readback == self.
|
|
85
|
+
return (mode_readback == self._state_dictionary[8])
|
|
86
86
|
elif mode_setting == self.mode.vent_continuous:
|
|
87
|
-
return (mode_readback == self.
|
|
87
|
+
return (mode_readback == self._state_dictionary[9])
|
|
88
88
|
elif mode_setting == self.mode.high_vacuum:
|
|
89
|
-
return (mode_readback == self.
|
|
89
|
+
return (mode_readback == self._state_dictionary[7])
|
|
90
90
|
|
|
91
91
|
def convert_result(self, response: Dict) -> Tuple:
|
|
92
92
|
'''
|
|
@@ -121,7 +121,10 @@ class CommandChamberBase(ICommand):
|
|
|
121
121
|
return f'{mode_as_int}'
|
|
122
122
|
|
|
123
123
|
def convert_state_dictionary(self, status_number):
|
|
124
|
-
|
|
124
|
+
if isinstance(status_number, str):
|
|
125
|
+
return status_number
|
|
126
|
+
else:
|
|
127
|
+
return self._state_dictionary[status_number]
|
|
125
128
|
|
|
126
129
|
@abstractmethod
|
|
127
130
|
def get_state_server(self, value_variant, state_variant, params=''):
|
|
@@ -148,7 +151,7 @@ class CommandChamberBase(ICommand):
|
|
|
148
151
|
return self.set_state_server_imp(set_mode)
|
|
149
152
|
|
|
150
153
|
def state_code_dict(self):
|
|
151
|
-
return self.
|
|
154
|
+
return self._state_dictionary
|
|
152
155
|
|
|
153
156
|
|
|
154
157
|
############################
|
|
@@ -181,10 +184,16 @@ class CommandChamberImp(CommandChamberBase):
|
|
|
181
184
|
return '', return_state
|
|
182
185
|
|
|
183
186
|
def set_state_server_imp(self, mode: int) -> Union[str, int]:
|
|
184
|
-
|
|
185
|
-
if
|
|
187
|
+
can_error = self._mvu.SetChamber(mode)
|
|
188
|
+
if self.instrument_name == 'PPMS':
|
|
189
|
+
if can_error > 1:
|
|
190
|
+
raise MultiPyVuError('Error when calling SetChamber()')
|
|
191
|
+
else:
|
|
192
|
+
# returning this string makes CommandMultiVu_base happy
|
|
193
|
+
return 'Call was successful'
|
|
194
|
+
elif can_error > 0:
|
|
186
195
|
raise MultiPyVuError('Error when calling SetChamber()')
|
|
187
|
-
return
|
|
196
|
+
return can_error
|
|
188
197
|
|
|
189
198
|
|
|
190
199
|
############################
|
|
@@ -58,7 +58,7 @@ class CommandFieldBase(ICommand):
|
|
|
58
58
|
self.instrument_name = instrument_name
|
|
59
59
|
|
|
60
60
|
# Field state code dictionary
|
|
61
|
-
self.
|
|
61
|
+
self._state_dictionary = {
|
|
62
62
|
1: 'Stable',
|
|
63
63
|
2: 'Switch Warming',
|
|
64
64
|
3: 'Switch Cooling',
|
|
@@ -131,7 +131,10 @@ class CommandFieldBase(ICommand):
|
|
|
131
131
|
return f'{set_point},{rate_per_sec},{approach.value},{mode}'
|
|
132
132
|
|
|
133
133
|
def convert_state_dictionary(self, status_number):
|
|
134
|
-
|
|
134
|
+
if isinstance(status_number, str):
|
|
135
|
+
return status_number
|
|
136
|
+
else:
|
|
137
|
+
return self._state_dictionary[status_number]
|
|
135
138
|
|
|
136
139
|
@abstractmethod
|
|
137
140
|
def get_state_server(self, value_variant, state_variant, params=''):
|
|
@@ -193,7 +196,7 @@ class CommandFieldBase(ICommand):
|
|
|
193
196
|
return error
|
|
194
197
|
|
|
195
198
|
def state_code_dict(self):
|
|
196
|
-
return self.
|
|
199
|
+
return self._state_dictionary
|
|
197
200
|
|
|
198
201
|
|
|
199
202
|
############################
|
|
@@ -240,14 +243,20 @@ class CommandFieldImp(CommandFieldBase):
|
|
|
240
243
|
set_driven: int
|
|
241
244
|
) -> Union[str, int]:
|
|
242
245
|
try:
|
|
243
|
-
|
|
246
|
+
can_error = self._mvu.setField(field,
|
|
244
247
|
set_rate_per_sec,
|
|
245
248
|
set_approach,
|
|
246
249
|
set_driven
|
|
247
250
|
)
|
|
248
|
-
if
|
|
251
|
+
if self.instrument_name == 'PPMS':
|
|
252
|
+
if can_error > 1:
|
|
253
|
+
raise MultiPyVuError('Error when calling SetField()')
|
|
254
|
+
else:
|
|
255
|
+
# returning this string makes CommandMultiVu_base happy
|
|
256
|
+
return 'Call was successful'
|
|
257
|
+
elif can_error > 0:
|
|
249
258
|
raise MultiPyVuError('Error when calling SetField()')
|
|
250
|
-
return
|
|
259
|
+
return can_error
|
|
251
260
|
except AttributeError:
|
|
252
261
|
# this will raise a pywin_com_error if it is bad
|
|
253
262
|
return str(self._mvu)
|
|
@@ -67,7 +67,7 @@ class CommandMultiVuBase():
|
|
|
67
67
|
result_string = result if type(result) == str else f'{result:.4f}'
|
|
68
68
|
return f'{result_string},{mv_command.units},{code_in_words}'
|
|
69
69
|
|
|
70
|
-
def set_state(self, command, arg_string)
|
|
70
|
+
def set_state(self, command, arg_string):
|
|
71
71
|
'''
|
|
72
72
|
Sets the state for a given command using the arg_string for parameters
|
|
73
73
|
|
|
@@ -82,10 +82,6 @@ class CommandMultiVuBase():
|
|
|
82
82
|
FIELD: set point, rate, approach, and magnetic state.
|
|
83
83
|
CHAMBER: mode
|
|
84
84
|
|
|
85
|
-
Returns:
|
|
86
|
-
--------
|
|
87
|
-
str: Error message
|
|
88
|
-
|
|
89
85
|
Raises
|
|
90
86
|
------
|
|
91
87
|
MultiVuExeException
|
|
@@ -105,7 +101,7 @@ class CommandMultiVuBase():
|
|
|
105
101
|
msg = f'Error when setting the {command} {arg_string}: '
|
|
106
102
|
msg += f'error = {err}'
|
|
107
103
|
raise MultiPyVuError(msg)
|
|
108
|
-
|
|
104
|
+
|
|
109
105
|
if isinstance(err, str):
|
|
110
106
|
can_error_msg = mv_command.convert_state_dictionary(err)
|
|
111
107
|
if can_error_msg == 'Call was successful':
|
|
@@ -44,7 +44,7 @@ class CommandTemperatureBase(ICommand):
|
|
|
44
44
|
super().__init__()
|
|
45
45
|
|
|
46
46
|
# Temperature state code dictionary
|
|
47
|
-
self.
|
|
47
|
+
self._state_dictionary = {
|
|
48
48
|
1: "Stable",
|
|
49
49
|
2: "Tracking",
|
|
50
50
|
5: "Near",
|
|
@@ -108,10 +108,13 @@ class CommandTemperatureBase(ICommand):
|
|
|
108
108
|
return f'{set_point},{rate_per_minute},{approach_mode.value}'
|
|
109
109
|
|
|
110
110
|
def convert_state_dictionary(self, status_number):
|
|
111
|
-
|
|
111
|
+
if isinstance(status_number, str):
|
|
112
|
+
return status_number
|
|
113
|
+
else:
|
|
114
|
+
return self._state_dictionary[status_number]
|
|
112
115
|
|
|
113
116
|
def state_code_dict(self):
|
|
114
|
-
return self.
|
|
117
|
+
return self._state_dictionary
|
|
115
118
|
|
|
116
119
|
@abstractmethod
|
|
117
120
|
def get_state_server(self, arg_string: str) -> Union[str, int]:
|
|
@@ -160,18 +163,20 @@ class CommandTemperatureBase(ICommand):
|
|
|
160
163
|
############################
|
|
161
164
|
|
|
162
165
|
class CommandTemperatureImp(CommandTemperatureBase):
|
|
163
|
-
def __init__(self, multivu_win32com):
|
|
166
|
+
def __init__(self, multivu_win32com, instrument_name):
|
|
164
167
|
'''
|
|
165
168
|
Parameters:
|
|
166
169
|
----------
|
|
167
170
|
multivu_win32com: Union[win32.dynamic.CDispatch, None]
|
|
171
|
+
mvu_flavor: str
|
|
168
172
|
'''
|
|
169
173
|
super().__init__()
|
|
170
174
|
self._mvu = multivu_win32com
|
|
175
|
+
self.instrument_name = instrument_name
|
|
171
176
|
|
|
172
177
|
def get_state_server(self, value_variant, state_variant, params=''):
|
|
173
|
-
|
|
174
|
-
if
|
|
178
|
+
can_error = self._mvu.GetTemperature(value_variant, state_variant)
|
|
179
|
+
if can_error > 0:
|
|
175
180
|
raise MultiPyVuError('Error when calling GetTemperature()')
|
|
176
181
|
temperature = value_variant.value
|
|
177
182
|
return_state = int(state_variant.value)
|
|
@@ -184,15 +189,21 @@ class CommandTemperatureImp(CommandTemperatureBase):
|
|
|
184
189
|
set_approach: int
|
|
185
190
|
) -> Union[str, int]:
|
|
186
191
|
try:
|
|
187
|
-
|
|
192
|
+
can_error = self._mvu.SetTemperature(temperature,
|
|
188
193
|
set_rate_per_min,
|
|
189
194
|
set_approach)
|
|
190
195
|
except pywin_com_error:
|
|
191
196
|
raise MultiPyVuError('No pywin32 connection to MultiVu. Is MultiVu running?')
|
|
192
197
|
else:
|
|
193
|
-
if
|
|
198
|
+
if self.instrument_name == 'PPMS':
|
|
199
|
+
if can_error > 1:
|
|
200
|
+
raise MultiPyVuError('Error when calling SetTemperature()')
|
|
201
|
+
else:
|
|
202
|
+
# returning this string makes CommandMultiVu_base happy
|
|
203
|
+
return 'Call was successful'
|
|
204
|
+
elif can_error > 0:
|
|
194
205
|
raise MultiPyVuError('Error when calling SetTemperature()')
|
|
195
|
-
return
|
|
206
|
+
return can_error
|
|
196
207
|
|
|
197
208
|
|
|
198
209
|
############################
|
|
@@ -30,7 +30,7 @@ def create_command_mv(mvu_flavor, win32_dispatch=None):
|
|
|
30
30
|
A CommandMultiVu object. If win32_dispatch is None, it returns
|
|
31
31
|
a simulated object.
|
|
32
32
|
'''
|
|
33
|
-
cmd_dict = {'TEMP': create_command_temp(win32_dispatch),
|
|
33
|
+
cmd_dict = {'TEMP': create_command_temp(win32_dispatch, mvu_flavor),
|
|
34
34
|
'FIELD': create_command_field(win32_dispatch, mvu_flavor),
|
|
35
35
|
'CHAMBER': create_command_chamber(win32_dispatch, mvu_flavor),
|
|
36
36
|
'SDO': create_command_sdo(win32_dispatch),
|
|
@@ -42,7 +42,8 @@ def create_command_mv(mvu_flavor, win32_dispatch=None):
|
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
def create_command_temp(
|
|
45
|
-
win32_dispatch=None
|
|
45
|
+
win32_dispatch=None,
|
|
46
|
+
mvu_flavor=''
|
|
46
47
|
) -> Union[temperature.CommandTemperatureSim,
|
|
47
48
|
temperature.CommandTemperatureImp]:
|
|
48
49
|
'''
|
|
@@ -61,7 +62,7 @@ def create_command_temp(
|
|
|
61
62
|
if win32_dispatch is None:
|
|
62
63
|
return temperature.CommandTemperatureSim()
|
|
63
64
|
else:
|
|
64
|
-
return temperature.CommandTemperatureImp(win32_dispatch)
|
|
65
|
+
return temperature.CommandTemperatureImp(win32_dispatch, mvu_flavor)
|
|
65
66
|
|
|
66
67
|
|
|
67
68
|
def create_command_field(
|
|
@@ -31,6 +31,7 @@ from .exceptions import (MultiPyVuError,
|
|
|
31
31
|
ServerCloseError,
|
|
32
32
|
SocketError
|
|
33
33
|
)
|
|
34
|
+
from .__version import __version__ as mpv_version
|
|
34
35
|
|
|
35
36
|
if sys.platform == 'win32':
|
|
36
37
|
import msvcrt # Used to help detect the esc-key
|
|
@@ -88,6 +89,7 @@ class ClientBase():
|
|
|
88
89
|
self.logger.info(response['result'])
|
|
89
90
|
self._instr = self._message.instr
|
|
90
91
|
self.instrument_name = self._message.instr.name
|
|
92
|
+
self.logger.debug(f'MultiPyVu Version: {mpv_version}')
|
|
91
93
|
return self
|
|
92
94
|
|
|
93
95
|
def __exit__(self, exc_type, exc_value, exc_traceback) -> bool:
|
|
@@ -45,6 +45,14 @@ def catch_thread_error(func):
|
|
|
45
45
|
def error_handler(*args, **kwargs):
|
|
46
46
|
try:
|
|
47
47
|
func(*args, **kwargs)
|
|
48
|
+
# ignore the errors handled in _exit()
|
|
49
|
+
except (
|
|
50
|
+
KeyboardInterrupt,
|
|
51
|
+
MultiPyVuError,
|
|
52
|
+
UserWarning,
|
|
53
|
+
ClientCloseError
|
|
54
|
+
) as e:
|
|
55
|
+
raise e
|
|
48
56
|
except BaseException:
|
|
49
57
|
name = threading.current_thread().name
|
|
50
58
|
msg = f'Exception in thread \'{name}\' '
|
|
@@ -188,8 +196,8 @@ class Server(Subject):
|
|
|
188
196
|
def __enter__(self):
|
|
189
197
|
try:
|
|
190
198
|
sel = self.config_sock()
|
|
191
|
-
except OSError
|
|
192
|
-
#
|
|
199
|
+
except OSError:
|
|
200
|
+
# invalid connection, so return None
|
|
193
201
|
return None
|
|
194
202
|
quit_keys = "ctrl-c"
|
|
195
203
|
if sys.platform == 'win32':
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
__version__ = "2.
|
|
2
|
+
__version__ = "2.2.0"
|
|
@@ -14,6 +14,7 @@ import time
|
|
|
14
14
|
import re
|
|
15
15
|
import logging
|
|
16
16
|
from enum import Enum, auto
|
|
17
|
+
from typing import Tuple
|
|
17
18
|
|
|
18
19
|
from .Command_factory import create_command_mv
|
|
19
20
|
from .project_vars import SERVER_NAME, PYWIN32_VERSION, MIN_PYWIN32_VERSION
|
|
@@ -108,14 +109,14 @@ class Instrument():
|
|
|
108
109
|
self.multi_vu = None
|
|
109
110
|
self._connect_to_MultiVu(self.name)
|
|
110
111
|
|
|
111
|
-
def
|
|
112
|
+
def _exe_to_common_name(self, exe_name: str) -> str:
|
|
112
113
|
'''
|
|
113
|
-
Returns the name of the MultiVu
|
|
114
|
+
Returns the common name of the MultiVu flavor.
|
|
114
115
|
|
|
115
116
|
Parameters
|
|
116
117
|
----------
|
|
117
|
-
|
|
118
|
-
The name of the MultiVu flavor.
|
|
118
|
+
exe_name : str
|
|
119
|
+
The name of the MultiVu flavor executable.
|
|
119
120
|
|
|
120
121
|
Returns
|
|
121
122
|
-------
|
|
@@ -123,17 +124,18 @@ class Instrument():
|
|
|
123
124
|
A string of the specific MultiVu flavor .exe
|
|
124
125
|
|
|
125
126
|
'''
|
|
126
|
-
if
|
|
127
|
-
name =
|
|
128
|
-
elif
|
|
129
|
-
name =
|
|
130
|
-
elif
|
|
131
|
-
name =
|
|
132
|
-
elif
|
|
133
|
-
name =
|
|
127
|
+
if exe_name.capitalize() == 'PpmsMvu.exe'.capitalize():
|
|
128
|
+
name = InstrumentList.PPMS.name
|
|
129
|
+
elif exe_name.capitalize() == 'SquidVsm.exe'.capitalize():
|
|
130
|
+
name = InstrumentList.MPMS3.name
|
|
131
|
+
elif exe_name.capitalize() == 'VersaLab.exe'.capitalize():
|
|
132
|
+
name = InstrumentList.VERSALAB.name
|
|
133
|
+
elif exe_name.capitalize() == 'OptiCool.exe'.capitalize():
|
|
134
|
+
name = InstrumentList.OPTICOOL.name
|
|
135
|
+
elif exe_name.capitalize() == 'DynaCool.exe'.capitalize():
|
|
136
|
+
name = InstrumentList.DYNACOOL.name
|
|
134
137
|
else:
|
|
135
|
-
|
|
136
|
-
name += '.exe'
|
|
138
|
+
raise ValueError(f'{exe_name} is not a recognized executable name')
|
|
137
139
|
return name
|
|
138
140
|
|
|
139
141
|
def _get_class_id(self, inst: str) -> str:
|
|
@@ -179,29 +181,28 @@ class Instrument():
|
|
|
179
181
|
err_msg += 'the MultiVu flavor.'
|
|
180
182
|
raise MultiPyVuError(err_msg)
|
|
181
183
|
|
|
182
|
-
|
|
183
|
-
if
|
|
184
|
+
self.name, self.exe_name = self.detect_multivu()
|
|
185
|
+
if self.name != instrument_name:
|
|
184
186
|
if instrument_name == '':
|
|
185
|
-
msg = f'Found {
|
|
187
|
+
msg = f'Found {self.name} running.'
|
|
186
188
|
self.logger.info(msg)
|
|
187
189
|
msg = f'MultiPyVu Version: {mpv_version}'
|
|
188
190
|
self.logger.debug(msg)
|
|
189
191
|
else:
|
|
190
192
|
msg = f'User specified {instrument_name}, but detected '
|
|
191
|
-
msg += f'{
|
|
193
|
+
msg += f'{self.name} running. Either leave out a '
|
|
192
194
|
msg += 'specific MultiVu flavor and use the detected '
|
|
193
195
|
msg += 'one, or have the specified flavor match the '
|
|
194
196
|
msg += 'running instance.'
|
|
195
197
|
raise ValueError(msg)
|
|
196
|
-
self.name = detected_name
|
|
197
|
-
self.exe_name = self._get_exe(self.name)
|
|
198
198
|
self.class_id = self._get_class_id(self.name)
|
|
199
199
|
self.initialize_multivu_win32com()
|
|
200
200
|
|
|
201
|
-
def detect_multivu(self) -> str:
|
|
201
|
+
def detect_multivu(self) -> Tuple[str, str]:
|
|
202
202
|
'''
|
|
203
203
|
This looks in the file system for a running version of
|
|
204
|
-
MultiVu. Once it is found, the function returns the
|
|
204
|
+
MultiVu. Once it is found, the function returns the a
|
|
205
|
+
tuple with the common name and the executable name.
|
|
205
206
|
|
|
206
207
|
Raises
|
|
207
208
|
------
|
|
@@ -211,8 +212,8 @@ class Instrument():
|
|
|
211
212
|
|
|
212
213
|
Returns
|
|
213
214
|
-------
|
|
214
|
-
|
|
215
|
-
Returns the common name of the QD instrument.
|
|
215
|
+
tuple[str]
|
|
216
|
+
Returns the (common name, executable name) of the QD instrument.
|
|
216
217
|
|
|
217
218
|
'''
|
|
218
219
|
# Build a list of enum, instrumentType
|
|
@@ -220,6 +221,10 @@ class Instrument():
|
|
|
220
221
|
# Remove the last item (called na)
|
|
221
222
|
instrument_names.pop()
|
|
222
223
|
|
|
224
|
+
# declare these variables so that they are available to return
|
|
225
|
+
common_name = ''
|
|
226
|
+
exe_name = ''
|
|
227
|
+
|
|
223
228
|
# Use WMIC to get the list of running programs with 'multivu'
|
|
224
229
|
# in their path
|
|
225
230
|
cmd = 'WMIC PROCESS WHERE "COMMANDLINE like \'%multivu%\'" GET '
|
|
@@ -235,15 +240,9 @@ class Instrument():
|
|
|
235
240
|
exe_found = re.findall(exe_search, i)
|
|
236
241
|
if len(exe_found) > 0:
|
|
237
242
|
name, location, process_id = exe_found[0]
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
# the programs in the list and instantiate the instrument
|
|
242
|
-
# and add to MultiVu_list.
|
|
243
|
-
# MultiVu_list = []
|
|
244
|
-
# for instr in instrument_names:
|
|
245
|
-
# if instr.name in proc.stdout.upper():
|
|
246
|
-
# MultiVu_list.append(instr.name)
|
|
243
|
+
exe_name = name + '.exe'
|
|
244
|
+
common_name = self._exe_to_common_name(exe_name)
|
|
245
|
+
open_mv_dict[common_name] = (location, process_id)
|
|
247
246
|
|
|
248
247
|
# Declare errors if to few or too many are found; for one found,
|
|
249
248
|
# declare which version is identified
|
|
@@ -268,8 +267,7 @@ class Instrument():
|
|
|
268
267
|
self.logger.info(msg)
|
|
269
268
|
else:
|
|
270
269
|
self.logger.debug(msg)
|
|
271
|
-
|
|
272
|
-
return self.name
|
|
270
|
+
return common_name, exe_name
|
|
273
271
|
|
|
274
272
|
def initialize_multivu_win32com(self):
|
|
275
273
|
'''
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: MultiPyVu
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Control MultiVu using Python
|
|
5
5
|
Author-email: Damon D Jackson <djackson@qdusa.com>
|
|
6
6
|
Maintainer-email: "Quantum Design, Inc." <apps@qdusa.com>
|
|
@@ -383,6 +383,12 @@ client = mpv.Client(port=6000)
|
|
|
383
383
|
- A log file named QdMultiVu.log shows the traffic between the server and client which can also be useful during troubleshooting.
|
|
384
384
|
|
|
385
385
|
## Changelog<a class="anchor" id="changelog"></a>
|
|
386
|
+
**2.2.0**
|
|
387
|
+
- January 2024
|
|
388
|
+
- Corrected a bug that prevented the Server from recognizing PPMS and MPMS3 MultiVu flavors
|
|
389
|
+
- Log the version number when the Client connects to the Server
|
|
390
|
+
- Remove unwanted warnings when quitting the Server using the esc-key.
|
|
391
|
+
|
|
386
392
|
**2.1.4**
|
|
387
393
|
- October 2023
|
|
388
394
|
- Import full module as MultiPyVu. Instead of loading the three sub-modules as:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|