quarchpy 2.1.14.dev1__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 (80) 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 +90 -74
  11. quarchpy/device/scanDevices.py +12 -0
  12. quarchpy/qps/qpsFuncs.py +7 -4
  13. quarchpy/user_interface/user_interface.py.bak +3 -5
  14. quarchpy/utilities/TestCenter.py +1 -1
  15. quarchpy/utilities/TestCenter.py.bak +1 -4
  16. quarchpy/utilities/Version.py +50 -0
  17. {quarchpy-2.1.14.dev1.dist-info → quarchpy-2.1.14.dev2.dist-info}/METADATA +1 -1
  18. {quarchpy-2.1.14.dev1.dist-info → quarchpy-2.1.14.dev2.dist-info}/RECORD +20 -78
  19. quarchpy/.idea/.name +0 -1
  20. quarchpy/.idea/inspectionProfiles/Project_Default.xml +0 -26
  21. quarchpy/__pycache__/__init__.cpython-311.pyc +0 -0
  22. quarchpy/__pycache__/_version.cpython-311.pyc +0 -0
  23. quarchpy/__pycache__/connection.cpython-311.pyc +0 -0
  24. quarchpy/__pycache__/run.cpython-311.pyc +0 -0
  25. quarchpy/config_files/__pycache__/__init__.cpython-311.pyc +0 -0
  26. quarchpy/config_files/__pycache__/quarch_config_parser.cpython-311.pyc +0 -0
  27. quarchpy/connection_specific/__pycache__/StreamChannels.cpython-311.pyc +0 -0
  28. quarchpy/connection_specific/__pycache__/__init__.cpython-311.pyc +0 -0
  29. quarchpy/connection_specific/__pycache__/connection_QIS.cpython-311.pyc +0 -0
  30. quarchpy/connection_specific/__pycache__/connection_QPS.cpython-311.pyc +0 -0
  31. quarchpy/connection_specific/__pycache__/connection_ReST.cpython-311.pyc +0 -0
  32. quarchpy/connection_specific/__pycache__/connection_Serial.cpython-311.pyc +0 -0
  33. quarchpy/connection_specific/__pycache__/connection_USB.cpython-311.pyc +0 -0
  34. quarchpy/connection_specific/serial/__pycache__/__init__.cpython-311.pyc +0 -0
  35. quarchpy/connection_specific/serial/__pycache__/serialutil.cpython-311.pyc +0 -0
  36. quarchpy/connection_specific/serial/__pycache__/serialwin32.cpython-311.pyc +0 -0
  37. quarchpy/connection_specific/serial/__pycache__/win32.cpython-311.pyc +0 -0
  38. quarchpy/connection_specific/serial/tools/__pycache__/__init__.cpython-311.pyc +0 -0
  39. quarchpy/connection_specific/serial/tools/__pycache__/list_ports.cpython-311.pyc +0 -0
  40. quarchpy/connection_specific/serial/tools/__pycache__/list_ports_common.cpython-311.pyc +0 -0
  41. quarchpy/connection_specific/serial/tools/__pycache__/list_ports_windows.cpython-311.pyc +0 -0
  42. quarchpy/connection_specific/usb_libs/__pycache__/libusb1.cpython-311.pyc +0 -0
  43. quarchpy/connection_specific/usb_libs/__pycache__/usb1.cpython-311.pyc +0 -0
  44. quarchpy/debug/TextScanIP.py +0 -11
  45. quarchpy/debug/__pycache__/SystemTest.cpython-311.pyc +0 -0
  46. quarchpy/debug/__pycache__/__init__.cpython-311.pyc +0 -0
  47. quarchpy/debug/__pycache__/module_debug.cpython-311.pyc +0 -0
  48. quarchpy/debug/__pycache__/simple_terminal.cpython-311.pyc +0 -0
  49. quarchpy/debug/__pycache__/upgrade_quarchpy.cpython-311.pyc +0 -0
  50. quarchpy/debug/__pycache__/versionCompare.cpython-311.pyc +0 -0
  51. quarchpy/device/__pycache__/__init__.cpython-311.pyc +0 -0
  52. quarchpy/device/__pycache__/device.cpython-311.pyc +0 -0
  53. quarchpy/device/__pycache__/quarchArray.cpython-311.pyc +0 -0
  54. quarchpy/device/__pycache__/quarchPPM.cpython-311.pyc +0 -0
  55. quarchpy/device/__pycache__/quarchQPS.cpython-311.pyc +0 -0
  56. quarchpy/device/__pycache__/scanDevices.cpython-311.pyc +0 -0
  57. quarchpy/device/device.py.bak +0 -504
  58. quarchpy/device/quarchQPS.py.bak +0 -396
  59. quarchpy/device/scanDevices.py.bak +0 -661
  60. quarchpy/disk_test/__pycache__/AbsDiskFinder.cpython-311.pyc +0 -0
  61. quarchpy/disk_test/__pycache__/DiskTargetSelection.cpython-311.pyc +0 -0
  62. quarchpy/disk_test/__pycache__/__init__.cpython-311.pyc +0 -0
  63. quarchpy/disk_test/__pycache__/iometerDiskFinder.cpython-311.pyc +0 -0
  64. quarchpy/fio/__pycache__/FIO_interface.cpython-311.pyc +0 -0
  65. quarchpy/fio/__pycache__/__init__.cpython-311.pyc +0 -0
  66. quarchpy/iometer/__pycache__/__init__.cpython-311.pyc +0 -0
  67. quarchpy/iometer/__pycache__/gen_iometer_template.cpython-311.pyc +0 -0
  68. quarchpy/iometer/__pycache__/iometerFuncs.cpython-311.pyc +0 -0
  69. quarchpy/qis/__pycache__/StreamHeaderInfo.cpython-311.pyc +0 -0
  70. quarchpy/qis/__pycache__/__init__.cpython-311.pyc +0 -0
  71. quarchpy/qis/__pycache__/qisFuncs.cpython-311.pyc +0 -0
  72. quarchpy/qps/__pycache__/__init__.cpython-311.pyc +0 -0
  73. quarchpy/qps/__pycache__/qpsFuncs.cpython-311.pyc +0 -0
  74. quarchpy/user_interface/__pycache__/__init__.cpython-311.pyc +0 -0
  75. quarchpy/user_interface/__pycache__/user_interface.cpython-311.pyc +0 -0
  76. quarchpy/utilities/__pycache__/TestCenter.cpython-311.pyc +0 -0
  77. quarchpy/utilities/__pycache__/TimeValue.cpython-311.pyc +0 -0
  78. quarchpy/utilities/__pycache__/__init__.cpython-311.pyc +0 -0
  79. {quarchpy-2.1.14.dev1.dist-info → quarchpy-2.1.14.dev2.dist-info}/WHEEL +0 -0
  80. {quarchpy-2.1.14.dev1.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
@@ -263,12 +260,11 @@ class QisInterface:
263
260
 
264
261
  baseSamplePeriodS = int(re.search('^\d*\.?\d*', baseSamplePeriod).group())*(10**baseSampleUnitExponent)
265
262
 
266
- # TODO: MD Thinks this implements software averaging, is unused and now performed in QIS
267
- if streamAverage != None:
268
- #Matt converting streamAveraging into number
269
- streamAverage = self.convertStreamAverage(streamAverage)
270
-
271
- stripesPerAverage = float(streamAverage) / (float(baseSamplePeriod) * 4e-6)
263
+ # # TODO: MD Thinks this implements software averaging, is unused and now performed in QIS
264
+ # if streamAverage != None:
265
+ # #Matt converting streamAveraging into number
266
+ # streamAverage = self.convertStreamAverage(streamAverage)
267
+ # stripesPerAverage = float(streamAverage) / (float(baseSamplePeriodS) * 4e-6)
272
268
  isRun = True
273
269
  while isRun:
274
270
  try:
@@ -279,7 +275,7 @@ class QisInterface:
279
275
  while self.stopFlagList[i] and (not streamOverrun) and (not streamComplete):
280
276
  #now = time.time()
281
277
  streamOverrun, removeChar, newStripes = self.streamGetStripesText(self.streamSock, module, numStripesPerRead)
282
- newStripes = newStripes.replace(b' ', str.encode(separator))
278
+ newStripes = newStripes.replace(' ', separator)
283
279
  #print (time.time() - now)
284
280
  if streamOverrun:
285
281
  self.deviceDict[module][0:3] = [True, 'Stopped', 'Device buffer overrun']
@@ -309,22 +305,26 @@ class QisInterface:
309
305
  if streamDuration != None:
310
306
  # Get the last data line in the file
311
307
  lastLine = newStripes.splitlines()[-3] # the last data line is followed by 'eof' and '>'
312
- lastTime = lastLine.decode().split(separator)[0] # get the first (time) entry
308
+ lastTime = lastLine.split(separator)[0] # get the first (time) entry
313
309
 
314
310
  # if the last entry is still within the required stream length, write the whole lot
315
311
  if int(lastTime) < int(streamDuration/(10**baseSampleUnitExponent)): # < rather than <= because we start at 0
316
312
  f.write(newStripes[:removeChar])
313
+ inMemoryData.write(newStripes[:removeChar])
314
+
317
315
  # else write each line individually until we have reached the desired endpoint
318
316
  else:
319
317
  for thisLine in newStripes.splitlines()[:-2]:
320
- lastTime = thisLine.decode().split(separator)[0]
318
+ lastTime = thisLine.split(separator)[0]
321
319
  if int(lastTime) < int(streamDuration/(10**baseSampleUnitExponent)):
322
320
  f.write(thisLine + b'\r' + b'\n') # Put the CR back on the end
321
+ inMemoryData.write(thisLine + b'\r' + b'\n')
323
322
  else:
324
323
  streamComplete = True
325
324
  break
326
325
  else:
327
326
  f.write(newStripes[:removeChar])
327
+ inMemoryData.write(newStripes[:removeChar])
328
328
 
329
329
  else:
330
330
  maxFileExceeded = True
@@ -332,6 +332,8 @@ class QisInterface:
332
332
  maxFileStatus = self.streamBufferStatus(device=module, sock=self.streamSock)
333
333
  f.write('Warning: Max file size exceeded before end of stream.\n')
334
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 + '.')
335
337
  self.deviceDict[module][0:3] = [True, 'Stopped', 'User defined max filesize reached']
