Skip to content

naneos.uploader

The naneos-uploader command: gather from every device in reach and upload.

This is what the Raspberry Pi service runs (see installers/install.sh). It can also be started by hand, for example to test a Pi without uploading:

naneos-uploader --no-upload --interval 10

installed_from()

Where pip got the package from (a git archive URL, a path) or "PyPI".

Lets the first log line tell which branch or tag a Pi is running, since the version number alone does not.

Source code in src/naneos/uploader.py
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
def installed_from() -> str:
    """Where pip got the package from (a git archive URL, a path) or "PyPI".

    Lets the first log line tell which branch or tag a Pi is running, since the
    version number alone does not.
    """
    try:
        text = distribution("naneos-devices").read_text("direct_url.json")
    except PackageNotFoundError:
        return "an uninstalled checkout"
    if not text:
        return "PyPI"
    try:
        return str(json.loads(text).get("url", "unknown source"))
    except ValueError:
        return "unknown source"

warn_if_wifi_power_save_on()

Log a warning if the WiFi chip is allowed to sleep.

Turning it off needs root and outlives the process, so the installer does that. This service runs as an unprivileged user and can only report it: on a Pi Zero 2 W power save parks the link when idle, which stalls uploads and costs BLE airtime on the antenna the two radios share.

Source code in src/naneos/uploader.py
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
def warn_if_wifi_power_save_on() -> None:
    """Log a warning if the WiFi chip is allowed to sleep.

    Turning it off needs root and outlives the process, so the installer does
    that. This service runs as an unprivileged user and can only report it: on a
    Pi Zero 2 W power save parks the link when idle, which stalls uploads and
    costs BLE airtime on the antenna the two radios share.
    """
    if shutil.which("iw") is None:
        return

    try:
        result = subprocess.run(["iw", "dev"], capture_output=True, text=True, timeout=5)
        devices = [
            line.split()[1]
            for line in result.stdout.splitlines()
            if line.strip().startswith("Interface")
        ]

        for device in devices:
            result = subprocess.run(
                ["iw", "dev", device, "get", "power_save"],
                capture_output=True,
                text=True,
                timeout=5,
            )
            if "on" in result.stdout.split():
                logger.warning(
                    f"WiFi power save is on for {device}: uploads may stall, and BLE "
                    f"shares the antenna. Run `sudo iw dev {device} set power_save off`, "
                    "or re-run the installer to make it persistent."
                )
    except (OSError, subprocess.SubprocessError) as e:
        logger.debug(f"Could not read WiFi power save state: {e}")