Skip to content

Data Models

The alpha_hwr.models module contains Pydantic models representing the pump's state and configuration. All models are fully typed and validated.

Telemetry Models

TelemetryData

Real-time telemetry data from the pump including flow, pressure, power, temperature, and electrical measurements.

Bases: BaseModel

Telemetry data from Grundfos Alpha HWR pump.

flow_gpm property

Convert flow to GPM.

formatted_string property

Get a human-readable string representation.

head_ft property

Convert head to feet.

head_psi property

Convert head to PSI.

media_temperature_f property

Convert media temperature to Fahrenheit.

Write Results

What a verified write reports back. The value fields carry what the pump actually holds, read back after the write — see Verified Writes.

WriteResult

The settled outcome of one write.

For ACCEPTED, CLAMPED and REJECTED the value fields carry what the pump actually holds, read back after the write - not what was asked for. The request survives alongside in the requested_* fields, so the result is self-contained for logging and for deciding whether to retry.

ok property

True when the pump took the write.

A clamp counts: the pump accepted the command and stored a value of its own choosing, which is a different thing from refusing it.

WriteStatus

Bases: StrEnum

How a write ended. Every operation reaches exactly one of these.

The distinction that matters for a caller deciding whether to retry is INVALID versus REJECTED: the first is a property of the request and is decided before anything reaches the wire, so retrying it unchanged cannot help. The second means the pump or its state refused, which a later attempt might not hit.

ACCEPTED = 'accepted' class-attribute instance-attribute

The pump confirmed the requested value.

CLAMPED = 'clamped' class-attribute instance-attribute

The pump stored a different value. Measured on an ALPHA HWR: asking for 600 RPM stores 1650 and asking for 4400 stores 3671, the ends of its own limits block. A clamp is a successful write, not a failure - the settled value is in :attr:WriteResult.value.

INVALID = 'invalid' class-attribute instance-attribute

Malformed or out of range. Decided before any wire write.

REJECTED = 'rejected' class-attribute instance-attribute

The pump kept its old value, nacked the command, or a precondition could not be read. detail says which.

SUPERSEDED = 'superseded' class-attribute instance-attribute

A newer write to the same value replaced this one while it queued.

TIMEOUT = 'timeout' class-attribute instance-attribute

No confirmation within the operation's budget, or the link dropped.

WriteCommand

Bases: StrEnum

Which kind of write an operation performs.

SET_PUMP_STATE = 'set_pump_state' class-attribute instance-attribute

Coupled run-state and schedule change; composed of the two above.

Control Models

SetpointInfo

Current pump control configuration including mode, setpoint value, and operational limits.

Bases: BaseModel

Setpoint information for current control mode.

get_display_value()

Get setpoint value with appropriate unit based on control mode.

Returns:

Type Description
tuple[float, str]

Tuple of (value, unit_string)

Notes

All setpoint values are stored in user-facing units (the ControlService converts raw pump units before storing):

  • Pressure modes: stored in meters of water column (m H2O)
  • Flow modes: stored in m³/h
  • Speed mode: stored in RPM
  • Temperature modes: stored in °C

get_limits_display()

Get min/max setpoint limits with appropriate unit conversion.

Returns:

Type Description
tuple[tuple[float, str], tuple[float, str]] | None

Tuple of ((min_value, unit), (max_value, unit)), or None if limits not available.

AlarmInfo

Current alarm and warning status with human-readable descriptions.

Bases: BaseModel

Alarm and warning information.

Device Models

DeviceInfo

Device identification information including serial number, firmware versions, and product details.

Bases: BaseModel

Device identification and version information.

Statistics

Cumulative pump statistics including operating hours and start count.

Bases: BaseModel

Cumulative operating statistics.

Schedule Models

ScheduleEntry

A single schedule time window for pump operation. Supports 5 independent schedule layers.

Bases: BaseModel

Schedule entry for pump operation timing.

Represents a single time window when the pump should operate. Includes validation for time ranges and overlap detection.

Notes

The enabled field indicates whether this specific day has an active schedule in the pump's internal storage. When reading schedules via get_schedule(), only enabled entries are returned. There is no way to "disable" an entry - you can only clear/remove it entirely. The enabled field is primarily used internally for the binary protocol format.

begin_time property

