SCPI-Instrument-Control 1.1.0__tar.gz → 3.0.0__tar.gz

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 (194) hide show
  1. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/CHANGELOG.md +148 -1
  2. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/MANIFEST.in +3 -4
  3. {scpi_instrument_control-1.1.0/SCPI_Instrument_Control.egg-info → scpi_instrument_control-3.0.0}/PKG-INFO +87 -21
  4. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/README.md +70 -16
  5. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0/SCPI_Instrument_Control.egg-info}/PKG-INFO +87 -21
  6. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/SCPI_Instrument_Control.egg-info/SOURCES.txt +31 -4
  7. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/SCPI_Instrument_Control.egg-info/entry_points.txt +1 -0
  8. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/SCPI_Instrument_Control.egg-info/requires.txt +16 -2
  9. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/SCPI_Instrument_Control.egg-info/top_level.txt +0 -1
  10. scpi_instrument_control-3.0.0/examples/README.md +96 -0
  11. scpi_instrument_control-3.0.0/examples/dialect_override_example.py +59 -0
  12. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/function_generator_basic.py +2 -2
  13. scpi_instrument_control-3.0.0/examples/gateway_rest_client.py +71 -0
  14. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/probe_calibration_analysis.py +5 -5
  15. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/report_generation_example.py +5 -5
  16. scpi_instrument_control-3.0.0/examples/trend_logging_walkthrough.py +52 -0
  17. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/pyproject.toml +23 -10
  18. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/__init__.py +1 -1
  19. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/automation.py +28 -12
  20. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/channel.py +92 -31
  21. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/connection/base.py +4 -0
  22. scpi_instrument_control-3.0.0/scpi_control/connection/mock/__init__.py +5 -0
  23. scpi_instrument_control-1.1.0/scpi_control/connection/mock.py → scpi_instrument_control-3.0.0/scpi_control/connection/mock/base.py +68 -86
  24. scpi_instrument_control-3.0.0/scpi_control/connection/mock/helpers.py +25 -0
  25. scpi_instrument_control-3.0.0/scpi_control/connection/mock/lecroy.py +96 -0
  26. scpi_instrument_control-3.0.0/scpi_control/connection/mock/siglent.py +235 -0
  27. scpi_instrument_control-3.0.0/scpi_control/connection/mock/tektronix.py +226 -0
  28. scpi_instrument_control-3.0.0/scpi_control/connection/socket.py +302 -0
  29. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/connection/visa_connection.py +7 -5
  30. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/exceptions.py +6 -0
  31. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/function_generator.py +4 -4
  32. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/app.py +4 -4
  33. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/connection_manager.py +7 -7
  34. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/main_window.py +15 -19
  35. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/daq_ai_panel.py +4 -12
  36. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/daq_data_view.py +2 -4
  37. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/daq_scan_config.py +4 -8
  38. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/math_panel.py +2 -4
  39. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/psu_control.py +2 -4
  40. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/terminal_widget.py +10 -20
  41. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/timebase_control.py +4 -8
  42. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/vector_graphics_panel.py +2 -2
  43. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/math_channel.py +5 -14
  44. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/measurement.py +66 -15
  45. scpi_instrument_control-3.0.0/scpi_control/measurement_badges.py +123 -0
  46. scpi_instrument_control-3.0.0/scpi_control/models.py +613 -0
  47. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/oscilloscope.py +82 -22
  48. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/power_supply.py +5 -5
  49. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/__init__.py +1 -1
  50. scpi_instrument_control-3.0.0/scpi_control/report_generator/analysis/__init__.py +1 -0
  51. scpi_instrument_control-3.0.0/scpi_control/report_generator/analysis/computed_analyzer.py +137 -0
  52. scpi_instrument_control-3.0.0/scpi_control/report_generator/app.py +109 -0
  53. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/generators/markdown_generator.py +12 -8
  54. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/generators/pdf_generator.py +147 -139
  55. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/llm/analyzer.py +20 -8
  56. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/llm/client.py +134 -91
  57. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/llm/context_builder.py +13 -16
  58. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/llm/daq_analyzer.py +21 -16
  59. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/llm/prompts.py +17 -1
  60. scpi_instrument_control-3.0.0/scpi_control/report_generator/llm/tools.py +274 -0
  61. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/main_window.py +37 -40
  62. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/models/report_data.py +48 -21
  63. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/models/template.py +26 -0
  64. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/utils/waveform_analyzer.py +96 -25
  65. scpi_instrument_control-3.0.0/scpi_control/report_generator/utils/waveform_loader.py +386 -0
  66. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/widgets/ai_analysis_panel.py +22 -3
  67. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/widgets/metadata_panel.py +87 -1
  68. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/widgets/pdf_preview_dialog.py +5 -2
  69. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/widgets/template_manager_dialog.py +29 -0
  70. scpi_instrument_control-3.0.0/scpi_control/scpi_commands.py +875 -0
  71. scpi_instrument_control-3.0.0/scpi_control/server/__init__.py +0 -0
  72. scpi_instrument_control-3.0.0/scpi_control/server/__main__.py +19 -0
  73. scpi_instrument_control-3.0.0/scpi_control/server/api/__init__.py +0 -0
  74. scpi_instrument_control-3.0.0/scpi_control/server/api/discovery.py +35 -0
  75. scpi_instrument_control-3.0.0/scpi_control/server/api/scope.py +467 -0
  76. scpi_instrument_control-3.0.0/scpi_control/server/api/sessions.py +50 -0
  77. scpi_instrument_control-3.0.0/scpi_control/server/api/stream.py +103 -0
  78. scpi_instrument_control-3.0.0/scpi_control/server/app.py +91 -0
  79. scpi_instrument_control-3.0.0/scpi_control/server/compute.py +109 -0
  80. scpi_instrument_control-3.0.0/scpi_control/server/discovery.py +126 -0
  81. scpi_instrument_control-3.0.0/scpi_control/server/recorder.py +66 -0
  82. scpi_instrument_control-3.0.0/scpi_control/server/schemas.py +113 -0
  83. scpi_instrument_control-3.0.0/scpi_control/server/sessions.py +392 -0
  84. scpi_instrument_control-3.0.0/scpi_control/server/static/assets/index-0Vpguwg6.js +9 -0
  85. scpi_instrument_control-3.0.0/scpi_control/server/static/assets/index-CyUPLIHk.css +1 -0
  86. scpi_instrument_control-3.0.0/scpi_control/server/static/index.html +13 -0
  87. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/trigger.py +138 -51
  88. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/vector_graphics.py +3 -2
  89. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/waveform.py +77 -206
  90. scpi_instrument_control-3.0.0/scpi_control/waveform_schema.py +44 -0
  91. scpi_instrument_control-3.0.0/scpi_control/waveform_transfer.py +370 -0
  92. scpi_instrument_control-1.1.0/docs/VISUAL_MEASUREMENTS.md +0 -638
  93. scpi_instrument_control-1.1.0/examples/README.md +0 -254
  94. scpi_instrument_control-1.1.0/scpi_control/connection/socket.py +0 -211
  95. scpi_instrument_control-1.1.0/scpi_control/models.py +0 -300
  96. scpi_instrument_control-1.1.0/scpi_control/report_generator/app.py +0 -38
  97. scpi_instrument_control-1.1.0/scpi_control/report_generator/utils/waveform_loader.py +0 -316
  98. scpi_instrument_control-1.1.0/scpi_control/scpi_commands.py +0 -206
  99. scpi_instrument_control-1.1.0/siglent/__init__.py +0 -35
  100. scpi_instrument_control-1.1.0/siglent/exceptions.py +0 -40
  101. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/LICENSE +0 -0
  102. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/SCPI_Instrument_Control.egg-info/dependency_links.txt +0 -0
  103. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/docs/SDS800XHD_Series_ProgrammingGuide_EN11G.pdf +0 -0
  104. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/docs/images/01_main_window.png +0 -0
  105. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/docs/images/channel_controls.png +0 -0
  106. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/docs/images/cursors.png +0 -0
  107. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/docs/images/fft_analysis.png +0 -0
  108. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/docs/images/main_window.png +0 -0
  109. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/docs/images/measurements_panel.png +0 -0
  110. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/docs/images/visual_measurements.png +0 -0
  111. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/advanced_analysis.py +0 -0
  112. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/basic_usage.py +0 -0
  113. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/batch_capture.py +0 -0
  114. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/continuous_capture.py +0 -0
  115. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/data_logger_basic.py +0 -0
  116. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/live_plot.py +0 -0
  117. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/measurements.py +0 -0
  118. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/psu_advanced_features.py +0 -0
  119. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/psu_basic_control.py +0 -0
  120. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/psu_gui_test.py +0 -0
  121. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/psu_usb_connection.py +0 -0
  122. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/simple_capture.py +0 -0
  123. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/trigger_based_capture.py +0 -0
  124. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/vector_graphics_xy_mode.py +0 -0
  125. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/examples/waveform_capture.py +0 -0
  126. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/resources/Test Equipment Wide.png +0 -0
  127. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/resources/Test Equipment.icns +0 -0
  128. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/resources/Test Equipment.ico +0 -0
  129. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/resources/Test Equipment.png +0 -0
  130. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/analysis.py +0 -0
  131. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/awg_models.py +0 -0
  132. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/awg_output.py +0 -0
  133. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/awg_scpi_commands.py +0 -0
  134. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/connection/__init__.py +0 -0
  135. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/daq_models.py +0 -0
  136. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/daq_scpi_commands.py +0 -0
  137. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/data_logger.py +0 -0
  138. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/__init__.py +0 -0
  139. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/daq_worker.py +0 -0
  140. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/live_view_worker.py +0 -0
  141. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/utils/validators.py +0 -0
  142. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/vnc_window.py +0 -0
  143. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/waveform_capture_worker.py +0 -0
  144. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/__init__.py +0 -0
  145. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/channel_control.py +0 -0
  146. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/cursor_panel.py +0 -0
  147. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/daq_channel_config.py +0 -0
  148. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/data_logger_control.py +0 -0
  149. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/error_dialog.py +0 -0
  150. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/fft_display.py +0 -0
  151. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/measurement_marker.py +0 -0
  152. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/measurement_markers/__init__.py +0 -0
  153. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/measurement_markers/frequency_marker.py +0 -0
  154. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/measurement_markers/timing_marker.py +0 -0
  155. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/measurement_markers/voltage_marker.py +0 -0
  156. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/measurement_panel.py +0 -0
  157. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/protocol_decode_panel.py +0 -0
  158. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/reference_panel.py +0 -0
  159. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/scope_web_view.py +0 -0
  160. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/trigger_control.py +0 -0
  161. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/visual_measurement_panel.py +0 -0
  162. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/waveform_display.py +0 -0
  163. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/gui/widgets/waveform_display_pg.py +0 -0
  164. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/measurement_config.py +0 -0
  165. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/power_supply_output.py +0 -0
  166. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/protocol_decode.py +0 -0
  167. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/protocol_decoders/__init__.py +0 -0
  168. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/protocol_decoders/i2c_decoder.py +0 -0
  169. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/protocol_decoders/spi_decoder.py +0 -0
  170. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/protocol_decoders/uart_decoder.py +0 -0
  171. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/psu_data_logger.py +0 -0
  172. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/psu_models.py +0 -0
  173. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/psu_scpi_commands.py +0 -0
  174. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/py.typed +0 -0
  175. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/reference_waveform.py +0 -0
  176. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/generators/__init__.py +0 -0
  177. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/generators/base.py +0 -0
  178. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/llm/__init__.py +0 -0
  179. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/llm/daq_context_builder.py +0 -0
  180. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/llm/daq_prompts.py +0 -0
  181. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/models/__init__.py +0 -0
  182. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/models/app_settings.py +0 -0
  183. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/models/criteria.py +0 -0
  184. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/models/plot_style.py +0 -0
  185. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/models/report_options.py +0 -0
  186. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/models/test_types.py +0 -0
  187. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/utils/__init__.py +0 -0
  188. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/utils/image_handler.py +0 -0
  189. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/widgets/__init__.py +0 -0
  190. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/widgets/chat_sidebar.py +0 -0
  191. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/widgets/llm_settings_dialog.py +0 -0
  192. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/report_generator/widgets/report_options_dialog.py +0 -0
  193. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/scpi_control/screen_capture.py +0 -0
  194. {scpi_instrument_control-1.1.0 → scpi_instrument_control-3.0.0}/setup.cfg +0 -0
@@ -7,15 +7,162 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [3.0.0] - 2026-07-17
11
+
12
+ ### ⚠️ Breaking Changes
13
+
14
+ - **The report generator's `WaveformData` fields are renamed, and `channel`
15
+ moved from the first constructor argument to the third.** `channel_name`,
16
+ `time_data`, and `voltage_data` are now `channel`, `time`, and `voltage`,
17
+ matching the base class's field order (`time`, `voltage`, `channel`, ...).
18
+ Because the position changed along with the name, positional construction
19
+ such as `WaveformData("CH1", t, v, ...)` does **not** fail with a
20
+ recognizable rename error — it silently assigns `"CH1"` to `time` and
21
+ blows up later with `AttributeError: 'str' object has no attribute
22
+ 'shape'`. Construct with keywords (`channel=`, `time=`, `voltage=`) to
23
+ migrate safely. This is a documented public API — see
24
+ [`docs/report-generator/api-reference.md`](docs/report-generator/api-reference.md).
25
+ - **`WaveformData.source` and `WaveformData.description` are removed**, on
26
+ both the library and report waveform types. `WaveformData(..., source="x")`
27
+ now raises `TypeError` instead of silently accepting the keyword.
28
+ - **`WaveformData.timebase` and `WaveformData.voltage_scale` are `None`
29
+ unless an instrument actually reported them**, instead of being derived by
30
+ assuming a 14-division horizontal grid and an 8-division vertical one —
31
+ Siglent's geometry, previously applied to Tektronix and LeCroy captures too
32
+ — with a flat trace given a bare 1.0 V/div. Real acquisitions are
33
+ unaffected: all three vendor backends pass genuine scope values. Code that
34
+ does arithmetic on `timebase`/`voltage_scale` from a *synthetic* waveform
35
+ (a math channel, or hand-built test data) — e.g. `wf.timebase * 1e6` — now
36
+ raises `TypeError` on `None` instead of silently using an invented number.
37
+ Guard with a `None` check, or supply real values.
10
38
 
