diff --git a/config-merger/script/merge_config.py b/config-merger/script/merge_config.py index 8c1c07d..3ae2f7a 100755 --- a/config-merger/script/merge_config.py +++ b/config-merger/script/merge_config.py @@ -132,7 +132,12 @@ def generate_env_file(config, output_dir): adsblol = bool(tar1090_config.get('adsblol_fallback', False)) and sited lines.append("# adsb.lol integration\n") lines.append(f"ADSBLOL_ENABLED={'true' if adsblol else 'false'}\n") - lines.append(f"ADSBLOL_RADIUS={tar1090_config.get('adsblol_radius', 40)}\n\n") + lines.append(f"ADSBLOL_RADIUS={tar1090_config.get('adsblol_radius', 40)}\n") + # Ordered chain of sources the tar1090 proxy tries until one answers. + # Written even when the fallback is off, so turning it on later needs no + # second config change. + upstreams = str(tar1090_config.get('adsb_upstreams') or 'https://api.adsb.lol').strip() + lines.append(f"ADSB_UPSTREAMS={upstreams}\n\n") # External ADS-B feed for readsb adsb_source = tar1090_config.get('adsb_source', '') diff --git a/config-merger/test/test_merge_config.py b/config-merger/test/test_merge_config.py index 0138a79..d87d02c 100755 --- a/config-merger/test/test_merge_config.py +++ b/config-merger/test/test_merge_config.py @@ -1014,6 +1014,40 @@ def test_tracker_removal_does_not_rewrite_user_yml(self): self.assertEqual(user['network']['ports']['track'], 3003) + def test_upstream_chain_written_to_env(self): + """The chain reaches the proxy as ADSB_UPSTREAMS""" + self.write_yaml(os.path.join(self.defaults_dir, 'default.yml'), { + 'tar1090': { + 'adsblol_fallback': True, + 'adsb_upstreams': 'https://adsb.retina.fm,https://api.adsb.lol', + 'location': {'latitude': 42.2, 'longitude': -72.7, 'altitude': 80}, + } + }) + self.write_yaml(os.path.join(self.defaults_dir, 'forced.yml'), {}) + + self.run_merge() + + with open(os.path.join(self.config_dir, 'tar1090.env')) as f: + env = f.read() + self.assertIn('ADSB_UPSTREAMS=https://adsb.retina.fm,https://api.adsb.lol\n', env) + + def test_upstream_chain_falls_back_to_adsblol_when_unset(self): + """A config predating the key still produces a usable chain""" + self.write_yaml(os.path.join(self.defaults_dir, 'default.yml'), { + 'tar1090': { + 'adsblol_fallback': True, + 'location': {'latitude': 42.2, 'longitude': -72.7, 'altitude': 80}, + } + }) + self.write_yaml(os.path.join(self.defaults_dir, 'forced.yml'), {}) + + self.run_merge() + + with open(os.path.join(self.config_dir, 'tar1090.env')) as f: + env = f.read() + self.assertIn('ADSB_UPSTREAMS=https://api.adsb.lol\n', env) + + class TestAtomicWrites(unittest.TestCase): """The compose .env must be replaced whole, never rewritten in place. diff --git a/config/default.yml b/config/default.yml index 50cad7c..e31ec00 100644 --- a/config/default.yml +++ b/config/default.yml @@ -120,6 +120,11 @@ tar1090: adsb_source: "" # Optional local ADS-B receiver (IP,PORT,PROTOCOL). Empty = rely on adsblol_fallback. adsblol_fallback: true adsblol_radius: 40 + # Ordered, comma-separated list of adsb.lol-format sources the tar1090 proxy + # tries until one answers. A local receiver still wins over all of them. + # adsb.lol refuses ~88% of a node's requests with 429, so RETINA's own + # service goes first and adsb.lol sits behind it. + adsb_upstreams: "https://adsb.retina.fm,https://api.adsb.lol" # retina-tracker sidecar (github.com/offworldlabs/retina-tracker) config. # blah2 has no built-in tracker of its own; this sidecar does all tracking. diff --git a/docker-compose.yml b/docker-compose.yml index 32b3565..c264dd8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -120,6 +120,7 @@ services: - TAR1090_DEFAULTCENTERLON=${RECEIVER_LON:-0} # adsb.lol proxy config - ADSBLOL_ENABLED=${ADSBLOL_ENABLED:-false} + - ADSB_UPSTREAMS=${ADSB_UPSTREAMS:-https://api.adsb.lol} - RECEIVER_LAT=${RECEIVER_LAT:-0} - RECEIVER_LON=${RECEIVER_LON:-0} - ADSBLOL_RADIUS=${ADSBLOL_RADIUS:-40} diff --git a/staging/docker-compose.staging.yml b/staging/docker-compose.staging.yml index d19f36b..f770e99 100644 --- a/staging/docker-compose.staging.yml +++ b/staging/docker-compose.staging.yml @@ -106,6 +106,7 @@ services: - TAR1090_DEFAULTCENTERLON=${RECEIVER_LON:--84.65191} # adsb.lol proxy config - ADSBLOL_ENABLED=${ADSBLOL_ENABLED:-true} + - ADSB_UPSTREAMS=${ADSB_UPSTREAMS:-https://api.adsb.lol} - RECEIVER_LAT=${RECEIVER_LAT:-33.939182} - RECEIVER_LON=${RECEIVER_LON:--84.65191} - ADSBLOL_RADIUS=${ADSBLOL_RADIUS:-40}