Software Requirements¶
This document defines the software requirements for the PurpleAir API (purpleair_api) package.
Each requirement is identified by a unique feature-grouped ID in the format [PREFIX-nn],
where the prefix indicates the feature area:
Prefix |
Feature Area |
|---|---|
|
General package & platform requirements |
|
Unified PurpleAirAPI client class |
|
Cloud Read API operations |
|
Cloud Write API operations |
|
Local network sensor operations |
|
Matter standard device & cluster conversion |
|
Error handling and exception hierarchy |
|
Request helpers and utility functions |
|
Testing and code coverage |
|
Code quality, formatting, and linting |
|
Documentation and landing page |
|
CI/CD pipelines, concurrency, and release automation |
Functional Requirements¶
General Requirements¶
[GEN-01] The system shall provide a pure Python package installable via pip for interacting
with PurpleAir air quality sensors via cloud and local network APIs.
[GEN-02] The system shall support Python 3.10, 3.11, 3.12, 3.13, and 3.14 across Linux, macOS, and Windows operating systems.
[GEN-03] The system shall use the requests library for executing HTTP and HTTPS requests.
[GEN-04] The package initializer (purpleair_api/__init__.py) shall remain clean and lightweight
to avoid circular dependencies or unwanted side-effects on import.
Unified Client Class¶
[CLIENT-01] The system shall provide a unified entry-point class PurpleAirAPI that inherits from
and combines PurpleAirReadAPI, PurpleAirWriteAPI, and PurpleAirLocalAPI.
[CLIENT-02] The PurpleAirAPI initializer shall accept your_api_read_key,
your_api_write_key, and your_ipv4_address (list of IPv4 strings) as optional arguments.
[CLIENT-03] The PurpleAirAPI initializer shall raise PurpleAirAPIError if none of
your_api_read_key, your_api_write_key, or your_ipv4_address are provided.
[CLIENT-04] When a read key is provided, PurpleAirAPI shall verify the key against the
https://api.purpleair.com/v1/keys endpoint and verify that the key type is READ;
otherwise, it shall raise PurpleAirAPIError.
[CLIENT-05] When a write key is provided, PurpleAirAPI shall verify the key against the
https://api.purpleair.com/v1/keys endpoint and verify that the key type is WRITE;
otherwise, it shall raise PurpleAirAPIError.
[CLIENT-06] The PurpleAirAPI class shall expose properties get_api_versions,
get_api_key_last_checked, and get_api_key_type providing metadata about verified keys.
[CLIENT-07] Debug logging within PurpleAirAPI shall not log sensitive API keys in plain text.
Cloud Read API Operations¶
[READ-01] The system shall provide a PurpleAirReadAPI class initialized with an optional
api_read_key parameter.
[READ-02] The system shall implement request_sensor_data(sensor_index, read_key, fields) to query
data for a single sensor by its index, with optional sensor-specific read key and field filters.
[READ-03] The system shall implement request_multiple_sensors_data(fields, location_type, read_keys,
show_only, modified_since, max_age, nwlng, nwlat, selng, selat) to retrieve data for multiple
sensors with support for geographic bounding boxes, location types (inside/outside), and timestamp
filters.
[READ-04] The system shall implement request_sensor_historic_data(sensor_index, read_key,
fields, start_timestamp, end_timestamp, average) to query historical readings with configurable
averaging periods (e.g., 10 minutes, 30 minutes, 1 hour, 6 hours, 1 day, 1 week, 1 month, 1 year).
[READ-05] The system shall implement request_group_list_data() to retrieve all sensor groups
associated with the authenticated account.
[READ-06] The system shall implement request_group_detail_data(group_id) to retrieve metadata
and sensor members for a specific group.
[READ-07] The system shall implement request_member_data(group_id, member_id, fields) to
retrieve current readings for an individual member of a sensor group.
[READ-08] The system shall implement request_member_historic_data(group_id, member_id, fields,
start_timestamp, end_timestamp, average) to retrieve historical readings for an individual group
member.
[READ-09] The system shall implement request_members_data(group_id, fields, location_type,
read_keys, show_only, modified_since, max_age, nwlng, nwlat, selng, selat) to query data across
all members of a sensor group.
[READ-10] The system shall implement request_organization_data() to query organization-level
sensor allocations and metadata.
Cloud Write API Operations¶
[WRITE-01] The system shall provide a PurpleAirWriteAPI class initialized with an optional
api_write_key parameter.
[WRITE-02] The system shall implement post_create_group_data(name) to create a new sensor group
on the PurpleAir cloud service.
[WRITE-03] The system shall implement post_create_member(group_id, sensor_index, sensor_id) to
add a sensor member to a designated group using its sensor index or sensor ID.
[WRITE-04] The system shall implement post_delete_group(group_id) to delete an existing sensor
group.
[WRITE-05] The system shall implement post_delete_member(group_id, member_id) to remove a member
from a sensor group.
Local Network Sensor Operations¶
[LOCAL-01] The system shall provide a PurpleAirLocalAPI class initialized with a list of IPv4
address strings representing local network sensors.
[LOCAL-02] The PurpleAirLocalAPI initializer shall validate IPv4 address formatting and raise
PurpleAirAPIError if the address list is empty, non-list, or contains invalid IP strings.
[LOCAL-03] The system shall implement request_local_sensor_data() to query sensor data directly
over HTTP from each configured sensor at http://<ipv4>/json.
[LOCAL-04] The system shall raise PurpleAirDeviceOfflineError with clear diagnostic details
when a local sensor is unreachable or encounters a network error.
Matter Standards Conversion¶
[MATTER-01] The system shall provide a PurpleAirMatterConverter class compliant with the
Connectivity Standards Alliance (CSA) Matter 1.5.1 Specification.
[MATTER-02] The system shall convert PurpleAir sensor data into Matter Air Quality Sensor Device
Type structures (Device Type ID 0x002D).
[MATTER-03] The system shall map readings into standard Matter clusters:
Air Quality Measurement Cluster (
0x005D)Temperature Measurement Cluster (
0x0402)Relative Humidity Measurement Cluster (
0x0405)Barometric Pressure Measurement Cluster (
0x0403)Carbon Dioxide Concentration Measurement Cluster (
0x040D)
[MATTER-04] The system shall calculate EPA Air Quality Index (AQI) values and ratings from PM2.5 measurements per official EPA AQI piecewise linear breakpoint equations.
[MATTER-05] The system shall provide unit conversion utilities including Fahrenheit to Celsius (for Matter 0.01 °C precision) and PSI to kPa (for Matter 0.1 kPa precision).
[MATTER-06] The system shall handle offline or unreachable sensors by setting air quality
ratings to UNKNOWN (0x00) and reporting appropriate status flags per Matter specifications.
Error and Exception Handling¶
[ERR-01] The system shall provide a base exception class PurpleAirAPIError inheriting from
Python’s standard Exception.
[ERR-02] The system shall provide PurpleAirDeviceError and PurpleAirDeviceOfflineError
for local device connectivity and communication failures.
[ERR-03] HTTP response errors shall capture and surface the HTTP status code, URL, and response body from the PurpleAir API service in error messages.
Helper and Utility Functions¶
[HELP-01] The system shall provide PurpleAirAPIHelpers containing reusable URL construction,
parameter formatting, and HTTP request dispatching methods (send_url_get_request,
send_url_post_request, send_url_delete_request).
[HELP-02] Common API query parameters (such as lists of fields or read keys) shall be automatically comma-separated and properly URL-encoded.
[HELP-03] The system shall support a debug mode toggled via debug_log without leaking sensitive
credentials in logs.
Non-Functional Requirements¶
Testing and Code Coverage¶
[TEST-01] The system shall maintain 100% statement and branch code coverage across all modules in the package.
[TEST-02] Unit tests shall run via Python’s standard unittest test runner with coverage.py.
[TEST-03] Unit tests shall use requests_mock to simulate HTTP responses for all cloud and local
endpoints without making live network calls during test execution.
[TEST-04] Unit tests shall execute cleanly across Ubuntu, macOS, and Windows runners for all supported Python versions (3.10 through 3.14).
Code Quality and Verification¶
[QUAL-01] All Python code shall adhere to the Black code style and pass automated formatting
checks in CI (.github/workflows/black.yml).
[QUAL-02] All GitHub Actions workflow YAML files shall adhere to strict formatting and pass
validation via yamllint using the repository’s .yamllint configuration.
[QUAL-03] Workflows managed by GitHub Agentic Workflows (gh-aw) shall compile cleanly
without warnings or errors via gh aw compile.
Documentation¶
[DOCS-01] Project documentation shall be authored in reStructuredText (reST) and built using Sphinx with the Furo theme.
[DOCS-02] All public modules, classes, and methods shall have comprehensive docstrings compliant
with Sphinx autodoc standards.
[DOCS-03] The project shall maintain a dedicated landing page under sphinx_docs_build/landing
that compiles a version switcher linking to the latest documentation and all historical releases.
[DOCS-04] The root documentation directory docs/ shall contain a .nojekyll file to prevent
GitHub Pages from ignoring directories with leading underscores (such as _static/ and _sources/).
[DOCS-05] Sphinx documentation builds in CI shall enforce SPHINXOPTS="-W" to treat all warnings
as errors, ensuring that broken cross-references or invalid reST markup fail the build.
CI/CD and Automation¶
[CICD-01] All CI workflows shall enforce concurrency groups named after their respective workflow
file (e.g., group: sphinx_build) with cancel-in-progress: true enabled.
[CICD-02] Fresh pushes to open pull requests shall immediately cancel previous in-progress runs for that workflow and start a new run on the latest commit.
[CICD-03] Pushes to the main branch shall cancel previous runs for that workflow and execute
against the latest commit on main.
[CICD-04] On every commit pushed to main, the documentation workflow shall build both the latest
documentation and the landing page, and deploy the updated site to GitHub Pages via
actions/deploy-pages@v5.
[CICD-05] When a new release is published (on: release: types: [published]), the documentation
workflow shall:
Check out the repository at the release tag.
Build versioned documentation into
docs/html_${VERSION}/.Switch to
mainand copy the versioned directory intodocs/.Update the version list sentinels (
.. VERSION_LIST_START/.. VERSION_LIST_END) insphinx_docs_build/landing/source/index.rst.Rebuild the landing page.
Automatically create a pull request into
mainwith the versioned docs and updated index usingpeter-evans/create-pull-request@v8.
[CICD-06] Distribution packaging for TestPyPI and PyPI shall be extracted into reusable composite
GitHub Actions, invoking pypa/gh-action-pypi-publish directly at the job step level for OIDC
Trusted Publishing compatibility.