quarchpy 2.1.11.dev4__py3-none-any.whl → 2.2.17.dev1__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 (745) hide show
  1. quarchpy/__init__.py +60 -8
  2. quarchpy/_version.py +1 -1
  3. quarchpy/config_files/Cable_Modules/QTL1253-01 - Mini SAS Module Config v3.5 c1.3.qfg +196 -196
  4. quarchpy/config_files/Cable_Modules/QTL1253-01 - Mini SAS Module Config v4.000 c1.3.qfg +198 -198
  5. quarchpy/config_files/Cable_Modules/QTL1253-02 - Mini SAS Module Config v3.5 c1.3.qfg +196 -196
  6. quarchpy/config_files/Cable_Modules/QTL1253-02 - Mini SAS Module Config v4.000 c1.3.qfg +198 -198
  7. quarchpy/config_files/Cable_Modules/QTL1253-xx - Mini SAS Module Config v4.003 c1.6.qfg +197 -197
  8. quarchpy/config_files/Cable_Modules/QTL1271-xx - Ethernet Module Config v3.5 c1.2.qfg +188 -188
  9. quarchpy/config_files/Cable_Modules/QTL1271-xx - Ethernet Module Config v4.000 c1.2.qfg +190 -190
  10. quarchpy/config_files/Cable_Modules/QTL1271-xx - Ethernet Module Config v4.100 c1.3.qfg +189 -189
  11. quarchpy/config_files/Cable_Modules/QTL1292-xx - SFP+ Cable Pull Module Config v4.000 c1.1.qfg +154 -154
  12. quarchpy/config_files/Cable_Modules/QTL1309-04 - USB 3.0 Module Config v4.003 c1.2.qfg +187 -187
  13. quarchpy/config_files/Cable_Modules/QTL1309-xx - USB 3.0 Module Config v3.5 c1.1.qfg +187 -187
  14. quarchpy/config_files/Cable_Modules/QTL1309-xx - USB 3.0 Module Config v4.000 c1.1.qfg +188 -188
  15. quarchpy/config_files/Cable_Modules/QTL1366-xx - QSFP Cable Pull Module Config v4.000 c1.1.qfg +209 -209
  16. quarchpy/config_files/Cable_Modules/QTL1383-xx - eSATAp Module Config v4.000 c1.3.qfg +190 -190
  17. quarchpy/config_files/Cable_Modules/QTL1521-02 - Mini SAS HD Module Config v4.000 c1.1.qfg +210 -210
  18. quarchpy/config_files/Cable_Modules/QTL1521-03 - Mini SAS HD Module Config v4.000 c1.1.qfg +210 -210
  19. quarchpy/config_files/Cable_Modules/QTL1521-05 - Mini SAS HD Module Config v4.005 c1.1.qfg +209 -209
  20. quarchpy/config_files/Cable_Modules/QTL1521-05 - Mini SAS HD Module Config v4.007 c1.2.qfg +209 -209
  21. quarchpy/config_files/Cable_Modules/QTL1521-xx - Mini SAS HD Module Config v4.003 c1.5.qfg +209 -209
  22. quarchpy/config_files/Cable_Modules/QTL1663-xx - Quad QSFP Cable Pull Module Config v4.000 c1.1.qfg +308 -308
  23. quarchpy/config_files/Cable_Modules/QTL1675-05 - Mini SAS HD Module w Triggering Config v4.007 c1.3.qfg +211 -211
  24. quarchpy/config_files/Cable_Modules/QTL1675-xx - Mini SAS HD Module w Triggering Config v4.000 c1.1.qfg +210 -210
  25. quarchpy/config_files/Cable_Modules/QTL1917-xx - Dual SFP+ Cable Pull Module Config v4.000 c1.1.qfg +174 -174
  26. quarchpy/config_files/Cable_Modules/QTL1971-01 - USB TypeC Module Config v4.000 c1.1.qfg +203 -203
  27. quarchpy/config_files/Cable_Modules/QTL1971-02 - USB TypeC Module Config v4.000 c1.1.qfg +203 -203
  28. quarchpy/config_files/Cable_Modules/QTL2022-xx - RJ-45 Cable Module Config v4.104 c1.3.QFG +189 -189
  29. quarchpy/config_files/Cable_Modules/QTL2058-xx - External PCIe Module Config v4.001 c1.1.qfg +209 -209
  30. quarchpy/config_files/Cable_Modules/QTL2138-01 - SFP28 Cable Pull Module Config v4.000 c1.1.qfg +154 -154
  31. quarchpy/config_files/Cable_Modules/QTL2146-01 - Gen4 OCuLink Cable Module Config v4.001 c1.1.qfg +212 -212
  32. quarchpy/config_files/Cable_Modules/QTL2162-01 - 24G mini SAS HD Cable Break Module Config v4.000 c1.qfg +209 -209
  33. quarchpy/config_files/Cable_Modules/QTL2171-01 - QSFP28 Cable Module Config v4.000 c1.qfg +198 -198
  34. quarchpy/config_files/Cable_Modules/QTL2171-02 - QSFP28 Cable Module Config v4.000 c1.qfg +198 -198
  35. quarchpy/config_files/Cable_Modules/QTL2341-01 - Gen4 External PCIe Cable Module v4.000.qfg +209 -209
  36. quarchpy/config_files/Cable_Modules/QTL2602-xx - Multiprotocol Link Breaker.qfg +178 -178
  37. quarchpy/config_files/Cable_Modules/QTL2834-xx - -48V DC Breaker Module v5.000 c1.0.qfg +177 -177
  38. quarchpy/config_files/Card_Modules/QTL1069-xx - SBB 2.0 Module Config v3.5 c1.1.qfg +366 -366
  39. quarchpy/config_files/Card_Modules/QTL1630-01 - PCIe Card Module v4.000 c1.0.qfg +280 -280
  40. quarchpy/config_files/Card_Modules/QTL1630-02 - PCIe Card Module Config v4.004 c1.2.qfg +283 -283
  41. quarchpy/config_files/Card_Modules/QTL1630-02 - PCIe Card Module Config v4.005 c1.2.qfg +283 -283
  42. quarchpy/config_files/Card_Modules/QTL1630-02 - PCIe Card Module Config v4.100 c1.4.qfg +284 -284
  43. quarchpy/config_files/Card_Modules/QTL1630-04 - PCIe Card Module Config v4.001 c1.1.qfg +287 -287
  44. quarchpy/config_files/Card_Modules/QTL1630-04 - PCIe Card Module Config v4.004 c1.2.qfg +287 -287
  45. quarchpy/config_files/Card_Modules/QTL1688-01 - PCIe Card Module w Triggering Config v4.004 c1.2.qfg +284 -284
  46. quarchpy/config_files/Card_Modules/QTL1688-01 - PCIe Card Module w Triggering Config v4.006 c1.3.qfg +285 -285
  47. quarchpy/config_files/Card_Modules/QTL1688-03 - PCIe Card Module w Triggering Config v4.001 c1.1.qfg +286 -286
  48. quarchpy/config_files/Card_Modules/QTL1688-03 - PCIe Card Module w Triggering Config v4.004 c1.2.qfg +288 -288
  49. quarchpy/config_files/Card_Modules/QTL1688-04 - PCIe Card Module w Triggering Config v4.005 c1.5.qfg +288 -288
  50. quarchpy/config_files/Card_Modules/QTL1688-05 - PCIe Card Module w Triggering Config v4.005 c1.qfg +288 -288
  51. quarchpy/config_files/Card_Modules/QTL1848-01 - PCIe Lite Card Module Config v4.000.qfg +122 -122
  52. quarchpy/config_files/Card_Modules/QTL1848-02 - PCIe Lite Card Module Config v4.000.qfg +134 -134
  53. quarchpy/config_files/Card_Modules/QTL1919-01 - PCIe x8 Card Module Config v4.001 c1.4.qfg +247 -247
  54. quarchpy/config_files/Card_Modules/QTL1920-01 - PCIe x8 Card Module w Triggering Config v4.000 c1.3.qfg +247 -247
  55. quarchpy/config_files/Card_Modules/QTL2019-xx - M.2 Horizontal Card Module Config v4.002 c1.1.qfg +219 -219
  56. quarchpy/config_files/Card_Modules/QTL2034-xx - M.2 M-Key Vertical Module Config v4.001 c1.1.qfg +221 -221
  57. quarchpy/config_files/Card_Modules/QTL2067-xx - PCIe SFF Module Config v4.000 c1.1.qfg +248 -248
  58. quarchpy/config_files/Card_Modules/QTL2067-xx - Sanblaze 2 Drive Riser Card Config v4.006 c1.4.qfg +256 -256
  59. quarchpy/config_files/Card_Modules/QTL2067-xx - Sanblaze 2 Drive Riser Card Config v4.007 c1.4.qfg +256 -256
  60. quarchpy/config_files/Card_Modules/QTL2073-01 - GEN3 PCIe Lite Card Module Config v4.001.qfg +134 -134
  61. quarchpy/config_files/Card_Modules/QTL2073-01 - PCIe Lite Card Module Config v4.000.qfg +134 -134
  62. quarchpy/config_files/Card_Modules/QTL2074-01 - GEN3 PCIe HS Card Module v4.005 c1.4.qfg +287 -287
  63. quarchpy/config_files/Card_Modules/QTL2074-01 - PCIe Card Module Config CurrentLimit v4.004 c1.2.qfg +287 -287
  64. quarchpy/config_files/Card_Modules/QTL2087-xx - PCIe GEN4 Card Module w Triggering Config v4.001 c1.1.qfg +287 -287
  65. quarchpy/config_files/Card_Modules/QTL2087-xx - PCIe GEN4 Card Module w Triggering Config v4.001 c1.3.qfg +277 -277
  66. quarchpy/config_files/Card_Modules/QTL2087-xx - PCIe GEN4 Card Module w Triggering Config v5.000 c1.4.qfg +277 -277
  67. quarchpy/config_files/Card_Modules/QTL2094-01 - Sanblaze Dualport Riser Card Config v4.001 c1.1.qfg +223 -223
  68. quarchpy/config_files/Card_Modules/QTL2128-xx - PCIe GEN4 Card Module w Triggering Config v4.000 c1.1.qfg +287 -287
  69. quarchpy/config_files/Card_Modules/QTL2128-xx - PCIe GEN4 Card Module w Triggering Config v4.001 c1.4.qfg +277 -277
  70. quarchpy/config_files/Card_Modules/QTL2135-xx - PCIe GEN4 Card Module w Triggering Config - Inrush Limit v4.001 c1.4.qfg +277 -277
  71. quarchpy/config_files/Card_Modules/QTL2161-01 - EDSFF x8 Module Config v4.000 c1.1.qfg +210 -210
  72. quarchpy/config_files/Card_Modules/QTL2171-xx - EDSFF x8 Module w Triggering Config 4.001 c1.1.qfg +213 -213
  73. quarchpy/config_files/Card_Modules/QTL2203-01 - Sanblaze Dualport Rack Riser Card Config v4.000 c1.1.qfg +218 -218
  74. quarchpy/config_files/Card_Modules/QTL2203-01 - Sanblaze Dualport Rack Riser Card Config v4.005 c1.5.qfg +218 -218
  75. quarchpy/config_files/Card_Modules/QTL2272-01 - GEN4 EDSFF x8 Module Config v4.000 c1.1.qfg +211 -211
  76. quarchpy/config_files/Card_Modules/QTL2282-01 - Sanblaze Singleport Rack Riser Card Config v4.000 c1.1.qfg +212 -212
  77. quarchpy/config_files/Card_Modules/QTL2282-01 - Sanblaze Singleport Rack Riser Card Config v4.002 c1.2.qfg +212 -212
  78. quarchpy/config_files/Card_Modules/QTL2318-01 - SANBlaze U.2 Rack Riser Card Config v4.000 c1.1.qfg +218 -218
  79. quarchpy/config_files/Card_Modules/QTL2322-03 - GEN4 M.2 M-Key Vertical Breaker Module Config v5.001 c1.3.qfg +220 -220
  80. quarchpy/config_files/Card_Modules/QTL2322-xx - GEN4 M.2 M-Key Vertical Breaker Module Config v5.000 c1.1.qfg +208 -208
  81. quarchpy/config_files/Card_Modules/QTL2334-xx - Gen4 EDSFF x4 Card Module Config v4.000 c1.1.qfg +187 -187
  82. quarchpy/config_files/Card_Modules/QTL2351-xx - GEN4 EDSFF x4 Card Module +Triggering Config v4.000 c1.1.qfg +189 -189
  83. quarchpy/config_files/Card_Modules/QTL2351-xx - GEN4 EDSFF x4 Card Module +Triggering Config v4.001 c1.2.qfg +190 -190
  84. quarchpy/config_files/Card_Modules/QTL2357-xx - PCIe GEN5 Card Module Config v5.000 c1.1.qfg +282 -282
  85. quarchpy/config_files/Card_Modules/QTL2358-xx - PCIe GEN5 Card Module w Triggering Config v5.000 c1.1.qfg +283 -283
  86. quarchpy/config_files/Card_Modules/QTL2378-xx - SANBlaze U.3 Rack Riser Card Config v4.000 c1.1.qfg +215 -215
  87. quarchpy/config_files/Card_Modules/QTL2378-xx - SANBlaze U.3 Rack Riser Card Config v4.001 c1.2.qfg +217 -217
  88. quarchpy/config_files/Card_Modules/QTL2395-01 - GEN4 M.2 M-Key Vertical Breaker Module w Triggering Config v5.000 c1.1.qfg +208 -208
  89. quarchpy/config_files/Card_Modules/QTL2395-02 - GEN4 M.2 M-Key Vertical Breaker Module w Triggering Config v5.001 c1.3.qfg +220 -220
  90. quarchpy/config_files/Card_Modules/QTL2395-03 - GEN4 M.2 M-Key Vertical Breaker Module w Triggering Config v5.001 c1.3.qfg +220 -220
  91. quarchpy/config_files/Card_Modules/QTL2396-xx - PCIe GEN5 Card Module w inrush Config v5.000 c1.1.qfg +282 -282
  92. quarchpy/config_files/Card_Modules/QTL2403-xx - Gen4 PCIe Lite Module Config v4.000.qfg +135 -135
  93. quarchpy/config_files/Card_Modules/QTL2515-xx - PCIe GEN4 Card Module w Triggering - Inrush Limit Config v4.001 c1.3.qfg +277 -277
  94. quarchpy/config_files/Card_Modules/QTL2652-xx - Gen5 PCIe Lite Module Config v4.000.qfg +130 -130
  95. quarchpy/config_files/Card_Modules/QTL2652-xx - Gen5 PCIe Lite Module Config v4.003.qfg +137 -137
  96. quarchpy/config_files/Card_Modules/QTL2658-xx - Gen5 PCIe Lite Module w Inrush Config v4.000.qfg +130 -130
  97. quarchpy/config_files/Card_Modules/QTL2661-xx - GEN5 PCIe U.3 Breaker Config w Triggering v5.000 c1.1.qfg +229 -229
  98. quarchpy/config_files/Card_Modules/QTL2662-xx - GEN5 PCIe U.3 Breaker Config v5.000 c1.1.qfg +228 -228
  99. quarchpy/config_files/Card_Modules/QTL2686-xx - Gen5 EDSFF E3 x4 Breaker Config v5.000.qfg +230 -230
  100. quarchpy/config_files/Card_Modules/QTL2686-xx - Gen5 EDSFF E3 x4 Breaker Config v5.001 c1.2.qfg +233 -233
  101. quarchpy/config_files/Card_Modules/QTL2686-xx - Gen5 EDSFF E3 x4 Breaker v5.000 c1.1.qfg +230 -230
  102. quarchpy/config_files/Card_Modules/QTL2692-xx - Gen5 EDSFF E3 x4 Breaker +Triggering Config v5.000.qfg +230 -230
  103. quarchpy/config_files/Card_Modules/QTL2692-xx - Gen5 EDSFF E3 x4 Breaker w Triggering Config v5.001 c1.2.qfg +233 -233
  104. quarchpy/config_files/Card_Modules/QTL2692-xx - Gen5 EDSFF E3 x4 Breaker w Triggering v5.000 c1.1.qfg +230 -230
  105. quarchpy/config_files/Card_Modules/QTL2766-xx - GEN4 EDSFF E1 x8 Breaker Config v5.000.qfg +253 -253
  106. quarchpy/config_files/Card_Modules/QTL2767-xx - GEN4 EDSFF E3 x8 Breaker Config v5.000.qfg +253 -253
  107. quarchpy/config_files/Card_Modules/QTL2768-xx - GEN4 EDSFF E3 2T x8 Breaker Config v5.000.qfg +253 -253
  108. quarchpy/config_files/Card_Modules/QTL2776-xx - GEN4 EDSFF E1 x8 Breaker +Triggering Config v5.000.qfg +253 -253
  109. quarchpy/config_files/Card_Modules/QTL2777-xx - GEN4 EDSFF E3 x8 Breaker +Triggering Config v5.000.qfg +253 -253
  110. quarchpy/config_files/Card_Modules/QTL2778-xx - GEN4 EDSFF E3 2T x8 Breaker +Triggering Config v5.000.qfg +253 -253
  111. quarchpy/config_files/Card_Modules/QTL2798-xx - PCIe GEN5 Card Module w Triggering w Inrush Limit Config v5.000 c1.1.qfg +283 -283
  112. quarchpy/config_files/Card_Modules/QTL2804-xx - GEN5 MCIO x4 to U.2 Breaker Config v5.000 c1.1.qfg +234 -234
  113. quarchpy/config_files/Card_Modules/QTL2805-xx - GEN5 MCIO x4 to U.2 Breaker + Triggering Config v5.000 c1.1.qfg +234 -234
  114. quarchpy/config_files/Card_Modules/QTL2814-xx - GEN5 AIC to U.2 Breaker + Triggering Config v5.000 c1.1 .qfg +233 -233
  115. quarchpy/config_files/Card_Modules/QTL2892-xx - GEN5 EDSFF E1 x4 Breaker.qfg +233 -233
  116. quarchpy/config_files/Card_Modules/QTL2925-xx - GEN5 EDSFF E1 x4 Breaker +Triggering.qfg +233 -233
  117. quarchpy/config_files/Drive_Modules/QTL1177-xx - HS Module Config v3.5 c1.5.qfg +198 -198
  118. quarchpy/config_files/Drive_Modules/QTL1177-xx - HS Module Config v4.000 c1.5.qfg +200 -200
  119. quarchpy/config_files/Drive_Modules/QTL1177-xx - HS Module Config v4.006 c1.8.qfg +199 -199
  120. quarchpy/config_files/Drive_Modules/QTL1215-xx - Lite Module Config v3.50.qfg +118 -118
  121. quarchpy/config_files/Drive_Modules/QTL1215-xx - Lite Module Config v4.000.qfg +118 -118
  122. quarchpy/config_files/Drive_Modules/QTL1301-xx - HS Lite Module Config v3.50.qfg +129 -129
  123. quarchpy/config_files/Drive_Modules/QTL1301-xx - HS Lite Module Config v4.000.qfg +129 -129
  124. quarchpy/config_files/Drive_Modules/QTL1429-01 - EMC HS Lite Module Config v4.000.qfg +129 -129
  125. quarchpy/config_files/Drive_Modules/QTL1429-02 - EMC HS Lite Module Config v4.002.qfg +120 -120
  126. quarchpy/config_files/Drive_Modules/QTL1623-03 - 12G HS Lite Module Config v4.001.qfg +128 -128
  127. quarchpy/config_files/Drive_Modules/QTL1623-04 - 12G HS Lite Module Config v4.001.qfg +128 -128
  128. quarchpy/config_files/Drive_Modules/QTL1680-xx - SCA2 Lite Module Config v4.001.qfg +135 -135
  129. quarchpy/config_files/Drive_Modules/QTL1689-01 - 12G HS Module Config v4.001 c1.1.qfg +199 -199
  130. quarchpy/config_files/Drive_Modules/QTL1689-04 - 12G HS Module Config v4.002 c1.1.qfg +196 -196
  131. quarchpy/config_files/Drive_Modules/QTL1689-05 - 12G HS Module Config v4.002 c1.1.qfg +196 -196
  132. quarchpy/config_files/Drive_Modules/QTL1743-02 - PCIe SFF Module Config v4.003 c1.3.qfg +222 -222
  133. quarchpy/config_files/Drive_Modules/QTL1743-02 - PCIe SFF Module Config v4.006 c1.4.qfg +213 -213
  134. quarchpy/config_files/Drive_Modules/QTL1743-xx - PCIe SFF Module Config v4.000 c1.1.qfg +221 -221
  135. quarchpy/config_files/Drive_Modules/QTL1753-xx - 12G Lite Module Config v4.000.qfg +116 -116
  136. quarchpy/config_files/Drive_Modules/QTL1921-01 - EMC 12G HS Lite Module Config v4.000.qfg +120 -120
  137. quarchpy/config_files/Drive_Modules/QTL2207-01 - GEN 4 PCIe U.2 Drive Module.qfg +217 -217
  138. quarchpy/config_files/Drive_Modules/QTL2207-02 - GEN 4 PCIe U.2 Drive Module v5.000.qfg +220 -220
  139. quarchpy/config_files/Drive_Modules/QTL2207-03 - GEN 4 PCIe SFF HS Drive Module Triggering v5.001.qfg +221 -221
  140. quarchpy/config_files/Drive_Modules/QTL2207-xx - GEN 4 PCIe U.2 Drive Module v4.001.qfg +219 -219
  141. quarchpy/config_files/Drive_Modules/QTL2207-xx - GEN 4 PCIe U.2 Drive Module.qfg +219 -219
  142. quarchpy/config_files/Drive_Modules/QTL2245-01 - GEN 4 PCIe U.3 HS Drive Module v4.000.qfg +223 -223
  143. quarchpy/config_files/Drive_Modules/QTL2245-xx - GEN 4 PCIe U.3 HS Drive Module.qfg +229 -229
  144. quarchpy/config_files/Drive_Modules/QTL2266-01 - GEN 4 PCIe SFF HS Drive Module Triggering.qfg +219 -219
  145. quarchpy/config_files/Drive_Modules/QTL2266-02 - GEN 4 PCIe SFF HS Drive Module Triggering v4.002.qfg +220 -220
  146. quarchpy/config_files/Drive_Modules/QTL2266-03 - GEN 4 PCIe SFF HS Drive Module Triggering v5.001.qfg +221 -221
  147. quarchpy/config_files/Drive_Modules/QTL2266-XX - GEN 4 PCIe SFF HS Drive Module Triggering.qfg +219 -219
  148. quarchpy/config_files/Drive_Modules/QTL2270-01 - GEN 4 PCIe U.3 HS Drive Module Triggering v4.000.qfg +225 -225
  149. quarchpy/config_files/Drive_Modules/QTL2270-xx - GEN 4 PCIe U.3 HS Drive Module Triggering.qfg +230 -230
  150. quarchpy/config_files/Drive_Modules/QTL2542-02 - 24G SAS Drive Breaker Module v5.001.qfg +194 -194
  151. quarchpy/config_files/Drive_Modules/QTL2542-xx - 24G SAS Drive Breaker v5.000 c1.1.qfg +194 -194
  152. quarchpy/config_files/Drive_Modules/QTL2543-xx - 24G SAS Drive Breaker +Triggering v5.000 c1.1.qfg +195 -195
  153. quarchpy/config_files/Drive_Modules/QTL2602-xx - Multiprotocol Link Breaker.qfg +178 -178
  154. quarchpy/config_files/Drive_Modules/QTL2645-xx - Gen5 PCIe U.2 Drive Module v5.000.qfg +227 -227
  155. quarchpy/config_files/Drive_Modules/QTL2645-xx - Gen5 PCIe U.2 Drive Module v5.001.qfg +227 -227
  156. quarchpy/config_files/Drive_Modules/QTL2645-xx - Gen5 PCIe U.2 Drive Module v5.003.qfg +227 -227
  157. quarchpy/config_files/Drive_Modules/QTL2645-xx - Gen5 PCIe U.2 Drive Module v5.007.qfg +229 -229
  158. quarchpy/config_files/Drive_Modules/QTL2651-xx - Gen5 PCIe U.2 Drive Module + Triggering v5.000.qfg +228 -228
  159. quarchpy/config_files/Drive_Modules/QTL2651-xx - Gen5 PCIe U.2 Drive Module + Triggering v5.001.qfg +228 -228
  160. quarchpy/config_files/Drive_Modules/QTL2651-xx - Gen5 PCIe U.2 Drive Module + Triggering v5.003.qfg +228 -228
  161. quarchpy/config_files/Drive_Modules/QTL2651-xx - Gen5 PCIe U.2 Drive Module v5.007.qfg +230 -230
  162. quarchpy/config_files/Drive_Modules/QTL2661-xx - Gen5 U.3 Drive Module + Triggering v5.000.qfg +229 -229
  163. quarchpy/config_files/Drive_Modules/QTL2662-xx - Gen5 PCIe U.3 Drive Module v5.000.qfg +228 -228
  164. quarchpy/config_files/Drive_Modules/QTL2757-xx - Gen5 SFF Lite Breaker Module Config v4.000.qfg +140 -140
  165. quarchpy/config_files/Drive_Modules/QTL2804-xx - Gen5 MCIO to U.2 Breaker +Triggering v5.003.qfg +253 -253
  166. quarchpy/config_files/Drive_Modules/QTL2804-xx - Gen5 MCIO to U.2 Breaker v5.001.qfg +234 -234
  167. quarchpy/config_files/Drive_Modules/QTL2805-xx - Gen5 MCIO to U.2 Breaker +Triggering v5.001.qfg +234 -234
  168. quarchpy/config_files/Drive_Modules/QTL2805-xx - Gen5 MCIO to U.2 Breaker +Triggering v5.002.qfg +253 -253
  169. quarchpy/config_files/Drive_Modules/QTL2805-xx - Gen5 MCIO to U.2 Breaker +Triggering v5.003.qfg +253 -253
  170. quarchpy/config_files/Drive_Modules/QTL2813-xx - Gen5 AIC to U.2 Breaker v5.001 c1.2.qfg +230 -230
  171. quarchpy/config_files/Drive_Modules/QTL2813-xx - Gen5 AIC to U.2 Breaker with Triggering v5.002 c1.3.qfg +253 -253
  172. quarchpy/config_files/Drive_Modules/QTL2814-xx - Gen5 AIC to U.2 Breaker with Triggering v5.001 c1.2.qfg +230 -230
  173. quarchpy/config_files/Drive_Modules/QTL2814-xx - Gen5 AIC to U.2 Breaker with Triggering v5.002 c1.3.qfg +253 -253
  174. quarchpy/config_files/Drive_Modules/QTL2892-xx - Gen5 EDSFF E1 x4 Breaker v5.001.qfg +233 -233
  175. quarchpy/config_files/Drive_Modules/Standard Drive Module Config v3.5 c1.1.qfg +171 -171
  176. quarchpy/config_files/Power_Margining/HD/QTL1944-xx - HD Power Module v5.000.qfg +123 -123
  177. quarchpy/config_files/Power_Margining/HD/QTL1944-xx - HD Power Module v5.003.qfg +124 -124
  178. quarchpy/config_files/Power_Margining/HD/QTL1995-xx - x6 HD Power Module v5.002.qfg +122 -122
  179. quarchpy/config_files/Power_Margining/HD/QTL1995-xx - x6 HD Power Module v5.003.qfg +123 -123
  180. quarchpy/config_files/Power_Margining/HD/QTL1999-xx - Single HD Power Module v5.002.qfg +122 -122
  181. quarchpy/config_files/Power_Margining/HD/QTL1999-xx - Single HD Power Module v5.003.qfg +123 -123
  182. quarchpy/config_files/Power_Margining/HD/QTL1999-xx - Single HD Power Module v6.000.qfg +124 -124
  183. quarchpy/config_files/Power_Margining/PPM/QTL1455-02 - Power Margining Module v4.101.qfg +78 -78
  184. quarchpy/config_files/Power_Margining/PPM/QTL1455-02 - Power Margining Module v4.200.qfg +80 -80
  185. quarchpy/config_files/Power_Margining/PPM/QTL1455-02 - Power Margining Module v4.201.qfg +82 -82
  186. quarchpy/config_files/Power_Margining/PPM/QTL1455-02 - Test Power Margining Module v4.004.qfg +73 -73
  187. quarchpy/config_files/Power_Margining/PPM/QTL1658-01 - Power Margining Module w. Triggering v4.101.qfg +78 -78
  188. quarchpy/config_files/Power_Margining/PPM/QTL1658-01 - Power Margining Module w. Triggering v4.200.qfg +80 -80
  189. quarchpy/config_files/Power_Margining/PPM/QTL1658-01 - Power Margining Module w. Triggering v4.201.qfg +82 -82
  190. quarchpy/config_files/Power_Margining/PPM/QTL1727-01 - 3v3 Power Margining Module w. Triggering v4.105.qfg +78 -78
  191. quarchpy/config_files/Power_Margining/PPM/QTL1727-01 - 3v3 Power Margining Module w. Triggering v4.200.qfg +80 -80
  192. quarchpy/config_files/Power_Margining/PPM/QTL1727-01 - 3v3 Power Margining Module w. Triggering v4.201.qfg +82 -82
  193. quarchpy/config_files/Power_Margining/PPM/QTL1730-01 - 3v3 Power Margining Module v4.105.qfg +78 -78
  194. quarchpy/config_files/Power_Margining/PPM/QTL1730-01 - 3v3 Power Margining Module v4.200.qfg +80 -80
  195. quarchpy/config_files/Power_Margining/PPM/QTL1730-01 - 3v3 Power Margining Module v4.201.qfg +82 -82
  196. quarchpy/config_files/Power_Margining/XLC/QTL1824-01 - Power Margining Module V2 - Triggering v4.000.qfg +80 -80
  197. quarchpy/config_files/Power_Margining/XLC/QTL1824-01 - Power Margining Module V2 - Triggering v4.200.qfg +81 -81
  198. quarchpy/config_files/Power_Margining/XLC/QTL1824-01 - Power Margining Module V2 - Triggering v4.202.qfg +87 -87
  199. quarchpy/config_files/Power_Margining/XLC/QTL1824-01 - Power Margining Module V2 - Triggering v4.210.qfg +88 -88
  200. quarchpy/config_files/Power_Margining/XLC/QTL1824-01 - Power Margining Module V2 - Triggering v4.211.qfg +121 -121
  201. quarchpy/config_files/Power_Margining/XLC/QTL1824-03 - Power Margining Module V2 - Triggering v4.213.qfg +121 -121
  202. quarchpy/config_files/Power_Margining/XLC/QTL1847-01 - Power Margining Module V2 v4.213.qfg +121 -121
  203. quarchpy/config_files/Switch_Modules/QTL1390-xx - 4-8 SATA MUX Module Config v4.002.qfg +186 -186
  204. quarchpy/config_files/Switch_Modules/QTL1443-xx - 1-8 USB3 MUX Module Config v4.002.qfg +147 -147
  205. quarchpy/config_files/Switch_Modules/QTL1443-xx - 1-8 USB3 MUX Module Config v4.003.qfg +147 -147
  206. quarchpy/config_files/Switch_Modules/QTL1443-xx - 1-8 USB3 MUX Module Config v4.100.qfg +147 -147
  207. quarchpy/config_files/Switch_Modules/QTL1449-xx - 1-8 PCIe MUX Module Config v4.000.qfg +145 -145
  208. quarchpy/config_files/Switch_Modules/QTL1490-xx - SATA Keyed HS Module Config v4.003 c1.6.qfg +194 -194
  209. quarchpy/config_files/Switch_Modules/QTL1490-xx - SATA Keyed HS Module Config v4.006 c1.8.qfg +193 -193
  210. quarchpy/config_files/Switch_Modules/QTL1530-xx - 1-8 DP MUX Module Config v4.000.qfg +145 -145
  211. quarchpy/config_files/Switch_Modules/QTL1564-xx - 12 Port Mini SAS HD MUX Module Config v4.000.qfg +184 -184
  212. quarchpy/config_files/Switch_Modules/QTL1584-xx - 1-4 ExpressCard MUX Module Config v4.000.qfg +81 -81
  213. quarchpy/config_files/quarch_config_parser.py +19 -16
  214. quarchpy/connection_specific/QPS/{License/argparse4j-license.txt → 3rdPartyLicenses/argparse4j-LICENSE.txt} +23 -25
  215. quarchpy/connection_specific/QPS/3rdPartyLicenses/com.sun.istack-license.html +59 -0
  216. quarchpy/connection_specific/QPS/{qis/License/LICENSE.txt → 3rdPartyLicenses/commons-io-LICENSE-2.0.txt} +202 -202
  217. quarchpy/connection_specific/QPS/3rdPartyLicenses/controlsfx-license.txt +29 -0
  218. quarchpy/connection_specific/QPS/{License/LICENSE.txt → 3rdPartyLicenses/evalex-LICENSE.txt} +202 -202
  219. quarchpy/connection_specific/QPS/3rdPartyLicenses/gson-license.txt +202 -0
  220. quarchpy/connection_specific/QPS/3rdPartyLicenses/guava-license.txt +202 -0
  221. quarchpy/connection_specific/QPS/3rdPartyLicenses/jakarta.activation-license.html +59 -0
  222. quarchpy/connection_specific/QPS/3rdPartyLicenses/jakarta.xml.bind-api-license.html +59 -0
  223. quarchpy/connection_specific/QPS/3rdPartyLicenses/janino-LICENSE.txt +31 -0
  224. quarchpy/connection_specific/QPS/3rdPartyLicenses/jfx-license.txt +347 -0
  225. quarchpy/connection_specific/QPS/3rdPartyLicenses/log4j-license.txt +202 -0
  226. quarchpy/connection_specific/QPS/3rdPartyLicenses/netty-LICENSE.txt +202 -0
  227. quarchpy/connection_specific/QPS/3rdPartyLicenses/netty-NOTICE.txt +239 -0
  228. quarchpy/connection_specific/QPS/3rdPartyLicenses/nsmenufx-LICENSE.txt +24 -0
  229. quarchpy/connection_specific/QPS/3rdPartyLicenses/slf4j-LICENSE.txt +24 -0
  230. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1253-01 - Mini SAS Module Config v3.5 c1.3.xml +597 -0
  231. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1253-01 - Mini SAS Module Config v4.000 c1.3.xml +597 -0
  232. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1253-02 - Mini SAS Module Config v3.5 c1.3.xml +597 -0
  233. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1253-02 - Mini SAS Module Config v4.000 c1.3.xml +597 -0
  234. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1253-xx - Mini SAS Module Config v4.003 c1.6.xml +599 -0
  235. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1271-xx - Ethernet Module Config v3.5 c1.2.xml +533 -0
  236. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1271-xx - Ethernet Module Config v4.000 c1.2.xml +533 -0
  237. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1271-xx - Ethernet Module Config v4.100 c1.3.xml +535 -0
  238. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1292-xx - SFP+ Cable Pull Module Config v4.000 c1.1.xml +449 -0
  239. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1309-04 - USB 3.0 Module Config v4.003 c1.2.xml +530 -0
  240. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1309-xx - USB 3.0 Module Config v3.5 c1.1.xml +528 -0
  241. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1309-xx - USB 3.0 Module Config v4.000 c1.1.xml +528 -0
  242. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1366-xx - QSFP Cable Pull Module Config v4.000 c1.1.xml +684 -0
  243. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1383-xx - eSATAp Module Config v4.000 c1.3.xml +542 -0
  244. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1521-02 - Mini SAS HD Module Config v4.000 c1.1.xml +670 -0
  245. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1521-03 - Mini SAS HD Module Config v4.000 c1.1.xml +670 -0
  246. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1521-05 - Mini SAS HD Module Config v4.005 c1.1.xml +672 -0
  247. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1521-05 - Mini SAS HD Module Config v4.007 c1.2.xml +672 -0
  248. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1521-xx - Mini SAS HD Module Config v4.003 c1.5.xml +672 -0
  249. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1663-xx - Quad QSFP Cable Pull Module Config v4.000 c1.1.xml +1523 -0
  250. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1675-05 - Mini SAS HD Module w Triggering Config v4.007 c1.3.xml +673 -0
  251. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1675-xx - Mini SAS HD Module w Triggering Config v4.000 c1.1.xml +673 -0
  252. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1917-xx - Dual SFP+ Cable Pull Module Config v4.000 c1.1.xml +614 -0
  253. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1971-01 - USB TypeC Module Config v4.000 c1.1.xml +637 -0
  254. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL1971-02 - USB TypeC Module Config v4.000 c1.1.xml +641 -0
  255. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL2022-xx - RJ-45 Cable Module Config v4.104 c1.3.xml +535 -0
  256. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL2058-xx - External PCIe Module Config v4.001 c1.1.xml +696 -0
  257. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL2138-01 - SFP28 Cable Pull Module Config v4.000 c1.1.xml +449 -0
  258. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL2146-01 - Gen4 OCuLink Cable Module Config v4.001 c1.1.xml +718 -0
  259. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL2162-01 - 24G mini SAS HD Cable Break Module Config v4.000 c1.xml +672 -0
  260. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL2171-01 - QSFP28 Cable Module Config v4.000 c1.xml +583 -0
  261. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL2171-02 - QSFP28 Cable Module Config v4.000 c1.xml +583 -0
  262. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL2341-01 - Gen4 External PCIe Cable Module v4.000.xml +625 -0
  263. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL2602-xx - Multiprotocol Link Breaker.xml +414 -0
  264. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL2834-xx - -48V DC Breaker Module v5.000 c1.0.xml +374 -0
  265. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Cable Modules/QTL3000-xx - RJ-45 Cable Module v5.000 c1.4.xml +539 -0
  266. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL1069-xx - SBB 2.0 Module Config v3.5 c1.1.xml +1614 -0
  267. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL1630-01 - PCIe Card Module v4.000 c1.0.xml +1271 -0
  268. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL1630-02 - PCIe Card Module Config v4.004 c1.2.xml +1289 -0
  269. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL1630-02 - PCIe Card Module Config v4.005 c1.2.xml +1289 -0
  270. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL1630-02 - PCIe Card Module Config v4.100 c1.4.xml +1290 -0
  271. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL1630-04 - PCIe Card Module Config v4.001 c1.1.xml +1297 -0
  272. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL1630-04 - PCIe Card Module Config v4.004 c1.2.xml +1301 -0
  273. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL1688-01 - PCIe Card Module w Triggering Config v4.004 c1.2.xml +1290 -0
  274. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL1688-01 - PCIe Card Module w Triggering Config v4.006 c1.3.xml +1291 -0
  275. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL1688-03 - PCIe Card Module w Triggering Config v4.001 c1.1.xml +1298 -0
  276. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL1688-03 - PCIe Card Module w Triggering Config v4.004 c1.2.xml +1302 -0
  277. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL1688-04 - PCIe Card Module w Triggering Config v4.005 c1.5.xml +1307 -0
  278. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL1688-05 - PCIe Card Module w Triggering Config v4.005 c1.xml +1307 -0
  279. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL1848-01 - PCIe Lite Card Module Config v4.000.xml +219 -0
  280. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL1848-02 - PCIe Lite Card Module Config v4.000.xml +286 -0
  281. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL1919-01 - PCIe x8 Card Module Config v4.001 c1.4.xml +965 -0
  282. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL1920-01 - PCIe x8 Card Module w Triggering Config v4.000 c1.3.xml +966 -0
  283. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2019-xx - M.2 Horizontal Card Module Config v4.002 c1.1.xml +703 -0
  284. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2034-xx - M.2 M-Key Vertical Module Config v4.001 c1.1.xml +737 -0
  285. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2067-xx - PCIe SFF Module Config v4.000 c1.1.xml +971 -0
  286. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2067-xx - Sanblaze 2 Drive Riser Card Config v4.006 c1.4.xml +1020 -0
  287. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2067-xx - Sanblaze 2 Drive Riser Card Config v4.007 c1.4.xml +1022 -0
  288. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2073-01 - GEN3 PCIe Lite Card Module Config v4.001.xml +286 -0
  289. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2073-01 - PCIe Lite Card Module Config v4.000.xml +286 -0
  290. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2074-01 - GEN3 PCIe HS Card Module v4.005 c1.4.xml +1301 -0
  291. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2074-01 - PCIe Card Module Config CurrentLimit v4.004 c1.2.xml +1301 -0
  292. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2087-xx - PCIe GEN4 Card Module w Triggering Config v4.001 c1.1.xml +1307 -0
  293. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2087-xx - PCIe GEN4 Card Module w Triggering Config v4.001 c1.3.xml +1212 -0
  294. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2087-xx - PCIe GEN4 Card Module w Triggering Config v5.000 c1.4.xml +1212 -0
  295. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2094-01 - Sanblaze Dualport Riser Card Config v4.001 c1.1.xml +773 -0
  296. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2128-xx - PCIe GEN4 Card Module w Triggering Config v4.000 c1.1.xml +1306 -0
  297. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2128-xx - PCIe GEN4 Card Module w Triggering Config v4.001 c1.4.xml +1211 -0
  298. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2135-xx - PCIe GEN4 Card Module w Triggering Config - Inrush Limit v4.001 c1.4.xml +1211 -0
  299. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2161-01 - EDSFF x8 Module Config v4.000 c1.1.xml +773 -0
  300. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2171-xx - EDSFF x8 Module w Triggering Config 4.001 c1.1.xml +785 -0
  301. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2203-01 - Sanblaze Dualport Rack Riser Card Config v4.000 c1.1.xml +715 -0
  302. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2203-01 - Sanblaze Dualport Rack Riser Card Config v4.005 c1.5.xml +715 -0
  303. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2272-01 - GEN4 EDSFF x8 Module Config v4.000 c1.1.xml +771 -0
  304. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2282-01 - Sanblaze Singleport Rack Riser Card Config v4.000 c1.1.xml +666 -0
  305. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2282-01 - Sanblaze Singleport Rack Riser Card Config v4.002 c1.2.xml +666 -0
  306. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2318-01 - SANBlaze U.2 Rack Riser Card Config v4.000 c1.1.xml +715 -0
  307. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2322-03 - GEN4 M.2 M-Key Vertical Breaker Module Config v5.001 c1.3.xml +738 -0
  308. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2322-xx - GEN4 M.2 M-Key Vertical Breaker Module Config v5.000 c1.1.xml +637 -0
  309. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2334-xx - Gen4 EDSFF x4 Card Module Config v4.000 c1.1.xml +615 -0
  310. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2351-xx - GEN4 EDSFF x4 Card Module +Triggering Config v4.000 c1.1.xml +621 -0
  311. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2351-xx - GEN4 EDSFF x4 Card Module +Triggering Config v4.001 c1.2.xml +624 -0
  312. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2357-xx - PCIe GEN5 Card Module Config v5.000 c1.1.xml +1242 -0
  313. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2358-xx - PCIe GEN5 Card Module w Triggering Config v5.000 c1.1.xml +1250 -0
  314. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2378-xx - SANBlaze U.3 Rack Riser Card Config v4.000 c1.1.xml +682 -0
  315. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2378-xx - SANBlaze U.3 Rack Riser Card Config v4.001 c1.2.xml +698 -0
  316. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2395-01 - GEN4 M.2 M-Key Vertical Breaker Module w Triggering Config v5.000 c1.1.xml +647 -0
  317. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2395-02 - GEN4 M.2 M-Key Vertical Breaker Module w Triggering Config v5.001 c1.3.xml +742 -0
  318. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2395-03 - GEN4 M.2 M-Key Vertical Breaker Module w Triggering Config v5.001 c1.3.xml +742 -0
  319. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2396-xx - PCIe GEN5 Card Module w inrush Config v5.000 c1.1.xml +1242 -0
  320. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2403-xx - Gen4 PCIe Lite Module Config v4.000.xml +293 -0
  321. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2515-xx - PCIe GEN4 Card Module w Triggering - Inrush Limit Config v4.001 c1.3.xml +1212 -0
  322. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2652-xx - Gen5 PCIe Lite Module Config v4.000.xml +259 -0
  323. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2652-xx - Gen5 PCIe Lite Module Config v4.003.xml +288 -0
  324. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2658-xx - Gen5 PCIe Lite Module w Inrush Config v4.000.xml +259 -0
  325. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2661-xx - GEN5 PCIe U.3 Breaker Config w Triggering v5.000 c1.1.xml +813 -0
  326. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2662-xx - GEN5 PCIe U.3 Breaker Config v5.000 c1.1.xml +801 -0
  327. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2686-xx - Gen5 EDSFF E3 x4 Breaker Config v5.000.xml +741 -0
  328. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2686-xx - Gen5 EDSFF E3 x4 Breaker Config v5.001 c1.2.xml +799 -0
  329. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2686-xx - Gen5 EDSFF E3 x4 Breaker Config v5.002 c1.4.xml +743 -0
  330. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2686-xx - Gen5 EDSFF E3 x4 Breaker v5.000 c1.1.xml +741 -0
  331. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2692-xx - Gen5 EDSFF E3 x4 Breaker +Triggering Config v5.000.xml +742 -0
  332. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2692-xx - Gen5 EDSFF E3 x4 Breaker w Triggering Config v5.001 c1.2.xml +800 -0
  333. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2692-xx - Gen5 EDSFF E3 x4 Breaker w Triggering v5.000 c1.1.xml +742 -0
  334. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2766-xx - GEN4 EDSFF E1 x8 Breaker Config v5.000.xml +982 -0
  335. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2767-xx - GEN4 EDSFF E3 x8 Breaker Config v5.000.xml +982 -0
  336. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2768-xx - GEN4 EDSFF E3 2T x8 Breaker Config v5.000.xml +982 -0
  337. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2776-xx - GEN4 EDSFF E1 x8 Breaker +Triggering Config v5.000.xml +983 -0
  338. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2777-xx - GEN4 EDSFF E3 x8 Breaker +Triggering Config v5.000.xml +983 -0
  339. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2778-xx - GEN4 EDSFF E3 2T x8 Breaker +Triggering Config v5.000.xml +983 -0
  340. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2798-xx - PCIe GEN5 Card Module w Triggering w Inrush Limit Config v5.000 c1.1.xml +1250 -0
  341. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2804-xx - GEN5 MCIO x4 to U.2 Breaker Config v5.000 c1.1.xml +813 -0
  342. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2805-xx - GEN5 MCIO x4 to U.2 Breaker + Triggering Config v5.000 c1.1.xml +814 -0
  343. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2813-xx - Gen5 AIC to U.2 Breaker v5.002 c1.3.xml +871 -0
  344. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2814-xx - GEN5 AIC to U.2 Breaker + Triggering Config v5.000 c1.1 .xml +807 -0
  345. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2814-xx - Gen5 AIC to U.2 Breaker + Triggering Config v5.002 c1.3.xml +872 -0
  346. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2892-xx - GEN5 EDSFF E1 x4 Breaker.xml +799 -0
  347. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2901-xx - GEN5 M.2 M-Key Horizontal Breaker Config v5.000 c1.1.xml +753 -0
  348. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2902-xx - GEN5 M.2 M-Key Horizontal Breaker w Triggering Config v5.000 c1.1.xml +762 -0
  349. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2902-xx- -Gen5 M.2 Horizontal Breaker +Triggering Config 5.000 c1.1.xml +762 -0
  350. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2925-xx - GEN5 EDSFF E1 x4 Breaker +Triggering.xml +800 -0
  351. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Card Modules/QTL2954-01 - fake delete.xml +947 -0
  352. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1177-xx - HS Module Config v3.5 c1.5.xml +592 -0
  353. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1177-xx - HS Module Config v4.000 c1.5.xml +592 -0
  354. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1177-xx - HS Module Config v4.006 c1.8.xml +594 -0
  355. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1215-xx - Lite Module Config v3.50.xml +203 -0
  356. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1215-xx - Lite Module Config v4.000.xml +203 -0
  357. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1301-xx - HS Lite Module Config v3.50.xml +281 -0
  358. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1301-xx - HS Lite Module Config v4.000.xml +281 -0
  359. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1429-01 - EMC HS Lite Module Config v4.000.xml +281 -0
  360. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1429-02 - EMC HS Lite Module Config v4.002.xml +234 -0
  361. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1623-03 - 12G HS Lite Module Config v4.001.xml +266 -0
  362. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1623-04 - 12G HS Lite Module Config v4.001.xml +266 -0
  363. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1680-xx - SCA2 Lite Module Config v4.001.xml +333 -0
  364. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1689-01 - 12G HS Module Config v4.001 c1.1.xml +594 -0
  365. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1689-04 - 12G HS Module Config v4.002 c1.1.xml +580 -0
  366. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1689-05 - 12G HS Module Config v4.002 c1.1.xml +579 -0
  367. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1743-02 - PCIe SFF Module Config v4.003 c1.3.xml +794 -0
  368. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1743-02 - PCIe SFF Module Config v4.006 c1.4.xml +698 -0
  369. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1743-xx - PCIe SFF Module Config v4.000 c1.1.xml +789 -0
  370. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1753-xx - 12G Lite Module Config v4.000.xml +192 -0
  371. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL1921-01 - EMC 12G HS Lite Module Config v4.000.xml +233 -0
  372. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2207-01 - GEN 4 PCIe U.2 Drive Module.xml +733 -0
  373. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2207-02 - GEN 4 PCIe U.2 Drive Module v5.000.xml +753 -0
  374. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2207-03 - GEN 4 PCIe SFF HS Drive Module Triggering v5.001.xml +763 -0
  375. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2207-xx - GEN 4 PCIe U.2 Drive Module v4.001.xml +751 -0
  376. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2207-xx - GEN 4 PCIe U.2 Drive Module.xml +746 -0
  377. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2245-01 - GEN 4 PCIe U.3 HS Drive Module v4.000.xml +789 -0
  378. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2245-xx - GEN 4 PCIe U.3 HS Drive Module.xml +823 -0
  379. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2266-01 - GEN 4 PCIe SFF HS Drive Module Triggering.xml +743 -0
  380. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2266-02 - GEN 4 PCIe SFF HS Drive Module Triggering v4.002.xml +758 -0
  381. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2266-03 - GEN 4 PCIe SFF HS Drive Module Triggering v5.001.xml +764 -0
  382. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2266-XX - GEN 4 PCIe SFF HS Drive Module Triggering.xml +747 -0
  383. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2270-01 - GEN 4 PCIe U.3 HS Drive Module Triggering v4.000.xml +798 -0
  384. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2270-xx - GEN 4 PCIe U.3 HS Drive Module Triggering.xml +835 -0
  385. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2542-02 - 24G SAS Drive Breaker Module v5.001.xml +530 -0
  386. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2542-xx - 24G SAS Drive Breaker v5.000 c1.1.xml +530 -0
  387. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2543-xx - 24G SAS Drive Breaker +Triggering v5.000 c1.1.xml +539 -0
  388. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2543-xx - 24G SAS Drive Breaker +Triggering v5.001 c1.3.xml +539 -0
  389. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2602-xx - Multiprotocol Link Breaker.xml +414 -0
  390. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2645-xx - Gen5 PCIe U.2 Drive Module v5.000.xml +792 -0
  391. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2645-xx - Gen5 PCIe U.2 Drive Module v5.001.xml +792 -0
  392. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2645-xx - Gen5 PCIe U.2 Drive Module v5.003.xml +793 -0
  393. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2645-xx - Gen5 PCIe U.2 Drive Module v5.007.xml +816 -0
  394. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2645-xx - Gen5 PCIe U.2 Drive Module v5.008.xml +818 -0
  395. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2651-xx - Gen5 PCIe U.2 Drive Module + Triggering v5.000.xml +801 -0
  396. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2651-xx - Gen5 PCIe U.2 Drive Module + Triggering v5.001.xml +801 -0
  397. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2651-xx - Gen5 PCIe U.2 Drive Module + Triggering v5.003.xml +802 -0
  398. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2651-xx - Gen5 PCIe U.2 Drive Module v5.007.xml +825 -0
  399. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2661-xx - Gen5 U.3 Drive Module + Triggering v5.000.xml +813 -0
  400. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2662-xx - Gen5 PCIe U.3 Drive Module v5.000.xml +801 -0
  401. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2757-xx - Gen5 SFF Lite Breaker Module Config v4.000.xml +272 -0
  402. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2804-xx - Gen5 MCIO to U.2 Breaker +Triggering v5.003.xml +818 -0
  403. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2804-xx - Gen5 MCIO to U.2 Breaker v5.001.xml +813 -0
  404. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2805-xx - Gen5 MCIO to U.2 Breaker +Triggering v5.001.xml +814 -0
  405. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2805-xx - Gen5 MCIO to U.2 Breaker +Triggering v5.002.xml +819 -0
  406. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2805-xx - Gen5 MCIO to U.2 Breaker +Triggering v5.003.xml +819 -0
  407. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2892-xx - Gen5 EDSFF E1 x4 Breaker v5.001.xml +799 -0
  408. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2892-xx - Gen5 EDSFF E1 x4 Breaker v5.002.xml +801 -0
  409. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2940-xx - Gen5 EDSFF E3 x8 Breaker v5.000.xml +1105 -0
  410. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/QTL2941-xx - Gen5 EDSFF E3 x8 Breaker +Triggering v5.000.xml +1106 -0
  411. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Drive Modules/Standard Drive Module Config v3.5 c1.1.xml +463 -0
  412. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Switch Modules/QTL1490-xx - SATA Keyed HS Module Config v4.003 c1.6.xml +555 -0
  413. quarchpy/connection_specific/QPS/DeviceConfig/breaker/Switch Modules/QTL1490-xx - SATA Keyed HS Module Config v4.006 c1.8.xml +557 -0
  414. quarchpy/connection_specific/QPS/DeviceConfig/colors/default-colors.properties +64 -0
  415. quarchpy/connection_specific/QPS/DeviceConfig/colors/qtl2789-colors.properties +2 -0
  416. quarchpy/connection_specific/QPS/InstallType.dat +1 -0
  417. quarchpy/connection_specific/QPS/Power-Studio-QuickStart.pdf +0 -0
  418. quarchpy/connection_specific/QPS/QuarchPowerStudio.properties.xml +0 -1
  419. quarchpy/connection_specific/QPS/app.jar +0 -0
  420. quarchpy/connection_specific/QPS/app.properties +7 -0
  421. quarchpy/connection_specific/QPS/commandLineOptions.txt +19 -10
  422. quarchpy/connection_specific/QPS/license.txt +1 -0
  423. quarchpy/connection_specific/QPS/qis/3rdPartyLicenses/com.sun.istack-license.html +59 -0
  424. quarchpy/connection_specific/QPS/qis/3rdPartyLicenses/dorkbox-LICENSE.Apachev2 +218 -0
  425. quarchpy/connection_specific/QPS/qis/3rdPartyLicenses/jSerialComm-LICENSE-APACHE-2.0 +202 -0
  426. quarchpy/connection_specific/QPS/qis/3rdPartyLicenses/jSerialComm-LICENSE-LGPL-3.0 +165 -0
  427. quarchpy/connection_specific/QPS/qis/3rdPartyLicenses/jakarta.activation-license.html +59 -0
  428. quarchpy/connection_specific/QPS/qis/3rdPartyLicenses/jakarta.xml.bind-api-license.html +59 -0
  429. quarchpy/connection_specific/QPS/qis/3rdPartyLicenses/javassist-License.html +381 -0
  430. quarchpy/connection_specific/QPS/qis/3rdPartyLicenses/jmdns-LICENSE.txt +202 -0
  431. quarchpy/connection_specific/QPS/qis/3rdPartyLicenses/jna-AL2.0 +177 -0
  432. quarchpy/connection_specific/QPS/qis/3rdPartyLicenses/kotlin-stdlib-LICENSE-2.0.txt +202 -0
  433. quarchpy/connection_specific/QPS/qis/3rdPartyLicenses/netty-LICENSE.txt +202 -0
  434. quarchpy/connection_specific/QPS/qis/3rdPartyLicenses/netty-NOTICE.txt +239 -0
  435. quarchpy/connection_specific/QPS/qis/3rdPartyLicenses/slf4j-LICENSE.txt +24 -0
  436. quarchpy/connection_specific/QPS/qis/3rdPartyLicenses/usb4java-LICENSE.md +20 -0
  437. quarchpy/connection_specific/QPS/qis/QuarchInstrumentServer.properties.xml +1 -0
  438. quarchpy/connection_specific/QPS/qis/README.txt +5 -5
  439. quarchpy/connection_specific/QPS/qis/help.txt +112 -61
  440. quarchpy/connection_specific/QPS/qis/license.txt +1 -0
  441. quarchpy/connection_specific/QPS/qis/qis-NoGUI.bat +1 -1
  442. quarchpy/connection_specific/QPS/qis/qis-NoGUI.sh +1 -1
  443. quarchpy/connection_specific/QPS/qis/qis.bat +1 -1
  444. quarchpy/connection_specific/QPS/qis/qis.jar +0 -0
  445. quarchpy/connection_specific/QPS/qis/qis.sh +1 -1
  446. quarchpy/connection_specific/QPS/qis/qis_lib/Collections-2.4.jar +0 -0
  447. quarchpy/connection_specific/QPS/qis/qis_lib/Desktop-1.1.jar +0 -0
  448. quarchpy/connection_specific/QPS/qis/qis_lib/EvalEx-3.5.0.jar +0 -0
  449. quarchpy/connection_specific/QPS/qis/qis_lib/Executor-3.13.jar +0 -0
  450. quarchpy/connection_specific/QPS/qis/qis_lib/JNA-1.2.jar +0 -0
  451. quarchpy/connection_specific/QPS/qis/qis_lib/OS-1.8.jar +0 -0
  452. quarchpy/connection_specific/QPS/qis/qis_lib/SystemTray-4.4.jar +0 -0
  453. quarchpy/connection_specific/QPS/qis/qis_lib/Updates-1.1.jar +0 -0
  454. quarchpy/connection_specific/QPS/qis/qis_lib/Utilities-1.46.jar +0 -0
  455. quarchpy/connection_specific/QPS/qis/qis_lib/cinterface-2.5.6.jar +0 -0
  456. quarchpy/connection_specific/QPS/qis/qis_lib/commons-compiler-3.1.12.jar +0 -0
  457. quarchpy/connection_specific/QPS/qis/qis_lib/commons-compiler-jdk-3.1.12.jar +0 -0
  458. quarchpy/connection_specific/QPS/qis/qis_lib/gson-2.13.1.jar +0 -0
  459. quarchpy/connection_specific/QPS/qis/qis_lib/istack-commons-runtime-3.0.11.jar +0 -0
  460. quarchpy/connection_specific/QPS/qis/qis_lib/jakarta.activation-api-2.1.0.jar +0 -0
  461. quarchpy/connection_specific/QPS/qis/qis_lib/jakarta.xml.bind-api-4.0.0.jar +0 -0
  462. quarchpy/connection_specific/QPS/qis/qis_lib/janino-3.1.12.jar +0 -0
  463. quarchpy/connection_specific/QPS/qis/qis_lib/javassist-3.29.2-GA.jar +0 -0
  464. quarchpy/connection_specific/QPS/qis/qis_lib/jaxb-core-4.0.0.jar +0 -0
  465. quarchpy/connection_specific/QPS/qis/qis_lib/jaxb-runtime-4.0.0.jar +0 -0
  466. quarchpy/connection_specific/QPS/qis/qis_lib/jmdns-3.6.0.jar +0 -0
  467. quarchpy/connection_specific/QPS/qis/qis_lib/jna-jpms-5.12.1.jar +0 -0
  468. quarchpy/connection_specific/QPS/qis/qis_lib/jna-platform-jpms-5.12.1.jar +0 -0
  469. quarchpy/connection_specific/QPS/qis/qis_lib/jul-to-slf4j-2.0.17.jar +0 -0
  470. quarchpy/connection_specific/QPS/qis/qis_lib/kotlin-stdlib-1.9.21.jar +0 -0
  471. quarchpy/connection_specific/QPS/qis/qis_lib/log4j-api-2.25.0.jar +0 -0
  472. quarchpy/connection_specific/QPS/qis/qis_lib/log4j-core-2.25.0.jar +0 -0
  473. quarchpy/connection_specific/QPS/qis/qis_lib/log4j-layout-template-json-2.25.0.jar +0 -0
  474. quarchpy/connection_specific/QPS/qis/qis_lib/log4j-slf4j2-impl-2.25.0.jar +0 -0
  475. quarchpy/connection_specific/QPS/qis/qis_lib/netty-buffer-4.2.2.Final.jar +0 -0
  476. quarchpy/connection_specific/QPS/qis/qis_lib/netty-codec-base-4.2.2.Final.jar +0 -0
  477. quarchpy/connection_specific/QPS/qis/qis_lib/netty-codec-http-4.2.2.Final.jar +0 -0
  478. quarchpy/connection_specific/QPS/qis/qis_lib/netty-common-4.2.2.Final.jar +0 -0
  479. quarchpy/connection_specific/QPS/qis/qis_lib/netty-handler-4.2.2.Final.jar +0 -0
  480. quarchpy/connection_specific/QPS/qis/qis_lib/netty-transport-4.2.2.Final.jar +0 -0
  481. quarchpy/connection_specific/QPS/qis/qis_lib/quarchcommon-2.1.9.jar +0 -0
  482. quarchpy/connection_specific/QPS/qis/qis_lib/slf4j-api-2.0.17.jar +0 -0
  483. quarchpy/connection_specific/QPS/qis/qis_lib/torridoncommon-1.2.8.jar +0 -0
  484. quarchpy/connection_specific/QPS/qis/qis_lib/usb4java-1.3.1.jar +0 -0
  485. quarchpy/connection_specific/QPS/qis/resources/filters/Example.txt +36 -0
  486. quarchpy/connection_specific/QPS/qis/resources/filters/iec_filters.xml +17 -0
  487. quarchpy/connection_specific/QPS/qis/resources/org/usb4java/darwin-x86-64/libusb4java.dylib +0 -0
  488. quarchpy/connection_specific/QPS/qis/resources/org/usb4java/linux-aarch64/libusb4java.so +0 -0
  489. quarchpy/connection_specific/QPS/qis/resources/org/usb4java/linux-arm/libusb4java.so +0 -0
  490. quarchpy/connection_specific/QPS/qis/resources/org/usb4java/linux-x86/libusb4java.so +0 -0
  491. quarchpy/connection_specific/QPS/qis/resources/org/usb4java/linux-x86-64/libusb4java.so +0 -0
  492. quarchpy/connection_specific/QPS/qis/resources/org/usb4java/win32-x86/libusb4java.dll +0 -0
  493. quarchpy/connection_specific/QPS/qis/resources/org/usb4java/win32-x86-64/libusb4java.dll +0 -0
  494. quarchpy/connection_specific/QPS/qps-command-reference.html +339 -0
  495. quarchpy/connection_specific/QPS/qps.jar +0 -0
  496. quarchpy/connection_specific/QPS/qps_lib/EvalEx-3.5.0.jar +0 -0
  497. quarchpy/connection_specific/QPS/qps_lib/commons-compiler-3.1.12.jar +0 -0
  498. quarchpy/connection_specific/QPS/qps_lib/commons-compiler-jdk-3.1.12.jar +0 -0
  499. quarchpy/connection_specific/QPS/qps_lib/commons-io-2.19.0.jar +0 -0
  500. quarchpy/connection_specific/QPS/qps_lib/controlsfx-11.2.2.jar +0 -0
  501. quarchpy/connection_specific/QPS/qps_lib/gson-2.13.1.jar +0 -0
  502. quarchpy/connection_specific/QPS/qps_lib/guava-33.4.8-jre.jar +0 -0
  503. quarchpy/connection_specific/QPS/qps_lib/istack-commons-runtime-3.0.11.jar +0 -0
  504. quarchpy/connection_specific/QPS/qps_lib/jakarta.activation-api-2.1.0.jar +0 -0
  505. quarchpy/connection_specific/QPS/qps_lib/jakarta.xml.bind-api-4.0.0.jar +0 -0
  506. quarchpy/connection_specific/QPS/qps_lib/janino-3.1.12.jar +0 -0
  507. quarchpy/connection_specific/QPS/qps_lib/jaxb-core-4.0.0.jar +0 -0
  508. quarchpy/connection_specific/QPS/qps_lib/jaxb-runtime-4.0.0.jar +0 -0
  509. quarchpy/connection_specific/QPS/qps_lib/jfa-1.2.0.jar +0 -0
  510. quarchpy/connection_specific/QPS/qps_lib/jfxutilities-1.0.5.jar +0 -0
  511. quarchpy/connection_specific/QPS/qps_lib/jna-5.17.0.jar +0 -0
  512. quarchpy/connection_specific/QPS/qps_lib/jul-to-slf4j-2.0.17.jar +0 -0
  513. quarchpy/connection_specific/QPS/qps_lib/log4j-api-2.25.0.jar +0 -0
  514. quarchpy/connection_specific/QPS/qps_lib/log4j-core-2.25.0.jar +0 -0
  515. quarchpy/connection_specific/QPS/qps_lib/log4j-layout-template-json-2.25.0.jar +0 -0
  516. quarchpy/connection_specific/QPS/qps_lib/log4j-slf4j2-impl-2.25.0.jar +0 -0
  517. quarchpy/connection_specific/QPS/qps_lib/netty-buffer-4.2.2.Final.jar +0 -0
  518. quarchpy/connection_specific/QPS/qps_lib/netty-codec-base-4.2.2.Final.jar +0 -0
  519. quarchpy/connection_specific/QPS/qps_lib/netty-codec-http-4.2.2.Final.jar +0 -0
  520. quarchpy/connection_specific/QPS/qps_lib/netty-common-4.2.2.Final.jar +0 -0
  521. quarchpy/connection_specific/QPS/qps_lib/netty-handler-4.2.2.Final.jar +0 -0
  522. quarchpy/connection_specific/QPS/qps_lib/netty-transport-4.2.2.Final.jar +0 -0
  523. quarchpy/connection_specific/QPS/qps_lib/nsmenufx-3.1.0.jar +0 -0
  524. quarchpy/connection_specific/QPS/qps_lib/quarchcommon-2.1.9.jar +0 -0
  525. quarchpy/connection_specific/QPS/qps_lib/qutils-1.0.2.jar +0 -0
  526. quarchpy/connection_specific/QPS/qps_lib/slf4j-api-2.0.17.jar +0 -0
  527. quarchpy/connection_specific/QPS/qps_lib/txw2-4.0.0.jar +0 -0
  528. quarchpy/connection_specific/QPS/resources/InstallBanner.bmp +0 -0
  529. quarchpy/connection_specific/QPS/resources/QPS.icns +0 -0
  530. quarchpy/connection_specific/QPS/resources/QPS.ico +0 -0
  531. quarchpy/connection_specific/QPS/resources/QPS.png +0 -0
  532. quarchpy/connection_specific/QPS/resources/QuarchIcon_128x128.png +0 -0
  533. quarchpy/connection_specific/QPS/resources/QuarchIcon_16x16.png +0 -0
  534. quarchpy/connection_specific/QPS/resources/QuarchIcon_256x256.png +0 -0
  535. quarchpy/connection_specific/QPS/resources/QuarchIcon_32x32.png +0 -0
  536. quarchpy/connection_specific/QPS/resources/QuarchIcon_64x64.png +0 -0
  537. quarchpy/connection_specific/QPS/resources/profiles/3_PHASE_PAM_AC_DEFAULT.rcf +533 -0
  538. quarchpy/connection_specific/QPS/resources/profiles/3_PHASE_PAM_AC_DEFAULT.scf +90 -0
  539. quarchpy/connection_specific/QPS/resources/profiles/3_PHASE_PAM_AC_FULL.rcf +830 -0
  540. quarchpy/connection_specific/QPS/resources/profiles/3_PHASE_PAM_AC_FULL.scf +144 -0
  541. quarchpy/connection_specific/QPS/resources/profiles/PAM_EXAMPLE_CONFIG.rcf +193 -0
  542. quarchpy/connection_specific/QPS/scriptCommands.txt +161 -22
  543. quarchpy/connection_specific/QPS/whats-new.txt +27 -0
  544. quarchpy/connection_specific/connection_QIS.py +1513 -1777
  545. quarchpy/connection_specific/connection_QPS.py +96 -11
  546. quarchpy/connection_specific/connection_ReST.py +29 -16
  547. quarchpy/connection_specific/connection_TCP.py +1 -1
  548. quarchpy/connection_specific/connection_Telnet.py +8 -2
  549. quarchpy/connection_specific/connection_USB.py +12 -13
  550. quarchpy/connection_specific/jdk_jres/__init__.py +0 -0
  551. quarchpy/connection_specific/jdk_jres/fix_permissions.py +60 -0
  552. quarchpy/connection_specific/mDNS.py +139 -0
  553. quarchpy/connection_specific/serial/rfc2217.py +2 -2
  554. quarchpy/connection_specific/serial/tools/list_ports_common.py +1 -4
  555. quarchpy/connection_specific/serial/tools/list_ports_linux.py +0 -6
  556. quarchpy/connection_specific/serial/tools/list_ports_osx.py +1 -6
  557. quarchpy/connection_specific/serial/tools/list_ports_posix.py +0 -5
  558. quarchpy/connection_specific/serial/tools/list_ports_windows.py +0 -6
  559. quarchpy/connection_specific/serial/urlhandler/protocol_alt.py +0 -4
  560. quarchpy/connection_specific/serial/urlhandler/protocol_hwgrep.py +0 -5
  561. quarchpy/connection_specific/serial/urlhandler/protocol_loop.py +1 -1
  562. quarchpy/connection_specific/serial/urlhandler/protocol_socket.py +1 -1
  563. quarchpy/connection_specific/serial/urlhandler/protocol_spy.py +0 -5
  564. quarchpy/connection_specific/usb_libs/usb1.py +4 -4
  565. quarchpy/debug/SystemTest.py +152 -41
  566. quarchpy/debug/module_debug.py +52 -38
  567. quarchpy/debug/simple_terminal.py +37 -28
  568. quarchpy/debug/upgrade_quarchpy.py +10 -14
  569. quarchpy/debug/versionCompare.py +2 -3
  570. quarchpy/device/__init__.py +10 -4
  571. quarchpy/device/device.py +1279 -402
  572. quarchpy/device/device_fixture_idn_info.py +8 -0
  573. quarchpy/device/device_idn_info.py +100 -0
  574. quarchpy/device/device_network_info.py +18 -0
  575. quarchpy/device/discovered_device.py +150 -0
  576. quarchpy/device/packet_processing.py +88 -0
  577. quarchpy/device/quarchArray.py +10 -6
  578. quarchpy/device/quarchPPM.py +395 -40
  579. quarchpy/device/quarchQPS.py +771 -294
  580. quarchpy/device/scanDevices.py +329 -230
  581. quarchpy/docs/CHANGES.rst +478 -328
  582. quarchpy/docs/_build/doctrees/CHANGES.doctree +0 -0
  583. quarchpy/docs/_build/doctrees/environment.pickle +0 -0
  584. quarchpy/docs/_build/doctrees/index.doctree +0 -0
  585. quarchpy/docs/_build/doctrees/readme.doctree +0 -0
  586. quarchpy/docs/_build/doctrees/source/changelog.doctree +0 -0
  587. quarchpy/docs/_build/doctrees/source/licenses.doctree +0 -0
  588. quarchpy/docs/_build/doctrees/source/modules.doctree +0 -0
  589. quarchpy/docs/_build/doctrees/source/quarchpy.calibration.doctree +0 -0
  590. quarchpy/docs/_build/doctrees/source/quarchpy.config_files.doctree +0 -0
  591. quarchpy/docs/_build/doctrees/source/quarchpy.connection_specific.doctree +0 -0
  592. quarchpy/docs/_build/doctrees/source/quarchpy.debug.doctree +0 -0
  593. quarchpy/docs/_build/doctrees/source/quarchpy.device.doctree +0 -0
  594. quarchpy/docs/_build/doctrees/source/quarchpy.disk_test.doctree +0 -0
  595. quarchpy/docs/_build/doctrees/source/quarchpy.doctree +0 -0
  596. quarchpy/docs/_build/doctrees/source/quarchpy.fio.doctree +0 -0
  597. quarchpy/docs/_build/doctrees/source/quarchpy.iometer.doctree +0 -0
  598. quarchpy/docs/_build/doctrees/source/quarchpy.qis.doctree +0 -0
  599. quarchpy/docs/_build/doctrees/source/quarchpy.qps.doctree +0 -0
  600. quarchpy/docs/_build/doctrees/source/quarchpy.user_interface.doctree +0 -0
  601. quarchpy/docs/_build/doctrees/source/quarchpy.utilities.doctree +0 -0
  602. quarchpy/docs/_build/doctrees/source/readme.doctree +0 -0
  603. quarchpy/docs/_build/html/.buildinfo +4 -4
  604. quarchpy/docs/_build/html/CHANGES.html +717 -484
  605. quarchpy/docs/_build/html/_sources/CHANGES.rst.txt +478 -314
  606. quarchpy/docs/_build/html/_sources/index.rst.txt +23 -23
  607. quarchpy/docs/_build/html/_sources/readme.rst.txt +41 -41
  608. quarchpy/docs/_build/html/_sources/source/modules.rst.txt +7 -7
  609. quarchpy/docs/_build/html/_sources/source/quarchpy.calibration.rst.txt +78 -78
  610. quarchpy/docs/_build/html/_sources/source/quarchpy.config_files.rst.txt +22 -22
  611. quarchpy/docs/_build/html/_sources/source/quarchpy.connection_specific.rst.txt +76 -76
  612. quarchpy/docs/_build/html/_sources/source/quarchpy.debug.rst.txt +38 -38
  613. quarchpy/docs/_build/html/_sources/source/quarchpy.device.rst.txt +54 -54
  614. quarchpy/docs/_build/html/_sources/source/quarchpy.disk_test.rst.txt +126 -126
  615. quarchpy/docs/_build/html/_sources/source/quarchpy.fio.rst.txt +30 -30
  616. quarchpy/docs/_build/html/_sources/source/quarchpy.iometer.rst.txt +22 -22
  617. quarchpy/docs/_build/html/_sources/source/quarchpy.qis.rst.txt +22 -22
  618. quarchpy/docs/_build/html/_sources/source/quarchpy.qps.rst.txt +22 -22
  619. quarchpy/docs/_build/html/_sources/source/quarchpy.rst.txt +50 -50
  620. quarchpy/docs/_build/html/_sources/source/quarchpy.user_interface.rst.txt +22 -22
  621. quarchpy/docs/_build/html/_sources/source/quarchpy.utilities.rst.txt +22 -22
  622. quarchpy/docs/_build/html/_static/alabaster.css +662 -700
  623. quarchpy/docs/_build/html/_static/basic.css +905 -904
  624. quarchpy/docs/_build/html/_static/doctools.js +106 -280
  625. quarchpy/docs/_build/html/_static/documentation_options.js +12 -11
  626. quarchpy/docs/_build/html/_static/language_data.js +192 -297
  627. quarchpy/docs/_build/html/_static/pygments.css +84 -82
  628. quarchpy/docs/_build/html/_static/searchtools.js +510 -404
  629. quarchpy/docs/_build/html/_static/sphinx_highlight.js +154 -0
  630. quarchpy/docs/_build/html/genindex.html +1876 -1430
  631. quarchpy/docs/_build/html/index.html +223 -188
  632. quarchpy/docs/_build/html/objects.inv +0 -0
  633. quarchpy/docs/_build/html/py-modindex.html +300 -306
  634. quarchpy/docs/_build/html/readme.html +137 -137
  635. quarchpy/docs/_build/html/search.html +123 -125
  636. quarchpy/docs/_build/html/searchindex.js +1 -1
  637. quarchpy/docs/_build/html/source/changelog.html +805 -537
  638. quarchpy/docs/_build/html/source/licenses.html +181 -181
  639. quarchpy/docs/_build/html/source/modules.html +222 -214
  640. quarchpy/docs/_build/html/source/quarchpy.calibration.html +147 -147
  641. quarchpy/docs/_build/html/source/quarchpy.config_files.html +136 -136
  642. quarchpy/docs/_build/html/source/quarchpy.connection_specific.html +1072 -615
  643. quarchpy/docs/_build/html/source/quarchpy.debug.html +241 -247
  644. quarchpy/docs/_build/html/source/quarchpy.device.html +4087 -1024
  645. quarchpy/docs/_build/html/source/quarchpy.disk_test.html +220 -220
  646. quarchpy/docs/_build/html/source/quarchpy.fio.html +218 -164
  647. quarchpy/docs/_build/html/source/quarchpy.html +823 -250
  648. quarchpy/docs/_build/html/source/quarchpy.iometer.html +271 -184
  649. quarchpy/docs/_build/html/source/quarchpy.qis.html +985 -249
  650. quarchpy/docs/_build/html/source/quarchpy.qps.html +186 -213
  651. quarchpy/docs/_build/html/source/quarchpy.user_interface.html +278 -319
  652. quarchpy/docs/_build/html/source/quarchpy.utilities.html +228 -211
  653. quarchpy/docs/_build/html/source/readme.html +147 -147
  654. quarchpy/docs/conf.py +56 -56
  655. quarchpy/docs/index.rst +23 -23
  656. quarchpy/docs/make.bat +35 -35
  657. quarchpy/docs/readme.rst +41 -41
  658. quarchpy/docs/source/modules.rst +7 -7
  659. quarchpy/docs/source/quarchpy.calibration.rst +78 -78
  660. quarchpy/docs/source/quarchpy.config_files.rst +22 -22
  661. quarchpy/docs/source/quarchpy.connection_specific.rst +76 -76
  662. quarchpy/docs/source/quarchpy.debug.rst +38 -38
  663. quarchpy/docs/source/quarchpy.device.rst +54 -54
  664. quarchpy/docs/source/quarchpy.disk_test.rst +126 -126
  665. quarchpy/docs/source/quarchpy.fio.rst +30 -30
  666. quarchpy/docs/source/quarchpy.iometer.rst +22 -22
  667. quarchpy/docs/source/quarchpy.qis.rst +22 -22
  668. quarchpy/docs/source/quarchpy.qps.rst +22 -22
  669. quarchpy/docs/source/quarchpy.rst +50 -50
  670. quarchpy/docs/source/quarchpy.user_interface.rst +22 -22
  671. quarchpy/docs/source/quarchpy.utilities.rst +22 -22
  672. quarchpy/fio/FIO_interface.py +258 -9
  673. quarchpy/fio/{test_performance_class.py → HIDEtest_performance_class.py} +533 -533
  674. quarchpy/fio/fioDiskFinder.py +1 -1
  675. quarchpy/fio/performanceClass.py +5 -4
  676. quarchpy/install_qps.py +369 -0
  677. quarchpy/qis/StreamHeaderInfo.py +5 -4
  678. quarchpy/qis/qisFuncs.py +234 -96
  679. quarchpy/qps/__init__.py +2 -2
  680. quarchpy/qps/qpsFuncs.py +238 -139
  681. quarchpy/run.py +103 -56
  682. quarchpy/user_interface/user_interface.py +201 -158
  683. quarchpy/utilities/TestCenter.py +64 -45
  684. quarchpy/utilities/TimeValue.py +4 -3
  685. quarchpy/utilities/Version.py +50 -0
  686. {quarchpy-2.1.11.dev4.dist-info → quarchpy-2.2.17.dev1.dist-info}/METADATA +174 -10
  687. quarchpy-2.2.17.dev1.dist-info/RECORD +763 -0
  688. {quarchpy-2.1.11.dev4.dist-info → quarchpy-2.2.17.dev1.dist-info}/WHEEL +1 -2
  689. quarchpy/.idea/.gitignore +0 -3
  690. quarchpy/.idea/inspectionProfiles/profiles_settings.xml +0 -6
  691. quarchpy/.idea/misc.xml +0 -4
  692. quarchpy/.idea/modules.xml +0 -8
  693. quarchpy/.idea/quarchpy.iml +0 -12
  694. quarchpy/.idea/workspace.xml +0 -146
  695. quarchpy/connection_specific/QPS/License/LGPL.txt +0 -167
  696. quarchpy/connection_specific/QPS/License/Material-Icons.txt +0 -1
  697. quarchpy/connection_specific/QPS/License/NOTICE.txt +0 -143
  698. quarchpy/connection_specific/QPS/License/Netty-license.txt +0 -143
  699. quarchpy/connection_specific/QPS/License/controlsfx-license.txt +0 -26
  700. quarchpy/connection_specific/QPS/License/usb4java-license.txt +0 -167
  701. quarchpy/connection_specific/QPS/qis/License/LGPL.txt +0 -167
  702. quarchpy/connection_specific/QPS/qis/License/NOTICE.txt +0 -143
  703. quarchpy/connection_specific/QPS/qis/qis_lib/CInterface-1.4.jar +0 -0
  704. quarchpy/connection_specific/QPS/qis/qis_lib/CInterface-1.5.01.jar +0 -0
  705. quarchpy/connection_specific/QPS/qis/qis_lib/CInterface-1.5.jar +0 -0
  706. quarchpy/connection_specific/QPS/qis/qis_lib/CInterface-1.6.1.jar +0 -0
  707. quarchpy/connection_specific/QPS/qis/qis_lib/CInterface-1.6.jar +0 -0
  708. quarchpy/connection_specific/QPS/qis/qis_lib/CInterface-1.7.jar +0 -0
  709. quarchpy/connection_specific/QPS/qis/qis_lib/QuarchCommon-0.2.3.jar +0 -0
  710. quarchpy/connection_specific/QPS/qis/qis_lib/QuarchCommon-0.2.4.jar +0 -0
  711. quarchpy/connection_specific/QPS/qis/qis_lib/commons-lang3-3.2.1.jar +0 -0
  712. quarchpy/connection_specific/QPS/qis/qis_lib/libusb4java-1.3.0-darwin-x86-64.jar +0 -0
  713. quarchpy/connection_specific/QPS/qis/qis_lib/libusb4java-1.3.0-linux-aarch64.jar +0 -0
  714. quarchpy/connection_specific/QPS/qis/qis_lib/libusb4java-1.3.0-linux-arm.jar +0 -0
  715. quarchpy/connection_specific/QPS/qis/qis_lib/libusb4java-1.3.0-linux-x86-64.jar +0 -0
  716. quarchpy/connection_specific/QPS/qis/qis_lib/libusb4java-1.3.0-linux-x86.jar +0 -0
  717. quarchpy/connection_specific/QPS/qis/qis_lib/libusb4java-1.3.0-win32-x86-64.jar +0 -0
  718. quarchpy/connection_specific/QPS/qis/qis_lib/libusb4java-1.3.0-win32-x86.jar +0 -0
  719. quarchpy/connection_specific/QPS/qis/qis_lib/netty-all-4.1.43.Final.jar +0 -0
  720. quarchpy/connection_specific/QPS/qis/qis_lib/usb4java-1.3.0.jar +0 -0
  721. quarchpy/connection_specific/QPS/qps.bat +0 -2
  722. quarchpy/connection_specific/QPS/qps.sh +0 -2
  723. quarchpy/connection_specific/QPS/qps_lib/QuarchCommon-0.2.2.jar +0 -0
  724. quarchpy/connection_specific/QPS/qps_lib/QuarchCommon-0.2.3.jar +0 -0
  725. quarchpy/connection_specific/QPS/qps_lib/QuarchCommon-0.2.4.jar +0 -0
  726. quarchpy/connection_specific/QPS/qps_lib/controlsfx-8.40.13.jar +0 -0
  727. quarchpy/connection_specific/QPS/qps_lib/controlsfx-8.40.14.jar +0 -0
  728. quarchpy/connection_specific/QPS/qps_lib/controlsfx-samples-8.40.13.jar +0 -0
  729. quarchpy/connection_specific/QPS/qps_lib/fxsampler-1.0.10.jar +0 -0
  730. quarchpy/connection_specific/QPS/qps_lib/jfxtras-labs-8.0-r6-SNAPSHOT.jar +0 -0
  731. quarchpy/connection_specific/QPS/qps_lib/jfxtras-labs-8.0-r6.jar +0 -0
  732. quarchpy/connection_specific/QPS/qps_lib/netty-all-4.0.37.Final.jar +0 -0
  733. quarchpy/connection_specific/QPS/qps_lib/netty-all-4.1.22.Final.jar +0 -0
  734. quarchpy/connection_specific/QPS/qps_lib/netty-all-4.1.22.Final_2.jar +0 -0
  735. quarchpy/connection_specific/QPS/qps_lib/netty-all-4.1.43.Final.jar +0 -0
  736. quarchpy/connection_specific/QPS/qps_lib/org.eclipse.fx.ide.css.jfx8_1.2.0.201501301049.jar +0 -0
  737. quarchpy/connection_specific/QPS/qps_lib/org.eclipse.fx.ide.css.jfx8_2.4.0.201605112122.jar +0 -0
  738. quarchpy/debug/quarchpy - Shortcut.lnk +0 -0
  739. quarchpy/device/deleteme.py +0 -100
  740. quarchpy-2.1.11.dev4.dist-info/RECORD +0 -489
  741. /quarchpy/connection_specific/QPS/{License → 3rdPartyLicenses}/Material-Icons-license.txt +0 -0
  742. /quarchpy/connection_specific/QPS/DeviceConfig/{QTL1995-02.XML → QTL1995-02.xml} +0 -0
  743. /quarchpy/connection_specific/QPS/DeviceConfig/{QTL1999-02.XML → QTL1999-02.xml} +0 -0
  744. /quarchpy/connection_specific/QPS/DeviceConfig/{QTL2312-01.XML → QTL2312-01.xml} +0 -0
  745. {quarchpy-2.1.11.dev4.dist-info → quarchpy-2.2.17.dev1.dist-info}/top_level.txt +0 -0
