Tech!

Kplex Home
Overview
Install
Config
Download
Changelog
Issues
Examples
top border

Kplex Configuration

Invocation

kplex -V | [-d 1..9] [-f <filename>] [-p <pidfile;>] [-o <option>] <interface> <interface> [<interface> ...]

Where:
The "-d" flag, if specified, will cause kplex to print debugging information, the verbosity of which is controlled by the flag's argument with "1" producing minimal additional debugging information and "9" producing verbose debug information.

<filename> is the path of a configuration file to use where default options and interfaces are defined. If not specified, kplex will look for its configuration in the following locations and use the first file found:

  • A location specified in the KPLEXCONF environment variable
  • OSX Only~/Library/Preferences/kplex.ini. This location is for backwards compatibility, will not be supported in the next major release and its use is discouraged.
  • OSX Only~/Library/Preferences/kplex.conf
  • ~/.kplex.conf
  • /etc/kplex.conf
Specifying filename as "-" disables looking for the default configuration files.

<pidfile> is the path of a file where kplex will write its pid for the convenience of mechanisms such as init files used to control system processes. If this option is specified and kplex finds that <pidfile> is locked by another process it will print a warning and exit.

<option> is an option specifier for the form:
<variable>=<value>
These correspond to configuration options which may otherwise be specified in "global" section of the configuration file (discussed in the Configuration File section below). Command line configuration options always override options given in the configuration file.

<interface> is an interface specifier which takes the form:

  • <interface_type>:<option>[,<option> ...] where:
    • <interface_type> is one of:
      • "serial": serial nmea 0183 data
      • "file": file (or standard in/out)
      • "tcp": nmea over TCP
      • "udp": nmea over UDP (unicast/broadcast/multicast)
      • "broadcast": nmea over UDP broadcast (DEPRECATED)
      • "bcast": synonym for "broadcast" (DEPRECATED)
      • "multicast": nmea over UDP multicast (DEPRECATED)
      • "mcast": synonym for "multicast" (DEPRECATED)
      • "pty": serial nmea data over a pseudo terminal
      • "gofree": nmea over TCP announced by Navico's "GoFree" protocol
    • <option> is one or more options of the form <var>=<val>. Some options are not optional. Options applicable to all interface types are:
      • "direction": May normally be one of "in" specifying an input, "out" specifying an output, or "both" specifying a bi-directional interface. Not all directions are applicable to all interface types. The default is "both" if an interface type permits bi-directional communication. It is more efficient to specify "in" or "out" if that is all an interface needs to do.
      • "qsize": Size of the interface's output queue. Not used for input only interfaces. Defaults should be fine. This should only need to be increased from default in the case of a bursty high-speed input feeding a slow ouput.
      • "checksum": Overrides the global checksum option for an interface. If set to "no", no checksum checks are performed on incoming sentences. If set to "yes" or "strict", incoming sentences without correct checksums are discarded. If set to "loose", sentences with incorrect checksums are discarded but those without any checksum are permitted. If set to "add", sentences with incorrect checksums are discarded but where no checksum is present, one will be added. If set to "addonly", a checksum will be added if absent but sentences with incorrect checksums are accepted. With "add" and "addonly", sentences without checksums are discarded if the addition of a checksum would exceed the maximum permitted sentence length.
      • "strict": May be "yes" to enable strict parsing of incoming sentences on an interface or "no" to disable it. This option overrides the global strict parsing option.
      • "loopback": May be "yes" to enable sentences read from an interface to be written back to it when communication is bi-directional or "no" (the default) to ensure sentences are not looped back to the interface they were read from. This option should be used with extreme caution and generally not at all with broadcast or multicast interfaces. This option has no effect on unidirectional interfaces.
      • "ifilter": Specifies an input filter (see below)
      • "ofilter": Specifies an output filter (see below)
      • "name": Attaches a symbolic name to an interface. This is only required if you intend to use the interface for failover (see below) but can be helpful for debugging. The value associated with "name" can be any string consisting of letters and or numbers which is not used as the "name" for another interface. If no "name" is assigned kplex will autogenerate one starting with an underscore ('_'). For this reason names starting with an underscore should not be manually assigned. Names are NOT case sensitive, so do not call one interface "Serial" and another "serial".
      • "srctag": Specifies that an NMEA-0183v4 TAG block containing a source identifier be prepended to sentences output on the interface if the value is "yes" or "input". The src identification string is the interface name (see the "name" option above) truncated to 15 characters or the string "kplex" if the interface name starts with an underscore as is the case with autogenerated (non-user-specified) names. A TAG block prepended by the "srctag=yes" option looks like: \s:kplex*23\ If "srctag=no" is specified, no source identifier is prepended. This is the default.
        If "srctag=input" is specified, the src identification string is the name of the interface on which the sentence arrived truncated to 15 characters or the string "kplex" if no "name" is specified for the input interface.
      • "timestamp": Specifies that an NMEA-0183v4 TAG block containing UNIX time (for example "\c:1423133110*5C\" should be prepended to sentences output on the interface. The timestamp is in seconds if the value is "s" or milliseconds if the value is "ms". Note that NMEA-0183v4 timestamps do not take account of leap seconds.
      • "optional": If "optional=no" is specified or this option is not given, kplex will exit if it cannot initialize the interface. If "optional=yes" is specified, failure of the interface to initialize will only cause kplex to exit if, as a result of it failing, kplex has no inputs or no outputs.
      • "heartbeat": Specifies that kplex should send a proprietary sentence from the interface with a frequency specified as the option's value in seconds, i.e. "heartbeat=60" will send a sentence every minute. Other instances of kplex will not further propagate these "heartbeats". This option is not valid on input-only interfaces.

      If source identifier and timestamps are both requested for an interface, they are combined into a single TAG block, source identifier first, e.g.: \s:kplex,c:1423133048*5F\

The -V flag instructs kplex to print its version number and exit. It should not be used with any other options.

Interface Types

Serial Interfaces

This is the traditional way of getting nmea data into your computer. kplex doesn't care whether your device is connected to via a traditional serial port or via a USB to serial converter so long as the device on which data are presented looks like a character special device and it can be configured with baud rate and a minimal set of other parameters. Note that you can't normally just plug your nmea tx/rx into a serial port. NMEA is RS422 whereas serial ports normally want RS232 input.

Interface-specific options:

  • filename=<device>
  • baud=<baud>
Where
  • <device> is the serial device (e.g. /dev/ttyS0)
  • <baud> is the baud rate. Defaults to 4800 if unspecified. Supported baud rates are: 4800, 9600, 19200, 38400, 57600, 115200, 230400 and 460800
You must minimally specify a device name for a serial interface. usb to serial converters often use /dev/ttyUSB0. Check your /var/adm/messages file and/or udev rules. Note that normal users are often not permitted to open serial devices. This may mean adding your user to a group which *is* allowed to read the device (e.g. "dialout", "uucp" or whatever).

"File" interfaces

This specification covers regular files, FIFOs and terminal i/o via standard input and standard output.

Interface-specific options:

  • filename=<file>
  • filenamex=<format>
  • persist=[yes|no]
  • append=[yes|no]
  • eol=[rn|n]
  • owner=<user>
  • group=<group>
  • perm=<permissions>
Where
  • <file> is either the file name to read from or write to or "-". In the latter case, standard input is used for inputs, standard out for outputs, and standard in and standard out for "BOTH". If not specified defaults to "-".
  • <format> is either "-", which is treated as in the "file" case above, or a format string from which a filename is constructed. The format string substitues variables preceded by the "%" haracter per the strftime(3) library call. Additionally, format strings in the format %{<keyword>} are substituted for the following values of <keyword>
    • "host". The hostname of the host on which kplex is running.
  • <user> is the user to set ownership of a created output file to.
  • <group> is the group to set a created output file to.
  • <permissions> are the file access permissions, in octal form, to set a created output file to.
"File" interfaces are slightly different from other interfaces in that by default sentences are terminated by <LF> rather than <CR><LF>. Because this is *nix and we don't want to muck about with redundant '\r's. Uniquely for "file" interfaces "loose" termination checking is default on input. Sentences input with just a terminating '\n' (ie <LF>) are converted to <CR><LF> for output to other interface types (i.e. serial, tcp, broadcast etc.).

If the option "eol=rn" is specified, file interfaces will output sentences terminated by <CR><LF>. Input sentences will be discarded if they are terminated with <LF> not preceded by <CR> and will not have additional <CR>s added.

"eol=n" specifies that the default behaviour for file interfaces (<LF> only as sentence delimiter) should be used.

"BOTH" is not supported as an I/O direction for the "file" type except for standard in / standard out.

If no "filename" option is given, standard in/out are used.

If "append=yes" is specified for an interface outputting to a regular file, output is appended to the file. If "append=no" (the default) is specified, the file will be truncated before output is written. This option may not be specified for input files, FIFOs or terminals.

"persist=yes" may only be specified on an interface connected to a FIFO. If specified it will re-open a FIFO when the reader or writer at the other end closes the pipe. If "persist=no" (the default) is specified, an input interface will exit on receipt of EOF. An output interface will exit when the reader at the other end of the pipe exits.

FIFOs block on open for read until something opens the FIFO for writing, and block on open for write until something opens them for reading. To avoid hanging kplex's initialisation thread, opening of FIFOs is delayed until individual reader and writer threads have been created. Output to file interfaces is line buffered.

For output to regular files, if the specified filename does not exist it will be created if permissions allow. If kplex creates an output file, it will be owned by the user of the kplex process unless the "owner=" option is specified, in which case the file's ownership will be set to the specified username. On most systems, kplex can only set username to something other than the owner of the kplex process when run as root. The group of an output file created by kplex will be set to the kplex process's primary group unless the "group=" option is specified in which case the file's group will be set to the specified group. The group must exist and the kplex process must have permission to set a file to that group. Normally this requires the kplex process's owner to be a member of the specified group. An output file created by kplex is normally readable and writable by user and group and readable by "other", modified by the user's umask. If "perm=" is specified, the permissions on a file created by kplex are set to the option's argument in octal *unmodified* by the processes's umask. Thus "perm=0666" will make the file readable and writable by user, group and other regardless of the kplex process's umask.

For output files which pre-exist and for all input files, the user,group and perm options are ignored.

TCP Interfaces

kplex can act either as a tcp server (allowing other programs on the same or other machines to connect to it) or as a tcp client, connecting to servers on the same or other systems. In "client" mode, kplex will attempt to connect to the server running on the port and address you specify. This may be a kplex tcp server interface or a commercial product, such as an nmea to wifi interface box. You must specify an ip address (IPv4 and IPv6 supported) for a tcp client connection. You may specify a port. If not specified, the port used will be the one your system associates with "nmea-0183", or the IANA assigned 10110 if your system doesn't know about "nmea-0183". If using kplex, the server port defaults to 10110. Consult manufacturer's documentation for the port to use for other products.

In Server mode, kplex listens for incoming connections. These may be from programs like iNavX or other instances of kplex. No data flows until a connection is made. kplex can accept many client connections simultaneously. The exact number will be system dependent but it will certainly be "enough".

Interface-specific options:

  • mode=<mode>
  • address=<address>
  • port=<port>
  • persist=[yes|no|fromstart]
  • retry=<seconds>
  • preamble=<preamble>
  • gpsd=[yes|no]
  • timeout=<timeout>
  • sndbuf=<sndbuf>
  • nodelay=[yes|no]
  • keepalive=[yes|no]
  • keepidle=<keepidle>
  • keepintvl=<keepinterval> ( Not Mac OS X < 10.9 )
  • keepcnt=<count> ( Not Mac OS X < 10.9 )
Where:
  • <mode> is either "server" or "client". If not specified, defaults to "client".
  • <address> is the server address to bind to for output interfaces and the remote tcp server to connect to for inputs. This can be:
    • A symbolic hostname (which must be resolvable on the host)
    • An IPv4 address in dotted decimal format
    • An IPv6 address
    For input interfaces, a remote host MUST be specified. For outputs, if address is not specified, or specified as "-" a wildcard address will be used and the server run on all available interfaces. Whether this is IPv4 only or IPv4 and IPv6 will depend on system configuration. IPv6 can be forced (if your system supports it) using a wildcard address of "0::0". An IPv6 server can accept IPv4 connections on a dual stacked host. You can happily ignore all mention of IPv6 if you want to. The address, if specified for an output, must correspond to one assigned to a interface on the host
  • <port> is the tcp port to run the server on. If not specified, defaults to the tcp port returned by a lookup of the service "nmea-0183" and if that fails the IANA assigned port for nmea-0183 10110 is used.
  • <seconds> is the number of seconds Default 5) to wait before each attempt at reconnecting a lost tcp connection. The "retry" option is only valid in conjunction with "persist=yes" or "persist=fromstart"
  • <preamble> is a string of characters to send after connecting to a remote server and before sending data, as described below.
  • <timeout> is the number of seconds to wait for an output operation to complete before assuming a connection has died, abandoning the data send operation and attempting to reconnect the interface. Only valid with output or bi-directional interfaces and only in conjunction with "persist=yes" or "persist=fromstart". Note that timeouts will not occur while data can still be passed to TCP, so the size of TCP buffers has an impact on how quickly a hung connection will be timed out.
  • <bufsize> is the size in bytes to set the TCP output buffer to. This option is valid only with "persist=yes" or "persist=fromstart" and defaults to 2048. Without "persist=yes" or "persist=fromstart" system default TCP buffer size is used. A buffer size of 2k should not negatively impact performance in this application. A smaller output buffer size generally results in hung output connections being detected faster.
  • <keepidle> is the number of seconds of inactivity on a tcp connection to wait before sending the first keepalive probe (see below). Only valid with "keepalive=yes".
  • <keepinterval> is the number of seconds to wait between each keepalive probe after the first (see below). Only valid with "keepalive=yes" and not available for Mac OS X prior to Mavericks.
  • <count> is the number of un-replied to keepalive probes (see below) before a tcp connection is considered lost. Only valid with "keepalive=yes" and not available for Mac OS X prior to Mavericks.
