quarchpy 2.1.20.dev1__py2.py3-none-any.whl → 2.1.20.dev3__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.
Files changed (152) hide show
  1. quarchpy/.idea/.name +1 -1
  2. quarchpy/.idea/inspectionProfiles/Project_Default.xml +26 -0
  3. quarchpy/.idea/modules.xml +0 -1
  4. quarchpy/.idea/quarchpy.iml +1 -4
  5. quarchpy/.idea/workspace.xml +25 -230
  6. quarchpy/__pycache__/__init__.cpython-311.pyc +0 -0
  7. quarchpy/__pycache__/_version.cpython-311.pyc +0 -0
  8. quarchpy/__pycache__/connection.cpython-311.pyc +0 -0
  9. quarchpy/__pycache__/run.cpython-311.pyc +0 -0
  10. quarchpy/_version.py +1 -1
  11. quarchpy/config_files/__pycache__/__init__.cpython-311.pyc +0 -0
  12. quarchpy/config_files/__pycache__/quarch_config_parser.cpython-311.pyc +0 -0
  13. quarchpy/connection_specific/QPS/qis/help.txt +12 -4
  14. quarchpy/connection_specific/QPS/qis/qis.jar +0 -0
  15. quarchpy/connection_specific/QPS/qis/qis_lib/CInterface-1.7.8.jar +0 -0
  16. quarchpy/connection_specific/QPS/qis/qis_lib/Collections-2.4.jar +0 -0
  17. quarchpy/connection_specific/QPS/qis/qis_lib/Desktop-1.1.jar +0 -0
  18. quarchpy/connection_specific/QPS/qis/qis_lib/Executor-3.13.jar +0 -0
  19. quarchpy/connection_specific/QPS/qis/qis_lib/JNA-1.2.jar +0 -0
  20. quarchpy/connection_specific/QPS/qis/qis_lib/OS-1.8.jar +0 -0
  21. quarchpy/connection_specific/QPS/qis/qis_lib/QuarchCommon-0.2.9.jar +0 -0
  22. quarchpy/connection_specific/QPS/qis/qis_lib/SystemTray-4.4.jar +0 -0
  23. quarchpy/connection_specific/QPS/qis/qis_lib/Updates-1.1.jar +0 -0
  24. quarchpy/connection_specific/QPS/qis/qis_lib/Utilities-1.46.jar +0 -0
  25. quarchpy/connection_specific/QPS/qis/qis_lib/commons-csv-1.8.jar +0 -0
  26. quarchpy/connection_specific/QPS/qis/qis_lib/javassist-3.29.2-GA.jar +0 -0
  27. quarchpy/connection_specific/QPS/qis/qis_lib/jna-jpms-5.12.1.jar +0 -0
  28. quarchpy/connection_specific/QPS/qis/qis_lib/jna-platform-jpms-5.12.1.jar +0 -0
  29. quarchpy/connection_specific/QPS/qis/qis_lib/kotlin-stdlib-1.9.21.jar +0 -0
  30. quarchpy/connection_specific/QPS/qis/qis_lib/slf4j-api-2.0.9.jar +0 -0
  31. quarchpy/connection_specific/QPS/qis/qis_lib/slf4j-simple-2.0.9.jar +0 -0
  32. quarchpy/connection_specific/QPS/qis/resources/filters/Example.txt +36 -0
  33. quarchpy/connection_specific/QPS/qis/resources/filters/filters.csv +1004 -0
  34. quarchpy/connection_specific/QPS/qis/resources/filters/iec_filters.xml +26 -0
  35. quarchpy/connection_specific/QPS/qis/resources/filters/iec_filters.xml.bak +26 -0
  36. quarchpy/connection_specific/QPS/qps.jar +0 -0
  37. quarchpy/connection_specific/QPS/qps_lib/QuarchCommon-0.2.9.jar +0 -0
  38. quarchpy/connection_specific/QPS/qps_lib/commons-lang3-3.12.0.jar +0 -0
  39. quarchpy/connection_specific/QPS/qps_lib/opencsv-5.9.jar +0 -0
  40. quarchpy/connection_specific/QPS/qps_lib/qis-1.40.jar +0 -0
  41. quarchpy/connection_specific/QPS/scriptCommands.txt +2 -2
  42. quarchpy/connection_specific/__pycache__/StreamChannels.cpython-311.pyc +0 -0
  43. quarchpy/connection_specific/__pycache__/__init__.cpython-311.pyc +0 -0
  44. quarchpy/connection_specific/__pycache__/connection_QIS.cpython-311.pyc +0 -0
  45. quarchpy/connection_specific/__pycache__/connection_QPS.cpython-311.pyc +0 -0
  46. quarchpy/connection_specific/__pycache__/connection_ReST.cpython-311.pyc +0 -0
  47. quarchpy/connection_specific/__pycache__/connection_Serial.cpython-311.pyc +0 -0
  48. quarchpy/connection_specific/__pycache__/connection_TCP.cpython-311.pyc +0 -0
  49. quarchpy/connection_specific/__pycache__/connection_Telnet.cpython-311.pyc +0 -0
  50. quarchpy/connection_specific/__pycache__/connection_USB.cpython-311.pyc +0 -0
  51. quarchpy/connection_specific/__pycache__/connection_mDNS.cpython-311.pyc +0 -0
  52. quarchpy/connection_specific/connection_QIS.py +5 -3
  53. quarchpy/connection_specific/connection_QIS.py.bak +1738 -0
  54. quarchpy/connection_specific/serial/__pycache__/__init__.cpython-311.pyc +0 -0
  55. quarchpy/connection_specific/serial/__pycache__/serialutil.cpython-311.pyc +0 -0
  56. quarchpy/connection_specific/serial/__pycache__/serialwin32.cpython-311.pyc +0 -0
  57. quarchpy/connection_specific/serial/__pycache__/win32.cpython-311.pyc +0 -0
  58. quarchpy/connection_specific/serial/tools/__pycache__/__init__.cpython-311.pyc +0 -0
  59. quarchpy/connection_specific/serial/tools/__pycache__/list_ports.cpython-311.pyc +0 -0
  60. quarchpy/connection_specific/serial/tools/__pycache__/list_ports_common.cpython-311.pyc +0 -0
  61. quarchpy/connection_specific/serial/tools/__pycache__/list_ports_windows.cpython-311.pyc +0 -0
  62. quarchpy/connection_specific/usb_libs/__pycache__/libusb1.cpython-311.pyc +0 -0
  63. quarchpy/connection_specific/usb_libs/__pycache__/usb1.cpython-311.pyc +0 -0
  64. quarchpy/debug/TextScanIP.py +11 -0
  65. quarchpy/debug/__pycache__/SystemTest.cpython-311.pyc +0 -0
  66. quarchpy/debug/__pycache__/__init__.cpython-311.pyc +0 -0
  67. quarchpy/debug/__pycache__/module_debug.cpython-311.pyc +0 -0
  68. quarchpy/debug/__pycache__/simple_terminal.cpython-311.pyc +0 -0
  69. quarchpy/debug/__pycache__/upgrade_quarchpy.cpython-311.pyc +0 -0
  70. quarchpy/debug/__pycache__/versionCompare.cpython-311.pyc +0 -0
  71. quarchpy/debug/simple_terminal.py +29 -25
  72. quarchpy/device/__pycache__/__init__.cpython-311.pyc +0 -0
  73. quarchpy/device/__pycache__/device.cpython-311.pyc +0 -0
  74. quarchpy/device/__pycache__/quarchArray.cpython-311.pyc +0 -0
  75. quarchpy/device/__pycache__/quarchPPM.cpython-311.pyc +0 -0
  76. quarchpy/device/__pycache__/quarchQPS.cpython-311.pyc +0 -0
  77. quarchpy/device/__pycache__/scanDevices.cpython-311.pyc +0 -0
  78. quarchpy/device/device.py.bak +504 -0
  79. quarchpy/device/quarchPPM.py.bak +67 -0
  80. quarchpy/device/quarchQPS.py.bak +396 -0
  81. quarchpy/device/scanDevices.py +78 -86
  82. quarchpy/device/scanDevices.py.bak +126 -106
  83. quarchpy/disk_test/__pycache__/AbsDiskFinder.cpython-311.pyc +0 -0
  84. quarchpy/disk_test/__pycache__/DiskTargetSelection.cpython-311.pyc +0 -0
  85. quarchpy/disk_test/__pycache__/__init__.cpython-311.pyc +0 -0
  86. quarchpy/disk_test/__pycache__/iometerDiskFinder.cpython-311.pyc +0 -0
  87. quarchpy/docs/CHANGES.rst +10 -0
  88. quarchpy/docs/CHANGES.rst.bak +364 -0
  89. quarchpy/docs/_build/doctrees/CHANGES.doctree +0 -0
  90. quarchpy/docs/_build/doctrees/environment.pickle +0 -0
  91. quarchpy/docs/_build/doctrees/source/changelog.doctree +0 -0
  92. quarchpy/docs/_build/doctrees/source/quarchpy.fio.doctree +0 -0
  93. quarchpy/docs/_build/html/CHANGES.html +121 -113
  94. quarchpy/docs/_build/html/_sources/CHANGES.rst.txt +6 -1
  95. quarchpy/docs/_build/html/_static/alabaster.css +14 -9
  96. quarchpy/docs/_build/html/_static/basic.css +1 -1
  97. quarchpy/docs/_build/html/_static/pygments.css +1 -1
  98. quarchpy/docs/_build/html/genindex.html +9 -27
  99. quarchpy/docs/_build/html/index.html +62 -60
  100. quarchpy/docs/_build/html/objects.inv +0 -0
  101. quarchpy/docs/_build/html/py-modindex.html +7 -11
  102. quarchpy/docs/_build/html/readme.html +7 -6
  103. quarchpy/docs/_build/html/search.html +7 -6
  104. quarchpy/docs/_build/html/searchindex.js +1 -1
  105. quarchpy/docs/_build/html/source/changelog.html +176 -167
  106. quarchpy/docs/_build/html/source/licenses.html +7 -6
  107. quarchpy/docs/_build/html/source/modules.html +8 -7
  108. quarchpy/docs/_build/html/source/quarchpy.calibration.html +7 -6
  109. quarchpy/docs/_build/html/source/quarchpy.config_files.html +7 -6
  110. quarchpy/docs/_build/html/source/quarchpy.connection_specific.html +7 -6
  111. quarchpy/docs/_build/html/source/quarchpy.debug.html +7 -6
  112. quarchpy/docs/_build/html/source/quarchpy.device.html +7 -6
  113. quarchpy/docs/_build/html/source/quarchpy.disk_test.html +7 -6
  114. quarchpy/docs/_build/html/source/quarchpy.fio.html +9 -34
  115. quarchpy/docs/_build/html/source/quarchpy.html +8 -16
  116. quarchpy/docs/_build/html/source/quarchpy.iometer.html +7 -6
  117. quarchpy/docs/_build/html/source/quarchpy.qis.html +7 -6
  118. quarchpy/docs/_build/html/source/quarchpy.qps.html +7 -6
  119. quarchpy/docs/_build/html/source/quarchpy.user_interface.html +7 -6
  120. quarchpy/docs/_build/html/source/quarchpy.utilities.html +7 -6
  121. quarchpy/docs/_build/html/source/readme.html +7 -6
  122. quarchpy/fio/__pycache__/FIO_interface.cpython-311.pyc +0 -0
  123. quarchpy/fio/__pycache__/__init__.cpython-311.pyc +0 -0
  124. quarchpy/fio/__pycache__/fioDiskFinder.cpython-311.pyc +0 -0
  125. quarchpy/iometer/__pycache__/__init__.cpython-311.pyc +0 -0
  126. quarchpy/iometer/__pycache__/gen_iometer_template.cpython-311.pyc +0 -0
  127. quarchpy/iometer/__pycache__/iometerFuncs.cpython-311.pyc +0 -0
  128. quarchpy/qis/__pycache__/StreamHeaderInfo.cpython-311.pyc +0 -0
  129. quarchpy/qis/__pycache__/__init__.cpython-311.pyc +0 -0
  130. quarchpy/qis/__pycache__/qisFuncs.cpython-311.pyc +0 -0
  131. quarchpy/qis/qisFuncs.py +48 -14
  132. quarchpy/qps/__pycache__/__init__.cpython-311.pyc +0 -0
  133. quarchpy/qps/__pycache__/qpsFuncs.cpython-311.pyc +0 -0
  134. quarchpy/qps/qpsFuncs.py.bak +28 -68
  135. quarchpy/user_interface/__pycache__/__init__.cpython-311.pyc +0 -0
  136. quarchpy/user_interface/__pycache__/user_interface.cpython-311.pyc +0 -0
  137. quarchpy/user_interface/user_interface.py.bak +749 -0
  138. quarchpy/utilities/TestCenter.py.bak +150 -0
  139. quarchpy/utilities/__pycache__/BitManipulation.cpython-311.pyc +0 -0
  140. quarchpy/utilities/__pycache__/TestCenter.cpython-311.pyc +0 -0
  141. quarchpy/utilities/__pycache__/TimeValue.cpython-311.pyc +0 -0
  142. quarchpy/utilities/__pycache__/Version.cpython-311.pyc +0 -0
  143. quarchpy/utilities/__pycache__/__init__.cpython-311.pyc +0 -0
  144. {quarchpy-2.1.20.dev1.dist-info → quarchpy-2.1.20.dev3.dist-info}/METADATA +11 -1
  145. {quarchpy-2.1.20.dev1.dist-info → quarchpy-2.1.20.dev3.dist-info}/RECORD +147 -115
  146. quarchpy/_version.py.bak +0 -1
  147. quarchpy/connection_specific/connection_mDNS.py.bak +0 -48
  148. quarchpy/debug/SystemTest.py.bak +0 -188
  149. quarchpy/fio/FIO_interface.py.bak +0 -322
  150. quarchpy/run.py.bak +0 -283
  151. {quarchpy-2.1.20.dev1.dist-info → quarchpy-2.1.20.dev3.dist-info}/WHEEL +0 -0
  152. {quarchpy-2.1.20.dev1.dist-info → quarchpy-2.1.20.dev3.dist-info}/top_level.txt +0 -0