336
338
  break
337
339
  else:
@@ -379,8 +381,9 @@ class QisInterface:
379
381
  if(streamAverage != None):
380
382
  leftover, remainingStripes = self.averageStripes(leftover, stripesPerAverage, newStripes[:removeChar], f, remainingStripes)
381
383
  else:
382
- newStripes = newStripes.replace(b' ', str.encode(separator))
384
+ newStripes = newStripes.replace(' ',separator)
383
385
  f.write(newStripes[:removeChar])
386
+ inMemoryData.write(newStripes[:removeChar])
384
387
  else:
385
388
  if not maxFileExceeded:
386
389
  maxFileStatus = self.streamBufferStatus(device=module, sock=self.streamSock)
@@ -395,6 +398,8 @@ class QisInterface:
395
398
  if maxFileExceeded:
396
399
  f.write(b'Warning: Max file size exceeded before end of stream.\n')
397
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 + '.')
398
403
  logging.warning('Max file size exceeded. Some data has not been saved to file: ' + maxFileStatus + '.')
399
404
 
400
405
  #printText('Stripes in buffer now: ' + self.streamBufferStatus(device=module, sock=self.streamSock))
@@ -466,11 +471,10 @@ class QisInterface:
466
471
  leftover = 0
467
472
  remainingStripes = []
