Skip to main content

python-afsapi

Asynchronous Python implementation of the Frontier Silicon API

Runtime dependency:

  • aiohttp
  • defusedxml

Development workflow (uv + ruff):

uv sync --group dev
uv run ruff check .
uv run pytest -q

Device recording tests (pytest-recording)

The repository includes integration tests that can record and replay real responses from the development radio.

  • Tests are in tests/test_device_recordings.py (read calls) and tests/test_device_recordings_write.py (write calls with state restore).
  • Cassettes are stored under tests/cassettes/.
  • Device tests replay cassettes by default (pytest runs them with no live device access).
  • Live/recording runs require both AFSAPI_DEVICE_IP and AFSAPI_DEVICE_PIN.

Set device IP + PIN and record fresh cassettes:

AFSAPI_DEVICE_IP="192.168.1.183" AFSAPI_DEVICE_PIN="1234" uv run pytest tests/test_device_recordings.py tests/test_device_recordings_write.py --run-device-tests --record-mode=once -q

Re-record all cassettes:

AFSAPI_DEVICE_IP="192.168.1.183" AFSAPI_DEVICE_PIN="1234" uv run pytest tests/test_device_recordings.py tests/test_device_recordings_write.py --run-device-tests --record-mode=all -q

Run default tests without touching the device:

uv run pytest -q

Usage

Navigation list readiness

nav_list() and get(Nodes.nav_list) collect the complete directory before returning items. Some radios need additional time after enabling navigation or changing folders: list reads can raise FSNodeBlockedError or return an FS_OK loading placeholder with item type 255 (sometimes without a name). These two conditions trigger up to 8 complete read attempts, separated by 1 second: at most 7 seconds of added retry sleeps, not an overall wall-clock timeout. HTTP request timeouts and time spent reading all pages are additional. A successful first read incurs no extra delay.

Each retry starts reading from the first page and discards the incomplete attempt; partial results are never yielded or duplicated. If the last read is still blocked, its FSNodeBlockedError is propagated. A persistent loading placeholder raises FSNodeBlockedError with a loading-specific message. Other errors and cancellation propagate without readiness retries. Navigation SET commands, other endpoints, and the low-level handle_list() iterator keep their existing behavior; no navigation state changes are replayed by this retry policy. A genuinely empty list remains an empty list.

This handles delayed readiness, not changes made by other clients to the radio's global navigation state, nor pagination/cadence limits on very large station directories.

import asyncio
from afsapi import AFSAPI

URL = 'http://192.168.1.XYZ:80/device'
PIN = 1234
TIMEOUT = 1 # in seconds

async def test():
    afsapi = await AFSAPI.create(URL, PIN, TIMEOUT)

    print(f'Set power succeeded? - {await afsapi.set_power(True)}' )
    print(f'Power on: {await afsapi.get_power()}')
    print(f'Friendly name: {await afsapi.get_friendly_name()}')

    for mode in await afsapi.get_modes():
        print(f'Available Mode: {mode}')
    print(f'Current Mode: {await afsapi.get_mode()}')

    for equaliser in await afsapi.get_equalisers():
        print(f'Equaliser: {equaliser}')

    print(f'EQ Preset: {await afsapi.get_eq_preset()}' )

    for preset in await afsapi.get_presets():
        print(f"Preset: {preset}")

    print(f'Set power succeeded? - {await afsapi.set_power(False)}')
    print(f'Set sleep succeeded? - {await afsapi.set_sleep(10)}')
    print(f'Sleep: {await afsapi.get_sleep()}')
    print(f'Get power {await afsapi.get_power()}' )


loop = asyncio.new_event_loop()
loop.run_until_complete(test())

Metadata

Release files for afsapi 1.0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for afsapi 1.0.3
File Size Uploaded Provenance Actions
afsapi-1.0.3.tar.gz 145.6 kB Without provenance Details for afsapi-1.0.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for afsapi 1.0.3
File Interpreter ABI Platform Actions
afsapi-1.0.3-py3-none-any.whl Python 3 none any Details for afsapi-1.0.3-py3-none-any.whl

Total release size: 169.9 kB

Release files / afsapi-1.0.3.tar.gz

Download URL afsapi-1.0.3.tar.gz
Size 145.6 kB
Tags Source
SHA-256 checksum
How to use checksums
83049a396799b6340c358383704008f5735d08010d36cb59f6922c58157b1e91
BLAKE2b-256 checksum
How to use checksums
c684adcdd85fa574704a521aa6c1613cd91013274c3fa9491833300d44835dd1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / afsapi-1.0.3-py3-none-any.whl

Download URL afsapi-1.0.3-py3-none-any.whl
Size 24.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e3f94abac18a0fe51041fae7036f6e2c6b96c55444de0aec7673261831b0fb3d
BLAKE2b-256 checksum
How to use checksums
798595d9397c90e1aebcf604702070c4196da917c87efded981546f278ba5567
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Security for afsapi 1.0.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page