quarchpy 2.1.13.dev2__py2.py3-none-any.whl → 2.1.14.dev2__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 (81) hide show
  1. quarchpy/.idea/modules.xml +1 -0
  2. quarchpy/.idea/quarchpy.iml +4 -1
  3. quarchpy/.idea/workspace.xml +149 -11
  4. quarchpy/_version.py +1 -1
  5. quarchpy/connection_specific/connection_QIS.py +213 -315
  6. quarchpy/connection_specific/connection_QIS.py.bak +253 -357
  7. quarchpy/connection_specific/connection_TCP.py +1 -1
  8. quarchpy/connection_specific/connection_mDNS.py +46 -0
  9. quarchpy/device/quarchPPM.py +2 -2
  10. quarchpy/device/quarchQPS.py +95 -86
  11. quarchpy/device/scanDevices.py +12 -0
  12. quarchpy/docs/CHANGES.rst +7 -1
  13. quarchpy/qps/qpsFuncs.py +7 -4
  14. quarchpy/run.py +1 -1
  15. quarchpy/user_interface/user_interface.py.bak +3 -5
  16. quarchpy/utilities/TestCenter.py +1 -1
  17. quarchpy/utilities/TestCenter.py.bak +1 -4
  18. quarchpy/utilities/Version.py +50 -0
  19. {quarchpy-2.1.13.dev2.dist-info → quarchpy-2.1.14.dev2.dist-info}/METADATA +8 -2
  20. {quarchpy-2.1.13.dev2.dist-info → quarchpy-2.1.14.dev2.dist-info}/RECORD +22 -79
  21. quarchpy/.idea/.name +0 -1
  22. quarchpy/.idea/inspectionProfiles/Project_Default.xml +0 -26
  23. quarchpy/__pycache__/__init__.cpython-311.pyc +0 -0
  24. quarchpy/__pycache__/_version.cpython-311.pyc +0 -0
  25. quarchpy/__pycache__/connection.cpython-311.pyc +0 -0
  26. quarchpy/__pycache__/run.cpython-311.pyc +0 -0
  27. quarchpy/config_files/__pycache__/__init__.cpython-311.pyc +0 -0
  28. quarchpy/config_files/__pycache__/quarch_config_parser.cpython-311.pyc +0 -0
  29. quarchpy/connection_specific/__pycache__/StreamChannels.cpython-311.pyc +0 -0
  30. quarchpy/connection_specific/__pycache__/__init__.cpython-311.pyc +0 -0
  31. quarchpy/connection_specific/__pycache__/connection_QIS.cpython-311.pyc +0 -0
  32. quarchpy/connection_specific/__pycache__/connection_QPS.cpython-311.pyc +0 -0
  33. quarchpy/connection_specific/__pycache__/connection_ReST.cpython-311.pyc +0 -0
  34. quarchpy/connection_specific/__pycache__/connection_Serial.cpython-311.pyc +0 -0
  35. quarchpy/connection_specific/__pycache__/connection_USB.cpython-311.pyc +0 -0
  36. quarchpy/connection_specific/serial/__pycache__/__init__.cpython-311.pyc +0 -0
  37. quarchpy/connection_specific/serial/__pycache__/serialutil.cpython-311.pyc +0 -0
  38. quarchpy/connection_specific/serial/__pycache__/serialwin32.cpython-311.pyc +0 -0
  39. quarchpy/connection_specific/serial/__pycache__/win32.cpython-311.pyc +0 -0
  40. quarchpy/connection_specific/serial/tools/__pycache__/__init__.cpython-311.pyc +0 -0
  41. quarchpy/connection_specific/serial/tools/__pycache__/list_ports.cpython-311.pyc +0 -0
  42. quarchpy/connection_specific/serial/tools/__pycache__/list_ports_common.cpython-311.pyc +0 -0
  43. quarchpy/connection_specific/serial/tools/__pycache__/list_ports_windows.cpython-311.pyc +0 -0
  44. quarchpy/connection_specific/usb_libs/__pycache__/libusb1.cpython-311.pyc +0 -0
  45. quarchpy/connection_specific/usb_libs/__pycache__/usb1.cpython-311.pyc +0 -0
  46. quarchpy/debug/TextScanIP.py +0 -11
  47. quarchpy/debug/__pycache__/SystemTest.cpython-311.pyc +0 -0
  48. quarchpy/debug/__pycache__/__init__.cpython-311.pyc +0 -0
  49. quarchpy/debug/__pycache__/module_debug.cpython-311.pyc +0 -0
  50. quarchpy/debug/__pycache__/simple_terminal.cpython-311.pyc +0 -0
  51. quarchpy/debug/__pycache__/upgrade_quarchpy.cpython-311.pyc +0 -0
  52. quarchpy/debug/__pycache__/versionCompare.cpython-311.pyc +0 -0
  53. quarchpy/device/__pycache__/__init__.cpython-311.pyc +0 -0
  54. quarchpy/device/__pycache__/device.cpython-311.pyc +0 -0
  55. quarchpy/device/__pycache__/quarchArray.cpython-311.pyc +0 -0
  56. quarchpy/device/__pycache__/quarchPPM.cpython-311.pyc +0 -0
  57. quarchpy/device/__pycache__/quarchQPS.cpython-311.pyc +0 -0
  58. quarchpy/device/__pycache__/scanDevices.cpython-311.pyc +0 -0
  59. quarchpy/device/device.py.bak +0 -504
  60. quarchpy/device/scanDevices.py.bak +0 -661
  61. quarchpy/disk_test/__pycache__/AbsDiskFinder.cpython-311.pyc +0 -0
  62. quarchpy/disk_test/__pycache__/DiskTargetSelection.cpython-311.pyc +0 -0
  63. quarchpy/disk_test/__pycache__/__init__.cpython-311.pyc +0 -0
  64. quarchpy/disk_test/__pycache__/iometerDiskFinder.cpython-311.pyc +0 -0
  65. quarchpy/fio/__pycache__/FIO_interface.cpython-311.pyc +0 -0
  66. quarchpy/fio/__pycache__/__init__.cpython-311.pyc +0 -0
  67. quarchpy/iometer/__pycache__/__init__.cpython-311.pyc +0 -0
  68. quarchpy/iometer/__pycache__/gen_iometer_template.cpython-311.pyc +0 -0
  69. quarchpy/iometer/__pycache__/iometerFuncs.cpython-311.pyc +0 -0
  70. quarchpy/qis/__pycache__/StreamHeaderInfo.cpython-311.pyc +0 -0
  71. quarchpy/qis/__pycache__/__init__.cpython-311.pyc +0 -0
  72. quarchpy/qis/__pycache__/qisFuncs.cpython-311.pyc +0 -0
  73. quarchpy/qps/__pycache__/__init__.cpython-311.pyc +0 -0
  74. quarchpy/qps/__pycache__/qpsFuncs.cpython-311.pyc +0 -0
  75. quarchpy/user_interface/__pycache__/__init__.cpython-311.pyc +0 -0
  76. quarchpy/user_interface/__pycache__/user_interface.cpython-311.pyc +0 -0
  77. quarchpy/utilities/__pycache__/TestCenter.cpython-311.pyc +0 -0
  78. quarchpy/utilities/__pycache__/TimeValue.cpython-311.pyc +0 -0
  79. quarchpy/utilities/__pycache__/__init__.cpython-311.pyc +0 -0
  80. {quarchpy-2.1.13.dev2.dist-info → quarchpy-2.1.14.dev2.dist-info}/WHEEL +0 -0
  81. {quarchpy-2.1.13.dev2.dist-info → quarchpy-2.1.14.dev2.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,4 @@
1
+ import csv
1
2
  import socket
2
3
  import re
3
4
  import time
@@ -9,7 +10,7 @@ import threading
9
10
  import math
10
11
  import logging
11
12
  import struct
12
- from pathlib import Path
13
+ from io import StringIO
13
14
  from quarchpy.user_interface import *
14
15
  import xml.etree.ElementTree as ET
15
16
  from connection_specific.StreamChannels import StreamGroups
@@ -46,13 +47,7 @@ class QisInterface:
46
47
  self.streamSock.settimeout(5)
47
48
  self.streamSock.connect((self.host, self.port))
48
49
  self.pythonVersion = sys.version[0]
49
- #self.sendText(self.streamSock, '$scan')
50
- #time.sleep(3)
51
- if self.pythonVersion == '3':
52
- temp = '>'
53
- self.cursor = temp.encode()
54
- else:
55
- self.cursor = '>'
50
+ self.cursor = '>'
56
51
  #clear packets
57
52
  welcomeString = self.streamSock.recv(self.maxRxBytes).rstrip()
58
53
 
@@ -111,19 +106,15 @@ class QisInterface:
111
106
  def closeConnection(self, sock=None, conString=None):
112
107
  if sock == None:
113
108
  sock = self.sock
114
-
115
109
  if conString is None:
116
110
  cmd="close"
117
111
  else:
118
112
  cmd =conString+" close"
119
113
 
120
- if self.pythonVersion == '3':
121
- response = self.sendAndReceiveText(sock, cmd).decode()
122
- else:
123
- response = self.sendAndReceiveText(sock, cmd)
114
+ response = self.sendAndReceiveText(sock, cmd)
124
115
  return response
125
116
 
126
- def startStream(self, module, fileName, fileMaxMB, streamName, streamAverage, releaseOnData, separator, streamDuration = None):
117
+ def startStream(self, module, fileName, fileMaxMB, streamName, streamAverage, releaseOnData, separator, streamDuration = None, inMemoryData = None):
127
118
  self.StreamRunSentSemaphore.acquire()
128
119
  self.deviceDictSetup('QIS')
129
120
  i = self.deviceMulti(module)
@@ -133,7 +124,7 @@ class QisInterface:
133
124
 
134
125
  # Create the thread
135
126
  t1 = threading.Thread(target=self.startStreamThread, name=module,
136
- args=(module, fileName, fileMaxMB, streamName, streamAverage, releaseOnData, separator, streamDuration))
127
+ args=(module, fileName, fileMaxMB, streamName, streamAverage, releaseOnData, separator, streamDuration, inMemoryData))
137
128
  # Start the thread