468
473
  streamOverrun = False
469
- if streamAverage != None:
470
- # Matt converting streamAveraging into number
471
- streamAverage = self.convertStreamAverage(streamAverage)
472
-
473
- stripesPerAverage = float(streamAverage) / (float(baseSamplePeriod) * 4e-6)
474
+ # if streamAverage != None:
475
+ # # Matt converting streamAveraging into number
476
+ # streamAverage = self.convertStreamAverage(streamAverage)
477
+ # stripesPerAverage = float(streamAverage) / (float(baseSamplePeriodS) * 4e-6)
474
478
 
475
479
  isRun = True
476
480
 
@@ -486,7 +490,7 @@ class QisInterface:
486
490
  # now = time.time()
487
491
  streamOverrun, removeChar, newStripes = self.streamGetStripesText(self.streamSock, module,
488
492
  numStripesPerRead)
489
- newStripes = newStripes.replace(b' ', str.encode(separator))
493
+ newStripes = newStripes.replace(' ',separator)
490
494
  # print(newStripes)
491
495
  # print(len(newStripes))
492
496
 
@@ -500,11 +504,7 @@ class QisInterface:
500
504
  if isEmpty == False:
501
505
  # Writes in file if not too big else stops streaming
502
506
  # print(newStripes)
503
-
504
- x = newStripes[:removeChar]
505
- y = x.decode("utf-8")
506
-
507
- print(f"decoded stripe : {y}")
507
+ print("decoded stripe : " + newStripes[:removeChar])
508
508
 
509
509
  # Writing multiple stripes
510
510
  if "\r\n" in y:
@@ -582,7 +582,7 @@ class QisInterface:
582
582
  if index == 0:
583
583
  continue
584
584
  with open(os.path.join(self.qps_record_dir_path, "data000",
585
- f"data000_00{index - 1}_000000000"),
585
+ "data000_00" + index - 1 + "_000000000"),
586
586
  "ab") as file1:
587
587
 
588
588
  x = struct.pack(">d", int(item))
@@ -605,7 +605,7 @@ class QisInterface:
605
605
  if group.group_id == 0:
606
606
 
607
607
  with open(os.path.join(self.qps_record_dir_path, "data000",
608
- f"data000_{x}_000000000"),
608
+ "data000_"+x+"_000000000"),
609
609
  "ab") as file1:
610
610
  x = struct.pack(">d", int(stripe[counter]))
611
611
  # logging.debug(item, x)
@@ -613,196 +613,11 @@ class QisInterface:
613
613
  else:
614
614
  # Write all in group 1 to digital
615
615
  with open(os.path.join(self.qps_record_dir_path, "data101",
616
- f"data101_{x}_000000000"),
616
+ "data101_"+x+"_000000000"),
617
617
  "ab") as file1:
618
618
  x = struct.pack(">d", int(stripe[counter]))
619
619
  # logging.debug(item, x)
620
620
  file1.write(x)