For most purposes you can just specify "tcp:direction=both,mode=server" to create a bi-directional tcp server.

If a client ("mode=client", the default) tcp connection is lost for any reason, kplex will not attempt to reconnect if "persist=no" (the default) is specified. The interface will shut down, but other interfaces will continue to operate. If "persist=yes" is specified for a client connection, kplex will attempt to reconnect when the connection is lost. When attempting to reconnect an outbound or bi-directional connection, kplex will discard all but the last message in its queue to minimise the amount of potentially stale data arriving at the server. The delay in seconds between successive attempt at reconnection may be specified using the "retry" option. "persist=yes" only tells kplex to reconnect a lost connection. If the first connection attempt fails it will not be re-tried and initialisation of that interface will fail. If persistent attempts to connect an initially failed connection are desired, "persist=fromstart" should be specified. Note that this option should be used with care to avoid repeated attempts to connect to a mis-typed hostname or address.

kplex will detect a dropped connection if the other end closes down "cleanly", i.e. the program it is connecting to shuts down or the machine it is running on is gracefully shut down. kplex may also detect a failed endpoint if it gets no response to data it is attempting to write. It may not, however, be able to detect a failed endpoint if it is purely reading from the other end and it is not notified that the data source has gone away. This may frequently happen if connecting from behind NAT (NAT mappings are lost) or if the other computer crashes or has power removed. In these cases it is useful to specify the "keepalive=yes" option (the default is "no"). This will cause tcp to send probes to the remote end point to check that it is still "alive". The first probe is sent after seconds of inactivity. The default value will be system dependent but is usually 2 hours. If no reply is received to this probe, further probes are sent <keepinterval> seconds apart. If <count> probes are sent without reply, kplex considers the connection dropped and will attempt to reconnect. The default values for the interval between keepalive probes and the number sent before the connection is considered lost are system dependent, but invariably higher than desirable for kplex's purposes. On Mac OS X versions prior to Mavericks, only the delay before the initial probe is configurable from within kplex, but the other two values are configurable on a system-wide basis with sysctl(8).

