SCPI-Instrument-Control 1.1.0__tar.gz → 2.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 (176) hide show
  1. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/CHANGELOG.md +59 -1
  2. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/MANIFEST.in +3 -1
  3. {scpi_instrument_control-1.1.0/SCPI_Instrument_Control.egg-info → scpi_instrument_control-2.0.0}/PKG-INFO +59 -18
  4. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/README.md +50 -13
  5. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0/SCPI_Instrument_Control.egg-info}/PKG-INFO +59 -18
  6. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/SCPI_Instrument_Control.egg-info/SOURCES.txt +16 -2
  7. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/SCPI_Instrument_Control.egg-info/entry_points.txt +1 -0
  8. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/SCPI_Instrument_Control.egg-info/requires.txt +8 -2
  9. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/SCPI_Instrument_Control.egg-info/top_level.txt +0 -1
  10. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/README.md +2 -2
  11. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/function_generator_basic.py +2 -2
  12. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/pyproject.toml +15 -10
  13. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/__init__.py +1 -1
  14. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/automation.py +28 -12
  15. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/channel.py +30 -18
  16. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/connection/base.py +4 -0
  17. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/connection/mock.py +206 -45
  18. scpi_instrument_control-2.0.0/scpi_control/connection/socket.py +302 -0
  19. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/connection/visa_connection.py +7 -5
  20. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/function_generator.py +4 -4
  21. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/app.py +4 -4
  22. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/connection_manager.py +7 -7
  23. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/main_window.py +15 -19
  24. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/daq_ai_panel.py +2 -4
  25. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/daq_data_view.py +2 -4
  26. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/daq_scan_config.py +4 -8
  27. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/math_panel.py +2 -4
  28. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/psu_control.py +2 -4
  29. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/terminal_widget.py +10 -20
  30. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/timebase_control.py +4 -8
  31. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/vector_graphics_panel.py +2 -2
  32. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/models.py +21 -0
  33. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/oscilloscope.py +51 -21
  34. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/power_supply.py +5 -5
  35. scpi_instrument_control-2.0.0/scpi_control/scpi_commands.py +339 -0
  36. scpi_instrument_control-2.0.0/scpi_control/server/__init__.py +0 -0
  37. scpi_instrument_control-2.0.0/scpi_control/server/__main__.py +19 -0
  38. scpi_instrument_control-2.0.0/scpi_control/server/api/__init__.py +0 -0
  39. scpi_instrument_control-2.0.0/scpi_control/server/api/discovery.py +35 -0
  40. scpi_instrument_control-2.0.0/scpi_control/server/api/scope.py +467 -0
  41. scpi_instrument_control-2.0.0/scpi_control/server/api/sessions.py +50 -0
  42. scpi_instrument_control-2.0.0/scpi_control/server/api/stream.py +103 -0
  43. scpi_instrument_control-2.0.0/scpi_control/server/app.py +91 -0
  44. scpi_instrument_control-2.0.0/scpi_control/server/compute.py +109 -0
  45. scpi_instrument_control-2.0.0/scpi_control/server/discovery.py +126 -0
  46. scpi_instrument_control-2.0.0/scpi_control/server/recorder.py +66 -0
  47. scpi_instrument_control-2.0.0/scpi_control/server/schemas.py +113 -0
  48. scpi_instrument_control-2.0.0/scpi_control/server/sessions.py +392 -0
  49. scpi_instrument_control-2.0.0/scpi_control/server/static/assets/index-0Vpguwg6.js +9 -0
  50. scpi_instrument_control-2.0.0/scpi_control/server/static/assets/index-CyUPLIHk.css +1 -0
  51. scpi_instrument_control-2.0.0/scpi_control/server/static/index.html +13 -0
  52. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/trigger.py +88 -44
  53. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/vector_graphics.py +3 -2
  54. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/waveform.py +27 -9
  55. scpi_instrument_control-1.1.0/scpi_control/connection/socket.py +0 -211
  56. scpi_instrument_control-1.1.0/scpi_control/scpi_commands.py +0 -206
  57. scpi_instrument_control-1.1.0/siglent/__init__.py +0 -35
  58. scpi_instrument_control-1.1.0/siglent/exceptions.py +0 -40
  59. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/LICENSE +0 -0
  60. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/SCPI_Instrument_Control.egg-info/dependency_links.txt +0 -0
  61. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/docs/SDS800XHD_Series_ProgrammingGuide_EN11G.pdf +0 -0
  62. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/docs/VISUAL_MEASUREMENTS.md +0 -0
  63. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/docs/images/01_main_window.png +0 -0
  64. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/docs/images/channel_controls.png +0 -0
  65. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/docs/images/cursors.png +0 -0
  66. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/docs/images/fft_analysis.png +0 -0
  67. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/docs/images/main_window.png +0 -0
  68. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/docs/images/measurements_panel.png +0 -0
  69. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/docs/images/visual_measurements.png +0 -0
  70. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/advanced_analysis.py +0 -0
  71. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/basic_usage.py +0 -0
  72. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/batch_capture.py +0 -0
  73. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/continuous_capture.py +0 -0
  74. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/data_logger_basic.py +0 -0
  75. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/live_plot.py +0 -0
  76. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/measurements.py +0 -0
  77. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/probe_calibration_analysis.py +0 -0
  78. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/psu_advanced_features.py +0 -0
  79. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/psu_basic_control.py +0 -0
  80. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/psu_gui_test.py +0 -0
  81. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/psu_usb_connection.py +0 -0
  82. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/report_generation_example.py +0 -0
  83. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/simple_capture.py +0 -0
  84. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/trigger_based_capture.py +0 -0
  85. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/vector_graphics_xy_mode.py +0 -0
  86. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/examples/waveform_capture.py +0 -0
  87. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/resources/Test Equipment Wide.png +0 -0
  88. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/resources/Test Equipment.icns +0 -0
  89. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/resources/Test Equipment.ico +0 -0
  90. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/resources/Test Equipment.png +0 -0
  91. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/analysis.py +0 -0
  92. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/awg_models.py +0 -0
  93. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/awg_output.py +0 -0
  94. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/awg_scpi_commands.py +0 -0
  95. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/connection/__init__.py +0 -0
  96. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/daq_models.py +0 -0
  97. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/daq_scpi_commands.py +0 -0
  98. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/data_logger.py +0 -0
  99. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/exceptions.py +0 -0
  100. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/__init__.py +0 -0
  101. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/daq_worker.py +0 -0
  102. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/live_view_worker.py +0 -0
  103. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/utils/validators.py +0 -0
  104. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/vnc_window.py +0 -0
  105. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/waveform_capture_worker.py +0 -0
  106. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/__init__.py +0 -0
  107. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/channel_control.py +0 -0
  108. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/cursor_panel.py +0 -0
  109. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/daq_channel_config.py +0 -0
  110. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/data_logger_control.py +0 -0
  111. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/error_dialog.py +0 -0
  112. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/fft_display.py +0 -0
  113. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/measurement_marker.py +0 -0
  114. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/measurement_markers/__init__.py +0 -0
  115. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/measurement_markers/frequency_marker.py +0 -0
  116. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/measurement_markers/timing_marker.py +0 -0
  117. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/measurement_markers/voltage_marker.py +0 -0
  118. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/measurement_panel.py +0 -0
  119. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/protocol_decode_panel.py +0 -0
  120. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/reference_panel.py +0 -0
  121. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/scope_web_view.py +0 -0
  122. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/trigger_control.py +0 -0
  123. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/visual_measurement_panel.py +0 -0
  124. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/waveform_display.py +0 -0
  125. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/gui/widgets/waveform_display_pg.py +0 -0
  126. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/math_channel.py +0 -0
  127. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/measurement.py +0 -0
  128. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/measurement_config.py +0 -0
  129. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/power_supply_output.py +0 -0
  130. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/protocol_decode.py +0 -0
  131. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/protocol_decoders/__init__.py +0 -0
  132. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/protocol_decoders/i2c_decoder.py +0 -0
  133. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/protocol_decoders/spi_decoder.py +0 -0
  134. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/protocol_decoders/uart_decoder.py +0 -0
  135. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/psu_data_logger.py +0 -0
  136. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/psu_models.py +0 -0
  137. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/psu_scpi_commands.py +0 -0
  138. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/py.typed +0 -0
  139. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/reference_waveform.py +0 -0
  140. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/__init__.py +0 -0
  141. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/app.py +0 -0
  142. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/generators/__init__.py +0 -0
  143. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/generators/base.py +0 -0
  144. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/generators/markdown_generator.py +0 -0
  145. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/generators/pdf_generator.py +0 -0
  146. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/llm/__init__.py +0 -0
  147. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/llm/analyzer.py +0 -0
  148. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/llm/client.py +0 -0
  149. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/llm/context_builder.py +0 -0
  150. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/llm/daq_analyzer.py +0 -0
  151. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/llm/daq_context_builder.py +0 -0
  152. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/llm/daq_prompts.py +0 -0
  153. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/llm/prompts.py +0 -0
  154. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/main_window.py +0 -0
  155. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/models/__init__.py +0 -0
  156. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/models/app_settings.py +0 -0
  157. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/models/criteria.py +0 -0
  158. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/models/plot_style.py +0 -0
  159. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/models/report_data.py +0 -0
  160. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/models/report_options.py +0 -0
  161. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/models/template.py +0 -0
  162. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/models/test_types.py +0 -0
  163. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/utils/__init__.py +0 -0
  164. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/utils/image_handler.py +0 -0
  165. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/utils/waveform_analyzer.py +0 -0
  166. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/utils/waveform_loader.py +0 -0
  167. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/widgets/__init__.py +0 -0
  168. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/widgets/ai_analysis_panel.py +0 -0
  169. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/widgets/chat_sidebar.py +0 -0
  170. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/widgets/llm_settings_dialog.py +0 -0
  171. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/widgets/metadata_panel.py +0 -0
  172. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/widgets/pdf_preview_dialog.py +0 -0
  173. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/widgets/report_options_dialog.py +0 -0
  174. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/report_generator/widgets/template_manager_dialog.py +0 -0
  175. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/scpi_control/screen_capture.py +0 -0
  176. {scpi_instrument_control-1.1.0 → scpi_instrument_control-2.0.0}/setup.cfg +0 -0