621
-
622
-
623
- # Send text and get the backends response. - acts as wrapper to the sendAndReceiveText, intended to provide some extra convenience
624
- # when sending commands to module (as opposed to back end)
625
- # 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
626
- # After command is sent wait for betweenCommandDelay which defaults to 0 but can be specified to add a delay between commands
627
- # The objects connection needs to be opened (connect()) before this is used
628
- def sendCmd(self, device='', cmd='$help', sock=None, readUntilCursor=True, betweenCommandDelay=0.0, expectedResponse = True):
629
- if sock==None:
630
- sock = self.sock
631
- if not (device == ''):
632
- self.deviceDictSetup(device)
633
-
634
- if expectedResponse is False:
635
- self.sendText(sock, cmd, device)
636
- return
637
-
638
- res = self.sendAndReceiveText(sock, cmd, device, readUntilCursor)
639
- if (betweenCommandDelay > 0):
640
- time.sleep(betweenCommandDelay)
641
- #If ends with cursor get rid of it
642
- if res[-1:] == self.cursor:
643
- res = res[:-3] #remove last three chars - hopefully '\r\n>'
644
- # time.sleep(0.1)
645
- return res.decode()
646
-
647
-
648
- def sendAndReceiveCmd(self, sock=None, cmd='$help', device='', readUntilCursor=True, betweenCommandDelay=0.0):
649
- if sock==None:
650
- sock = self.sock
651
- if not (device == ''):
652
- self.deviceDictSetup(device)
653
- if self.pythonVersion == '3':
654
- res = self.sendAndReceiveText(sock, cmd, device, readUntilCursor).decode()
655
- else:
656
- res = self.sendAndReceiveText(sock, cmd, device, readUntilCursor)
657
- if (betweenCommandDelay > 0):
658
- time.sleep(betweenCommandDelay)
659
- #If ends with cursor get rid of it
660
- if res[-1:] == '>':
661
- res = res[:-3] #remove last three chars - hopefully '\r\n>'
662
- return cmd + ' : ' + res
663
-
664
- # Send text to the back end then read it's response
665
- # The objects connection needs to be opened (connect()) before this is used
666
- # 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
667
- def sendAndReceiveText(self, sock, sentText='$help', device='', readUntilCursor=True):
668
- self.sockSemaphore.acquire()
669
- try:
670
- self.sendText(sock, sentText, device)
671
- if self.pythonVersion == '3':
672
- res = bytearray()
673
- res.extend(self.rxBytes(sock))
674
- #Somtimes we just get one cursor back of currently unknown origins
675
- #If that happens discard it and read again
676
- if len(res)==0:
677
- logging.warning("empty response from QIS. Retrying.")
678
- streamResp=self.sendAndReceiveText(sock, "stream?",device,readUntilCursor).lower()
679
- if len(streamResp)==0:
680
- raise("Empty response from QIS twice in a row")
681
- else:
682
- logging.warning("Response recovered Successfully. Continuing.")
683
- res = bytearray()
684
- res.extend(self.rxBytes(sock))
685
- if len(res) == 0:
686
- raise ("empty response from QIS after second ")
687
- if res[0] == self.cursor:
688
- #res[0] = self.rxBytes(sock)
689
- logging.warning('Only Returned Cursor!!!!!')
690
- #If create socked fail (between backend and tcp/ip module)
691
- cba = 'Create Socket Fail'
692
- if cba.encode() == res[0]:
693
- logging.warning(res[0].decode())
694
- cba = 'Connection Timeout'
695
- if cba.encode() == res[0]:
696
- logging.warning(res[0].decode())
697
- #If reading until a cursor comes back then keep reading until a cursor appears or max tries exceeded
698
- if readUntilCursor:
699
- maxReads = 1000
700
- count = 1
701
- #check for cursor at end of read and if not there read again
702
- while res[-1:] != self.cursor:
703
- res.extend(self.rxBytes(sock))
704
- count += 1
705
- if count >= maxReads:
706
- raise Exception(' Count = Error: max reads exceeded before cursor returned')
707
- return res
708
- else:
709
- res = self.rxBytes(sock)
710
- #Somtimes we just get one cursor back of currently unknown origins
711
- #If that happens discard it and read again
712
- if res == self.cursor:
713
- #printText(" CURSOR ONLY")
714
- res = self.rxBytes(sock)
715
- #If create socked fail (between backend and tcp/ip module)
716
- if 'Create Socket Fail' in res:
717
- raise Exception(res)
718
- if 'Connection Timeout' in res:
719
- raise Exception(res)
720
- #If reading until a cursor comes back then keep reading until a cursor appears or max tries exceeded
721
- if readUntilCursor:
722
- maxReads = 1000
723
- count = 1
724
- #check for cursor at end of read and if not there read again
725
- while res[-1:] != self.cursor:
726
- res += self.rxBytes(sock)
727
- count += 1
728
- if count >= maxReads:
729
- raise Exception(' Count = Error: max reads exceeded before cursor returned')
730
- return res
731
-
732
- except Exception as e:
733
- raise e
734
- finally:
735
- self.sockSemaphore.release()
736
-
737
- def rxBytes(self,sock):
738
- #sock.setblocking(0) #make socket non-blocking
739
- #printText('rxBytes')
740
- maxExceptions=10
741
- exceptions=0
742
- maxReadRepeats=50
743
- readRepeats=0
744
- timeout_in_seconds = 10
745
- #Keep trying to read bytes until we get some, unless number of read repeads or exceptions is exceeded
746
- while True:
747
- try:
748
- #select.select returns a list of waitable objects which are ready. On windows it has to be sockets.
749
- #The first arguement is a list of objects to wait for reading, second writing, third 'exceptional condition'
750
- #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.
751
- ready = select.select([sock], [], [], timeout_in_seconds)
752
- #time.sleep(0.1)
753
- #ready = [1,2]
754
- if ready[0]:
755
- ret = sock.recv(self.maxRxBytes)
756
- #time.sleep(0.1)
757
- return ret
758
- else:
759
- #printText('rxBytes - readRepeats + 1')
760
-
761
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
762
- sock.connect((self.host, self.port))
763
- sock.settimeout(5)
764
-
765
- try:
766
- welcomeString = self.sock.recv(self.maxRxBytes).rstrip()
767
- welcomeString = 'Connected@' + self.host + ':' + str(self.port) + ' ' + '\n ' + welcomeString
768
- printText('New Welcome:' + welcomeString)
769
- except Exception as e:
770
- logging.error('tried and failed to get new welcome')
771
- raise e
772
-
773
- readRepeats=readRepeats+1
774
- time.sleep(0.5)
775
-
776
- except Exception as e:
777
- #printText('rxBytes - exceptions + 1')
778
- exceptions=exceptions+1
779
- time.sleep(0.5)
780
- raise e
781
-
782
- #If read repeats has been exceeded we failed to get any data on this read.
783
- # !!! This is likely to break whatever called us !!!
784
- if readRepeats >= maxReadRepeats:
785
- logging.error('Max read repeats exceeded - returning.')
786
- return 'No data received from QIS'
787
- #If number of exceptions exceeded then give up by exiting
788
- if exceptions >= maxExceptions:
789
- logging.error('Max exceptions exceeded - exiting') #exceptions are probably 10035 non-blocking socket could not complete immediatley
790
- exit()
791
-
792
- # Send text to the back end don't read it's response
793
- # The objects connection needs to be opened (connect()) before this is used
794
- def sendText(self, sock, message='$help', device=''):
795
- if device != '':
796
- specialTimeout = '%500000'
797
- message = device + specialTimeout + ' ' + message
798
- #printText('Sending: "' + message + '" ' + self.host + ':' + str(self.port))
799
-
800
- if self.pythonVersion == 2:
801
- sock.sendall(message + '\r\n')
802
- else:
803
- convM = message + '\r\n'
804
- sock.sendall(convM.encode('utf-8'))
805
- return 'Sent:' + message
806
621
 
