The \gui{} contains a TCP server that can be used to control the \vna{} with SCPI commands.
\section{SCPI Server Configuration}
The server is configurable in the preferences: \menu[,]{Window,Preferences,General}
\screenshot{0.3}{serverconfig.png}
If enabled, it will accept any TCP connection at the configured port. Once the connection is established, it can be used to send SCPI commands and receive replies. Only one connection at a time is possible, if a second connection is created, the first one will be closed by the \gui{}. Alternatively, a port can be manually configured by setting the ``port'' argument:
\begin{lstlisting}
./LibreVNA-GUI --port 1234
\end{lstlisting}
This enables the SCPI server at the specified port, regardless of what is configured in the preferences (useful for starting multiple instances at different ports at the same time). If no graphical user interface is required, the \gui{} can be hidden:
\begin{lstlisting}
./LibreVNA-GUI --port 1234 --no-gui
\end{lstlisting}
\section{General Syntax}
The syntax follows the usual SCPI rules:
\begin{itemize}
\item All commands are case insensitive (implicitly converted to uppercase before evaluated)
\item The command tree is organized in branches, separated by a colon:
\query{Lists all available commands}{*LST?}{None}{List of commands, separated by newline}
\subsection{Device Commands}
This section contains general device commands, available regardless of the current mode.
\subsubsection{DEVice:DISConnect}
\event{Disconnects from the device}{DEVice:DISConnect}{None}
\subsubsection{DEVice:CONNect}
\event{Connects to a device. If no serialnumber is specified, the connection is made with the first device found}{DEVice:CONNect [<serialnumber>]}{<serialnumber> Serialnumber of the device that should be connected}
\begin{example}
:DEV:CONN 206039903350
\end{example}
\query{Queries the serial number of the connected device}{DEVice:CONNect?}{None}{<serialnumber> or ``Not connected''}
\event{Updates the firmware of the connected device}{DEVice:UPDATE <fw\_file>}{<fw\_file> Path to the firmware file}
Important points when saving/loading setup files through SCPI commands:
\begin{itemize}
\item The path must be either absolute or relative to the location of the GUI application.
\item If the LibreVNA-GUI (and thus also the SCPI server) is running on a different machine than the SCPI client, the firmware file must be stored on the machine that runs the GUI.
This command provides read/write access to the preferences. The recommended way is usually to change the preferences manually in the GUI. But if for some reason that is not an option, this is also possible through the SCPI server. There is no complete documentation for all available preferences, refer to the source code.
\event{Set a preferences entry}{DEVice:PREFerences <name> <value>}{<name> Name of the preferences entry\\ <value> New value for the preferences entry}
\begin{example}
:DEV:PREF Startup.ConnectToFirstDevice false
\end{example}
Most settings take effect immediately but some (such as changing the port for the SCPI server) are only applied when the preferences are saved. Also see command~\ref{DEV:APPLYPREF}.
\query{Returns a preferences entry}{DEVice:PREFerences? <name>}{<name> Name of the preferences entry}{Current value of the preferences entry}
\subsubsection{DEVice:APPLYPREFerences}
\label{DEV:APPLYPREF}
\event{Permanently stores the preferences after a setting has been changed}{DEVice:APPLYPREFerences}{None}
\event{Switches the device to the specified mode}{DEVice:MODE <mode>}{<mode>:\\\hspace{1cm} VNA: set to vector analyzer\\\hspace{1cm} GEN: set to signal generator\\\hspace{1cm} SA: set to spectrum analyzer}
\query{Queries the currently active mode}{DEVice:MODE?}{None}{<mode>:\\\hspace{1cm} VNA: set to vector analyzer\\\hspace{1cm} GEN: set to signal generator\\\hspace{1cm} SA: set to spectrum analyzer}
\event{Saves the GUI setup to a file}{DEVice:SETUP:SAVE}{<filename>}
Important points when saving/loading setup files through SCPI commands:
\begin{itemize}
\item Filenames must be either absolute or relative to the location of the GUI application.
\item If the LibreVNA-GUI (and thus also the SCPI server) is running on a different machine than the SCPI client, the setup files will be saved/loaded from the machine that runs the GUI.
\item If no (or a wrong) file ending is specified, ``.setup'' is automatically added to the filename.
\end{itemize}
\subsubsection{DEVice:SETUP:LOAD}
\query{Loads a setup file}{DEVice:SETUP:LOAD?}{<filename>}{TRUE or FALSE}
\begin{itemize}
\item Filenames must be either absolute or relative to the location of the GUI application.
\item The filename must include the file ending ``.setup''.
\query{Queries the (theoretical) maximum frequency when using harmonic mixing in VNA mode}{DEVice:INFo:LIMits:MAXHARMonicfrequency?}{None}{maximum frequency in Hz}
These commands change or query VNA settings. Although most of them are available regardless of the current device mode, they usually only have an effect once the VNA mode is active (e.g. it is possible to change the span while in signal generator mode but it does not effect the \vna{} until the mode is switched to VNA). Certain commands (like taking a calibration measurement) are only available in VNA mode and will return an error if another mode is active.
<acquired sweeps> resets to zero whenever a setting is changed. It is incremented at the end of each sweep, but will not go above the number of configured sweeps for the averaging.
\textbf{\# of active sweep}&\textbf{<acquired sweeps>}\\
\hline
1 & 0\\
2 & 1\\
3 & 2\\
4 & 3\\
5 & 3\\
\end{longtable}
\subsubsection{VNA:ACQuisition:FINished}
\query{Queries whether the average filter has reached a steady state (that is <acquired sweeps> = <averaging sweeps>)}{VNA:ACQuisition:FINished?}{None}{TRUE or FALSE}
\event{Configures the VNA for single or continuous sweep}{VNA:ACQuisition:SINGLE}{TRUE or FALSE}
\query{Queries whether the VNA is set up for single sweep}{VNA:ACQuisition:SINGLE?}{None}{TRUE or FALSE}
If single sweep is enabled, the acquisition is stopped when the required number of averages have been reached. There are two ways to trigger a new sweep:
\begin{itemize}
\item Change any sweep setting (e.g. center frequency)
\item Issue the command again (i.e. VNA:ACQ:SINGLE TRUE always triggers a new sweep)
\footnotesize{Note: actual response will not include newlines between data points, only at the end}
\end{center}
\subsubsection{VNA:TRACe:AT}
\query{Returns the data at a specific frequency (possibly interpolated)}{VNA:TRACe:AT?}{<trace>, either by name or by index\\<frequency>, in Hz}{real,imag (or ``NaN,NaN'' if specified frequeny is invalid)}
\query{Returns the content of multiple trace according to the touchstone format}{VNA:TRACe:TOUCHSTONE?}{<trace1>,<trace2>,<trace3>,...}{Touchstone file content in ASCII}
Some additional constraints apply:
\begin{itemize}
\item The number of specified traces must be a square number. The number of ports in the touchstone file is inferred from that.
\item Only frequency domain traces are allowed.
\item All traces must have the same number of points and the same start/stop frequency.
\item The order in which the traces are specified matters and depending on its index and each trace must be a reflection or transmission measurement:
\begin{itemize}
\item Assuming that $n$ is the number of ports of the desired touchstone file, the $n*n$ number of traces must be specified in this order:
\query{Returns the highest frequency contained in the trace}{VNA:TRACe:MAXFrequency?}{<trace>, either by name or by index}{maximum frequency in Hz}
\subsubsection{VNA:TRACe:MINFrequency}
\query{Returns the lowest frequency contained in the trace}{VNA:TRACe:MINFrequency?}{<trace>, either by name or by index}{maximum frequency in Hz}
\subsubsection{VNA:TRACe:MAXAmplitude}
\query{Returns the datapoint with the highest amplitude in the trace}{VNA:TRACe:MAXAmplitude?}{<trace>, either by name or by index}{<frequency>,<real>,<imag> of the highest amplitude point}
\begin{example}
:VNA:TRAC:MAXA? S21
5.66406e+9,-6.21766e-5,-0.000795846
\end{example}
\subsubsection{VNA:TRACe:MINAmplitude}
\query{Returns the datapoint with the lowest amplitude in the trace}{VNA:TRACe:MINAmplitude?}{<trace>, either by name or by index}{<frequency>,<real>,<imag> of the lowest amplitude point}
\event{Enables/disables de-embedding on a trace}{VNA:TRACe:DEEMBedding:ACTive}{<trace>, either by name or by index\\<enable>, either TRUE or FALSE}
If no de-embedding is configured for the selected trace, enabling the de-embedding will fail.
\query{Queries whether de-embedding is active for the selected trace}{VNA:TRACe:DEEMBedding:ACTive?}{<trace>, either by name or by index}{TRUE or FALSE}
\subsubsection{VNA:TRACe:DEEMBedding:AVAILable}
\query{Queries whether de-embedding is available for the selected trace}{VNA:TRACe:DEEMBedding:AVAILable?}{<trace>, either by name or by index}{TRUE or FALSE}
\event{Sets the measurement parameter that is stored in the trace}{VNA:TRACe:PARAMeter}{<trace>, either by name or by index\\<parameter>, options are S11, S12, S21 or S22}
\query{Queries the measurement parameter of a trace}{VNA:TRACe:PARAMeter?}{<trace>, either by name or by index}{S11, S12, S21 or S22}
\subsubsection{VNA:TRACe:TYPE}
\event{Sets the storage type of a trace}{VNA:TRACe:TYPE}{<trace>, either by name or by index\\<type>, options are OVERWRITE, MAXHOLD or MINHOLD}
\query{Queries the storage type of a trace}{VNA:TRACe:TYPE?}{<trace>, either by name or by index}{OVERWRITE, MAXHOLD or MINHOLD}
{[<standard>]}, calibration kit standard name, optional\\}
\subsubsection{VNA:CALibration:TYPE}
\query{Returns the type of the specified measurement}{VNA:CALibration:TYPE?}{<measurement number>}{Measurement type, one of:\\
\hspace{1cm}OPEN\\
\hspace{1cm}SHORT\\
\hspace{1cm}LOAD\\
\hspace{1cm}THROUGH\\
\hspace{1cm}ISOLATION\\}
\subsubsection{VNA:CALibration:PORT}
\event{Sets the port for the specified measurement}{VNA:CALibration:PORT}{<measurement number> <port number>}
\query{Returns the port for the specified measurement}{VNA:CALibration:PORT?}{<measurement number>}{<port number>}
\subsubsection{VNA:CALibration:STANDARD}
\event{Sets the calibration standard which will be used for the specified measurement}{VNA:CALibration:STANDARD}{<measurement number> <standard name>}
\query{Returns the standard name for the specified measurement}{VNA:CALibration:STANDARD?}{<measurement number>}{Name of used calibration standard (from calibration kit)}
\subsubsection{VNA:CALibration:MEASure}
\event{Starts a calibration measurement. This command fails if no device is connected, the VNA mode is not active or a calibration measurement is already in progress.}{VNA:CALibration:MEASure}{<measurement 1>,<measurement 2>,...}
Any number of measurements can be specified (by their number). These measurements will be taken simultaneously. This only works if they are measuring different ports (e.g. measure SHORT on port 1 and OPEN on port 2). If colliding measurements are specified (e.g. SHORT on port 1 and LOAD on port 1), an error is returned and no measurements are started.
\event{Saves the active calibration to a file}{VNA:CALibration:SAVE}{<filename>}
Important points when saving/loading calibration files through SCPI commands:
\begin{itemize}
\item Filenames must be either absolute or relative to the location of the GUI application.
\item If the LibreVNA-GUI (and thus also the SCPI server) is running on a different machine than the SCPI client, the calibration files will be saved/loaded from the machine that runs the GUI.
\end{itemize}
\subsubsection{VNA:CALibration:LOAD}
\query{Loads a calibration file}{VNA:CALibration:LOAD?}{<filename>}{TRUE or FALSE}
These commands change or query signal generator settings. Although most of them are available regardless of the current device mode, they usually only have an effect once the generator mode is active.
\subsubsection{GENerator:FREQuency}
\event{Sets the output frequeny}{GENerator:FREQuency}{<frequency>, in Hz}
\query{Queries the selected output frequency}{GENerator:FREQuency?}{None}{frequency in Hz}
\subsubsection{GENerator:LVL}
\event{Sets the output power}{GENerator:LVL}{<output level>, in dBm}
\query{Queries the selected output power}{GENerator:LVL?}{None}{output level in dBm}
\subsubsection{GENerator:PORT}
\event{Sets the active output port}{GENerator:PORT}{<output port>\\
\hspace{1cm}0: output disabled\\
\hspace{1cm}1: output signal at port 1\\
\hspace{1cm}2: output signal at port 2\\}
\query{Queries the selected output}{GENerator:PORT?}{None}{output port}
\subsection{Spectrum Analyzer Commands}
These commands change or query spectrum analyzer settings. Although most of them are available regardless of the current device mode, they usually only have an effect once the spectrum analyzer mode is active.
\subsubsection{SA:FREQuency:SPAN}
\event{Sets the span of the sweep}{SA:FREQuency:SPAN}{<span>, in Hz}
\query{Queries the currently selected span}{SA:FREQuency:SPAN?}{None}{span in Hz}
\subsubsection{SA:FREQuency:START}
\event{Sets the start frequency of the sweep}{SA:FREQuency:START}{<start frequency>, in Hz}
\query{Queries the currently selected start frequency}{SA:FREQuency:START?}{None}{start frequency in Hz}
\subsubsection{SA:FREQuency:CENTer}
\event{Sets the center frequency of the sweep}{SA:FREQuency:CENTer}{<center frequency>, in Hz}
\query{Queries the currently selected center frequency}{SA:FREQuency:CENTer?}{None}{center frequency in Hz}
\subsubsection{SA:FREQuency:STOP}
\event{Sets the stop frequency of the sweep}{SA:FREQuency:STOP}{<stop frequency>, in Hz}
\query{Queries the currently selected stop frequency}{SA:FREQuency:STOP?}{None}{stop frequency in Hz}
\subsubsection{SA:FREQuency:FULL}
\event{Sets the device to the maximum span possible}{SA:FREQuency:FULL}{None}
<acquired sweeps> resets to zero whenever a setting is changed. It is incremented at the end of each sweep, but will not go above the number of configured sweeps for the averaging.
\textbf{\# of active sweep}&\textbf{<acquired sweeps>}\\
\hline
1 & 0\\
2 & 1\\
3 & 2\\
4 & 3\\
5 & 3\\
\end{longtable}
\subsubsection{SA:ACQuisition:FINished}
\query{Queries whether the average filter has reached a steady state (that is <acquired sweeps> = <averaging sweeps>)}{SA:ACQuisition:FINished?}{None}{TRUE or FALSE}
\event{Configures the spectrum analyzer for single or continuous sweep}{SA:ACQuisition:SINGLE}{TRUE or FALSE}
\query{Queries whether the spectrum analyzer is set up for single sweep}{SA:ACQuisition:SINGLE?}{None}{TRUE or FALSE}
If single sweep is enabled, the acquisition is stopped when the required number of averages have been reached. There are two ways to trigger a new sweep:
\begin{itemize}
\item Change any sweep setting (e.g. center frequency)
\item Issue the command again (i.e. SA:ACQ:SINGLE TRUE always triggers a new sweep)
\event{Enables/disables signal identification}{SA:ACQuisition:SIGid}{<enabled>, option are TRUE, FALSE, 1 or 0}
\query{Queries whether signal identification is enabled}{SA:ACQuisition:SIGid?}{None}{TRUE or FALSE}
\subsubsection{SA:TRACKing:ENable}
\event{Enables/disables the tracking generator}{SA:TRACKing:ENable}{<enabled>, option are TRUE, FALSE, 1 or 0}
\query{Queries whether tracking generator is enabled}{SA:TRACKing:ENable?}{None}{TRUE or FALSE}
\subsubsection{SA:TRACKing:PORT}
\event{Sets the output port of the tracking generator}{SA:TRACKing:PORT}{<port>, either 1 or 2}
\query{Queries the output port of the tracking generator}{SA:TRACKing:PORT?}{None}{1 or 2}
\subsubsection{SA:TRACKing:LVL}
\event{Sets the output power of the tracking generator}{SA:TRACKing:LVL}{<output level>, in dBm}
\query{Queries the selected output power of the tracking generator}{SA:TRACKing:LVL?}{None}{output level in dBm}
\subsubsection{SA:TRACKing:OFFset}
\event{Sets the offset frequency of the tracking generator}{SA:TRACKing:OFFset}{<offset>, in Hz}
\query{Queries the selected offset frequency of the tracking generator}{SA:TRACKing:OFFset?}{None}{offset in Hz}
\subsubsection{SA:TRACKing:NORMalize:ENable}
\event{Enables/disables normalization. If the span has changed since the last active normalization, a normalization measurement is also started.}{SA:TRACKing:NORMalize:ENable}{<enabled>, option are TRUE, FALSE, 1 or 0}
\query{Queries whether tracking generator normalization is enabled}{SA:TRACKing:NORMalize:ENable?}{None}{TRUE or FALSE}
\subsubsection{SA:TRACKing:NORMalize:MEASure}
\event{Triggers a new normalization measurement}{SA:TRACKing:NORMalize:MEASure}{None}
\subsubsection{SA:TRACKing:NORMalize:LVL}
\event{Sets the reference level for the normalization}{SA:TRACKing:NORMalize:LVL}{<normalization level>, in dBm}
\query{Queries the selected reference level for the normalization}{SA:TRACKing:NORMalize:LVL?}{None}{normalization level in dBm}
\subsubsection{SA:TRACe:LIST}
\query{Lists the names of all available traces}{SA:TRACe:LIST?}{None}{comma-separated list of trace name}
\query{Returns the data at a specific frequency (possibly interpolated)}{SA:TRACe:AT?}{<trace>, either by name or by index\\<frequency>, in Hz}{<dBm> or ``NaN'' if specified frequeny is invalid)}
\query{Returns the datapoint with the highest amplitude in the trace}{SA:TRACe:MAXAmplitude?}{<trace>, either by name or by index}{<frequency>,<dBm> of the highest amplitude point}
\query{Returns the datapoint with the lowest amplitude in the trace}{SA:TRACe:MINAmplitude?}{<trace>, either by name or by index}{<frequency>,<dBm> of the lowest amplitude point}
\event{Creates a new trace}{SA:TRACe:NEW}{<trace name>}
\subsubsection{SA:TRACe:RENAME}
\event{Changes the name of a trace}{SA:TRACe:RENAME}{<trace>, either by name or by index\\<new name>}
\subsubsection{SA:TRACe:PAUSE}
\event{Pauses (freezes) a trace}{SA:TRACe:PAUSE}{<trace>, either by name or by index}
\subsubsection{SA:TRACe:RESUME}
\event{Resumes (unfreezes) a trace}{SA:TRACe:RESUME}{<trace>, either by name or by index}
\subsubsection{SA:TRACe:PAUSED}
\query{Queries whether a trace is paused}{SA:TRACe:PAUSED?}{<trace>, either by name or by index}{TRUE or FALSE}
\subsubsection{SA:TRACe:PARAMeter}
\event{Sets the measurement parameter that is stored in the trace}{SA:TRACe:PARAMeter}{<trace>, either by name or by index\\<parameter>, options are PORT1 and PORT2}
\query{Queries the measurement parameter of a trace}{SA:TRACe:PARAMeter?}{<trace>, either by name or by index}{PORT1 or PORT2}
\subsubsection{SA:TRACe:TYPE}
\event{Sets the storage type of a trace}{SA:TRACe:TYPE}{<trace>, either by name or by index\\<type>, options are OVERWRITE, MAXHOLD or MINHOLD}
\query{Queries the storage type of a trace}{SA:TRACe:TYPE?}{<trace>, either by name or by index}{OVERWRITE, MAXHOLD or MINHOLD}
The SCPI server works well for configuring the device and also for reading trace data once an acquition is done. But it isn't very well suited for reading data while the device is capturing it. For some applications (e.g. when running continuous sweeps) it may be beneficial to process the data externally as it getting captured. For this purpose, the LibreVNA-GUI supports streaming the data over dedicated ports.
These streaming servers have to be enbled first. This can be done in \menu[,]{Window,Preferences,Streaming Servers}.
There are a total of 5 streaming servers available. They can all be enabled and used at the same time, although not all servers will output data all the time.
\begin{itemize}
\item\textbf{VNA raw data:} Outputs the raw S-parameters without any calibration applied. This output is always available, even when a calibration is enabled or de-embedding it active. Apart from averaging (if enabled) no processing is done on the data.
\item\textbf{VNA calibrated data:} Outputs the calibrated S-parameters with the calibration applied. This output is only available when a calibration is enabled.
\item\textbf{VNA de-embedded data:} Outputs the de-embedded S-parameters with the de-embbeding and calibration (if enabled) applied. This output is only available when de-embedding is active.
\item\textbf{SA raw data:} Outputs the raw (not normalized) power levels from the spectrum analyzer. This output is always available, even when normalizing is active.
\item\textbf{SA normalized data:} Outputs the normalized power levels from the spectrum analyzer. This output is only available when normalizing is active.
\end{itemize}
\vspace{0.5cm}
All servers output a newline-terminated line of json formatted data for each measurement point in the sweep: