diff --git a/README.md b/README.md index ca83f20..e04dcd0 100644 --- a/README.md +++ b/README.md @@ -281,6 +281,8 @@ The ULTRAFEEDER_CONFIG parameter can have multiple config strings, separated by - ULTRAFEEDER_CONFIG=adsb,host,port,protocol[,uuid=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX][,extra-arguments] ...or... - ULTRAFEEDER_CONFIG=mlat,host,port[,return_port][,uuid=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX][,extra-arguments] +...or to retrieve MLAT data from a remote receiver... +- ULTRAFEEDER_CONFIG=mlat,host,port[,return_port][,uuid=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX][,input_connect=remote-host:port,lat=xx.xxxx,lon=yy.yyyy,alt=zzz][,extra-arguments] ...or... - ULTRAFEEDER_CONFIG=mlathub,host,port,protocol[,uuid=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX][,extra-arguments] ``` @@ -300,6 +302,11 @@ In the above configuration strings: - `vrs_out`: SBS-format output - `uuid=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX` is an optional parameter that sets the UUID for this specific instance. It will override the global `UUID` parameter. This is only needed when you want to send different UUIDs to different aggregators. - `extra-arguments` can be any additional command line argument you want to pass to readsb, mlathub, or mlat-client. Example: `--net-only`. Please make sure to only once pass in an extra argument for each of the adsb|mlat|mlathub service. +- To connect to a remote receiver and send MLAT data to a MLAT Server, create a `mlat` instance with these additional parameters - `input_connect=remote-host:port,lat=xx.xxxx,lon=yy.yyyy,alt=zzz`, where: + - `input_connect=remote-host:port` defines the remote receiver's hostname or IP address and the port number where BEAST output data is available + - `lat=xx.xxxx` defines the remote receiver's latitude + - `lon=yy.yyyy` defines the remote receiver's longitude + - `alt=zzz` defines the remote receiver's altitude in meters above the eliptoid (~above sea level) ##### Networking parameters @@ -387,11 +394,12 @@ where: - `port` is the port (TCP or UDP) of the target MLAT server (mandatory) - `return_port` is the port at which the MLAT results are made available in BEAST format. We recommend to sequentially number them starting at 39000 (optional) - `uuid=xxxx` defines a unique user ID for this MLAT server instance. If included, the string must start with `uuid=` (optional) +- `input_connect=hostname:port` / `lat=xxxx` / `lon=xxxx` / `alt=xxxx` defines a unique input connection/latitude/longitude/altitude. This can be used to connect to a remote Beast source and forward MLAT data to an MLAT server - `extra-arguments` are any additional command line arguments that you would like to use for this MLAT Client instance (optional) Note - the three optional parameters (`return_port`, `uuid=`, and `extra-arguments`) can be given in any order. -If no UUID is specified with the `MLAT_CONFIG` parameter, it will use the value of the `UUID` parameter if it exists. If that fails, no UUID parameter is included with `mlat-client`. +If no UUID is specified with the `MLAT_CONFIG` parameter, it will use the value of the `UUID` parameter if it exists. If that fails, a random UUID will be generated for each instance of `mlat-client` with format `00000000-ffff-aaaa-rrrr-tttttttttttt` where `rrrr` is a random hexadecimal number and `tttttttttttt` contains the UUID creation time (secs since epoch) in hexadecimal format. ### Web Gui (`tar1090`) Configuration diff --git a/rootfs/etc/cont-init.d/01-print-container-version b/rootfs/etc/cont-init.d/01-print-container-version index 39e03a0..2301490 100644 --- a/rootfs/etc/cont-init.d/01-print-container-version +++ b/rootfs/etc/cont-init.d/01-print-container-version @@ -20,4 +20,6 @@ source /scripts/common # If not, see . #--------------------------------------------------------------------------------------------- +alias s6wrap='s6wrap --quiet' + [[ -f /.CONTAINER_VERSION ]] && s6wrap --prepend=01-print-container-version --timestamps --args echo "Container Version: $(cat /.CONTAINER_VERSION), build date $(stat -c '%y' /.CONTAINER_VERSION |sed 's|\(.*\)\.[0-9]* \(.*\)|\1 \2|g')" || true diff --git a/rootfs/etc/services.d/mlat-client/run b/rootfs/etc/services.d/mlat-client/run index 839b780..424cee8 100644 --- a/rootfs/etc/services.d/mlat-client/run +++ b/rootfs/etc/services.d/mlat-client/run @@ -18,6 +18,8 @@ #--------------------------------------------------------------------------------------------- APPNAME="mlat-client" +alias s6wrap='s6wrap --quiet' + s6wrap --prepend="${APPNAME}" --timestamps --args echo "Started as an s6 service" source /scripts/common @@ -74,9 +76,6 @@ do # put individual params into the $params array: readarray -td "," params < <(printf '%s' "${instance}") - uuid_arg=false - extra_args="" - # Check if the params array has values for the mandatory elements: if [[ -z "${params[0]}" ]] || [[ -z "${params[1]}" ]] then @@ -86,31 +85,52 @@ do sleep infinity fi + # Now process the the arguments + # The order doesn't matter, we'll do pattern matching: + # If the argument is a number, then it must be the beast_results port + # If the argument starts with "uuid=", then it must be a UUID, etc. + # If the argument isn't any of the above, then it's an "extra argument" + + unset uuid_arg lat_arg lon_arg alt_arg input_connect_arg return_port_arg extra_args + + for ((i=2; i<${#params[*]}; i++)) + do + if [[ -n "${params[i]}" ]] && [[ "${params[i]}" =~ ^[0-9]+$ ]]; then + # It's a number so it must be the return port + return_port_arg="${params[i]}" + elif header="${params[i]:0:5}" && [[ "${header,,}" == "uuid=" ]]; then + # It's a UUID + uuid_arg="${params[i]#*=}" + elif header="${params[i]:0:4}" && [[ "${header,,}" == "lat=" ]]; then + # It's a latitude + lat_arg="${params[i]#*=}" + elif header="${params[i]:0:4}" && [[ "${header,,}" == "lon=" ]]; then + # It's a longitude + lon_arg="${params[i]#*=}" + elif header="${params[i]:0:4}" && [[ "${header,,}" == "alt=" ]]; then + # It's a latitude + alt_arg="${params[i]#*=}" + elif header="${params[i]:0:14}" && [[ "${header,,}" == "input_connect=" ]]; then + #It's the input_connect parameter value + input_connect_arg="${params[i]#*=}" + else + # It's an Extra Args string + extra_args="$extra_args ${params[i]}" + fi + done + # ------------------------------------------------ # Build the MLAT parameter string: - MLAT_PARAM=(--input-type "${MLAT_INPUT_TYPE}") - MLAT_PARAM+=(--input-connect localhost:30005) + MLAT_PARAM=(--input-type "${MLAT_INPUT_TYPE:-auto}") MLAT_PARAM+=(--server "${params[0]}:${params[1]}") - if [ -n "${LAT}" ]; then - MLAT_PARAM+=(--lat "${LAT}") - elif [ -n "${READSB_LAT}" ]; then - MLAT_PARAM+=(--lat "${READSB_LAT}") - fi + # add return port: + [ -n "${return_port_arg}" ] && MLAT_PARAM+=("--results beast,listen,${return_port_arg}") || true - if [ -n "${LONG}" ]; then - MLAT_PARAM+=(--lon "${LONG}") - elif [ -n "${READSB_LON}" ]; then - MLAT_PARAM+=(--lon "${READSB_LON}") - fi + # add input-connect to the param array: + MLAT_PARAM+=(--input-connect "${input_connect_arg:-localhost:30005}") - if [ -n "${ALT}" ]; then - MLAT_PARAM+=(--alt "${ALT}") - elif [ -n "${READSB_ALT}" ]; then - MLAT_PARAM+=(--alt "${READSB_ALT}") - fi - - if [[ -n "${MLAT_USER}" ]]; then + if [ -n "${MLAT_USER}" ]; then MLAT_PARAM+=(--user "${MLAT_USER}") else rnd="${RANDOM}" @@ -118,33 +138,44 @@ do MLAT_PARAM+=(--user "${rnd}") fi - # Now process the rest of the arguments - # The order doesn't matter, we'll do pattern matching: - # If the argument is a number, then it must be the beast_results port - # If the argument starts with "uuid=", then it must be a UUID - # If the argument isn't any of the above, then it's an "extra argument" + # add LAT/LON/ALT to instance: + if [ -n "${lat_arg}" ]; then + MLAT_PARAM+=(--lat "${lat_arg}") + elif [ -n "${LAT}" ]; then + MLAT_PARAM+=(--lat "${LAT}") + elif [ -n "${READSB_LAT}" ]; then + MLAT_PARAM+=(--lat "${READSB_LAT}") + fi - for ((i=2; i<${#params[*]}; i++)) - do - if [[ -n "${params[i]}" ]] && [[ "${params[i]}" =~ ^[0-9]+$ ]]; then - # It's a number so it must be the return port - MLAT_PARAM+=("--results beast,listen,${params[i]}") + if [ -n "${lon_arg}" ]; then + MLAT_PARAM+=(--lon "${lon_arg}") + elif [ -n "${LONG}" ]; then + MLAT_PARAM+=(--lon "${LONG}") + elif [ -n "${READSB_LON}" ]; then + MLAT_PARAM+=(--lon "${READSB_LON}") + fi - elif header="${params[i]:0:5}" && [[ "${header,,}" == "uuid=" ]]; then - # It's a UUID - MLAT_PARAM+=("--uuid ${params[i]:5}") - uuid_arg=true + if [ -n "${alt_arg}" ]; then + MLAT_PARAM+=(--alt "${alt_arg}") + elif [ -n "${ALT}" ]; then + MLAT_PARAM+=(--alt "${ALT}") + elif [ -n "${READSB_ALT}" ]; then + MLAT_PARAM+=(--alt "${READSB_ALT}") + fi - else - # It's an Extra Args string - extra_args="$extra_args ${params[i]}" - - fi - done - # If no UUID was set in the argument strings, check if we can use the generic UUID parameter - if [[ $uuid_arg == false ]] && [[ -n "${UUID}" ]]; then + # Add UUID to instance + if [ -n "$uuid_arg" ]; then + MLAT_PARAM+=("--uuid ${uuid_arg}") + elif [ -n "${UUID}" ]; then + MLAT_PARAM+=("--uuid ${UUID}") + else + # generate a random UUID + UUID="$(cat /proc/sys/kernel/random/uuid)" + [[ -z "${UUID}" ]] && UUID="$(printf '00000000-ffff-aaaa-%04x-%012x\n' "$RANDOM" "$(date +%s)")" + s6wrap --prepend="${APPNAME}" --timestamps --args echo "WARNING: UUID is not defined - using randomized uuid \"${UUID}\"" MLAT_PARAM+=("--uuid ${UUID}") fi + # Now add the extra_args, if any: [[ -n "${extra_args}" ]] && MLAT_PARAM+=("${extra_args}") || true @@ -169,9 +200,9 @@ do #shellcheck disable=SC2069,SC2086 if [[ -z "${LOGLEVEL}" ]] || [[ "${LOGLEVEL,,}" == "verbose" ]]; then - { exec s6wrap --prepend="${APPNAME}" --timestamps --args ${execstring}; } & + { exec s6wrap --prepend="${APPNAME}][${params[0]}" --timestamps --args ${execstring}; } & elif [[ "${LOGLEVEL,,}" == "error" ]]; then - { exec s6wrap --prepend="${APPNAME}" --timestamps --args ${execstring} 2>&1 >/dev/null; } & + { exec s6wrap --prepend="${APPNAME}][${params[0]}" --timestamps --args ${execstring} 2>&1 >/dev/null; } & elif [[ "${LOGLEVEL,,}" == "none" ]]; then { exec ${execstring} >/dev/null 2>/dev/null; } & fi @@ -179,9 +210,10 @@ do # pid_array is indexed by the PID of each mlat_client and contains the MLAT_PARAMs for that instance # This is done so we can monitor them and restart them if needed pid_array[$!]="${MLAT_PARAM[*]}" - sleep 5 done +sleep 5 + # All MLAT Clients are up, so set the flag. This flag is read by MLATHUB as a sign that it's # safe to start up touch /run/mlathub_up @@ -195,15 +227,18 @@ do then # it exited - let's restart: sleep "${RESTARTTIMER}" - [[ "${LOGLEVEL,,}" != "none" ]] && s6wrap --prepend="${APPNAME}" --timestamps --args echo "MLAT_Client $(awk '{print $6}' <<< "${pid_array[$mlat_pid]}") exited. Attempting to restart." || true + servername="$(awk '{print $4}' <<< "${pid_array[$mlat_pid]}")" + servername="${servername%%:*}" + + [[ "${LOGLEVEL,,}" != "none" ]] && s6wrap --prepend="${APPNAME}[${servername}" --timestamps --args echo "MLAT_Client ${servername} exited. Attempting to restart." || true # shellcheck disable=SC2086 execstring="$(echo ${MLAT_CMD} ${pid_array[$mlat_pid]} | xargs)" #shellcheck disable=SC2069,SC2086 if [[ -z "${LOGLEVEL}" ]] || [[ "${LOGLEVEL,,}" == "verbose" ]]; then - { exec s6wrap --prepend="${APPNAME}" --timestamps --args ${execstring} 2>&1; } & + { exec s6wrap --prepend="${APPNAME}][${servername}" --timestamps --args ${execstring} 2>&1; } & elif [[ "${LOGLEVEL,,}" == "error" ]]; then - { exec s6wrap --prepend="${APPNAME}" --timestamps --args ${execstring} 2>&1 >/dev/null; } & + { exec s6wrap --prepend="${APPNAME}][${servername}" --timestamps --args ${execstring} 2>&1 >/dev/null; } & elif [[ "${LOGLEVEL,,}" == "none" ]]; then { exec ${execstring} >/dev/null 2>/dev/null; } & fi diff --git a/rootfs/etc/services.d/mlathub/run b/rootfs/etc/services.d/mlathub/run index 9429ee7..7393500 100644 --- a/rootfs/etc/services.d/mlathub/run +++ b/rootfs/etc/services.d/mlathub/run @@ -4,6 +4,7 @@ APPNAME="mlathub" source /scripts/common source /scripts/interpret_ultrafeeder_config +alias s6wrap='s6wrap --quiet' if [[ -z "${MLAT_CONFIG}" ]] && [[ -z "$MLATHUB_NET_CONNECTOR" ]]; then s6wrap --prepend="${APPNAME}" --timestamps --args echo "No MLAT servers have been defined in MLAT_CONFIG and no external sources have been defined in MLATHUB_NET_CONNECTOR - no need to start MLATHUB" diff --git a/rootfs/etc/services.d/readsb/run b/rootfs/etc/services.d/readsb/run index 13663b0..7c00eb0 100644 --- a/rootfs/etc/services.d/readsb/run +++ b/rootfs/etc/services.d/readsb/run @@ -5,6 +5,7 @@ APPNAME="readsb" source /scripts/common source /scripts/interpret_ultrafeeder_config +alias s6wrap='s6wrap --quiet' mkdir -p /run/readsb diff --git a/rootfs/scripts/interpret_ultrafeeder_config b/rootfs/scripts/interpret_ultrafeeder_config index 889a585..f2026c6 100755 --- a/rootfs/scripts/interpret_ultrafeeder_config +++ b/rootfs/scripts/interpret_ultrafeeder_config @@ -46,6 +46,10 @@ # `vrs_out`: SBS-format output # `uuid=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX` is an optional parameter that sets the UUID for this specific instance. # It will override the global `UUID` parameter. This is only needed when you want to send different UUIDs to different aggregators. +# `input_connect=host:port is an optional parameter that sets the input_connect values for this instance` +# `lat=xxxx` is an optional parameter that sets the latitude for this specific instance +# `lon=xxxx` is an optional parameter that sets the longitude for this specific instance +# `alt=xxxx` is an optional parameter that sets the altitude for this specific instance # `extra-arguments` can be any additional command line argument you want to pass to readsb, mlathub, or mlat-client # Example: `--net-only`. Please make sure to only once pass in an extra argument for each of the adsb|mlat|mlathub service.