807
622
  # Query the backend for a list of connected modules. A $scan command is sent to refresh the list of devices,
808
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
@@ -811,21 +626,9 @@ class QisInterface:
811
626
 
812
627
  if sock == None:
813
628
  sock = self.sock
814
- scanWait = 2
815
- #printText('Scanning for devices and waiting ' + str(scanWait) + ' seconds.')
816
- if self.pythonVersion == '3':
817
- #devString = self.sendAndReceiveText(sock, '$scan').decode
818
- #time.sleep(scanWait)
819
- devString = self.sendAndReceiveText(sock, '$list').decode()
820
- else:
821
- #devString = self.sendAndReceiveText(sock, '$scan')
822
- #time.sleep(scanWait)
823
- devString = self.sendAndReceiveText(sock, '$list')
824
-
629
+ devString = self.sendAndReceiveText(sock, '$list')
825
630
  devString = devString.replace('>', '')
826
- devString = devString.replace(r'\d+\) ', '')
827
-
828
- #printText('"' + devString + '"')
631
+ devString = devString.replace(r'\d+\) ', '')
829
632
  devString = devString.split('\r\n')
830
633
  devString = filter(None, devString) #remove empty elements
831
634
  return devString
@@ -833,21 +636,10 @@ class QisInterface:
833
636
  def get_list_details(self, sock=None):
834
637
  if sock == None:
835
638
  sock = self.sock
836
- scanWait = 2
837
- # printText('Scanning for devices and waiting ' + str(scanWait) + ' seconds.')
838
- if self.pythonVersion == '3':
839
- # devString = self.sendAndReceiveText(sock, '$scan').decode
840
- # time.sleep(scanWait)
841
- devString = self.sendAndReceiveText(sock, '$list details').decode()
842
- else:
843
- # devString = self.sendAndReceiveText(sock, '$scan')
844
- # time.sleep(scanWait)
845
- devString = self.sendAndReceiveText(sock, '$list details')
846
639
 
640
+ devString = self.sendAndReceiveText(sock, '$list details')
847
641
  devString = devString.replace('>', '')
848
642
  devString = devString.replace(r'\d+\) ', '')
849
-
850
- # printText('"' + devString + '"')
851
643
  devString = devString.split('\r\n')
852
644
  devString = [x for x in devString if x] # remove empty elements
853
645
  return devString
@@ -886,9 +678,6 @@ class QisInterface:
886
678
  logging.warning(e)
887
679
  logging.warning("No module found at " + ipAddress)
888
680
 
889
-
890
-
891
-
892
681
  def GetQisModuleSelection(self, favouriteOnly=True , additionalOptions=['rescan', 'all con types', 'ip scan'], scan=True):
893
682
  tableHeaders =["Modules"]
894
683
  ip_address = None
@@ -924,33 +713,19 @@ class QisInterface:
924
713
  foundDevices = "1"
925
714
  foundDevices2 = "2" # this is used to check if new modules are being discovered or if all have been found.
926
715
  scanWait = 2 # The number of seconds waited between the two scans.
927
- if self.pythonVersion == '3':
928
- if scan:
929
- if ipAddress == None:
930
- devString = self.sendAndReceiveText(self.sock, '$scan').decode
931
- else:
932
- devString = self.sendAndReceiveText(self.sock, '$scan TCP::' + ipAddress).decode
933
- time.sleep(scanWait)
934
- while foundDevices not in foundDevices2:
935
- foundDevices = self.sendAndReceiveText(self.sock, '$list').decode()
936
- time.sleep(scanWait)
937
- foundDevices2 = self.sendAndReceiveText(self.sock, '$list').decode()
938
- else:
939
- foundDevices = self.sendAndReceiveText(self.sock, '$list').decode()
940
716
 
941
- else:
942
- if scan:
943
- if ipAddress == None:
944
- devString = self.sendAndReceiveText(self.sock, '$scan').decode
945
- else:
946
- devString = self.sendAndReceiveText(self.sock, '$scan TCP::' + ipAddress).decode
947
- time.sleep(scanWait)
948
- while foundDevices not in foundDevices2:
949
- foundDevices = self.sendAndReceiveText(self.sock, '$list')
950
- time.sleep(scanWait)
951
- foundDevices2 = self.sendAndReceiveText(self.sock, '$list')
717
+ if scan:
718
+ if ipAddress == None:
719
+ devString = self.sendAndReceiveText(self.sock, '$scan')
952
720
  else:
721
+ devString = self.sendAndReceiveText(self.sock, '$scan TCP::' + ipAddress)
722
+ time.sleep(scanWait)
723
+ while foundDevices not in foundDevices2:
953
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')
954
729
 
955
730
  if not "no devices found" in foundDevices.lower():
956
731
  foundDevices = foundDevices.replace('>', '')
@@ -1000,10 +775,7 @@ class QisInterface:
1000
775
  if sock == None:
1001
776
  sock = self.sock
1002
777
  index = 0 # index of relevant line in split string
1003
- if self.pythonVersion == '3':
1004
- streamStatus = self.sendAndReceiveText(sock, 'stream?', device).decode()
1005
- else:
1006
- streamStatus = self.sendAndReceiveText(sock, 'stream?', device)
778
+ streamStatus = self.sendAndReceiveText(sock, 'stream?', device)
1007
779
  streamStatus = streamStatus.split('\r\n')
1008
780
  streamStatus[index] = re.sub(r':', '', streamStatus[index]) #remove :
