From 9fe3ae7e7da0daf2b1cd674e2c23570772e426fc Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Wed, 30 Apr 2025 22:21:40 +0200 Subject: [PATCH 01/45] Remove the scripts pytest.py and py3test.py They will be replaced by the official pytest tool. Because of name clash it would be impossible to call the pytest tool from the bindings directory. --- bindings/Makefile.am | 15 +---- bindings/py3test.py | 129 ------------------------------------------- bindings/pytest.py | 122 ---------------------------------------- configure.ac | 4 -- 4 files changed, 1 insertion(+), 269 deletions(-) delete mode 100755 bindings/py3test.py delete mode 100755 bindings/pytest.py diff --git a/bindings/Makefile.am b/bindings/Makefile.am index 11ecea1ec..6224997ae 100644 --- a/bindings/Makefile.am +++ b/bindings/Makefile.am @@ -21,7 +21,7 @@ SWGDEP = \ $(SWGFILES) EXTRA_DIST = $(SWGFILES) \ - Makefile.PL perltest.pl tcltest.tcl.in pytest.py py3test.py \ + Makefile.PL perltest.pl tcltest.tcl.in \ luatest.lua README.python exampledir = $(docdir)/examples @@ -95,16 +95,6 @@ pyexec_ltlib = _Hamlib.la MOSTLYCLEANFILES += hamlibpy_wrap.c Hamlib.py *.pyc BUILT_SOURCES += hamlibpy_wrap.c Hamlib.py -# Set by AM_CONDITIONAL in configure.ac -if PYVER_3 -pytest = py3test.py -else !PYVER_3 -pytest = pytest.py -endif -# PYVER_3 - -example_DATA += $(pytest) - nodist_pyexec_PYTHON = Hamlib.py nodist__Hamlib_la_SOURCES = hamlibpy_wrap.c @@ -116,9 +106,6 @@ _Hamlib_la_LTLIBRARIES = $(pyexec_ltlib) all-py: $(pyexec_ltlib) check-py: all-py - $(AM_V_at)PYTHONPATH=$(builddir):$(builddir)/.libs \ - $(PYTHON) $(srcdir)/$(pytest) \ - || echo "Python test failed" 1>&2 Hamlib.py: hamlibpy_wrap.c diff --git a/bindings/py3test.py b/bindings/py3test.py deleted file mode 100755 index 52f85e1e7..000000000 --- a/bindings/py3test.py +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -import sys -# Change this path to match your "make install" path -sys.path.append('/usr/local/lib/python3.10/site-packages') - -## Uncomment to run this script from an in-tree build (or adjust to the -## build directory) without installing the bindings. -#sys.path.append ('.') -#sys.path.append ('.libs') - -import Hamlib - -def StartUp(): - """Simple script to test the Hamlib.py module with Python3.""" - - print("%s: Python %s; %s\n" \ - % (sys.argv[0], sys.version.split()[0], Hamlib.cvar.hamlib_version)) - - Hamlib.rig_set_debug(Hamlib.RIG_DEBUG_NONE) - - # Init RIG_MODEL_DUMMY - my_rig = Hamlib.Rig(Hamlib.RIG_MODEL_DUMMY) - my_rig.set_conf("rig_pathname", "/dev/Rig") - my_rig.set_conf("retry", "5") - - my_rig.open () - - rpath = my_rig.get_conf("rig_pathname") - retry = my_rig.get_conf("retry") - - print("status(str):\t\t%s" % Hamlib.rigerror(my_rig.error_status)) - print("get_conf:\t\tpath = %s, retry = %s" \ - % (rpath, retry)) - - my_rig.set_freq(Hamlib.RIG_VFO_B, 5700000000) - my_rig.set_vfo(Hamlib.RIG_VFO_B) - - print("freq:\t\t\t%s" % my_rig.get_freq()) - - my_rig.set_freq(Hamlib.RIG_VFO_A, 145550000) - (mode, width) = my_rig.get_mode(Hamlib.RIG_VFO_A) - - print("mode:\t\t\t%s\nbandwidth:\t\t%s" % (Hamlib.rig_strrmode(mode), width)) - - my_rig.set_mode(Hamlib.RIG_MODE_CW) - (mode, width) = my_rig.get_mode() - - print("mode:\t\t\t%s\nbandwidth:\t\t%s" % (Hamlib.rig_strrmode(mode), width)) - - print("Backend copyright:\t%s" % my_rig.caps.copyright) - print("Model:\t\t\t%s" % my_rig.caps.model_name) - print("Manufacturer:\t\t%s" % my_rig.caps.mfg_name) - print("Backend version:\t%s" % my_rig.caps.version) - print("Backend status:\t\t%s" % Hamlib.rig_strstatus(my_rig.caps.status)) - print("Rig info:\t\t%s" % my_rig.get_info()) - - my_rig.set_level("VOXDELAY", 1) - - print("VOX delay:\t\t%s" % my_rig.get_level_i("VOXDELAY")) - - my_rig.set_level(Hamlib.RIG_LEVEL_VOXDELAY, 5) - - print("VOX delay:\t\t%s" % my_rig.get_level_i(Hamlib.RIG_LEVEL_VOXDELAY)) - - af = 12.34 - - print("Setting AF to %0.2f...." % (af)) - - my_rig.set_level("AF", af) - - print("status:\t\t\t%s - %s" % (my_rig.error_status, - Hamlib.rigerror(my_rig.error_status))) - - print("AF level:\t\t%0.2f" % my_rig.get_level_f(Hamlib.RIG_LEVEL_AF)) - print("Power level:\t\t%0.2f" % my_rig.get_level_f(Hamlib.RIG_LEVEL_RFPOWER_METER)) - print("Power level Watts:\t\t%0.2f" % my_rig.get_level_f(Hamlib.RIG_LEVEL_RFPOWER_METER_WATTS)) - print("strength:\t\t%s" % my_rig.get_level_i(Hamlib.RIG_LEVEL_STRENGTH)) - print("status:\t\t\t%s" % my_rig.error_status) - print("status(str):\t\t%s" % Hamlib.rigerror(my_rig.error_status)) - - chan = Hamlib.channel(Hamlib.RIG_VFO_B) - my_rig.get_channel(chan,1) - - print("get_channel status:\t%s" % my_rig.error_status) - print("VFO:\t\t\t%s, %s" % (Hamlib.rig_strvfo(chan.vfo), chan.freq)) - print("Attenuators:\t\t%s" % my_rig.caps.attenuator) - # Can't seem to get get_vfo_info to work - #(freq, width, mode, split) = my_rig.get_vfo_info(Hamlib.RIG_VFO_A,freq,width,mode,split) - #print("Rig vfo_info:\t\tfreq=%s, mode=%s, width=%s, split=%s" % (freq, mode, width, split)) - print("\nSending Morse, '73'") - - my_rig.send_morse(Hamlib.RIG_VFO_A, "73") - my_rig.close() - - print("\nSome static functions:") - - err, lon1, lat1 = Hamlib.locator2longlat("IN98XC") - err, lon2, lat2 = Hamlib.locator2longlat("DM33DX") - err, loc1 = Hamlib.longlat2locator(lon1, lat1, 3) - err, loc2 = Hamlib.longlat2locator(lon2, lat2, 3) - - print("Loc1:\t\tIN98XC -> %9.4f, %9.4f -> %s" % (lon1, lat1, loc1)) - print("Loc2:\t\tDM33DX -> %9.4f, %9.4f -> %s" % (lon2, lat2, loc2)) - - err, dist, az = Hamlib.qrb(lon1, lat1, lon2, lat2) - longpath = Hamlib.distance_long_path(dist) - - print("Distance:\t%.3f km, azimuth %.2f, long path:\t%.3f km" \ - % (dist, az, longpath)) - - # dec2dms expects values from 180 to -180 - # sw is 1 when deg is negative (west or south) as 0 cannot be signed - err, deg1, mins1, sec1, sw1 = Hamlib.dec2dms(lon1) - err, deg2, mins2, sec2, sw2 = Hamlib.dec2dms(lat1) - - lon3 = Hamlib.dms2dec(deg1, mins1, sec1, sw1) - lat3 = Hamlib.dms2dec(deg2, mins2, sec2, sw2) - - print('Longitude:\t%4.4f, %4d° %2d\' %2d" %1s\trecoded: %9.4f' \ - % (lon1, deg1, mins1, sec1, ('W' if sw1 else 'E'), lon3)) - - print('Latitude:\t%4.4f, %4d° %2d\' %2d" %1s\trecoded: %9.4f' \ - % (lat1, deg2, mins2, sec2, ('S' if sw2 else 'N'), lat3)) - - my_rig.set_vfo_opt(0); - -if __name__ == '__main__': - StartUp() diff --git a/bindings/pytest.py b/bindings/pytest.py deleted file mode 100755 index b271834a5..000000000 --- a/bindings/pytest.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python2 -# -*- coding: utf-8 -*- - -import sys - -## Uncomment to run this script from an in-tree build (or adjust to the -## build directory) without installing the bindings. -#sys.path.append ('.') -#sys.path.append ('.libs') - -import Hamlib - -def StartUp(verbose): - """Simple script to test the Hamlib.py module with Python2.""" - - print "%s: Python %s; %s\n" \ - % (sys.argv[0], sys.version.split()[0], Hamlib.cvar.hamlib_version) - - Hamlib.rig_set_debug([Hamlib.RIG_DEBUG_NONE, Hamlib.RIG_DEBUG_VERBOSE][verbose]) - - # Init RIG_MODEL_DUMMY - my_rig = Hamlib.Rig(Hamlib.RIG_MODEL_DUMMY) - my_rig.set_conf("rig_pathname", "/dev/Rig") - my_rig.set_conf("retry", "5") - - my_rig.open() - - rpath = my_rig.get_conf("rig_pathname") - retry = my_rig.get_conf("retry") - - print "status(str):\t\t", Hamlib.rigerror(my_rig.error_status) - print "get_conf:\t\tpath = %s, retry = %s" \ - % (rpath, retry) - - my_rig.set_freq(Hamlib.RIG_VFO_B, 5700000000) - my_rig.set_vfo(Hamlib.RIG_VFO_B) - - print "freq:\t\t\t", my_rig.get_freq() - - my_rig.set_freq(Hamlib.RIG_VFO_A, 145550000) - (mode, width) = my_rig.get_mode() - - print "mode:\t\t\t", Hamlib.rig_strrmode(mode), "\nbandwidth:\t\t", width - - my_rig.set_mode(Hamlib.RIG_MODE_CW) - (mode, width) = my_rig.get_mode() - - print "mode:\t\t\t", Hamlib.rig_strrmode(mode), "\nbandwidth:\t\t", width - - print "Backend copyright:\t", my_rig.caps.copyright - print "Model:\t\t\t", my_rig.caps.model_name - print "Manufacturer:\t\t", my_rig.caps.mfg_name - print "Backend version:\t", my_rig.caps.version - print "Backend status:\t\t", Hamlib.rig_strstatus(my_rig.caps.status) - print "Rig info:\t\t", my_rig.get_info() - - my_rig.set_level("VOXDELAY", 1) - - print "VOX delay:\t\t", my_rig.get_level_i("VOXDELAY") - - my_rig.set_level(Hamlib.RIG_LEVEL_VOXDELAY, 5) - - print "VOX delay:\t\t", my_rig.get_level_i(Hamlib.RIG_LEVEL_VOXDELAY) - - af = 12.34 - - print "Setting AF to %0.2f...." % (af) - - my_rig.set_level("AF", af) - - print "status:\t\t\t%s - %s" % (my_rig.error_status, - Hamlib.rigerror(my_rig.error_status)) - - print "AF level:\t\t%0.2f" % my_rig.get_level_f(Hamlib.RIG_LEVEL_AF) - print "strength:\t\t", my_rig.get_level_i(Hamlib.RIG_LEVEL_STRENGTH) - print "status:\t\t\t", my_rig.error_status - print "status(str):\t\t", Hamlib.rigerror(my_rig.error_status) - - chan = Hamlib.channel(Hamlib.RIG_VFO_B) - my_rig.get_channel(chan,1) - - print "get_channel status:\t", my_rig.error_status - print "VFO:\t\t\t", Hamlib.rig_strvfo(chan.vfo), ", ", chan.freq - print "Attenuators:\t\t", my_rig.caps.attenuator - print "\nSending Morse, '73'" - - my_rig.send_morse(Hamlib.RIG_VFO_A, "73") - my_rig.close () - - print "\nSome static functions:" - - err, lon1, lat1 = Hamlib.locator2longlat("IN98XC") - err, lon2, lat2 = Hamlib.locator2longlat("DM33DX") - err, loc1 = Hamlib.longlat2locator(lon1, lat1, 3) - err, loc2 = Hamlib.longlat2locator(lon2, lat2, 3) - - print "Loc1:\t\tIN98XC -> %9.4f, %9.4f -> %s" % (lon1, lat1, loc1) - print "Loc2:\t\tDM33DX -> %9.4f, %9.4f -> %s" % (lon2, lat2, loc2) - - err, dist, az = Hamlib.qrb(lon1, lat1, lon2, lat2) - longpath = Hamlib.distance_long_path(dist) - - print "Distance:\t%.3f km, azimuth %.2f, long path:\t%.3f km" \ - % (dist, az, longpath) - - # dec2dms expects values from 180 to -180 - # sw is 1 when deg is negative (west or south) as 0 cannot be signed - err, deg1, mins1, sec1, sw1 = Hamlib.dec2dms(lon1) - err, deg2, mins2, sec2, sw2 = Hamlib.dec2dms(lat1) - - lon3 = Hamlib.dms2dec(deg1, mins1, sec1, sw1) - lat3 = Hamlib.dms2dec(deg2, mins2, sec2, sw2) - - print 'Longitude:\t%4.4f, %4d° %2d\' %2d" %1s\trecoded: %9.4f' \ - % (lon1, deg1, mins1, sec1, ('W' if sw1 else 'E'), lon3) - - print 'Latitude:\t%4.4f, %4d° %2d\' %2d" %1s\trecoded: %9.4f' \ - % (lat1, deg2, mins2, sec2, ('S' if sw2 else 'N'), lat3) - - -if __name__ == '__main__': - StartUp([0,1]["-v" in sys.argv]) diff --git a/configure.ac b/configure.ac index 4ef857e1d..3aecb6e51 100644 --- a/configure.ac +++ b/configure.ac @@ -615,10 +615,6 @@ AS_IF([test x"${cf_with_python_binding}" = "xyes"],[ AM_CONDITIONAL([ENABLE_PYTHON], [test x"${cf_with_python_binding}" = "xyes"]) -dnl Determine whether to install pytest.py or py3test.py to $(docdir)/examples -AM_PYTHON_CHECK_VERSION([${PYTHON}], [3.0], [pyver_3="yes"], [pyver_3="no"]) -AM_CONDITIONAL([PYVER_3], [test x"${pyver_3}" = x"yes"]) - # Tcl binding AC_MSG_CHECKING([Whether to build Tcl bindings]) AC_ARG_WITH([tcl-binding], From f4dcd7d565d3baaafacf083c0fc5572c4361f274 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Wed, 30 Apr 2025 23:19:40 +0200 Subject: [PATCH 02/45] Add a pytest test copying all the contents of the old py3test.py Python tests are enabled by default when building the Python bindings if pytest is available at configuration time: ./configure --with-python-binding or ./configure --with-python-binding --enable-pytest=check To fail the configure step if the tests can't be enabled: ./configure --with-python-binding --enable-pytest or ./configure --with-python-binding --enable-pytest=yes To disable the tests: ./configure --with-python-binding --enable-pytest=no To run the tests: make -C bindings/ check --- bindings/Makefile.am | 10 ++- bindings/python/test_startup.py | 127 ++++++++++++++++++++++++++++++++ configure.ac | 28 +++++++ 3 files changed, 164 insertions(+), 1 deletion(-) create mode 100755 bindings/python/test_startup.py diff --git a/bindings/Makefile.am b/bindings/Makefile.am index 6224997ae..cc9e35f3b 100644 --- a/bindings/Makefile.am +++ b/bindings/Makefile.am @@ -22,6 +22,7 @@ SWGDEP = \ EXTRA_DIST = $(SWGFILES) \ Makefile.PL perltest.pl tcltest.tcl.in \ + python/test_startup.py \ luatest.lua README.python exampledir = $(docdir)/examples @@ -105,7 +106,14 @@ _Hamlib_la_LTLIBRARIES = $(pyexec_ltlib) all-py: $(pyexec_ltlib) -check-py: all-py +check-py: all-py pytest-${enable_pytest} + +pytest-yes: + $(AM_V_at)PYTHONPATH=$(builddir):$(builddir)/.libs \ + $(PYTEST) --capture=no $(srcdir)/ + +pytest-no: + @echo "Skipping pytest run" Hamlib.py: hamlibpy_wrap.c diff --git a/bindings/python/test_startup.py b/bindings/python/test_startup.py new file mode 100755 index 000000000..6c6ca1549 --- /dev/null +++ b/bindings/python/test_startup.py @@ -0,0 +1,127 @@ +#! /bin/env pytest +"""Tests of the Python bindings for Hamlib + +Running this script directly will use the installed bindings. +For an in-tree run use "make check", or set PYTHONPATH to point to +the directories containing Hamlib.py and _Hamlib.so. +""" +import sys + +import Hamlib + +class TestClass: + """Container class for tests""" + + def test_startup(self): + """Simple script to test the Hamlib.py module with Python3.""" + + print("%s: Python %s; %s\n" \ + % (sys.argv[0], sys.version.split()[0], Hamlib.cvar.hamlib_version)) + + Hamlib.rig_set_debug(Hamlib.RIG_DEBUG_NONE) + + # Init RIG_MODEL_DUMMY + my_rig = Hamlib.Rig(Hamlib.RIG_MODEL_DUMMY) + my_rig.set_conf("rig_pathname", "/dev/Rig") + my_rig.set_conf("retry", "5") + + my_rig.open () + + rpath = my_rig.get_conf("rig_pathname") + retry = my_rig.get_conf("retry") + + print("status(str):\t\t%s" % Hamlib.rigerror(my_rig.error_status)) + print("get_conf:\t\tpath = %s, retry = %s" \ + % (rpath, retry)) + + my_rig.set_freq(Hamlib.RIG_VFO_B, 5700000000) + my_rig.set_vfo(Hamlib.RIG_VFO_B) + + print("freq:\t\t\t%s" % my_rig.get_freq()) + + my_rig.set_freq(Hamlib.RIG_VFO_A, 145550000) + (mode, width) = my_rig.get_mode(Hamlib.RIG_VFO_A) + + print("mode:\t\t\t%s\nbandwidth:\t\t%s" % (Hamlib.rig_strrmode(mode), width)) + + my_rig.set_mode(Hamlib.RIG_MODE_CW) + (mode, width) = my_rig.get_mode() + + print("mode:\t\t\t%s\nbandwidth:\t\t%s" % (Hamlib.rig_strrmode(mode), width)) + + print("Backend copyright:\t%s" % my_rig.caps.copyright) + print("Model:\t\t\t%s" % my_rig.caps.model_name) + print("Manufacturer:\t\t%s" % my_rig.caps.mfg_name) + print("Backend version:\t%s" % my_rig.caps.version) + print("Backend status:\t\t%s" % Hamlib.rig_strstatus(my_rig.caps.status)) + print("Rig info:\t\t%s" % my_rig.get_info()) + + my_rig.set_level("VOXDELAY", 1) + + print("VOX delay:\t\t%s" % my_rig.get_level_i("VOXDELAY")) + + my_rig.set_level(Hamlib.RIG_LEVEL_VOXDELAY, 5) + + print("VOX delay:\t\t%s" % my_rig.get_level_i(Hamlib.RIG_LEVEL_VOXDELAY)) + + af = 12.34 + + print("Setting AF to %0.2f...." % (af)) + + my_rig.set_level("AF", af) + + print("status:\t\t\t%s - %s" % (my_rig.error_status, + Hamlib.rigerror(my_rig.error_status))) + + print("AF level:\t\t%0.2f" % my_rig.get_level_f(Hamlib.RIG_LEVEL_AF)) + print("Power level:\t\t%0.2f" % my_rig.get_level_f(Hamlib.RIG_LEVEL_RFPOWER_METER)) + print("Power level Watts:\t\t%0.2f" % my_rig.get_level_f(Hamlib.RIG_LEVEL_RFPOWER_METER_WATTS)) + print("strength:\t\t%s" % my_rig.get_level_i(Hamlib.RIG_LEVEL_STRENGTH)) + print("status:\t\t\t%s" % my_rig.error_status) + print("status(str):\t\t%s" % Hamlib.rigerror(my_rig.error_status)) + + chan = Hamlib.channel(Hamlib.RIG_VFO_B) + my_rig.get_channel(chan,1) + + print("get_channel status:\t%s" % my_rig.error_status) + print("VFO:\t\t\t%s, %s" % (Hamlib.rig_strvfo(chan.vfo), chan.freq)) + print("Attenuators:\t\t%s" % my_rig.caps.attenuator) + # Can't seem to get get_vfo_info to work + #(freq, width, mode, split) = my_rig.get_vfo_info(Hamlib.RIG_VFO_A,freq,width,mode,split) + #print("Rig vfo_info:\t\tfreq=%s, mode=%s, width=%s, split=%s" % (freq, mode, width, split)) + print("\nSending Morse, '73'") + + my_rig.send_morse(Hamlib.RIG_VFO_A, "73") + my_rig.close() + + print("\nSome static functions:") + + err, lon1, lat1 = Hamlib.locator2longlat("IN98XC") + err, lon2, lat2 = Hamlib.locator2longlat("DM33DX") + err, loc1 = Hamlib.longlat2locator(lon1, lat1, 3) + err, loc2 = Hamlib.longlat2locator(lon2, lat2, 3) + + print("Loc1:\t\tIN98XC -> %9.4f, %9.4f -> %s" % (lon1, lat1, loc1)) + print("Loc2:\t\tDM33DX -> %9.4f, %9.4f -> %s" % (lon2, lat2, loc2)) + + err, dist, az = Hamlib.qrb(lon1, lat1, lon2, lat2) + longpath = Hamlib.distance_long_path(dist) + + print("Distance:\t%.3f km, azimuth %.2f, long path:\t%.3f km" \ + % (dist, az, longpath)) + + # dec2dms expects values from 180 to -180 + # sw is 1 when deg is negative (west or south) as 0 cannot be signed + err, deg1, mins1, sec1, sw1 = Hamlib.dec2dms(lon1) + err, deg2, mins2, sec2, sw2 = Hamlib.dec2dms(lat1) + + lon3 = Hamlib.dms2dec(deg1, mins1, sec1, sw1) + lat3 = Hamlib.dms2dec(deg2, mins2, sec2, sw2) + + print('Longitude:\t%4.4f, %4d° %2d\' %2d" %1s\trecoded: %9.4f' \ + % (lon1, deg1, mins1, sec1, ('W' if sw1 else 'E'), lon3)) + + print('Latitude:\t%4.4f, %4d° %2d\' %2d" %1s\trecoded: %9.4f' \ + % (lat1, deg2, mins2, sec2, ('S' if sw2 else 'N'), lat3)) + + my_rig.set_vfo_opt(0); diff --git a/configure.ac b/configure.ac index 3aecb6e51..0c3ec35b8 100644 --- a/configure.ac +++ b/configure.ac @@ -615,6 +615,33 @@ AS_IF([test x"${cf_with_python_binding}" = "xyes"],[ AM_CONDITIONAL([ENABLE_PYTHON], [test x"${cf_with_python_binding}" = "xyes"]) +AC_ARG_ENABLE([pytest], + [AS_HELP_STRING([--enable-pytest], + [execute Python tests @<:@default=check@:>@]) + ], + [enable_pytest=check] +) + +AS_IF([test "x$enable_pytest" != "xno"], + [AC_PATH_PROG([PYTEST], [pytest])] +) + +AS_IF([test "x$PYTEST" = "x"], + [have_pytest=no], + [have_pytest=yes] +) + +AS_IF([test "x$enable_pytest" = "xyes"], + [AS_IF([test "x$have_pytest" = "xno"], + [AC_MSG_ERROR([pytest requested but not found])] + )] +) + +# "check" is replaced by the rsult ("yes" or "no") +enable_pytest=$have_pytest + +AC_SUBST([enable_pytest]) + # Tcl binding AC_MSG_CHECKING([Whether to build Tcl bindings]) AC_ARG_WITH([tcl-binding], @@ -976,5 +1003,6 @@ echo \ Enable USB backends ${cf_with_libusb} Enable shared libs ${enable_shared} Enable static libs ${enable_static} + Enable Python tests ${enable_pytest} -----------------------------------------------------------------------" From c693afb04058886cc374ce2d024adc57740d6463 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Thu, 1 May 2025 23:24:52 +0200 Subject: [PATCH 03/45] Replace print() with assert So changes in behavior can be detected. --- bindings/python/test_startup.py | 144 ++++++++++++++++---------------- 1 file changed, 74 insertions(+), 70 deletions(-) diff --git a/bindings/python/test_startup.py b/bindings/python/test_startup.py index 6c6ca1549..b72e5cf5f 100755 --- a/bindings/python/test_startup.py +++ b/bindings/python/test_startup.py @@ -5,7 +5,7 @@ Running this script directly will use the installed bindings. For an in-tree run use "make check", or set PYTHONPATH to point to the directories containing Hamlib.py and _Hamlib.so. """ -import sys +from pytest import approx import Hamlib @@ -15,113 +15,117 @@ class TestClass: def test_startup(self): """Simple script to test the Hamlib.py module with Python3.""" - print("%s: Python %s; %s\n" \ - % (sys.argv[0], sys.version.split()[0], Hamlib.cvar.hamlib_version)) + assert isinstance(Hamlib.cvar.hamlib_version, str) Hamlib.rig_set_debug(Hamlib.RIG_DEBUG_NONE) - # Init RIG_MODEL_DUMMY - my_rig = Hamlib.Rig(Hamlib.RIG_MODEL_DUMMY) - my_rig.set_conf("rig_pathname", "/dev/Rig") - my_rig.set_conf("retry", "5") + model = Hamlib.RIG_MODEL_DUMMY + my_rig = Hamlib.Rig(model) + assert my_rig is not None + assert my_rig.set_conf("rig_pathname", "/dev/Rig") is None + assert my_rig.set_conf("retry", "5") is None - my_rig.open () + assert my_rig.open() is None - rpath = my_rig.get_conf("rig_pathname") - retry = my_rig.get_conf("retry") + assert my_rig.get_conf("rig_pathname") == "/dev/Rig" + assert my_rig.get_conf("retry") == '5' - print("status(str):\t\t%s" % Hamlib.rigerror(my_rig.error_status)) - print("get_conf:\t\tpath = %s, retry = %s" \ - % (rpath, retry)) + assert my_rig.error_status == Hamlib.RIG_OK + # assert Hamlib.rigerror(my_rig.error_status) == "Command completed successfully\n" # FIXME: the string returned contains debug messages, fix in PR #1727 - my_rig.set_freq(Hamlib.RIG_VFO_B, 5700000000) - my_rig.set_vfo(Hamlib.RIG_VFO_B) + assert my_rig.set_freq(Hamlib.RIG_VFO_B, 5700000000) is None + assert my_rig.set_vfo(Hamlib.RIG_VFO_B) is None + assert my_rig.get_freq() == 5700000000 - print("freq:\t\t\t%s" % my_rig.get_freq()) + assert my_rig.set_freq(Hamlib.RIG_VFO_A, 145550000) is None - my_rig.set_freq(Hamlib.RIG_VFO_A, 145550000) (mode, width) = my_rig.get_mode(Hamlib.RIG_VFO_A) + assert Hamlib.rig_strrmode(mode) == 'FM' + assert width == 15000 - print("mode:\t\t\t%s\nbandwidth:\t\t%s" % (Hamlib.rig_strrmode(mode), width)) - - my_rig.set_mode(Hamlib.RIG_MODE_CW) + assert my_rig.set_mode(Hamlib.RIG_MODE_CW) is None (mode, width) = my_rig.get_mode() + assert Hamlib.rig_strrmode(mode) == 'CW' + assert width == 0 - print("mode:\t\t\t%s\nbandwidth:\t\t%s" % (Hamlib.rig_strrmode(mode), width)) + assert isinstance(my_rig.caps.copyright, str) + assert isinstance(my_rig.caps.model_name, str) + assert isinstance(my_rig.caps.mfg_name, str) + assert isinstance(my_rig.caps.version, str) + assert isinstance(Hamlib.rig_strstatus(my_rig.caps.status), str) + assert isinstance(my_rig.get_info(), str) - print("Backend copyright:\t%s" % my_rig.caps.copyright) - print("Model:\t\t\t%s" % my_rig.caps.model_name) - print("Manufacturer:\t\t%s" % my_rig.caps.mfg_name) - print("Backend version:\t%s" % my_rig.caps.version) - print("Backend status:\t\t%s" % Hamlib.rig_strstatus(my_rig.caps.status)) - print("Rig info:\t\t%s" % my_rig.get_info()) + assert my_rig.set_level("VOXDELAY", 1) is None + assert my_rig.get_level_i("VOXDELAY") == 1 - my_rig.set_level("VOXDELAY", 1) - - print("VOX delay:\t\t%s" % my_rig.get_level_i("VOXDELAY")) - - my_rig.set_level(Hamlib.RIG_LEVEL_VOXDELAY, 5) - - print("VOX delay:\t\t%s" % my_rig.get_level_i(Hamlib.RIG_LEVEL_VOXDELAY)) + assert my_rig.set_level(Hamlib.RIG_LEVEL_VOXDELAY, 5) is None + assert my_rig.get_level_i(Hamlib.RIG_LEVEL_VOXDELAY) == 5 af = 12.34 + assert my_rig.set_level("AF", af) is None + assert my_rig.error_status == Hamlib.RIG_OK + assert my_rig.get_level_f(Hamlib.RIG_LEVEL_AF) == approx(12.34) + assert my_rig.error_status == Hamlib.RIG_OK - print("Setting AF to %0.2f...." % (af)) - - my_rig.set_level("AF", af) - - print("status:\t\t\t%s - %s" % (my_rig.error_status, - Hamlib.rigerror(my_rig.error_status))) - - print("AF level:\t\t%0.2f" % my_rig.get_level_f(Hamlib.RIG_LEVEL_AF)) - print("Power level:\t\t%0.2f" % my_rig.get_level_f(Hamlib.RIG_LEVEL_RFPOWER_METER)) - print("Power level Watts:\t\t%0.2f" % my_rig.get_level_f(Hamlib.RIG_LEVEL_RFPOWER_METER_WATTS)) - print("strength:\t\t%s" % my_rig.get_level_i(Hamlib.RIG_LEVEL_STRENGTH)) - print("status:\t\t\t%s" % my_rig.error_status) - print("status(str):\t\t%s" % Hamlib.rigerror(my_rig.error_status)) + assert my_rig.get_level_f(Hamlib.RIG_LEVEL_RFPOWER_METER) + assert my_rig.get_level_f(Hamlib.RIG_LEVEL_RFPOWER_METER_WATTS) + assert my_rig.get_level_i(Hamlib.RIG_LEVEL_STRENGTH) chan = Hamlib.channel(Hamlib.RIG_VFO_B) - my_rig.get_channel(chan,1) + assert chan.vfo == Hamlib.RIG_VFO_B + assert my_rig.get_channel(chan, 1) is None + assert my_rig.error_status == Hamlib.RIG_OK - print("get_channel status:\t%s" % my_rig.error_status) - print("VFO:\t\t\t%s, %s" % (Hamlib.rig_strvfo(chan.vfo), chan.freq)) - print("Attenuators:\t\t%s" % my_rig.caps.attenuator) + assert Hamlib.rig_strvfo(chan.vfo) == 'MainB' + assert chan.freq == 5700000000 + assert my_rig.caps.attenuator == [10, 20, 30, 0, 0, 0, 0, 0] # Can't seem to get get_vfo_info to work #(freq, width, mode, split) = my_rig.get_vfo_info(Hamlib.RIG_VFO_A,freq,width,mode,split) #print("Rig vfo_info:\t\tfreq=%s, mode=%s, width=%s, split=%s" % (freq, mode, width, split)) - print("\nSending Morse, '73'") - my_rig.send_morse(Hamlib.RIG_VFO_A, "73") - my_rig.close() + assert my_rig.send_morse(Hamlib.RIG_VFO_A, "73") is None + assert my_rig.close() is None - print("\nSome static functions:") + # Some static functions err, lon1, lat1 = Hamlib.locator2longlat("IN98XC") - err, lon2, lat2 = Hamlib.locator2longlat("DM33DX") - err, loc1 = Hamlib.longlat2locator(lon1, lat1, 3) - err, loc2 = Hamlib.longlat2locator(lon2, lat2, 3) + assert err == Hamlib.RIG_OK + assert lon1 == approx(-0.0417, abs=1.0e-04) # FIXME why need to override tolerance? + assert lat1 == approx(48.1042) + assert Hamlib.longlat2locator(lon1, lat1, 3) == [Hamlib.RIG_OK, 'IN98XC'] - print("Loc1:\t\tIN98XC -> %9.4f, %9.4f -> %s" % (lon1, lat1, loc1)) - print("Loc2:\t\tDM33DX -> %9.4f, %9.4f -> %s" % (lon2, lat2, loc2)) + err, lon2, lat2 = Hamlib.locator2longlat("DM33DX") + assert err == Hamlib.RIG_OK + assert lon2 == approx(-113.7083) + assert lat2 == approx(33.9792) + assert Hamlib.longlat2locator(lon2, lat2, 3) == [Hamlib.RIG_OK, 'DM33DX'] err, dist, az = Hamlib.qrb(lon1, lat1, lon2, lat2) + assert err == Hamlib.RIG_OK + assert dist == approx(8765.814) + assert az == approx(309.0) longpath = Hamlib.distance_long_path(dist) - - print("Distance:\t%.3f km, azimuth %.2f, long path:\t%.3f km" \ - % (dist, az, longpath)) + assert longpath == approx(31266.186) # dec2dms expects values from 180 to -180 # sw is 1 when deg is negative (west or south) as 0 cannot be signed err, deg1, mins1, sec1, sw1 = Hamlib.dec2dms(lon1) + assert err == Hamlib.RIG_OK + assert deg1 == 0 + assert mins1 == 2 + assert sec1 == 29 + assert sw1 == 1 + err, deg2, mins2, sec2, sw2 = Hamlib.dec2dms(lat1) + assert err == Hamlib.RIG_OK + assert deg2 == 48 + assert mins2 == 6 + assert sec2 == 15 + assert sw2 == 0 lon3 = Hamlib.dms2dec(deg1, mins1, sec1, sw1) lat3 = Hamlib.dms2dec(deg2, mins2, sec2, sw2) + assert lon3 == approx(-0.0414, abs=1.0e-04) # FIXME why need to override tolerance? + assert lat3 == approx(48.1042) - print('Longitude:\t%4.4f, %4d° %2d\' %2d" %1s\trecoded: %9.4f' \ - % (lon1, deg1, mins1, sec1, ('W' if sw1 else 'E'), lon3)) - - print('Latitude:\t%4.4f, %4d° %2d\' %2d" %1s\trecoded: %9.4f' \ - % (lat1, deg2, mins2, sec2, ('S' if sw2 else 'N'), lat3)) - - my_rig.set_vfo_opt(0); + assert my_rig.set_vfo_opt(0) is None From 77c02b58bb9bbd81b92ae728c5b72a86a22c6bc1 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 25 May 2025 23:03:03 +0200 Subject: [PATCH 04/45] Add tests for the Rig class --- bindings/python/test_rig.py | 156 ++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100755 bindings/python/test_rig.py diff --git a/bindings/python/test_rig.py b/bindings/python/test_rig.py new file mode 100755 index 000000000..5a2da7b31 --- /dev/null +++ b/bindings/python/test_rig.py @@ -0,0 +1,156 @@ +#! /bin/env pytest +"""Tests of the Python bindings for Hamlib + +Running this script directly will use the installed bindings. +For an in-tree run use "make check", or set PYTHONPATH to point to +the directories containing Hamlib.py and _Hamlib.so. +""" +import Hamlib + +Hamlib.rig_set_debug(Hamlib.RIG_DEBUG_NONE) + +RIG_MODEL = Hamlib.RIG_MODEL_DUMMY + +class TestClass: + """Container class for tests""" + + def test_without_open(self): + """Call all the methods that do not depend on open()""" + rig = Hamlib.Rig(RIG_MODEL) + assert rig is not None + assert rig.do_exception == 0 + assert rig.error_status == Hamlib.RIG_OK + + assert isinstance(rig.caps.model_name, str) + assert isinstance(rig.caps.mfg_name, str) + assert isinstance(rig.caps.version, str) + assert isinstance(rig.caps.copyright, str) + + assert rig.set_conf("", "") is None + assert rig.get_conf("") == "" + assert rig.get_conf(0) == "" + conf = rig.get_conf("mcfg") + assert isinstance(conf, str) + assert rig.set_conf("mcfg", "foo") is None + conf = rig.get_conf("mcfg") + assert conf == "foo" + + assert rig.token_lookup("") is None + + + def test_with_open(self): + """Call all the methods that depend on open()""" + rig = Hamlib.Rig(RIG_MODEL) + assert rig is not None + + assert rig.state.comm_state == 0 + assert rig.open() is None + assert rig.state.comm_state == 1 + info = rig.get_info() + assert isinstance(info, str) + assert rig.close() is None + assert rig.state.comm_state == 0 + info = rig.get_info() + assert info is None + + + def test_misc(self): + """Just call all the methods""" + rig = Hamlib.Rig(RIG_MODEL) + assert rig is not None + + rig.caps + # FIXME rig.chan_clear() + rig.close() + rig.ext_token_lookup("") + # FIXME rig.get_ant() + rig.get_chan_all() + rig.get_channel(0, 0, 0) + rig.get_channel(0, 0) + rig.get_conf("") + rig.get_ctcss_sql() + rig.get_ctcss_tone() + rig.get_dcd() + rig.get_dcs_code() + rig.get_dcs_sql() + rig.get_ext_func(0) + rig.get_ext_level(0) + rig.get_ext_parm(0) + rig.get_freq() + rig.get_func(0) + rig.get_info() + rig.get_level(0) + rig.get_level_f(0) + rig.get_level_i(0) + rig.get_mem() + rig.get_mode() + rig.get_parm(0) + rig.get_parm_f(0) + rig.get_parm_i(0) + rig.get_powerstat() + rig.get_ptt() + rig.get_rit() + rig.get_rptr_offs() + rig.get_rptr_shift() + rig.get_split_freq() + rig.get_split_mode() + # FIXME rig.get_split_vfo() + rig.get_trn() + rig.get_ts() + rig.get_vfo() + # FIXME rig.get_vfo_info() + rig.get_xit() + rig.has_get_level(0) + rig.has_scan(0) + rig.has_set_func(0) + rig.has_set_parm(0) + rig.has_vfo_op(0) + rig.lookup_mem_caps(0) + rig.mem_count() + rig.open() + rig.passband_narrow(0) + rig.passband_normal(0) + rig.passband_wide(0) + rig.recv_dtmf() + rig.reset(Hamlib.RIG_RESET_NONE) + rig.rig + rig.scan(0, 0, 0) + rig.send_dtmf(0, "") + rig.send_morse(0, "") + option = Hamlib.value_t() + option.i = 0 # FIXME use constants RIG_ANT_* when available + rig.set_ant(Hamlib.RIG_VFO_CURR, option) + rig.set_bank(0, 0) + channel = Hamlib.channel() + rig.set_channel(channel) + rig.set_conf("", "") + rig.set_ctcss_sql(0, 0) + rig.set_ctcss_tone(0, 0) + rig.set_dcs_code(0, 0) + rig.set_dcs_sql(0, 0) + rig.set_ext_func(0, 0) + # FIXME rig.set_ext_level() + # FIXME rig.set_ext_parm() + rig.set_freq(0, 0) + rig.set_func(0, 0, 0) + rig.set_level(0, 0, 0) + rig.set_mem(0, 0) + rig.set_mode(0, 0, 0) + rig.set_parm(0, 0) + rig.set_powerstat(0) + rig.set_ptt(0, 0) + rig.set_rit(0, 0) + rig.set_rptr_offs(0, 0) + rig.set_rptr_shift(0, 0) + rig.set_split_freq(0, 0) + rig.set_split_freq_mode(0, 0) + rig.set_split_mode(0, 0) + rig.set_split_vfo(0, 0) + rig.set_trn(0) + rig.set_ts(0, 0) + rig.set_vfo(0) + rig.set_vfo_opt(0) + rig.set_xit(0, 0) + rig.state + rig.token_lookup("") + rig.vfo_op(0, 0) From 65ffc5426b8c47d1a082ed793c5750ddf61f3a79 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Fri, 30 May 2025 23:57:58 +0200 Subject: [PATCH 05/45] Remove undocumented unused method rig.chan_clear() --- bindings/python/test_rig.py | 1 - bindings/rig.swg | 4 ---- 2 files changed, 5 deletions(-) diff --git a/bindings/python/test_rig.py b/bindings/python/test_rig.py index 5a2da7b31..4f290d8d4 100755 --- a/bindings/python/test_rig.py +++ b/bindings/python/test_rig.py @@ -60,7 +60,6 @@ class TestClass: assert rig is not None rig.caps - # FIXME rig.chan_clear() rig.close() rig.ext_token_lookup("") # FIXME rig.get_ant() diff --git a/bindings/rig.swg b/bindings/rig.swg index a101d1575..b44528b89 100644 --- a/bindings/rig.swg +++ b/bindings/rig.swg @@ -478,10 +478,6 @@ typedef channel_t * const_channel_t_p; /* TODO: handle ext_level's */ } - void chan_clear(struct channel *chans, int nb_chans = 1) { - memset(chans, 0, sizeof(struct channel)*nb_chans); - } - void get_chan_all(struct channel *chans) { self->error_status = rig_get_chan_all(self->rig, RIG_VFO_NONE, chans); /* TODO: handle ext_level's */ From 591f7cf5c818fc38d2a2b9b217ca866b46826b0e Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sat, 31 May 2025 23:08:37 +0200 Subject: [PATCH 06/45] Fix Rig.get_ant() --- bindings/python/test_rig.py | 5 ++++- bindings/rig.swg | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/bindings/python/test_rig.py b/bindings/python/test_rig.py index 4f290d8d4..a5160abe1 100755 --- a/bindings/python/test_rig.py +++ b/bindings/python/test_rig.py @@ -62,7 +62,10 @@ class TestClass: rig.caps rig.close() rig.ext_token_lookup("") - # FIXME rig.get_ant() + option = Hamlib.value_t() + ant = 0 # FIXME use constants RIG_ANT_* when available + rig.get_ant(option, ant, 0) + option.i == 0 rig.get_chan_all() rig.get_channel(0, 0, 0) rig.get_channel(0, 0) diff --git a/bindings/rig.swg b/bindings/rig.swg index b44528b89..c7e579640 100644 --- a/bindings/rig.swg +++ b/bindings/rig.swg @@ -453,7 +453,7 @@ typedef channel_t * const_channel_t_p; METHOD1VGET(get_rit, shortfreq_t) METHOD1VGET(get_xit, shortfreq_t) METHOD1VGET(get_ts, shortfreq_t) - extern void get_ant(ant_t *ant_rx, ant_t *ant_tx, ant_t *ant_curr, value_t * OUTPUT, ant_t ant, vfo_t vfo = RIG_VFO_CURR); + extern void get_ant(ant_t *OUTPUT, ant_t *OUTPUT, ant_t *OUTPUT, value_t *OUTPUT, ant_t ant, vfo_t vfo = RIG_VFO_CURR); extern void get_vfo_info (int *satmode, split_t *split, pbwidth_t *width, rmode_t *mode, freq_t *freq, vfo_t vfo = RIG_VFO_CURR); METHOD1VGET(get_mem, int) METHOD1GET(get_powerstat, powerstat_t) From 637ccebe0261a2a101d072bd56fe2bd180c6ce7e Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Thu, 12 Jun 2025 07:56:05 +0200 Subject: [PATCH 07/45] Test returned datatypes --- bindings/python/test_rig.py | 243 ++++++++++++++++++++++-------------- 1 file changed, 149 insertions(+), 94 deletions(-) diff --git a/bindings/python/test_rig.py b/bindings/python/test_rig.py index a5160abe1..a7d2aa206 100755 --- a/bindings/python/test_rig.py +++ b/bindings/python/test_rig.py @@ -59,100 +59,155 @@ class TestClass: rig = Hamlib.Rig(RIG_MODEL) assert rig is not None - rig.caps - rig.close() - rig.ext_token_lookup("") + assert rig.close() is None + assert rig.ext_token_lookup("") is None option = Hamlib.value_t() - ant = 0 # FIXME use constants RIG_ANT_* when available - rig.get_ant(option, ant, 0) - option.i == 0 - rig.get_chan_all() - rig.get_channel(0, 0, 0) - rig.get_channel(0, 0) - rig.get_conf("") - rig.get_ctcss_sql() - rig.get_ctcss_tone() - rig.get_dcd() - rig.get_dcs_code() - rig.get_dcs_sql() - rig.get_ext_func(0) - rig.get_ext_level(0) - rig.get_ext_parm(0) - rig.get_freq() - rig.get_func(0) - rig.get_info() - rig.get_level(0) - rig.get_level_f(0) - rig.get_level_i(0) - rig.get_mem() - rig.get_mode() - rig.get_parm(0) - rig.get_parm_f(0) - rig.get_parm_i(0) - rig.get_powerstat() - rig.get_ptt() - rig.get_rit() - rig.get_rptr_offs() - rig.get_rptr_shift() - rig.get_split_freq() - rig.get_split_mode() - # FIXME rig.get_split_vfo() - rig.get_trn() - rig.get_ts() - rig.get_vfo() - # FIXME rig.get_vfo_info() - rig.get_xit() - rig.has_get_level(0) - rig.has_scan(0) - rig.has_set_func(0) - rig.has_set_parm(0) - rig.has_vfo_op(0) - rig.lookup_mem_caps(0) - rig.mem_count() - rig.open() - rig.passband_narrow(0) - rig.passband_normal(0) - rig.passband_wide(0) - rig.recv_dtmf() - rig.reset(Hamlib.RIG_RESET_NONE) - rig.rig - rig.scan(0, 0, 0) - rig.send_dtmf(0, "") - rig.send_morse(0, "") + ant = 0 # FIXME should use a RIG_ANT_* constant but it isn't available in the bindings + assert isinstance(rig.get_ant(option, ant), list) + assert isinstance(rig.get_ant(option, ant, Hamlib.RIG_VFO_CURR), list) + assert option.i == 0 + assert rig.get_chan_all() is None + channel = 0 + readonly = 0 + assert isinstance(rig.get_channel(channel), Hamlib.channel) + assert isinstance(rig.get_channel(channel, Hamlib.RIG_VFO_CURR), Hamlib.channel) + assert isinstance(rig.get_channel(channel, Hamlib.RIG_VFO_CURR, readonly), Hamlib.channel) + assert isinstance(rig.get_conf(""), str) + assert isinstance(rig.get_ctcss_sql(), int) + assert isinstance(rig.get_ctcss_sql(0), int) + assert isinstance(rig.get_ctcss_tone(), int) + assert isinstance(rig.get_ctcss_tone(0), int) + assert isinstance(rig.get_dcd(), int) + assert isinstance(rig.get_dcd(Hamlib.RIG_VFO_CURR,), int) + assert isinstance(rig.get_dcs_code(), int) + assert isinstance(rig.get_dcs_code(0), int) + assert isinstance(rig.get_dcs_sql(), int) + assert isinstance(rig.get_dcs_sql(0), int) + assert isinstance(rig.get_ext_func(0), int) + assert isinstance(rig.get_ext_func(0, 0), int) + assert rig.get_ext_level(0) is None + assert rig.get_ext_level(0, 0) is None + assert rig.get_ext_parm(0) is None + assert isinstance(rig.get_freq(), float) + assert isinstance(rig.get_freq(Hamlib.RIG_VFO_CURR), float) + assert isinstance(rig.get_func(0), int) + assert isinstance(rig.get_func(0, 0), int) + assert rig.get_info() is None + assert rig.get_level(0) is None + assert isinstance(rig.get_level_f(0), float) + assert isinstance(rig.get_level_i(0), int) + assert isinstance(rig.get_mem(), int) + assert isinstance(rig.get_mem(Hamlib.RIG_VFO_CURR), int) + assert isinstance(rig.get_mode(), list) + assert isinstance(rig.get_mode(Hamlib.RIG_VFO_CURR), list) + assert rig.get_parm(0) is None + assert isinstance(rig.get_parm_f(0), float) + assert isinstance(rig.get_parm_i(0), int) + assert isinstance(rig.get_powerstat(), int) + assert isinstance(rig.get_ptt(), int) + assert isinstance(rig.get_ptt(Hamlib.RIG_VFO_CURR), int) + assert isinstance(rig.get_rit(), int) + assert isinstance(rig.get_rit(Hamlib.RIG_VFO_CURR), int) + assert isinstance(rig.get_rptr_offs(), int) + assert isinstance(rig.get_rptr_offs(Hamlib.RIG_VFO_CURR), int) + assert isinstance(rig.get_rptr_shift(), int) + assert isinstance(rig.get_rptr_shift(Hamlib.RIG_VFO_CURR), int) + assert isinstance(rig.get_split_freq(), float) + assert isinstance(rig.get_split_freq(Hamlib.RIG_VFO_CURR), float) + assert isinstance(rig.get_split_mode(), list) + assert isinstance(rig.get_split_mode(Hamlib.RIG_VFO_CURR), list) + # assert rig.get_split_vfo() is None # FIXME + # assert rig.get_split_vfo(Hamlib.RIG_VFO_CURR) is None # FIXME + assert isinstance(rig.get_trn(), int) # deprecated + assert isinstance(rig.get_ts(), int) + assert isinstance(rig.get_ts(Hamlib.RIG_VFO_CURR), int) + assert isinstance(rig.get_vfo(), int) + # assert rig.get_vfo_info(Hamlib.RIG_VFO_CURR) is None # FIXME + # assert rig.get_vfo_info(Hamlib.RIG_VFO_CURR, 2) is None # FIXME + # assert rig.get_vfo_info(Hamlib.RIG_VFO_CURR, 2, 3) is None # FIXME + assert isinstance(rig.get_xit(), int) + assert isinstance(rig.get_xit(Hamlib.RIG_VFO_CURR), int) + # assert rig_has_get_func(0) FIXME not defined + assert rig.has_get_level(0) is None # FIXME should return setting_t + # assert rig_has_get_parm(0) FIXME not defined + assert rig.has_scan(0) is None # FIXME should return scan_t + assert rig.has_set_func(0) is None # FIXME should return setting_t + # assert rig_has_set_level(0) FIXME not defined + assert rig.has_set_parm(0) is None # FIXME should return setting_t + assert rig.has_vfo_op(0) is None # FIXME should return vfo_op_t + assert rig.lookup_mem_caps() is None + assert rig.lookup_mem_caps(0) is None + assert isinstance(rig.mem_count(), int) + assert rig.open() is None + assert rig.passband_narrow(0) is None + assert rig.passband_normal(0) is None + assert rig.passband_wide(0) is None + assert isinstance(rig.recv_dtmf(), str) + assert isinstance(rig.recv_dtmf(0), str) + assert rig.reset(Hamlib.RIG_RESET_NONE) is None + assert rig.scan(0, 0) is None + assert rig.scan(0, 0, 0) is None + assert rig.send_dtmf(0, "") is None + assert rig.send_morse(0, "") is None option = Hamlib.value_t() - option.i = 0 # FIXME use constants RIG_ANT_* when available - rig.set_ant(Hamlib.RIG_VFO_CURR, option) - rig.set_bank(0, 0) + option.i = 0 # FIXME should use a RIG_ANT_* constant but it isn't available in the bindings + assert rig.set_ant(Hamlib.RIG_VFO_CURR, option) is None + assert rig.set_ant(Hamlib.RIG_VFO_CURR, option, 0) is None + assert rig.set_bank(0, 0) is None channel = Hamlib.channel() - rig.set_channel(channel) - rig.set_conf("", "") - rig.set_ctcss_sql(0, 0) - rig.set_ctcss_tone(0, 0) - rig.set_dcs_code(0, 0) - rig.set_dcs_sql(0, 0) - rig.set_ext_func(0, 0) - # FIXME rig.set_ext_level() - # FIXME rig.set_ext_parm() - rig.set_freq(0, 0) - rig.set_func(0, 0, 0) - rig.set_level(0, 0, 0) - rig.set_mem(0, 0) - rig.set_mode(0, 0, 0) - rig.set_parm(0, 0) - rig.set_powerstat(0) - rig.set_ptt(0, 0) - rig.set_rit(0, 0) - rig.set_rptr_offs(0, 0) - rig.set_rptr_shift(0, 0) - rig.set_split_freq(0, 0) - rig.set_split_freq_mode(0, 0) - rig.set_split_mode(0, 0) - rig.set_split_vfo(0, 0) - rig.set_trn(0) - rig.set_ts(0, 0) - rig.set_vfo(0) - rig.set_vfo_opt(0) - rig.set_xit(0, 0) - rig.state - rig.token_lookup("") - rig.vfo_op(0, 0) + channel = Hamlib.channel(0) + channel = Hamlib.channel(0, 0) + assert rig.set_channel(channel) is None + assert rig.set_conf("", "") is None + assert rig.set_ctcss_sql(0, 0) is None + assert rig.set_ctcss_tone(0, 0) is None + assert rig.set_dcs_code(0, 0) is None + assert rig.set_dcs_sql(0) is None + assert rig.set_dcs_sql(0, 0) is None + assert rig.set_ext_func(0, 0) is None + assert rig.set_ext_func(0, 0, 0) is None + level = 0 + value = Hamlib.value_t() + assert rig.set_ext_level(level, value) is None + assert rig.set_ext_level(level, value, Hamlib.RIG_VFO_CURR) is None + value = Hamlib.value_t() + assert rig.set_ext_parm(0, value) is None + assert rig.set_freq(0, 0) is None + assert rig.set_func(0, 0, 0) is None + assert rig.set_level(0, 0, 0) is None + assert rig.set_mem(0, 0) is None + assert rig.set_mode(0) is None + assert rig.set_mode(0, 0) is None + assert rig.set_mode(0, 0, 0) is None + assert rig.set_parm(0, 0) is None + assert rig.set_powerstat(0) is None + assert rig.set_ptt(0, 0) is None + assert rig.set_rit(0, 0) is None + assert rig.set_rptr_offs(0, 0) is None + assert rig.set_rptr_shift(0, 0) is None + assert rig.set_split_freq(0, 0) is None + assert rig.set_split_freq_mode(0, 0) is None + assert rig.set_split_freq_mode(0, 0, 0) is None + assert rig.set_split_freq_mode(0, 0, 0, 0) is None + assert rig.set_split_mode(0) is None + assert rig.set_split_mode(0, 0) is None + assert rig.set_split_mode(0, 0, 0) is None + assert rig.set_split_vfo(0, 0) is None + assert rig.set_split_vfo(0, 0, 0) is None + assert rig.set_trn(0) is None # deprecated + assert rig.set_ts(0, 0) is None + assert rig.set_vfo(0) is None + assert rig.set_vfo_opt(0) is None + assert rig.set_xit(0, 0) is None + assert rig.token_lookup("") is None + assert rig.vfo_op(0, 0) is None + + + def test_object_creation(self): + """Create all objects available""" + rig = Hamlib.Rig(RIG_MODEL) + assert rig is not None + + assert isinstance(rig.caps, Hamlib.rig_caps) + assert isinstance(rig.rig, Hamlib.s_rig) + assert isinstance(rig.state, Hamlib.rig_state) From bf4daf1486a4a35f14089722e08e7458e7d1b36b Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sat, 14 Jun 2025 19:22:06 +0200 Subject: [PATCH 08/45] Enable pytest in github actions, also for feature/* branches --- .github/workflows/c-cpp.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 6741060f4..d635fb592 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -2,7 +2,7 @@ name: C/C++ CI on: push: - branches: [ master ] + branches: [ master, feature/* ] pull_request: branches: [ master ] @@ -21,6 +21,7 @@ jobs: sudo apt install libusb-1.0-0-dev sudo apt install libgpiod-dev sudo apt install grep + sudo apt install python3-dev python3-pytest - name: Install dependencies on macOS if: runner.os == 'macOS' run: | @@ -38,7 +39,11 @@ jobs: - name: README Debug run: grep README Makefile.am - name: configure - run: ./configure + if: runner.os != 'macOS' + run: ./configure --with-python-binding + - name: configure on macOS + if: runner.os == 'macOS' + run: ./configure --without-python-binding - name: make run: make -j 4 - name: make check From 8a191213e6d42ce00a059fc70c556587e0e91368 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 4 May 2025 21:41:29 +0200 Subject: [PATCH 09/45] Add missing definitions for amplifiers --- bindings/hamlib.swg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bindings/hamlib.swg b/bindings/hamlib.swg index 05284c282..e07dd0010 100644 --- a/bindings/hamlib.swg +++ b/bindings/hamlib.swg @@ -228,6 +228,9 @@ %include %include +%include +%include + %inline { typedef const char * const_char_string; } From aa5c232def665e39714414fc30ce8a775ecce6f9 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sat, 24 May 2025 19:11:43 +0200 Subject: [PATCH 10/45] Rename and fix AMPMETHOD1VGET macro Drop the V which means VFO and add missing parentheses. --- bindings/amplifier.swg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/amplifier.swg b/bindings/amplifier.swg index 3d445361f..c7beaf4f0 100644 --- a/bindings/amplifier.swg +++ b/bindings/amplifier.swg @@ -104,7 +104,7 @@ typedef struct Amp { /* * declare wrapper method with one output argument besides AMP* */ -#define AMPMETHOD1VGET(f, t1) t1 f \ +#define AMPMETHOD1GET(f, t1) t1 f () \ { t1 _##t1; self->error_status = amp_##f(self->amp, &_##t1); return _##t1; } From df0d434b27cb7abdc86c926a1f7437b5926f953b Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 25 May 2025 08:26:42 +0200 Subject: [PATCH 11/45] Remove more symbols from Hamlib module using regexes --- bindings/ignore.swg | 288 ++++++++++++++------------------------------ 1 file changed, 91 insertions(+), 197 deletions(-) diff --git a/bindings/ignore.swg b/bindings/ignore.swg index 258b7677c..327f91fb0 100644 --- a/bindings/ignore.swg +++ b/bindings/ignore.swg @@ -1,213 +1,107 @@ /* unsupported Hamlib's calls */ /* useless macros */ -%ignore _RIG_H; -%ignore _RIGLIST_H; -%ignore _ROTLIST_H; -%ignore _ROTATOR_H; -%ignore RIG_DUMMY; -%ignore RIG_BACKEND_DUMMY; -%ignore RIG_YAESU; -%ignore RIG_BACKEND_YAESU; -%ignore RIG_KENWOOD; -%ignore RIG_BACKEND_KENWOOD; -%ignore RIG_ICOM; -%ignore RIG_BACKEND_ICOM; -%ignore RIG_PCR; -%ignore RIG_BACKEND_PCR; -%ignore RIG_AOR; -%ignore RIG_BACKEND_AOR; -%ignore RIG_JRC; -%ignore RIG_BACKEND_JRC; -%ignore RIG_RADIOSHACK; -%ignore RIG_BACKEND_RADIOSHACK; -%ignore RIG_UNIDEN; -%ignore RIG_BACKEND_UNIDEN; -%ignore RIG_DRAKE; -%ignore RIG_BACKEND_DRAKE; -%ignore RIG_LOWE; -%ignore RIG_BACKEND_LOWE; -%ignore RIG_RACAL; -%ignore RIG_BACKEND_RACAL; -%ignore RIG_WJ; -%ignore RIG_BACKEND_WJ; -%ignore RIG_EK; -%ignore RIG_BACKEND_EK; -%ignore RIG_SKANTI; -%ignore RIG_BACKEND_SKANTI; -%ignore RIG_PRM80; -%ignore RIG_BACKEND_PRM80; -%ignore RIG_WINRADIO; -%ignore RIG_BACKEND_WINRADIO; -%ignore RIG_TENTEC; -%ignore RIG_BACKEND_TENTEC; -%ignore RIG_ALINCO; -%ignore RIG_BACKEND_ALINCO; -%ignore RIG_KACHINA; -%ignore RIG_BACKEND_KACHINA; -%ignore RIG_RPC; -%ignore RIG_BACKEND_RPC; -%ignore RIG_GNURADIO; -%ignore RIG_BACKEND_GNURADIO; -%ignore RIG_MICROTUNE; -%ignore RIG_BACKEND_MICROTUNE; -%ignore RIG_TAPR; -%ignore RIG_BACKEND_TAPR; -%ignore RIG_FLEXRADIO; -%ignore RIG_BACKEND_FLEXRADIO; -%ignore RIG_RFT; -%ignore RIG_BACKEND_RFT; -%ignore RIG_KIT; -%ignore RIG_BACKEND_KIT; -%ignore RIG_TUNER; -%ignore RIG_BACKEND_TUNER; -%ignore RIG_RS; -%ignore RIG_BACKEND_RS; -%ignore RIG_ADAT; -%ignore RIG_BACKEND_ADAT; -%ignore RIG_ICMARINE; -%ignore RIG_BACKEND_ICMARINE; +%ignore AMP_DUMMY; +%ignore AMP_ELECRAFT; +%ignore AMP_GEMINI; +%ignore AMP_EXPERT; + +%ignore RIG_ADAT; +%ignore RIG_ALINCO; +%ignore RIG_ANYTONE; +%ignore RIG_AOR; +%ignore RIG_BARRETT; +%ignore RIG_CODAN; +%ignore RIG_COMMRADIO; +%ignore RIG_DORJI; +%ignore RIG_DRAKE; +%ignore RIG_DUMMY; +%ignore RIG_EK; +%ignore RIG_ELAD; +%ignore RIG_FLEXRADIO; +%ignore RIG_GNURADIO; +%ignore RIG_GOMSPACE; +%ignore RIG_ICMARINE; +%ignore RIG_ICOM; +%ignore RIG_JRC; +%ignore RIG_KACHINA; +%ignore RIG_KENWOOD; +%ignore RIG_KIT; +%ignore RIG_LOWE; +%ignore RIG_MDS; +%ignore RIG_MICROTUNE; +%ignore RIG_MOTOROLA; +%ignore RIG_PCR; +%ignore RIG_PRM80; +%ignore RIG_RACAL; +%ignore RIG_RADIOSHACK; +%ignore RIG_RFT; +%ignore RIG_RS; +%ignore RIG_SKANTI; +%ignore RIG_TAPR; +%ignore RIG_TENTEC; +%ignore RIG_TUNER; +%ignore RIG_UNIDEN; +%ignore RIG_WINRADIO; +%ignore RIG_WJ; +%ignore RIG_YAESU; -%ignore ROT_DUMMY; -%ignore ROT_BACKEND_DUMMY; -%ignore ROT_RPC; -%ignore ROT_BACKEND_RPC; -%ignore ROT_EASYCOMM; -%ignore ROT_BACKEND_EASYCOMM; -%ignore ROT_FODTRACK; -%ignore ROT_BACKEND_FODTRACK; -%ignore ROT_ROTOREZ; -%ignore ROT_BACKEND_ROTOREZ; -%ignore ROT_SARTEK; -%ignore ROT_BACKEND_SARTEK; -%ignore ROT_GS232A; -%ignore ROT_BACKEND_GS232A; -%ignore ROT_KIT; -%ignore ROT_BACKEND_KIT; -%ignore ROT_HEATHKIT; -%ignore ROT_BACKEND_HEATHKIT; -%ignore ROT_SPID; -%ignore ROT_BACKEND_SPID; -%ignore ROT_M2; -%ignore ROT_BACKEND_M2; -%ignore ROT_ARS; -%ignore ROT_BACKEND_ARS; %ignore ROT_AMSAT; -%ignore ROT_BACKEND_AMSAT; -%ignore ROT_TS7400; -%ignore ROT_BACKEND_TS7400; +%ignore ROT_ANDROIDSENSOR; +%ignore ROT_APEX; +%ignore ROT_ARRAYSOLUTIONS; +%ignore ROT_ARS; %ignore ROT_CELESTRON; -%ignore ROT_BACKEND_CELESTRON; +%ignore ROT_CNCTRK; +%ignore ROT_DUMMY; +%ignore ROT_EASYCOMM; +%ignore ROT_ETHER6; +%ignore ROT_FLIR; +%ignore ROT_FODTRACK; +%ignore ROT_GRBLTRK; +%ignore ROT_GS232A; +%ignore ROT_HEATHKIT; +%ignore ROT_INDI; +%ignore ROT_IOPTRON; +%ignore ROT_KIT; +%ignore ROT_M2; +%ignore ROT_MEADE; +%ignore ROT_PROSISTEL; +%ignore ROT_RADANT; +%ignore ROT_ROTOREZ; +%ignore ROT_SAEBRTRACK; +%ignore ROT_SARTEK; +%ignore ROT_SATEL; +%ignore ROT_SKYWATCHER; +%ignore ROT_SPID; +%ignore ROT_TS7400; %ignore PRIfreq; %ignore SCNfreq; %ignore FREQFMT; -%ignore rig_open; -%ignore rig_set_freq; -%ignore rig_get_freq; -%ignore rig_set_mode; -%ignore rig_get_mode; -%ignore rig_set_vfo; -%ignore rig_get_vfo; -%ignore rig_set_ptt; -%ignore rig_get_ptt; -%ignore rig_get_dcd; -%ignore rig_set_rptr_shift; -%ignore rig_get_rptr_shift; -%ignore rig_set_rptr_offs; -%ignore rig_get_rptr_offs; -%ignore rig_set_ctcss_tone; -%ignore rig_get_ctcss_tone; -%ignore rig_set_dcs_code; -%ignore rig_get_dcs_code; -%ignore rig_set_ctcss_sql; -%ignore rig_get_ctcss_sql; -%ignore rig_set_dcs_sql; -%ignore rig_get_dcs_sql; -%ignore rig_set_split_freq; -%ignore rig_get_split_freq; -%ignore rig_set_split_mode; -%ignore rig_get_split_mode; -%ignore rig_set_split; -%ignore rig_get_split; -%ignore rig_set_rit; -%ignore rig_get_rit; -%ignore rig_set_xit; -%ignore rig_get_xit; -%ignore rig_set_ts; -%ignore rig_get_ts; -%ignore rig_power2mW; -%ignore rig_mW2power; -%ignore rig_get_resolution; -%ignore rig_set_level; -%ignore rig_get_level; -%ignore rig_set_parm; -%ignore rig_get_parm; -%ignore rig_set_conf; -%ignore rig_get_conf; -%ignore rig_set_powerstat; -%ignore rig_get_powerstat; -%ignore rig_reset; -%ignore rig_set_ext_level; -%ignore rig_get_ext_level; -%ignore rig_set_ext_parm; -%ignore rig_get_ext_parm; -%ignore rig_ext_level_foreach; -%ignore rig_ext_parm_foreach; -%ignore rig_token_lookup; -%ignore rig_close; -%ignore rig_cleanup; -%ignore rig_probe; -%ignore rig_set_ant; -%ignore rig_get_ant; -%ignore rig_has_get_level; -%ignore rig_has_set_level; -%ignore rig_has_get_parm; -%ignore rig_has_set_parm; -%ignore rig_has_get_func; -%ignore rig_has_set_func; -%ignore rig_set_func; -%ignore rig_get_func; -%ignore rig_send_dtmf; -%ignore rig_recv_dtmf; -%ignore rig_send_morse; -%ignore rig_set_bank; -%ignore rig_set_mem; -%ignore rig_get_mem; -%ignore rig_vfo_op; -%ignore rig_has_vfo_op; -%ignore rig_scan; -%ignore rig_has_scan; -%ignore rig_set_channel; -%ignore rig_get_channel; -%ignore rig_set_trn; -%ignore rig_get_trn; -%ignore rig_set_freq_callback; -%ignore rig_set_mode_callback; -%ignore rig_set_vfo_callback; -%ignore rig_set_ptt_callback; -%ignore rig_set_dcd_callback; -%ignore rig_set_pltune_callback; -%ignore rig_get_info; -%ignore rig_passband_normal; -%ignore rig_passband_narrow; -%ignore rig_passband_wide; -%ignore rig_get_vfo_info; +// remove defines from Hamlib class +%rename("$ignore", regexmatch$name="^_") ""; +%rename("$ignore", regexmatch$name="^AMP_BACKEND") ""; +%rename("$ignore", regexmatch$name="^RIG_BACKEND") ""; +%rename("$ignore", regexmatch$name="^ROT_BACKEND") ""; -%ignore rot_open; -%ignore rot_close; -%ignore rot_cleanup; -%ignore rot_set_conf; -%ignore rot_get_conf; -%ignore rot_set_position; -%ignore rot_get_position; -%ignore rot_stop; -%ignore rot_park; -%ignore rot_reset; -%ignore rot_move; -%ignore rot_get_info; +// remove methods from Hamlib class +%rename("$ignore", regexmatch$name="^amp_", %$isfunction) ""; +%rename("$ignore", regexmatch$name="^rig_", %$isfunction) ""; +%rename("$ignore", regexmatch$name="^rot_", %$isfunction) ""; +// re-add some methods +%rename("%s") rig_set_debug; +%rename("%s", regexmatch$name="^rig_str", %$isfunction) ""; +// remove typedefs +%ignore s_rig; +%ignore s_rot; + +%ignore amp; +%ignore debugmsgsave; +%ignore debugmsgsave2; +%ignore debugmsgsave3; %ignore hamlib_copyright2; %ignore hamlib_version2; %ignore macro_name; From 4b0fa60e95cae7a977a6ca6884b07f589fd03ef9 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 15 Jun 2025 11:29:28 +0200 Subject: [PATCH 12/45] Remove ignored symbol --- bindings/python/test_rig.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bindings/python/test_rig.py b/bindings/python/test_rig.py index a7d2aa206..5c64f31e8 100755 --- a/bindings/python/test_rig.py +++ b/bindings/python/test_rig.py @@ -209,5 +209,4 @@ class TestClass: assert rig is not None assert isinstance(rig.caps, Hamlib.rig_caps) - assert isinstance(rig.rig, Hamlib.s_rig) assert isinstance(rig.state, Hamlib.rig_state) From 48c40dc326e089b62ecd6a7d0c5b5957d4718082 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 25 May 2025 11:55:59 +0200 Subject: [PATCH 13/45] Move includes in the files where they are used Makes the other files less dependent on being included by hamlib.swg and more self-contained. Need to explicitly add %include for amplist.h, riglist.h, rotlist.h to have the definitions picked up by SWIG even if they are included by the main .swg file. --- bindings/amplifier.swg | 6 ++++++ bindings/hamlib.swg | 12 ------------ bindings/rig.swg | 6 ++++++ bindings/rotator.swg | 6 ++++++ 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/bindings/amplifier.swg b/bindings/amplifier.swg index c7beaf4f0..27e76de4a 100644 --- a/bindings/amplifier.swg +++ b/bindings/amplifier.swg @@ -19,6 +19,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ +%{ +#include +%} + +%include +%include %inline %{ diff --git a/bindings/hamlib.swg b/bindings/hamlib.swg index e07dd0010..bdeb876bc 100644 --- a/bindings/hamlib.swg +++ b/bindings/hamlib.swg @@ -29,9 +29,6 @@ #include -#include -#include -#include //mdblack98 -- Commented this out -- is anybody using the functions in misc.h? //If so, then those functions should be moved to rig.h //#include "misc.h" @@ -222,15 +219,6 @@ %include -%include -%include - -%include -%include - -%include -%include - %inline { typedef const char * const_char_string; } diff --git a/bindings/rig.swg b/bindings/rig.swg index c7e579640..7c6101798 100644 --- a/bindings/rig.swg +++ b/bindings/rig.swg @@ -18,6 +18,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ +%{ +#include +%} + +%include +%include %inline %{ diff --git a/bindings/rotator.swg b/bindings/rotator.swg index 2e527fcef..90d07c281 100644 --- a/bindings/rotator.swg +++ b/bindings/rotator.swg @@ -18,6 +18,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ +%{ +#include +%} + +%include +%include %inline %{ From bca1d80d205b00f1a005806c52ffb7363243b194 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 25 May 2025 14:01:19 +0200 Subject: [PATCH 14/45] Move/add %immutable in their files Makes the other files less dependent on being included by hamlib.swg and more self-contained. Also drop the symbols that are ignored. --- bindings/amplifier.swg | 5 +++++ bindings/hamlib.swg | 31 +++++++++++-------------------- bindings/rig.swg | 5 +++++ bindings/rotator.swg | 5 +++++ 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/bindings/amplifier.swg b/bindings/amplifier.swg index 27e76de4a..840ae389b 100644 --- a/bindings/amplifier.swg +++ b/bindings/amplifier.swg @@ -23,6 +23,11 @@ #include %} +%immutable amp_caps::model_name; +%immutable amp_caps::mfg_name; +%immutable amp_caps::version; +%immutable amp_caps::copyright; + %include %include diff --git a/bindings/hamlib.swg b/bindings/hamlib.swg index bdeb876bc..04f3968b5 100644 --- a/bindings/hamlib.swg +++ b/bindings/hamlib.swg @@ -37,6 +37,17 @@ %} +/* + * symbols that shouldn't be changed + */ +%immutable clone_combo_get; +%immutable clone_combo_set; +%immutable confparams::dflt; +%immutable confparams::label; +%immutable confparams::name; +%immutable confparams::tooltip; +%immutable cs; + /* * symbols that won't be wrapped */ @@ -197,26 +208,6 @@ #endif #endif -%immutable confparams::name; -%immutable confparams::label; -%immutable confparams::tooltip; -%immutable confparams::dflt; -%immutable cs; -%immutable rig_caps::model_name; -%immutable rig_caps::mfg_name; -%immutable rig_caps::version; -%immutable rig_caps::copyright; -%immutable hamlib_version2; -%immutable hamlib_copyright2; - -%immutable clone_combo_set; -%immutable clone_combo_get; - -%immutable rot_caps::model_name; -%immutable rot_caps::mfg_name; -%immutable rot_caps::version; -%immutable rot_caps::copyright; - %include %inline { diff --git a/bindings/rig.swg b/bindings/rig.swg index 7c6101798..e0f3373e6 100644 --- a/bindings/rig.swg +++ b/bindings/rig.swg @@ -22,6 +22,11 @@ #include %} +%immutable rig_caps::model_name; +%immutable rig_caps::mfg_name; +%immutable rig_caps::version; +%immutable rig_caps::copyright; + %include %include diff --git a/bindings/rotator.swg b/bindings/rotator.swg index 90d07c281..bbf2a637a 100644 --- a/bindings/rotator.swg +++ b/bindings/rotator.swg @@ -22,6 +22,11 @@ #include %} +%immutable rot_caps::model_name; +%immutable rot_caps::mfg_name; +%immutable rot_caps::version; +%immutable rot_caps::copyright; + %include %include From f2aaed6e0947bebeb6cccb8d392110e14568a96c Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 25 May 2025 14:17:38 +0200 Subject: [PATCH 15/45] Add missing type of the 4th argument of macro AMPMETHOD4 --- bindings/amplifier.swg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/amplifier.swg b/bindings/amplifier.swg index 840ae389b..26d4c4c8d 100644 --- a/bindings/amplifier.swg +++ b/bindings/amplifier.swg @@ -54,7 +54,7 @@ typedef struct Amp { { self->error_status = amp_##f(self->amp, _##t1##_1, _##t2##_2); } #define AMPMETHOD3(f, t1, t2, t3) void f (t1 _##t1##_1, t2 _##t2##_2, t3 _##t3##_3) \ { self->error_status = amp_##f(self->amp, _##t1##_1, _##t2##_2, t3 _##t3##_3); } -#define AMPMETHOD4(f, t1, t2, t3, t4) void f (t1 _##t1##_1, t2 _##t2##_3, t3 _##t3##_3, ##t4##_4) \ +#define AMPMETHOD4(f, t1, t2, t3, t4) void f (t1 _##t1##_1, t2 _##t2##_3, t3 _##t3##_3, t4 ##t4##_4) \ { self->error_status = amp_##f(self->amp, _##t1##_1, _##t2##_3, t3 _##t3##_3, ##t4##_4); } %extend Amp { From 464450384d95f2f6777db5552c1992bf118faded Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 15 Jun 2025 11:11:12 +0200 Subject: [PATCH 16/45] Add a Python script to autogenerate some tests for pytest --- bindings/Makefile.am | 5 ++ bindings/python/generate_tests.py | 92 +++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100755 bindings/python/generate_tests.py diff --git a/bindings/Makefile.am b/bindings/Makefile.am index cc9e35f3b..bc11e2235 100644 --- a/bindings/Makefile.am +++ b/bindings/Makefile.am @@ -22,6 +22,7 @@ SWGDEP = \ EXTRA_DIST = $(SWGFILES) \ Makefile.PL perltest.pl tcltest.tcl.in \ + python/generate_tests.py \ python/test_startup.py \ luatest.lua README.python @@ -108,6 +109,10 @@ all-py: $(pyexec_ltlib) check-py: all-py pytest-${enable_pytest} +generate-pytests: all-py + $(AM_V_at)PYTHONPATH=$(builddir):$(builddir)/.libs \ + $(PYTHON) "$(srcdir)/python/generate_tests.py" "$(srcdir)/python/" + pytest-yes: $(AM_V_at)PYTHONPATH=$(builddir):$(builddir)/.libs \ $(PYTEST) --capture=no $(srcdir)/ diff --git a/bindings/python/generate_tests.py b/bindings/python/generate_tests.py new file mode 100755 index 000000000..e7c79bd68 --- /dev/null +++ b/bindings/python/generate_tests.py @@ -0,0 +1,92 @@ +#! /bin/env python +""" +Creates tests for the Python bindings for Hamlib + +Running this script directly will use the installed bindings. +For an in-tree run use "make check", or set PYTHONPATH to point to +the directories containing Hamlib.py and _Hamlib.so. +""" +import inspect +import os +import sys + +import Hamlib + +# This class gets copied to the generated file with replacements +class TestClass: + """A pytest class for {object_name}""" + + @classmethod + def setup_class(cls): + """Common initialization before calling test methods""" + cls.actual_callables, cls.actual_properties = cls.generate_data({object_name}) + + def test_callables(self): + """Check that nothing was added or removed""" + expected_callables = {expected_callables} + assert expected_callables == self.actual_callables + + def test_properties(self): + """Check that nothing was added or removed""" + expected_properties = {expected_properties} + assert expected_properties == self.actual_properties + + @classmethod + def generate_data(cls, the_object): + """Extract callables and properties from the given object""" + callables = [] + properties = [] + for method_or_property in dir(the_object): + if not method_or_property.startswith("_"): + if callable(getattr(the_object, method_or_property)): + callables.append(method_or_property) + else: + properties.append(method_or_property) + + return callables, properties + + +def generate_file(object_name, callables, properties): + """Create a complete file for pytest""" + + file_header = '''#! /bin/env pytest +""" +Tests of the Python bindings for Hamlib + +DO NOT EDIT this autogenerated file, run "make generate-pytests" instead +""" +import Hamlib +''' + filename = f"test_{object_name.replace(".", "_")}_class.py" + class_source = inspect.getsource(TestClass) + expected_callables = repr(callables) + expected_properties = repr(properties) + + print(f"Generating {filename}") + with open(filename, "w", encoding='utf-8') as output_file: + print(file_header, file=output_file) + print(class_source.format( + object_name=object_name, + expected_callables=expected_callables, + expected_properties=expected_properties), + file=output_file, end='') + + +if __name__ == "__main__": + if len(sys.argv) == 2 and not sys.argv[1].startswith("-"): + os.chdir(sys.argv[1]) + else: + print("Usage: {sys.argv[0]} [OUTPUT_DIRECTORY]", file=sys.stderr) + sys.exit(1) + for the_object in ( + Hamlib, + Hamlib.Amp, + Hamlib.Rig, + Hamlib.Rot, + ): + try: + full_name = f"{the_object.__module__}.{the_object.__name__}" + except AttributeError: + full_name = the_object.__name__ + expected_callables, expected_properties = TestClass.generate_data(the_object) + generate_file(full_name, expected_callables, expected_properties) From 57b23e7efcc862a784fb55c1d00f87f19c3d4393 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 15 Jun 2025 11:12:42 +0200 Subject: [PATCH 17/45] Add autogenerated test scripts for pytest --- bindings/Makefile.am | 4 +++ bindings/python/test_Hamlib_Amp_class.py | 39 ++++++++++++++++++++++++ bindings/python/test_Hamlib_Rig_class.py | 39 ++++++++++++++++++++++++ bindings/python/test_Hamlib_Rot_class.py | 39 ++++++++++++++++++++++++ bindings/python/test_Hamlib_class.py | 39 ++++++++++++++++++++++++ 5 files changed, 160 insertions(+) create mode 100755 bindings/python/test_Hamlib_Amp_class.py create mode 100755 bindings/python/test_Hamlib_Rig_class.py create mode 100755 bindings/python/test_Hamlib_Rot_class.py create mode 100755 bindings/python/test_Hamlib_class.py diff --git a/bindings/Makefile.am b/bindings/Makefile.am index bc11e2235..550b6d0eb 100644 --- a/bindings/Makefile.am +++ b/bindings/Makefile.am @@ -23,6 +23,10 @@ SWGDEP = \ EXTRA_DIST = $(SWGFILES) \ Makefile.PL perltest.pl tcltest.tcl.in \ python/generate_tests.py \ + python/test_Hamlib_Amp_class.py \ + python/test_Hamlib_class.py \ + python/test_Hamlib_Rig_class.py \ + python/test_Hamlib_Rot_class.py \ python/test_startup.py \ luatest.lua README.python diff --git a/bindings/python/test_Hamlib_Amp_class.py b/bindings/python/test_Hamlib_Amp_class.py new file mode 100755 index 000000000..db0462838 --- /dev/null +++ b/bindings/python/test_Hamlib_Amp_class.py @@ -0,0 +1,39 @@ +#! /bin/env pytest +""" +Tests of the Python bindings for Hamlib + +DO NOT EDIT this autogenerated file, run "make generate-pytests" instead +""" +import Hamlib + +class TestClass: + """A pytest class for Hamlib.Amp""" + + @classmethod + def setup_class(cls): + """Common initialization before calling test methods""" + cls.actual_callables, cls.actual_properties = cls.generate_data(Hamlib.Amp) + + def test_callables(self): + """Check that nothing was added or removed""" + expected_callables = ['close', 'get_conf', 'get_info', 'open', 'reset', 'set_conf', 'set_freq', 'set_powerstat', 'token_lookup'] + assert expected_callables == self.actual_callables + + def test_properties(self): + """Check that nothing was added or removed""" + expected_properties = ['caps', 'do_exception', 'error_status', 'state', 'thisown'] + assert expected_properties == self.actual_properties + + @classmethod + def generate_data(cls, the_object): + """Extract callables and properties from the given object""" + callables = [] + properties = [] + for method_or_property in dir(the_object): + if not method_or_property.startswith("_"): + if callable(getattr(the_object, method_or_property)): + callables.append(method_or_property) + else: + properties.append(method_or_property) + + return callables, properties diff --git a/bindings/python/test_Hamlib_Rig_class.py b/bindings/python/test_Hamlib_Rig_class.py new file mode 100755 index 000000000..7f5d440ac --- /dev/null +++ b/bindings/python/test_Hamlib_Rig_class.py @@ -0,0 +1,39 @@ +#! /bin/env pytest +""" +Tests of the Python bindings for Hamlib + +DO NOT EDIT this autogenerated file, run "make generate-pytests" instead +""" +import Hamlib + +class TestClass: + """A pytest class for Hamlib.Rig""" + + @classmethod + def setup_class(cls): + """Common initialization before calling test methods""" + cls.actual_callables, cls.actual_properties = cls.generate_data(Hamlib.Rig) + + def test_callables(self): + """Check that nothing was added or removed""" + expected_callables = ['close', 'ext_token_lookup', 'get_ant', 'get_chan_all', 'get_channel', 'get_conf', 'get_ctcss_sql', 'get_ctcss_tone', 'get_dcd', 'get_dcs_code', 'get_dcs_sql', 'get_ext_func', 'get_ext_level', 'get_ext_parm', 'get_freq', 'get_func', 'get_info', 'get_level', 'get_level_f', 'get_level_i', 'get_mem', 'get_mode', 'get_parm', 'get_parm_f', 'get_parm_i', 'get_powerstat', 'get_ptt', 'get_rit', 'get_rptr_offs', 'get_rptr_shift', 'get_split_freq', 'get_split_mode', 'get_split_vfo', 'get_trn', 'get_ts', 'get_vfo', 'get_vfo_info', 'get_xit', 'has_get_level', 'has_scan', 'has_set_func', 'has_set_parm', 'has_vfo_op', 'lookup_mem_caps', 'mem_count', 'open', 'passband_narrow', 'passband_normal', 'passband_wide', 'recv_dtmf', 'reset', 'scan', 'send_dtmf', 'send_morse', 'set_ant', 'set_bank', 'set_channel', 'set_conf', 'set_ctcss_sql', 'set_ctcss_tone', 'set_dcs_code', 'set_dcs_sql', 'set_ext_func', 'set_ext_level', 'set_ext_parm', 'set_freq', 'set_func', 'set_level', 'set_mem', 'set_mode', 'set_parm', 'set_powerstat', 'set_ptt', 'set_rit', 'set_rptr_offs', 'set_rptr_shift', 'set_split_freq', 'set_split_freq_mode', 'set_split_mode', 'set_split_vfo', 'set_trn', 'set_ts', 'set_vfo', 'set_vfo_opt', 'set_xit', 'token_lookup', 'vfo_op'] + assert expected_callables == self.actual_callables + + def test_properties(self): + """Check that nothing was added or removed""" + expected_properties = ['caps', 'do_exception', 'error_status', 'rig', 'state', 'thisown'] + assert expected_properties == self.actual_properties + + @classmethod + def generate_data(cls, the_object): + """Extract callables and properties from the given object""" + callables = [] + properties = [] + for method_or_property in dir(the_object): + if not method_or_property.startswith("_"): + if callable(getattr(the_object, method_or_property)): + callables.append(method_or_property) + else: + properties.append(method_or_property) + + return callables, properties diff --git a/bindings/python/test_Hamlib_Rot_class.py b/bindings/python/test_Hamlib_Rot_class.py new file mode 100755 index 000000000..596f05f60 --- /dev/null +++ b/bindings/python/test_Hamlib_Rot_class.py @@ -0,0 +1,39 @@ +#! /bin/env pytest +""" +Tests of the Python bindings for Hamlib + +DO NOT EDIT this autogenerated file, run "make generate-pytests" instead +""" +import Hamlib + +class TestClass: + """A pytest class for Hamlib.Rot""" + + @classmethod + def setup_class(cls): + """Common initialization before calling test methods""" + cls.actual_callables, cls.actual_properties = cls.generate_data(Hamlib.Rot) + + def test_callables(self): + """Check that nothing was added or removed""" + expected_callables = ['close', 'get_conf', 'get_info', 'get_position', 'move', 'open', 'park', 'reset', 'set_conf', 'set_position', 'stop', 'token_lookup'] + assert expected_callables == self.actual_callables + + def test_properties(self): + """Check that nothing was added or removed""" + expected_properties = ['caps', 'do_exception', 'error_status', 'rot', 'state', 'thisown'] + assert expected_properties == self.actual_properties + + @classmethod + def generate_data(cls, the_object): + """Extract callables and properties from the given object""" + callables = [] + properties = [] + for method_or_property in dir(the_object): + if not method_or_property.startswith("_"): + if callable(getattr(the_object, method_or_property)): + callables.append(method_or_property) + else: + properties.append(method_or_property) + + return callables, properties diff --git a/bindings/python/test_Hamlib_class.py b/bindings/python/test_Hamlib_class.py new file mode 100755 index 000000000..58d83b613 --- /dev/null +++ b/bindings/python/test_Hamlib_class.py @@ -0,0 +1,39 @@ +#! /bin/env pytest +""" +Tests of the Python bindings for Hamlib + +DO NOT EDIT this autogenerated file, run "make generate-pytests" instead +""" +import Hamlib + +class TestClass: + """A pytest class for Hamlib""" + + @classmethod + def setup_class(cls): + """Common initialization before calling test methods""" + cls.actual_callables, cls.actual_properties = cls.generate_data(Hamlib) + + def test_callables(self): + """Check that nothing was added or removed""" + expected_callables = ['Amp', 'Rig', 'Rot', 'add2debugmsgsave', 'amp_caps', 'amp_state', 'azimuth_long_path', 'cal_table', 'cal_table_float', 'cal_table_float_table', 'cal_table_table', 'chan_list', 'channel', 'channelArray', 'channel_cap', 'confparams', 'confparams_u', 'confparams_u_c', 'confparams_u_n', 'dec2dmmm', 'dec2dms', 'deferred_config_header', 'deferred_config_item', 'distance_long_path', 'dmmm2dec', 'dms2dec', 'ext_list', 'filter_list', 'freq_range_t', 'gran', 'hamlib_port_deprecated_parm', 'hamlib_port_deprecated_parm_cm108', 'hamlib_port_deprecated_parm_gpio', 'hamlib_port_deprecated_parm_parallel', 'hamlib_port_deprecated_parm_serial', 'hamlib_port_deprecated_parm_usb', 'hamlib_port_deprecated_post_write_date', 'hamlib_port_deprecated_type', 'hamlib_port_parm', 'hamlib_port_parm_cm108', 'hamlib_port_parm_gpio', 'hamlib_port_parm_parallel', 'hamlib_port_parm_serial', 'hamlib_port_parm_usb', 'hamlib_port_post_write_date', 'hamlib_port_t', 'hamlib_port_t_deprecated', 'hamlib_port_type', 'hl_usleep', 'locator2longlat', 'longlat2locator', 'multicast_s', 'netrigctl_get_vfo_mode', 'qrb', 'rig_cache_deprecated', 'rig_callbacks', 'rig_caps', 'rig_set_debug', 'rig_spectrum_avg_mode', 'rig_spectrum_line', 'rig_spectrum_scope', 'rig_state', 'rig_state_deprecated', 'rig_stragclevel', 'rig_strcommstatus', 'rig_strfunc', 'rig_strlevel', 'rig_strmtype', 'rig_strparm', 'rig_strptrshift', 'rig_strrmode', 'rig_strrmodes', 'rig_strscan', 'rig_strspectrummode', 'rig_strstatus', 'rig_strvfo', 'rig_strvfop', 'rigerror', 'rigerror2', 'rot_caps', 'rot_state', 'toneArray', 'tuning_step_list', 'value_t', 'value_t_b'] + assert expected_callables == self.actual_callables + + def test_properties(self): + """Check that nothing was added or removed""" + expected_properties = ['AMP_FLAG_1', 'AMP_FLAG_2', 'AMP_LEVEL_FAULT', 'AMP_LEVEL_NH', 'AMP_LEVEL_NONE', 'AMP_LEVEL_PF', 'AMP_LEVEL_PWR', 'AMP_LEVEL_PWR_FWD', 'AMP_LEVEL_PWR_INPUT', 'AMP_LEVEL_PWR_PEAK', 'AMP_LEVEL_PWR_REFLECTED', 'AMP_LEVEL_SWR', 'AMP_MODEL_DUMMY', 'AMP_MODEL_ELECRAFT_KPA1500', 'AMP_MODEL_EXPERT_FA', 'AMP_MODEL_GEMINI_DX1200', 'AMP_MODEL_NETAMPCTL', 'AMP_MODEL_NONE', 'AMP_RESET_AMP', 'AMP_RESET_FAULT', 'AMP_RESET_MEM', 'AMP_TYPE_OTHER', 'BUILTINFUNC', 'CTCSS_LIST_SIZE', 'DCS_LIST_SIZE', 'DEBUGMSGSAVE_SIZE', 'GPIO1', 'GPIO2', 'GPIO3', 'GPIO4', 'HAMLIB_CACHE_ALL', 'HAMLIB_CACHE_ALWAYS', 'HAMLIB_CACHE_FREQ', 'HAMLIB_CACHE_MODE', 'HAMLIB_CACHE_PTT', 'HAMLIB_CACHE_SPLIT', 'HAMLIB_CACHE_VFO', 'HAMLIB_CACHE_WIDTH', 'HAMLIB_CHANLSTSIZ', 'HAMLIB_CHECK_RIG_CAPS', 'HAMLIB_COOKIE_SIZE', 'HAMLIB_ELAPSED_GET', 'HAMLIB_ELAPSED_INVALIDATE', 'HAMLIB_ELAPSED_SET', 'HAMLIB_FIFO_SIZE', 'HAMLIB_FILPATHLEN', 'HAMLIB_FLTLSTSIZ', 'HAMLIB_FRQRANGESIZ', 'HAMLIB_MAXCHANDESC', 'HAMLIB_MAXDBLSTSIZ', 'HAMLIB_MAX_AGC_LEVELS', 'HAMLIB_MAX_CAL_LENGTH', 'HAMLIB_MAX_MODES', 'HAMLIB_MAX_ROTORS', 'HAMLIB_MAX_RSCANS', 'HAMLIB_MAX_SNAPSHOT_PACKET_SIZE', 'HAMLIB_MAX_SPECTRUM_AVG_MODES', 'HAMLIB_MAX_SPECTRUM_DATA', 'HAMLIB_MAX_SPECTRUM_MODES', 'HAMLIB_MAX_SPECTRUM_SCOPES', 'HAMLIB_MAX_SPECTRUM_SPANS', 'HAMLIB_MAX_VFOS', 'HAMLIB_MAX_VFO_OPS', 'HAMLIB_RIGNAMSIZ', 'HAMLIB_RIGVERSIZ', 'HAMLIB_SECRET_LENGTH', 'HAMLIB_SETTINGS_FILE', 'HAMLIB_TSLSTSIZ', 'MAX_MODELS_PER_BACKEND', 'NETAMPCTL_RET', 'NETRIGCTL_RET', 'NETROTCTL_RET', 'RIG_AGC_AUTO', 'RIG_AGC_FAST', 'RIG_AGC_LAST', 'RIG_AGC_LONG', 'RIG_AGC_MEDIUM', 'RIG_AGC_NONE', 'RIG_AGC_OFF', 'RIG_AGC_ON', 'RIG_AGC_SLOW', 'RIG_AGC_SUPERFAST', 'RIG_AGC_USER', 'RIG_ANN_CW', 'RIG_ANN_ENG', 'RIG_ANN_FREQ', 'RIG_ANN_JAP', 'RIG_ANN_NONE', 'RIG_ANN_OFF', 'RIG_ANN_RXMODE', 'RIG_ANT_MAX', 'RIG_ANT_NONE', 'RIG_BANDSELECT_10M', 'RIG_BANDSELECT_12M', 'RIG_BANDSELECT_13CM', 'RIG_BANDSELECT_15M', 'RIG_BANDSELECT_160M', 'RIG_BANDSELECT_17M', 'RIG_BANDSELECT_1_25M', 'RIG_BANDSELECT_20M', 'RIG_BANDSELECT_2200M', 'RIG_BANDSELECT_23CM', 'RIG_BANDSELECT_2M', 'RIG_BANDSELECT_30M', 'RIG_BANDSELECT_33CM', 'RIG_BANDSELECT_3CM', 'RIG_BANDSELECT_40M', 'RIG_BANDSELECT_4M', 'RIG_BANDSELECT_5CM', 'RIG_BANDSELECT_600M', 'RIG_BANDSELECT_60M', 'RIG_BANDSELECT_6M', 'RIG_BANDSELECT_70CM', 'RIG_BANDSELECT_80M', 'RIG_BANDSELECT_9CM', 'RIG_BANDSELECT_AIR', 'RIG_BANDSELECT_GEN', 'RIG_BANDSELECT_MW', 'RIG_BANDSELECT_UNUSED', 'RIG_BANDSELECT_WFM', 'RIG_BAND_10M', 'RIG_BAND_12M', 'RIG_BAND_144MHZ', 'RIG_BAND_15M', 'RIG_BAND_160M', 'RIG_BAND_17M', 'RIG_BAND_20M', 'RIG_BAND_30M', 'RIG_BAND_40M', 'RIG_BAND_430MHZ', 'RIG_BAND_60M', 'RIG_BAND_6M', 'RIG_BAND_80M', 'RIG_BAND_AIR', 'RIG_BAND_GEN', 'RIG_BAND_MW', 'RIG_BAND_UNUSED', 'RIG_BIN_MAX', 'RIG_BUSBUSY', 'RIG_BUSERROR', 'RIG_CAPS_HAS_GET_LEVEL', 'RIG_CAPS_HAS_SET_LEVEL', 'RIG_CAPS_MFG_NAME_CPTR', 'RIG_CAPS_MODEL_NAME_CPTR', 'RIG_CAPS_PORT_TYPE', 'RIG_CAPS_PTT_TYPE', 'RIG_CAPS_RIG_MODEL', 'RIG_CAPS_STATUS_CPTR', 'RIG_CAPS_TARGETABLE_VFO', 'RIG_CAPS_VERSION_CPTR', 'RIG_CHFLAG_DATA', 'RIG_CHFLAG_NONE', 'RIG_CHFLAG_PSKIP', 'RIG_CHFLAG_SKIP', 'RIG_CLIENT_GPREDICT', 'RIG_CLIENT_UNKNOWN', 'RIG_CLIENT_WSJTX', 'RIG_COMBO_MAX', 'RIG_COMM_STATUS_CONNECTING', 'RIG_COMM_STATUS_DISCONNECTED', 'RIG_COMM_STATUS_ERROR', 'RIG_COMM_STATUS_OK', 'RIG_COMM_STATUS_TERMINATED', 'RIG_COMM_STATUS_WARNING', 'RIG_CONF_BINARY', 'RIG_CONF_BUTTON', 'RIG_CONF_CHECKBUTTON', 'RIG_CONF_COMBO', 'RIG_CONF_END', 'RIG_CONF_INT', 'RIG_CONF_NUMERIC', 'RIG_CONF_STRING', 'RIG_COOKIE_GET', 'RIG_COOKIE_RELEASE', 'RIG_COOKIE_RENEW', 'RIG_DBLST_END', 'RIG_DCD_CM108', 'RIG_DCD_GPIO', 'RIG_DCD_GPION', 'RIG_DCD_NONE', 'RIG_DCD_OFF', 'RIG_DCD_ON', 'RIG_DCD_PARALLEL', 'RIG_DCD_RIG', 'RIG_DCD_SERIAL_CAR', 'RIG_DCD_SERIAL_CTS', 'RIG_DCD_SERIAL_DSR', 'RIG_DEBUG_BUG', 'RIG_DEBUG_CACHE', 'RIG_DEBUG_ERR', 'RIG_DEBUG_NONE', 'RIG_DEBUG_TRACE', 'RIG_DEBUG_VERBOSE', 'RIG_DEBUG_WARN', 'RIG_EACCESS', 'RIG_EARG', 'RIG_ECONF', 'RIG_EDEPRECATED', 'RIG_EDOM', 'RIG_EEND', 'RIG_EINTERNAL', 'RIG_EINVAL', 'RIG_EIO', 'RIG_ELIMIT', 'RIG_ENAVAIL', 'RIG_ENIMPL', 'RIG_ENOMEM', 'RIG_ENTARGET', 'RIG_EPOWER', 'RIG_EPROTO', 'RIG_ERJCTED', 'RIG_ESECURITY', 'RIG_ETIMEOUT', 'RIG_ETRUNC', 'RIG_EVFO', 'RIG_FLAG_APRS', 'RIG_FLAG_COMPUTER', 'RIG_FLAG_DXCLUSTER', 'RIG_FLAG_HANDHELD', 'RIG_FLAG_MOBILE', 'RIG_FLAG_RECEIVER', 'RIG_FLAG_SCANNER', 'RIG_FLAG_TNC', 'RIG_FLAG_TRANSMITTER', 'RIG_FLAG_TRUNKING', 'RIG_FLAG_TUNER', 'RIG_FLT_ANY', 'RIG_FUNCTION_CLEANUP', 'RIG_FUNCTION_CLOSE', 'RIG_FUNCTION_DECODE_EVENT', 'RIG_FUNCTION_GET_ANT', 'RIG_FUNCTION_GET_CHANNEL', 'RIG_FUNCTION_GET_CHAN_ALL_CB', 'RIG_FUNCTION_GET_CONF', 'RIG_FUNCTION_GET_CONF2', 'RIG_FUNCTION_GET_CTCSS_SQL', 'RIG_FUNCTION_GET_CTCSS_TONE', 'RIG_FUNCTION_GET_DCD', 'RIG_FUNCTION_GET_DCS_CODE', 'RIG_FUNCTION_GET_DCS_SQL', 'RIG_FUNCTION_GET_EXT_FUNC', 'RIG_FUNCTION_GET_EXT_LEVEL', 'RIG_FUNCTION_GET_EXT_PARM', 'RIG_FUNCTION_GET_FREQ', 'RIG_FUNCTION_GET_FUNC', 'RIG_FUNCTION_GET_INFO', 'RIG_FUNCTION_GET_LEVEL', 'RIG_FUNCTION_GET_MEM', 'RIG_FUNCTION_GET_MEM_ALL_CB', 'RIG_FUNCTION_GET_MODE', 'RIG_FUNCTION_GET_PARM', 'RIG_FUNCTION_GET_POWERSTAT', 'RIG_FUNCTION_GET_PTT', 'RIG_FUNCTION_GET_RIT', 'RIG_FUNCTION_GET_RPTR_OFFS', 'RIG_FUNCTION_GET_RPTR_SHIFT', 'RIG_FUNCTION_GET_SPLIT_FREQ', 'RIG_FUNCTION_GET_SPLIT_FREQ_MODE', 'RIG_FUNCTION_GET_SPLIT_VFO', 'RIG_FUNCTION_GET_TONE', 'RIG_FUNCTION_GET_TONE_SQL', 'RIG_FUNCTION_GET_TRN', 'RIG_FUNCTION_GET_TS', 'RIG_FUNCTION_GET_VFO', 'RIG_FUNCTION_GET_XIT', 'RIG_FUNCTION_INIT', 'RIG_FUNCTION_IS_ASYNC_FRAME', 'RIG_FUNCTION_MW2POWER', 'RIG_FUNCTION_OPEN', 'RIG_FUNCTION_POWER2MW', 'RIG_FUNCTION_PROCESS_ASYNC_FRAME', 'RIG_FUNCTION_READ_FRAME_DIRECT', 'RIG_FUNCTION_RESET', 'RIG_FUNCTION_SCAN', 'RIG_FUNCTION_SEND_DTMF', 'RIG_FUNCTION_SEND_MORSE', 'RIG_FUNCTION_SEND_VOICE_MEM', 'RIG_FUNCTION_SET_ANT', 'RIG_FUNCTION_SET_BANK', 'RIG_FUNCTION_SET_CHANNEL', 'RIG_FUNCTION_SET_CHAN_ALL_CB', 'RIG_FUNCTION_SET_CONF', 'RIG_FUNCTION_SET_CTCSS_SQL', 'RIG_FUNCTION_SET_CTCSS_TONE', 'RIG_FUNCTION_SET_DCS_CODE', 'RIG_FUNCTION_SET_DCS_SQL', 'RIG_FUNCTION_SET_EXT_FUNC', 'RIG_FUNCTION_SET_EXT_LEVEL', 'RIG_FUNCTION_SET_EXT_PARM', 'RIG_FUNCTION_SET_FREQ', 'RIG_FUNCTION_SET_FUNC', 'RIG_FUNCTION_SET_LEVEL', 'RIG_FUNCTION_SET_MEM', 'RIG_FUNCTION_SET_MEM_ALL_CB', 'RIG_FUNCTION_SET_MODE', 'RIG_FUNCTION_SET_PARM', 'RIG_FUNCTION_SET_POWERSTAT', 'RIG_FUNCTION_SET_PTT', 'RIG_FUNCTION_SET_RIT', 'RIG_FUNCTION_SET_RPTR_OFFS', 'RIG_FUNCTION_SET_RPTR_SHIFT', 'RIG_FUNCTION_SET_SPLIT_FREQ', 'RIG_FUNCTION_SET_SPLIT_FREQ_MODE', 'RIG_FUNCTION_SET_SPLIT_MODE', 'RIG_FUNCTION_SET_SPLIT_VFO', 'RIG_FUNCTION_SET_TONE', 'RIG_FUNCTION_SET_TONE_SQL', 'RIG_FUNCTION_SET_TRN', 'RIG_FUNCTION_SET_TS', 'RIG_FUNCTION_SET_VFO', 'RIG_FUNCTION_SET_VFO_OPT', 'RIG_FUNCTION_SET_XIT', 'RIG_FUNCTION_STOP_MORSE', 'RIG_FUNCTION_STOP_VOICE_MEM', 'RIG_FUNCTION_VFO_OP', 'RIG_FUNCTION_WAIT_MORSE', 'RIG_FUNC_ABM', 'RIG_FUNC_AFC', 'RIG_FUNC_AFLT', 'RIG_FUNC_AIP', 'RIG_FUNC_ANF', 'RIG_FUNC_ANL', 'RIG_FUNC_APF', 'RIG_FUNC_ARO', 'RIG_FUNC_BC', 'RIG_FUNC_BC2', 'RIG_FUNC_BIT49', 'RIG_FUNC_BIT50', 'RIG_FUNC_BIT51', 'RIG_FUNC_BIT52', 'RIG_FUNC_BIT53', 'RIG_FUNC_BIT54', 'RIG_FUNC_BIT55', 'RIG_FUNC_BIT56', 'RIG_FUNC_BIT57', 'RIG_FUNC_BIT58', 'RIG_FUNC_BIT59', 'RIG_FUNC_BIT60', 'RIG_FUNC_BIT61', 'RIG_FUNC_BIT62', 'RIG_FUNC_BIT63', 'RIG_FUNC_COMP', 'RIG_FUNC_CSQL', 'RIG_FUNC_DIVERSITY', 'RIG_FUNC_DSQL', 'RIG_FUNC_DUAL_WATCH', 'RIG_FUNC_FAGC', 'RIG_FUNC_FBKIN', 'RIG_FUNC_LOCK', 'RIG_FUNC_MBC', 'RIG_FUNC_MN', 'RIG_FUNC_MON', 'RIG_FUNC_MUTE', 'RIG_FUNC_NB', 'RIG_FUNC_NB2', 'RIG_FUNC_NONE', 'RIG_FUNC_NR', 'RIG_FUNC_OVF_STATUS', 'RIG_FUNC_RESUME', 'RIG_FUNC_REV', 'RIG_FUNC_RF', 'RIG_FUNC_RIT', 'RIG_FUNC_SATMODE', 'RIG_FUNC_SBKIN', 'RIG_FUNC_SCEN', 'RIG_FUNC_SCOPE', 'RIG_FUNC_SEND_MORSE', 'RIG_FUNC_SEND_VOICE_MEM', 'RIG_FUNC_SLICE', 'RIG_FUNC_SPECTRUM', 'RIG_FUNC_SPECTRUM_HOLD', 'RIG_FUNC_SQL', 'RIG_FUNC_SYNC', 'RIG_FUNC_TBURST', 'RIG_FUNC_TONE', 'RIG_FUNC_TRANSCEIVE', 'RIG_FUNC_TSQL', 'RIG_FUNC_TUNER', 'RIG_FUNC_VOX', 'RIG_FUNC_VSC', 'RIG_FUNC_XIT', 'RIG_HANDSHAKE_HARDWARE', 'RIG_HANDSHAKE_NONE', 'RIG_HANDSHAKE_XONXOFF', 'RIG_KEYERTYPE_BUG', 'RIG_KEYERTYPE_PADDLE', 'RIG_KEYERTYPE_STRAIGHT', 'RIG_KEYERTYPE_UNKNOWN', 'RIG_LEVEL_53', 'RIG_LEVEL_54', 'RIG_LEVEL_55', 'RIG_LEVEL_56', 'RIG_LEVEL_57', 'RIG_LEVEL_58', 'RIG_LEVEL_59', 'RIG_LEVEL_60', 'RIG_LEVEL_61', 'RIG_LEVEL_62', 'RIG_LEVEL_63', 'RIG_LEVEL_AF', 'RIG_LEVEL_AGC', 'RIG_LEVEL_AGC_TIME', 'RIG_LEVEL_ALC', 'RIG_LEVEL_ANTIVOX', 'RIG_LEVEL_APF', 'RIG_LEVEL_ATT', 'RIG_LEVEL_BALANCE', 'RIG_LEVEL_BAND_SELECT', 'RIG_LEVEL_BKINDL', 'RIG_LEVEL_BKIN_DLYMS', 'RIG_LEVEL_COMP', 'RIG_LEVEL_COMP_METER', 'RIG_LEVEL_CWPITCH', 'RIG_LEVEL_FLOAT_LIST', 'RIG_LEVEL_ID_METER', 'RIG_LEVEL_IF', 'RIG_LEVEL_KEYSPD', 'RIG_LEVEL_METER', 'RIG_LEVEL_MICGAIN', 'RIG_LEVEL_MONITOR_GAIN', 'RIG_LEVEL_NB', 'RIG_LEVEL_NONE', 'RIG_LEVEL_NOTCHF', 'RIG_LEVEL_NOTCHF_RAW', 'RIG_LEVEL_NR', 'RIG_LEVEL_PBT_IN', 'RIG_LEVEL_PBT_OUT', 'RIG_LEVEL_PREAMP', 'RIG_LEVEL_RAWSTR', 'RIG_LEVEL_READONLY_LIST', 'RIG_LEVEL_RF', 'RIG_LEVEL_RFPOWER', 'RIG_LEVEL_RFPOWER_METER', 'RIG_LEVEL_RFPOWER_METER_WATTS', 'RIG_LEVEL_SLOPE_HIGH', 'RIG_LEVEL_SLOPE_LOW', 'RIG_LEVEL_SPECTRUM_ATT', 'RIG_LEVEL_SPECTRUM_AVG', 'RIG_LEVEL_SPECTRUM_EDGE_HIGH', 'RIG_LEVEL_SPECTRUM_EDGE_LOW', 'RIG_LEVEL_SPECTRUM_MODE', 'RIG_LEVEL_SPECTRUM_REF', 'RIG_LEVEL_SPECTRUM_SPAN', 'RIG_LEVEL_SPECTRUM_SPEED', 'RIG_LEVEL_SQL', 'RIG_LEVEL_STRENGTH', 'RIG_LEVEL_SWR', 'RIG_LEVEL_TEMP_METER', 'RIG_LEVEL_USB_AF', 'RIG_LEVEL_USB_AF_INPUT', 'RIG_LEVEL_VD_METER', 'RIG_LEVEL_VOXDELAY', 'RIG_LEVEL_VOXGAIN', 'RIG_MEM_CAPS_ALL', 'RIG_METER_ALC', 'RIG_METER_COMP', 'RIG_METER_DB', 'RIG_METER_IC', 'RIG_METER_NONE', 'RIG_METER_PO', 'RIG_METER_SWR', 'RIG_METER_TEMP', 'RIG_METER_VDD', 'RIG_MODEL_505DSP', 'RIG_MODEL_ACLOG', 'RIG_MODEL_ADT_200A', 'RIG_MODEL_AR16', 'RIG_MODEL_AR2500', 'RIG_MODEL_AR2700', 'RIG_MODEL_AR3000', 'RIG_MODEL_AR3000A', 'RIG_MODEL_AR3030', 'RIG_MODEL_AR5000', 'RIG_MODEL_AR5000A', 'RIG_MODEL_AR7030', 'RIG_MODEL_AR7030P', 'RIG_MODEL_AR8000', 'RIG_MODEL_AR8200', 'RIG_MODEL_AR8600', 'RIG_MODEL_ARMSTRONG', 'RIG_MODEL_ATD578UVIII', 'RIG_MODEL_BARRETT_2050', 'RIG_MODEL_BARRETT_4050', 'RIG_MODEL_BARRETT_4100', 'RIG_MODEL_BARRETT_950', 'RIG_MODEL_BC235', 'RIG_MODEL_BC245', 'RIG_MODEL_BC250', 'RIG_MODEL_BC780', 'RIG_MODEL_BC785', 'RIG_MODEL_BC786', 'RIG_MODEL_BC895', 'RIG_MODEL_BC898', 'RIG_MODEL_BCD396T', 'RIG_MODEL_BCD996T', 'RIG_MODEL_BCT8', 'RIG_MODEL_CMH530', 'RIG_MODEL_CODAN_2110', 'RIG_MODEL_CODAN_ENVOY', 'RIG_MODEL_CODAN_NGT', 'RIG_MODEL_CTX10', 'RIG_MODEL_DDS60', 'RIG_MODEL_DELTAII', 'RIG_MODEL_DKR8', 'RIG_MODEL_DKR8A', 'RIG_MODEL_DKR8B', 'RIG_MODEL_DORJI_DRA818U', 'RIG_MODEL_DORJI_DRA818V', 'RIG_MODEL_DRT1', 'RIG_MODEL_DSP10', 'RIG_MODEL_DTTSP', 'RIG_MODEL_DTTSP_UDP', 'RIG_MODEL_DUMMY', 'RIG_MODEL_DUMMY_NOVFO', 'RIG_MODEL_DWT', 'RIG_MODEL_DX77', 'RIG_MODEL_DXSR8', 'RIG_MODEL_EB200', 'RIG_MODEL_EK070', 'RIG_MODEL_EK890', 'RIG_MODEL_EK891', 'RIG_MODEL_EK895', 'RIG_MODEL_EK89X', 'RIG_MODEL_EKD500', 'RIG_MODEL_ELAD_FDM_DUO', 'RIG_MODEL_ELEKTOR304', 'RIG_MODEL_ELEKTOR507', 'RIG_MODEL_ESM500', 'RIG_MODEL_ESMC', 'RIG_MODEL_F6K', 'RIG_MODEL_FASDR', 'RIG_MODEL_FIFISDR', 'RIG_MODEL_FLRIG', 'RIG_MODEL_FRG100', 'RIG_MODEL_FRG8800', 'RIG_MODEL_FRG9600', 'RIG_MODEL_FT100', 'RIG_MODEL_FT1000', 'RIG_MODEL_FT1000D', 'RIG_MODEL_FT1000MP', 'RIG_MODEL_FT1000MPMKV', 'RIG_MODEL_FT1000MPMKVFLD', 'RIG_MODEL_FT2000', 'RIG_MODEL_FT450', 'RIG_MODEL_FT450D', 'RIG_MODEL_FT575', 'RIG_MODEL_FT600', 'RIG_MODEL_FT650', 'RIG_MODEL_FT710', 'RIG_MODEL_FT736R', 'RIG_MODEL_FT747', 'RIG_MODEL_FT757', 'RIG_MODEL_FT757GXII', 'RIG_MODEL_FT767', 'RIG_MODEL_FT817', 'RIG_MODEL_FT818', 'RIG_MODEL_FT820', 'RIG_MODEL_FT840', 'RIG_MODEL_FT847', 'RIG_MODEL_FT847UNI', 'RIG_MODEL_FT857', 'RIG_MODEL_FT890', 'RIG_MODEL_FT891', 'RIG_MODEL_FT897', 'RIG_MODEL_FT897D', 'RIG_MODEL_FT900', 'RIG_MODEL_FT9000', 'RIG_MODEL_FT9000OLD', 'RIG_MODEL_FT920', 'RIG_MODEL_FT950', 'RIG_MODEL_FT980', 'RIG_MODEL_FT990', 'RIG_MODEL_FT990UNI', 'RIG_MODEL_FT991', 'RIG_MODEL_FTDX10', 'RIG_MODEL_FTDX101D', 'RIG_MODEL_FTDX101MP', 'RIG_MODEL_FTDX1200', 'RIG_MODEL_FTDX3000', 'RIG_MODEL_FTDX5000', 'RIG_MODEL_FUNCUBEDONGLE', 'RIG_MODEL_FUNCUBEDONGLEPLUS', 'RIG_MODEL_FX4', 'RIG_MODEL_G303', 'RIG_MODEL_G305', 'RIG_MODEL_G313', 'RIG_MODEL_G315', 'RIG_MODEL_G90', 'RIG_MODEL_GNURADIO', 'RIG_MODEL_GRAUDIO', 'RIG_MODEL_GRAUDIOIQ', 'RIG_MODEL_GS100', 'RIG_MODEL_HF1000', 'RIG_MODEL_HF1000A', 'RIG_MODEL_HF150', 'RIG_MODEL_HF225', 'RIG_MODEL_HF235', 'RIG_MODEL_HF250', 'RIG_MODEL_HIQSDR', 'RIG_MODEL_HPSDR', 'RIG_MODEL_IC1271', 'RIG_MODEL_IC1275', 'RIG_MODEL_IC271', 'RIG_MODEL_IC2730', 'RIG_MODEL_IC275', 'RIG_MODEL_IC375', 'RIG_MODEL_IC471', 'RIG_MODEL_IC475', 'RIG_MODEL_IC575', 'RIG_MODEL_IC7000', 'RIG_MODEL_IC703', 'RIG_MODEL_IC705', 'RIG_MODEL_IC706', 'RIG_MODEL_IC706MKII', 'RIG_MODEL_IC706MKIIG', 'RIG_MODEL_IC707', 'RIG_MODEL_IC7100', 'RIG_MODEL_IC718', 'RIG_MODEL_IC7200', 'RIG_MODEL_IC725', 'RIG_MODEL_IC726', 'RIG_MODEL_IC728', 'RIG_MODEL_IC729', 'RIG_MODEL_IC7300', 'RIG_MODEL_IC731', 'RIG_MODEL_IC735', 'RIG_MODEL_IC736', 'RIG_MODEL_IC737', 'RIG_MODEL_IC738', 'RIG_MODEL_IC7410', 'RIG_MODEL_IC746', 'RIG_MODEL_IC746PRO', 'RIG_MODEL_IC751', 'RIG_MODEL_IC751A', 'RIG_MODEL_IC756', 'RIG_MODEL_IC756PRO', 'RIG_MODEL_IC756PROII', 'RIG_MODEL_IC756PROIII', 'RIG_MODEL_IC7600', 'RIG_MODEL_IC761', 'RIG_MODEL_IC7610', 'RIG_MODEL_IC765', 'RIG_MODEL_IC7700', 'RIG_MODEL_IC775', 'RIG_MODEL_IC7760', 'RIG_MODEL_IC78', 'RIG_MODEL_IC7800', 'RIG_MODEL_IC781', 'RIG_MODEL_IC785x', 'RIG_MODEL_IC820', 'RIG_MODEL_IC821H', 'RIG_MODEL_IC905', 'RIG_MODEL_IC910', 'RIG_MODEL_IC9100', 'RIG_MODEL_IC92D', 'RIG_MODEL_IC970', 'RIG_MODEL_IC9700', 'RIG_MODEL_ICF8101', 'RIG_MODEL_ICID1', 'RIG_MODEL_ICR10', 'RIG_MODEL_ICR20', 'RIG_MODEL_ICR30', 'RIG_MODEL_ICR6', 'RIG_MODEL_ICR7000', 'RIG_MODEL_ICR71', 'RIG_MODEL_ICR7100', 'RIG_MODEL_ICR72', 'RIG_MODEL_ICR75', 'RIG_MODEL_ICR8500', 'RIG_MODEL_ICR8600', 'RIG_MODEL_ICR9000', 'RIG_MODEL_ICR9500', 'RIG_MODEL_ICRX7', 'RIG_MODEL_IC_M700PRO', 'RIG_MODEL_IC_M710', 'RIG_MODEL_IC_M802', 'RIG_MODEL_IC_M803', 'RIG_MODEL_ID31', 'RIG_MODEL_ID4100', 'RIG_MODEL_ID51', 'RIG_MODEL_ID5100', 'RIG_MODEL_JST145', 'RIG_MODEL_JST245', 'RIG_MODEL_K2', 'RIG_MODEL_K3', 'RIG_MODEL_K3S', 'RIG_MODEL_K4', 'RIG_MODEL_KX2', 'RIG_MODEL_KX3', 'RIG_MODEL_LAB599_TX500', 'RIG_MODEL_MALACHITE', 'RIG_MODEL_MC4020', 'RIG_MODEL_MCHFQRP', 'RIG_MODEL_MDS4710', 'RIG_MODEL_MDS9710', 'RIG_MODEL_MICOM2', 'RIG_MODEL_MICROTUNE_4702', 'RIG_MODEL_MICROTUNE_4707', 'RIG_MODEL_MICROTUNE_4937', 'RIG_MODEL_MINISCOUT', 'RIG_MODEL_MINIVNA', 'RIG_MODEL_NETRIGCTL', 'RIG_MODEL_NONE', 'RIG_MODEL_NRD345', 'RIG_MODEL_NRD525', 'RIG_MODEL_NRD535', 'RIG_MODEL_NRD545', 'RIG_MODEL_OMNIVI', 'RIG_MODEL_OMNIVIP', 'RIG_MODEL_OS456', 'RIG_MODEL_OS535', 'RIG_MODEL_PARAGON2', 'RIG_MODEL_PCR100', 'RIG_MODEL_PCR1000', 'RIG_MODEL_PCR1500', 'RIG_MODEL_PCR2500', 'RIG_MODEL_PERSEUS', 'RIG_MODEL_PMR171', 'RIG_MODEL_PMSDR', 'RIG_MODEL_POWERSDR', 'RIG_MODEL_PRM8060', 'RIG_MODEL_PRM8070', 'RIG_MODEL_PRO2052', 'RIG_MODEL_PT8000A', 'RIG_MODEL_Q900', 'RIG_MODEL_QRPLABS', 'RIG_MODEL_QRPLABS_QMX', 'RIG_MODEL_QUISK', 'RIG_MODEL_R5000', 'RIG_MODEL_RA3702', 'RIG_MODEL_RA3710', 'RIG_MODEL_RA3720', 'RIG_MODEL_RA3790', 'RIG_MODEL_RA6790', 'RIG_MODEL_RS2005', 'RIG_MODEL_RS2006', 'RIG_MODEL_RS2035', 'RIG_MODEL_RS2041', 'RIG_MODEL_RS2042', 'RIG_MODEL_RS64', 'RIG_MODEL_RSHFIQ', 'RIG_MODEL_RX320', 'RIG_MODEL_RX331', 'RIG_MODEL_RX340', 'RIG_MODEL_RX350', 'RIG_MODEL_SDR1000', 'RIG_MODEL_SDR1000RFE', 'RIG_MODEL_SDRCONSOLE', 'RIG_MODEL_SDRSHARP', 'RIG_MODEL_SDRUNO', 'RIG_MODEL_SDU5000', 'RIG_MODEL_SDU5500', 'RIG_MODEL_SI570AVRUSB', 'RIG_MODEL_SI570PEABERRY1', 'RIG_MODEL_SI570PEABERRY2', 'RIG_MODEL_SI570PICUSB', 'RIG_MODEL_SMARTSDR_A', 'RIG_MODEL_SMARTSDR_B', 'RIG_MODEL_SMARTSDR_C', 'RIG_MODEL_SMARTSDR_D', 'RIG_MODEL_SMARTSDR_E', 'RIG_MODEL_SMARTSDR_F', 'RIG_MODEL_SMARTSDR_G', 'RIG_MODEL_SMARTSDR_H', 'RIG_MODEL_SR2200', 'RIG_MODEL_TCI1X', 'RIG_MODEL_THD72A', 'RIG_MODEL_THD74', 'RIG_MODEL_THD7A', 'RIG_MODEL_THD7AG', 'RIG_MODEL_THETIS', 'RIG_MODEL_THF6A', 'RIG_MODEL_THF7E', 'RIG_MODEL_THG71', 'RIG_MODEL_TMD700', 'RIG_MODEL_TMD710', 'RIG_MODEL_TMV7', 'RIG_MODEL_TMV71', 'RIG_MODEL_TRANSFOX', 'RIG_MODEL_TRC80', 'RIG_MODEL_TRP7000', 'RIG_MODEL_TRP8000', 'RIG_MODEL_TRP8255', 'RIG_MODEL_TRP9000', 'RIG_MODEL_TRUSDX', 'RIG_MODEL_TRXMANAGER_RIG', 'RIG_MODEL_TS140S', 'RIG_MODEL_TS2000', 'RIG_MODEL_TS440', 'RIG_MODEL_TS450S', 'RIG_MODEL_TS480', 'RIG_MODEL_TS50', 'RIG_MODEL_TS570D', 'RIG_MODEL_TS570S', 'RIG_MODEL_TS590S', 'RIG_MODEL_TS590SG', 'RIG_MODEL_TS680S', 'RIG_MODEL_TS690S', 'RIG_MODEL_TS711', 'RIG_MODEL_TS790', 'RIG_MODEL_TS811', 'RIG_MODEL_TS850', 'RIG_MODEL_TS870S', 'RIG_MODEL_TS890S', 'RIG_MODEL_TS930', 'RIG_MODEL_TS940', 'RIG_MODEL_TS950S', 'RIG_MODEL_TS950SDX', 'RIG_MODEL_TS990S', 'RIG_MODEL_TT516', 'RIG_MODEL_TT526', 'RIG_MODEL_TT538', 'RIG_MODEL_TT550', 'RIG_MODEL_TT565', 'RIG_MODEL_TT585', 'RIG_MODEL_TT588', 'RIG_MODEL_TT599', 'RIG_MODEL_USRP', 'RIG_MODEL_USRP0', 'RIG_MODEL_USRP_G', 'RIG_MODEL_V4L', 'RIG_MODEL_V4L2', 'RIG_MODEL_VR5000', 'RIG_MODEL_VX1700', 'RIG_MODEL_WJ8711', 'RIG_MODEL_WJ8888', 'RIG_MODEL_WR1000', 'RIG_MODEL_WR1500', 'RIG_MODEL_WR1550', 'RIG_MODEL_WR3100', 'RIG_MODEL_WR3150', 'RIG_MODEL_WR3500', 'RIG_MODEL_WR3700', 'RIG_MODEL_X108G', 'RIG_MODEL_X5105', 'RIG_MODEL_X6100', 'RIG_MODEL_X6200', 'RIG_MODEL_XG3', 'RIG_MODEL_XK2100', 'RIG_MODEL_XK852', 'RIG_MODEL_XPLORER', 'RIG_MODE_ALL', 'RIG_MODE_AM', 'RIG_MODE_AMN', 'RIG_MODE_AMS', 'RIG_MODE_BIT46', 'RIG_MODE_BIT47', 'RIG_MODE_BIT48', 'RIG_MODE_BIT49', 'RIG_MODE_BIT50', 'RIG_MODE_BIT51', 'RIG_MODE_BIT52', 'RIG_MODE_BIT53', 'RIG_MODE_BIT54', 'RIG_MODE_BIT55', 'RIG_MODE_BIT56', 'RIG_MODE_BIT57', 'RIG_MODE_BIT58', 'RIG_MODE_BIT59', 'RIG_MODE_BIT60', 'RIG_MODE_BIT61', 'RIG_MODE_BIT62', 'RIG_MODE_C4FM', 'RIG_MODE_CW', 'RIG_MODE_CWN', 'RIG_MODE_CWR', 'RIG_MODE_DCR', 'RIG_MODE_DD', 'RIG_MODE_DPMR', 'RIG_MODE_DSB', 'RIG_MODE_DSTAR', 'RIG_MODE_ECSS', 'RIG_MODE_ECSSLSB', 'RIG_MODE_ECSSUSB', 'RIG_MODE_FAX', 'RIG_MODE_FM', 'RIG_MODE_FMN', 'RIG_MODE_IQ', 'RIG_MODE_ISBLSB', 'RIG_MODE_ISBUSB', 'RIG_MODE_LSB', 'RIG_MODE_LSBD1', 'RIG_MODE_LSBD2', 'RIG_MODE_LSBD3', 'RIG_MODE_NONE', 'RIG_MODE_NXDNVN', 'RIG_MODE_NXDN_N', 'RIG_MODE_P25', 'RIG_MODE_PKTAM', 'RIG_MODE_PKTFM', 'RIG_MODE_PKTFMN', 'RIG_MODE_PKTLSB', 'RIG_MODE_PKTSSB', 'RIG_MODE_PKTUSB', 'RIG_MODE_PSK', 'RIG_MODE_PSKR', 'RIG_MODE_RTTY', 'RIG_MODE_RTTYR', 'RIG_MODE_SAH', 'RIG_MODE_SAL', 'RIG_MODE_SAM', 'RIG_MODE_SPEC', 'RIG_MODE_SSB', 'RIG_MODE_TESTS_MAX', 'RIG_MODE_USB', 'RIG_MODE_USBD1', 'RIG_MODE_USBD2', 'RIG_MODE_USBD3', 'RIG_MODE_WFM', 'RIG_MTYPE_BAND', 'RIG_MTYPE_CALL', 'RIG_MTYPE_EDGE', 'RIG_MTYPE_MEM', 'RIG_MTYPE_MEMOPAD', 'RIG_MTYPE_MORSE', 'RIG_MTYPE_NONE', 'RIG_MTYPE_PRIO', 'RIG_MTYPE_SAT', 'RIG_MTYPE_SPLIT', 'RIG_MTYPE_VOICE', 'RIG_MULTICAST_POLL', 'RIG_MULTICAST_SPECTRUM', 'RIG_MULTICAST_TRANSCEIVE', 'RIG_OK', 'RIG_OP_BAND_DOWN', 'RIG_OP_BAND_UP', 'RIG_OP_CPY', 'RIG_OP_DOWN', 'RIG_OP_FROM_VFO', 'RIG_OP_LEFT', 'RIG_OP_MCL', 'RIG_OP_NONE', 'RIG_OP_RIGHT', 'RIG_OP_TOGGLE', 'RIG_OP_TO_VFO', 'RIG_OP_TUNE', 'RIG_OP_UP', 'RIG_OP_XCHG', 'RIG_PARITY_EVEN', 'RIG_PARITY_MARK', 'RIG_PARITY_NONE', 'RIG_PARITY_ODD', 'RIG_PARITY_SPACE', 'RIG_PARM_AFIF', 'RIG_PARM_AFIF_ACC', 'RIG_PARM_AFIF_LAN', 'RIG_PARM_AFIF_WLAN', 'RIG_PARM_ANN', 'RIG_PARM_APO', 'RIG_PARM_BACKLIGHT', 'RIG_PARM_BANDSELECT', 'RIG_PARM_BAT', 'RIG_PARM_BEEP', 'RIG_PARM_KEYERTYPE', 'RIG_PARM_KEYLIGHT', 'RIG_PARM_NONE', 'RIG_PARM_SCREENSAVER', 'RIG_PARM_TIME', 'RIG_PORT_CM108', 'RIG_PORT_DEVICE', 'RIG_PORT_DTMF', 'RIG_PORT_GPIO', 'RIG_PORT_GPION', 'RIG_PORT_NETWORK', 'RIG_PORT_NONE', 'RIG_PORT_PACKET', 'RIG_PORT_PARALLEL', 'RIG_PORT_RPC', 'RIG_PORT_SERIAL', 'RIG_PORT_UDP_NETWORK', 'RIG_PORT_ULTRA', 'RIG_PORT_USB', 'RIG_POWER_OFF', 'RIG_POWER_ON', 'RIG_POWER_OPERATE', 'RIG_POWER_STANDBY', 'RIG_POWER_UNKNOWN', 'RIG_PTRX_AMPPORT', 'RIG_PTRX_AMPSTATE', 'RIG_PTRX_CACHE', 'RIG_PTRX_DCDPORT', 'RIG_PTRX_MAXIMUM', 'RIG_PTRX_NONE', 'RIG_PTRX_PTTPORT', 'RIG_PTRX_RIGPORT', 'RIG_PTRX_ROTPORT', 'RIG_PTRX_ROTPORT2', 'RIG_PTRX_ROTSTATE', 'RIG_PTRX_STATE', 'RIG_PTT_CM108', 'RIG_PTT_GPIO', 'RIG_PTT_GPION', 'RIG_PTT_NONE', 'RIG_PTT_OFF', 'RIG_PTT_ON', 'RIG_PTT_ON_DATA', 'RIG_PTT_ON_MIC', 'RIG_PTT_PARALLEL', 'RIG_PTT_RIG', 'RIG_PTT_RIG_MICDATA', 'RIG_PTT_SERIAL_DTR', 'RIG_PTT_SERIAL_RTS', 'RIG_RESET_MASTER', 'RIG_RESET_MCALL', 'RIG_RESET_NONE', 'RIG_RESET_SOFT', 'RIG_RESET_VFO', 'RIG_RPT_SHIFT_MINUS', 'RIG_RPT_SHIFT_NONE', 'RIG_RPT_SHIFT_PLUS', 'RIG_SCAN_DELTA', 'RIG_SCAN_MEM', 'RIG_SCAN_NONE', 'RIG_SCAN_PLT', 'RIG_SCAN_PRIO', 'RIG_SCAN_PROG', 'RIG_SCAN_SLCT', 'RIG_SCAN_STOP', 'RIG_SCAN_VFO', 'RIG_SETTING_MAX', 'RIG_SIGNAL_OFF', 'RIG_SIGNAL_ON', 'RIG_SIGNAL_UNSET', 'RIG_SPECTRUM_MODE_CENTER', 'RIG_SPECTRUM_MODE_CENTER_SCROLL', 'RIG_SPECTRUM_MODE_FIXED', 'RIG_SPECTRUM_MODE_FIXED_SCROLL', 'RIG_SPECTRUM_MODE_NONE', 'RIG_SPLIT_OFF', 'RIG_SPLIT_ON', 'RIG_STATUS_ALPHA', 'RIG_STATUS_BETA', 'RIG_STATUS_BUGGY', 'RIG_STATUS_STABLE', 'RIG_STATUS_UNTESTED', 'RIG_TARGETABLE_ALL', 'RIG_TARGETABLE_ANT', 'RIG_TARGETABLE_BAND', 'RIG_TARGETABLE_BANK', 'RIG_TARGETABLE_COMMON', 'RIG_TARGETABLE_FREQ', 'RIG_TARGETABLE_FUNC', 'RIG_TARGETABLE_LEVEL', 'RIG_TARGETABLE_MEM', 'RIG_TARGETABLE_MODE', 'RIG_TARGETABLE_NONE', 'RIG_TARGETABLE_PTT', 'RIG_TARGETABLE_PURE', 'RIG_TARGETABLE_RITXIT', 'RIG_TARGETABLE_ROOFING', 'RIG_TARGETABLE_SPECTRUM', 'RIG_TARGETABLE_TONE', 'RIG_TRN_OFF', 'RIG_TRN_POLL', 'RIG_TRN_RIG', 'RIG_TS_ANY', 'RIG_TYPE_OTHER', 'RIG_VFO_A', 'RIG_VFO_ALL', 'RIG_VFO_B', 'RIG_VFO_C', 'RIG_VFO_CURR', 'RIG_VFO_MAIN', 'RIG_VFO_MAIN_A', 'RIG_VFO_MAIN_B', 'RIG_VFO_MAIN_C', 'RIG_VFO_MEM', 'RIG_VFO_NONE', 'RIG_VFO_OTHER', 'RIG_VFO_RX', 'RIG_VFO_SUB', 'RIG_VFO_SUB_A', 'RIG_VFO_SUB_B', 'RIG_VFO_SUB_C', 'RIG_VFO_TX', 'RIG_VFO_TX_FLAG', 'RIG_VFO_VFO', 'ROT_FLAG_AZIMUTH', 'ROT_FLAG_ELEVATION', 'ROT_FUNC_BIT63', 'ROT_FUNC_NONE', 'ROT_LEVEL_63', 'ROT_LEVEL_FLOAT_LIST', 'ROT_LEVEL_NONE', 'ROT_LEVEL_READONLY_LIST', 'ROT_LEVEL_SPEED', 'ROT_MODEL_ANDROIDSENSOR', 'ROT_MODEL_APEX_SHARED_LOOP', 'ROT_MODEL_ARRAYSOLUTIONS_SAL_12_20_30', 'ROT_MODEL_CNCTRK', 'ROT_MODEL_DCU', 'ROT_MODEL_DUMMY', 'ROT_MODEL_EASYCOMM1', 'ROT_MODEL_EASYCOMM2', 'ROT_MODEL_EASYCOMM3', 'ROT_MODEL_ERC', 'ROT_MODEL_ETHER6', 'ROT_MODEL_F1TETRACKER', 'ROT_MODEL_FLIR', 'ROT_MODEL_FODTRACK', 'ROT_MODEL_GRBLTRK_NET', 'ROT_MODEL_GRBLTRK_SER', 'ROT_MODEL_GS23', 'ROT_MODEL_GS232', 'ROT_MODEL_GS232A', 'ROT_MODEL_GS232A_AZ', 'ROT_MODEL_GS232A_EL', 'ROT_MODEL_GS232B', 'ROT_MODEL_GS232B_AZ', 'ROT_MODEL_GS232B_EL', 'ROT_MODEL_GS232_GENERIC', 'ROT_MODEL_GS23_AZ', 'ROT_MODEL_HD1780', 'ROT_MODEL_IF100', 'ROT_MODEL_INDI', 'ROT_MODEL_IOPTRON', 'ROT_MODEL_LVB', 'ROT_MODEL_MEADE', 'ROT_MODEL_NETROTCTL', 'ROT_MODEL_NEXSTAR', 'ROT_MODEL_NONE', 'ROT_MODEL_PCROTOR', 'ROT_MODEL_PROSISTEL_COMBI_TRACK_AZEL', 'ROT_MODEL_PROSISTEL_D_AZ', 'ROT_MODEL_PROSISTEL_D_EL', 'ROT_MODEL_PROSISTEL_D_EL_CBOXAZ', 'ROT_MODEL_PSTROTATOR', 'ROT_MODEL_RADANT', 'ROT_MODEL_RC2800', 'ROT_MODEL_RC2800_EARLY_AZ', 'ROT_MODEL_RC2800_EARLY_AZEL', 'ROT_MODEL_RCI_AZ', 'ROT_MODEL_RCI_AZEL', 'ROT_MODEL_ROTORCARD', 'ROT_MODEL_ROTOREZ', 'ROT_MODEL_RT21', 'ROT_MODEL_SAEBRTRACK', 'ROT_MODEL_SARTEK1', 'ROT_MODEL_SATEL', 'ROT_MODEL_SATROTCTL', 'ROT_MODEL_SKYWATCHER', 'ROT_MODEL_SPID_MD01_ROT2PROG', 'ROT_MODEL_SPID_ROT1PROG', 'ROT_MODEL_SPID_ROT2PROG', 'ROT_MODEL_ST2', 'ROT_MODEL_TS7400', 'ROT_MODEL_YRC1', 'ROT_MOVE_CCW', 'ROT_MOVE_CW', 'ROT_MOVE_DOWN', 'ROT_MOVE_DOWN_CCW', 'ROT_MOVE_DOWN_CW', 'ROT_MOVE_DOWN_LEFT', 'ROT_MOVE_DOWN_RIGHT', 'ROT_MOVE_LEFT', 'ROT_MOVE_RIGHT', 'ROT_MOVE_UP', 'ROT_MOVE_UP_CCW', 'ROT_MOVE_UP_CW', 'ROT_MOVE_UP_LEFT', 'ROT_MOVE_UP_RIGHT', 'ROT_PARM_FLOAT_LIST', 'ROT_PARM_NONE', 'ROT_PARM_READONLY_LIST', 'ROT_RESET_ALL', 'ROT_SPEED_NOCHANGE', 'ROT_STATUS_BUSY', 'ROT_STATUS_LIMIT_DOWN', 'ROT_STATUS_LIMIT_LEFT', 'ROT_STATUS_LIMIT_RIGHT', 'ROT_STATUS_LIMIT_UP', 'ROT_STATUS_MOVING', 'ROT_STATUS_MOVING_AZ', 'ROT_STATUS_MOVING_DOWN', 'ROT_STATUS_MOVING_EL', 'ROT_STATUS_MOVING_LEFT', 'ROT_STATUS_MOVING_RIGHT', 'ROT_STATUS_MOVING_UP', 'ROT_STATUS_NONE', 'ROT_STATUS_OVERLAP_DOWN', 'ROT_STATUS_OVERLAP_LEFT', 'ROT_STATUS_OVERLAP_RIGHT', 'ROT_STATUS_OVERLAP_UP', 'ROT_TYPE_OTHER', 'TWIDDLE_OFF', 'TWIDDLE_ON', 'VFO_DUAL', 'cvar', 'hamlib_copyright', 'hamlib_version'] + assert expected_properties == self.actual_properties + + @classmethod + def generate_data(cls, the_object): + """Extract callables and properties from the given object""" + callables = [] + properties = [] + for method_or_property in dir(the_object): + if not method_or_property.startswith("_"): + if callable(getattr(the_object, method_or_property)): + callables.append(method_or_property) + else: + properties.append(method_or_property) + + return callables, properties From 98fdcf130f2e1b3bd7a0ae85f350bb7f07d4da33 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 4 May 2025 21:42:10 +0200 Subject: [PATCH 18/45] Add tests for the Amp object --- bindings/python/test_amp.py | 78 +++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100755 bindings/python/test_amp.py diff --git a/bindings/python/test_amp.py b/bindings/python/test_amp.py new file mode 100755 index 000000000..0673d644c --- /dev/null +++ b/bindings/python/test_amp.py @@ -0,0 +1,78 @@ +#! /bin/env pytest +"""Tests of the Python bindings for Hamlib + +Running this script directly will use the installed bindings. +For an in-tree run use "make check", or set PYTHONPATH to point to +the directories containing Hamlib.py and _Hamlib.so. +""" +import Hamlib + +Hamlib.rig_set_debug(Hamlib.RIG_DEBUG_NONE) + +AMP_MODEL = Hamlib.AMP_MODEL_DUMMY + +class TestClass: + """Container class for tests""" + + def test_without_open(self): + """Call all the methods that do not depend on open()""" + amp = Hamlib.Amp(AMP_MODEL) + assert amp is not None + assert amp.do_exception == 0 + assert amp.error_status == Hamlib.RIG_OK + + assert isinstance(amp.caps.model_name, str) + assert isinstance(amp.caps.mfg_name, str) + assert isinstance(amp.caps.version, str) + assert isinstance(amp.caps.copyright, str) + + assert amp.set_conf("", "") is None + assert amp.get_conf("") == "" + assert amp.get_conf(0) == "" + conf = amp.get_conf("mcfg") + assert isinstance(conf, str) + assert amp.set_conf("mcfg", "foo") is None + conf = amp.get_conf("mcfg") + assert conf == "" # FIXME: should return "foo" + + assert amp.token_lookup("") is None + + + def test_with_open(self): + """Call all the methods that depend on open()""" + amp = Hamlib.Amp(AMP_MODEL) + assert amp is not None + + assert amp.state.comm_state == 0 + assert amp.open() is None + assert amp.state.comm_state == 1 + info = amp.get_info() + assert isinstance(info, str) + assert amp.reset(Hamlib.AMP_RESET_FAULT) is None + assert amp.set_freq(0) is None + assert amp.set_freq(123.45) is None + assert amp.get_freq() == 123.45 + assert amp.get_level(Hamlib.AMP_LEVEL_NONE) is None + level = amp.get_level(Hamlib.AMP_LEVEL_SWR) + assert isinstance(level, float) + level = amp.get_level(Hamlib.AMP_LEVEL_PWR_REFLECTED) + assert isinstance(level, int) + level = amp.get_level(Hamlib.AMP_LEVEL_FAULT) + assert isinstance(level, str) + level = amp.get_level(123456) + assert level is None + assert amp.set_powerstat(Hamlib.RIG_POWER_ON) is None + assert amp.get_powerstat() == Hamlib.RIG_POWER_ON + assert amp.close() is None + assert amp.state.comm_state == 0 + info = amp.get_info() + assert info is None + + + def test_object_creation(self): + """Create all objects available""" + amp = Hamlib.Rig(AMP_MODEL) + assert amp is not None + + assert isinstance(amp.caps, Hamlib.rig_caps) + assert isinstance(amp.state, Hamlib.rig_state) From 02f7b96163ac4a086ed62fc0b75ac1fbcb7c95cf Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sat, 24 May 2025 19:12:31 +0200 Subject: [PATCH 19/45] Implement Amp.get_powerstat --- bindings/amplifier.swg | 5 +---- bindings/python/test_amp.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/bindings/amplifier.swg b/bindings/amplifier.swg index 26d4c4c8d..4a94ed736 100644 --- a/bindings/amplifier.swg +++ b/bindings/amplifier.swg @@ -144,6 +144,7 @@ typedef struct Amp { return s; } + AMPMETHOD1GET(get_powerstat, powerstat_t) }; %{ @@ -151,8 +152,4 @@ typedef struct Amp { { self->error_status = amp_get_freq(self->amp, freq); } - void Amp_get_powerstat(Amp *self, powerstat_t *status) - { - self->error_status = amp_get_powerstat(self->amp, status); - } %} diff --git a/bindings/python/test_amp.py b/bindings/python/test_amp.py index 0673d644c..f3239d3a3 100755 --- a/bindings/python/test_amp.py +++ b/bindings/python/test_amp.py @@ -64,6 +64,36 @@ class TestClass: assert amp.set_powerstat(Hamlib.RIG_POWER_ON) is None assert amp.get_powerstat() == Hamlib.RIG_POWER_ON assert amp.close() is None + + + def test_all_methods(self): + """Just call all the methods""" + amp = Hamlib.Amp(AMP_MODEL) + assert amp is not None + + # the tests that do not depend on open() + assert amp.set_conf("", "") is None + assert amp.get_conf("") == "" + assert amp.get_conf(0) == "" + conf = amp.get_conf("mcfg") + assert isinstance(conf, str) + assert amp.set_conf("mcfg", "foo") is None + conf = amp.get_conf("mcfg") + assert conf == "" # FIXME: should return "foo" + assert amp.token_lookup("") is None + + # the tests that depend on open() + assert amp.state.comm_state == 0 + assert amp.open() is None + assert amp.state.comm_state == 1 + info = amp.get_info() + assert isinstance(info, str) + assert amp.reset(Hamlib.AMP_RESET_FAULT) is None + assert amp.set_freq(0) is None + # assert amp.get_freq() is None # FIXME: AttributeError: 'Amp' object has no attribute 'get_freq' + assert amp.set_powerstat(Hamlib.RIG_POWER_ON) is None + assert amp.get_powerstat() == Hamlib.RIG_POWER_ON + assert amp.close() is None assert amp.state.comm_state == 0 info = amp.get_info() assert info is None From 4e415f412be941598e48e5c311a5e54e4833de03 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sat, 24 May 2025 19:15:53 +0200 Subject: [PATCH 20/45] Implement Amp.get_freq --- bindings/amplifier.swg | 9 ++------- bindings/python/test_amp.py | 3 ++- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/bindings/amplifier.swg b/bindings/amplifier.swg index 4a94ed736..59c16e7bc 100644 --- a/bindings/amplifier.swg +++ b/bindings/amplifier.swg @@ -137,6 +137,8 @@ typedef struct Amp { return s; } + AMPMETHOD1GET(get_freq, freq_t) + const char * get_info(void) { const char *s; s = amp_get_info(self->amp); @@ -146,10 +148,3 @@ typedef struct Amp { AMPMETHOD1GET(get_powerstat, powerstat_t) }; -%{ - - void Amp_get_freq(Amp *self, freq_t *freq) - { - self->error_status = amp_get_freq(self->amp, freq); - } -%} diff --git a/bindings/python/test_amp.py b/bindings/python/test_amp.py index f3239d3a3..22b0f3af7 100755 --- a/bindings/python/test_amp.py +++ b/bindings/python/test_amp.py @@ -90,7 +90,8 @@ class TestClass: assert isinstance(info, str) assert amp.reset(Hamlib.AMP_RESET_FAULT) is None assert amp.set_freq(0) is None - # assert amp.get_freq() is None # FIXME: AttributeError: 'Amp' object has no attribute 'get_freq' + assert amp.set_freq(123.45) is None + assert amp.get_freq() == 123.45 assert amp.set_powerstat(Hamlib.RIG_POWER_ON) is None assert amp.get_powerstat() == Hamlib.RIG_POWER_ON assert amp.close() is None From f7d38f92cac73fb8b952f5dde3853f40ef910e14 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sat, 24 May 2025 20:51:01 +0200 Subject: [PATCH 21/45] Implement Amp.get_level --- bindings/amplifier.swg | 17 +++++++++++++++++ bindings/python/test_amp.py | 9 +++++++++ 2 files changed, 26 insertions(+) diff --git a/bindings/amplifier.swg b/bindings/amplifier.swg index 59c16e7bc..a22a02765 100644 --- a/bindings/amplifier.swg +++ b/bindings/amplifier.swg @@ -147,4 +147,21 @@ typedef struct Amp { } AMPMETHOD1GET(get_powerstat, powerstat_t) + + PyObject * get_level(setting_t level) + { + value_t val; + + self->error_status = amp_get_level(self->amp, level, &val); + if (self->error_status != RIG_OK) + return Py_None; + + if (AMP_LEVEL_IS_FLOAT(level)) + return PyFloat_FromDouble(val.f); + else if (AMP_LEVEL_IS_STRING(level)) + return PyUnicode_FromString(val.s); + + return PyLong_FromLong(val.i); + } + }; diff --git a/bindings/python/test_amp.py b/bindings/python/test_amp.py index 22b0f3af7..f3d915071 100755 --- a/bindings/python/test_amp.py +++ b/bindings/python/test_amp.py @@ -92,6 +92,15 @@ class TestClass: assert amp.set_freq(0) is None assert amp.set_freq(123.45) is None assert amp.get_freq() == 123.45 + assert amp.get_level(Hamlib.AMP_LEVEL_NONE) is None + level = amp.get_level(Hamlib.AMP_LEVEL_SWR) + assert isinstance(level, float) + level = amp.get_level(Hamlib.AMP_LEVEL_PWR_REFLECTED) + assert isinstance(level, int) + level = amp.get_level(Hamlib.AMP_LEVEL_FAULT) + assert isinstance(level, str) + level = amp.get_level(123456) + assert level is None assert amp.set_powerstat(Hamlib.RIG_POWER_ON) is None assert amp.get_powerstat() == Hamlib.RIG_POWER_ON assert amp.close() is None From 4b64ea316994d7c8e25d44f08a682fc5170b2aa3 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 15 Jun 2025 12:28:40 +0200 Subject: [PATCH 22/45] Update autogenerated tests for Amp object --- bindings/python/test_Hamlib_Amp_class.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/test_Hamlib_Amp_class.py b/bindings/python/test_Hamlib_Amp_class.py index db0462838..77a2dc0ae 100755 --- a/bindings/python/test_Hamlib_Amp_class.py +++ b/bindings/python/test_Hamlib_Amp_class.py @@ -16,7 +16,7 @@ class TestClass: def test_callables(self): """Check that nothing was added or removed""" - expected_callables = ['close', 'get_conf', 'get_info', 'open', 'reset', 'set_conf', 'set_freq', 'set_powerstat', 'token_lookup'] + expected_callables = ['close', 'get_conf', 'get_freq', 'get_info', 'get_level', 'get_powerstat', 'open', 'reset', 'set_conf', 'set_freq', 'set_powerstat', 'token_lookup'] assert expected_callables == self.actual_callables def test_properties(self): From a172b6001fa90e3fd32ff91262e06c1ca6bb7831 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 4 May 2025 18:32:33 +0200 Subject: [PATCH 23/45] Add tests for the Rot object --- bindings/python/test_rot.py | 74 +++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 bindings/python/test_rot.py diff --git a/bindings/python/test_rot.py b/bindings/python/test_rot.py new file mode 100644 index 000000000..ceb619540 --- /dev/null +++ b/bindings/python/test_rot.py @@ -0,0 +1,74 @@ +#! /bin/env pytest +"""Tests of the Python bindings for Hamlib + +Running this script directly will use the installed bindings. +For an in-tree run use "make check", or set PYTHONPATH to point to +the directories containing Hamlib.py and _Hamlib.so. +""" +import Hamlib + +Hamlib.rig_set_debug(Hamlib.RIG_DEBUG_NONE) + +ROT_MODEL = Hamlib.ROT_MODEL_DUMMY + +class TestClass: + """Container class for tests""" + + def test_without_open(self): + """Call all the methods that do not depend on open()""" + rot = Hamlib.Rot(ROT_MODEL) + assert rot is not None + assert rot.do_exception == 0 + assert rot.error_status == Hamlib.RIG_OK + + assert isinstance(rot.caps.model_name, str) + assert isinstance(rot.caps.mfg_name, str) + assert isinstance(rot.caps.version, str) + assert isinstance(rot.caps.copyright, str) + + assert rot.set_conf("", "") is None + assert rot.get_conf("") == "" + assert rot.get_conf(0) == "" + conf = rot.get_conf("mcfg") + assert isinstance(conf, str) + assert rot.set_conf("mcfg", "foo") is None + conf = rot.get_conf("mcfg") + assert conf == "foo" + + assert rot.token_lookup("") is None + + + def test_with_open(self): + """Call all the methods that depend on open()""" + rot = Hamlib.Rot(ROT_MODEL) + assert rot is not None + + assert rot.state.comm_state == 0 + assert rot.open() is None + assert rot.state.comm_state == 1 + info = rot.get_info() + assert isinstance(info, str) + assert rot.set_position(0.0, 0.0) is None + assert rot.get_position() == [0.0, 0.0] + assert rot.move(0, 0) is None + speed = 4 + assert rot.move(Hamlib.ROT_MOVE_UP, speed) is None + assert rot.move(Hamlib.ROT_MOVE_LEFT, speed) is None + assert rot.get_position() == [0.0, 0.0] # FIXME + assert rot.status() is None + assert rot.stop() is None + assert rot.park() is None + assert rot.reset(Hamlib.ROT_RESET_ALL) is None + assert rot.close() is None + assert rot.state.comm_state == 0 + info = rot.get_info() + assert info is None + + + def test_object_creation(self): + """Create all objects available""" + rot = Hamlib.Rig(ROT_MODEL) + assert rot is not None + + assert isinstance(rot.caps, Hamlib.rig_caps) + assert isinstance(rot.state, Hamlib.rig_state) From 5a5279492ebc46d1b758b847a9e41be111fda5e0 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Mon, 2 Jun 2025 11:26:36 +0200 Subject: [PATCH 24/45] Mark asserts that are currently failing --- bindings/python/test_rig.py | 14 +++++++++----- bindings/python/test_rot.py | 5 ++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/bindings/python/test_rig.py b/bindings/python/test_rig.py index 5c64f31e8..4790dc92e 100755 --- a/bindings/python/test_rig.py +++ b/bindings/python/test_rig.py @@ -5,6 +5,8 @@ Running this script directly will use the installed bindings. For an in-tree run use "make check", or set PYTHONPATH to point to the directories containing Hamlib.py and _Hamlib.so. """ +from pytest import raises + import Hamlib Hamlib.rig_set_debug(Hamlib.RIG_DEBUG_NONE) @@ -116,15 +118,17 @@ class TestClass: assert isinstance(rig.get_split_freq(Hamlib.RIG_VFO_CURR), float) assert isinstance(rig.get_split_mode(), list) assert isinstance(rig.get_split_mode(Hamlib.RIG_VFO_CURR), list) - # assert rig.get_split_vfo() is None # FIXME - # assert rig.get_split_vfo(Hamlib.RIG_VFO_CURR) is None # FIXME + with raises(TypeError): + assert rig.get_split_vfo() is None # FIXME + assert rig.get_split_vfo(Hamlib.RIG_VFO_CURR) is None # FIXME assert isinstance(rig.get_trn(), int) # deprecated assert isinstance(rig.get_ts(), int) assert isinstance(rig.get_ts(Hamlib.RIG_VFO_CURR), int) assert isinstance(rig.get_vfo(), int) - # assert rig.get_vfo_info(Hamlib.RIG_VFO_CURR) is None # FIXME - # assert rig.get_vfo_info(Hamlib.RIG_VFO_CURR, 2) is None # FIXME - # assert rig.get_vfo_info(Hamlib.RIG_VFO_CURR, 2, 3) is None # FIXME + with raises(TypeError): + assert rig.get_vfo_info(Hamlib.RIG_VFO_CURR) is None # FIXME + assert rig.get_vfo_info(Hamlib.RIG_VFO_CURR, 2) is None # FIXME + assert rig.get_vfo_info(Hamlib.RIG_VFO_CURR, 2, 3) is None # FIXME assert isinstance(rig.get_xit(), int) assert isinstance(rig.get_xit(Hamlib.RIG_VFO_CURR), int) # assert rig_has_get_func(0) FIXME not defined diff --git a/bindings/python/test_rot.py b/bindings/python/test_rot.py index ceb619540..c4a9b1230 100644 --- a/bindings/python/test_rot.py +++ b/bindings/python/test_rot.py @@ -5,6 +5,8 @@ Running this script directly will use the installed bindings. For an in-tree run use "make check", or set PYTHONPATH to point to the directories containing Hamlib.py and _Hamlib.so. """ +from pytest import raises + import Hamlib Hamlib.rig_set_debug(Hamlib.RIG_DEBUG_NONE) @@ -55,7 +57,8 @@ class TestClass: assert rot.move(Hamlib.ROT_MOVE_UP, speed) is None assert rot.move(Hamlib.ROT_MOVE_LEFT, speed) is None assert rot.get_position() == [0.0, 0.0] # FIXME - assert rot.status() is None + with raises(AttributeError): + assert rot.status() is None assert rot.stop() is None assert rot.park() is None assert rot.reset(Hamlib.ROT_RESET_ALL) is None From cc0dbc9efd7b3efbe360029e2987aa2c87490717 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Mon, 2 Jun 2025 17:47:23 +0200 Subject: [PATCH 25/45] Implement Rot.set_func() --- bindings/python/test_rot.py | 6 ++++++ bindings/rotator.swg | 1 + 2 files changed, 7 insertions(+) diff --git a/bindings/python/test_rot.py b/bindings/python/test_rot.py index c4a9b1230..6f9c931a5 100644 --- a/bindings/python/test_rot.py +++ b/bindings/python/test_rot.py @@ -62,6 +62,12 @@ class TestClass: assert rot.stop() is None assert rot.park() is None assert rot.reset(Hamlib.ROT_RESET_ALL) is None + + status = 0 + assert rot.set_func(1, status) is None + status = 1 + assert rot.set_func(1, status) is None + assert rot.close() is None assert rot.state.comm_state == 0 info = rot.get_info() diff --git a/bindings/rotator.swg b/bindings/rotator.swg index bbf2a637a..9b29de45a 100644 --- a/bindings/rotator.swg +++ b/bindings/rotator.swg @@ -89,6 +89,7 @@ typedef struct Rot { ROTMETHOD0(open) ROTMETHOD0(close) + ROTMETHOD2(set_func, setting_t, int) ROTMETHOD2(set_position, azimuth_t, elevation_t) extern void get_position(azimuth_t *OUTPUT, elevation_t *OUTPUT); ROTMETHOD0(stop) From bb79bbc2782712fb21bda8b70d3b51f8e4eb9736 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Mon, 2 Jun 2025 17:47:31 +0200 Subject: [PATCH 26/45] Implement Rot.get_func() --- bindings/python/test_rot.py | 2 ++ bindings/rotator.swg | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/bindings/python/test_rot.py b/bindings/python/test_rot.py index 6f9c931a5..994024be1 100644 --- a/bindings/python/test_rot.py +++ b/bindings/python/test_rot.py @@ -65,8 +65,10 @@ class TestClass: status = 0 assert rot.set_func(1, status) is None + assert rot.get_func(1) == status status = 1 assert rot.set_func(1, status) is None + assert rot.get_func(1) == 0 # FIXME should read status assert rot.close() is None assert rot.state.comm_state == 0 diff --git a/bindings/rotator.swg b/bindings/rotator.swg index 9b29de45a..02c8b74c4 100644 --- a/bindings/rotator.swg +++ b/bindings/rotator.swg @@ -90,6 +90,7 @@ typedef struct Rot { ROTMETHOD0(close) ROTMETHOD2(set_func, setting_t, int) + extern void get_func(setting_t func, int *OUTPUT); ROTMETHOD2(set_position, azimuth_t, elevation_t) extern void get_position(azimuth_t *OUTPUT, elevation_t *OUTPUT); ROTMETHOD0(stop) @@ -136,6 +137,13 @@ typedef struct Rot { }; %{ +/* + * this one returns 1 value + */ +void Rot_get_func(Rot *self, setting_t func, int *status) +{ + self->error_status = rot_get_func(self->rot, func, status); +} /* * this one returns 2 values, here is a perl example: From cfca827f5e85c4162e1accb05e0f6b8e4b611fcc Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Mon, 2 Jun 2025 17:56:13 +0200 Subject: [PATCH 27/45] Implement Rot.set_parm() --- bindings/python/test_rot.py | 3 +++ bindings/rotator.swg | 3 +++ 2 files changed, 6 insertions(+) diff --git a/bindings/python/test_rot.py b/bindings/python/test_rot.py index 994024be1..8ab9756ee 100644 --- a/bindings/python/test_rot.py +++ b/bindings/python/test_rot.py @@ -70,6 +70,9 @@ class TestClass: assert rot.set_func(1, status) is None assert rot.get_func(1) == 0 # FIXME should read status + value.i = 5 + assert rot.set_parm(Hamlib.ROT_PARM_NONE, value) is None + assert rot.close() is None assert rot.state.comm_state == 0 info = rot.get_info() diff --git a/bindings/rotator.swg b/bindings/rotator.swg index 02c8b74c4..d8b100651 100644 --- a/bindings/rotator.swg +++ b/bindings/rotator.swg @@ -91,6 +91,9 @@ typedef struct Rot { ROTMETHOD2(set_func, setting_t, int) extern void get_func(setting_t func, int *OUTPUT); + + ROTMETHOD2(set_parm, setting_t, value_t) + ROTMETHOD2(set_position, azimuth_t, elevation_t) extern void get_position(azimuth_t *OUTPUT, elevation_t *OUTPUT); ROTMETHOD0(stop) From 94774a63d99ae55b28e602dd6d1ad3ce271b30c7 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 15 Jun 2025 15:46:58 +0200 Subject: [PATCH 28/45] Implement Rot.set_level() --- bindings/python/test_rot.py | 3 +++ bindings/rotator.swg | 2 ++ 2 files changed, 5 insertions(+) diff --git a/bindings/python/test_rot.py b/bindings/python/test_rot.py index 8ab9756ee..3f148aaa8 100644 --- a/bindings/python/test_rot.py +++ b/bindings/python/test_rot.py @@ -57,6 +57,9 @@ class TestClass: assert rot.move(Hamlib.ROT_MOVE_UP, speed) is None assert rot.move(Hamlib.ROT_MOVE_LEFT, speed) is None assert rot.get_position() == [0.0, 0.0] # FIXME + value = Hamlib.value_t() + value.i = 3 + assert rot.set_level(Hamlib.ROT_LEVEL_SPEED, value) is None with raises(AttributeError): assert rot.status() is None assert rot.stop() is None diff --git a/bindings/rotator.swg b/bindings/rotator.swg index d8b100651..53c7d2a0d 100644 --- a/bindings/rotator.swg +++ b/bindings/rotator.swg @@ -92,6 +92,8 @@ typedef struct Rot { ROTMETHOD2(set_func, setting_t, int) extern void get_func(setting_t func, int *OUTPUT); + ROTMETHOD2(set_level, setting_t, value_t) + ROTMETHOD2(set_parm, setting_t, value_t) ROTMETHOD2(set_position, azimuth_t, elevation_t) From 8093f05c656a40de1fb9eb3c64f598a22575ebeb Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 15 Jun 2025 15:11:02 +0200 Subject: [PATCH 29/45] Implement Rot.get_level() --- bindings/python/test_rot.py | 2 ++ bindings/rotator.swg | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/bindings/python/test_rot.py b/bindings/python/test_rot.py index 3f148aaa8..b48a43e40 100644 --- a/bindings/python/test_rot.py +++ b/bindings/python/test_rot.py @@ -60,6 +60,8 @@ class TestClass: value = Hamlib.value_t() value.i = 3 assert rot.set_level(Hamlib.ROT_LEVEL_SPEED, value) is None + assert rot.get_level(Hamlib.ROT_LEVEL_NONE) is None + assert rot.get_level(Hamlib.ROT_LEVEL_SPEED) == 3 with raises(AttributeError): assert rot.status() is None assert rot.stop() is None diff --git a/bindings/rotator.swg b/bindings/rotator.swg index 53c7d2a0d..58160e55f 100644 --- a/bindings/rotator.swg +++ b/bindings/rotator.swg @@ -138,6 +138,20 @@ typedef struct Rot { return s; } + PyObject * get_level(setting_t level) + { + value_t val; + + self->error_status = rot_get_level(self->rot, level, &val); + if (self->error_status != RIG_OK) + return Py_None; + + if (ROT_LEVEL_IS_FLOAT(level)) + return PyFloat_FromDouble(val.f); + + return PyLong_FromLong(val.i); + } + /* TODO: get_conf_list, .. */ }; From 5d142de5cd5cee1dc8312ae4171bdfd6007bc055 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 15 Jun 2025 15:13:05 +0200 Subject: [PATCH 30/45] Implement Rot.get_parm() --- bindings/python/test_rot.py | 1 + bindings/rotator.swg | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/bindings/python/test_rot.py b/bindings/python/test_rot.py index b48a43e40..51a6e05bc 100644 --- a/bindings/python/test_rot.py +++ b/bindings/python/test_rot.py @@ -77,6 +77,7 @@ class TestClass: value.i = 5 assert rot.set_parm(Hamlib.ROT_PARM_NONE, value) is None + assert rot.get_parm(Hamlib.ROT_PARM_NONE) is None # FIXME should Dummy support this? assert rot.close() is None assert rot.state.comm_state == 0 diff --git a/bindings/rotator.swg b/bindings/rotator.swg index 58160e55f..a9d4fb8a5 100644 --- a/bindings/rotator.swg +++ b/bindings/rotator.swg @@ -152,6 +152,20 @@ typedef struct Rot { return PyLong_FromLong(val.i); } + PyObject * get_parm(setting_t parm) + { + value_t val; + + self->error_status = rot_get_parm(self->rot, parm, &val); + if (self->error_status != RIG_OK) + return Py_None; + + if (ROT_PARM_IS_FLOAT(parm)) + return PyFloat_FromDouble(val.f); + + return PyLong_FromLong(val.i); + } + /* TODO: get_conf_list, .. */ }; From 20960b726e03a9916887838c6c7608a55087d3ca Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Mon, 2 Jun 2025 18:38:13 +0200 Subject: [PATCH 31/45] Implement Rot.set_ext_level() --- bindings/python/test_rot.py | 2 ++ bindings/rotator.swg | 2 ++ 2 files changed, 4 insertions(+) diff --git a/bindings/python/test_rot.py b/bindings/python/test_rot.py index 51a6e05bc..72c1eeea2 100644 --- a/bindings/python/test_rot.py +++ b/bindings/python/test_rot.py @@ -68,6 +68,8 @@ class TestClass: assert rot.park() is None assert rot.reset(Hamlib.ROT_RESET_ALL) is None + assert rot.set_ext_level(0, value) is None + status = 0 assert rot.set_func(1, status) is None assert rot.get_func(1) == status diff --git a/bindings/rotator.swg b/bindings/rotator.swg index a9d4fb8a5..c5136590a 100644 --- a/bindings/rotator.swg +++ b/bindings/rotator.swg @@ -89,6 +89,8 @@ typedef struct Rot { ROTMETHOD0(open) ROTMETHOD0(close) + ROTMETHOD2(set_ext_level, hamlib_token_t, value_t) + ROTMETHOD2(set_func, setting_t, int) extern void get_func(setting_t func, int *OUTPUT); From f7710d96b084100451125662d265859f2ea9cc08 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Mon, 2 Jun 2025 19:46:16 +0200 Subject: [PATCH 32/45] Implement Rot.set_ext_func() --- bindings/python/test_rot.py | 1 + bindings/rotator.swg | 1 + 2 files changed, 2 insertions(+) diff --git a/bindings/python/test_rot.py b/bindings/python/test_rot.py index 72c1eeea2..39deda45c 100644 --- a/bindings/python/test_rot.py +++ b/bindings/python/test_rot.py @@ -68,6 +68,7 @@ class TestClass: assert rot.park() is None assert rot.reset(Hamlib.ROT_RESET_ALL) is None + assert rot.set_ext_func(0, 0) is None assert rot.set_ext_level(0, value) is None status = 0 diff --git a/bindings/rotator.swg b/bindings/rotator.swg index c5136590a..0e5507a3f 100644 --- a/bindings/rotator.swg +++ b/bindings/rotator.swg @@ -89,6 +89,7 @@ typedef struct Rot { ROTMETHOD0(open) ROTMETHOD0(close) + ROTMETHOD2(set_ext_func, hamlib_token_t, int) ROTMETHOD2(set_ext_level, hamlib_token_t, value_t) ROTMETHOD2(set_func, setting_t, int) From be1a558e0def0fff6f24f8fb595869ec9aa28968 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Mon, 2 Jun 2025 19:46:35 +0200 Subject: [PATCH 33/45] Implement Rot.set_ext_parm() --- bindings/python/test_rot.py | 1 + bindings/rotator.swg | 1 + 2 files changed, 2 insertions(+) diff --git a/bindings/python/test_rot.py b/bindings/python/test_rot.py index 39deda45c..e4f5dce01 100644 --- a/bindings/python/test_rot.py +++ b/bindings/python/test_rot.py @@ -70,6 +70,7 @@ class TestClass: assert rot.set_ext_func(0, 0) is None assert rot.set_ext_level(0, value) is None + assert rot.set_ext_parm(0, value) is None status = 0 assert rot.set_func(1, status) is None diff --git a/bindings/rotator.swg b/bindings/rotator.swg index 0e5507a3f..f8f4fcf1e 100644 --- a/bindings/rotator.swg +++ b/bindings/rotator.swg @@ -91,6 +91,7 @@ typedef struct Rot { ROTMETHOD2(set_ext_func, hamlib_token_t, int) ROTMETHOD2(set_ext_level, hamlib_token_t, value_t) + ROTMETHOD2(set_ext_parm, hamlib_token_t, value_t) ROTMETHOD2(set_func, setting_t, int) extern void get_func(setting_t func, int *OUTPUT); From e34026707ce2b487c2bc234e773b3d1650bd9c83 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Mon, 2 Jun 2025 20:33:29 +0200 Subject: [PATCH 34/45] Implement Rot.get_ext_func() --- bindings/python/test_rot.py | 1 + bindings/rotator.swg | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/bindings/python/test_rot.py b/bindings/python/test_rot.py index e4f5dce01..a67608268 100644 --- a/bindings/python/test_rot.py +++ b/bindings/python/test_rot.py @@ -69,6 +69,7 @@ class TestClass: assert rot.reset(Hamlib.ROT_RESET_ALL) is None assert rot.set_ext_func(0, 0) is None + assert rot.get_ext_func(0) is None assert rot.set_ext_level(0, value) is None assert rot.set_ext_parm(0, value) is None diff --git a/bindings/rotator.swg b/bindings/rotator.swg index f8f4fcf1e..ba9e0176d 100644 --- a/bindings/rotator.swg +++ b/bindings/rotator.swg @@ -142,6 +142,17 @@ typedef struct Rot { return s; } + PyObject * get_ext_func(hamlib_token_t token) + { + int status; + + self->error_status = rot_get_ext_func(self->rot, token, &status); + if (self->error_status != RIG_OK) + return Py_None; + + return PyLong_FromLong(status); + } + PyObject * get_level(setting_t level) { value_t val; From 6fd6e94d3b02b70e9cc23fc3ac2d65c859e60ad6 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Mon, 2 Jun 2025 20:33:47 +0200 Subject: [PATCH 35/45] Implement Rot.get_ext_level() --- bindings/python/test_rot.py | 1 + bindings/rotator.swg | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/bindings/python/test_rot.py b/bindings/python/test_rot.py index a67608268..61fd1abf6 100644 --- a/bindings/python/test_rot.py +++ b/bindings/python/test_rot.py @@ -71,6 +71,7 @@ class TestClass: assert rot.set_ext_func(0, 0) is None assert rot.get_ext_func(0) is None assert rot.set_ext_level(0, value) is None + assert rot.get_ext_level(0) is None assert rot.set_ext_parm(0, value) is None status = 0 diff --git a/bindings/rotator.swg b/bindings/rotator.swg index ba9e0176d..f4bfedaea 100644 --- a/bindings/rotator.swg +++ b/bindings/rotator.swg @@ -153,6 +153,17 @@ typedef struct Rot { return PyLong_FromLong(status); } + PyObject * get_ext_level(hamlib_token_t token) + { + value_t val; + + self->error_status = rot_get_ext_level(self->rot, token, &val); + if (self->error_status != RIG_OK) + return Py_None; + + return PyLong_FromLong(val.i); + } + PyObject * get_level(setting_t level) { value_t val; From 5c58c9920793f400686744dfa70fc413179bfd8e Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Mon, 2 Jun 2025 20:33:57 +0200 Subject: [PATCH 36/45] Implement Rot.get_ext_parm() --- bindings/python/test_rot.py | 1 + bindings/rotator.swg | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/bindings/python/test_rot.py b/bindings/python/test_rot.py index 61fd1abf6..fedf368ea 100644 --- a/bindings/python/test_rot.py +++ b/bindings/python/test_rot.py @@ -73,6 +73,7 @@ class TestClass: assert rot.set_ext_level(0, value) is None assert rot.get_ext_level(0) is None assert rot.set_ext_parm(0, value) is None + assert rot.get_ext_parm(0) is None status = 0 assert rot.set_func(1, status) is None diff --git a/bindings/rotator.swg b/bindings/rotator.swg index f4bfedaea..205a20417 100644 --- a/bindings/rotator.swg +++ b/bindings/rotator.swg @@ -164,6 +164,17 @@ typedef struct Rot { return PyLong_FromLong(val.i); } + PyObject * get_ext_parm(hamlib_token_t token) + { + value_t val; + + self->error_status = rot_get_ext_parm(self->rot, token, &val); + if (self->error_status != RIG_OK) + return Py_None; + + return PyLong_FromLong(val.i); + } + PyObject * get_level(setting_t level) { value_t val; From 5915f173221f6fe8d4e32b6e97e3a15179b8e1cb Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 15 Jun 2025 15:59:19 +0200 Subject: [PATCH 37/45] Update autogenerated tests for Rot object --- bindings/python/test_Hamlib_Rot_class.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/test_Hamlib_Rot_class.py b/bindings/python/test_Hamlib_Rot_class.py index 596f05f60..107d07bee 100755 --- a/bindings/python/test_Hamlib_Rot_class.py +++ b/bindings/python/test_Hamlib_Rot_class.py @@ -16,7 +16,7 @@ class TestClass: def test_callables(self): """Check that nothing was added or removed""" - expected_callables = ['close', 'get_conf', 'get_info', 'get_position', 'move', 'open', 'park', 'reset', 'set_conf', 'set_position', 'stop', 'token_lookup'] + expected_callables = ['close', 'get_conf', 'get_ext_func', 'get_ext_level', 'get_ext_parm', 'get_func', 'get_info', 'get_level', 'get_parm', 'get_position', 'move', 'open', 'park', 'reset', 'set_conf', 'set_ext_func', 'set_ext_level', 'set_ext_parm', 'set_func', 'set_level', 'set_parm', 'set_position', 'stop', 'token_lookup'] assert expected_callables == self.actual_callables def test_properties(self): From ec8eaab1f529332e886f2ae606a7e26ec3930e2e Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sat, 7 Jun 2025 18:43:20 +0200 Subject: [PATCH 38/45] Enable assert Hamlib.rigerror() Pull request #1727 has been merged so now the test succeeds. --- bindings/python/test_startup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/test_startup.py b/bindings/python/test_startup.py index b72e5cf5f..e4cfaf8c0 100755 --- a/bindings/python/test_startup.py +++ b/bindings/python/test_startup.py @@ -31,7 +31,7 @@ class TestClass: assert my_rig.get_conf("retry") == '5' assert my_rig.error_status == Hamlib.RIG_OK - # assert Hamlib.rigerror(my_rig.error_status) == "Command completed successfully\n" # FIXME: the string returned contains debug messages, fix in PR #1727 + assert Hamlib.rigerror(my_rig.error_status) == "Command completed successfully\n" assert my_rig.set_freq(Hamlib.RIG_VFO_B, 5700000000) is None assert my_rig.set_vfo(Hamlib.RIG_VFO_B) is None From a42d18b59fd0e8b1747f65f7b2df7d189b9d8876 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sat, 7 Jun 2025 21:47:09 +0200 Subject: [PATCH 39/45] Change the ignore list to explicitly accept symbols This way the list documents all available symbols (even if in abbreviated form) instead of those not available. --- bindings/ignore.swg | 168 ++++++++++++++++++++++---------------------- 1 file changed, 83 insertions(+), 85 deletions(-) diff --git a/bindings/ignore.swg b/bindings/ignore.swg index 327f91fb0..d09b1a232 100644 --- a/bindings/ignore.swg +++ b/bindings/ignore.swg @@ -1,90 +1,86 @@ -/* unsupported Hamlib's calls */ - -/* useless macros */ -%ignore AMP_DUMMY; -%ignore AMP_ELECRAFT; -%ignore AMP_GEMINI; -%ignore AMP_EXPERT; - -%ignore RIG_ADAT; -%ignore RIG_ALINCO; -%ignore RIG_ANYTONE; -%ignore RIG_AOR; -%ignore RIG_BARRETT; -%ignore RIG_CODAN; -%ignore RIG_COMMRADIO; -%ignore RIG_DORJI; -%ignore RIG_DRAKE; -%ignore RIG_DUMMY; -%ignore RIG_EK; -%ignore RIG_ELAD; -%ignore RIG_FLEXRADIO; -%ignore RIG_GNURADIO; -%ignore RIG_GOMSPACE; -%ignore RIG_ICMARINE; -%ignore RIG_ICOM; -%ignore RIG_JRC; -%ignore RIG_KACHINA; -%ignore RIG_KENWOOD; -%ignore RIG_KIT; -%ignore RIG_LOWE; -%ignore RIG_MDS; -%ignore RIG_MICROTUNE; -%ignore RIG_MOTOROLA; -%ignore RIG_PCR; -%ignore RIG_PRM80; -%ignore RIG_RACAL; -%ignore RIG_RADIOSHACK; -%ignore RIG_RFT; -%ignore RIG_RS; -%ignore RIG_SKANTI; -%ignore RIG_TAPR; -%ignore RIG_TENTEC; -%ignore RIG_TUNER; -%ignore RIG_UNIDEN; -%ignore RIG_WINRADIO; -%ignore RIG_WJ; -%ignore RIG_YAESU; - -%ignore ROT_AMSAT; -%ignore ROT_ANDROIDSENSOR; -%ignore ROT_APEX; -%ignore ROT_ARRAYSOLUTIONS; -%ignore ROT_ARS; -%ignore ROT_CELESTRON; -%ignore ROT_CNCTRK; -%ignore ROT_DUMMY; -%ignore ROT_EASYCOMM; -%ignore ROT_ETHER6; -%ignore ROT_FLIR; -%ignore ROT_FODTRACK; -%ignore ROT_GRBLTRK; -%ignore ROT_GS232A; -%ignore ROT_HEATHKIT; -%ignore ROT_INDI; -%ignore ROT_IOPTRON; -%ignore ROT_KIT; -%ignore ROT_M2; -%ignore ROT_MEADE; -%ignore ROT_PROSISTEL; -%ignore ROT_RADANT; -%ignore ROT_ROTOREZ; -%ignore ROT_SAEBRTRACK; -%ignore ROT_SARTEK; -%ignore ROT_SATEL; -%ignore ROT_SKYWATCHER; -%ignore ROT_SPID; -%ignore ROT_TS7400; - -%ignore PRIfreq; -%ignore SCNfreq; -%ignore FREQFMT; +/* Unsupported Hamlib's methods, properties and constants */ // remove defines from Hamlib class %rename("$ignore", regexmatch$name="^_") ""; -%rename("$ignore", regexmatch$name="^AMP_BACKEND") ""; -%rename("$ignore", regexmatch$name="^RIG_BACKEND") ""; -%rename("$ignore", regexmatch$name="^ROT_BACKEND") ""; +%rename("$ignore", regexmatch$name="^AMP_") ""; +%rename("$ignore", regexmatch$name="^RIG_") ""; +%rename("$ignore", regexmatch$name="^ROT_") ""; + +// re-add useful defines + +// Amplifiers +%rename("%s", regexmatch$name="^AMP_FLAG_") ""; +%rename("%s", regexmatch$name="^AMP_LEVEL_") ""; +%rename("%s", regexmatch$name="^AMP_MODEL_") ""; +%rename("%s", regexmatch$name="^AMP_RESET_") ""; +%rename("%s", regexmatch$name="^AMP_TYPE_") ""; + +// Rigs +%rename("%s", regexmatch$name="^RIG_AGC_") ""; +%rename("%s", regexmatch$name="^RIG_ANN_") ""; +%rename("%s", regexmatch$name="^RIG_ANT_") ""; +%rename("%s", regexmatch$name="^RIG_BANDSELECT_") ""; +%rename("%s", regexmatch$name="^RIG_BAND_") ""; +%rename("%s") RIG_BUSBUSY; +%rename("%s") RIG_BUSERROR; +%rename("%s", regexmatch$name="^RIG_CAPS_") ""; +%rename("%s", regexmatch$name="^RIG_CHFLAG_") ""; +%rename("%s", regexmatch$name="^RIG_CLIENT_") ""; +%rename("%s", regexmatch$name="^RIG_COMM_") ""; +%rename("%s", regexmatch$name="^RIG_CONF_") ""; +%rename("%s", regexmatch$name="^RIG_COOKIE_") ""; +%rename("%s", regexmatch$name="^RIG_DCD_") ""; +%rename("%s", regexmatch$name="^RIG_DEBUG_") ""; +%rename("%s", regexmatch$name="^RIG_E") ""; +%rename("%s", regexmatch$name="^RIG_FLAG_") ""; +%rename("%s", regexmatch$name="^RIG_FLT_") ""; +%rename("%s", regexmatch$name="^RIG_FUNCTION_") ""; +%rename("%s", regexmatch$name="^RIG_FUNC_") ""; +%rename("%s", regexmatch$name="^RIG_HANDSHAKE_") ""; +%rename("%s", regexmatch$name="^RIG_KEYERTYPE_") ""; +%rename("%s", regexmatch$name="^RIG_LEVEL_") ""; +%rename("%s", regexmatch$name="^RIG_MEM_CAPS_") ""; +%rename("%s", regexmatch$name="^RIG_METER_") ""; +%rename("%s", regexmatch$name="^RIG_MODEL_") ""; +%rename("%s", regexmatch$name="^RIG_MODE_") ""; +%rename("%s", regexmatch$name="^RIG_MTYPE_") ""; +%rename("%s", regexmatch$name="^RIG_MULTICAST_") ""; +%rename("%s", regexmatch$name="^RIG_OP_") ""; +%rename("%s") RIG_OK; +%rename("%s", regexmatch$name="^RIG_PARITY_") ""; +%rename("%s", regexmatch$name="^RIG_PARM_") ""; +%rename("%s", regexmatch$name="^RIG_PORT_") ""; +%rename("%s", regexmatch$name="^RIG_POWER_") ""; +%rename("%s", regexmatch$name="^RIG_PTRX_") ""; +%rename("%s", regexmatch$name="^RIG_PTT_") ""; +%rename("%s", regexmatch$name="^RIG_RESET_") ""; +%rename("%s", regexmatch$name="^RIG_RPT_SHIFT_") ""; +%rename("%s", regexmatch$name="^RIG_SCAN_") ""; +%rename("%s", regexmatch$name="^RIG_SETTING_") ""; +%rename("%s", regexmatch$name="^RIG_SIGNAL_") ""; +%rename("%s", regexmatch$name="^RIG_SPECTRUM_MODE_") ""; +%rename("%s", regexmatch$name="^RIG_SPLIT_") ""; +%rename("%s", regexmatch$name="^RIG_STATUS_") ""; +%rename("%s", regexmatch$name="^RIG_TARGETABLE_") ""; +%rename("%s", regexmatch$name="^RIG_TRN_") ""; +%rename("%s", regexmatch$name="^RIG_TS_") ""; +%rename("%s", regexmatch$name="^RIG_TYPE_") ""; +%rename("%s", regexmatch$name="^RIG_VFO_") ""; +%ignore RIG_EK; // an internal macro +%ignore RIG_ELAD; // an internal macro + +// Rotators + +%rename("%s", regexmatch$name="^ROT_FLAG_") ""; +%rename("%s", regexmatch$name="^ROT_FUNC_") ""; +%rename("%s", regexmatch$name="^ROT_LEVEL_") ""; +%rename("%s", regexmatch$name="^ROT_MODEL_") ""; +%rename("%s", regexmatch$name="^ROT_MOVE_") ""; +%rename("%s", regexmatch$name="^ROT_PARM_") ""; +%rename("%s", regexmatch$name="^ROT_RESET_") ""; +%rename("%s", regexmatch$name="^ROT_SPEED_") ""; +%rename("%s", regexmatch$name="^ROT_STATUS_") ""; +%rename("%s", regexmatch$name="^ROT_TYPE_") ""; // remove methods from Hamlib class %rename("$ignore", regexmatch$name="^amp_", %$isfunction) ""; @@ -110,8 +106,10 @@ %ignore fd_sync_error_write; %ignore fd_sync_error_read; - %ignore FIFO_RIG; +%ignore FREQFMT; +%ignore PRIfreq; +%ignore SCNfreq; #ifdef SWIGLUA %ignore Rig::set_level(setting_t,int,vfo_t); From 5d1baed7e57615b74ce832a806e6c76709f4c62d Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sat, 7 Jun 2025 21:53:35 +0200 Subject: [PATCH 40/45] Test setting and getting meaningful values --- bindings/python/test_rot.py | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/bindings/python/test_rot.py b/bindings/python/test_rot.py index fedf368ea..ca885ba0f 100644 --- a/bindings/python/test_rot.py +++ b/bindings/python/test_rot.py @@ -16,6 +16,13 @@ ROT_MODEL = Hamlib.ROT_MODEL_DUMMY class TestClass: """Container class for tests""" + TOK_EL_ROT_MAGICLEVEL = 1 + TOK_EL_ROT_MAGICFUNC = 2 + # TOK_EL_ROT_MAGICOP = 3 # handled by get_ext_level/set_ext_level + TOK_EP_ROT_MAGICPARM = 4 + # TOK_EL_ROT_MAGICCOMBO = 5 # handled by get_ext_level/set_ext_level + TOK_EL_ROT_MAGICEXTFUNC = 6 + def test_without_open(self): """Call all the methods that do not depend on open()""" rot = Hamlib.Rot(ROT_MODEL) @@ -68,19 +75,23 @@ class TestClass: assert rot.park() is None assert rot.reset(Hamlib.ROT_RESET_ALL) is None - assert rot.set_ext_func(0, 0) is None - assert rot.get_ext_func(0) is None - assert rot.set_ext_level(0, value) is None - assert rot.get_ext_level(0) is None - assert rot.set_ext_parm(0, value) is None - assert rot.get_ext_parm(0) is None + assert rot.set_ext_func(self.TOK_EL_ROT_MAGICEXTFUNC, 5) is None + assert rot.get_ext_func(self.TOK_EL_ROT_MAGICEXTFUNC) == 5 + + value.i = 6 + assert rot.set_ext_level(self.TOK_EL_ROT_MAGICLEVEL, value) is None + assert rot.get_ext_level(self.TOK_EL_ROT_MAGICLEVEL) == 6 + + value.i = 7 + assert rot.set_ext_parm(self.TOK_EP_ROT_MAGICPARM, value) is None + assert rot.get_ext_parm(self.TOK_EP_ROT_MAGICPARM) == 7 status = 0 assert rot.set_func(1, status) is None assert rot.get_func(1) == status status = 1 - assert rot.set_func(1, status) is None - assert rot.get_func(1) == 0 # FIXME should read status + assert rot.set_func(self.TOK_EL_ROT_MAGICFUNC, status) is None + assert rot.get_func(self.TOK_EL_ROT_MAGICFUNC) == 0 # FIXME should return status value.i = 5 assert rot.set_parm(Hamlib.ROT_PARM_NONE, value) is None From 16a0ad7bf146418fa452e11edf34238f4c7b1e05 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 15 Jun 2025 16:48:40 +0200 Subject: [PATCH 41/45] Update autogenerated tests for Hamlib module --- bindings/python/test_Hamlib_class.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/test_Hamlib_class.py b/bindings/python/test_Hamlib_class.py index 58d83b613..663a6db98 100755 --- a/bindings/python/test_Hamlib_class.py +++ b/bindings/python/test_Hamlib_class.py @@ -21,7 +21,7 @@ class TestClass: def test_properties(self): """Check that nothing was added or removed""" - expected_properties = ['AMP_FLAG_1', 'AMP_FLAG_2', 'AMP_LEVEL_FAULT', 'AMP_LEVEL_NH', 'AMP_LEVEL_NONE', 'AMP_LEVEL_PF', 'AMP_LEVEL_PWR', 'AMP_LEVEL_PWR_FWD', 'AMP_LEVEL_PWR_INPUT', 'AMP_LEVEL_PWR_PEAK', 'AMP_LEVEL_PWR_REFLECTED', 'AMP_LEVEL_SWR', 'AMP_MODEL_DUMMY', 'AMP_MODEL_ELECRAFT_KPA1500', 'AMP_MODEL_EXPERT_FA', 'AMP_MODEL_GEMINI_DX1200', 'AMP_MODEL_NETAMPCTL', 'AMP_MODEL_NONE', 'AMP_RESET_AMP', 'AMP_RESET_FAULT', 'AMP_RESET_MEM', 'AMP_TYPE_OTHER', 'BUILTINFUNC', 'CTCSS_LIST_SIZE', 'DCS_LIST_SIZE', 'DEBUGMSGSAVE_SIZE', 'GPIO1', 'GPIO2', 'GPIO3', 'GPIO4', 'HAMLIB_CACHE_ALL', 'HAMLIB_CACHE_ALWAYS', 'HAMLIB_CACHE_FREQ', 'HAMLIB_CACHE_MODE', 'HAMLIB_CACHE_PTT', 'HAMLIB_CACHE_SPLIT', 'HAMLIB_CACHE_VFO', 'HAMLIB_CACHE_WIDTH', 'HAMLIB_CHANLSTSIZ', 'HAMLIB_CHECK_RIG_CAPS', 'HAMLIB_COOKIE_SIZE', 'HAMLIB_ELAPSED_GET', 'HAMLIB_ELAPSED_INVALIDATE', 'HAMLIB_ELAPSED_SET', 'HAMLIB_FIFO_SIZE', 'HAMLIB_FILPATHLEN', 'HAMLIB_FLTLSTSIZ', 'HAMLIB_FRQRANGESIZ', 'HAMLIB_MAXCHANDESC', 'HAMLIB_MAXDBLSTSIZ', 'HAMLIB_MAX_AGC_LEVELS', 'HAMLIB_MAX_CAL_LENGTH', 'HAMLIB_MAX_MODES', 'HAMLIB_MAX_ROTORS', 'HAMLIB_MAX_RSCANS', 'HAMLIB_MAX_SNAPSHOT_PACKET_SIZE', 'HAMLIB_MAX_SPECTRUM_AVG_MODES', 'HAMLIB_MAX_SPECTRUM_DATA', 'HAMLIB_MAX_SPECTRUM_MODES', 'HAMLIB_MAX_SPECTRUM_SCOPES', 'HAMLIB_MAX_SPECTRUM_SPANS', 'HAMLIB_MAX_VFOS', 'HAMLIB_MAX_VFO_OPS', 'HAMLIB_RIGNAMSIZ', 'HAMLIB_RIGVERSIZ', 'HAMLIB_SECRET_LENGTH', 'HAMLIB_SETTINGS_FILE', 'HAMLIB_TSLSTSIZ', 'MAX_MODELS_PER_BACKEND', 'NETAMPCTL_RET', 'NETRIGCTL_RET', 'NETROTCTL_RET', 'RIG_AGC_AUTO', 'RIG_AGC_FAST', 'RIG_AGC_LAST', 'RIG_AGC_LONG', 'RIG_AGC_MEDIUM', 'RIG_AGC_NONE', 'RIG_AGC_OFF', 'RIG_AGC_ON', 'RIG_AGC_SLOW', 'RIG_AGC_SUPERFAST', 'RIG_AGC_USER', 'RIG_ANN_CW', 'RIG_ANN_ENG', 'RIG_ANN_FREQ', 'RIG_ANN_JAP', 'RIG_ANN_NONE', 'RIG_ANN_OFF', 'RIG_ANN_RXMODE', 'RIG_ANT_MAX', 'RIG_ANT_NONE', 'RIG_BANDSELECT_10M', 'RIG_BANDSELECT_12M', 'RIG_BANDSELECT_13CM', 'RIG_BANDSELECT_15M', 'RIG_BANDSELECT_160M', 'RIG_BANDSELECT_17M', 'RIG_BANDSELECT_1_25M', 'RIG_BANDSELECT_20M', 'RIG_BANDSELECT_2200M', 'RIG_BANDSELECT_23CM', 'RIG_BANDSELECT_2M', 'RIG_BANDSELECT_30M', 'RIG_BANDSELECT_33CM', 'RIG_BANDSELECT_3CM', 'RIG_BANDSELECT_40M', 'RIG_BANDSELECT_4M', 'RIG_BANDSELECT_5CM', 'RIG_BANDSELECT_600M', 'RIG_BANDSELECT_60M', 'RIG_BANDSELECT_6M', 'RIG_BANDSELECT_70CM', 'RIG_BANDSELECT_80M', 'RIG_BANDSELECT_9CM', 'RIG_BANDSELECT_AIR', 'RIG_BANDSELECT_GEN', 'RIG_BANDSELECT_MW', 'RIG_BANDSELECT_UNUSED', 'RIG_BANDSELECT_WFM', 'RIG_BAND_10M', 'RIG_BAND_12M', 'RIG_BAND_144MHZ', 'RIG_BAND_15M', 'RIG_BAND_160M', 'RIG_BAND_17M', 'RIG_BAND_20M', 'RIG_BAND_30M', 'RIG_BAND_40M', 'RIG_BAND_430MHZ', 'RIG_BAND_60M', 'RIG_BAND_6M', 'RIG_BAND_80M', 'RIG_BAND_AIR', 'RIG_BAND_GEN', 'RIG_BAND_MW', 'RIG_BAND_UNUSED', 'RIG_BIN_MAX', 'RIG_BUSBUSY', 'RIG_BUSERROR', 'RIG_CAPS_HAS_GET_LEVEL', 'RIG_CAPS_HAS_SET_LEVEL', 'RIG_CAPS_MFG_NAME_CPTR', 'RIG_CAPS_MODEL_NAME_CPTR', 'RIG_CAPS_PORT_TYPE', 'RIG_CAPS_PTT_TYPE', 'RIG_CAPS_RIG_MODEL', 'RIG_CAPS_STATUS_CPTR', 'RIG_CAPS_TARGETABLE_VFO', 'RIG_CAPS_VERSION_CPTR', 'RIG_CHFLAG_DATA', 'RIG_CHFLAG_NONE', 'RIG_CHFLAG_PSKIP', 'RIG_CHFLAG_SKIP', 'RIG_CLIENT_GPREDICT', 'RIG_CLIENT_UNKNOWN', 'RIG_CLIENT_WSJTX', 'RIG_COMBO_MAX', 'RIG_COMM_STATUS_CONNECTING', 'RIG_COMM_STATUS_DISCONNECTED', 'RIG_COMM_STATUS_ERROR', 'RIG_COMM_STATUS_OK', 'RIG_COMM_STATUS_TERMINATED', 'RIG_COMM_STATUS_WARNING', 'RIG_CONF_BINARY', 'RIG_CONF_BUTTON', 'RIG_CONF_CHECKBUTTON', 'RIG_CONF_COMBO', 'RIG_CONF_END', 'RIG_CONF_INT', 'RIG_CONF_NUMERIC', 'RIG_CONF_STRING', 'RIG_COOKIE_GET', 'RIG_COOKIE_RELEASE', 'RIG_COOKIE_RENEW', 'RIG_DBLST_END', 'RIG_DCD_CM108', 'RIG_DCD_GPIO', 'RIG_DCD_GPION', 'RIG_DCD_NONE', 'RIG_DCD_OFF', 'RIG_DCD_ON', 'RIG_DCD_PARALLEL', 'RIG_DCD_RIG', 'RIG_DCD_SERIAL_CAR', 'RIG_DCD_SERIAL_CTS', 'RIG_DCD_SERIAL_DSR', 'RIG_DEBUG_BUG', 'RIG_DEBUG_CACHE', 'RIG_DEBUG_ERR', 'RIG_DEBUG_NONE', 'RIG_DEBUG_TRACE', 'RIG_DEBUG_VERBOSE', 'RIG_DEBUG_WARN', 'RIG_EACCESS', 'RIG_EARG', 'RIG_ECONF', 'RIG_EDEPRECATED', 'RIG_EDOM', 'RIG_EEND', 'RIG_EINTERNAL', 'RIG_EINVAL', 'RIG_EIO', 'RIG_ELIMIT', 'RIG_ENAVAIL', 'RIG_ENIMPL', 'RIG_ENOMEM', 'RIG_ENTARGET', 'RIG_EPOWER', 'RIG_EPROTO', 'RIG_ERJCTED', 'RIG_ESECURITY', 'RIG_ETIMEOUT', 'RIG_ETRUNC', 'RIG_EVFO', 'RIG_FLAG_APRS', 'RIG_FLAG_COMPUTER', 'RIG_FLAG_DXCLUSTER', 'RIG_FLAG_HANDHELD', 'RIG_FLAG_MOBILE', 'RIG_FLAG_RECEIVER', 'RIG_FLAG_SCANNER', 'RIG_FLAG_TNC', 'RIG_FLAG_TRANSMITTER', 'RIG_FLAG_TRUNKING', 'RIG_FLAG_TUNER', 'RIG_FLT_ANY', 'RIG_FUNCTION_CLEANUP', 'RIG_FUNCTION_CLOSE', 'RIG_FUNCTION_DECODE_EVENT', 'RIG_FUNCTION_GET_ANT', 'RIG_FUNCTION_GET_CHANNEL', 'RIG_FUNCTION_GET_CHAN_ALL_CB', 'RIG_FUNCTION_GET_CONF', 'RIG_FUNCTION_GET_CONF2', 'RIG_FUNCTION_GET_CTCSS_SQL', 'RIG_FUNCTION_GET_CTCSS_TONE', 'RIG_FUNCTION_GET_DCD', 'RIG_FUNCTION_GET_DCS_CODE', 'RIG_FUNCTION_GET_DCS_SQL', 'RIG_FUNCTION_GET_EXT_FUNC', 'RIG_FUNCTION_GET_EXT_LEVEL', 'RIG_FUNCTION_GET_EXT_PARM', 'RIG_FUNCTION_GET_FREQ', 'RIG_FUNCTION_GET_FUNC', 'RIG_FUNCTION_GET_INFO', 'RIG_FUNCTION_GET_LEVEL', 'RIG_FUNCTION_GET_MEM', 'RIG_FUNCTION_GET_MEM_ALL_CB', 'RIG_FUNCTION_GET_MODE', 'RIG_FUNCTION_GET_PARM', 'RIG_FUNCTION_GET_POWERSTAT', 'RIG_FUNCTION_GET_PTT', 'RIG_FUNCTION_GET_RIT', 'RIG_FUNCTION_GET_RPTR_OFFS', 'RIG_FUNCTION_GET_RPTR_SHIFT', 'RIG_FUNCTION_GET_SPLIT_FREQ', 'RIG_FUNCTION_GET_SPLIT_FREQ_MODE', 'RIG_FUNCTION_GET_SPLIT_VFO', 'RIG_FUNCTION_GET_TONE', 'RIG_FUNCTION_GET_TONE_SQL', 'RIG_FUNCTION_GET_TRN', 'RIG_FUNCTION_GET_TS', 'RIG_FUNCTION_GET_VFO', 'RIG_FUNCTION_GET_XIT', 'RIG_FUNCTION_INIT', 'RIG_FUNCTION_IS_ASYNC_FRAME', 'RIG_FUNCTION_MW2POWER', 'RIG_FUNCTION_OPEN', 'RIG_FUNCTION_POWER2MW', 'RIG_FUNCTION_PROCESS_ASYNC_FRAME', 'RIG_FUNCTION_READ_FRAME_DIRECT', 'RIG_FUNCTION_RESET', 'RIG_FUNCTION_SCAN', 'RIG_FUNCTION_SEND_DTMF', 'RIG_FUNCTION_SEND_MORSE', 'RIG_FUNCTION_SEND_VOICE_MEM', 'RIG_FUNCTION_SET_ANT', 'RIG_FUNCTION_SET_BANK', 'RIG_FUNCTION_SET_CHANNEL', 'RIG_FUNCTION_SET_CHAN_ALL_CB', 'RIG_FUNCTION_SET_CONF', 'RIG_FUNCTION_SET_CTCSS_SQL', 'RIG_FUNCTION_SET_CTCSS_TONE', 'RIG_FUNCTION_SET_DCS_CODE', 'RIG_FUNCTION_SET_DCS_SQL', 'RIG_FUNCTION_SET_EXT_FUNC', 'RIG_FUNCTION_SET_EXT_LEVEL', 'RIG_FUNCTION_SET_EXT_PARM', 'RIG_FUNCTION_SET_FREQ', 'RIG_FUNCTION_SET_FUNC', 'RIG_FUNCTION_SET_LEVEL', 'RIG_FUNCTION_SET_MEM', 'RIG_FUNCTION_SET_MEM_ALL_CB', 'RIG_FUNCTION_SET_MODE', 'RIG_FUNCTION_SET_PARM', 'RIG_FUNCTION_SET_POWERSTAT', 'RIG_FUNCTION_SET_PTT', 'RIG_FUNCTION_SET_RIT', 'RIG_FUNCTION_SET_RPTR_OFFS', 'RIG_FUNCTION_SET_RPTR_SHIFT', 'RIG_FUNCTION_SET_SPLIT_FREQ', 'RIG_FUNCTION_SET_SPLIT_FREQ_MODE', 'RIG_FUNCTION_SET_SPLIT_MODE', 'RIG_FUNCTION_SET_SPLIT_VFO', 'RIG_FUNCTION_SET_TONE', 'RIG_FUNCTION_SET_TONE_SQL', 'RIG_FUNCTION_SET_TRN', 'RIG_FUNCTION_SET_TS', 'RIG_FUNCTION_SET_VFO', 'RIG_FUNCTION_SET_VFO_OPT', 'RIG_FUNCTION_SET_XIT', 'RIG_FUNCTION_STOP_MORSE', 'RIG_FUNCTION_STOP_VOICE_MEM', 'RIG_FUNCTION_VFO_OP', 'RIG_FUNCTION_WAIT_MORSE', 'RIG_FUNC_ABM', 'RIG_FUNC_AFC', 'RIG_FUNC_AFLT', 'RIG_FUNC_AIP', 'RIG_FUNC_ANF', 'RIG_FUNC_ANL', 'RIG_FUNC_APF', 'RIG_FUNC_ARO', 'RIG_FUNC_BC', 'RIG_FUNC_BC2', 'RIG_FUNC_BIT49', 'RIG_FUNC_BIT50', 'RIG_FUNC_BIT51', 'RIG_FUNC_BIT52', 'RIG_FUNC_BIT53', 'RIG_FUNC_BIT54', 'RIG_FUNC_BIT55', 'RIG_FUNC_BIT56', 'RIG_FUNC_BIT57', 'RIG_FUNC_BIT58', 'RIG_FUNC_BIT59', 'RIG_FUNC_BIT60', 'RIG_FUNC_BIT61', 'RIG_FUNC_BIT62', 'RIG_FUNC_BIT63', 'RIG_FUNC_COMP', 'RIG_FUNC_CSQL', 'RIG_FUNC_DIVERSITY', 'RIG_FUNC_DSQL', 'RIG_FUNC_DUAL_WATCH', 'RIG_FUNC_FAGC', 'RIG_FUNC_FBKIN', 'RIG_FUNC_LOCK', 'RIG_FUNC_MBC', 'RIG_FUNC_MN', 'RIG_FUNC_MON', 'RIG_FUNC_MUTE', 'RIG_FUNC_NB', 'RIG_FUNC_NB2', 'RIG_FUNC_NONE', 'RIG_FUNC_NR', 'RIG_FUNC_OVF_STATUS', 'RIG_FUNC_RESUME', 'RIG_FUNC_REV', 'RIG_FUNC_RF', 'RIG_FUNC_RIT', 'RIG_FUNC_SATMODE', 'RIG_FUNC_SBKIN', 'RIG_FUNC_SCEN', 'RIG_FUNC_SCOPE', 'RIG_FUNC_SEND_MORSE', 'RIG_FUNC_SEND_VOICE_MEM', 'RIG_FUNC_SLICE', 'RIG_FUNC_SPECTRUM', 'RIG_FUNC_SPECTRUM_HOLD', 'RIG_FUNC_SQL', 'RIG_FUNC_SYNC', 'RIG_FUNC_TBURST', 'RIG_FUNC_TONE', 'RIG_FUNC_TRANSCEIVE', 'RIG_FUNC_TSQL', 'RIG_FUNC_TUNER', 'RIG_FUNC_VOX', 'RIG_FUNC_VSC', 'RIG_FUNC_XIT', 'RIG_HANDSHAKE_HARDWARE', 'RIG_HANDSHAKE_NONE', 'RIG_HANDSHAKE_XONXOFF', 'RIG_KEYERTYPE_BUG', 'RIG_KEYERTYPE_PADDLE', 'RIG_KEYERTYPE_STRAIGHT', 'RIG_KEYERTYPE_UNKNOWN', 'RIG_LEVEL_53', 'RIG_LEVEL_54', 'RIG_LEVEL_55', 'RIG_LEVEL_56', 'RIG_LEVEL_57', 'RIG_LEVEL_58', 'RIG_LEVEL_59', 'RIG_LEVEL_60', 'RIG_LEVEL_61', 'RIG_LEVEL_62', 'RIG_LEVEL_63', 'RIG_LEVEL_AF', 'RIG_LEVEL_AGC', 'RIG_LEVEL_AGC_TIME', 'RIG_LEVEL_ALC', 'RIG_LEVEL_ANTIVOX', 'RIG_LEVEL_APF', 'RIG_LEVEL_ATT', 'RIG_LEVEL_BALANCE', 'RIG_LEVEL_BAND_SELECT', 'RIG_LEVEL_BKINDL', 'RIG_LEVEL_BKIN_DLYMS', 'RIG_LEVEL_COMP', 'RIG_LEVEL_COMP_METER', 'RIG_LEVEL_CWPITCH', 'RIG_LEVEL_FLOAT_LIST', 'RIG_LEVEL_ID_METER', 'RIG_LEVEL_IF', 'RIG_LEVEL_KEYSPD', 'RIG_LEVEL_METER', 'RIG_LEVEL_MICGAIN', 'RIG_LEVEL_MONITOR_GAIN', 'RIG_LEVEL_NB', 'RIG_LEVEL_NONE', 'RIG_LEVEL_NOTCHF', 'RIG_LEVEL_NOTCHF_RAW', 'RIG_LEVEL_NR', 'RIG_LEVEL_PBT_IN', 'RIG_LEVEL_PBT_OUT', 'RIG_LEVEL_PREAMP', 'RIG_LEVEL_RAWSTR', 'RIG_LEVEL_READONLY_LIST', 'RIG_LEVEL_RF', 'RIG_LEVEL_RFPOWER', 'RIG_LEVEL_RFPOWER_METER', 'RIG_LEVEL_RFPOWER_METER_WATTS', 'RIG_LEVEL_SLOPE_HIGH', 'RIG_LEVEL_SLOPE_LOW', 'RIG_LEVEL_SPECTRUM_ATT', 'RIG_LEVEL_SPECTRUM_AVG', 'RIG_LEVEL_SPECTRUM_EDGE_HIGH', 'RIG_LEVEL_SPECTRUM_EDGE_LOW', 'RIG_LEVEL_SPECTRUM_MODE', 'RIG_LEVEL_SPECTRUM_REF', 'RIG_LEVEL_SPECTRUM_SPAN', 'RIG_LEVEL_SPECTRUM_SPEED', 'RIG_LEVEL_SQL', 'RIG_LEVEL_STRENGTH', 'RIG_LEVEL_SWR', 'RIG_LEVEL_TEMP_METER', 'RIG_LEVEL_USB_AF', 'RIG_LEVEL_USB_AF_INPUT', 'RIG_LEVEL_VD_METER', 'RIG_LEVEL_VOXDELAY', 'RIG_LEVEL_VOXGAIN', 'RIG_MEM_CAPS_ALL', 'RIG_METER_ALC', 'RIG_METER_COMP', 'RIG_METER_DB', 'RIG_METER_IC', 'RIG_METER_NONE', 'RIG_METER_PO', 'RIG_METER_SWR', 'RIG_METER_TEMP', 'RIG_METER_VDD', 'RIG_MODEL_505DSP', 'RIG_MODEL_ACLOG', 'RIG_MODEL_ADT_200A', 'RIG_MODEL_AR16', 'RIG_MODEL_AR2500', 'RIG_MODEL_AR2700', 'RIG_MODEL_AR3000', 'RIG_MODEL_AR3000A', 'RIG_MODEL_AR3030', 'RIG_MODEL_AR5000', 'RIG_MODEL_AR5000A', 'RIG_MODEL_AR7030', 'RIG_MODEL_AR7030P', 'RIG_MODEL_AR8000', 'RIG_MODEL_AR8200', 'RIG_MODEL_AR8600', 'RIG_MODEL_ARMSTRONG', 'RIG_MODEL_ATD578UVIII', 'RIG_MODEL_BARRETT_2050', 'RIG_MODEL_BARRETT_4050', 'RIG_MODEL_BARRETT_4100', 'RIG_MODEL_BARRETT_950', 'RIG_MODEL_BC235', 'RIG_MODEL_BC245', 'RIG_MODEL_BC250', 'RIG_MODEL_BC780', 'RIG_MODEL_BC785', 'RIG_MODEL_BC786', 'RIG_MODEL_BC895', 'RIG_MODEL_BC898', 'RIG_MODEL_BCD396T', 'RIG_MODEL_BCD996T', 'RIG_MODEL_BCT8', 'RIG_MODEL_CMH530', 'RIG_MODEL_CODAN_2110', 'RIG_MODEL_CODAN_ENVOY', 'RIG_MODEL_CODAN_NGT', 'RIG_MODEL_CTX10', 'RIG_MODEL_DDS60', 'RIG_MODEL_DELTAII', 'RIG_MODEL_DKR8', 'RIG_MODEL_DKR8A', 'RIG_MODEL_DKR8B', 'RIG_MODEL_DORJI_DRA818U', 'RIG_MODEL_DORJI_DRA818V', 'RIG_MODEL_DRT1', 'RIG_MODEL_DSP10', 'RIG_MODEL_DTTSP', 'RIG_MODEL_DTTSP_UDP', 'RIG_MODEL_DUMMY', 'RIG_MODEL_DUMMY_NOVFO', 'RIG_MODEL_DWT', 'RIG_MODEL_DX77', 'RIG_MODEL_DXSR8', 'RIG_MODEL_EB200', 'RIG_MODEL_EK070', 'RIG_MODEL_EK890', 'RIG_MODEL_EK891', 'RIG_MODEL_EK895', 'RIG_MODEL_EK89X', 'RIG_MODEL_EKD500', 'RIG_MODEL_ELAD_FDM_DUO', 'RIG_MODEL_ELEKTOR304', 'RIG_MODEL_ELEKTOR507', 'RIG_MODEL_ESM500', 'RIG_MODEL_ESMC', 'RIG_MODEL_F6K', 'RIG_MODEL_FASDR', 'RIG_MODEL_FIFISDR', 'RIG_MODEL_FLRIG', 'RIG_MODEL_FRG100', 'RIG_MODEL_FRG8800', 'RIG_MODEL_FRG9600', 'RIG_MODEL_FT100', 'RIG_MODEL_FT1000', 'RIG_MODEL_FT1000D', 'RIG_MODEL_FT1000MP', 'RIG_MODEL_FT1000MPMKV', 'RIG_MODEL_FT1000MPMKVFLD', 'RIG_MODEL_FT2000', 'RIG_MODEL_FT450', 'RIG_MODEL_FT450D', 'RIG_MODEL_FT575', 'RIG_MODEL_FT600', 'RIG_MODEL_FT650', 'RIG_MODEL_FT710', 'RIG_MODEL_FT736R', 'RIG_MODEL_FT747', 'RIG_MODEL_FT757', 'RIG_MODEL_FT757GXII', 'RIG_MODEL_FT767', 'RIG_MODEL_FT817', 'RIG_MODEL_FT818', 'RIG_MODEL_FT820', 'RIG_MODEL_FT840', 'RIG_MODEL_FT847', 'RIG_MODEL_FT847UNI', 'RIG_MODEL_FT857', 'RIG_MODEL_FT890', 'RIG_MODEL_FT891', 'RIG_MODEL_FT897', 'RIG_MODEL_FT897D', 'RIG_MODEL_FT900', 'RIG_MODEL_FT9000', 'RIG_MODEL_FT9000OLD', 'RIG_MODEL_FT920', 'RIG_MODEL_FT950', 'RIG_MODEL_FT980', 'RIG_MODEL_FT990', 'RIG_MODEL_FT990UNI', 'RIG_MODEL_FT991', 'RIG_MODEL_FTDX10', 'RIG_MODEL_FTDX101D', 'RIG_MODEL_FTDX101MP', 'RIG_MODEL_FTDX1200', 'RIG_MODEL_FTDX3000', 'RIG_MODEL_FTDX5000', 'RIG_MODEL_FUNCUBEDONGLE', 'RIG_MODEL_FUNCUBEDONGLEPLUS', 'RIG_MODEL_FX4', 'RIG_MODEL_G303', 'RIG_MODEL_G305', 'RIG_MODEL_G313', 'RIG_MODEL_G315', 'RIG_MODEL_G90', 'RIG_MODEL_GNURADIO', 'RIG_MODEL_GRAUDIO', 'RIG_MODEL_GRAUDIOIQ', 'RIG_MODEL_GS100', 'RIG_MODEL_HF1000', 'RIG_MODEL_HF1000A', 'RIG_MODEL_HF150', 'RIG_MODEL_HF225', 'RIG_MODEL_HF235', 'RIG_MODEL_HF250', 'RIG_MODEL_HIQSDR', 'RIG_MODEL_HPSDR', 'RIG_MODEL_IC1271', 'RIG_MODEL_IC1275', 'RIG_MODEL_IC271', 'RIG_MODEL_IC2730', 'RIG_MODEL_IC275', 'RIG_MODEL_IC375', 'RIG_MODEL_IC471', 'RIG_MODEL_IC475', 'RIG_MODEL_IC575', 'RIG_MODEL_IC7000', 'RIG_MODEL_IC703', 'RIG_MODEL_IC705', 'RIG_MODEL_IC706', 'RIG_MODEL_IC706MKII', 'RIG_MODEL_IC706MKIIG', 'RIG_MODEL_IC707', 'RIG_MODEL_IC7100', 'RIG_MODEL_IC718', 'RIG_MODEL_IC7200', 'RIG_MODEL_IC725', 'RIG_MODEL_IC726', 'RIG_MODEL_IC728', 'RIG_MODEL_IC729', 'RIG_MODEL_IC7300', 'RIG_MODEL_IC731', 'RIG_MODEL_IC735', 'RIG_MODEL_IC736', 'RIG_MODEL_IC737', 'RIG_MODEL_IC738', 'RIG_MODEL_IC7410', 'RIG_MODEL_IC746', 'RIG_MODEL_IC746PRO', 'RIG_MODEL_IC751', 'RIG_MODEL_IC751A', 'RIG_MODEL_IC756', 'RIG_MODEL_IC756PRO', 'RIG_MODEL_IC756PROII', 'RIG_MODEL_IC756PROIII', 'RIG_MODEL_IC7600', 'RIG_MODEL_IC761', 'RIG_MODEL_IC7610', 'RIG_MODEL_IC765', 'RIG_MODEL_IC7700', 'RIG_MODEL_IC775', 'RIG_MODEL_IC7760', 'RIG_MODEL_IC78', 'RIG_MODEL_IC7800', 'RIG_MODEL_IC781', 'RIG_MODEL_IC785x', 'RIG_MODEL_IC820', 'RIG_MODEL_IC821H', 'RIG_MODEL_IC905', 'RIG_MODEL_IC910', 'RIG_MODEL_IC9100', 'RIG_MODEL_IC92D', 'RIG_MODEL_IC970', 'RIG_MODEL_IC9700', 'RIG_MODEL_ICF8101', 'RIG_MODEL_ICID1', 'RIG_MODEL_ICR10', 'RIG_MODEL_ICR20', 'RIG_MODEL_ICR30', 'RIG_MODEL_ICR6', 'RIG_MODEL_ICR7000', 'RIG_MODEL_ICR71', 'RIG_MODEL_ICR7100', 'RIG_MODEL_ICR72', 'RIG_MODEL_ICR75', 'RIG_MODEL_ICR8500', 'RIG_MODEL_ICR8600', 'RIG_MODEL_ICR9000', 'RIG_MODEL_ICR9500', 'RIG_MODEL_ICRX7', 'RIG_MODEL_IC_M700PRO', 'RIG_MODEL_IC_M710', 'RIG_MODEL_IC_M802', 'RIG_MODEL_IC_M803', 'RIG_MODEL_ID31', 'RIG_MODEL_ID4100', 'RIG_MODEL_ID51', 'RIG_MODEL_ID5100', 'RIG_MODEL_JST145', 'RIG_MODEL_JST245', 'RIG_MODEL_K2', 'RIG_MODEL_K3', 'RIG_MODEL_K3S', 'RIG_MODEL_K4', 'RIG_MODEL_KX2', 'RIG_MODEL_KX3', 'RIG_MODEL_LAB599_TX500', 'RIG_MODEL_MALACHITE', 'RIG_MODEL_MC4020', 'RIG_MODEL_MCHFQRP', 'RIG_MODEL_MDS4710', 'RIG_MODEL_MDS9710', 'RIG_MODEL_MICOM2', 'RIG_MODEL_MICROTUNE_4702', 'RIG_MODEL_MICROTUNE_4707', 'RIG_MODEL_MICROTUNE_4937', 'RIG_MODEL_MINISCOUT', 'RIG_MODEL_MINIVNA', 'RIG_MODEL_NETRIGCTL', 'RIG_MODEL_NONE', 'RIG_MODEL_NRD345', 'RIG_MODEL_NRD525', 'RIG_MODEL_NRD535', 'RIG_MODEL_NRD545', 'RIG_MODEL_OMNIVI', 'RIG_MODEL_OMNIVIP', 'RIG_MODEL_OS456', 'RIG_MODEL_OS535', 'RIG_MODEL_PARAGON2', 'RIG_MODEL_PCR100', 'RIG_MODEL_PCR1000', 'RIG_MODEL_PCR1500', 'RIG_MODEL_PCR2500', 'RIG_MODEL_PERSEUS', 'RIG_MODEL_PMR171', 'RIG_MODEL_PMSDR', 'RIG_MODEL_POWERSDR', 'RIG_MODEL_PRM8060', 'RIG_MODEL_PRM8070', 'RIG_MODEL_PRO2052', 'RIG_MODEL_PT8000A', 'RIG_MODEL_Q900', 'RIG_MODEL_QRPLABS', 'RIG_MODEL_QRPLABS_QMX', 'RIG_MODEL_QUISK', 'RIG_MODEL_R5000', 'RIG_MODEL_RA3702', 'RIG_MODEL_RA3710', 'RIG_MODEL_RA3720', 'RIG_MODEL_RA3790', 'RIG_MODEL_RA6790', 'RIG_MODEL_RS2005', 'RIG_MODEL_RS2006', 'RIG_MODEL_RS2035', 'RIG_MODEL_RS2041', 'RIG_MODEL_RS2042', 'RIG_MODEL_RS64', 'RIG_MODEL_RSHFIQ', 'RIG_MODEL_RX320', 'RIG_MODEL_RX331', 'RIG_MODEL_RX340', 'RIG_MODEL_RX350', 'RIG_MODEL_SDR1000', 'RIG_MODEL_SDR1000RFE', 'RIG_MODEL_SDRCONSOLE', 'RIG_MODEL_SDRSHARP', 'RIG_MODEL_SDRUNO', 'RIG_MODEL_SDU5000', 'RIG_MODEL_SDU5500', 'RIG_MODEL_SI570AVRUSB', 'RIG_MODEL_SI570PEABERRY1', 'RIG_MODEL_SI570PEABERRY2', 'RIG_MODEL_SI570PICUSB', 'RIG_MODEL_SMARTSDR_A', 'RIG_MODEL_SMARTSDR_B', 'RIG_MODEL_SMARTSDR_C', 'RIG_MODEL_SMARTSDR_D', 'RIG_MODEL_SMARTSDR_E', 'RIG_MODEL_SMARTSDR_F', 'RIG_MODEL_SMARTSDR_G', 'RIG_MODEL_SMARTSDR_H', 'RIG_MODEL_SR2200', 'RIG_MODEL_TCI1X', 'RIG_MODEL_THD72A', 'RIG_MODEL_THD74', 'RIG_MODEL_THD7A', 'RIG_MODEL_THD7AG', 'RIG_MODEL_THETIS', 'RIG_MODEL_THF6A', 'RIG_MODEL_THF7E', 'RIG_MODEL_THG71', 'RIG_MODEL_TMD700', 'RIG_MODEL_TMD710', 'RIG_MODEL_TMV7', 'RIG_MODEL_TMV71', 'RIG_MODEL_TRANSFOX', 'RIG_MODEL_TRC80', 'RIG_MODEL_TRP7000', 'RIG_MODEL_TRP8000', 'RIG_MODEL_TRP8255', 'RIG_MODEL_TRP9000', 'RIG_MODEL_TRUSDX', 'RIG_MODEL_TRXMANAGER_RIG', 'RIG_MODEL_TS140S', 'RIG_MODEL_TS2000', 'RIG_MODEL_TS440', 'RIG_MODEL_TS450S', 'RIG_MODEL_TS480', 'RIG_MODEL_TS50', 'RIG_MODEL_TS570D', 'RIG_MODEL_TS570S', 'RIG_MODEL_TS590S', 'RIG_MODEL_TS590SG', 'RIG_MODEL_TS680S', 'RIG_MODEL_TS690S', 'RIG_MODEL_TS711', 'RIG_MODEL_TS790', 'RIG_MODEL_TS811', 'RIG_MODEL_TS850', 'RIG_MODEL_TS870S', 'RIG_MODEL_TS890S', 'RIG_MODEL_TS930', 'RIG_MODEL_TS940', 'RIG_MODEL_TS950S', 'RIG_MODEL_TS950SDX', 'RIG_MODEL_TS990S', 'RIG_MODEL_TT516', 'RIG_MODEL_TT526', 'RIG_MODEL_TT538', 'RIG_MODEL_TT550', 'RIG_MODEL_TT565', 'RIG_MODEL_TT585', 'RIG_MODEL_TT588', 'RIG_MODEL_TT599', 'RIG_MODEL_USRP', 'RIG_MODEL_USRP0', 'RIG_MODEL_USRP_G', 'RIG_MODEL_V4L', 'RIG_MODEL_V4L2', 'RIG_MODEL_VR5000', 'RIG_MODEL_VX1700', 'RIG_MODEL_WJ8711', 'RIG_MODEL_WJ8888', 'RIG_MODEL_WR1000', 'RIG_MODEL_WR1500', 'RIG_MODEL_WR1550', 'RIG_MODEL_WR3100', 'RIG_MODEL_WR3150', 'RIG_MODEL_WR3500', 'RIG_MODEL_WR3700', 'RIG_MODEL_X108G', 'RIG_MODEL_X5105', 'RIG_MODEL_X6100', 'RIG_MODEL_X6200', 'RIG_MODEL_XG3', 'RIG_MODEL_XK2100', 'RIG_MODEL_XK852', 'RIG_MODEL_XPLORER', 'RIG_MODE_ALL', 'RIG_MODE_AM', 'RIG_MODE_AMN', 'RIG_MODE_AMS', 'RIG_MODE_BIT46', 'RIG_MODE_BIT47', 'RIG_MODE_BIT48', 'RIG_MODE_BIT49', 'RIG_MODE_BIT50', 'RIG_MODE_BIT51', 'RIG_MODE_BIT52', 'RIG_MODE_BIT53', 'RIG_MODE_BIT54', 'RIG_MODE_BIT55', 'RIG_MODE_BIT56', 'RIG_MODE_BIT57', 'RIG_MODE_BIT58', 'RIG_MODE_BIT59', 'RIG_MODE_BIT60', 'RIG_MODE_BIT61', 'RIG_MODE_BIT62', 'RIG_MODE_C4FM', 'RIG_MODE_CW', 'RIG_MODE_CWN', 'RIG_MODE_CWR', 'RIG_MODE_DCR', 'RIG_MODE_DD', 'RIG_MODE_DPMR', 'RIG_MODE_DSB', 'RIG_MODE_DSTAR', 'RIG_MODE_ECSS', 'RIG_MODE_ECSSLSB', 'RIG_MODE_ECSSUSB', 'RIG_MODE_FAX', 'RIG_MODE_FM', 'RIG_MODE_FMN', 'RIG_MODE_IQ', 'RIG_MODE_ISBLSB', 'RIG_MODE_ISBUSB', 'RIG_MODE_LSB', 'RIG_MODE_LSBD1', 'RIG_MODE_LSBD2', 'RIG_MODE_LSBD3', 'RIG_MODE_NONE', 'RIG_MODE_NXDNVN', 'RIG_MODE_NXDN_N', 'RIG_MODE_P25', 'RIG_MODE_PKTAM', 'RIG_MODE_PKTFM', 'RIG_MODE_PKTFMN', 'RIG_MODE_PKTLSB', 'RIG_MODE_PKTSSB', 'RIG_MODE_PKTUSB', 'RIG_MODE_PSK', 'RIG_MODE_PSKR', 'RIG_MODE_RTTY', 'RIG_MODE_RTTYR', 'RIG_MODE_SAH', 'RIG_MODE_SAL', 'RIG_MODE_SAM', 'RIG_MODE_SPEC', 'RIG_MODE_SSB', 'RIG_MODE_TESTS_MAX', 'RIG_MODE_USB', 'RIG_MODE_USBD1', 'RIG_MODE_USBD2', 'RIG_MODE_USBD3', 'RIG_MODE_WFM', 'RIG_MTYPE_BAND', 'RIG_MTYPE_CALL', 'RIG_MTYPE_EDGE', 'RIG_MTYPE_MEM', 'RIG_MTYPE_MEMOPAD', 'RIG_MTYPE_MORSE', 'RIG_MTYPE_NONE', 'RIG_MTYPE_PRIO', 'RIG_MTYPE_SAT', 'RIG_MTYPE_SPLIT', 'RIG_MTYPE_VOICE', 'RIG_MULTICAST_POLL', 'RIG_MULTICAST_SPECTRUM', 'RIG_MULTICAST_TRANSCEIVE', 'RIG_OK', 'RIG_OP_BAND_DOWN', 'RIG_OP_BAND_UP', 'RIG_OP_CPY', 'RIG_OP_DOWN', 'RIG_OP_FROM_VFO', 'RIG_OP_LEFT', 'RIG_OP_MCL', 'RIG_OP_NONE', 'RIG_OP_RIGHT', 'RIG_OP_TOGGLE', 'RIG_OP_TO_VFO', 'RIG_OP_TUNE', 'RIG_OP_UP', 'RIG_OP_XCHG', 'RIG_PARITY_EVEN', 'RIG_PARITY_MARK', 'RIG_PARITY_NONE', 'RIG_PARITY_ODD', 'RIG_PARITY_SPACE', 'RIG_PARM_AFIF', 'RIG_PARM_AFIF_ACC', 'RIG_PARM_AFIF_LAN', 'RIG_PARM_AFIF_WLAN', 'RIG_PARM_ANN', 'RIG_PARM_APO', 'RIG_PARM_BACKLIGHT', 'RIG_PARM_BANDSELECT', 'RIG_PARM_BAT', 'RIG_PARM_BEEP', 'RIG_PARM_KEYERTYPE', 'RIG_PARM_KEYLIGHT', 'RIG_PARM_NONE', 'RIG_PARM_SCREENSAVER', 'RIG_PARM_TIME', 'RIG_PORT_CM108', 'RIG_PORT_DEVICE', 'RIG_PORT_DTMF', 'RIG_PORT_GPIO', 'RIG_PORT_GPION', 'RIG_PORT_NETWORK', 'RIG_PORT_NONE', 'RIG_PORT_PACKET', 'RIG_PORT_PARALLEL', 'RIG_PORT_RPC', 'RIG_PORT_SERIAL', 'RIG_PORT_UDP_NETWORK', 'RIG_PORT_ULTRA', 'RIG_PORT_USB', 'RIG_POWER_OFF', 'RIG_POWER_ON', 'RIG_POWER_OPERATE', 'RIG_POWER_STANDBY', 'RIG_POWER_UNKNOWN', 'RIG_PTRX_AMPPORT', 'RIG_PTRX_AMPSTATE', 'RIG_PTRX_CACHE', 'RIG_PTRX_DCDPORT', 'RIG_PTRX_MAXIMUM', 'RIG_PTRX_NONE', 'RIG_PTRX_PTTPORT', 'RIG_PTRX_RIGPORT', 'RIG_PTRX_ROTPORT', 'RIG_PTRX_ROTPORT2', 'RIG_PTRX_ROTSTATE', 'RIG_PTRX_STATE', 'RIG_PTT_CM108', 'RIG_PTT_GPIO', 'RIG_PTT_GPION', 'RIG_PTT_NONE', 'RIG_PTT_OFF', 'RIG_PTT_ON', 'RIG_PTT_ON_DATA', 'RIG_PTT_ON_MIC', 'RIG_PTT_PARALLEL', 'RIG_PTT_RIG', 'RIG_PTT_RIG_MICDATA', 'RIG_PTT_SERIAL_DTR', 'RIG_PTT_SERIAL_RTS', 'RIG_RESET_MASTER', 'RIG_RESET_MCALL', 'RIG_RESET_NONE', 'RIG_RESET_SOFT', 'RIG_RESET_VFO', 'RIG_RPT_SHIFT_MINUS', 'RIG_RPT_SHIFT_NONE', 'RIG_RPT_SHIFT_PLUS', 'RIG_SCAN_DELTA', 'RIG_SCAN_MEM', 'RIG_SCAN_NONE', 'RIG_SCAN_PLT', 'RIG_SCAN_PRIO', 'RIG_SCAN_PROG', 'RIG_SCAN_SLCT', 'RIG_SCAN_STOP', 'RIG_SCAN_VFO', 'RIG_SETTING_MAX', 'RIG_SIGNAL_OFF', 'RIG_SIGNAL_ON', 'RIG_SIGNAL_UNSET', 'RIG_SPECTRUM_MODE_CENTER', 'RIG_SPECTRUM_MODE_CENTER_SCROLL', 'RIG_SPECTRUM_MODE_FIXED', 'RIG_SPECTRUM_MODE_FIXED_SCROLL', 'RIG_SPECTRUM_MODE_NONE', 'RIG_SPLIT_OFF', 'RIG_SPLIT_ON', 'RIG_STATUS_ALPHA', 'RIG_STATUS_BETA', 'RIG_STATUS_BUGGY', 'RIG_STATUS_STABLE', 'RIG_STATUS_UNTESTED', 'RIG_TARGETABLE_ALL', 'RIG_TARGETABLE_ANT', 'RIG_TARGETABLE_BAND', 'RIG_TARGETABLE_BANK', 'RIG_TARGETABLE_COMMON', 'RIG_TARGETABLE_FREQ', 'RIG_TARGETABLE_FUNC', 'RIG_TARGETABLE_LEVEL', 'RIG_TARGETABLE_MEM', 'RIG_TARGETABLE_MODE', 'RIG_TARGETABLE_NONE', 'RIG_TARGETABLE_PTT', 'RIG_TARGETABLE_PURE', 'RIG_TARGETABLE_RITXIT', 'RIG_TARGETABLE_ROOFING', 'RIG_TARGETABLE_SPECTRUM', 'RIG_TARGETABLE_TONE', 'RIG_TRN_OFF', 'RIG_TRN_POLL', 'RIG_TRN_RIG', 'RIG_TS_ANY', 'RIG_TYPE_OTHER', 'RIG_VFO_A', 'RIG_VFO_ALL', 'RIG_VFO_B', 'RIG_VFO_C', 'RIG_VFO_CURR', 'RIG_VFO_MAIN', 'RIG_VFO_MAIN_A', 'RIG_VFO_MAIN_B', 'RIG_VFO_MAIN_C', 'RIG_VFO_MEM', 'RIG_VFO_NONE', 'RIG_VFO_OTHER', 'RIG_VFO_RX', 'RIG_VFO_SUB', 'RIG_VFO_SUB_A', 'RIG_VFO_SUB_B', 'RIG_VFO_SUB_C', 'RIG_VFO_TX', 'RIG_VFO_TX_FLAG', 'RIG_VFO_VFO', 'ROT_FLAG_AZIMUTH', 'ROT_FLAG_ELEVATION', 'ROT_FUNC_BIT63', 'ROT_FUNC_NONE', 'ROT_LEVEL_63', 'ROT_LEVEL_FLOAT_LIST', 'ROT_LEVEL_NONE', 'ROT_LEVEL_READONLY_LIST', 'ROT_LEVEL_SPEED', 'ROT_MODEL_ANDROIDSENSOR', 'ROT_MODEL_APEX_SHARED_LOOP', 'ROT_MODEL_ARRAYSOLUTIONS_SAL_12_20_30', 'ROT_MODEL_CNCTRK', 'ROT_MODEL_DCU', 'ROT_MODEL_DUMMY', 'ROT_MODEL_EASYCOMM1', 'ROT_MODEL_EASYCOMM2', 'ROT_MODEL_EASYCOMM3', 'ROT_MODEL_ERC', 'ROT_MODEL_ETHER6', 'ROT_MODEL_F1TETRACKER', 'ROT_MODEL_FLIR', 'ROT_MODEL_FODTRACK', 'ROT_MODEL_GRBLTRK_NET', 'ROT_MODEL_GRBLTRK_SER', 'ROT_MODEL_GS23', 'ROT_MODEL_GS232', 'ROT_MODEL_GS232A', 'ROT_MODEL_GS232A_AZ', 'ROT_MODEL_GS232A_EL', 'ROT_MODEL_GS232B', 'ROT_MODEL_GS232B_AZ', 'ROT_MODEL_GS232B_EL', 'ROT_MODEL_GS232_GENERIC', 'ROT_MODEL_GS23_AZ', 'ROT_MODEL_HD1780', 'ROT_MODEL_IF100', 'ROT_MODEL_INDI', 'ROT_MODEL_IOPTRON', 'ROT_MODEL_LVB', 'ROT_MODEL_MEADE', 'ROT_MODEL_NETROTCTL', 'ROT_MODEL_NEXSTAR', 'ROT_MODEL_NONE', 'ROT_MODEL_PCROTOR', 'ROT_MODEL_PROSISTEL_COMBI_TRACK_AZEL', 'ROT_MODEL_PROSISTEL_D_AZ', 'ROT_MODEL_PROSISTEL_D_EL', 'ROT_MODEL_PROSISTEL_D_EL_CBOXAZ', 'ROT_MODEL_PSTROTATOR', 'ROT_MODEL_RADANT', 'ROT_MODEL_RC2800', 'ROT_MODEL_RC2800_EARLY_AZ', 'ROT_MODEL_RC2800_EARLY_AZEL', 'ROT_MODEL_RCI_AZ', 'ROT_MODEL_RCI_AZEL', 'ROT_MODEL_ROTORCARD', 'ROT_MODEL_ROTOREZ', 'ROT_MODEL_RT21', 'ROT_MODEL_SAEBRTRACK', 'ROT_MODEL_SARTEK1', 'ROT_MODEL_SATEL', 'ROT_MODEL_SATROTCTL', 'ROT_MODEL_SKYWATCHER', 'ROT_MODEL_SPID_MD01_ROT2PROG', 'ROT_MODEL_SPID_ROT1PROG', 'ROT_MODEL_SPID_ROT2PROG', 'ROT_MODEL_ST2', 'ROT_MODEL_TS7400', 'ROT_MODEL_YRC1', 'ROT_MOVE_CCW', 'ROT_MOVE_CW', 'ROT_MOVE_DOWN', 'ROT_MOVE_DOWN_CCW', 'ROT_MOVE_DOWN_CW', 'ROT_MOVE_DOWN_LEFT', 'ROT_MOVE_DOWN_RIGHT', 'ROT_MOVE_LEFT', 'ROT_MOVE_RIGHT', 'ROT_MOVE_UP', 'ROT_MOVE_UP_CCW', 'ROT_MOVE_UP_CW', 'ROT_MOVE_UP_LEFT', 'ROT_MOVE_UP_RIGHT', 'ROT_PARM_FLOAT_LIST', 'ROT_PARM_NONE', 'ROT_PARM_READONLY_LIST', 'ROT_RESET_ALL', 'ROT_SPEED_NOCHANGE', 'ROT_STATUS_BUSY', 'ROT_STATUS_LIMIT_DOWN', 'ROT_STATUS_LIMIT_LEFT', 'ROT_STATUS_LIMIT_RIGHT', 'ROT_STATUS_LIMIT_UP', 'ROT_STATUS_MOVING', 'ROT_STATUS_MOVING_AZ', 'ROT_STATUS_MOVING_DOWN', 'ROT_STATUS_MOVING_EL', 'ROT_STATUS_MOVING_LEFT', 'ROT_STATUS_MOVING_RIGHT', 'ROT_STATUS_MOVING_UP', 'ROT_STATUS_NONE', 'ROT_STATUS_OVERLAP_DOWN', 'ROT_STATUS_OVERLAP_LEFT', 'ROT_STATUS_OVERLAP_RIGHT', 'ROT_STATUS_OVERLAP_UP', 'ROT_TYPE_OTHER', 'TWIDDLE_OFF', 'TWIDDLE_ON', 'VFO_DUAL', 'cvar', 'hamlib_copyright', 'hamlib_version'] + expected_properties = ['AMP_FLAG_1', 'AMP_FLAG_2', 'AMP_LEVEL_FAULT', 'AMP_LEVEL_NH', 'AMP_LEVEL_NONE', 'AMP_LEVEL_PF', 'AMP_LEVEL_PWR', 'AMP_LEVEL_PWR_FWD', 'AMP_LEVEL_PWR_INPUT', 'AMP_LEVEL_PWR_PEAK', 'AMP_LEVEL_PWR_REFLECTED', 'AMP_LEVEL_SWR', 'AMP_MODEL_DUMMY', 'AMP_MODEL_ELECRAFT_KPA1500', 'AMP_MODEL_EXPERT_FA', 'AMP_MODEL_GEMINI_DX1200', 'AMP_MODEL_NETAMPCTL', 'AMP_MODEL_NONE', 'AMP_RESET_AMP', 'AMP_RESET_FAULT', 'AMP_RESET_MEM', 'AMP_TYPE_OTHER', 'BUILTINFUNC', 'CTCSS_LIST_SIZE', 'DCS_LIST_SIZE', 'DEBUGMSGSAVE_SIZE', 'GPIO1', 'GPIO2', 'GPIO3', 'GPIO4', 'HAMLIB_CACHE_ALL', 'HAMLIB_CACHE_ALWAYS', 'HAMLIB_CACHE_FREQ', 'HAMLIB_CACHE_MODE', 'HAMLIB_CACHE_PTT', 'HAMLIB_CACHE_SPLIT', 'HAMLIB_CACHE_VFO', 'HAMLIB_CACHE_WIDTH', 'HAMLIB_CHANLSTSIZ', 'HAMLIB_CHECK_RIG_CAPS', 'HAMLIB_COOKIE_SIZE', 'HAMLIB_ELAPSED_GET', 'HAMLIB_ELAPSED_INVALIDATE', 'HAMLIB_ELAPSED_SET', 'HAMLIB_FIFO_SIZE', 'HAMLIB_FILPATHLEN', 'HAMLIB_FLTLSTSIZ', 'HAMLIB_FRQRANGESIZ', 'HAMLIB_MAXCHANDESC', 'HAMLIB_MAXDBLSTSIZ', 'HAMLIB_MAX_AGC_LEVELS', 'HAMLIB_MAX_CAL_LENGTH', 'HAMLIB_MAX_MODES', 'HAMLIB_MAX_ROTORS', 'HAMLIB_MAX_RSCANS', 'HAMLIB_MAX_SNAPSHOT_PACKET_SIZE', 'HAMLIB_MAX_SPECTRUM_AVG_MODES', 'HAMLIB_MAX_SPECTRUM_DATA', 'HAMLIB_MAX_SPECTRUM_MODES', 'HAMLIB_MAX_SPECTRUM_SCOPES', 'HAMLIB_MAX_SPECTRUM_SPANS', 'HAMLIB_MAX_VFOS', 'HAMLIB_MAX_VFO_OPS', 'HAMLIB_RIGNAMSIZ', 'HAMLIB_RIGVERSIZ', 'HAMLIB_SECRET_LENGTH', 'HAMLIB_SETTINGS_FILE', 'HAMLIB_TSLSTSIZ', 'MAX_MODELS_PER_BACKEND', 'NETAMPCTL_RET', 'NETRIGCTL_RET', 'NETROTCTL_RET', 'RIG_AGC_AUTO', 'RIG_AGC_FAST', 'RIG_AGC_LAST', 'RIG_AGC_LONG', 'RIG_AGC_MEDIUM', 'RIG_AGC_NONE', 'RIG_AGC_OFF', 'RIG_AGC_ON', 'RIG_AGC_SLOW', 'RIG_AGC_SUPERFAST', 'RIG_AGC_USER', 'RIG_ANN_CW', 'RIG_ANN_ENG', 'RIG_ANN_FREQ', 'RIG_ANN_JAP', 'RIG_ANN_NONE', 'RIG_ANN_OFF', 'RIG_ANN_RXMODE', 'RIG_ANT_MAX', 'RIG_ANT_NONE', 'RIG_BANDSELECT_10M', 'RIG_BANDSELECT_12M', 'RIG_BANDSELECT_13CM', 'RIG_BANDSELECT_15M', 'RIG_BANDSELECT_160M', 'RIG_BANDSELECT_17M', 'RIG_BANDSELECT_1_25M', 'RIG_BANDSELECT_20M', 'RIG_BANDSELECT_2200M', 'RIG_BANDSELECT_23CM', 'RIG_BANDSELECT_2M', 'RIG_BANDSELECT_30M', 'RIG_BANDSELECT_33CM', 'RIG_BANDSELECT_3CM', 'RIG_BANDSELECT_40M', 'RIG_BANDSELECT_4M', 'RIG_BANDSELECT_5CM', 'RIG_BANDSELECT_600M', 'RIG_BANDSELECT_60M', 'RIG_BANDSELECT_6M', 'RIG_BANDSELECT_70CM', 'RIG_BANDSELECT_80M', 'RIG_BANDSELECT_9CM', 'RIG_BANDSELECT_AIR', 'RIG_BANDSELECT_GEN', 'RIG_BANDSELECT_MW', 'RIG_BANDSELECT_UNUSED', 'RIG_BANDSELECT_WFM', 'RIG_BAND_10M', 'RIG_BAND_12M', 'RIG_BAND_144MHZ', 'RIG_BAND_15M', 'RIG_BAND_160M', 'RIG_BAND_17M', 'RIG_BAND_20M', 'RIG_BAND_30M', 'RIG_BAND_40M', 'RIG_BAND_430MHZ', 'RIG_BAND_60M', 'RIG_BAND_6M', 'RIG_BAND_80M', 'RIG_BAND_AIR', 'RIG_BAND_GEN', 'RIG_BAND_MW', 'RIG_BAND_UNUSED', 'RIG_BUSBUSY', 'RIG_BUSERROR', 'RIG_CAPS_HAS_GET_LEVEL', 'RIG_CAPS_HAS_SET_LEVEL', 'RIG_CAPS_MFG_NAME_CPTR', 'RIG_CAPS_MODEL_NAME_CPTR', 'RIG_CAPS_PORT_TYPE', 'RIG_CAPS_PTT_TYPE', 'RIG_CAPS_RIG_MODEL', 'RIG_CAPS_STATUS_CPTR', 'RIG_CAPS_TARGETABLE_VFO', 'RIG_CAPS_VERSION_CPTR', 'RIG_CHFLAG_DATA', 'RIG_CHFLAG_NONE', 'RIG_CHFLAG_PSKIP', 'RIG_CHFLAG_SKIP', 'RIG_CLIENT_GPREDICT', 'RIG_CLIENT_UNKNOWN', 'RIG_CLIENT_WSJTX', 'RIG_COMM_STATUS_CONNECTING', 'RIG_COMM_STATUS_DISCONNECTED', 'RIG_COMM_STATUS_ERROR', 'RIG_COMM_STATUS_OK', 'RIG_COMM_STATUS_TERMINATED', 'RIG_COMM_STATUS_WARNING', 'RIG_CONF_BINARY', 'RIG_CONF_BUTTON', 'RIG_CONF_CHECKBUTTON', 'RIG_CONF_COMBO', 'RIG_CONF_END', 'RIG_CONF_INT', 'RIG_CONF_NUMERIC', 'RIG_CONF_STRING', 'RIG_COOKIE_GET', 'RIG_COOKIE_RELEASE', 'RIG_COOKIE_RENEW', 'RIG_DCD_CM108', 'RIG_DCD_GPIO', 'RIG_DCD_GPION', 'RIG_DCD_NONE', 'RIG_DCD_OFF', 'RIG_DCD_ON', 'RIG_DCD_PARALLEL', 'RIG_DCD_RIG', 'RIG_DCD_SERIAL_CAR', 'RIG_DCD_SERIAL_CTS', 'RIG_DCD_SERIAL_DSR', 'RIG_DEBUG_BUG', 'RIG_DEBUG_CACHE', 'RIG_DEBUG_ERR', 'RIG_DEBUG_NONE', 'RIG_DEBUG_TRACE', 'RIG_DEBUG_VERBOSE', 'RIG_DEBUG_WARN', 'RIG_EACCESS', 'RIG_EARG', 'RIG_ECONF', 'RIG_EDEPRECATED', 'RIG_EDOM', 'RIG_EEND', 'RIG_EINTERNAL', 'RIG_EINVAL', 'RIG_EIO', 'RIG_ELIMIT', 'RIG_ENAVAIL', 'RIG_ENIMPL', 'RIG_ENOMEM', 'RIG_ENTARGET', 'RIG_EPOWER', 'RIG_EPROTO', 'RIG_ERJCTED', 'RIG_ESECURITY', 'RIG_ETIMEOUT', 'RIG_ETRUNC', 'RIG_EVFO', 'RIG_FLAG_APRS', 'RIG_FLAG_COMPUTER', 'RIG_FLAG_DXCLUSTER', 'RIG_FLAG_HANDHELD', 'RIG_FLAG_MOBILE', 'RIG_FLAG_RECEIVER', 'RIG_FLAG_SCANNER', 'RIG_FLAG_TNC', 'RIG_FLAG_TRANSMITTER', 'RIG_FLAG_TRUNKING', 'RIG_FLAG_TUNER', 'RIG_FLT_ANY', 'RIG_FUNCTION_CLEANUP', 'RIG_FUNCTION_CLOSE', 'RIG_FUNCTION_DECODE_EVENT', 'RIG_FUNCTION_GET_ANT', 'RIG_FUNCTION_GET_CHANNEL', 'RIG_FUNCTION_GET_CHAN_ALL_CB', 'RIG_FUNCTION_GET_CONF', 'RIG_FUNCTION_GET_CONF2', 'RIG_FUNCTION_GET_CTCSS_SQL', 'RIG_FUNCTION_GET_CTCSS_TONE', 'RIG_FUNCTION_GET_DCD', 'RIG_FUNCTION_GET_DCS_CODE', 'RIG_FUNCTION_GET_DCS_SQL', 'RIG_FUNCTION_GET_EXT_FUNC', 'RIG_FUNCTION_GET_EXT_LEVEL', 'RIG_FUNCTION_GET_EXT_PARM', 'RIG_FUNCTION_GET_FREQ', 'RIG_FUNCTION_GET_FUNC', 'RIG_FUNCTION_GET_INFO', 'RIG_FUNCTION_GET_LEVEL', 'RIG_FUNCTION_GET_MEM', 'RIG_FUNCTION_GET_MEM_ALL_CB', 'RIG_FUNCTION_GET_MODE', 'RIG_FUNCTION_GET_PARM', 'RIG_FUNCTION_GET_POWERSTAT', 'RIG_FUNCTION_GET_PTT', 'RIG_FUNCTION_GET_RIT', 'RIG_FUNCTION_GET_RPTR_OFFS', 'RIG_FUNCTION_GET_RPTR_SHIFT', 'RIG_FUNCTION_GET_SPLIT_FREQ', 'RIG_FUNCTION_GET_SPLIT_FREQ_MODE', 'RIG_FUNCTION_GET_SPLIT_VFO', 'RIG_FUNCTION_GET_TONE', 'RIG_FUNCTION_GET_TONE_SQL', 'RIG_FUNCTION_GET_TRN', 'RIG_FUNCTION_GET_TS', 'RIG_FUNCTION_GET_VFO', 'RIG_FUNCTION_GET_XIT', 'RIG_FUNCTION_INIT', 'RIG_FUNCTION_IS_ASYNC_FRAME', 'RIG_FUNCTION_MW2POWER', 'RIG_FUNCTION_OPEN', 'RIG_FUNCTION_POWER2MW', 'RIG_FUNCTION_PROCESS_ASYNC_FRAME', 'RIG_FUNCTION_READ_FRAME_DIRECT', 'RIG_FUNCTION_RESET', 'RIG_FUNCTION_SCAN', 'RIG_FUNCTION_SEND_DTMF', 'RIG_FUNCTION_SEND_MORSE', 'RIG_FUNCTION_SEND_VOICE_MEM', 'RIG_FUNCTION_SET_ANT', 'RIG_FUNCTION_SET_BANK', 'RIG_FUNCTION_SET_CHANNEL', 'RIG_FUNCTION_SET_CHAN_ALL_CB', 'RIG_FUNCTION_SET_CONF', 'RIG_FUNCTION_SET_CTCSS_SQL', 'RIG_FUNCTION_SET_CTCSS_TONE', 'RIG_FUNCTION_SET_DCS_CODE', 'RIG_FUNCTION_SET_DCS_SQL', 'RIG_FUNCTION_SET_EXT_FUNC', 'RIG_FUNCTION_SET_EXT_LEVEL', 'RIG_FUNCTION_SET_EXT_PARM', 'RIG_FUNCTION_SET_FREQ', 'RIG_FUNCTION_SET_FUNC', 'RIG_FUNCTION_SET_LEVEL', 'RIG_FUNCTION_SET_MEM', 'RIG_FUNCTION_SET_MEM_ALL_CB', 'RIG_FUNCTION_SET_MODE', 'RIG_FUNCTION_SET_PARM', 'RIG_FUNCTION_SET_POWERSTAT', 'RIG_FUNCTION_SET_PTT', 'RIG_FUNCTION_SET_RIT', 'RIG_FUNCTION_SET_RPTR_OFFS', 'RIG_FUNCTION_SET_RPTR_SHIFT', 'RIG_FUNCTION_SET_SPLIT_FREQ', 'RIG_FUNCTION_SET_SPLIT_FREQ_MODE', 'RIG_FUNCTION_SET_SPLIT_MODE', 'RIG_FUNCTION_SET_SPLIT_VFO', 'RIG_FUNCTION_SET_TONE', 'RIG_FUNCTION_SET_TONE_SQL', 'RIG_FUNCTION_SET_TRN', 'RIG_FUNCTION_SET_TS', 'RIG_FUNCTION_SET_VFO', 'RIG_FUNCTION_SET_VFO_OPT', 'RIG_FUNCTION_SET_XIT', 'RIG_FUNCTION_STOP_MORSE', 'RIG_FUNCTION_STOP_VOICE_MEM', 'RIG_FUNCTION_VFO_OP', 'RIG_FUNCTION_WAIT_MORSE', 'RIG_FUNC_ABM', 'RIG_FUNC_AFC', 'RIG_FUNC_AFLT', 'RIG_FUNC_AIP', 'RIG_FUNC_ANF', 'RIG_FUNC_ANL', 'RIG_FUNC_APF', 'RIG_FUNC_ARO', 'RIG_FUNC_BC', 'RIG_FUNC_BC2', 'RIG_FUNC_BIT49', 'RIG_FUNC_BIT50', 'RIG_FUNC_BIT51', 'RIG_FUNC_BIT52', 'RIG_FUNC_BIT53', 'RIG_FUNC_BIT54', 'RIG_FUNC_BIT55', 'RIG_FUNC_BIT56', 'RIG_FUNC_BIT57', 'RIG_FUNC_BIT58', 'RIG_FUNC_BIT59', 'RIG_FUNC_BIT60', 'RIG_FUNC_BIT61', 'RIG_FUNC_BIT62', 'RIG_FUNC_BIT63', 'RIG_FUNC_COMP', 'RIG_FUNC_CSQL', 'RIG_FUNC_DIVERSITY', 'RIG_FUNC_DSQL', 'RIG_FUNC_DUAL_WATCH', 'RIG_FUNC_FAGC', 'RIG_FUNC_FBKIN', 'RIG_FUNC_LOCK', 'RIG_FUNC_MBC', 'RIG_FUNC_MN', 'RIG_FUNC_MON', 'RIG_FUNC_MUTE', 'RIG_FUNC_NB', 'RIG_FUNC_NB2', 'RIG_FUNC_NONE', 'RIG_FUNC_NR', 'RIG_FUNC_OVF_STATUS', 'RIG_FUNC_RESUME', 'RIG_FUNC_REV', 'RIG_FUNC_RF', 'RIG_FUNC_RIT', 'RIG_FUNC_SATMODE', 'RIG_FUNC_SBKIN', 'RIG_FUNC_SCEN', 'RIG_FUNC_SCOPE', 'RIG_FUNC_SEND_MORSE', 'RIG_FUNC_SEND_VOICE_MEM', 'RIG_FUNC_SLICE', 'RIG_FUNC_SPECTRUM', 'RIG_FUNC_SPECTRUM_HOLD', 'RIG_FUNC_SQL', 'RIG_FUNC_SYNC', 'RIG_FUNC_TBURST', 'RIG_FUNC_TONE', 'RIG_FUNC_TRANSCEIVE', 'RIG_FUNC_TSQL', 'RIG_FUNC_TUNER', 'RIG_FUNC_VOX', 'RIG_FUNC_VSC', 'RIG_FUNC_XIT', 'RIG_HANDSHAKE_HARDWARE', 'RIG_HANDSHAKE_NONE', 'RIG_HANDSHAKE_XONXOFF', 'RIG_KEYERTYPE_BUG', 'RIG_KEYERTYPE_PADDLE', 'RIG_KEYERTYPE_STRAIGHT', 'RIG_KEYERTYPE_UNKNOWN', 'RIG_LEVEL_53', 'RIG_LEVEL_54', 'RIG_LEVEL_55', 'RIG_LEVEL_56', 'RIG_LEVEL_57', 'RIG_LEVEL_58', 'RIG_LEVEL_59', 'RIG_LEVEL_60', 'RIG_LEVEL_61', 'RIG_LEVEL_62', 'RIG_LEVEL_63', 'RIG_LEVEL_AF', 'RIG_LEVEL_AGC', 'RIG_LEVEL_AGC_TIME', 'RIG_LEVEL_ALC', 'RIG_LEVEL_ANTIVOX', 'RIG_LEVEL_APF', 'RIG_LEVEL_ATT', 'RIG_LEVEL_BALANCE', 'RIG_LEVEL_BAND_SELECT', 'RIG_LEVEL_BKINDL', 'RIG_LEVEL_BKIN_DLYMS', 'RIG_LEVEL_COMP', 'RIG_LEVEL_COMP_METER', 'RIG_LEVEL_CWPITCH', 'RIG_LEVEL_FLOAT_LIST', 'RIG_LEVEL_ID_METER', 'RIG_LEVEL_IF', 'RIG_LEVEL_KEYSPD', 'RIG_LEVEL_METER', 'RIG_LEVEL_MICGAIN', 'RIG_LEVEL_MONITOR_GAIN', 'RIG_LEVEL_NB', 'RIG_LEVEL_NONE', 'RIG_LEVEL_NOTCHF', 'RIG_LEVEL_NOTCHF_RAW', 'RIG_LEVEL_NR', 'RIG_LEVEL_PBT_IN', 'RIG_LEVEL_PBT_OUT', 'RIG_LEVEL_PREAMP', 'RIG_LEVEL_RAWSTR', 'RIG_LEVEL_READONLY_LIST', 'RIG_LEVEL_RF', 'RIG_LEVEL_RFPOWER', 'RIG_LEVEL_RFPOWER_METER', 'RIG_LEVEL_RFPOWER_METER_WATTS', 'RIG_LEVEL_SLOPE_HIGH', 'RIG_LEVEL_SLOPE_LOW', 'RIG_LEVEL_SPECTRUM_ATT', 'RIG_LEVEL_SPECTRUM_AVG', 'RIG_LEVEL_SPECTRUM_EDGE_HIGH', 'RIG_LEVEL_SPECTRUM_EDGE_LOW', 'RIG_LEVEL_SPECTRUM_MODE', 'RIG_LEVEL_SPECTRUM_REF', 'RIG_LEVEL_SPECTRUM_SPAN', 'RIG_LEVEL_SPECTRUM_SPEED', 'RIG_LEVEL_SQL', 'RIG_LEVEL_STRENGTH', 'RIG_LEVEL_SWR', 'RIG_LEVEL_TEMP_METER', 'RIG_LEVEL_USB_AF', 'RIG_LEVEL_USB_AF_INPUT', 'RIG_LEVEL_VD_METER', 'RIG_LEVEL_VOXDELAY', 'RIG_LEVEL_VOXGAIN', 'RIG_MEM_CAPS_ALL', 'RIG_METER_ALC', 'RIG_METER_COMP', 'RIG_METER_DB', 'RIG_METER_IC', 'RIG_METER_NONE', 'RIG_METER_PO', 'RIG_METER_SWR', 'RIG_METER_TEMP', 'RIG_METER_VDD', 'RIG_MODEL_505DSP', 'RIG_MODEL_ACLOG', 'RIG_MODEL_ADT_200A', 'RIG_MODEL_AR16', 'RIG_MODEL_AR2500', 'RIG_MODEL_AR2700', 'RIG_MODEL_AR3000', 'RIG_MODEL_AR3000A', 'RIG_MODEL_AR3030', 'RIG_MODEL_AR5000', 'RIG_MODEL_AR5000A', 'RIG_MODEL_AR7030', 'RIG_MODEL_AR7030P', 'RIG_MODEL_AR8000', 'RIG_MODEL_AR8200', 'RIG_MODEL_AR8600', 'RIG_MODEL_ARMSTRONG', 'RIG_MODEL_ATD578UVIII', 'RIG_MODEL_BARRETT_2050', 'RIG_MODEL_BARRETT_4050', 'RIG_MODEL_BARRETT_4100', 'RIG_MODEL_BARRETT_950', 'RIG_MODEL_BC235', 'RIG_MODEL_BC245', 'RIG_MODEL_BC250', 'RIG_MODEL_BC780', 'RIG_MODEL_BC785', 'RIG_MODEL_BC786', 'RIG_MODEL_BC895', 'RIG_MODEL_BC898', 'RIG_MODEL_BCD396T', 'RIG_MODEL_BCD996T', 'RIG_MODEL_BCT8', 'RIG_MODEL_CMH530', 'RIG_MODEL_CODAN_2110', 'RIG_MODEL_CODAN_ENVOY', 'RIG_MODEL_CODAN_NGT', 'RIG_MODEL_CTX10', 'RIG_MODEL_DDS60', 'RIG_MODEL_DELTAII', 'RIG_MODEL_DKR8', 'RIG_MODEL_DKR8A', 'RIG_MODEL_DKR8B', 'RIG_MODEL_DORJI_DRA818U', 'RIG_MODEL_DORJI_DRA818V', 'RIG_MODEL_DRT1', 'RIG_MODEL_DSP10', 'RIG_MODEL_DTTSP', 'RIG_MODEL_DTTSP_UDP', 'RIG_MODEL_DUMMY', 'RIG_MODEL_DUMMY_NOVFO', 'RIG_MODEL_DWT', 'RIG_MODEL_DX77', 'RIG_MODEL_DXSR8', 'RIG_MODEL_EB200', 'RIG_MODEL_EK070', 'RIG_MODEL_EK890', 'RIG_MODEL_EK891', 'RIG_MODEL_EK895', 'RIG_MODEL_EK89X', 'RIG_MODEL_EKD500', 'RIG_MODEL_ELAD_FDM_DUO', 'RIG_MODEL_ELEKTOR304', 'RIG_MODEL_ELEKTOR507', 'RIG_MODEL_ESM500', 'RIG_MODEL_ESMC', 'RIG_MODEL_F6K', 'RIG_MODEL_FASDR', 'RIG_MODEL_FIFISDR', 'RIG_MODEL_FLRIG', 'RIG_MODEL_FRG100', 'RIG_MODEL_FRG8800', 'RIG_MODEL_FRG9600', 'RIG_MODEL_FT100', 'RIG_MODEL_FT1000', 'RIG_MODEL_FT1000D', 'RIG_MODEL_FT1000MP', 'RIG_MODEL_FT1000MPMKV', 'RIG_MODEL_FT1000MPMKVFLD', 'RIG_MODEL_FT2000', 'RIG_MODEL_FT450', 'RIG_MODEL_FT450D', 'RIG_MODEL_FT575', 'RIG_MODEL_FT600', 'RIG_MODEL_FT650', 'RIG_MODEL_FT710', 'RIG_MODEL_FT736R', 'RIG_MODEL_FT747', 'RIG_MODEL_FT757', 'RIG_MODEL_FT757GXII', 'RIG_MODEL_FT767', 'RIG_MODEL_FT817', 'RIG_MODEL_FT818', 'RIG_MODEL_FT820', 'RIG_MODEL_FT840', 'RIG_MODEL_FT847', 'RIG_MODEL_FT847UNI', 'RIG_MODEL_FT857', 'RIG_MODEL_FT890', 'RIG_MODEL_FT891', 'RIG_MODEL_FT897', 'RIG_MODEL_FT897D', 'RIG_MODEL_FT900', 'RIG_MODEL_FT9000', 'RIG_MODEL_FT9000OLD', 'RIG_MODEL_FT920', 'RIG_MODEL_FT950', 'RIG_MODEL_FT980', 'RIG_MODEL_FT990', 'RIG_MODEL_FT990UNI', 'RIG_MODEL_FT991', 'RIG_MODEL_FTDX10', 'RIG_MODEL_FTDX101D', 'RIG_MODEL_FTDX101MP', 'RIG_MODEL_FTDX1200', 'RIG_MODEL_FTDX3000', 'RIG_MODEL_FTDX5000', 'RIG_MODEL_FUNCUBEDONGLE', 'RIG_MODEL_FUNCUBEDONGLEPLUS', 'RIG_MODEL_FX4', 'RIG_MODEL_G303', 'RIG_MODEL_G305', 'RIG_MODEL_G313', 'RIG_MODEL_G315', 'RIG_MODEL_G90', 'RIG_MODEL_GNURADIO', 'RIG_MODEL_GRAUDIO', 'RIG_MODEL_GRAUDIOIQ', 'RIG_MODEL_GS100', 'RIG_MODEL_HF1000', 'RIG_MODEL_HF1000A', 'RIG_MODEL_HF150', 'RIG_MODEL_HF225', 'RIG_MODEL_HF235', 'RIG_MODEL_HF250', 'RIG_MODEL_HIQSDR', 'RIG_MODEL_HPSDR', 'RIG_MODEL_IC1271', 'RIG_MODEL_IC1275', 'RIG_MODEL_IC271', 'RIG_MODEL_IC2730', 'RIG_MODEL_IC275', 'RIG_MODEL_IC375', 'RIG_MODEL_IC471', 'RIG_MODEL_IC475', 'RIG_MODEL_IC575', 'RIG_MODEL_IC7000', 'RIG_MODEL_IC703', 'RIG_MODEL_IC705', 'RIG_MODEL_IC706', 'RIG_MODEL_IC706MKII', 'RIG_MODEL_IC706MKIIG', 'RIG_MODEL_IC707', 'RIG_MODEL_IC7100', 'RIG_MODEL_IC718', 'RIG_MODEL_IC7200', 'RIG_MODEL_IC725', 'RIG_MODEL_IC726', 'RIG_MODEL_IC728', 'RIG_MODEL_IC729', 'RIG_MODEL_IC7300', 'RIG_MODEL_IC731', 'RIG_MODEL_IC735', 'RIG_MODEL_IC736', 'RIG_MODEL_IC737', 'RIG_MODEL_IC738', 'RIG_MODEL_IC7410', 'RIG_MODEL_IC746', 'RIG_MODEL_IC746PRO', 'RIG_MODEL_IC751', 'RIG_MODEL_IC751A', 'RIG_MODEL_IC756', 'RIG_MODEL_IC756PRO', 'RIG_MODEL_IC756PROII', 'RIG_MODEL_IC756PROIII', 'RIG_MODEL_IC7600', 'RIG_MODEL_IC761', 'RIG_MODEL_IC7610', 'RIG_MODEL_IC765', 'RIG_MODEL_IC7700', 'RIG_MODEL_IC775', 'RIG_MODEL_IC7760', 'RIG_MODEL_IC78', 'RIG_MODEL_IC7800', 'RIG_MODEL_IC781', 'RIG_MODEL_IC785x', 'RIG_MODEL_IC820', 'RIG_MODEL_IC821H', 'RIG_MODEL_IC905', 'RIG_MODEL_IC910', 'RIG_MODEL_IC9100', 'RIG_MODEL_IC92D', 'RIG_MODEL_IC970', 'RIG_MODEL_IC9700', 'RIG_MODEL_ICF8101', 'RIG_MODEL_ICID1', 'RIG_MODEL_ICR10', 'RIG_MODEL_ICR20', 'RIG_MODEL_ICR30', 'RIG_MODEL_ICR6', 'RIG_MODEL_ICR7000', 'RIG_MODEL_ICR71', 'RIG_MODEL_ICR7100', 'RIG_MODEL_ICR72', 'RIG_MODEL_ICR75', 'RIG_MODEL_ICR8500', 'RIG_MODEL_ICR8600', 'RIG_MODEL_ICR9000', 'RIG_MODEL_ICR9500', 'RIG_MODEL_ICRX7', 'RIG_MODEL_IC_M700PRO', 'RIG_MODEL_IC_M710', 'RIG_MODEL_IC_M802', 'RIG_MODEL_IC_M803', 'RIG_MODEL_ID31', 'RIG_MODEL_ID4100', 'RIG_MODEL_ID51', 'RIG_MODEL_ID5100', 'RIG_MODEL_JST145', 'RIG_MODEL_JST245', 'RIG_MODEL_K2', 'RIG_MODEL_K3', 'RIG_MODEL_K3S', 'RIG_MODEL_K4', 'RIG_MODEL_KX2', 'RIG_MODEL_KX3', 'RIG_MODEL_LAB599_TX500', 'RIG_MODEL_MALACHITE', 'RIG_MODEL_MC4020', 'RIG_MODEL_MCHFQRP', 'RIG_MODEL_MDS4710', 'RIG_MODEL_MDS9710', 'RIG_MODEL_MICOM2', 'RIG_MODEL_MICROTUNE_4702', 'RIG_MODEL_MICROTUNE_4707', 'RIG_MODEL_MICROTUNE_4937', 'RIG_MODEL_MINISCOUT', 'RIG_MODEL_MINIVNA', 'RIG_MODEL_NETRIGCTL', 'RIG_MODEL_NONE', 'RIG_MODEL_NRD345', 'RIG_MODEL_NRD525', 'RIG_MODEL_NRD535', 'RIG_MODEL_NRD545', 'RIG_MODEL_OMNIVI', 'RIG_MODEL_OMNIVIP', 'RIG_MODEL_OS456', 'RIG_MODEL_OS535', 'RIG_MODEL_PARAGON2', 'RIG_MODEL_PCR100', 'RIG_MODEL_PCR1000', 'RIG_MODEL_PCR1500', 'RIG_MODEL_PCR2500', 'RIG_MODEL_PERSEUS', 'RIG_MODEL_PMR171', 'RIG_MODEL_PMSDR', 'RIG_MODEL_POWERSDR', 'RIG_MODEL_PRM8060', 'RIG_MODEL_PRM8070', 'RIG_MODEL_PRO2052', 'RIG_MODEL_PT8000A', 'RIG_MODEL_Q900', 'RIG_MODEL_QRPLABS', 'RIG_MODEL_QRPLABS_QMX', 'RIG_MODEL_QUISK', 'RIG_MODEL_R5000', 'RIG_MODEL_RA3702', 'RIG_MODEL_RA3710', 'RIG_MODEL_RA3720', 'RIG_MODEL_RA3790', 'RIG_MODEL_RA6790', 'RIG_MODEL_RS2005', 'RIG_MODEL_RS2006', 'RIG_MODEL_RS2035', 'RIG_MODEL_RS2041', 'RIG_MODEL_RS2042', 'RIG_MODEL_RS64', 'RIG_MODEL_RSHFIQ', 'RIG_MODEL_RX320', 'RIG_MODEL_RX331', 'RIG_MODEL_RX340', 'RIG_MODEL_RX350', 'RIG_MODEL_SDR1000', 'RIG_MODEL_SDR1000RFE', 'RIG_MODEL_SDRCONSOLE', 'RIG_MODEL_SDRSHARP', 'RIG_MODEL_SDRUNO', 'RIG_MODEL_SDU5000', 'RIG_MODEL_SDU5500', 'RIG_MODEL_SI570AVRUSB', 'RIG_MODEL_SI570PEABERRY1', 'RIG_MODEL_SI570PEABERRY2', 'RIG_MODEL_SI570PICUSB', 'RIG_MODEL_SMARTSDR_A', 'RIG_MODEL_SMARTSDR_B', 'RIG_MODEL_SMARTSDR_C', 'RIG_MODEL_SMARTSDR_D', 'RIG_MODEL_SMARTSDR_E', 'RIG_MODEL_SMARTSDR_F', 'RIG_MODEL_SMARTSDR_G', 'RIG_MODEL_SMARTSDR_H', 'RIG_MODEL_SR2200', 'RIG_MODEL_TCI1X', 'RIG_MODEL_THD72A', 'RIG_MODEL_THD74', 'RIG_MODEL_THD7A', 'RIG_MODEL_THD7AG', 'RIG_MODEL_THETIS', 'RIG_MODEL_THF6A', 'RIG_MODEL_THF7E', 'RIG_MODEL_THG71', 'RIG_MODEL_TMD700', 'RIG_MODEL_TMD710', 'RIG_MODEL_TMV7', 'RIG_MODEL_TMV71', 'RIG_MODEL_TRANSFOX', 'RIG_MODEL_TRC80', 'RIG_MODEL_TRP7000', 'RIG_MODEL_TRP8000', 'RIG_MODEL_TRP8255', 'RIG_MODEL_TRP9000', 'RIG_MODEL_TRUSDX', 'RIG_MODEL_TRXMANAGER_RIG', 'RIG_MODEL_TS140S', 'RIG_MODEL_TS2000', 'RIG_MODEL_TS440', 'RIG_MODEL_TS450S', 'RIG_MODEL_TS480', 'RIG_MODEL_TS50', 'RIG_MODEL_TS570D', 'RIG_MODEL_TS570S', 'RIG_MODEL_TS590S', 'RIG_MODEL_TS590SG', 'RIG_MODEL_TS680S', 'RIG_MODEL_TS690S', 'RIG_MODEL_TS711', 'RIG_MODEL_TS790', 'RIG_MODEL_TS811', 'RIG_MODEL_TS850', 'RIG_MODEL_TS870S', 'RIG_MODEL_TS890S', 'RIG_MODEL_TS930', 'RIG_MODEL_TS940', 'RIG_MODEL_TS950S', 'RIG_MODEL_TS950SDX', 'RIG_MODEL_TS990S', 'RIG_MODEL_TT516', 'RIG_MODEL_TT526', 'RIG_MODEL_TT538', 'RIG_MODEL_TT550', 'RIG_MODEL_TT565', 'RIG_MODEL_TT585', 'RIG_MODEL_TT588', 'RIG_MODEL_TT599', 'RIG_MODEL_USRP', 'RIG_MODEL_USRP0', 'RIG_MODEL_USRP_G', 'RIG_MODEL_V4L', 'RIG_MODEL_V4L2', 'RIG_MODEL_VR5000', 'RIG_MODEL_VX1700', 'RIG_MODEL_WJ8711', 'RIG_MODEL_WJ8888', 'RIG_MODEL_WR1000', 'RIG_MODEL_WR1500', 'RIG_MODEL_WR1550', 'RIG_MODEL_WR3100', 'RIG_MODEL_WR3150', 'RIG_MODEL_WR3500', 'RIG_MODEL_WR3700', 'RIG_MODEL_X108G', 'RIG_MODEL_X5105', 'RIG_MODEL_X6100', 'RIG_MODEL_X6200', 'RIG_MODEL_XG3', 'RIG_MODEL_XK2100', 'RIG_MODEL_XK852', 'RIG_MODEL_XPLORER', 'RIG_MODE_ALL', 'RIG_MODE_AM', 'RIG_MODE_AMN', 'RIG_MODE_AMS', 'RIG_MODE_BIT46', 'RIG_MODE_BIT47', 'RIG_MODE_BIT48', 'RIG_MODE_BIT49', 'RIG_MODE_BIT50', 'RIG_MODE_BIT51', 'RIG_MODE_BIT52', 'RIG_MODE_BIT53', 'RIG_MODE_BIT54', 'RIG_MODE_BIT55', 'RIG_MODE_BIT56', 'RIG_MODE_BIT57', 'RIG_MODE_BIT58', 'RIG_MODE_BIT59', 'RIG_MODE_BIT60', 'RIG_MODE_BIT61', 'RIG_MODE_BIT62', 'RIG_MODE_C4FM', 'RIG_MODE_CW', 'RIG_MODE_CWN', 'RIG_MODE_CWR', 'RIG_MODE_DCR', 'RIG_MODE_DD', 'RIG_MODE_DPMR', 'RIG_MODE_DSB', 'RIG_MODE_DSTAR', 'RIG_MODE_ECSS', 'RIG_MODE_ECSSLSB', 'RIG_MODE_ECSSUSB', 'RIG_MODE_FAX', 'RIG_MODE_FM', 'RIG_MODE_FMN', 'RIG_MODE_IQ', 'RIG_MODE_ISBLSB', 'RIG_MODE_ISBUSB', 'RIG_MODE_LSB', 'RIG_MODE_LSBD1', 'RIG_MODE_LSBD2', 'RIG_MODE_LSBD3', 'RIG_MODE_NONE', 'RIG_MODE_NXDNVN', 'RIG_MODE_NXDN_N', 'RIG_MODE_P25', 'RIG_MODE_PKTAM', 'RIG_MODE_PKTFM', 'RIG_MODE_PKTFMN', 'RIG_MODE_PKTLSB', 'RIG_MODE_PKTSSB', 'RIG_MODE_PKTUSB', 'RIG_MODE_PSK', 'RIG_MODE_PSKR', 'RIG_MODE_RTTY', 'RIG_MODE_RTTYR', 'RIG_MODE_SAH', 'RIG_MODE_SAL', 'RIG_MODE_SAM', 'RIG_MODE_SPEC', 'RIG_MODE_SSB', 'RIG_MODE_TESTS_MAX', 'RIG_MODE_USB', 'RIG_MODE_USBD1', 'RIG_MODE_USBD2', 'RIG_MODE_USBD3', 'RIG_MODE_WFM', 'RIG_MTYPE_BAND', 'RIG_MTYPE_CALL', 'RIG_MTYPE_EDGE', 'RIG_MTYPE_MEM', 'RIG_MTYPE_MEMOPAD', 'RIG_MTYPE_MORSE', 'RIG_MTYPE_NONE', 'RIG_MTYPE_PRIO', 'RIG_MTYPE_SAT', 'RIG_MTYPE_SPLIT', 'RIG_MTYPE_VOICE', 'RIG_MULTICAST_POLL', 'RIG_MULTICAST_SPECTRUM', 'RIG_MULTICAST_TRANSCEIVE', 'RIG_OK', 'RIG_OP_BAND_DOWN', 'RIG_OP_BAND_UP', 'RIG_OP_CPY', 'RIG_OP_DOWN', 'RIG_OP_FROM_VFO', 'RIG_OP_LEFT', 'RIG_OP_MCL', 'RIG_OP_NONE', 'RIG_OP_RIGHT', 'RIG_OP_TOGGLE', 'RIG_OP_TO_VFO', 'RIG_OP_TUNE', 'RIG_OP_UP', 'RIG_OP_XCHG', 'RIG_PARITY_EVEN', 'RIG_PARITY_MARK', 'RIG_PARITY_NONE', 'RIG_PARITY_ODD', 'RIG_PARITY_SPACE', 'RIG_PARM_AFIF', 'RIG_PARM_AFIF_ACC', 'RIG_PARM_AFIF_LAN', 'RIG_PARM_AFIF_WLAN', 'RIG_PARM_ANN', 'RIG_PARM_APO', 'RIG_PARM_BACKLIGHT', 'RIG_PARM_BANDSELECT', 'RIG_PARM_BAT', 'RIG_PARM_BEEP', 'RIG_PARM_KEYERTYPE', 'RIG_PARM_KEYLIGHT', 'RIG_PARM_NONE', 'RIG_PARM_SCREENSAVER', 'RIG_PARM_TIME', 'RIG_PORT_CM108', 'RIG_PORT_DEVICE', 'RIG_PORT_DTMF', 'RIG_PORT_GPIO', 'RIG_PORT_GPION', 'RIG_PORT_NETWORK', 'RIG_PORT_NONE', 'RIG_PORT_PACKET', 'RIG_PORT_PARALLEL', 'RIG_PORT_RPC', 'RIG_PORT_SERIAL', 'RIG_PORT_UDP_NETWORK', 'RIG_PORT_ULTRA', 'RIG_PORT_USB', 'RIG_POWER_OFF', 'RIG_POWER_ON', 'RIG_POWER_OPERATE', 'RIG_POWER_STANDBY', 'RIG_POWER_UNKNOWN', 'RIG_PTRX_AMPPORT', 'RIG_PTRX_AMPSTATE', 'RIG_PTRX_CACHE', 'RIG_PTRX_DCDPORT', 'RIG_PTRX_MAXIMUM', 'RIG_PTRX_NONE', 'RIG_PTRX_PTTPORT', 'RIG_PTRX_RIGPORT', 'RIG_PTRX_ROTPORT', 'RIG_PTRX_ROTPORT2', 'RIG_PTRX_ROTSTATE', 'RIG_PTRX_STATE', 'RIG_PTT_CM108', 'RIG_PTT_GPIO', 'RIG_PTT_GPION', 'RIG_PTT_NONE', 'RIG_PTT_OFF', 'RIG_PTT_ON', 'RIG_PTT_ON_DATA', 'RIG_PTT_ON_MIC', 'RIG_PTT_PARALLEL', 'RIG_PTT_RIG', 'RIG_PTT_RIG_MICDATA', 'RIG_PTT_SERIAL_DTR', 'RIG_PTT_SERIAL_RTS', 'RIG_RESET_MASTER', 'RIG_RESET_MCALL', 'RIG_RESET_NONE', 'RIG_RESET_SOFT', 'RIG_RESET_VFO', 'RIG_RPT_SHIFT_MINUS', 'RIG_RPT_SHIFT_NONE', 'RIG_RPT_SHIFT_PLUS', 'RIG_SCAN_DELTA', 'RIG_SCAN_MEM', 'RIG_SCAN_NONE', 'RIG_SCAN_PLT', 'RIG_SCAN_PRIO', 'RIG_SCAN_PROG', 'RIG_SCAN_SLCT', 'RIG_SCAN_STOP', 'RIG_SCAN_VFO', 'RIG_SETTING_MAX', 'RIG_SIGNAL_OFF', 'RIG_SIGNAL_ON', 'RIG_SIGNAL_UNSET', 'RIG_SPECTRUM_MODE_CENTER', 'RIG_SPECTRUM_MODE_CENTER_SCROLL', 'RIG_SPECTRUM_MODE_FIXED', 'RIG_SPECTRUM_MODE_FIXED_SCROLL', 'RIG_SPECTRUM_MODE_NONE', 'RIG_SPLIT_OFF', 'RIG_SPLIT_ON', 'RIG_STATUS_ALPHA', 'RIG_STATUS_BETA', 'RIG_STATUS_BUGGY', 'RIG_STATUS_STABLE', 'RIG_STATUS_UNTESTED', 'RIG_TARGETABLE_ALL', 'RIG_TARGETABLE_ANT', 'RIG_TARGETABLE_BAND', 'RIG_TARGETABLE_BANK', 'RIG_TARGETABLE_COMMON', 'RIG_TARGETABLE_FREQ', 'RIG_TARGETABLE_FUNC', 'RIG_TARGETABLE_LEVEL', 'RIG_TARGETABLE_MEM', 'RIG_TARGETABLE_MODE', 'RIG_TARGETABLE_NONE', 'RIG_TARGETABLE_PTT', 'RIG_TARGETABLE_PURE', 'RIG_TARGETABLE_RITXIT', 'RIG_TARGETABLE_ROOFING', 'RIG_TARGETABLE_SPECTRUM', 'RIG_TARGETABLE_TONE', 'RIG_TRN_OFF', 'RIG_TRN_POLL', 'RIG_TRN_RIG', 'RIG_TS_ANY', 'RIG_TYPE_OTHER', 'RIG_VFO_A', 'RIG_VFO_ALL', 'RIG_VFO_B', 'RIG_VFO_C', 'RIG_VFO_CURR', 'RIG_VFO_MAIN', 'RIG_VFO_MAIN_A', 'RIG_VFO_MAIN_B', 'RIG_VFO_MAIN_C', 'RIG_VFO_MEM', 'RIG_VFO_NONE', 'RIG_VFO_OTHER', 'RIG_VFO_RX', 'RIG_VFO_SUB', 'RIG_VFO_SUB_A', 'RIG_VFO_SUB_B', 'RIG_VFO_SUB_C', 'RIG_VFO_TX', 'RIG_VFO_TX_FLAG', 'RIG_VFO_VFO', 'ROT_FLAG_AZIMUTH', 'ROT_FLAG_ELEVATION', 'ROT_FUNC_BIT63', 'ROT_FUNC_NONE', 'ROT_LEVEL_63', 'ROT_LEVEL_FLOAT_LIST', 'ROT_LEVEL_NONE', 'ROT_LEVEL_READONLY_LIST', 'ROT_LEVEL_SPEED', 'ROT_MODEL_ANDROIDSENSOR', 'ROT_MODEL_APEX_SHARED_LOOP', 'ROT_MODEL_ARRAYSOLUTIONS_SAL_12_20_30', 'ROT_MODEL_CNCTRK', 'ROT_MODEL_DCU', 'ROT_MODEL_DUMMY', 'ROT_MODEL_EASYCOMM1', 'ROT_MODEL_EASYCOMM2', 'ROT_MODEL_EASYCOMM3', 'ROT_MODEL_ERC', 'ROT_MODEL_ETHER6', 'ROT_MODEL_F1TETRACKER', 'ROT_MODEL_FLIR', 'ROT_MODEL_FODTRACK', 'ROT_MODEL_GRBLTRK_NET', 'ROT_MODEL_GRBLTRK_SER', 'ROT_MODEL_GS23', 'ROT_MODEL_GS232', 'ROT_MODEL_GS232A', 'ROT_MODEL_GS232A_AZ', 'ROT_MODEL_GS232A_EL', 'ROT_MODEL_GS232B', 'ROT_MODEL_GS232B_AZ', 'ROT_MODEL_GS232B_EL', 'ROT_MODEL_GS232_GENERIC', 'ROT_MODEL_GS23_AZ', 'ROT_MODEL_HD1780', 'ROT_MODEL_IF100', 'ROT_MODEL_INDI', 'ROT_MODEL_IOPTRON', 'ROT_MODEL_LVB', 'ROT_MODEL_MEADE', 'ROT_MODEL_NETROTCTL', 'ROT_MODEL_NEXSTAR', 'ROT_MODEL_NONE', 'ROT_MODEL_PCROTOR', 'ROT_MODEL_PROSISTEL_COMBI_TRACK_AZEL', 'ROT_MODEL_PROSISTEL_D_AZ', 'ROT_MODEL_PROSISTEL_D_EL', 'ROT_MODEL_PROSISTEL_D_EL_CBOXAZ', 'ROT_MODEL_PSTROTATOR', 'ROT_MODEL_RADANT', 'ROT_MODEL_RC2800', 'ROT_MODEL_RC2800_EARLY_AZ', 'ROT_MODEL_RC2800_EARLY_AZEL', 'ROT_MODEL_RCI_AZ', 'ROT_MODEL_RCI_AZEL', 'ROT_MODEL_ROTORCARD', 'ROT_MODEL_ROTOREZ', 'ROT_MODEL_RT21', 'ROT_MODEL_SAEBRTRACK', 'ROT_MODEL_SARTEK1', 'ROT_MODEL_SATEL', 'ROT_MODEL_SATROTCTL', 'ROT_MODEL_SKYWATCHER', 'ROT_MODEL_SPID_MD01_ROT2PROG', 'ROT_MODEL_SPID_ROT1PROG', 'ROT_MODEL_SPID_ROT2PROG', 'ROT_MODEL_ST2', 'ROT_MODEL_TS7400', 'ROT_MODEL_YRC1', 'ROT_MOVE_CCW', 'ROT_MOVE_CW', 'ROT_MOVE_DOWN', 'ROT_MOVE_DOWN_CCW', 'ROT_MOVE_DOWN_CW', 'ROT_MOVE_DOWN_LEFT', 'ROT_MOVE_DOWN_RIGHT', 'ROT_MOVE_LEFT', 'ROT_MOVE_RIGHT', 'ROT_MOVE_UP', 'ROT_MOVE_UP_CCW', 'ROT_MOVE_UP_CW', 'ROT_MOVE_UP_LEFT', 'ROT_MOVE_UP_RIGHT', 'ROT_PARM_FLOAT_LIST', 'ROT_PARM_NONE', 'ROT_PARM_READONLY_LIST', 'ROT_RESET_ALL', 'ROT_SPEED_NOCHANGE', 'ROT_STATUS_BUSY', 'ROT_STATUS_LIMIT_DOWN', 'ROT_STATUS_LIMIT_LEFT', 'ROT_STATUS_LIMIT_RIGHT', 'ROT_STATUS_LIMIT_UP', 'ROT_STATUS_MOVING', 'ROT_STATUS_MOVING_AZ', 'ROT_STATUS_MOVING_DOWN', 'ROT_STATUS_MOVING_EL', 'ROT_STATUS_MOVING_LEFT', 'ROT_STATUS_MOVING_RIGHT', 'ROT_STATUS_MOVING_UP', 'ROT_STATUS_NONE', 'ROT_STATUS_OVERLAP_DOWN', 'ROT_STATUS_OVERLAP_LEFT', 'ROT_STATUS_OVERLAP_RIGHT', 'ROT_STATUS_OVERLAP_UP', 'ROT_TYPE_OTHER', 'TWIDDLE_OFF', 'TWIDDLE_ON', 'VFO_DUAL', 'cvar', 'hamlib_copyright', 'hamlib_version'] assert expected_properties == self.actual_properties @classmethod From c453cc788dda5decb553a90ed79c1b2324a38af9 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sun, 15 Jun 2025 19:53:41 +0200 Subject: [PATCH 42/45] Update README.developer --- README.developer | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/README.developer b/README.developer index 1c1a7c27c..bdca0f715 100644 --- a/README.developer +++ b/README.developer @@ -285,6 +285,7 @@ Optional, but highly recommended: * perl devel # h2xs * tcl devel # tcltk-depends * python devel # python-config +* pytest * lua devel * libxml2 devel # xml2-config --version * libgd2 devel # gdlib-config --version (rigmatrix) @@ -440,6 +441,46 @@ as above and once the run is complete: The resulting generated document in the 'latex' directory is 'refman.pdf'. +1.3.2 Automated tests + +Automated tests are executed running: + + make check + +The makefiles run the simple tests with automake. +The make variable TESTS contains the tests to be run and the variables +check_PROGRAMS and check_SCRIPTS contain the executables needed to run the +tests that aren't built by make all. +For more information see the automake manual at +https://www.gnu.org/software/automake/manual/html_node/Scripts_002dbased-Testsuites.html + +1.3.2.1 C tests + +Tests written in C are available in the tests/ directory. They are run with: + + make -C tests/ check + +1.3.2.2 Python tests with pytest + +Tests written in Python are available in the bindings/python directory if +Hamlib is configured to build the Python bindings and if pytest is installed, +eg.: + + ./configure --with-python-binding --enable-pytest + +They are run with: + + make -C bindings/ check + +The Python scripts consist in handwritten tests, meant to test realistic use +cases, and autogenerated tests, meant to detect unwanted changes in the +bindings. When a public symbol is added to the bindings or removed, the +autogenerated tests must be updated: + + make -C bindings/ generate-pytests + +and the handwritten tests should be updated to reflect the change. + 1.4. Feedback From 68633fa627088739b5bc6f50d6e3c99ff81cd76b Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sat, 21 Jun 2025 17:43:46 +0200 Subject: [PATCH 43/45] Add SWIG macros --- bindings/Makefile.am | 2 +- bindings/macros.swg | 92 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 bindings/macros.swg diff --git a/bindings/Makefile.am b/bindings/Makefile.am index 550b6d0eb..41b44a92a 100644 --- a/bindings/Makefile.am +++ b/bindings/Makefile.am @@ -9,7 +9,7 @@ AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/include -I$(top_srcdir)/bindings \ AM_CFLAGS = @AM_CPPFLAGS@ -fno-strict-aliasing AM_CXXFLAGS = -O2 -SWGFILES = hamlib.swg ignore.swg rig.swg rotator.swg amplifier.swg +SWGFILES = hamlib.swg ignore.swg rig.swg rotator.swg amplifier.swg macros.swg SWGDEP = \ $(top_srcdir)/include/hamlib/rig.h \ diff --git a/bindings/macros.swg b/bindings/macros.swg new file mode 100644 index 000000000..9f16b9f30 --- /dev/null +++ b/bindings/macros.swg @@ -0,0 +1,92 @@ +/* +Common SWIG macros +*/ + +/* + * Macro GET_TOKEN + * + * function_prefix: + * the first part of the function name (eg. one of: amp_ rig_ rot_) + * + * function_name: + * the name that will be seen in the bindings and that creates a valid Hamlib function + * name when appended to the function_prefix + * + * class_pointer: + * the pointer to the instance of the class (eg. one of self->amp self->rig self->rot) + */ +%define GET_TOKEN(function_prefix, function_name, class_pointer) +PyObject * ##function_name(hamlib_token_t token) +{ + int value; + + self->error_status = ##function_prefix ##function_name(##class_pointer, token, &value); + if (self->error_status != RIG_OK) + return Py_None; + + return PyLong_FromLong(value); +} +%enddef + +/* + * Macro GET_VALUE_T + * + * function_prefix: + * the first part of the function name (eg. one of: amp_ rig_ rot_) + * + * function_name: + * the name that creates a valid Hamlib function name when appended to the + * function_prefix + * + * class_pointer: + * the pointer to the instance of the class (eg. one of self->amp self->rig self->rot) + * + * level_prefix: + * the prefix of the macro that checks the datatype (eg. one of AMP_ RIG_ ROT_) + */ +%define GET_VALUE_T(function_prefix, function_name, class_pointer, level_prefix) +PyObject * ##function_name(hamlib_token_t token) +{ + value_t value; + + self->error_status = ##function_prefix ##function_name(##class_pointer, token, &value); + if (self->error_status != RIG_OK) + return Py_None; + +#if defined(##level_prefix LEVEL_IS_FLOAT) + if (##level_prefix LEVEL_IS_FLOAT(token)) + return PyFloat_FromDouble(value.f); +#endif + +#if defined(##level_prefix LEVEL_IS_STRING) + if (##level_prefix LEVEL_IS_STRING(token)) + return PyUnicode_FromString(value.s); +#endif + + return PyLong_FromLong(value.i); +} +%enddef + +/* + * Macro ROT_GET_LONG + * + * function_name: + * the name that will be seen in the bindings when appended to get_ + * and that creates a valid Hamlib function when appended to rot_get_ + * eg. ROT_GET_LONG(func) creates Rot.get_func() that calls rot_get_func() + */ +%define ROT_GET_LONG(function_name) + GET_TOKEN(rot_, get_ ##function_name, self->rot) +%enddef + +/* +* Macro ROT_GET_VALUE_T +* +* function_name: +* the name that will be seen in the bindings when appended to get_ +* and that creates a valid Hamlib function when appended to rot_get_ +* eg. ROT_GET_VALUE_T(level) creates Rot.get_level() that calls rot_get_level() +*/ +%define ROT_GET_VALUE_T(function_name) + GET_VALUE_T(rot_, get_ ##function_name, self->rot, ROT_) +%enddef From 93c16bcdd568e0e3fce550cd27ece193a85eea5c Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sat, 21 Jun 2025 22:30:36 +0200 Subject: [PATCH 44/45] Use the macros --- bindings/rotator.swg | 79 ++++++-------------------------------------- 1 file changed, 10 insertions(+), 69 deletions(-) diff --git a/bindings/rotator.swg b/bindings/rotator.swg index 205a20417..7cff51045 100644 --- a/bindings/rotator.swg +++ b/bindings/rotator.swg @@ -22,6 +22,7 @@ #include %} +%include macros.swg %immutable rot_caps::model_name; %immutable rot_caps::mfg_name; %immutable rot_caps::version; @@ -94,7 +95,6 @@ typedef struct Rot { ROTMETHOD2(set_ext_parm, hamlib_token_t, value_t) ROTMETHOD2(set_func, setting_t, int) - extern void get_func(setting_t func, int *OUTPUT); ROTMETHOD2(set_level, setting_t, value_t) @@ -119,6 +119,15 @@ typedef struct Rot { ROTMETHOD2(set_conf, hamlib_token_t, const_char_string) + ROT_GET_LONG(func) + ROT_GET_LONG(ext_func) + + ROT_GET_VALUE_T(level) + ROT_GET_VALUE_T(ext_level) + + ROT_GET_VALUE_T(parm) + ROT_GET_VALUE_T(ext_parm) + const char *get_conf(hamlib_token_t tok) { static char s[128] = ""; self->error_status = rot_get_conf(self->rot, tok, s); @@ -142,78 +151,10 @@ typedef struct Rot { return s; } - PyObject * get_ext_func(hamlib_token_t token) - { - int status; - - self->error_status = rot_get_ext_func(self->rot, token, &status); - if (self->error_status != RIG_OK) - return Py_None; - - return PyLong_FromLong(status); - } - - PyObject * get_ext_level(hamlib_token_t token) - { - value_t val; - - self->error_status = rot_get_ext_level(self->rot, token, &val); - if (self->error_status != RIG_OK) - return Py_None; - - return PyLong_FromLong(val.i); - } - - PyObject * get_ext_parm(hamlib_token_t token) - { - value_t val; - - self->error_status = rot_get_ext_parm(self->rot, token, &val); - if (self->error_status != RIG_OK) - return Py_None; - - return PyLong_FromLong(val.i); - } - - PyObject * get_level(setting_t level) - { - value_t val; - - self->error_status = rot_get_level(self->rot, level, &val); - if (self->error_status != RIG_OK) - return Py_None; - - if (ROT_LEVEL_IS_FLOAT(level)) - return PyFloat_FromDouble(val.f); - - return PyLong_FromLong(val.i); - } - - PyObject * get_parm(setting_t parm) - { - value_t val; - - self->error_status = rot_get_parm(self->rot, parm, &val); - if (self->error_status != RIG_OK) - return Py_None; - - if (ROT_PARM_IS_FLOAT(parm)) - return PyFloat_FromDouble(val.f); - - return PyLong_FromLong(val.i); - } - /* TODO: get_conf_list, .. */ }; %{ -/* - * this one returns 1 value - */ -void Rot_get_func(Rot *self, setting_t func, int *status) -{ - self->error_status = rot_get_func(self->rot, func, status); -} /* * this one returns 2 values, here is a perl example: From 66977a0f129ac18fe11ce0580d7a94ab8542db56 Mon Sep 17 00:00:00 2001 From: Daniele Forsi IU5HKX Date: Sat, 21 Jun 2025 21:27:37 +0200 Subject: [PATCH 45/45] Explain unexpected results --- bindings/python/test_rot.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/bindings/python/test_rot.py b/bindings/python/test_rot.py index ca885ba0f..f51ea46ce 100644 --- a/bindings/python/test_rot.py +++ b/bindings/python/test_rot.py @@ -57,13 +57,17 @@ class TestClass: assert rot.state.comm_state == 1 info = rot.get_info() assert isinstance(info, str) - assert rot.set_position(0.0, 0.0) is None - assert rot.get_position() == [0.0, 0.0] + assert rot.set_position(1.23, 4.56) is None + # When the Dummy rotator simulates movement, this test is too fast + # to see a changed position + assert rot.get_position() == [0.0, 0.0] # should be [1.23, 4.56] assert rot.move(0, 0) is None speed = 4 assert rot.move(Hamlib.ROT_MOVE_UP, speed) is None assert rot.move(Hamlib.ROT_MOVE_LEFT, speed) is None - assert rot.get_position() == [0.0, 0.0] # FIXME + # When the Dummy rotator simulates movement, this test is too fast + # to see a changed position + assert rot.get_position() == [0.0, 0.0] # should be [-90.0, 90.0] value = Hamlib.value_t() value.i = 3 assert rot.set_level(Hamlib.ROT_LEVEL_SPEED, value) is None @@ -86,16 +90,15 @@ class TestClass: assert rot.set_ext_parm(self.TOK_EP_ROT_MAGICPARM, value) is None assert rot.get_ext_parm(self.TOK_EP_ROT_MAGICPARM) == 7 + # Dummy rotator doesn't support functions status = 0 - assert rot.set_func(1, status) is None - assert rot.get_func(1) == status - status = 1 - assert rot.set_func(self.TOK_EL_ROT_MAGICFUNC, status) is None - assert rot.get_func(self.TOK_EL_ROT_MAGICFUNC) == 0 # FIXME should return status + assert rot.set_func(Hamlib.ROT_FUNC_NONE, status) is None + assert rot.get_func(Hamlib.ROT_FUNC_NONE) is None + # Dummy rotator doesn't support parameters value.i = 5 assert rot.set_parm(Hamlib.ROT_PARM_NONE, value) is None - assert rot.get_parm(Hamlib.ROT_PARM_NONE) is None # FIXME should Dummy support this? + assert rot.get_parm(Hamlib.ROT_PARM_NONE) is None assert rot.close() is None assert rot.state.comm_state == 0