From b140283133a5a6cace26f5d67aa6f9389dd44a97 Mon Sep 17 00:00:00 2001 From: rpatel3001 Date: Mon, 8 Apr 2024 10:20:22 -0400 Subject: [PATCH] works with rtl-sdr --- .github/workflows/deploy.yml | 41 +++++++++++ Dockerfile | 70 +++++++++++++++++++ README.md | 54 ++++++++++++++ iridium-toolkit.patch | 34 +++++++++ .../etc/s6-overlay/s6-rc.d/acars_bridge/run | 2 + .../etc/s6-overlay/s6-rc.d/acars_bridge/type | 1 + .../s6-overlay/s6-rc.d/iridium-extractor/run | 10 +++ .../s6-overlay/s6-rc.d/iridium-extractor/type | 1 + .../s6-rc.d/iridium-reassembler-map/run | 11 +++ .../s6-rc.d/iridium-reassembler-map/type | 1 + .../s6-rc.d/iridium-reassembler/run | 6 ++ .../s6-rc.d/iridium-reassembler/type | 1 + rootfs/etc/s6-overlay/s6-rc.d/map-server/run | 11 +++ rootfs/etc/s6-overlay/s6-rc.d/map-server/type | 1 + .../s6-rc.d/user/contents.d/acars_bridge | 0 .../s6-rc.d/user/contents.d/iridium-extractor | 0 .../user/contents.d/iridium-reassembler | 0 .../user/contents.d/iridium-reassembler-map | 0 .../s6-rc.d/user/contents.d/map-server | 0 rootfs/etc/s6-overlay/scripts/acars_bridge | 35 ++++++++++ 20 files changed, 279 insertions(+) create mode 100644 .github/workflows/deploy.yml create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 iridium-toolkit.patch create mode 100644 rootfs/etc/s6-overlay/s6-rc.d/acars_bridge/run create mode 100644 rootfs/etc/s6-overlay/s6-rc.d/acars_bridge/type create mode 100644 rootfs/etc/s6-overlay/s6-rc.d/iridium-extractor/run create mode 100644 rootfs/etc/s6-overlay/s6-rc.d/iridium-extractor/type create mode 100644 rootfs/etc/s6-overlay/s6-rc.d/iridium-reassembler-map/run create mode 100644 rootfs/etc/s6-overlay/s6-rc.d/iridium-reassembler-map/type create mode 100644 rootfs/etc/s6-overlay/s6-rc.d/iridium-reassembler/run create mode 100644 rootfs/etc/s6-overlay/s6-rc.d/iridium-reassembler/type create mode 100644 rootfs/etc/s6-overlay/s6-rc.d/map-server/run create mode 100644 rootfs/etc/s6-overlay/s6-rc.d/map-server/type create mode 100644 rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/acars_bridge create mode 100644 rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/iridium-extractor create mode 100644 rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/iridium-reassembler create mode 100644 rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/iridium-reassembler-map create mode 100644 rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/map-server create mode 100755 rootfs/etc/s6-overlay/scripts/acars_bridge diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..49d3da6 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,41 @@ +name: Build and deploy to ghcr.io + +on: + workflow_dispatch: + inputs: + reason: + required: true + description: 'Reason for running this workflow' + push: + branches: + - master + paths-ignore: + - '**.md' + +jobs: + build: + name: 'Build' + runs-on: ubuntu-latest + steps: + - name: "Build:checkout" + uses: actions/checkout@v3 + + - name: "Build:qemu" + uses: docker/setup-qemu-action@v2 + + - name: "Build:buildx" + uses: docker/setup-buildx-action@v2 + + - name: "Build:login" + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: 'Build:buildandpush' + uses: docker/build-push-action@v3.0.0 + with: + push: true + platforms: linux/amd64,linux/arm64 + tags: ghcr.io/${{ github.repository }}:latest,ghcr.io/${{ github.repository }}:${{ github.run_number }}-${{ github.sha }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..18d6c40 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,70 @@ +FROM rust:1.77.0 as builder +WORKDIR /tmp/acars-bridge +# hadolint ignore=DL3008,DL3003,SC1091 +RUN set -x && \ + apt-get update && \ + apt-get install -y --no-install-recommends libzmq3-dev + +RUN set -x && \ + git clone https://github.com/sdr-enthusiasts/acars-bridge.git . && \ + cargo build --release && \ + # clean up the apt-cache + apt-get clean && \ + rm -rf /var/lib/apt/lists/* && \ + cp /tmp/acars-bridge/target/release/acars-bridge . && \ + cargo clean + +FROM ghcr.io/sdr-enthusiasts/docker-baseimage:soapyrtlsdr + +ENV OUTPUT_SERVER="acarshub" \ + OUTPUT_SERVER_PORT="5558" \ + OUTPUT_SERVER_MODE="udp" + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +COPY iridium-toolkit.patch /tmp/iridium-toolkit.patch + +# hadolint ignore=DL3008,SC2086,DL4006,SC2039 +RUN set -x && \ + TEMP_PACKAGES=() && \ + KEPT_PACKAGES=() && \ + TEMP_PACKAGES+=() && \ + # temp + TEMP_PACKAGES+=(build-essential) && \ + TEMP_PACKAGES+=(cmake) && \ + TEMP_PACKAGES+=(git) && \ + TEMP_PACKAGES+=(gnuradio-dev) && \ + TEMP_PACKAGES+=(libsndfile1-dev) && \ + # keep + KEPT_PACKAGES+=(python3) && \ + KEPT_PACKAGES+=(python3-prctl) && \ + KEPT_PACKAGES+=(pypy3) && \ + KEPT_PACKAGES+=(gnuradio) && \ + KEPT_PACKAGES+=(gr-osmosdr) && \ + KEPT_PACKAGES+=(libsndfile1) && \ + apt-get update && \ + apt-get install -y --no-install-recommends \ + "${KEPT_PACKAGES[@]}" \ + "${TEMP_PACKAGES[@]}" && \ + # install pip dependencies + pypy3 -m pip install --force-reinstall --break-system-packages crcmod zmq && \ + # install iridium-toolkit + git clone https://github.com/muccc/iridium-toolkit.git /opt/iridium-toolkit && \ + pushd /opt/iridium-toolkit && \ + git apply /tmp/iridium-toolkit.patch && \ + popd && \ + # install gr-iridium + git clone https://github.com/muccc/gr-iridium.git /src/gr-iridium && \ + pushd /src/gr-iridium && \ + cmake -B build && \ + cmake --build build -j`nproc` && \ + cmake --install build && \ + ldconfig && \ + popd && \ + # Clean up + apt-get remove -y "${TEMP_PACKAGES[@]}" && \ + apt-get autoremove -y && \ + rm -rf /src/* /tmp/* /var/lib/apt/lists/* + +COPY --from=builder /tmp/acars-bridge/acars-bridge /opt/acars-bridge +COPY rootfs / diff --git a/README.md b/README.md new file mode 100644 index 0000000..8e4e214 --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +# docker-gr-iridium-toolkit +[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/rpatel3001/docker-gr-iridium-toolkit/deploy.yml?branch=master)](https://github.com/rpatel3001/docker-gr-iridium-toolkit/actions/workflows/deploy.yml) +[![Discord](https://img.shields.io/discord/734090820684349521)](https://discord.gg/sTf9uYF) + +A Docker image to use the [gr-iridium](https://github.com/muccc/gr-iridium) and [iridium-toolkit](https://github.com/muccc/iridium-toolkit) software from the [Chaos Computer Club München](https://muc.ccc.de/) to parse ACARS messages on the Iridium network. + +Under active development, everything is subject to change without notice. + +--- + +## Docker Compose + +``` +services: + irdm: + container_name: irdm + hostname: irdm + image: ghcr.io/rpatel3001/docker-gr-iridium-toolkit +# build: docker-gr-iridium-toolkit + restart: always + tty: true # actually needed, for iridium-parser.py + ports: + - 8888:8888 # for beam map + device_cgroup_rules: + - 'c 189:* rwm' + volumes: + - /dev:/dev:rw + - ./irdm.conf:/opt/irdm.conf:ro + environment: +# - LOG_EXTRACTOR_STATS=true +# - LOG_MAP=true +# - EXTRACTOR_ARGS= -D 10 + - PARSER_ARGS= --harder --uw-ec # runs slower, remove uw-ec then harder if message rate is high + - STATION_ID=XX-YYYY-IRDM + - OUTPUT_SERVER=acarshub + - OUTPUT_SERVER_PORT=5558 +``` + +irdm.conf has details of your SDR device. Full details can be found [here](https://github.com/muccc/gr-iridium?tab=readme-ov-file#configuration-file). An example for using an RTL-SDR with max gain and bias-tee enabled: + +``` +[osmosdr-source] +sample_rate=2500000 +center_freq=1625600000 + +# Uncomment to use the RTL-SDR's Bias Tee if available +device_args='rtl=0,bias=1' + +# Automatic bandwidth +bandwidth=0 + +# LNA gain +gain=49.6 +``` diff --git a/iridium-toolkit.patch b/iridium-toolkit.patch new file mode 100644 index 0000000..ca9d3a5 --- /dev/null +++ b/iridium-toolkit.patch @@ -0,0 +1,34 @@ +diff --git a/iridiumtk/reassembler/ida.py b/iridiumtk/reassembler/ida.py +index 0938146..177be65 100755 +--- a/iridiumtk/reassembler/ida.py ++++ b/iridiumtk/reassembler/ida.py +@@ -63,6 +63,7 @@ class ReassembleIDA(Reassemble): + self.otime=m.time + self.odata=m.data + self.ofreq=m.frequency ++ self.olevel=m.level + + ok=False + for (idx,(freq,time,ctr,dat,cont,ul)) in enumerate(self.buf[:]): +diff --git a/iridiumtk/reassembler/sbd.py b/iridiumtk/reassembler/sbd.py +index 103c1c0..97154fe 100755 +--- a/iridiumtk/reassembler/sbd.py ++++ b/iridiumtk/reassembler/sbd.py +@@ -4,7 +4,7 @@ + import sys + import datetime + import re +-from util import to_ascii ++from util import to_ascii, channelize + + from .base import * + from .ida import ReassembleIDA +@@ -362,6 +362,8 @@ class ReassembleIDASBDACARS(ReassembleIDASBD): + # that we want to include in the output. For example, we could include the raw SBD message in the output. + # Or possibly other embedded modes if they are present in the SBD message. + ++ out['freq'] = channelize(self.ofreq)[0] * channel_width + base_freq ++ out['level'] = f"{self.olevel:.1f}" + out['header'] = q.hdr.hex() + + print(json.dumps(out), file=outfile) diff --git a/rootfs/etc/s6-overlay/s6-rc.d/acars_bridge/run b/rootfs/etc/s6-overlay/s6-rc.d/acars_bridge/run new file mode 100644 index 0000000..a600547 --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/acars_bridge/run @@ -0,0 +1,2 @@ +#!/bin/sh +exec /etc/s6-overlay/scripts/acars_bridge diff --git a/rootfs/etc/s6-overlay/s6-rc.d/acars_bridge/type b/rootfs/etc/s6-overlay/s6-rc.d/acars_bridge/type new file mode 100644 index 0000000..5883cff --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/acars_bridge/type @@ -0,0 +1 @@ +longrun diff --git a/rootfs/etc/s6-overlay/s6-rc.d/iridium-extractor/run b/rootfs/etc/s6-overlay/s6-rc.d/iridium-extractor/run new file mode 100644 index 0000000..91a6b8e --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/iridium-extractor/run @@ -0,0 +1,10 @@ +#!/command/with-contenv bash +#shellcheck shell=bash + +echo "Starting iridium-extractor and iridium-parser" + +if [[ -n ${LOG_EXTRACTOR_STATS} ]]; then + python3 -u `which iridium-extractor` $EXTRACTOR_ARGS /opt/irdm.conf 2> >(stdbuf -o0 awk '{print "[iridium-extractor] " strftime("%Y/%m/%d %H:%M:%S", systime()) " " $0}') > >(pypy3 -u /opt/iridium-toolkit/iridium-parser.py $PARSER_ARGS -o zmq 2>&1 | stdbuf -o0 awk '{print "[iridium-parser] " strftime("%Y/%m/%d %H:%M:%S", systime()) " " $0}') +else + python3 -u `which iridium-extractor` $EXTRACTOR_ARGS /opt/irdm.conf 2> /dev/null | pypy3 -u /opt/iridium-toolkit/iridium-parser.py $PARSER_ARGS -o zmq 2>&1 | stdbuf -o0 awk '{print "[iridium-parser] " strftime("%Y/%m/%d %H:%M:%S", systime()) " " $0}' +fi diff --git a/rootfs/etc/s6-overlay/s6-rc.d/iridium-extractor/type b/rootfs/etc/s6-overlay/s6-rc.d/iridium-extractor/type new file mode 100644 index 0000000..5883cff --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/iridium-extractor/type @@ -0,0 +1 @@ +longrun diff --git a/rootfs/etc/s6-overlay/s6-rc.d/iridium-reassembler-map/run b/rootfs/etc/s6-overlay/s6-rc.d/iridium-reassembler-map/run new file mode 100644 index 0000000..38ded18 --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/iridium-reassembler-map/run @@ -0,0 +1,11 @@ +#!/command/with-contenv bash +#shellcheck shell=bash + +echo "Starting map reassembler" +cd /opt/iridium-toolkit/html + +if [[ -n $LOG_MAP ]]; then + pypy3 -u /opt/iridium-toolkit/reassembler.py -i zmq: -m live-map 2>&1 | stdbuf -o0 awk '{print "[iridium-reassembler-map] " strftime("%Y/%m/%d %H:%M:%S", systime()) " " $0}' +else + pypy3 -u /opt/iridium-toolkit/reassembler.py -i zmq: -m live-map &> /dev/null +fi diff --git a/rootfs/etc/s6-overlay/s6-rc.d/iridium-reassembler-map/type b/rootfs/etc/s6-overlay/s6-rc.d/iridium-reassembler-map/type new file mode 100644 index 0000000..5883cff --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/iridium-reassembler-map/type @@ -0,0 +1 @@ +longrun diff --git a/rootfs/etc/s6-overlay/s6-rc.d/iridium-reassembler/run b/rootfs/etc/s6-overlay/s6-rc.d/iridium-reassembler/run new file mode 100644 index 0000000..a02e8f9 --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/iridium-reassembler/run @@ -0,0 +1,6 @@ +#!/command/with-contenv bash +#shellcheck shell=bash + +echo "Starting reassembler" + +pypy3 -u /opt/iridium-toolkit/reassembler.py -i zmq: -m acars -a json --station $STATION_ID > >(nc -u localhost 5558) diff --git a/rootfs/etc/s6-overlay/s6-rc.d/iridium-reassembler/type b/rootfs/etc/s6-overlay/s6-rc.d/iridium-reassembler/type new file mode 100644 index 0000000..5883cff --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/iridium-reassembler/type @@ -0,0 +1 @@ +longrun diff --git a/rootfs/etc/s6-overlay/s6-rc.d/map-server/run b/rootfs/etc/s6-overlay/s6-rc.d/map-server/run new file mode 100644 index 0000000..c73fc1b --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/map-server/run @@ -0,0 +1,11 @@ +#!/command/with-contenv bash +#shellcheck shell=bash + +echo "Starting map-server" +cd /opt/iridium-toolkit/html + +if [[ -n $LOG_MAP ]]; then + python3 -m http.server --bind 0.0.0.0 8888 2>&1 | stdbuf -o0 awk '{print "[map-server] " strftime("%Y/%m/%d %H:%M:%S", systime()) " " $0}' +else + python3 -m http.server --bind 0.0.0.0 8888 &> /dev/null +fi diff --git a/rootfs/etc/s6-overlay/s6-rc.d/map-server/type b/rootfs/etc/s6-overlay/s6-rc.d/map-server/type new file mode 100644 index 0000000..5883cff --- /dev/null +++ b/rootfs/etc/s6-overlay/s6-rc.d/map-server/type @@ -0,0 +1 @@ +longrun diff --git a/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/acars_bridge b/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/acars_bridge new file mode 100644 index 0000000..e69de29 diff --git a/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/iridium-extractor b/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/iridium-extractor new file mode 100644 index 0000000..e69de29 diff --git a/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/iridium-reassembler b/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/iridium-reassembler new file mode 100644 index 0000000..e69de29 diff --git a/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/iridium-reassembler-map b/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/iridium-reassembler-map new file mode 100644 index 0000000..e69de29 diff --git a/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/map-server b/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/map-server new file mode 100644 index 0000000..e69de29 diff --git a/rootfs/etc/s6-overlay/scripts/acars_bridge b/rootfs/etc/s6-overlay/scripts/acars_bridge new file mode 100755 index 0000000..f4d8ef1 --- /dev/null +++ b/rootfs/etc/s6-overlay/scripts/acars_bridge @@ -0,0 +1,35 @@ +#!/command/with-contenv bash +# shellcheck shell=bash + +SCRIPT_NAME="$(basename "$0")" +SCRIPT_NAME="${SCRIPT_NAME%.*}" + +# shellcheck disable=SC2034 +s6wrap=(s6wrap --quiet --timestamps --prepend="$SCRIPT_NAME" --args) +# lets see if legacy SERVER / SERVER_PORT are set + +# detect legacy udp +if [[ "$OUTPUT_SERVER_MODE" == "udp" ]]; then + "${s6wrap[@]}" echo "[WARN] Using UDP mode to connect to $OUTPUT_SERVER:$OUTPUT_SERVER_PORT. Suggest switching to TCP or ZMQ Mode. Please see documentation for more information." +fi + +SOURCE_PORT=5558 +ACARS_BRIDGE_BIN="/opt/acars-bridge" +ACARS_BRIDGE_CMD=(--source-port "$SOURCE_PORT") +ACARS_BRIDGE_CMD+=(--source-protocol "udp") +ACARS_BRIDGE_CMD+=(--source-host "0.0.0.0") + +if [[ -n "$OUTPUT_SERVER" ]]; then + ACARS_BRIDGE_CMD+=(--destination-host "$OUTPUT_SERVER") +fi + +if [[ -n "$OUTPUT_SERVER_PORT" ]]; then + ACARS_BRIDGE_CMD+=(--destination-port "$OUTPUT_SERVER_PORT") +fi + +if [[ -n "$OUTPUT_SERVER_MODE" ]]; then + ACARS_BRIDGE_CMD+=(--destination-protocol "$OUTPUT_SERVER_MODE") +fi + +"${s6wrap[@]}" echo "[INFO] Starting acars-bridge with command: $ACARS_BRIDGE_BIN ${ACARS_BRIDGE_CMD[*]}" +"${s6wrap[@]}" "$ACARS_BRIDGE_BIN" "${ACARS_BRIDGE_CMD[@]}"