quarchpy/device/device.py CHANGED
@@ -1,491 +1,1368 @@
1
- import time, sys, os ,logging
2
-
3
- from quarchpy.connection import QISConnection, PYConnection, QPSConnection
4
- from quarchpy import user_interface
1
+ from __future__ import annotations
2
+ from typing import Optional, Tuple, Any, Union # Added for type hinting in docstrings
3
+ import logging
4
+ logger = logging.getLogger(__name__)
5
+ import os
5
6
  import re
7
+ import sys
8
+ import time
6
9
 
10
+ from quarchpy.qps import isQpsRunning
11
+ from quarchpy.qis import isQisRunning
12
+
13
+ from quarchpy.connection import QISConnection, PYConnection, QPSConnection
14
+ # Check Python version and set timeout exception
15
+ if sys.version_info.major == 2:
16
+ try:
17
+ import socket
18
+
19
+ timeout_exception = socket.timeout
20
+ except AttributeError as e:
21
+ timeout_exception = None
22
+ logger.error(f"Socket timeout unavailable: {e}")
23
+ else:
24
+ timeout_exception = TimeoutError # Python 3: Use built-in TimeoutError
25
+
26
+ # --- Main Device Class ---
7
27
  class quarchDevice:
8
28
  """
9
- Allows control over a Quarch device, over a wide range of underlying connection methods. This is the core class
10
- used for control of all Quarch products.
11
-
29
+ Allows control over a Quarch device, over a wide range of underlying
30
+ connection methods. This is the core class used for control of all
31
+ Quarch products.
32
+
33
+ Attributes:
34
+ ConString (str): The potentially modified connection string used.
35
+ ConType (str): The specified connection type ('PY', 'QIS', 'QPS').
36
+ timeout (int): The communication timeout in seconds.
37
+ connectionObj (Optional[QISConnection, QPSConnection, PYConnection]): The underlying connection
38
+ object (e.g., PYConnection, QISConnection instance). None if connection failed or is closed.
39
+ ConCommsType (Optional[str]): The actual communication type determined
40
+ by the connection object (e.g., 'USB', 'TCP'). Set for PY type.
41
+ connectionName (Optional[str]): The target identifier determined by the
42
+ connection object (e.g., 'QTL1234-01-001', '192.168.1.100'). Set for PY type.
43
+ connectionTypeName (Optional[str]): Alias for ConCommsType. Set for PY type.
12
44
  """