11
- ## [1.0.1] - 2026-01-07
39
+ ### Added
40
+
41
+ - Tektronix and LeCroy oscilloscope support (core control, waveform
42
+ acquisition, measurements): two more wire dialects (`tektronix`, `lecroy`)
43
+ alongside the existing Siglent legacy/modern pair, auto-detected from
44
+ `*IDN?` via a manufacturer-first routing step. Covers the Tektronix
45
+ TBS1000C Series and 2 Series MSO, and the LeCroy WaveSurfer 3000z and
46
+ WaveRunner 8000 series. See the
47
+ [SCPI Dialects guide](docs/user-guide/scpi-dialects.md) for the full
48
+ per-vendor command tables and known gaps (e.g. LeCroy
49
+ statistics/cursors/holdoff, Tek 16-bit waveform transfer).
50
+ - Tektronix MSO 4/5/6 Series support (MSO44, MSO46, MSO54, MSO56, MSO58,
51
+ MSO58LP, MSO64), including 6- and 8-channel models.
52
+ - Badge-based measurements for the modern Tektronix MSO families, which also
53
+ enables `measure()` on the MSO 2-Series.
54
+ - **Report generator — local-LLM analysis and richer PDFs**
55
+ (`pip install "SCPI-Instrument-Control[report-generator]"`). Everything here
56
+ is local-only — no cloud providers, no API keys.
57
+ - Local-LLM (Ollama) tool calling: the model can call read-only report tools
58
+ to ground its answers, behind a capability gate that no-ops when the local
59
+ model cannot do tool calls.
60
+ - Waveform analysis tools for the model — `analyze_plateaus`, `list_edges`,
61
+ and `analyze_spectrum` — plus `WaveformAnalyzer.calculate_spectrum`.
62
+ - Deterministic no-LLM analysis: a `ComputedAnalyzer` populates per-waveform
63
+ statistics and regions on every report, and composes a summary, findings,
64
+ and recommendations when no LLM wrote them. Reports now attribute their
65
+ summary by source (manual / AI / computed) rather than a bare AI flag.
66
+ - Vector PDF plots: waveform, FFT, and region plots render as scalable vector
67
+ graphics instead of rasterized images.
68
+ - Page framework: a running header/footer and page numbers on every page,
69
+ with section headings kept from stranding at the bottom of a page.
70
+ - Template branding: a template's logo, company name, header/footer text, and
71
+ four brand colours apply to the generated PDF, and a built-in starter
72
+ template can be seeded from the Template Manager.
73
+
74
+ ### Changed
75
+
76
+ - On the Siglent modern dialect, `trigger.holdoff`, measurement statistics,
77
+ cursors, and `channel.unit` now raise `FeatureNotSupportedError` immediately
78
+ instead of writing an unsupported command and timing out
79
+ (`SiglentTimeoutError`). Code that caught the timeout to detect these
80
+ unsupported operations must now catch `FeatureNotSupportedError` instead.
81
+ - Probe-ratio wire format on the legacy and modern dialects now serializes
82
+ floats compactly (`10.0` is sent as `10`), matching how real scopes echo the
83
+ value back.
84
+ - `add_measurement` now validates and case-normalizes its measurement type
85
+ (unknown types raise instead of being sent verbatim to the instrument).
86
+ - Channel numbers are validated against the connected model's channel count
87
+ instead of a fixed 1-4 range. Scopes with fewer than four channels now raise
88
+ `InvalidParameterError` for a channel they do not have, where they
89
+ previously queried it.
90
+ - The report generator's `WaveformData` is now a subclass of
91
+ `scpi_control.waveform.WaveformData` (see Breaking Changes above for the
92
+ field rename and reorder this involved). Report waveforms now inherit the
93
+ library's array-shape validation, and `channel` is now guaranteed to be a
94
+ `str` by the type itself. The loader's explicit `str()` calls at each
95
+ construction site are unchanged and now redundant, not removed — they stay
96
+ as a defensive measure against `np.str_`/`bytes` values handed back at the
97
+ MAT/HDF5 boundary.
98
+
99
+ ## [2.0.0] - 2026-07-15
100
+
101
+ ### ⚠️ Breaking Changes
102
+
103
+ - **Removed the `siglent` compatibility shim.** `import siglent` now raises
104
+ `ModuleNotFoundError`; use `import scpi_control` (identical API). The shim
105
+ had emitted a `DeprecationWarning` since 1.0.0, which announced its removal
106
+ in v2.0.0. If you cannot migrate yet, pin `SCPI-Instrument-Control<2.0`.
107
+ - **Python 3.9+ required** (was 3.8+; Python 3.8 reached end of life in
108
+ October 2024). CI now tests Python 3.9 through 3.14.
12
109
 
