diff --git a/README.md b/README.md index ef89dd3..7f966b3 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,13 @@ docker logs -f satdump | grep -v "(D)" | grep -v "Table Broadcast" | grep -v "Re | Variable | Description | Default | |----------|-------------|---------| -| `RUN_CMD` | The command to run when the container starts. The container will restart when it returns. | Unset | -| `JSON_OUT` | The `host:port` to forward reformatted JSON messages to. | `acars_router:5550` | +| `RUN_CMD` | The command to run when the container starts. The container will restart when it returns. | Unset | +| `UDP_IN` | The UDP port for the JSON reformatter to listen for raw satdump JSON on. This is set in udp_sinks sections of the Inmarsat.json file. | `5557` | +| `JSON_OUT` | The UDP `host:port` to forward reformatted JSON messages to. | `acarshub:5557` | +| `LOG_RAW` | Set to any value to log the output of the satdump command to stdout. | Unset | +| `LOG_IN_JSON` | Set to any value to log the JSON output of satdump to stdout. | Unset | +| `LOG_IN_JSON_FILT` | Set to any value to log the JSON output of satdump to stdout, after filtering out non-ACARS messages. | Unset | +| `LOG_OUT_JSON` | Set to any value to log the reformatted JSON output to stdout. | Unset | ## Docker Compose @@ -45,7 +50,7 @@ services: # - RUN_CMD=satdump live inmarsat_aero_6 /tmp/satdump_out --source rtlsdr --source_id 0 --gain 49 --samplerate 1.536e6 --frequency 1545.6e6 --multi_vfo /vfo.json 2>&1 | grep -v "Invalid CRC!" acarshubsat: - image: ghcr.io/sdr-enthusiasts/docker-acarshub:latest + build: https://github.com/rpatel3001/docker-acarshub.git#inmarsat-L container_name: acarshubsat restart: always ports: @@ -56,27 +61,13 @@ services: - /var/log:size=64M environment: - TZ=America/New_York - - ENABLE_ACARS=external - - MIN_LOG_LEVEL=3 - - acars_router: - image: ghcr.io/sdr-enthusiasts/acars_router:latest - container_name: acars_router - restart: always - environment: - - TZ=America/New_York - - AR_SEND_UDP_ACARS=acarshubsat:5550 - tmpfs: - - /run:exec,size=64M - - /var/log - - + - ENABLE_IMSL=external ``` The above setup is intended to decode Inmarsat 4F3 98W from an rtl_tcp stream at 10.0.0.114:7373. To directly use an RTL-SDR instead, uncomment the `cgroup` and `/dev` lines and switch which `RUN_CMD` line is commented. You may need to change the `--source_id` if you have more than one RTL-SDR. -`vfo.json` contains the frequencies and decoder pipelines being used. You'll note that they are not exact due to an approximately 3.11 kHz frequency error in my RTL-SDR. You will likely need to look at a waterfall and adjust these values based on your specific device. They may even need tuning as ambient temperature changes. +`vfo.json` contains the frequencies and decoder pipelines being used. You'll note that they are not exact due to an approximately 3.8 kHz frequency error in my RTL-SDR. You will likely need to look at a waterfall and adjust these values based on your specific device. They may even need tuning as ambient temperature or the tuned center frequency changes. I have since bought a Nooelec SMArt XTR which does not require any offset. ``` { @@ -175,7 +166,7 @@ The above setup is intended to decode Inmarsat 4F3 98W from an rtl_tcp stream at } ``` -`Inmarsat.json` overrides the default settings for each decoder pipeline, including station_id, udp_sink, and save_file. The below file does not save files, sends every decoder pipeline's output to 10.0.0.14:5556, and sets a `station_id` based on the pipeline. +`Inmarsat.json` overrides the default settings for each decoder pipeline, including station_id, udp_sink, and save_file. The below file does not save files, sends every decoder pipeline's output to 10.0.0.14:5557, and sets a `station_id` based on the pipeline. ``` { @@ -218,7 +209,7 @@ The above setup is intended to decode Inmarsat 4F3 98W from an rtl_tcp stream at "udp_sinks": { "test": { "address": "127.0.0.1", - "port": 5556 + "port": 5557 } } } @@ -266,7 +257,7 @@ The above setup is intended to decode Inmarsat 4F3 98W from an rtl_tcp stream at "udp_sinks": { "test": { "address": "127.0.0.1", - "port": 5556 + "port": 5557 } } } @@ -313,7 +304,7 @@ The above setup is intended to decode Inmarsat 4F3 98W from an rtl_tcp stream at "udp_sinks": { "test": { "address": "127.0.0.1", - "port": 5556 + "port": 5557 } } } @@ -363,7 +354,7 @@ The above setup is intended to decode Inmarsat 4F3 98W from an rtl_tcp stream at "udp_sinks": { "test": { "address": "127.0.0.1", - "port": 5556 + "port": 5557 } } } @@ -417,7 +408,7 @@ The above setup is intended to decode Inmarsat 4F3 98W from an rtl_tcp stream at "udp_sinks": { "test": { "address": "127.0.0.1", - "port": 5556 + "port": 5557 } } } diff --git a/rootfs/etc/s6-overlay/s6-rc.d/reformat/run b/rootfs/etc/s6-overlay/s6-rc.d/reformat/run index 70560e4..1cf808a 100644 --- a/rootfs/etc/s6-overlay/s6-rc.d/reformat/run +++ b/rootfs/etc/s6-overlay/s6-rc.d/reformat/run @@ -4,4 +4,5 @@ # shellcheck disable=SC1091 #sleep 86400 echo "starting JSON reformatter" -exec python3 -u /etc/scripts/reformat.py 2>&1 + +exec python3 -u /etc/scripts/reformat.py diff --git a/rootfs/etc/s6-overlay/s6-rc.d/satdump/run b/rootfs/etc/s6-overlay/s6-rc.d/satdump/run index 5a81551..6be8ad4 100644 --- a/rootfs/etc/s6-overlay/s6-rc.d/satdump/run +++ b/rootfs/etc/s6-overlay/s6-rc.d/satdump/run @@ -4,4 +4,9 @@ # shellcheck disable=SC1091 #sleep 86400 echo "running command: $RUN_CMD" -exec bash -c "$RUN_CMD" + +if [ -n "${LOG_RAW}" ]; then + exec bash -c "$RUN_CMD" +else + exec bash -c "$RUN_CMD > /dev/null" +fi diff --git a/rootfs/etc/scripts/reformat.py b/rootfs/etc/scripts/reformat.py index a6fcfde..8aea312 100644 --- a/rootfs/etc/scripts/reformat.py +++ b/rootfs/etc/scripts/reformat.py @@ -31,14 +31,14 @@ def rx_thread(port, rxq): def tx_thread(host, txq): prctl.set_name(f"tx {host[0]}:{host[1]}") enc = locale.getpreferredencoding(False) -# sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.connect(host) + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +# sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +# sock.connect(host) print(f"Connected to JSON output at {host[0]}:{host[1]}") while True: msg = txq.get() - sock.sendall(msg.encode(enc)) -# sock.sendto(msg.encode(enc), host) +# sock.sendall(msg.encode(enc)) + sock.sendto(msg.encode(enc), host) # wrapper to catch exceptions and restart threads def thread_wrapper(func, *args): @@ -182,22 +182,21 @@ def thread_wrapper(func, *args): "RIOCDYA": " ", } -json_in = getenv("UDP_IN", "5556") +json_in = getenv("UDP_IN", "5557") json_in = json_in.split(";") json_in = [int(x) for x in json_in] -sbs_out = getenv("JSON_OUT", "acars_router:5550") -#sbs_out = getenv("JSON_OUT", "10.0.0.109:5559") -sbs_out = sbs_out.split(";") -sbs_out = [x.split(":") for x in sbs_out] -sbs_out = [(x,int(y)) for x,y in sbs_out] +json_out = getenv("JSON_OUT", "acarshub:5557") +json_out = json_out.split(";") +json_out = [x.split(":") for x in json_out] +json_out = [(x,int(y)) for x,y in json_out] rxq = SimpleQueue() for p in json_in: Thread(name=f"rx {p}", target=thread_wrapper, args=(rx_thread, p, rxq)).start() txqs = [] -for i,s in enumerate(sbs_out): +for i,s in enumerate(json_out): txqs.append(SimpleQueue()) Thread(name=f"tx {s[0]}:{s[1]}", target=thread_wrapper, args=(tx_thread, s, txqs[-1])).start() @@ -212,6 +211,9 @@ def thread_wrapper(func, *args): # print(f"{raw}\n") data = loads(raw) + if getenv("LOG_IN_JSON"): + pprint(data) + print() if not data or "ACARS" != data.get("msg_name"): continue @@ -234,23 +236,28 @@ def thread_wrapper(func, *args): gsa = ges1.groupdict().get("gs") from_decoded = f"{gsa}/{gesLoc.get(gsa, '')}" + station = data.get("source").get("station_id", "") + try: + statind = station.rindex("-") + except: + statind = len(station) + out = { - "freq": 1545.0 if "6" in data.get("source").get("station_id", "") else 1545.075 if "12" in data.get("source").get("station_id", "") else 1546, - "channel": 0, - "error": 0, - "level": 0.0, + "freq": 1545.0 if "6" in station else 1545.075 if "12" in station else 1546, +# "error": 0, +# "level": 0.0, "timestamp": data.get("timestamp"), "app": { "name": data.get("source", {}).get("app", {}).get("name", ""), "ver": data.get("source", {}).get("app", {}).get("version", "") }, - "station_id": data.get("source").get("station_id", ""), + "station_id": station[:statind], "icao": data.get("signal_unit", {}).get("aes_id", ""), "toaddr": data.get("signal_unit", {}).get("aes_id", ""), "mode": str(data.get("mode", "")), "label": data.get("label", ""), "block_id": str(data.get("bi", "")), - "ack": "", +# "ack": "", "tail": data.get("plane_reg[1:]", ""), "text": data.get("message", ""), "msgno": str(data.get("signal_unit", {}).get("ref_no", "")), @@ -261,7 +268,7 @@ def thread_wrapper(func, *args): } if data.get("libacars", {}).get("arinc622", {}).get("cpdlc"): - out["decodedText"] = { + out["decodedText"] = dumps({ "decoder": { "decodedStatus": "partial" }, @@ -269,9 +276,9 @@ def thread_wrapper(func, *args): "label": data.get("libacars", {}).get("arinc622", {}).get("msg_type", ""), "value": dumps(data.get("libacars", {}).get("arinc622", {}).get("cpdlc", "")) } - } + }) elif data.get("libacars", {}).get("arinc622", {}).get("adsc"): - out["decodedText"] = { + out["decodedText"] = dumps({ "decoder": { "decodedStatus": "partial" }, @@ -279,9 +286,9 @@ def thread_wrapper(func, *args): "label": data.get("libacars", {}).get("arinc622", {}).get("msg_type", ""), "value": dumps(data.get("libacars", {}).get("arinc622", {}).get("adsc", "")) } - } + }) elif data.get("libacars", {}).get("arinc622"): - out["decodedText"] = { + out["decodedText"] = dumps({ "decoder": { "decodedStatus": "partial" }, @@ -289,13 +296,21 @@ def thread_wrapper(func, *args): "label": data.get("libacars", {}).get("arinc622", {}).get("msg_type", ""), "value": dumps(data.get("libacars", {}).get("arinc622", "")) } - } + }) + + if out.get("decodedText"): +# out["libacars"] = f"
Decoded:
{data['libacars']}" + out["libacars"] = data["libacars"] - #pprint(out) - #print() + if getenv("LOG_IN_JSON_FILT"): + pprint(data) + print() + if getenv("LOG_OUT_JSON"): + pprint(out) + print() for q in txqs: - q.put(dumps(out)+"\r\n") + q.put(dumps({"imsl":out})+"\r\n") except KeyboardInterrupt: exit() except BaseException: