Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ serial connection, or reading **data recorded to disk**.
**Talk to a live device.** Open a connection and read/write registers by class:

```python
from harp.device import Device, WhoAmI, OperationControl, OperationControlPayload, OperationMode
from harp.device.core import OperationControl, OperationControlPayload, OperationMode, WhoAmI
from harp.device.client import Device
from harp.serial import open_serial_device

# Use "COMx" on Windows, "/dev/ttyUSBx" on Linux.
Expand Down Expand Up @@ -86,7 +87,7 @@ does under the hood:

```python
from pathlib import Path
from harp.device import create_device_module
from harp.device.schema import create_device_module

behavior = create_device_module(Path("device.yml").read_bytes())
AnalogData = behavior.AnalogData # registers are reached by name...
Expand Down
28 changes: 14 additions & 14 deletions docs/api/device.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

---

::: harp.device.Device
::: harp.device.create_device_module
::: harp.device.parse_device_schema
::: harp.device.ConverterContext
::: harp.device.HarpFramer
::: harp.device.ITransport
::: harp.device.TransportError
::: harp.device.REGISTER_MAP
::: harp.device.OperationControl
::: harp.device.OperationMode
::: harp.device.ResetDevice
::: harp.device.ResetFlags
::: harp.device.ClockConfiguration
::: harp.device.ClockConfigurationFlags
::: harp.device.client.Device
::: harp.device.client.HarpFramer
::: harp.device.client.ITransport
::: harp.device.client.TransportError
::: harp.device.schema.create_device_module
::: harp.device.schema.parse_device_schema
::: harp.device.schema.ConverterContext
::: harp.device.core.REGISTER_MAP
::: harp.device.core.OperationControl
::: harp.device.core.OperationMode
::: harp.device.core.ResetDevice
::: harp.device.core.ResetFlags
::: harp.device.core.ClockConfiguration
::: harp.device.core.ClockConfigurationFlags
3 changes: 2 additions & 1 deletion docs/examples/create_device_module/create_device_module.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from pathlib import Path

from harp.data import parse_to_dataframe
from harp.device import Device, create_device_module
from harp.device.client import Device
from harp.device.schema import create_device_module
from harp.serial import open_serial_device

SERIAL_PORT = "/dev/ttyUSB0" # or "COMx" in Windows ("x" is the number of the serial port)
Expand Down
3 changes: 2 additions & 1 deletion docs/examples/get_info/get_info.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from harp.device import REGISTER_MAP, Device, WhoAmI
from harp.device.core import REGISTER_MAP, WhoAmI
from harp.device.client import Device
from harp.serial import open_serial_device

SERIAL_PORT = "/dev/ttyUSB0" # or "COMx" in Windows ("x" is the number of the serial port)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from harp.device import (
Device,
from harp.device.core import (
EnableFlag,
OperationControl,
OperationControlPayload,
OperationMode,
WhoAmI,
)
from harp.device.client import Device
from harp.serial import open_serial_device

SERIAL_PORT = "/dev/ttyUSB0" # or "COMx" in Windows ("x" is the number of the serial port)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from harp.data import parse_to_dataframe
from harp.device import OperationControl
from harp.device.core import OperationControl

# Parse a single register's binary dump into a pandas DataFrame — one row per
# frame, one column per field. The register class tells `parse_to_dataframe` how
Expand Down
4 changes: 2 additions & 2 deletions docs/examples/read_dataset/read_dataset.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from harp.data import REFERENCE_EPOCH, create_dataset_reader
from harp.device import OperationControl
from harp.device.core import OperationControl