138
129
  t1.start()
139
130
 
@@ -163,7 +154,6 @@ class QisInterface:
163
154
  pass
164
155
  # just wait until event is cleared
165
156
 
166
-
167
157
  def stopStream(self, module, blocking = True):
168
158
  moduleName=module.ConString
169
159
  i = self.deviceMulti(moduleName)
@@ -191,15 +181,20 @@ class QisInterface:
191
181
  else:
192
182
  running = False
193
183
  time.sleep(0.1)
194
-
195
- # This is the function that is run when t1 is created. It is run in a seperate thread from
196
- # the main application so streaming can happen without blocking the main application from
197
- # doing other things. Within this function/thread you have to be very careful not to try
198
- # and 'communicate' with anything from other threads. If you do, you MUST use a thread safe
199
- # way of communicating. The thread creates it's own socket and should use that, NOT the objects socket
200
- # (which some of the comms with module functions will use by default).
201
- def startStreamThread(self, module, fileName, fileMaxMB, streamName, streamAverage, releaseOnData, separator, streamDuration = None):
184
+
185
+ def startStreamThread(self, module, fileName, fileMaxMB, streamName, streamAverage, releaseOnData, separator, streamDuration = None, inMemoryData = None):
186
+ # This is the function that is run when t1 is created. It is run in a seperate thread from
187
+ # the main application so streaming can happen without blocking the main application from
188
+ # doing other things. Within this function/thread you have to be very careful not to try
189
+ # and 'communicate' with anything from other threads. If you do, you MUST use a thread safe
190
+ # way of communicating. The thread creates it's own socket and should use that, NOT the objects socket
191
+ # (which some of the comms with module functions will use by default).
192
+
202
193
  #Start module streaming and then read stream data
