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.
Device Models
DeviceInfo
Device identification information including serial number, firmware versions, and product details.
Statistics
Cumulative pump statistics including operating hours and start count.
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
|
|
tuple[bool, str | None]
|
|
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.
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).