If "persist=yes" is specified for a tcp client connection but no "keepalive=" option is given, keepalives will default to "on" and unless explicitly specified otherwise, the following values will be set:

  • keepidle=30
  • keepintvl=10 (Not Mac OS X prior to 10.9)
  • keepcnt=3 (Not Mac OS X prior to 10.9)

If "nodelay=yes" is specified or the nodelay option is not used, kplex will disable the nagle algorithm on an outbound tcp connection. This results in fractionally faster delivery of data to clients at the expense of slightly more network traffic and is generalyl desirable on a local area network. Where minimising network use is a priority (such as sending data over a mobile data connection with a per-megabyte charge) specifying "nodelay=no" can reduce network traffic at the expense of a slight increase in latency.

The "preamble" option is used to send a set of characters to a remote server to identify a sending station before transmitting data. It is not part of the NMEA-0183 specification (for standards-compliant source identification, use source TAGs instead) but is used by some AIS aggregation sites as an alternative to per-station dedicated TCP ports. If specified with the "persist" option, the preamble string will be sent after each reconnection following connection loss. Non-ASCII characters may be specified either by a backslash followed by the (exactly) 3-digit octal representation of the character or the sequence "\x" followed by the (exactly) 2-digit hexadecimal representation of the character. The NULL character must be specified as "\000" or "\x00" and may not be abbreviated to "\0" or "\x0". Standard escape sequences (\a,\b,\f,\r,\n,\t,\v) are recognised. Other escaped characters are sent literally without the leading backslash. Any string termination must be explicitly stated, so a NULL- terminated string must end with "\000" or "\x00". Care must be taken when using this option on the command line due to shell interpretation of escape characters. Only one "preamble" may be specified and this option may not be used with "mode=server".

If "gpsd=yes" is specified kplex will use port 2947 as a default if the "port" option is not specified and will set the preamble to: ?WATCH={"enable":true,"nmea":true} This will enable nmea output from an instance of gpsd connected to. This option may not be used with "mode=server" or the "preamble" option.

UDP Interfaces

NOTE: As of kplex 1.3 UDP interfaces are now preferred over the existing "broadcast" and "multicast" interface types. However the "udp" interface is new in this version. If you encounter problems, please report the issue and consider reverting to the older "broadcast" or "multicast" interface types while your problem is under investigation.

This method encapsulates nmea sentences within UDP datagrams which are sent via unicast, multicast or broadcast.

Interface-specific options:

  • address=<address>
  • port=<port>
  • device=<interface>
  • type=[unicast|broadcast|multicast]
  • coalesce=[yes|no]

Where:

  • <address> is the interface address to bind to for inbound kplex interfaces or the address to send to for outbound interfaces. If not specified for an input interface, kplex will receive broadcast and unicast traffic sent to the desired port on a given interface if one is specified, or all interfaces if non is specified. If no address is specified for an output or bi-directional interface, a system interface must be specified, in which case the broadcast or point-to-point destination address is assumed for outbound datagrams with inbound datagrams received for the address of the specified interface in the case of point-to-point system interfaces or the interface's broadcast address where the system interface is broadcast-capable. For sending and receiving of multicast datagrams an address must be specified. kplex should work out whether any provided address is unicast, multicast or broadcast and act accordingly. "group=" is a synonym for "address=" for backwards compatibility with deprecated mcast interfaces.
  • <device> specifies the system interface (e.g. "wlan1", "eth0") to use. If the kplex interface is inbound and an interface is specified, kplex will attempt to bind to an address if one is specified which belongs to that system interface, or the first address found associated with that system interface if no address is specified. For bi-directional and outbound multicast and broadcast interfaces all traffic is sent and received using a specified system interface. For bi-directional and outbound unicast interfaces any received traffic will be on the interface specified. For outbound datagrams the source address will be set to an address associated with the specified interface. If no device is specified for inbound or outbound multicast interfaces, the routing table is used to determine which system interface to use. For broadcast and unicast interfaces inbound traffic will be received on the system interface corresponding to a specified broadcast or unicast address where no system interface is specified or any system address if no device or address is specified.
  • <port> if specified is the udp port or service name. If not specified defaults to the udp port returned by a lookup of the service "nmea-0183" and if that fails the IANA assigned port for nmea-0183 10110 is used.

Note that broadcast is inherently IPv4 (it does not exist in IPv6) and inefficient, forcing all nodes on a network to process data which they are potentially uninterested in. Multicast is the superior technique but not as widely supported by other marine applications.

Bi-directional unicast interfaces do not necessarily mean what you think they mean. Outbound packets will be sent from an ephemeral port and will be received from *any* sender of UDP packets containing valid NMEA-0183 data on that port. This is invariably not what you want and it is normally better to use separate send and receive interfaces for bi-directional communication over UDP between two instances of kplex.

Bi-directional broadcast interfaces will ignore sentences they transmit in order to minimize the possibility of data loops. When specifying multiple interfaces which may send or recive data transmitted to the same broadcast address, care should be taken to avoid data loops and consequent broadcast storms.