1009
781
  return streamStatus[index]
@@ -1014,10 +786,7 @@ class QisInterface:
1014
786
  if sock == None:
1015
787
  sock = self.sock
1016
788
  index = 1 # index of relevant line in split string
1017
- if self.pythonVersion == '3':
1018
- streamStatus = self.sendAndReceiveText(sock, 'stream?', device).decode()
1019
- else:
1020
- streamStatus = self.sendAndReceiveText(sock, 'stream?', device)
789
+ streamStatus = self.sendAndReceiveText(sock, 'stream?', device)
1021
790
  streamStatus = streamStatus.split('\r\n')
1022
791
  streamStatus[index] = re.sub(r'^Stripes Buffered: ', '', streamStatus[index])
1023
792
  return streamStatus[index]
@@ -1032,10 +801,7 @@ class QisInterface:
1032
801
  if sock == None:
1033
802
  sock = self.sock
1034
803
  index = 2 # index of relevant line in split string
1035
- if self.pythonVersion == '3':
1036
- streamStatus = self.sendAndReceiveText(sock, sentText='stream text header', device=device).decode()
1037
- else:
1038
- streamStatus = self.sendAndReceiveText(sock, sentText='stream text header', device=device)
804
+ streamStatus = self.sendAndReceiveText(sock, sentText='stream text header', device=device)
1039
805
 
1040
806
  self.qps_stream_header = streamStatus
1041
807
 
@@ -1076,10 +842,7 @@ class QisInterface:
1076
842
  if sock == None:
1077
843
  sock = self.sock
1078
844
  index = 0 # index of relevant line in split string
1079
- if self.pythonVersion == '3':
1080
- streamStatus = self.sendAndReceiveText(sock,'stream text header', device).decode()
1081
- else:
1082
- streamStatus = self.sendAndReceiveText(sock,'stream text header', device)
845
+ streamStatus = self.sendAndReceiveText(sock,'stream text header', device)
1083
846
  streamStatus = streamStatus.split('\r\n')
1084
847
  if 'Header Not Available' in streamStatus[0]:
1085
848
  str = streamStatus[0] + '. Check stream has been ran on device.'
@@ -1106,10 +869,7 @@ class QisInterface:
1106
869
  if sock == None:
1107
870
  sock = self.sock
1108
871
  index = 1 # index of relevant line in split string STREAM MODE HEADER [?|V1,V2,V3]
1109
- if self.pythonVersion == '3':
1110
- streamStatus = self.sendAndReceiveText(sock,'stream text header', device).decode()
1111
- else:
1112
- streamStatus = self.sendAndReceiveText(sock,'stream text header', device)
872
+ streamStatus = self.sendAndReceiveText(sock,'stream text header', device)
1113
873
  # Check if this is a new XML form header
1114
874
  if (self.isXmlHeader (streamStatus)):
1115
875
  # Get the basic averaging rate (V3 header)
@@ -1144,12 +904,8 @@ class QisInterface:
1144
904
  str = streamStatus[0] + '. Check stream has been ran on device.'
1145
905
  logging.error(str)
1146
906
  return str
1147
- if self.pythonVersion == '3':
1148
- outputMode = self.sendAndReceiveText(sock,'Config Output Mode?', device).decode()
1149
- powerMode = self.sendAndReceiveText(sock,'stream mode power?', device).decode()
1150
- else:
1151
- outputMode = self.sendAndReceiveText(sock,'Config Output Mode?', device)
1152
- 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)
1153
909
  format = int(re.sub(r'^Format: ', '', streamStatus[index]))
1154
910
  b0 = 1 #12V_I
1155
911
  b1 = 1 << 1 #12V_V
@@ -1190,10 +946,7 @@ class QisInterface:
1190
946
  bufferStatus = False
1191
947
  # Allows the status check to be skipped when emptying the buffer after streaming has stopped (saving time)
1192
948
  if (skipStatusCheck == False):
1193
- if self.pythonVersion == '3':
1194
- streamStatus = self.sendAndReceiveText(sock, 'stream?', device).decode()
1195
- else:
1196
- streamStatus = self.sendAndReceiveText(sock, 'stream?', device)
949
+ streamStatus = self.sendAndReceiveText(sock, 'stream?', device)
1197
950
  if ('Overrun' in streamStatus) or ('8388608 of 8388608' in streamStatus):
1198
951
  bufferStatus = True
1199
952
  stripes = self.sendAndReceiveText(sock, 'stream text all', device, readUntilCursor=True)
@@ -1201,11 +954,7 @@ class QisInterface:
1201
954
  if stripes[-1:] != self.cursor:
1202
955
  return "Error no cursor returned."
1203
956
  else:
1204
- if self.pythonVersion == '3':
1205
- endOfFile = 'eof\r\n>'
1206
- genEndOfFile = endOfFile.encode()
1207
- else:
1208
- genEndOfFile = 'eof\r\n>'
957
+ genEndOfFile = 'eof\r\n>'
1209
958
  if stripes[-6:] == genEndOfFile:
1210
959
  removeChar = -6
1211
960
  else:
@@ -1266,8 +1015,6 @@ class QisInterface:
1266
1015
  finalAverage = splitList[0:2] + [str(round(x / streamAverage)) for x in runningAverage]
1267
1016
  for counter in xrange(len(finalAverage)-1):
1268
1017
  finalAverage[counter] = finalAverage[counter] + ' '
1269
- if self.pythonVersion == '3':
1270
- finalAverage = finalAverage.encode
1271
1018
  for x in finalAverage:
1272
1019
  f.write(x)
1273
1020
  f.write('\r\n')
