Skip to main content

omixom-data

Cliente Python de la Omixom Data API v3: lectura de series de mediciones y réplica incremental para mantener una copia siempre al día.

pip install omixom-data

Requiere Python 3.11+ y un token de acceso de la red Omixom.

Mantener una copia al día

El caso típico es replicar las mediciones de un grupo de equipos y seguirlas en el tiempo. El Feed encapsula todo el protocolo (bootstrap paginado, cursores, coherencia del snapshot) y lo entrega en batches: cada batch es una página de trabajo acotado que trae sus eventos y el estado que la deja atrás.

from omixom_data import Client, MeasurementDeleted

with Client(token="...") as client:
    feed = client.feed([30125, 30126])  # toda la historia de cada equipo

    for batch in feed.batches():  # bootstrap + cambios, hasta estar al día
        for event in batch.events:
            if isinstance(event, MeasurementDeleted):
                store.delete(event.station, event.module, event.time)
            else:
                store.upsert(event.station, event.module, event.time, event.value)
        save(batch.state.model_dump_json())  # checkpoint alineado a la página

El contrato es aplicar primero, guardar después (idealmente ambos en una transacción del store propio). Con ese orden, cortar el proceso en cualquier punto (incluso a mitad de un backfill de días) deja como peor caso una página re-aplicada, y aplicar eventos es idempotente por diseño: MeasurementUpserted deja la copia en ese valor, MeasurementDeleted la quita, re-aplicar no cambia nada. Cada batch persistido es progreso ganado; break entre batches es siempre seguro.

Para volver a sincronizar (el próximo poll o la próxima corrida del proceso):

from omixom_data import Client, FeedState

with Client(token="...") as client:
    feed = client.resume(FeedState.model_validate_json(saved))
    for batch in feed.batches():  # solo lo que falta desde el checkpoint
        apply_all(batch.events)
        save(batch.state.model_dump_json())

batches() es re-llamable: cada llamada avanza hasta quedar al día y la siguiente retoma desde ahí, así que el loop de un daemon es batches() + esperar el intervalo deseado. El avance es por módulo (el estado guarda un cursor por serie) y los requests van por estación: el bootstrap de varios equipos avanza round-robin para solapar sus límites de uso.

Acotar el rango

from datetime import UTC, datetime

feed = client.feed([30125], date_from=datetime(2023, 1, 1, tzinfo=UTC))  # desde 2023
feed = client.feed(
    [30125],
    date_from=datetime(2023, 1, 1, tzinfo=UTC),
    date_to=datetime(2024, 1, 1, tzinfo=UTC),  # 2023 completo
)

Sin fechas, cada equipo se replica desde su fecha de instalación. Con date_from solo, la réplica sigue recibiendo lo nuevo; con ambas, la ventana queda cerrada pero las correcciones a datos de esa ventana siguen llegando. modules acota a esos módulos, de cualquiera de las estaciones dadas (una estación sin módulos seleccionados no genera requests); el conjunto replicado queda fijado al crear el feed, así que un sensor instalado después no se suma solo (ver abajo). categories filtra qué tipo de dato replicar; con ese filtro, un punto corregido hacia una categoría no seleccionada llega como borrado (salió de la vista replicada).

Sumar módulos a un feed existente

Un sensor instalado después de crear el feed se suma con add_modules, sobre un feed nuevo o retomado; sin lista de módulos entran todos los del equipo que falten:

feed = client.resume(FeedState.model_validate_json(saved))
feed.add_modules(30125)  # o add_modules(30125, [4812]) para uno puntual

for batch in feed.batches():  # el nuevo hace su bootstrap; el resto sigue donde estaba
    apply_all(batch.events)
    save(batch.state.model_dump_json())

Devuelve los ids agregados (los ya rastreados se omiten) y rechaza con ValueError un módulo que no pertenece al equipo. También sirve para sumar una estación nueva al feed. El alta queda persistida con el state del próximo batch, así que si el proceso corta antes, la próxima corrida tiene que volver a llamarlo.

Lecturas puntuales

Para consultas de una sola vez, sin réplica:

client.stations()  # equipos accesibles con el token
client.station(30125)  # fecha de instalación y módulos

for point in client.series(  # la serie completa de una ventana, en streaming
    30125,
    date_from=datetime(2024, 1, 1, tzinfo=UTC),
    date_to=datetime(2024, 2, 1, tzinfo=UTC),
):
    print(point.module, point.time, point.value)

series camina todas las páginas por adentro repitiendo el cursor de la primera, así el resultado entero es un corte coherente de la base aunque haya escrituras concurrentes. Para materializar la serie, list(client.series(...)).

Debajo de eso está el acceso crudo página por página (series_page, changes_page), donde el manejo del cursor queda a cargo del caller: para paginar de forma coherente hay que repetir el request con date_from igual al next_from recibido y cursor igual al cursor recibido.

Errores y límites de uso

Los errores de la API llegan como excepciones tipadas bajo OmixomDataError: AuthenticationError, NotFoundError, InvalidRequestError, RateLimitedError y ServerError. Ante un 429 el cliente espera lo que indique Retry-After y reintenta solo; Client(..., wait_on_rate_limit=False) desactiva la espera y levanta RateLimitedError con el tiempo sugerido en retry_after.

Desarrollo

uv sync
uv run tox        # style + tests + cobertura

Download files

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

Source Distribution

omixom_data-0.3.0.tar.gz (54.5 kB view details)

Uploaded Source

Built Distribution

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

omixom_data-0.3.0-py3-none-any.whl (15.3 kB view details)

Uploaded Python 3

File details

Details for the file omixom_data-0.3.0.tar.gz.

File metadata

  • Download URL: omixom_data-0.3.0.tar.gz
  • Upload date:
  • Size: 54.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.7 {"installer":{"name":"uv","version":"0.12.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 omixom_data-0.3.0.tar.gz
Algorithm Hash digest
SHA256 ffaba313d4d9d74c8970ccb0f27bb8c833e094b76aeea80c834c8fa15f4c110b
MD5 31e9cd483c09005f1cd556c941688e7f
BLAKE2b-256 8ec38a0fe5ceb6b92fd69872e3236da84e54c66cd5d34a413729ecac0e0b11cc

See more details on using hashes here.

File details

Details for the file omixom_data-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: omixom_data-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 15.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.7 {"installer":{"name":"uv","version":"0.12.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 omixom_data-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 90686931ec1fd3ffd6d34ddf6aba7e1d1812974208b7a705a1127d15ed1a7386
MD5 b893ba1431970a5d6d4d0ac41f320f45
BLAKE2b-256 218e88f7ea36051d9ab82bc383d4c630b4c851978cc78f2f1cdce2d5af9db767

See more details on using hashes here.

Release history Release notifications | RSS feed

0.3.1

2 files

This release

0.3.0 This release

2 files

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