Get formatted begin time (HH:MM).

begin_time_obj property

Get begin time as datetime.time object.

day_index property

Get day index (0=Monday, 6=Sunday).

end_time property

Get formatted end time (HH:MM).

end_time_obj property

Get end time as datetime.time object.

crosses_midnight()

Check if this schedule entry crosses midnight.

Returns:

Type Description
bool

True if end time is before begin time (indicating midnight crossing)

from_bytes(data, day, layer=0) classmethod

Parse from 6-byte binary format.

Parameters:

Name Type Description Default
data bytes

6-byte binary data

required
day str

Day name for this entry

required
layer int

Schedule layer (0-4)

0

Returns:

Type Description
ScheduleEntry

ScheduleEntry instance

Raises:

Type Description
ValueError

If data is not 6 bytes

from_dict(data) classmethod

Create ScheduleEntry from dictionary (e.g., from get_schedule() output).

Parameters:

Name Type Description Default
data dict

Dictionary with schedule entry fields

required

Returns:

Type Description
ScheduleEntry

ScheduleEntry instance

get_duration_minutes()

Calculate entry duration in minutes.

Returns:

Type Description
int

Duration in minutes. If end time is before begin time,

int

assumes the schedule crosses midnight and calculates accordingly.

Examples:

  • 06:00 to 08:00 = 120 minutes
  • 22:00 to 02:00 = 240 minutes (crosses midnight)

is_valid_time_range()

Validate that the time range is sensible.

Returns:

Type Description
bool

Tuple of (is_valid, error_message)

str | None
  • (True, None) if valid
tuple[bool, str | None]
  • (False, "error message") if invalid
Checks
  • Duration is not zero
  • Times are not identical

overlaps_with(other)

Check if this entry overlaps with another entry.

Only checks for overlap if both entries are: - On the same day - On the same layer - Both enabled

Parameters:

Name Type Description Default
other ScheduleEntry

Another ScheduleEntry to compare with

required

Returns:

Type Description
bool

True if the entries overlap in time

Examples:

  • 06:00-08:00 and 07:00-09:00 = True (overlap)
  • 06:00-08:00 and 08:00-10:00 = False (adjacent, no overlap)
  • 06:00-08:00 and 10:00-12:00 = False (separate)
  • 22:00-02:00 and 01:00-03:00 = True (both cross midnight, overlap)

to_bytes()

Convert to 6-byte binary format for writing to pump.

Format

Byte 0: Enabled flag (0x01 if enabled, 0x00 if disabled) Byte 1: Action code (0x02 for run) Byte 2: Start hour (0-23) Byte 3: Start minute (0-59) Byte 4: End hour (0-23) Byte 5: End minute (0-59)

Returns:

Type Description
bytes

6-byte binary representation

to_dict()

Convert to dictionary format matching get_schedule() output.

Returns:

Type Description
dict

Dictionary with all schedule entry fields

validate_day(v) classmethod

Validate day name is one of the valid weekdays (case-insensitive).

Historical Data Models

EventLogEntry

A single event log entry from the pump's event history.

Bases: BaseModel

Single event log entry from the pump.

The pump maintains a circular buffer of 20 event log entries (SubID 10200-10219), where 0 is the newest and 19 is the oldest.

Each entry is 16 bytes containing timestamp, cycle counter, mode, and event type information.

EventLogMetadata

Metadata for event log entries.

Bases: BaseModel

Metadata about the event log (SubID 10199).

The metadata is 7 bytes containing information about the current cycle counter and number of available entries in the log.

Structure (7 bytes): - Bytes 0-1: Current cycle counter (uint16 BE) - Bytes 2-3: Available entries (uint16 BE) - Bytes 4-5: Max buffer size (uint16 BE, always 20) - Byte 6: Reserved/flags (uint8, typically 0)

TrendDataPoint

A single data point in a trend series.

Bases: BaseModel

Single data point in a trend series.

TrendDataSeries

A series of trend data points for a single parameter.

Bases: BaseModel

A series of trend data points for a specific metric.

Contains two sets of data: - 10-cycle: High frequency recent data - 100-cycle: Lower frequency historical data

TrendDataCollection

Collection of all trend data series (flow, head, temperature, power).

Bases: BaseModel

Collection of all trend data series.