@@ -1352,10 +1099,7 @@ class QisInterface:
1352
1099
  sock = self.sock
1353
1100
 
1354
1101
  # Get the raw data
1355
- if self.pythonVersion == '3':
1356
- headerData = self.sendAndReceiveText(sock, sentText='stream text header', device=device).decode()
1357
- else:
1358
- headerData = self.sendAndReceiveText(sock, sentText='stream text header', device=device)
1102
+ headerData = self.sendAndReceiveText(sock, sentText='stream text header', device=device)
1359
1103
 
1360
1104
  # The XML can contain the cursor on the end! Trap and remove it here TODO: Needs fixed in the command layer above
1361
1105
  if ('\r\n>' in headerData):
@@ -1420,7 +1164,7 @@ class QisInterface:
1420
1164
  inner_path_analogues = os.path.join(directory, in_folder_analogue)
1421
1165
  os.mkdir(inner_path_analogues)
1422
1166
  except:
1423
- logging.warning(f"Failed to make inner directory for analogue signals {inner_path_analogues}")
1167
+ logging.warning("Failed to make inner directory for analogue signals " + inner_path_analogues)
1424
1168
  return False
1425
1169
 
1426
1170
  in_folder_digitals = "data101"
@@ -1429,26 +1173,26 @@ class QisInterface:
1429
1173
  inner_path_digitals = os.path.join(directory, in_folder_digitals)
1430
1174
  os.mkdir(inner_path_digitals)
1431
1175
  except:
1432
- logging.warning(f"Failed to make inner directory for digital signals {inner_path_digitals}")
1176
+ logging.warning("Failed to make inner directory for digital signals "+ inner_path_digitals)
1433
1177
  return False
1434
1178
 
1435
- logging.debug(f"Steaming to : {self.qps_record_dir_path}")
1179
+ logging.debug("Steaming to : " + self.qps_record_dir_path)
1436
1180
 
1437
1181
  logging.debug("Creating qps data files")
1438
1182
  try:
1439
1183
  for i in range(non_dig_counter):
1440
- file_name = f"data000_00{i}_000000000"
1184
+ file_name = "data000_00"+i+"_000000000"
1441
1185
  f = open(os.path.join(inner_path_analogues, file_name), "w")
1442
1186
  f.close()
1443
1187
  for i in range(digital_count):
1444
1188
  x = i
1445
1189
  while len(str(x)) < 3:
1446
1190
  x = "0" + str(x)
1447
- file_name = f"data101_{x}_000000000"
1191
+ file_name = "data101_"+x+"_000000000"
1448
1192
  f = open(os.path.join(inner_path_digitals, file_name), "w")
1449
1193
  f.close()
1450
1194
  except:
1451
- logging.warning(f"failed to create qps data files for analogue signals")
1195
+ logging.warning("failed to create qps data files for analogue signals")
1452
1196
  return False
1453
1197
 
1454
1198
  logging.debug("Finished creating qps data files")
@@ -1460,7 +1204,7 @@ class QisInterface:
1460
1204
  f = open(os.path.join(self.qps_record_dir_path, file_nome), "w")
1461
1205
  f.close()
1462
1206
  except Exception as err:
1463
- logging.warning(f"failed to create qps upper level files, {err}")
1207
+ logging.warning("failed to create qps upper level files, "+err)
1464
1208
  return False
1465
1209
 
1466
1210
  try:
@@ -1471,7 +1215,7 @@ class QisInterface:
1471
1215
  f = open(os.path.join(self.qps_record_dir_path, "data101.idx"), "wb")
1472
1216
  f.close()
1473
1217
  except Exception as err:
1474
- logging.warning(f"failed to create data000.idx file, {err}")
1218
+ logging.warning("failed to create data000.idx file, "+err)
1475
1219
  return False
1476
1220
 
1477
1221
  logging.debug("Finished creating QPS dir structure")
@@ -1482,11 +1226,11 @@ class QisInterface:
1482
1226
  folder_name = None
1483
1227
  # Checking if there was a directory passed; and if it's a valid directory
1484
1228
  if not directory:
1485
- 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")
1486
1230
  logging.debug("No directory specified")
1487
1231
  elif not os.path.isdir(directory):
1488
- new_dir = os.path.join(str(Path.home()), "AppData", "Local", "Quarch", "QPS", "Recordings")
1489
- logging.warning(f"{directory} was not a valid directory, streaming to default location: \n{new_dir}")
1232
+ new_dir = os.path.join(str(os.path.expanduser("~"), "AppData", "Local", "Quarch", "QPS", "Recordings"))
1233
+ logging.warning(directory+" was not a valid directory, streaming to default location: \n"+new_dir)
1490
1234
  directory = new_dir
1491
1235
  else:
1492
1236
  # Split the directory into a path of folders
@@ -1499,7 +1243,7 @@ class QisInterface:
1499
1243
  # If no folder name for the stream was passed, then default to 'quarchpy_recording' and a timestamp
1500
1244
  if not folder_name:
1501
1245
  folder_name = "quarchpy_recording"
1502
- folder_name = f"{folder_name}-{time.time()}"
1246
+ folder_name = folder_name + "-" + time.time()
1503
1247
  path = os.path.join(directory, self.qps_stream_folder_name)
1504
1248
  os.mkdir(path)
1505
1249
  self.qps_record_dir_path = path
@@ -1547,15 +1291,15 @@ class QisInterface:
1547
1291
  raise "No data written to file"
1548
1292
 
1549
1293
  num_records = len(data) / 8
1550
- logging.debug(f"num_record = {num_records}")
1294
+ logging.debug("num_record = " + num_records)
1551
1295
  return_b_array.append(int(num_records).to_bytes(4, byteorder='big'))