@@ -178,39 +178,32 @@ List all Quarch devices found over LAN, using a UDP broadcast scan
178
178
  def list_network(target_conn="all", debugPring=False, lanTimeout=1, ipAddressLookup=None):
179
179
 
180
180
  retVal={}
181
-
182
181
  lan_modules = dict()
183
-
184
182
  specifiedDevice = None
185
-
186
183
  # Broadcast the message.
187
184
  logging.debug("Broadcast LAN discovery message for UDP scan to all network interfaces")
188
185
  ipList = socket.gethostbyname_ex(socket.gethostname())
189
186
  logging.debug(os.path.basename(__file__) + ": Discovered the following interfaces: " + str(ipList))
190
187
 
188
+
189
+
191
190
  for ip in ipList[2]:
192
-
193
191
  logging.debug(os.path.basename(__file__) + ": Broadcasting on : " + ip)
194
-
195
192
  try:
196
-
197
193
  mySocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
198
194
  mySocket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
199
195
  mySocket.settimeout(lanTimeout)
200
196
  mySocket.bind((ip,56732))
201
-
202
- if ipAddressLookup is not None:
203
- # Attempts to find the device through UDP then REST
204
- specifiedDevice = lookupDevice(str(ipAddressLookup).strip(), mySocket, lan_modules)
205
-
206
197
  except Exception as err:
