Skip to content

Commit

Permalink
add various logging, change output to UDP to acarshub, update readme
Browse files Browse the repository at this point in the history
  • Loading branch information
rpatel3001 committed Mar 24, 2024
1 parent 2dc64be commit fbb9d21
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 54 deletions.
41 changes: 16 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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:
Expand All @@ -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.

```
{
Expand Down Expand Up @@ -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.

```
{
Expand Down Expand Up @@ -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
}
}
}
Expand Down Expand Up @@ -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
}
}
}
Expand Down Expand Up @@ -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
}
}
}
Expand Down Expand Up @@ -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
}
}
}
Expand Down Expand Up @@ -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
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion rootfs/etc/s6-overlay/s6-rc.d/reformat/run
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 6 additions & 1 deletion rootfs/etc/s6-overlay/s6-rc.d/satdump/run
Original file line number Diff line number Diff line change
Expand Up @@ -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
69 changes: 42 additions & 27 deletions rootfs/etc/scripts/reformat.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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()

Expand All @@ -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

Expand All @@ -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", "")),
Expand All @@ -261,41 +268,49 @@ def thread_wrapper(func, *args):
}

if data.get("libacars", {}).get("arinc622", {}).get("cpdlc"):
out["decodedText"] = {
out["decodedText"] = dumps({
"decoder": {
"decodedStatus": "partial"
},
"formatted": {
"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"
},
"formatted": {
"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"
},
"formatted": {
"label": data.get("libacars", {}).get("arinc622", {}).get("msg_type", ""),
"value": dumps(data.get("libacars", {}).get("arinc622", ""))
}
}
})

if out.get("decodedText"):
# out["libacars"] = f"<p>Decoded:</p><p><pre>{data['libacars']}</pre></p>"
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:
Expand Down

0 comments on commit fbb9d21

Please sign in to comment.