diff --git a/utils/adsbexchange-stats/Makefile b/utils/adsbexchange-stats/Makefile new file mode 100644 index 0000000000000..227d82f53c455 --- /dev/null +++ b/utils/adsbexchange-stats/Makefile @@ -0,0 +1,144 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2026 Dr Bill Mcilhargey +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +# Dual-license: OpenWrt packaging files (this Makefile, init script, +# helpers, patches) are GPL-2.0-only. The upstream json-status payload +# (ADSBexchange.com, (c) 2020) remains under its original MIT license. + +include $(TOPDIR)/rules.mk + +PKG_NAME:=adsbexchange-stats +PKG_VERSION:=2023-02-22 +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/ADSBexchange/adsbexchange-stats.git +PKG_SOURCE_VERSION:=11647f27de3eef51fb19bcb39f0dc0b8500a6671 +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.xz +PKG_MIRROR_HASH:=b16c3c708daea4389f1d850aca1c899cfd9827785038c332c4bf28e541ae5992 + +PKG_LICENSE:=MIT GPL-2.0-only +PKG_LICENSE_FILES:=LICENSE + +PKG_MAINTAINER:=Dr Bill Mcilhargey + +include $(INCLUDE_DIR)/package.mk + +define Package/adsbexchange-stats + SECTION:=utils + CATEGORY:=Utilities + TITLE:=ADSBexchange.com statistics uploader + URL:=https://github.com/ADSBexchange/adsbexchange-stats + # Hard-depends on readsb-wiedehopf: shares feeder identity, the + # readsb-uuid CLI, and /usr/lib/readsb/functions.sh. + # gzip is intentionally omitted -- BusyBox provides the `gzip` applet + # which is what the upload path uses; +gzip would pull standalone GNU + # gzip and break opkg dep resolution on stock feeds. + DEPENDS:=+bash +jq +curl +coreutils-stat +readsb-wiedehopf + PKGARCH:=all +endef + +define Package/adsbexchange-stats/description + ADSBexchange.com statistics uploader for OpenWrt. + + Periodically reads aircraft.json from readsb (via readsb-wiedehopf), + aggregates per-aircraft RSSI and counts, and POSTs the result to + https://adsbexchange.com identified by the selected enabled feeder's + UUID (its override, or readsb.main.uuid). Installation does not enable + or start uploads. Use readsb-feeder --setup-companions to opt in. + + Service knobs live in /etc/config/adsbexchange-stats. + Manage the station UUID with `readsb-uuid`. + + Daemon control: + service adsbexchange-stats {start|stop|restart|reload|status|enable|disable} + logread -e adsbexchange-stats -- uploader logs + + Extra (non-procd) actions: + service adsbexchange-stats showurl + -- print the public per-station + ADSBexchange stats URL + (derived from the selected feeder) + service adsbexchange-stats about -- package and configuration help + service adsbexchange-stats activate + -- consent to statistics uploads + for an enabled ADSBexchange feeder +endef + +# Pure shell payload; nothing to compile or stage-install. +Build/Configure:=: +Build/Compile:=: +Build/Install:=: + +define Package/adsbexchange-stats/conffiles +/etc/config/adsbexchange-stats +endef + +define Package/adsbexchange-stats/install + $(INSTALL_DIR) \ + $(1)/etc/config \ + $(1)/etc/init.d \ + $(1)/usr/lib/adsbexchange-stats \ + $(1)/usr/share/adsbexchange-stats + $(INSTALL_BIN) $(PKG_BUILD_DIR)/json-status $(1)/usr/share/adsbexchange-stats/json-status + $(INSTALL_CONF) ./files/adsbexchange-stats.config $(1)/etc/config/adsbexchange-stats + $(INSTALL_BIN) ./files/adsbexchange-stats.init $(1)/etc/init.d/adsbexchange-stats + $(INSTALL_DATA) ./files/adsbexchange-stats.functions.sh $(1)/usr/lib/adsbexchange-stats/functions.sh + $(INSTALL_DATA) ./files/adsbexchange-stats.json-status-helpers.sh \ + $(1)/usr/lib/adsbexchange-stats/json-status-helpers.sh + # Substitute @PKG_*@ placeholders in the init banner so values + # stay sourced from this Makefile (PKG_VERSION/PKG_MAINTAINER/...). + $(SED) 's,@PKG_VERSION@,$(PKG_VERSION)-$(PKG_RELEASE),g' $(1)/etc/init.d/adsbexchange-stats + $(SED) 's,@PKG_LICENSE@,$(PKG_LICENSE),g' $(1)/etc/init.d/adsbexchange-stats + $(SED) 's,@PKG_URL@,https://github.com/ADSBexchange/adsbexchange-stats,g' $(1)/etc/init.d/adsbexchange-stats + $(SED) 's,@PKG_MAINTAINER@,$(PKG_MAINTAINER),g' $(1)/etc/init.d/adsbexchange-stats +endef + +define Package/adsbexchange-stats/postinst +#!/bin/sh +[ -n "$${IPKG_INSTROOT}" ] && exit 0 +[ "$${PKG_UPGRADE}" = "1" ] && { +/etc/init.d/adsbexchange-stats enabled && /etc/init.d/adsbexchange-stats restart +exit 0 +} +cat <<'EOF' +adsbexchange-stats installed; statistics uploads remain disabled. + Optional setup: readsb-feeder --setup-companions + Uploads require separate explicit consent and use the selected feeder UUID. + Help: service adsbexchange-stats about +EOF +exit 0 +endef + +define Package/adsbexchange-stats/prerm +#!/bin/sh +# Stop and disable before opkg removes the init script. Output is +# silenced because procd's `service delete` ubus call emits a harmless +# "Command failed: Not found" when no live service entry exists. +[ -n "$${IPKG_INSTROOT}" ] && exit 0 +[ "$${PKG_UPGRADE}" = "1" ] && exit 0 +{ + if [ -x /etc/init.d/adsbexchange-stats ]; then + /etc/init.d/adsbexchange-stats running && \ + /etc/init.d/adsbexchange-stats stop + /etc/init.d/adsbexchange-stats disable + fi +} >/dev/null 2>&1 +exit 0 +endef + +define Package/adsbexchange-stats/postrm +#!/bin/sh +# Tidy the runtime dir; /var/run is tmpfs and would clear at reboot +# anyway. Intentionally untouched: readsb.main.uuid (shared station +# identity) and /etc/config/adsbexchange-stats (opkg `conffiles`). +[ -n "$${IPKG_INSTROOT}" ] && exit 0 +rm -rf /var/run/adsbexchange-stats +exit 0 +endef + +$(eval $(call BuildPackage,adsbexchange-stats)) diff --git a/utils/adsbexchange-stats/README.md b/utils/adsbexchange-stats/README.md new file mode 100644 index 0000000000000..48aaa2e2aa7ff --- /dev/null +++ b/utils/adsbexchange-stats/README.md @@ -0,0 +1,322 @@ +# adsbexchange-stats + +Optional ranking-dashboard statistics uploader for ADSBexchange.com on +OpenWrt. Companion to [`readsb-wiedehopf`](../readsb-wiedehopf/) -- it +periodically reads `aircraft.json` from the local readsb daemon, +aggregates per-aircraft RSSI and counts, and POSTs the result to +ADSBexchange identified by the selected feeder's effective UUID. Pure feeding does +**not** require this package; install it only if you want your station +listed on the per-station web ranking. + +## Contents + +* [Quick start](#quick-start) +* [What gets installed](#what-gets-installed) +* [Configuration](#configuration) + * [`/etc/config/adsbexchange-stats` -- main section options](#etcconfigadsbexchange-stats----main-section-options) +* [Station UUID](#station-uuid) +* [Service control](#service-control) +* [Logging and diagnostics](#logging-and-diagnostics) + * [Log levels](#log-levels) +* [Relationship to readsb-wiedehopf](#relationship-to-readsb-wiedehopf) +* [Tests](#tests) +* [License](#license) + +## Quick start + +```sh +opkg install readsb-wiedehopf # required dependency +opkg install adsbexchange-stats +readsb-uuid # station UUID, unless the feeder overrides it +readsb-feeder --setup-companions adsbx # use your enabled ADSBx feeder section name +service adsbexchange-stats showurl # print this station's stats URL +``` + +Installation **does not enable or start uploads**. OpenWrt's generic +package hooks may register and invoke the init script, but the default +`enabled=0` permission prevents any uploader process from starting. +The readsb wizard +offers the optional package only when installed or available in cached +configured-feed metadata. A separate default-No prompt explains the +statistics upload before installation or activation. Selecting No leaves +normal ADSBexchange feeding unchanged. + +For explicit noninteractive activation (this command constitutes consent +to the external statistics upload): + +```sh +service adsbexchange-stats activate adsbx +``` + +The named section must exist, use `preset adsbexchange`, be enabled, +and have a valid effective UUID. `activate` selects it, enables the +uploader's UCI setting and boot service, then restarts the uploader. +Pending readsb or uploader edits must be explicitly committed or +reverted before activation. +There is one uploader selection; changing it replaces the previous +selection rather than starting a second upload process. + +Upgrades preserve the existing boot-enable state and do not auto-enable +a previously disabled service. Older installations that have no +`feeder` selection must explicitly select one before uploading; the +package never guesses which of several feeders to use. + +To watch the uploader: + +```sh +logread -e adsbexchange-stats +``` + +## What gets installed + +| Path | Purpose | +| ----------------------------------------------------- | ------------------------------------------------------------------------------------ | +| `/usr/share/adsbexchange-stats/json-status` | patched upstream uploader (bash; runs under procd) | +| `/etc/config/adsbexchange-stats` | UCI config (declarative; see below) | +| `/etc/init.d/adsbexchange-stats` | procd service and `activate`, `showurl`, `about` actions | +| `/usr/lib/adsbexchange-stats/functions.sh` | shared sh helpers (logging, UUID, json path resolution) | +| `/usr/lib/adsbexchange-stats/json-status-helpers.sh` | upload-side helpers (curl wrapper, periodic summary) | +| `/var/run/adsbexchange-stats/` | runtime dir (env file, uuid, scratch JSON; tmpfs) | + +## Configuration + +`/etc/config/adsbexchange-stats` is **declarative-only by design** -- +it carries options, not documentation. Comments (lines starting with +`#`) do not survive `uci commit`: every committer (manual `uci`, LuCI, +this package's own reload trigger, `readsb-uuid`) rewrites the file in +canonical form and strips them. All option documentation therefore +lives in this source-repository README and in `service adsbexchange-stats about`, never +inside the conffile itself. (The same convention is used by the +companion `readsb-wiedehopf` package.) + +The init script reads the conffile together with the selected feeder's +UUID and `readsb.main.write_json` from `/etc/config/readsb`, renders an env +file at `/var/run/adsbexchange-stats/env`, and supervises the uploader +under procd. +Scalar values in that generated file are shell-quoted, including log +tags and runtime paths; quotes, whitespace, and shell punctuation are +preserved as data rather than interpreted as commands. + +The shared helpers preserve preconfigured `ADSBX_RUNTIME_DIR`, +`ADSBX_ENV_FILE`, `ADSBX_UUID_FILE`, and `ADSBX_UPLOADER` values. +When file paths are unset, they are derived from the runtime directory. + +Reload triggers are registered on **both** `adsbexchange-stats` and +`readsb`, so the recommended workflow is: + +```sh +uci set adsbexchange-stats.main.