194
+ if inMemoryData is not None:
195
+ if not isinstance(inMemoryData, StringIO):
196
+ print("Error! The parameter 'inMemoryData' is NOT of type StringIO")
197
+ exit()
203
198
 
204
199
  stripes = ['Empty Header']
205
200
  #Send stream command so module starts streaming data into the backends buffer
@@ -234,6 +229,8 @@ class QisInterface:
234
229
  formatHeader = self.streamHeaderFormat(device=module, sock=self.streamSock)
235
230
  formatHeader = formatHeader.replace(", ", separator)
236
231
  f.write(formatHeader + '\n')
232
+ inMemoryData.write(formatHeader + '\n')
233
+
237
234
  numStripesPerRead = 4096
238
235
  maxFileExceeded = False
239
236
  openAttempts = 0
@@ -278,7 +275,7 @@ class QisInterface:
278
275
  while self.stopFlagList[i] and (not streamOverrun) and (not streamComplete):
279
276
  #now = time.time()
280
277
  streamOverrun, removeChar, newStripes = self.streamGetStripesText(self.streamSock, module, numStripesPerRead)
281
- newStripes = newStripes.replace(b' ', str.encode(separator))
278
+ newStripes = newStripes.replace(' ', separator)
282
279
  #print (time.time() - now)
283
280
  if streamOverrun:
284
281
  self.deviceDict[module][0:3] = [True, 'Stopped', 'Device buffer overrun']
@@ -308,22 +305,26 @@ class QisInterface:
308
305
  if streamDuration != None:
309
306
  # Get the last data line in the file
310
307
  lastLine = newStripes.splitlines()[-3] # the last data line is followed by 'eof' and '>'
311
- lastTime = lastLine.decode().split(separator)[0] # get the first (time) entry
308
+ lastTime = lastLine.split(separator)[0] # get the first (time) entry
312
309
 
313
310
  # if the last entry is still within the required stream length, write the whole lot
314
311
  if int(lastTime) < int(streamDuration/(10**baseSampleUnitExponent)): # < rather than <= because we start at 0
315
312
  f.write(newStripes[:removeChar])
313
+ inMemoryData.write(newStripes[:removeChar])
314
+
316
315
  # else write each line individually until we have reached the desired endpoint
317
316
  else:
318
317
  for thisLine in newStripes.splitlines()[:-2]:
319
- lastTime = thisLine.decode().split(separator)[0]
318
+ lastTime = thisLine.split(separator)[0]
320
319
  if int(lastTime) < int(streamDuration/(10**baseSampleUnitExponent)):
321
320
  f.write(thisLine + b'\r' + b'\n') # Put the CR back on the end
321
+ inMemoryData.write(thisLine + b'\r' + b'\n')
322
322
  else:
323
323
  streamComplete = True
324
324
  break
325
325
  else:
326
326
  f.write(newStripes[:removeChar])
327
+ inMemoryData.write(newStripes[:removeChar])
327
328
 
328
329
  else:
329
330
  maxFileExceeded = True
@@ -331,6 +332,8 @@ class QisInterface:
331
332
  maxFileStatus = self.streamBufferStatus(device=module, sock=self.streamSock)
332
333
  f.write('Warning: Max file size exceeded before end of stream.\n')
333
334
  f.write('Unrecorded stripes in buffer when file full: ' + maxFileStatus + '.')
335
+ inMemoryData.write('Warning: Max file size exceeded before end of stream.\n')
336
+ inMemoryData.write('Unrecorded stripes in buffer when file full: ' + maxFileStatus + '.')
334
337
  self.deviceDict[module][0:3] = [True, 'Stopped', 'User defined max filesize reached']
335
338
  break
336
339
  else:
@@ -378,8 +381,9 @@ class QisInterface:
378
381
  if(streamAverage != None):
379
382
  leftover, remainingStripes = self.averageStripes(leftover, stripesPerAverage, newStripes[:removeChar], f, remainingStripes)
380
383
  else:
381
- newStripes = newStripes.replace(b' ', str.encode(separator))
384
+ newStripes = newStripes.replace(' ',separator)
382
385
  f.write(newStripes[:removeChar])
386
+ inMemoryData.write(newStripes[:removeChar])
383
387
  else:
384
388
  if not maxFileExceeded:
385
389
  maxFileStatus = self.streamBufferStatus(device=module, sock=self.streamSock)
@@ -394,6 +398,8 @@ class QisInterface:
394
398
  if maxFileExceeded:
395
399
  f.write(b'Warning: Max file size exceeded before end of stream.\n')
396
400
  f.write(b'Unrecorded stripes in buffer when file full: ' + maxFileStatus + '.')
401
+ inMemoryData.write(b'Warning: Max file size exceeded before end of stream.\n')
402
+ inMemoryData.write(b'Unrecorded stripes in buffer when file full: ' + maxFileStatus + '.')
397
403
  logging.warning('Max file size exceeded. Some data has not been saved to file: ' + maxFileStatus + '.')
398
404
 
399
405
  #printText('Stripes in buffer now: ' + self.streamBufferStatus(device=module, sock=self.streamSock))
@@ -484,7 +490,7 @@ class QisInterface:
484
490
  # now = time.time()
485
491
  streamOverrun, removeChar, newStripes = self.streamGetStripesText(self.streamSock, module,
486
492
  numStripesPerRead)
487
- newStripes = newStripes.replace(b' ', str.encode(separator))
493
+ newStripes = newStripes.replace(' ',separator)
488
494
  # print(newStripes)
489
495
  # print(len(newStripes))
490
496
 
@@ -498,11 +504,7 @@ class QisInterface:
498
504
  if isEmpty == False:
499
505
  # Writes in file if not too big else stops streaming
500
506
  # print(newStripes)
501
-
502
- x = newStripes[:removeChar]
503
- y = x.decode("utf-8")
504
-
505
- print("decoded stripe : " + y)
507
+ print("decoded stripe : " + newStripes[:removeChar])
506
508
 