,p> Bi-directional multicast interfaces will ignore sentences they transmit.

Generally kplex can work out whether an interface should use unicast, multicast or broadcast traffic from the supplied <address> so the "type" option should not normally be given and doing so to force an mode not consistent with the supplied address will result in an error. One use for the "type" option is when supplying a "device" but no "address" option to an inbound interface. In this case the receiving interface will expect unicast traffic unless "type=broadcast" is explicitly requested.

By default or if "coalesce=no" is specified, input sentences are always transmitted one per packet as soon as they can be. If "coalesce=yes" is specified, kplex will buffer parts of a multi-part AIS message. Buffered data will be transmitted if the last part of the message is received (even if all the intervening parts have not been), there is insufficient space to store another sentence, or a sentence arrives which is not part of the buffered message. In the latter cases the newly arrived sentence is buffered if it is part (but not the last fragment) of a multi-part AIS sentence, otherwise it is transmitted immediately. kplex does not re-order out of order fragments of a multi-part AIS message.

Broadcast Interfaces

Broadcast interfaces are now deprecated and will be removed from a future version of kplex. Use udp interfaces instead if possible.

This method involves nmea sentences encapsulated within UDP datagrams sent to a broadcast address.

Interface-specific options:

  • device=<interface>
  • address=<address>
  • port=<port>

