Skip to main content

harp-device

The transport-agnostic device layer for the Harp protocol: the core Harp registers and a Device base that handles framing, request/reply and register access. It depends only on harp-protocol, with no transport dependencies. Pair it with a transport such as harp-serial.

Read/write registers

A Device operates over a transport. read and write take a register class:

from harp.device import core

# `device` is a Device opened over some transport, see harp-serial
who = device.read(core.WhoAmI).payload          # -> np.uint16
device.write(core.OperationControl, payload)   # write a register

When a request fails

An error reply raises DeviceError, which keeps the reply as reply so the frame sent by the device stays available for inspection. Pass raise_on_error=False to the constructor to receive such a reply as an ordinary return value instead. A transport failure raises TransportError, and every later request reports the same failure rather than waiting for a reply that cannot arrive. A device that never answers raises TimeoutError after REPLY_TIMEOUT, which is also what happens when close is called during a request.

Extend for a specific device

A device is described by a module. Downstream, often generated, packages record the device identity as WHO_AM_I, declare the register classes at module level, and expand the core REGISTER_MAP beside them:

from harp.device.core import REGISTER_MAP as _CORE_REGISTER_MAP

WHO_AM_I: int = 1216
REGISTER_MAP = {**_CORE_REGISTER_MAP, 32: DigitalInputState, ...}

This is the same structure create_device_module builds from a schema, so a device reads the same way whether it was generated ahead of time or compiled at runtime. A WHO_AM_I of 0 marks an unregistered device, used while a device is in development or outside the official registry, and identity checks are skipped for it.

A device module names only what its schema declares, the registers beside the enums and payload classes built from them. The core registers and any core mask reused by the schema have a single definition, in harp.device.core, and are accessed from there rather than through the device module. The core register set is not a device, so it carries no WHO_AM_I. REGISTER_MAP covers the complete device address space, including both core and application registers.

Pass the module to Device, or to open_device, to validate identity on open:

from harp.device import behavior, client, core

with client.Device(transport, behavior) as device:
    device.read(core.WhoAmI)                 # a core register
    device.read(behavior.DigitalInputState)  # declared by the schema

The WHO_AM_I in the module determines the check, and 0 skips it. Omitting the module skips validation. The module is not otherwise consulted: registers are passed to read, write and subscribe as arguments either way, and only a subscribed register is parsed on arrival. Core registers such as WhoAmI and OperationControl come from harp.device.core and are read the same way.

A new transport is just an object implementing the ITransport protocol, with open, write, read and close.

Generate registers from a device.yml

Without a pre-generated device package, create_device_module builds the same structure at runtime from Harp device.yml text. It emits register, enum, and payload classes at module level, a REGISTER_MAP beside them, and the identity declared by the schema as WHO_AM_I. Identifiers match a generated package name for name: register, enum, and payload class names come from the yml verbatim, payload fields are snake_case, and enum members are SCREAMING_SNAKE_CASE. A maskType the schema does not declare resolves against the core masks, and a register marked private is emitted with an underscore-prefixed name.

from pathlib import Path

from harp.device import schema

behavior = schema.create_device_module(Path("device.yml").read_bytes())
reg = behavior.AnalogData          # by name
reg = behavior.REGISTER_MAP[44]    # or by address

The module is not registered in sys.modules, so it has to be bound rather than imported. Names come from the schema at runtime, so they don't autocomplete and aren't statically checked. A generated package on disk gives both.

For a custom interfaceType, pass its converter via converters=, keyed by {InterfaceType}Converter or {MemberName}Converter. An unresolved custom type raises UnknownConverterError, or pass require_converters=False to decode it natively:

schema.create_device_module(yml_text, converters={"DataConverter": DataConverter()})

parse_device_schema(yml_text) is also public, returning the parsed schema model without a module: registers, masks, and optional device identity.

harp-device is released as open source under the MIT license. Bug reports and contributions are welcome at the GitHub repository.

Metadata

Release files for harp-device 0.5.0

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

Source distribution (sdist)

Source distribution for harp-device 0.5.0
File Size Uploaded Provenance
harp_device-0.5.0.tar.gz 26.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for harp-device 0.5.0
File Interpreter ABI Platform
harp_device-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 53.7 kB

Release files / harp_device-0.5.0.tar.gz

Download URL harp_device-0.5.0.tar.gz
Size 26.1 kB
Tags Source
SHA-256 checksum
How to use checksums
fbeed57addb265e6e040c37b2438c1b8e6e1b2b8524f168f87f8aca98ea42aec
BLAKE2b-256 checksum
How to use checksums
8418f48f8b553b09ce119e5819b075f1bce538797e333154a20206c557484cdb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","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}

Release files / harp_device-0.5.0-py3-none-any.whl

Download URL harp_device-0.5.0-py3-none-any.whl
Size 27.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
acf178e38cb943a950914dc69323845c572fef32ce5cb82f6877135395a67bf1
BLAKE2b-256 checksum
How to use checksums
03cd2303fe6cd78a23fa274f6ffc1943099f450509a89dfd88e94afcbee4db83
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","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}

Security for harp-device 0.5.0

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