507
509
  # Writing multiple stripes
508
510
  if "\r\n" in y:
@@ -616,191 +618,6 @@ class QisInterface:
616
618
  x = struct.pack(">d", int(stripe[counter]))
617
619
  # logging.debug(item, x)
618
620
  file1.write(x)
619
-
620
-
621
- # Send text and get the backends response. - acts as wrapper to the sendAndReceiveText, intended to provide some extra convenience
622
- # when sending commands to module (as opposed to back end)
623
- # If read until cursor is set to True (which is default) then keep reading response until a cursor is returned as the last character of result string
624
- # After command is sent wait for betweenCommandDelay which defaults to 0 but can be specified to add a delay between commands
625
- # The objects connection needs to be opened (connect()) before this is used
626
- def sendCmd(self, device='', cmd='$help', sock=None, readUntilCursor=True, betweenCommandDelay=0.0, expectedResponse = True):
627
- if sock==None:
628
- sock = self.sock
629
- if not (device == ''):
630
- self.deviceDictSetup(device)
631
-
632
- if expectedResponse is False:
633
- self.sendText(sock, cmd, device)
634
- return
635
-
636
- res = self.sendAndReceiveText(sock, cmd, device, readUntilCursor)
637
- if (betweenCommandDelay > 0):
638
- time.sleep(betweenCommandDelay)
639
- #If ends with cursor get rid of it
640
- if res[-1:] == self.cursor:
641
- res = res[:-3] #remove last three chars - hopefully '\r\n>'
642
- # time.sleep(0.1)
643
- return res.decode()
644
-
645
-
646
- def sendAndReceiveCmd(self, sock=None, cmd='$help', device='', readUntilCursor=True, betweenCommandDelay=0.0):
647
- if sock==None:
648
- sock = self.sock
649
- if not (device == ''):
650
- self.deviceDictSetup(device)
651
- if self.pythonVersion == '3':
652
- res = self.sendAndReceiveText(sock, cmd, device, readUntilCursor).decode()
653
- else:
654
- res = self.sendAndReceiveText(sock, cmd, device, readUntilCursor)
655
- if (betweenCommandDelay > 0):
656
- time.sleep(betweenCommandDelay)
657
- #If ends with cursor get rid of it
658
- if res[-1:] == '>':
659
- res = res[:-3] #remove last three chars - hopefully '\r\n>'
660
- return cmd + ' : ' + res
661
-
662
- # Send text to the back end then read it's response
663
- # The objects connection needs to be opened (connect()) before this is used
664
- # If read until cursor is set to True (which is default) then keep reading response until a cursor is returned as the last character of result string
665
- def sendAndReceiveText(self, sock, sentText='$help', device='', readUntilCursor=True):
666
- self.sockSemaphore.acquire()
667
- try:
668
- self.sendText(sock, sentText, device)
669
- if self.pythonVersion == '3':
670
- res = bytearray()
671
- res.extend(self.rxBytes(sock))
672
- #Somtimes we just get one cursor back of currently unknown origins
673
- #If that happens discard it and read again
674
- if len(res)==0:
675
- logging.warning("empty response from QIS. Retrying.")
676
- streamResp=self.sendAndReceiveText(sock, "stream?",device,readUntilCursor).lower()
677
- if len(streamResp)==0:
678
- raise("Empty response from QIS twice in a row")
679
- else:
680
- logging.warning("Response recovered Successfully. Continuing.")
681
- res = bytearray()
682
- res.extend(self.rxBytes(sock))
683
- if len(res) == 0:
684
- raise ("empty response from QIS after second ")
685
- if res[0] == self.cursor:
686
- #res[0] = self.rxBytes(sock)
687
- logging.warning('Only Returned Cursor!!!!!')
688
- #If create socked fail (between backend and tcp/ip module)
689
- cba = 'Create Socket Fail'
690
- if cba.encode() == res[0]:
691
- logging.warning(res[0].decode())
692
- cba = 'Connection Timeout'
693
- if cba.encode() == res[0]:
694
- logging.warning(res[0].decode())
695
- #If reading until a cursor comes back then keep reading until a cursor appears or max tries exceeded
696
- if readUntilCursor:
697
- maxReads = 1000
698
- count = 1
699
- #check for cursor at end of read and if not there read again
700
- while res[-1:] != self.cursor:
701
- res.extend(self.rxBytes(sock))
702
- count += 1
703
- if count >= maxReads:
704
- raise Exception(' Count = Error: max reads exceeded before cursor returned')
705
- return res
706
- else:
707
- res = self.rxBytes(sock)
708
- #Somtimes we just get one cursor back of currently unknown origins
709
- #If that happens discard it and read again
710
- if res == self.cursor:
711
- #printText(" CURSOR ONLY")
712
- res = self.rxBytes(sock)
713
- #If create socked fail (between backend and tcp/ip module)
714
- if 'Create Socket Fail' in res:
715
- raise Exception(res)
716
- if 'Connection Timeout' in res:
717
- raise Exception(res)
718
- #If reading until a cursor comes back then keep reading until a cursor appears or max tries exceeded
719
- if readUntilCursor:
720
- maxReads = 1000
721
- count = 1
722
- #check for cursor at end of read and if not there read again
723
- while res[-1:] != self.cursor:
724
- res += self.rxBytes(sock)
725
- count += 1
726
- if count >= maxReads:
727
- raise Exception(' Count = Error: max reads exceeded before cursor returned')
728
- return res
729
-
730
- except Exception as e:
731
- raise e
732
- finally:
733
- self.sockSemaphore.release()
734
-
735
- def rxBytes(self,sock):
736
- #sock.setblocking(0) #make socket non-blocking
737
- #printText('rxBytes')
738
- maxExceptions=10
739
- exceptions=0
740
- maxReadRepeats=50
741
- readRepeats=0
742
- timeout_in_seconds = 10
743
- #Keep trying to read bytes until we get some, unless number of read repeads or exceptions is exceeded
744
- while True:
745
- try:
746
- #select.select returns a list of waitable objects which are ready. On windows it has to be sockets.
747
- #The first arguement is a list of objects to wait for reading, second writing, third 'exceptional condition'
748
- #We only use the read list and our socket to check if it is readable. if no timeout is specified then it blocks until it becomes readable.
749
- ready = select.select([sock], [], [], timeout_in_seconds)
750
- #time.sleep(0.1)
751
- #ready = [1,2]
752
- if ready[0]:
753
- ret = sock.recv(self.maxRxBytes)
754
- #time.sleep(0.1)
755
- return ret
756
- else:
757
- #printText('rxBytes - readRepeats + 1')
758
-
759
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
760
- sock.connect((self.host, self.port))
761
- sock.settimeout(5)
762
-
763
- try:
764
- welcomeString = self.sock.recv(self.maxRxBytes).rstrip()
765
- welcomeString = 'Connected@' + self.host + ':' + str(self.port) + ' ' + '\n ' + welcomeString
766
- printText('New Welcome:' + welcomeString)
767
- except Exception as e:
768
- logging.error('tried and failed to get new welcome')
769
- raise e
770
-
771
- readRepeats=readRepeats+1
772
- time.sleep(0.5)
773
-
774
- except Exception as e:
775
- #printText('rxBytes - exceptions + 1')
776
- exceptions=exceptions+1
777
- time.sleep(0.5)
778
- raise e
779
-
780
- #If read repeats has been exceeded we failed to get any data on this read.
781
- # !!! This is likely to break whatever called us !!!
782
- if readRepeats >= maxReadRepeats:
783
- logging.error('Max read repeats exceeded - returning.')
784
- return 'No data received from QIS'
785
- #If number of exceptions exceeded then give up by exiting
786
- if exceptions >= maxExceptions:
787
- logging.error('Max exceptions exceeded - exiting') #exceptions are probably 10035 non-blocking socket could not complete immediatley
788
- exit()
789
-
790
- # Send text to the back end don't read it's response
791
- # The objects connection needs to be opened (connect()) before this is used
792
- def sendText(self, sock, message='$help', device=''):
793
- if device != '':
794
- specialTimeout = '%500000'
795
- message = device + specialTimeout + ' ' + message
796
- #printText('Sending: "' + message + '" ' + self.host + ':' + str(self.port))
797
-
798
- if self.pythonVersion == 2:
799
- sock.sendall(message + '\r\n')
800
- else:
801
- convM = message + '\r\n'
802
- sock.sendall(convM.encode('utf-8'))
803
- return 'Sent:' + message
804
621
 