1552
1296
 
1553
1297
  start_number = 0
1554
- logging.debug(f"start_record = {start_number}")
1298
+ logging.debug("start_record = " + start_number)
1555
1299
  return_b_array.append(start_number.to_bytes(8, byteorder='big'))
1556
1300
 
1557
1301
  num_records = num_records - 1
1558
- logging.debug(f"last_Record_number = {num_records}")
1302
+ logging.debug("last_Record_number = "+num_records)
1559
1303
  return_b_array.append(int(num_records).to_bytes(8, byteorder='big'))
1560
1304
 
1561
1305
  # Add names of every file in data000 dir here.
@@ -1611,15 +1355,15 @@ class QisInterface:
1611
1355
  raise "No data written to file"
1612
1356
 
1613
1357
  num_records = len(data) / 8
1614
- logging.debug(f"num_record = {num_records}")
1358
+ logging.debug("num_record = "+ num_records)
1615
1359
  return_b_array.append(int(num_records).to_bytes(4, byteorder='big'))
1616
1360
 
1617
1361
  start_number = 0
1618
- logging.debug(f"start_record = {start_number}")
1362
+ logging.debug("start_record = "+start_number)
1619
1363
  return_b_array.append(start_number.to_bytes(8, byteorder='big'))
1620
1364
 
1621
1365
  num_records = num_records - 1
1622
- logging.debug(f"last_Record_number = {num_records}")
1366
+ logging.debug("last_Record_number = "+ num_records)
1623
1367
  return_b_array.append(int(num_records).to_bytes(8, byteorder='big'))
1624
1368
 
1625
1369
  # Add names of every file in data000 dir here.
@@ -1735,30 +1479,30 @@ class QisInterface:
1735
1479
  def add_header_to_buffer(self, outBuffer, return_b_array, stream_header_size, temp_dict):
1736
1480
  number = 2
1737
1481
  outBuffer.append(number.to_bytes(4, byteorder='big'))
1738
- logging.debug(f"indexVersion : {number}")
1482
+ logging.debug("indexVersion : "+ number)
1739
1483
 
1740
1484
  number = 1 if self.has_digitals else 0
1741
1485
  outBuffer.append(number.to_bytes(4, byteorder='big'))
1742
- logging.debug(f"value0 : {number}")
1486
+ logging.debug("value0 : "+ number)
1743
1487
  number = stream_header_size
1744
1488
  outBuffer.append(number.to_bytes(4, byteorder='big'))
1745
- logging.debug(f"header_size : {number}")
1746
- logging.debug(f"legacyVersion : {temp_dict['legacyVersion']}")
1489
+ logging.debug("header_size : "+number)
1490
+ logging.debug("legacyVersion : "+ temp_dict['legacyVersion'])
1747
1491
  outBuffer.append(int(temp_dict["legacyVersion"]).to_bytes(4, byteorder='big'))
1748
- logging.debug(f"legacyAverage : {temp_dict['legacyAverage']}")
1492
+ logging.debug("legacyAverage : " + temp_dict['legacyAverage'])
1749
1493
  outBuffer.append(int(temp_dict["legacyAverage"]).to_bytes(4, byteorder='big'))
1750
- logging.debug(f"legacyFormat : {temp_dict['legacyFormat']}")
1494
+ logging.debug("legacyFormat : "+temp_dict['legacyFormat'])
1751
1495
  outBuffer.append(int(temp_dict["legacyFormat"]).to_bytes(4, byteorder='big'))
1752
- logging.debug(f"mainPeriod : {temp_dict['mainPeriod']}")
1496
+ logging.debug("mainPeriod : "+temp_dict['mainPeriod'])
1753
1497
  outBuffer.append(int(temp_dict["mainPeriod"]).to_bytes(4, byteorder='big'))
1754
- logging.debug(f"channels : {temp_dict['channels']}")
1498
+ logging.debug("channels : "+temp_dict['channels'])
1755
1499
  outBuffer.append(int(temp_dict["channels"]).to_bytes(4, byteorder='big'))
1756
1500
  return_b_array.append(int(self.qps_record_start_time).to_bytes(8, byteorder='big'))
1757
1501
  index_record_state = True
1758
1502
  logging.debug(int(1))
1759
1503
  return_b_array.append(int(1).to_bytes(1, byteorder='big'))
1760
1504
  record_type = 1
1761
- logging.debug(f"record type : {int(index_record_state)}")
1505
+ logging.debug("record type : "+int(index_record_state))
1762
1506
  return_b_array.append(int(record_type).to_bytes(1, byteorder='big'))
1763
1507
 
1764
1508
  def write_b_array_to_idx_file(self, f, return_b_array):
@@ -1799,15 +1543,167 @@ class QisInterface:
1799
1543
  x = str(x).split(".")
1800
1544
  x = x[0]
1801
1545
  x = x.replace("-", " ")
1802
- f.write(f"Started: {x}\n")
1803
- f.write(f"Device: {module}\n")
1546
+ f.write("Started: "+x+"\n")
1547
+ f.write("Device: " + module + "\n")
1804
1548
  f.write("Fixture: \n")
1805
1549
 
1806
1550
  x = datetime.datetime.now()
1807
1551
  x = str(x).split(".")
1808
1552
  x = x[0]
1809
1553
  x = x.replace("-", " ")
1810
- f.write(f"Saved: {x}\n")
1554
+ f.write("Saved: "+x+ "\n")
1555
+
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 #Format for py2/3 and return.
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()
1811
1707
 
1812
1708
 
1813
1709
  def strToBb(string_in, add_length=True):