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.

Download files

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

Source Distribution

harp_device-0.5.0.tar.gz (26.1 kB view details)

Uploaded Source

Built Distribution

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

harp_device-0.5.0-py3-none-any.whl (27.7 kB view details)

Uploaded Python 3

File details

Details for the file harp_device-0.5.0.tar.gz.

File metadata

  • Download URL: harp_device-0.5.0.tar.gz
  • Upload date:
  • Size: 26.1 kB
  • Tags: Source
  • Uploaded using 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}

File hashes

Hashes for harp_device-0.5.0.tar.gz
Algorithm Hash digest
SHA256 fbeed57addb265e6e040c37b2438c1b8e6e1b2b8524f168f87f8aca98ea42aec
MD5 c19c5f74df042f5cdd36c067aa81469b
BLAKE2b-256 8418f48f8b553b09ce119e5819b075f1bce538797e333154a20206c557484cdb

See more details on using hashes here.

File details

Details for the file harp_device-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: harp_device-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 27.7 kB
  • Tags: Python 3
  • Uploaded using 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}

File hashes

Hashes for harp_device-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 acf178e38cb943a950914dc69323845c572fef32ce5cb82f6877135395a67bf1
MD5 e8375aae89ead333b06aa995dd885656
BLAKE2b-256 03cd2303fe6cd78a23fa274f6ffc1943099f450509a89dfd88e94afcbee4db83

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.5.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