805
622
  # Query the backend for a list of connected modules. A $scan command is sent to refresh the list of devices,
806
623
  # Then a wait occurs while the backend discovers devices (network ones can take a while) and then a list of device name strings is returned
@@ -809,21 +626,9 @@ class QisInterface:
809
626
 
810
627
  if sock == None:
811
628
  sock = self.sock
812
- scanWait = 2
813
- #printText('Scanning for devices and waiting ' + str(scanWait) + ' seconds.')
814
- if self.pythonVersion == '3':
815
- #devString = self.sendAndReceiveText(sock, '$scan').decode
816
- #time.sleep(scanWait)
817
- devString = self.sendAndReceiveText(sock, '$list').decode()
818
- else:
819
- #devString = self.sendAndReceiveText(sock, '$scan')
820
- #time.sleep(scanWait)
821
- devString = self.sendAndReceiveText(sock, '$list')
822
-
629
+ devString = self.sendAndReceiveText(sock, '$list')
823
630
  devString = devString.replace('>', '')
824
- devString = devString.replace(r'\d+\) ', '')
825
-
826
- #printText('"' + devString + '"')
631
+ devString = devString.replace(r'\d+\) ', '')
827
632
  devString = devString.split('\r\n')
828
633
  devString = filter(None, devString) #remove empty elements
829
634
  return devString
@@ -831,21 +636,10 @@ class QisInterface:
831
636
  def get_list_details(self, sock=None):
832
637
  if sock == None:
833
638
  sock = self.sock
834
- scanWait = 2
835
- # printText('Scanning for devices and waiting ' + str(scanWait) + ' seconds.')
836
- if self.pythonVersion == '3':
837
- # devString = self.sendAndReceiveText(sock, '$scan').decode
838
- # time.sleep(scanWait)
839
- devString = self.sendAndReceiveText(sock, '$list details').decode()
840
- else:
841
- # devString = self.sendAndReceiveText(sock, '$scan')
842
- # time.sleep(scanWait)
843
- devString = self.sendAndReceiveText(sock, '$list details')
844
639
 
640
+ devString = self.sendAndReceiveText(sock, '$list details')
845
641
  devString = devString.replace('>', '')
846
642
  devString = devString.replace(r'\d+\) ', '')
847
-
848
- # printText('"' + devString + '"')
849
643
  devString = devString.split('\r\n')
850
644
  devString = [x for x in devString if x] # remove empty elements
851
645
  return devString
@@ -884,9 +678,6 @@ class QisInterface:
884
678
  logging.warning(e)
885
679
  logging.warning("No module found at " + ipAddress)
886
680
 
887
-
888
-
889
-
890
681
  def GetQisModuleSelection(self, favouriteOnly=True , additionalOptions=['rescan', 'all con types', 'ip scan'], scan=True):
891
682
  tableHeaders =["Modules"]
892
683
  ip_address = None
@@ -922,33 +713,19 @@ class QisInterface:
922
713
  foundDevices = "1"
923
714
  foundDevices2 = "2" # this is used to check if new modules are being discovered or if all have been found.
924
715
  scanWait = 2 # The number of seconds waited between the two scans.