13
45
 
14
- def __init__(self, ConString, ConType="PY", timeout="5"):
15
- """
16
- Constructor for quarchDevice, allowing the connection method of the device to be specified.
17
-
18
- Parameters
19
- ----------
20
- ConString : str
21
-
22
- Connection string, specifying the underlying connection type and module identifier. The underlying
23
- connection must be supported both by the connection type and the target module.
24
-
25
- Example:
26
- USB:QTL1743 - USB connection with given part number
27
- USB:QTL1743-03-015 - USB connection with fully qualified serial number
28
- SERIAL:COM4 - Serial connection with COM port (ttyS0 for linux)
29
- TCP:192.168.1.55 - LAN(TCP) connection to IP address
30
- TELNET:QTL1079-03-004 - LAN(TELNET) connection to netBIOS name (must resolve to IP address)
31
- REST:192.168.1.60 - LAN(REST) connection to IP address
32
-
33
- ConType : {'PY', 'QIS', 'QPS'}
34
-
35
- Specifies the software type which runs the connection:
36
- PY - (Default) Connection is run via pure Python code
37
-
38
- QIS - Power modules only, connection run via QIS (Quarch Instrument Server) for easy power capture in raw formats.
39
- Serial is not supported. IP and port can be specified to connect to a QIS instance running at another location "QIS:192.168.1.100:9722"
40
-
41
- QPS - Power modules only, connection run via QPS (Quarch Power Studio) for automated power capture and analysis within thr QPS graphical environment.
42
- Serial is not supported. IP and port can be specified to connect to a QPS instance running at another location "QPS:192.168.1.100:9822"
43
-
44
- timeout : str, optional
45
-
46
- Timeout in seconds for the device to respond.
47
-
48
- """
49
-
46
+ def __init__(self, ConString: str, ConType: str = "PY", timeout: str = "5", host=None, port=None):
47
+ """
48
+ Initializes the quarchDevice, establishes the connection.
49
+
50
+ Performs initial parameter validation, determines the connection type,
51
+ delegates to specific helper methods to create the underlying connection
52
+ object (PYConnection, QISConnection, or QPSConnection), and verifies
53
+ the connection.
54
+
55
+ Args:
56
+ ConString (str): The connection string (e.g., "USB:ID", "TCP:IP", "QIS:ID").
57
+ ConType (str, optional): The connection mode ('PY', 'QIS', 'QPS'). Defaults to "PY".
58
+ timeout (str, optional): Communication timeout in seconds. Defaults to "5".
59
+
60
+ Raises:
61
+ ValueError: If ConString format is invalid or timeout is not numeric.
62
+ ConnectionError: If establishing the connection fails.
63
+ TimeoutError: If verifying the device on QIS/QPS times out.
64
+ ImportError: If required underlying connection classes are missing.
65
+ """
66
+ # --- Initial setup and validation ---
67
+ # Initialize all instance attributes first
68
+ self.ConType = ""
69
+ self.ConString = ""
70
+ self.connectionTypeName = None
71
+ self.connectionName = None
72
+ self.ConCommsType = None
73
+ self.connectionObj = None
74
+ self.timeout = 5 # Default int timeout
75
+ self.is_module_resetting = False
76
+
77
+ # Call helper to store and validate parameters
78
+ self._store_and_validate_params(ConString, ConType, timeout)
79
+
80
+ logger.debug(f"Initializing quarchDevice with ConString='{self.ConString}', ConType='{self.ConType}', Timeout='{self.timeout}'")
81
+ con_type_upper = self.ConType.upper()
82
+
83
+ # --- Delegate to specific initialization method ---
84
+ if con_type_upper == "PY":
85
+ self._initialize_py_connection()
86
+ elif con_type_upper.startswith("QIS"):
87
+ self._initialize_qis_connection()
88
+ elif con_type_upper.startswith("QPS"):
89
+ self._initialize_qps_connection()
90
+ else:
91
+ # Invalid ConType should have been caught by check_module_format
92
+ raise ValueError(f"Invalid connection type '{self.ConType}'.")
93
+
94
+ # --- Final connection verification ---
95
+ self._verify_connection_object()
96
+ logger.info(f"Connection successful: Type='{self.ConType}', Target='{getattr(self.connectionObj, 'ConnTarget', 'Unknown')}'")
97
+
98
+ # --- Private Helper Methods ---
99
+
100
+ def _store_and_validate_params(self, ConString: str, ConType: str, timeout: str):
101
+ """
102
+ Stores initial parameters and performs basic validation.
103
+
104
+ Sets self.ConString (with lowercasing rule), self.ConType,
105
+ validates and sets self.timeout (as int), and calls
106
+ check_module_format to validate ConString format.
107
+
108
+ Args:
109
+ ConString (str): The raw connection string.
110
+ ConType (str): The raw connection type.
111
+ timeout (str): The raw timeout value.
112
+
113
+ Raises:
114
+ ValueError: If timeout is non-numeric or ConString format is invalid.
115
+ """
50
116
  self.ConString = ConString
