Repository: pymeasure/pymeasure (language: python)

Issue:
Allow usage of "VBS" commands for LeCroy / Teledyne oscilloscopes
The "MAUI" class oscilloscopes mentions "VBS" commands:
![image](https://github.com/user-attachments/assets/67bfeaca-1e92-4eaf-b5c8-675318e47ea5)


(The full manual: https://cdn.teledynelecroy.com/files/manuals/maui-remote-control-and-automation-manual.pdf)

Nowhere it is explained clearly what this refers to, but I think it's [VBScript](https://en.wikipedia.org/wiki/VBScript) (Microsoft Visual Basic Scripting Edition)?

I can't find any mention of it in the docs, it would be nice to be included for the Teledyne oscilloscopes.

The Teledyne official package does support it:
```python
        print('Trying to make a connection to ', connection_string)
        dso = LeCroyDSO(ActiveDSO(connection_string))
        
        # ...

        # query the value
        response = dso.query('C1:VDIV?')
        print(response)

        # query it VBS style
        vbs_response = dso.query_vbs('app.Acquisition.C1.VerScale')
        print(vbs_response)
```
([full example](https://lecroydso.readthedocs.io/en/latest/introduction/otherexamples.html))


Discussion / hints:
The most important question is: Can you do it with the normal serial communication or do you need another connection type?

Thanks for your idea.

Generally we are glad for better device usage.
I think no other connection is needed. I have a draft ready on my PC, I just need to borrow the company's Teledyne to test it out. If it works I'll create the PR.
Ok.
Thanks for improving and expanding pymeasure.

Fix patch:
diff --git a/pymeasure/instruments/teledyne/teledyneMAUI.py b/pymeasure/instruments/teledyne/teledyneMAUI.py
index 1160c465a0..c8e9decc34 100644
--- a/pymeasure/instruments/teledyne/teledyneMAUI.py
+++ b/pymeasure/instruments/teledyne/teledyneMAUI.py
@@ -101,8 +101,11 @@ class TeledyneMAUI(TeledyneOscilloscope):
     The manual detailing the API is "MAUI Oscilloscopes Remote Control and Automation Manual"
     (`link`_).
 
+    This class of Teledyne oscilloscopes also support direct VBS commands.
+    See :meth:`~vbs_ask` and :meth:`~vbs_write`.
+
     .. _link: https://cdn.teledynelecroy.com/files/manuals/
-              maui-remote-control-automation_27jul22.pdf
+              maui-remote-control-and-automation-manual.pdf
     """
 
     ch_1 = Instrument.ChannelCreator(TeledyneMAUIChannel, 1)
@@ -116,6 +119,40 @@ class TeledyneMAUI(TeledyneOscilloscope):
     # Change listed values for existing commands:
     bwlimit_values = TeledyneMAUIChannel.BANDWIDTH_LIMITS
 
+    def vbs_write(self, message: str):
+        """Write a VBS command directly to the device.
+
+        This class of oscilloscopes also allows the direct usage of Visual Basic
+        Scripting (VBScript). With this method a literal VBS command is sent.
+        You can use the 'MAUI Browser' on the oscilloscope to list all available
+        variables.
+
+        A very basic example of usage:
+
+        .. code:: python
+
+           instrument.vbs_write("app.Display.GridMode = Dual")
+        """
+        query = f"VBS '{message}'"
+        self.write(query)
+
+    def vbs_ask(self, name: str) -> str:
+        """Return the value of a VBS variable.
+
+        Only the target needs to be specified, a query is formatted by this method.
+        Note: the target name is not escaped!
+
+        See :meth:`~vbs_write` for more info.
+
+        A very basic example of usage:
+
+        .. code:: python
+
+           instrument.vbs_ask("app.Display.GridMode")
+        """
+        query = f"VBS? 'Return={name}'"
+        return self.ask(query)
+
     ###############
     #   Trigger   #
     ###############


Test patch:
diff --git a/tests/instruments/teledyne/test_teledyneMAUI.py b/tests/instruments/teledyne/test_teledyneMAUI.py
index 84f8cf702c..25ec52386e 100644
--- a/tests/instruments/teledyne/test_teledyneMAUI.py
+++ b/tests/instruments/teledyne/test_teledyneMAUI.py
@@ -117,5 +117,17 @@ def test_attenuation():
         assert instr.ch_1.probe_attenuation == 0.1
 
 
+def test_vbs():
+    with expected_protocol(
+        TeledyneMAUI,
+        [(b"CHDR OFF", None),
+         (b"VBS 'my_command(x)'", None),
+         (b"VBS? 'Return=my_var'", b"0\n"),
+         ]
+    ) as instr:
+        instr.vbs_write("my_command(x)")
+        assert instr.vbs_ask("my_var") == "0\n"
+
+
 if __name__ == '__main__':
     pytest.main()
diff --git a/tests/instruments/teledyne/test_teledyneMAUI_with_device.py b/tests/instruments/teledyne/test_teledyneMAUI_with_device.py
index 88305aeb94..c2c3a37e24 100644
--- a/tests/instruments/teledyne/test_teledyneMAUI_with_device.py
+++ b/tests/instruments/teledyne/test_teledyneMAUI_with_device.py
@@ -309,6 +309,12 @@ def test_trigger_setup(self, resetted_instrument):
         resetted_instrument.trigger_setup(**expected)
         assert resetted_instrument.trigger == expected
 
+    def test_vbs(self, resetted_instrument):
+        """Test reading and writing values through the VBS interface."""
+        resetted_instrument.vbs_write("app.Acquisition.C1.VerScale=0.01")
+        val = resetted_instrument.vbs_ask("app.Acquisition.C1.VerScale")
+        assert val == "0.01\n"
+
 
 if __name__ == "__main__":
     pytest.main()