925
- if self.pythonVersion == '3':
926
- if scan:
927
- if ipAddress == None:
928
- devString = self.sendAndReceiveText(self.sock, '$scan').decode
929
- else:
930
- devString = self.sendAndReceiveText(self.sock, '$scan TCP::' + ipAddress).decode
931
- time.sleep(scanWait)
932
- while foundDevices not in foundDevices2:
933
- foundDevices = self.sendAndReceiveText(self.sock, '$list').decode()
934
- time.sleep(scanWait)
935
- foundDevices2 = self.sendAndReceiveText(self.sock, '$list').decode()
936
- else:
937
- foundDevices = self.sendAndReceiveText(self.sock, '$list').decode()
938
716
 
939
- else:
940
- if scan:
941
- if ipAddress == None:
942
- devString = self.sendAndReceiveText(self.sock, '$scan').decode
943
- else:
944
- devString = self.sendAndReceiveText(self.sock, '$scan TCP::' + ipAddress).decode
945
- time.sleep(scanWait)
946
- while foundDevices not in foundDevices2:
947
- foundDevices = self.sendAndReceiveText(self.sock, '$list')
948
- time.sleep(scanWait)
949
- foundDevices2 = self.sendAndReceiveText(self.sock, '$list')
717
+ if scan:
718
+ if ipAddress == None:
719
+ devString = self.sendAndReceiveText(self.sock, '$scan')
950
720
  else:
721
+ devString = self.sendAndReceiveText(self.sock, '$scan TCP::' + ipAddress)
722
+ time.sleep(scanWait)
723
+ while foundDevices not in foundDevices2:
951
724
  foundDevices = self.sendAndReceiveText(self.sock, '$list')
725
+ time.sleep(scanWait)
726
+ foundDevices2 = self.sendAndReceiveText(self.sock, '$list')
727
+ else:
728
+ foundDevices = self.sendAndReceiveText(self.sock, '$list')
952
729
 
953
730
  if not "no devices found" in foundDevices.lower():
954
731
  foundDevices = foundDevices.replace('>', '')
@@ -998,10 +775,7 @@ class QisInterface:
998
775
  if sock == None:
999
776
  sock = self.sock
1000
777
  index = 0 # index of relevant line in split string
1001
- if self.pythonVersion == '3':
1002
- streamStatus = self.sendAndReceiveText(sock, 'stream?', device).decode()
1003
- else:
1004
- streamStatus = self.sendAndReceiveText(sock, 'stream?', device)
778
+ streamStatus = self.sendAndReceiveText(sock, 'stream?', device)
1005
779
  streamStatus = streamStatus.split('\r\n')
1006
780
  streamStatus[index] = re.sub(r':', '', streamStatus[index]) #remove :
1007
781
  return streamStatus[index]
@@ -1012,10 +786,7 @@ class QisInterface:
1012
786
  if sock == None:
1013
787
  sock = self.sock
1014
788
  index = 1 # index of relevant line in split string
1015
- if self.pythonVersion == '3':
1016
- streamStatus = self.sendAndReceiveText(sock, 'stream?', device).decode()
1017
- else:
1018
- streamStatus = self.sendAndReceiveText(sock, 'stream?', device)
789
+ streamStatus = self.sendAndReceiveText(sock, 'stream?', device)
1019
790
  streamStatus = streamStatus.split('\r\n')
1020
791
  streamStatus[index] = re.sub(r'^Stripes Buffered: ', '', streamStatus[index])
1021
792
  return streamStatus[index]
@@ -1030,10 +801,7 @@ class QisInterface:
1030
801
  if sock == None:
1031
802
  sock = self.sock
1032
803
  index = 2 # index of relevant line in split string
1033
- if self.pythonVersion == '3':
1034
- streamStatus = self.sendAndReceiveText(sock, sentText='stream text header', device=device).decode()
1035
- else:
1036
- streamStatus = self.sendAndReceiveText(sock, sentText='stream text header', device=device)
804
+ streamStatus = self.sendAndReceiveText(sock, sentText='stream text header', device=device)
1037
805
 
1038
806
  self.qps_stream_header = streamStatus
1039
807
 
@@ -1074,10 +842,7 @@ class QisInterface:
1074
842
  if sock == None:
1075
843
  sock = self.sock
1076
844
  index = 0 # index of relevant line in split string
1077
- if self.pythonVersion == '3':
1078
- streamStatus = self.sendAndReceiveText(sock,'stream text header', device).decode()
1079
- else:
1080
- streamStatus = self.sendAndReceiveText(sock,'stream text header', device)
845
+ streamStatus = self.sendAndReceiveText(sock,'stream text header', device)
1081
846
  streamStatus = streamStatus.split('\r\n')
1082
847
  if 'Header Not Available' in streamStatus[0]:
1083
848
  str = streamStatus[0] + '. Check stream has been ran on device.'
@@ -1104,10 +869,7 @@ class QisInterface:
1104
869
  if sock == None:
1105
870
  sock = self.sock
1106
871
  index = 1 # index of relevant line in split string STREAM MODE HEADER [?|V1,V2,V3]
1107
- if self.pythonVersion == '3':
1108
- streamStatus = self.sendAndReceiveText(sock,'stream text header', device).decode()
1109
- else:
1110
- streamStatus = self.sendAndReceiveText(sock,'stream text header', device)
872
+ streamStatus = self.sendAndReceiveText(sock,'stream text header', device)
1111
873
  # Check if this is a new XML form header
1112
874
  if (self.isXmlHeader (streamStatus)):
1113
875
  # Get the basic averaging rate (V3 header)
@@ -1142,12 +904,8 @@ class QisInterface:
1142
904
  str = streamStatus[0] + '. Check stream has been ran on device.'
1143
905
  logging.error(str)
1144
906
  return str
1145
- if self.pythonVersion == '3':
1146
- outputMode = self.sendAndReceiveText(sock,'Config Output Mode?', device).decode()
1147
- powerMode = self.sendAndReceiveText(sock,'stream mode power?', device).decode()
1148
- else:
1149
- outputMode = self.sendAndReceiveText(sock,'Config Output Mode?', device)
1150
- powerMode = self.sendAndReceiveText(sock,'stream mode power?', device)
907
+ outputMode = self.sendAndReceiveText(sock,'Config Output Mode?', device)
908
+ powerMode = self.sendAndReceiveText(sock,'stream mode power?', device)
1151
909
  format = int(re.sub(r'^Format: ', '', streamStatus[index]))