117
+ # Lowercase unless serial
51
118
  if "serial" not in ConString.lower():
52
119
  self.ConString = ConString.lower()
53
- self.ConType = ConType
120
+ self.ConType = ConType
121
+ self.connectionObj = None # Ensure it's reset here
122
+ self.timeout = int(timeout)
54
123
 
55
- try:
56
- self.timeout = int(timeout)
57
- except:
58
- raise Exception("Invalid value for timeout, must be a numeric value")
124
+ # Use the globally defined check_module_format function
125
+ if not check_module_format(self.ConString):
126
+ raise ValueError(f"Module format is invalid for connection string: '{self.ConString}'")
127
+
128
+ def _initialize_py_connection(self):
129
+ """
130
+ Initializes the connection using the PY (Pure Python) method.
59
131
 
60
- if checkModuleFormat(self.ConString) == False:
61
- raise Exception("Module format is invalid!")
132
+ Handles colon formatting, resolves target using get_connection_target if
133
+ applicable, creates the PYConnection object, stores connection details,
134
+ and verifies communication with a '*tst?' command.
62
135
 
63
- # Initializes the object as a python or QIS connection
64
- ## Python
65
- if self.ConType.upper() == "PY":
136
+ Sets:
137
+ self.connectionObj, self.ConCommsType, self.connectionName,
138
+ self.connectionTypeName, self.ConString (potentially updated).
66
139
 
67
- # replacing colons
68
- numb_colons = self.ConString.count(":")
69
- if numb_colons == 2:
70
- self.ConString = self.ConString.replace('::', ':')
140
+ Raises:
141
+ ConnectionError: If connection fails or device doesn't respond correctly.
142
+ ImportError: If PYConnection class is missing.
143
+ """
144
+ logger.debug("Attempting PY connection...")
145
+ # Handle potential double colons
146
+ numb_colons = self.ConString.count(":")
147
+ if numb_colons == 2:
148
+ logger.debug("Replacing '::' with ':' in ConString for PY connection.")
149
+ self.ConString = self.ConString.replace('::', ':')
71
150
 
