Skip to content

Client API

The AlphaHWRClient is the main entry point for interacting with Grundfos ALPHA HWR pumps. It provides a service-oriented architecture where specialized services handle different aspects of pump communication.

Overview

The client acts as a facade and coordinator for specialized services:

  • Telemetry - Real-time sensor data and monitoring
  • Control - Pump control operations (start, stop, mode changes)
  • Schedule - Weekly schedule management across 5 layers
  • Device Info - Device identification and statistics
  • Configuration - Backup and restore operations
  • Time - Real-time clock management
  • History - Historical trend data (100 cycles)
  • Event Log - Pump event history (20 entries)

Basic Usage

import asyncio
from alpha_hwr import AlphaHWRClient


async def main():
    # Connect using context manager (automatic disconnect)
    async with AlphaHWRClient("AA:BB:CC:DD:EE:FF") as client:
        # Read telemetry
        data = await client.telemetry.read_once()
        print(f"Flow: {data.flow_m3h} m³/h")

        # Control pump
        await client.control.set_constant_pressure(1.5)

        # Manage schedules
        entries = await client.schedule.read_entries()


asyncio.run(main())

API Reference

alpha_hwr.client.AlphaHWRClient

Main client for Grundfos ALPHA HWR pump interaction.

Provides a unified API for all pump operations through specialized services. Manages BLE connection, authentication, and service lifecycle.

Services

telemetry: Read sensor data (flow, pressure, power, temperature) control: Start/stop pump, set modes and setpoints schedule: Manage weekly pump schedules device_info: Read device identification and statistics config: Backup and restore pump configuration time: Read and synchronize pump real-time clock history: Read historical trend data (flow, head, temperature) event_log: Read pump event log entries and metadata writes: The serialized write path; every write settles through it single_events: One-off scheduled runs and vacations

Attributes:

Name Type Description
address str | None

BLE device address (UUID on macOS, MAC on Linux/Windows)

adapter str | None

Optional BLE adapter identifier

session Session | None

Session manager (tracks authentication state)

transport Transport | None

BLE transport layer

auth AuthenticationHandler | None

Authentication handler

Example

async with AlphaHWRClient("DEVICE_ADDRESS") as client: # doctest: +SKIP ... # Telemetry ... data = await client.telemetry.read_once() ... print(f"Flow: {data.flow_m3h} m³/h") ... ... # Control ... await client.control.start() ... await client.control.set_constant_pressure(1.5) ... ... # Schedule ... await client.schedule.enable() ... ... # Backup ... await client.config.backup("pump.json")

Implementation Notes

The client is a thin orchestration layer. All business logic lives in the service modules. This makes the code: - Easier to understand (single responsibility per service) - Easier to test (mock services independently) - Easier to port (services are self-contained)

telemetry = None instance-attribute

control = None instance-attribute

device_info = None instance-attribute

schedule = None instance-attribute

history = None instance-attribute

event_log = None instance-attribute

time = None instance-attribute

single_events = None instance-attribute

writes = None instance-attribute

config = None instance-attribute

is_ready property

Whether the client knows enough about the pump to write safely.

True once connected, authenticated, and the pump's stored configuration has been read. Writes that carry fields the caller did not set need that reading to preserve them, so this is the signal to wait for before driving the pump programmatically - rather than guessing at a settle delay.

__init__(address=None, adapter=None, auto_authenticate=True)

Initialize the ALPHA HWR client.

Parameters:

Name Type Description Default
address str | None

BLE device address (UUID on macOS, MAC on Linux/Windows). If None, reads from ALPHA_HWR_DEVICE_ADDRESS env variable.

None
adapter str | None

Optional BLE adapter identifier (platform-specific)

None
auto_authenticate bool

Automatically authenticate after connection (default True)

True
Example
Use address from environment

client = AlphaHWRClient()

Use specific address

client = AlphaHWRClient("A1B2C3D4-E5F6-7890-1234-567890ABCDEF")

Specify adapter (Linux)

client = AlphaHWRClient(address="00:11:22:33:44:55", adapter="hci1")

connect(timeout=60.0, fast_mode=False) async

Connect to the pump via BLE.

Establishes BLE connection, initializes transport layer, and sets up all service modules. If auto_authenticate is enabled, also performs authentication handshake.

If no address is configured, automatically attempts to discover a nearby ALPHA HWR pump.

Parameters:

Name Type Description Default
timeout float

Connection timeout in seconds (default 60s)

60.0
fast_mode bool

If True, skips authentication delays (for testing)

False

Raises:

Type Description
ConnectionError

If connection fails or no device found during discovery

ValueError

If discovery fails

Example
Connect to specific address

client = AlphaHWRClient("DEVICE_ADDRESS") await client.connect() # doctest: +SKIP

Connect using automatic discovery

client = AlphaHWRClient() await client.connect() # doctest: +SKIP

Implementation Notes

Connection sequence: 1. Resolve address (discovery if needed) 2. Scan for advertisement data before connecting 3. Create BleakClient with device address ...

disconnect() async

Disconnect from the pump.

Cleanly shuts down all services, stops BLE notifications, and disconnects from the device.

Example

await client.disconnect() # doctest: +SKIP print(f"Connected: {client.is_connected}") # False # doctest: +SKIP

Implementation Notes

Disconnect sequence: 1. Stop BLE notifications 2. Clear service references 3. Disconnect BLE client 4. Reset all state

Safe to call multiple times (idempotent).

authenticate(fast_mode=False) async

Authenticate with the pump.

Performs the authentication handshake to enable control operations. Read-only operations (telemetry, device info) don't require authentication, but control operations (start, stop, mode changes) do.

Parameters:

Name Type Description Default
fast_mode bool

If True, skips delays for testing purposes.

False

Returns:

Type Description
bool

True if authentication successful, False otherwise

Example

success = await client.authenticate() # doctest: +SKIP if success: # doctest: +SKIP ... print("Authenticated successfully") ... await client.control.start()

__aenter__() async

Async context manager entry - connects to pump.

__aexit__(exc_type, exc_val, exc_tb) async

Async context manager exit - disconnects from pump.

wait_until_ready(timeout=30.0) async

Wait for :attr:is_ready, retrying the cache read if it failed.

Parameters:

Name Type Description Default
timeout float

Seconds to keep trying.

30.0

Returns:

Type Description
bool

True if the client became ready in time.

get_run_state() async

What state the run flag and schedule flag put the pump in.

Worth asking rather than reading the two flags separately: one of their four combinations - stopped with the schedule armed - can never run, and looks healthy from every angle except the water.

set_run_state(target) async

Move the pump to a state it can actually act on.

Writes only the flags that differ, in an order that never passes through the stalled combination - arming a schedule over a stopped pump, even for the moment between two writes, is a window that can be missed.

Parameters:

Name Type Description Default
target RunState

off, engaged or scheduled. stalled is a diagnosis rather than something to ask for, and is refused.

required

Returns:

Type Description
WriteResult

The most severe of the underlying writes, so a partial failure

WriteResult

surfaces rather than being averaged away.