1152
910
  b0 = 1 #12V_I
1153
911
  b1 = 1 << 1 #12V_V
@@ -1188,10 +946,7 @@ class QisInterface:
1188
946
  bufferStatus = False
1189
947
  # Allows the status check to be skipped when emptying the buffer after streaming has stopped (saving time)
1190
948
  if (skipStatusCheck == False):
1191
- if self.pythonVersion == '3':
1192
- streamStatus = self.sendAndReceiveText(sock, 'stream?', device).decode()
1193
- else:
1194
- streamStatus = self.sendAndReceiveText(sock, 'stream?', device)
949
+ streamStatus = self.sendAndReceiveText(sock, 'stream?', device)
1195
950
  if ('Overrun' in streamStatus) or ('8388608 of 8388608' in streamStatus):
1196
951
  bufferStatus = True
1197
952
  stripes = self.sendAndReceiveText(sock, 'stream text all', device, readUntilCursor=True)
@@ -1199,11 +954,7 @@ class QisInterface:
1199
954
  if stripes[-1:] != self.cursor:
1200
955
  return "Error no cursor returned."
1201
956
  else:
1202
- if self.pythonVersion == '3':
1203
- endOfFile = 'eof\r\n>'
1204
- genEndOfFile = endOfFile.encode()
1205
- else:
1206
- genEndOfFile = 'eof\r\n>'
957
+ genEndOfFile = 'eof\r\n>'
1207
958
  if stripes[-6:] == genEndOfFile:
1208
959
  removeChar = -6
1209
960
  else:
@@ -1264,8 +1015,6 @@ class QisInterface:
1264
1015
  finalAverage = splitList[0:2] + [str(round(x / streamAverage)) for x in runningAverage]
1265
1016
  for counter in xrange(len(finalAverage)-1):
1266
1017
  finalAverage[counter] = finalAverage[counter] + ' '
1267
- if self.pythonVersion == '3':
1268
- finalAverage = finalAverage.encode
1269
1018
  for x in finalAverage:
1270
1019
  f.write(x)
1271
1020
  f.write('\r\n')
@@ -1350,10 +1099,7 @@ class QisInterface:
1350
1099
  sock = self.sock
1351
1100
 
1352
1101
  # Get the raw data
1353
- if self.pythonVersion == '3':
1354
- headerData = self.sendAndReceiveText(sock, sentText='stream text header', device=device).decode()
1355
- else:
1356
- headerData = self.sendAndReceiveText(sock, sentText='stream text header', device=device)
1102
+ headerData = self.sendAndReceiveText(sock, sentText='stream text header', device=device)
1357
1103
 
1358
1104
  # The XML can contain the cursor on the end! Trap and remove it here TODO: Needs fixed in the command layer above
1359
1105
  if ('\r\n>' in headerData):
@@ -1480,10 +1226,10 @@ class QisInterface:
1480
1226
  folder_name = None
1481
1227
  # Checking if there was a directory passed; and if it's a valid directory
1482
1228
  if not directory:
1483
- directory = os.path.join(str(Path.home()), "AppData", "Local", "Quarch", "QPS", "Recordings")
1229
+ directory = os.path.join(os.path.expanduser("~"), "AppData", "Local", "Quarch", "QPS", "Recordings")
1484
1230
  logging.debug("No directory specified")
1485
1231
  elif not os.path.isdir(directory):
1486
- new_dir = os.path.join(str(Path.home()), "AppData", "Local", "Quarch", "QPS", "Recordings")
1232
+ new_dir = os.path.join(str(os.path.expanduser("~"), "AppData", "Local", "Quarch", "QPS", "Recordings"))
1487
1233
  logging.warning(directory+" was not a valid directory, streaming to default location: \n"+new_dir)
1488
1234
  directory = new_dir
1489
1235
  else:
@@ -1808,6 +1554,158 @@ class QisInterface:
1808
1554
  f.write("Saved: "+x+ "\n")
1809
1555
 
1810
1556
 