Where:

  • <device> specifies the system interface (e.g. "wlan1", "eth0") to use. This must be specified for outbound or bi-directional interfaces. kplex will only broadcast out through one interface. If the kplex interface is inbound and an interface is specified, kplex will attempt to bind to that interface and only accept packets received on that interface. Unfortunately this is a privileged operation on most GNU/Linux systems and kplex will often silently fail to do this without root privileges. You can possibly achieve a similar effect without root privileges by use of the <address> specifier (see below). If interface is not specified (or given as "-"), kplex will listen on all interfaces unless an <address> is specified (see below).
  • <port> if specified is the udp port or service name. If not specified defaults to the udp port returned by a lookup of the service "nmea-0183" and if that fails the IANA assigned port for nmea-0183 10110 is used.
  • <address> is the IPv4 interface address to bind to for inbound kplex interfaces or the address to send to for outbound interfaces. If unspecified for an input, kplex will receive broadcast and unicast udp to the relevant port on any <interface> specified, or all system interfaces if none was specified or the user as insufficient privileges to bind to a specific system interface. If an address is specified for an inbound broadcast interface, kplex will receive only packets to that address. Note that if you specify the IP address of a system interface, you will NOT receive broadcast traffic. If you specify a broadcast address (either the subnet broadcast address or the "all hosts" broadcast address 255.255.255.255 you will ONLY receive that *type* of broadcast (ie subnet OR all hosts). For this reason, this parameter is best left unspecified by most users. For outbound connections, this parameter specifies the broadcast address to use. It must be a broadcast address appropriate for the system interface you have specified and will default to the subnet broadcast address associated with the first address found for the specified system interface. If your client programs are particularly stupid they may be expecting the all hosts broadcast address of 255.255.255.255. If things don't work with the default, try this in the <address>.

Note that broadcast is inherently IPv4 (it does not exist in IPv6) and highly inefficient, forcing all nodes on a network to process data which they are potentially uninterested in. Multicast is the superior technique but not supported by many (if any) marine navigation applications at present.

Multicast Interfaces

Multicast interfaces are now deprecated and will be removed from a future version of kplex. Use udp interfaces instead if possible.

Multicast interfaces are similar to broadcast interfaces, but available with IPv6 as well as IPv4 and more efficient. In an ethernet network, a broadcast packet will require all nodes on a network to pass the packet to their IP stacks to determine whether or not it is of interest to them. IP multicast addresses map to ethernet multicast addresses. An operating system tells its network interface to accept only multicast packets with hardware addresses it is interested in. The mapping is not 1:1 (many IP multicast addresses map to one ethernet multicast address) but on a busy network, use of multicast instead of broadcast can dramatically cut down the number of packets a given node's network stack needs to process.

Interface-specific options:

  • group=<multicast address>
  • device=<interface>
  • port=<port>

Where:

  • <multicast address> is the multicast group address. This must be specified.
  • <interface> is the network interface to use (e.g., "eth0", "wlan1" etc.). If unspecified, if a bind address is specified, the system interface assigned that address will be used, otherwise the choice of interface will be left to the system and normally based on the routing table.
  • <port> if specified is the udp port or service name. If not specified defaults to the udp port returned by a lookup of the service "nmea-0183" and if that fails the IANA assigned port for nmea-0183 (10110) is used.

A multicast group address to used must be specified for an "multicast:" interface. For link local IPv6 multicast addresses, an interface device must be specified. This may be done in one of two ways:

  1. by appending the multicast group address with "%" followed by the interface name, for example:
        group=ff02::a0:200%wlan0
    
  2. by specifying the interface with the "device" option, e.g.:
        device=wlan0
    

If a device is not specified in one of the above ways for multicast addresses other than IPv6 link and interface local groups, the routing table will be used to select the outgoing interface for multicast packets.

GoFree Interfaces

GoFree is Navico's service discovery protocol which allows applications to connect to a network services without knowing details of its address. A kplex gofree interfaces listens on the IPv4 multicast address (239.2.1.1) and port (2052) which Navico have specified for announcements of the "nmea-0183" service. If not currently connected to an announced "nmea-0183" service, a kplex gofree interface will attempt to initiate a connection to the unicast TCP IPv4 address/port found in the first appropriate service announcement it sees. If a gofree interface is currently connected to an nmea-0183 service, On receipt of an announcement for an alternate service location (i.e. the IPv4 address/port of an nmea-0183 service on another multifunction display ("MFD"), if the last announcement for the currently connected service was more than 2 seconds prior, the gofree interface will terminate the current service connection and reconnect to the newly announced service. If the last announcement for the current service was less than 2 seconds prior, kplex will only initiate a connection to the alternate service if the current connection has terminated.

Interface-specific options:

  • device=<interface>

Where:

  • <interface> specifies the system interface (e.g. "wlan1", "eth0") to use. If unspecified the system will select the interface to listen for service announcements on, normally defaulting to the first multicast-capable non-loopback device.

GoFree does not support bi-directional nmea-0183 connections so all gofree interfaces have an implicit "direction=in" option. It is an error to specify "direction=out" for a gofree interface. Any output filters specified for a gofree interface are ignored.

Pseudo Terminal (pty) interfaces

Pty interfaces are pretty much the same as serial interfaces except that the devices concerned do not correspond to physical input and output devices on your system. Actually, in the case of inputs it makes no difference whether you specify "serial:" "pty:": The code ends up going down the same path.

Where ptys come in handy with kplex is if you want to split a serial input between one or more programs running on a computer and possibly some outputs too.

Interface-specific options:

  • mode=<mode>
  • filename=<file>
  • baud=<baud>
  • owner=<user>
  • group=<group>
  • perm=<permissions>
Where
  • <mode> is either "master" or "slave"
  • <file> is either the pty to connect to in "slave" mode or, in "master" mode, a path name specifying a symbolic link that will be created pointing to the slave side of an output pty
  • <baud> is the baud rate. Defaults to 4800 if unspecified. Supported baud rates are: 4800, 9600, 19200, 38400, 57600, 115200
  • <user> is the username for the slave side of a master pty to be set to.
  • <group> is the group to set the slave side of a master pty to.
  • <permissions> are the permissions in octal form to set the slave side of a master pty to.
<file> must be specified in slave mode. In master mode, kplex creates a master/ slave pty pair. If you give kplex a <file> it will attempt to create a symbolic link with that pathname pointing to the slave side of the pty it creates. If the path given currently exists as a symbolic link it will be replaced. If it exists but is not a symbolic link (e.g. it's a regular file or device) kplex will exit with an error. If no pty name is given, or if it is given as "-", kplex just prints the name of the slave pty created without creating a symlink.

Specifying a pathname (and creating a symlink) is useful for providing a persistent interface.

Where kplex is directed to create a master pty interface with "mode=master", the slave side of the pty (which other processes will use to communicate with kplex) will be created using system default ownership and permissions. On many systems this will mean the owner of the device will be the owner of the kplex process, the group will be set to "tty" and the permissions will be 0620 (i.e. read/write by owner, write only by group and inaccessible to others).

if "owner=<user>" is specified, the owner of the slave side of a master pty will be set to <user> if <user> is a valid system user and the owner of the kplex process is permitted to change the file's ownership in this way. Normally this may only be used by a kplex process running as root.

If "group=<group>" is specified, the group of the slave side of a master pty will be set to <group> if <group> is a valid system group and the owner of the kplex process is permitted to change the file's group in this way. Normally only root or a member of the specified group is able to make this change.

If "perm=<permissions>" is specified where <permissions> are the desired permissions of the slave side of a master pty in octal format, permissions are set accordingly. Only file access bits are settable. Attempts to set setuid/setgid/sticky bits will be ignored. A leading "0" is allowed but not required for permissions. Note that "000" is neither a useful nor, in this case, permitted access mode.

As an example, Assume you wish to take AIS input from a serial port, make it available to opencpn but also create a tcp server to make the data available to inavX on an ipad. The user of OpenCPN is a member of the dialout group but not tty. You might invoke kplex like this:

kplex serial:direction=in,filename=/dev/ttyUSB0,baud=38400 pty:direction=out,mode=master,filename=/home/fred/.opencpn/ais,baud=38400,group=dialout,perm=640 tcp:direction=out,mode=server

And add the following to /home/fred/.opencpn/opencpn.conf:

[Settings/AISPort]
Port=Serial:/home/fred/.opencpn/ais

This creates the /home/fred/.opencpn/ais, which opencpn will use for its AIS input, as a symlink to the slave of a pty which kplex opens at 38400 baud in addition to a tcp server.

Filtering

kplex allows you specify two types of filter: Input and Output Input Filters dictate what sentences an input interface forwards Output filters dictate which sentences get passed out of an output interface. An input filter is used by input and bi-directional interfaces but ignored by output interfaces. Likewise, an output filter is used by output and bi-directional interfaces and ignored by input interfaces. Connections spawned by servers inherit their parent's filters, so connections to a tcp server will be filtered according to the server's filters. A filter consists of a series of filter rules. Each filter rule consists of either a "+", "-" or "~" (to specify an "ALLOW", "DENY" or "LIMIT" rule respectively) followed by a "match string" which is either the word "all" or 5 characters. The match string may optionally be followed by the "%" character and the name of an interface (which must have been given to an interface using the "name=" option). A "LIMIT" rule must additionally have a "/" character followed by a whole number (i.e. without a decimal point) representing the minimum number of seconds which must pass between successive sentences matching that rule being permitted to pass. Filter rules are separated by a colon (":" character). Filter rules are applied in the order they are specified to a sentence being filtered.

A filter rule which specifies the word "all" matches all sentences. If a filter rule specifies a 5 character match string, these are compared with the 5 character NMEA 0183 talker/message type of the sentence being filtered. The filter rule matches if each character is the same as the corresponding character in the sentence being filtered. A "*" in a filter matches any character. Thus a filter rule specifying: GP*** would match any sentences produced by a GPS talker (excluding any proprietary sentences not specifying talker as "GP").

If a source interface has been specified for a rule, a given sentence must additionally have entered kplex from an interface with the specified "name" for the rule to "match". Thus a filter specified as GP***%Serial1 would match sentences with a talker id of "GP" only if received on the interface with the name "Serial1".

When a filter rule "matches" a sentence, it "fires". If the rule was an "allow" rule (ie prepended by a "+", the sentence is allowed. If the rule was a "deny" rule (ie prepended by a "-"), the sentence is dropped. If the rule was a "limit" rule, the sentence is passed if and only if time in seconds since the last time a sentence matching this that rule was allowed to pass was equal to or greater than the number of seconds following the "/" in the rule specification.

If no rules are matched the sentence is allowed. Thus a filter such as: ifilter=+GP***:+AI***:+SDDBT is pointless. It allows all sentences as it denies none. To *only* allow AIS, GPS and Depth below transducer sentences, you need to deny what is not explicitly allowed by adding "-all" to the end of the filter specification: ifilter=+GP***:+AI***:+SDDBT:-all Obviously order is important. Putting "-all" at the beginning would simply deny all sentences.

Specifying an interface in a rule applied to an ifilter is generally pointless.

IMPORTANT NOTE:
proprietary sentences start with "$P" followed by a three character vendor code, followed by a vendor-specified string which may be, and often is, more than one character in length. kplex can only filter on the 5 characters following the "$" and thus cannot precisely filter all proprietary sentences. Similarly kplex cannot completely filter query sentences which consist of "$" followed by the two letter talker id of the requester, the two letter talker id of the target talker, the character "Q", a comma and the three character sentence mnemonic. Only the 5 characters after the "$" (ie requester/target pair) can be filtered on.

Failover

kplex allows you to specify special filters which are intended to allow you to use a particular source for one type of data if it is available, but allowing that type of data to be passed from another interface if it hasn't been seen on the preferred input interface for a specified period of time. This behaviour is specified using the "failover=" directive in the [global] section of the configuration file or as a -o option on the command line. The format is: failover=<filter>:<delay>:<interface>[:<delay>:<interface>]... Where:

  • <filter> is a filter specifier as described in "Filtering" above
  • <delay> is the number of seconds without seeing data which matches the filter on a higher priority interface before the datum is passed
  • <interface> is the name of the interface to which the <delay> specifier applies. An interface must be given a "name=" option to be usable with failover.
Any number of :<delay>:<interface> specifiers may be added. Any interface not specified on a "failover" line will never pass sentences matching the filter.

"Primary" interfaces (ie those where the data should "normally" come from) should be specified with a <delay> of 0.

Example:
You have 3 GPS sources available. The main GPS is fed via a serial connection you have named "serial1". A second is available from a USB GPS you have named "USBpuck". As a last resort you have your phone transmitting nmea over tcp on an input you have named "phone". You might specify: failover=GP***:0:serial1:30:USBpuck:60:phone This will always pass sentences with a talker id of "GP" from the interface named "serial1". If no "GP" sentences are seen on serial1 for 30 seconds, kplex will pass sentences matching "GP***" from USBpuck until a "GP***" sentence is next seen on serial1. If no "GP***" sentences are seen on either serial1 or USBpuck for 60 seconds, kplex will start passing such sentences from the "phone" connection until such point as those sentences are seen on either of the higher priority interfaces.

Stopping

kplex closes down if it has no more outputs. If kplex has no more inputs, it closes down after all outputs have transmitted any buffered data. Interfaces shut down when the end of data input is reached (e.g. on end of file for file inputs or a network peer terminates its end of the connection) or on error. Outputs terminate when they are unable to write due to a network peer terminating or some error condition.

If the process receives a SIGTERM (e.g. from the kill command) or SIGINT (e.g. from ctrl-C pressed at the terminal kplex is running in), kplex will shut all its interfaces down, allowing any buffered data to be transmitted, before exiting.

To stop an instance of kplex which is running in the foreground, hold down the "Ctrl" key and hit "c".

To stop an instance of kplex running in daemon mode, send it the termination signal, e.g. "pkill kplex".

kplex should always clean up all of its interfaces, including restoring serial line settings to what they were when kplex started. If this doesn't happen it's a bug: Please report it.

NMEA-0183v4 TAG block handling

kplex will strip all NMEA-0183v4 TAG blocks from the input stream and discard them. Correctly formatted following sentences will be multiplexed. kplex does not conform to NMEA-0183v4 and will ignore all query and control messages.

Timestamps and source identifiers conform, as far as can be determined from publicly available sources, to the NMEA-0183v4 TAG specification. Note however that at this time implementation of TAG block handling in various programs and devices is variable and other programs may discard sentences with correctly formatted TAG blocks prepended

Example usage

Inputs from ais data on one serial port, other nmea data on a serial to usb interface. Output to broadcast udp and one usb to serial interface:

kplex serial:direction=in,filename=/dev/ttyS0,baud=38400 serial:direction=in,filename=/dev/ttyUSB0 tcp:direction=out,mode=server serial:direction=out,filename=/dev/ttyUSB1,baud=38400

Bi-directional communication with tcp server on 192.168.1.50, port 2200. Output to pseudo terminal, creating link for opencpn to read and write at /tmp/nmea, 38400 baud

kplex tcp:direction=both,mode=client,address=192.168.1.50,port=2200 pty:direction=both,mode=master,filename=/tmp/nmea,baud=38400

Input from GPS on usb to serial interface, outputting to tcp server, IPv6 multicast group ff05::10:110 on the default port and a data log file which appends an RMC sentence once per hour:

kplex serial:direction=in,filename=/dev/ttyUSB0 tcp:mode=server,direction=out mcast:group=ff05::10:110,direction=out file:filename=/var/tmp/datalog,direction=out,append=yes,ofilter=~GPRMC/3600:-all

Configuration File syntax

The configuration file syntax is similar to the command line sytanx, but new lines are used to separate options instead of commas and the start of an interface specification is signalled by the interface type enclosed by square brackets as the only non-white space on a line. Everything that follows the start of an interface section is considered an option relating to that interface until the beginning of the next interface section or the end of the file.

Everything after a '#' character on a line is ignored.

A special "interface" type, "global", may be used to specify options not specific to a particular interface. "global" options currently supported are:

  • qsize=<qsize>
    Where:
    • <qsize> is the size (in sentences) of kplex's central multiplexing queue This should not normally need changing.
  • mode=<mode>
    Where:
    • <mode> is either "foreground" (the default) or "background", the former is the default. The latter tells kplex to detach form its controlling terminal and run as a daemon process.
  • checksum=[yes|no|strict|loose|add|addonly]
    Where
    • "checksum=no" tells kplex to perform no checksum processing.
    • "checksum=yes" and "checksum=strict" tell kplex to discard incoming sentences without a correct checksum.
    • "checksum=loose" tells kplex to discard sentences with an incorrect checksum but to accept those with no checksum.
    • "checksum=add" tells kplex to discard sentences with an incorrect checksum but to add one if none is present.
    • "checksum=addonly" tells kplex to add a checksum if none is present but not to otherwise perform checksum checking.
    Both "add" and "addonly" arguments cause sentences without checksums to be discarded if the addition of a checksum would exceed the maximum sentence length. The default is not to calculate checksums as it is assumed that this will be done by end consumer applications. This option may be overriden by the per-interface "checksum" option.
  • strict=[yes|no]
    Where
    • "strict=yes" tells kplex to require all sentences received to be correctly terminated with a <CR><LF> sequence unless overridden on a per-interface "strict" option or a per-interface "eol=n". If "strict=no" is specified all interfaces will default to a looser parsing strategy which will allow input sentences to be terminated by a <CR>, <LF> or NULL (0x00). This option applies to input sentences only and has no effect on interface output. However terminated on input when loose parsing ("strict=no") is in effect, sentences output from interfaces other than file interfaces will be <CR><LF> terminated. If this value is not specified and no per-interface "strict=" specification is given, processing will default to "strict=yes" for all interface types *except* file interfaces, For "file" interfaces the default is loose ("strict=no") processing.
  • logto=<facility>
    Where
    • <facility> is the syslog facility to use for logging. The default is "daemon", telling kplex to use the LOG_DAEMON syslog facility. <facility> is the same string as would be used in a syslog.conf(5) file, so to log to LOG_LOCAL7, specify "logto=local7".
  • failover=<failover specification>
    Where
    • <failover specification> is a series of colon-separated filter:delay:interface tuples as described in the "Failover" section above.
  • graceperiod=<secs>
    Where
    • <secs> is the number of seconds to wait for output to be cleanly sent before termination when kplex shuts down (default 3).
  • debuglevel=<level>
    Where
    • <level> is the verbosity of debug information is required and should be an integer value between 0 and 9 inclusive. 0 (default)gives no debugging information. 9 is maximum.
  • As an example, the first item in the "example usage" section above could be specified in a configuration file:
    # This is a comment and will be ignored
    [serial]
    direction=in
    filename=/dev/ttyS0
    baud=38400 # baud will be read, but this comment ignored
    # whitespace is ignored
    
    [serial]
    direction=in
    filename=/dev/ttyUSB0
    [tcp]
    direction=out
    mode=server
    [serial]
    direction=out
    filename=/dev/ttyUSB1
    baud=38400
    
    # This is the end of the example file
    

    To Do

    Possible future enhancements include:

    • A set of commands to allow modifying kplex on the fly, for example to add, subtract and modify the current interface list. The structure of kplex means this would be a relatively straightforward addition
    • A nice GUI. Obviously.

    Q&A

    Question and Answers have now been moved to a dedicated FAQ page.

    Thanks to / Takk til / Tak til / Tack til / Dank Aan / Merci à all who have contributed with feedback, suggestions, correction of typos and bug reports. Keep them coming.

    bottom border