# A Harp acquisition is usually saved as a de-multiplexed dataset folder — one
# `.bin` file per register, named "<DeviceName>_<address>.bin", next to the
Expand Down Expand Up @@ -39,7 +39,7 @@
# can drive the reader directly — construct `DatasetReader(module, folder)`:
#
# from harp.data import DatasetReader
# from harp.device import create_device_module
# from harp.device.schema import create_device_module
# from pathlib import Path
#
# behavior = create_device_module((Path("session.harp") / "device.yml").read_bytes())
Expand Down
6 changes: 3 additions & 3 deletions docs/examples/subscribing_to_events/subscribing_to_events.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import numpy as np
from harp.device import (
REGISTER_MAP,
Device,
from harp.device.core import (
EnableFlag,
OperationControl,
OperationControlPayload,
OperationMode,
REGISTER_MAP,
TimestampSeconds,
)
from harp.device.client import Device
from harp.protocol import HarpMessage, ParsedHarpMessage
from harp.serial import open_serial_device

Expand Down
4 changes: 2 additions & 2 deletions src/packages/harp-data/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ per register, named `<DeviceName>_<address>.bin`, alongside the device's
```

Reading is driven by a generated
[`harp.device.Device`](../harp-device) that describes how to decode each register.
[`harp.device.client.Device`](../harp-device) that describes how to decode each register.
`create_dataset_reader` does that for you — it finds the `device.yml` in the folder,
builds the device, and returns a ready-to-use reader:

Expand All @@ -43,7 +43,7 @@ Already have a device module (e.g. a pre-generated package, or one built with
```python
from pathlib import Path
from harp.data import DatasetReader
from harp.device import create_device_module
from harp.device.schema import create_device_module

behavior = create_device_module((Path("session.harp") / "device.yml").read_bytes())
reader = DatasetReader(behavior, "session.harp")
Expand Down
8 changes: 4 additions & 4 deletions src/packages/harp-data/src/harp/data/_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from typing import Any

import pandas as pd
from harp.device import DeviceModuleLike, create_device_module
from harp.device.schema import DeviceModuleLike, create_device_module
from harp.protocol import RegisterBase
from harp.protocol._constants import _TIMESTAMP_FLAG

Expand Down Expand Up @@ -43,7 +43,7 @@ class DatasetReader:
everything = reader.read_all() # {register_name: DataFrame}

``device_module`` is a device module -- a generated device package, or one built from a
schema with :func:`~harp.device.create_device_module`. Its ``REGISTER_MAP`` and
schema with :func:`~harp.device.schema.create_device_module`. Its ``REGISTER_MAP`` and
``__name__`` are read on demand. ``name`` overrides the ``<DeviceName>`` file
prefix, which defaults to the module name.

Expand Down Expand Up @@ -197,14 +197,14 @@ def create_dataset_reader(
"""Build a :class:`DatasetReader` for a dataset folder, device and all.

Convenience wrapper that finds the device schema inside ``root`` (``device.yml``
by default), builds its module with :func:`~harp.device.create_device_module`, and
by default), builds its module with :func:`~harp.device.schema.create_device_module`, and
returns a reader ready to :meth:`~DatasetReader.read`::

reader = create_dataset_reader("session.harp")
df = reader.read(44)

``schema`` points at the schema file explicitly when it isn't ``root/device.yml``.
``converters`` and ``strict`` are forwarded to :func:`~harp.device.create_device_module`
``converters`` and ``strict`` are forwarded to :func:`~harp.device.schema.create_device_module`
for custom ``interfaceType`` decoding; ``name`` and ``resolver`` are forwarded to
:class:`DatasetReader`. Use ``DatasetReader(device_module, root)`` directly when you
already have a (e.g. pre-generated) device module.
Expand Down
7 changes: 4 additions & 3 deletions src/packages/harp-device/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ dependencies. Pair it with a transport (e.g. [`harp-serial`](../harp-serial)).
A `Device` is driven over a transport; `read`/`write` take a register class:

```python
from harp.device import Device, WhoAmI, OperationControl
from harp.device.core import OperationControl, WhoAmI
from harp.device.client import Device

# `device` is a Device opened over some transport (see harp-serial)
who = device.read(WhoAmI).parsed # -> np.uint16
Expand All @@ -24,7 +25,7 @@ device identity as `WHO_AM_I`, declare the register classes at module level, and
the core `REGISTER_MAP` beside them:

```python
from harp.device import REGISTER_MAP as _CORE_REGISTER_MAP
from harp.device.core import REGISTER_MAP as _CORE_REGISTER_MAP

WHO_AM_I: int = 1216
REGISTER_MAP = {**_CORE_REGISTER_MAP, 32: DigitalInputState, ...}
Expand Down Expand Up @@ -72,7 +73,7 @@ names come from the yml verbatim, payload fields are `snake_case`, and enum memb

```python
from pathlib import Path
from harp.device import create_device_module
from harp.device.schema import create_device_module

behavior = create_device_module(Path("device.yml").read_bytes())
reg = behavior.AnalogData # by name
Expand Down
50 changes: 0 additions & 50 deletions src/packages/harp-device/src/harp/device/_schema/__init__.py

This file was deleted.

14 changes: 14 additions & 0 deletions src/packages/harp-device/src/harp/device/client/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""Talking to a Harp device: the device itself, its transport and the framer."""

from ._device import Device, EventHandler, Subscription
from ._framer import HarpFramer
from ._transport import ITransport, TransportError

__all__ = [
"Device",
"EventHandler",
"Subscription",
"HarpFramer",
"ITransport",
"TransportError",
]
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from ._framer import HarpFramer
from ._transport import ITransport, TransportError
from ._registers import (
from harp.device.core import (
WhoAmI,
)

Expand Down Expand Up @@ -69,12 +69,12 @@ def __exit__(self, *args: object) -> None:

class Device:
"""Harp device protocol logic (framing, request/reply, register access)
over an :class:`~harp.device.ITransport`.
over an :class:`~harp.device.client.ITransport`.

Must be opened before use, via ``with`` or :meth:`open`. :meth:`read`,
:meth:`write` and :meth:`subscribe` take a register class, so the device holds
no register collection of its own: a device's registers live in its module,
beside a ``REGISTER_MAP`` (see :func:`~harp.device.create_device_module`, or the
beside a ``REGISTER_MAP`` (see :func:`~harp.device.schema.create_device_module`, or the
``harp-device`` README for the statically generated equivalent).

A subclass sets :attr:`__whoami__` to validate device identity on open
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class TransportError(Exception):

@runtime_checkable
class ITransport(Protocol):
"""Byte channel a :class:`~harp.device.Device` drives.
"""Byte channel a :class:`~harp.device.client.Device` drives.

Owns no protocol logic. Failures are reported as :class:`TransportError`.
"""
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from ._device import Device, EventHandler, Subscription
from ._emit_module import DeviceModule, DeviceModuleLike, create_device_module
from ._framer import HarpFramer
"""The core register set every Harp device carries, and its address space."""

from ._register_map import REGISTER_MAP
from ._registers import (
AssemblyVersion,
ClockConfiguration,
Expand All @@ -26,22 +26,8 @@
TimestampSeconds,
WhoAmI,
)
from ._register_map import REGISTER_MAP
from ._schema import ConverterContext, parse_device_schema
from ._transport import ITransport, TransportError

__all__ = [
"Device",
"EventHandler",
"Subscription",
"create_device_module",
"DeviceModule",
"DeviceModuleLike",
"parse_device_schema",
"ConverterContext",
"HarpFramer",
"ITransport",
"TransportError",
"REGISTER_MAP",
"WhoAmI",
"HardwareVersionHigh",
Expand Down
12 changes: 12 additions & 0 deletions src/packages/harp-device/src/harp/device/schema/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""Building a device interface from a Harp ``device.yml`` at runtime."""

from ._emit import ConverterContext, parse_device_schema
from ._module import DeviceModule, DeviceModuleLike, create_device_module

__all__ = [
"create_device_module",
"DeviceModule",
"DeviceModuleLike",
"parse_device_schema",
"ConverterContext",
]
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@

from harp.protocol import RegisterBase

from ._register_map import REGISTER_MAP as CORE_REGISTER_MAP
from ._schema import create_registers, parse_device_schema
from ._schema._emit import ConverterValue
from harp.device.core import REGISTER_MAP as CORE_REGISTER_MAP
from ._emit import ConverterValue, create_registers, parse_device_schema

#: Module name used when the schema carries no ``device`` header.
_DEFAULT_NAME = "Device"
Expand Down
3 changes: 2 additions & 1 deletion src/packages/harp-serial/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ Like the builtin `open`, the returned device is connected and ready; use it in a
`with` block for guaranteed cleanup:

```python
from harp.device import Device, WhoAmI
from harp.device.core import WhoAmI
from harp.device.client import Device
from harp.serial import open_serial_device

with open_serial_device(Device, port="COM3", baudrate=1_000_000) as dev:
Expand Down
4 changes: 2 additions & 2 deletions src/packages/harp-serial/src/harp/serial/_serial.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

import serial

from harp.device import Device, TransportError
from harp.device.client import Device, TransportError

D = TypeVar("D", bound=Device)

DEFAULT_BAUDRATE: int = 1_000_000


class SerialTransport:
"""A serial-port :class:`~harp.device.ITransport` (structural conformance)."""
"""A serial-port :class:`~harp.device.client.ITransport` (structural conformance)."""

def __init__(self, port: str, baudrate: int = DEFAULT_BAUDRATE) -> None:
self._port = port
Expand Down
Loading