13
110
  ### Added
14
111
 
112
+ - **Browser-based lab gateway** (`pip install "SCPI-Instrument-Control[web]"`,
113
+ then `scpi-web` or `python -m scpi_control.server`): a FastAPI server that
114
+ manages named multi-instrument sessions and serves a React UI to any
115
+ browser on the LAN. Mock-first — every feature works against the built-in
116
+ mock scope (`mock: true`).
117
+ - Live waveform streaming over WebSocket, with channel, timebase, trigger,
118
+ and acquisition (run/stop/single/auto) controls
119
+ - LAN instrument discovery and a dashboard-style home screen
120
+ - Measurements with live values and cross-tab-synchronized selection
121
+ - Software math channels (M1/M2) streamed as canvas traces
122
+ - SCPI terminal, instrument screenshot PNG, full-resolution waveform
123
+ export as CSV and JSON
124
+ - FFT spectrum view computed server-side from full-resolution data
125
+ (window selection, peak markers, THD readout)
126
+ - Software Butterworth filters (lowpass/highpass/bandpass) streamed as
127
+ F1/F2 traces
128
+ - Reference waveforms: save named snapshots, ghost overlay on the canvas,
129
+ live correlation and max-deviation statistics
130
+ - Measurement trend recording: server-side ring buffer at ~1 Hz, live
131
+ trend chart, CSV export; the measurement selection locks while recording
132
+ - Dual-dialect SCPI support: legacy (e.g. SDS1104X-E) and modern
133
+ (e.g. SDS800X HD) Siglent command sets behind one API, auto-detected from
134
+ `*IDN?` with a manual override
135
+
15
136
  ### Changed
16
137
 
138
+ - Connection layer hardened: thread-safe socket handling, exact-length
139
+ binary reads, default SCPI port 5025
140
+ - `wait_for_trigger` honors a user-configured NORMAL trigger mode instead of
141
+ forcing SINGLE
142
+ - Black formatting standardized on the 26.x stable style; dev extra now
143
+ requires `black>=26.5,<27` (installed on Python >= 3.10, where Black 26 is available)
144
+ - Removed the unused `uplot` frontend dependency (the UI draws on a
145
+ hand-rolled canvas)
146
+
17
147
  ### Fixed
18
148
 