207
-
208
198
  logging.debug("Error while trying to bind to network interfaces: "+" Error: "+str(err))
209
199
 
210
- mySocket.sendto(b'Discovery: Who is out there?\0\n', ('255.255.255.255', 30303))
200
+ if ipAddressLookup is not None:
201
+ # Attempts to find the device through UDP then REST
202
+ specifiedDevice = lookupDevice(str(ipAddressLookup).strip(), mySocket, lan_modules)
211
203
 
212
- counter = 0
213
204
 
205
+ mySocket.sendto(b'Discovery: Who is out there?\0\n', ('255.255.255.255', 30303))
206
+ counter = 0
214
207
  # Receive messages until timeout.
215
208
  while True:
216
209
  network_modules = {}
@@ -218,7 +211,7 @@ def list_network(target_conn="all", debugPring=False, lanTimeout=1, ipAddressLoo
218
211
  # Receive raw message until timeout, then break.
219
212
  try:
220
213
  msg_received = mySocket.recvfrom(256)
221
- except:
214
+ except Exception as e:
222
215
  # check if any a device was targeted directly and allow parse
223
216
  if specifiedDevice is not None:
224
217
  msg_received = specifiedDevice
@@ -240,14 +233,10 @@ def list_network(target_conn="all", debugPring=False, lanTimeout=1, ipAddressLoo
240
233
  else:
241
234
  index = repr(lines[0]).replace("'", "")
242
235
  data = repr(lines[1:]).replace("'", "").replace("b", "")
243
-
244
236
  network_modules[index] = data
245
-
246
237
  module_name = get_user_level_serial_number(network_modules)
247
238
  logging.debug("Found UDP response: " + module_name)
248
-
249
239
  ip_module = msg_received[1][0].strip()
250
-
251
240
  try:
252
241
  # Add a QTL before modules without it.
253
242
  if "QTL" not in module_name.decode("utf-8"):
@@ -277,15 +266,20 @@ def list_network(target_conn="all", debugPring=False, lanTimeout=1, ipAddressLoo
277
266
  # Append the information to the list.
278
267
  lan_modules["TCP:" + ip_module] = module_name
279
268
  logging.debug("Found TCP module: " + module_name)
280
-
281
269
  mySocket.close()
270
+
282
271
  logging.debug("Finished UDP scan")
283
272
  retVal.update(lan_modules)
284
273
  return retVal
285
274
 
286
275
 
287
- ''''''
276
+
288
277
  def get_user_level_serial_number(network_modules):
278
+ '''
279
+
280
+ :param network_modules:
281
+ :return:
282
+ '''
289
283
  list_of_multi_module_units = ["1995"] # List of modules that require enclosure number + Port to be displayed.
290
284
 
291
285
  # Filter the raw message to get the module and ip address.
@@ -313,54 +307,53 @@ def get_user_level_serial_number(network_modules):
313
307
  ''''''
314
308
  def lookupDevice(ipAddressLookup, mySocket, lan_modules):
315
309
  try:
316
- printText("Ipaddress lookup " + ipAddressLookup)
310
+ logging.debug("Ipaddress lookup " + ipAddressLookup)
317
311
  # For future reference, 0 is the C terminator for a string
318
312
  mySocket.sendto(b'Discovery: Who is out there?\0\n', (str(ipAddressLookup).strip(), 30303))
319
313
  specifiedDevice = mySocket.recvfrom(256)
320
314
  # Check to see if the response contains the connection protocol
321
- if ("\\x8a") or ("138") or ("\\x84") or ("132") or ("\\x85") or ("133") not in specifiedDevice:
322
- # If not allow it to fall-back to REST
323
- specifiedDevice = None
324
- else:
325
- # Exit as device was found correctly
326
- return specifiedDevice
315
+ return specifiedDevice
327
316
  except Exception as e:
328
- printText("Error during UDP lookup " + str(e))
329
- printText("Is the IP address correct?\r\n")
330
- # Return if there's an error
331
- return None
317
+ logging.warning("Error during UDP lookup of IP address "+ str(ipAddressLookup) +" Error: " + str(e))
318
+ logging.warning("No Quarch module found at this address. Please check the IP address and that you can ping it.\r\n")
319
+ return None
320
+ #
321
+ # if specifiedDevice is None: #Only True if TCP not found or errored
322
+ # try:
323
+ # restCon = connection_ReST.ReSTConn(str(ipAddressLookup).replace("\r\n", ""))
324
+ # restDevice = restCon.sendCommand("*enclosure?") #Try use enclosure for PPMs
325
+ # if "fail" in restDevice.lower(): # This will fail nicely for other modules
326
+ # restDevice = restCon.sendCommand("*serial?") # and serial number will be used in place.
327
+ # if not str(restDevice).startswith("QTL"):
328
+ # restDevice = "QTL" + restDevice
329
+ # # Exit as device was found correctly
330
+ # # Add the item to list
331
+ # lan_modules["REST:" + str(ipAddressLookup).replace("\r\n", "")] = restDevice
332
+ # specifiedDevice=None # Don't return rest connection, to bypass tcp parsing.
333
+ # except Exception as e:
334
+ # logging.warning("Error During REST scan of IP address " + str(ipAddressLookup) + " Error: " + str(e))
335
+ # logging.warning("Please check the IP address and that you can ping it.\r\n")
336
+ #
337
+ # # Needs to return None so previous method will not attempt another lookup.
338
+ # return specifiedDevice
339
+
332
340
 
333
- if specifiedDevice is None:
334
- try:
335
- restCon = connection_ReST.ReSTConn(str(ipAddressLookup).replace("\r\n", ""))
336
- restDevice = restCon.sendCommand("*serial?")
337
- if not str(restDevice).startswith("QTL"):
338
- restDevice = "QTL" + restDevice
339
- # Add the item to list
340
- lan_modules["REST:" + str(ipAddressLookup).replace("\r\n", "")] = restDevice
341
341
 
342
- except Exception as e:
343
- printText("Error During REST scan " + str(e))
344
-
345
- # Needs to return None so previous method will not attempt another lookup.
346
- return None
347
-
348
-
349
- """
350
- Takes in the connection target and returns the serial number of a module found on the standard scan.
351
-
352
- Parameters
353
- ----------
354
- connectionTarget= : str
355
- The connection target of the module you would like to know the serial number of.
356
-
357
- Returns
358
- -------
359
- ret_val : str
360
- The Serial number of the supplied device.
361
-
362
- """
363
342
  def getSerialNumberFromConnectionTarget(connectionTarget):
343
+ """
344
+ Takes in the connection target and returns the serial number of a module found on the standard scan.
345
+
346
+ Parameters
347
+ ----------
348
+ connectionTarget= : str
349
+ The connection target of the module you would like to know the serial number of.
350
+
351
+ Returns
352
+ -------
353
+ ret_val : str
354
+ The Serial number of the supplied device.
355
+
356
+ """
364
357
  myDict = scanDevices(favouriteOnly=False)
365
358
  for k,v in myDict.items():
366
359
  if k == connectionTarget:
@@ -368,32 +361,31 @@ def getSerialNumberFromConnectionTarget(connectionTarget):
368
361
  return None
369
362
 
370
363
 
371
- """
372
- Takes in the connection type and serial number of a module and returns the connection target.
373
-
374
- Parameters
375
- ----------
376
- module_string= : str
377
- The connection type and serial number combination eg. TCP:QTL1999-05-005.
378
-
379
- scan_dictionary= :dict, optional
380
- A scan dictionary can be passed so that a scan does not need to take place on every call.
381
- This would be advised if calling this for every item in a list of serial numbers.
382
-
383
- connection_preference= : list str, optional
384
- The preference of which connection type to prioratise if none it given.
385
- Defaults to "USB", "TCP", "SERIAL", "REST", "TELNET" in that order.
386
-
387
- include_conn_type = : boolean, optional
388
- Decided whether the connection type will appear in the return value eg. TCP:192.168.1.1 vs 192.168.1.1
389
-
390
- Returns
391
- -------
392
- ret_val : str
393
- The Connection target of the supplied device.
394
-
395
- """
396
364
  def get_connection_target(module_string ,scan_dictionary=None, connection_preference= None, include_conn_type = True):
365
+ """
366
+ Takes in the connection type and serial number of a module and returns the connection target.
367
+
368
+ Parameters
369
+ ----------
370
+ module_string= : str
371
+ The connection type and serial number combination eg. TCP:QTL1999-05-005.
372
+
373
+ scan_dictionary= :dict, optional
374
+ A scan dictionary can be passed so that a scan does not need to take place on every call.
375
+ This would be advised if calling this for every item in a list of serial numbers.
376
+
377
+ connection_preference= : list str, optional
378
+ The preference of which connection type to prioratise if none it given.
379
+ Defaults to "USB", "TCP", "SERIAL", "REST", "TELNET" in that order.
380
+
381
+ include_conn_type = : boolean, optional
382
+ Decided whether the connection type will appear in the return value eg. TCP:192.168.1.1 vs 192.168.1.1
383
+
384
+ Returns
385
+ -------
386
+ ret_val : str
387
+ The Connection target of the supplied device.
388
+ """
397
389
  logging.debug("Getting connection target for : "+ str(module_string))
398
390
  if connection_preference == None:
399
391
  connection_preference = ["USB", "TCP", "SERIAL", "REST", "TELNET"]
@@ -20,7 +20,8 @@ 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
23
- from quarchpy.connection_specific.connection_mDNS import MyListener
23
+
24
+ # TODO: bodge bodge bodge
24
25
  from quarchpy.utilities import TestCenter
25
26
 
26
27
 
@@ -175,9 +176,25 @@ def list_USB(debuPrint=False):
175
176
  '''
176
177
  List all Quarch devices found over LAN, using a UDP broadcast scan
177
178
  '''
179
+
180
+ def get_interface_ips():
181
+ interfaces = socket.if_nameindex()
182
+ interface_ips = {}
183
+ for idx, interface in interfaces:
184
+ try:
185
+ addresses = socket.getaddrinfo(interface, None)
186
+ ip_addresses = [addr[4][0] for addr in addresses]
187
+ interface_ips[interface] = ip_addresses
188
+ except socket.gaierror:
189
+ logging.warning(f"Unable to get IP address for interface {interface}")
190
+ return interface_ips
178
191
  def list_network(target_conn="all", debugPring=False, lanTimeout=1, ipAddressLookup=None):
179
192
 
180
193
  retVal={}
194
+ # Create and configure the socket for broadcast.
195
+ mySocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
196
+ mySocket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
197
+ mySocket.settimeout(lanTimeout)
181
198
 
182
199
  lan_modules = dict()
183
200
 
@@ -186,101 +203,96 @@ def list_network(target_conn="all", debugPring=False, lanTimeout=1, ipAddressLoo
186
203
  if ipAddressLookup is not None:
187
204
  # Attempts to find the device through UDP then REST
188
205
  specifiedDevice = lookupDevice(str(ipAddressLookup).strip(), mySocket, lan_modules )
206
+ mySocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
207
+ mySocket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
208
+ mySocket.settimeout(lanTimeout)
209
+
210
+
189
211
 
190
212
  # Broadcast the message.
191
213
  logging.debug("Broadcast LAN discovery message for UDP scan to all network interfaces")
192
- ipList = socket.gethostbyname_ex(socket.gethostname())
193
- logging.debug(os.path.basename(__file__) + ": Discovered the following interfaces: " + str(ipList))
194
-
195
- for ip in ipList[2]:
196
-
197
- logging.debug(os.path.basename(__file__) + ": Broadcasting on : " + ip)
198
-
214
+ logging.debug("Available network interfaces before binding:")
215
+ interfaces = socket.if_nameindex()
216
+ for idx, interface in interfaces:
217
+ logging.debug(f"Interface {idx}: {interface}")
218
+ try:
219
+ # Bind to all network interfaces using '', same as '0.0.0.0'
220
+ mySocket.bind(('',56732))
221
+ except Exception as err:
222
+ logging.debug("Error while trying to bind to network interfaces: "+" Error: "+str(err))
223
+ mySocket.sendto(b'Discovery: Who is out there?\0\n', ('255.255.255.255', 30303))
224
+ #mySocket.sendto(b'Discovery: Who is out there?\0\n', ('255.255.255.255', 30303)) #56732
225
+
226
+ counter = 0
227
+
228
+ # Receive messages until timeout.
229
+ while True:
230
+ network_modules = {}
231
+ counter += 1
232
+ # Receive raw message until timeout, then break.
199
233
  try:
234
+ msg_received = mySocket.recvfrom(256)
235
+ except:
236
+ # check if any a device was targeted directly and allow parse
237
+ if specifiedDevice is not None:
238
+ msg_received = specifiedDevice
239
+ specifiedDevice = None
240
+ else:
241
+ break
242
+ cont = 0
243
+
244
+ # print(msg_received)
245
+ # Used split \r\n since values of 13 or 10 were looked at as /r and /n when using splitlines
246
+ # This fixes for all cases except if 13 is followed by 10.
247
+ splits = msg_received[0].split(b"\r\n")
248
+ del splits[-1]
249
+ for lines in splits:
250
+ if cont <= 1:
251
+ index = cont
252
+ data = repr(lines).replace("'", "").replace("b", "")
253
+ cont += 1
254
+ else:
255
+ index = repr(lines[0]).replace("'", "")
256
+ data = repr(lines[1:]).replace("'", "").replace("b", "")
200
257
 
201
- mySocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
202
- mySocket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
203
- mySocket.settimeout(lanTimeout)
204
- mySocket.bind((ip,56732))
205
-
206
- except Exception as err:
207
-
208
- logging.debug("Error while trying to bind to network interfaces: "+" Error: "+str(err))
209
-
210
-
211
-
212
- mySocket.sendto(b'Discovery: Who is out there?\0\n', ('255.255.255.255', 30303))
258
+ network_modules[index] = data
213
259
 
214
- counter = 0
260
+ module_name = get_user_level_serial_number(network_modules)
261
+ logging.debug("Found UDP response: " + module_name)
215
262
 
216
- # Receive messages until timeout.
217
- while True:
218
- network_modules = {}
219
- counter += 1
220
- # Receive raw message until timeout, then break.
221
- try:
222
- msg_received = mySocket.recvfrom(256)
223
- except:
224
- # check if any a device was targeted directly and allow parse
225
- if specifiedDevice is not None:
226
- msg_received = specifiedDevice
227
- specifiedDevice = None
228
- else:
229
- break
230
- cont = 0
231
-
232
- # print(msg_received)
233
- # Used split \r\n since values of 13 or 10 were looked at as /r and /n when using splitlines
234
- # This fixes for all cases except if 13 is followed by 10.
235
- splits = msg_received[0].split(b"\r\n")
236
- del splits[-1]
237
- for lines in splits:
238
- if cont <= 1:
239
- index = cont
240
- data = repr(lines).replace("'", "").replace("b", "")
241
- cont += 1
242
- else:
243
- index = repr(lines[0]).replace("'", "")
244
- data = repr(lines[1:]).replace("'", "").replace("b", "")
245
-
246
- network_modules[index] = data
247
-
248
- module_name = get_user_level_serial_number(network_modules)
249
- logging.debug("Found UDP response: " + module_name)
250
-
251
- ip_module = msg_received[1][0].strip()
263
+ ip_module = msg_received[1][0].strip()
252
264
 
253
- try:
254
- # Add a QTL before modules without it.
255
- if "QTL" not in module_name.decode("utf-8"):
256
- module_name = "QTL" + module_name.decode("utf-8")
257
- except:
258
- # Add a QTL before modules without it.
259
- if "QTL" not in module_name:
260
- module_name = "QTL" + module_name
261
-
262
- # Checks if there's a value in the TELNET key.
263
- if (target_conn.lower() == "all" or target_conn.lower() == "telnet"):
264
- if network_modules.get("\\x8a") or network_modules.get("138"):
265
- # Append the information to the list.
266
- lan_modules["TELNET:" + ip_module] = module_name
267
- logging.debug("Found Telnet module: " + module_name)
268
-
269
- # Checks if there's a value in the REST key.
270
- if (target_conn.lower() == "all" or target_conn.lower() == "rest"):
271
- if network_modules.get("\\x84") or network_modules.get("132"):
272
- # Append the information to the list.
273
- lan_modules["REST:" + ip_module] = module_name
274
- logging.debug("Found REST module: " + module_name)
275
-
276
- # Checks if there's a value in the TCP key.
277
- if (target_conn.lower() == "all" or target_conn.lower() == "tcp"):
278
- if network_modules.get("\\x85") or network_modules.get("133"):
279
- # Append the information to the list.
280
- lan_modules["TCP:" + ip_module] = module_name
281
- logging.debug("Found TCP module: " + module_name)
282
-
283
- mySocket.close()
265
+ try:
266
+ # Add a QTL before modules without it.
267
+ if "QTL" not in module_name.decode("utf-8"):
268
+ module_name = "QTL" + module_name.decode("utf-8")
269
+ except:
270
+ # Add a QTL before modules without it.
271
+ if "QTL" not in module_name:
272
+ module_name = "QTL" + module_name
273
+
274
+ # Checks if there's a value in the TELNET key.
275
+ if (target_conn.lower() == "all" or target_conn.lower() == "telnet"):
276
+ if network_modules.get("\\x8a") or network_modules.get("138"):
277
+ # Append the information to the list.
278
+ lan_modules["TELNET:" + ip_module] = module_name
279
+ logging.debug("Found Telnet module: " + module_name)
280
+
281
+ # Checks if there's a value in the REST key.
282
+ if (target_conn.lower() == "all" or target_conn.lower() == "rest"):
283
+ if network_modules.get("\\x84") or network_modules.get("132"):
284
+ # Append the information to the list.
285
+ lan_modules["REST:" + ip_module] = module_name
286
+ logging.debug("Found REST module: " + module_name)
287
+
288
+ # Checks if there's a value in the TCP key.
289
+ if (target_conn.lower() == "all" or target_conn.lower() == "tcp"):
290
+ if network_modules.get("\\x85") or network_modules.get("133"):
291
+ # Append the information to the list.
292
+ lan_modules["TCP:" + ip_module] = module_name
293
+ logging.debug("Found TCP module: " + module_name)
294
+
295
+ mySocket.close()
284
296
  logging.debug("Finished UDP scan")
285
297
  retVal.update(lan_modules)
286
298
  return retVal
@@ -459,12 +471,6 @@ def filter_module_type(module_type_filter, found_devices):
459
471
  filtered_devices.update({key: value})
460
472
  return filtered_devices
461
473
 
462
- def scan_mDNS(mdnsListener):
463
- from zeroconf import ServiceBrowser, Zeroconf
464
- zeroconf = Zeroconf()
465
- listener = mdnsListener
466
- browser = ServiceBrowser(zeroconf, "_http._tcp.local.", listener)
467
-
468
474
 
469
475
  '''
470
476
  Scans for Quarch modules across the given interface(s). Returns a dictionary of module addresses and serial numbers
@@ -474,19 +480,12 @@ def scanDevices(target_conn="all", lanTimeout=1, scanInArray=True, favouriteOnly
474
480
  foundDevices = dict()
475
481
  scannedArrays = list()
476
482
 
477
-
478
483
  if target_conn.lower() == "all":
479
484
  foundDevices = list_USB()
480
485
  foundDevices = mergeDict(foundDevices, list_serial())
481
486
  try:
482
487
  #This will fail if the test machine is not connected to a network
483
488
  foundDevices = mergeDict(foundDevices, list_network("all", ipAddressLookup=ipAddressLookup, lanTimeout=lanTimeout))
484
- try:
485
- mdnsListener = MyListener()
486
- scan_mDNS(mdnsListener)
487
- foundDevices = mergeDict(foundDevices, mdnsListener.found_devices)
488
- except Exception as mdnsExcept:
489
- logging.debug("An error occurred while trying to use the mdns listner to scan\n" +str(mdnsExcept))
490
489
  except Exception as e:
491
490
  logging.error(e)
492
491
  logging.warning("Network scan failed, check network connection")
@@ -513,8 +512,8 @@ def scanDevices(target_conn="all", lanTimeout=1, scanInArray=True, favouriteOnly
513
512
  foundDevices = mergeDict(foundDevices, scanDevices)
514
513
  myArrayControler.closeConnection()
515
514
  except Exception as e:
516
- logging.debug(e, exc_info=True)
517
- logging.debug("Cannot get serial number. Quarch device may be in use by another program.")
515
+ logging.error(e, exc_info=True)
516
+ logging.warning("Cannot get serial number. Quarch device may be in use by another program.")
518
517
  foundDevices[k] = "DEVICE IN USE"
519
518
 
520
519
  if (favouriteOnly):
@@ -594,7 +593,7 @@ def userSelectDevice(scanDictionary=None, scanFilterStr=None,favouriteOnly=True,
594
593
 
595
594
 
596
595
  if nice: #Prepair the data for niceListSelection using displayTable().
597
- if additionalOptions is None: additionalOptions = ["Specify IP Address","Rescan","Quit"]
596
+ if additionalOptions is None: additionalOptions = ["IP Scan","Rescan","Quit"]
598
597
  tempList = []
599
598
  tempEl = []
600
599
  for k, v in scanDictionary.items():
@@ -617,7 +616,7 @@ def userSelectDevice(scanDictionary=None, scanFilterStr=None,favouriteOnly=True,
617
616
  devicesString.append(k + '=' + v + ": " + k[:charPos])
618
617
  devicesString = ','.join(devicesString)
619
618
  if additionalOptions is None :
620
- additionalOptions = "Specify IP Address=IP Scan,Rescan=Rescan,Quit=Quit"
619
+ additionalOptions = "IP Scan=IP Scan,Rescan=Rescan,Quit=Quit"
621
620
  userStr = listSelection(title=title,message=message,selectionList=devicesString, additionalOptions=additionalOptions)
622
621
 
623
622
  # Process the user response
@@ -631,7 +630,7 @@ def userSelectDevice(scanDictionary=None, scanFilterStr=None,favouriteOnly=True,
631
630
  ip_address = None
632
631
  scanDictionary = None
633
632
  favouriteOnly = False
634
- elif(userStr.lower() in 'specify ip address'):
633
+ elif(userStr.lower() in 'ip scan'):
635
634
  ip_address = requestDialog("Please input IP Address of the module you would like to connect to: ")
636
635
  scanDictionary = None
637
636
  favouriteOnly = False
@@ -639,3 +638,24 @@ def userSelectDevice(scanDictionary=None, scanFilterStr=None,favouriteOnly=True,
639
638
  # Return the address string of the selected module
640
639
  return userStr
641
640
 
641
+
642
+ #Not used but could come in usefull in near future.
643
+ # def userSelectAndReturnDevice(scanDictionary=None, scanFilterStr=None,favouriteOnly=True, message=None, title=None, nice=True, additionalOptions =["rescan","all conn types", "quit"], target_conn="all"):
644
+ # scanDictionary = scanDevices()
645
+ # connectionTarget = userSelectDevice(scanDictionary, scanFilterStr, favouriteOnly, message, title, nice,
646
+ # additionalOptions, target_conn)
647
+ # serialNumber = getSerialNumberFromConnectionTarget(connectionTarget)
648
+ #
649
+ # if connectionTarget.__contains__("<") and connectionTarget.__contains__(">"):
650
+ # connectionTarget, portNumber = connectionTarget.split("<")
651
+ # portNumber = portNumber[:-1]
652
+ # myDevice = quarchDevice(connectionTarget)
653
+ # myArrayController = quarchArray(myDevice)
654
+ # mySubDevice = myArrayController.getSubDevice(portNumber)
655
+ # myDevice = mySubDevice
656
+ # elif(serialNumber.lower().__contains__("qtl1999") or serialNumber.lower().__contains__("qtl1995") or serialNumber.lower().__contains__("qtl2312")):
657
+ # myDevice = quarchPPM(quarchDevice(connectionTarget))
658
+ #
659
+ # else:
660
+ # myDevice = quarchDevice(connectionTarget)
661
+ # return myDevice
quarchpy/docs/CHANGES.rst CHANGED
@@ -13,6 +13,16 @@ Quarchpy
13
13
  Change Log
14
14
  ----------
15
15
 
16
+ 2.1.20
17
+ ------
18
+ - Improved direct IP scanning for quarch modules.
19
+
20
+ 2.1.19
21
+ ------
22
+ - Imporoved QIS streaming
23
+ - Bug fixes
24
+ - Added zeroconf, numpy and pandas as requirements
25
+
16
26
  2.1.18
17
27
  ------
18
28
  - Minor bug fix