1557
+ # when sending commands to module (as opposed to back end)
1558
+ # If read until cursor is set to True (which is default) then keep reading response until a cursor is returned as the last character of result string
1559
+ # After command is sent wait for betweenCommandDelay which defaults to 0 but can be specified to add a delay between commands
1560
+ # The objects connection needs to be opened (connect()) before this is used
1561
+ def sendCmd(self, device='', cmd='$help', sock=None, readUntilCursor=True, betweenCommandDelay=0.0, expectedResponse = True):
1562
+ '''Send command is used to send a command to QIS and as far as I can see it has no difference than sendAndReceiveCmd'''
1563
+ if expectedResponse is True:
1564
+ res = self.sendAndReceiveCmd(device=device, cmd=cmd, sock=sock, readUntilCursor=readUntilCursor, betweenCommandDelay=betweenCommandDelay)
1565
+ #If ends with cursor get rid of it
1566
+ if res[-1:] == self.cursor:
1567
+ res = res[:-3] #remove last three chars - hopefully '\r\n>'
1568
+ return res
1569
+ else :
1570
+ self.sendText(sock, cmd, device)
1571
+ return
1572
+
1573
+ def sendAndReceiveCmd(self, sock=None, cmd='$help', device='', readUntilCursor=True, betweenCommandDelay=0.0):
1574
+ if sock==None:
1575
+ sock = self.sock
1576
+ if not (device == ''):
1577
+ self.deviceDictSetup(device)
1578
+ res = self.sendAndReceiveText(sock, cmd, device, readUntilCursor)
1579
+ if (betweenCommandDelay > 0):
1580
+ time.sleep(betweenCommandDelay)
1581
+ #If ends with cursor get rid of it
1582
+ if res[-1:] == '>':
1583
+ res = res[:-3] #remove last three chars - hopefully '\r\n>'
1584
+ return cmd + ' : ' + res
1585
+
1586
+ def sendAndReceiveText(self, sock, sentText='$help', device='', readUntilCursor=True):
1587
+ # Send text to QIS
1588
+ # The objects connection needs to be opened (connect()) before this is used
1589
+ # If read until cursor is set to True (which is default) then keep reading response until a cursor is returned as the last character of result string
1590
+
1591
+ # do sendText
1592
+ self.sockSemaphore.acquire()
1593
+ try:
1594
+ #Send Text
1595
+ self.sendText(sock, sentText, device)
1596
+ #Receive Response
1597
+ res = self.receiveText(sock)
1598
+ # Error Check / validate response
1599
+ if len(res) == 0:
1600
+ #logging.error("Empty response from QIS.")
1601
+ raise (Exception("Empty response from QIS. Sent: " +sentText))
1602
+ if res[0] == self.cursor:
1603
+ logging.warning('Only Returned Cursor!!!!!')
1604
+ if 'Create Socket Fail' == res[0]: # If create socked fail (between QIS and tcp/ip module)
1605
+ logging.warning(res[0])
1606
+ if 'Connection Timeout' == res[0]:
1607
+ logging.warning(res[0])
1608
+ # If reading until a cursor comes back then keep reading until a cursor appears or max tries exceeded
1609
+ if readUntilCursor:
1610
+ maxReads = 1000
1611
+ count = 1
1612
+ # check for cursor at end of read and if not there read again
1613
+ while res[-1:] != self.cursor:
1614
+ res+= self.receiveText(sock) #TODO Confirm this works with multi response CMD Like a $get stats on a large stream with many annos. test with py2 and py3
1615
+ #res.extend(self.rxBytes(sock))
1616
+ count += 1
1617
+ if count >= maxReads:
1618
+ raise Exception(' Count = Error: max reads exceeded before cursor returned')
1619
+ return res
1620
+
1621
+ except Exception as e:
1622
+ #something went wrong during send qis cmd
1623
+ logging.error(e)
1624
+ raise e
1625
+ finally:
1626
+ self.sockSemaphore.release()
1627
+
1628
+
1629
+ def receiveText(self, sock):
1630
+ if self.pythonVersion == '3':
1631
+ res = bytearray()
1632
+ res.extend(self.rxBytes(sock))
1633
+ res = res.decode()
1634
+ else:
1635
+ res = self.rxBytes(sock)
1636
+ return res
1637
+
1638
+ def sendText(self, sock, message='$help', device=''):
1639
+ # Send text to QIS, don't read it's response
1640
+ # The objects connection needs to be opened (connect()) before this is used
1641
+ if device != '':
1642
+ specialTimeout = '%500000'
1643
+ message = device + specialTimeout + ' ' + message
1644
+ #printText('Sending: "' + message + '" ' + self.host + ':' + str(self.port))
1645
+
1646
+ if self.pythonVersion == 2:
1647
+ sock.sendall(message + '\r\n')
1648
+ else:
1649
+ convM = message + '\r\n'
1650
+ sock.sendall(convM.encode('utf-8'))
1651
+ return 'Sent:' + message
1652
+
1653
+ def rxBytes(self,sock):
1654
+ #sock.setblocking(0) #make socket non-blocking
1655
+ #printText('rxBytes')
1656
+ maxExceptions=10
1657
+ exceptions=0
1658
+ maxReadRepeats=50
1659
+ readRepeats=0
1660
+ timeout_in_seconds = 10
1661
+ #Keep trying to read bytes until we get some, unless number of read repeads or exceptions is exceeded
1662
+ while True:
1663
+ try:
1664
+ #select.select returns a list of waitable objects which are ready. On windows it has to be sockets.
1665
+ #The first arguement is a list of objects to wait for reading, second writing, third 'exceptional condition'
1666
+ #We only use the read list and our socket to check if it is readable. if no timeout is specified then it blocks until it becomes readable.
1667
+ ready = select.select([sock], [], [], timeout_in_seconds)
1668
+ #time.sleep(0.1)
1669
+ #ready = [1,2]
1670
+ if ready[0]:
1671
+ ret = sock.recv(self.maxRxBytes)
1672
+ #time.sleep(0.1)
1673
+ return ret
1674
+ else:
1675
+ #printText('rxBytes - readRepeats + 1')
1676
+
1677
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1678
+ sock.connect((self.host, self.port))
1679
+ sock.settimeout(5)
1680
+
1681
+ try:
1682
+ welcomeString = self.sock.recv(self.maxRxBytes).rstrip()
1683
+ welcomeString = 'Connected@' + self.host + ':' + str(self.port) + ' ' + '\n ' + welcomeString
1684
+ printText('New Welcome:' + welcomeString)
1685
+ except Exception as e:
1686
+ logging.error('tried and failed to get new welcome')
1687
+ raise e
1688
+
1689
+ readRepeats=readRepeats+1
1690
+ time.sleep(0.5)
1691
+
1692
+ except Exception as e:
1693
+ #printText('rxBytes - exceptions + 1')
1694
+ exceptions=exceptions+1
1695
+ time.sleep(0.5)
1696
+ raise e
1697
+
1698
+ #If read repeats has been exceeded we failed to get any data on this read.
1699
+ # !!! This is likely to break whatever called us !!!
1700
+ if readRepeats >= maxReadRepeats:
1701
+ logging.error('Max read repeats exceeded - returning.')
1702
+ return 'No data received from QIS'
1703
+ #If number of exceptions exceeded then give up by exiting
1704
+ if exceptions >= maxExceptions:
1705
+ logging.error('Max exceptions exceeded - exiting') #exceptions are probably 10035 non-blocking socket could not complete immediatley
1706
+ exit()
1707
+
1708
+
1811
1709
  def strToBb(string_in, add_length=True):
1812
1710
  length = len(str(string_in))
1813
1711
  b_array = []