@@ -7,15 +7,73 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.0.0] - 2026-07-15
10
11
 
11
- ## [1.0.1] - 2026-01-07
12
+ ### ⚠️ Breaking Changes
13
+
14
+ - **Removed the `siglent` compatibility shim.** `import siglent` now raises
15
+ `ModuleNotFoundError`; use `import scpi_control` (identical API). The shim
16
+ had emitted a `DeprecationWarning` since 1.0.0, which announced its removal
17
+ in v2.0.0. If you cannot migrate yet, pin `SCPI-Instrument-Control<2.0`.
18
+ - **Python 3.9+ required** (was 3.8+; Python 3.8 reached end of life in
19
+ October 2024). CI now tests Python 3.9 through 3.14.
12
20
 
13
21
  ### Added
14
22
 
23
+ - **Browser-based lab gateway** (`pip install "SCPI-Instrument-Control[web]"`,
24
+ then `scpi-web` or `python -m scpi_control.server`): a FastAPI server that
25
+ manages named multi-instrument sessions and serves a React UI to any
26
+ browser on the LAN. Mock-first — every feature works against the built-in
27
+ mock scope (`mock: true`).
28
+ - Live waveform streaming over WebSocket, with channel, timebase, trigger,
29
+ and acquisition (run/stop/single/auto) controls
30
+ - LAN instrument discovery and a dashboard-style home screen
31
+ - Measurements with live values and cross-tab-synchronized selection
32
+ - Software math channels (M1/M2) streamed as canvas traces
33
+ - SCPI terminal, instrument screenshot PNG, full-resolution waveform
34
+ export as CSV and JSON
35
+ - FFT spectrum view computed server-side from full-resolution data
36
+ (window selection, peak markers, THD readout)
37
+ - Software Butterworth filters (lowpass/highpass/bandpass) streamed as
38
+ F1/F2 traces
39
+ - Reference waveforms: save named snapshots, ghost overlay on the canvas,
40
+ live correlation and max-deviation statistics
41
+ - Measurement trend recording: server-side ring buffer at ~1 Hz, live
42
+ trend chart, CSV export; the measurement selection locks while recording
43
+ - Dual-dialect SCPI support: legacy (e.g. SDS1104X-E) and modern
44
+ (e.g. SDS800X HD) Siglent command sets behind one API, auto-detected from
45
+ `*IDN?` with a manual override
46
+
15
47
  ### Changed
