Skip to main content

Async Python client for the DIVERA 24/7 REST API.

Project description

divera247

An async Python client for the DIVERA 24/7 REST API and WebSocket push stream, built on httpx and pydantic.

Installation

pip install divera247
# or, with uv:
uv add 'divera247'

Optional: WebSocket streaming

The push-event WebSocket subscription talks to wss://ws.divera247.com/ws via httpx-ws, which is kept out of the default install for users who only need the REST API. Install it through the ws extra:

pip install 'divera247[ws]'
# or, with uv:
uv add 'divera247[ws]'

Quickstart

import anyio
from divera247 import AccessKeyAuth, Divera247Client


async def main() -> None:
    async with Divera247Client(auth=AccessKeyAuth('YOUR_ACCESS_KEY')) as client:
        alarms = await client.alarm.get_alarms()
        for alarm in alarms.data or []:
            print(alarm)


anyio.run(main)

Every v2 endpoint group is exposed as a lazily-instantiated attribute on Divera247Client:

Attribute Endpoint group
client.alarm /api/v2/alarms
client.attachment /api/v2/attachments
client.auth_api /api/v2/auth
client.dashboard /api/v2/dashboard
client.event /api/v2/events
client.file /api/v2/file
client.message /api/v2/messages
client.message_channel /api/v2/message-channels
client.news /api/v2/news
client.operations /api/v2/operations
client.password /api/v2/password
client.pull /api/v2/pull
client.reporttype /api/v2/reporttypes
client.shift_plans /api/v2/shift-plans
client.statusgeber /api/v2/statusgeber
client.using_vehicle /api/v2/using-vehicles
client.using_vehicle_crew /api/v2/using-vehicles/...
client.using_vehicle_property /api/v2/using-vehicles/...

Authentication

Three auth flows are provided in divera247.auth, all of which set the Authorization: Bearer <token> header so the same credentials work for both REST and WebSocket:

from divera247 import AccessKeyAuth, JwtAuth, RefreshingJwtAuth

# Static access key (simplest; no token refresh).
AccessKeyAuth('YOUR_ACCESS_KEY')

# Pre-obtained JWT.
JwtAuth('eyJhbGciOi...')

# Access-key backed JWT that is fetched on first use and refreshed shortly
# before `exp`. Safe to share between concurrent tasks.
RefreshingJwtAuth('YOUR_ACCESS_KEY')

Error handling

HTTP errors and envelope errors (success: false) are both funnelled through the hierarchy in divera247.errors:

from divera247 import (
    DiveraAPIError,
    DiveraAuthError,
    DiveraRateLimitError,
    DiveraValidationError,
)

try:
    await client.alarm.get_alarms()
except DiveraAuthError:
    ...                               # 401 / 403
except DiveraRateLimitError as exc:
    await anyio.sleep(exc.retry_after or 1)
except DiveraValidationError as exc:
    print(exc.errors)                 # field -> message mapping
except DiveraAPIError as exc:
    print(exc.status_code, exc.body)  # catch-all for other HTTP errors

Endpoints that return the standard {"success": ..., "data": ...} envelope can be additionally guarded with ensure_success(parsed) when success=false bodies should turn into exceptions.

Customising the HTTP client

Divera247Client is deliberately a thin wrapper: its own constructor only takes the auth, an optional base_url, and an optional pre-built session. Anything you'd normally configure on an httpx.AsyncClient -- timeouts, headers (including User-Agent), proxies, transports, event hooks -- is done by building your own client and passing it in via session=:

import httpx

async with httpx.AsyncClient(
    auth=AccessKeyAuth('...'),
    base_url='https://app.divera247.com/api/',
    timeout=httpx.Timeout(60.0, connect=15.0),
    headers={'User-Agent': 'my-app/1.0', 'Accept-Language': 'de'},
    proxy='http://proxy.local:3128',
    verify=False,
) as external:
    client = Divera247Client(auth=AccessKeyAuth('...'), session=external)
    ...

When a session= is passed the caller keeps ownership: the session is not closed when the client is exited.

WebSocket streaming

Two entry points live in divera247.websocket:

  • subscribe_websocket(client, ...) yields events from a single session and exits when the server disconnects. Use it when you want to drive your own reconnect policy.
  • stream_websocket(client, ...) wraps subscribe_websocket in a jittered exponential-backoff reconnect loop. Use it when you want a "just keep me subscribed" iterator.
from divera247.websocket import (
    ClusterPullEvent,
    UnknownEvent,
    UserStatusEvent,
    stream_websocket,
)

async for event in stream_websocket(client, ucr_id=527_459):
    match event:
        case UserStatusEvent(ucr=ucr, status=status):
            ...                                   # status is a PullStatusData
        case ClusterPullEvent(cluster=cluster, pull=pull):
            ...                                   # re-fetch pull.type (e.g. "alarm") + pull.id
        case UnknownEvent():
            ...                                   # forward-compatible fallback

WebSocketAuthenticationError propagates out of the loop so an unusable credential doesn't get retried forever.

API schemas

The schemas/ directory contains the vendor-published OpenAPI YAML files that this client was built against -- see schemas/README.md for details and the mapping to divera247.endpoints / divera247.models.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

divera247-0.0.1b2.tar.gz (49.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

divera247-0.0.1b2-py3-none-any.whl (70.1 kB view details)

Uploaded Python 3

File details

Details for the file divera247-0.0.1b2.tar.gz.

File metadata

  • Download URL: divera247-0.0.1b2.tar.gz
  • Upload date:
  • Size: 49.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for divera247-0.0.1b2.tar.gz
Algorithm Hash digest
SHA256 90364b862ad04f71f292cb2834515321b572156cfce80d6a2da5f873e5a5f868
MD5 740044582b1e66a1fb838e6fa1ee4f15
BLAKE2b-256 1ec3a604cef953ee7839a0a71ad348426c0a0abe0bccb9c4ec9809389a813d40

See more details on using hashes here.

File details

Details for the file divera247-0.0.1b2-py3-none-any.whl.

File metadata

  • Download URL: divera247-0.0.1b2-py3-none-any.whl
  • Upload date:
  • Size: 70.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for divera247-0.0.1b2-py3-none-any.whl
Algorithm Hash digest
SHA256 a99826ede38b541fe64c1f933a6f2d4ca62b58dc02c47b7fbd0e0783d229fd99
MD5 ff68978c745f7d61c2be90571cdcf271
BLAKE2b-256 88ecfcbbd40820bfbdef41343098d68fe0fd7267b31e614fce078147251d910c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page