149
+ - Mock-fidelity and hardware-behavior fixes from the 2026-07 code audit
150
+ (trigger vocabulary mapping, waveform preamble parsing, measurement
151
+ timeout handling, and related issues)
152
+
153
+ ## [1.1.0] - 2026-01-12
154
+
155
+ ### Added
156
+
157
+ - Data acquisition / data logger instrument support (`DataLogger`): Keysight
158
+ 34970A/DAQ970A-style SCPI units — DMM function configuration (V/I/R/
159
+ temperature), scan lists, triggering, alarms, channel scaling, and timed
160
+ logging helpers (PR #39)
161
+
162
+ ## [1.0.1] - 2026-01-07
163
+
164
+ Packaging and metadata fixes for the 1.0.0 rename release; no functional changes.
165
+
19
166
  ## [1.0.0] - 2026-01-06
20
167
 
21
168
  ### ⚠️ MAJOR RELEASE - Package Renamed
@@ -6,13 +6,14 @@ include pyproject.toml
6
6
 
7
7
  # Include user-facing documentation
8
8
  recursive-include docs/images *.png *.jpg
9
- include docs/VISUAL_MEASUREMENTS.md
10
- include docs/SCREENSHOT_GUIDE.md
11
9
  include docs/SDS800XHD_Series_ProgrammingGuide_EN11G.pdf
12
10
 
13
11
  # Include resources (logos, icons)
14
12
  recursive-include resources *.png *.ico *.icns
15
13
 
14
+ # Include web gateway frontend build output (when present)
15
+ recursive-include scpi_control/server/static *
16
+
16
17
  # Include examples
17
18
  recursive-include examples *.py
18
19
  recursive-include examples *.md
@@ -21,8 +22,6 @@ recursive-include examples *.md
21
22
  exclude docs/development/*
22
23
  exclude docs/README_SCREENSHOTS.md
23
24
  exclude docs/SCREENSHOT_CHECKLIST.md
24
- exclude docs/CONTRIBUTING.md
25
- exclude docs/SECURITY.md
26
25
  recursive-exclude tests *
27
26
  recursive-exclude scripts *
28
27
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: SCPI-Instrument-Control
3
- Version: 1.1.0
3
+ Version: 3.0.0
4
4
  Summary: Universal Python library for controlling SCPI-compatible test equipment via Ethernet/LAN. Supports oscilloscopes (Siglent SDS series, generic SCPI scopes), function generators/AWGs (Siglent SDG series, generic SCPI AWGs), and power supplies (Siglent SPD series, generic SCPI PSUs). Features include waveform capture, measurements, FFT analysis, PyQt6 GUI, automated report generation with AI analysis, and comprehensive SCPI command abstraction.
5
5
  Author: Robin Mumm
6
6
  Maintainer: little-did-I-know
@@ -17,11 +17,12 @@ Classifier: Intended Audience :: Developers
17
17
  Classifier: Intended Audience :: Manufacturing
18
18
  Classifier: Operating System :: OS Independent
19
19
  Classifier: Programming Language :: Python :: 3
20
- Classifier: Programming Language :: Python :: 3.8
21
20
  Classifier: Programming Language :: Python :: 3.9
22
21
  Classifier: Programming Language :: Python :: 3.10
23
22
  Classifier: Programming Language :: Python :: 3.11
24
23
  Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Programming Language :: Python :: 3.14
25
26
  Classifier: Programming Language :: Python :: 3 :: Only
26
27
  Classifier: Topic :: Scientific/Engineering
27
28
  Classifier: Topic :: Scientific/Engineering :: Interface Engine/Protocol Translator
@@ -30,7 +31,7 @@ Classifier: Topic :: System :: Networking :: Monitoring
30
31
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
31
32
  Classifier: Environment :: X11 Applications :: Qt
32
33
  Classifier: Typing :: Typed
33
- Requires-Python: >=3.8
34
+ Requires-Python: >=3.9
34
35
  Description-Content-Type: text/markdown
35
36
  License-File: LICENSE
36
37
  Requires-Dist: numpy>=1.24.0
@@ -40,17 +41,20 @@ Provides-Extra: dev
40
41
  Requires-Dist: pytest>=7.0; extra == "dev"
41
42
  Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
42
43
  Requires-Dist: codecov>=2.1.0; extra == "dev"
43
- Requires-Dist: black>=23.0; extra == "dev"
44
+ Requires-Dist: black<27,>=26.5; python_version >= "3.10" and extra == "dev"
44
45
  Requires-Dist: flake8>=6.0; extra == "dev"
45
46
  Requires-Dist: build>=0.10.0; extra == "dev"
46
47
  Requires-Dist: twine>=4.0.0; extra == "dev"
47
- Requires-Dist: black[jupyter]>=23.0; extra == "dev"
48
48
  Provides-Extra: hdf5
49
49
  Requires-Dist: h5py>=3.8.0; extra == "hdf5"
50
50
  Provides-Extra: gui
51
51
  Requires-Dist: PyQt6>=6.6.0; extra == "gui"
52
52
  Requires-Dist: PyQt6-WebEngine>=6.6.0; extra == "gui"
53
53
  Requires-Dist: pyqtgraph>=0.13.0; extra == "gui"
54
+ Provides-Extra: web
55
+ Requires-Dist: fastapi>=0.115; extra == "web"
56
+ Requires-Dist: uvicorn[standard]>=0.30; extra == "web"
57
+ Requires-Dist: Pillow>=10.0; extra == "web"
54
58
  Provides-Extra: fun
55
59
  Requires-Dist: shapely>=2.0.0; extra == "fun"
56
60
  Requires-Dist: Pillow>=10.0.0; extra == "fun"
@@ -60,7 +64,11 @@ Requires-Dist: PyQt6>=6.6.0; extra == "report-generator"
60
64
  Requires-Dist: Pillow>=10.0.0; extra == "report-generator"
61
65
  Requires-Dist: requests>=2.31.0; extra == "report-generator"
62
66
  Requires-Dist: reportlab>=4.0.0; extra == "report-generator"
67
+ Requires-Dist: svglib>=1.5.0; extra == "report-generator"
63
68
  Requires-Dist: ollama>=0.6.0; extra == "report-generator"
69
+ Requires-Dist: PyMuPDF>=1.23.0; extra == "report-generator"
70
+ Requires-Dist: psutil>=5.9.0; extra == "report-generator"
71
+ Requires-Dist: nvidia-ml-py>=12.0.0; extra == "report-generator"
64
72
  Provides-Extra: power-supply-beta
65
73
  Provides-Extra: usb
66
74
  Requires-Dist: pyvisa>=1.14.0; extra == "usb"
@@ -85,7 +93,11 @@ Requires-Dist: Pillow>=10.0.0; extra == "all"
85
93
  Requires-Dist: svgpathtools>=1.6.0; extra == "all"
86
94
  Requires-Dist: requests>=2.31.0; extra == "all"
87
95
  Requires-Dist: reportlab>=4.0.0; extra == "all"
96
+ Requires-Dist: svglib>=1.5.0; extra == "all"
88
97
  Requires-Dist: ollama>=0.6.0; extra == "all"
98
+ Requires-Dist: PyMuPDF>=1.23.0; extra == "all"
99
+ Requires-Dist: psutil>=5.9.0; extra == "all"
100
+ Requires-Dist: nvidia-ml-py>=12.0.0; extra == "all"
89
101
  Dynamic: license-file
90
102
 
91
103
  # SCPI Instrument Control
@@ -312,7 +324,7 @@ pip install "SCPI-Instrument-Control[all]"
312
324
 
313
325
  #### 2. Update Your Import Statements
314
326
 
315
- **Old imports** (deprecated but still work):
327
+ **Old imports** (no longer work as of v2.0.0):
316
328
 
317
329
  ```python
318
330
  from siglent import Oscilloscope, PowerSupply, FunctionGenerator
@@ -330,16 +342,11 @@ from scpi_control.waveform import Waveform
330
342
 
331
343
  #### 3. Backward Compatibility
332
344
 
333
- **Good news**: The old `import siglent` syntax still works! A compatibility shim automatically redirects to `scpi_control`.
334
-
335
- However, you'll see a `DeprecationWarning` encouraging you to update your code:
336
-
337
- ```
338
- DeprecationWarning: The 'siglent' package name is deprecated and will be removed in v2.0.0.
339
- Please update your imports to use 'scpi_control' instead.
340
- ```
341
-
342
- **The compatibility layer will be removed in v2.0.0**, so please migrate your code when convenient.
345
+ The `siglent` compatibility shim was removed in **v2.0.0** (it had emitted a
346
+ `DeprecationWarning` since v1.0.0). `import siglent` now raises
347
+ `ModuleNotFoundError` update your imports to `scpi_control` as shown above;
348
+ the API is otherwise identical. If you cannot migrate yet, pin
349
+ `SCPI-Instrument-Control<2.0`.
343
350
 
344
351
  #### 4. Command-Line Tools
345
352
 
@@ -357,7 +364,7 @@ No changes needed to scripts or automation that invoke these commands.
357
364
  | Old | New | Status |
358
365
  |-----|-----|--------|
359
366
  | PyPI package: `siglent` | PyPI package: `SCPI-Instrument-Control` | **Changed** |
360
- | `import siglent` | `import scpi_control` | **Recommended** |
367
+ | `import siglent` | `import scpi_control` | **Required since v2.0.0** |
361
368
  | `siglent-gui` command | `siglent-gui` command | **Unchanged** |
362
369
  | `siglent-report-generator` command | `siglent-report-generator` command | **Unchanged** |
363
370
 
@@ -422,7 +429,7 @@ main()
422
429
 
423
430
  ### Core Library
424
431
 
425
- - Python 3.8+
432
+ - Python 3.9+
426
433
  - NumPy >= 1.24.0
427
434
  - Matplotlib >= 3.7.0
428
435
  - SciPy >= 1.10.0
@@ -681,6 +688,50 @@ See `examples/vector_graphics_xy_mode.py` for programmatic usage and animation e
681
688
  - I2C, SPI, UART, CAN, LIN decoding
682
689
  - Packet analysis and export
683
690
 
691
+ ## Web Gateway (beta)
692
+
693
+ Control instruments from any browser on your LAN:
694
+
695
+ ```bash
696
+ pip install scpi-instrument-control[web] # includes the browser gateway
697
+ scpi-web --host 0.0.0.0 --port 8765
698
+ ```
699
+
700
+ Open `http://<gateway-pc>:8765`. Sessions can target real scopes by IP or a
701
+ built-in mock (`mock: true`) for hardware-free use. The API is documented at
702
+ `/docs` (OpenAPI). No authentication in this release — bind to `127.0.0.1`
703
+ (the default) unless your LAN is trusted.
704
+
705
+ Full documentation: [Web Gateway guide](https://little-did-I-know.github.io/SCPI-Instrument-Control/gateway/) — overview, browser UI tour, and the complete REST & WebSocket API reference.
706
+
707
+ - `GET /api/discover` scans the gateway's subnet (or `?cidr=…`) for SCPI
708
+ instruments on port 5025 and lists them with model and dialect — handy when
709
+ DHCP moves your instruments around.
710
+ - `GET .../scope/screenshot.png` — the instrument's display as a PNG
711
+ - `GET .../scope/waveform?channels=1,2&max_points=N` — waveform data as JSON
712
+ - `GET/PATCH .../scope/math/{1,2}` — software math channels (streamed as M1/M2 traces)
713
+ - `GET .../scope/measurements` — the current measurement selection
714
+ - `GET/PATCH .../scope/spectrum` — server-computed FFT spectrum (streamed as `spectrum` frames)
715
+ - `GET .../scope/filters` + `PATCH .../scope/filters/{1,2}` — software Butterworth filters (streamed as F1/F2 traces)
716
+ - `GET/POST/DELETE .../scope/references` + `GET/PUT .../scope/reference` — saved reference waveforms and the live overlay
717
+ - `POST .../scope/log/start` / `POST .../scope/log/stop` — record the selected measurements (~1 Hz) server-side
718
+ - `GET .../scope/log`, `GET .../scope/log/data?since=`, `GET .../scope/log.csv` — recording status, rows, and CSV export
719
+
720
+ ### Browser UI
721
+
722
+ ```bash
723
+ make webapp-install # once
724
+ make webapp-build # build the UI into the server
725
+ scpi-web --host 0.0.0.0 # serve API + UI on one port
726
+ ```
727
+
728
+ Open `http://<gateway-pc>:8765`. For UI development, run `scpi-web` in one
729
+ terminal and `cd webapp/app && npm run dev` in another — Vite proxies `/api`
730
+ (HTTP and WebSocket) to the gateway with hot reload.
731
+
732
+ The home screen scans your LAN and lists instruments to connect to, resume, or
733
+ open a shared session on — plus manual IP and a hardware-free mock.
734
+
684
735
  ## API Documentation
685
736
 
686
737
  ### Oscilloscope
@@ -854,18 +905,33 @@ See the `examples/` directory for complete working examples:
854
905
 
855
906
  ## Supported Models
856
907
 
857
- ### Fully Tested
908
+ ### Siglent (Fully Tested)
858
909
 
859
910
  - **SDS800X HD Series**: SDS804X HD, SDS824X HD
860
911
  - **SDS1000X-E Series**: SDS1102X-E, SDS1104X-E, SDS1202X-E, SDS1204X-E
861
912
  - **SDS2000X Plus Series**: SDS2104X+, SDS2204X+, SDS2354X+
862
913
  - **SDS5000X Series**: SDS5034X, SDS5054X, SDS5104X
863
914
 
915
+ ### Tektronix and LeCroy (core control + measurements)
916
+
917
+ - **Tektronix TBS1000C Series**: TBS1102C
918
+ - **Tektronix 2 Series MSO**: MSO24
919
+ - **Tektronix 4 Series MSO**: MSO44, MSO46
920
+ - **Tektronix 5 Series MSO**: MSO54, MSO56, MSO58, MSO58LP
921
+ - **Tektronix 6 Series MSO**: MSO64
922
+ - **LeCroy WaveSurfer 3000z Series**: WaveSurfer 3024z
923
+ - **LeCroy WaveRunner 8000 Series**: WaveRunner 8104
924
+
925
+ All Tektronix MSO models (2/4/5/6 Series) share one command variant and
926
+ support automated measurements — see the [SCPI Dialects guide](https://little-did-I-know.github.io/SCPI-Instrument-Control/user-guide/scpi-dialects/) for the full per-vendor gap list.
927
+
928
+ Command tables were verified command-by-command against the vendor programmer manuals (Tektronix TBS1000C, 2 Series MSO, and 4/5/6 Series MSO/6 Series LPD manuals; the Teledyne LeCroy MAUI Remote Control and Automation Manual) and exercised against a dialect-aware mock; not yet run against real Tektronix or LeCroy hardware.
929
+
864
930
  ### Compatibility
865
931
 
866
- Should work with other Siglent oscilloscopes that support SCPI commands over Ethernet. Model-specific features are auto-detected via the `ModelCapability` registry.
932
+ Should work with other Siglent oscilloscopes that support SCPI commands over Ethernet. Model-specific features are auto-detected via the `ModelCapability` registry. Unrecognized Tektronix or LeCroy models fall back to a conservative generic profile for that vendor (with a logged warning) rather than being rejected outright.
867
933
 
868
- **Note**: Some SCPI commands vary between models. The library includes model-specific command variants for HD, X, and Plus series.
934
+ **Note**: Some SCPI commands vary between models. The library includes model-specific command variants for HD, X, and Plus series (Siglent) and for TBS vs. MSO (2/4/5/6 Series share one variant) (Tektronix).
869
935
 
870
936
  ## Contributing
871
937
 
@@ -222,7 +222,7 @@ pip install "SCPI-Instrument-Control[all]"
222
222
 
223
223
  #### 2. Update Your Import Statements
224
224
 
225
- **Old imports** (deprecated but still work):
225
+ **Old imports** (no longer work as of v2.0.0):
226
226
 
227
227
  ```python
228
228
  from siglent import Oscilloscope, PowerSupply, FunctionGenerator
@@ -240,16 +240,11 @@ from scpi_control.waveform import Waveform
240
240
 
241
241
  #### 3. Backward Compatibility
242
242
 
243
- **Good news**: The old `import siglent` syntax still works! A compatibility shim automatically redirects to `scpi_control`.
244
-
245
- However, you'll see a `DeprecationWarning` encouraging you to update your code:
246
-
247
- ```
248
- DeprecationWarning: The 'siglent' package name is deprecated and will be removed in v2.0.0.
249
- Please update your imports to use 'scpi_control' instead.
250
- ```
251
-
252
- **The compatibility layer will be removed in v2.0.0**, so please migrate your code when convenient.
243
+ The `siglent` compatibility shim was removed in **v2.0.0** (it had emitted a
244
+ `DeprecationWarning` since v1.0.0). `import siglent` now raises
245
+ `ModuleNotFoundError` update your imports to `scpi_control` as shown above;
246
+ the API is otherwise identical. If you cannot migrate yet, pin
247
+ `SCPI-Instrument-Control<2.0`.
253
248
 
254
249
  #### 4. Command-Line Tools
255
250
 
@@ -267,7 +262,7 @@ No changes needed to scripts or automation that invoke these commands.
267
262
  | Old | New | Status |
268
263
  |-----|-----|--------|
269
264
  | PyPI package: `siglent` | PyPI package: `SCPI-Instrument-Control` | **Changed** |
270
- | `import siglent` | `import scpi_control` | **Recommended** |
265
+ | `import siglent` | `import scpi_control` | **Required since v2.0.0** |
271
266
  | `siglent-gui` command | `siglent-gui` command | **Unchanged** |
272
267
  | `siglent-report-generator` command | `siglent-report-generator` command | **Unchanged** |
273
268
 
@@ -332,7 +327,7 @@ main()
332
327
 
333
328
  ### Core Library
334
329
 
335
- - Python 3.8+
330
+ - Python 3.9+
336
331
  - NumPy >= 1.24.0
337
332
  - Matplotlib >= 3.7.0
338
333
  - SciPy >= 1.10.0
@@ -591,6 +586,50 @@ See `examples/vector_graphics_xy_mode.py` for programmatic usage and animation e
591
586
  - I2C, SPI, UART, CAN, LIN decoding
592
587
  - Packet analysis and export
593
588
 
589
+ ## Web Gateway (beta)
590
+
591
+ Control instruments from any browser on your LAN:
592
+
593
+ ```bash
594
+ pip install scpi-instrument-control[web] # includes the browser gateway
595
+ scpi-web --host 0.0.0.0 --port 8765
596
+ ```
597
+
598
+ Open `http://<gateway-pc>:8765`. Sessions can target real scopes by IP or a
599
+ built-in mock (`mock: true`) for hardware-free use. The API is documented at
600
+ `/docs` (OpenAPI). No authentication in this release — bind to `127.0.0.1`
601
+ (the default) unless your LAN is trusted.
602
+
603
+ Full documentation: [Web Gateway guide](https://little-did-I-know.github.io/SCPI-Instrument-Control/gateway/) — overview, browser UI tour, and the complete REST & WebSocket API reference.
604
+
605
+ - `GET /api/discover` scans the gateway's subnet (or `?cidr=…`) for SCPI
606
+ instruments on port 5025 and lists them with model and dialect — handy when
607
+ DHCP moves your instruments around.
608
+ - `GET .../scope/screenshot.png` — the instrument's display as a PNG
609
+ - `GET .../scope/waveform?channels=1,2&max_points=N` — waveform data as JSON
610
+ - `GET/PATCH .../scope/math/{1,2}` — software math channels (streamed as M1/M2 traces)
611
+ - `GET .../scope/measurements` — the current measurement selection
612
+ - `GET/PATCH .../scope/spectrum` — server-computed FFT spectrum (streamed as `spectrum` frames)
613
+ - `GET .../scope/filters` + `PATCH .../scope/filters/{1,2}` — software Butterworth filters (streamed as F1/F2 traces)
614
+ - `GET/POST/DELETE .../scope/references` + `GET/PUT .../scope/reference` — saved reference waveforms and the live overlay
615
+ - `POST .../scope/log/start` / `POST .../scope/log/stop` — record the selected measurements (~1 Hz) server-side
616
+ - `GET .../scope/log`, `GET .../scope/log/data?since=`, `GET .../scope/log.csv` — recording status, rows, and CSV export
617
+
618
+ ### Browser UI
619
+
620
+ ```bash
621
+ make webapp-install # once
622
+ make webapp-build # build the UI into the server
623
+ scpi-web --host 0.0.0.0 # serve API + UI on one port
624
+ ```
625
+
626
+ Open `http://<gateway-pc>:8765`. For UI development, run `scpi-web` in one
627
+ terminal and `cd webapp/app && npm run dev` in another — Vite proxies `/api`
628
+ (HTTP and WebSocket) to the gateway with hot reload.
629
+
630
+ The home screen scans your LAN and lists instruments to connect to, resume, or
631
+ open a shared session on — plus manual IP and a hardware-free mock.
632
+
594
633
  ## API Documentation
595
634
 
596
635
  ### Oscilloscope
@@ -764,18 +803,33 @@ See the `examples/` directory for complete working examples:
764
803
 
765
804
  ## Supported Models
766
805
 
767
- ### Fully Tested
806
+ ### Siglent (Fully Tested)
768
807
 
769
808
  - **SDS800X HD Series**: SDS804X HD, SDS824X HD
770
809
  - **SDS1000X-E Series**: SDS1102X-E, SDS1104X-E, SDS1202X-E, SDS1204X-E
771
810
  - **SDS2000X Plus Series**: SDS2104X+, SDS2204X+, SDS2354X+
772
811
  - **SDS5000X Series**: SDS5034X, SDS5054X, SDS5104X
773
812
 
813
+ ### Tektronix and LeCroy (core control + measurements)
814
+
815
+ - **Tektronix TBS1000C Series**: TBS1102C
816
+ - **Tektronix 2 Series MSO**: MSO24
817
+ - **Tektronix 4 Series MSO**: MSO44, MSO46
818
+ - **Tektronix 5 Series MSO**: MSO54, MSO56, MSO58, MSO58LP
819
+ - **Tektronix 6 Series MSO**: MSO64
820
+ - **LeCroy WaveSurfer 3000z Series**: WaveSurfer 3024z
821
+ - **LeCroy WaveRunner 8000 Series**: WaveRunner 8104
822
+
823
+ All Tektronix MSO models (2/4/5/6 Series) share one command variant and
824
+ support automated measurements — see the [SCPI Dialects guide](https://little-did-I-know.github.io/SCPI-Instrument-Control/user-guide/scpi-dialects/) for the full per-vendor gap list.
825
+
826
+ Command tables were verified command-by-command against the vendor programmer manuals (Tektronix TBS1000C, 2 Series MSO, and 4/5/6 Series MSO/6 Series LPD manuals; the Teledyne LeCroy MAUI Remote Control and Automation Manual) and exercised against a dialect-aware mock; not yet run against real Tektronix or LeCroy hardware.
827
+
774
828
  ### Compatibility
775
829
 
776
- Should work with other Siglent oscilloscopes that support SCPI commands over Ethernet. Model-specific features are auto-detected via the `ModelCapability` registry.
830
+ Should work with other Siglent oscilloscopes that support SCPI commands over Ethernet. Model-specific features are auto-detected via the `ModelCapability` registry. Unrecognized Tektronix or LeCroy models fall back to a conservative generic profile for that vendor (with a logged warning) rather than being rejected outright.
777
831
 
778
- **Note**: Some SCPI commands vary between models. The library includes model-specific command variants for HD, X, and Plus series.
832
+ **Note**: Some SCPI commands vary between models. The library includes model-specific command variants for HD, X, and Plus series (Siglent) and for TBS vs. MSO (2/4/5/6 Series share one variant) (Tektronix).
779
833
 
780
834
  ## Contributing
781
835