ROTCTLD(1)
π ROTCTLD β the TCP rotator control daemon, bestie edition π
okay so picture this: rotctld is literally the group chat admin for your rotator π it's a rotator control daemon (from the Hamlib Utilities fam) that handles client requests over TCP sockets, so multiple user programs can share one rotator. yes queen, sharing is caring (though ngl that part needs more development, we're being honest here). and if you want multiple rotators? just run multiple rotctld processes on different TCP ports, slay. the command syntax is the same as rotctl(1), and the whole point is that it's especially useful for client authors writing in Perl, Python, PHP, and other languages. iykyk.
β¨ SYNOPSIS β¨
rotctld [-hlLuV] [-m id] [-r device] [-s baud] [-T IPADDR] [-t number]
[-C parm=val] [-v[-Z]]
π DESCRIPTION π
so rotctld talks to a client through a TCP socket using text commands shared with rotctl. the protocol is genuinely simple: commands get sent to rotctld on one line, and rotctld responds to "get" commands with the requested values, one per line, when it works. when it doesn't work? it responds with one line RPRT x, where 'x' is a negative number indicating the error code. commands that don't return values respond with the line RPRT x, where 'x' is 0 when successful, otherwise it's a negative number indicating the error code. every line is terminated with a newline \n character. this protocol is primarily for use by the NET rotctl (rotator model 2) backend. periodt.
then there's a whole separate Extended Response Protocol that extends the above behavior by echoing the received command string as a header, any returned values as a key: value pair, and the RPRT x string as the end of response marker which includes the Hamlib success or failure value. see the PROTOCOL section for details (coming in a later part, don't worry bestie). highkey consider using this protocol for clients that will interact with rotctld directly through a TCP socket.
keep in mind that Hamlib is BETA level software π¨ while a lot of backend libraries lack complete rotator support, the basic functions are usually well supported. it's giving "work in progress but make it cute".
please report bugs and provide feedback at the e-mail address given in the BUGS section below (that's a later part too, stay tuned π¦). patches and code enhancements sent to the same address are welcome β we love a contributor moment π
πΈ OPTIONS πΈ
this program follows the usual GNU command line syntax. short options that take an argument may have the value follow immediately or be separated by a space. long options starting with two dashes (-) require an = between the option and any argument. no cap.
here's the summary of the supported options, and yes i'm listing all of them because we don't skip:
-m,--model=idβ select rotator model number. see model list (userotctld -l). note:rotctl(or third party software using the C API) will use rotator model 2 for NET rotctl β this model number is not used forrotctldeven though it shows in the model list. pls don't get confused π-r,--rot-file=deviceβ use device as the file name of the port connected to the rotator. often a serial port, but could be a USB to serial adapter. typically/dev/ttyS0,/dev/ttyS1,/dev/ttyUSB0, etc. on Linux,COM1,COM2, etc. on MS Windows. the BSD flavors and Mac OS/X have their own designations, so see your system's documentation bestie π«Ά-s,--serial-speed=baudβ set serial speed to baud rate. uses maximum serial speed from rotator backend capabilities as the default β¨-T,--listen-addr=IPADDRβ use IPADDR as the listening IP address. the default isANY.rotctldcan be run and connected to like this:
rotctld (binds to all interfaces)
rotctl -m 2
rotctl -m 2 -r 127.0.0.1
rotctl -m 2 -r localhost
rotctl -m 2 -r 192.168.1.1 (local IP address)
rotctl -m 2 -r ::1 (on Linux rotctld doesn't listen on IPV6 by default)
rotctld -T 127.0.0.1 (bind only to 127.0.0.1)
rotctl -m 2 (binds to all interfaces)
rotctl -m 2 -r 127.0.0.1 (bind only to 127.0.0.1)
-t,--port=numberβ use number as the TCP listening port. the default is4533. note: asrotctld's default port is4533, it is advisable to use odd numbered ports forrotctld, e.g.4533,4535,4537, etc. odd numbers are the vibe π₯-L,--show-confβ list all configuration parameters for the rotator defined with-mabove π-C,--set-conf=parm=val[,parm=val]β set rotator configuration parameter(s), e.g.stop_bits=2. use the-Loption above for a list of configuration parameters for a given model number.-u,--dump-stateβ dump state for the rotator defined with-mabove and exit.-u,--dump-capsβ dump capabilities for the rotator defined with-mabove and exit.
yes bestie, -u shows up twice in the original β that's literally how it's written and i am not about to edit the source material. just a lil' manpage folklore for you π
-l,--listβ list all rotator model numbers defined in Hamlib and exit. the list is sorted by model number. note: in Linux the list can be scrolled back using Shift-PageUp/Shift-PageDown, or using the scrollbars of a virtual terminal in X or the cmd window in Windows. the output can be piped tomore(1)orless(1), e.g.rotctl -l | moreπ§-v,--verboseβ set verbose mode, cumulative (see DIAGNOSTICS below, later part, patience bb).-Z,--debug-time-stampsβ enable time stamps for the debug messages. use only in combination with the-voption as it generates no output on its own π-h,--helpβ show a summary of these options and exit.-V,--versionβ show version ofrotctldand exit.
note: some options may not be implemented by a given backend and will return an error. this is most likely to occur with the--set-confand--show-confoptions. not every model ate, and that's just the tea π΅
also be aware: the backend for the rotator to be controlled, or the rotator itself, may not support some commands. in that case, the operation will fail with a Hamlib error code. it's giving "tried my best, error code incoming" π
okay that's part one mwah π more sections incoming, don't go anywhere β SEE ALSO, PROTOCOL, DIAGNOSTICS, BUGS, and the rest are all still coming your way. you got this bestie π
β¨ COMMANDS β¨
okay bestie, so here's the tea on how you actually talk to this thing π«Ά Commands go over the TCP socket in one of two ways: either as a single char, or as a long command name plus the value(s) β space separated, all on one '\n'-terminated line. Go check PROTOCOL for the full deets.
Since basically every Hamlib operation has a set method and a get method, they keep it cute and simple: an upper case letter = the set method, and the matching lower case letter = the get method. Every operation also has a long name, and to send that long name you just prepend a backslash, '\'. Iconic. π
Example (Perl): print $socket "\\dump_caps\n"; β this shows you what the rotator's backend can actually do.
β οΈ Note: in Perl and a bunch of other languages, a'\'needs to be escaped with a preceding'\', so even though two backslash characters show up in the code, only one gets passed torotctld. This is a possible bug, beware! π
Also important: the backend for the rotator you're controlling β or the rotator itself β might not support some commands. When that happens, the operation just fails with a Hamlib error message. No cap. π
Here's the full rundown of supported commands. For set commands, the quoted italicized string gets replaced by the value in the description. For get commands, the quoted italicized string is the key name of the value returned. β¨
P,set_pos'Azimuth' 'Elevation' β Set the position. 'Azimuth' and 'Elevation' are floating point values. For example (typed text shown in bold):P 163.0 41.0. Note: if the rotator doesn't support setting elevation (most do not), supply"0.0"for 'Elevation'.p,get_posβ Get the position. 'Azimuth' and 'Elevation' come back as double precision floating point values.M,move'Direction' 'Speed' β Move the rotator in a specific direction at the given rate. 'Direction' is an integer or keyword, defined as:'2'= UP,'4'= DOWN,'8'= LEFT or CCW,'16'= RIGHT or CW,'32'= UP_LEFT or UP_CCW,'R64'= UP_RIGHT = UP_CW,'128'= DOWN_LEFT or DOWN_CCW,'256'= DOWN_RIGHT or DOWN_CW. 'Speed' is an integer between1and100, and you use-1for no change to the current speed. Note: not all backends that implement the move command actually use the Speed value. π€·S,stopβ Stop the rotator. periodt.K,parkβ Park the rotator. π ΏοΈC,set_conf'Token' 'Value' β Set a configuration parameter. 'Token' is a string β peep the-Coption and the-Loutput. 'Value' is a string of up to20characters.R,reset'Reset' β Reset the rotator. 'Reset' accepts an integer value of'1'for "Reset All"._,get_infoβ Get miscellaneous info about the rotator. Returns 'Info' "Model Name".dump_stateβ Return certain state information about the rotator backend.1,dump_capsβ Not a real rot remote command, it just dumps capabilities, i.e. what the backend knows about this model, and what it can do. π§w,send_cmd'Cmd' β Send a raw command string straight to the rotator. ASCII CR gets appended automatically at the end of the command for text protocols. For binary protocols, enter hexadecimal values as"\0xAA\0xBB". π₯
π Locator Commands π
These commands are all about the conversions, bestie β Degrees Minutes Seconds to other formats, Maidenhead square locator conversions, and distance + azimuth conversions. It's giving math but make it cute. π¦
L,lonlat2loc'Longitude' 'Latitude' 'Loc Len' β Returns the Maidenhead 'Locator' for the given 'Longitude' and 'Latitude'. 'Longitude' and 'Latitude' are floating point values. 'Loc Len' is the precision of the returned square and should be an even numbered integer value between2and12. For example:
L -170.0 -85.0 12
returns:
Locator: AA55AA00AA00
l,loc2lonlat'Locator' β Returns 'Longitude' and 'Latitude' in decimal degrees at the approximate center of the requested Maidenhead grid square. 'Locator' can be from2to12characters in length. West longitude is expressed as a negative value. South latitude is expressed as a negative value. For example:
l AA55AA00AA00
returns:
Longitude: -169.999983 Latitude: -84.999991
β οΈ Note: despite the use of double precision variables internally, some rounding error occurs. π
D,dms2dec'Degrees' 'Minutes' 'Seconds' 'S/W' β Returns 'Dec Degrees', a signed floating point value. 'Degrees' and 'Minutes' are integer values. 'Seconds' is a floating point value. 'S/W' is a flag where'1'means South latitude or West longitude, and'0'means North or East β the flag is needed because computers don't recognize a signed zero, even though only the 'Degrees' value is typically signed in DMS notation. computers really said "signed zero? never heard of her" πd,dec2dms'Dec Degrees' β Returns 'Degrees' 'Minutes' 'Seconds' 'S/W'. Values are as indms2decabove.E,dmmm2dec'Degrees' 'Dec Minutes' 'S/W' β Returns 'Dec Degrees', a signed floating point value. 'Degrees' is an integer value. 'Dec Minutes' is a floating point value. 'S/W' is a flag as indms2decabove.e,dec2dmmm'Dec Deg' β Returns 'Degrees' 'Minutes' 'S/W'. Values are as indmmm2decabove.B,qrb'Lon 1' 'Lat 1' 'Lon 2' 'Lat 2' β Returns 'Distance' and 'Azimuth'. 'Distance' is in km. 'Azimuth' is in degrees. The supplied Lon/Lat values are signed floating point numbers.A,a_sp2a_lp'Short Path Deg' β Returns 'Long Path Deg'. Both the supplied argument and the returned value are floating point values within the range of0.00to360.00.
β οΈ Note: supplying a negative value will return an error message. π
a,d_sp2d_lp'Short Path km' β Returns 'Long Path km'. Both the supplied argument and the returned value are floating point values.pause'Seconds' β Pause for the given whole (integer) number of 'Seconds' before sending the next command to the rotator. self care bestie, sometimes you just gotta wait βΈοΈβ¨
π PROTOCOL π
okay so rotctld speaks two protocols, bestie: the Default Protocol and the Extended Response Protocol. β¨
The Default Protocol is mainly for when Hamlib library functions talk to rotctld β aka βNET rotctlβ, which you get with rotator model 2. It's giving built-in C API energy, no cap. π«Ά
The Extended Response Protocol is for scripts and other programs that are talking directly to rotctld, because it gives you consistent feedback. So if you want receipts, this is the one. π
π Default Protocol π
The Default Protocol is intentionally simple, like it woke up and chose minimalism. Commands go in on a single line with whatever values are needed. In practice, you get reliable results by ending each command string with a newline character, \n. β¨
Example set position (Perl code):
print $socket "P 135 10\n";
or:
print $socket "\\set_pos 135 10\n"; # escape leading β\β
A one-line response gets sent as a reply to set commands: RPRT x\n, where x is the Hamlib error code, and 0 means the command succeeded. Slay. β
Responses from rotctld get commands are text values and match the same tokens used in the set commands. Each value comes back on its own line. If there's an error, the string RPRT x\n is returned, where x is the Hamlib error code. π
Example get position (Perl code):
print $socket "p\n";
"135"
"10"
Most get functions return one to three values. A notable exception is the dump_caps command, which returns many lines of key:value pairs. It's giving overachiever. π
This protocol is primarily used by the βNET rotctlβ (rotctl model 2) backend, which lets applications already written for Hamlib's C API take advantage of rotctld without the need of rewriting application code. An application's user can select rotator model 2 (βNET rotctlβ) and then set rot_pathname to localhost:4533 or another network host:port (set by the -T/-t options, respectively, above). Iconic behavior. π
β¨ Extended Response Protocol β¨
The Extended Response Protocol adds several rules to the strings returned by rotctld and adds a rule for the command syntax. So it's the Default Protocol but with more structure, more drama, more receipts. π
- The command received by rotctld is echoed with its long command name followed by the value(s) (if any) received from the client, terminated by the specified response separator, as the first record of the response.
- The last record of each block is the string
RPRT x\n, wherexis the numeric return value of the Hamlib backend function that was called by the command. - Any records consisting of data values returned by the rotator backend are prepended by a string immediately followed by a colon, then a space, and then the value terminated by the response separator β e.g.
Azimuth: 90.000000\nwhen the command was prepended by+. - All commands received will be acknowledged by rotctld with records from rules 1 and 2. Records from rule 3 are only returned when data values must be returned to the client.
An example response to a P command sent from the shell prompt (note the prepended +):
$ echo "+P 90 45" | nc -w 1 localhost 4533
set_pos: 90 45
RPRT 0
In this case, the long command name and values are returned on the first line, and the second line contains the end-of-block marker and the numeric rotor backend return value indicating success. Periodt. β
An example response to a get_pos query:
$ echo "+\get_pos" | nc -w 1 localhost 4533
get_pos:
Azimuth: 90.000000
Elevation: 45.000000
RPRT 0
Note: The \ is still required for the long command name even with the ERP character. Don't forget it, bestie. π«Ά
In this case, as no value is passed to rotctld, the first line consists only of the long command name. The final line shows that the command was processed successfully by the rotor backend. π
Invoking the Extended Response Protocol requires prepending a command with a punctuation character. As shown in the examples above, prepending a + character to the command results in the responses being separated by a newline character (\n). Any other punctuation character recognized by the C ispunct() function except \, ?, or _ will cause that character to become the response separator and the entire response will be on one line. Wild, but make it fashion. π
Separator character summary:
+β Each record of the response is appended with a newline (\n).;,|, or,,β Each record of the response is appended by the given character, resulting in the entire response on one line. These are common record separators for text representations of spreadsheet data, etc.?β Reserved for help in rotctl._β Reserved forget_infoshort command#β Reserved for comments when reading a command file script.
Note: Other punctuation characters have not been tested! Use at your own risk. β οΈ
For example, invoking a get_pos query with a leading ; returns:
get_pos:;Azimuth: 90.000000;Elevation: 45.000000;RPRT 0
Or, using the pipe character | returns:
get_pos:|Azimuth: 90.000000|Elevation: 45.000000|RPRT 0
And a set_pos command prepended with a | returns:
set_pos: 135 22.5|RPRT 0
Such a format will allow reading a response as a single event using a preferred response separator. Other punctuation characters have not been tested! π
All commands with the exception of set_conf have been tested with the Extended Response protocol and the included testrotctld.pl Perl script. So set_conf is the one who didn't show up to the group project, but that's on period. π
π©Ί DIAGNOSTICS π©Ί
The -v, --verbose option allows different levels of diagnostics to be output to stderr and correspond to -v for BUG, -vv for ERR, -vvv for WARN, -vvvv for VERBOSE, or -vvvvv for TRACE. So you can choose your own adventure, but make it logs. π
A given verbose level is useful for providing needed debugging information to the email address below. For example, TRACE output shows all of the values sent to and received from the radio, which is very useful for radio backend library development and may be requested by the developers. They love a good trace. π
πΈ EXAMPLES πΈ
Start rotctld for a Hy-Gain Ham IV rotor with the Idiom Press RotorEZ board installed using a USB-to-serial adapter and backgrounding:
$ rotctld -m 401 -r /dev/ttyUSB1 &
Start rotctld for RotorEZ using COM2 on Win32:
> rotctld -m 401 -r COM2
Connect to the already running rotctld, and set position to 135.0 degrees azimuth and 30.0 degrees elevation with a 1 second read timeout from the shell prompt:
$ echo "\set_pos 135.0 30.0" | nc -w 1 localhost 4533
Connect to a running rotctld with rotctl on the local host:
$ rotctl -m 2
π SECURITY π
No authentication whatsoever; DO NOT leave this TCP port open wide to the Internet. Please ask if stronger security is needed or consider using a Secure Shell (ssh(1)) tunnel. Protect your rotator, bestie. π‘οΈ
As rotctld does not need any greater permissions than rotctl, it is advisable to not start rotctld as βrootβ or another system user account in order to limit any vulnerability. Stay humble, stay unprivileged. π
π BUGS π
The daemon is not detaching and backgrounding itself. π
No method to exit the daemon, so the kill(1) command must be used to terminate it. It's giving unhinged, but okay. π
Multiple clients using the daemon may experience contention with the connected rotator. Sharing is caring, but it's also chaos. π
Report bugs to:
Hamlib Developer mailing list
π COPYING π
This file is part of Hamlib, a project to develop a library that simplifies radio, rotator, and amplifier control functions for developers of software primarily of interest to radio amateurs and those interested in radio communications. π
Copyright Β© 2000-2009 Stephane Fillod Copyright Β© 2000-2018 the Hamlib Group (various contributors) Copyright Β© 2011-2020 Nate Bargmann
This is free software; see the file COPYING for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. No cap. π«Ά
π SEE ALSO π
kill(1), rotctl(1), ssh(1), hamlib(7)
π COLOPHON π
Links to the Hamlib Wiki, Git repository, release archives, and daily snapshot archives are available via hamlib.org. Go explore, bestie. π¦
That's the whole vibe! This is from Hamlib, dated 2020-09-09, and it's the ROTCTLD(1) manual. Mwah π
π¦ where this page comes from
- alpine 3.24: hamlib-doc 4.7.1-r0 Β· LGPL-2.0-or-later
- arch rolling: hamlib 4.7.2-2 Β· GPL-2.0-or-later AND LGPL-2.0-or-later
- nixos 26.05: hamlib 4.7.2
- nixpkgs unstable: hamlib 4.7.2
- opensuse-leap 16.0: hamlib 4.7.2-bp160.1.1 Β· LGPL-2.1-only
- opensuse-leap 16.0: hamlib 4.7.2-bp160.1.1 Β· LGPL-2.1-only
- opensuse-leap 16.0: hamlib 4.7.2-bp160.1.1 Β· LGPL-2.1-only
- opensuse-leap 16.0: hamlib 4.7.2-bp160.1.1 Β· LGPL-2.1-only
- ubuntu stonking: libhamlib-utils 4.7.2-2 Β· LGPL-2.1-or-later AND GPL-2.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms