quarchpy 2.1.24.dev5__py2.py3-none-any.whl → 2.1.25__py2.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.
- quarchpy/__pycache__/__init__.cpython-311.pyc +0 -0
- quarchpy/__pycache__/_version.cpython-311.pyc +0 -0
- quarchpy/__pycache__/connection.cpython-311.pyc +0 -0
- quarchpy/__pycache__/run.cpython-311.pyc +0 -0
- quarchpy/_version.py +1 -1
- quarchpy/config_files/__pycache__/__init__.cpython-311.pyc +0 -0
- quarchpy/config_files/__pycache__/quarch_config_parser.cpython-311.pyc +0 -0
- quarchpy/connection_specific/QPS/qis/qis.jar +0 -0
- quarchpy/connection_specific/QPS/qis/qis_lib/{CInterface-1.7.9.jar → CInterface-1.8.2.jar} +0 -0
- quarchpy/connection_specific/QPS/qis/qis_lib/{CInterface-1.8.0.jar → CInterface-1.9.jar} +0 -0
- quarchpy/connection_specific/QPS/{qps_lib/QuarchCommon-0.2.12.jar → qis/qis_lib/QuarchCommon-0.2.13.jar} +0 -0
- quarchpy/connection_specific/QPS/qps.jar +0 -0
- quarchpy/connection_specific/QPS/{qis/qis_lib/QuarchCommon-0.2.12.jar → qps_lib/QuarchCommon-0.2.13.jar} +0 -0
- quarchpy/connection_specific/QPS/qps_lib/{qis-1.41.jar → qis-1.43.jar} +0 -0
- quarchpy/connection_specific/QPS/resources/InstallBanner.bmp +0 -0
- quarchpy/connection_specific/QPS/resources/QPS.ico +0 -0
- quarchpy/connection_specific/QPS/resources/QPS.png +0 -0
- quarchpy/connection_specific/QPS/resources/QuarchIcon_128x128.png +0 -0
- quarchpy/connection_specific/QPS/resources/QuarchIcon_16x16.png +0 -0
- quarchpy/connection_specific/QPS/resources/QuarchIcon_256x256.png +0 -0
- quarchpy/connection_specific/QPS/resources/QuarchIcon_32x32.png +0 -0
- quarchpy/connection_specific/QPS/resources/QuarchIcon_64x64.png +0 -0
- quarchpy/connection_specific/QPS/scriptCommands.txt +17 -2
- quarchpy/connection_specific/__pycache__/StreamChannels.cpython-311.pyc +0 -0
- quarchpy/connection_specific/__pycache__/__init__.cpython-311.pyc +0 -0
- quarchpy/connection_specific/__pycache__/connection_QIS.cpython-311.pyc +0 -0
- quarchpy/connection_specific/__pycache__/connection_QPS.cpython-311.pyc +0 -0
- quarchpy/connection_specific/__pycache__/connection_ReST.cpython-311.pyc +0 -0
- quarchpy/connection_specific/__pycache__/connection_Serial.cpython-311.pyc +0 -0
- quarchpy/connection_specific/__pycache__/connection_TCP.cpython-311.pyc +0 -0
- quarchpy/connection_specific/__pycache__/connection_Telnet.cpython-311.pyc +0 -0
- quarchpy/connection_specific/__pycache__/connection_USB.cpython-311.pyc +0 -0
- quarchpy/connection_specific/__pycache__/mDNS.cpython-311.pyc +0 -0
- quarchpy/connection_specific/connection_QPS.py +52 -0
- quarchpy/connection_specific/mDNS.py +126 -0
- quarchpy/connection_specific/serial/__pycache__/__init__.cpython-311.pyc +0 -0
- quarchpy/connection_specific/serial/__pycache__/serialutil.cpython-311.pyc +0 -0
- quarchpy/connection_specific/serial/__pycache__/serialwin32.cpython-311.pyc +0 -0
- quarchpy/connection_specific/serial/__pycache__/win32.cpython-311.pyc +0 -0
- quarchpy/connection_specific/serial/tools/__pycache__/__init__.cpython-311.pyc +0 -0
- quarchpy/connection_specific/serial/tools/__pycache__/list_ports.cpython-311.pyc +0 -0
- quarchpy/connection_specific/serial/tools/__pycache__/list_ports_common.cpython-311.pyc +0 -0
- quarchpy/connection_specific/serial/tools/__pycache__/list_ports_windows.cpython-311.pyc +0 -0
- quarchpy/debug/__pycache__/SystemTest.cpython-311.pyc +0 -0
- quarchpy/debug/__pycache__/__init__.cpython-311.pyc +0 -0
- quarchpy/debug/__pycache__/module_debug.cpython-311.pyc +0 -0
- quarchpy/debug/__pycache__/simple_terminal.cpython-311.pyc +0 -0
- quarchpy/debug/__pycache__/upgrade_quarchpy.cpython-311.pyc +0 -0
- quarchpy/debug/__pycache__/versionCompare.cpython-311.pyc +0 -0
- quarchpy/device/__pycache__/__init__.cpython-311.pyc +0 -0
- quarchpy/device/__pycache__/device.cpython-311.pyc +0 -0
- quarchpy/device/__pycache__/quarchArray.cpython-311.pyc +0 -0
- quarchpy/device/__pycache__/quarchPPM.cpython-311.pyc +0 -0
- quarchpy/device/__pycache__/quarchQPS.cpython-311.pyc +0 -0
- quarchpy/device/__pycache__/scanDevices.cpython-311.pyc +0 -0
- quarchpy/device/device.py +72 -22
- quarchpy/device/scanDevices.py +26 -11
- quarchpy/disk_test/__pycache__/AbsDiskFinder.cpython-311.pyc +0 -0
- quarchpy/disk_test/__pycache__/DiskTargetSelection.cpython-311.pyc +0 -0
- quarchpy/disk_test/__pycache__/__init__.cpython-311.pyc +0 -0
- quarchpy/disk_test/__pycache__/iometerDiskFinder.cpython-311.pyc +0 -0
- quarchpy/docs/CHANGES.rst +9 -0
- quarchpy/docs/_build/doctrees/CHANGES.doctree +0 -0
- quarchpy/docs/_build/doctrees/environment.pickle +0 -0
- quarchpy/docs/_build/doctrees/source/changelog.doctree +0 -0
- quarchpy/docs/_build/doctrees/source/quarchpy.connection_specific.doctree +0 -0
- quarchpy/docs/_build/doctrees/source/quarchpy.device.doctree +0 -0
- quarchpy/docs/_build/doctrees/source/quarchpy.qps.doctree +0 -0
- quarchpy/docs/_build/html/CHANGES.html +132 -119
- quarchpy/docs/_build/html/_sources/CHANGES.rst.txt +9 -0
- quarchpy/docs/_build/html/genindex.html +4 -0
- quarchpy/docs/_build/html/index.html +62 -60
- quarchpy/docs/_build/html/objects.inv +0 -0
- quarchpy/docs/_build/html/readme.html +6 -7
- quarchpy/docs/_build/html/searchindex.js +1 -1
- quarchpy/docs/_build/html/source/changelog.html +194 -179
- quarchpy/docs/_build/html/source/licenses.html +6 -7
- quarchpy/docs/_build/html/source/quarchpy.connection_specific.html +10 -0
- quarchpy/docs/_build/html/source/quarchpy.device.html +1 -1
- quarchpy/docs/_build/html/source/quarchpy.html +2 -0
- quarchpy/docs/_build/html/source/quarchpy.iometer.html +6 -7
- quarchpy/docs/_build/html/source/quarchpy.qps.html +2 -2
- quarchpy/docs/_build/html/source/quarchpy.utilities.html +6 -7
- quarchpy/docs/_build/html/source/readme.html +6 -7
- quarchpy/fio/__pycache__/FIO_interface.cpython-311.pyc +0 -0
- quarchpy/fio/__pycache__/__init__.cpython-311.pyc +0 -0
- quarchpy/fio/__pycache__/fioDiskFinder.cpython-311.pyc +0 -0
- quarchpy/iometer/__pycache__/__init__.cpython-311.pyc +0 -0
- quarchpy/iometer/__pycache__/gen_iometer_template.cpython-311.pyc +0 -0
- quarchpy/iometer/__pycache__/iometerFuncs.cpython-311.pyc +0 -0
- quarchpy/qis/__pycache__/StreamHeaderInfo.cpython-311.pyc +0 -0
- quarchpy/qis/__pycache__/__init__.cpython-311.pyc +0 -0
- quarchpy/qis/__pycache__/qisFuncs.cpython-311.pyc +0 -0
- quarchpy/qps/__pycache__/__init__.cpython-311.pyc +0 -0
- quarchpy/qps/__pycache__/qpsFuncs.cpython-311.pyc +0 -0
- quarchpy/qps/qpsFuncs.py +20 -10
- quarchpy/qps/qpsFuncs.py.bak +281 -0
- quarchpy/user_interface/__pycache__/__init__.cpython-311.pyc +0 -0
- quarchpy/user_interface/__pycache__/user_interface.cpython-311.pyc +0 -0
- quarchpy/user_interface/user_interface.py +3 -1
- quarchpy/utilities/__pycache__/TestCenter.cpython-311.pyc +0 -0
- quarchpy/utilities/__pycache__/TimeValue.cpython-311.pyc +0 -0
- quarchpy/utilities/__pycache__/Version.cpython-311.pyc +0 -0
- quarchpy/utilities/__pycache__/__init__.cpython-311.pyc +0 -0
- {quarchpy-2.1.24.dev5.dist-info → quarchpy-2.1.25.dist-info}/METADATA +10 -1
- {quarchpy-2.1.24.dev5.dist-info → quarchpy-2.1.25.dist-info}/RECORD +108 -57
- quarchpy/connection_specific/QPS/qis/qis_lib/CInterface-1.7.04.jar +0 -0
- quarchpy/connection_specific/QPS/qis/qis_lib/CInterface-1.7.8.jar +0 -0
- quarchpy/connection_specific/QPS/qis/qis_lib/CInterface-1.8.1.jar +0 -0
- quarchpy/connection_specific/QPS/qis/qis_lib/QuarchCommon-0.2.6.jar +0 -0
- quarchpy/connection_specific/QPS/qis/qis_lib/QuarchCommon-0.2.9.jar +0 -0
- quarchpy/connection_specific/QPS/qis/qis_lib/commons-csv-1.8.jar +0 -0
- quarchpy/connection_specific/QPS/qis/qis_lib/commons-lang3-3.2.1.jar +0 -0
- quarchpy/connection_specific/QPS/qis/resources/filters/filters.csv +0 -1004
- quarchpy/connection_specific/QPS/qps_lib/QuarchCommon-0.2.6.jar +0 -0
- quarchpy/connection_specific/QPS/qps_lib/QuarchCommon-0.2.9.jar +0 -0
- quarchpy/connection_specific/QPS/qps_lib/commons-lang3-3.12.0.jar +0 -0
- quarchpy/connection_specific/QPS/qps_lib/jfxtras-labs-8.0-r6.jar +0 -0
- quarchpy/connection_specific/QPS/qps_lib/opencsv-5.9.jar +0 -0
- quarchpy/connection_specific/QPS/qps_lib/qis-1.39.jar +0 -0
- quarchpy/connection_specific/QPS/qps_lib/qis-1.40.jar +0 -0
- quarchpy/connection_specific/connection_mDNS.py +0 -40
- {quarchpy-2.1.24.dev5.dist-info → quarchpy-2.1.25.dist-info}/WHEEL +0 -0
- {quarchpy-2.1.24.dev5.dist-info → quarchpy-2.1.25.dist-info}/top_level.txt +0 -0
Binary file
|
Binary file
|
Binary file
|
Binary file
|
quarchpy/_version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "2.1.
|
1
|
+
__version__ = "2.1.25"
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -1,7 +1,7 @@
|
|
1
1
|
QPS Command Summary
|
2
2
|
Copyright (c) Quarch Ltd
|
3
|
-
QPS v1.39
|
4
|
-
Generated:
|
3
|
+
QPS v1.39.13
|
4
|
+
Generated: 13-May-2024
|
5
5
|
|
6
6
|
|
7
7
|
*** Commands ***
|
@@ -345,6 +345,19 @@ Default value: NONE
|
|
345
345
|
Examples:
|
346
346
|
$open recording qpsFile="C:\quarch\recordings\AC\AC_Gen_test\AC_Gen_Test.qps"
|
347
347
|
|
348
|
+
Command: $progress check
|
349
|
+
Description: Checks the progress of a specific QPS task
|
350
|
+
Version: 2
|
351
|
+
Arguments
|
352
|
+
Argument: task
|
353
|
+
Description: The task to be checked
|
354
|
+
Index: 0
|
355
|
+
Type: STRING
|
356
|
+
Default value: NONE
|
357
|
+
Acceptable values: [open recording]
|
358
|
+
Examples:
|
359
|
+
$progress check task="open recording"
|
360
|
+
|
348
361
|
Command: $qis launch
|
349
362
|
Description: Launches new QIS instance
|
350
363
|
Version: 2
|
@@ -992,6 +1005,8 @@ $module scan ~ Scans for available devices
|
|
992
1005
|
|
993
1006
|
$open recording ~ Opens a recording
|
994
1007
|
|
1008
|
+
$progress check ~ Checks the progress of a specific QPS task
|
1009
|
+
|
995
1010
|
$qis launch ~ Launches new QIS instance
|
996
1011
|
|
997
1012
|
$qis shutdown ~ Shuts down current QIS instance
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -140,6 +140,17 @@ class QpsInterface:
|
|
140
140
|
time.sleep(
|
141
141
|
sleep) # Time must be allowed for QPS to Scan. If another scan request is sent it will time out and throw an error.
|
142
142
|
|
143
|
+
def get_list_details(self, sock=None):
|
144
|
+
if sock == None:
|
145
|
+
sock = self.sock
|
146
|
+
devString = self.sendCmdVerbose("$module list details")
|
147
|
+
#devString = self.sendAndReceiveText(sock, '$list details')
|
148
|
+
devString = devString.replace('>', '')
|
149
|
+
devString = devString.replace(r'\d+\) ', '')
|
150
|
+
devString = devString.split('\r\n')
|
151
|
+
devString = [x for x in devString if x] # remove empty elements
|
152
|
+
return devString
|
153
|
+
|
143
154
|
def getDeviceList(self, scan = True, ipAddress = None):
|
144
155
|
deviceList = []
|
145
156
|
scanWait = 2
|
@@ -182,4 +193,45 @@ class QpsInterface:
|
|
182
193
|
#return list of devices
|
183
194
|
return deviceList
|
184
195
|
|
196
|
+
|
197
|
+
def open_recording(self, file_path, cmdTimeout=5, pollInterval=3, startOpenTimout=5):
|
198
|
+
"""
|
199
|
+
|
200
|
+
"""
|
201
|
+
#print("Open recording at file : \""+str(file_path)+"\"")
|
202
|
+
self.sendCmdVerbose("$open recording qpsFile=\""+str(file_path)+"\"",timeout=cmdTimeout)
|
203
|
+
loadingStarted=False
|
204
|
+
message=""
|
205
|
+
startTime=time.time()
|
206
|
+
notLoadingMessageStartTime=None
|
207
|
+
while(1):
|
208
|
+
update=self.sendCmdVerbose("$progress check \"open recording\"",timeout=cmdTimeout)
|
209
|
+
#print(update)
|
210
|
+
m = re.search('\d+(\.\d+)?%', update)
|
211
|
+
if m: # A percentage was found
|
212
|
+
loadingStarted=True
|
213
|
+
found = float(m.group(0)[:-1])
|
214
|
+
user_interface.progressBar(found,100)
|
215
|
+
if found > 99.9: # This will catch the case we have 99.9999% or 100% loaded. recording with less that 1mill records auto return 100%
|
216
|
+
message = "Passed, Recording opened, loading detected and complete."
|
217
|
+
break
|
218
|
+
elif("Chart window is open but no loading is in progress." in update):
|
219
|
+
if loadingStarted ==True:
|
220
|
+
# Loading started and has now ended, so we can exit the loop.
|
221
|
+
message="Passed, Recording opened, loading detected and complete."
|
222
|
+
break
|
223
|
+
else: # QPS has not started loading a recording.
|
224
|
+
if notLoadingMessageStartTime == None:
|
225
|
+
# Start a timer from now so that if loading doesn't take place between now and a timeout value,
|
226
|
+
# we exit, stating that no loading started within the desired time.
|
227
|
+
notLoadingMessageStartTime = time.time()
|
228
|
+
elif time.time() - notLoadingMessageStartTime> startOpenTimout:
|
229
|
+
message = "No detection that QPS started loading the recording within "+str(startOpenTimout)+"s."
|
230
|
+
break
|
231
|
+
|
232
|
+
time.sleep(pollInterval) #Sleep pollInterval time, so we are not hammering QPS for updates while its busy loading.
|
233
|
+
time.sleep(1) #sleep outside the loop as there is a
|
234
|
+
return message
|
235
|
+
|
236
|
+
|
185
237
|
|
@@ -0,0 +1,126 @@
|
|
1
|
+
import platform # For getting the operating system name
|
2
|
+
import subprocess # For executing a shell command
|
3
|
+
|
4
|
+
from zeroconf import Zeroconf
|
5
|
+
|
6
|
+
|
7
|
+
def ping(host):
|
8
|
+
"""
|
9
|
+
Returns True if host (str) responds to a ping request.
|
10
|
+
"""
|
11
|
+
# Option for the number of packets as a function of
|
12
|
+
param = '-n' if platform.system().lower() == 'windows' else '-c'
|
13
|
+
|
14
|
+
# Building the command. Ex: "ping -c 1 google.com"
|
15
|
+
command = ['ping', param, '1', host]
|
16
|
+
|
17
|
+
# Execute the ping command and capture the output and return code
|
18
|
+
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
19
|
+
|
20
|
+
# Check the return code and output to determine the result
|
21
|
+
if result.returncode == 0 and ("destination host unreachable" not in str(result.stdout).lower()):
|
22
|
+
return True # Ping successful
|
23
|
+
else:
|
24
|
+
return False # Ping failed
|
25
|
+
|
26
|
+
|
27
|
+
class MyListener:
|
28
|
+
"""
|
29
|
+
MyListener class to handle service updates, removals, and additions in Zeroconf
|
30
|
+
"""
|
31
|
+
|
32
|
+
_instance = None
|
33
|
+
|
34
|
+
@classmethod
|
35
|
+
def get_instance(cls):
|
36
|
+
"""
|
37
|
+
Get an instance of MyListener class. If none exists, create one.
|
38
|
+
"""
|
39
|
+
if cls._instance is None:
|
40
|
+
cls._instance = MyListener()
|
41
|
+
return cls._instance
|
42
|
+
|
43
|
+
def __init__(self):
|
44
|
+
"""
|
45
|
+
Initialize MyListener instance.
|
46
|
+
"""
|
47
|
+
self.found_devices = {}
|
48
|
+
self.mdns_service_running = False
|
49
|
+
self.zeroconf = None
|
50
|
+
self.target_conn = None
|
51
|
+
|
52
|
+
def update_service(self, zc, type_, name):
|
53
|
+
"""
|
54
|
+
Handle service update event.
|
55
|
+
"""
|
56
|
+
info = zc.get_service_info(type_, name)
|
57
|
+
if "Quarch:" in str(info):
|
58
|
+
# decode the incoming properties from mdns
|
59
|
+
decoded_properties = {key.decode('utf-8'): value.decode('utf-8') for key, value in info.properties.items()}
|
60
|
+
decoded_ip = ".".join(str(byte) for byte in info.addresses[0])
|
61
|
+
self.get_instance().add_device(decoded_properties, decoded_ip)
|
62
|
+
|
63
|
+
def remove_service(self, zc, type_, name):
|
64
|
+
"""
|
65
|
+
Handle service removal event.
|
66
|
+
"""
|
67
|
+
return None
|
68
|
+
|
69
|
+
def add_service(self, zc, type_, name):
|
70
|
+
"""
|
71
|
+
Handle service addition event.
|
72
|
+
"""
|
73
|
+
info = zc.get_service_info(type_, name)
|
74
|
+
if "Quarch:" in str(info):
|
75
|
+
# decode the incoming properties from mdns
|
76
|
+
decoded_properties = {key.decode('utf-8'): value.decode('utf-8') for key, value in info.properties.items()}
|
77
|
+
decoded_ip = ".".join(str(byte) for byte in info.addresses[0])
|
78
|
+
self.get_instance().add_device(decoded_properties, decoded_ip)
|
79
|
+
|
80
|
+
def add_device(self, properties_dict, ip_address):
|
81
|
+
"""
|
82
|
+
Add a device to the found devices dictionary.
|
83
|
+
"""
|
84
|
+
qtl_num = "QTL" + properties_dict['86'] if '86' in properties_dict else None
|
85
|
+
# Check if module contains REST connection
|
86
|
+
if '84' in properties_dict:
|
87
|
+
# Check the user specified connection type
|
88
|
+
if self.get_instance().target_conn == "all" or self.get_instance().target_conn == "rest":
|
89
|
+
if properties_dict['84'] == '80':
|
90
|
+
# print("Rest connection exists for device: " + qtl_num)
|
91
|
+
# Updates the found devices dict
|
92
|
+
self.get_instance().update_device_dict(device_dict={"REST:" + ip_address: qtl_num})
|
93
|
+
# Check if module contains TCP connection
|
94
|
+
if '85' in properties_dict:
|
95
|
+
# Check the user specified connection type
|
96
|
+
if self.get_instance().target_conn == "all" or self.get_instance().target_conn == "tcp":
|
97
|
+
if properties_dict['85'] == "9760":
|
98
|
+
# print("TCP connection exists for device: " + qtl_num)
|
99
|
+
# Updates the found devices dict
|
100
|
+
self.get_instance().update_device_dict(device_dict={"TCP:" + ip_address: qtl_num})
|
101
|
+
|
102
|
+
def update_device_dict(self, device_dict):
|
103
|
+
"""
|
104
|
+
Update the found devices dictionary.
|
105
|
+
"""
|
106
|
+
self.get_instance().found_devices.update(device_dict)
|
107
|
+
|
108
|
+
def get_found_devices(self):
|
109
|
+
"""
|
110
|
+
Get the found devices and perform ping check.
|
111
|
+
"""
|
112
|
+
temp_dict = self.get_instance().found_devices
|
113
|
+
for key, value in list(temp_dict.items()):
|
114
|
+
result = ping(key[key.index(":") + 1:])
|
115
|
+
if not result or self.get_instance().target_conn not in key.lower():
|
116
|
+
del self.get_instance().found_devices[key]
|
117
|
+
print(str(self.get_instance().found_devices))
|
118
|
+
return self.get_instance().found_devices
|
119
|
+
|
120
|
+
def get_zeroconf(self):
|
121
|
+
"""
|
122
|
+
Get the Zeroconf instance. If none exists, create one.
|
123
|
+
"""
|
124
|
+
if self.get_instance().zeroconf is None:
|
125
|
+
self.get_instance().zeroconf = Zeroconf()
|
126
|
+
return self.get_instance().zeroconf
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
quarchpy/device/device.py
CHANGED
@@ -110,21 +110,16 @@ class quarchDevice:
|
|
110
110
|
## QIS
|
111
111
|
# ConType may be QIS only or QIS:ip:port [:3] checks if the first 3 letters are QIS.
|
112
112
|
elif self.ConType[:3].upper() == "QIS":
|
113
|
-
# If host and port are specified.
|
114
|
-
|
115
|
-
#
|
116
|
-
|
117
|
-
# QIS port should be an int.
|
118
|
-
port = int(port)
|
119
|
-
# If host and port are not specified.
|
120
|
-
except:
|
113
|
+
try: # If host and port are specified.
|
114
|
+
QIS, host, port = self.ConType.split(':') # Extract QIS, host and port.
|
115
|
+
port = int(port) # QIS port should be an int.
|
116
|
+
except: # If host and port are not specified.
|
121
117
|
host = '127.0.0.1'
|
122
118
|
port = 9722
|
123
119
|
|
124
120
|
numb_colons = self.ConString.count(":")
|
125
121
|
if numb_colons == 1:
|
126
122
|
self.ConString = self.ConString.replace(':', '::')
|
127
|
-
|
128
123
|
# Creates the connection object.
|
129
124
|
self.connectionObj = QISConnection(self.ConString, host, port)
|
130
125
|
|
@@ -132,9 +127,8 @@ class quarchDevice:
|
|
132
127
|
list_str = "".join(list).lower()
|
133
128
|
|
134
129
|
timeout = time.time() + int(timeout) # now + n seconds
|
135
|
-
|
136
130
|
# check for device in list, has a timeout
|
137
|
-
while time.time() < timeout:
|
131
|
+
while time.time() < timeout: # look for the connection string in qis $list details
|
138
132
|
|
139
133
|
# Check if it's a module's QTL number
|
140
134
|
if "qtl" not in self.ConString.lower():
|
@@ -143,7 +137,6 @@ class quarchDevice:
|
|
143
137
|
ip_address = re.search(r"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}", self.ConString)
|
144
138
|
if not ip_address:
|
145
139
|
raise ValueError("ConString " + self.ConString + " does not contain a valid QTL number or IP address")
|
146
|
-
|
147
140
|
# Attempt to get QTL number from qis "$list details"
|
148
141
|
temp_str = _check_ip_in_qis_list(ip_address.group(), self.connectionObj.qis.get_list_details())
|
149
142
|
if temp_str:
|
@@ -159,9 +152,8 @@ class quarchDevice:
|
|
159
152
|
if "located" in str(self.connectionObj.qis.scanIP(self.ConString)).lower():
|
160
153
|
# Note - Qis takes a moment or 2 to add this newly located device to the $list 21/03/23
|
161
154
|
timeout += 20 # Extend the timeout as the drive was located
|
162
|
-
|
163
155
|
while time.time() < timeout:
|
164
|
-
# try find the
|
156
|
+
# try find the QTL from ipaddress
|
165
157
|
temp_str = _check_ip_in_qis_list(ip_address.group(), self.connectionObj.qis.get_list_details())
|
166
158
|
if temp_str:
|
167
159
|
# If the item is found, break out of this loop
|
@@ -181,8 +173,7 @@ class quarchDevice:
|
|
181
173
|
time.sleep(1)
|
182
174
|
list = self.connectionObj.qis.getDeviceList()
|
183
175
|
list_str = "".join(list).lower()
|
184
|
-
else:
|
185
|
-
# If we didn't hit a 'break' condition in the above loop, then it timed out
|
176
|
+
else: # If we didn't hit a 'break' condition in the above loop, then it timed out
|
186
177
|
raise timeout_exception("Could not find module " + self.ConString + " from Qis within specified time")
|
187
178
|
|
188
179
|
self.connectionObj.qis.sendAndReceiveCmd(cmd="$default " + self.ConString)
|
@@ -190,9 +181,9 @@ class quarchDevice:
|
|
190
181
|
## QPS
|
191
182
|
elif self.ConType[:3].upper() == "QPS":
|
192
183
|
try:
|
193
|
-
# Extract
|
194
|
-
|
195
|
-
#
|
184
|
+
# Extract QPS, host and port.
|
185
|
+
QPS, host, port = self.ConType.split(':')
|
186
|
+
# QPS port should be an int.
|
196
187
|
port = int(port)
|
197
188
|
# If host and port are not specified.
|
198
189
|
except:
|
@@ -204,6 +195,65 @@ class quarchDevice:
|
|
204
195
|
self.ConString = self.ConString.replace(':', '::')
|
205
196
|
|
206
197
|
self.connectionObj = QPSConnection(host, port)
|
198
|
+
list = self.connectionObj.qps.sendCmdVerbose("$module list details").replace("\r\n","\n").split("\n")
|
199
|
+
list_str = "".join(list).lower()
|
200
|
+
|
201
|
+
timeout = time.time() + int(timeout) # now + n seconds
|
202
|
+
# check for device in list, has a timeout
|
203
|
+
while time.time() < timeout: # look for the connection string in QPS $list details
|
204
|
+
|
205
|
+
# Check if it's a module's QTL number
|
206
|
+
if "qtl" not in self.ConString.lower():
|
207
|
+
|
208
|
+
# If not, check if it contains a valid IP address format
|
209
|
+
ip_address = re.search(r"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}", self.ConString)
|
210
|
+
if not ip_address:
|
211
|
+
raise ValueError("ConString " + self.ConString + " does not contain a valid QTL number or IP address")
|
212
|
+
|
213
|
+
# Attempt to get QTL number from QPS "$list details"
|
214
|
+
temp_str = _check_ip_in_qis_list(ip_address.group(), list)
|
215
|
+
if temp_str:
|
216
|
+
# If found
|
217
|
+
self.ConString = temp_str
|
218
|
+
break
|
219
|
+
|
220
|
+
logging.debug("Did not find ip address in list details, attempt targetted QPS scan")
|
221
|
+
|
222
|
+
# If it's not present in the list already, then try scanning for it via QPS
|
223
|
+
# Scan is purposefully after initial check! 09/03/2023
|
224
|
+
# Valid response example "Located device: 192.168.1.3"
|
225
|
+
|
226
|
+
if "located" in str(self.connectionObj.qps.scanIP(self.ConString)).lower():
|
227
|
+
# Note - QPS takes a moment or 2 to add this newly located device to the $list 21/03/23
|
228
|
+
timeout += 20 # Extend the timeout as the drive was located
|
229
|
+
while time.time() < timeout:
|
230
|
+
# try find the QTL from ipaddress
|
231
|
+
temp_str = _check_ip_in_qis_list(ip_address.group(), self.connectionObj.qps.get_list_details())
|
232
|
+
if temp_str:
|
233
|
+
# If the item is found, break out of this loop
|
234
|
+
self.ConString = temp_str
|
235
|
+
break
|
236
|
+
time.sleep(1) # Slow down the poll
|
237
|
+
else:
|
238
|
+
# if it's not found, continue and allow program to timeout
|
239
|
+
continue
|
240
|
+
# Break out of both loops
|
241
|
+
break
|
242
|
+
|
243
|
+
elif str(self.ConString).lower() in str(list_str).lower():
|
244
|
+
# If we have QTL device, and it's in list, nothing more needs done.
|
245
|
+
break
|
246
|
+
else:
|
247
|
+
time.sleep(1)
|
248
|
+
list = self.connectionObj.qps.getDeviceList()
|
249
|
+
list_str = "".join(list).lower()
|
250
|
+
else: # If we didn't hit a 'break' condition in the above loop, then it timed out
|
251
|
+
raise timeout_exception("Could not find module " + self.ConString + " from QPS within specified time")
|
252
|
+
|
253
|
+
|
254
|
+
|
255
|
+
|
256
|
+
|
207
257
|
|
208
258
|
## Neither PY or QIS, connection cannot be created.
|
209
259
|
else:
|
@@ -238,7 +288,7 @@ class quarchDevice:
|
|
238
288
|
# send command to log
|
239
289
|
logging.debug(os.path.basename(__file__) + ": "+self.ConType[:3]+" sending command: " + CommandString)
|
240
290
|
|
241
|
-
if self.ConType[:3] == "QIS":
|
291
|
+
if self.ConType[:3].upper() == "QIS":
|
242
292
|
|
243
293
|
numb_colons = self.ConString.count(":")
|
244
294
|
if numb_colons == 1:
|
@@ -249,13 +299,13 @@ class quarchDevice:
|
|
249
299
|
logging.debug(os.path.basename(__file__) + ": "+self.ConType[:3]+" received: " + response)
|
250
300
|
return response
|
251
301
|
|
252
|
-
elif self.ConType == "PY":
|
302
|
+
elif self.ConType.upper() == "PY":
|
253
303
|
response = self.connectionObj.connection.sendCommand(CommandString, expectedResponse=expectedResponse)
|
254
304
|
# send response to log
|
255
305
|
logging.debug(os.path.basename(__file__) + ": "+self.ConType[:3]+" received: " + response)
|
256
306
|
return response
|
257
307
|
|
258
|
-
elif self.ConType[:3] == "QPS":
|
308
|
+
elif self.ConType[:3].upper() == "QPS":
|
259
309
|
# If "$" CMD is for QPS, else its for the specific module. Since QPS can talk to many modules we must added the conString.
|
260
310
|
if CommandString[0] != '$':
|
261
311
|
CommandString = self.ConString + " " + CommandString
|
quarchpy/device/scanDevices.py
CHANGED
@@ -20,8 +20,7 @@ from quarchpy.connection_specific.connection_Serial import serialList, serial
|
|
20
20
|
from quarchpy.device.quarchArray import isThisAnArrayController
|
21
21
|
from quarchpy.connection_specific.connection_USB import TQuarchUSB_IF
|
22
22
|
from quarchpy.connection_specific import connection_ReST, connection_TCP
|
23
|
-
from quarchpy.connection_specific.
|
24
|
-
from quarchpy.utilities import TestCenter
|
23
|
+
from quarchpy.connection_specific.mDNS import MyListener
|
25
24
|
|
26
25
|
|
27
26
|
'''
|
@@ -475,11 +474,14 @@ def filter_module_type(module_type_filter, found_devices):
|
|
475
474
|
filtered_devices.update({key: value})
|
476
475
|
return filtered_devices
|
477
476
|
|
478
|
-
def scan_mDNS(mdnsListener):
|
477
|
+
def scan_mDNS(mdnsListener, zeroconf=None):
|
479
478
|
from zeroconf import ServiceBrowser, Zeroconf
|
480
|
-
zeroconf
|
479
|
+
if zeroconf is None:
|
480
|
+
zeroconf = Zeroconf()
|
481
481
|
listener = mdnsListener
|
482
482
|
browser = ServiceBrowser(zeroconf, "_http._tcp.local.", listener)
|
483
|
+
return browser
|
484
|
+
|
483
485
|
|
484
486
|
|
485
487
|
'''
|
@@ -487,10 +489,23 @@ Scans for Quarch modules across the given interface(s). Returns a dictionary of
|
|
487
489
|
'''
|
488
490
|
def scanDevices(target_conn="all", lanTimeout=1, scanInArray=True, favouriteOnly=True,filterStr=None,
|
489
491
|
module_type_filter=None, ipAddressLookup=None):
|
492
|
+
|
490
493
|
foundDevices = dict()
|
491
494
|
scannedArrays = list()
|
492
|
-
|
493
|
-
|
495
|
+
|
496
|
+
# Setup mdns with zeroconf
|
497
|
+
# Ensure listener/zeroconf instance stay persistent (ensures only one thread is used for each scan cycle)
|
498
|
+
mdns_listener = MyListener().get_instance()
|
499
|
+
zeroconf = mdns_listener.get_zeroconf()
|
500
|
+
# Setup new mdns discovery service for every scan cycle
|
501
|
+
browser = scan_mDNS(mdns_listener, zeroconf)
|
502
|
+
# Set target_conn
|
503
|
+
mdns_listener.target_conn = target_conn.lower()
|
504
|
+
# Setup mdns discovery that stays persistent in the background - (could be removed)
|
505
|
+
# if not mdns_listener.mdns_service_running:
|
506
|
+
# from zeroconf import ServiceBrowser, Zeroconf
|
507
|
+
# scan_mDNS(mdns_listener, None)
|
508
|
+
# mdns_listener.mdns_service_running = True
|
494
509
|
|
495
510
|
if target_conn.lower() == "all":
|
496
511
|
foundDevices = list_USB()
|
@@ -498,10 +513,7 @@ def scanDevices(target_conn="all", lanTimeout=1, scanInArray=True, favouriteOnly
|
|
498
513
|
try:
|
499
514
|
#This will fail if the test machine is not connected to a network
|
500
515
|
foundDevices = mergeDict(foundDevices, list_network("all", ipAddressLookup=ipAddressLookup, lanTimeout=lanTimeout))
|
501
|
-
|
502
|
-
foundDevices = mergeDict(foundDevices, mdnsListener.found_devices)
|
503
|
-
except Exception as mdnsExcept:
|
504
|
-
logging.debug("An error occurred while trying to use the mdns listner to scan\n" +str(mdnsExcept))
|
516
|
+
foundDevices = mergeDict(foundDevices, mdns_listener.get_found_devices())
|
505
517
|
except Exception as e:
|
506
518
|
logging.error(e)
|
507
519
|
logging.warning("Network scan failed, check network connection")
|
@@ -514,6 +526,8 @@ def scanDevices(target_conn="all", lanTimeout=1, scanInArray=True, favouriteOnly
|
|
514
526
|
|
515
527
|
if target_conn.lower() == "tcp" or target_conn.lower() == "rest" or target_conn.lower() == "telnet":
|
516
528
|
foundDevices = list_network(target_conn, ipAddressLookup=ipAddressLookup, lanTimeout=lanTimeout)
|
529
|
+
foundDevices = mergeDict(foundDevices, mdns_listener.get_found_devices())
|
530
|
+
|
517
531
|
|
518
532
|
if (scanInArray):
|
519
533
|
for k, v in foundDevices.items(): # k=Connection target, v=serial number
|
@@ -567,7 +581,8 @@ def scanDevices(target_conn="all", lanTimeout=1, scanInArray=True, favouriteOnly
|
|
567
581
|
# used to filter module via type ( Power / Drive / ...)
|
568
582
|
if module_type_filter:
|
569
583
|
foundDevices = filter_module_type(module_type_filter, foundDevices)
|
570
|
-
|
584
|
+
# Cancels the mdns discovery service (required to close active thread)
|
585
|
+
browser.cancel()
|
571
586
|
return foundDevices
|
572
587
|
|
573
588
|
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
quarchpy/docs/CHANGES.rst
CHANGED
@@ -13,6 +13,15 @@ Quarchpy
|
|
13
13
|
Change Log
|
14
14
|
----------
|
15
15
|
|
16
|
+
2.1.25
|
17
|
+
------
|
18
|
+
- New QPS 1.40 and Qis 1.43
|
19
|
+
- mdns scanning added to quarchpy
|
20
|
+
|
21
|
+
2.1.24
|
22
|
+
------
|
23
|
+
- Yanked
|
24
|
+
|
16
25
|
2.1.23
|
17
26
|
------
|
18
27
|
- QIS and QPS devices and interfaces can use sendCommand to send comannds to the modules and to the applications uniformly
|
Binary file
|
Binary file
|
Binary file
|