72
- if self.ConString.lower().find("qtl") != -1 and self.ConString.lower().find("usb") ==-1:
73
- from .scanDevices import get_connection_target
74
- self.ConString = get_connection_target(self.ConString)
151
+ # Resolve target if needed
152
+ self._resolve_py_target()
75
153
 
76
- # Create the connection object
154
+ # Create PYConnection object
155
+ try:
156
+ # Store PYConnection object
77
157
  self.connectionObj = PYConnection(self.ConString)
78
- self.ConCommsType = self.connectionObj.ConnTypeStr
158
+ # Store connection details from the object
159
+ self.ConCommsType = getattr(self.connectionObj, 'ConnTypeStr', None)
160
+ self.connectionName = getattr(self.connectionObj, 'ConnTarget', None)
161
+ self.connectionTypeName = self.ConCommsType # Alias
162
+ logger.debug(f"PY Connection details: Type='{self.connectionTypeName}', Target='{self.connectionName}'")
163
+ except Exception as e_pyconn:
164
+ logger.error(f"Failed to create PYConnection for '{self.ConString}': {e_pyconn}", exc_info=True)
165
+ raise ConnectionError(f"Failed to establish PY connection for '{self.ConString}'") from e_pyconn
166
+
167
+ # Verify communication with *tst?
168
+ self._test_py_connection()
169
+
170
+ def _resolve_py_target(self):
171
+ """
172
+ Attempts to resolve ConString target if needed for PY connections.
79
173
 
80
- # Exposes the connection type and module for later use.
81
- self.connectionName = self.connectionObj.ConnTarget
82
- self.connectionTypeName = self.connectionObj.ConnTypeStr
174
+ If the ConString looks like a QTL identifier (contains 'qtl') but is
175
+ not explicitly USB, it calls the external `get_connection_target`
176
+ function to find the best actual connection string (e.g., a specific
177
+ COM port or IP address) and updates `self.ConString` if found.
83
178
 
84
- time.sleep(0.1)
85
- item = None
86
- item = self.connectionObj.connection.sendCommand("*tst?")
87
- if "OK" in item:
88
- pass
89
- elif "FAIL" in item:
90
- pass
91
- elif item is not None:
92
- pass
179
+ Uses:
180
+ self.ConString
181
+ get_connection_target (imported function)
182
+
183
+ Modifies:
184
+ self.ConString (if target is resolved)
185
+ """
186
+ # Check conditions: contains 'qtl', not 'usb', and helper function exists
187
+ if "qtl" in self.ConString.lower() and "usb" not in self.ConString.lower():
188
+ from quarchpy.device import get_connection_target
189
+ if get_connection_target is not None:
190
+ try:
191
+ logger.debug(f"Attempting to resolve connection target for '{self.ConString}'...")
192
+ resolved_con_string = get_connection_target(self.ConString)
193
+ if resolved_con_string and "Fail" not in resolved_con_string: # Check for failure string
194
+ logger.debug(f"Resolved '{self.ConString}' to '{resolved_con_string}'")
195
+ self.ConString = resolved_con_string # Update if successful
196
+ else:
197
+ logger.warning(f"get_connection_target failed or returned empty for '{self.ConString}'. Using original.")
198
+ except Exception as e_scan:
199
+ # Log error but continue with original ConString
200
+ logger.error(f"Error calling get_connection_target: {e_scan}. Using original ConString.")
93
201
  else:
94
- raise Exception("No module responded to *tst? command!")
95
- time.sleep(0.1)
202
+ # Log if resolution needed but helper unavailable
203
+ logger.warning("get_connection_target function not available, cannot resolve connection string.")
204
+
205
+ def _test_py_connection(self):
206
+ """
207
+ Sends '*tst?' command to verify communication for PY connections.
208
+
209
+ Checks if the response contains "OK" or "FAIL".
210
+ Closes connection and raises ConnectionError
211
+ if the test fails or times out.
96
212
 
97
- ## QIS
98
- # ConType may be QIS only or QIS:ip:port [:3] checks if the first 3 letters are QIS.
99
- elif self.ConType[:3].upper() == "QIS":
100
- # If host and port are specified.
213
+ Raises:
214
+ ConnectionError: If the command fails or the response is invalid.
215
+ """
216
+ try:
217
+ # Use snake_case internally
218
+ item = self.send_command("*tst?")
219
+ except Exception as e_tst:
220
+ logger.warning(f"Error sending *tst? during init: {e_tst}")
221
+ # Raise a more specific error indicating communication failure
222
+ raise ConnectionError("Module failed to respond to *tst? command during initialization.") from e_tst
223
+
224
+ # Check if response indicates basic communication success
225
+ response_ok = item is not None and ("OK" in item or "FAIL" in item)
226
+ if not response_ok:
227
+ logger.error(f"No valid module response to *tst? command! Received: '{item}'")
101
228
  try:
102
- # Extract QIS, host and port.
103
- QIS, host, port = self.ConType.split(':')
104
- # QIS port should be an int.
105
- port = int(port)
106
- # If host and port are not specified.
107
- except:
108
- host = '127.0.0.1'
109
- port = 9722
110
-
111
- numb_colons = self.ConString.count(":")
112
- if numb_colons == 1:
113
- self.ConString = self.ConString.replace(':', '::')
114
-
115
- # Creates the connection object.
116
- self.connectionObj = QISConnection(self.ConString, host, port)
229
+ self.close_connection()
230
+ except Exception as close_err:
231
+ logger.error(f"Error closing connection after *tst? failure: {close_err}")
232
+ # Raise error indicating failed test
233
+ raise ConnectionError(f"No valid module response to *tst? command! Received: '{item}'")
234
+ logger.debug("*tst? check successful.")
235
+
236
+ def _parse_server_details(self, default_port: int) -> Tuple[str, int]:
237
+ """
238
+ Parses host and port from self.ConType for QIS/QPS connection types.
239
+
240
+ Expects self.ConType to be like "QIS" or "QIS:host:port".
241
+ Returns defaults ('127.0.0.1', default_port) if parsing fails or is not applicable.
242
+
243
+ Args:
244
+ default_port (int): The default port number for the server type (QIS/QPS).
245
+
246
+ Returns:
247
+ tuple[str, int]: A tuple containing the host (str) and port (int).
248
+ """
249
+ host = '127.0.0.1'
250
+ port = default_port
251
+ con_type_upper = self.ConType.upper()
252
+ # Determine prefix based on actual ConType start
253
+ prefix = "QIS" if con_type_upper.startswith("QIS") else "QPS" if con_type_upper.startswith("QPS") else None
117
254
 