16
48
 
49
+ - Connection layer hardened: thread-safe socket handling, exact-length
50
+ binary reads, default SCPI port 5025
51
+ - `wait_for_trigger` honors a user-configured NORMAL trigger mode instead of
52
+ forcing SINGLE
53
+ - Black formatting standardized on the 26.x stable style; dev extra now
54
+ requires `black>=26.5,<27` (installed on Python >= 3.10, where Black 26 is available)
55
+ - Removed the unused `uplot` frontend dependency (the UI draws on a
56
+ hand-rolled canvas)
57
+
17
58
  ### Fixed
18
59
 
60
+ - Mock-fidelity and hardware-behavior fixes from the 2026-07 code audit
61
+ (trigger vocabulary mapping, waveform preamble parsing, measurement
62
+ timeout handling, and related issues)
63
+
64
+ ## [1.1.0] - 2026-01-12
65
+
66
+ ### Added
67
+
68
+ - Data acquisition / data logger instrument support (`DataLogger`): Keysight
69
+ 34970A/DAQ970A-style SCPI units — DMM function configuration (V/I/R/
70
+ temperature), scan lists, triggering, alarms, channel scaling, and timed
71
+ logging helpers (PR #39)
72
+
73
+ ## [1.0.1] - 2026-01-07
74
+
75
+ Packaging and metadata fixes for the 1.0.0 rename release; no functional changes.
76
+
19
77
  ## [1.0.0] - 2026-01-06
20
78
 
21
79
  ### ⚠️ MAJOR RELEASE - Package Renamed
@@ -7,12 +7,14 @@ include pyproject.toml
7
7
  # Include user-facing documentation
8
8
  recursive-include docs/images *.png *.jpg
9
9
  include docs/VISUAL_MEASUREMENTS.md
10
- include docs/SCREENSHOT_GUIDE.md
11
10
  include docs/SDS800XHD_Series_ProgrammingGuide_EN11G.pdf
12
11
 
13
12
  # Include resources (logos, icons)
14
13
  recursive-include resources *.png *.ico *.icns
15
14
 
15
+ # Include web gateway frontend build output (when present)
16
+ recursive-include scpi_control/server/static *
17
+
16
18
  # Include examples
17
19
  recursive-include examples *.py
18
20
  recursive-include examples *.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: SCPI-Instrument-Control
3
- Version: 1.1.0
3
+ Version: 2.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"
@@ -312,7 +316,7 @@ pip install "SCPI-Instrument-Control[all]"
312
316
 
313
317
  #### 2. Update Your Import Statements
314
318
 
315
- **Old imports** (deprecated but still work):
319
+ **Old imports** (no longer work as of v2.0.0):
316
320
 
317
321
  ```python
318
322
  from siglent import Oscilloscope, PowerSupply, FunctionGenerator
@@ -330,16 +334,11 @@ from scpi_control.waveform import Waveform
330
334
 
331
335
  #### 3. Backward Compatibility
332
336
 
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.
337
+ The `siglent` compatibility shim was removed in **v2.0.0** (it had emitted a
338
+ `DeprecationWarning` since v1.0.0). `import siglent` now raises
339
+ `ModuleNotFoundError` update your imports to `scpi_control` as shown above;
340
+ the API is otherwise identical. If you cannot migrate yet, pin
341
+ `SCPI-Instrument-Control<2.0`.
343
342
 
344
343
  #### 4. Command-Line Tools
345
344
 
@@ -357,7 +356,7 @@ No changes needed to scripts or automation that invoke these commands.
357
356
  | Old | New | Status |
358
357
  |-----|-----|--------|
359
358
  | PyPI package: `siglent` | PyPI package: `SCPI-Instrument-Control` | **Changed** |
360
- | `import siglent` | `import scpi_control` | **Recommended** |
359
+ | `import siglent` | `import scpi_control` | **Required since v2.0.0** |
361
360
  | `siglent-gui` command | `siglent-gui` command | **Unchanged** |
362
361
  | `siglent-report-generator` command | `siglent-report-generator` command | **Unchanged** |
363
362
 
@@ -422,7 +421,7 @@ main()
422
421
 
423
422
  ### Core Library
424
423
 
425
- - Python 3.8+
424
+ - Python 3.9+
426
425
  - NumPy >= 1.24.0
427
426
  - Matplotlib >= 3.7.0
428
427
  - SciPy >= 1.10.0
@@ -681,6 +680,48 @@ See `examples/vector_graphics_xy_mode.py` for programmatic usage and animation e
681
680
  - I2C, SPI, UART, CAN, LIN decoding
682
681
  - Packet analysis and export
683
682
 
683
+ ## Web Gateway (beta)
684
+
685
+ Control instruments from any browser on your LAN:
686
+
687
+ ```bash
688
+ pip install scpi-instrument-control[web] # includes the browser gateway
689
+ scpi-web --host 0.0.0.0 --port 8765
690
+ ```
691
+
692
+ Open `http://<gateway-pc>:8765`. Sessions can target real scopes by IP or a
693
+ built-in mock (`mock: true`) for hardware-free use. The API is documented at
694
+ `/docs` (OpenAPI). No authentication in this release — bind to `127.0.0.1`
695
+ (the default) unless your LAN is trusted.
696
+
697
+ - `GET /api/discover` scans the gateway's subnet (or `?cidr=…`) for SCPI
698
+ instruments on port 5025 and lists them with model and dialect — handy when
699
+ DHCP moves your instruments around.
700
+ - `GET .../scope/screenshot.png` — the instrument's display as a PNG
701
+ - `GET .../scope/waveform?channels=1,2&max_points=N` — waveform data as JSON
702
+ - `GET/PATCH .../scope/math/{1,2}` — software math channels (streamed as M1/M2 traces)
703
+ - `GET .../scope/measurements` — the current measurement selection
704
+ - `GET/PATCH .../scope/spectrum` — server-computed FFT spectrum (streamed as `spectrum` frames)
705
+ - `GET .../scope/filters` + `PATCH .../scope/filters/{1,2}` — software Butterworth filters (streamed as F1/F2 traces)
706
+ - `GET/POST/DELETE .../scope/references` + `GET/PUT .../scope/reference` — saved reference waveforms and the live overlay
707
+ - `POST .../scope/log/start` / `POST .../scope/log/stop` — record the selected measurements (~1 Hz) server-side
708
+ - `GET .../scope/log`, `GET .../scope/log/data?since=`, `GET .../scope/log.csv` — recording status, rows, and CSV export
709
+
710
+ ### Browser UI
711
+
712
+ ```bash
713
+ make webapp-install # once
714
+ make webapp-build # build the UI into the server
715
+ scpi-web --host 0.0.0.0 # serve API + UI on one port
716
+ ```
717
+
718
+ Open `http://<gateway-pc>:8765`. For UI development, run `scpi-web` in one
719
+ terminal and `cd webapp/app && npm run dev` in another — Vite proxies `/api`
720
+ (HTTP and WebSocket) to the gateway with hot reload.
721
+
722
+ The home screen scans your LAN and lists instruments to connect to, resume, or
723
+ open a shared session on — plus manual IP and a hardware-free mock.
724
+
684
725
  ## API Documentation
685
726
 
686
727
  ### Oscilloscope
@@ -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,48 @@ 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
+ - `GET /api/discover` scans the gateway's subnet (or `?cidr=…`) for SCPI
604
+ instruments on port 5025 and lists them with model and dialect — handy when
605
+ DHCP moves your instruments around.
606
+ - `GET .../scope/screenshot.png` — the instrument's display as a PNG
607
+ - `GET .../scope/waveform?channels=1,2&max_points=N` — waveform data as JSON
608
+ - `GET/PATCH .../scope/math/{1,2}` — software math channels (streamed as M1/M2 traces)
609
+ - `GET .../scope/measurements` — the current measurement selection
610
+ - `GET/PATCH .../scope/spectrum` — server-computed FFT spectrum (streamed as `spectrum` frames)
611
+ - `GET .../scope/filters` + `PATCH .../scope/filters/{1,2}` — software Butterworth filters (streamed as F1/F2 traces)
612
+ - `GET/POST/DELETE .../scope/references` + `GET/PUT .../scope/reference` — saved reference waveforms and the live overlay
613
+ - `POST .../scope/log/start` / `POST .../scope/log/stop` — record the selected measurements (~1 Hz) server-side
614
+ - `GET .../scope/log`, `GET .../scope/log/data?since=`, `GET .../scope/log.csv` — recording status, rows, and CSV export
615
+
616
+ ### Browser UI
617
+
618
+ ```bash
619
+ make webapp-install # once
620
+ make webapp-build # build the UI into the server
621
+ scpi-web --host 0.0.0.0 # serve API + UI on one port
622
+ ```
623
+
624
+ Open `http://<gateway-pc>:8765`. For UI development, run `scpi-web` in one
625
+ terminal and `cd webapp/app && npm run dev` in another — Vite proxies `/api`
626
+ (HTTP and WebSocket) to the gateway with hot reload.
627
+
628
+ The home screen scans your LAN and lists instruments to connect to, resume, or
629
+ open a shared session on — plus manual IP and a hardware-free mock.
630
+
594
631
  ## API Documentation
595
632
 
596
633
  ### Oscilloscope
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: SCPI-Instrument-Control
3
- Version: 1.1.0
3
+ Version: 2.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"
@@ -312,7 +316,7 @@ pip install "SCPI-Instrument-Control[all]"
312
316
 
313
317
  #### 2. Update Your Import Statements
314
318
 
315
- **Old imports** (deprecated but still work):
319
+ **Old imports** (no longer work as of v2.0.0):
316
320
 
317
321
  ```python
318
322
  from siglent import Oscilloscope, PowerSupply, FunctionGenerator
@@ -330,16 +334,11 @@ from scpi_control.waveform import Waveform
330
334
 
331
335
  #### 3. Backward Compatibility
332
336
 
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.
337
+ The `siglent` compatibility shim was removed in **v2.0.0** (it had emitted a
338
+ `DeprecationWarning` since v1.0.0). `import siglent` now raises
339
+ `ModuleNotFoundError` update your imports to `scpi_control` as shown above;
340
+ the API is otherwise identical. If you cannot migrate yet, pin
341
+ `SCPI-Instrument-Control<2.0`.
343
342
 
344
343
  #### 4. Command-Line Tools
345
344
 
@@ -357,7 +356,7 @@ No changes needed to scripts or automation that invoke these commands.
357
356
  | Old | New | Status |
358
357
  |-----|-----|--------|
359
358
  | PyPI package: `siglent` | PyPI package: `SCPI-Instrument-Control` | **Changed** |
360
- | `import siglent` | `import scpi_control` | **Recommended** |
359
+ | `import siglent` | `import scpi_control` | **Required since v2.0.0** |
361
360
  | `siglent-gui` command | `siglent-gui` command | **Unchanged** |
362
361
  | `siglent-report-generator` command | `siglent-report-generator` command | **Unchanged** |
363
362
 
@@ -422,7 +421,7 @@ main()
422
421
 
423
422
  ### Core Library
424
423
 
425
- - Python 3.8+
424
+ - Python 3.9+
426
425
  - NumPy >= 1.24.0
427
426
  - Matplotlib >= 3.7.0
428
427
  - SciPy >= 1.10.0
@@ -681,6 +680,48 @@ See `examples/vector_graphics_xy_mode.py` for programmatic usage and animation e
681
680
  - I2C, SPI, UART, CAN, LIN decoding
682
681
  - Packet analysis and export
683
682
 
683
+ ## Web Gateway (beta)
684
+
685
+ Control instruments from any browser on your LAN:
686
+
687
+ ```bash
688
+ pip install scpi-instrument-control[web] # includes the browser gateway
689
+ scpi-web --host 0.0.0.0 --port 8765
690
+ ```
691
+
692
+ Open `http://<gateway-pc>:8765`. Sessions can target real scopes by IP or a
693
+ built-in mock (`mock: true`) for hardware-free use. The API is documented at
694
+ `/docs` (OpenAPI). No authentication in this release — bind to `127.0.0.1`
695
+ (the default) unless your LAN is trusted.
696
+
697
+ - `GET /api/discover` scans the gateway's subnet (or `?cidr=…`) for SCPI
698
+ instruments on port 5025 and lists them with model and dialect — handy when
699
+ DHCP moves your instruments around.
700
+ - `GET .../scope/screenshot.png` — the instrument's display as a PNG
701
+ - `GET .../scope/waveform?channels=1,2&max_points=N` — waveform data as JSON
702
+ - `GET/PATCH .../scope/math/{1,2}` — software math channels (streamed as M1/M2 traces)
703
+ - `GET .../scope/measurements` — the current measurement selection
704
+ - `GET/PATCH .../scope/spectrum` — server-computed FFT spectrum (streamed as `spectrum` frames)
705
+ - `GET .../scope/filters` + `PATCH .../scope/filters/{1,2}` — software Butterworth filters (streamed as F1/F2 traces)
706
+ - `GET/POST/DELETE .../scope/references` + `GET/PUT .../scope/reference` — saved reference waveforms and the live overlay
707
+ - `POST .../scope/log/start` / `POST .../scope/log/stop` — record the selected measurements (~1 Hz) server-side
708
+ - `GET .../scope/log`, `GET .../scope/log/data?since=`, `GET .../scope/log.csv` — recording status, rows, and CSV export
709
+
710
+ ### Browser UI
711
+
712
+ ```bash
713
+ make webapp-install # once
714
+ make webapp-build # build the UI into the server
715
+ scpi-web --host 0.0.0.0 # serve API + UI on one port
716
+ ```
717
+
718
+ Open `http://<gateway-pc>:8765`. For UI development, run `scpi-web` in one
719
+ terminal and `cd webapp/app && npm run dev` in another — Vite proxies `/api`
720
+ (HTTP and WebSocket) to the gateway with hot reload.
721
+
722
+ The home screen scans your LAN and lists instruments to connect to, resume, or
723
+ open a shared session on — plus manual IP and a hardware-free mock.
724
+
684
725
  ## API Documentation
685
726
 
686
727
  ### Oscilloscope
@@ -152,5 +152,19 @@ scpi_control/report_generator/widgets/metadata_panel.py
152
152
  scpi_control/report_generator/widgets/pdf_preview_dialog.py
153
153
  scpi_control/report_generator/widgets/report_options_dialog.py
154
154
  scpi_control/report_generator/widgets/template_manager_dialog.py
155
- siglent/__init__.py
156
- siglent/exceptions.py
155
+ scpi_control/server/__init__.py
156
+ scpi_control/server/__main__.py
157
+ scpi_control/server/app.py
158
+ scpi_control/server/compute.py
159
+ scpi_control/server/discovery.py
160
+ scpi_control/server/recorder.py
161
+ scpi_control/server/schemas.py
162
+ scpi_control/server/sessions.py
163
+ scpi_control/server/api/__init__.py
164
+ scpi_control/server/api/discovery.py
165
+ scpi_control/server/api/scope.py
166
+ scpi_control/server/api/sessions.py
167
+ scpi_control/server/api/stream.py
168
+ scpi_control/server/static/index.html
169
+ scpi_control/server/static/assets/index-0Vpguwg6.js
170
+ scpi_control/server/static/assets/index-CyUPLIHk.css
@@ -1,3 +1,4 @@
1
1
  [console_scripts]
2
+ scpi-web = scpi_control.server.__main__:main
2
3
  siglent-gui = scpi_control.gui.app:main
3
4
  siglent-report-generator = scpi_control.report_generator.app:main
@@ -21,11 +21,12 @@ pyinstaller>=6.0.0
21
21
  pytest>=7.0
22
22
  pytest-cov>=4.0.0
23
23
  codecov>=2.1.0
24
- black>=23.0
25
24
  flake8>=6.0
26
25
  build>=0.10.0
27
26
  twine>=4.0.0
28
- black[jupyter]>=23.0
27
+
28
+ [dev:python_version >= "3.10"]
29
+ black<27,>=26.5
29
30
 
30
31
  [docs]
31
32
  mkdocs>=1.5.0
@@ -62,3 +63,8 @@ ollama>=0.6.0
62
63
  [usb]
63
64
  pyvisa>=1.14.0
64
65
  pyvisa-py>=0.7.0
66
+
67
+ [web]
68
+ fastapi>=0.115
69
+ uvicorn[standard]>=0.30
70
+ Pillow>=10.0
@@ -232,7 +232,7 @@ collector.save_data(waveforms, 'output.mat', format='mat')
232
232
  ## Quick Start - Programmatic API
233
233
 
234
234
  ```python
235
- from siglent.automation import DataCollector
235
+ from scpi_control.automation import DataCollector
236
236
 
237
237
  # Simple capture
238
238
  with DataCollector('192.168.1.100') as collector:
@@ -245,7 +245,7 @@ with DataCollector('192.168.1.100') as collector:
245
245
  ## Tips
246
246
 
247
247
  - Make sure your oscilloscope is connected to the same network as your computer
248
- - Ensure the SCPI port (5024) is accessible
248
+ - Ensure the SCPI port (5025) is accessible
249
249
  - Some commands may vary slightly between oscilloscope models - refer to your programming manual
250
250
  - Enable at least one channel before capturing waveforms
251
251
  - Use AUTO trigger mode for continuous acquisition
@@ -11,7 +11,7 @@ Supported models:
11
11
  Requirements:
12
12
  - Function generator connected to network
13
13
  - IP address configured on generator
14
- - Default SCPI port: 5024
14
+ - Default SCPI port: 5025
15
15
 
16
16
  Usage:
17
17
  python function_generator_basic.py --ip 192.168.1.100
@@ -32,7 +32,7 @@ def main():
32
32
  """Main function to demonstrate AWG control."""
33
33
  parser = argparse.ArgumentParser(description="Control Siglent Function Generator")
34
34
  parser.add_argument("--ip", type=str, default="192.168.1.100", help="Function generator IP address")
35
- parser.add_argument("--port", type=int, default=5024, help="SCPI port (default: 5024)")
35
+ parser.add_argument("--port", type=int, default=5025, help="SCPI port (default: 5025)")
36
36
  args = parser.parse_args()
37
37
 
38
38
  logger.info(f"Connecting to function generator at {args.ip}:{args.port}")