Catalog PyPI
PACKAGE EXPLORERView in registry

afsapi

PyPI

Asynchronous implementation of the Frontier Silicon API

Versions collected1
Direct dependencies2From release 1.0.3
Last observed20 Oct, 21:13 UTC

README

Version 1.0.3 documentation

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())

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
1.0.316 Oct 20262

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
wlcrs/python-afsapi

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 21:13 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:cb7005b0897d1fbf89fe89ccf59da3fd89cae461894f35e5e7d9fd90aea605e8