118
- list = self.connectionObj.qis.getDeviceList()
119
- list_str = "".join(list).lower()
120
-
121
- timeout = time.time() + int(timeout) # now + n seconds
122
-
123
- # check for device in list, has a timeout
124
- while time.time() < timeout:
125
-
126
- # Check if it's a module's QTL number
127
- if "qtl" not in self.ConString.lower():
128
-
129
- # If not, check if it contains a valid IP address format
130
- ip_address = re.search(r"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}", self.ConString)
131
- if not ip_address:
132
- raise ValueError(f"ConString {self.ConString} does not contain a valid QTL number or IP address")
133
-
134
- # Attempt to get QTL number from qis "$list details"
135
- temp_str = _check_ip_in_qis_list(ip_address.group(), self.connectionObj.qis.get_list_details())
136
- if temp_str:
137
- # If found
138
- self.ConString = temp_str
139
- break
140
-
141
- logging.debug("Did not find ip address in list details, attempt targetted qis scan")
142
-
143
- # If it's not present in the list already, then try scanning for it via qis
144
- # Scan is purposefully after initial check! 09/03/2023
145
- # Valid response example "Located device: 192.168.1.3"
146
- if "located" in str(self.connectionObj.qis.scanIP(self.ConString)).lower():
147
- # Note - Qis takes a moment or 2 to add this newly located device to the $list 21/03/23
148
- timeout += 20 # Extend the timeout as the drive was located
149
-
150
- while time.time() < timeout:
151
- # try find the new device again from ipaddress
152
- temp_str = _check_ip_in_qis_list(ip_address.group(), self.connectionObj.qis.get_list_details())
153
- if temp_str:
154
- # If the item is found, break out of this loop
155
- self.ConString = temp_str
156
- break
157
- time.sleep(1) # Slow down the poll
158
- else:
159
- # if it's not found, continue and allow program to timeout
160
- continue
161
- # Break out of both loops
162
- break
163
-
164
- elif str(self.ConString).lower() in str(list_str).lower():
165
- # If we have QTL device, and it's in list, nothing more needs done.
255
+ if prefix:
256
+ try:
257
+ # Attempt to split ConType string like "QIS:host:port"
258
+ _, host_parsed, port_str = self.ConType.split(':')
259
+ port = int(port_str) # Convert port part to integer
260
+ host = host_parsed # Use parsed host
261
+ except ValueError:
262
+ # Handles cases where split fails (not 3 parts) or int conversion fails
263
+ # Only log warning if it looked like host/port were provided but were invalid
264
+ if con_type_upper != prefix:
265
+ logger.warning(f"Could not parse host/port from ConType '{self.ConType}', using defaults {host}:{port}.")
266
+ except Exception as e_parse:
267
+ # Catch any other unexpected parsing errors
268
+ logger.warning(f"Error parsing ConType '{self.ConType}': {e_parse}. Using defaults {host}:{port}.")
269
+ return host, port
270
+
271
+ def _prepare_server_con_string(self):
272
+ """
273
+ Formats self.ConString by replacing single ':' with '::' if needed.
274
+
275
+ This is sometimes required for QIS/QPS connection libraries when only
276
+ one colon is present in the identifier part (e.g., "TCP:ID" becomes "TCP::ID").
277
+
278
+ Modifies:
279
+ self.ConString
280
+ """
281
+ numb_colons = self.ConString.count(":")
282
+ # Apply replacement only if exactly one colon exists
283
+ if numb_colons == 1:
284
+ logger.debug(f"Replacing single colon ':' with '::' in ConString '{self.ConString}' for server connection.")
285
+ self.ConString = self.ConString.replace(':', '::')
286
+
287
+ def _verify_server_device(self, server_conn_obj: Any, server_type: str):
288
+ """
289
+ Finds and verifies the target device on a QIS or QPS server.
290
+
291
+ Repeatedly checks the server's device list for the target device
292
+ (self.ConString), handling identification by QTL number or IP address.
293
+ If identified by IP, resolves it to the device's actual connection string
294
+ (e.g., "TYPE::QTL...") using _check_ip_in_qis_list. May trigger a
295
+ network scan via the server connection object's scanIP method if needed.
296
+
297
+ Args:
298
+ server_conn_obj (Any): The specific QIS/QPS connection object
299
+ (e.g., self.connectionObj.qis). Type hinted as Any
300
+ as the exact type depends on the imported library.
301
+ server_type (str): "QIS" or "QPS" for logging/error messages.
302
+
303
+ Returns:
304
+ bool: True if the device was successfully found and verified.
305
+ `self.ConString` may be updated as a side effect if resolved via IP.
306
+
307
+ Raises:
308
+ ValueError: If ConString is IP-based but contains no valid IP.
309
+ TimeoutError: If the device cannot be found/verified within self.timeout.
310
+ Exception: Propagates exceptions from server_conn_obj methods.
311
+ """
312
+ # --- Initialization ---
313
+ logger.debug(f"Verifying device '{self.ConString}' on {server_type} server...")
314
+ list_details = None
315
+ list_str_lower = None
316
+ found = False
317
+ connect_timeout = time.time() + self.timeout # Calculate deadline
318
+
319
+ # --- Main Verification Loop ---
320
+ while time.time() < connect_timeout:
321
+ # --- Get current list details ---
322
+ try:
323
+ list_details = server_conn_obj.get_list_details() # Assumes method exists
324
+ list_str_lower = "".join(list_details).lower()
325
+ except Exception as e_list:
326
+ logger.warning(f"Failed to refresh {server_type} list details during check: {e_list}")
327
+ if time.time() >= connect_timeout:
166
328
  break
