diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4e63957..431ef0e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.4.0 + rev: v4.5.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -12,11 +12,11 @@ repos: - id: check-builtin-literals - repo: https://github.com/asottile/setup-cfg-fmt - rev: v1.16.0 + rev: v2.5.0 hooks: - id: setup-cfg-fmt - repo: https://github.com/dizballanze/gray - rev: v0.10.1 + rev: v0.14.0 hooks: - id: gray diff --git a/aprsd/cmds/server.py b/aprsd/cmds/server.py index b1848ae..89a6c74 100644 --- a/aprsd/cmds/server.py +++ b/aprsd/cmds/server.py @@ -11,7 +11,7 @@ from aprsd import main as aprsd_main from aprsd import packets, plugin, threads, utils from aprsd.main import cli from aprsd.rpc import server as rpc_server -from aprsd.threads import rx, tx +from aprsd.threads import registry, rx, tx CONF = cfg.CONF @@ -112,6 +112,11 @@ def server(ctx, flush): bcn_thread = tx.BeaconSendThread() bcn_thread.start() + if CONF.aprs_registry.enabled: + LOG.info("Registry Enabled. Starting Registry thread.") + registry_thread = registry.APRSRegistryThread() + registry_thread.start() + if CONF.rpc_settings.enabled: rpc = rpc_server.APRSDRPCThread() rpc.start() diff --git a/aprsd/conf/common.py b/aprsd/conf/common.py index e615601..553c9ea 100644 --- a/aprsd/conf/common.py +++ b/aprsd/conf/common.py @@ -24,6 +24,11 @@ webchat_group = cfg.OptGroup( title="Settings specific to the webchat command", ) +registry_group = cfg.OptGroup( + name="aprs_registry", + title="APRS Registry settings", +) + aprsd_opts = [ cfg.StrOpt( @@ -222,6 +227,39 @@ webchat_opts = [ ), ] +registry_opts = [ + cfg.StrOpt( + "enabled", + default=False, + help="Enable sending aprs registry information. This will let the " + "APRS registry know about your service and it's uptime. " + "No personal information is sent, just the callsign, uptime and description. " + "The service callsign is the callsign set in [DEFAULT] section.", + ), + cfg.StrOpt( + "description", + default=None, + help="Description of the service to send to the APRS registry. " + "This is what will show up in the APRS registry." + "If not set, the description will be the same as the callsign.", + ), + cfg.StrOpt( + "registry_url", + default="https://aprs.hemna.com", + help="The APRS registry domain name to send the information to.", + ), + cfg.StrOpt( + "service_website", + default=None, + help="The website for your APRS service to send to the APRS registry.", + ), + cfg.StrOpt( + "frequency_seconds", + default=900, + help="The frequency in seconds to send the APRS registry information.", + ), +] + def register_opts(config): config.register_opts(aprsd_opts) @@ -234,6 +272,8 @@ def register_opts(config): config.register_opts(rpc_opts, group=rpc_group) config.register_group(webchat_group) config.register_opts(webchat_opts, group=webchat_group) + config.register_group(registry_group) + config.register_opts(registry_opts, group=registry_group) def list_opts(): @@ -243,4 +283,5 @@ def list_opts(): watch_list_group.name: watch_list_opts, rpc_group.name: rpc_opts, webchat_group.name: webchat_opts, + registry_group.name: registry_opts, } diff --git a/aprsd/threads/registry.py b/aprsd/threads/registry.py new file mode 100644 index 0000000..10e03d7 --- /dev/null +++ b/aprsd/threads/registry.py @@ -0,0 +1,46 @@ +import logging + +from oslo_config import cfg +import requests + +from aprsd import stats +from aprsd import threads as aprsd_threads + + +CONF = cfg.CONF +LOG = logging.getLogger("APRSD") + +class APRSRegistryThread(aprsd_threads.APRSDThread): + """This sends service information to the configured APRS Registry.""" + _loop_cnt: int = 1 + + def __init__(self): + super().__init__("APRSRegistryThread") + self._loop_cnt = 1 + if not CONF.registry.enabled: + LOG.error( + "APRS Registry is not enabled. ", + ) + LOG.error( + "APRS Registry thread is STOPPING.", + ) + self.stop() + + def loop(self): + # Only call the registry every N seconds + if self._loop_cnt % CONF.registry.frequency_seconds == 0: + info = { + "callsign": CONF.callsign, + "description": CONF.registry.description, + "service_website": CONF.registry.service_website, + "uptime": stats.APRSDStats().uptime, + } + try: + requests.post( + f"{CONF.registry.registry_url}/api/v1/register", + json=info, + ) + except Exception as e: + LOG.error(f"Failed to send registry info: {e}") + + return True