167
- else:
168
- time.sleep(1)
169
- list = self.connectionObj.qis.getDeviceList()
170
- list_str = "".join(list).lower()
329
+ time.sleep(1) # Wait before retrying list fetch
330
+ continue # Skip rest of loop iteration
331
+
332
+ # --- Determine target type (IP or QTL) ---
333
+ target_lower = self.ConString.lower()
334
+
335
+ if "qtl" not in target_lower:
336
+ # --- Target is likely IP Address ---
337
+ ip_match = re.search(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", target_lower)
338
+ if not ip_match:
339
+ raise ValueError(f"ConString '{self.ConString}' has no QTL and no valid IP for {server_type}.")
340
+ target_ip = ip_match.group()
341
+
342
+ # Call helper to find by IP (handles list check, scan, re-check)
343
+ resolved_string = self._find_device_by_ip(server_conn_obj, server_type, list_details, target_ip)
344
+ if resolved_string:
345
+ # Side effect: self.ConString was updated in helper
346
+ found = True
347
+ break # Exit main loop
348
+ # If _find_device_by_ip returns None, IP wasn't found in this iteration/scan attempt
171
349
  else:
172
- # If we didn't hit a 'break' condition in the above loop, then it timed out
173
- raise TimeoutError(f"Could not find module '{self.ConString}' from Qis within specified time")
350
+ # --- Target is QTL Number ---
351
+ if self._find_device_by_qtl(list_str_lower, target_lower):
352
+ found = True # Found via QTL
353
+ break # Exit main loop
354
+
355
+ # --- Not found yet, wait before next iteration ---
356
+ if time.time() >= connect_timeout:
357
+ break # Exit loop if timeout reached before sleeping
358
+ logger.debug(f"Target '{self.ConString}' not found in {server_type} list yet. Waiting 1s before retry...")
359
+ time.sleep(1)
360
+
361
+ # --- Loop Finished: Final Check ---
362
+ if not found:
363
+ logger.error(f"Timeout: Could not find/verify module '{self.ConString}' in {server_type} within {self.timeout}s.")
364
+ raise TimeoutError(f"Could not find module '{self.ConString}' in {server_type} within {self.timeout}s")
365
+
366
+ logger.info(f"Successfully verified device '{self.ConString}' in {server_type}.")
367
+ return True # Indicate success
368
+
369
+ def _find_device_by_ip(self, server_conn_obj, server_type, list_details, target_ip):
370
+ """
371
+ Attempts to find the device via IP, potentially resolving it and scanning.
174
372
 
175
- self.connectionObj.qis.sendAndReceiveCmd(cmd="$default " + self.ConString)
373
+ Checks the provided list, then optionally scans if not found and re-checks.
374
+ Updates self.ConString if resolved via IP lookup.
176
375
 
177
- ## QPS
178
- elif self.ConType[:3].upper() == "QPS":
179
- try:
180
- # Extract QIS, host and port.
181
- QIS, host, port = self.ConType.split(':')
182
- # QIS port should be an int.
183
- port = int(port)
184
- # If host and port are not specified.
185
- except:
186
- host = '127.0.0.1'
187
- port = 9822
188
-
189
- numb_colons = self.ConString.count(":")
190
- if numb_colons == 1:
191
- self.ConString = self.ConString.replace(':', '::')
376
+ Args:
377
+ server_conn_obj: The specific QIS/QPS connection object (e.g., self.connectionObj.qis).
378
+ server_type (str): "QIS" or "QPS" for logging/error messages.
379
+ list_details (list): The current list details from the server.
380
+ target_ip (str): The IP address being searched for.
381
+
382
+ Returns:
383
+ str: The resolved ConString if found (and self.ConString is updated).
384
+ None: If not found via IP lookup or scan within this attempt.
385
+
386
+ Raises:
387
+ Exceptions from underlying scanIP or get_list_details calls.
388
+ """
389
+ # 1. Check current list details for the IP
390
+ resolved_con_string = _check_ip_in_qis_list(target_ip, list_details)
391
+ if resolved_con_string:
392
+ logger.info(f"Resolved IP {target_ip} to '{resolved_con_string}' from {server_type} list.")
393
+ self.ConString = resolved_con_string # Update instance ConString
394
+ return resolved_con_string # Return resolved string
395
+
396
+ # 2. IP not in list, attempt network scan if possible
397
+ logger.debug(f"IP {target_ip} not in {server_type} list, attempting network scan...")
398
+ try:
399
+ scan_method = getattr(server_conn_obj, 'scanIP', None)
400
+ if not scan_method:
401
+ logger.warning(f"scanIP method not found on {server_type} connection object.")
402
+ return None # Cannot scan
403
+
404
+ scan_response = scan_method(target_ip) # Scan using the target IP
405
+ if "located" not in str(scan_response).lower():
406
+ logger.debug(f"{server_type} scan for {target_ip} did not locate the device.")
407
+ return None # Scan didn't find it
408
+
409
+ # 3. Scan located the device, now re-check the list after a delay
410
+ logger.info(f"{server_type} located {target_ip} via scan. Re-checking list after delay...")
411
+ # Use a shorter, fixed timeout for this re-check phase
412
+ scan_recheck_timeout = time.time() + 20 # Allow 20s for list update
413
+ time.sleep(2) # Initial pause
414
+
415
+ while time.time() < scan_recheck_timeout:
416
+ current_list_details = server_conn_obj.get_list_details() # Re-fetch
417
+ resolved_con_string = _check_ip_in_qis_list(target_ip, current_list_details)
418
+ if resolved_con_string:
419
+ logger.info(f"Resolved IP {target_ip} to '{resolved_con_string}' after scan.")
420
+ self.ConString = resolved_con_string # Update instance ConString
421
+ return resolved_con_string # Return resolved string
422
+ # If not found yet, wait before checking again
423
+ if time.time() >= scan_recheck_timeout:
424
+ break # Check timeout before sleep
425
+ logger.debug(f"IP {target_ip} still not resolved in {server_type} list post-scan, retrying...")
426
+ time.sleep(1)
427
+
428
+ # If loop finishes without finding, log it
429
+ logger.warning(f"Device at {target_ip} was located by scan but did not appear resolvable in {server_type} list within timeout.")
430
+ return None # Not found even after scan
431
+
432
+ except Exception as e_findIP:
433
+ # Log errors during the scan process but don't necessarily stop verification yet
434
+ logger.warning(f"Error during {server_type} scan/re-check for {target_ip}: {e_findIP}")
435
+ return None # Indicate IP search failed for this attempt
436
+
437
+ @staticmethod
438
+ def _find_device_by_qtl(list_str_lower, target_qtl_lower):
439
+ """Checks if the target QTL identifier exists in the server list string."""
440
+ if target_qtl_lower in list_str_lower:
441
+ logger.debug(f"Found target QTL '{target_qtl_lower}' directly in server list.")
442
+ return True
443
+ return False
444
+
445
+ def _initialize_qis_connection(self):
446
+ """
447
+ Initializes the connection using the QIS method.
448
+
449
+ Parses host/port, prepares connection string, creates QISConnection object,
450
+ verifies the device presence on the server using the common helper, and
451
+ sets the device as default on the QIS server.
192
452
 
453
+ Sets:
454
+ self.connectionObj, self.ConString.
455
+
456
+ Raises:
457
+ ConnectionError: If connection or verification fails.
458
+ TimeoutError: If verification times out.
459
+ ImportError: If QISConnection class is missing.
460
+ """
461
+ logger.debug("Attempting QIS connection...")
462
+ host, port = self._parse_server_details(default_port=9722)
463
+ self._prepare_server_con_string()
464
+
465
+ # Create QISConnection object
466
+ try:
467
+ # Assumes QISConnection is imported
468
+ self.connectionObj = QISConnection(self.ConString, host, port)
469
+ logger.debug(f"QISConnection object created for '{self.ConString}' via {host}:{port}")
470
+ except Exception as e_qisconn:
471
+ logger.error(f"Failed to create QISConnection: {e_qisconn}", exc_info=True)
472
+ raise ConnectionError("Failed to establish QIS connection.") from e_qisconn
473
+
474
+ # Verify device presence on the QIS server
475
+ try:
476
+ # Pass the QIS-specific sub-object (self.connectionObj.qis) to the helper
477
+ self._verify_server_device(self.connectionObj.qis, "QIS")
478
+ except TimeoutError as e_timeout:
479
+ self.close_connection() # Close object if verification failed
480
+ raise e_timeout # Re-raise timeout
481
+ except Exception as e_qis_conn:
482
+ self.close_connection() # Close object if verification failed
483
+ raise ConnectionError(f"Failed QIS device verification: {e_qis_conn}") from e_qis_conn
484
+
485
+ # Set QIS default device
486
+ try:
487
+ set_default_cmd = f"$default {self.ConString}"
488
+ logger.debug(f"Setting QIS default device: {set_default_cmd}")
489
+ # Assumes sendAndReceiveCmd exists on QIS object
490
+ response = self.connectionObj.qis.sendAndReceiveCmd(cmd=set_default_cmd)
491
+ logger.debug(f"QIS set default response: {response}")
492
+ if "fail" in response.lower():
493
+ logger.warning(f"QIS command '$default {self.ConString}' failed.")
494
+ except Exception as e_def:
495
+ logger.warning(f"Error setting QIS default device: {e_def}")
496
+
497
+ def _initialize_qps_connection(self, host=None, port=None):
498
+ """
499
+ Initializes the connection using the QPS method.
500
+
501
+ Parses host/port, prepares connection string, creates QPSConnection object,
502
+ and verifies the device presence on the server using the common helper.
503
+
504
+ Sets:
505
+ self.connectionObj, self.ConString (potentially updated).
506
+
507
+ Raises:
508
+ ConnectionError: If connection or verification fails.
509
+ TimeoutError: If verification times out.
510
+ ImportError: If QPSConnection class is missing.
511
+ """
512
+ logger.debug("Attempting QPS connection...")
513
+ host, port = self._parse_server_details(default_port=9822) # type: ignore[misc] # Private call ok
514
+ self._prepare_server_con_string() # type: ignore[misc] # Private call ok
515
+
516
+ # Create QPSConnection object
517
+ try:
518
+ # Assumes QPSConnection is imported
193
519
  self.connectionObj = QPSConnection(host, port)
520
+ logger.debug(f"QPSConnection object created via {host}:{port}")
521
+ except Exception as e_qpsconn:
522
+ logger.error(f"Failed to create QPSConnection: {e_qpsconn}", exc_info=True)
523
+ raise ConnectionError("Failed to establish QPS connection.") from e_qpsconn
194
524
 
195
- ## Neither PY or QIS, connection cannot be created.
196
- else:
197
- raise ValueError("Invalid connection type. Acceptable values [PY,QIS,QPS]")
525
+ # Verify device presence on the QPS server
526
+ try:
527
+ # Pass the QPS-specific sub-object (self.connectionObj.qps) to the helper
528
+ self._verify_server_device(self.connectionObj.qps, "QPS") # type: ignore[misc] # Private call ok
529
+ except TimeoutError as e_timeout:
530
+ self.close_connection() # Close object if verification failed
531
+ raise e_timeout # Re-raise timeout
532
+ except Exception as e_qps_conn:
533
+ self.close_connection() # Close object if verification failed
534
+ raise ConnectionError(f"Failed QPS device verification: {e_qps_conn}") from e_qps_conn
535
+ # QPS typically doesn't use/need a '$default' command
536
+
537
+ def _verify_connection_object(self):
538
+ """
539
+ Performs final checks to ensure a valid connection object exists.
540
+
541
+ Raises:
542
+ ConnectionError: If self.connectionObj is None or lacks expected attributes.
543
+ """
544
+ if not self.connectionObj:
545
+ # This should ideally be caught by specific init helpers, but acts as a final safeguard
546
+ raise ConnectionError("Connection object (self.connectionObj) was not successfully created by initializer.")
547
+
548
+ # Commenting out destructor as is still causing issues
549
+ # def __del__(self):
550
+ # """ Ensures the connection is closed when the object is garbage collected. """
551
+ # try:
552
+ # # Close all connections
553
+ # if not self.is_module_resetting:
554
+ # self.close_connection()
555
+ # else:
556
+ # self.is_module_resetting = False
557
+ # except Exception as e_close:
558
+ # # Avoid errors during shutdown sequence
559
+ # if logging and logging.error:
560
+ # logger.error(f"Error during automatic connection close in destructor: {e_close}")
561
+
562
+ # --- Public Methods (Wrappers + snake_case) ---
563
+
564
+ # --- sendCommand ---
565
+ def send_command(self, command_string: str, is_response_expected: bool = True) -> str:
566
+ """
567
+ Executes a text command on the connected device.
568
+
569
+ Sends the command string via the appropriate underlying connection object
570
+ (PY, QIS, or QPS) and returns the response. Handles QIS/QPS specific
571
+ formatting or command routing as needed.
572
+
573
+ Args:
574
+ command_string (str): The text command to send (e.g., "*IDN?").
575
+ is_response_expected (bool, optional): If False, the method may return
576
+ faster as it doesn't wait for/read a response. Defaults to True.
577
+
578
+ Returns:
579
+ str: The response string from the device. Returns an empty string if
580
+ no response was expected or received, or if the underlying connection
581
+ returned None.
582
+
583
+ Raises:
584
+ ConnectionError: If the device is not connected, or if communication fails.
585
+ TimeoutError: If the device response times out.
586
+ NotImplementedError: If the method is called for an unsupported ConType.
587
+ """
588
+ logger.debug(f"{os.path.basename(__file__)}: {self.ConType[:3]} sending command: {command_string}")
198
589
 
199
- logging.debug(os.path.basename(__file__) + " ConString : " + str(self.ConString) + " ConType : " + str(self.ConType))
590
+ if not hasattr(self, 'connectionObj') or not self.connectionObj:
591
+ raise ConnectionError("Connection object not available in send_command.")
200
592
 
593
+ con_type_upper = self.ConType.upper()
594
+ try:
595
+ if con_type_upper.startswith("QIS"):
596
+ # Use current ConString state (might have been updated)
597
+ current_con_string = self.ConString
598
+ numb_colons = current_con_string.count(":")
599
+ if numb_colons == 1:
600
+ current_con_string = current_con_string.replace(':', '::')
601
+ # Assumes QISConnection type for connectionObj
602
+ response = self.connectionObj.qis.sendCommand(command_string, device=current_con_string, expectedResponse=is_response_expected)
603
+
604
+ elif con_type_upper == "PY":
605
+ # Assumes PYConnection type for connectionObj
606
+ if hasattr(self.connectionObj, 'connection') and hasattr(self.connectionObj.connection, 'sendCommand'):
607
+ response = self.connectionObj.connection.sendCommand(command_string, expectedResponse=is_response_expected)
608
+ else:
609
+ raise AttributeError("PYConnection object missing expected structure.")
610
+
611
+ elif con_type_upper.startswith("QPS"):
612
+ # Assumes QPSConnection type for connectionObj
613
+ if command_string and command_string[0] != '$':
614
+ command_string = f"{self.ConString} {command_string}" # Prepend target ID
615
+ response = self.connectionObj.qps.sendCommand(command_string, is_response_expected)
616
+ else:
617
+ raise NotImplementedError(f"send_command not implemented for ConType {self.ConType}")
201
618
 
202
- # def setCanStream(self):
203
- # ask module name if = name in list
204
- # TODO: expectedResponse does nothing can it be removed
205
- # TODO: The connectionObj should be an instance of a common base class such that the IF block here is not needed
206
- def sendCommand(self, CommandString, expectedResponse = True):
619
+ except timeout_exception: # Use platform specific timeout
620
+ logger.error(f"Timeout sending command: '{command_string}'")
621
+ raise TimeoutError(f"Timeout sending command: {command_string}")
622
+ except Exception as e_cmd_exception:
623
+ logger.error(f"Error sending command '{command_string}': {e_cmd_exception}", exc_info=True)
624
+ raise ConnectionError(f"Error sending command '{command_string}'") from e_cmd_exception
625
+
626
+ response_str = response if response is not None else "" # Ensure string
627
+ logger.debug(f"{os.path.basename(__file__)}: {self.ConType[:3]} received: {response_str[:100]}{'...' if len(response_str) > 100 else ''}")
628
+ return response_str
629
+
630
+ def sendCommand(self, CommandString: str, expectedResponse: bool = True) -> str:
207
631
  """
208
- Executes a text based command on the device. This is the primary way of controlling a device. The full command set available to use
209
- is found in the technical manual for the device.
210
-
211
- Parameters
212
- ----------
213
- CommandString : str
632
+ DEPRECATED - Use send_command instead.
633
+
634
+ Executes a text command on the connected device.
214
635
 
215
- The text based command string to send to the device
216
-
217
- Returns
218
- -------
219
- command_response : str or None
636
+ Sends the command string via the appropriate underlying connection object
637
+ (PY, QIS, or QPS) and returns the response. Handles QIS/QPS specific
638
+ formatting or command routing as needed.
220
639
 
221
- The response text from the module. Multiline responses will be seperated with LF. Some commands
222
- do not return a response and None will be returned
640
+ Args:
641
+ CommandString (str): The text command to send (e.g., "*IDN?").
642
+ expectedResponse (bool, optional): If False, the method may return
643
+ faster as it doesn't wait for/read a response. Defaults to True.
223
644
 
645
+ Returns:
646
+ str: The response string from the device. Returns an empty string if
647
+ no response was expected or received, or if the underlying connection
648
+ returned None.
649
+
650
+ Raises:
651
+ ConnectionError: If the device is not connected, or if communication fails.
652
+ TimeoutError: If the device response times out.
653
+ NotImplementedError: If the method is called for an unsupported ConType.
654
+ """
655
+ return self.send_command(CommandString, expectedResponse)
656
+
657
+ # --- sendBinaryCommand ---
658
+ def send_binary_command(self, cmd: bytes) -> bytes:
224
659
  """
660
+ Sends a binary command and reads binary response (USB only).
661
+
662
+ This method is typically used for low-level or USB-specific communication.
663
+ It assumes a PY connection type with a specific underlying structure.
225
664
 
226
- # send command to log
227
- logging.debug(os.path.basename(__file__) + ": "+self.ConType[:3]+" sending command: " + CommandString)
665
+ Args:
666
+ cmd (bytes): The binary command sequence to send.
228
667
 
229
- if self.ConType[:3] == "QIS":
668
+ Returns:
669
+ bytes: The binary data read back from the device.
670
+
671
+ Raises:
672
+ TypeError: If the connection type is not PY or the underlying
673
+ connection object structure is unexpected.
674
+ ConnectionError: If communication fails.
675
+ """
676
+ # Check connection type and structure
677
+ if self.ConType.upper() != "PY" or \
678
+ not hasattr(self.connectionObj, 'connection') or \
679
+ not hasattr(self.connectionObj.connection, 'Connection') or \
680
+ not hasattr(self.connectionObj.connection.Connection, 'SendCommand') or \
681
+ not hasattr(self.connectionObj.connection.Connection, 'BulkRead'):
682
+ raise TypeError(f"send_binary_command requires a PY connection with a USB connection.")
683
+
684
+ logger.debug("Sending binary command...")
685
+ try:
686
+ self.connectionObj.connection.Connection.SendCommand(cmd)
687
+ response = self.connectionObj.connection.Connection.BulkRead()
688
+ except Exception as e_binary_exception:
689
+ logger.error(f"Error during binary command: {e_binary_exception}", exc_info=True)
690
+ raise ConnectionError("Failed to send/receive binary command.") from e_binary_exception
230
691
 
231
- numb_colons = self.ConString.count(":")
232
- if numb_colons == 1:
233
- self.ConString = self.ConString.replace(':', '::')
692
+ logger.debug("Received binary response.")
693
+ return response if response is not None else b"" # Ensure bytes return
234
694
 
235
- response = self.connectionObj.qis.sendCmd(self.ConString, CommandString)
236
- # send response to log
237
- logging.debug(os.path.basename(__file__) + ": "+self.ConType[:3]+" received: " + response)
238
- return response
695
+ def sendBinaryCommand(self, cmd: bytes) -> bytes:
696
+ """
697
+ DEPRECATED - Use send_binary_command instead.
239
698
 
240
- elif self.ConType == "PY":
241
- response = self.connectionObj.connection.sendCommand(CommandString)
242
- # send response to log
243
- logging.debug(os.path.basename(__file__) + ": "+self.ConType[:3]+" received: " + response)
244
- return response
699
+ Sends a binary command and reads binary response (USB only).
245
700
 
246
- elif self.ConType[:3] == "QPS":
247
- # checking if the command string passed has a $ as first char
248
- if CommandString[0] != '$':
249
- CommandString = self.ConString + " " + CommandString
701
+ This method is typically used for low-level or USB-specific communication.
702
+ It assumes a PY connection type with a specific underlying structure.
250
703
 
251
- response = self.connectionObj.qps.sendCmdVerbose(CommandString)
252
- # send response to log
253
- logging.debug(os.path.basename(__file__) + ": "+self.ConType[:3]+" received: " + response)
254
- return response
704
+ Args:
705
+ cmd (bytes): The binary command sequence to send.
255
706
 
256
- # Only works for usb
257
- # TODO: Can this be marked '_' for private use only
258
- def sendBinaryCommand(self, cmd):
259
- self.connectionObj.connection.Connection.SendCommand(cmd)
260
- return self.connectionObj.connection.Connection.BulkRead()
707
+ Returns:
708
+ bytes: The binary data read back from the device.
261
709
 
262
- # TODO: Not using class hierarchy based connectionObj, recreation of PYConnection may not release the previous handle in time.
263
- # QPS and QIS actions are different despite the underlying connection being the same!
264
- def openConnection(self):
710
+ Raises:
711
+ TypeError: If the connection type is not PY or the underlying
712
+ connection object structure is unexpected.
713
+ ConnectionError: If communication fails.
265
714
  """
266
- Opens the connection to the module. This will be open by default on creation of quarchDevice but this
267
- allows re-opening if required.
268
-
715
+ return self.send_binary_command(cmd)
716
+
717
+ # --- openConnection ---
718
+ def open_connection(self) -> Any:
269
719
  """
270
-
271
- logging.debug("Attempting to open " + self.ConType[:3] + " connection")
720
+ Opens or re-opens the connection to the module.
272
721
 
273
- if self.ConType[:3] == "QIS":
274
- self.connectionObj.qis.connect() #todo should have a return val so that failed connections are caught.
722
+ Handles reopening logic based on the connection type (PY, QIS, QPS).
723
+ For PY, it recreates the connection object. For QIS/QPS, it calls
724
+ the underlying connect method.
275
725
 
276
- elif self.ConType == "PY":
277
- del self.connectionObj
278
- self.connectionObj = PYConnection(self.ConString)
279
- return self.connectionObj
726
+ Returns:
727
+ Any: For PY connections, returns the new PYConnection object.
728
+ For QIS/QPS, returns the result of the underlying connect call
729
+ (could be bool or other status). Returns True for successful QIS connect.
280
730
 
281
- elif self.ConType[:3] == "QPS":
282
- return self.connectionObj.qps.connect(self.ConString)
731
+ Raises:
732
+ AttributeError: If the connection object is missing expected methods (connect).
733
+ ConnectionError: If reopening the connection fails.
734
+ ValueError: If the connection type is not recognized.
735
+ """
736
+ logger.debug(f"Attempting to open {self.ConType[:3]} connection")
737
+ con_type_upper = self.ConType.upper()
283
738
 
284
- else:
285
- raise Exception("Connection type not recognised")
286
-
287
- # TODO: Not using class hierarchy based connectionObj. QPS and QIS actions are different despite the underlying connection being the same!
288
- def closeConnection(self):
289
- """
290
- Closes the connection to the module, freeing the module for other uses. This should always be called whern you are finished with a device.
291
-
292
- """
293
-
294
- logging.debug("Attempting to close " + self.ConType[:3] + " connection")
295
-
296
- if self.ConType[:3] == "QIS":
297
- #self.connectionObj.qis.disconnect()
298
- self.connectionObj.qis.closeConnection(conString=self.ConString)
299
- elif self.ConType == "PY":
300
- self.connectionObj.connection.close()
301
-
302
- elif self.ConType[:3] == "QPS":
303
- self.connectionObj.qps.disconnect(self.ConString)
304
-
305
- return "OK"
306
-
307
-
308
- # TODO: Not using class hierarchy based connectionObj.
309
- def resetDevice(self, timeout=10):
310
- """
311
- Issues a power-on-reset command to the device. Attempts to recover the connection to the module after reset.
312
- Function halts until the timeout is complete or the module is found
313
-
314
- Parameters
315
- ----------
316
- timeout : int
317
-
318
- Number of seconds to wait for the module to re-enumerate and become available
319
-
320
- Returns
321
- -------
322
- result : bool
323
-
324
- True if the device was found and reconnected, false if it was not and we timed out
325
-
326
- """
327
-
328
- # send command to log
329
- logging.debug(os.path.basename(__file__) + ": sending command: *rst" )
330
-
331
- if self.ConType[:3] == "QIS":
332
-
333
- numb_colons = self.ConString.count(":")
334
- if numb_colons == 1:
335
- self.ConString = self.ConString.replace(':', '::')
336
-
337
- retval = self.ConString
338
- self.connectionObj.qis.sendCmd(self.ConString, "*rst", expectedResponse = False)
339
- logging.debug(os.path.basename(__file__) + ": connecting back to " + retval)
340
-
341
- elif self.ConType == "PY":
342
- retval = self.ConString
343
- self.connectionObj.connection.sendCommand("*rst" , expectedResponse = False)
344
- self.connectionObj.connection.close()
345
- logging.debug(os.path.basename(__file__) + ": connecting back to " + retval)
346
- #pos fix for making new connectionObj. Works for py connection but more complex for qis & qps
347
- #self.connectionObj = PYConnection(self.ConString)
348
-
349
- elif self.ConType[:3] == "QPS":
350
- # checking if the command string passed has a $ as first char
351
- retval = self.ConString
352
- CommandString = self.ConString + " " + "*rst"
353
- self.connectionObj.qps.sendCmdVerbose(CommandString, expectedResponse = False)
354
- logging.debug(os.path.basename(__file__) + ": connecting back to " + retval)
355
-
356
- #TODO: Idealy we want to call an openConnection() funct to set the connectionObj to the new value not creating a new obj
357
-
358
- temp = None
739
+ try:
740
+ if con_type_upper.startswith("QIS"):
741
+ if hasattr(self.connectionObj, 'qis') and hasattr(self.connectionObj.qis, 'connect'):
742
+ self.connectionObj.qis.connect()
743
+ logger.info("QIS connect called.")
744
+ return True # Assume success if no exception
745
+ else:
746
+ raise AttributeError("QIS connection object or connect method not found.")
747
+
748
+ elif con_type_upper == "PY":
749
+ # Recreate PYConnection (original logic, potentially risky)
750
+ logger.warning("Recreating PYConnection in open_connection. Previous handles might linger.")
751
+ if self.connectionObj and hasattr(self.connectionObj, 'connection') and hasattr(self.connectionObj.connection, 'close'):
752
+ try:
753
+ self.connectionObj.connection.close() # Close old one first
754
+ except Exception as e_connection_exception:
755
+ logger.warning(f"Unable to close old PY Connection: {e_connection_exception}")
756
+ pass
757
+ # Recreate (assumes PYConnection is imported)
758
+ self.connectionObj = PYConnection(self.ConString)
759
+ logger.info(f"PY Connection recreated for {self.ConString}")
760
+ # Update internal details
761
+ self.ConCommsType = getattr(self.connectionObj, 'ConnTypeStr', None)
762
+ self.connectionName = getattr(self.connectionObj, 'ConnTarget', None)
763
+ self.connectionTypeName = self.ConCommsType
764
+ return self.connectionObj # Return new object
765
+
766
+ elif con_type_upper.startswith("QPS"):
767
+ if hasattr(self.connectionObj, 'qps') and hasattr(self.connectionObj.qps, 'connect'):
768
+ result = self.connectionObj.qps.connect(self.ConString)
769
+ logger.info(f"QPS connect called for {self.ConString}. Result: {result}")
770
+ return result
771
+ else:
772
+ raise AttributeError("QPS connection object or connect method not found.")
773
+
774
+ else:
775
+ raise ValueError("Connection type not recognised in open_connection")
776
+
777
+ except Exception as e_conn:
778
+ logger.error(f"Failed to open connection for {self.ConString} ({self.ConType}): {e_conn}", exc_info=True)
779
+ raise ConnectionError(f"Failed to open connection for {self.ConString}") from e_conn
780
+
781
+ def openConnection(self) -> Any:
782
+ """
783
+ DEPRECATED - Use open_connection instead.
784
+
785
+ Opens or re-opens the connection to the module.
786
+
787
+ Handles reopening logic based on the connection type (PY, QIS, QPS).
788
+ For PY, it recreates the connection object. For QIS/QPS, it calls
789
+ the underlying connect method.
790
+
791
+ Returns:
792
+ Any: For PY connections, returns the new PYConnection object.
793
+ For QIS/QPS, returns the result of the underlying connect call
794
+ (could be bool or other status). Returns True for successful QIS connect.
795
+
796
+ Raises:
797
+ AttributeError: If the connection object is missing expected methods (connect).
798
+ ConnectionError: If reopening the connection fails.
799
+ ValueError: If the connection type is not recognized.
800
+ """
801
+ return self.open_connection()
802
+
803
+ # --- closeConnection ---
804
+ def close_connection(self) -> str:
805
+ """
806
+ Closes the connection to the module.
807
+
808
+ Handles closing logic based on connection type (PY, QIS, QPS).
809
+ Clears the internal connection object reference upon successful close.
810
+
811
+ Returns:
812
+ str: "OK" on success, "FAIL" on failure or if no connection exists.
813
+ """
814
+ # This method contains the original logic from closeConnection
815
+ logger.debug(f"Attempting to close {self.ConType[:3]} connection for {self.ConString}")
816
+ con_type_upper = self.ConType.upper()
817
+ closed_ok = False
818
+ conn_obj_to_close = self.connectionObj # Work with current object
819
+
820
+ if conn_obj_to_close is None:
821
+ logger.debug("No connection object exists to close.")
822
+ return "OK" # Nothing to do
823
+
824
+ try:
825
+ if con_type_upper.startswith("QIS"):
826
+ if hasattr(conn_obj_to_close, 'qis') and hasattr(conn_obj_to_close.qis, 'closeConnection'):
827
+ if isQisRunning():
828
+ conn_obj_to_close.qis.closeConnection(conString=self.ConString)
829
+ closed_ok = True
830
+ else:
831
+ logger.warning("QIS connection object or closeConnection method not found.")
832
+
833
+ elif con_type_upper == "PY":
834
+ if hasattr(conn_obj_to_close, 'connection') and hasattr(conn_obj_to_close.connection, 'close'):
835
+ conn_obj_to_close.connection.close()
836
+ closed_ok = True
837
+ else:
838
+ logger.warning("PY connection object structure invalid for close.")
839
+
840
+ elif con_type_upper.startswith("QPS"):
841
+ if hasattr(conn_obj_to_close, 'qps') and hasattr(conn_obj_to_close.qps, 'disconnect'):
842
+ if isQpsRunning():
843
+ conn_obj_to_close.qps.disconnect(self.ConString) # QPS uses disconnect
844
+ closed_ok = True
845
+ else:
846
+ logger.warning("QPS connection object or disconnect method not found.")
847
+ else:
848
+ logger.error(f"Cannot close unknown connection type: {self.ConType}")
849
+
850
+ if closed_ok:
851
+ logger.info(f"Connection closed for {self.ConString}")
852
+ self.connectionObj = None # Clear reference only if close succeeded
853
+ return "OK"
854
+ else:
855
+ logger.warning(f"Could not close connection for {self.ConString} - state uncertain.")
856
+ return "FAIL"
857
+
858
+ except Exception as e_close:
859
+ logger.error(f"Error during close_connection for {self.ConString}: {e_close}", exc_info=True)
860
+ # Do not clear self.connectionObj if close failed with exception
861
+ return "FAIL"
862
+
863
+ def closeConnection(self) -> str:
864
+ """
865
+ DEPRECATED - Use close_connection instead.
866
+
867
+ Closes the connection to the module.
868
+
869
+ Handles closing logic based on connection type (PY, QIS, QPS).
870
+ Clears the internal connection object reference upon successful close.
871
+
872
+ Returns:
873
+ str: "OK" on success, "FAIL" on failure or if no connection exists.
874
+ """
875
+ return self.close_connection()
876
+
877
+ # --- resetDevice ---
878
+ def reset_device(self, timeout: int = 10) -> bool:
879
+ """
880
+ Issues a reset command and attempts recovery.
881
+
882
+ Sends '*rst' to the device, handles connection type specifics (like
883
+ closing PY connection), then attempts to reconnect within the timeout period.
884
+
885
+ Args:
886
+ timeout (int, optional): Seconds to wait for reconnection. Defaults to 10.
887
+
888
+ Returns:
889
+ bool: True if reset and reconnection were successful, False otherwise.
890
+
891
+ Raises:
892
+ ConnectionError: If sending the reset command fails initially (and connection exists).
893
+ """
894
+ logger.debug(f"{os.path.basename(__file__)}: sending command: *rst")
895
+ self.is_module_resetting = True
896
+
897
+ original_con_string = self.ConString # Store original target before potential modification
898
+ original_con_type = self.ConType # Store original type
899
+ con_type_upper = self.ConType.upper()
900
+
901
+ if not hasattr(self, 'connectionObj') or not self.connectionObj:
902
+ logger.error("Cannot reset device, no connection object.")
903
+ return False
904
+
905
+ # --- Send Reset Command ---
906
+ try:
907
+ if con_type_upper.startswith("QIS"):
908
+ current_con_string = original_con_string
909
+ numb_colons = current_con_string.count(":")
910
+ if numb_colons == 1:
911
+ current_con_string = current_con_string.replace(':', '::')
912
+ self.connectionObj.qis.sendCmd(current_con_string, "*rst", expectedResponse=False)
913
+ elif con_type_upper == "PY":
914
+ self.connectionObj.connection.sendCommand("*rst", expectedResponse=False)
915
+ self.connectionObj.connection.close() # Close PY after reset
916
+ self.connectionObj = None # Clear potentially invalid object
917
+ elif con_type_upper.startswith("QPS"):
918
+ CommandString = f"{original_con_string} *rst"
919
+ self.connectionObj.qps.sendCmdVerbose(CommandString, expectedResponse=False)
920
+ else:
921
+ logger.error(f"Reset not supported for connection type {self.ConType}")
922
+ return False
923
+ logger.debug("*rst command sent successfully.")
924
+
925
+ except Exception as e_reset:
926
+ logger.error(f"Error sending *rst command: {e_reset}", exc_info=True)
927
+ # Attempt to close connection forcefully on error before recovery attempt?
928
+ try:
929
+ self.close_connection()
930
+ except Exception as e_close:
931
+ logger.warning(f"Unable to close current connection: {e_close}")
932
+ pass
933
+ # Return False as reset command itself failed
934
+ return False
935
+
936
+ # --- Recovery Attempt ---
937
+ logger.debug(f"Attempting to reconnect to {original_con_string} after reset...")
938
+ temp_device = None
359
939
  startTime = time.time()
360
- time.sleep(0.6) #most devices are visable again after 0.6 seconds.
361
- while temp == None:
940
+ time.sleep(0.6)
941
+
942
+ while temp_device is None:
943
+ # Check timeout
944
+ if (time.time() - startTime) > timeout:
945
+ logger.critical(f"Reconnection failed to {original_con_string} within {timeout}s timeout.")
946
+ self.connectionObj = None # Ensure connectionObj is None if recovery failed
947
+ return False
362
948
  try:
363
- #user_interface.printText("Restart time is : " + str(time.time() - startTime) + " timeout is : " + str(timeout))
364
- temp = getQuarchDevice(retval)
365
- except:
366
- time.sleep(0.2) # wait before trying again if not timed out.
367
- if (time.time() - startTime) > timeout:
368
- logging.critical(os.path.basename(__file__) + ": connection failed to " + retval)
369
- return False
370
-
371
- self.connectionObj = temp.connectionObj
372
- time.sleep(1) #Must wait before sending a command to device. If done instantly device errors out "device busy"
949
+ # Calculate remaining timeout for the attempt
950
+ remaining_timeout = max(1, timeout - int(time.time() - startTime))
951
+ temp_device = get_quarch_device(original_con_string, ConType=original_con_type, timeout=str(remaining_timeout))
952
+ except Exception as recon_e:
953
+ logger.debug(f"Reconnect attempt failed: {recon_e}. Retrying...")
954
+ time.sleep(0.2)
955
+
956
+ # --- Recovery Successful ---
957
+ logger.info(f"Successfully reconnected to {original_con_string} after reset.")
958
+ # Replace the current connection object and potentially other details
959
+ self.connectionObj = temp_device.connectionObj
960
+ self.ConString = temp_device.ConString # Update ConString (might have changed if resolved)
961
+ self.ConType = temp_device.ConType # Update ConType (should likely be same?)
962
+ # Copy other relevant attributes if necessary
963
+ self.timeout = temp_device.timeout
964
+ if hasattr(temp_device, 'ConCommsType'):
965
+ self.ConCommsType = temp_device.ConCommsType
966
+ if hasattr(temp_device, 'connectionName'):
967
+ self.connectionName = temp_device.connectionName
968
+ if hasattr(temp_device, 'connectionTypeName'):
969
+ self.connectionTypeName = temp_device.connectionTypeName
970
+
971
+ time.sleep(1)
373
972
  return True
374
-
375
-
376
- def sendAndVerifyCommand(self, commandString, responseExpected="OK", exception=True):
377
- """
378
- Sends a command to the device and verifies the response is as expected. This is a simple
379
- wrapper of sendCommand and helps write cleaner code in test scripts.
380
-
381
- Parameters
382
- ----------
383
- commandString : str
384
-
385
- The text command to send to the device
386
-
387
- commandString : str, optional
388
-
389
- The expected text response from the module.
390
-
391
- exception : bool, optional
392
-
393
- If True, an exception is raised on mismatch. If False, we just return False
394
-
395
- Returns
396
- -------
397
- result : bool
398
-
399
- True if we matched the response, False if we did not
400
-
401
- Raises
402
- ------
403
- ValueError
404
- If the response does not match AND the exception parameter is set to True
405
-
406
- """
407
-
408
- responseStr = self.sendCommand(commandString)
409
- if (responseStr != responseExpected):
410
- if (exception):
411
- raise ValueError("Command Sent: " + commandString + ", Expected response: " + responseExpected + ", Response received: " + responseStr)
973
+
974
+ def resetDevice(self, timeout: int = 10) -> bool:
975
+ """
976
+ DEPRECATED - Use reset_device instead.
977
+
978
+ Issues a reset command and attempts recovery.
979
+
980
+ Sends '*rst' to the device, handles connection type specifics (like
981
+ closing PY connection), then attempts to reconnect within the timeout period.
982
+
983
+ Args:
984
+ timeout (int, optional): Seconds to wait for reconnection. Defaults to 10.
985
+
986
+ Returns:
987
+ bool: True if reset and reconnection were successful, False otherwise.
988
+
989
+ Raises:
990
+ ConnectionError: If sending the reset command fails initially (and connection exists).
991
+ """
992
+ return self.reset_device(timeout)
993
+
994
+ # --- send_and_verify_command/sendAndVerifyCommand ---
995
+ def send_and_verify_command(self, command_string: str, expected_response: str = "OK", exception: bool = True) -> bool:
996
+ """
997
+ Sends a command and verifies the response matches expected string.
998
+
999
+ A convenience wrapper around `send_command`.
1000
+
1001
+ Args:
1002
+ command_string (str): The text command to send.
1003
+ expected_response (str, optional): The exact string expected back from
1004
+ the device. Defaults to "OK". Comparison is case-sensitive.
1005
+ exception (bool, optional): If True, raises ValueError if the response
1006
+ does not match. If False, returns False on mismatch. Defaults to True.
1007
+
1008
+ Returns:
1009
+ bool: True if the response matched `expected_response`, False otherwise
1010
+ (only if `exception` is False).
1011
+
1012
+ Raises:
1013
+ ValueError: If the response does not match `expected_response` and
1014
+ `exception` is True.
1015
+ ConnectionError: If sending the command fails.
1016
+ TimeoutError: If the device times out responding.
1017
+ """
1018
+ responseStr = self.send_command(command_string)
1019
+
1020
+ if responseStr != expected_response:
1021
+ error_msg = f"Command Sent: '{command_string}', Expected response: '{expected_response}', Response received: '{responseStr}'"
1022
+ logger.error(error_msg)
1023
+ if exception:
1024
+ raise ValueError(error_msg)
412
1025
  else:
413
1026
  return False
414
1027
  else:
1028
+ logger.debug(f"Command '{command_string}' verified successfully (Response: '{expected_response}').")
415
1029
  return True
416
1030
 
417
- def getRuntime(self, command="conf:runtimes?"):
418
- '''
419
-
420
- :param command: can be overridden to ask for PAM fixture runtime
421
- :return:
422
- '''
423
- runtime = self.sendCommand(command)
424
- if runtime.lower().__contains__("fail"):
425
- logging.error("runtime check failed, check FW and FPGA are up to date")
426
- # if the response matches [int]s then the result was valid, return digits, (otherwise return None)
427
- if runtime.endswith("s"):
428
- try :
429
- runtime = int(runtime[:-1])
430
- return runtime
431
- except:
432
- logging.error("runtime response not a valid int : " + str(runtime))
1031
+ def sendAndVerifyCommand(self, commandString: str, responseExpected: str = "OK", exception: bool = True) -> bool:
1032
+ """
1033
+ DEPRECATED - Use send_and_verify_command instead.
1034
+
1035
+ Sends a command and verifies the response matches expected string.
1036
+
1037
+ A convenience wrapper around `send_command`.
1038
+
1039
+ Args:
1040
+ commandString (str): The text command to send.
1041
+ responseExpected (str, optional): The exact string expected back from
1042
+ the device. Defaults to "OK". Comparison is case-sensitive.
1043
+ exception (bool, optional): If True, raises ValueError if the response
1044
+ does not match. If False, returns False on mismatch. Defaults to True.
1045
+
1046
+ Returns:
1047
+ bool: True if the response matched `expected_response`, False otherwise
1048
+ (only if `exception` is False).
1049
+
1050
+ Raises:
1051
+ ValueError: If the response does not match `expected_response` and
1052
+ `exception` is True.
1053
+ ConnectionError: If sending the command fails.
1054
+ TimeoutError: If the device times out responding.
1055
+ """
1056
+ return self.send_and_verify_command(commandString, responseExpected, exception)
1057
+
1058
+ # --- get_runtime/getRuntime ---
1059
+ def get_runtime(self, command: str = "conf:runtimes?") -> Optional[int]:
1060
+ """
1061
+ Queries the device runtime and returns it as an integer in seconds.
1062
+
1063
+ Handles potential "FAIL" responses and non-numeric/non-'s' terminated responses.
1064
+
1065
+ Args:
1066
+ command (str, optional): The specific command to query runtime.
1067
+ Defaults to "conf:runtimes?". Can be overridden for different
1068
+ modules (e.g., PAM fixtures).
1069
+
1070
+ Returns:
1071
+ Optional[int]: The runtime in seconds if successfully parsed, otherwise None.
1072
+ """
1073
+ runtime_str = self.send_command(command)
1074
+
1075
+ if runtime_str is None:
1076
+ logger.error(f"Received None response for runtime command: {command}")
1077
+ return None
1078
+
1079
+ # Use case-insensitive check for "fail"
1080
+ if "fail" in runtime_str.lower():
1081
+ logger.error(f"Runtime check failed (Command: {command}, Response: {runtime_str}), check FW/FPGA?")
1082
+ return None # Return None on failure
1083
+
1084
+ # Check if response ends with 's' and try conversion
1085
+ if isinstance(runtime_str, str) and runtime_str.endswith("s"):
1086
+ try:
1087
+ runtime_int = int(runtime_str[:-1])
1088
+ logger.debug(f"Runtime parsed as {runtime_int} seconds.")
1089
+ return runtime_int
1090
+ except ValueError:
1091
+ logger.error(f"Runtime response '{runtime_str}' not a valid int format.")
1092
+ return None
1093
+ except Exception as e_runtime:
1094
+ logger.error(f"Unexpected error parsing runtime '{runtime_str}': {e_runtime}", exc_info=True)
1095
+ return None
433
1096
  else:
1097
+ # Log if format is unexpected
1098
+ logger.warning(f"Runtime response '{runtime_str}' did not end with 's' or was not string. Cannot parse as seconds.")
434
1099
  return None
435
1100
 
1101
+ def getRuntime(self, command: str = "conf:runtimes?") -> Optional[int]:
1102
+ """
1103
+ DEPRECATED - Use get_runtime instead.
436
1104
 
437
- def _check_ip_in_qis_list(ip_address, detailed_device_list):
438
- """
439
- Checks if the IP address is in qis device list
440
- :param detailed_device_list: list formatted return from qis command "$list details"
441
- :return String : return contype and constring for module if it's in list, else None
1105
+ Queries the device runtime and returns it as an integer in seconds.
1106
+
1107
+ Handles potential "FAIL" responses and non-numeric/non-'s' terminated responses.
1108
+
1109
+ Args:
1110
+ command (str, optional): The specific command to query runtime.
1111
+ Defaults to "conf:runtimes?". Can be overridden for different
1112
+ modules (e.g., PAM fixtures).
1113
+
1114
+ Returns:
1115
+ Optional[int]: The runtime in seconds if successfully parsed, otherwise None.
1116
+ """
1117
+ return self.get_runtime(command)
1118
+
1119
+
1120
+ # --- Top-Level Function Definitions ---
1121
+
1122
+ def _check_ip_in_qis_list(ip_address: str, detailed_device_list: list) -> Optional[str]:
442
1123
  """
443
- # logging.debug(f"List details from Qis : \n{str(''.join(detailed_device_list))}")
1124
+ Checks if an IP address exists in a QIS/QPS device list detail output.
1125
+
1126
+ Parses the list provided by the server to find an entry matching the IP
1127
+ address (specifically for TCP entries) and returns the corresponding
1128
+ full connection string (e.g., "TCP::QTL...") if found.
444
1129
 
445
- for module in detailed_device_list:
446
- # Note for future developers : Restricted this to only TCP modules, not RESt
447
- if ip_address in module and "tcp" in module.lower():
448
- # '1) REST::QTL2312-01-009 IP:192.168.1.5 Port:80 NBName:2312-01-009 Stream:No Name:Power Analysis Module'
449
- # Split on spaces and grab second element ("tcp::qtl2312-01-009")
450
- ret_string = module.split()[1]
451
- return ret_string
1130
+ Args:
1131
+ ip_address (str): The IP address to search for.
1132
+ detailed_device_list (list[str]): A list where each string is a line
1133
+ from the server's "$list details" or "$module list details" output.
452
1134
 
453
- # If the ip address wasn't found, then return none
1135
+ Returns:
1136
+ Optional[str]: The resolved connection string (e.g., "TCP::QTL...") if a
1137
+ matching TCP entry is found, otherwise None.
1138
+ """
1139
+ # This function's logic remains unchanged
1140
+ if not detailed_device_list:
1141
+ return None
1142
+
1143
+ for module_line in detailed_device_list:
1144
+ # Use regex to find IP pattern robustly
1145
+ ip_match = re.search(r"\bIP:(" + re.escape(ip_address) + r")\b", module_line) # Match exact IP
1146
+ if ip_match:
1147
+ # Found the IP, check if it's a TCP entry
1148
+ if "tcp" in module_line.lower():
1149
+ # Try to extract the "TYPE::ID" part using regex or split
1150
+ conn_str_match = re.search(r"^\s*\d+\)\s+([A-Z]+::\S+)", module_line) # Look for "N) TYPE::ID"
1151
+ if conn_str_match:
1152
+ logger.debug(f"Resolved IP {ip_address} using regex to: {conn_str_match.group(1)}")
1153
+ return conn_str_match.group(1)
1154
+ else:
1155
+ # Fallback to original split method if regex fails
1156
+ parts = module_line.split()
1157
+ if len(parts) > 1 and "::" in parts[1]:
1158
+ logger.debug(f"Resolved IP {ip_address} using split method to: {parts[1]}")
1159
+ return parts[1]
1160
+ else:
1161
+ logger.warning(f"Found IP {ip_address} in TCP line, but couldn't extract TYPE::ID: {module_line}")
1162
+ else:
1163
+ logger.debug(f"IP {ip_address} found but not a TCP entry: {module_line}")
1164
+
1165
+ # IP address not found in any relevant line
454
1166
  return None
455
1167
 
456
- # TODO: Can we make this an '_' internal function?
457
- def checkModuleFormat(ConString):
458
- ConnectionTypes = ["USB", "SERIAL", "TELNET", "REST", "TCP"] # acceptable conTypes
459
1168
 
1169
+ # --- checkModuleFormat / check_module_format ---
1170
+ def check_module_format(ConString: str) -> bool:
1171
+ """
1172
+ Checks the basic validity of a connection string format.
1173
+
1174
+ Verifies presence of ':', checks against allowed connection types,
1175
+ and validates the number of colons or sub-device format.
1176
+
1177
+ Args:
1178
+ ConString (str): The connection string to validate.
1179
+
1180
+ Returns:
1181
+ bool: True if the format seems valid, False otherwise.
1182
+
1183
+ Note:
1184
+ Uses a specific list of allowed connection types defined within.
1185
+ May recursively call itself to validate controller part of sub-device strings.
1186
+ """
1187
+ if not ConString:
1188
+ return True # Allow empty
1189
+ if ':' not in ConString:
1190
+ logger.warning("check_module_format: Connection string missing ':'.")
1191
+ return False
1192
+
1193
+ ConnectionTypes = ["USB", "SERIAL", "TELNET", "REST", "TCP"]
460
1194
  conTypeSpecified = ConString[:ConString.find(':')]
461
1195
 
462
1196
  correctConType = False
463
1197
  for value in ConnectionTypes:
464
1198
  if value.lower() == conTypeSpecified.lower():
465
1199
  correctConType = True
1200
+ break
466
1201
 
467
1202
  if not correctConType:
468
- logging.warning("Invalid connection type specified in Module string, use one of [USB|SERIAL|TELNET|REST|TCP]")
1203
+ logger.warning(f"Invalid connection type specified ('{conTypeSpecified}'). Use one of {ConnectionTypes}")
1204
+ logger.warning(f"Invalid connection string: {ConString}")
469
1205
  return False
470
1206
 
471
1207
  numb_colons = ConString.count(":")
472
- if numb_colons > 2 or numb_colons <= 0:
473
- logging.warning("Invalid number of colons in module string")
1208
+
1209
+ # Check sub-device format first
1210
+ if "<" in ConString and ">" in ConString:
1211
+ match = re.match(r"^[A-Z]+:[^<>:]+<\d+>$", ConString, re.IGNORECASE)
1212
+ if match:
1213
+ controller_part = ConString.split('<')[0]
1214
+ if check_module_format(controller_part): # Recursive call
1215
+ return True
1216
+ else:
1217
+ logger.warning(f"Invalid controller part '{controller_part}' in '{ConString}'")
1218
+ else:
1219
+ logger.warning(f"Invalid sub-device syntax: '{ConString}'")
1220
+ # If sub-device checks failed, return False
474
1221
  return False
1222
+ else:
1223
+ # Not a sub-device, check original strict colon count (1 or 2)
1224
+ if numb_colons > 2 or numb_colons <= 0:
1225
+ logger.warning(f"Invalid number of colons ({numb_colons}) in module string (expected 1 or 2).")
1226
+ logger.warning(f"Invalid connection string: {ConString}")
1227
+ return False
475
1228
 
1229
+ # Passed basic checks
476
1230
  return True
477
1231
 
478
1232
 
479
- def getQuarchDevice(connectionTarget, ConType="PY", timeout="5"):
480
- '''creates a quarch device to be returned. Handles sub devices in quarch arrays. '''
1233
+ # Original checkModuleFormat function, kept for compatibility, now calls snake_case version
1234
+ def checkModuleFormat(ConString: str) -> bool:
1235
+ """
1236
+ DEPRECATED - Use check_module_format instead.
1237
+
1238
+ Checks the basic validity of a connection string format.
1239
+
1240
+ Verifies presence of ':', checks against allowed connection types,
1241
+ and validates the number of colons or sub-device format.
1242
+
1243
+ Args:
1244
+ ConString (str): The connection string to validate.
1245
+
1246
+ Returns:
1247
+ bool: True if the format seems valid, False otherwise.
1248
+
1249
+ Note:
1250
+ Uses a specific list of allowed connection types defined within.
1251
+ May recursively call itself to validate controller part of sub-device strings.
1252
+ """
1253
+ return check_module_format(ConString)
1254
+
1255
+
1256
+ # --- getQuarchDevice / get_quarch_device ---
1257
+ def get_quarch_device(connectionTarget: str, ConType: str = "PY", timeout: str = "5") -> 'Union[quarchDevice, subDevice]':
1258
+ """
1259
+ Creates and returns a quarchDevice or subDevice instance.
1260
+
1261
+ Parses the connectionTarget, determines if it's a standard device or a
1262
+ sub-device (e.g., "TYPE:ID<PORT>"), and instantiates the appropriate
1263
+ quarchDevice or subDevice object via the quarchArray class if needed.h
1264
+
1265
+ Args:
1266
+ connectionTarget (str): The connection string for the target device
1267
+ or sub-device.
1268
+ ConType (str, optional): The connection type hint ('PY', 'QIS', 'QPS', etc.)
1269
+ used when creating the base quarchDevice instance if not a sub-device.
1270
+ Defaults to "PY". Note: For sub-devices, the controller connection
1271
+ currently defaults to "PY" internally based on original logic.
1272
+ timeout (str, optional): The connection timeout in seconds as a string.
1273
+ Defaults to "5".
1274
+
1275
+ Returns:
1276
+ quarchDevice | subDevice | Any: An instance representing the connected device.
1277
+ Type hinted as Any because subDevice type might vary.
1278
+
1279
+ Raises:
1280
+ ImportError: If quarchArray components are needed but not found.
1281
+ ValueError: If the connectionTarget format is invalid.
1282
+ ConnectionError: If connecting to the device or controller fails.
1283
+ RuntimeError: For other unexpected errors during connection/instantiation.
1284
+ """
1285
+ # Import quarchArray
481
1286
  from .quarchArray import quarchArray
482
- if connectionTarget.__contains__("<") and connectionTarget.__contains__(">"):
483
- connectionTarget, portNumber = connectionTarget.split("<")
484
- portNumber = portNumber[:-1]
485
- myDevice = quarchDevice(connectionTarget, ConType="PY", timeout="5")
486
- myArrayController = quarchArray(myDevice)
487
- mySubDevice = myArrayController.getSubDevice(portNumber)
488
- myDevice = mySubDevice
1287
+
1288
+ # Original check for sub-device format using __contains__
1289
+ if isinstance(connectionTarget, str) and connectionTarget.__contains__("<") and connectionTarget.__contains__(">"):
1290
+ logger.debug(f"Detected sub-device format for {connectionTarget}")
1291
+ myDevice = None # Ensure defined in this scope
1292
+ myArrayController = None # Ensure defined
1293
+ try:
1294
+ controller_target_str, portNumberPart = connectionTarget.split("<")
1295
+ portNumberStr = portNumberPart[:-1] # Remove '>'
1296
+
1297
+ # Validate port number
1298
+ if not portNumberStr.isdigit():
1299
+ raise ValueError(f"Invalid port number '{portNumberStr}' in sub-device string")
1300
+ portNumber = int(portNumberStr)
1301
+
1302
+ # Validate controller part using the wrapper function (internal call)
1303
+ if not check_module_format(controller_target_str):
1304
+ raise ValueError(f"Invalid controller part format: '{controller_target_str}'")
1305
+
1306
+ logger.debug(f"Connecting to controller '{controller_target_str}' first...")
1307
+ myDeviceBase = quarchDevice(controller_target_str, ConType="PY", timeout=timeout)
1308
+
1309
+ logger.debug("Wrapping controller device with quarchArray...")
1310
+ myArrayController = quarchArray(myDeviceBase)
1311
+
1312
+ logger.debug(f"Getting subDevice for port {portNumber}...")
1313
+ mySubDevice = myArrayController.getSubDevice(portNumber)
1314
+
1315
+ myDevice = mySubDevice # Return the subDevice instance
1316
+ logger.info(f"Successfully connected to sub-device: {connectionTarget}")
1317
+ except (ImportError, ValueError, ConnectionError, RuntimeError) as e_device_error:
1318
+ # Catch specific known errors and re-raise
1319
+ logger.error(f"Failed to get sub-device '{connectionTarget}': {e_device_error}", exc_info=True)
1320
+ raise # Re-raise the caught exception
1321
+ except Exception as e_device_error:
1322
+ # Catch any other unexpected errors
1323
+ logger.error(f"Unexpected error getting sub-device '{connectionTarget}': {e_device_error}", exc_info=True)
1324
+ # Wrap in RuntimeError
1325
+ raise RuntimeError(f"Unexpected error getting sub-device '{connectionTarget}'") from e_device_error
1326
+
489
1327
  else:
1328
+ # Standard device connection
1329
+ logger.debug(f"Standard device connection for: {connectionTarget}")
1330
+ # Use passed ConType and timeout
490
1331
  myDevice = quarchDevice(connectionTarget, ConType=ConType, timeout=timeout)
491
- return myDevice
1332
+ logger.info(f"Successfully connected to standard device: {connectionTarget}")
1333
+
1334
+ return myDevice
1335
+
1336
+
1337
+ # Original getQuarchDevice function, kept for compatibility, now calls snake_case version
1338
+ def getQuarchDevice(connectionTarget: str, ConType: str = "PY", timeout: str = "5") -> 'Union[quarchDevice, subDevice]':
1339
+ """
1340
+ DEPRECATED - Use get_quarch_device instead.
1341
+
1342
+ Creates and returns a quarchDevice or subDevice instance.
1343
+
1344
+ Parses the connectionTarget, determines if it's a standard device or a
1345
+ sub-device (e.g., "TYPE:ID<PORT>"), and instantiates the appropriate
1346
+ quarchDevice or subDevice object via the quarchArray class if needed.
1347
+
1348
+ Args:
1349
+ connectionTarget (str): The connection string for the target device
1350
+ or sub-device.
1351
+ ConType (str, optional): The connection type hint ('PY', 'QIS', 'QPS', etc.)
1352
+ used when creating the base quarchDevice instance if not a sub-device.
1353
+ Defaults to "PY". Note: For sub-devices, the controller connection
1354
+ currently defaults to "PY" internally based on original logic.
1355
+ timeout (str, optional): The connection timeout in seconds as a string.
1356
+ Defaults to "5".
1357
+
1358
+ Returns:
1359
+ quarchDevice | subDevice | Any: An instance representing the connected device.
1360
+ Type hinted as Any because subDevice type might vary.
1361
+
1362
+ Raises:
1363
+ ImportError: If quarchArray components are needed but not found.
1364
+ ValueError: If the connectionTarget format is invalid.
1365
+ ConnectionError: If connecting to the device or controller fails.
1366
+ RuntimeError: For other unexpected errors during connection/instantiation.
1367
+ """
1368
+ return get_quarch_device(connectionTarget, ConType, timeout)